aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore14
-rw-r--r--INSTALL.md14
-rw-r--r--Makefile.in119
-rw-r--r--bootstrap/bin/start.bootbin5330 -> 5324 bytes
-rw-r--r--bootstrap/bin/start.script113
-rw-r--r--bootstrap/bin/start_clean.bootbin5330 -> 5324 bytes
-rw-r--r--bootstrap/bin/start_clean.script113
-rw-r--r--bootstrap/lib/compiler/ebin/beam_asm.beambin9028 -> 11640 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_block.beambin13136 -> 14388 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_bool.beambin14880 -> 16160 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_bsm.beambin12172 -> 13728 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_clean.beambin10128 -> 11468 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_dead.beambin11264 -> 11880 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_dict.beambin3956 -> 5364 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_disasm.beambin23268 -> 24968 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_flatten.beambin3252 -> 3448 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_jump.beambin8936 -> 9516 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_listing.beambin2720 -> 2904 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_opcodes.beambin6756 -> 6812 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_peep.beambin2356 -> 2456 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_receive.beambin5392 -> 5832 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_trim.beambin7764 -> 8568 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_type.beambin13016 -> 13820 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_utils.beambin12848 -> 14532 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_validator.beambin31328 -> 34328 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/cerl.beambin28236 -> 30264 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/cerl_clauses.beambin2676 -> 2876 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/cerl_inline.beambin33288 -> 37300 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/cerl_trees.beambin15824 -> 18960 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/compile.beambin33652 -> 36920 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/compiler.app67
-rw-r--r--bootstrap/lib/compiler/ebin/compiler.appup1
-rw-r--r--bootstrap/lib/compiler/ebin/core_lib.beambin5072 -> 5468 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/core_lint.beambin10944 -> 11632 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/core_parse.beambin35288 -> 37644 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/core_pp.beambin11148 -> 12124 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/core_scan.beambin6268 -> 6628 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/erl_bifs.beambin2100 -> 2100 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/rec_env.beambin4312 -> 4780 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_core_dsetel.beambin6352 -> 6996 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_core_fold.beambin43932 -> 47520 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_core_inline.beambin3996 -> 4212 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_expand_pmod.beambin7616 -> 8396 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_pre_attributes.beambin3028 -> 3360 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_pre_expand.beambin14156 -> 16188 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_codegen.beambin47920 -> 53752 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_core.beambin45460 -> 50988 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_kernel.beambin40848 -> 44604 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_kernel_pp.beambin10868 -> 11828 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_life.beambin21568 -> 23528 bytes
-rw-r--r--bootstrap/lib/compiler/egen/beam_opcodes.erl319
-rw-r--r--bootstrap/lib/compiler/egen/beam_opcodes.hrl12
-rw-r--r--bootstrap/lib/compiler/egen/core_parse.erl5426
-rw-r--r--bootstrap/lib/kernel/ebin/application.beambin2708 -> 3772 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/application_controller.beambin27960 -> 30684 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/application_master.beambin5944 -> 6352 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/application_starter.beambin1204 -> 1264 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/auth.beambin5908 -> 6328 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/code.beambin6284 -> 6732 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/code_server.beambin23736 -> 25956 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/disk_log.beambin32824 -> 36444 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/disk_log_1.beambin22804 -> 24896 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/disk_log_server.beambin5948 -> 6408 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/disk_log_sup.beambin552 -> 564 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/dist_ac.beambin24568 -> 26708 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/dist_util.beambin9544 -> 10508 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erl_boot_server.beambin5268 -> 5696 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erl_ddll.beambin2464 -> 2560 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erl_distribution.beambin1748 -> 1836 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erl_epmd.beambin6576 -> 7064 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erl_reply.beambin868 -> 912 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/error_handler.beambin1828 -> 1952 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/error_logger.beambin4084 -> 4344 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erts_debug.beambin2608 -> 2808 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/file.beambin11368 -> 12212 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/file_io_server.beambin13104 -> 14196 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/file_server.beambin4828 -> 5124 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/gen_sctp.beambin3164 -> 3528 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/gen_tcp.beambin2284 -> 2432 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/gen_udp.beambin1536 -> 1644 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/global.beambin29312 -> 32236 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/global_group.beambin16160 -> 17728 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/global_search.beambin2768 -> 3088 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/group.beambin10884 -> 11776 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/heart.beambin3624 -> 3912 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/hipe_unified_loader.beambin11460 -> 12540 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet.beambin18124 -> 19924 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet6_sctp.beambin1340 -> 1556 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet6_tcp.beambin2524 -> 2684 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet6_tcp_dist.beambin5832 -> 6256 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet6_udp.beambin1640 -> 1732 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_config.beambin8280 -> 8192 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_db.beambin24664 -> 26424 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_dns.beambin18712 -> 19748 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_gethost_native.beambin9680 -> 10500 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_hosts.beambin2016 -> 2112 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_parse.beambin11968 -> 13056 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_res.beambin13856 -> 14816 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_sctp.beambin2068 -> 2316 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_tcp.beambin2332 -> 2492 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_tcp_dist.beambin6116 -> 6540 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_udp.beambin1808 -> 1920 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/kernel.app120
-rw-r--r--bootstrap/lib/kernel/ebin/kernel.appup1
-rw-r--r--bootstrap/lib/kernel/ebin/kernel.beambin3596 -> 3792 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/kernel_config.beambin2556 -> 2720 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/net.beambin584 -> 616 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/net_adm.beambin2864 -> 3064 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/net_kernel.beambin21036 -> 22720 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/os.beambin4872 -> 5228 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/packages.beambin2096 -> 2244 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/pg2.beambin6984 -> 7696 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/ram_file.beambin6512 -> 6800 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/rpc.beambin8204 -> 8748 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/seq_trace.beambin1256 -> 1336 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/standard_error.beambin3460 -> 3636 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/user.beambin11460 -> 12360 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/user_drv.beambin9324 -> 10308 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/user_sup.beambin1676 -> 1768 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/wrap_log_reader.beambin3156 -> 3384 bytes
-rw-r--r--bootstrap/lib/kernel/include/dist.hrl (renamed from lib/kernel/src/dist.hrl)0
-rw-r--r--bootstrap/lib/kernel/include/dist_util.hrl (renamed from lib/kernel/src/dist_util.hrl)0
-rw-r--r--bootstrap/lib/kernel/include/inet_sctp.hrl2
-rw-r--r--bootstrap/lib/kernel/include/net_address.hrl (renamed from lib/kernel/src/net_address.hrl)0
-rw-r--r--bootstrap/lib/orber/include/Makefile66
-rw-r--r--bootstrap/lib/orber/include/corba.hrl148
-rw-r--r--bootstrap/lib/orber/include/ifr_types.hrl72
-rw-r--r--bootstrap/lib/orber/include/orber_pi.hrl76
-rw-r--r--bootstrap/lib/stdlib/ebin/array.beambin10720 -> 12036 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/base64.beambin4096 -> 4540 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/beam_lib.beambin16504 -> 18220 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/binary.beambin2480 -> 2640 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/c.beambin12752 -> 13932 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/calendar.beambin4696 -> 5176 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets.beambin48400 -> 53468 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_server.beambin6432 -> 7020 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_sup.beambin540 -> 552 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_utils.beambin25752 -> 28864 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_v8.beambin25132 -> 27520 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_v9.beambin45776 -> 50104 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dict.beambin8392 -> 9140 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/digraph.beambin7664 -> 8320 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/digraph_utils.beambin6252 -> 6800 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/edlin.beambin7392 -> 7912 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/edlin_expand.beambin2816 -> 3044 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/epp.beambin22132 -> 24188 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_bits.beambin2468 -> 2568 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_compile.beambin4736 -> 5076 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_eval.beambin21544 -> 23552 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_expand_records.beambin19888 -> 21812 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_internal.beambin4980 -> 5016 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_lint.beambin77224 -> 84904 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_parse.beambin66332 -> 71496 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_posix_msg.beambin4992 -> 5008 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_pp.beambin21384 -> 23344 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_scan.beambin30424 -> 31776 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_tar.beambin14320 -> 15352 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/error_logger_file_h.beambin4588 -> 5056 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/error_logger_tty_h.beambin4332 -> 4936 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/escript.beambin15428 -> 17044 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/ets.beambin18268 -> 20048 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/eval_bits.beambin6136 -> 6748 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/file_sorter.beambin28196 -> 30608 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/filelib.beambin6728 -> 7280 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/filename.beambin11628 -> 12560 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gb_sets.beambin7544 -> 8256 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gb_trees.beambin4624 -> 4992 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gen.beambin3592 -> 3864 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gen_event.beambin12064 -> 17412 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gen_fsm.beambin8880 -> 14764 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gen_server.beambin11776 -> 16780 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/io.beambin6172 -> 6608 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/io_lib.beambin8300 -> 8900 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/io_lib_format.beambin10928 -> 11960 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/io_lib_fread.beambin6836 -> 7404 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/io_lib_pretty.beambin11260 -> 12372 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/lib.beambin8148 -> 9072 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/lists.beambin27432 -> 29204 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/log_mf_h.beambin2444 -> 2644 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/math.beambin296 -> 308 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/ms_transform.beambin18684 -> 20224 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/orddict.beambin2620 -> 2748 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/ordsets.beambin1808 -> 1900 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/otp_internal.beambin8928 -> 9140 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/pg.beambin1932 -> 2064 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/pool.beambin3616 -> 3848 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/proc_lib.beambin8472 -> 9200 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/proplists.beambin4560 -> 4852 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/qlc.beambin64240 -> 69376 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/qlc_pt.beambin65960 -> 71592 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/queue.beambin5552 -> 5900 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/random.beambin1400 -> 1576 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/re.beambin11268 -> 12376 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/regexp.beambin7860 -> 8524 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/sets.beambin6456 -> 7020 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/shell.beambin28172 -> 30568 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/shell_default.beambin3552 -> 3884 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/slave.beambin4100 -> 4424 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/sofs.beambin37972 -> 41096 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/stdlib.app106
-rw-r--r--bootstrap/lib/stdlib/ebin/stdlib.appup1
-rw-r--r--bootstrap/lib/stdlib/ebin/string.beambin4328 -> 4744 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/supervisor.beambin16400 -> 21220 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/supervisor_bridge.beambin1908 -> 2760 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/sys.beambin6828 -> 7328 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/timer.beambin4924 -> 5452 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/unicode.beambin10808 -> 11552 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/win32reg.beambin5292 -> 5652 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/zip.beambin24552 -> 26824 bytes
-rw-r--r--bootstrap/lib/stdlib/egen/erl_parse.erl9680
-rw-r--r--bootstrap/lib/stdlib/include/erl_bits.hrl2
-rw-r--r--bootstrap/lib/stdlib/include/erl_compile.hrl2
-rw-r--r--bootstrap/lib/stdlib/include/ms_transform.hrl2
-rw-r--r--bootstrap/lib/stdlib/include/qlc.hrl2
-rw-r--r--configure.in6
-rw-r--r--erts/Makefile.in3
-rw-r--r--erts/aclocal.m4445
-rwxr-xr-xerts/autoconf/win32.config.cache.static2
-rw-r--r--erts/configure.in67
-rw-r--r--erts/doc/specs/.gitignore1
-rw-r--r--erts/doc/src/Makefile38
-rw-r--r--erts/doc/src/absform.xml3
-rw-r--r--erts/doc/src/alt_dist.xml4
-rw-r--r--erts/doc/src/epmd.xml4
-rw-r--r--erts/doc/src/erl.xml11
-rw-r--r--erts/doc/src/erl_driver.xml19
-rw-r--r--[-rwxr-xr-x]erts/doc/src/erl_ext_fig.gifbin3834 -> 3834 bytes
-rw-r--r--erts/doc/src/erl_nif.xml17
-rw-r--r--erts/doc/src/erl_prim_loader.xml88
-rw-r--r--erts/doc/src/erlang.xml685
-rw-r--r--erts/doc/src/erlsrv.xml19
-rw-r--r--erts/doc/src/erts_alloc.xml78
-rw-r--r--erts/doc/src/init.xml67
-rw-r--r--erts/doc/src/make.dep32
-rw-r--r--erts/doc/src/notes.xml353
-rw-r--r--erts/doc/src/specs.xml7
-rw-r--r--erts/doc/src/start_erl.xml31
-rw-r--r--erts/doc/src/zlib.xml363
-rw-r--r--erts/emulator/Makefile.in43
-rw-r--r--erts/emulator/beam/atom.c8
-rw-r--r--erts/emulator/beam/atom.names5
-rw-r--r--erts/emulator/beam/beam_bif_load.c149
-rw-r--r--erts/emulator/beam/beam_bp.c50
-rw-r--r--erts/emulator/beam/beam_bp.h6
-rw-r--r--erts/emulator/beam/beam_catches.c46
-rw-r--r--erts/emulator/beam/beam_debug.c32
-rw-r--r--erts/emulator/beam/beam_emu.c562
-rw-r--r--erts/emulator/beam/beam_load.c1428
-rw-r--r--erts/emulator/beam/beam_load.h15
-rw-r--r--erts/emulator/beam/bif.c220
-rw-r--r--erts/emulator/beam/bif.h155
-rw-r--r--erts/emulator/beam/bif.tab14
-rw-r--r--erts/emulator/beam/big.c56
-rw-r--r--erts/emulator/beam/big.h1
-rw-r--r--erts/emulator/beam/binary.c10
-rw-r--r--erts/emulator/beam/break.c20
-rw-r--r--erts/emulator/beam/dist.c78
-rw-r--r--erts/emulator/beam/dist.h4
-rw-r--r--erts/emulator/beam/erl_afit_alloc.c20
-rw-r--r--erts/emulator/beam/erl_alloc.c1349
-rw-r--r--erts/emulator/beam/erl_alloc.h210
-rw-r--r--erts/emulator/beam/erl_alloc.types62
-rw-r--r--erts/emulator/beam/erl_alloc_util.c1024
-rw-r--r--erts/emulator/beam/erl_alloc_util.h109
-rw-r--r--erts/emulator/beam/erl_ao_firstfit_alloc.c976
-rw-r--r--erts/emulator/beam/erl_ao_firstfit_alloc.h60
-rw-r--r--erts/emulator/beam/erl_arith.c8
-rw-r--r--erts/emulator/beam/erl_async.c737
-rw-r--r--erts/emulator/beam/erl_async.h66
-rw-r--r--erts/emulator/beam/erl_bestfit_alloc.c19
-rw-r--r--erts/emulator/beam/erl_bestfit_alloc.h2
-rw-r--r--erts/emulator/beam/erl_bif_binary.c64
-rw-r--r--erts/emulator/beam/erl_bif_ddll.c145
-rw-r--r--erts/emulator/beam/erl_bif_info.c474
-rw-r--r--erts/emulator/beam/erl_bif_lists.c104
-rw-r--r--erts/emulator/beam/erl_bif_op.c25
-rw-r--r--erts/emulator/beam/erl_bif_os.c24
-rw-r--r--erts/emulator/beam/erl_bif_port.c75
-rw-r--r--erts/emulator/beam/erl_bif_re.c135
-rw-r--r--erts/emulator/beam/erl_bif_timer.c3
-rw-r--r--erts/emulator/beam/erl_bif_trace.c144
-rw-r--r--erts/emulator/beam/erl_bits.c22
-rw-r--r--erts/emulator/beam/erl_bits.h4
-rw-r--r--erts/emulator/beam/erl_cpu_topology.c4
-rw-r--r--erts/emulator/beam/erl_db.c209
-rw-r--r--erts/emulator/beam/erl_db.h8
-rw-r--r--erts/emulator/beam/erl_db_hash.c117
-rw-r--r--erts/emulator/beam/erl_db_hash.h3
-rw-r--r--erts/emulator/beam/erl_db_tree.c34
-rw-r--r--erts/emulator/beam/erl_db_util.c62
-rw-r--r--erts/emulator/beam/erl_db_util.h6
-rw-r--r--erts/emulator/beam/erl_driver.h15
-rw-r--r--erts/emulator/beam/erl_drv_thread.c8
-rw-r--r--erts/emulator/beam/erl_gc.c102
-rw-r--r--erts/emulator/beam/erl_goodfit_alloc.c20
-rw-r--r--erts/emulator/beam/erl_init.c173
-rw-r--r--erts/emulator/beam/erl_instrument.c10
-rw-r--r--erts/emulator/beam/erl_lock_check.c14
-rw-r--r--erts/emulator/beam/erl_message.c4
-rw-r--r--erts/emulator/beam/erl_monitors.c20
-rw-r--r--erts/emulator/beam/erl_mtrace.c8
-rw-r--r--erts/emulator/beam/erl_nif.c93
-rw-r--r--erts/emulator/beam/erl_nif.h3
-rw-r--r--erts/emulator/beam/erl_nif_api_funcs.h202
-rw-r--r--erts/emulator/beam/erl_node_tables.c11
-rw-r--r--erts/emulator/beam/erl_port_task.c73
-rw-r--r--erts/emulator/beam/erl_port_task.h8
-rw-r--r--erts/emulator/beam/erl_process.c1786
-rw-r--r--erts/emulator/beam/erl_process.h132
-rw-r--r--erts/emulator/beam/erl_process_dump.c2
-rw-r--r--erts/emulator/beam/erl_process_lock.c33
-rw-r--r--erts/emulator/beam/erl_process_lock.h39
-rw-r--r--erts/emulator/beam/erl_sched_spec_pre_alloc.c305
-rw-r--r--erts/emulator/beam/erl_sched_spec_pre_alloc.h239
-rw-r--r--erts/emulator/beam/erl_smp.h983
-rw-r--r--erts/emulator/beam/erl_term.h8
-rw-r--r--erts/emulator/beam/erl_thr_progress.c1373
-rw-r--r--erts/emulator/beam/erl_thr_progress.h233
-rw-r--r--erts/emulator/beam/erl_thr_queue.c745
-rw-r--r--erts/emulator/beam/erl_thr_queue.h211
-rw-r--r--erts/emulator/beam/erl_threads.h956
-rw-r--r--erts/emulator/beam/erl_time.h4
-rw-r--r--erts/emulator/beam/erl_trace.c126
-rw-r--r--erts/emulator/beam/erl_unicode.c36
-rw-r--r--erts/emulator/beam/erl_vm.h8
-rw-r--r--erts/emulator/beam/export.c6
-rw-r--r--erts/emulator/beam/external.c92
-rw-r--r--erts/emulator/beam/external.h7
-rw-r--r--erts/emulator/beam/fix_alloc.c287
-rw-r--r--erts/emulator/beam/global.h69
-rw-r--r--erts/emulator/beam/io.c48
-rw-r--r--erts/emulator/beam/module.c5
-rw-r--r--erts/emulator/beam/ops.tab178
-rw-r--r--erts/emulator/beam/safe_hash.c10
-rw-r--r--erts/emulator/beam/sys.h334
-rw-r--r--erts/emulator/beam/time.c6
-rw-r--r--erts/emulator/beam/utils.c804
-rw-r--r--erts/emulator/drivers/common/efile_drv.c170
-rw-r--r--erts/emulator/drivers/common/inet_drv.c733
-rw-r--r--erts/emulator/drivers/unix/ttsl_drv.c3
-rw-r--r--[-rwxr-xr-x]erts/emulator/drivers/win32/win_efile.c6
-rw-r--r--erts/emulator/hipe/hipe_abi.txt2
-rw-r--r--erts/emulator/hipe/hipe_amd64_bifs.m451
-rw-r--r--erts/emulator/hipe/hipe_arm_bifs.m439
-rw-r--r--erts/emulator/hipe/hipe_bif0.h2
-rw-r--r--erts/emulator/hipe/hipe_bif2.c23
-rw-r--r--erts/emulator/hipe/hipe_bif_list.m426
-rw-r--r--erts/emulator/hipe/hipe_mkliterals.c74
-rw-r--r--erts/emulator/hipe/hipe_mode_switch.c52
-rw-r--r--erts/emulator/hipe/hipe_native_bif.c49
-rw-r--r--erts/emulator/hipe/hipe_native_bif.h17
-rw-r--r--erts/emulator/hipe/hipe_ppc_asm.m411
-rw-r--r--erts/emulator/hipe/hipe_ppc_bifs.m459
-rw-r--r--erts/emulator/hipe/hipe_process.h3
-rw-r--r--erts/emulator/hipe/hipe_risc_glue.h16
-rw-r--r--erts/emulator/hipe/hipe_sparc_bifs.m465
-rw-r--r--erts/emulator/hipe/hipe_x86_bifs.m455
-rw-r--r--erts/emulator/hipe/hipe_x86_glue.h19
-rw-r--r--erts/emulator/pcre/Makefile26
-rw-r--r--erts/emulator/pcre/Makefile.in165
-rw-r--r--erts/emulator/pcre/pcre.mk113
-rw-r--r--erts/emulator/sys/common/erl_check_io.c53
-rw-r--r--erts/emulator/sys/common/erl_check_io.h9
-rw-r--r--erts/emulator/sys/common/erl_mseg.c668
-rw-r--r--erts/emulator/sys/common/erl_mseg.h11
-rw-r--r--erts/emulator/sys/common/erl_poll.c281
-rw-r--r--erts/emulator/sys/common/erl_poll.h5
-rw-r--r--erts/emulator/sys/unix/erl_unix_sys.h6
-rw-r--r--erts/emulator/sys/unix/sys.c287
-rw-r--r--erts/emulator/sys/vxworks/sys.c20
-rw-r--r--erts/emulator/sys/win32/erl_poll.c68
-rw-r--r--erts/emulator/sys/win32/sys.c198
-rw-r--r--erts/emulator/sys/win32/sys_env.c14
-rw-r--r--erts/emulator/sys/win32/sys_interrupt.c9
-rw-r--r--erts/emulator/test/alloc_SUITE_data/allocator_test.h20
-rw-r--r--erts/emulator/test/alloc_SUITE_data/coalesce.c2
-rw-r--r--erts/emulator/test/alloc_SUITE_data/rbtree.c86
-rw-r--r--erts/emulator/test/binary_SUITE.erl57
-rw-r--r--erts/emulator/test/bs_construct_SUITE.erl17
-rw-r--r--erts/emulator/test/bs_match_misc_SUITE.erl14
-rw-r--r--erts/emulator/test/bs_utf_SUITE.erl12
-rw-r--r--erts/emulator/test/busy_port_SUITE.erl20
-rw-r--r--erts/emulator/test/call_trace_SUITE.erl26
-rw-r--r--erts/emulator/test/code_SUITE.erl196
-rw-r--r--erts/emulator/test/code_SUITE_data/fun_confusion.erl31
-rw-r--r--erts/emulator/test/code_SUITE_data/literals.erl21
-rw-r--r--erts/emulator/test/distribution_SUITE.erl31
-rw-r--r--erts/emulator/test/driver_SUITE.erl158
-rw-r--r--erts/emulator/test/driver_SUITE_data/Makefile.src4
-rw-r--r--erts/emulator/test/driver_SUITE_data/async_blast_drv.c124
-rw-r--r--erts/emulator/test/driver_SUITE_data/thr_free_drv.c241
-rw-r--r--erts/emulator/test/exception_SUITE.erl246
-rw-r--r--erts/emulator/test/float_SUITE.erl101
-rw-r--r--erts/emulator/test/fun_SUITE.erl10
-rw-r--r--erts/emulator/test/guard_SUITE.erl8
-rw-r--r--erts/emulator/test/hibernate_SUITE.erl31
-rw-r--r--erts/emulator/test/match_spec_SUITE.erl61
-rw-r--r--erts/emulator/test/mtx_SUITE.erl13
-rw-r--r--erts/emulator/test/mtx_SUITE_data/mtx_SUITE.c48
-rw-r--r--erts/emulator/test/nif_SUITE.erl104
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_SUITE.c118
-rw-r--r--erts/emulator/test/port_SUITE.erl2
-rw-r--r--erts/emulator/test/process_SUITE.erl99
-rw-r--r--erts/emulator/test/scheduler_SUITE.erl13
-rw-r--r--erts/emulator/test/system_info_SUITE.erl313
-rw-r--r--erts/emulator/test/trace_local_SUITE.erl32
-rwxr-xr-xerts/emulator/utils/beam_makeops261
-rwxr-xr-xerts/emulator/utils/make_preload1
-rwxr-xr-xerts/emulator/utils/make_tables39
-rw-r--r--erts/emulator/valgrind/suppress.patched.3.6.0307
-rw-r--r--erts/emulator/valgrind/suppress.standard268
-rw-r--r--erts/epmd/src/epmd.c6
-rw-r--r--erts/epmd/src/epmd_cli.c7
-rw-r--r--erts/epmd/src/epmd_int.h11
-rw-r--r--erts/epmd/src/epmd_srv.c23
-rw-r--r--erts/etc/common/erlc.c1
-rw-r--r--erts/etc/common/erlexec.c3
-rw-r--r--erts/etc/win32/Install.c5
-rw-r--r--erts/etc/win32/erlsrv/erlsrv_interactive.c191
-rw-r--r--erts/etc/win32/erlsrv/erlsrv_interactive.h4
-rw-r--r--[-rwxr-xr-x]erts/etc/win32/nsis/erlang_uninst.icobin766 -> 766 bytes
-rw-r--r--erts/etc/win32/start_erl.c161
-rw-r--r--erts/example/matrix_nif.c87
-rw-r--r--erts/include/internal/ethr_atomics.h8932
-rw-r--r--erts/include/internal/ethr_internal.h6
-rw-r--r--erts/include/internal/ethr_mutex.h145
-rw-r--r--erts/include/internal/ethr_optimized_fallbacks.h175
-rw-r--r--erts/include/internal/ethread.h163
-rw-r--r--erts/include/internal/ethread_header_config.h.in118
-rw-r--r--erts/include/internal/gcc/ethr_atomic.h251
-rw-r--r--erts/include/internal/gcc/ethr_dw_atomic.h115
-rw-r--r--erts/include/internal/gcc/ethr_membar.h73
-rw-r--r--erts/include/internal/gcc/ethread.h20
-rw-r--r--erts/include/internal/i386/atomic.h334
-rw-r--r--erts/include/internal/i386/ethr_dw_atomic.h278
-rw-r--r--erts/include/internal/i386/ethr_membar.h114
-rw-r--r--erts/include/internal/i386/ethread.h8
-rw-r--r--erts/include/internal/i386/rwlock.h5
-rw-r--r--erts/include/internal/i386/spinlock.h27
-rw-r--r--erts/include/internal/libatomic_ops/ethr_atomic.h298
-rw-r--r--erts/include/internal/libatomic_ops/ethr_membar.h75
-rw-r--r--erts/include/internal/libatomic_ops/ethread.h14
-rw-r--r--erts/include/internal/ppc32/atomic.h148
-rw-r--r--erts/include/internal/ppc32/ethr_membar.h63
-rw-r--r--erts/include/internal/ppc32/ethread.h5
-rw-r--r--erts/include/internal/ppc32/rwlock.h15
-rw-r--r--erts/include/internal/ppc32/spinlock.h10
-rw-r--r--erts/include/internal/pthread/ethr_event.h8
-rw-r--r--erts/include/internal/sparc32/atomic.h194
-rw-r--r--erts/include/internal/sparc32/ethr_membar.h115
-rw-r--r--erts/include/internal/sparc32/ethread.h7
-rw-r--r--erts/include/internal/sparc32/rwlock.h17
-rw-r--r--erts/include/internal/sparc32/spinlock.h11
-rw-r--r--erts/include/internal/tile/atomic.h136
-rw-r--r--erts/include/internal/tile/ethr_membar.h (renamed from lib/ssl/c_src/esock_winsock.h)37
-rw-r--r--erts/include/internal/tile/ethread.h5
-rw-r--r--erts/include/internal/win/ethr_atomic.h595
-rw-r--r--erts/include/internal/win/ethr_dw_atomic.h154
-rw-r--r--erts/include/internal/win/ethr_event.h16
-rw-r--r--erts/include/internal/win/ethr_membar.h145
-rw-r--r--erts/include/internal/win/ethread.h4
-rw-r--r--erts/lib_src/Makefile.in14
-rw-r--r--erts/lib_src/common/erl_misc_utils.c8
-rw-r--r--erts/lib_src/common/erl_printf.c14
-rw-r--r--erts/lib_src/common/erl_printf_format.c4
-rw-r--r--erts/lib_src/common/ethr_atomics.c4259
-rw-r--r--erts/lib_src/common/ethr_aux.c83
-rw-r--r--erts/lib_src/common/ethr_mutex.c501
-rw-r--r--erts/lib_src/pthread/ethr_x86_sse2_asm.c31
-rw-r--r--erts/lib_src/pthread/ethread.c102
-rwxr-xr-xerts/lib_src/utils/make_atomics_api2186
-rw-r--r--erts/lib_src/win/ethr_event.c22
-rw-r--r--erts/lib_src/win/ethread.c22
-rw-r--r--erts/preloaded/ebin/erl_prim_loader.beambin50392 -> 53080 bytes
-rw-r--r--erts/preloaded/ebin/erlang.beambin24148 -> 39568 bytes
-rw-r--r--erts/preloaded/ebin/init.beambin44880 -> 45264 bytes
-rw-r--r--erts/preloaded/ebin/otp_ring0.beambin1436 -> 1528 bytes
-rw-r--r--erts/preloaded/ebin/prim_file.beambin31528 -> 32448 bytes
-rw-r--r--erts/preloaded/ebin/prim_inet.beambin64892 -> 69916 bytes
-rw-r--r--erts/preloaded/ebin/prim_zip.beambin22444 -> 22532 bytes
-rw-r--r--erts/preloaded/ebin/zlib.beambin10620 -> 11836 bytes
-rw-r--r--erts/preloaded/src/erl_prim_loader.erl75
-rw-r--r--erts/preloaded/src/erlang.erl550
-rw-r--r--erts/preloaded/src/init.erl33
-rw-r--r--erts/preloaded/src/prim_file.erl31
-rw-r--r--erts/preloaded/src/prim_inet.erl162
-rw-r--r--erts/preloaded/src/prim_zip.erl4
-rw-r--r--erts/preloaded/src/zlib.erl227
-rw-r--r--erts/test/autoimport_SUITE.erl11
-rw-r--r--erts/test/erlc_SUITE.erl27
-rw-r--r--erts/test/ethread_SUITE.erl32
-rw-r--r--erts/test/ethread_SUITE_data/ethread_tests.c428
-rw-r--r--erts/test/nt_SUITE.erl8
-rw-r--r--erts/test/z_SUITE.erl23
-rw-r--r--erts/vsn.mk4
-rw-r--r--lib/Makefile37
-rw-r--r--lib/appmon/doc/src/make.dep26
-rw-r--r--lib/appmon/src/appmon_web.erl6
-rw-r--r--lib/asn1/c_src/Makefile41
-rw-r--r--lib/asn1/c_src/asn1_erl_driver.c1677
-rw-r--r--lib/asn1/c_src/asn1_erl_nif.c1305
-rw-r--r--lib/asn1/doc/src/Makefile90
-rw-r--r--lib/asn1/doc/src/asn1_spec.xmlsrc8
-rw-r--r--lib/asn1/doc/src/asn1_ug.xml50
-rw-r--r--lib/asn1/doc/src/asn1ct.xml41
-rw-r--r--lib/asn1/doc/src/asn1rt.xml65
-rw-r--r--lib/asn1/doc/src/make.dep31
-rw-r--r--lib/asn1/doc/src/notes.xml19
-rw-r--r--lib/asn1/src/Makefile4
-rw-r--r--lib/asn1/src/asn1.app.src5
-rw-r--r--lib/asn1/src/asn1_app.erl2
-rw-r--r--lib/asn1/src/asn1_server.erl107
-rw-r--r--lib/asn1/src/asn1ct.erl41
-rw-r--r--lib/asn1/src/asn1ct_check.erl50
-rw-r--r--lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl12
-rw-r--r--lib/asn1/src/asn1ct_constructed_per.erl116
-rw-r--r--lib/asn1/src/asn1ct_gen.erl35
-rw-r--r--lib/asn1/src/asn1ct_gen_ber_bin_v2.erl25
-rw-r--r--lib/asn1/src/asn1ct_gen_per.erl5
-rw-r--r--lib/asn1/src/asn1ct_gen_per_rt2ct.erl5
-rw-r--r--lib/asn1/src/asn1ct_value.erl8
-rw-r--r--lib/asn1/src/asn1rt.erl40
-rw-r--r--lib/asn1/src/asn1rt_ber_bin_v2.erl160
-rw-r--r--lib/asn1/src/asn1rt_check.erl2
-rw-r--r--lib/asn1/src/asn1rt_driver_handler.erl144
-rw-r--r--lib/asn1/src/asn1rt_nif.erl87
-rw-r--r--lib/asn1/src/asn1rt_per_bin.erl4
-rw-r--r--lib/asn1/src/asn1rt_per_bin_rt2ct.erl131
-rw-r--r--lib/asn1/test/asn1.cover1
-rw-r--r--lib/asn1/test/asn1_SUITE.erl.src10
-rw-r--r--[-rwxr-xr-x]lib/asn1/test/asn1_SUITE_data/DirectoryAbstractService.asn0
-rw-r--r--[-rwxr-xr-x]lib/asn1/test/asn1_SUITE_data/InformationFramework.asn0
-rw-r--r--[-rwxr-xr-x]lib/asn1/test/asn1_SUITE_data/LDAP.asn10
-rw-r--r--[-rwxr-xr-x]lib/asn1/test/asn1_SUITE_data/Nortel.asn0
-rw-r--r--[-rwxr-xr-x]lib/asn1/test/asn1_SUITE_data/UpperBounds.asn0
-rw-r--r--[-rwxr-xr-x]lib/asn1/test/asn1_SUITE_data/UsefulDefinitions.asn0
-rw-r--r--[-rwxr-xr-x]lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-CommonDataTypes.asn0
-rw-r--r--[-rwxr-xr-x]lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-Constants.asn0
-rw-r--r--[-rwxr-xr-x]lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-Containers.asn0
-rw-r--r--[-rwxr-xr-x]lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-IEs.asn0
-rw-r--r--[-rwxr-xr-x]lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Contents.asn0
-rw-r--r--[-rwxr-xr-x]lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Discriptions.asn0
-rw-r--r--lib/asn1/test/asn1_bin_v2_particular_SUITE.erl.src270
-rw-r--r--lib/asn1/test/ber_decode_error.erl6
-rw-r--r--lib/asn1/test/testPrim.erl21
-rw-r--r--lib/asn1/test/test_compile_options.erl41
-rw-r--r--lib/asn1/vsn.mk2
-rw-r--r--lib/common_test/doc/src/Makefile15
-rw-r--r--lib/common_test/doc/src/common_test_app.xml34
-rw-r--r--lib/common_test/doc/src/config_file_chapter.xml6
-rw-r--r--lib/common_test/doc/src/ct_hooks.xml10
-rw-r--r--lib/common_test/doc/src/ct_hooks_chapter.xml51
-rw-r--r--lib/common_test/doc/src/ct_run.xml7
-rw-r--r--[-rwxr-xr-x]lib/common_test/doc/src/filestruct.gifbin2960 -> 2960 bytes
-rw-r--r--lib/common_test/doc/src/make.dep27
-rw-r--r--lib/common_test/doc/src/notes.xml223
-rw-r--r--lib/common_test/doc/src/run_test_chapter.xml52
-rw-r--r--lib/common_test/doc/src/write_test_chapter.xml14
-rw-r--r--lib/common_test/include/ct.hrl3
-rw-r--r--lib/common_test/src/Makefile7
-rw-r--r--lib/common_test/src/common_test.app.src1
-rw-r--r--lib/common_test/src/ct.erl8
-rw-r--r--lib/common_test/src/ct_config.erl40
-rw-r--r--lib/common_test/src/ct_config_plain.erl24
-rw-r--r--lib/common_test/src/ct_config_xml.erl48
-rw-r--r--lib/common_test/src/ct_framework.erl131
-rw-r--r--lib/common_test/src/ct_hooks.erl166
-rw-r--r--lib/common_test/src/ct_line.erl266
-rw-r--r--lib/common_test/src/ct_logs.erl83
-rw-r--r--lib/common_test/src/ct_make.erl2
-rw-r--r--lib/common_test/src/ct_run.erl607
-rw-r--r--lib/common_test/src/ct_telnet.erl9
-rw-r--r--lib/common_test/src/ct_testspec.erl35
-rw-r--r--lib/common_test/src/ct_util.erl137
-rw-r--r--lib/common_test/src/ct_util.hrl5
-rw-r--r--lib/common_test/src/cth_log_redirect.erl111
-rw-r--r--lib/common_test/src/vts.erl133
-rw-r--r--lib/common_test/test/ct_error_SUITE.erl225
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_9_SUITE.erl22
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_3_SUITE.erl146
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_4_SUITE.erl135
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_5_SUITE.erl155
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_6_SUITE.erl114
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_7_SUITE.erl137
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_utils.erl43
-rw-r--r--lib/common_test/test/ct_groups_test_2_SUITE.erl6
-rw-r--r--lib/common_test/test/ct_hooks_SUITE.erl80
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_prio_SUITE.erl62
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl11
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/prio_cth.erl74
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/state_update_cth.erl2
-rw-r--r--lib/common_test/test/ct_repeat_1_SUITE.erl7
-rw-r--r--lib/common_test/test/ct_skip_SUITE.erl9
-rw-r--r--lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl2
-rw-r--r--lib/common_test/test/ct_test_support.erl7
-rw-r--r--lib/common_test/vsn.mk2
-rw-r--r--lib/compiler/doc/src/compile.xml8
-rw-r--r--lib/compiler/doc/src/make.dep19
-rw-r--r--lib/compiler/doc/src/notes.xml28
-rw-r--r--lib/compiler/src/beam_asm.erl113
-rw-r--r--lib/compiler/src/beam_block.erl35
-rw-r--r--lib/compiler/src/beam_bsm.erl9
-rw-r--r--lib/compiler/src/beam_clean.erl26
-rw-r--r--lib/compiler/src/beam_dead.erl10
-rw-r--r--lib/compiler/src/beam_dict.erl66
-rw-r--r--lib/compiler/src/beam_disasm.erl35
-rw-r--r--lib/compiler/src/beam_jump.erl49
-rw-r--r--lib/compiler/src/beam_listing.erl2
-rw-r--r--lib/compiler/src/beam_receive.erl2
-rw-r--r--lib/compiler/src/beam_trim.erl13
-rw-r--r--lib/compiler/src/beam_type.erl3
-rw-r--r--lib/compiler/src/beam_utils.erl16
-rw-r--r--lib/compiler/src/beam_validator.erl15
-rw-r--r--lib/compiler/src/compile.erl58
-rw-r--r--lib/compiler/src/erl_bifs.erl1
-rw-r--r--lib/compiler/src/genop.tab4
-rw-r--r--lib/compiler/src/sys_pre_expand.erl79
-rw-r--r--lib/compiler/src/v3_codegen.erl108
-rw-r--r--lib/compiler/src/v3_core.erl45
-rw-r--r--lib/compiler/src/v3_kernel.erl35
-rw-r--r--lib/compiler/src/v3_life.erl4
-rw-r--r--lib/compiler/test/Makefile1
-rw-r--r--lib/compiler/test/beam_disasm_SUITE.erl65
-rw-r--r--lib/compiler/test/bs_match_SUITE.erl4
-rw-r--r--lib/compiler/test/bs_utf_SUITE.erl21
-rw-r--r--lib/compiler/test/compile_SUITE.erl1
-rw-r--r--lib/compiler/test/error_SUITE.erl65
-rw-r--r--lib/compiler/test/fun_SUITE.erl52
-rw-r--r--lib/compiler/test/guard_SUITE.erl29
-rw-r--r--lib/compiler/test/inline_SUITE.erl3
-rw-r--r--lib/compiler/test/lc_SUITE.erl4
-rw-r--r--lib/compiler/test/misc_SUITE.erl4
-rw-r--r--lib/compiler/test/pmod_SUITE.erl4
-rw-r--r--lib/compiler/test/trycatch_SUITE.erl16
-rw-r--r--lib/compiler/vsn.mk2
-rw-r--r--lib/cosEvent/doc/src/Makefile84
-rw-r--r--lib/cosEvent/doc/src/make.dep34
-rw-r--r--lib/cosEvent/src/Makefile14
-rw-r--r--lib/cosEvent/test/Makefile14
-rw-r--r--lib/cosEventDomain/doc/src/Makefile87
-rw-r--r--lib/cosEventDomain/doc/src/make.dep23
-rw-r--r--lib/cosEventDomain/src/Makefile9
-rw-r--r--lib/cosFileTransfer/doc/src/CosFileTransfer_FileTransferSession.xml4
-rw-r--r--lib/cosFileTransfer/doc/src/Makefile87
-rw-r--r--lib/cosFileTransfer/doc/src/make.dep30
-rw-r--r--lib/cosFileTransfer/doc/src/notes.xml16
-rw-r--r--lib/cosFileTransfer/src/CosFileTransfer_FileTransferSession_impl.erl4
-rw-r--r--lib/cosFileTransfer/src/Makefile9
-rw-r--r--lib/cosFileTransfer/vsn.mk2
-rw-r--r--lib/cosNotification/doc/src/Makefile86
-rw-r--r--lib/cosNotification/doc/src/make.dep48
-rw-r--r--lib/cosNotification/src/Makefile31
-rw-r--r--lib/cosNotification/test/Makefile11
-rw-r--r--lib/cosProperty/doc/src/Makefile98
-rw-r--r--lib/cosProperty/doc/src/make.dep26
-rw-r--r--lib/cosProperty/src/Makefile8
-rw-r--r--lib/cosTime/doc/src/Makefile86
-rw-r--r--lib/cosTime/doc/src/make.dep22
-rw-r--r--lib/cosTime/src/Makefile13
-rw-r--r--lib/cosTransactions/doc/src/Makefile86
-rw-r--r--lib/cosTransactions/doc/src/make.dep27
-rw-r--r--lib/cosTransactions/src/Makefile9
-rw-r--r--lib/cosTransactions/test/Makefile11
-rw-r--r--lib/crypto/c_src/Makefile.in13
-rw-r--r--lib/crypto/c_src/crypto.c75
-rw-r--r--lib/crypto/doc/src/crypto.xml113
-rw-r--r--lib/crypto/doc/src/make.dep20
-rw-r--r--lib/crypto/doc/src/notes.xml25
-rw-r--r--lib/crypto/src/crypto.erl96
-rw-r--r--lib/crypto/test/crypto_SUITE.erl154
-rw-r--r--lib/crypto/vsn.mk2
-rw-r--r--lib/debugger/doc/src/debugger_chapter.xml42
-rw-r--r--lib/debugger/doc/src/int.xml4
-rw-r--r--lib/debugger/doc/src/make.dep29
-rw-r--r--lib/debugger/src/Makefile1
-rw-r--r--lib/debugger/src/dbg_debugged.erl15
-rw-r--r--lib/debugger/src/dbg_icmd.erl16
-rw-r--r--lib/debugger/src/dbg_ieval.erl570
-rw-r--r--lib/debugger/src/dbg_ieval.hrl8
-rw-r--r--lib/debugger/src/dbg_iload.erl356
-rw-r--r--lib/debugger/src/dbg_iserver.erl5
-rw-r--r--lib/debugger/src/dbg_istk.erl245
-rw-r--r--lib/debugger/src/dbg_ui_break_win.erl26
-rw-r--r--lib/debugger/src/dbg_ui_edit_win.erl8
-rw-r--r--lib/debugger/src/dbg_ui_filedialog_win.erl2
-rw-r--r--lib/debugger/src/dbg_ui_interpret.erl2
-rw-r--r--lib/debugger/src/dbg_ui_settings.erl4
-rw-r--r--lib/debugger/src/dbg_wx_break_win.erl30
-rw-r--r--lib/debugger/src/dbg_wx_filedialog_win.erl2
-rw-r--r--lib/debugger/src/dbg_wx_settings.erl6
-rw-r--r--[-rwxr-xr-x]lib/debugger/src/dbg_wx_trace_win.erl0
-rw-r--r--[-rwxr-xr-x]lib/debugger/src/dbg_wx_winman.erl0
-rw-r--r--lib/debugger/src/debugger.app.src1
-rw-r--r--lib/debugger/test/Makefile1
-rw-r--r--lib/debugger/test/bs_construct_SUITE.erl395
-rw-r--r--lib/debugger/test/bs_match_bin_SUITE.erl141
-rw-r--r--lib/debugger/test/bs_match_int_SUITE.erl206
-rw-r--r--lib/debugger/test/bs_match_misc_SUITE.erl453
-rw-r--r--lib/debugger/test/bs_match_tail_SUITE.erl12
-rw-r--r--lib/debugger/test/bug_SUITE.erl4
-rw-r--r--lib/debugger/test/exception_SUITE.erl264
-rw-r--r--lib/debugger/test/fun_SUITE.erl52
-rw-r--r--lib/debugger/test/guard_SUITE.erl217
-rw-r--r--lib/debugger/test/int_eval_SUITE.erl47
-rw-r--r--lib/debugger/test/int_eval_SUITE_data/my_int_eval_module.erl4
-rw-r--r--lib/debugger/test/int_eval_SUITE_data/stacktrace.erl130
-rw-r--r--lib/debugger/test/lc_SUITE.erl119
-rw-r--r--lib/debugger/test/line_number_SUITE.erl220
-rw-r--r--lib/debugger/test/test_lib.erl2
-rw-r--r--lib/debugger/test/trycatch_SUITE.erl17
-rw-r--r--[-rwxr-xr-x]lib/dialyzer/doc/src/Makefile0
-rw-r--r--[-rwxr-xr-x]lib/dialyzer/doc/src/book.xml0
-rw-r--r--[-rwxr-xr-x]lib/dialyzer/doc/src/fascicules.xml0
-rwxr-xr-xlib/dialyzer/doc/src/make.dep20
-rw-r--r--[-rwxr-xr-x]lib/dialyzer/doc/src/notes.xml109
-rw-r--r--[-rwxr-xr-x]lib/dialyzer/doc/src/part.xml0
-rw-r--r--[-rwxr-xr-x]lib/dialyzer/doc/src/part_notes.xml0
-rw-r--r--[-rwxr-xr-x]lib/dialyzer/doc/src/ref_man.xml0
-rw-r--r--[-rwxr-xr-x]lib/dialyzer/info0
-rw-r--r--lib/dialyzer/src/dialyzer_contracts.erl2
-rw-r--r--lib/dialyzer/src/dialyzer_dataflow.erl74
-rw-r--r--lib/dialyzer/src/dialyzer_typesig.erl228
-rw-r--r--lib/dialyzer/test/Makefile2
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/crash1
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/results/asn18
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/results/inets43
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/results/mnesia3
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/extract_translations4
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/common_eunit2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/comparisons153
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/failing_funs20
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/flatten2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/higher_order_discrepancy4
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/higher_order_discrepancy_28
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/my_sofs4
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/tuple_set_crash1
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/binary_lc_bug.erl8
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/codec_can.erl35
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/common_eunit.erl121
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/comparisons.erl322
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/failing_funs.erl250
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/file_open_encoding.erl4
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/higher_order_discrepancy.erl14
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/higher_order_discrepancy_2.erl14
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/list_to_bitstring.erl21
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/no_return_bug.erl42
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/nowarnunused.erl7
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/rebar_no_return.erl19
-rw-r--r--lib/dialyzer/vsn.mk2
-rwxr-xr-xlib/diameter/bin/diameterc35
-rw-r--r--lib/diameter/configure.in1
-rw-r--r--lib/diameter/doc/src/Makefile6
-rw-r--r--lib/diameter/doc/src/depend.sed12
-rw-r--r--lib/diameter/doc/src/diameter.xml181
-rw-r--r--lib/diameter/doc/src/diameter_app.xml47
-rw-r--r--lib/diameter/doc/src/diameter_compile.xml32
-rw-r--r--lib/diameter/doc/src/diameter_dict.xml9
-rw-r--r--lib/diameter/doc/src/diameter_sctp.xml10
-rw-r--r--lib/diameter/doc/src/diameter_soc.xml10
-rw-r--r--lib/diameter/doc/src/diameter_tcp.xml57
-rw-r--r--lib/diameter/doc/src/diameter_transport.xml38
-rw-r--r--lib/diameter/doc/src/notes.xml129
-rw-r--r--lib/diameter/include/diameter_gen.hrl12
-rw-r--r--lib/diameter/make/rules.mk.in6
-rw-r--r--lib/diameter/src/.gitignore (renamed from lib/diameter/src/compiler/.gitignore)1
-rw-r--r--lib/diameter/src/Makefile221
-rw-r--r--lib/diameter/src/app/.gitignore6
-rw-r--r--lib/diameter/src/app/Makefile199
-rw-r--r--lib/diameter/src/app/diameter.mk.in47
-rw-r--r--lib/diameter/src/app/diameter_gen_base_accounting.dia68
-rw-r--r--lib/diameter/src/app/diameter_gen_base_rfc3588.dia413
-rw-r--r--lib/diameter/src/app/modules.mk68
-rw-r--r--lib/diameter/src/base/diameter.app.src (renamed from lib/diameter/src/app/diameter.app.src)2
-rw-r--r--lib/diameter/src/base/diameter.appup.src30
-rw-r--r--lib/diameter/src/base/diameter.erl (renamed from lib/diameter/src/app/diameter.erl)0
-rw-r--r--lib/diameter/src/base/diameter_app.erl (renamed from lib/diameter/src/app/diameter_app.erl)0
-rw-r--r--lib/diameter/src/base/diameter_callback.erl (renamed from lib/diameter/src/app/diameter_callback.erl)8
-rw-r--r--lib/diameter/src/base/diameter_capx.erl (renamed from lib/diameter/src/app/diameter_capx.erl)154
-rw-r--r--lib/diameter/src/base/diameter_codec.erl (renamed from lib/diameter/src/app/diameter_codec.erl)42
-rw-r--r--lib/diameter/src/base/diameter_config.erl (renamed from lib/diameter/src/app/diameter_config.erl)11
-rw-r--r--lib/diameter/src/base/diameter_dbg.erl (renamed from lib/diameter/src/app/diameter_dbg.erl)147
-rw-r--r--lib/diameter/src/base/diameter_dict.erl (renamed from lib/diameter/src/app/diameter_dict.erl)0
-rw-r--r--lib/diameter/src/base/diameter_info.erl (renamed from lib/diameter/src/app/diameter_info.erl)0
-rw-r--r--lib/diameter/src/base/diameter_internal.hrl (renamed from lib/diameter/src/app/diameter_internal.hrl)25
-rw-r--r--lib/diameter/src/base/diameter_lib.erl (renamed from lib/diameter/src/app/diameter_lib.erl)40
-rw-r--r--lib/diameter/src/base/diameter_misc_sup.erl (renamed from lib/diameter/src/app/diameter_misc_sup.erl)0
-rw-r--r--lib/diameter/src/base/diameter_peer.erl (renamed from lib/diameter/src/app/diameter_peer.erl)11
-rw-r--r--lib/diameter/src/base/diameter_peer_fsm.erl (renamed from lib/diameter/src/app/diameter_peer_fsm.erl)319
-rw-r--r--lib/diameter/src/base/diameter_peer_fsm_sup.erl (renamed from lib/diameter/src/app/diameter_peer_fsm_sup.erl)0
-rw-r--r--lib/diameter/src/base/diameter_reg.erl (renamed from lib/diameter/src/app/diameter_reg.erl)12
-rw-r--r--lib/diameter/src/base/diameter_service.erl (renamed from lib/diameter/src/app/diameter_service.erl)314
-rw-r--r--lib/diameter/src/base/diameter_service_sup.erl (renamed from lib/diameter/src/app/diameter_service_sup.erl)0
-rw-r--r--lib/diameter/src/base/diameter_session.erl (renamed from lib/diameter/src/app/diameter_session.erl)0
-rw-r--r--lib/diameter/src/base/diameter_stats.erl (renamed from lib/diameter/src/app/diameter_stats.erl)11
-rw-r--r--lib/diameter/src/base/diameter_sup.erl (renamed from lib/diameter/src/app/diameter_sup.erl)0
-rw-r--r--lib/diameter/src/base/diameter_sync.erl (renamed from lib/diameter/src/app/diameter_sync.erl)35
-rw-r--r--lib/diameter/src/base/diameter_types.erl (renamed from lib/diameter/src/app/diameter_types.erl)0
-rw-r--r--lib/diameter/src/base/diameter_types.hrl (renamed from lib/diameter/src/app/diameter_types.hrl)0
-rw-r--r--lib/diameter/src/base/diameter_watchdog.erl (renamed from lib/diameter/src/app/diameter_watchdog.erl)10
-rw-r--r--lib/diameter/src/base/diameter_watchdog_sup.erl (renamed from lib/diameter/src/app/diameter_watchdog_sup.erl)0
-rw-r--r--lib/diameter/src/compiler/Makefile141
-rw-r--r--lib/diameter/src/compiler/diameter_codegen.erl83
-rw-r--r--lib/diameter/src/compiler/diameter_exprecs.erl (renamed from lib/diameter/src/app/diameter_exprecs.erl)0
-rw-r--r--lib/diameter/src/compiler/diameter_make.erl122
-rw-r--r--lib/diameter/src/compiler/diameter_spec_util.erl87
-rw-r--r--lib/diameter/src/compiler/modules.mk27
-rw-r--r--lib/diameter/src/depend.sed51
-rw-r--r--lib/diameter/src/dict/base_accounting.dia69
-rw-r--r--lib/diameter/src/dict/base_rfc3588.dia414
-rw-r--r--lib/diameter/src/dict/relay.dia (renamed from lib/diameter/src/app/diameter_gen_relay.dia)1
-rw-r--r--lib/diameter/src/gen/.gitignore2
-rw-r--r--lib/diameter/src/modules.mk93
-rw-r--r--lib/diameter/src/transport/Makefile141
-rw-r--r--lib/diameter/src/transport/diameter_sctp.erl108
-rw-r--r--lib/diameter/src/transport/diameter_tcp.erl284
-rw-r--r--lib/diameter/src/transport/modules.mk29
-rw-r--r--lib/diameter/test/.gitignore (renamed from lib/diameter/src/transport/.gitignore)2
-rw-r--r--lib/diameter/test/Makefile423
-rw-r--r--lib/diameter/test/depend.sed (renamed from lib/diameter/src/app/depend.sed)20
-rw-r--r--lib/diameter/test/diameter.spec8
-rw-r--r--lib/diameter/test/diameter_SUITE.erl108
-rw-r--r--lib/diameter/test/diameter_app_SUITE.erl270
-rw-r--r--lib/diameter/test/diameter_app_test.erl393
-rw-r--r--lib/diameter/test/diameter_appup_test.erl539
-rw-r--r--lib/diameter/test/diameter_capx_SUITE.erl432
-rw-r--r--lib/diameter/test/diameter_codec_SUITE.erl76
-rw-r--r--lib/diameter/test/diameter_codec_test.erl500
-rw-r--r--lib/diameter/test/diameter_compiler_test.erl104
-rw-r--r--lib/diameter/test/diameter_config_test.erl105
-rw-r--r--lib/diameter/test/diameter_ct.erl55
-rw-r--r--lib/diameter/test/diameter_ct.hrl (renamed from lib/diameter/src/app/diameter.appup.src)10
-rw-r--r--lib/diameter/test/diameter_dict_SUITE.erl151
-rw-r--r--lib/diameter/test/diameter_enum.erl406
-rw-r--r--lib/diameter/test/diameter_etcp_test.beambin1808 -> 0 bytes
-rw-r--r--lib/diameter/test/diameter_failover_SUITE.erl257
-rw-r--r--lib/diameter/test/diameter_peer_test.erl104
-rw-r--r--lib/diameter/test/diameter_reg_SUITE.erl119
-rw-r--r--lib/diameter/test/diameter_reg_test.erl104
-rw-r--r--lib/diameter/test/diameter_relay_SUITE.erl363
-rw-r--r--lib/diameter/test/diameter_session_test.erl104
-rw-r--r--lib/diameter/test/diameter_stats_SUITE.erl92
-rw-r--r--lib/diameter/test/diameter_stats_test.erl104
-rw-r--r--lib/diameter/test/diameter_sync_SUITE.erl139
-rw-r--r--lib/diameter/test/diameter_sync_test.erl104
-rw-r--r--lib/diameter/test/diameter_tcp_test.erl482
-rw-r--r--lib/diameter/test/diameter_test_lib.erl478
-rw-r--r--lib/diameter/test/diameter_test_lib.hrl106
-rw-r--r--lib/diameter/test/diameter_test_server.erl551
-rw-r--r--lib/diameter/test/diameter_tls_SUITE.erl406
-rw-r--r--lib/diameter/test/diameter_tls_SUITE_data/Makefile.ca (renamed from lib/ssl/c_src/Makefile)39
-rw-r--r--lib/diameter/test/diameter_traffic_SUITE.erl753
-rw-r--r--lib/diameter/test/diameter_transport_SUITE.erl436
-rw-r--r--lib/diameter/test/diameter_util.erl322
-rw-r--r--lib/diameter/test/diameter_watchdog_SUITE.erl540
-rw-r--r--lib/diameter/test/modules.mk46
-rw-r--r--lib/diameter/test/release.sed (renamed from lib/diameter/src/subdirs.mk)22
-rw-r--r--lib/diameter/test/slask/diameter_persistent_table_test.erl495
-rw-r--r--lib/diameter/vsn.mk2
-rw-r--r--lib/docbuilder/doc/src/notes.xml18
-rw-r--r--lib/docbuilder/src/docb_gen.erl4
-rw-r--r--lib/docbuilder/src/docb_main.erl12
-rw-r--r--lib/docbuilder/src/docb_transform.erl2
-rw-r--r--lib/docbuilder/src/docb_xml_check.erl1
-rw-r--r--[-rwxr-xr-x]lib/docbuilder/test/docb_SUITE_data/cdata_problem.xml0
-rw-r--r--lib/docbuilder/vsn.mk2
-rw-r--r--[-rwxr-xr-x]lib/docbuilder/xsd/application.xsd0
-rw-r--r--[-rwxr-xr-x]lib/docbuilder/xsd/appref.xsd0
-rw-r--r--[-rwxr-xr-x]lib/docbuilder/xsd/book.xsd0
-rw-r--r--[-rwxr-xr-x]lib/docbuilder/xsd/chapter.xsd0
-rw-r--r--[-rwxr-xr-x]lib/docbuilder/xsd/common.entities.xsd0
-rw-r--r--[-rwxr-xr-x]lib/docbuilder/xsd/common.header.xsd0
-rw-r--r--[-rwxr-xr-x]lib/docbuilder/xsd/common.image.xsd0
-rw-r--r--[-rwxr-xr-x]lib/docbuilder/xsd/common.refs.xsd0
-rw-r--r--[-rwxr-xr-x]lib/docbuilder/xsd/common.table.xsd0
-rw-r--r--[-rwxr-xr-x]lib/docbuilder/xsd/common.xsd0
-rw-r--r--[-rwxr-xr-x]lib/docbuilder/xsd/comref.xsd0
-rw-r--r--[-rwxr-xr-x]lib/docbuilder/xsd/cref.xsd0
-rw-r--r--[-rwxr-xr-x]lib/docbuilder/xsd/erlref.xsd0
-rw-r--r--[-rwxr-xr-x]lib/docbuilder/xsd/fascicules.xsd0
-rw-r--r--[-rwxr-xr-x]lib/docbuilder/xsd/fileref.xsd0
-rw-r--r--[-rwxr-xr-x]lib/docbuilder/xsd/part.xsd0
-rw-r--r--lib/edoc/Makefile2
-rw-r--r--lib/edoc/doc/Makefile11
-rw-r--r--lib/edoc/doc/overview.edoc15
-rw-r--r--lib/edoc/doc/src/Makefile2
-rw-r--r--lib/edoc/doc/src/make.dep21
-rw-r--r--lib/edoc/doc/src/notes.xml51
-rw-r--r--lib/edoc/include/Makefile2
-rw-r--r--lib/edoc/include/edoc_doclet.hrl2
-rw-r--r--lib/edoc/priv/edoc_generate.src3
-rw-r--r--lib/edoc/src/Makefile2
-rw-r--r--lib/edoc/src/edoc.erl21
-rw-r--r--lib/edoc/src/edoc.hrl2
-rw-r--r--lib/edoc/src/edoc_data.erl4
-rw-r--r--lib/edoc/src/edoc_doclet.erl6
-rw-r--r--lib/edoc/src/edoc_extract.erl27
-rw-r--r--lib/edoc/src/edoc_layout.erl22
-rw-r--r--lib/edoc/src/edoc_lib.erl24
-rw-r--r--lib/edoc/src/edoc_macros.erl2
-rw-r--r--lib/edoc/src/edoc_parser.yrl18
-rw-r--r--lib/edoc/src/edoc_refs.erl2
-rw-r--r--lib/edoc/src/edoc_report.erl4
-rw-r--r--lib/edoc/src/edoc_run.erl4
-rw-r--r--lib/edoc/src/edoc_scanner.erl4
-rw-r--r--lib/edoc/src/edoc_specs.erl10
-rw-r--r--lib/edoc/src/edoc_tags.erl4
-rw-r--r--lib/edoc/src/edoc_types.erl9
-rw-r--r--lib/edoc/src/edoc_types.hrl2
-rw-r--r--lib/edoc/src/edoc_wiki.erl25
-rw-r--r--lib/edoc/src/otpsgml_layout.erl6
-rw-r--r--lib/edoc/test/edoc_SUITE.erl2
-rw-r--r--lib/edoc/vsn.mk2
-rw-r--r--lib/erl_docgen/doc/src/notes.xml46
-rwxr-xr-xlib/erl_docgen/priv/bin/xref_mod_app.escript7
-rw-r--r--lib/erl_docgen/priv/xsl/db_eix.xsl180
-rw-r--r--lib/erl_docgen/priv/xsl/db_html.xsl2
-rw-r--r--lib/erl_docgen/priv/xsl/db_man.xsl149
-rw-r--r--lib/erl_docgen/priv/xsl/db_pdf.xsl52
-rw-r--r--lib/erl_docgen/priv/xsl/db_pdf_params.xsl8
-rw-r--r--lib/erl_docgen/vsn.mk2
-rw-r--r--lib/erl_interface/doc/src/ei.xml8
-rw-r--r--lib/erl_interface/doc/src/erl_format.xml4
-rw-r--r--lib/erl_interface/doc/src/make.dep24
-rw-r--r--lib/erl_interface/doc/src/notes.xml47
-rw-r--r--lib/erl_interface/src/Makefile.in34
-rw-r--r--lib/erl_interface/src/connect/ei_resolve.c7
-rw-r--r--lib/erl_interface/src/encode/encode_atom.c8
-rw-r--r--lib/erl_interface/src/encode/encode_string.c8
-rw-r--r--lib/erl_interface/src/legacy/erl_fix_alloc.c6
-rw-r--r--lib/erl_interface/src/misc/ei_decode_term.c10
-rw-r--r--lib/erl_interface/src/registry/reg_dump.c1
-rw-r--r--lib/erl_interface/src/registry/reg_restore.c5
-rw-r--r--lib/erl_interface/test/all_SUITE_data/Makefile.src2
-rw-r--r--lib/erl_interface/test/all_SUITE_data/init_tc.erl18
-rw-r--r--lib/erl_interface/test/port_call_SUITE_data/Makefile.src4
-rw-r--r--lib/erl_interface/vsn.mk2
-rw-r--r--lib/et/doc/src/notes.xml16
-rw-r--r--lib/et/src/et_wx_viewer.erl4
-rw-r--r--lib/et/vsn.mk2
-rw-r--r--lib/eunit/AUTHORS2
-rw-r--r--lib/eunit/Makefile2
-rw-r--r--lib/eunit/doc/.gitignore4
-rw-r--r--lib/eunit/doc/edoc-info3
-rw-r--r--lib/eunit/doc/erlang.pngbin2109 -> 0 bytes
-rw-r--r--lib/eunit/doc/eunit.html71
-rw-r--r--lib/eunit/doc/eunit_surefire.html78
-rw-r--r--lib/eunit/doc/index.html17
-rw-r--r--lib/eunit/doc/modules-frame.html13
-rw-r--r--lib/eunit/doc/overview-summary.html1032
-rw-r--r--lib/eunit/doc/overview.edoc5
-rw-r--r--lib/eunit/doc/packages-frame.html11
-rw-r--r--lib/eunit/doc/src/make.dep19
-rw-r--r--lib/eunit/doc/src/notes.xml57
-rw-r--r--lib/eunit/doc/stylesheet.css55
-rw-r--r--lib/eunit/examples/Makefile2
-rw-r--r--lib/eunit/include/eunit.hrl104
-rw-r--r--lib/eunit/src/Makefile13
-rw-r--r--lib/eunit/src/eunit.app.src16
-rw-r--r--lib/eunit/src/eunit.erl7
-rw-r--r--lib/eunit/src/eunit_autoexport.erl4
-rw-r--r--lib/eunit/src/eunit_data.erl74
-rw-r--r--lib/eunit/src/eunit_internal.hrl6
-rw-r--r--lib/eunit/src/eunit_lib.erl5
-rw-r--r--lib/eunit/src/eunit_listener.erl4
-rw-r--r--lib/eunit/src/eunit_proc.erl4
-rw-r--r--lib/eunit/src/eunit_serial.erl4
-rw-r--r--lib/eunit/src/eunit_server.erl11
-rw-r--r--lib/eunit/src/eunit_striptests.erl6
-rw-r--r--lib/eunit/src/eunit_surefire.erl68
-rw-r--r--lib/eunit/src/eunit_test.erl76
-rw-r--r--lib/eunit/src/eunit_tests.erl30
-rw-r--r--lib/eunit/src/eunit_tty.erl4
-rw-r--r--lib/eunit/vsn.mk2
-rw-r--r--lib/gs/contribs/bonk/sounder.erl20
-rw-r--r--lib/gs/contribs/cols/cols.erl6
-rw-r--r--lib/gs/contribs/mandel/mandel.erl4
-rw-r--r--lib/gs/contribs/othello/othello_board.erl6
-rw-r--r--lib/gs/doc/src/make.dep58
-rw-r--r--lib/gs/doc/src/notes.xml16
-rw-r--r--lib/gs/examples/calc2.erl4
-rw-r--r--lib/gs/src/Makefile4
-rw-r--r--lib/gs/src/gstk_editor.erl4
-rw-r--r--lib/gs/src/gstk_generic.erl2
-rw-r--r--lib/gs/src/gstk_image.erl4
-rw-r--r--lib/gs/src/tool_utils.erl3
-rw-r--r--lib/gs/vsn.mk2
-rw-r--r--lib/hipe/cerl/erl_bif_types.erl129
-rw-r--r--lib/hipe/cerl/erl_types.erl19
-rw-r--r--lib/hipe/doc/src/make.dep13
-rw-r--r--lib/hipe/doc/src/notes.xml63
-rw-r--r--lib/hipe/icode/hipe_beam_to_icode.erl13
-rw-r--r--[-rwxr-xr-x]lib/hipe/icode/hipe_icode_pp.erl0
-rw-r--r--[-rwxr-xr-x]lib/hipe/icode/hipe_icode_ssa.erl0
-rw-r--r--lib/hipe/main/hipe.hrl.src9
-rw-r--r--lib/hipe/regalloc/hipe_node_sets.erl4
-rw-r--r--lib/hipe/rtl/Makefile26
-rw-r--r--lib/hipe/rtl/hipe_rtl_lcm.erl4
-rw-r--r--[-rwxr-xr-x]lib/hipe/util/hipe_dot.erl0
-rw-r--r--lib/hipe/vsn.mk2
-rw-r--r--lib/ic/c_src/Makefile.in8
-rw-r--r--lib/ic/doc/src/Makefile108
-rw-r--r--lib/ic/doc/src/make.dep24
-rw-r--r--lib/ic/doc/src/notes.xml34
-rw-r--r--lib/ic/examples/pre_post_condition/Makefile9
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/ignore_config_record.inf1
-rw-r--r--lib/ic/src/ic.erl4
-rw-r--r--lib/ic/src/ic_pp.erl472
-rw-r--r--lib/ic/src/ic_pragma.erl19
-rw-r--r--lib/ic/vsn.mk2
-rw-r--r--lib/inets/Makefile2
-rw-r--r--lib/inets/doc/archive/rfc3986.txt3419
-rw-r--r--lib/inets/doc/src/Makefile96
-rw-r--r--lib/inets/doc/src/ftp.xml21
-rw-r--r--lib/inets/doc/src/http_server.xml2
-rw-r--r--lib/inets/doc/src/httpc.xml13
-rw-r--r--lib/inets/doc/src/httpd.xml12
-rw-r--r--lib/inets/doc/src/make.dep47
-rw-r--r--lib/inets/doc/src/mod_auth.xml2
-rw-r--r--lib/inets/doc/src/mod_esi.xml12
-rw-r--r--lib/inets/doc/src/notes.xml751
-rw-r--r--lib/inets/doc/src/notes_history.xml4
-rw-r--r--lib/inets/src/ftp/ftp.erl151
-rw-r--r--lib/inets/src/http_client/Makefile1
-rw-r--r--lib/inets/src/http_client/http.erl132
-rw-r--r--lib/inets/src/http_client/httpc.erl46
-rw-r--r--lib/inets/src/http_client/httpc_cookie.erl218
-rw-r--r--lib/inets/src/http_client/httpc_handler.erl2
-rw-r--r--lib/inets/src/http_client/httpc_internal.hrl41
-rw-r--r--lib/inets/src/http_client/httpc_manager.erl29
-rw-r--r--lib/inets/src/http_client/httpc_response.erl9
-rw-r--r--lib/inets/src/http_lib/http_internal.hrl1
-rw-r--r--lib/inets/src/http_lib/http_transport.erl59
-rw-r--r--lib/inets/src/http_lib/http_uri.erl63
-rw-r--r--lib/inets/src/http_lib/http_util.erl20
-rw-r--r--lib/inets/src/http_server/httpd_conf.erl10
-rw-r--r--lib/inets/src/http_server/httpd_esi.erl4
-rw-r--r--lib/inets/src/http_server/httpd_file.erl8
-rw-r--r--lib/inets/src/http_server/httpd_request.erl10
-rw-r--r--lib/inets/src/http_server/httpd_request_handler.erl6
-rw-r--r--lib/inets/src/http_server/httpd_response.erl17
-rw-r--r--lib/inets/src/http_server/httpd_util.erl53
-rw-r--r--lib/inets/src/http_server/mod_auth_mnesia.erl4
-rw-r--r--lib/inets/src/http_server/mod_responsecontrol.erl55
-rw-r--r--lib/inets/src/inets_app/Makefile3
-rw-r--r--lib/inets/src/inets_app/inets.app.src3
-rw-r--r--lib/inets/src/inets_app/inets.appup.src40
-rw-r--r--lib/inets/src/inets_app/inets.mk4
-rw-r--r--lib/inets/src/inets_app/inets_service.erl37
-rw-r--r--lib/inets/src/tftp/tftp.erl57
-rw-r--r--lib/inets/test/ftp_suite_lib.erl82
-rw-r--r--lib/inets/test/ftp_windows_2003_server_test.erl22
-rw-r--r--lib/inets/test/http_format_SUITE.erl4
-rw-r--r--lib/inets/test/httpc_SUITE.erl201
-rw-r--r--lib/inets/test/httpc_cookie_SUITE.erl185
-rw-r--r--lib/inets/test/httpd_1_1.erl108
-rw-r--r--lib/inets/test/httpd_SUITE.erl334
-rw-r--r--lib/inets/test/httpd_basic_SUITE.erl140
-rw-r--r--lib/inets/test/httpd_mod.erl32
-rw-r--r--lib/inets/test/httpd_test_lib.erl57
-rw-r--r--lib/inets/test/httpd_time_test.erl6
-rw-r--r--lib/inets/test/inets_test_lib.erl10
-rw-r--r--lib/inets/vsn.mk2
-rw-r--r--lib/inviso/doc/src/make.dep27
-rw-r--r--lib/inviso/src/inviso_tool_lib.erl8
-rw-r--r--lib/jinterface/doc/src/make.dep20
-rw-r--r--lib/jinterface/java_src/Makefile16
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile (renamed from lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile.otp)2
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangString.java5
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/ignore_config_record.inf1
-rw-r--r--lib/kernel/doc/src/Makefile2
-rw-r--r--lib/kernel/doc/src/app.xml4
-rw-r--r--lib/kernel/doc/src/code.xml343
-rw-r--r--lib/kernel/doc/src/disk_log.xml3
-rw-r--r--lib/kernel/doc/src/erl_ddll.xml2
-rw-r--r--lib/kernel/doc/src/file.xml41
-rw-r--r--lib/kernel/doc/src/gen_sctp.xml279
-rw-r--r--lib/kernel/doc/src/gen_tcp.xml25
-rw-r--r--lib/kernel/doc/src/gen_udp.xml21
-rw-r--r--lib/kernel/doc/src/heart.xml2
-rw-r--r--lib/kernel/doc/src/inet.xml68
-rw-r--r--lib/kernel/doc/src/kernel_app.xml11
-rw-r--r--lib/kernel/doc/src/make.dep28
-rw-r--r--lib/kernel/doc/src/net_kernel.xml12
-rw-r--r--lib/kernel/doc/src/notes.xml58
-rw-r--r--lib/kernel/doc/src/os.xml3
-rw-r--r--lib/kernel/examples/uds_dist/c_src/uds_drv.c6
-rw-r--r--lib/kernel/include/dist.hrl (renamed from lib/ssl/src/ssl_broker_sup.erl)42
-rw-r--r--lib/kernel/include/dist_util.hrl87
-rw-r--r--lib/kernel/include/net_address.hrl28
-rw-r--r--lib/kernel/src/Makefile17
-rw-r--r--lib/kernel/src/application.erl12
-rw-r--r--lib/kernel/src/application_controller.erl19
-rw-r--r--lib/kernel/src/auth.erl4
-rw-r--r--lib/kernel/src/code.erl135
-rw-r--r--lib/kernel/src/code_server.erl19
-rw-r--r--lib/kernel/src/disk_log.erl22
-rw-r--r--lib/kernel/src/error_handler.erl9
-rw-r--r--lib/kernel/src/file.erl25
-rw-r--r--lib/kernel/src/gen_sctp.erl206
-rw-r--r--lib/kernel/src/gen_tcp.erl120
-rw-r--r--lib/kernel/src/gen_udp.erl87
-rw-r--r--lib/kernel/src/global.erl23
-rw-r--r--lib/kernel/src/inet.erl190
-rw-r--r--lib/kernel/src/inet6_sctp.erl17
-rw-r--r--lib/kernel/src/inet6_tcp.erl8
-rw-r--r--lib/kernel/src/inet6_udp.erl6
-rw-r--r--lib/kernel/src/inet_config.erl52
-rw-r--r--lib/kernel/src/inet_dns_record_adts.pl12
-rw-r--r--lib/kernel/src/inet_int.hrl16
-rw-r--r--lib/kernel/src/inet_res.erl4
-rw-r--r--lib/kernel/src/inet_sctp.erl21
-rw-r--r--lib/kernel/src/inet_tcp.erl8
-rw-r--r--lib/kernel/src/inet_udp.erl4
-rw-r--r--lib/kernel/src/rpc.erl5
-rw-r--r--lib/kernel/src/user_drv.erl8
-rw-r--r--lib/kernel/test/application_SUITE.erl74
-rw-r--r--lib/kernel/test/application_SUITE_data/Makefile.src5
-rw-r--r--lib/kernel/test/application_SUITE_data/deadlock/deadlock.app8
-rw-r--r--lib/kernel/test/application_SUITE_data/deadlock/deadlock.erl69
-rw-r--r--lib/kernel/test/code_SUITE.erl55
-rw-r--r--lib/kernel/test/disk_log_SUITE.erl15
-rw-r--r--lib/kernel/test/erl_boot_server_SUITE.erl2
-rw-r--r--lib/kernel/test/erl_prim_loader_SUITE.erl2
-rw-r--r--lib/kernel/test/file_SUITE.erl2
-rw-r--r--lib/kernel/test/gen_sctp_SUITE.erl1007
-rw-r--r--lib/kernel/test/gen_tcp_api_SUITE.erl8
-rw-r--r--lib/kernel/test/gen_udp_SUITE.erl15
-rw-r--r--lib/kernel/test/global_SUITE.erl17
-rw-r--r--lib/kernel/test/global_group_SUITE.erl16
-rw-r--r--lib/kernel/test/inet_SUITE.erl2
-rw-r--r--lib/kernel/test/inet_res_SUITE.erl19
-rwxr-xr-xlib/kernel/test/inet_res_SUITE_data/run-named37
-rw-r--r--lib/kernel/test/init_SUITE.erl2
-rw-r--r--lib/kernel/test/pg2_SUITE.erl1
-rw-r--r--lib/kernel/test/ram_file_SUITE.erl4
-rw-r--r--lib/kernel/test/zlib_SUITE.erl12
-rw-r--r--lib/kernel/vsn.mk2
-rw-r--r--lib/megaco/.gitignore3
-rw-r--r--lib/megaco/configure.in3
-rw-r--r--lib/megaco/doc/src/Makefile105
-rw-r--r--lib/megaco/doc/src/make.dep59
-rw-r--r--lib/megaco/doc/src/megaco.xml6
-rw-r--r--lib/megaco/doc/src/notes.xml97
-rw-r--r--lib/megaco/examples/meas/Makefile.in (renamed from lib/megaco/examples/meas/Makefile)38
-rw-r--r--lib/megaco/examples/meas/meas.sh.skel.src (renamed from lib/megaco/examples/meas/meas.sh.skel)4
-rw-r--r--lib/megaco/examples/meas/modules.mk8
-rw-r--r--lib/megaco/examples/meas/mstone1.sh.skel.src (renamed from lib/megaco/examples/meas/mstone1.sh.skel)4
-rw-r--r--lib/megaco/src/app/megaco.appup.src22
-rw-r--r--lib/megaco/src/binary/depend.mk198
-rw-r--r--lib/megaco/src/flex/Makefile.in11
-rw-r--r--lib/megaco/test/megaco_codec_v1_test.erl4
-rw-r--r--lib/megaco/test/megaco_codec_v2_test.erl4
-rw-r--r--lib/megaco/test/megaco_mess_test.erl92
-rw-r--r--lib/megaco/test/megaco_profile.erl343
-rw-r--r--lib/megaco/test/megaco_test_lib.erl10
-rw-r--r--lib/megaco/vsn.mk2
-rw-r--r--lib/mnesia/doc/src/Makefile86
-rw-r--r--lib/mnesia/doc/src/make.dep46
-rw-r--r--lib/mnesia/doc/src/mnesia.xml4
-rw-r--r--lib/mnesia/doc/src/mnesia_frag_hash.xml2
-rw-r--r--lib/mnesia/doc/src/notes.xml73
-rw-r--r--lib/mnesia/src/Makefile4
-rw-r--r--lib/mnesia/src/mnesia.appup.src6
-rw-r--r--lib/mnesia/src/mnesia_bup.erl4
-rw-r--r--lib/mnesia/src/mnesia_controller.erl14
-rw-r--r--lib/mnesia/src/mnesia_dumper.erl9
-rw-r--r--lib/mnesia/src/mnesia_event.erl6
-rw-r--r--lib/mnesia/src/mnesia_frag.erl12
-rw-r--r--lib/mnesia/src/mnesia_lib.erl8
-rw-r--r--lib/mnesia/src/mnesia_loader.erl246
-rw-r--r--lib/mnesia/src/mnesia_log.erl5
-rw-r--r--lib/mnesia/src/mnesia_monitor.erl90
-rw-r--r--lib/mnesia/src/mnesia_recover.erl6
-rw-r--r--lib/mnesia/src/mnesia_schema.erl595
-rw-r--r--lib/mnesia/test/mnesia_evil_backup.erl8
-rw-r--r--lib/mnesia/test/mnesia_evil_coverage_test.erl4
-rw-r--r--lib/mnesia/test/mnesia_install_test.erl23
-rw-r--r--lib/mnesia/vsn.mk2
-rw-r--r--lib/observer/doc/src/make.dep29
-rw-r--r--lib/observer/doc/src/notes.xml16
-rw-r--r--lib/observer/doc/src/ttb.xml233
-rw-r--r--lib/observer/doc/src/ttb_ug.xml385
-rw-r--r--lib/observer/src/Makefile9
-rw-r--r--lib/observer/src/ttb.erl734
-rw-r--r--lib/observer/test/Makefile3
-rw-r--r--lib/observer/test/client.erl28
-rw-r--r--lib/observer/test/server.erl44
-rw-r--r--lib/observer/test/ttb_SUITE.erl916
-rw-r--r--lib/observer/test/ttb_helper.erl157
-rw-r--r--lib/observer/vsn.mk2
-rw-r--r--lib/odbc/c_src/Makefile.in7
-rw-r--r--lib/odbc/c_src/odbcserver.c71
-rw-r--r--lib/odbc/c_src/odbcserver.h3
-rw-r--r--lib/odbc/doc/src/Makefile87
-rw-r--r--lib/odbc/doc/src/databases.xml6
-rw-r--r--lib/odbc/doc/src/make.dep27
-rw-r--r--lib/odbc/doc/src/notes.xml44
-rw-r--r--lib/odbc/doc/src/odbc.xml8
-rw-r--r--lib/odbc/src/odbc.appup.src6
-rw-r--r--lib/odbc/src/odbc.erl7
-rw-r--r--lib/odbc/src/odbc_internal.hrl3
-rw-r--r--lib/odbc/test/Makefile3
-rw-r--r--lib/odbc/test/mysql.erl277
-rw-r--r--lib/odbc/test/odbc.dynspec31
-rw-r--r--lib/odbc/test/odbc.spec24
-rw-r--r--lib/odbc/test/odbc.spec.win5
-rw-r--r--lib/odbc/test/odbc_connect_SUITE.erl237
-rw-r--r--lib/odbc/test/odbc_data_type_SUITE.erl516
-rw-r--r--lib/odbc/test/odbc_query_SUITE.erl64
-rw-r--r--lib/odbc/test/odbc_start_SUITE.erl27
-rw-r--r--lib/odbc/test/odbc_test.hrl13
-rw-r--r--lib/odbc/test/odbc_test_lib.erl83
-rw-r--r--lib/odbc/test/oracle.erl12
-rw-r--r--lib/odbc/test/postgres.erl23
-rw-r--r--lib/odbc/test/sqlserver.erl12
-rw-r--r--lib/odbc/vsn.mk2
-rw-r--r--lib/orber/COSS/CosNaming/Makefile8
-rw-r--r--lib/orber/doc/src/Makefile89
-rw-r--r--lib/orber/doc/src/Orber/ignore_config_record.inf1
-rw-r--r--lib/orber/doc/src/make.dep62
-rw-r--r--lib/orber/doc/src/notes.xml16
-rw-r--r--lib/orber/doc/src/orber_ifr.xml4
-rw-r--r--lib/orber/examples/Stack/Makefile12
-rw-r--r--lib/orber/include/Makefile66
-rw-r--r--[-rwxr-xr-x]lib/orber/priv/Makefile0
-rw-r--r--[-rwxr-xr-x]lib/orber/priv/blank.html0
-rw-r--r--[-rwxr-xr-x]lib/orber/priv/info_frames.html0
-rw-r--r--[-rwxr-xr-x]lib/orber/priv/main_frame.html0
-rw-r--r--[-rwxr-xr-x]lib/orber/priv/orber.tool0
-rw-r--r--[-rwxr-xr-x]lib/orber/priv/orber_help.txt0
-rw-r--r--[-rwxr-xr-x]lib/orber/priv/start_info.html0
-rw-r--r--lib/orber/src/Makefile13
-rw-r--r--lib/orber/src/corba.erl4
-rw-r--r--lib/orber/src/orber_diagnostics.erl4
-rw-r--r--lib/orber/src/orber_ifr.erl2
-rw-r--r--lib/orber/test/Makefile26
-rw-r--r--lib/orber/vsn.mk2
-rw-r--r--lib/os_mon/c_src/Makefile.in8
-rw-r--r--lib/os_mon/c_src/cpu_sup.c21
-rw-r--r--lib/os_mon/doc/src/make.dep21
-rw-r--r--lib/os_mon/doc/src/notes.xml16
-rw-r--r--lib/os_mon/mibs/Makefile3
-rw-r--r--lib/os_mon/vsn.mk2
-rw-r--r--lib/otp_mibs/doc/src/make.dep20
-rw-r--r--lib/parsetools/doc/src/leex.xml6
-rw-r--r--lib/parsetools/doc/src/make.dep21
-rw-r--r--lib/parsetools/doc/src/notes.xml46
-rw-r--r--lib/parsetools/doc/src/yecc.xml16
-rw-r--r--lib/parsetools/include/yeccpre.hrl4
-rw-r--r--lib/parsetools/src/leex.erl177
-rw-r--r--lib/parsetools/src/yecc.erl55
-rw-r--r--lib/parsetools/src/yeccparser.erl4
-rw-r--r--lib/parsetools/test/leex_SUITE.erl20
-rw-r--r--lib/parsetools/test/yecc_SUITE.erl14
-rw-r--r--lib/parsetools/vsn.mk2
-rw-r--r--lib/percept/doc/src/make.dep34
-rw-r--r--lib/percept/doc/src/notes.xml26
-rw-r--r--[-rwxr-xr-x]lib/percept/doc/src/part_notes.xml0
-rw-r--r--lib/percept/src/percept_db.erl13
-rw-r--r--[-rwxr-xr-x]lib/percept/test/percept_SUITE_data/ipc-dist.datbin2098105 -> 2098105 bytes
-rw-r--r--lib/percept/vsn.mk2
-rw-r--r--lib/pman/doc/src/make.dep26
-rw-r--r--[-rwxr-xr-x]lib/public_key/asn1/DSS.asn10
-rw-r--r--lib/public_key/asn1/InformationFramework.asn1682
-rw-r--r--lib/public_key/asn1/Makefile24
-rw-r--r--[-rwxr-xr-x]lib/public_key/asn1/PKCS-1.asn10
-rw-r--r--lib/public_key/asn1/PKCS-8.asn183
-rw-r--r--lib/public_key/asn1/PKCS-FRAME.set.asn3
-rw-r--r--lib/public_key/asn1/PKCS5v2-0.asn1142
-rw-r--r--lib/public_key/asn1/README2
-rw-r--r--lib/public_key/doc/src/Makefile86
-rw-r--r--lib/public_key/doc/src/introduction.xml8
-rw-r--r--lib/public_key/doc/src/make.dep21
-rw-r--r--lib/public_key/doc/src/notes.xml17
-rw-r--r--lib/public_key/doc/src/public_key.xml39
-rw-r--r--lib/public_key/include/public_key.hrl1
-rw-r--r--lib/public_key/src/Makefile6
-rw-r--r--lib/public_key/src/pubkey_pbe.erl213
-rw-r--r--lib/public_key/src/pubkey_pem.erl81
-rw-r--r--lib/public_key/src/public_key.app.src4
-rw-r--r--lib/public_key/src/public_key.appup.src74
-rw-r--r--lib/public_key/src/public_key.erl109
-rw-r--r--lib/public_key/test/Makefile3
-rw-r--r--lib/public_key/test/pbe_SUITE.erl259
-rw-r--r--lib/public_key/test/pbe_SUITE_data/des_cbc_enc_key.pem11
-rw-r--r--lib/public_key/test/pbe_SUITE_data/des_ede3_cbc_enc_key.pem11
-rw-r--r--lib/public_key/test/pbe_SUITE_data/rc2_cbc_enc_key.pem12
-rw-r--r--lib/public_key/test/public_key_SUITE.erl27
-rw-r--r--lib/public_key/vsn.mk2
-rw-r--r--lib/reltool/doc/src/make.dep20
-rw-r--r--lib/reltool/doc/src/notes.xml30
-rw-r--r--lib/reltool/src/reltool_sys_win.erl133
-rw-r--r--lib/reltool/vsn.mk2
-rw-r--r--lib/runtime_tools/c_src/Makefile.in15
-rw-r--r--lib/runtime_tools/doc/src/dbg.xml35
-rw-r--r--lib/runtime_tools/doc/src/make.dep20
-rw-r--r--lib/runtime_tools/doc/src/notes.xml17
-rw-r--r--lib/runtime_tools/src/Makefile3
-rw-r--r--lib/runtime_tools/src/dbg.erl65
-rw-r--r--lib/runtime_tools/src/erts_alloc_config.erl10
-rw-r--r--lib/runtime_tools/src/inviso_rt.erl4
-rw-r--r--lib/runtime_tools/src/inviso_rt_lib.erl16
-rw-r--r--lib/runtime_tools/src/observer_backend.erl123
-rw-r--r--lib/runtime_tools/src/runtime_tools.app.src3
-rw-r--r--lib/runtime_tools/src/runtime_tools_sup.erl4
-rw-r--r--lib/runtime_tools/src/ttb_autostart.erl55
-rw-r--r--lib/runtime_tools/test/inviso_SUITE.erl22
-rw-r--r--lib/runtime_tools/vsn.mk2
-rw-r--r--lib/sasl/doc/src/make.dep22
-rw-r--r--lib/sasl/doc/src/notes.xml98
-rw-r--r--lib/sasl/doc/src/release_handler.xml28
-rw-r--r--lib/sasl/doc/src/systools.xml10
-rw-r--r--lib/sasl/examples/src/Makefile4
-rw-r--r--lib/sasl/src/erlsrv.erl31
-rw-r--r--lib/sasl/src/release_handler.erl241
-rw-r--r--lib/sasl/src/release_handler_1.erl289
-rw-r--r--lib/sasl/src/systools_lib.erl40
-rw-r--r--lib/sasl/src/systools_make.erl180
-rw-r--r--lib/sasl/src/systools_relup.erl68
-rw-r--r--lib/sasl/test/Makefile5
-rw-r--r--lib/sasl/test/installer.erl80
-rw-r--r--lib/sasl/test/release_handler_SUITE.erl742
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/Makefile.src117
-rwxr-xr-xlib/sasl/test/release_handler_SUITE_data/clients/start_cli138
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/erl.ini.src4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/heart_restart.bat3
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/README33
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/ebin/a.app (renamed from lib/sasl/test/release_handler_SUITE_data/lib/a-1.0/src/a.app)4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/ebin/a.appup3
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/priv/file (renamed from bootstrap/lib/kernel/egen/.gitignore)0
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/src/a.erl54
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/src/a_sup.erl (renamed from lib/asn1/src/asn1_sup.erl)30
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/b-1.0/ebin/b.app7
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/b-1.0/src/b_lib.erl3
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/b-1.0/src/b_server.erl37
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/ebin/b.app7
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/ebin/b.appup6
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/src/b_lib.erl3
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/src/b_server.erl37
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/installer-1.0/ebin/installer.app2
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/ebin/many_mods.app17
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m.erl11
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m1.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m10.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m2.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m3.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m4.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m5.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m6.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m7.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m8.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m9.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/ebin/many_mods.app17
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/ebin/many_mods.appup22
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m.erl11
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m1.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m10.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m2.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m3.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m4.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m5.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m6.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m7.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m8.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m9.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-2.0/ebin/many_mods.app7
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-2.0/ebin/many_mods.appup24
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-2.0/src/m.erl11
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/ebin/dummy.app7
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_app.erl9
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_server.erl56
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_sup.erl15
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_sup_2.erl15
-rwxr-xr-xlib/sasl/test/release_handler_SUITE_data/start_client (renamed from lib/sasl/test/release_handler_SUITE_data/clients/start_cli2)2
-rw-r--r--lib/sasl/test/rh_test_lib.erl100
-rw-r--r--lib/sasl/test/systools_SUITE.erl87
-rw-r--r--lib/sasl/vsn.mk2
-rw-r--r--lib/snmp/Makefile7
-rw-r--r--lib/snmp/doc/src/Makefile138
-rw-r--r--lib/snmp/doc/src/depend.mk83
-rw-r--r--lib/snmp/doc/src/make.dep77
-rw-r--r--lib/snmp/doc/src/notes.xml1221
-rw-r--r--lib/snmp/doc/src/notes_history.xml924
-rw-r--r--lib/snmp/doc/src/snmpc.xml15
-rw-r--r--lib/snmp/doc/src/snmpc_cmd.xml34
-rw-r--r--lib/snmp/doc/src/snmpm.xml40
-rw-r--r--lib/snmp/mibs/Makefile.in34
-rw-r--r--lib/snmp/src/agent/snmp_target_mib.erl23
-rw-r--r--lib/snmp/src/agent/snmp_view_based_acm_mib.erl6
-rw-r--r--lib/snmp/src/agent/snmpa_agent.erl2
-rw-r--r--lib/snmp/src/agent/snmpa_conf.erl9
-rw-r--r--lib/snmp/src/agent/snmpa_mpd.erl104
-rw-r--r--lib/snmp/src/agent/snmpa_set_lib.erl8
-rw-r--r--lib/snmp/src/app/snmp.appup.src212
-rw-r--r--lib/snmp/src/compile/Makefile11
-rw-r--r--lib/snmp/src/compile/depend.mk2
-rw-r--r--lib/snmp/src/compile/snmpc.erl9
-rw-r--r--lib/snmp/src/compile/snmpc.src94
-rw-r--r--lib/snmp/src/compile/snmpc_lib.erl6
-rw-r--r--lib/snmp/src/compile/snmpc_lib.hrl15
-rw-r--r--lib/snmp/src/manager/snmpm.erl8
-rw-r--r--lib/snmp/src/manager/snmpm_config.erl515
-rw-r--r--lib/snmp/src/manager/snmpm_mpd.erl49
-rw-r--r--lib/snmp/src/manager/snmpm_net_if.erl31
-rw-r--r--lib/snmp/src/manager/snmpm_server.erl77
-rw-r--r--lib/snmp/src/misc/snmp_conf.erl83
-rw-r--r--lib/snmp/src/misc/snmp_config.erl10
-rw-r--r--lib/snmp/src/misc/snmp_note_store.erl15
-rw-r--r--lib/snmp/test/Makefile4
-rw-r--r--lib/snmp/test/snmp_compiler_test.erl48
-rw-r--r--lib/snmp/test/snmp_manager_test.erl185
-rw-r--r--[-rwxr-xr-x]lib/snmp/test/snmp_manager_user_old.erl0
-rw-r--r--lib/snmp/test/test_config/Makefile18
-rw-r--r--lib/snmp/vsn.mk2
-rw-r--r--lib/ssh/doc/src/Makefile85
-rw-r--r--lib/ssh/doc/src/make.dep19
-rw-r--r--lib/ssh/doc/src/notes.xml14
-rw-r--r--[-rwxr-xr-x]lib/ssh/src/DSS.asn10
-rw-r--r--lib/ssh/src/Makefile9
-rw-r--r--[-rwxr-xr-x]lib/ssh/src/PKCS-1.asn10
-rw-r--r--lib/ssh/src/ssh.appup.src10
-rw-r--r--[-rwxr-xr-x]lib/ssh/src/ssh_bits.erl0
-rw-r--r--[-rwxr-xr-x]lib/ssh/src/ssh_connect.hrl0
-rw-r--r--[-rwxr-xr-x]lib/ssh/src/ssh_dsa.erl0
-rw-r--r--[-rwxr-xr-x]lib/ssh/src/ssh_file.erl0
-rw-r--r--[-rwxr-xr-x]lib/ssh/src/ssh_io.erl0
-rw-r--r--[-rwxr-xr-x]lib/ssh/src/ssh_math.erl0
-rw-r--r--[-rwxr-xr-x]lib/ssh/src/ssh_rsa.erl0
-rw-r--r--[-rwxr-xr-x]lib/ssh/src/ssh_sftp.erl12
-rw-r--r--[-rwxr-xr-x]lib/ssh/src/ssh_userauth.hrl0
-rw-r--r--[-rwxr-xr-x]lib/ssh/src/ssh_xfer.hrl0
-rw-r--r--lib/ssh/test/Makefile2
-rw-r--r--lib/ssh/vsn.mk2
-rw-r--r--lib/ssl/Makefile4
-rw-r--r--lib/ssl/c_src/Makefile.dist33
-rw-r--r--lib/ssl/c_src/Makefile.in215
-rw-r--r--lib/ssl/c_src/Makefile.win32147
-rw-r--r--lib/ssl/c_src/Makefile.win32.dist45
-rw-r--r--lib/ssl/c_src/debuglog.c251
-rw-r--r--lib/ssl/c_src/debuglog.h50
-rw-r--r--lib/ssl/c_src/esock.c1904
-rw-r--r--lib/ssl/c_src/esock.h273
-rw-r--r--lib/ssl/c_src/esock_openssl.c1213
-rw-r--r--lib/ssl/c_src/esock_osio.c328
-rw-r--r--lib/ssl/c_src/esock_osio.h34
-rw-r--r--lib/ssl/c_src/esock_poll.c222
-rw-r--r--lib/ssl/c_src/esock_poll.h60
-rw-r--r--lib/ssl/c_src/esock_posix_str.c642
-rw-r--r--lib/ssl/c_src/esock_posix_str.h28
-rw-r--r--lib/ssl/c_src/esock_ssl.h110
-rw-r--r--lib/ssl/c_src/esock_utils.c150
-rw-r--r--lib/ssl/c_src/esock_utils.h32
-rw-r--r--lib/ssl/doc/src/Makefile4
-rw-r--r--lib/ssl/doc/src/notes.xml60
-rw-r--r--lib/ssl/doc/src/old_ssl.xml709
-rw-r--r--lib/ssl/doc/src/refman.xml5
-rw-r--r--lib/ssl/doc/src/ssl.xml52
-rw-r--r--lib/ssl/doc/src/ssl_distribution.xml209
-rw-r--r--lib/ssl/doc/src/ssl_protocol.xml18
-rw-r--r--lib/ssl/doc/src/using_ssl.xml8
-rw-r--r--lib/ssl/src/Makefile12
-rw-r--r--lib/ssl/src/inet_ssl_dist.erl456
-rw-r--r--lib/ssl/src/inet_tls_dist.erl275
-rw-r--r--lib/ssl/src/ssl.app.src10
-rw-r--r--lib/ssl/src/ssl.appup.src2
-rw-r--r--lib/ssl/src/ssl.erl461
-rw-r--r--lib/ssl/src/ssl_broker.erl1188
-rw-r--r--lib/ssl/src/ssl_broker_int.hrl38
-rw-r--r--lib/ssl/src/ssl_certificate.erl77
-rw-r--r--lib/ssl/src/ssl_certificate_db.erl85
-rw-r--r--lib/ssl/src/ssl_cipher.erl80
-rw-r--r--lib/ssl/src/ssl_connection.erl236
-rw-r--r--lib/ssl/src/ssl_connection_sup.erl12
-rw-r--r--lib/ssl/src/ssl_dist_sup.erl84
-rw-r--r--lib/ssl/src/ssl_handshake.erl73
-rw-r--r--lib/ssl/src/ssl_int.hrl99
-rw-r--r--lib/ssl/src/ssl_internal.hrl14
-rw-r--r--lib/ssl/src/ssl_manager.erl117
-rw-r--r--lib/ssl/src/ssl_prim.erl173
-rw-r--r--lib/ssl/src/ssl_record.erl18
-rw-r--r--lib/ssl/src/ssl_server.erl1378
-rw-r--r--lib/ssl/src/ssl_session.erl21
-rw-r--r--lib/ssl/src/ssl_session_cache.erl18
-rw-r--r--lib/ssl/src/ssl_ssl2.erl4
-rw-r--r--lib/ssl/src/ssl_sup.erl42
-rw-r--r--lib/ssl/src/ssl_tls_dist_proxy.erl325
-rw-r--r--lib/ssl/test/Makefile23
-rw-r--r--lib/ssl/test/old_ssl_active_SUITE.erl395
-rw-r--r--lib/ssl/test/old_ssl_active_once_SUITE.erl417
-rw-r--r--lib/ssl/test/old_ssl_misc_SUITE.erl117
-rw-r--r--lib/ssl/test/old_ssl_passive_SUITE.erl382
-rw-r--r--lib/ssl/test/old_ssl_peer_cert_SUITE.erl191
-rw-r--r--lib/ssl/test/old_ssl_protocol_SUITE.erl185
-rw-r--r--lib/ssl/test/old_ssl_verify_SUITE.erl153
-rw-r--r--lib/ssl/test/old_transport_accept_SUITE.erl258
-rw-r--r--lib/ssl/test/ssl.cover19
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl431
-rw-r--r--lib/ssl/test/ssl_cipher_SUITE.erl163
-rw-r--r--lib/ssl/test/ssl_dist_SUITE.erl (renamed from lib/ssl/test/old_ssl_dist_SUITE.erl)363
-rw-r--r--lib/ssl/test/ssl_dist_SUITE_data/dHParam.pem5
-rw-r--r--lib/ssl/test/ssl_handshake_SUITE.erl67
-rw-r--r--lib/ssl/test/ssl_packet_SUITE.erl302
-rw-r--r--lib/ssl/test/ssl_session_cache_SUITE.erl56
-rw-r--r--lib/ssl/test/ssl_test_MACHINE.erl940
-rw-r--r--lib/ssl/test/ssl_test_lib.erl14
-rw-r--r--lib/ssl/test/ssl_to_openssl_SUITE.erl124
-rw-r--r--lib/ssl/vsn.mk2
-rw-r--r--lib/stdlib/doc/src/beam_lib.xml1
-rw-r--r--lib/stdlib/doc/src/calendar.xml15
-rw-r--r--lib/stdlib/doc/src/dets.xml5
-rw-r--r--lib/stdlib/doc/src/erl_tar.xml60
-rw-r--r--lib/stdlib/doc/src/ets.xml14
-rw-r--r--lib/stdlib/doc/src/gb_sets.xml1
-rw-r--r--lib/stdlib/doc/src/gen_fsm.xml11
-rw-r--r--lib/stdlib/doc/src/io.xml2
-rw-r--r--lib/stdlib/doc/src/lists.xml26
-rw-r--r--lib/stdlib/doc/src/make.dep40
-rw-r--r--lib/stdlib/doc/src/notes.xml165
-rw-r--r--lib/stdlib/doc/src/qlc.xml1
-rw-r--r--lib/stdlib/doc/src/random.xml5
-rw-r--r--lib/stdlib/doc/src/supervisor.xml83
-rw-r--r--lib/stdlib/doc/src/timer.xml13
-rw-r--r--lib/stdlib/doc/src/unicode.xml3
-rw-r--r--lib/stdlib/doc/src/unicode_usage.xml4
-rw-r--r--lib/stdlib/doc/src/zip.xml22
-rw-r--r--lib/stdlib/examples/erl_id_trans.erl9
-rw-r--r--lib/stdlib/src/beam_lib.erl33
-rw-r--r--lib/stdlib/src/c.erl2
-rw-r--r--lib/stdlib/src/calendar.erl78
-rw-r--r--lib/stdlib/src/dets.erl121
-rw-r--r--lib/stdlib/src/dets.hrl3
-rw-r--r--lib/stdlib/src/dets_v8.erl20
-rw-r--r--lib/stdlib/src/dets_v9.erl118
-rw-r--r--lib/stdlib/src/epp.erl37
-rw-r--r--lib/stdlib/src/erl_compile.erl3
-rw-r--r--lib/stdlib/src/erl_eval.erl13
-rw-r--r--lib/stdlib/src/erl_expand_records.erl2
-rw-r--r--lib/stdlib/src/erl_internal.erl3
-rw-r--r--lib/stdlib/src/erl_lint.erl57
-rw-r--r--lib/stdlib/src/erl_parse.yrl22
-rw-r--r--lib/stdlib/src/erl_pp.erl10
-rw-r--r--lib/stdlib/src/erl_scan.erl7
-rw-r--r--lib/stdlib/src/erl_tar.erl30
-rw-r--r--lib/stdlib/src/error_logger_tty_h.erl69
-rw-r--r--lib/stdlib/src/escript.erl8
-rw-r--r--lib/stdlib/src/eval_bits.erl57
-rw-r--r--lib/stdlib/src/filename.erl25
-rw-r--r--lib/stdlib/src/gen.erl4
-rw-r--r--lib/stdlib/src/gen_event.erl83
-rw-r--r--lib/stdlib/src/gen_fsm.erl63
-rw-r--r--lib/stdlib/src/gen_server.erl47
-rw-r--r--lib/stdlib/src/io_lib.erl8
-rw-r--r--lib/stdlib/src/io_lib_fread.erl64
-rw-r--r--lib/stdlib/src/lib.erl46
-rw-r--r--lib/stdlib/src/lists.erl29
-rw-r--r--lib/stdlib/src/ms_transform.erl17
-rw-r--r--lib/stdlib/src/otp_internal.erl46
-rw-r--r--lib/stdlib/src/proplists.erl3
-rw-r--r--lib/stdlib/src/qlc.erl12
-rw-r--r--lib/stdlib/src/queue.erl127
-rw-r--r--lib/stdlib/src/random.erl42
-rw-r--r--lib/stdlib/src/re.erl18
-rw-r--r--lib/stdlib/src/shell.erl2
-rw-r--r--lib/stdlib/src/sofs.erl5
-rw-r--r--lib/stdlib/src/supervisor.erl147
-rw-r--r--lib/stdlib/src/supervisor_bridge.erl9
-rw-r--r--lib/stdlib/src/sys.erl4
-rw-r--r--lib/stdlib/src/timer.erl6
-rw-r--r--lib/stdlib/src/unicode.erl12
-rw-r--r--lib/stdlib/src/zip.erl10
-rw-r--r--lib/stdlib/test/Makefile1
-rw-r--r--lib/stdlib/test/beam_lib_SUITE.erl56
-rw-r--r--lib/stdlib/test/dets_SUITE.erl299
-rw-r--r--lib/stdlib/test/epp_SUITE.erl37
-rw-r--r--lib/stdlib/test/epp_SUITE_data/bar.hrl4
-rw-r--r--lib/stdlib/test/epp_SUITE_data/include/bar.hrl3
-rw-r--r--lib/stdlib/test/epp_SUITE_data/include/foo.hrl4
-rw-r--r--lib/stdlib/test/epp_SUITE_data/include_local.erl6
-rw-r--r--lib/stdlib/test/erl_eval_SUITE.erl8
-rw-r--r--lib/stdlib/test/erl_lint_SUITE.erl2
-rw-r--r--lib/stdlib/test/erl_pp_SUITE.erl5
-rw-r--r--lib/stdlib/test/erl_scan_SUITE.erl4
-rw-r--r--lib/stdlib/test/ets_SUITE.erl341
-rw-r--r--lib/stdlib/test/file_sorter_SUITE.erl16
-rw-r--r--lib/stdlib/test/filelib_SUITE.erl11
-rw-r--r--lib/stdlib/test/gen_server_SUITE.erl2
-rw-r--r--lib/stdlib/test/io_SUITE.erl30
-rw-r--r--lib/stdlib/test/ms_transform_SUITE.erl45
-rw-r--r--lib/stdlib/test/proc_lib_SUITE.erl2
-rw-r--r--lib/stdlib/test/qlc_SUITE.erl2
-rw-r--r--lib/stdlib/test/re_SUITE.erl92
-rw-r--r--lib/stdlib/test/shell_SUITE.erl6
-rw-r--r--lib/stdlib/test/sofs_SUITE.erl6
-rw-r--r--lib/stdlib/test/string_SUITE.erl4
-rw-r--r--lib/stdlib/test/supervisor_1.erl6
-rw-r--r--lib/stdlib/test/supervisor_2.erl (renamed from lib/ssl/test/ssl_test_MACHINE.hrl)39
-rw-r--r--lib/stdlib/test/supervisor_SUITE.erl324
-rw-r--r--lib/stdlib/test/supervisor_bridge_SUITE.erl44
-rw-r--r--lib/stdlib/test/sys_SUITE.erl2
-rw-r--r--lib/stdlib/test/tar_SUITE.erl78
-rw-r--r--lib/stdlib/test/unicode_SUITE.erl4
-rw-r--r--lib/stdlib/test/zip_SUITE.erl3
-rw-r--r--lib/stdlib/vsn.mk2
-rw-r--r--lib/syntax_tools/doc/Makefile9
-rw-r--r--lib/syntax_tools/doc/src/make.dep22
-rw-r--r--lib/syntax_tools/doc/src/notes.xml2
-rw-r--r--lib/syntax_tools/src/erl_syntax.erl7
-rw-r--r--lib/syntax_tools/src/erl_tidy.erl4
-rw-r--r--lib/test_server/doc/src/Makefile6
-rw-r--r--lib/test_server/doc/src/make.dep24
-rw-r--r--lib/test_server/doc/src/notes.xml144
-rw-r--r--lib/test_server/doc/src/ts.xml2
-rw-r--r--lib/test_server/include/test_server.hrl5
-rw-r--r--lib/test_server/include/test_server_line.hrl3
-rw-r--r--lib/test_server/src/Makefile1
-rw-r--r--lib/test_server/src/test_server.app.src1
-rw-r--r--lib/test_server/src/test_server.erl579
-rw-r--r--lib/test_server/src/test_server_ctrl.erl139
-rw-r--r--lib/test_server/src/test_server_line.erl387
-rw-r--r--lib/test_server/src/test_server_sup.erl23
-rw-r--r--lib/test_server/src/ts.config2
-rw-r--r--lib/test_server/src/ts_erl_config.erl5
-rw-r--r--lib/test_server/src/ts_install_cth.erl17
-rw-r--r--lib/test_server/test/Makefile2
-rw-r--r--lib/test_server/test/test_server_SUITE.erl6
-rw-r--r--lib/test_server/vsn.mk2
-rw-r--r--lib/toolbar/doc/src/make.dep26
-rw-r--r--lib/toolbar/doc/src/notes.xml16
-rw-r--r--lib/toolbar/src/toolbar_toolconfig.erl6
-rw-r--r--lib/toolbar/vsn.mk2
-rw-r--r--lib/tools/c_src/Makefile.in11
-rw-r--r--lib/tools/doc/src/eprof.xml2
-rw-r--r--lib/tools/doc/src/instrument.xml6
-rw-r--r--lib/tools/doc/src/make.dep33
-rw-r--r--lib/tools/doc/src/notes.xml38
-rw-r--r--lib/tools/doc/src/xref.xml8
-rw-r--r--lib/tools/emacs/erlang.el86
-rw-r--r--lib/tools/src/cover.erl8
-rw-r--r--lib/tools/src/xref_reader.erl25
-rw-r--r--lib/tools/test/cover_SUITE.erl31
-rw-r--r--lib/tools/test/cover_SUITE_data/otp_6115/f1.erl11
-rw-r--r--lib/tools/test/eprof_SUITE_data/ed.script2
-rw-r--r--lib/tools/test/eprof_SUITE_data/eed.erl91
-rw-r--r--lib/tools/test/xref_SUITE.erl87
-rw-r--r--lib/tools/test/xref_SUITE_data/fun_mfa_r14.beambin0 -> 1116 bytes
-rw-r--r--lib/tools/test/xref_SUITE_data/fun_mfa_r14.erl18
-rw-r--r--lib/tools/vsn.mk2
-rw-r--r--lib/tv/doc/src/Makefile83
-rw-r--r--lib/tv/doc/src/make.dep32
-rw-r--r--lib/tv/doc/src/notes.xml2
-rw-r--r--lib/tv/src/tv_db_search.erl32
-rw-r--r--lib/tv/src/tv_main.erl2
-rw-r--r--lib/tv/src/tv_mnesia_rpc.erl2
-rw-r--r--lib/typer/src/typer.erl14
-rw-r--r--lib/typer/vsn.mk2
-rw-r--r--lib/webtool/doc/src/make.dep20
-rw-r--r--lib/webtool/doc/src/notes.xml18
-rw-r--r--lib/webtool/priv/Makefile8
-rw-r--r--lib/webtool/vsn.mk2
-rw-r--r--lib/wx/api_gen/gen_util.erl50
-rw-r--r--lib/wx/api_gen/gl_gen.erl4
-rw-r--r--lib/wx/api_gen/wx_doxygen.conf1
-rw-r--r--lib/wx/api_gen/wx_extra/wxListCtrl.c_src161
-rw-r--r--lib/wx/api_gen/wx_extra/wxListCtrl.erl112
-rw-r--r--lib/wx/api_gen/wx_gen.erl25
-rw-r--r--lib/wx/api_gen/wx_gen_cpp.erl363
-rw-r--r--lib/wx/api_gen/wx_gen_erl.erl316
-rw-r--r--lib/wx/api_gen/wxapi.conf16
-rw-r--r--lib/wx/c_src/egl_impl.cpp72
-rw-r--r--lib/wx/c_src/gen/wxe_derived_dest.h41
-rw-r--r--lib/wx/c_src/gen/wxe_events.cpp572
-rw-r--r--lib/wx/c_src/gen/wxe_funcs.cpp241
-rw-r--r--lib/wx/c_src/gen/wxe_init.cpp2
-rw-r--r--lib/wx/c_src/gen/wxe_macros.h3377
-rw-r--r--lib/wx/c_src/wxePrintout.cpp269
-rw-r--r--lib/wx/c_src/wxe_impl.cpp248
-rw-r--r--lib/wx/c_src/wxe_impl.h11
-rw-r--r--lib/wx/doc/src/make.dep13
-rw-r--r--lib/wx/doc/src/notes.xml33
-rw-r--r--[-rwxr-xr-x]lib/wx/examples/demo/Makefile2
-rw-r--r--lib/wx/examples/demo/ex_listCtrl.erl50
-rw-r--r--lib/wx/examples/simple/Makefile2
-rw-r--r--[-rwxr-xr-x]lib/wx/examples/simple/hello.erl0
-rw-r--r--[-rwxr-xr-x]lib/wx/examples/simple/menu.erl0
-rw-r--r--[-rwxr-xr-x]lib/wx/examples/simple/minimal.erl0
-rw-r--r--[-rwxr-xr-x]lib/wx/examples/simple/sample.xpm0
-rw-r--r--[-rwxr-xr-x]lib/wx/examples/sudoku/Makefile2
-rw-r--r--[-rwxr-xr-x]lib/wx/examples/sudoku/sudoku.erl0
-rw-r--r--[-rwxr-xr-x]lib/wx/examples/sudoku/sudoku.hrl0
-rw-r--r--[-rwxr-xr-x]lib/wx/examples/sudoku/sudoku_board.erl0
-rw-r--r--[-rwxr-xr-x]lib/wx/examples/sudoku/sudoku_game.erl0
-rw-r--r--[-rwxr-xr-x]lib/wx/examples/sudoku/sudoku_gui.erl0
-rw-r--r--[-rwxr-xr-x]lib/wx/examples/xrc/Makefile5
-rw-r--r--lib/wx/include/gl.hrl1682
-rw-r--r--lib/wx/include/wx.hrl10
-rw-r--r--lib/wx/src/gen/wxArtProvider.erl6
-rw-r--r--lib/wx/src/gen/wxAuiManager.erl8
-rw-r--r--lib/wx/src/gen/wxAuiNotebook.erl8
-rw-r--r--lib/wx/src/gen/wxAuiPaneInfo.erl12
-rw-r--r--lib/wx/src/gen/wxBitmap.erl4
-rw-r--r--lib/wx/src/gen/wxBitmapButton.erl6
-rw-r--r--lib/wx/src/gen/wxBoxSizer.erl6
-rw-r--r--lib/wx/src/gen/wxBufferedDC.erl10
-rw-r--r--lib/wx/src/gen/wxButton.erl8
-rw-r--r--lib/wx/src/gen/wxCalendarCtrl.erl8
-rw-r--r--lib/wx/src/gen/wxCaret.erl14
-rw-r--r--lib/wx/src/gen/wxCheckBox.erl6
-rw-r--r--lib/wx/src/gen/wxCheckListBox.erl4
-rw-r--r--lib/wx/src/gen/wxChoice.erl8
-rw-r--r--lib/wx/src/gen/wxChoicebook.erl10
-rw-r--r--lib/wx/src/gen/wxColourPickerCtrl.erl6
-rw-r--r--lib/wx/src/gen/wxComboBox.erl8
-rw-r--r--lib/wx/src/gen/wxContextMenuEvent.erl6
-rw-r--r--lib/wx/src/gen/wxDC.erl92
-rw-r--r--lib/wx/src/gen/wxDatePickerCtrl.erl4
-rw-r--r--lib/wx/src/gen/wxDialog.erl6
-rw-r--r--lib/wx/src/gen/wxDirDialog.erl4
-rw-r--r--lib/wx/src/gen/wxDirPickerCtrl.erl6
-rw-r--r--lib/wx/src/gen/wxFileDialog.erl4
-rw-r--r--lib/wx/src/gen/wxFilePickerCtrl.erl6
-rw-r--r--lib/wx/src/gen/wxFlexGridSizer.erl6
-rw-r--r--lib/wx/src/gen/wxFontPickerCtrl.erl6
-rw-r--r--lib/wx/src/gen/wxFrame.erl8
-rw-r--r--lib/wx/src/gen/wxGLCanvas.erl6
-rw-r--r--lib/wx/src/gen/wxGauge.erl6
-rw-r--r--lib/wx/src/gen/wxGenericDirCtrl.erl6
-rw-r--r--lib/wx/src/gen/wxGraphicsContext.erl12
-rw-r--r--lib/wx/src/gen/wxGraphicsMatrix.erl8
-rw-r--r--lib/wx/src/gen/wxGraphicsPath.erl18
-rw-r--r--lib/wx/src/gen/wxGrid.erl42
-rw-r--r--lib/wx/src/gen/wxGridBagSizer.erl58
-rw-r--r--lib/wx/src/gen/wxGridCellAttr.erl4
-rw-r--r--lib/wx/src/gen/wxGridCellEditor.erl6
-rw-r--r--lib/wx/src/gen/wxGridCellRenderer.erl6
-rw-r--r--lib/wx/src/gen/wxGridEvent.erl4
-rw-r--r--lib/wx/src/gen/wxGridSizer.erl6
-rw-r--r--lib/wx/src/gen/wxHelpEvent.erl6
-rw-r--r--lib/wx/src/gen/wxHtmlWindow.erl8
-rw-r--r--lib/wx/src/gen/wxIconBundle.erl4
-rw-r--r--lib/wx/src/gen/wxImage.erl26
-rw-r--r--lib/wx/src/gen/wxImageList.erl4
-rw-r--r--lib/wx/src/gen/wxJoystickEvent.erl4
-rw-r--r--lib/wx/src/gen/wxKeyEvent.erl4
-rw-r--r--lib/wx/src/gen/wxLayoutAlgorithm.erl4
-rw-r--r--lib/wx/src/gen/wxListBox.erl12
-rw-r--r--lib/wx/src/gen/wxListCtrl.erl110
-rw-r--r--lib/wx/src/gen/wxListEvent.erl4
-rw-r--r--lib/wx/src/gen/wxListItemAttr.erl122
-rw-r--r--lib/wx/src/gen/wxListbook.erl10
-rw-r--r--lib/wx/src/gen/wxMDIChildFrame.erl6
-rw-r--r--lib/wx/src/gen/wxMDIParentFrame.erl6
-rw-r--r--lib/wx/src/gen/wxMessageDialog.erl4
-rw-r--r--lib/wx/src/gen/wxMiniFrame.erl6
-rw-r--r--lib/wx/src/gen/wxMouseEvent.erl6
-rw-r--r--lib/wx/src/gen/wxMoveEvent.erl4
-rw-r--r--lib/wx/src/gen/wxMultiChoiceDialog.erl4
-rw-r--r--lib/wx/src/gen/wxNotebook.erl12
-rw-r--r--lib/wx/src/gen/wxPageSetupDialogData.erl22
-rw-r--r--lib/wx/src/gen/wxPalette.erl4
-rw-r--r--lib/wx/src/gen/wxPanel.erl4
-rw-r--r--lib/wx/src/gen/wxPasswordEntryDialog.erl4
-rw-r--r--lib/wx/src/gen/wxPreviewControlBar.erl4
-rw-r--r--lib/wx/src/gen/wxPreviewFrame.erl4
-rw-r--r--lib/wx/src/gen/wxPrintout.erl24
-rw-r--r--lib/wx/src/gen/wxRadioBox.erl12
-rw-r--r--lib/wx/src/gen/wxRadioButton.erl6
-rw-r--r--lib/wx/src/gen/wxRegion.erl22
-rw-r--r--lib/wx/src/gen/wxSashEvent.erl4
-rw-r--r--lib/wx/src/gen/wxSashLayoutWindow.erl8
-rw-r--r--lib/wx/src/gen/wxSashWindow.erl4
-rw-r--r--lib/wx/src/gen/wxScrollBar.erl6
-rw-r--r--lib/wx/src/gen/wxScrolledWindow.erl16
-rw-r--r--lib/wx/src/gen/wxSingleChoiceDialog.erl4
-rw-r--r--lib/wx/src/gen/wxSizeEvent.erl4
-rw-r--r--lib/wx/src/gen/wxSizer.erl44
-rw-r--r--lib/wx/src/gen/wxSizerItem.erl22
-rw-r--r--lib/wx/src/gen/wxSlider.erl6
-rw-r--r--lib/wx/src/gen/wxSpinButton.erl6
-rw-r--r--lib/wx/src/gen/wxSpinCtrl.erl6
-rw-r--r--lib/wx/src/gen/wxSplashScreen.erl4
-rw-r--r--lib/wx/src/gen/wxSplitterWindow.erl6
-rw-r--r--lib/wx/src/gen/wxStaticBitmap.erl6
-rw-r--r--lib/wx/src/gen/wxStaticBox.erl6
-rw-r--r--lib/wx/src/gen/wxStaticBoxSizer.erl6
-rw-r--r--lib/wx/src/gen/wxStaticLine.erl6
-rw-r--r--lib/wx/src/gen/wxStaticText.erl6
-rw-r--r--lib/wx/src/gen/wxStatusBar.erl4
-rw-r--r--lib/wx/src/gen/wxStdDialogButtonSizer.erl6
-rw-r--r--lib/wx/src/gen/wxStyledTextCtrl.erl18
-rw-r--r--lib/wx/src/gen/wxSystemOptions.erl87
-rw-r--r--lib/wx/src/gen/wxTextCtrl.erl10
-rw-r--r--lib/wx/src/gen/wxTextEntryDialog.erl4
-rw-r--r--lib/wx/src/gen/wxToggleButton.erl6
-rw-r--r--lib/wx/src/gen/wxToolBar.erl10
-rw-r--r--lib/wx/src/gen/wxToolbook.erl10
-rw-r--r--lib/wx/src/gen/wxTreeCtrl.erl18
-rw-r--r--lib/wx/src/gen/wxTreeEvent.erl4
-rw-r--r--lib/wx/src/gen/wxTreebook.erl10
-rw-r--r--lib/wx/src/gen/wxWindow.erl88
-rw-r--r--lib/wx/src/gen/wx_misc.erl8
-rw-r--r--lib/wx/src/gen/wxe_debug.hrl3376
-rw-r--r--lib/wx/src/gen/wxe_funcs.hrl3376
-rw-r--r--lib/wx/src/wx_object.erl6
-rw-r--r--lib/wx/src/wxe_server.erl52
-rw-r--r--lib/wx/test/wx_class_SUITE.erl146
-rw-r--r--lib/wx/test/wx_event_SUITE.erl34
-rw-r--r--lib/wx/test/wxt.erl6
-rw-r--r--lib/wx/vsn.mk2
-rw-r--r--[-rwxr-xr-x]lib/xmerl/doc/examples/test_html.erl0
-rw-r--r--[-rwxr-xr-x]lib/xmerl/doc/examples/xml/test.xml0
-rw-r--r--[-rwxr-xr-x]lib/xmerl/doc/examples/xml/test2.xml0
-rw-r--r--[-rwxr-xr-x]lib/xmerl/doc/examples/xml/test3.xml0
-rw-r--r--[-rwxr-xr-x]lib/xmerl/doc/examples/xml/test4.xml0
-rw-r--r--[-rwxr-xr-x]lib/xmerl/doc/examples/xml/test5.xml0
-rw-r--r--[-rwxr-xr-x]lib/xmerl/doc/examples/xml/testdtd.dtd0
-rw-r--r--[-rwxr-xr-x]lib/xmerl/doc/examples/xml/xmerl.xml0
-rw-r--r--lib/xmerl/doc/src/make.dep24
-rw-r--r--lib/xmerl/doc/src/notes.xml57
-rw-r--r--[-rwxr-xr-x]lib/xmerl/doc/src/part_notes.xml0
-rw-r--r--[-rwxr-xr-x]lib/xmerl/include/xmerl.hrl17
-rw-r--r--[-rwxr-xr-x]lib/xmerl/include/xmerl_xlink.hrl0
-rw-r--r--lib/xmerl/include/xmerl_xsd.hrl1
-rw-r--r--lib/xmerl/src/xmerl.erl2
-rw-r--r--lib/xmerl/src/xmerl_lib.erl3
-rw-r--r--lib/xmerl/src/xmerl_sax_parser_base.erlsrc38
-rw-r--r--lib/xmerl/src/xmerl_scan.erl399
-rw-r--r--lib/xmerl/src/xmerl_ucs.erl37
-rw-r--r--lib/xmerl/src/xmerl_validate.erl103
-rw-r--r--lib/xmerl/src/xmerl_xpath.erl114
-rw-r--r--lib/xmerl/src/xmerl_xpath_lib.erl4
-rw-r--r--lib/xmerl/src/xmerl_xpath_parse.yrl1
-rw-r--r--lib/xmerl/src/xmerl_xpath_pred.erl9
-rw-r--r--lib/xmerl/src/xmerl_xsd.erl110
-rw-r--r--lib/xmerl/test/Makefile2
-rw-r--r--lib/xmerl/test/xmerl_SUITE.erl66
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/misc.tar.gzbin47121 -> 48157 bytes
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_abbrev.erl2
-rw-r--r--lib/xmerl/test/xmerl_test_lib.erl6
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE.erl7
-rw-r--r--[-rwxr-xr-x]lib/xmerl/test/xmerl_xsd_SUITE_data/mim.xsd0
-rw-r--r--lib/xmerl/vsn.mk2
-rw-r--r--[-rwxr-xr-x]lib/xmerl/xmerl.pub0
-rw-r--r--make/otp.mk.in8
-rw-r--r--make/otp_release_targets.mk6
-rw-r--r--make/otp_subdir.mk7
-rw-r--r--make/target.mk36
-rwxr-xr-xotp_build35
-rw-r--r--system/doc/design_principles/Makefile2
-rw-r--r--system/doc/design_principles/make.dep31
-rw-r--r--system/doc/design_principles/spec_proc.xml48
-rw-r--r--system/doc/design_principles/sup_princ.xml21
-rw-r--r--system/doc/efficiency_guide/Makefile2
-rw-r--r--system/doc/efficiency_guide/make.dep16
-rw-r--r--system/doc/efficiency_guide/profiling.xml57
-rw-r--r--system/doc/embedded/Makefile2
-rw-r--r--system/doc/embedded/make.dep14
-rw-r--r--system/doc/getting_started/Makefile2
-rw-r--r--system/doc/getting_started/make.dep14
-rw-r--r--system/doc/getting_started/seq_prog.xml22
-rw-r--r--system/doc/installation_guide/make.dep13
-rw-r--r--system/doc/oam/Makefile2
-rw-r--r--system/doc/oam/make.dep26
-rw-r--r--system/doc/programming_examples/Makefile2
-rw-r--r--system/doc/programming_examples/make.dep20
-rw-r--r--system/doc/reference_manual/Makefile2
-rw-r--r--system/doc/reference_manual/code_loading.xml4
-rw-r--r--system/doc/reference_manual/distributed.xml10
-rw-r--r--system/doc/reference_manual/expressions.xml36
-rw-r--r--system/doc/reference_manual/macros.xml2
-rw-r--r--system/doc/reference_manual/make.dep16
-rw-r--r--[-rwxr-xr-x]system/doc/reference_manual/typespec.xml0
-rw-r--r--system/doc/system_architecture_intro/Makefile2
-rw-r--r--system/doc/system_architecture_intro/make.dep13
-rw-r--r--system/doc/system_principles/Makefile2
-rw-r--r--system/doc/system_principles/make.dep14
-rw-r--r--system/doc/top/src/erl_html_tools.erl10
-rw-r--r--system/doc/tutorial/Makefile2
-rw-r--r--system/doc/tutorial/make.dep35
1878 files changed, 91826 insertions, 75751 deletions
diff --git a/.gitignore b/.gitignore
index 592ac6668b..e6920fbeca 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,6 +15,12 @@ autom4te.cache
!/erts/preloaded/ebin/*.beam
!/lib/*/test/*_SUITE_data/*.beam
+#
+# Generated source code files.
+#
+/bootstrap/lib/compiler/egen
+/bootstrap/lib/stdlib/egen
+
# Compiler derivatives
#
# Do not use too creative wildcards.
@@ -91,6 +97,12 @@ lib/wx/priv/win32/
lib/wx/win32/
make/win32/
+# Used by ic & orber & cos* applications.
+IDL-GENERATED
+
+# Used by applications that run javadoc (e.g. ic).
+JAVADOC-GENERATED
+
# Anchored from $ERL_TOP
/bin
/config.log
@@ -98,12 +110,12 @@ make/win32/
/bootstrap/bin/*
/bootstrap/target
-!/bootstrap/bin/*.script
!/bootstrap/bin/*.boot
/bootstrap/lib/asn1
/bootstrap/lib/hipe
/bootstrap/lib/ic
+/bootstrap/lib/orber
/bootstrap/lib/parsetools
/bootstrap/lib/sasl
/bootstrap/lib/snmp
diff --git a/INSTALL.md b/INSTALL.md
index 1061c5187a..8a3b71e4ec 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -27,7 +27,7 @@ on Unix. For detailed instructions on how to
Binary releases for Windows can be found at
<http://www.erlang.org/download.html>.
-Before reading the above mensioned documents you are in any case advised to
+Before reading the above mentioned documents you are in any case advised to
read this document first, since it covers building Erlang/OTP in general as
well as other important information.
@@ -273,12 +273,6 @@ Some of the available `configure` options are:
* `--with-ssl=PATH` - Specify location of OpenSSL include and lib
* `--{with,without}-ssl` - OpenSSL (without implies that the `crypto`,
`ssh`, and `ssl` won't be built)
-* `--enable-ethread-pre-pentium4-compatibility` - Enable compatibility with
- x86 processors before pentium 4 (back to 486) in the ethread library. If
- not passed the ethread library (part of the runtime system) will use
- instructions that first appeared on the pentium 4 processor when building
- for x86. This option will be automatically enabled if required on the
- build machine.
* `--with-libatomic_ops=PATH` - Use the `libatomic_ops` library for atomic
memory accesses. If `configure` should inform you about no native atomic
implementation available, you typically want to try using the
@@ -424,7 +418,7 @@ as before, but the build process will take a much longer time.
### Building in Git ###
When building in a Git working directory you also have to have a GNU `autoconf`
-of at least version 2.59 on your system. This since you need to generate the
+of at least version 2.59 on your system, because you need to generate the
`configure` scripts before you can start building.
The `configure` scripts are generated by invoking `./otp_build autoconf` in
@@ -436,7 +430,7 @@ when checking out a branch. Regenerated `configure` scripts imply that you
have to run `configure` and build again.
> *NOTE*: Running `./otp_build autoconf` is **not** needed when building
-> an unmodified version the released source.
+> an unmodified version of the released source.
Other useful information can be found at our github wiki:
<http://wiki.github.com/erlang/otp>
@@ -726,7 +720,7 @@ Copyright and License
%CopyrightBegin%
-Copyright Ericsson AB 1998-2010. All Rights Reserved.
+Copyright Ericsson AB 1998-2011. All Rights Reserved.
The contents of this file are subject to the Erlang Public License,
Version 1.1, (the "License"); you may not use this file except in
diff --git a/Makefile.in b/Makefile.in
index 5acd390333..902c21fb52 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -19,6 +19,8 @@
# Toplevel makefile for building the Erlang system
#
+.NOTPARALLEL:
+
# ----------------------------------------------------------------------
# And you'd think that this would be obvious... :-)
@@ -156,7 +158,9 @@ ERLANG_LIBDIR = $(DESTDIR)$(ERLANG_INST_LIBDIR)
MAKE = @MAKE_PROG@
# This should be set to the target "arch-vendor-os"
-export TARGET = @TARGET@
+TARGET := @TARGET@
+include $(ERL_TOP)/make/target.mk
+export TARGET
BOOTSTRAP_ONLY = @BOOTSTRAP_ONLY@
@@ -309,13 +313,13 @@ ifeq ($(BOOTSTRAP_ONLY),yes)
all: bootstrap
else
# The normal case; not cross compiling, and not bootstrap only build.
-all: bootstrap libs local_setup dialyzer
+all: bootstrap libs local_setup
endif
else
# Cross compiling
-all: cross_check_erl depend emulator libs start_scripts dialyzer
+all: cross_check_erl depend emulator libs start_scripts
endif
@@ -349,8 +353,7 @@ endif
all_bootstraps: emulator \
bootstrap_setup \
secondary_bootstrap_build secondary_bootstrap_copy \
- tertiary_bootstrap_build tertiary_bootstrap_copy \
- fourth_bootstrap_build fourth_bootstrap_copy
+ tertiary_bootstrap_build tertiary_bootstrap_copy
#
# Use these targets when you want to use the erl and erlc
@@ -374,17 +377,6 @@ else
cd $(ERL_TOP)/lib && \
ERL_TOP=$(ERL_TOP) PATH=$(INST_PATH_PREFIX)$${PATH} \
$(MAKE) BUILD_ALL=1 TESTROOT=$(RELEASE_ROOT) release
-ifneq ($(findstring vxworks,$(TARGET)),vxworks)
- @if test -f lib/dialyzer/SKIP ; then \
- echo "=== Skipping dialyzer, reason:" ; \
- cat lib/dialyzer/SKIP ; \
- echo "===" ; \
- else \
- cd $(ERL_TOP)/lib/dialyzer && \
- ERL_TOP=$(ERL_TOP) PATH=$(INST_PATH_PREFIX)$${PATH} \
- $(MAKE) BUILD_ALL=1 TESTROOT=$(RELEASE_ROOT) release ; \
- fi
-endif
endif
cd $(ERL_TOP)/erts && \
ERL_TOP=$(ERL_TOP) PATH=$(INST_PATH_PREFIX)$${PATH} \
@@ -402,9 +394,6 @@ else
cd $(ERL_TOP)/lib && \
PATH=$(ERL_TOP)/bin:$${PATH} ERL_TOP=$(ERL_TOP) \
$(MAKE) BUILD_ALL=1 TESTROOT=$(RELEASE_ROOT) $@
- cd $(ERL_TOP)/lib/dialyzer && \
- PATH=$(ERL_TOP)/bin:$${PATH} ERL_TOP=$(ERL_TOP) \
- $(MAKE) BUILD_ALL=1 TESTROOT=$(RELEASE_ROOT) $@
endif
cd $(ERL_TOP)/erts && \
PATH=$(ERL_TOP)/bin:$${PATH} ERL_TOP=$(ERL_TOP) \
@@ -423,7 +412,7 @@ BOOT_BINDIR=$(BOOTSTRAP_ROOT)/bootstrap/erts/bin
BEAM_EVM=$(ERL_TOP)/bin/$(TARGET)/beam_evm
BOOTSTRAP_COMPILER = $(BOOTSTRAP_TOP)/primary_compiler
-.PHONY: emulator libs kernel stdlib compiler hipe dialyzer typer syntax_tools preloaded
+.PHONY: emulator libs kernel stdlib compiler hipe typer syntax_tools preloaded
emulator:
cd erts && ERL_TOP=$(ERL_TOP) $(MAKE) NO_START_SCRIPTS=true $(TYPE) FLAVOR=$(FLAVOR)
@@ -458,19 +447,6 @@ hipe:
ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)$${PATH} \
$(MAKE) opt BUILD_ALL=true
-dialyzer:
-ifneq ($(OTP_SMALL_BUILD),true)
- @if test -f lib/dialyzer/SKIP ; then \
- echo "=== Skipping dialyzer, reason:" ; \
- cat lib/dialyzer/SKIP ; \
- echo "===" ; \
- else \
- cd lib/dialyzer && \
- ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)$${PATH} \
- $(MAKE) opt BUILD_ALL=true ; \
- fi
-endif
-
typer:
cd lib/typer && \
ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)$${PATH} \
@@ -487,7 +463,8 @@ preloaded:
$(MAKE) opt BUILD_ALL=true
dep depend:
- test X"$$ERTS_SKIP_DEPEND" = X"true" || (cd erts/emulator && ERL_TOP=$(ERL_TOP) $(MAKE) generate depend)
+ test X"$$ERTS_SKIP_DEPEND" = X"true" || (cd erts/emulator && ERL_TOP=$(ERL_TOP) $(MAKE) generate)
+ test X"$$ERTS_SKIP_DEPEND" = X"true" || (cd erts/emulator && ERL_TOP=$(ERL_TOP) $(MAKE) depend)
test X"$$ERTS_SKIP_DEPEND" = X"true" || (cd erts/lib_src && ERL_TOP=$(ERL_TOP) $(MAKE) depend)
# Creates "erl" and "erlc" in bootstrap/bin which uses the precompiled
@@ -563,6 +540,8 @@ secondary_bootstrap_copy:
if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/parsetools ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/parsetools ; fi
if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/parsetools/ebin ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/parsetools/ebin ; fi
if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/parsetools/include ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/parsetools/include ; fi
+ if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/orber ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/orber ; fi
+ if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/orber/include ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/orber/include ; fi
for x in lib/parsetools/ebin/*.beam; do \
BN=`basename $$x`; \
TF=$(BOOTSTRAP_ROOT)/bootstrap/lib/parsetools/ebin/$$BN; \
@@ -610,6 +589,16 @@ secondary_bootstrap_copy:
true; \
done
# cp -f lib/asn1/src/*.erl lib/asn1/src/*.hrl $(BOOTSTRAP_ROOT)/bootstrap/lib/asn1/src
+ for x in lib/orber/include/*.hrl; do \
+ BN=`basename $$x`; \
+ TF=$(BOOTSTRAP_ROOT)/bootstrap/lib/orber/include/$$BN; \
+ test -f $$TF && \
+ test '!' -z "`find $$x -newer $$TF -print`" && \
+ cp $$x $$TF; \
+ test '!' -f $$TF && \
+ cp $$x $$TF; \
+ true; \
+ done
tertiary_bootstrap_build:
cd lib && \
@@ -631,13 +620,6 @@ tertiary_bootstrap_copy:
true; \
done
# cp lib/snmp/ebin/*.beam $(BOOTSTRAP_ROOT)/bootstrap/lib/snmp/ebin
-
-fourth_bootstrap_build:
- cd lib && \
- ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)$${PATH} \
- $(MAKE) opt FOURTH_BOOTSTRAP=true
-
-fourth_bootstrap_copy:
if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/sasl ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/sasl ; fi
if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/sasl/ebin ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/sasl/ebin ; fi
if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/sasl/include ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/sasl/include ; fi
@@ -724,7 +706,6 @@ fourth_bootstrap_copy:
cp $$x $$TF; \
true; \
done
-
# cp lib/syntax_tools/ebin/*.beam $(BOOTSTRAP_ROOT)/bootstrap/lib/syntax_tools/ebin
.PHONY: check_recreate_primary_bootstrap recreate_primary_bootstrap
@@ -875,50 +856,10 @@ tests release_tests: $(TEST_DIRS)
$(TEST_DIRS):
if test -f $@/Makefile; then \
- (cd $@; $(MAKE) TESTROOT=$(TESTSUITE_ROOT) release_tests) || exit $$?; \
+ (cd $@; $(MAKE) TESTROOT=$(TESTSUITE_ROOT) \
+ PATH=$(ERL_TOP)/bin:$(BOOT_PREFIX)$${PATH} release_tests) || exit $$?; \
fi
-# ----------------------------------------------------------------------
-# Obsolete type of bootstrap where all stages where built with installed sytem
-# shuld no longer be used and is soon to be removed.
-# Abbreviations: OC = Old Compiler, NC = New Compiler,
-# OE = Old Emulator, NE = New Emulator
-
-old_com_bootstrap: old_bootstrap_nc_for_ne_all_stages old_bootstrap_ne old_bootstrap_scripts
-
-#
-# Builds the New Compiler for the New Emulator (using existing erlc
-# and possibly new compiler) then copy everything to the release area.
-# Use to create the commerciall bootstrap version, which should be obsolete.
-#
-old_bootstrap_nc_for_ne_all_stages:
- test -d $(TESTROOT) || mkdir -p $(TESTROOT)
- cd lib && $(MAKE) BOOTSTRAP=1 TYPE=release release
- cd lib && $(MAKE) SECONDARY_BOOTSTRAP=1 TYPE=release release
- cd lib && $(MAKE) TERTIARY_BOOTSTRAP=1 TYPE=release release
- cd lib && $(MAKE) FOURTH_BOOTSTRAP=1 TYPE=release release
-
-
-
-old_bootstrap_ne:
- cd erts && $(MAKE) release
-
-old_bootstrap_scripts:
- cd erts/start_scripts && $(MAKE) release
-
-
-# This is one strange name for a target, this actually builds and strips only
-# the primary bootstrap, a minimal set of beam files to be able to continue
-# bootstrap builds. It's used by other makefiles, so I refrain from
-# changing the name right now...
-bootstrap_nc_for_ne_no_debug_sym:
- test -d $(TESTROOT) || mkdir -p $(TESTROOT)
- cd lib && $(MAKE) ERLC_FLAGS='-pa $(BOOTSTRAP_COMPILER)/ebin' \
- BOOTSTRAP_TOP=$(BOOTSTRAP_TOP) BOOTSTRAP=1 TYPE=release release
- $(ERL_TOP)/erts/emulator/utils/beam_strip $(TESTROOT)/lib/*/ebin/*.beam
-
-# ----------------------------------------------------------------------
-
#
# Install
#
@@ -947,15 +888,6 @@ else
cd lib && \
ERL_TOP=$(ERL_TOP) PATH=$(INST_PATH_PREFIX)$${PATH} \
$(MAKE) TESTROOT=$(ERLANG_LIBDIR) BUILD_ALL=true release
- @if test -f lib/dialyzer/SKIP ; then \
- echo "=== Skipping dialyzer, reason:" ; \
- cat lib/dialyzer/SKIP ; \
- echo "===" ; \
- else \
- cd lib/dialyzer && \
- ERL_TOP=$(ERL_TOP) PATH=$(INST_PATH_PREFIX)$${PATH} \
- $(MAKE) TESTROOT=$(ERLANG_LIBDIR) BUILD_ALL=true release ; \
- fi
endif
install.Install:
@@ -1007,7 +939,6 @@ clean: check_recreate_primary_bootstrap
find . -type f -name SKIP -print | xargs $(RM)
cd erts && ERL_TOP=$(ERL_TOP) $(MAKE) clean
cd lib && ERL_TOP=$(ERL_TOP) $(MAKE) clean BUILD_ALL=true
- cd lib/dialyzer && ERL_TOP=$(ERL_TOP) $(MAKE) clean
#
# Just wipe out emulator, not libraries
diff --git a/bootstrap/bin/start.boot b/bootstrap/bin/start.boot
index 875f1b1c8b..0b1fd8e039 100644
--- a/bootstrap/bin/start.boot
+++ b/bootstrap/bin/start.boot
Binary files differ
diff --git a/bootstrap/bin/start.script b/bootstrap/bin/start.script
deleted file mode 100644
index 9b447c34a9..0000000000
--- a/bootstrap/bin/start.script
+++ /dev/null
@@ -1,113 +0,0 @@
-%% script generated at {2011,5,20} {15,43,53}
-{script,
- {"OTP APN 181 01","R14B03"},
- [{preLoaded,
- [erl_prim_loader,erlang,init,otp_ring0,prim_file,prim_inet,prim_zip,
- zlib]},
- {progress,preloaded},
- {path,["$ROOT/lib/kernel/ebin","$ROOT/lib/stdlib/ebin"]},
- {primLoad,[error_handler]},
- {kernel_load_completed},
- {progress,kernel_load_completed},
- {path,["$ROOT/lib/kernel/ebin"]},
- {primLoad,
- [application,application_controller,application_master,
- application_starter,auth,code,code_server,disk_log,disk_log_1,
- disk_log_server,disk_log_sup,dist_ac,dist_util,erl_boot_server,
- erl_ddll,erl_distribution,erl_epmd,erl_reply,error_logger,
- erts_debug,file,file_io_server,file_server,gen_sctp,gen_tcp,gen_udp,
- global,global_group,global_search,group,heart,hipe_unified_loader,
- inet,inet6_sctp,inet6_tcp,inet6_tcp_dist,inet6_udp,inet_config,
- inet_db,inet_dns,inet_gethost_native,inet_hosts,inet_parse,inet_res,
- inet_sctp,inet_tcp,inet_tcp_dist,inet_udp,kernel,kernel_config,net,
- net_adm,net_kernel,os,packages,pg2,ram_file,rpc,seq_trace,
- standard_error,user,user_drv,user_sup,wrap_log_reader]},
- {path,["$ROOT/lib/stdlib/ebin"]},
- {primLoad,
- [array,base64,beam_lib,binary,c,calendar,dets,dets_server,dets_sup,
- dets_utils,dets_v8,dets_v9,dict,digraph,digraph_utils,edlin,
- edlin_expand,epp,erl_bits,erl_compile,erl_eval,erl_expand_records,
- erl_internal,erl_lint,erl_parse,erl_posix_msg,erl_pp,erl_scan,
- erl_tar,error_logger_file_h,error_logger_tty_h,escript,ets,
- eval_bits,file_sorter,filelib,filename,gb_sets,gb_trees,gen,
- gen_event,gen_fsm,gen_server,io,io_lib,io_lib_format,io_lib_fread,
- io_lib_pretty,lib,lists,log_mf_h,math,ms_transform,orddict,ordsets,
- otp_internal,pg,pool,proc_lib,proplists,qlc,qlc_pt,queue,random,re,
- regexp,sets,shell,shell_default,slave,sofs,string,supervisor,
- supervisor_bridge,sys,timer,unicode,win32reg,zip]},
- {progress,modules_loaded},
- {path,["$ROOT/lib/kernel/ebin","$ROOT/lib/stdlib/ebin"]},
- {kernelProcess,heart,{heart,start,[]}},
- {kernelProcess,error_logger,{error_logger,start_link,[]}},
- {kernelProcess,application_controller,
- {application_controller,start,
- [{application,kernel,
- [{description,"ERTS CXC 138 10"},
- {vsn,"2.14.4"},
- {id,[]},
- {modules,
- [application,application_controller,application_master,
- application_starter,auth,code,packages,code_server,
- dist_util,erl_boot_server,erl_distribution,erl_reply,
- error_handler,error_logger,file,file_server,
- file_io_server,global,global_group,global_search,
- group,heart,hipe_unified_loader,inet6_tcp,
- inet6_tcp_dist,inet6_udp,inet6_sctp,inet_config,
- inet_hosts,inet_gethost_native,inet_tcp_dist,kernel,
- kernel_config,net,net_adm,net_kernel,os,ram_file,rpc,
- user,user_drv,user_sup,disk_log,disk_log_1,
- disk_log_server,disk_log_sup,dist_ac,erl_ddll,
- erl_epmd,erts_debug,gen_tcp,gen_udp,gen_sctp,inet,
- inet_db,inet_dns,inet_parse,inet_res,inet_tcp,
- inet_udp,inet_sctp,pg2,seq_trace,standard_error,
- wrap_log_reader]},
- {registered,
- [application_controller,erl_reply,auth,boot_server,
- code_server,disk_log_server,disk_log_sup,
- erl_prim_loader,error_logger,file_server_2,
- fixtable_server,global_group,global_name_server,heart,
- init,kernel_config,kernel_sup,net_kernel,net_sup,rex,
- user,os_server,ddll_server,erl_epmd,inet_db,pg2]},
- {applications,[]},
- {included_applications,[]},
- {env,[{error_logger,tty}]},
- {start_phases,undefined},
- {maxT,infinity},
- {maxP,infinity},
- {mod,{kernel,[]}}]}]}},
- {progress,init_kernel_started},
- {apply,
- {application,load,
- [{application,stdlib,
- [{description,"ERTS CXC 138 10"},
- {vsn,"1.17.4"},
- {id,[]},
- {modules,
- [array,base64,beam_lib,binary,c,calendar,dets,
- dets_server,dets_sup,dets_utils,dets_v8,dets_v9,dict,
- digraph,digraph_utils,edlin,edlin_expand,epp,
- eval_bits,erl_bits,erl_compile,erl_eval,
- erl_expand_records,erl_internal,erl_lint,erl_parse,
- erl_posix_msg,erl_pp,erl_scan,erl_tar,
- error_logger_file_h,error_logger_tty_h,escript,ets,
- file_sorter,filelib,filename,gb_trees,gb_sets,gen,
- gen_event,gen_fsm,gen_server,io,io_lib,io_lib_format,
- io_lib_fread,io_lib_pretty,lib,lists,log_mf_h,math,
- ms_transform,orddict,ordsets,otp_internal,pg,pool,
- proc_lib,proplists,qlc,qlc_pt,queue,random,re,regexp,
- sets,shell,shell_default,slave,sofs,string,supervisor,
- supervisor_bridge,sys,timer,unicode,win32reg,zip]},
- {registered,
- [timer_server,rsh_starter,take_over_monitor,
- pool_master,dets]},
- {applications,[kernel]},
- {included_applications,[]},
- {env,[]},
- {start_phases,undefined},
- {maxT,infinity},
- {maxP,infinity}]}]}},
- {progress,applications_loaded},
- {apply,{application,start_boot,[kernel,permanent]}},
- {apply,{application,start_boot,[stdlib,permanent]}},
- {apply,{c,erlangrc,[]}},
- {progress,started}]}.
diff --git a/bootstrap/bin/start_clean.boot b/bootstrap/bin/start_clean.boot
index 875f1b1c8b..0b1fd8e039 100644
--- a/bootstrap/bin/start_clean.boot
+++ b/bootstrap/bin/start_clean.boot
Binary files differ
diff --git a/bootstrap/bin/start_clean.script b/bootstrap/bin/start_clean.script
deleted file mode 100644
index 9b447c34a9..0000000000
--- a/bootstrap/bin/start_clean.script
+++ /dev/null
@@ -1,113 +0,0 @@
-%% script generated at {2011,5,20} {15,43,53}
-{script,
- {"OTP APN 181 01","R14B03"},
- [{preLoaded,
- [erl_prim_loader,erlang,init,otp_ring0,prim_file,prim_inet,prim_zip,
- zlib]},
- {progress,preloaded},
- {path,["$ROOT/lib/kernel/ebin","$ROOT/lib/stdlib/ebin"]},
- {primLoad,[error_handler]},
- {kernel_load_completed},
- {progress,kernel_load_completed},
- {path,["$ROOT/lib/kernel/ebin"]},
- {primLoad,
- [application,application_controller,application_master,
- application_starter,auth,code,code_server,disk_log,disk_log_1,
- disk_log_server,disk_log_sup,dist_ac,dist_util,erl_boot_server,
- erl_ddll,erl_distribution,erl_epmd,erl_reply,error_logger,
- erts_debug,file,file_io_server,file_server,gen_sctp,gen_tcp,gen_udp,
- global,global_group,global_search,group,heart,hipe_unified_loader,
- inet,inet6_sctp,inet6_tcp,inet6_tcp_dist,inet6_udp,inet_config,
- inet_db,inet_dns,inet_gethost_native,inet_hosts,inet_parse,inet_res,
- inet_sctp,inet_tcp,inet_tcp_dist,inet_udp,kernel,kernel_config,net,
- net_adm,net_kernel,os,packages,pg2,ram_file,rpc,seq_trace,
- standard_error,user,user_drv,user_sup,wrap_log_reader]},
- {path,["$ROOT/lib/stdlib/ebin"]},
- {primLoad,
- [array,base64,beam_lib,binary,c,calendar,dets,dets_server,dets_sup,
- dets_utils,dets_v8,dets_v9,dict,digraph,digraph_utils,edlin,
- edlin_expand,epp,erl_bits,erl_compile,erl_eval,erl_expand_records,
- erl_internal,erl_lint,erl_parse,erl_posix_msg,erl_pp,erl_scan,
- erl_tar,error_logger_file_h,error_logger_tty_h,escript,ets,
- eval_bits,file_sorter,filelib,filename,gb_sets,gb_trees,gen,
- gen_event,gen_fsm,gen_server,io,io_lib,io_lib_format,io_lib_fread,
- io_lib_pretty,lib,lists,log_mf_h,math,ms_transform,orddict,ordsets,
- otp_internal,pg,pool,proc_lib,proplists,qlc,qlc_pt,queue,random,re,
- regexp,sets,shell,shell_default,slave,sofs,string,supervisor,
- supervisor_bridge,sys,timer,unicode,win32reg,zip]},
- {progress,modules_loaded},
- {path,["$ROOT/lib/kernel/ebin","$ROOT/lib/stdlib/ebin"]},
- {kernelProcess,heart,{heart,start,[]}},
- {kernelProcess,error_logger,{error_logger,start_link,[]}},
- {kernelProcess,application_controller,
- {application_controller,start,
- [{application,kernel,
- [{description,"ERTS CXC 138 10"},
- {vsn,"2.14.4"},
- {id,[]},
- {modules,
- [application,application_controller,application_master,
- application_starter,auth,code,packages,code_server,
- dist_util,erl_boot_server,erl_distribution,erl_reply,
- error_handler,error_logger,file,file_server,
- file_io_server,global,global_group,global_search,
- group,heart,hipe_unified_loader,inet6_tcp,
- inet6_tcp_dist,inet6_udp,inet6_sctp,inet_config,
- inet_hosts,inet_gethost_native,inet_tcp_dist,kernel,
- kernel_config,net,net_adm,net_kernel,os,ram_file,rpc,
- user,user_drv,user_sup,disk_log,disk_log_1,
- disk_log_server,disk_log_sup,dist_ac,erl_ddll,
- erl_epmd,erts_debug,gen_tcp,gen_udp,gen_sctp,inet,
- inet_db,inet_dns,inet_parse,inet_res,inet_tcp,
- inet_udp,inet_sctp,pg2,seq_trace,standard_error,
- wrap_log_reader]},
- {registered,
- [application_controller,erl_reply,auth,boot_server,
- code_server,disk_log_server,disk_log_sup,
- erl_prim_loader,error_logger,file_server_2,
- fixtable_server,global_group,global_name_server,heart,
- init,kernel_config,kernel_sup,net_kernel,net_sup,rex,
- user,os_server,ddll_server,erl_epmd,inet_db,pg2]},
- {applications,[]},
- {included_applications,[]},
- {env,[{error_logger,tty}]},
- {start_phases,undefined},
- {maxT,infinity},
- {maxP,infinity},
- {mod,{kernel,[]}}]}]}},
- {progress,init_kernel_started},
- {apply,
- {application,load,
- [{application,stdlib,
- [{description,"ERTS CXC 138 10"},
- {vsn,"1.17.4"},
- {id,[]},
- {modules,
- [array,base64,beam_lib,binary,c,calendar,dets,
- dets_server,dets_sup,dets_utils,dets_v8,dets_v9,dict,
- digraph,digraph_utils,edlin,edlin_expand,epp,
- eval_bits,erl_bits,erl_compile,erl_eval,
- erl_expand_records,erl_internal,erl_lint,erl_parse,
- erl_posix_msg,erl_pp,erl_scan,erl_tar,
- error_logger_file_h,error_logger_tty_h,escript,ets,
- file_sorter,filelib,filename,gb_trees,gb_sets,gen,
- gen_event,gen_fsm,gen_server,io,io_lib,io_lib_format,
- io_lib_fread,io_lib_pretty,lib,lists,log_mf_h,math,
- ms_transform,orddict,ordsets,otp_internal,pg,pool,
- proc_lib,proplists,qlc,qlc_pt,queue,random,re,regexp,
- sets,shell,shell_default,slave,sofs,string,supervisor,
- supervisor_bridge,sys,timer,unicode,win32reg,zip]},
- {registered,
- [timer_server,rsh_starter,take_over_monitor,
- pool_master,dets]},
- {applications,[kernel]},
- {included_applications,[]},
- {env,[]},
- {start_phases,undefined},
- {maxT,infinity},
- {maxP,infinity}]}]}},
- {progress,applications_loaded},
- {apply,{application,start_boot,[kernel,permanent]}},
- {apply,{application,start_boot,[stdlib,permanent]}},
- {apply,{c,erlangrc,[]}},
- {progress,started}]}.
diff --git a/bootstrap/lib/compiler/ebin/beam_asm.beam b/bootstrap/lib/compiler/ebin/beam_asm.beam
index 5719592cae..103ed82529 100644
--- a/bootstrap/lib/compiler/ebin/beam_asm.beam
+++ b/bootstrap/lib/compiler/ebin/beam_asm.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_block.beam b/bootstrap/lib/compiler/ebin/beam_block.beam
index 41be7667fc..a5699221fe 100644
--- a/bootstrap/lib/compiler/ebin/beam_block.beam
+++ b/bootstrap/lib/compiler/ebin/beam_block.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_bool.beam b/bootstrap/lib/compiler/ebin/beam_bool.beam
index ef6e7823cc..d8f91ec36d 100644
--- a/bootstrap/lib/compiler/ebin/beam_bool.beam
+++ b/bootstrap/lib/compiler/ebin/beam_bool.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_bsm.beam b/bootstrap/lib/compiler/ebin/beam_bsm.beam
index 48302c39d2..02f82a9341 100644
--- a/bootstrap/lib/compiler/ebin/beam_bsm.beam
+++ b/bootstrap/lib/compiler/ebin/beam_bsm.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_clean.beam b/bootstrap/lib/compiler/ebin/beam_clean.beam
index 0b28815f2a..70523ca134 100644
--- a/bootstrap/lib/compiler/ebin/beam_clean.beam
+++ b/bootstrap/lib/compiler/ebin/beam_clean.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_dead.beam b/bootstrap/lib/compiler/ebin/beam_dead.beam
index 652e2b44ea..b177adb455 100644
--- a/bootstrap/lib/compiler/ebin/beam_dead.beam
+++ b/bootstrap/lib/compiler/ebin/beam_dead.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_dict.beam b/bootstrap/lib/compiler/ebin/beam_dict.beam
index b65ebca3cd..81e62b0a7d 100644
--- a/bootstrap/lib/compiler/ebin/beam_dict.beam
+++ b/bootstrap/lib/compiler/ebin/beam_dict.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_disasm.beam b/bootstrap/lib/compiler/ebin/beam_disasm.beam
index c8e2b27623..377c738709 100644
--- a/bootstrap/lib/compiler/ebin/beam_disasm.beam
+++ b/bootstrap/lib/compiler/ebin/beam_disasm.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_flatten.beam b/bootstrap/lib/compiler/ebin/beam_flatten.beam
index 402f2a14ae..0ac0dc7b92 100644
--- a/bootstrap/lib/compiler/ebin/beam_flatten.beam
+++ b/bootstrap/lib/compiler/ebin/beam_flatten.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_jump.beam b/bootstrap/lib/compiler/ebin/beam_jump.beam
index 1ee7b725fb..f45b8d3124 100644
--- a/bootstrap/lib/compiler/ebin/beam_jump.beam
+++ b/bootstrap/lib/compiler/ebin/beam_jump.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_listing.beam b/bootstrap/lib/compiler/ebin/beam_listing.beam
index b282af5fce..662edc0651 100644
--- a/bootstrap/lib/compiler/ebin/beam_listing.beam
+++ b/bootstrap/lib/compiler/ebin/beam_listing.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_opcodes.beam b/bootstrap/lib/compiler/ebin/beam_opcodes.beam
index 6ded472cb0..2c414f1c7d 100644
--- a/bootstrap/lib/compiler/ebin/beam_opcodes.beam
+++ b/bootstrap/lib/compiler/ebin/beam_opcodes.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_peep.beam b/bootstrap/lib/compiler/ebin/beam_peep.beam
index 279dd272b5..aaba79046c 100644
--- a/bootstrap/lib/compiler/ebin/beam_peep.beam
+++ b/bootstrap/lib/compiler/ebin/beam_peep.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_receive.beam b/bootstrap/lib/compiler/ebin/beam_receive.beam
index 4d88e80acd..ae873a1082 100644
--- a/bootstrap/lib/compiler/ebin/beam_receive.beam
+++ b/bootstrap/lib/compiler/ebin/beam_receive.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_trim.beam b/bootstrap/lib/compiler/ebin/beam_trim.beam
index 5c0d405843..b1275f787a 100644
--- a/bootstrap/lib/compiler/ebin/beam_trim.beam
+++ b/bootstrap/lib/compiler/ebin/beam_trim.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_type.beam b/bootstrap/lib/compiler/ebin/beam_type.beam
index cccf58b7a4..67e6dbd8a1 100644
--- a/bootstrap/lib/compiler/ebin/beam_type.beam
+++ b/bootstrap/lib/compiler/ebin/beam_type.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_utils.beam b/bootstrap/lib/compiler/ebin/beam_utils.beam
index c335748e8a..b80810bfb2 100644
--- a/bootstrap/lib/compiler/ebin/beam_utils.beam
+++ b/bootstrap/lib/compiler/ebin/beam_utils.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_validator.beam b/bootstrap/lib/compiler/ebin/beam_validator.beam
index 32e75091f4..211c56424e 100644
--- a/bootstrap/lib/compiler/ebin/beam_validator.beam
+++ b/bootstrap/lib/compiler/ebin/beam_validator.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/cerl.beam b/bootstrap/lib/compiler/ebin/cerl.beam
index 9f45f9f441..399aeb6442 100644
--- a/bootstrap/lib/compiler/ebin/cerl.beam
+++ b/bootstrap/lib/compiler/ebin/cerl.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/cerl_clauses.beam b/bootstrap/lib/compiler/ebin/cerl_clauses.beam
index 5004b4d4c2..e4db75d0e0 100644
--- a/bootstrap/lib/compiler/ebin/cerl_clauses.beam
+++ b/bootstrap/lib/compiler/ebin/cerl_clauses.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/cerl_inline.beam b/bootstrap/lib/compiler/ebin/cerl_inline.beam
index e0cfce01ae..582604e3cc 100644
--- a/bootstrap/lib/compiler/ebin/cerl_inline.beam
+++ b/bootstrap/lib/compiler/ebin/cerl_inline.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/cerl_trees.beam b/bootstrap/lib/compiler/ebin/cerl_trees.beam
index d46cfe54b7..673954eaac 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 c4b31874cc..bead5a1399 100644
--- a/bootstrap/lib/compiler/ebin/compile.beam
+++ b/bootstrap/lib/compiler/ebin/compile.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/compiler.app b/bootstrap/lib/compiler/ebin/compiler.app
deleted file mode 100644
index fffb64c3a0..0000000000
--- a/bootstrap/lib/compiler/ebin/compiler.app
+++ /dev/null
@@ -1,67 +0,0 @@
-% This is an -*- erlang -*- file.
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-
-{application, compiler,
- [{description, "ERTS CXC 138 10"},
- {vsn, "4.7.3"},
- {modules, [
- beam_asm,
- beam_block,
- beam_bool,
- beam_bsm,
- beam_clean,
- beam_dead,
- beam_dict,
- beam_disasm,
- beam_flatten,
- beam_jump,
- beam_listing,
- beam_opcodes,
- beam_peep,
- beam_receive,
- beam_trim,
- beam_type,
- beam_utils,
- beam_validator,
- cerl,
- cerl_clauses,
- cerl_inline,
- cerl_trees,
- compile,
- core_scan,
- core_lint,
- core_parse,
- core_pp,
- core_lib,
- erl_bifs,
- rec_env,
- sys_core_dsetel,
- sys_core_fold,
- sys_core_inline,
- sys_expand_pmod,
- sys_pre_attributes,
- sys_pre_expand,
- v3_codegen,
- v3_core,
- v3_kernel,
- v3_kernel_pp,
- v3_life
- ]},
- {registered, []},
- {applications, [kernel, stdlib]},
- {env, []}]}.
diff --git a/bootstrap/lib/compiler/ebin/compiler.appup b/bootstrap/lib/compiler/ebin/compiler.appup
deleted file mode 100644
index 10c9fd3dde..0000000000
--- a/bootstrap/lib/compiler/ebin/compiler.appup
+++ /dev/null
@@ -1 +0,0 @@
-{"4.7.1",[],[]}.
diff --git a/bootstrap/lib/compiler/ebin/core_lib.beam b/bootstrap/lib/compiler/ebin/core_lib.beam
index 8796f7e13e..ddb5278d00 100644
--- a/bootstrap/lib/compiler/ebin/core_lib.beam
+++ b/bootstrap/lib/compiler/ebin/core_lib.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/core_lint.beam b/bootstrap/lib/compiler/ebin/core_lint.beam
index 813c444d9c..225fa95aea 100644
--- a/bootstrap/lib/compiler/ebin/core_lint.beam
+++ b/bootstrap/lib/compiler/ebin/core_lint.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/core_parse.beam b/bootstrap/lib/compiler/ebin/core_parse.beam
index 973659b27b..11926c4a16 100644
--- a/bootstrap/lib/compiler/ebin/core_parse.beam
+++ b/bootstrap/lib/compiler/ebin/core_parse.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/core_pp.beam b/bootstrap/lib/compiler/ebin/core_pp.beam
index fb9001c52f..f1841d810b 100644
--- a/bootstrap/lib/compiler/ebin/core_pp.beam
+++ b/bootstrap/lib/compiler/ebin/core_pp.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/core_scan.beam b/bootstrap/lib/compiler/ebin/core_scan.beam
index cd2146d722..e0e4859095 100644
--- a/bootstrap/lib/compiler/ebin/core_scan.beam
+++ b/bootstrap/lib/compiler/ebin/core_scan.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/erl_bifs.beam b/bootstrap/lib/compiler/ebin/erl_bifs.beam
index 128f8a88d2..b411e06c08 100644
--- a/bootstrap/lib/compiler/ebin/erl_bifs.beam
+++ b/bootstrap/lib/compiler/ebin/erl_bifs.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/rec_env.beam b/bootstrap/lib/compiler/ebin/rec_env.beam
index 8a1de81396..91a86d9855 100644
--- a/bootstrap/lib/compiler/ebin/rec_env.beam
+++ b/bootstrap/lib/compiler/ebin/rec_env.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_core_dsetel.beam b/bootstrap/lib/compiler/ebin/sys_core_dsetel.beam
index 2975d77648..0764734cb1 100644
--- a/bootstrap/lib/compiler/ebin/sys_core_dsetel.beam
+++ b/bootstrap/lib/compiler/ebin/sys_core_dsetel.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_core_fold.beam b/bootstrap/lib/compiler/ebin/sys_core_fold.beam
index c7b247762c..b07afc0938 100644
--- a/bootstrap/lib/compiler/ebin/sys_core_fold.beam
+++ b/bootstrap/lib/compiler/ebin/sys_core_fold.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_core_inline.beam b/bootstrap/lib/compiler/ebin/sys_core_inline.beam
index 919b616c62..5b9e9d7c3e 100644
--- a/bootstrap/lib/compiler/ebin/sys_core_inline.beam
+++ b/bootstrap/lib/compiler/ebin/sys_core_inline.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_expand_pmod.beam b/bootstrap/lib/compiler/ebin/sys_expand_pmod.beam
index 3323279d7d..5142cdde01 100644
--- a/bootstrap/lib/compiler/ebin/sys_expand_pmod.beam
+++ b/bootstrap/lib/compiler/ebin/sys_expand_pmod.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_pre_attributes.beam b/bootstrap/lib/compiler/ebin/sys_pre_attributes.beam
index 9708cff55e..4b3e984ed4 100644
--- a/bootstrap/lib/compiler/ebin/sys_pre_attributes.beam
+++ b/bootstrap/lib/compiler/ebin/sys_pre_attributes.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_pre_expand.beam b/bootstrap/lib/compiler/ebin/sys_pre_expand.beam
index 7b4d278e30..12664c7270 100644
--- a/bootstrap/lib/compiler/ebin/sys_pre_expand.beam
+++ b/bootstrap/lib/compiler/ebin/sys_pre_expand.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_codegen.beam b/bootstrap/lib/compiler/ebin/v3_codegen.beam
index 51fac17844..3a8d68a611 100644
--- a/bootstrap/lib/compiler/ebin/v3_codegen.beam
+++ b/bootstrap/lib/compiler/ebin/v3_codegen.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_core.beam b/bootstrap/lib/compiler/ebin/v3_core.beam
index 87cb60e41c..ff7144c2bc 100644
--- a/bootstrap/lib/compiler/ebin/v3_core.beam
+++ b/bootstrap/lib/compiler/ebin/v3_core.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_kernel.beam b/bootstrap/lib/compiler/ebin/v3_kernel.beam
index 18790f80a6..48b89b374b 100644
--- a/bootstrap/lib/compiler/ebin/v3_kernel.beam
+++ b/bootstrap/lib/compiler/ebin/v3_kernel.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam b/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam
index b7d2a409b5..485aa63dcb 100644
--- a/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam
+++ b/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_life.beam b/bootstrap/lib/compiler/ebin/v3_life.beam
index 3f0a409447..b7996884f4 100644
--- a/bootstrap/lib/compiler/ebin/v3_life.beam
+++ b/bootstrap/lib/compiler/ebin/v3_life.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/egen/beam_opcodes.erl b/bootstrap/lib/compiler/egen/beam_opcodes.erl
deleted file mode 100644
index fda227f90f..0000000000
--- a/bootstrap/lib/compiler/egen/beam_opcodes.erl
+++ /dev/null
@@ -1,319 +0,0 @@
--module(beam_opcodes).
-%% Warning: Do not edit this file.
-%% Auto-generated by 'beam_makeops'.
-
--export([format_number/0]).
--export([opcode/2,opname/1]).
-
--spec format_number() -> 0.
-format_number() -> 0.
-
--spec opcode(atom(), 0..8) -> 1..152.
-opcode(label, 1) -> 1;
-opcode(func_info, 3) -> 2;
-opcode(int_code_end, 0) -> 3;
-opcode(call, 2) -> 4;
-opcode(call_last, 3) -> 5;
-opcode(call_only, 2) -> 6;
-opcode(call_ext, 2) -> 7;
-opcode(call_ext_last, 3) -> 8;
-opcode(bif0, 2) -> 9;
-opcode(bif1, 4) -> 10;
-opcode(bif2, 5) -> 11;
-opcode(allocate, 2) -> 12;
-opcode(allocate_heap, 3) -> 13;
-opcode(allocate_zero, 2) -> 14;
-opcode(allocate_heap_zero, 3) -> 15;
-opcode(test_heap, 2) -> 16;
-opcode(init, 1) -> 17;
-opcode(deallocate, 1) -> 18;
-opcode(return, 0) -> 19;
-opcode(send, 0) -> 20;
-opcode(remove_message, 0) -> 21;
-opcode(timeout, 0) -> 22;
-opcode(loop_rec, 2) -> 23;
-opcode(loop_rec_end, 1) -> 24;
-opcode(wait, 1) -> 25;
-opcode(wait_timeout, 2) -> 26;
-%%opcode(m_plus, 4) -> 27;
-%%opcode(m_minus, 4) -> 28;
-%%opcode(m_times, 4) -> 29;
-%%opcode(m_div, 4) -> 30;
-%%opcode(int_div, 4) -> 31;
-%%opcode(int_rem, 4) -> 32;
-%%opcode(int_band, 4) -> 33;
-%%opcode(int_bor, 4) -> 34;
-%%opcode(int_bxor, 4) -> 35;
-%%opcode(int_bsl, 4) -> 36;
-%%opcode(int_bsr, 4) -> 37;
-%%opcode(int_bnot, 3) -> 38;
-opcode(is_lt, 3) -> 39;
-opcode(is_ge, 3) -> 40;
-opcode(is_eq, 3) -> 41;
-opcode(is_ne, 3) -> 42;
-opcode(is_eq_exact, 3) -> 43;
-opcode(is_ne_exact, 3) -> 44;
-opcode(is_integer, 2) -> 45;
-opcode(is_float, 2) -> 46;
-opcode(is_number, 2) -> 47;
-opcode(is_atom, 2) -> 48;
-opcode(is_pid, 2) -> 49;
-opcode(is_reference, 2) -> 50;
-opcode(is_port, 2) -> 51;
-opcode(is_nil, 2) -> 52;
-opcode(is_binary, 2) -> 53;
-%%opcode(is_constant, 2) -> 54;
-opcode(is_list, 2) -> 55;
-opcode(is_nonempty_list, 2) -> 56;
-opcode(is_tuple, 2) -> 57;
-opcode(test_arity, 3) -> 58;
-opcode(select_val, 3) -> 59;
-opcode(select_tuple_arity, 3) -> 60;
-opcode(jump, 1) -> 61;
-opcode('catch', 2) -> 62;
-opcode(catch_end, 1) -> 63;
-opcode(move, 2) -> 64;
-opcode(get_list, 3) -> 65;
-opcode(get_tuple_element, 3) -> 66;
-opcode(set_tuple_element, 3) -> 67;
-%%opcode(put_string, 3) -> 68;
-opcode(put_list, 3) -> 69;
-opcode(put_tuple, 2) -> 70;
-opcode(put, 1) -> 71;
-opcode(badmatch, 1) -> 72;
-opcode(if_end, 0) -> 73;
-opcode(case_end, 1) -> 74;
-opcode(call_fun, 1) -> 75;
-%%opcode(make_fun, 3) -> 76;
-opcode(is_function, 2) -> 77;
-opcode(call_ext_only, 2) -> 78;
-%%opcode(bs_start_match, 2) -> 79;
-%%opcode(bs_get_integer, 5) -> 80;
-%%opcode(bs_get_float, 5) -> 81;
-%%opcode(bs_get_binary, 5) -> 82;
-%%opcode(bs_skip_bits, 4) -> 83;
-%%opcode(bs_test_tail, 2) -> 84;
-%%opcode(bs_save, 1) -> 85;
-%%opcode(bs_restore, 1) -> 86;
-%%opcode(bs_init, 2) -> 87;
-%%opcode(bs_final, 2) -> 88;
-opcode(bs_put_integer, 5) -> 89;
-opcode(bs_put_binary, 5) -> 90;
-opcode(bs_put_float, 5) -> 91;
-opcode(bs_put_string, 2) -> 92;
-%%opcode(bs_need_buf, 1) -> 93;
-opcode(fclearerror, 0) -> 94;
-opcode(fcheckerror, 1) -> 95;
-opcode(fmove, 2) -> 96;
-opcode(fconv, 2) -> 97;
-opcode(fadd, 4) -> 98;
-opcode(fsub, 4) -> 99;
-opcode(fmul, 4) -> 100;
-opcode(fdiv, 4) -> 101;
-opcode(fnegate, 3) -> 102;
-opcode(make_fun2, 1) -> 103;
-opcode('try', 2) -> 104;
-opcode(try_end, 1) -> 105;
-opcode(try_case, 1) -> 106;
-opcode(try_case_end, 1) -> 107;
-opcode(raise, 2) -> 108;
-opcode(bs_init2, 6) -> 109;
-%%opcode(bs_bits_to_bytes, 3) -> 110;
-opcode(bs_add, 5) -> 111;
-opcode(apply, 1) -> 112;
-opcode(apply_last, 2) -> 113;
-opcode(is_boolean, 2) -> 114;
-opcode(is_function2, 3) -> 115;
-opcode(bs_start_match2, 5) -> 116;
-opcode(bs_get_integer2, 7) -> 117;
-opcode(bs_get_float2, 7) -> 118;
-opcode(bs_get_binary2, 7) -> 119;
-opcode(bs_skip_bits2, 5) -> 120;
-opcode(bs_test_tail2, 3) -> 121;
-opcode(bs_save2, 2) -> 122;
-opcode(bs_restore2, 2) -> 123;
-opcode(gc_bif1, 5) -> 124;
-opcode(gc_bif2, 6) -> 125;
-%%opcode(bs_final2, 2) -> 126;
-%%opcode(bs_bits_to_bytes2, 2) -> 127;
-%%opcode(put_literal, 2) -> 128;
-opcode(is_bitstr, 2) -> 129;
-opcode(bs_context_to_binary, 1) -> 130;
-opcode(bs_test_unit, 3) -> 131;
-opcode(bs_match_string, 4) -> 132;
-opcode(bs_init_writable, 0) -> 133;
-opcode(bs_append, 8) -> 134;
-opcode(bs_private_append, 6) -> 135;
-opcode(trim, 2) -> 136;
-opcode(bs_init_bits, 6) -> 137;
-opcode(bs_get_utf8, 5) -> 138;
-opcode(bs_skip_utf8, 4) -> 139;
-opcode(bs_get_utf16, 5) -> 140;
-opcode(bs_skip_utf16, 4) -> 141;
-opcode(bs_get_utf32, 5) -> 142;
-opcode(bs_skip_utf32, 4) -> 143;
-opcode(bs_utf8_size, 3) -> 144;
-opcode(bs_put_utf8, 3) -> 145;
-opcode(bs_utf16_size, 3) -> 146;
-opcode(bs_put_utf16, 3) -> 147;
-opcode(bs_put_utf32, 3) -> 148;
-opcode(on_load, 0) -> 149;
-opcode(recv_mark, 1) -> 150;
-opcode(recv_set, 1) -> 151;
-opcode(gc_bif3, 7) -> 152;
-opcode(Name, Arity) -> erlang:error(badarg, [Name,Arity]).
-
--spec opname(1..152) -> {atom(),0..8}.
-opname(1) -> {label,1};
-opname(2) -> {func_info,3};
-opname(3) -> {int_code_end,0};
-opname(4) -> {call,2};
-opname(5) -> {call_last,3};
-opname(6) -> {call_only,2};
-opname(7) -> {call_ext,2};
-opname(8) -> {call_ext_last,3};
-opname(9) -> {bif0,2};
-opname(10) -> {bif1,4};
-opname(11) -> {bif2,5};
-opname(12) -> {allocate,2};
-opname(13) -> {allocate_heap,3};
-opname(14) -> {allocate_zero,2};
-opname(15) -> {allocate_heap_zero,3};
-opname(16) -> {test_heap,2};
-opname(17) -> {init,1};
-opname(18) -> {deallocate,1};
-opname(19) -> {return,0};
-opname(20) -> {send,0};
-opname(21) -> {remove_message,0};
-opname(22) -> {timeout,0};
-opname(23) -> {loop_rec,2};
-opname(24) -> {loop_rec_end,1};
-opname(25) -> {wait,1};
-opname(26) -> {wait_timeout,2};
-opname(27) -> {m_plus,4};
-opname(28) -> {m_minus,4};
-opname(29) -> {m_times,4};
-opname(30) -> {m_div,4};
-opname(31) -> {int_div,4};
-opname(32) -> {int_rem,4};
-opname(33) -> {int_band,4};
-opname(34) -> {int_bor,4};
-opname(35) -> {int_bxor,4};
-opname(36) -> {int_bsl,4};
-opname(37) -> {int_bsr,4};
-opname(38) -> {int_bnot,3};
-opname(39) -> {is_lt,3};
-opname(40) -> {is_ge,3};
-opname(41) -> {is_eq,3};
-opname(42) -> {is_ne,3};
-opname(43) -> {is_eq_exact,3};
-opname(44) -> {is_ne_exact,3};
-opname(45) -> {is_integer,2};
-opname(46) -> {is_float,2};
-opname(47) -> {is_number,2};
-opname(48) -> {is_atom,2};
-opname(49) -> {is_pid,2};
-opname(50) -> {is_reference,2};
-opname(51) -> {is_port,2};
-opname(52) -> {is_nil,2};
-opname(53) -> {is_binary,2};
-opname(54) -> {is_constant,2};
-opname(55) -> {is_list,2};
-opname(56) -> {is_nonempty_list,2};
-opname(57) -> {is_tuple,2};
-opname(58) -> {test_arity,3};
-opname(59) -> {select_val,3};
-opname(60) -> {select_tuple_arity,3};
-opname(61) -> {jump,1};
-opname(62) -> {'catch',2};
-opname(63) -> {catch_end,1};
-opname(64) -> {move,2};
-opname(65) -> {get_list,3};
-opname(66) -> {get_tuple_element,3};
-opname(67) -> {set_tuple_element,3};
-opname(68) -> {put_string,3};
-opname(69) -> {put_list,3};
-opname(70) -> {put_tuple,2};
-opname(71) -> {put,1};
-opname(72) -> {badmatch,1};
-opname(73) -> {if_end,0};
-opname(74) -> {case_end,1};
-opname(75) -> {call_fun,1};
-opname(76) -> {make_fun,3};
-opname(77) -> {is_function,2};
-opname(78) -> {call_ext_only,2};
-opname(79) -> {bs_start_match,2};
-opname(80) -> {bs_get_integer,5};
-opname(81) -> {bs_get_float,5};
-opname(82) -> {bs_get_binary,5};
-opname(83) -> {bs_skip_bits,4};
-opname(84) -> {bs_test_tail,2};
-opname(85) -> {bs_save,1};
-opname(86) -> {bs_restore,1};
-opname(87) -> {bs_init,2};
-opname(88) -> {bs_final,2};
-opname(89) -> {bs_put_integer,5};
-opname(90) -> {bs_put_binary,5};
-opname(91) -> {bs_put_float,5};
-opname(92) -> {bs_put_string,2};
-opname(93) -> {bs_need_buf,1};
-opname(94) -> {fclearerror,0};
-opname(95) -> {fcheckerror,1};
-opname(96) -> {fmove,2};
-opname(97) -> {fconv,2};
-opname(98) -> {fadd,4};
-opname(99) -> {fsub,4};
-opname(100) -> {fmul,4};
-opname(101) -> {fdiv,4};
-opname(102) -> {fnegate,3};
-opname(103) -> {make_fun2,1};
-opname(104) -> {'try',2};
-opname(105) -> {try_end,1};
-opname(106) -> {try_case,1};
-opname(107) -> {try_case_end,1};
-opname(108) -> {raise,2};
-opname(109) -> {bs_init2,6};
-opname(110) -> {bs_bits_to_bytes,3};
-opname(111) -> {bs_add,5};
-opname(112) -> {apply,1};
-opname(113) -> {apply_last,2};
-opname(114) -> {is_boolean,2};
-opname(115) -> {is_function2,3};
-opname(116) -> {bs_start_match2,5};
-opname(117) -> {bs_get_integer2,7};
-opname(118) -> {bs_get_float2,7};
-opname(119) -> {bs_get_binary2,7};
-opname(120) -> {bs_skip_bits2,5};
-opname(121) -> {bs_test_tail2,3};
-opname(122) -> {bs_save2,2};
-opname(123) -> {bs_restore2,2};
-opname(124) -> {gc_bif1,5};
-opname(125) -> {gc_bif2,6};
-opname(126) -> {bs_final2,2};
-opname(127) -> {bs_bits_to_bytes2,2};
-opname(128) -> {put_literal,2};
-opname(129) -> {is_bitstr,2};
-opname(130) -> {bs_context_to_binary,1};
-opname(131) -> {bs_test_unit,3};
-opname(132) -> {bs_match_string,4};
-opname(133) -> {bs_init_writable,0};
-opname(134) -> {bs_append,8};
-opname(135) -> {bs_private_append,6};
-opname(136) -> {trim,2};
-opname(137) -> {bs_init_bits,6};
-opname(138) -> {bs_get_utf8,5};
-opname(139) -> {bs_skip_utf8,4};
-opname(140) -> {bs_get_utf16,5};
-opname(141) -> {bs_skip_utf16,4};
-opname(142) -> {bs_get_utf32,5};
-opname(143) -> {bs_skip_utf32,4};
-opname(144) -> {bs_utf8_size,3};
-opname(145) -> {bs_put_utf8,3};
-opname(146) -> {bs_utf16_size,3};
-opname(147) -> {bs_put_utf16,3};
-opname(148) -> {bs_put_utf32,3};
-opname(149) -> {on_load,0};
-opname(150) -> {recv_mark,1};
-opname(151) -> {recv_set,1};
-opname(152) -> {gc_bif3,7};
-opname(Number) -> erlang:error(badarg, [Number]).
diff --git a/bootstrap/lib/compiler/egen/beam_opcodes.hrl b/bootstrap/lib/compiler/egen/beam_opcodes.hrl
deleted file mode 100644
index 6ad7d17118..0000000000
--- a/bootstrap/lib/compiler/egen/beam_opcodes.hrl
+++ /dev/null
@@ -1,12 +0,0 @@
-%% Warning: Do not edit this file.
-%% Auto-generated by 'beam_makeops'.
-
--define(tag_u, 0).
--define(tag_i, 1).
--define(tag_a, 2).
--define(tag_x, 3).
--define(tag_y, 4).
--define(tag_f, 5).
--define(tag_h, 6).
--define(tag_z, 7).
-
diff --git a/bootstrap/lib/compiler/egen/core_parse.erl b/bootstrap/lib/compiler/egen/core_parse.erl
deleted file mode 100644
index 399d61109f..0000000000
--- a/bootstrap/lib/compiler/egen/core_parse.erl
+++ /dev/null
@@ -1,5426 +0,0 @@
--module(core_parse).
--export([parse/1, parse_and_scan/1, format_error/1]).
--file("core_parse.yrl", 372).
-
-%% The following directive is needed for (significantly) faster compilation
-%% of the generated .erl file by the HiPE compiler. Please do not remove.
--compile([{hipe,[{regalloc,linear_scan}]}]).
-
--include("core_parse.hrl").
-
--import(cerl, [c_cons/2,c_tuple/1]).
-
-tok_val(T) -> element(3, T).
-tok_line(T) -> element(2, T).
-
--file("/opt/installs/lib/erlang/lib/parsetools-2.0.5/include/yeccpre.hrl", 0).
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% The parser generator will insert appropriate declarations before this line.%
-
--type yecc_ret() :: {'error', _} | {'ok', _}.
-
--spec parse(Tokens :: list()) -> yecc_ret().
-parse(Tokens) ->
- yeccpars0(Tokens, {no_func, no_line}, 0, [], []).
-
--spec parse_and_scan({function() | {atom(), atom()}, [_]}
- | {atom(), atom(), [_]}) -> yecc_ret().
-parse_and_scan({F, A}) -> % Fun or {M, F}
- yeccpars0([], {{F, A}, no_line}, 0, [], []);
-parse_and_scan({M, F, A}) ->
- yeccpars0([], {{{M, F}, A}, no_line}, 0, [], []).
-
--spec format_error(any()) -> [char() | list()].
-format_error(Message) ->
- case io_lib:deep_char_list(Message) of
- true ->
- Message;
- _ ->
- io_lib:write(Message)
- end.
-
-%% To be used in grammar files to throw an error message to the parser
-%% toplevel. Doesn't have to be exported!
--compile({nowarn_unused_function, return_error/2}).
--spec return_error(integer(), any()) -> no_return().
-return_error(Line, Message) ->
- throw({error, {Line, ?MODULE, Message}}).
-
--define(CODE_VERSION, "1.4").
-
-yeccpars0(Tokens, Tzr, State, States, Vstack) ->
- try yeccpars1(Tokens, Tzr, State, States, Vstack)
- catch
- error: Error ->
- Stacktrace = erlang:get_stacktrace(),
- try yecc_error_type(Error, Stacktrace) of
- Desc ->
- erlang:raise(error, {yecc_bug, ?CODE_VERSION, Desc},
- Stacktrace)
- catch _:_ -> erlang:raise(error, Error, Stacktrace)
- end;
- %% Probably thrown from return_error/2:
- throw: {error, {_Line, ?MODULE, _M}} = Error ->
- Error
- end.
-
-yecc_error_type(function_clause, [{?MODULE,F,ArityOrArgs} | _]) ->
- case atom_to_list(F) of
- "yeccgoto_" ++ SymbolL ->
- {ok,[{atom,_,Symbol}],_} = erl_scan:string(SymbolL),
- State = case ArityOrArgs of
- [S,_,_,_,_,_,_] -> S;
- _ -> state_is_unknown
- end,
- {Symbol, State, missing_in_goto_table}
- end.
-
-yeccpars1([Token | Tokens], Tzr, State, States, Vstack) ->
- yeccpars2(State, element(1, Token), States, Vstack, Token, Tokens, Tzr);
-yeccpars1([], {{F, A},_Line}, State, States, Vstack) ->
- case apply(F, A) of
- {ok, Tokens, Endline} ->
- yeccpars1(Tokens, {{F, A}, Endline}, State, States, Vstack);
- {eof, Endline} ->
- yeccpars1([], {no_func, Endline}, State, States, Vstack);
- {error, Descriptor, _Endline} ->
- {error, Descriptor}
- end;
-yeccpars1([], {no_func, no_line}, State, States, Vstack) ->
- Line = 999999,
- yeccpars2(State, '$end', States, Vstack, yecc_end(Line), [],
- {no_func, Line});
-yeccpars1([], {no_func, Endline}, State, States, Vstack) ->
- yeccpars2(State, '$end', States, Vstack, yecc_end(Endline), [],
- {no_func, Endline}).
-
-%% yeccpars1/7 is called from generated code.
-%%
-%% When using the {includefile, Includefile} option, make sure that
-%% yeccpars1/7 can be found by parsing the file without following
-%% include directives. yecc will otherwise assume that an old
-%% yeccpre.hrl is included (one which defines yeccpars1/5).
-yeccpars1(State1, State, States, Vstack, Token0, [Token | Tokens], Tzr) ->
- yeccpars2(State, element(1, Token), [State1 | States],
- [Token0 | Vstack], Token, Tokens, Tzr);
-yeccpars1(State1, State, States, Vstack, Token0, [], {{_F,_A}, _Line}=Tzr) ->
- yeccpars1([], Tzr, State, [State1 | States], [Token0 | Vstack]);
-yeccpars1(State1, State, States, Vstack, Token0, [], {no_func, no_line}) ->
- Line = yecctoken_end_location(Token0),
- yeccpars2(State, '$end', [State1 | States], [Token0 | Vstack],
- yecc_end(Line), [], {no_func, Line});
-yeccpars1(State1, State, States, Vstack, Token0, [], {no_func, Line}) ->
- yeccpars2(State, '$end', [State1 | States], [Token0 | Vstack],
- yecc_end(Line), [], {no_func, Line}).
-
-%% For internal use only.
-yecc_end({Line,_Column}) ->
- {'$end', Line};
-yecc_end(Line) ->
- {'$end', Line}.
-
-yecctoken_end_location(Token) ->
- try
- {text, Str} = erl_scan:token_info(Token, text),
- {line, Line} = erl_scan:token_info(Token, line),
- Parts = re:split(Str, "\n"),
- Dline = length(Parts) - 1,
- Yline = Line + Dline,
- case erl_scan:token_info(Token, column) of
- {column, Column} ->
- Col = byte_size(lists:last(Parts)),
- {Yline, Col + if Dline =:= 0 -> Column; true -> 1 end};
- undefined ->
- Yline
- end
- catch _:_ ->
- yecctoken_location(Token)
- end.
-
--compile({nowarn_unused_function, yeccerror/1}).
-yeccerror(Token) ->
- Text = yecctoken_to_string(Token),
- Location = yecctoken_location(Token),
- {error, {Location, ?MODULE, ["syntax error before: ", Text]}}.
-
--compile({nowarn_unused_function, yecctoken_to_string/1}).
-yecctoken_to_string(Token) ->
- case catch erl_scan:token_info(Token, text) of
- {text, Txt} -> Txt;
- _ -> yecctoken2string(Token)
- end.
-
-yecctoken_location(Token) ->
- case catch erl_scan:token_info(Token, location) of
- {location, Loc} -> Loc;
- _ -> element(2, Token)
- end.
-
--compile({nowarn_unused_function, yecctoken2string/1}).
-yecctoken2string({atom, _, A}) -> io_lib:write(A);
-yecctoken2string({integer,_,N}) -> io_lib:write(N);
-yecctoken2string({float,_,F}) -> io_lib:write(F);
-yecctoken2string({char,_,C}) -> io_lib:write_char(C);
-yecctoken2string({var,_,V}) -> io_lib:format("~s", [V]);
-yecctoken2string({string,_,S}) -> io_lib:write_unicode_string(S);
-yecctoken2string({reserved_symbol, _, A}) -> io_lib:write(A);
-yecctoken2string({_Cat, _, Val}) -> io_lib:format("~p",[Val]);
-yecctoken2string({dot, _}) -> "'.'";
-yecctoken2string({'$end', _}) ->
- [];
-yecctoken2string({Other, _}) when is_atom(Other) ->
- io_lib:write(Other);
-yecctoken2string(Other) ->
- io_lib:write(Other).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
-
--file("/ldisk/egil/git/otp/bootstrap/lib/compiler/egen/core_parse.erl", 199).
-
-yeccpars2(0=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_0(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(1=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_1(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(2=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_2(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(3=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_3(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(4=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_4(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(5=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_5(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(6=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_6(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(7=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_7(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(8=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_8(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(9=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_9(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(10=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_10(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(11=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_11(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(12=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_12(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(13=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_13(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(14=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(15=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_15(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(16=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(17=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_17(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(18=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(19=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(20=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_20(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(21=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_21(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(22=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(23=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(24=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(25=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_25(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(26=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_26(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(27=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_27(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(28=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_28(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(29=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_29(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(30=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(31=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(32=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(33=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(34=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(35=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(36=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(37=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_37(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(38=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_38(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(39=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_39(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(40=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(41=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_41(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(42=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(43=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_43(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(44=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_44(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(45=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(46=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(47=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_47(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(48=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(49=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_49(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(50=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_50(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(51=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_43(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(52=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_52(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(53=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_53(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(54=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_54(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(55=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_55(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(56=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_56(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(57=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_57(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(58=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_58(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(59=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_59(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(60=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_60(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(61=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(62=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_62(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(63=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_63(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(64=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_64(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(65=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_65(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(66=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_66(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(67=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_67(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(68=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_68(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(69=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_69(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(70=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_70(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(71=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_71(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(72=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_72(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(73=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_73(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(74=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_74(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(75=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_75(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(76=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_76(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(77=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_77(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(78=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_78(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(79=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_79(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(80=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_80(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(81=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_81(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(82=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_82(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(83=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_83(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(84=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_84(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(85=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_85(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(86=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_86(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(87=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_85(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(88=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_88(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(89=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_89(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(90=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_83(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(91=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_91(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(92=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_85(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(93=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_93(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(94=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_94(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(95=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_95(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(96=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_96(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(97=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_97(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(98=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_98(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(99=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_99(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(100=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_100(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(101=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_101(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(102=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_102(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(103=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_103(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(104=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_104(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(105=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_105(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(106=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_106(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(107=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_107(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(108=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(109=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_109(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(110=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_110(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(111=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_111(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(112=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_112(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(113=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_113(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(114=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_114(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(115=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_115(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(116=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_116(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(117=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_117(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(118=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_118(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(119=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_119(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(120=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_120(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(121=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_121(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(122=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_122(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(123=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_123(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(124=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_124(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(125=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_125(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(126=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_126(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(127=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_127(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(128=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_128(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(129=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_129(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(130=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_130(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(131=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_131(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(132=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_132(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(133=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(134=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_134(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(135=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(136=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(137=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(138=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(139=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_139(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(140=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_140(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(141=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(142=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_142(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(143=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(144=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_144(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(145=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_145(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(146=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_146(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(147=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_147(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(148=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(149=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_149(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(150=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_150(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(151=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_151(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(152=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_139(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(153=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_153(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(154=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_154(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(155=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_155(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(156=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_156(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(157=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_157(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(158=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_158(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(159=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(160=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_160(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(161=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_139(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(162=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_162(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(163=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(164=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_164(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(165=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_165(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(166=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_166(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(167=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_167(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(168=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_168(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(169=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_169(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(170=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_170(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(171=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_171(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(172=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_172(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(173=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_173(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(174=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_174(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(175=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_175(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(176=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_176(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(177=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_177(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(178=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_178(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(179=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_179(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(180=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_180(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(181=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_181(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(182=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(183=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_183(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(184=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_184(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(185=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_185(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(186=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_186(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(187=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_187(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(188=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_188(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(189=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_189(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(190=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_190(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(191=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_191(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(192=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_192(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(193=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_63(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(194=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_194(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(195=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_195(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(196=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_63(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(197=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_197(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(198=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_198(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(199=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_191(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(200=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_200(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(201=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_201(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(202=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_202(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(203=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(204=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_204(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(205=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_205(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(206=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_206(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(207=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_191(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(208=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_208(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(209=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_191(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(210=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_210(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(211=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_211(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(212=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_205(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(213=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_213(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(214=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_214(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(215=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_215(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(216=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_216(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(217=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_217(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(218=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_218(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(219=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_63(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(220=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_220(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(221=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_221(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(222=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_222(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(223=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_223(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(224=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_224(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(225=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_225(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(226=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_226(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(227=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_227(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(228=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_191(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(229=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_229(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(230=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_230(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(231=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_191(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(232=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_232(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(233=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_233(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(234=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_234(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(235=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_235(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(236=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_236(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(237=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_237(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(238=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_238(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(239=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_239(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(240=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(241=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_241(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(242=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(243=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_243(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(244=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_244(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(245=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_245(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(246=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_246(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(247=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_247(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(248=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_248(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(249=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_249(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(250=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_250(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(251=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(252=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_252(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(253=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_253(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(254=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(255=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_255(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(256=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(257=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_257(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(258=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(259=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_259(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(260=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_260(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(261=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_261(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(262=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_262(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(263=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_263(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(264=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_264(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(265=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_265(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(266=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(267=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_244(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(268=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_268(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(269=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_244(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(270=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_270(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(271=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_271(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(272=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_272(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(273=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(274=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_274(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(275=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(276=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_276(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(277=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_277(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(278=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_271(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(279=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_279(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(280=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_280(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(281=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_281(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(282=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_282(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(283=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_283(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(284=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_63(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(285=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_285(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(286=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_286(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(287=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_287(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(288=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_288(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(289=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_289(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(290=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_290(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(291=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_291(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(292=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_292(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(293=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(294=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_294(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(295=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_295(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(296=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(297=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_297(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(298=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_298(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(299=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_299(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(300=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_300(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(301=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_301(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(302=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_302(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(303=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_303(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(304=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_304(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(305=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_305(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(306=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_306(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(307=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(308=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_308(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(309=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_309(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(310=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_63(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(311=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_311(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(312=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_312(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(313=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_313(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(314=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_314(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(315=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_315(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(316=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_4(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(317=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_5(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(318=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_318(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(319=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_319(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(320=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_320(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(321=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_63(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(322=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_322(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(323=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_323(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(Other, _, _, _, _, _, _) ->
- erlang:error({yecc_bug,"1.4",{missing_state_in_action_table, Other}}).
-
-yeccpars2_0(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 2, Ss, Stack, T, Ts, Tzr);
-yeccpars2_0(S, module, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 3, Ss, Stack, T, Ts, Tzr);
-yeccpars2_0(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_1(_S, '$end', _Ss, Stack, _T, _Ts, _Tzr) ->
- {ok, hd(Stack)};
-yeccpars2_1(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_2(S, module, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 315, Ss, Stack, T, Ts, Tzr);
-yeccpars2_2(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_3(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 4, Ss, Stack, T, Ts, Tzr);
-yeccpars2_3(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_4(S, '[', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 6, Ss, Stack, T, Ts, Tzr);
-yeccpars2_4(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_5(S, attributes, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 18, Ss, Stack, T, Ts, Tzr);
-yeccpars2_5(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_6(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 10, Ss, Stack, T, Ts, Tzr);
-yeccpars2_6(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 11, Ss, Stack, T, Ts, Tzr);
-yeccpars2_6(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_7(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_exported_name(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_8(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 16, Ss, Stack, T, Ts, Tzr);
-yeccpars2_8(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_9(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 14, Ss, Stack, T, Ts, Tzr);
-yeccpars2_9(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_9_(Stack),
- yeccgoto_exported_names(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_10(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_10_(Stack),
- yeccgoto_module_export(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_11(S, '/', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 12, Ss, Stack, T, Ts, Tzr);
-yeccpars2_11(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_12(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 13, Ss, Stack, T, Ts, Tzr);
-yeccpars2_12(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_13(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_13_(Stack),
- yeccgoto_function_name(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_14(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 11, Ss, Stack, T, Ts, Tzr);
-yeccpars2_14(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_15_(Stack),
- yeccgoto_exported_names(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_16_(Stack),
- yeccgoto_module_export(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_17(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 61, Ss, Stack, T, Ts, Tzr);
-yeccpars2_17(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 11, Ss, Stack, T, Ts, Tzr);
-yeccpars2_17(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_17_(Stack),
- yeccpars2_58(_S, Cat, [17 | Ss], NewStack, T, Ts, Tzr).
-
-yeccpars2_18(S, '[', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 19, Ss, Stack, T, Ts, Tzr);
-yeccpars2_18(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_19(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 22, Ss, Stack, T, Ts, Tzr);
-yeccpars2_19(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 23, Ss, Stack, T, Ts, Tzr);
-yeccpars2_19(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_20(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 55, Ss, Stack, T, Ts, Tzr);
-yeccpars2_20(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_21(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 53, Ss, Stack, T, Ts, Tzr);
-yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_21_(Stack),
- yeccgoto_attribute_list(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_22_(Stack),
- yeccgoto_module_attribute(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_23(S, '=', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 24, Ss, Stack, T, Ts, Tzr);
-yeccpars2_23(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_24(S, '[', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 30, Ss, Stack, T, Ts, Tzr);
-yeccpars2_24(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 31, Ss, Stack, T, Ts, Tzr);
-yeccpars2_24(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 36, Ss, Stack, T, Ts, Tzr);
-yeccpars2_24(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_24(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_cont_24(S, char, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 32, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_24(S, float, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 33, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_24(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 34, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_24(S, string, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 35, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_24(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_literal(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_26_(Stack),
- yeccgoto_atomic_literal(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_27(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_27_(Stack),
- yeccgoto_attribute(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_28(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_literal(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_29(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_literal(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_30(S, '[', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 30, Ss, Stack, T, Ts, Tzr);
-yeccpars2_30(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 44, Ss, Stack, T, Ts, Tzr);
-yeccpars2_30(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 31, Ss, Stack, T, Ts, Tzr);
-yeccpars2_30(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 36, Ss, Stack, T, Ts, Tzr);
-yeccpars2_30(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_24(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_31_(Stack),
- yeccgoto_atomic_literal(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_32(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_32_(Stack),
- yeccgoto_atomic_literal(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_33(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_33_(Stack),
- yeccgoto_atomic_literal(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_34(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_34_(Stack),
- yeccgoto_atomic_literal(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_35(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_35_(Stack),
- yeccgoto_atomic_literal(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_36(S, '[', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 30, Ss, Stack, T, Ts, Tzr);
-yeccpars2_36(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 31, Ss, Stack, T, Ts, Tzr);
-yeccpars2_36(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 36, Ss, Stack, T, Ts, Tzr);
-yeccpars2_36(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 39, Ss, Stack, T, Ts, Tzr);
-yeccpars2_36(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_24(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_37(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 42, Ss, Stack, T, Ts, Tzr);
-yeccpars2_37(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_38(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 40, Ss, Stack, T, Ts, Tzr);
-yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_38_(Stack),
- yeccgoto_literals(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_39(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_39_(Stack),
- yeccgoto_tuple_literal(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_40: see yeccpars2_24
-
-yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_41_(Stack),
- yeccgoto_literals(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_42_(Stack),
- yeccgoto_tuple_literal(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_43(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 46, Ss, Stack, T, Ts, Tzr);
-yeccpars2_43(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 47, Ss, Stack, T, Ts, Tzr);
-yeccpars2_43(S, '|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 48, Ss, Stack, T, Ts, Tzr);
-yeccpars2_43(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_44(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_44_(Stack),
- yeccgoto_nil(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_45(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_45_(Stack),
- yeccgoto_cons_literal(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_46: see yeccpars2_24
-
-yeccpars2_47(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_47_(Stack),
- yeccgoto_tail_literal(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_48: see yeccpars2_24
-
-yeccpars2_49(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 50, Ss, Stack, T, Ts, Tzr);
-yeccpars2_49(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_50(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_50_(Stack),
- yeccgoto_tail_literal(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_51: see yeccpars2_43
-
-yeccpars2_52(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_52_(Stack),
- yeccgoto_tail_literal(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_53(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 23, Ss, Stack, T, Ts, Tzr);
-yeccpars2_53(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_54(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_54_(Stack),
- yeccgoto_attribute_list(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_55(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_|Nss] = Ss,
- NewStack = yeccpars2_55_(Stack),
- yeccgoto_module_attribute(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_56(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 314, Ss, Stack, T, Ts, Tzr);
-yeccpars2_56(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_57(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_anno_function_name(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_58(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_module_defs(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_59(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 61, Ss, Stack, T, Ts, Tzr);
-yeccpars2_59(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 11, Ss, Stack, T, Ts, Tzr);
-yeccpars2_59(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_59_(Stack),
- yeccpars2_313(_S, Cat, [59 | Ss], NewStack, T, Ts, Tzr).
-
-yeccpars2_60(S, '=', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 96, Ss, Stack, T, Ts, Tzr);
-yeccpars2_60(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_61: see yeccpars2_14
-
-yeccpars2_62(S, '-|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 63, Ss, Stack, T, Ts, Tzr);
-yeccpars2_62(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_63(S, '[', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 65, Ss, Stack, T, Ts, Tzr);
-yeccpars2_63(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_64(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 95, Ss, Stack, T, Ts, Tzr);
-yeccpars2_64(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_65(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 73, Ss, Stack, T, Ts, Tzr);
-yeccpars2_65(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_85(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_66(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_constant(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_67(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_67_(Stack),
- yeccgoto_atomic_constant(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_68(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 94, Ss, Stack, T, Ts, Tzr);
-yeccpars2_68(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_69(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 92, Ss, Stack, T, Ts, Tzr);
-yeccpars2_69(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_69_(Stack),
- yeccgoto_constants(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_70(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_constant(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_71(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_constant(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_72(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 44, Ss, Stack, T, Ts, Tzr);
-yeccpars2_72(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_85(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_73(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_73_(Stack),
- yeccgoto_annotation(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_74(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_74_(Stack),
- yeccgoto_atomic_constant(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_75(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_75_(Stack),
- yeccgoto_atomic_constant(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_76(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_76_(Stack),
- yeccgoto_atomic_constant(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_77(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_77_(Stack),
- yeccgoto_atomic_constant(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_78(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_78_(Stack),
- yeccgoto_atomic_constant(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_79(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 81, Ss, Stack, T, Ts, Tzr);
-yeccpars2_79(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_85(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_80(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 82, Ss, Stack, T, Ts, Tzr);
-yeccpars2_80(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_81(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_81_(Stack),
- yeccgoto_tuple_constant(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_82(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_82_(Stack),
- yeccgoto_tuple_constant(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_83(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 85, Ss, Stack, T, Ts, Tzr);
-yeccpars2_83(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 86, Ss, Stack, T, Ts, Tzr);
-yeccpars2_83(S, '|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 87, Ss, Stack, T, Ts, Tzr);
-yeccpars2_83(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_84(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_84_(Stack),
- yeccgoto_cons_constant(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_85(S, '[', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 72, Ss, Stack, T, Ts, Tzr);
-yeccpars2_85(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 74, Ss, Stack, T, Ts, Tzr);
-yeccpars2_85(S, char, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 75, Ss, Stack, T, Ts, Tzr);
-yeccpars2_85(S, float, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 76, Ss, Stack, T, Ts, Tzr);
-yeccpars2_85(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 77, Ss, Stack, T, Ts, Tzr);
-yeccpars2_85(S, string, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 78, Ss, Stack, T, Ts, Tzr);
-yeccpars2_85(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 79, Ss, Stack, T, Ts, Tzr);
-yeccpars2_85(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_86(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_86_(Stack),
- yeccgoto_tail_constant(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_87: see yeccpars2_85
-
-yeccpars2_88(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 89, Ss, Stack, T, Ts, Tzr);
-yeccpars2_88(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_89(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_89_(Stack),
- yeccgoto_tail_constant(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_90: see yeccpars2_83
-
-yeccpars2_91(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_91_(Stack),
- yeccgoto_tail_constant(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_92: see yeccpars2_85
-
-yeccpars2_93(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_93_(Stack),
- yeccgoto_constants(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_94(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_94_(Stack),
- yeccgoto_annotation(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_95(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_95_(Stack),
- yeccgoto_anno_function_name(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_96(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 99, Ss, Stack, T, Ts, Tzr);
-yeccpars2_96(S, 'fun', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 100, Ss, Stack, T, Ts, Tzr);
-yeccpars2_96(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_97(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_anno_fun(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_98(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_98_(Stack),
- yeccgoto_function_definition(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_99(S, 'fun', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 100, Ss, Stack, T, Ts, Tzr);
-yeccpars2_99(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_100(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 101, Ss, Stack, T, Ts, Tzr);
-yeccpars2_100(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_101(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 105, Ss, Stack, T, Ts, Tzr);
-yeccpars2_101(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 106, Ss, Stack, T, Ts, Tzr);
-yeccpars2_101(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
-yeccpars2_101(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_102(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_anno_variable(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_103(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 306, Ss, Stack, T, Ts, Tzr);
-yeccpars2_103(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_104(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 304, Ss, Stack, T, Ts, Tzr);
-yeccpars2_104(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_104_(Stack),
- yeccgoto_anno_variables(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_105(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
-yeccpars2_105(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_106(S, '->', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 108, Ss, Stack, T, Ts, Tzr);
-yeccpars2_106(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_107(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_107_(Stack),
- yeccgoto_variable(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_108(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 130, Ss, Stack, T, Ts, Tzr);
-yeccpars2_108(S, char, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 32, Ss, Stack, T, Ts, Tzr);
-yeccpars2_108(S, float, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 33, Ss, Stack, T, Ts, Tzr);
-yeccpars2_108(S, 'fun', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 100, Ss, Stack, T, Ts, Tzr);
-yeccpars2_108(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 34, Ss, Stack, T, Ts, Tzr);
-yeccpars2_108(S, string, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 35, Ss, Stack, T, Ts, Tzr);
-yeccpars2_108(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
-yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_108(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_cont_108(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 129, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_108(S, '<', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 131, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_108(S, '[', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 132, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_108(S, apply, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 133, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_108(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 134, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_108(S, call, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 135, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_108(S, 'case', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 136, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_108(S, 'catch', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 137, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_108(S, do, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 138, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_108(S, 'let', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 139, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_108(S, letrec, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 140, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_108(S, primop, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 141, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_108(S, 'receive', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 142, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_108(S, 'try', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 143, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_108(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 144, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_108(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_single_expression(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_single_expression(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_single_expression(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expression(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_single_expression(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_single_expression(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_single_expression(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_single_expression(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_single_expression(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_single_expression(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_single_expression(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_anno_expression(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_single_expression(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_single_expression(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_single_expression(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_single_expression(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_single_expression(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_single_expression(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_single_expression(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_128(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_128_(Stack),
- yeccgoto_fun_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_129(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 287, Ss, Stack, T, Ts, Tzr);
-yeccpars2_129(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_130(S, char, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 32, Ss, Stack, T, Ts, Tzr);
-yeccpars2_130(S, float, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 33, Ss, Stack, T, Ts, Tzr);
-yeccpars2_130(S, 'fun', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 100, Ss, Stack, T, Ts, Tzr);
-yeccpars2_130(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 34, Ss, Stack, T, Ts, Tzr);
-yeccpars2_130(S, string, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 35, Ss, Stack, T, Ts, Tzr);
-yeccpars2_130(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
-yeccpars2_130(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_108(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_131(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 130, Ss, Stack, T, Ts, Tzr);
-yeccpars2_131(S, '>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 281, Ss, Stack, T, Ts, Tzr);
-yeccpars2_131(S, char, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 32, Ss, Stack, T, Ts, Tzr);
-yeccpars2_131(S, float, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 33, Ss, Stack, T, Ts, Tzr);
-yeccpars2_131(S, 'fun', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 100, Ss, Stack, T, Ts, Tzr);
-yeccpars2_131(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 34, Ss, Stack, T, Ts, Tzr);
-yeccpars2_131(S, string, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 35, Ss, Stack, T, Ts, Tzr);
-yeccpars2_131(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
-yeccpars2_131(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_108(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_132(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 130, Ss, Stack, T, Ts, Tzr);
-yeccpars2_132(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 44, Ss, Stack, T, Ts, Tzr);
-yeccpars2_132(S, char, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 32, Ss, Stack, T, Ts, Tzr);
-yeccpars2_132(S, float, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 33, Ss, Stack, T, Ts, Tzr);
-yeccpars2_132(S, 'fun', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 100, Ss, Stack, T, Ts, Tzr);
-yeccpars2_132(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 34, Ss, Stack, T, Ts, Tzr);
-yeccpars2_132(S, string, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 35, Ss, Stack, T, Ts, Tzr);
-yeccpars2_132(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
-yeccpars2_132(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_108(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-%% yeccpars2_133: see yeccpars2_108
-
-yeccpars2_134(S, '/', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 12, Ss, Stack, T, Ts, Tzr);
-yeccpars2_134(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_134_(Stack),
- yeccgoto_atomic_literal(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_135: see yeccpars2_108
-
-%% yeccpars2_136: see yeccpars2_108
-
-%% yeccpars2_137: see yeccpars2_108
-
-%% yeccpars2_138: see yeccpars2_108
-
-yeccpars2_139(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 105, Ss, Stack, T, Ts, Tzr);
-yeccpars2_139(S, '<', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 155, Ss, Stack, T, Ts, Tzr);
-yeccpars2_139(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
-yeccpars2_139(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_140(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 61, Ss, Stack, T, Ts, Tzr);
-yeccpars2_140(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 11, Ss, Stack, T, Ts, Tzr);
-yeccpars2_140(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_140_(Stack),
- yeccpars2_250(250, Cat, [140 | Ss], NewStack, T, Ts, Tzr).
-
-%% yeccpars2_141: see yeccpars2_108
-
-yeccpars2_142(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 178, Ss, Stack, T, Ts, Tzr);
-yeccpars2_142(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 179, Ss, Stack, T, Ts, Tzr);
-yeccpars2_142(S, '<', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 180, Ss, Stack, T, Ts, Tzr);
-yeccpars2_142(S, '[', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 181, Ss, Stack, T, Ts, Tzr);
-yeccpars2_142(S, 'after', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 182, Ss, Stack, T, Ts, Tzr);
-yeccpars2_142(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 31, Ss, Stack, T, Ts, Tzr);
-yeccpars2_142(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
-yeccpars2_142(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 183, Ss, Stack, T, Ts, Tzr);
-yeccpars2_142(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_24(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-%% yeccpars2_143: see yeccpars2_108
-
-yeccpars2_144(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 130, Ss, Stack, T, Ts, Tzr);
-yeccpars2_144(S, char, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 32, Ss, Stack, T, Ts, Tzr);
-yeccpars2_144(S, float, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 33, Ss, Stack, T, Ts, Tzr);
-yeccpars2_144(S, 'fun', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 100, Ss, Stack, T, Ts, Tzr);
-yeccpars2_144(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 34, Ss, Stack, T, Ts, Tzr);
-yeccpars2_144(S, string, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 35, Ss, Stack, T, Ts, Tzr);
-yeccpars2_144(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
-yeccpars2_144(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 147, Ss, Stack, T, Ts, Tzr);
-yeccpars2_144(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_108(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_145(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 150, Ss, Stack, T, Ts, Tzr);
-yeccpars2_145(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_146(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 148, Ss, Stack, T, Ts, Tzr);
-yeccpars2_146(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_146_(Stack),
- yeccgoto_anno_expressions(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_147(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_147_(Stack),
- yeccgoto_tuple(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_148: see yeccpars2_108
-
-yeccpars2_149(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_149_(Stack),
- yeccgoto_anno_expressions(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_150(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_150_(Stack),
- yeccgoto_tuple(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_151(S, 'of', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 152, Ss, Stack, T, Ts, Tzr);
-yeccpars2_151(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_152: see yeccpars2_139
-
-yeccpars2_153(S, '->', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 159, Ss, Stack, T, Ts, Tzr);
-yeccpars2_153(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_154(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_154_(Stack),
- yeccgoto_let_vars(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_155(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 105, Ss, Stack, T, Ts, Tzr);
-yeccpars2_155(S, '>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 157, Ss, Stack, T, Ts, Tzr);
-yeccpars2_155(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
-yeccpars2_155(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_156(S, '>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 158, Ss, Stack, T, Ts, Tzr);
-yeccpars2_156(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_157(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_157_(Stack),
- yeccgoto_let_vars(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_158(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_158_(Stack),
- yeccgoto_let_vars(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_159: see yeccpars2_108
-
-yeccpars2_160(S, 'catch', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 161, Ss, Stack, T, Ts, Tzr);
-yeccpars2_160(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_161: see yeccpars2_139
-
-yeccpars2_162(S, '->', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 163, Ss, Stack, T, Ts, Tzr);
-yeccpars2_162(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_163: see yeccpars2_108
-
-yeccpars2_164(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_,_,_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_164_(Stack),
- yeccgoto_try_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_165(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_other_pattern(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_166(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_166_(Stack),
- yeccgoto_receive_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_167(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_anno_pattern(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_168(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_other_pattern(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_169(S, 'when', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 240, Ss, Stack, T, Ts, Tzr);
-yeccpars2_169(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_170(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_anno_clause(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_171(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_other_pattern(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_172(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_other_pattern(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_173(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_atomic_pattern(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_174(S, '=', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 191, Ss, Stack, T, Ts, Tzr);
-yeccpars2_174(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_anno_pattern(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_175(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_175_(Stack),
- yeccgoto_clause_pattern(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_176(S, 'after', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 182, Ss, Stack, T, Ts, Tzr);
-yeccpars2_176(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_177(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 178, Ss, Stack, T, Ts, Tzr);
-yeccpars2_177(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 179, Ss, Stack, T, Ts, Tzr);
-yeccpars2_177(S, '<', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 180, Ss, Stack, T, Ts, Tzr);
-yeccpars2_177(S, '[', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 181, Ss, Stack, T, Ts, Tzr);
-yeccpars2_177(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 31, Ss, Stack, T, Ts, Tzr);
-yeccpars2_177(S, char, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 32, Ss, Stack, T, Ts, Tzr);
-yeccpars2_177(S, float, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 33, Ss, Stack, T, Ts, Tzr);
-yeccpars2_177(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 34, Ss, Stack, T, Ts, Tzr);
-yeccpars2_177(S, string, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 35, Ss, Stack, T, Ts, Tzr);
-yeccpars2_177(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
-yeccpars2_177(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 183, Ss, Stack, T, Ts, Tzr);
-yeccpars2_177(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_177_(Stack),
- yeccgoto_anno_clauses(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_178(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 222, Ss, Stack, T, Ts, Tzr);
-yeccpars2_178(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_179(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 178, Ss, Stack, T, Ts, Tzr);
-yeccpars2_179(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 186, Ss, Stack, T, Ts, Tzr);
-yeccpars2_179(S, '<', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 180, Ss, Stack, T, Ts, Tzr);
-yeccpars2_179(S, '[', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 181, Ss, Stack, T, Ts, Tzr);
-yeccpars2_179(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 31, Ss, Stack, T, Ts, Tzr);
-yeccpars2_179(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
-yeccpars2_179(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 183, Ss, Stack, T, Ts, Tzr);
-yeccpars2_179(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_24(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_180(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 178, Ss, Stack, T, Ts, Tzr);
-yeccpars2_180(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 186, Ss, Stack, T, Ts, Tzr);
-yeccpars2_180(S, '>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 215, Ss, Stack, T, Ts, Tzr);
-yeccpars2_180(S, '[', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 181, Ss, Stack, T, Ts, Tzr);
-yeccpars2_180(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 31, Ss, Stack, T, Ts, Tzr);
-yeccpars2_180(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
-yeccpars2_180(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 183, Ss, Stack, T, Ts, Tzr);
-yeccpars2_180(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_24(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_181(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 178, Ss, Stack, T, Ts, Tzr);
-yeccpars2_181(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 186, Ss, Stack, T, Ts, Tzr);
-yeccpars2_181(S, '[', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 181, Ss, Stack, T, Ts, Tzr);
-yeccpars2_181(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 44, Ss, Stack, T, Ts, Tzr);
-yeccpars2_181(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 31, Ss, Stack, T, Ts, Tzr);
-yeccpars2_181(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
-yeccpars2_181(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 183, Ss, Stack, T, Ts, Tzr);
-yeccpars2_181(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_24(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-%% yeccpars2_182: see yeccpars2_108
-
-yeccpars2_183(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 178, Ss, Stack, T, Ts, Tzr);
-yeccpars2_183(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 186, Ss, Stack, T, Ts, Tzr);
-yeccpars2_183(S, '[', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 181, Ss, Stack, T, Ts, Tzr);
-yeccpars2_183(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 31, Ss, Stack, T, Ts, Tzr);
-yeccpars2_183(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
-yeccpars2_183(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 183, Ss, Stack, T, Ts, Tzr);
-yeccpars2_183(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 187, Ss, Stack, T, Ts, Tzr);
-yeccpars2_183(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_24(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_184(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 201, Ss, Stack, T, Ts, Tzr);
-yeccpars2_184(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_185(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 199, Ss, Stack, T, Ts, Tzr);
-yeccpars2_185(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_185_(Stack),
- yeccgoto_anno_patterns(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_186(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 178, Ss, Stack, T, Ts, Tzr);
-yeccpars2_186(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 105, Ss, Stack, T, Ts, Tzr);
-yeccpars2_186(S, '[', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 181, Ss, Stack, T, Ts, Tzr);
-yeccpars2_186(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 31, Ss, Stack, T, Ts, Tzr);
-yeccpars2_186(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
-yeccpars2_186(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 183, Ss, Stack, T, Ts, Tzr);
-yeccpars2_186(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_24(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_187(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_187_(Stack),
- yeccgoto_tuple_pattern(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_188(S, '-|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 196, Ss, Stack, T, Ts, Tzr);
-yeccpars2_188(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_anno_variable(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_189(S, '-|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 193, Ss, Stack, T, Ts, Tzr);
-yeccpars2_189(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_190(S, '=', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 191, Ss, Stack, T, Ts, Tzr);
-yeccpars2_190(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_191(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 178, Ss, Stack, T, Ts, Tzr);
-yeccpars2_191(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 186, Ss, Stack, T, Ts, Tzr);
-yeccpars2_191(S, '[', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 181, Ss, Stack, T, Ts, Tzr);
-yeccpars2_191(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 31, Ss, Stack, T, Ts, Tzr);
-yeccpars2_191(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
-yeccpars2_191(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 183, Ss, Stack, T, Ts, Tzr);
-yeccpars2_191(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_24(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_192(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_192_(Stack),
- yeccgoto_other_pattern(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_193: see yeccpars2_63
-
-yeccpars2_194(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 195, Ss, Stack, T, Ts, Tzr);
-yeccpars2_194(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_195(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_195_(Stack),
- yeccgoto_anno_pattern(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_196: see yeccpars2_63
-
-yeccpars2_197(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 198, Ss, Stack, T, Ts, Tzr);
-yeccpars2_197(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_198(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_198_(Stack),
- yeccgoto_anno_variable(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_199: see yeccpars2_191
-
-yeccpars2_200(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_200_(Stack),
- yeccgoto_anno_patterns(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_201(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_201_(Stack),
- yeccgoto_tuple_pattern(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_202(S, '->', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 203, Ss, Stack, T, Ts, Tzr);
-yeccpars2_202(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_203: see yeccpars2_108
-
-yeccpars2_204(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_|Nss] = Ss,
- NewStack = yeccpars2_204_(Stack),
- yeccgoto_timeout(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_205(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 207, Ss, Stack, T, Ts, Tzr);
-yeccpars2_205(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 208, Ss, Stack, T, Ts, Tzr);
-yeccpars2_205(S, '|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 209, Ss, Stack, T, Ts, Tzr);
-yeccpars2_205(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_206(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_206_(Stack),
- yeccgoto_cons_pattern(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_207: see yeccpars2_191
-
-yeccpars2_208(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_208_(Stack),
- yeccgoto_tail_pattern(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_209: see yeccpars2_191
-
-yeccpars2_210(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 211, Ss, Stack, T, Ts, Tzr);
-yeccpars2_210(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_211(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_211_(Stack),
- yeccgoto_tail_pattern(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_212: see yeccpars2_205
-
-yeccpars2_213(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_213_(Stack),
- yeccgoto_tail_pattern(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_214(S, '>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 216, Ss, Stack, T, Ts, Tzr);
-yeccpars2_214(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_215(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_215_(Stack),
- yeccgoto_clause_pattern(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_216(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_216_(Stack),
- yeccgoto_clause_pattern(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_217(S, '-|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 193, Ss, Stack, T, Ts, Tzr);
-yeccpars2_217(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_anno_pattern(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_218(S, '-|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 219, Ss, Stack, T, Ts, Tzr);
-yeccpars2_218(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_219: see yeccpars2_63
-
-yeccpars2_220(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 221, Ss, Stack, T, Ts, Tzr);
-yeccpars2_220(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_221(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_221_(Stack),
- yeccgoto_anno_clause(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_222(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 225, Ss, Stack, T, Ts, Tzr);
-yeccpars2_222(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 226, Ss, Stack, T, Ts, Tzr);
-yeccpars2_222(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_223(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 236, Ss, Stack, T, Ts, Tzr);
-yeccpars2_223(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_224(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 234, Ss, Stack, T, Ts, Tzr);
-yeccpars2_224(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_224_(Stack),
- yeccgoto_segment_patterns(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_225(S, '<', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 228, Ss, Stack, T, Ts, Tzr);
-yeccpars2_225(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_226(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 227, Ss, Stack, T, Ts, Tzr);
-yeccpars2_226(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_227(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_|Nss] = Ss,
- NewStack = yeccpars2_227_(Stack),
- yeccgoto_binary_pattern(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_228: see yeccpars2_191
-
-yeccpars2_229(S, '>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 230, Ss, Stack, T, Ts, Tzr);
-yeccpars2_229(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_230(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 231, Ss, Stack, T, Ts, Tzr);
-yeccpars2_230(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_231: see yeccpars2_191
-
-yeccpars2_232(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 233, Ss, Stack, T, Ts, Tzr);
-yeccpars2_232(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_233(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_233_(Stack),
- yeccgoto_segment_pattern(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_234(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 225, Ss, Stack, T, Ts, Tzr);
-yeccpars2_234(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_235(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_235_(Stack),
- yeccgoto_segment_patterns(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_236(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 237, Ss, Stack, T, Ts, Tzr);
-yeccpars2_236(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_237(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_237_(Stack),
- yeccgoto_binary_pattern(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_238(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_238_(Stack),
- yeccgoto_anno_clauses(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_239(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_239_(Stack),
- yeccgoto_receive_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_240: see yeccpars2_108
-
-yeccpars2_241(S, '->', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 242, Ss, Stack, T, Ts, Tzr);
-yeccpars2_241(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_242: see yeccpars2_108
-
-yeccpars2_243(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_243_(Stack),
- yeccgoto_clause(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_244(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 246, Ss, Stack, T, Ts, Tzr);
-yeccpars2_244(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_245(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_245_(Stack),
- yeccgoto_primop_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_246(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 130, Ss, Stack, T, Ts, Tzr);
-yeccpars2_246(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 248, Ss, Stack, T, Ts, Tzr);
-yeccpars2_246(S, char, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 32, Ss, Stack, T, Ts, Tzr);
-yeccpars2_246(S, float, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 33, Ss, Stack, T, Ts, Tzr);
-yeccpars2_246(S, 'fun', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 100, Ss, Stack, T, Ts, Tzr);
-yeccpars2_246(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 34, Ss, Stack, T, Ts, Tzr);
-yeccpars2_246(S, string, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 35, Ss, Stack, T, Ts, Tzr);
-yeccpars2_246(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
-yeccpars2_246(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_108(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_247(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 249, Ss, Stack, T, Ts, Tzr);
-yeccpars2_247(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_248(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_248_(Stack),
- yeccgoto_arg_list(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_249(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_249_(Stack),
- yeccgoto_arg_list(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_250(S, in, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 251, Ss, Stack, T, Ts, Tzr);
-yeccpars2_250(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_251: see yeccpars2_108
-
-yeccpars2_252(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_|Nss] = Ss,
- NewStack = yeccpars2_252_(Stack),
- yeccgoto_letrec_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_253(S, '=', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 254, Ss, Stack, T, Ts, Tzr);
-yeccpars2_253(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_254: see yeccpars2_108
-
-yeccpars2_255(S, in, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 256, Ss, Stack, T, Ts, Tzr);
-yeccpars2_255(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_256: see yeccpars2_108
-
-yeccpars2_257(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_257_(Stack),
- yeccgoto_let_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_258: see yeccpars2_108
-
-yeccpars2_259(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_259_(Stack),
- yeccgoto_sequence(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_260(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_260_(Stack),
- yeccgoto_catch_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_261(S, 'of', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 262, Ss, Stack, T, Ts, Tzr);
-yeccpars2_261(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_262(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 178, Ss, Stack, T, Ts, Tzr);
-yeccpars2_262(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 179, Ss, Stack, T, Ts, Tzr);
-yeccpars2_262(S, '<', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 180, Ss, Stack, T, Ts, Tzr);
-yeccpars2_262(S, '[', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 181, Ss, Stack, T, Ts, Tzr);
-yeccpars2_262(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 31, Ss, Stack, T, Ts, Tzr);
-yeccpars2_262(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
-yeccpars2_262(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 183, Ss, Stack, T, Ts, Tzr);
-yeccpars2_262(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_24(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_263(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 264, Ss, Stack, T, Ts, Tzr);
-yeccpars2_263(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_264(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_264_(Stack),
- yeccgoto_case_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_265(S, ':', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 266, Ss, Stack, T, Ts, Tzr);
-yeccpars2_265(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_266: see yeccpars2_108
-
-%% yeccpars2_267: see yeccpars2_244
-
-yeccpars2_268(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_268_(Stack),
- yeccgoto_call_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_269: see yeccpars2_244
-
-yeccpars2_270(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_270_(Stack),
- yeccgoto_application_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_271(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 273, Ss, Stack, T, Ts, Tzr);
-yeccpars2_271(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 274, Ss, Stack, T, Ts, Tzr);
-yeccpars2_271(S, '|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 275, Ss, Stack, T, Ts, Tzr);
-yeccpars2_271(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_272(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_272_(Stack),
- yeccgoto_cons(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_273: see yeccpars2_108
-
-yeccpars2_274(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_274_(Stack),
- yeccgoto_tail(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_275: see yeccpars2_108
-
-yeccpars2_276(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 277, Ss, Stack, T, Ts, Tzr);
-yeccpars2_276(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_277(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_277_(Stack),
- yeccgoto_tail(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_278: see yeccpars2_271
-
-yeccpars2_279(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_279_(Stack),
- yeccgoto_tail(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_280(S, '>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 282, Ss, Stack, T, Ts, Tzr);
-yeccpars2_280(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_281(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_281_(Stack),
- yeccgoto_expression(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_282(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_282_(Stack),
- yeccgoto_expression(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_283(S, '-|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 284, Ss, Stack, T, Ts, Tzr);
-yeccpars2_283(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_284: see yeccpars2_63
-
-yeccpars2_285(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 286, Ss, Stack, T, Ts, Tzr);
-yeccpars2_285(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_286(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_286_(Stack),
- yeccgoto_anno_expression(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_287(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 290, Ss, Stack, T, Ts, Tzr);
-yeccpars2_287(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 291, Ss, Stack, T, Ts, Tzr);
-yeccpars2_287(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_288(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 301, Ss, Stack, T, Ts, Tzr);
-yeccpars2_288(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_289(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 299, Ss, Stack, T, Ts, Tzr);
-yeccpars2_289(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_289_(Stack),
- yeccgoto_segments(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_290(S, '<', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 293, Ss, Stack, T, Ts, Tzr);
-yeccpars2_290(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_291(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 292, Ss, Stack, T, Ts, Tzr);
-yeccpars2_291(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_292(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_|Nss] = Ss,
- NewStack = yeccpars2_292_(Stack),
- yeccgoto_binary(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_293: see yeccpars2_108
-
-yeccpars2_294(S, '>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 295, Ss, Stack, T, Ts, Tzr);
-yeccpars2_294(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_295(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 296, Ss, Stack, T, Ts, Tzr);
-yeccpars2_295(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_296: see yeccpars2_108
-
-yeccpars2_297(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 298, Ss, Stack, T, Ts, Tzr);
-yeccpars2_297(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_298(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_298_(Stack),
- yeccgoto_segment(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_299(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 290, Ss, Stack, T, Ts, Tzr);
-yeccpars2_299(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_300(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_300_(Stack),
- yeccgoto_segments(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_301(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 302, Ss, Stack, T, Ts, Tzr);
-yeccpars2_301(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_302(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_302_(Stack),
- yeccgoto_binary(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_303(S, '-|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 196, Ss, Stack, T, Ts, Tzr);
-yeccpars2_303(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_304(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 105, Ss, Stack, T, Ts, Tzr);
-yeccpars2_304(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
-yeccpars2_304(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_305(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_305_(Stack),
- yeccgoto_anno_variables(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_306(S, '->', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 307, Ss, Stack, T, Ts, Tzr);
-yeccpars2_306(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_307: see yeccpars2_108
-
-yeccpars2_308(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_308_(Stack),
- yeccgoto_fun_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_309(S, '-|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 310, Ss, Stack, T, Ts, Tzr);
-yeccpars2_309(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_310: see yeccpars2_63
-
-yeccpars2_311(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 312, Ss, Stack, T, Ts, Tzr);
-yeccpars2_311(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_312(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_312_(Stack),
- yeccgoto_anno_fun(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_313(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_313_(Stack),
- yeccgoto_function_definitions(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_314(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_314_(Stack),
- yeccgoto_module_definition(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_315(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 316, Ss, Stack, T, Ts, Tzr);
-yeccpars2_315(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_316: see yeccpars2_4
-
-%% yeccpars2_317: see yeccpars2_5
-
-yeccpars2_318(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 61, Ss, Stack, T, Ts, Tzr);
-yeccpars2_318(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 11, Ss, Stack, T, Ts, Tzr);
-yeccpars2_318(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_318_(Stack),
- yeccpars2_58(_S, Cat, [318 | Ss], NewStack, T, Ts, Tzr).
-
-yeccpars2_319(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 320, Ss, Stack, T, Ts, Tzr);
-yeccpars2_319(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_320(S, '-|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 321, Ss, Stack, T, Ts, Tzr);
-yeccpars2_320(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_321: see yeccpars2_63
-
-yeccpars2_322(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 323, Ss, Stack, T, Ts, Tzr);
-yeccpars2_322(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_323(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_,_,_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_323_(Stack),
- yeccgoto_module_definition(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccgoto_anno_clause(142, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_177(177, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_clause(177, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_177(177, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_clause(262, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_177(177, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_anno_clauses(142, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_176(176, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_clauses(177=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_238(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_clauses(262, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_263(263, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_anno_expression(108=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_128(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(131, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_146(146, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(132, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_271(271, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(133, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_244(269, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(135, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_265(265, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(136, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_261(261, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(137=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_260(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(138, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(258, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(141, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_244(244, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(143, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_151(151, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(144, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_146(146, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(148, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_146(146, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(159, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_160(160, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(163=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_164(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(182, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_202(202, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(203=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_204(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(240, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_241(241, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(242=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_243(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(246, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_146(146, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(251=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_252(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(254, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_255(255, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(256=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_257(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(258=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_259(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(266, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_244(267, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(273, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_271(278, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(275, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_276(276, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(293, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_294(294, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(296, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_146(146, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expression(307=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_308(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_anno_expressions(131, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_280(280, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expressions(144, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_145(145, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expressions(148=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_149(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expressions(246, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_247(247, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_expressions(296, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_297(297, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_anno_fun(96=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_98(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_anno_function_name(17, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_60(60, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_function_name(59, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_60(60, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_function_name(140, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_60(60, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_function_name(318, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_60(60, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_anno_pattern(142=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_175(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_pattern(177=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_175(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_pattern(179=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_175(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_pattern(180, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_185(185, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_pattern(181, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_205(205, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_pattern(183, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_185(185, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_pattern(191=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_192(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_pattern(199, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_185(185, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_pattern(207, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_205(212, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_pattern(209, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_210(210, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_pattern(228, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_229(229, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_pattern(231, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_185(185, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_pattern(262=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_175(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_anno_patterns(180, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_214(214, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_patterns(183, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_184(184, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_patterns(199=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_200(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_patterns(231, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_232(232, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_anno_variable(101, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_104(104, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_variable(139=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_154(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_variable(142, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_174(174, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_variable(152=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_154(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_variable(155, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_104(104, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_variable(161=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_154(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_variable(177, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_174(174, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_variable(179, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_174(174, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_variable(180, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_174(174, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_variable(181, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_174(174, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_variable(183, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_174(174, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_variable(186, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_190(190, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_variable(191, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_174(174, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_variable(199, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_174(174, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_variable(207, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_174(174, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_variable(209, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_174(174, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_variable(228, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_174(174, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_variable(231, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_174(174, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_variable(262, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_174(174, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_variable(304, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_104(104, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_anno_variables(101, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_103(103, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_variables(155, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_156(156, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_anno_variables(304=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_305(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_annotation(63, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_64(64, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_annotation(193, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_194(194, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_annotation(196, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_197(197, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_annotation(219, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_220(220, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_annotation(284, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_285(285, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_annotation(310, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_311(311, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_annotation(321, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_322(322, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_application_expr(108=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(130=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(131=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(132=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(133=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(135=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(137=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(141=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(143=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(144=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(148=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(159=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(163=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(182=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(203=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(240=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(242=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(246=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(251=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(254=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(256=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(258=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(266=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(273=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(275=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(293=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(296=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_application_expr(307=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_127(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_arg_list(244=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_245(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_arg_list(267=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_268(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_arg_list(269=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_270(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_atomic_constant(65=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_71(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_constant(72=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_71(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_constant(79=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_71(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_constant(85=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_71(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_constant(87=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_71(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_constant(92=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_71(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_atomic_literal(24=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(30=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(36=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(40=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(46=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(48=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(108=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(130=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(131=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(132=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(133=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(135=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(137=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(141=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(142=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_173(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(143=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(144=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(148=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(159=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(163=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(177=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_173(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(179=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_173(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(180=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_173(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(181=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_173(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(182=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(183=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_173(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(186=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_173(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(191=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_173(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(199=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_173(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(203=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(207=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_173(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(209=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_173(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_173(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(231=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_173(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(240=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(242=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(246=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(251=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(254=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(256=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(258=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(262=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_173(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(266=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(273=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(275=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(293=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(296=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_literal(307=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_atomic_pattern(142=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_172(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_pattern(177=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_172(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_pattern(179=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_172(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_pattern(180=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_172(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_pattern(181=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_172(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_pattern(183=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_172(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_pattern(186=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_172(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_pattern(191=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_172(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_pattern(199=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_172(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_pattern(207=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_172(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_pattern(209=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_172(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_pattern(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_172(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_pattern(231=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_172(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic_pattern(262=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_172(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_attribute(19, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(21, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_attribute(53, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(21, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_attribute_list(19, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_attribute_list(53=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_54(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_binary(108=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(130=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(131=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(132=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(133=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(135=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(137=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(141=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(143=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(144=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(148=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(159=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(163=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(182=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(203=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(240=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(242=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(246=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(251=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(254=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(256=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(258=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(266=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(273=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(275=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(293=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(296=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(307=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_binary_pattern(142=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_171(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_pattern(177=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_171(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_pattern(179=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_171(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_pattern(180=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_171(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_pattern(181=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_171(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_pattern(183=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_171(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_pattern(186=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_171(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_pattern(191=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_171(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_pattern(199=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_171(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_pattern(207=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_171(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_pattern(209=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_171(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_pattern(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_171(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_pattern(231=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_171(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_pattern(262=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_171(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_call_expr(108=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(130=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(131=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(132=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(133=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(135=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(137=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(141=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(143=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(144=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(148=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(159=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(163=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(182=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(203=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(240=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(242=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(246=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(251=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(254=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(256=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(258=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(266=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(273=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(275=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(293=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(296=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_call_expr(307=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_case_expr(108=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(130=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(131=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(132=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(133=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(135=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(137=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(141=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(143=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(144=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(148=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(159=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(163=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(182=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(203=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(240=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(242=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(246=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(251=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(254=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(256=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(258=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(266=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(273=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(275=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(293=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(296=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(307=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_123(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_catch_expr(108=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(130=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(131=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(132=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(133=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(135=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(137=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(141=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(143=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(144=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(148=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(159=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(163=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(182=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(203=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(240=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(242=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(246=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(251=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(254=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(256=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(258=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(266=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(273=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(275=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(293=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(296=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_catch_expr(307=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_clause(142=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_170(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_clause(177=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_170(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_clause(179, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_218(218, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_clause(262=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_170(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_clause_pattern(142, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_169(169, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_clause_pattern(177, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_169(169, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_clause_pattern(179, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_169(169, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_clause_pattern(262, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_169(169, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_cons(108=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(130=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(131=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(132=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(133=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(135=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(137=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(141=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(143=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(144=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(148=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(159=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(163=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(182=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(203=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(240=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(242=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(246=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(251=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(254=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(256=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(258=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(266=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(273=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(275=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(293=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(296=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons(307=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_121(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_cons_constant(65=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_70(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons_constant(72=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_70(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons_constant(79=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_70(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons_constant(85=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_70(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons_constant(87=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_70(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons_constant(92=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_70(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_cons_literal(24=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons_literal(30=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons_literal(36=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons_literal(40=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons_literal(46=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons_literal(48=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_cons_pattern(142=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_168(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons_pattern(177=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_168(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons_pattern(179=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_168(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons_pattern(180=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_168(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons_pattern(181=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_168(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons_pattern(183=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_168(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons_pattern(186=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_168(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons_pattern(191=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_168(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons_pattern(199=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_168(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons_pattern(207=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_168(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons_pattern(209=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_168(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons_pattern(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_168(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons_pattern(231=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_168(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cons_pattern(262=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_168(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_constant(65, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_69(69, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_constant(72, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_83(83, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_constant(79, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_69(69, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_constant(85, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_83(90, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_constant(87, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_88(88, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_constant(92, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_69(69, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_constants(65, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_68(68, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_constants(79, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_80(80, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_constants(92=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_93(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_exported_name(6, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_9(9, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_exported_name(14, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_9(9, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_exported_names(6, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_8(8, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_exported_names(14=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_expression(108=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(130, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_283(283, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(131=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(132=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(133=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(135=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(137=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(141=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(143=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(144=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(148=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(159=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(163=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(182=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(203=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(240=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(242=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(246=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(251=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(254=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(256=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(258=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(266=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(273=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(275=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(293=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(296=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expression(307=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_fun_expr(96=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_97(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(99, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_309(309, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(108=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(130=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(131=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(132=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(133=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(135=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(137=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(141=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(143=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(144=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(148=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(159=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(163=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(182=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(203=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(240=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(242=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(246=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(251=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(254=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(256=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(258=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(266=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(273=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(275=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(293=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(296=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(307=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_function_definition(17, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_59(59, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_definition(59, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_59(59, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_definition(140, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_59(59, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_definition(318, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_59(59, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_function_definitions(17=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_58(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_definitions(59=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_313(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_definitions(140, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_250(250, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_definitions(318=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_58(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_function_name(6=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_7(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(14=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_7(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(17=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_57(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(59=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_57(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(61, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_62(62, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(108=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(130=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(131=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(132=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(133=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(135=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(137=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(140=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_57(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(141=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(143=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(144=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(148=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(159=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(163=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(182=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(203=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(240=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(242=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(246=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(251=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(254=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(256=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(258=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(266=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(273=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(275=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(293=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(296=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(307=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_118(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_name(318=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_57(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_let_expr(108=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(130=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(131=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(132=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(133=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(135=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(137=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(141=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(143=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(144=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(148=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(159=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(163=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(182=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(203=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(240=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(242=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(246=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(251=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(254=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(256=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(258=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(266=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(273=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(275=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(293=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(296=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_expr(307=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_117(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_let_vars(139, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_253(253, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_vars(152, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_153(153, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_let_vars(161, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_162(162, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_letrec_expr(108=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(130=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(131=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(132=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(133=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(135=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(137=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(141=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(143=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(144=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(148=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(159=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(163=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(182=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(203=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(240=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(242=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(246=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(251=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(254=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(256=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(258=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(266=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(273=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(275=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(293=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(296=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_letrec_expr(307=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_literal(24=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_literal(30, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(43, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_literal(36, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(38, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_literal(40, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(38, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_literal(46, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(51, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_literal(48, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_49(49, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_literals(36, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_literals(40=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_module_attribute(5, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_module_attribute(317, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_318(318, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_module_definition(0, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_1(1, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_module_defs(17, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_56(56, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_module_defs(318, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_319(319, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_module_export(4, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_5(5, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_module_export(316, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_5(317, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_nil(24=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(30=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(36=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(40=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(46=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(48=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(65=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_67(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(72=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_67(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(79=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_67(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(85=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_67(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(87=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_67(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(92=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_67(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(108=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(130=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(131=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(132=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(133=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(135=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(137=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(141=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(142=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(143=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(144=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(148=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(159=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(163=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(177=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(179=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(180=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(181=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(182=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(183=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(186=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(191=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(199=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(203=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(207=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(209=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(231=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(240=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(242=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(246=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(251=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(254=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(256=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(258=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(262=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(266=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(273=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(275=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(293=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(296=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_nil(307=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_other_pattern(142=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_167(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_other_pattern(177=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_167(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_other_pattern(179, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_217(217, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_other_pattern(180=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_167(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_other_pattern(181=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_167(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_other_pattern(183=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_167(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_other_pattern(186, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_189(189, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_other_pattern(191=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_167(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_other_pattern(199=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_167(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_other_pattern(207=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_167(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_other_pattern(209=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_167(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_other_pattern(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_167(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_other_pattern(231=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_167(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_other_pattern(262=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_167(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_primop_expr(108=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(130=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(131=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(132=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(133=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(135=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(137=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(141=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(143=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(144=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(148=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(159=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(163=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(182=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(203=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(240=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(242=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(246=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(251=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(254=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(256=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(258=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(266=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(273=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(275=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(293=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(296=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_primop_expr(307=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_receive_expr(108=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(130=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(131=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(132=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(133=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(135=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(137=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(141=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(143=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(144=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(148=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(159=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(163=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(182=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(203=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(240=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(242=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(246=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(251=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(254=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(256=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(258=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(266=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(273=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(275=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(293=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(296=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(307=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_segment(287, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_289(289, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_segment(299, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_289(289, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_segment_pattern(222, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_224(224, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_segment_pattern(234, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_224(224, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_segment_patterns(222, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_223(223, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_segment_patterns(234=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_235(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_segments(287, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_288(288, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_segments(299=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_300(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_sequence(108=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(130=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(131=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(132=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(133=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(135=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(137=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(141=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(143=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(144=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(148=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(159=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(163=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(182=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(203=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(240=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(242=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(246=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(251=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(254=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(256=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(258=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(266=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(273=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(275=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(293=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(296=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_sequence(307=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_single_expression(108=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(130=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(131=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(132=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(133=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(135=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(137=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(141=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(143=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(144=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(148=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(159=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(163=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(182=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(203=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(240=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(242=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(246=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(251=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(254=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(256=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(258=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(266=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(273=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(275=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(293=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(296=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_single_expression(307=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_tail(271=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_272(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tail(278=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_279(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_tail_constant(83=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_84(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tail_constant(90=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_91(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_tail_literal(43=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tail_literal(51=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_52(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_tail_pattern(205=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_206(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tail_pattern(212=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_213(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_timeout(142=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_166(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_timeout(176=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_239(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_try_expr(108=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(130=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(131=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(132=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(133=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(135=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(137=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(141=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(143=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(144=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(148=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(159=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(163=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(182=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(203=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(240=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(242=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(246=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(251=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(254=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(256=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(258=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(266=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(273=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(275=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(293=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(296=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(307=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_tuple(108=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(130=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(131=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(132=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(133=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(135=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(137=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(141=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(143=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(144=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(148=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(159=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(163=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(182=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(203=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(240=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(242=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(246=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(251=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(254=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(256=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(258=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(266=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(273=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(275=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(293=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(296=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(307=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_tuple_constant(65=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_66(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple_constant(72=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_66(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple_constant(79=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_66(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple_constant(85=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_66(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple_constant(87=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_66(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple_constant(92=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_66(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_tuple_literal(24=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple_literal(30=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple_literal(36=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple_literal(40=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple_literal(46=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple_literal(48=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_tuple_pattern(142=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_165(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple_pattern(177=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_165(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple_pattern(179=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_165(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple_pattern(180=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_165(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple_pattern(181=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_165(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple_pattern(183=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_165(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple_pattern(186=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_165(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple_pattern(191=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_165(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple_pattern(199=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_165(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple_pattern(207=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_165(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple_pattern(209=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_165(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple_pattern(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_165(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple_pattern(231=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_165(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple_pattern(262=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_165(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_variable(101=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_102(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(105, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_303(303, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(108=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(130=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(131=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(132=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(133=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(135=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(137=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(139=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_102(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(141=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(142=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_102(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(143=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(144=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(148=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(152=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_102(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(155=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_102(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(159=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(161=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_102(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(163=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(177=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_102(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(179, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_188(188, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(180=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_102(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(181=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_102(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(182=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(183=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_102(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(186, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_188(188, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(191=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_102(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(199=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_102(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(203=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(207=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_102(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(209=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_102(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_102(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(231=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_102(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(240=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(242=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(246=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(251=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(254=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(256=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(258=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(262=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_102(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(266=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(273=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(275=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(293=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(296=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(304=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_102(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_variable(307=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
--compile({inline,yeccpars2_9_/1}).
--file("core_parse.yrl", 89).
-yeccpars2_9_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--compile({inline,yeccpars2_10_/1}).
--file("core_parse.yrl", 85).
-yeccpars2_10_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- [ ]
- end | __Stack].
-
--compile({inline,yeccpars2_13_/1}).
--file("core_parse.yrl", 288).
-yeccpars2_13_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- # c_var { name = { tok_val ( __1 ) , tok_val ( __3 ) } }
- end | __Stack].
-
--compile({inline,yeccpars2_15_/1}).
--file("core_parse.yrl", 88).
-yeccpars2_15_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--compile({inline,yeccpars2_16_/1}).
--file("core_parse.yrl", 86).
-yeccpars2_16_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- __2
- end | __Stack].
-
--compile({inline,yeccpars2_17_/1}).
--file("core_parse.yrl", 110).
-yeccpars2_17_(__Stack0) ->
- [begin
- [ ]
- end | __Stack0].
-
--compile({inline,yeccpars2_21_/1}).
--file("core_parse.yrl", 97).
-yeccpars2_21_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--compile({inline,yeccpars2_22_/1}).
--file("core_parse.yrl", 93).
-yeccpars2_22_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ ]
- end | __Stack].
-
--compile({inline,yeccpars2_26_/1}).
--file("core_parse.yrl", 252).
-yeccpars2_26_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- # c_literal { val = [ ] }
- end | __Stack].
-
--compile({inline,yeccpars2_27_/1}).
--file("core_parse.yrl", 100).
-yeccpars2_27_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { # c_literal { val = tok_val ( __1 ) } , __3 }
- end | __Stack].
-
--compile({inline,yeccpars2_31_/1}).
--file("core_parse.yrl", 250).
-yeccpars2_31_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- # c_literal { val = tok_val ( __1 ) }
- end | __Stack].
-
--compile({inline,yeccpars2_32_/1}).
--file("core_parse.yrl", 247).
-yeccpars2_32_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- # c_literal { val = tok_val ( __1 ) }
- end | __Stack].
-
--compile({inline,yeccpars2_33_/1}).
--file("core_parse.yrl", 249).
-yeccpars2_33_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- # c_literal { val = tok_val ( __1 ) }
- end | __Stack].
-
--compile({inline,yeccpars2_34_/1}).
--file("core_parse.yrl", 248).
-yeccpars2_34_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- # c_literal { val = tok_val ( __1 ) }
- end | __Stack].
-
--compile({inline,yeccpars2_35_/1}).
--file("core_parse.yrl", 251).
-yeccpars2_35_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- # c_literal { val = tok_val ( __1 ) }
- end | __Stack].
-
--compile({inline,yeccpars2_38_/1}).
--file("core_parse.yrl", 245).
-yeccpars2_38_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--compile({inline,yeccpars2_39_/1}).
--file("core_parse.yrl", 254).
-yeccpars2_39_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- c_tuple ( [ ] )
- end | __Stack].
-
--compile({inline,yeccpars2_41_/1}).
--file("core_parse.yrl", 244).
-yeccpars2_41_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--compile({inline,yeccpars2_42_/1}).
--file("core_parse.yrl", 255).
-yeccpars2_42_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- c_tuple ( __2 )
- end | __Stack].
-
--compile({inline,yeccpars2_44_/1}).
--file("core_parse.yrl", 66).
-yeccpars2_44_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- { nil , tok_line ( __1 ) }
- end | __Stack].
-
--compile({inline,yeccpars2_45_/1}).
--file("core_parse.yrl", 257).
-yeccpars2_45_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- c_cons ( __2 , __3 )
- end | __Stack].
-
--compile({inline,yeccpars2_47_/1}).
--file("core_parse.yrl", 259).
-yeccpars2_47_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- # c_literal { val = [ ] }
- end | __Stack].
-
--compile({inline,yeccpars2_50_/1}).
--file("core_parse.yrl", 260).
-yeccpars2_50_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- __2
- end | __Stack].
-
--compile({inline,yeccpars2_52_/1}).
--file("core_parse.yrl", 261).
-yeccpars2_52_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- # c_cons { hd = __2 , tl = __3 }
- end | __Stack].
-
--compile({inline,yeccpars2_54_/1}).
--file("core_parse.yrl", 96).
-yeccpars2_54_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--compile({inline,yeccpars2_55_/1}).
--file("core_parse.yrl", 94).
-yeccpars2_55_(__Stack0) ->
- [__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- __3
- end | __Stack].
-
--compile({inline,yeccpars2_59_/1}).
--file("core_parse.yrl", 110).
-yeccpars2_59_(__Stack0) ->
- [begin
- [ ]
- end | __Stack0].
-
--compile({inline,yeccpars2_67_/1}).
--file("core_parse.yrl", 135).
-yeccpars2_67_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ ]
- end | __Stack].
-
--compile({inline,yeccpars2_69_/1}).
--file("core_parse.yrl", 128).
-yeccpars2_69_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--compile({inline,yeccpars2_73_/1}).
--file("core_parse.yrl", 104).
-yeccpars2_73_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- [ ]
- end | __Stack].
-
--compile({inline,yeccpars2_74_/1}).
--file("core_parse.yrl", 133).
-yeccpars2_74_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- tok_val ( __1 )
- end | __Stack].
-
--compile({inline,yeccpars2_75_/1}).
--file("core_parse.yrl", 130).
-yeccpars2_75_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- tok_val ( __1 )
- end | __Stack].
-
--compile({inline,yeccpars2_76_/1}).
--file("core_parse.yrl", 132).
-yeccpars2_76_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- tok_val ( __1 )
- end | __Stack].
-
--compile({inline,yeccpars2_77_/1}).
--file("core_parse.yrl", 131).
-yeccpars2_77_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- tok_val ( __1 )
- end | __Stack].
-
--compile({inline,yeccpars2_78_/1}).
--file("core_parse.yrl", 134).
-yeccpars2_78_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- tok_val ( __1 )
- end | __Stack].
-
--compile({inline,yeccpars2_81_/1}).
--file("core_parse.yrl", 137).
-yeccpars2_81_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- { }
- end | __Stack].
-
--compile({inline,yeccpars2_82_/1}).
--file("core_parse.yrl", 138).
-yeccpars2_82_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- list_to_tuple ( __2 )
- end | __Stack].
-
--compile({inline,yeccpars2_84_/1}).
--file("core_parse.yrl", 140).
-yeccpars2_84_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __2 | __3 ]
- end | __Stack].
-
--compile({inline,yeccpars2_86_/1}).
--file("core_parse.yrl", 142).
-yeccpars2_86_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ ]
- end | __Stack].
-
--compile({inline,yeccpars2_89_/1}).
--file("core_parse.yrl", 143).
-yeccpars2_89_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- __2
- end | __Stack].
-
--compile({inline,yeccpars2_91_/1}).
--file("core_parse.yrl", 144).
-yeccpars2_91_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __2 | __3 ]
- end | __Stack].
-
--compile({inline,yeccpars2_93_/1}).
--file("core_parse.yrl", 127).
-yeccpars2_93_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--compile({inline,yeccpars2_94_/1}).
--file("core_parse.yrl", 105).
-yeccpars2_94_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- __2
- end | __Stack].
-
--compile({inline,yeccpars2_95_/1}).
--file("core_parse.yrl", 292).
-yeccpars2_95_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- core_lib : set_anno ( __2 , __4 )
- end | __Stack].
-
--compile({inline,yeccpars2_98_/1}).
--file("core_parse.yrl", 114).
-yeccpars2_98_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { __1 , __3 }
- end | __Stack].
-
--compile({inline,yeccpars2_104_/1}).
--file("core_parse.yrl", 201).
-yeccpars2_104_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--compile({inline,yeccpars2_107_/1}).
--file("core_parse.yrl", 198).
-yeccpars2_107_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- # c_var { name = tok_val ( __1 ) }
- end | __Stack].
-
--compile({inline,yeccpars2_128_/1}).
--file("core_parse.yrl", 302).
-yeccpars2_128_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- # c_fun { vars = [ ] , body = __5 }
- end | __Stack].
-
--compile({inline,yeccpars2_134_/1}).
--file("core_parse.yrl", 250).
-yeccpars2_134_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- # c_literal { val = tok_val ( __1 ) }
- end | __Stack].
-
--compile({inline,yeccpars2_140_/1}).
--file("core_parse.yrl", 110).
-yeccpars2_140_(__Stack0) ->
- [begin
- [ ]
- end | __Stack0].
-
--compile({inline,yeccpars2_146_/1}).
--file("core_parse.yrl", 216).
-yeccpars2_146_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--compile({inline,yeccpars2_147_/1}).
--file("core_parse.yrl", 263).
-yeccpars2_147_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- c_tuple ( [ ] )
- end | __Stack].
-
--compile({inline,yeccpars2_149_/1}).
--file("core_parse.yrl", 215).
-yeccpars2_149_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--compile({inline,yeccpars2_150_/1}).
--file("core_parse.yrl", 264).
-yeccpars2_150_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- c_tuple ( __2 )
- end | __Stack].
-
--compile({inline,yeccpars2_154_/1}).
--file("core_parse.yrl", 294).
-yeccpars2_154_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--compile({inline,yeccpars2_157_/1}).
--file("core_parse.yrl", 295).
-yeccpars2_157_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- [ ]
- end | __Stack].
-
--compile({inline,yeccpars2_158_/1}).
--file("core_parse.yrl", 296).
-yeccpars2_158_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- __2
- end | __Stack].
-
--compile({inline,yeccpars2_164_/1}).
--file("core_parse.yrl", 345).
-yeccpars2_164_(__Stack0) ->
- [__10,__9,__8,__7,__6,__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- Len = length ( __8 ) ,
- if Len =:= 2 ; Len =:= 3 ->
- # c_try { arg = __2 , vars = __4 , body = __6 , evars = __8 , handler = __10 } ;
- true ->
- return_error ( tok_line ( __7 ) ,
- "expected 2 or 3 exception variables in 'try'" )
- end
- end | __Stack].
-
--compile({inline,yeccpars2_166_/1}).
--file("core_parse.yrl", 356).
-yeccpars2_166_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- { T , A } = __2 ,
- # c_receive { clauses = [ ] , timeout = T , action = A }
- end | __Stack].
-
--compile({inline,yeccpars2_175_/1}).
--file("core_parse.yrl", 325).
-yeccpars2_175_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--compile({inline,yeccpars2_177_/1}).
--file("core_parse.yrl", 316).
-yeccpars2_177_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--compile({inline,yeccpars2_185_/1}).
--file("core_parse.yrl", 161).
-yeccpars2_185_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--compile({inline,yeccpars2_187_/1}).
--file("core_parse.yrl", 172).
-yeccpars2_187_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- c_tuple ( [ ] )
- end | __Stack].
-
--compile({inline,yeccpars2_192_/1}).
--file("core_parse.yrl", 168).
-yeccpars2_192_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- # c_alias { var = __1 , pat = __3 }
- end | __Stack].
-
--compile({inline,yeccpars2_195_/1}).
--file("core_parse.yrl", 156).
-yeccpars2_195_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- core_lib : set_anno ( __2 , __4 )
- end | __Stack].
-
--compile({inline,yeccpars2_198_/1}).
--file("core_parse.yrl", 205).
-yeccpars2_198_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- core_lib : set_anno ( __2 , __4 )
- end | __Stack].
-
--compile({inline,yeccpars2_200_/1}).
--file("core_parse.yrl", 160).
-yeccpars2_200_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--compile({inline,yeccpars2_201_/1}).
--file("core_parse.yrl", 173).
-yeccpars2_201_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- c_tuple ( __2 )
- end | __Stack].
-
--compile({inline,yeccpars2_204_/1}).
--file("core_parse.yrl", 363).
-yeccpars2_204_(__Stack0) ->
- [__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { __2 , __4 }
- end | __Stack].
-
--compile({inline,yeccpars2_206_/1}).
--file("core_parse.yrl", 176).
-yeccpars2_206_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- # c_cons { hd = __2 , tl = __3 }
- end | __Stack].
-
--compile({inline,yeccpars2_208_/1}).
--file("core_parse.yrl", 178).
-yeccpars2_208_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- # c_literal { val = [ ] }
- end | __Stack].
-
--compile({inline,yeccpars2_211_/1}).
--file("core_parse.yrl", 179).
-yeccpars2_211_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- __2
- end | __Stack].
-
--compile({inline,yeccpars2_213_/1}).
--file("core_parse.yrl", 181).
-yeccpars2_213_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- # c_cons { hd = __2 , tl = __3 }
- end | __Stack].
-
--compile({inline,yeccpars2_215_/1}).
--file("core_parse.yrl", 326).
-yeccpars2_215_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- [ ]
- end | __Stack].
-
--compile({inline,yeccpars2_216_/1}).
--file("core_parse.yrl", 327).
-yeccpars2_216_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- __2
- end | __Stack].
-
--compile({inline,yeccpars2_221_/1}).
--file("core_parse.yrl", 320).
-yeccpars2_221_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- core_lib : set_anno ( __2 , __4 )
- end | __Stack].
-
--compile({inline,yeccpars2_224_/1}).
--file("core_parse.yrl", 187).
-yeccpars2_224_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--compile({inline,yeccpars2_227_/1}).
--file("core_parse.yrl", 183).
-yeccpars2_227_(__Stack0) ->
- [__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- # c_binary { segments = [ ] }
- end | __Stack].
-
--compile({inline,yeccpars2_233_/1}).
--file("core_parse.yrl", 190).
-yeccpars2_233_(__Stack0) ->
- [__7,__6,__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- case __6 of
- [ S , U , T , Fs ] ->
- # c_bitstr { val = __3 , size = S , unit = U , type = T , flags = Fs } ;
- true ->
- return_error ( tok_line ( __1 ) ,
- "expected 4 arguments in binary segment" )
- end
- end | __Stack].
-
--compile({inline,yeccpars2_235_/1}).
--file("core_parse.yrl", 186).
-yeccpars2_235_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--compile({inline,yeccpars2_237_/1}).
--file("core_parse.yrl", 184).
-yeccpars2_237_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- # c_binary { segments = __3 }
- end | __Stack].
-
--compile({inline,yeccpars2_238_/1}).
--file("core_parse.yrl", 315).
-yeccpars2_238_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __2 ]
- end | __Stack].
-
--compile({inline,yeccpars2_239_/1}).
--file("core_parse.yrl", 359).
-yeccpars2_239_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { T , A } = __3 ,
- # c_receive { clauses = __2 , timeout = T , action = A }
- end | __Stack].
-
--compile({inline,yeccpars2_243_/1}).
--file("core_parse.yrl", 323).
-yeccpars2_243_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- # c_clause { pats = __1 , guard = __3 , body = __5 }
- end | __Stack].
-
--compile({inline,yeccpars2_245_/1}).
--file("core_parse.yrl", 337).
-yeccpars2_245_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- # c_primop { name = __2 , args = __3 }
- end | __Stack].
-
--compile({inline,yeccpars2_248_/1}).
--file("core_parse.yrl", 339).
-yeccpars2_248_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- [ ]
- end | __Stack].
-
--compile({inline,yeccpars2_249_/1}).
--file("core_parse.yrl", 340).
-yeccpars2_249_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- __2
- end | __Stack].
-
--compile({inline,yeccpars2_252_/1}).
--file("core_parse.yrl", 310).
-yeccpars2_252_(__Stack0) ->
- [__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- # c_letrec { defs = __2 , body = __4 }
- end | __Stack].
-
--compile({inline,yeccpars2_257_/1}).
--file("core_parse.yrl", 307).
-yeccpars2_257_(__Stack0) ->
- [__6,__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- # c_let { vars = __2 , arg = __4 , body = __6 }
- end | __Stack].
-
--compile({inline,yeccpars2_259_/1}).
--file("core_parse.yrl", 299).
-yeccpars2_259_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- # c_seq { arg = __2 , body = __3 }
- end | __Stack].
-
--compile({inline,yeccpars2_260_/1}).
--file("core_parse.yrl", 353).
-yeccpars2_260_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- # c_catch { body = __2 }
- end | __Stack].
-
--compile({inline,yeccpars2_264_/1}).
--file("core_parse.yrl", 313).
-yeccpars2_264_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- # c_case { arg = __2 , clauses = __4 }
- end | __Stack].
-
--compile({inline,yeccpars2_268_/1}).
--file("core_parse.yrl", 334).
-yeccpars2_268_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- # c_call { module = __2 , name = __4 , args = __5 }
- end | __Stack].
-
--compile({inline,yeccpars2_270_/1}).
--file("core_parse.yrl", 330).
-yeccpars2_270_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- # c_apply { op = __2 , args = __3 }
- end | __Stack].
-
--compile({inline,yeccpars2_272_/1}).
--file("core_parse.yrl", 266).
-yeccpars2_272_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- c_cons ( __2 , __3 )
- end | __Stack].
-
--compile({inline,yeccpars2_274_/1}).
--file("core_parse.yrl", 268).
-yeccpars2_274_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- # c_literal { val = [ ] }
- end | __Stack].
-
--compile({inline,yeccpars2_277_/1}).
--file("core_parse.yrl", 269).
-yeccpars2_277_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- __2
- end | __Stack].
-
--compile({inline,yeccpars2_279_/1}).
--file("core_parse.yrl", 270).
-yeccpars2_279_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- c_cons ( __2 , __3 )
- end | __Stack].
-
--compile({inline,yeccpars2_281_/1}).
--file("core_parse.yrl", 218).
-yeccpars2_281_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- # c_values { es = [ ] }
- end | __Stack].
-
--compile({inline,yeccpars2_282_/1}).
--file("core_parse.yrl", 219).
-yeccpars2_282_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- # c_values { es = __2 }
- end | __Stack].
-
--compile({inline,yeccpars2_286_/1}).
--file("core_parse.yrl", 213).
-yeccpars2_286_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- core_lib : set_anno ( __2 , __4 )
- end | __Stack].
-
--compile({inline,yeccpars2_289_/1}).
--file("core_parse.yrl", 276).
-yeccpars2_289_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--compile({inline,yeccpars2_292_/1}).
--file("core_parse.yrl", 272).
-yeccpars2_292_(__Stack0) ->
- [__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- # c_literal { val = << >> }
- end | __Stack].
-
--compile({inline,yeccpars2_298_/1}).
--file("core_parse.yrl", 279).
-yeccpars2_298_(__Stack0) ->
- [__7,__6,__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- case __6 of
- [ S , U , T , Fs ] ->
- # c_bitstr { val = __3 , size = S , unit = U , type = T , flags = Fs } ;
- true ->
- return_error ( tok_line ( __1 ) ,
- "expected 4 arguments in binary segment" )
- end
- end | __Stack].
-
--compile({inline,yeccpars2_300_/1}).
--file("core_parse.yrl", 275).
-yeccpars2_300_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--compile({inline,yeccpars2_302_/1}).
--file("core_parse.yrl", 273).
-yeccpars2_302_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- # c_binary { segments = __3 }
- end | __Stack].
-
--compile({inline,yeccpars2_305_/1}).
--file("core_parse.yrl", 200).
-yeccpars2_305_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--compile({inline,yeccpars2_308_/1}).
--file("core_parse.yrl", 304).
-yeccpars2_308_(__Stack0) ->
- [__6,__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- # c_fun { vars = __3 , body = __6 }
- end | __Stack].
-
--compile({inline,yeccpars2_312_/1}).
--file("core_parse.yrl", 117).
-yeccpars2_312_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- core_lib : set_anno ( __2 , __4 )
- end | __Stack].
-
--compile({inline,yeccpars2_313_/1}).
--file("core_parse.yrl", 108).
-yeccpars2_313_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __2 ]
- end | __Stack].
-
--compile({inline,yeccpars2_314_/1}).
--file("core_parse.yrl", 77).
-yeccpars2_314_(__Stack0) ->
- [__6,__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- # c_module { name = # c_literal { val = tok_val ( __2 ) } , exports = __3 ,
- attrs = __4 , defs = __5 }
- end | __Stack].
-
--compile({inline,yeccpars2_318_/1}).
--file("core_parse.yrl", 110).
-yeccpars2_318_(__Stack0) ->
- [begin
- [ ]
- end | __Stack0].
-
--compile({inline,yeccpars2_323_/1}).
--file("core_parse.yrl", 82).
-yeccpars2_323_(__Stack0) ->
- [__10,__9,__8,__7,__6,__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- # c_module { anno = __9 , name = tok_val ( __3 ) , exports = __4 ,
- attrs = __5 , defs = __6 }
- end | __Stack].
-
-
--file("core_parse.yrl", 384).
diff --git a/bootstrap/lib/kernel/ebin/application.beam b/bootstrap/lib/kernel/ebin/application.beam
index ca16b97197..5bdfcefb87 100644
--- a/bootstrap/lib/kernel/ebin/application.beam
+++ b/bootstrap/lib/kernel/ebin/application.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/application_controller.beam b/bootstrap/lib/kernel/ebin/application_controller.beam
index 113faeda01..565691df01 100644
--- a/bootstrap/lib/kernel/ebin/application_controller.beam
+++ b/bootstrap/lib/kernel/ebin/application_controller.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/application_master.beam b/bootstrap/lib/kernel/ebin/application_master.beam
index 602dc36104..4d1098bcec 100644
--- a/bootstrap/lib/kernel/ebin/application_master.beam
+++ b/bootstrap/lib/kernel/ebin/application_master.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/application_starter.beam b/bootstrap/lib/kernel/ebin/application_starter.beam
index 405d2f388a..14ff4dc088 100644
--- a/bootstrap/lib/kernel/ebin/application_starter.beam
+++ b/bootstrap/lib/kernel/ebin/application_starter.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/auth.beam b/bootstrap/lib/kernel/ebin/auth.beam
index 3c038f87aa..3796221d6b 100644
--- a/bootstrap/lib/kernel/ebin/auth.beam
+++ b/bootstrap/lib/kernel/ebin/auth.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/code.beam b/bootstrap/lib/kernel/ebin/code.beam
index 960b96ce4c..3d2bf91b93 100644
--- a/bootstrap/lib/kernel/ebin/code.beam
+++ b/bootstrap/lib/kernel/ebin/code.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/code_server.beam b/bootstrap/lib/kernel/ebin/code_server.beam
index 3d66c1c282..f0be53008b 100644
--- a/bootstrap/lib/kernel/ebin/code_server.beam
+++ b/bootstrap/lib/kernel/ebin/code_server.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/disk_log.beam b/bootstrap/lib/kernel/ebin/disk_log.beam
index 0b9ee6fb8d..cd01c579bf 100644
--- a/bootstrap/lib/kernel/ebin/disk_log.beam
+++ b/bootstrap/lib/kernel/ebin/disk_log.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/disk_log_1.beam b/bootstrap/lib/kernel/ebin/disk_log_1.beam
index bbc42326cb..a61ef2ad3f 100644
--- a/bootstrap/lib/kernel/ebin/disk_log_1.beam
+++ b/bootstrap/lib/kernel/ebin/disk_log_1.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/disk_log_server.beam b/bootstrap/lib/kernel/ebin/disk_log_server.beam
index 089b5d578b..39197f3995 100644
--- a/bootstrap/lib/kernel/ebin/disk_log_server.beam
+++ b/bootstrap/lib/kernel/ebin/disk_log_server.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/disk_log_sup.beam b/bootstrap/lib/kernel/ebin/disk_log_sup.beam
index a98998064d..4e68c9af84 100644
--- a/bootstrap/lib/kernel/ebin/disk_log_sup.beam
+++ b/bootstrap/lib/kernel/ebin/disk_log_sup.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/dist_ac.beam b/bootstrap/lib/kernel/ebin/dist_ac.beam
index 29be008e0c..c86598a689 100644
--- a/bootstrap/lib/kernel/ebin/dist_ac.beam
+++ b/bootstrap/lib/kernel/ebin/dist_ac.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/dist_util.beam b/bootstrap/lib/kernel/ebin/dist_util.beam
index 93f0a3754a..094d909535 100644
--- a/bootstrap/lib/kernel/ebin/dist_util.beam
+++ b/bootstrap/lib/kernel/ebin/dist_util.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erl_boot_server.beam b/bootstrap/lib/kernel/ebin/erl_boot_server.beam
index d88224b5d0..19f6ceeda2 100644
--- a/bootstrap/lib/kernel/ebin/erl_boot_server.beam
+++ b/bootstrap/lib/kernel/ebin/erl_boot_server.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erl_ddll.beam b/bootstrap/lib/kernel/ebin/erl_ddll.beam
index c83b5e393c..b909dd2786 100644
--- a/bootstrap/lib/kernel/ebin/erl_ddll.beam
+++ b/bootstrap/lib/kernel/ebin/erl_ddll.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erl_distribution.beam b/bootstrap/lib/kernel/ebin/erl_distribution.beam
index d4e52d01a9..b084e63a0d 100644
--- a/bootstrap/lib/kernel/ebin/erl_distribution.beam
+++ b/bootstrap/lib/kernel/ebin/erl_distribution.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erl_epmd.beam b/bootstrap/lib/kernel/ebin/erl_epmd.beam
index 847ed69e23..8ae4bbaf14 100644
--- a/bootstrap/lib/kernel/ebin/erl_epmd.beam
+++ b/bootstrap/lib/kernel/ebin/erl_epmd.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erl_reply.beam b/bootstrap/lib/kernel/ebin/erl_reply.beam
index 97b027a67d..c492a19d6f 100644
--- a/bootstrap/lib/kernel/ebin/erl_reply.beam
+++ b/bootstrap/lib/kernel/ebin/erl_reply.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/error_handler.beam b/bootstrap/lib/kernel/ebin/error_handler.beam
index 5a17c845eb..6d56c98c67 100644
--- a/bootstrap/lib/kernel/ebin/error_handler.beam
+++ b/bootstrap/lib/kernel/ebin/error_handler.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/error_logger.beam b/bootstrap/lib/kernel/ebin/error_logger.beam
index c89e4d36c9..e07bef5657 100644
--- a/bootstrap/lib/kernel/ebin/error_logger.beam
+++ b/bootstrap/lib/kernel/ebin/error_logger.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erts_debug.beam b/bootstrap/lib/kernel/ebin/erts_debug.beam
index 9108d7e6d5..b7bf2ea58e 100644
--- a/bootstrap/lib/kernel/ebin/erts_debug.beam
+++ b/bootstrap/lib/kernel/ebin/erts_debug.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/file.beam b/bootstrap/lib/kernel/ebin/file.beam
index 39af418b30..19251f8a4f 100644
--- a/bootstrap/lib/kernel/ebin/file.beam
+++ b/bootstrap/lib/kernel/ebin/file.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/file_io_server.beam b/bootstrap/lib/kernel/ebin/file_io_server.beam
index f7c170fd28..3783cd7b11 100644
--- a/bootstrap/lib/kernel/ebin/file_io_server.beam
+++ b/bootstrap/lib/kernel/ebin/file_io_server.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/file_server.beam b/bootstrap/lib/kernel/ebin/file_server.beam
index 70bdb58805..7b03c3ea0d 100644
--- a/bootstrap/lib/kernel/ebin/file_server.beam
+++ b/bootstrap/lib/kernel/ebin/file_server.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/gen_sctp.beam b/bootstrap/lib/kernel/ebin/gen_sctp.beam
index 1d51915a4f..3092353498 100644
--- a/bootstrap/lib/kernel/ebin/gen_sctp.beam
+++ b/bootstrap/lib/kernel/ebin/gen_sctp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/gen_tcp.beam b/bootstrap/lib/kernel/ebin/gen_tcp.beam
index f684fe1bf2..02103cc215 100644
--- a/bootstrap/lib/kernel/ebin/gen_tcp.beam
+++ b/bootstrap/lib/kernel/ebin/gen_tcp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/gen_udp.beam b/bootstrap/lib/kernel/ebin/gen_udp.beam
index 1591c85048..3b9ca85608 100644
--- a/bootstrap/lib/kernel/ebin/gen_udp.beam
+++ b/bootstrap/lib/kernel/ebin/gen_udp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/global.beam b/bootstrap/lib/kernel/ebin/global.beam
index 7cfbafb942..8049d8d729 100644
--- a/bootstrap/lib/kernel/ebin/global.beam
+++ b/bootstrap/lib/kernel/ebin/global.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/global_group.beam b/bootstrap/lib/kernel/ebin/global_group.beam
index ec789e71ff..f1e6fa219e 100644
--- a/bootstrap/lib/kernel/ebin/global_group.beam
+++ b/bootstrap/lib/kernel/ebin/global_group.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/global_search.beam b/bootstrap/lib/kernel/ebin/global_search.beam
index fe18f8f49a..aa70042058 100644
--- a/bootstrap/lib/kernel/ebin/global_search.beam
+++ b/bootstrap/lib/kernel/ebin/global_search.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/group.beam b/bootstrap/lib/kernel/ebin/group.beam
index b72a13dbc7..67f78948d4 100644
--- a/bootstrap/lib/kernel/ebin/group.beam
+++ b/bootstrap/lib/kernel/ebin/group.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/heart.beam b/bootstrap/lib/kernel/ebin/heart.beam
index 9d381acaff..b20f872241 100644
--- a/bootstrap/lib/kernel/ebin/heart.beam
+++ b/bootstrap/lib/kernel/ebin/heart.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam b/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam
index a53e6f8800..c4a1a850a7 100644
--- a/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam
+++ b/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet.beam b/bootstrap/lib/kernel/ebin/inet.beam
index faac3fc921..9c19e084a6 100644
--- a/bootstrap/lib/kernel/ebin/inet.beam
+++ b/bootstrap/lib/kernel/ebin/inet.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet6_sctp.beam b/bootstrap/lib/kernel/ebin/inet6_sctp.beam
index d9917f0347..10c2644259 100644
--- a/bootstrap/lib/kernel/ebin/inet6_sctp.beam
+++ b/bootstrap/lib/kernel/ebin/inet6_sctp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet6_tcp.beam b/bootstrap/lib/kernel/ebin/inet6_tcp.beam
index c573bc2821..4c80d1d71e 100644
--- a/bootstrap/lib/kernel/ebin/inet6_tcp.beam
+++ b/bootstrap/lib/kernel/ebin/inet6_tcp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet6_tcp_dist.beam b/bootstrap/lib/kernel/ebin/inet6_tcp_dist.beam
index 05d8da8751..1bc785fa37 100644
--- a/bootstrap/lib/kernel/ebin/inet6_tcp_dist.beam
+++ b/bootstrap/lib/kernel/ebin/inet6_tcp_dist.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet6_udp.beam b/bootstrap/lib/kernel/ebin/inet6_udp.beam
index 74cbff87c0..736c0157e5 100644
--- a/bootstrap/lib/kernel/ebin/inet6_udp.beam
+++ b/bootstrap/lib/kernel/ebin/inet6_udp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_config.beam b/bootstrap/lib/kernel/ebin/inet_config.beam
index b3061fffa1..fc1e2c8387 100644
--- a/bootstrap/lib/kernel/ebin/inet_config.beam
+++ b/bootstrap/lib/kernel/ebin/inet_config.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_db.beam b/bootstrap/lib/kernel/ebin/inet_db.beam
index 095d624ea7..d2c636d21f 100644
--- a/bootstrap/lib/kernel/ebin/inet_db.beam
+++ b/bootstrap/lib/kernel/ebin/inet_db.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_dns.beam b/bootstrap/lib/kernel/ebin/inet_dns.beam
index cfd46c29da..be1c7c4766 100644
--- a/bootstrap/lib/kernel/ebin/inet_dns.beam
+++ b/bootstrap/lib/kernel/ebin/inet_dns.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_gethost_native.beam b/bootstrap/lib/kernel/ebin/inet_gethost_native.beam
index 0b901a8f27..4bf616ad46 100644
--- a/bootstrap/lib/kernel/ebin/inet_gethost_native.beam
+++ b/bootstrap/lib/kernel/ebin/inet_gethost_native.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_hosts.beam b/bootstrap/lib/kernel/ebin/inet_hosts.beam
index 03a48175dd..c73b477683 100644
--- a/bootstrap/lib/kernel/ebin/inet_hosts.beam
+++ b/bootstrap/lib/kernel/ebin/inet_hosts.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_parse.beam b/bootstrap/lib/kernel/ebin/inet_parse.beam
index 5afff695e5..14ca272933 100644
--- a/bootstrap/lib/kernel/ebin/inet_parse.beam
+++ b/bootstrap/lib/kernel/ebin/inet_parse.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_res.beam b/bootstrap/lib/kernel/ebin/inet_res.beam
index 61fe96d055..9e8e9fa4de 100644
--- a/bootstrap/lib/kernel/ebin/inet_res.beam
+++ b/bootstrap/lib/kernel/ebin/inet_res.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_sctp.beam b/bootstrap/lib/kernel/ebin/inet_sctp.beam
index bfd6b4b252..063e17f388 100644
--- a/bootstrap/lib/kernel/ebin/inet_sctp.beam
+++ b/bootstrap/lib/kernel/ebin/inet_sctp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_tcp.beam b/bootstrap/lib/kernel/ebin/inet_tcp.beam
index 59abaedf6e..d16795f44d 100644
--- a/bootstrap/lib/kernel/ebin/inet_tcp.beam
+++ b/bootstrap/lib/kernel/ebin/inet_tcp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_tcp_dist.beam b/bootstrap/lib/kernel/ebin/inet_tcp_dist.beam
index 6c98977be5..22f2db4182 100644
--- a/bootstrap/lib/kernel/ebin/inet_tcp_dist.beam
+++ b/bootstrap/lib/kernel/ebin/inet_tcp_dist.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_udp.beam b/bootstrap/lib/kernel/ebin/inet_udp.beam
index 7bd4848f07..917e3da3a7 100644
--- a/bootstrap/lib/kernel/ebin/inet_udp.beam
+++ b/bootstrap/lib/kernel/ebin/inet_udp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/kernel.app b/bootstrap/lib/kernel/ebin/kernel.app
deleted file mode 100644
index 9b5bff5033..0000000000
--- a/bootstrap/lib/kernel/ebin/kernel.app
+++ /dev/null
@@ -1,120 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%% This is an -*- erlang -*- file.
-%%
-{application, kernel,
- [
- {description, "ERTS CXC 138 10"},
- {vsn, "2.14.4"},
- {modules, [application,
- application_controller,
- application_master,
- application_starter,
- auth,
- code,
- packages,
- code_server,
- dist_util,
- erl_boot_server,
- erl_distribution,
- erl_reply,
- error_handler,
- error_logger,
- file,
- file_server,
- file_io_server,
- global,
- global_group,
- global_search,
- group,
- heart,
- hipe_unified_loader,
- inet6_tcp,
- inet6_tcp_dist,
- inet6_udp,
- inet6_sctp,
- inet_config,
- inet_hosts,
- inet_gethost_native,
- inet_tcp_dist,
- kernel,
- kernel_config,
- net,
- net_adm,
- net_kernel,
- os,
- ram_file,
- rpc,
- user,
- user_drv,
- user_sup,
- disk_log,
- disk_log_1,
- disk_log_server,
- disk_log_sup,
- dist_ac,
- erl_ddll,
- erl_epmd,
- erts_debug,
- gen_tcp,
- gen_udp,
- gen_sctp,
- inet,
- inet_db,
- inet_dns,
- inet_parse,
- inet_res,
- inet_tcp,
- inet_udp,
- inet_sctp,
- pg2,
- seq_trace,
- standard_error,
- wrap_log_reader]},
- {registered, [application_controller,
- erl_reply,
- auth,
- boot_server,
- code_server,
- disk_log_server,
- disk_log_sup,
- erl_prim_loader,
- error_logger,
- file_server_2,
- fixtable_server,
- global_group,
- global_name_server,
- heart,
- init,
- kernel_config,
- kernel_sup,
- net_kernel,
- net_sup,
- rex,
- user,
- os_server,
- ddll_server,
- erl_epmd,
- inet_db,
- pg2]},
- {applications, []},
- {env, [{error_logger, tty}]},
- {mod, {kernel, []}}
- ]
-}.
diff --git a/bootstrap/lib/kernel/ebin/kernel.appup b/bootstrap/lib/kernel/ebin/kernel.appup
deleted file mode 100644
index f287e992f1..0000000000
--- a/bootstrap/lib/kernel/ebin/kernel.appup
+++ /dev/null
@@ -1 +0,0 @@
-{"2.14.3",[],[]}.
diff --git a/bootstrap/lib/kernel/ebin/kernel.beam b/bootstrap/lib/kernel/ebin/kernel.beam
index e1db5986dc..8321a999c1 100644
--- a/bootstrap/lib/kernel/ebin/kernel.beam
+++ b/bootstrap/lib/kernel/ebin/kernel.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/kernel_config.beam b/bootstrap/lib/kernel/ebin/kernel_config.beam
index da5fa04de5..c5a63b6217 100644
--- a/bootstrap/lib/kernel/ebin/kernel_config.beam
+++ b/bootstrap/lib/kernel/ebin/kernel_config.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/net.beam b/bootstrap/lib/kernel/ebin/net.beam
index 21df570be5..ae7db397e1 100644
--- a/bootstrap/lib/kernel/ebin/net.beam
+++ b/bootstrap/lib/kernel/ebin/net.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/net_adm.beam b/bootstrap/lib/kernel/ebin/net_adm.beam
index 21d54cac85..182c2cd0fc 100644
--- a/bootstrap/lib/kernel/ebin/net_adm.beam
+++ b/bootstrap/lib/kernel/ebin/net_adm.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/net_kernel.beam b/bootstrap/lib/kernel/ebin/net_kernel.beam
index b53dd9295a..451d054667 100644
--- a/bootstrap/lib/kernel/ebin/net_kernel.beam
+++ b/bootstrap/lib/kernel/ebin/net_kernel.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/os.beam b/bootstrap/lib/kernel/ebin/os.beam
index de55c53503..1291f1cdfa 100644
--- a/bootstrap/lib/kernel/ebin/os.beam
+++ b/bootstrap/lib/kernel/ebin/os.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/packages.beam b/bootstrap/lib/kernel/ebin/packages.beam
index cbe6bc6590..511c6a6e74 100644
--- a/bootstrap/lib/kernel/ebin/packages.beam
+++ b/bootstrap/lib/kernel/ebin/packages.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/pg2.beam b/bootstrap/lib/kernel/ebin/pg2.beam
index a669e64bea..439bbc24f2 100644
--- a/bootstrap/lib/kernel/ebin/pg2.beam
+++ b/bootstrap/lib/kernel/ebin/pg2.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/ram_file.beam b/bootstrap/lib/kernel/ebin/ram_file.beam
index 402c7ea2d3..02baece827 100644
--- a/bootstrap/lib/kernel/ebin/ram_file.beam
+++ b/bootstrap/lib/kernel/ebin/ram_file.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/rpc.beam b/bootstrap/lib/kernel/ebin/rpc.beam
index 38ae0f4694..4355f300e9 100644
--- a/bootstrap/lib/kernel/ebin/rpc.beam
+++ b/bootstrap/lib/kernel/ebin/rpc.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/seq_trace.beam b/bootstrap/lib/kernel/ebin/seq_trace.beam
index ce4f50c6f3..ceb4e14324 100644
--- a/bootstrap/lib/kernel/ebin/seq_trace.beam
+++ b/bootstrap/lib/kernel/ebin/seq_trace.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/standard_error.beam b/bootstrap/lib/kernel/ebin/standard_error.beam
index 62ab951bff..f34c1a9bd1 100644
--- a/bootstrap/lib/kernel/ebin/standard_error.beam
+++ b/bootstrap/lib/kernel/ebin/standard_error.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/user.beam b/bootstrap/lib/kernel/ebin/user.beam
index 76e9973a93..6433bcf859 100644
--- a/bootstrap/lib/kernel/ebin/user.beam
+++ b/bootstrap/lib/kernel/ebin/user.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/user_drv.beam b/bootstrap/lib/kernel/ebin/user_drv.beam
index ddb0442f28..15b09a5f93 100644
--- a/bootstrap/lib/kernel/ebin/user_drv.beam
+++ b/bootstrap/lib/kernel/ebin/user_drv.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/user_sup.beam b/bootstrap/lib/kernel/ebin/user_sup.beam
index 5632210843..b68c8979ff 100644
--- a/bootstrap/lib/kernel/ebin/user_sup.beam
+++ b/bootstrap/lib/kernel/ebin/user_sup.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/wrap_log_reader.beam b/bootstrap/lib/kernel/ebin/wrap_log_reader.beam
index 9f648c9a42..1af9de5e72 100644
--- a/bootstrap/lib/kernel/ebin/wrap_log_reader.beam
+++ b/bootstrap/lib/kernel/ebin/wrap_log_reader.beam
Binary files differ
diff --git a/lib/kernel/src/dist.hrl b/bootstrap/lib/kernel/include/dist.hrl
index aea1ab81ba..aea1ab81ba 100644
--- a/lib/kernel/src/dist.hrl
+++ b/bootstrap/lib/kernel/include/dist.hrl
diff --git a/lib/kernel/src/dist_util.hrl b/bootstrap/lib/kernel/include/dist_util.hrl
index f2b0598532..f2b0598532 100644
--- a/lib/kernel/src/dist_util.hrl
+++ b/bootstrap/lib/kernel/include/dist_util.hrl
diff --git a/bootstrap/lib/kernel/include/inet_sctp.hrl b/bootstrap/lib/kernel/include/inet_sctp.hrl
index 3c072cc1db..169ba013aa 100644
--- a/bootstrap/lib/kernel/include/inet_sctp.hrl
+++ b/bootstrap/lib/kernel/include/inet_sctp.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/kernel/src/net_address.hrl b/bootstrap/lib/kernel/include/net_address.hrl
index 5342076507..5342076507 100644
--- a/lib/kernel/src/net_address.hrl
+++ b/bootstrap/lib/kernel/include/net_address.hrl
diff --git a/bootstrap/lib/orber/include/Makefile b/bootstrap/lib/orber/include/Makefile
deleted file mode 100644
index 5aaeed1015..0000000000
--- a/bootstrap/lib/orber/include/Makefile
+++ /dev/null
@@ -1,66 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1998-2011. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(ORBER_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/orber-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-EXTERNAL_HRL_FILES= ../include/corba.hrl \
- ../include/ifr_types.hrl \
- ../include/orber_pi.hrl
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-debug opt clean docs:
-
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-
-release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(EXTERNAL_HRL_FILES) $(RELSYSDIR)/include
-
-
-release_docs_spec:
-
-
diff --git a/bootstrap/lib/orber/include/corba.hrl b/bootstrap/lib/orber/include/corba.hrl
deleted file mode 100644
index 526662d59d..0000000000
--- a/bootstrap/lib/orber/include/corba.hrl
+++ /dev/null
@@ -1,148 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%------------------------------------------------------------
-%% File: corba.hrl
-%%
-%% Description:
-%% Standard header file for the Orber Erlang CORBA environment
-%%
-%%-----------------------------------------------------------------
--ifndef(corba_hrl).
--define(corba_hrl, true).
-
-%%
-%% Implementation repository record (not used and can therefor be changed)
-%%
--record(orb_ImplDef, {node, module, typename, start=start, args=[[]], pid}).
-
-%%
-%% Any record
-%%
--record(any, {typecode, value}).
-
-%%
-%% Any record
-%%
--record(fixed, {digits, scale, value}).
-
-%%
-%% Service context record
-%%
--record('IOP_ServiceContext', {context_id, context_data}).
-
-%%
-%% Exception recod for the resolve initial reference functions
-%%
--record('InvalidName', {'OE_ID'="IDL:omg.org/CORBA/ORB/InvalidName:1.0"}).
-
-%% Orber OMG assigned TAG's
-%% Service Context IDs 0x45524904 - 0x45524907 ("ERI\x04" - "ERI\x07")
-%% Component IDs 0x45524904 - 0x45524907 ("ERI\x04" - "ERI\x07")
-%% ORB type IDs 0x45524904 - 0x45524907 ("ERI\x04" - "ERI\x07")
--define(ORBER_ORB_TYPE_1, 16#45524904).
-%-define(ORBER_ORB_TYPE_2, 16#45524905).
-%-define(ORBER_ORB_TYPE_3, 16#45524906).
-%-define(ORBER_ORB_TYPE_4, 16#45524907).
-
-%-define(ORBER_COMPONENT_1, 16#45524904).
-%-define(ORBER_COMPONENT_2, 16#45524905).
-%-define(ORBER_COMPONENT_3, 16#45524906).
-%-define(ORBER_COMPONENT_4, 16#45524907).
-
--define(ORBER_GENERIC_CTX_ID, 16#45524904).
-%-define(ORBER_SERVICE_CTX_2, 16#45524905).
-%-define(ORBER_SERVICE_CTX_3, 16#45524906).
-%-define(ORBER_SERVICE_CTX_4, 16#45524907).
-
-%%
-%% System exceptions
-%%
-
-%% VMCID
-%% VMCID base assigned to OMG
--define(CORBA_OMGVMCID, 16#4f4d0000).
-
-%% Orber's VMCID base - "ER\x00\x00" - "ER\x0f\xff".
-%% Range 16#45520000 -> 16#45520fff
--define(ORBER_VMCID, 16#45520000).
-
-%% Some other Vendors VMCID bases.
--define(IONA_VMCID_1, 16#4f4f0000).
--define(IONA_VMCID_2, 16#49540000).
--define(SUN_VMCID, 16#53550000).
--define(BORLAND_VMCID, 16#56420000).
--define(TAO_VMCID, 16#54410000).
--define(PRISMTECH_VMCID,16#50540000).
-
--define(ex_body, {'OE_ID'="", minor=?ORBER_VMCID, completion_status}).
-
--record('UNKNOWN', ?ex_body).
--record('BAD_PARAM', ?ex_body).
--record('NO_MEMORY', ?ex_body).
--record('IMP_LIMIT', ?ex_body).
--record('COMM_FAILURE', ?ex_body).
--record('INV_OBJREF', ?ex_body).
--record('NO_PERMISSION', ?ex_body).
--record('INTERNAL', ?ex_body).
--record('MARSHAL', ?ex_body).
--record('INITIALIZE', ?ex_body).
--record('NO_IMPLEMENT', ?ex_body).
--record('BAD_TYPECODE', ?ex_body).
--record('BAD_OPERATION', ?ex_body).
--record('NO_RESOURCES', ?ex_body).
--record('NO_RESPONSE', ?ex_body).
--record('PERSIST_STORE', ?ex_body).
--record('BAD_INV_ORDER', ?ex_body).
--record('TRANSIENT', ?ex_body).
--record('FREE_MEM', ?ex_body).
--record('INV_IDENT', ?ex_body).
--record('INV_FLAG', ?ex_body).
--record('INTF_REPOS', ?ex_body).
--record('BAD_CONTEXT', ?ex_body).
--record('OBJ_ADAPTER', ?ex_body).
--record('DATA_CONVERSION', ?ex_body).
--record('OBJECT_NOT_EXIST', ?ex_body).
--record('TRANSACTION_REQUIRED', ?ex_body).
--record('TRANSACTION_ROLLEDBACK', ?ex_body).
--record('INVALID_TRANSACTION', ?ex_body).
--record('INV_POLICY', ?ex_body).
--record('CODESET_INCOMPATIBLE', ?ex_body).
--record('REBIND', ?ex_body).
--record('TIMEOUT', ?ex_body).
--record('TRANSACTION_UNAVAILABLE', ?ex_body).
--record('TRANSACTION_MODE', ?ex_body).
--record('BAD_QOS', ?ex_body).
-
-%% Defines for the enum exception_type (is also used for reply_status)
--define(NO_EXCEPTION, 'no_exception').
--define(USER_EXCEPTION, 'user_exception').
--define(SYSTEM_EXCEPTION, 'system_exception').
-
-%% Defines for the enum completion_status.
--define(COMPLETED_YES, 'COMPLETED_YES').
--define(COMPLETED_NO, 'COMPLETED_NO').
--define(COMPLETED_MAYBE, 'COMPLETED_MAYBE').
-
-
--undef(ex_body).
-
-
--endif.
diff --git a/bootstrap/lib/orber/include/ifr_types.hrl b/bootstrap/lib/orber/include/ifr_types.hrl
deleted file mode 100644
index 324b32bd4f..0000000000
--- a/bootstrap/lib/orber/include/ifr_types.hrl
+++ /dev/null
@@ -1,72 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : ifr_types.hrl
-%% Purpose : Record definitions for structs used in the interface repository
-%%----------------------------------------------------------------------
-
-
-%%%----------------------------------------------------------------------
-%%% *********************************************************************
-%%% * *
-%%% * PLEASE NOTE *
-%%% * *
-%%% * If a record is removed or added in this file, select/2 in *
-%%% * orber_ifr.erl _MUST_ be updated accordingly. *
-%%% * *
-%%% *********************************************************************
-%%%----------------------------------------------------------------------
-
--record(contained_description, {kind, value}).
-
--record(structmember, {name, type, type_def}).
-
--record(unionmember, {name, label, type, type_def}).
-
--record(container_description, {contained_object, kind, value}).
-
--record(moduledescription, {name, id, defined_in, version}).
-
--record(constantdescription, {name, id, defined_in, version, type, value}).
-
--record(typedescription, {name, id, defined_in, version, type}).
-
--define(make_typedescription(Obj,Object_type),
- #typedescription{name = Obj#Object_type.name,
- id = Obj#Object_type.id,
- defined_in = Obj#Object_type.defined_in,
- version = Obj#Object_type.version,
- type = Obj#Object_type.type}).
-
--record(exceptiondescription, {name, id, defined_in, version, type}).
-
--record(attributedescription, {name, id, defined_in, version, type, mode}).
-
--record(parameterdescription, {name, type, type_def, mode}).
-
--record(operationdescription, {name, id, defined_in, version, result, mode,
- contexts, parameters, exceptions}).
-
--record(fullinterfacedescription, {name, id, defined_in, version, operations,
- attributes, base_interfaces, type}).
-
--record(interfacedescription, {name, id, defined_in, version,
- base_interfaces}).
diff --git a/bootstrap/lib/orber/include/orber_pi.hrl b/bootstrap/lib/orber/include/orber_pi.hrl
deleted file mode 100644
index 69f14a5165..0000000000
--- a/bootstrap/lib/orber/include/orber_pi.hrl
+++ /dev/null
@@ -1,76 +0,0 @@
-%%----------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_pi.hrl
-%% Purpose :
-%%----------------------------------------------------------------------
-
-%%=============== CONSTANTS ==================================
-%%-------- PortableInterceptor::Interceptor (local) ----------
-%% Reply Status
--define('PortableInterceptor_SUCCESSFUL', 0).
--define('PortableInterceptor_SYSTEM_EXCEPTION', 1).
--define('PortableInterceptor_USER_EXCEPTION', 2).
--define('PortableInterceptor_LOCATION_FORWARD', 3).
--define('PortableInterceptor_LOCATION_FORWARD_PERMANENT', 4).
--define('PortableInterceptor_TRANSPORT_RETRY', 5).
-
-
-%%=============== EXCEPTIONS =================================
-%%-------- PortableInterceptor::Interceptor (local) ----------
-%% forward eq. CORBA::Object, premanent eq. boolean
--record('PortableInterceptor_ForwardRequest', {'OE_ID'="local", forward, permanent}).
--record('PortableInterceptor_InvalidSlot', {'OE_ID'="local"}).
-
-%%--------------- IOP_N::Codec (local) -----------------------
--record('IOP_N_Codec_InvalidTypeForEncoding', {'OE_ID'="local"}).
--record('IOP_N_Codec_FormatMismatch', {'OE_ID'="local"}).
--record('IOP_N_Codec_TypeMismatch', {'OE_ID'="local"}).
-
-%%--------------- IOP_N (Module level) -----------------------
--define('IOP_N_ENCODING_CDR_ENCAPS', 0).
-
-%%--------------- IOP_N::CodecFactory (Module level) ---------
--record('IOP_N_CodecFactory_UnknownEncoding', {'OE_ID'="local"}).
-
-%%--------------- IOP_N::ORBInitInfo (Module level) ----------
-%% name eq. string()
--record('PortableInterceptor_ORBInitInfo_DuplicateName', {'OE_ID'="local", name}).
--record('PortableInterceptor_ORBInitInfo_InvalidName', {'OE_ID'="local"}).
-
-
-%%=============== DATA STRUCTURES ============================
-%%--------------- IOP_N (Module level) -----------------------
--record('IOP_N_Encoding',
- {format, %% Currently only 'IOP_N_ENCODING_CDR_ENCAPS' allowed.
- major_version, %% 1 only
- minor_version}). %% 0,1 or 2
-
-
-%%--------------- Dynamic (Module level) ---------------------
-%% argument eq. #any{},
-%% mode eq. CORBA::ParameterMode - PARAM_IN, PARAM_OUT, PARAM_INOUT.
--record('Dynamic_Parameter',
- {argument,
- mode}).
-
-%%--------------- END OF MODULE ------------------------------
-
diff --git a/bootstrap/lib/stdlib/ebin/array.beam b/bootstrap/lib/stdlib/ebin/array.beam
index 5e309a9842..8741e4d5df 100644
--- a/bootstrap/lib/stdlib/ebin/array.beam
+++ b/bootstrap/lib/stdlib/ebin/array.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/base64.beam b/bootstrap/lib/stdlib/ebin/base64.beam
index 3d429d9de0..04a1388637 100644
--- a/bootstrap/lib/stdlib/ebin/base64.beam
+++ b/bootstrap/lib/stdlib/ebin/base64.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/beam_lib.beam b/bootstrap/lib/stdlib/ebin/beam_lib.beam
index d29c13189a..b1f5baf3b8 100644
--- a/bootstrap/lib/stdlib/ebin/beam_lib.beam
+++ b/bootstrap/lib/stdlib/ebin/beam_lib.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/binary.beam b/bootstrap/lib/stdlib/ebin/binary.beam
index 5180c122d2..0cc6c6fce9 100644
--- a/bootstrap/lib/stdlib/ebin/binary.beam
+++ b/bootstrap/lib/stdlib/ebin/binary.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/c.beam b/bootstrap/lib/stdlib/ebin/c.beam
index 7a31c9bfef..8c69197cbc 100644
--- a/bootstrap/lib/stdlib/ebin/c.beam
+++ b/bootstrap/lib/stdlib/ebin/c.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/calendar.beam b/bootstrap/lib/stdlib/ebin/calendar.beam
index 09cd444a79..3f4f14abc3 100644
--- a/bootstrap/lib/stdlib/ebin/calendar.beam
+++ b/bootstrap/lib/stdlib/ebin/calendar.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets.beam b/bootstrap/lib/stdlib/ebin/dets.beam
index 002b3c9229..47cc5e70bb 100644
--- a/bootstrap/lib/stdlib/ebin/dets.beam
+++ b/bootstrap/lib/stdlib/ebin/dets.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets_server.beam b/bootstrap/lib/stdlib/ebin/dets_server.beam
index 5978a933ed..d71185c9dd 100644
--- a/bootstrap/lib/stdlib/ebin/dets_server.beam
+++ b/bootstrap/lib/stdlib/ebin/dets_server.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets_sup.beam b/bootstrap/lib/stdlib/ebin/dets_sup.beam
index 9bc79d6468..35b8c8a799 100644
--- a/bootstrap/lib/stdlib/ebin/dets_sup.beam
+++ b/bootstrap/lib/stdlib/ebin/dets_sup.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets_utils.beam b/bootstrap/lib/stdlib/ebin/dets_utils.beam
index 817ded2d62..a372faf6ac 100644
--- a/bootstrap/lib/stdlib/ebin/dets_utils.beam
+++ b/bootstrap/lib/stdlib/ebin/dets_utils.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets_v8.beam b/bootstrap/lib/stdlib/ebin/dets_v8.beam
index 968b9bcb28..a20f0469ce 100644
--- a/bootstrap/lib/stdlib/ebin/dets_v8.beam
+++ b/bootstrap/lib/stdlib/ebin/dets_v8.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets_v9.beam b/bootstrap/lib/stdlib/ebin/dets_v9.beam
index 355c5819cf..a52d126adf 100644
--- a/bootstrap/lib/stdlib/ebin/dets_v9.beam
+++ b/bootstrap/lib/stdlib/ebin/dets_v9.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dict.beam b/bootstrap/lib/stdlib/ebin/dict.beam
index 9b65b345ff..35e67d6c59 100644
--- a/bootstrap/lib/stdlib/ebin/dict.beam
+++ b/bootstrap/lib/stdlib/ebin/dict.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/digraph.beam b/bootstrap/lib/stdlib/ebin/digraph.beam
index 79c25f5a30..2c1788668d 100644
--- a/bootstrap/lib/stdlib/ebin/digraph.beam
+++ b/bootstrap/lib/stdlib/ebin/digraph.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/digraph_utils.beam b/bootstrap/lib/stdlib/ebin/digraph_utils.beam
index 18ebd2e30c..a578c67e00 100644
--- a/bootstrap/lib/stdlib/ebin/digraph_utils.beam
+++ b/bootstrap/lib/stdlib/ebin/digraph_utils.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/edlin.beam b/bootstrap/lib/stdlib/ebin/edlin.beam
index 9fc93d042c..874bc4e107 100644
--- a/bootstrap/lib/stdlib/ebin/edlin.beam
+++ b/bootstrap/lib/stdlib/ebin/edlin.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/edlin_expand.beam b/bootstrap/lib/stdlib/ebin/edlin_expand.beam
index 0ca05e1bc3..04177ed645 100644
--- a/bootstrap/lib/stdlib/ebin/edlin_expand.beam
+++ b/bootstrap/lib/stdlib/ebin/edlin_expand.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/epp.beam b/bootstrap/lib/stdlib/ebin/epp.beam
index 528692fb81..0cc31bcac9 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_bits.beam b/bootstrap/lib/stdlib/ebin/erl_bits.beam
index d338fe3778..595be6a76a 100644
--- a/bootstrap/lib/stdlib/ebin/erl_bits.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_bits.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_compile.beam b/bootstrap/lib/stdlib/ebin/erl_compile.beam
index 18693b47a3..1ce1d02ef0 100644
--- a/bootstrap/lib/stdlib/ebin/erl_compile.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_compile.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_eval.beam b/bootstrap/lib/stdlib/ebin/erl_eval.beam
index 184918e97d..3184aabc87 100644
--- a/bootstrap/lib/stdlib/ebin/erl_eval.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_eval.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_expand_records.beam b/bootstrap/lib/stdlib/ebin/erl_expand_records.beam
index e292c379b0..c5c1d71941 100644
--- a/bootstrap/lib/stdlib/ebin/erl_expand_records.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_expand_records.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_internal.beam b/bootstrap/lib/stdlib/ebin/erl_internal.beam
index 8d080bdacc..07e7f2a377 100644
--- a/bootstrap/lib/stdlib/ebin/erl_internal.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_internal.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_lint.beam b/bootstrap/lib/stdlib/ebin/erl_lint.beam
index 552c418ee8..7b1eaf1f15 100644
--- a/bootstrap/lib/stdlib/ebin/erl_lint.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_lint.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_parse.beam b/bootstrap/lib/stdlib/ebin/erl_parse.beam
index 27e760de1f..c026e8401f 100644
--- a/bootstrap/lib/stdlib/ebin/erl_parse.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_parse.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_posix_msg.beam b/bootstrap/lib/stdlib/ebin/erl_posix_msg.beam
index 7d934adb92..48f3d58dbb 100644
--- a/bootstrap/lib/stdlib/ebin/erl_posix_msg.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_posix_msg.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_pp.beam b/bootstrap/lib/stdlib/ebin/erl_pp.beam
index 9dbed0af01..2c32b68322 100644
--- a/bootstrap/lib/stdlib/ebin/erl_pp.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_pp.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_scan.beam b/bootstrap/lib/stdlib/ebin/erl_scan.beam
index 51082779b8..b5e7c1c24e 100644
--- a/bootstrap/lib/stdlib/ebin/erl_scan.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_scan.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_tar.beam b/bootstrap/lib/stdlib/ebin/erl_tar.beam
index 7cf0571935..9de0e978e3 100644
--- a/bootstrap/lib/stdlib/ebin/erl_tar.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_tar.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/error_logger_file_h.beam b/bootstrap/lib/stdlib/ebin/error_logger_file_h.beam
index 13a91def18..f5609d124c 100644
--- a/bootstrap/lib/stdlib/ebin/error_logger_file_h.beam
+++ b/bootstrap/lib/stdlib/ebin/error_logger_file_h.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/error_logger_tty_h.beam b/bootstrap/lib/stdlib/ebin/error_logger_tty_h.beam
index 50dd448b1b..886bba634c 100644
--- a/bootstrap/lib/stdlib/ebin/error_logger_tty_h.beam
+++ b/bootstrap/lib/stdlib/ebin/error_logger_tty_h.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/escript.beam b/bootstrap/lib/stdlib/ebin/escript.beam
index a76250e466..18066abf53 100644
--- a/bootstrap/lib/stdlib/ebin/escript.beam
+++ b/bootstrap/lib/stdlib/ebin/escript.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/ets.beam b/bootstrap/lib/stdlib/ebin/ets.beam
index 1e0742e341..8bc5103946 100644
--- a/bootstrap/lib/stdlib/ebin/ets.beam
+++ b/bootstrap/lib/stdlib/ebin/ets.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/eval_bits.beam b/bootstrap/lib/stdlib/ebin/eval_bits.beam
index 1db24ccfc9..ac375672f6 100644
--- a/bootstrap/lib/stdlib/ebin/eval_bits.beam
+++ b/bootstrap/lib/stdlib/ebin/eval_bits.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/file_sorter.beam b/bootstrap/lib/stdlib/ebin/file_sorter.beam
index 281c66b3ee..0c910821f6 100644
--- a/bootstrap/lib/stdlib/ebin/file_sorter.beam
+++ b/bootstrap/lib/stdlib/ebin/file_sorter.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/filelib.beam b/bootstrap/lib/stdlib/ebin/filelib.beam
index 7c1ba41e59..5d8a6f7b07 100644
--- a/bootstrap/lib/stdlib/ebin/filelib.beam
+++ b/bootstrap/lib/stdlib/ebin/filelib.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/filename.beam b/bootstrap/lib/stdlib/ebin/filename.beam
index d8c81df4d9..35031334c4 100644
--- a/bootstrap/lib/stdlib/ebin/filename.beam
+++ b/bootstrap/lib/stdlib/ebin/filename.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/gb_sets.beam b/bootstrap/lib/stdlib/ebin/gb_sets.beam
index 1928430e56..d42fed4c30 100644
--- a/bootstrap/lib/stdlib/ebin/gb_sets.beam
+++ b/bootstrap/lib/stdlib/ebin/gb_sets.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/gb_trees.beam b/bootstrap/lib/stdlib/ebin/gb_trees.beam
index 7bebf1a54e..bbe958dc66 100644
--- a/bootstrap/lib/stdlib/ebin/gb_trees.beam
+++ b/bootstrap/lib/stdlib/ebin/gb_trees.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/gen.beam b/bootstrap/lib/stdlib/ebin/gen.beam
index 71733a69cf..806515e2e0 100644
--- a/bootstrap/lib/stdlib/ebin/gen.beam
+++ b/bootstrap/lib/stdlib/ebin/gen.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/gen_event.beam b/bootstrap/lib/stdlib/ebin/gen_event.beam
index 321d3e7733..95188a534a 100644
--- a/bootstrap/lib/stdlib/ebin/gen_event.beam
+++ b/bootstrap/lib/stdlib/ebin/gen_event.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/gen_fsm.beam b/bootstrap/lib/stdlib/ebin/gen_fsm.beam
index 3467b05cd6..5ee3a82cb6 100644
--- a/bootstrap/lib/stdlib/ebin/gen_fsm.beam
+++ b/bootstrap/lib/stdlib/ebin/gen_fsm.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/gen_server.beam b/bootstrap/lib/stdlib/ebin/gen_server.beam
index 8354aabd1c..e37fa78649 100644
--- a/bootstrap/lib/stdlib/ebin/gen_server.beam
+++ b/bootstrap/lib/stdlib/ebin/gen_server.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/io.beam b/bootstrap/lib/stdlib/ebin/io.beam
index 7af592caa0..0a2ae3490c 100644
--- a/bootstrap/lib/stdlib/ebin/io.beam
+++ b/bootstrap/lib/stdlib/ebin/io.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/io_lib.beam b/bootstrap/lib/stdlib/ebin/io_lib.beam
index c0af612d77..07cefba99e 100644
--- a/bootstrap/lib/stdlib/ebin/io_lib.beam
+++ b/bootstrap/lib/stdlib/ebin/io_lib.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/io_lib_format.beam b/bootstrap/lib/stdlib/ebin/io_lib_format.beam
index cfebe1597a..5fb023c5e1 100644
--- a/bootstrap/lib/stdlib/ebin/io_lib_format.beam
+++ b/bootstrap/lib/stdlib/ebin/io_lib_format.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/io_lib_fread.beam b/bootstrap/lib/stdlib/ebin/io_lib_fread.beam
index bebe0a6c75..5ecd664026 100644
--- a/bootstrap/lib/stdlib/ebin/io_lib_fread.beam
+++ b/bootstrap/lib/stdlib/ebin/io_lib_fread.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/io_lib_pretty.beam b/bootstrap/lib/stdlib/ebin/io_lib_pretty.beam
index 9a8b68c6e0..f7a239e18c 100644
--- a/bootstrap/lib/stdlib/ebin/io_lib_pretty.beam
+++ b/bootstrap/lib/stdlib/ebin/io_lib_pretty.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/lib.beam b/bootstrap/lib/stdlib/ebin/lib.beam
index 07740547ed..5d44d3f8f1 100644
--- a/bootstrap/lib/stdlib/ebin/lib.beam
+++ b/bootstrap/lib/stdlib/ebin/lib.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/lists.beam b/bootstrap/lib/stdlib/ebin/lists.beam
index fe06dc3b4a..5e23551fb3 100644
--- a/bootstrap/lib/stdlib/ebin/lists.beam
+++ b/bootstrap/lib/stdlib/ebin/lists.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/log_mf_h.beam b/bootstrap/lib/stdlib/ebin/log_mf_h.beam
index 4afaff66d4..fdb417b71e 100644
--- a/bootstrap/lib/stdlib/ebin/log_mf_h.beam
+++ b/bootstrap/lib/stdlib/ebin/log_mf_h.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/math.beam b/bootstrap/lib/stdlib/ebin/math.beam
index 0103016730..e97284ca1e 100644
--- a/bootstrap/lib/stdlib/ebin/math.beam
+++ b/bootstrap/lib/stdlib/ebin/math.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/ms_transform.beam b/bootstrap/lib/stdlib/ebin/ms_transform.beam
index 898ee9861d..1af64e9d63 100644
--- a/bootstrap/lib/stdlib/ebin/ms_transform.beam
+++ b/bootstrap/lib/stdlib/ebin/ms_transform.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/orddict.beam b/bootstrap/lib/stdlib/ebin/orddict.beam
index d6bed77761..6892fd2c9e 100644
--- a/bootstrap/lib/stdlib/ebin/orddict.beam
+++ b/bootstrap/lib/stdlib/ebin/orddict.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/ordsets.beam b/bootstrap/lib/stdlib/ebin/ordsets.beam
index c3f2c3b7b1..6228f1b5d6 100644
--- a/bootstrap/lib/stdlib/ebin/ordsets.beam
+++ b/bootstrap/lib/stdlib/ebin/ordsets.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/otp_internal.beam b/bootstrap/lib/stdlib/ebin/otp_internal.beam
index 2fbda80a5e..f22f936f42 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/pg.beam b/bootstrap/lib/stdlib/ebin/pg.beam
index 026d102a75..0b08fb57ca 100644
--- a/bootstrap/lib/stdlib/ebin/pg.beam
+++ b/bootstrap/lib/stdlib/ebin/pg.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/pool.beam b/bootstrap/lib/stdlib/ebin/pool.beam
index 29e5f83b5e..a16364e1d9 100644
--- a/bootstrap/lib/stdlib/ebin/pool.beam
+++ b/bootstrap/lib/stdlib/ebin/pool.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/proc_lib.beam b/bootstrap/lib/stdlib/ebin/proc_lib.beam
index d2fb37b8ea..6b5c081480 100644
--- a/bootstrap/lib/stdlib/ebin/proc_lib.beam
+++ b/bootstrap/lib/stdlib/ebin/proc_lib.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/proplists.beam b/bootstrap/lib/stdlib/ebin/proplists.beam
index bed96c6b1a..6f0e5d6409 100644
--- a/bootstrap/lib/stdlib/ebin/proplists.beam
+++ b/bootstrap/lib/stdlib/ebin/proplists.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/qlc.beam b/bootstrap/lib/stdlib/ebin/qlc.beam
index e250a375dd..1576557a09 100644
--- a/bootstrap/lib/stdlib/ebin/qlc.beam
+++ b/bootstrap/lib/stdlib/ebin/qlc.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/qlc_pt.beam b/bootstrap/lib/stdlib/ebin/qlc_pt.beam
index d405d8483f..805203b00e 100644
--- a/bootstrap/lib/stdlib/ebin/qlc_pt.beam
+++ b/bootstrap/lib/stdlib/ebin/qlc_pt.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/queue.beam b/bootstrap/lib/stdlib/ebin/queue.beam
index 19d24cfaa6..663b1a49ff 100644
--- a/bootstrap/lib/stdlib/ebin/queue.beam
+++ b/bootstrap/lib/stdlib/ebin/queue.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/random.beam b/bootstrap/lib/stdlib/ebin/random.beam
index 9f2361d586..9df28216b0 100644
--- a/bootstrap/lib/stdlib/ebin/random.beam
+++ b/bootstrap/lib/stdlib/ebin/random.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/re.beam b/bootstrap/lib/stdlib/ebin/re.beam
index da228c5542..85125291e9 100644
--- a/bootstrap/lib/stdlib/ebin/re.beam
+++ b/bootstrap/lib/stdlib/ebin/re.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/regexp.beam b/bootstrap/lib/stdlib/ebin/regexp.beam
index d021c5779b..023f2fb9b2 100644
--- a/bootstrap/lib/stdlib/ebin/regexp.beam
+++ b/bootstrap/lib/stdlib/ebin/regexp.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/sets.beam b/bootstrap/lib/stdlib/ebin/sets.beam
index 5ef47425a0..5ac7691a8f 100644
--- a/bootstrap/lib/stdlib/ebin/sets.beam
+++ b/bootstrap/lib/stdlib/ebin/sets.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/shell.beam b/bootstrap/lib/stdlib/ebin/shell.beam
index a8a03d5f3b..2a853ea58c 100644
--- a/bootstrap/lib/stdlib/ebin/shell.beam
+++ b/bootstrap/lib/stdlib/ebin/shell.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/shell_default.beam b/bootstrap/lib/stdlib/ebin/shell_default.beam
index 57ac5f2046..fa64e33080 100644
--- a/bootstrap/lib/stdlib/ebin/shell_default.beam
+++ b/bootstrap/lib/stdlib/ebin/shell_default.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/slave.beam b/bootstrap/lib/stdlib/ebin/slave.beam
index ceb4f0e60f..dfc8cad9d6 100644
--- a/bootstrap/lib/stdlib/ebin/slave.beam
+++ b/bootstrap/lib/stdlib/ebin/slave.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/sofs.beam b/bootstrap/lib/stdlib/ebin/sofs.beam
index 8cbcfb55de..5d9b1bd6c0 100644
--- a/bootstrap/lib/stdlib/ebin/sofs.beam
+++ b/bootstrap/lib/stdlib/ebin/sofs.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/stdlib.app b/bootstrap/lib/stdlib/ebin/stdlib.app
deleted file mode 100644
index bcce209e27..0000000000
--- a/bootstrap/lib/stdlib/ebin/stdlib.app
+++ /dev/null
@@ -1,106 +0,0 @@
-%% This is an -*- erlang -*- file.
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-{application, stdlib,
- [{description, "ERTS CXC 138 10"},
- {vsn, "1.17.4"},
- {modules, [array,
- base64,
- beam_lib,
- binary,
- c,
- calendar,
- dets,
- dets_server,
- dets_sup,
- dets_utils,
- dets_v8,
- dets_v9,
- dict,
- digraph,
- digraph_utils,
- edlin,
- edlin_expand,
- epp,
- eval_bits,
- erl_bits,
- erl_compile,
- erl_eval,
- erl_expand_records,
- erl_internal,
- erl_lint,
- erl_parse,
- erl_posix_msg,
- erl_pp,
- erl_scan,
- erl_tar,
- error_logger_file_h,
- error_logger_tty_h,
- escript,
- ets,
- file_sorter,
- filelib,
- filename,
- gb_trees,
- gb_sets,
- gen,
- gen_event,
- gen_fsm,
- gen_server,
- io,
- io_lib,
- io_lib_format,
- io_lib_fread,
- io_lib_pretty,
- lib,
- lists,
- log_mf_h,
- math,
- ms_transform,
- orddict,
- ordsets,
- otp_internal,
- pg,
- pool,
- proc_lib,
- proplists,
- qlc,
- qlc_pt,
- queue,
- random,
- re,
- regexp,
- sets,
- shell,
- shell_default,
- slave,
- sofs,
- string,
- supervisor,
- supervisor_bridge,
- sys,
- timer,
- unicode,
- win32reg,
- zip]},
- {registered,[timer_server,rsh_starter,take_over_monitor,pool_master,
- dets]},
- {applications, [kernel]},
- {env, []}]}.
-
diff --git a/bootstrap/lib/stdlib/ebin/stdlib.appup b/bootstrap/lib/stdlib/ebin/stdlib.appup
deleted file mode 100644
index 1b03a40251..0000000000
--- a/bootstrap/lib/stdlib/ebin/stdlib.appup
+++ /dev/null
@@ -1 +0,0 @@
-{"1.17.3",[],[]}.
diff --git a/bootstrap/lib/stdlib/ebin/string.beam b/bootstrap/lib/stdlib/ebin/string.beam
index 0de0b44cb8..5086591504 100644
--- a/bootstrap/lib/stdlib/ebin/string.beam
+++ b/bootstrap/lib/stdlib/ebin/string.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/supervisor.beam b/bootstrap/lib/stdlib/ebin/supervisor.beam
index 4e46676a20..d1fe9e0cf5 100644
--- a/bootstrap/lib/stdlib/ebin/supervisor.beam
+++ b/bootstrap/lib/stdlib/ebin/supervisor.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/supervisor_bridge.beam b/bootstrap/lib/stdlib/ebin/supervisor_bridge.beam
index 686078826d..6480117b9e 100644
--- a/bootstrap/lib/stdlib/ebin/supervisor_bridge.beam
+++ b/bootstrap/lib/stdlib/ebin/supervisor_bridge.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/sys.beam b/bootstrap/lib/stdlib/ebin/sys.beam
index e972bcbd14..724dfed4e6 100644
--- a/bootstrap/lib/stdlib/ebin/sys.beam
+++ b/bootstrap/lib/stdlib/ebin/sys.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/timer.beam b/bootstrap/lib/stdlib/ebin/timer.beam
index 0bfe233ad7..5f8f714a78 100644
--- a/bootstrap/lib/stdlib/ebin/timer.beam
+++ b/bootstrap/lib/stdlib/ebin/timer.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/unicode.beam b/bootstrap/lib/stdlib/ebin/unicode.beam
index 62e348b3a5..b560f13933 100644
--- a/bootstrap/lib/stdlib/ebin/unicode.beam
+++ b/bootstrap/lib/stdlib/ebin/unicode.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/win32reg.beam b/bootstrap/lib/stdlib/ebin/win32reg.beam
index 45b268ebac..9c7893f7ff 100644
--- a/bootstrap/lib/stdlib/ebin/win32reg.beam
+++ b/bootstrap/lib/stdlib/ebin/win32reg.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/zip.beam b/bootstrap/lib/stdlib/ebin/zip.beam
index 74f7c6a208..051c688e73 100644
--- a/bootstrap/lib/stdlib/ebin/zip.beam
+++ b/bootstrap/lib/stdlib/ebin/zip.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/egen/erl_parse.erl b/bootstrap/lib/stdlib/egen/erl_parse.erl
deleted file mode 100644
index 97952dcb46..0000000000
--- a/bootstrap/lib/stdlib/egen/erl_parse.erl
+++ /dev/null
@@ -1,9680 +0,0 @@
--module(erl_parse).
--export([parse/1, parse_and_scan/1, format_error/1]).
--file("erl_parse.yrl", 502).
-
--export([parse_form/1,parse_exprs/1,parse_term/1]).
--export([normalise/1,abstract/1,tokens/1,tokens/2]).
--export([abstract/2, package_segments/1]).
--export([inop_prec/1,preop_prec/1,func_prec/0,max_prec/0]).
--export([set_line/2,get_attribute/2,get_attributes/1]).
-
-%% The following directive is needed for (significantly) faster compilation
-%% of the generated .erl file by the HiPE compiler. Please do not remove.
--compile([{hipe,[{regalloc,linear_scan}]}]).
-
--export_type([abstract_clause/0, abstract_expr/0, abstract_form/0,
- error_info/0]).
-
--type abstract_clause() :: term().
--type abstract_expr() :: term().
--type abstract_form() :: term().
--type error_description() :: term().
--type error_info() :: {erl_scan:line(), module(), error_description()}.
--type token() :: {Tag :: atom(), Line :: erl_scan:line()}.
-
-%% mkop(Op, Arg) -> {op,Line,Op,Arg}.
-%% mkop(Left, Op, Right) -> {op,Line,Op,Left,Right}.
-
--define(mkop2(L, OpPos, R),
- begin
- {Op,Pos} = OpPos,
- {op,Pos,Op,L,R}
- end).
-
--define(mkop1(OpPos, A),
- begin
- {Op,Pos} = OpPos,
- {op,Pos,Op,A}
- end).
-
-%% keep track of line info in tokens
--define(line(Tup), element(2, Tup)).
-
-%% Entry points compatible to old erl_parse.
-%% These really suck and are only here until Calle gets multiple
-%% entry points working.
-
--spec parse_form(Tokens) -> {ok, AbsForm} | {error, ErrorInfo} when
- Tokens :: [token()],
- AbsForm :: abstract_form(),
- ErrorInfo :: error_info().
-parse_form([{'-',L1},{atom,L2,spec}|Tokens]) ->
- parse([{'-',L1},{'spec',L2}|Tokens]);
-parse_form(Tokens) ->
- parse(Tokens).
-
--spec parse_exprs(Tokens) -> {ok, ExprList} | {error, ErrorInfo} when
- Tokens :: [token()],
- ExprList :: [abstract_expr()],
- ErrorInfo :: error_info().
-parse_exprs(Tokens) ->
- case parse([{atom,0,f},{'(',0},{')',0},{'->',0}|Tokens]) of
- {ok,{function,_Lf,f,0,[{clause,_Lc,[],[],Exprs}]}} ->
- {ok,Exprs};
- {error,_} = Err -> Err
- end.
-
--spec parse_term(Tokens) -> {ok, Term} | {error, ErrorInfo} when
- Tokens :: [token()],
- Term :: term(),
- ErrorInfo :: error_info().
-parse_term(Tokens) ->
- case parse([{atom,0,f},{'(',0},{')',0},{'->',0}|Tokens]) of
- {ok,{function,_Lf,f,0,[{clause,_Lc,[],[],[Expr]}]}} ->
- try normalise(Expr) of
- Term -> {ok,Term}
- catch
- _:_R -> {error,{?line(Expr),?MODULE,"bad term"}}
- end;
- {ok,{function,_Lf,f,0,[{clause,_Lc,[],[],[_E1,E2|_Es]}]}} ->
- {error,{?line(E2),?MODULE,"bad term"}};
- {error,_} = Err -> Err
- end.
-
--type attributes() :: 'export' | 'file' | 'import' | 'module'
- | 'opaque' | 'record' | 'type'.
-
-build_typed_attribute({atom,La,record},
- {typed_record, {atom,_Ln,RecordName}, RecTuple}) ->
- {attribute,La,record,{RecordName,record_tuple(RecTuple)}};
-build_typed_attribute({atom,La,Attr},
- {type_def, {call,_,{atom,_,TypeName},Args}, Type})
- when Attr =:= 'type' ; Attr =:= 'opaque' ->
- case lists:all(fun({var, _, _}) -> true;
- (_) -> false
- end, Args) of
- true -> {attribute,La,Attr,{TypeName,Type,Args}};
- false -> error_bad_decl(La, Attr)
- end;
-build_typed_attribute({atom,La,Attr},_) ->
- case Attr of
- record -> error_bad_decl(La, record);
- type -> error_bad_decl(La, type);
- opaque -> error_bad_decl(La, opaque);
- _ -> ret_err(La, "bad attribute")
- end.
-
-build_type_spec({spec,La}, {SpecFun, TypeSpecs}) ->
- NewSpecFun =
- case SpecFun of
- {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,
- {attribute,La,spec,{NewSpecFun, TypeSpecs}}.
-
-find_arity_from_specs([Spec|_]) ->
- %% Use the first spec to find the arity. If all are not the same,
- %% erl_lint will find this.
- Fun = case Spec of
- {type, _, bounded_fun, [F, _]} -> F;
- {type, _, 'fun', _} = F -> F
- end,
- {type, _, 'fun', [{type, _, product, Args},_]} = Fun,
- length(Args).
-
-build_def(LHS, Types) ->
- IsSubType = {atom, ?line(LHS), is_subtype},
- {type, ?line(LHS), constraint, [IsSubType, [LHS, Types]]}.
-
-lift_unions(T1, {type, _La, union, List}) ->
- {type, ?line(T1), union, [T1|List]};
-lift_unions(T1, T2) ->
- {type, ?line(T1), union, [T1, T2]}.
-
-skip_paren({paren_type,_L,[Type]}) ->
- skip_paren(Type);
-skip_paren(Type) ->
- Type.
-
-build_gen_type({atom, La, tuple}) ->
- {type, La, tuple, any};
-build_gen_type({atom, La, Name}) ->
- {type, La, Name, []}.
-
-build_bin_type([{var, _, '_'}|Left], Int) ->
- build_bin_type(Left, Int);
-build_bin_type([], Int) ->
- skip_paren(Int);
-build_bin_type([{var, La, _}|_], _) ->
- ret_err(La, "Bad binary type").
-
-%% build_attribute(AttrName, AttrValue) ->
-%% {attribute,Line,module,Module}
-%% {attribute,Line,export,Exports}
-%% {attribute,Line,import,Imports}
-%% {attribute,Line,record,{Name,Inits}}
-%% {attribute,Line,file,{Name,Line}}
-%% {attribute,Line,Name,Val}
-
-build_attribute({atom,La,module}, Val) ->
- case Val of
- [{atom,_Lm,Module}] ->
- {attribute,La,module,Module};
- [{atom,_Lm,Module},ExpList] ->
- {attribute,La,module,{Module,var_list(ExpList)}};
- [Name] ->
- case package_segments(Name) of
- error ->
- error_bad_decl(La, module);
- Module ->
- {attribute,La,module,Module}
- end;
- [Name,ExpList] ->
- case package_segments(Name) of
- error ->
- error_bad_decl(La, module);
- Module ->
- {attribute,La,module,{Module,var_list(ExpList)}}
- end;
- _Other ->
- error_bad_decl(La, module)
- end;
-build_attribute({atom,La,export}, Val) ->
- case Val of
- [ExpList] ->
- {attribute,La,export,farity_list(ExpList)};
- _Other -> error_bad_decl(La, export)
- end;
-build_attribute({atom,La,import}, Val) ->
- case Val of
- [Name] ->
- case package_segments(Name) of
- error ->
- error_bad_decl(La, import);
- Module ->
- {attribute,La,import,Module}
- end;
- [{atom,_Lm,Mod},ImpList] ->
- {attribute,La,import,{Mod,farity_list(ImpList)}};
- [Name, ImpList] ->
- case package_segments(Name) of
- error ->
- error_bad_decl(La, import);
- Module ->
- {attribute,La,import,{Module,farity_list(ImpList)}}
- end;
- _Other -> error_bad_decl(La, import)
- end;
-build_attribute({atom,La,record}, Val) ->
- case Val of
- [{atom,_Ln,Record},RecTuple] ->
- {attribute,La,record,{Record,record_tuple(RecTuple)}};
- _Other -> error_bad_decl(La, record)
- end;
-build_attribute({atom,La,file}, Val) ->
- case Val of
- [{string,_Ln,Name},{integer,_Ll,Line}] ->
- {attribute,La,file,{Name,Line}};
- _Other -> error_bad_decl(La, file)
- end;
-build_attribute({atom,La,Attr}, Val) ->
- case Val of
- [Expr0] ->
- Expr = attribute_farity(Expr0),
- {attribute,La,Attr,term(Expr)};
- _Other -> ret_err(La, "bad attribute")
- end.
-
-var_list({cons,_Lc,{var,_,V},Tail}) ->
- [V|var_list(Tail)];
-var_list({nil,_Ln}) -> [];
-var_list(Other) ->
- ret_err(?line(Other), "bad variable list").
-
-attribute_farity({cons,L,H,T}) ->
- {cons,L,attribute_farity(H),attribute_farity(T)};
-attribute_farity({tuple,L,Args0}) ->
- Args = attribute_farity_list(Args0),
- {tuple,L,Args};
-attribute_farity({op,L,'/',{atom,_,_}=Name,{integer,_,_}=Arity}) ->
- {tuple,L,[Name,Arity]};
-attribute_farity(Other) -> Other.
-
-attribute_farity_list(Args) ->
- [attribute_farity(A) || A <- Args].
-
--spec error_bad_decl(integer(), attributes()) -> no_return().
-
-error_bad_decl(L, S) ->
- ret_err(L, io_lib:format("bad ~w declaration", [S])).
-
-farity_list({cons,_Lc,{op,_Lo,'/',{atom,_La,A},{integer,_Li,I}},Tail}) ->
- [{A,I}|farity_list(Tail)];
-farity_list({nil,_Ln}) -> [];
-farity_list(Other) ->
- ret_err(?line(Other), "bad function arity").
-
-record_tuple({tuple,_Lt,Fields}) ->
- record_fields(Fields);
-record_tuple(Other) ->
- ret_err(?line(Other), "bad record declaration").
-
-record_fields([{atom,La,A}|Fields]) ->
- [{record_field,La,{atom,La,A}}|record_fields(Fields)];
-record_fields([{match,_Lm,{atom,La,A},Expr}|Fields]) ->
- [{record_field,La,{atom,La,A},Expr}|record_fields(Fields)];
-record_fields([{typed,Expr,TypeInfo}|Fields]) ->
- [Field] = record_fields([Expr]),
- TypeInfo1 =
- case Expr of
- {match, _, _, _} -> TypeInfo; %% If we have an initializer.
- {atom, La, _} ->
- case has_undefined(TypeInfo) of
- false ->
- TypeInfo2 = maybe_add_paren(TypeInfo),
- lift_unions(abstract(undefined, La), TypeInfo2);
- true ->
- TypeInfo
- end
- end,
- [{typed_record_field,Field,TypeInfo1}|record_fields(Fields)];
-record_fields([Other|_Fields]) ->
- ret_err(?line(Other), "bad record field");
-record_fields([]) -> [].
-
-has_undefined({atom,_,undefined}) ->
- true;
-has_undefined({ann_type,_,[_,T]}) ->
- has_undefined(T);
-has_undefined({paren_type,_,[T]}) ->
- has_undefined(T);
-has_undefined({type,_,union,Ts}) ->
- lists:any(fun has_undefined/1, Ts);
-has_undefined(_) ->
- false.
-
-maybe_add_paren({ann_type,L,T}) ->
- {paren_type,L,[{ann_type,L,T}]};
-maybe_add_paren(T) ->
- T.
-
-term(Expr) ->
- try normalise(Expr)
- catch _:_R -> ret_err(?line(Expr), "bad attribute")
- end.
-
-package_segments(Name) ->
- package_segments(Name, [], []).
-
-package_segments({record_field, _, F1, F2}, Fs, As) ->
- package_segments(F1, [F2 | Fs], As);
-package_segments({atom, _, A}, [F | Fs], As) ->
- package_segments(F, Fs, [A | As]);
-package_segments({atom, _, A}, [], As) ->
- lists:reverse([A | As]);
-package_segments(_, _, _) ->
- error.
-
-%% build_function([Clause]) -> {function,Line,Name,Arity,[Clause]}
-
-build_function(Cs) ->
- Name = element(3, hd(Cs)),
- Arity = length(element(4, hd(Cs))),
- {function,?line(hd(Cs)),Name,Arity,check_clauses(Cs, Name, Arity)}.
-
-%% build_rule([Clause]) -> {rule,Line,Name,Arity,[Clause]'}
-
-build_rule(Cs) ->
- Name = element(3, hd(Cs)),
- Arity = length(element(4, hd(Cs))),
- {rule,?line(hd(Cs)),Name,Arity,check_clauses(Cs, Name, Arity)}.
-
-%% build_fun(Line, [Clause]) -> {'fun',Line,{clauses,[Clause]}}.
-
-build_fun(Line, Cs) ->
- Arity = length(element(4, hd(Cs))),
- {'fun',Line,{clauses,check_clauses(Cs, 'fun', Arity)}}.
-
-check_clauses(Cs, Name, Arity) ->
- mapl(fun ({clause,L,N,As,G,B}) when N =:= Name, length(As) =:= Arity ->
- {clause,L,As,G,B};
- ({clause,L,_N,_As,_G,_B}) ->
- ret_err(L, "head mismatch") end, Cs).
-
-build_try(L,Es,Scs,{Ccs,As}) ->
- {'try',L,Es,Scs,Ccs,As}.
-
--spec ret_err(_, _) -> no_return().
-ret_err(L, S) ->
- {location,Location} = get_attribute(L, location),
- return_error(Location, S).
-
-%% mapl(F,List)
-%% an alternative map which always maps from left to right
-%% and makes it possible to interrupt the mapping with throw on
-%% the first occurence from left as expected.
-%% can be removed when the jam machine (and all other machines)
-%% uses the standardized (Erlang 5.0) evaluation order (from left to right)
-mapl(F, [H|T]) ->
- V = F(H),
- [V | mapl(F,T)];
-mapl(_, []) ->
- [].
-
-%% Convert between the abstract form of a term and a term.
-
--spec normalise(AbsTerm) -> Data when
- AbsTerm :: abstract_expr(),
- Data :: term().
-normalise({char,_,C}) -> C;
-normalise({integer,_,I}) -> I;
-normalise({float,_,F}) -> F;
-normalise({atom,_,A}) -> A;
-normalise({string,_,S}) -> S;
-normalise({nil,_}) -> [];
-normalise({bin,_,Fs}) ->
- {value, B, _} =
- eval_bits:expr_grp(Fs, [],
- fun(E, _) ->
- {value, normalise(E), []}
- end, [], true),
- B;
-normalise({cons,_,Head,Tail}) ->
- [normalise(Head)|normalise(Tail)];
-normalise({tuple,_,Args}) ->
- list_to_tuple(normalise_list(Args));
-%% Atom dot-notation, as in 'foo.bar.baz'
-normalise({record_field,_,_,_}=A) ->
- case package_segments(A) of
- error -> erlang:error({badarg, A});
- As -> list_to_atom(packages:concat(As))
- end;
-%% Special case for unary +/-.
-normalise({op,_,'+',{char,_,I}}) -> I;
-normalise({op,_,'+',{integer,_,I}}) -> I;
-normalise({op,_,'+',{float,_,F}}) -> F;
-normalise({op,_,'-',{char,_,I}}) -> -I; %Weird, but compatible!
-normalise({op,_,'-',{integer,_,I}}) -> -I;
-normalise({op,_,'-',{float,_,F}}) -> -F;
-normalise(X) -> erlang:error({badarg, X}).
-
-normalise_list([H|T]) ->
- [normalise(H)|normalise_list(T)];
-normalise_list([]) ->
- [].
-
--spec abstract(Data) -> AbsTerm when
- Data :: term(),
- AbsTerm :: abstract_expr().
-abstract(T) when is_integer(T) -> {integer,0,T};
-abstract(T) when is_float(T) -> {float,0,T};
-abstract(T) when is_atom(T) -> {atom,0,T};
-abstract([]) -> {nil,0};
-abstract(B) when is_bitstring(B) ->
- {bin, 0, [abstract_byte(Byte, 0) || Byte <- bitstring_to_list(B)]};
-abstract([C|T]) when is_integer(C), 0 =< C, C < 256 ->
- abstract_string(T, [C]);
-abstract([H|T]) ->
- {cons,0,abstract(H),abstract(T)};
-abstract(Tuple) when is_tuple(Tuple) ->
- {tuple,0,abstract_list(tuple_to_list(Tuple))}.
-
-abstract_string([C|T], String) when is_integer(C), 0 =< C, C < 256 ->
- abstract_string(T, [C|String]);
-abstract_string([], String) ->
- {string, 0, lists:reverse(String)};
-abstract_string(T, String) ->
- not_string(String, abstract(T)).
-
-not_string([C|T], Result) ->
- not_string(T, {cons, 0, {integer, 0, C}, Result});
-not_string([], Result) ->
- Result.
-
-abstract_list([H|T]) ->
- [abstract(H)|abstract_list(T)];
-abstract_list([]) ->
- [].
-
-abstract_byte(Byte, Line) when is_integer(Byte) ->
- {bin_element, Line, {integer, Line, Byte}, default, default};
-abstract_byte(Bits, Line) ->
- Sz = bit_size(Bits),
- <<Val:Sz>> = Bits,
- {bin_element, Line, {integer, Line, Val}, {integer, Line, Sz}, default}.
-
-%%% abstract/2 keeps the line number
-abstract(T, Line) when is_integer(T) -> {integer,Line,T};
-abstract(T, Line) when is_float(T) -> {float,Line,T};
-abstract(T, Line) when is_atom(T) -> {atom,Line,T};
-abstract([], Line) -> {nil,Line};
-abstract(B, Line) when is_bitstring(B) ->
- {bin, Line, [abstract_byte(Byte, Line) || Byte <- bitstring_to_list(B)]};
-abstract([C|T], Line) when is_integer(C), 0 =< C, C < 256 ->
- abstract_string(T, [C], Line);
-abstract([H|T], Line) ->
- {cons,Line,abstract(H, Line),abstract(T, Line)};
-abstract(Tuple, Line) when is_tuple(Tuple) ->
- {tuple,Line,abstract_list(tuple_to_list(Tuple), Line)}.
-
-abstract_string([C|T], String, Line) when is_integer(C), 0 =< C, C < 256 ->
- abstract_string(T, [C|String], Line);
-abstract_string([], String, Line) ->
- {string, Line, lists:reverse(String)};
-abstract_string(T, String, Line) ->
- not_string(String, abstract(T, Line), Line).
-
-not_string([C|T], Result, Line) ->
- not_string(T, {cons, Line, {integer, Line, C}, Result}, Line);
-not_string([], Result, _Line) ->
- Result.
-
-abstract_list([H|T], Line) ->
- [abstract(H, Line)|abstract_list(T, Line)];
-abstract_list([], _Line) ->
- [].
-
-%% Generate a list of tokens representing the abstract term.
-
--spec tokens(AbsTerm) -> Tokens when
- AbsTerm :: abstract_expr(),
- Tokens :: [token()].
-tokens(Abs) ->
- tokens(Abs, []).
-
--spec tokens(AbsTerm, MoreTokens) -> Tokens when
- AbsTerm :: abstract_expr(),
- MoreTokens :: [token()],
- Tokens :: [token()].
-tokens({char,L,C}, More) -> [{char,L,C}|More];
-tokens({integer,L,N}, More) -> [{integer,L,N}|More];
-tokens({float,L,F}, More) -> [{float,L,F}|More];
-tokens({atom,L,A}, More) -> [{atom,L,A}|More];
-tokens({var,L,V}, More) -> [{var,L,V}|More];
-tokens({string,L,S}, More) -> [{string,L,S}|More];
-tokens({nil,L}, More) -> [{'[',L},{']',L}|More];
-tokens({cons,L,Head,Tail}, More) ->
- [{'[',L}|tokens(Head, tokens_tail(Tail, More))];
-tokens({tuple,L,[]}, More) ->
- [{'{',L},{'}',L}|More];
-tokens({tuple,L,[E|Es]}, More) ->
- [{'{',L}|tokens(E, tokens_tuple(Es, ?line(E), More))].
-
-tokens_tail({cons,L,Head,Tail}, More) ->
- [{',',L}|tokens(Head, tokens_tail(Tail, More))];
-tokens_tail({nil,L}, More) ->
- [{']',L}|More];
-tokens_tail(Other, More) ->
- L = ?line(Other),
- [{'|',L}|tokens(Other, [{']',L}|More])].
-
-tokens_tuple([E|Es], Line, More) ->
- [{',',Line}|tokens(E, tokens_tuple(Es, ?line(E), More))];
-tokens_tuple([], Line, More) ->
- [{'}',Line}|More].
-
-%% Give the relative precedences of operators.
-
-inop_prec('=') -> {150,100,100};
-inop_prec('!') -> {150,100,100};
-inop_prec('orelse') -> {160,150,150};
-inop_prec('andalso') -> {200,160,160};
-inop_prec('==') -> {300,200,300};
-inop_prec('/=') -> {300,200,300};
-inop_prec('=<') -> {300,200,300};
-inop_prec('<') -> {300,200,300};
-inop_prec('>=') -> {300,200,300};
-inop_prec('>') -> {300,200,300};
-inop_prec('=:=') -> {300,200,300};
-inop_prec('=/=') -> {300,200,300};
-inop_prec('++') -> {400,300,300};
-inop_prec('--') -> {400,300,300};
-inop_prec('+') -> {400,400,500};
-inop_prec('-') -> {400,400,500};
-inop_prec('bor') -> {400,400,500};
-inop_prec('bxor') -> {400,400,500};
-inop_prec('bsl') -> {400,400,500};
-inop_prec('bsr') -> {400,400,500};
-inop_prec('or') -> {400,400,500};
-inop_prec('xor') -> {400,400,500};
-inop_prec('*') -> {500,500,600};
-inop_prec('/') -> {500,500,600};
-inop_prec('div') -> {500,500,600};
-inop_prec('rem') -> {500,500,600};
-inop_prec('band') -> {500,500,600};
-inop_prec('and') -> {500,500,600};
-inop_prec('#') -> {800,700,800};
-inop_prec(':') -> {900,800,900};
-inop_prec('.') -> {900,900,1000}.
-
--type pre_op() :: 'catch' | '+' | '-' | 'bnot' | 'not' | '#'.
-
--spec preop_prec(pre_op()) -> {0 | 600 | 700, 100 | 700 | 800}.
-
-preop_prec('catch') -> {0,100};
-preop_prec('+') -> {600,700};
-preop_prec('-') -> {600,700};
-preop_prec('bnot') -> {600,700};
-preop_prec('not') -> {600,700};
-preop_prec('#') -> {700,800}.
-
--spec func_prec() -> {800,700}.
-
-func_prec() -> {800,700}.
-
--spec max_prec() -> 1000.
-
-max_prec() -> 1000.
-
-%%% [Experimental]. The parser just copies the attributes of the
-%%% scanner tokens to the abstract format. This design decision has
-%%% been hidden to some extent: use set_line() and get_attribute() to
-%%% access the second element of (almost all) of the abstract format
-%%% tuples. A typical use is to negate line numbers to prevent the
-%%% compiler from emitting warnings and errors. The second element can
-%%% (of course) be set to any value, but then these functions no
-%%% longer apply. To get all present attributes as a property list
-%%% get_attributes() should be used.
-
-set_line(L, F) ->
- erl_scan:set_attribute(line, L, F).
-
-get_attribute(L, Name) ->
- erl_scan:attributes_info(L, Name).
-
-get_attributes(L) ->
- erl_scan:attributes_info(L).
-
--file("/opt/installs/lib/erlang/lib/parsetools-2.0.5/include/yeccpre.hrl", 0).
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% The parser generator will insert appropriate declarations before this line.%
-
--type yecc_ret() :: {'error', _} | {'ok', _}.
-
--spec parse(Tokens :: list()) -> yecc_ret().
-parse(Tokens) ->
- yeccpars0(Tokens, {no_func, no_line}, 0, [], []).
-
--spec parse_and_scan({function() | {atom(), atom()}, [_]}
- | {atom(), atom(), [_]}) -> yecc_ret().
-parse_and_scan({F, A}) -> % Fun or {M, F}
- yeccpars0([], {{F, A}, no_line}, 0, [], []);
-parse_and_scan({M, F, A}) ->
- yeccpars0([], {{{M, F}, A}, no_line}, 0, [], []).
-
--spec format_error(any()) -> [char() | list()].
-format_error(Message) ->
- case io_lib:deep_char_list(Message) of
- true ->
- Message;
- _ ->
- io_lib:write(Message)
- end.
-
-%% To be used in grammar files to throw an error message to the parser
-%% toplevel. Doesn't have to be exported!
--compile({nowarn_unused_function, return_error/2}).
--spec return_error(integer(), any()) -> no_return().
-return_error(Line, Message) ->
- throw({error, {Line, ?MODULE, Message}}).
-
--define(CODE_VERSION, "1.4").
-
-yeccpars0(Tokens, Tzr, State, States, Vstack) ->
- try yeccpars1(Tokens, Tzr, State, States, Vstack)
- catch
- error: Error ->
- Stacktrace = erlang:get_stacktrace(),
- try yecc_error_type(Error, Stacktrace) of
- Desc ->
- erlang:raise(error, {yecc_bug, ?CODE_VERSION, Desc},
- Stacktrace)
- catch _:_ -> erlang:raise(error, Error, Stacktrace)
- end;
- %% Probably thrown from return_error/2:
- throw: {error, {_Line, ?MODULE, _M}} = Error ->
- Error
- end.
-
-yecc_error_type(function_clause, [{?MODULE,F,ArityOrArgs} | _]) ->
- case atom_to_list(F) of
- "yeccgoto_" ++ SymbolL ->
- {ok,[{atom,_,Symbol}],_} = erl_scan:string(SymbolL),
- State = case ArityOrArgs of
- [S,_,_,_,_,_,_] -> S;
- _ -> state_is_unknown
- end,
- {Symbol, State, missing_in_goto_table}
- end.
-
-yeccpars1([Token | Tokens], Tzr, State, States, Vstack) ->
- yeccpars2(State, element(1, Token), States, Vstack, Token, Tokens, Tzr);
-yeccpars1([], {{F, A},_Line}, State, States, Vstack) ->
- case apply(F, A) of
- {ok, Tokens, Endline} ->
- yeccpars1(Tokens, {{F, A}, Endline}, State, States, Vstack);
- {eof, Endline} ->
- yeccpars1([], {no_func, Endline}, State, States, Vstack);
- {error, Descriptor, _Endline} ->
- {error, Descriptor}
- end;
-yeccpars1([], {no_func, no_line}, State, States, Vstack) ->
- Line = 999999,
- yeccpars2(State, '$end', States, Vstack, yecc_end(Line), [],
- {no_func, Line});
-yeccpars1([], {no_func, Endline}, State, States, Vstack) ->
- yeccpars2(State, '$end', States, Vstack, yecc_end(Endline), [],
- {no_func, Endline}).
-
-%% yeccpars1/7 is called from generated code.
-%%
-%% When using the {includefile, Includefile} option, make sure that
-%% yeccpars1/7 can be found by parsing the file without following
-%% include directives. yecc will otherwise assume that an old
-%% yeccpre.hrl is included (one which defines yeccpars1/5).
-yeccpars1(State1, State, States, Vstack, Token0, [Token | Tokens], Tzr) ->
- yeccpars2(State, element(1, Token), [State1 | States],
- [Token0 | Vstack], Token, Tokens, Tzr);
-yeccpars1(State1, State, States, Vstack, Token0, [], {{_F,_A}, _Line}=Tzr) ->
- yeccpars1([], Tzr, State, [State1 | States], [Token0 | Vstack]);
-yeccpars1(State1, State, States, Vstack, Token0, [], {no_func, no_line}) ->
- Line = yecctoken_end_location(Token0),
- yeccpars2(State, '$end', [State1 | States], [Token0 | Vstack],
- yecc_end(Line), [], {no_func, Line});
-yeccpars1(State1, State, States, Vstack, Token0, [], {no_func, Line}) ->
- yeccpars2(State, '$end', [State1 | States], [Token0 | Vstack],
- yecc_end(Line), [], {no_func, Line}).
-
-%% For internal use only.
-yecc_end({Line,_Column}) ->
- {'$end', Line};
-yecc_end(Line) ->
- {'$end', Line}.
-
-yecctoken_end_location(Token) ->
- try
- {text, Str} = erl_scan:token_info(Token, text),
- {line, Line} = erl_scan:token_info(Token, line),
- Parts = re:split(Str, "\n"),
- Dline = length(Parts) - 1,
- Yline = Line + Dline,
- case erl_scan:token_info(Token, column) of
- {column, Column} ->
- Col = byte_size(lists:last(Parts)),
- {Yline, Col + if Dline =:= 0 -> Column; true -> 1 end};
- undefined ->
- Yline
- end
- catch _:_ ->
- yecctoken_location(Token)
- end.
-
--compile({nowarn_unused_function, yeccerror/1}).
-yeccerror(Token) ->
- Text = yecctoken_to_string(Token),
- Location = yecctoken_location(Token),
- {error, {Location, ?MODULE, ["syntax error before: ", Text]}}.
-
--compile({nowarn_unused_function, yecctoken_to_string/1}).
-yecctoken_to_string(Token) ->
- case catch erl_scan:token_info(Token, text) of
- {text, Txt} -> Txt;
- _ -> yecctoken2string(Token)
- end.
-
-yecctoken_location(Token) ->
- case catch erl_scan:token_info(Token, location) of
- {location, Loc} -> Loc;
- _ -> element(2, Token)
- end.
-
--compile({nowarn_unused_function, yecctoken2string/1}).
-yecctoken2string({atom, _, A}) -> io_lib:write(A);
-yecctoken2string({integer,_,N}) -> io_lib:write(N);
-yecctoken2string({float,_,F}) -> io_lib:write(F);
-yecctoken2string({char,_,C}) -> io_lib:write_char(C);
-yecctoken2string({var,_,V}) -> io_lib:format("~s", [V]);
-yecctoken2string({string,_,S}) -> io_lib:write_unicode_string(S);
-yecctoken2string({reserved_symbol, _, A}) -> io_lib:write(A);
-yecctoken2string({_Cat, _, Val}) -> io_lib:format("~p",[Val]);
-yecctoken2string({dot, _}) -> "'.'";
-yecctoken2string({'$end', _}) ->
- [];
-yecctoken2string({Other, _}) when is_atom(Other) ->
- io_lib:write(Other);
-yecctoken2string(Other) ->
- io_lib:write(Other).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 779).
-
-yeccpars2(0=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_0(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(1=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_1(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(2=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_2(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(3=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_3(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(4=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_4(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(5=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_5(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(6=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_6(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(7=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_7(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(8=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_8(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(9=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_9(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(10=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_10(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(11=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_11(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(12=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_12(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(13=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_13(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(14=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_14(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(15=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_15(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(16=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_16(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(17=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_17(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(18=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_18(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(19=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_19(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(20=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_20(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(21=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_21(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(22=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_22(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(23=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_23(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(24=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_24(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(25=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_25(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(26=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_26(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(27=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_27(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(28=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_28(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(29=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_29(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(30=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_30(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(31=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_31(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(32=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_32(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(33=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_33(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(34=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_34(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(35=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_35(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(36=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_36(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(37=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_37(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(38=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_38(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(39=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_39(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(40=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_40(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(41=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_41(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(42=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_42(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(43=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_43(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(44=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_44(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(45=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(46=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_46(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(47=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_47(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(48=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_48(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(49=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_49(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(50=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_50(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(51=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_51(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(52=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_52(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(53=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(54=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_54(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(55=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(56=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(57=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_57(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(58=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_58(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(59=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_59(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(60=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(61=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_61(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(62=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_62(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(63=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_63(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(64=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_64(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(65=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_65(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(66=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(67=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_67(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(68=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_68(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(69=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_69(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(70=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_70(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(71=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_71(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(72=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_72(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(73=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_73(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(74=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(75=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_75(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(76=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(77=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_77(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(78=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_78(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(79=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_79(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(80=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(81=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_81(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(82=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_82(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(83=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_83(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(84=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(85=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_85(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(86=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_86(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(87=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(88=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_88(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(89=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_89(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(90=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(91=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_91(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(92=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_92(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(93=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_93(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(94=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_94(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(95=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_95(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(96=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_96(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(97=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(98=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_98(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(99=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_83(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(100=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_100(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(101=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(102=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_102(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(103=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_83(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(104=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_104(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(105=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_83(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(106=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_106(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(107=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_75(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(108=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_108(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(109=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(110=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_110(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(111=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_111(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(112=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_112(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(113=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_113(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(114=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_114(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(115=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_115(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(116=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_116(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(117=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(118=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_83(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(119=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_119(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(120=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_120(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(121=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(122=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_122(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(123=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_83(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(124=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_124(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(125=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_125(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(126=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_126(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(127=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(128=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_128(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(129=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(130=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_130(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(131=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_131(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(132=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_132(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(133=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_133(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(134=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(135=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_135(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(136=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(137=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_137(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(138=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(139=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_139(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(140=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_140(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(141=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_141(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(142=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_142(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(143=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_143(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(144=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_83(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(145=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_145(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(146=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(147=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_147(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(148=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_148(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(149=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_149(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(150=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_150(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(151=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_151(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(152=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_152(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(153=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_153(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(154=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_154(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(155=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_155(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(156=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_156(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(157=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_157(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(158=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_158(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(159=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_83(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(160=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_160(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(161=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_10(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(162=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_162(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(163=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_163(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(164=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_164(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(165=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_165(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(166=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(167=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_167(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(168=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_168(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(169=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_169(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(170=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_170(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(171=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_171(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(172=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_172(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(173=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_173(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(174=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(175=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_175(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(176=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(177=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_177(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(178=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_178(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(179=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_179(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(180=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_180(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(181=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_181(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(182=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_182(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(183=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_183(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(184=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_184(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(185=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_185(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(186=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_186(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(187=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_187(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(188=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_188(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(189=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_189(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(190=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_190(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(191=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(192=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_192(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(193=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_193(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(194=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_194(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(195=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_181(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(196=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_196(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(197=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_197(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(198=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_198(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(199=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_199(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(200=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_200(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(201=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_201(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(202=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_202(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(203=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_203(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(204=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_204(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(205=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_199(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(206=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_206(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(207=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_207(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(208=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_208(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(209=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_209(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(210=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_210(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(211=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_211(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(212=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_212(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(213=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_213(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(214=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_214(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(215=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_215(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(216=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_216(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(217=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_217(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(218=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_218(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(219=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_219(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(220=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(221=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_221(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(222=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(223=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_223(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(224=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_224(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(225=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_225(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(226=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_226(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(227=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_227(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(228=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(229=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_229(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(230=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_230(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(231=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_230(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(232=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_232(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(233=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_233(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(234=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_230(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(235=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_235(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(236=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_230(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(237=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_237(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(238=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_230(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(239=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_239(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(240=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_240(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(241=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_241(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(242=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_242(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(243=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_243(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(244=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_244(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(245=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_245(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(246=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_246(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(247=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_247(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(248=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_230(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(249=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_230(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(250=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_250(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(251=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_251(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(252=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_252(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(253=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_253(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(254=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_254(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(255=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_255(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(256=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_256(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(257=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_257(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(258=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_258(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(259=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_259(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(260=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_260(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(261=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_230(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(262=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_262(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(263=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_263(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(264=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_264(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(265=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_265(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(266=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_266(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(267=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_267(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(268=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_268(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(269=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_269(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(270=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_270(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(271=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_271(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(272=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_181(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(273=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_273(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(274=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_274(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(275=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_275(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(276=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_276(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(277=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_277(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(278=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_278(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(279=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_279(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(280=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_280(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(281=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_281(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(282=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_282(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(283=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_283(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(284=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_284(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(285=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_285(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(286=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_286(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(287=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_287(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(288=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_288(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(289=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_289(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(290=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(291=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_291(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(292=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_292(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(293=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_293(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(294=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_294(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(295=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_295(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(296=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_296(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(297=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_297(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(298=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_298(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(299=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_299(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(300=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_300(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(301=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_301(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(302=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_302(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(303=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_303(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(304=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_304(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(305=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_305(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(306=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_295(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(307=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_307(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(308=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_308(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(309=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_309(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(310=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_310(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(311=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_311(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(312=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_312(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(313=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_313(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(314=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_314(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(315=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_315(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(316=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_316(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(317=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_317(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(318=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_318(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(319=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_319(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(320=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_320(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(321=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_321(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(322=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_322(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(323=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_323(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(324=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_324(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(325=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_325(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(326=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_326(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(327=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_327(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(328=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_328(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(329=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_329(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(330=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_330(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(331=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_331(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(332=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_332(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(333=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_333(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(334=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_334(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(335=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_335(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(336=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_336(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(337=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_337(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(338=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_338(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(339=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_339(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(340=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_340(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(341=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_341(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(342=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_342(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(343=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_343(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(344=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_322(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(345=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_345(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(346=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_346(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(347=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_347(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(348=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_348(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(349=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_349(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(350=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_350(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(351=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_351(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(352=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_352(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(353=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_353(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(354=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_354(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(355=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_355(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(356=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_356(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(357=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_357(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(358=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_358(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(359=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_359(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(360=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_360(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(361=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_361(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(362=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_362(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(363=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_363(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(364=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_364(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(365=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_365(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(366=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_366(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(367=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_367(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(368=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_368(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(369=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_369(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(370=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_319(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(371=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_371(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(372=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_372(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(373=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_373(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(374=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_374(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(375=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_375(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(376=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_376(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(377=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_377(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(378=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_378(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(379=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_379(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(380=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_322(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(381=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_381(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(382=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_382(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(383=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_383(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(384=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_384(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(385=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_385(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(386=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_386(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(387=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_387(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(388=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_388(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(389=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_389(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(390=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_322(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(391=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_391(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(392=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_392(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(393=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_393(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(394=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_394(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(395=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_395(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(396=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_322(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(397=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_397(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(398=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_398(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(399=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_322(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(400=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_400(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(401=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_334(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(402=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_402(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(403=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_334(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(404=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_334(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(405=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_405(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(406=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_406(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(407=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_334(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(408=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_408(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(409=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_409(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(410=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_410(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(411=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_411(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(412=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_412(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(413=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_413(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(414=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_322(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(415=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_415(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(416=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_322(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(417=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_417(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(418=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_418(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(419=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_409(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(420=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_420(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(421=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_295(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(422=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_422(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(423=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_423(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(424=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_424(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(425=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_425(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(426=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_426(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(427=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_427(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(428=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(429=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_429(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(430=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_430(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(431=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_431(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(432=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_322(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(433=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_433(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(434=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_434(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(435=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_435(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(436=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_68(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(437=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_437(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(438=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_438(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(439=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_439(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(440=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(441=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_322(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(442=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_442(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(443=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_443(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(444=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(445=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_445(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(446=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_446(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(447=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_447(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(448=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_448(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(449=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_449(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(450=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_431(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(451=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_451(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(452=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_452(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(453=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_453(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(454=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_454(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(455=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_455(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(456=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_10(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(457=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_457(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(458=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_83(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(459=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_459(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(460=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_460(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(461=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_461(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(462=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_10(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(463=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_463(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(464=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_464(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(Other, _, _, _, _, _, _) ->
- erlang:error({yecc_bug,"1.4",{missing_state_in_action_table, Other}}).
-
-yeccpars2_0(S, '-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 9, Ss, Stack, T, Ts, Tzr);
-yeccpars2_0(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 10, Ss, Stack, T, Ts, Tzr);
-yeccpars2_0(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_1(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_1_(Stack),
- yeccgoto_rule(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_2(S, ';', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 460, Ss, Stack, T, Ts, Tzr);
-yeccpars2_2(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_2_(Stack),
- yeccgoto_rule_clauses(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_3(S, dot, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 459, Ss, Stack, T, Ts, Tzr);
-yeccpars2_3(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_4(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_4_(Stack),
- yeccgoto_function(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_5(S, ';', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 454, Ss, Stack, T, Ts, Tzr);
-yeccpars2_5(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_5_(Stack),
- yeccgoto_function_clauses(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_6(S, dot, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 453, Ss, Stack, T, Ts, Tzr);
-yeccpars2_6(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_7(_S, '$end', _Ss, Stack, _T, _Ts, _Tzr) ->
- {ok, hd(Stack)};
-yeccpars2_7(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_8(S, dot, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 452, Ss, Stack, T, Ts, Tzr);
-yeccpars2_8(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_9(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 292, Ss, Stack, T, Ts, Tzr);
-yeccpars2_9(S, spec, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 293, Ss, Stack, T, Ts, Tzr);
-yeccpars2_9(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_10(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 13, Ss, Stack, T, Ts, Tzr);
-yeccpars2_10(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_11(S, 'when', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 84, Ss, Stack, T, Ts, Tzr);
-yeccpars2_11(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_11_(Stack),
- yeccpars2_287(287, Cat, [11 | Ss], NewStack, T, Ts, Tzr).
-
-yeccpars2_12(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_12_(Stack),
- yeccgoto_clause_args(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_13(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 44, Ss, Stack, T, Ts, Tzr);
-yeccpars2_13(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 45, Ss, Stack, T, Ts, Tzr);
-yeccpars2_13(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 46, Ss, Stack, T, Ts, Tzr);
-yeccpars2_13(S, '+', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 47, Ss, Stack, T, Ts, Tzr);
-yeccpars2_13(S, '-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 48, Ss, Stack, T, Ts, Tzr);
-yeccpars2_13(S, '.', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 49, Ss, Stack, T, Ts, Tzr);
-yeccpars2_13(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 52, Ss, Stack, T, Ts, Tzr);
-yeccpars2_13(S, 'bnot', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 54, Ss, Stack, T, Ts, Tzr);
-yeccpars2_13(S, 'catch', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 56, Ss, Stack, T, Ts, Tzr);
-yeccpars2_13(S, 'not', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 62, Ss, Stack, T, Ts, Tzr);
-yeccpars2_13(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 67, Ss, Stack, T, Ts, Tzr);
-yeccpars2_13(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 68, Ss, Stack, T, Ts, Tzr);
-yeccpars2_13(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_13(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_cont_13(S, '<<', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 50, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_13(S, '[', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 51, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_13(S, 'begin', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 53, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_13(S, 'case', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 55, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_13(S, char, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 57, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_13(S, float, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 58, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_13(S, 'fun', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 59, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_13(S, 'if', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 60, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_13(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 61, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_13(S, 'query', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 63, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_13(S, 'receive', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 64, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_13(S, string, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 65, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_13(S, 'try', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 66, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_13(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_max(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_max(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_atomic(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_17(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 282, Ss, Stack, T, Ts, Tzr);
-yeccpars2_17(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_700(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_max(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_max(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_20(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 44, Ss, Stack, T, Ts, Tzr);
-yeccpars2_20(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 45, Ss, Stack, T, Ts, Tzr);
-yeccpars2_20(S, '.', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 49, Ss, Stack, T, Ts, Tzr);
-yeccpars2_20(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 52, Ss, Stack, T, Ts, Tzr);
-yeccpars2_20(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 67, Ss, Stack, T, Ts, Tzr);
-yeccpars2_20(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 68, Ss, Stack, T, Ts, Tzr);
-yeccpars2_20(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_13(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_max(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_max(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_max(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_700(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_max(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_26(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 280, Ss, Stack, T, Ts, Tzr);
-yeccpars2_26(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_27(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 275, Ss, Stack, T, Ts, Tzr);
-yeccpars2_27(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_900(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_28(S, '.', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 271, Ss, Stack, T, Ts, Tzr);
-yeccpars2_28(S, ':', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 272, Ss, Stack, T, Ts, Tzr);
-yeccpars2_28(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_800(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_29(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 13, Ss, Stack, T, Ts, Tzr);
-yeccpars2_29(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_700(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_600(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_500(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_32(S, '*', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 262, Ss, Stack, T, Ts, Tzr);
-yeccpars2_32(S, '/', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 263, Ss, Stack, T, Ts, Tzr);
-yeccpars2_32(S, 'and', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 264, Ss, Stack, T, Ts, Tzr);
-yeccpars2_32(S, 'band', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 265, Ss, Stack, T, Ts, Tzr);
-yeccpars2_32(S, 'div', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 266, Ss, Stack, T, Ts, Tzr);
-yeccpars2_32(S, 'rem', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 267, Ss, Stack, T, Ts, Tzr);
-yeccpars2_32(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_400(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_33(S, '+', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 250, Ss, Stack, T, Ts, Tzr);
-yeccpars2_33(S, '++', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 251, Ss, Stack, T, Ts, Tzr);
-yeccpars2_33(S, '-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 252, Ss, Stack, T, Ts, Tzr);
-yeccpars2_33(S, '--', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 253, Ss, Stack, T, Ts, Tzr);
-yeccpars2_33(S, 'bor', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 254, Ss, Stack, T, Ts, Tzr);
-yeccpars2_33(S, 'bsl', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 255, Ss, Stack, T, Ts, Tzr);
-yeccpars2_33(S, 'bsr', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 256, Ss, Stack, T, Ts, Tzr);
-yeccpars2_33(S, 'bxor', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 257, Ss, Stack, T, Ts, Tzr);
-yeccpars2_33(S, 'or', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 258, Ss, Stack, T, Ts, Tzr);
-yeccpars2_33(S, 'xor', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 259, Ss, Stack, T, Ts, Tzr);
-yeccpars2_33(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_300(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_34(S, '/=', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 239, Ss, Stack, T, Ts, Tzr);
-yeccpars2_34(S, '<', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 240, Ss, Stack, T, Ts, Tzr);
-yeccpars2_34(S, '=/=', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 241, Ss, Stack, T, Ts, Tzr);
-yeccpars2_34(S, '=:=', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 242, Ss, Stack, T, Ts, Tzr);
-yeccpars2_34(S, '=<', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 243, Ss, Stack, T, Ts, Tzr);
-yeccpars2_34(S, '==', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 244, Ss, Stack, T, Ts, Tzr);
-yeccpars2_34(S, '>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 245, Ss, Stack, T, Ts, Tzr);
-yeccpars2_34(S, '>=', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 246, Ss, Stack, T, Ts, Tzr);
-yeccpars2_34(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_200(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_35(S, 'andalso', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 236, Ss, Stack, T, Ts, Tzr);
-yeccpars2_35(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_160(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_36(S, 'orelse', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 234, Ss, Stack, T, Ts, Tzr);
-yeccpars2_36(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_150(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_37(S, '!', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 230, Ss, Stack, T, Ts, Tzr);
-yeccpars2_37(S, '=', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 231, Ss, Stack, T, Ts, Tzr);
-yeccpars2_37(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_100(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_39(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 228, Ss, Stack, T, Ts, Tzr);
-yeccpars2_39(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_39_(Stack),
- yeccgoto_exprs(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_max(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_max(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_max(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_max(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_44(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 211, Ss, Stack, T, Ts, Tzr);
-yeccpars2_44(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_45(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 44, Ss, Stack, T, Ts, Tzr);
-yeccpars2_45(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 45, Ss, Stack, T, Ts, Tzr);
-yeccpars2_45(S, '+', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 47, Ss, Stack, T, Ts, Tzr);
-yeccpars2_45(S, '-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 48, Ss, Stack, T, Ts, Tzr);
-yeccpars2_45(S, '.', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 49, Ss, Stack, T, Ts, Tzr);
-yeccpars2_45(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 52, Ss, Stack, T, Ts, Tzr);
-yeccpars2_45(S, 'bnot', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 54, Ss, Stack, T, Ts, Tzr);
-yeccpars2_45(S, 'catch', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 56, Ss, Stack, T, Ts, Tzr);
-yeccpars2_45(S, 'not', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 62, Ss, Stack, T, Ts, Tzr);
-yeccpars2_45(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 67, Ss, Stack, T, Ts, Tzr);
-yeccpars2_45(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 68, Ss, Stack, T, Ts, Tzr);
-yeccpars2_45(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_13(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_46(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_46_(Stack),
- yeccgoto_argument_list(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_47(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_prefix_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_48(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_prefix_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_49(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 208, Ss, Stack, T, Ts, Tzr);
-yeccpars2_49(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_50(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 45, Ss, Stack, T, Ts, Tzr);
-yeccpars2_50(S, '+', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 47, Ss, Stack, T, Ts, Tzr);
-yeccpars2_50(S, '-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 48, Ss, Stack, T, Ts, Tzr);
-yeccpars2_50(S, '>>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 187, Ss, Stack, T, Ts, Tzr);
-yeccpars2_50(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 52, Ss, Stack, T, Ts, Tzr);
-yeccpars2_50(S, 'bnot', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 54, Ss, Stack, T, Ts, Tzr);
-yeccpars2_50(S, 'not', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 62, Ss, Stack, T, Ts, Tzr);
-yeccpars2_50(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 67, Ss, Stack, T, Ts, Tzr);
-yeccpars2_50(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 68, Ss, Stack, T, Ts, Tzr);
-yeccpars2_50(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_13(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_51(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 44, Ss, Stack, T, Ts, Tzr);
-yeccpars2_51(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 45, Ss, Stack, T, Ts, Tzr);
-yeccpars2_51(S, '+', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 47, Ss, Stack, T, Ts, Tzr);
-yeccpars2_51(S, '-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 48, Ss, Stack, T, Ts, Tzr);
-yeccpars2_51(S, '.', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 49, Ss, Stack, T, Ts, Tzr);
-yeccpars2_51(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 172, Ss, Stack, T, Ts, Tzr);
-yeccpars2_51(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 52, Ss, Stack, T, Ts, Tzr);
-yeccpars2_51(S, 'bnot', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 54, Ss, Stack, T, Ts, Tzr);
-yeccpars2_51(S, 'catch', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 56, Ss, Stack, T, Ts, Tzr);
-yeccpars2_51(S, 'not', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 62, Ss, Stack, T, Ts, Tzr);
-yeccpars2_51(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 67, Ss, Stack, T, Ts, Tzr);
-yeccpars2_51(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 68, Ss, Stack, T, Ts, Tzr);
-yeccpars2_51(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_13(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_52(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_atomic(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-%% yeccpars2_53: see yeccpars2_45
-
-yeccpars2_54(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_prefix_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-%% yeccpars2_55: see yeccpars2_45
-
-%% yeccpars2_56: see yeccpars2_45
-
-yeccpars2_57(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_atomic(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_58(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_atomic(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_59(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 13, Ss, Stack, T, Ts, Tzr);
-yeccpars2_59(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 152, Ss, Stack, T, Ts, Tzr);
-yeccpars2_59(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_60: see yeccpars2_45
-
-yeccpars2_61(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_atomic(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_62(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_prefix_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_63(S, '[', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 127, Ss, Stack, T, Ts, Tzr);
-yeccpars2_63(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_64(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 44, Ss, Stack, T, Ts, Tzr);
-yeccpars2_64(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 45, Ss, Stack, T, Ts, Tzr);
-yeccpars2_64(S, '+', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 47, Ss, Stack, T, Ts, Tzr);
-yeccpars2_64(S, '-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 48, Ss, Stack, T, Ts, Tzr);
-yeccpars2_64(S, '.', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 49, Ss, Stack, T, Ts, Tzr);
-yeccpars2_64(S, 'after', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 117, Ss, Stack, T, Ts, Tzr);
-yeccpars2_64(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 52, Ss, Stack, T, Ts, Tzr);
-yeccpars2_64(S, 'bnot', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 54, Ss, Stack, T, Ts, Tzr);
-yeccpars2_64(S, 'catch', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 56, Ss, Stack, T, Ts, Tzr);
-yeccpars2_64(S, 'not', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 62, Ss, Stack, T, Ts, Tzr);
-yeccpars2_64(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 67, Ss, Stack, T, Ts, Tzr);
-yeccpars2_64(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 68, Ss, Stack, T, Ts, Tzr);
-yeccpars2_64(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_13(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_65(S, string, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 65, Ss, Stack, T, Ts, Tzr);
-yeccpars2_65(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_strings(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-%% yeccpars2_66: see yeccpars2_45
-
-yeccpars2_67(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_max(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_68(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 44, Ss, Stack, T, Ts, Tzr);
-yeccpars2_68(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 45, Ss, Stack, T, Ts, Tzr);
-yeccpars2_68(S, '+', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 47, Ss, Stack, T, Ts, Tzr);
-yeccpars2_68(S, '-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 48, Ss, Stack, T, Ts, Tzr);
-yeccpars2_68(S, '.', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 49, Ss, Stack, T, Ts, Tzr);
-yeccpars2_68(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 52, Ss, Stack, T, Ts, Tzr);
-yeccpars2_68(S, 'bnot', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 54, Ss, Stack, T, Ts, Tzr);
-yeccpars2_68(S, 'catch', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 56, Ss, Stack, T, Ts, Tzr);
-yeccpars2_68(S, 'not', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 62, Ss, Stack, T, Ts, Tzr);
-yeccpars2_68(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 67, Ss, Stack, T, Ts, Tzr);
-yeccpars2_68(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 68, Ss, Stack, T, Ts, Tzr);
-yeccpars2_68(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 70, Ss, Stack, T, Ts, Tzr);
-yeccpars2_68(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_13(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_69(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 71, Ss, Stack, T, Ts, Tzr);
-yeccpars2_69(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_70(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_70_(Stack),
- yeccgoto_tuple(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_71(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_71_(Stack),
- yeccgoto_tuple(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_72(S, 'of', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 76, Ss, Stack, T, Ts, Tzr);
-yeccpars2_72(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_78(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_73(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_73_(Stack),
- yeccgoto_try_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_74: see yeccpars2_45
-
-yeccpars2_75(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 44, Ss, Stack, T, Ts, Tzr);
-yeccpars2_75(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 45, Ss, Stack, T, Ts, Tzr);
-yeccpars2_75(S, '+', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 47, Ss, Stack, T, Ts, Tzr);
-yeccpars2_75(S, '-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 48, Ss, Stack, T, Ts, Tzr);
-yeccpars2_75(S, '.', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 49, Ss, Stack, T, Ts, Tzr);
-yeccpars2_75(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 95, Ss, Stack, T, Ts, Tzr);
-yeccpars2_75(S, 'bnot', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 54, Ss, Stack, T, Ts, Tzr);
-yeccpars2_75(S, 'catch', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 56, Ss, Stack, T, Ts, Tzr);
-yeccpars2_75(S, 'not', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 62, Ss, Stack, T, Ts, Tzr);
-yeccpars2_75(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 96, Ss, Stack, T, Ts, Tzr);
-yeccpars2_75(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 68, Ss, Stack, T, Ts, Tzr);
-yeccpars2_75(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_13(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-%% yeccpars2_76: see yeccpars2_45
-
-yeccpars2_77(S, 'when', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 84, Ss, Stack, T, Ts, Tzr);
-yeccpars2_77(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_77_(Stack),
- yeccpars2_83(83, Cat, [77 | Ss], NewStack, T, Ts, Tzr).
-
-yeccpars2_78(S, 'after', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 74, Ss, Stack, T, Ts, Tzr);
-yeccpars2_78(S, 'catch', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 75, Ss, Stack, T, Ts, Tzr);
-yeccpars2_78(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_79(S, ';', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 80, Ss, Stack, T, Ts, Tzr);
-yeccpars2_79(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_79_(Stack),
- yeccgoto_cr_clauses(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_80: see yeccpars2_45
-
-yeccpars2_81(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_81_(Stack),
- yeccgoto_cr_clauses(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_82(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_82_(Stack),
- yeccgoto_try_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_83(S, '->', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 90, Ss, Stack, T, Ts, Tzr);
-yeccpars2_83(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_84: see yeccpars2_45
-
-yeccpars2_85(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_85_(Stack),
- yeccgoto_clause_guard(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_86(S, ';', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 87, Ss, Stack, T, Ts, Tzr);
-yeccpars2_86(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_86_(Stack),
- yeccgoto_guard(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_87: see yeccpars2_45
-
-yeccpars2_88(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_88_(Stack),
- yeccgoto_guard(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_89(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_89_(Stack),
- yeccgoto_cr_clause(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_90: see yeccpars2_45
-
-yeccpars2_91(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_91_(Stack),
- yeccgoto_clause_body(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_92(S, 'after', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 109, Ss, Stack, T, Ts, Tzr);
-yeccpars2_92(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 110, Ss, Stack, T, Ts, Tzr);
-yeccpars2_92(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_93(S, ';', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
-yeccpars2_93(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_93_(Stack),
- yeccgoto_try_clauses(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_94(S, 'when', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 84, Ss, Stack, T, Ts, Tzr);
-yeccpars2_94(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_94_(Stack),
- yeccpars2_83(105, Cat, [94 | Ss], NewStack, T, Ts, Tzr).
-
-yeccpars2_95(S, ':', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 101, Ss, Stack, T, Ts, Tzr);
-yeccpars2_95(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_atomic(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_96(S, ':', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 97, Ss, Stack, T, Ts, Tzr);
-yeccpars2_96(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_max(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-%% yeccpars2_97: see yeccpars2_45
-
-yeccpars2_98(S, 'when', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 84, Ss, Stack, T, Ts, Tzr);
-yeccpars2_98(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_98_(Stack),
- yeccpars2_83(99, Cat, [98 | Ss], NewStack, T, Ts, Tzr).
-
-%% yeccpars2_99: see yeccpars2_83
-
-yeccpars2_100(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_100_(Stack),
- yeccgoto_try_clause(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_101: see yeccpars2_45
-
-yeccpars2_102(S, 'when', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 84, Ss, Stack, T, Ts, Tzr);
-yeccpars2_102(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_102_(Stack),
- yeccpars2_83(103, Cat, [102 | Ss], NewStack, T, Ts, Tzr).
-
-%% yeccpars2_103: see yeccpars2_83
-
-yeccpars2_104(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_104_(Stack),
- yeccgoto_try_clause(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_105: see yeccpars2_83
-
-yeccpars2_106(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_106_(Stack),
- yeccgoto_try_clause(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_107: see yeccpars2_75
-
-yeccpars2_108(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_108_(Stack),
- yeccgoto_try_clauses(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_109: see yeccpars2_45
-
-yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_110_(Stack),
- yeccgoto_try_catch(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_111(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 112, Ss, Stack, T, Ts, Tzr);
-yeccpars2_111(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_112_(Stack),
- yeccgoto_try_catch(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_113(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 114, Ss, Stack, T, Ts, Tzr);
-yeccpars2_113(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_114_(Stack),
- yeccgoto_try_catch(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_115_(Stack),
- yeccgoto_strings(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_116(S, 'after', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 121, Ss, Stack, T, Ts, Tzr);
-yeccpars2_116(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 122, Ss, Stack, T, Ts, Tzr);
-yeccpars2_116(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_117: see yeccpars2_45
-
-%% yeccpars2_118: see yeccpars2_83
-
-yeccpars2_119(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 120, Ss, Stack, T, Ts, Tzr);
-yeccpars2_119(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_120_(Stack),
- yeccgoto_receive_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_121: see yeccpars2_45
-
-yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_122_(Stack),
- yeccgoto_receive_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_123: see yeccpars2_83
-
-yeccpars2_124(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 125, Ss, Stack, T, Ts, Tzr);
-yeccpars2_124(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_125_(Stack),
- yeccgoto_receive_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_126(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 141, Ss, Stack, T, Ts, Tzr);
-yeccpars2_126(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_127: see yeccpars2_45
-
-yeccpars2_128(S, '||', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 129, Ss, Stack, T, Ts, Tzr);
-yeccpars2_128(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_129: see yeccpars2_45
-
-yeccpars2_130(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 140, Ss, Stack, T, Ts, Tzr);
-yeccpars2_130(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_131(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 138, Ss, Stack, T, Ts, Tzr);
-yeccpars2_131(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_131_(Stack),
- yeccgoto_lc_exprs(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_132(S, '<-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 136, Ss, Stack, T, Ts, Tzr);
-yeccpars2_132(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_lc_expr(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_133(S, '<=', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 134, Ss, Stack, T, Ts, Tzr);
-yeccpars2_133(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_max(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-%% yeccpars2_134: see yeccpars2_45
-
-yeccpars2_135(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_135_(Stack),
- yeccgoto_lc_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_136: see yeccpars2_45
-
-yeccpars2_137(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_137_(Stack),
- yeccgoto_lc_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_138: see yeccpars2_45
-
-yeccpars2_139(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_139_(Stack),
- yeccgoto_lc_exprs(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_140(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_140_(Stack),
- yeccgoto_list_comprehension(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_141(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_141_(Stack),
- yeccgoto_query_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_142(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 148, Ss, Stack, T, Ts, Tzr);
-yeccpars2_142(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_143(S, ';', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 146, Ss, Stack, T, Ts, Tzr);
-yeccpars2_143(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_143_(Stack),
- yeccgoto_if_clauses(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_144: see yeccpars2_83
-
-yeccpars2_145(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_145_(Stack),
- yeccgoto_if_clause(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_146: see yeccpars2_45
-
-yeccpars2_147(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_147_(Stack),
- yeccgoto_if_clauses(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_148(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_148_(Stack),
- yeccgoto_if_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_149(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 163, Ss, Stack, T, Ts, Tzr);
-yeccpars2_149(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_150(S, ';', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 161, Ss, Stack, T, Ts, Tzr);
-yeccpars2_150(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_150_(Stack),
- yeccgoto_fun_clauses(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_151(S, 'when', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 84, Ss, Stack, T, Ts, Tzr);
-yeccpars2_151(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_151_(Stack),
- yeccpars2_83(159, Cat, [151 | Ss], NewStack, T, Ts, Tzr).
-
-yeccpars2_152(S, '/', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 153, Ss, Stack, T, Ts, Tzr);
-yeccpars2_152(S, ':', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 154, Ss, Stack, T, Ts, Tzr);
-yeccpars2_152(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_153(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 158, Ss, Stack, T, Ts, Tzr);
-yeccpars2_153(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_154(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 155, Ss, Stack, T, Ts, Tzr);
-yeccpars2_154(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_155(S, '/', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 156, Ss, Stack, T, Ts, Tzr);
-yeccpars2_155(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_156(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 157, Ss, Stack, T, Ts, Tzr);
-yeccpars2_156(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_157(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_157_(Stack),
- yeccgoto_fun_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_158(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_|Nss] = Ss,
- NewStack = yeccpars2_158_(Stack),
- yeccgoto_fun_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_159: see yeccpars2_83
-
-yeccpars2_160(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_160_(Stack),
- yeccgoto_fun_clause(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_161: see yeccpars2_10
-
-yeccpars2_162(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_162_(Stack),
- yeccgoto_fun_clauses(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_163(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_163_(Stack),
- yeccgoto_fun_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_164(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_164_(Stack),
- yeccgoto_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_165(S, 'of', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 166, Ss, Stack, T, Ts, Tzr);
-yeccpars2_165(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_166: see yeccpars2_45
-
-yeccpars2_167(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 168, Ss, Stack, T, Ts, Tzr);
-yeccpars2_167(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_168(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_168_(Stack),
- yeccgoto_case_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_169(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 170, Ss, Stack, T, Ts, Tzr);
-yeccpars2_169(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_170(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_170_(Stack),
- yeccgoto_expr_max(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_171(S, '||', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 129, Ss, Stack, T, Ts, Tzr);
-yeccpars2_171(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_179(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_172(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_172_(Stack),
- yeccgoto_list(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_173(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_173_(Stack),
- yeccgoto_list(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_174: see yeccpars2_45
-
-yeccpars2_175(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_175_(Stack),
- yeccgoto_tail(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_176: see yeccpars2_45
-
-yeccpars2_177(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 178, Ss, Stack, T, Ts, Tzr);
-yeccpars2_177(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_178(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_178_(Stack),
- yeccgoto_tail(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_179(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 174, Ss, Stack, T, Ts, Tzr);
-yeccpars2_179(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 175, Ss, Stack, T, Ts, Tzr);
-yeccpars2_179(S, '|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 176, Ss, Stack, T, Ts, Tzr);
-yeccpars2_179(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_180(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_180_(Stack),
- yeccgoto_tail(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_181(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 45, Ss, Stack, T, Ts, Tzr);
-yeccpars2_181(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 52, Ss, Stack, T, Ts, Tzr);
-yeccpars2_181(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 67, Ss, Stack, T, Ts, Tzr);
-yeccpars2_181(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 68, Ss, Stack, T, Ts, Tzr);
-yeccpars2_181(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_13(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_182(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_bit_expr(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_183(S, ':', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 195, Ss, Stack, T, Ts, Tzr);
-yeccpars2_183(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_183_(Stack),
- yeccpars2_194(194, Cat, [183 | Ss], NewStack, T, Ts, Tzr).
-
-yeccpars2_184(S, '||', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 191, Ss, Stack, T, Ts, Tzr);
-yeccpars2_184(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_expr_max(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_185(S, '>>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 190, Ss, Stack, T, Ts, Tzr);
-yeccpars2_185(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_186(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 188, Ss, Stack, T, Ts, Tzr);
-yeccpars2_186(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_186_(Stack),
- yeccgoto_bin_elements(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_187(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_187_(Stack),
- yeccgoto_binary(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_188(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 45, Ss, Stack, T, Ts, Tzr);
-yeccpars2_188(S, '+', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 47, Ss, Stack, T, Ts, Tzr);
-yeccpars2_188(S, '-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 48, Ss, Stack, T, Ts, Tzr);
-yeccpars2_188(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 52, Ss, Stack, T, Ts, Tzr);
-yeccpars2_188(S, 'bnot', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 54, Ss, Stack, T, Ts, Tzr);
-yeccpars2_188(S, 'not', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 62, Ss, Stack, T, Ts, Tzr);
-yeccpars2_188(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 67, Ss, Stack, T, Ts, Tzr);
-yeccpars2_188(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 68, Ss, Stack, T, Ts, Tzr);
-yeccpars2_188(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_13(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_189(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_189_(Stack),
- yeccgoto_bin_elements(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_190(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_190_(Stack),
- yeccgoto_binary(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_191: see yeccpars2_45
-
-yeccpars2_192(S, '>>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 193, Ss, Stack, T, Ts, Tzr);
-yeccpars2_192(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_193(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_193_(Stack),
- yeccgoto_binary_comprehension(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_194(S, '/', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 199, Ss, Stack, T, Ts, Tzr);
-yeccpars2_194(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_194_(Stack),
- yeccpars2_198(_S, Cat, [194 | Ss], NewStack, T, Ts, Tzr).
-
-%% yeccpars2_195: see yeccpars2_181
-
-yeccpars2_196(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_bit_size_expr(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_197(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_197_(Stack),
- yeccgoto_opt_bit_size_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_198(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_198_(Stack),
- yeccgoto_bin_element(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_199(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 202, Ss, Stack, T, Ts, Tzr);
-yeccpars2_199(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_200(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_200_(Stack),
- yeccgoto_opt_bit_type_list(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_201(S, '-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 205, Ss, Stack, T, Ts, Tzr);
-yeccpars2_201(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_201_(Stack),
- yeccgoto_bit_type_list(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_202(S, ':', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 203, Ss, Stack, T, Ts, Tzr);
-yeccpars2_202(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_202_(Stack),
- yeccgoto_bit_type(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_203(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 204, Ss, Stack, T, Ts, Tzr);
-yeccpars2_203(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_204(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_204_(Stack),
- yeccgoto_bit_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_205: see yeccpars2_199
-
-yeccpars2_206(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_206_(Stack),
- yeccgoto_bit_type_list(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_207(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_207_(Stack),
- yeccgoto_bit_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_208(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_208_(Stack),
- yeccgoto_expr_900(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_209(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 210, Ss, Stack, T, Ts, Tzr);
-yeccpars2_209(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_210(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_210_(Stack),
- yeccgoto_expr_max(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_211(S, '.', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 213, Ss, Stack, T, Ts, Tzr);
-yeccpars2_211(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 214, Ss, Stack, T, Ts, Tzr);
-yeccpars2_211(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_212(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_212_(Stack),
- yeccgoto_record_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_213(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 227, Ss, Stack, T, Ts, Tzr);
-yeccpars2_213(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_214(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 219, Ss, Stack, T, Ts, Tzr);
-yeccpars2_214(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_224(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_215(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 226, Ss, Stack, T, Ts, Tzr);
-yeccpars2_215(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_216(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 224, Ss, Stack, T, Ts, Tzr);
-yeccpars2_216(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_216_(Stack),
- yeccgoto_record_fields(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_217(S, '=', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 222, Ss, Stack, T, Ts, Tzr);
-yeccpars2_217(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_218(S, '=', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 220, Ss, Stack, T, Ts, Tzr);
-yeccpars2_218(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_219(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_219_(Stack),
- yeccgoto_record_tuple(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_220: see yeccpars2_45
-
-yeccpars2_221(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_221_(Stack),
- yeccgoto_record_field(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_222: see yeccpars2_45
-
-yeccpars2_223(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_223_(Stack),
- yeccgoto_record_field(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_224(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 217, Ss, Stack, T, Ts, Tzr);
-yeccpars2_224(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 218, Ss, Stack, T, Ts, Tzr);
-yeccpars2_224(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_225(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_225_(Stack),
- yeccgoto_record_fields(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_226(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_226_(Stack),
- yeccgoto_record_tuple(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_227(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_|Nss] = Ss,
- NewStack = yeccpars2_227_(Stack),
- yeccgoto_record_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_228: see yeccpars2_45
-
-yeccpars2_229(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_229_(Stack),
- yeccgoto_exprs(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_230(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 44, Ss, Stack, T, Ts, Tzr);
-yeccpars2_230(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 45, Ss, Stack, T, Ts, Tzr);
-yeccpars2_230(S, '+', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 47, Ss, Stack, T, Ts, Tzr);
-yeccpars2_230(S, '-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 48, Ss, Stack, T, Ts, Tzr);
-yeccpars2_230(S, '.', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 49, Ss, Stack, T, Ts, Tzr);
-yeccpars2_230(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 52, Ss, Stack, T, Ts, Tzr);
-yeccpars2_230(S, 'bnot', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 54, Ss, Stack, T, Ts, Tzr);
-yeccpars2_230(S, 'not', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 62, Ss, Stack, T, Ts, Tzr);
-yeccpars2_230(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 67, Ss, Stack, T, Ts, Tzr);
-yeccpars2_230(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 68, Ss, Stack, T, Ts, Tzr);
-yeccpars2_230(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_13(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-%% yeccpars2_231: see yeccpars2_230
-
-yeccpars2_232(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_232_(Stack),
- yeccgoto_expr_100(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_233(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_233_(Stack),
- yeccgoto_expr_100(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_234: see yeccpars2_230
-
-yeccpars2_235(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_235_(Stack),
- yeccgoto_expr_150(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_236: see yeccpars2_230
-
-yeccpars2_237(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_237_(Stack),
- yeccgoto_expr_160(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_238: see yeccpars2_230
-
-yeccpars2_239(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_comp_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_240(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_comp_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_241(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_comp_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_242(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_comp_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_243(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_comp_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_244(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_comp_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_245(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_comp_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_246(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_comp_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_247(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_247_(Stack),
- yeccgoto_expr_200(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_248: see yeccpars2_230
-
-%% yeccpars2_249: see yeccpars2_230
-
-yeccpars2_250(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_add_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_251(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_list_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_252(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_add_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_253(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_list_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_254(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_add_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_255(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_add_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_256(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_add_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_257(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_add_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_258(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_add_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_259(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_add_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_260(S, '*', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 262, Ss, Stack, T, Ts, Tzr);
-yeccpars2_260(S, '/', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 263, Ss, Stack, T, Ts, Tzr);
-yeccpars2_260(S, 'and', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 264, Ss, Stack, T, Ts, Tzr);
-yeccpars2_260(S, 'band', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 265, Ss, Stack, T, Ts, Tzr);
-yeccpars2_260(S, 'div', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 266, Ss, Stack, T, Ts, Tzr);
-yeccpars2_260(S, 'rem', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 267, Ss, Stack, T, Ts, Tzr);
-yeccpars2_260(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_260_(Stack),
- yeccgoto_expr_400(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_261: see yeccpars2_230
-
-yeccpars2_262(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_mult_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_263(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_mult_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_264(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_mult_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_265(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_mult_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_266(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_mult_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_267(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_mult_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_268(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_268_(Stack),
- yeccgoto_expr_500(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_269(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_269_(Stack),
- yeccgoto_expr_300(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_270(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_270_(Stack),
- yeccgoto_function_call(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_271(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 274, Ss, Stack, T, Ts, Tzr);
-yeccpars2_271(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_272: see yeccpars2_181
-
-yeccpars2_273(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_273_(Stack),
- yeccgoto_expr_800(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_274(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_274_(Stack),
- yeccgoto_expr_900(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_275(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 276, Ss, Stack, T, Ts, Tzr);
-yeccpars2_275(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_276(S, '.', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 278, Ss, Stack, T, Ts, Tzr);
-yeccpars2_276(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 214, Ss, Stack, T, Ts, Tzr);
-yeccpars2_276(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_277(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_|Nss] = Ss,
- NewStack = yeccpars2_277_(Stack),
- yeccgoto_record_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_278(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 279, Ss, Stack, T, Ts, Tzr);
-yeccpars2_278(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_279(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_279_(Stack),
- yeccgoto_record_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_280(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_280_(Stack),
- yeccgoto_argument_list(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_281(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_281_(Stack),
- yeccgoto_expr_600(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_282(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 283, Ss, Stack, T, Ts, Tzr);
-yeccpars2_282(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_283(S, '.', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 285, Ss, Stack, T, Ts, Tzr);
-yeccpars2_283(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 214, Ss, Stack, T, Ts, Tzr);
-yeccpars2_283(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_284(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_|Nss] = Ss,
- NewStack = yeccpars2_284_(Stack),
- yeccgoto_record_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_285(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 286, Ss, Stack, T, Ts, Tzr);
-yeccpars2_285(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_286(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_286_(Stack),
- yeccgoto_record_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_287(S, '->', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 90, Ss, Stack, T, Ts, Tzr);
-yeccpars2_287(S, ':-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 290, Ss, Stack, T, Ts, Tzr);
-yeccpars2_287(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_288(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_|Nss] = Ss,
- NewStack = yeccpars2_288_(Stack),
- yeccgoto_rule_clause(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_289(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_|Nss] = Ss,
- NewStack = yeccpars2_289_(Stack),
- yeccgoto_function_clause(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_290: see yeccpars2_45
-
-yeccpars2_291(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_291_(Stack),
- yeccgoto_rule_body(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_292(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 44, Ss, Stack, T, Ts, Tzr);
-yeccpars2_292(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 428, Ss, Stack, T, Ts, Tzr);
-yeccpars2_292(S, '+', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 47, Ss, Stack, T, Ts, Tzr);
-yeccpars2_292(S, '-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 48, Ss, Stack, T, Ts, Tzr);
-yeccpars2_292(S, '.', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 49, Ss, Stack, T, Ts, Tzr);
-yeccpars2_292(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 52, Ss, Stack, T, Ts, Tzr);
-yeccpars2_292(S, 'bnot', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 54, Ss, Stack, T, Ts, Tzr);
-yeccpars2_292(S, 'catch', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 56, Ss, Stack, T, Ts, Tzr);
-yeccpars2_292(S, 'not', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 62, Ss, Stack, T, Ts, Tzr);
-yeccpars2_292(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 67, Ss, Stack, T, Ts, Tzr);
-yeccpars2_292(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 68, Ss, Stack, T, Ts, Tzr);
-yeccpars2_292(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_13(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_293(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 296, Ss, Stack, T, Ts, Tzr);
-yeccpars2_293(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 297, Ss, Stack, T, Ts, Tzr);
-yeccpars2_293(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_294(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_294_(Stack),
- yeccgoto_attribute(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_295(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 310, Ss, Stack, T, Ts, Tzr);
-yeccpars2_295(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_296(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 297, Ss, Stack, T, Ts, Tzr);
-yeccpars2_296(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_297(S, '/', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 298, Ss, Stack, T, Ts, Tzr);
-yeccpars2_297(S, ':', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 299, Ss, Stack, T, Ts, Tzr);
-yeccpars2_297(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_spec_fun(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_298(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 304, Ss, Stack, T, Ts, Tzr);
-yeccpars2_298(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_299(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 300, Ss, Stack, T, Ts, Tzr);
-yeccpars2_299(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_300(S, '/', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 301, Ss, Stack, T, Ts, Tzr);
-yeccpars2_300(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_300_(Stack),
- yeccgoto_spec_fun(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_301(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 302, Ss, Stack, T, Ts, Tzr);
-yeccpars2_301(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_302(S, '::', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 303, Ss, Stack, T, Ts, Tzr);
-yeccpars2_302(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_303(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_303_(Stack),
- yeccgoto_spec_fun(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_304(S, '::', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 305, Ss, Stack, T, Ts, Tzr);
-yeccpars2_304(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_305(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_|Nss] = Ss,
- NewStack = yeccpars2_305_(Stack),
- yeccgoto_spec_fun(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_306: see yeccpars2_295
-
-yeccpars2_307(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 423, Ss, Stack, T, Ts, Tzr);
-yeccpars2_307(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_308(S, ';', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 421, Ss, Stack, T, Ts, Tzr);
-yeccpars2_308(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_308_(Stack),
- yeccgoto_type_sigs(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_309(S, 'when', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 409, Ss, Stack, T, Ts, Tzr);
-yeccpars2_309(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_type_sig(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_310(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 323, Ss, Stack, T, Ts, Tzr);
-yeccpars2_310(S, '+', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 47, Ss, Stack, T, Ts, Tzr);
-yeccpars2_310(S, '-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 48, Ss, Stack, T, Ts, Tzr);
-yeccpars2_310(S, 'bnot', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 54, Ss, Stack, T, Ts, Tzr);
-yeccpars2_310(S, 'not', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 62, Ss, Stack, T, Ts, Tzr);
-yeccpars2_310(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 329, Ss, Stack, T, Ts, Tzr);
-yeccpars2_310(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_310(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_cont_310(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 321, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_310(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 322, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_310(S, '<<', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 324, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_310(S, '[', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 325, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_310(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 326, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_310(S, 'fun', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 327, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_310(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 328, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_310(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 330, Ss, Stack, T, Ts, Tzr);
-yeccpars2_cont_310(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_311(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_type_400(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_312(S, '*', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 262, Ss, Stack, T, Ts, Tzr);
-yeccpars2_312(S, '/', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 263, Ss, Stack, T, Ts, Tzr);
-yeccpars2_312(S, 'and', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 264, Ss, Stack, T, Ts, Tzr);
-yeccpars2_312(S, 'band', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 265, Ss, Stack, T, Ts, Tzr);
-yeccpars2_312(S, 'div', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 266, Ss, Stack, T, Ts, Tzr);
-yeccpars2_312(S, 'rem', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 267, Ss, Stack, T, Ts, Tzr);
-yeccpars2_312(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_type_300(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_313(S, '+', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 250, Ss, Stack, T, Ts, Tzr);
-yeccpars2_313(S, '-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 252, Ss, Stack, T, Ts, Tzr);
-yeccpars2_313(S, '..', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 404, Ss, Stack, T, Ts, Tzr);
-yeccpars2_313(S, 'bor', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 254, Ss, Stack, T, Ts, Tzr);
-yeccpars2_313(S, 'bsl', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 255, Ss, Stack, T, Ts, Tzr);
-yeccpars2_313(S, 'bsr', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 256, Ss, Stack, T, Ts, Tzr);
-yeccpars2_313(S, 'bxor', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 257, Ss, Stack, T, Ts, Tzr);
-yeccpars2_313(S, 'or', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 258, Ss, Stack, T, Ts, Tzr);
-yeccpars2_313(S, 'xor', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 259, Ss, Stack, T, Ts, Tzr);
-yeccpars2_313(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_type_200(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_314(S, '|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 401, Ss, Stack, T, Ts, Tzr);
-yeccpars2_314(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_top_type_100(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_315(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_type_500(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_316(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 398, Ss, Stack, T, Ts, Tzr);
-yeccpars2_316(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_317(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_top_type(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_318(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 396, Ss, Stack, T, Ts, Tzr);
-yeccpars2_318(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_318_(Stack),
- yeccgoto_top_types(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_319(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 336, Ss, Stack, T, Ts, Tzr);
-yeccpars2_319(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_310(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_type(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_321(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 384, Ss, Stack, T, Ts, Tzr);
-yeccpars2_321(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_322(S, '+', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 47, Ss, Stack, T, Ts, Tzr);
-yeccpars2_322(S, '-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 48, Ss, Stack, T, Ts, Tzr);
-yeccpars2_322(S, 'bnot', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 54, Ss, Stack, T, Ts, Tzr);
-yeccpars2_322(S, 'not', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 62, Ss, Stack, T, Ts, Tzr);
-yeccpars2_322(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 329, Ss, Stack, T, Ts, Tzr);
-yeccpars2_322(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_310(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_323(S, '->', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 380, Ss, Stack, T, Ts, Tzr);
-yeccpars2_323(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_324(S, '>>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 365, Ss, Stack, T, Ts, Tzr);
-yeccpars2_324(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 366, Ss, Stack, T, Ts, Tzr);
-yeccpars2_324(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_325(S, '+', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 47, Ss, Stack, T, Ts, Tzr);
-yeccpars2_325(S, '-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 48, Ss, Stack, T, Ts, Tzr);
-yeccpars2_325(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 358, Ss, Stack, T, Ts, Tzr);
-yeccpars2_325(S, 'bnot', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 54, Ss, Stack, T, Ts, Tzr);
-yeccpars2_325(S, 'not', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 62, Ss, Stack, T, Ts, Tzr);
-yeccpars2_325(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 329, Ss, Stack, T, Ts, Tzr);
-yeccpars2_325(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_310(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_326(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 347, Ss, Stack, T, Ts, Tzr);
-yeccpars2_326(S, ':', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 348, Ss, Stack, T, Ts, Tzr);
-yeccpars2_326(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_type(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_327(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 337, Ss, Stack, T, Ts, Tzr);
-yeccpars2_327(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_328(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_type(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_329(S, '::', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 334, Ss, Stack, T, Ts, Tzr);
-yeccpars2_329(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_type(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_330(S, '+', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 47, Ss, Stack, T, Ts, Tzr);
-yeccpars2_330(S, '-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 48, Ss, Stack, T, Ts, Tzr);
-yeccpars2_330(S, 'bnot', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 54, Ss, Stack, T, Ts, Tzr);
-yeccpars2_330(S, 'not', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 62, Ss, Stack, T, Ts, Tzr);
-yeccpars2_330(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 329, Ss, Stack, T, Ts, Tzr);
-yeccpars2_330(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 332, Ss, Stack, T, Ts, Tzr);
-yeccpars2_330(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_310(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_331(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 333, Ss, Stack, T, Ts, Tzr);
-yeccpars2_331(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_332(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_332_(Stack),
- yeccgoto_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_333(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_333_(Stack),
- yeccgoto_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_334(S, '+', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 47, Ss, Stack, T, Ts, Tzr);
-yeccpars2_334(S, '-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 48, Ss, Stack, T, Ts, Tzr);
-yeccpars2_334(S, 'bnot', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 54, Ss, Stack, T, Ts, Tzr);
-yeccpars2_334(S, 'not', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 62, Ss, Stack, T, Ts, Tzr);
-yeccpars2_334(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 336, Ss, Stack, T, Ts, Tzr);
-yeccpars2_334(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_310(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_335(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_335_(Stack),
- yeccgoto_top_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_336(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_type(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_337(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 340, Ss, Stack, T, Ts, Tzr);
-yeccpars2_337(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 341, Ss, Stack, T, Ts, Tzr);
-yeccpars2_337(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_338(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 346, Ss, Stack, T, Ts, Tzr);
-yeccpars2_338(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_339(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_fun_type_100(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_340(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 323, Ss, Stack, T, Ts, Tzr);
-yeccpars2_340(S, '+', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 47, Ss, Stack, T, Ts, Tzr);
-yeccpars2_340(S, '-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 48, Ss, Stack, T, Ts, Tzr);
-yeccpars2_340(S, '...', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 342, Ss, Stack, T, Ts, Tzr);
-yeccpars2_340(S, 'bnot', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 54, Ss, Stack, T, Ts, Tzr);
-yeccpars2_340(S, 'not', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 62, Ss, Stack, T, Ts, Tzr);
-yeccpars2_340(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 329, Ss, Stack, T, Ts, Tzr);
-yeccpars2_340(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_310(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_341(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_341_(Stack),
- yeccgoto_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_342(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 343, Ss, Stack, T, Ts, Tzr);
-yeccpars2_342(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_343(S, '->', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 344, Ss, Stack, T, Ts, Tzr);
-yeccpars2_343(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_344: see yeccpars2_322
-
-yeccpars2_345(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_345_(Stack),
- yeccgoto_fun_type_100(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_346(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_|Nss] = Ss,
- NewStack = yeccpars2_346_(Stack),
- yeccgoto_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_347(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 355, Ss, Stack, T, Ts, Tzr);
-yeccpars2_347(S, '+', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 47, Ss, Stack, T, Ts, Tzr);
-yeccpars2_347(S, '-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 48, Ss, Stack, T, Ts, Tzr);
-yeccpars2_347(S, 'bnot', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 54, Ss, Stack, T, Ts, Tzr);
-yeccpars2_347(S, 'not', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 62, Ss, Stack, T, Ts, Tzr);
-yeccpars2_347(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 329, Ss, Stack, T, Ts, Tzr);
-yeccpars2_347(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_310(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_348(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 349, Ss, Stack, T, Ts, Tzr);
-yeccpars2_348(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_349(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 350, Ss, Stack, T, Ts, Tzr);
-yeccpars2_349(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_350(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 352, Ss, Stack, T, Ts, Tzr);
-yeccpars2_350(S, '+', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 47, Ss, Stack, T, Ts, Tzr);
-yeccpars2_350(S, '-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 48, Ss, Stack, T, Ts, Tzr);
-yeccpars2_350(S, 'bnot', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 54, Ss, Stack, T, Ts, Tzr);
-yeccpars2_350(S, 'not', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 62, Ss, Stack, T, Ts, Tzr);
-yeccpars2_350(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 329, Ss, Stack, T, Ts, Tzr);
-yeccpars2_350(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_310(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_351(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 353, Ss, Stack, T, Ts, Tzr);
-yeccpars2_351(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_352(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_352_(Stack),
- yeccgoto_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_353(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_353_(Stack),
- yeccgoto_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_354(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 356, Ss, Stack, T, Ts, Tzr);
-yeccpars2_354(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_355(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_355_(Stack),
- yeccgoto_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_356(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_|Nss] = Ss,
- NewStack = yeccpars2_356_(Stack),
- yeccgoto_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_357(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 359, Ss, Stack, T, Ts, Tzr);
-yeccpars2_357(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 360, Ss, Stack, T, Ts, Tzr);
-yeccpars2_357(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_358(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_358_(Stack),
- yeccgoto_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_359(S, '...', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 361, Ss, Stack, T, Ts, Tzr);
-yeccpars2_359(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_360(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_360_(Stack),
- yeccgoto_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_361(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 362, Ss, Stack, T, Ts, Tzr);
-yeccpars2_361(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_362(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_362_(Stack),
- yeccgoto_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_363(S, '>>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 379, Ss, Stack, T, Ts, Tzr);
-yeccpars2_363(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_364(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 372, Ss, Stack, T, Ts, Tzr);
-yeccpars2_364(S, '>>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 373, Ss, Stack, T, Ts, Tzr);
-yeccpars2_364(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_365(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_365_(Stack),
- yeccgoto_binary_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_366(S, ':', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 367, Ss, Stack, T, Ts, Tzr);
-yeccpars2_366(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_367(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 369, Ss, Stack, T, Ts, Tzr);
-yeccpars2_367(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_310(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccpars2_368(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_368_(Stack),
- yeccgoto_bin_base_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_369(S, '*', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 370, Ss, Stack, T, Ts, Tzr);
-yeccpars2_369(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_type(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
-
-%% yeccpars2_370: see yeccpars2_319
-
-yeccpars2_371(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_371_(Stack),
- yeccgoto_bin_unit_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_372(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 375, Ss, Stack, T, Ts, Tzr);
-yeccpars2_372(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_373(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_373_(Stack),
- yeccgoto_binary_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_374(S, '>>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 378, Ss, Stack, T, Ts, Tzr);
-yeccpars2_374(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_375(S, ':', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 376, Ss, Stack, T, Ts, Tzr);
-yeccpars2_375(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_376(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 377, Ss, Stack, T, Ts, Tzr);
-yeccpars2_376(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_377(S, '*', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 370, Ss, Stack, T, Ts, Tzr);
-yeccpars2_377(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_378(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_378_(Stack),
- yeccgoto_binary_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_379(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_379_(Stack),
- yeccgoto_binary_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_380: see yeccpars2_322
-
-yeccpars2_381(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_|Nss] = Ss,
- NewStack = yeccpars2_381_(Stack),
- yeccgoto_fun_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_382(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 383, Ss, Stack, T, Ts, Tzr);
-yeccpars2_382(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_383(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_383_(Stack),
- yeccgoto_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_384(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 385, Ss, Stack, T, Ts, Tzr);
-yeccpars2_384(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_385(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 388, Ss, Stack, T, Ts, Tzr);
-yeccpars2_385(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 389, Ss, Stack, T, Ts, Tzr);
-yeccpars2_385(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_386(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 394, Ss, Stack, T, Ts, Tzr);
-yeccpars2_386(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_387(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 392, Ss, Stack, T, Ts, Tzr);
-yeccpars2_387(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_387_(Stack),
- yeccgoto_field_types(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_388(S, '::', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 390, Ss, Stack, T, Ts, Tzr);
-yeccpars2_388(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_389(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_|Nss] = Ss,
- NewStack = yeccpars2_389_(Stack),
- yeccgoto_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_390: see yeccpars2_322
-
-yeccpars2_391(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_391_(Stack),
- yeccgoto_field_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_392(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 388, Ss, Stack, T, Ts, Tzr);
-yeccpars2_392(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_393(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_393_(Stack),
- yeccgoto_field_types(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_394(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_394_(Stack),
- yeccgoto_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_395(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_395_(Stack),
- yeccgoto_type_500(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_396: see yeccpars2_322
-
-yeccpars2_397(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_397_(Stack),
- yeccgoto_top_types(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_398(S, '->', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 399, Ss, Stack, T, Ts, Tzr);
-yeccpars2_398(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_399: see yeccpars2_322
-
-yeccpars2_400(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_400_(Stack),
- yeccgoto_fun_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_401: see yeccpars2_334
-
-yeccpars2_402(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_402_(Stack),
- yeccgoto_top_type_100(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_403: see yeccpars2_334
-
-%% yeccpars2_404: see yeccpars2_334
-
-yeccpars2_405(S, '+', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 250, Ss, Stack, T, Ts, Tzr);
-yeccpars2_405(S, '-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 252, Ss, Stack, T, Ts, Tzr);
-yeccpars2_405(S, 'bor', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 254, Ss, Stack, T, Ts, Tzr);
-yeccpars2_405(S, 'bsl', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 255, Ss, Stack, T, Ts, Tzr);
-yeccpars2_405(S, 'bsr', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 256, Ss, Stack, T, Ts, Tzr);
-yeccpars2_405(S, 'bxor', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 257, Ss, Stack, T, Ts, Tzr);
-yeccpars2_405(S, 'or', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 258, Ss, Stack, T, Ts, Tzr);
-yeccpars2_405(S, 'xor', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 259, Ss, Stack, T, Ts, Tzr);
-yeccpars2_405(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_405_(Stack),
- yeccgoto_type_200(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_406(S, '*', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 262, Ss, Stack, T, Ts, Tzr);
-yeccpars2_406(S, '/', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 263, Ss, Stack, T, Ts, Tzr);
-yeccpars2_406(S, 'and', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 264, Ss, Stack, T, Ts, Tzr);
-yeccpars2_406(S, 'band', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 265, Ss, Stack, T, Ts, Tzr);
-yeccpars2_406(S, 'div', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 266, Ss, Stack, T, Ts, Tzr);
-yeccpars2_406(S, 'rem', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 267, Ss, Stack, T, Ts, Tzr);
-yeccpars2_406(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_406_(Stack),
- yeccgoto_type_300(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_407: see yeccpars2_334
-
-yeccpars2_408(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_408_(Stack),
- yeccgoto_type_400(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_409(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 412, Ss, Stack, T, Ts, Tzr);
-yeccpars2_409(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 413, Ss, Stack, T, Ts, Tzr);
-yeccpars2_409(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_410(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_410_(Stack),
- yeccgoto_type_sig(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_411(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 419, Ss, Stack, T, Ts, Tzr);
-yeccpars2_411(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_411_(Stack),
- yeccgoto_type_guards(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_412(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 416, Ss, Stack, T, Ts, Tzr);
-yeccpars2_412(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_413(S, '::', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 414, Ss, Stack, T, Ts, Tzr);
-yeccpars2_413(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_414: see yeccpars2_322
-
-yeccpars2_415(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_415_(Stack),
- yeccgoto_type_guard(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_416: see yeccpars2_322
-
-yeccpars2_417(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 418, Ss, Stack, T, Ts, Tzr);
-yeccpars2_417(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_418(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_|Nss] = Ss,
- NewStack = yeccpars2_418_(Stack),
- yeccgoto_type_guard(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_419: see yeccpars2_409
-
-yeccpars2_420(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_420_(Stack),
- yeccgoto_type_guards(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_421: see yeccpars2_295
-
-yeccpars2_422(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_422_(Stack),
- yeccgoto_type_sigs(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_423(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_|Nss] = Ss,
- NewStack = yeccpars2_423_(Stack),
- yeccgoto_type_spec(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_424(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_424_(Stack),
- yeccgoto_type_spec(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_425(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_425_(Stack),
- yeccgoto_attribute(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_426(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 450, Ss, Stack, T, Ts, Tzr);
-yeccpars2_426(S, '::', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 432, Ss, Stack, T, Ts, Tzr);
-yeccpars2_426(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_426_(Stack),
- yeccgoto_attr_val(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_427(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_427_(Stack),
- yeccgoto_attribute(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_428: see yeccpars2_45
-
-yeccpars2_429(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 449, Ss, Stack, T, Ts, Tzr);
-yeccpars2_429(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_430(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 210, Ss, Stack, T, Ts, Tzr);
-yeccpars2_430(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 431, Ss, Stack, T, Ts, Tzr);
-yeccpars2_430(S, '::', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 432, Ss, Stack, T, Ts, Tzr);
-yeccpars2_430(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_431(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 44, Ss, Stack, T, Ts, Tzr);
-yeccpars2_431(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 45, Ss, Stack, T, Ts, Tzr);
-yeccpars2_431(S, '+', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 47, Ss, Stack, T, Ts, Tzr);
-yeccpars2_431(S, '-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 48, Ss, Stack, T, Ts, Tzr);
-yeccpars2_431(S, '.', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 49, Ss, Stack, T, Ts, Tzr);
-yeccpars2_431(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 52, Ss, Stack, T, Ts, Tzr);
-yeccpars2_431(S, 'bnot', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 54, Ss, Stack, T, Ts, Tzr);
-yeccpars2_431(S, 'catch', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 56, Ss, Stack, T, Ts, Tzr);
-yeccpars2_431(S, 'not', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 62, Ss, Stack, T, Ts, Tzr);
-yeccpars2_431(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 67, Ss, Stack, T, Ts, Tzr);
-yeccpars2_431(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 436, Ss, Stack, T, Ts, Tzr);
-yeccpars2_431(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_cont_13(S, Cat, Ss, Stack, T, Ts, Tzr).
-
-%% yeccpars2_432: see yeccpars2_322
-
-yeccpars2_433(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_433_(Stack),
- yeccgoto_typed_attr_val(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_434(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_434_(Stack),
- yeccgoto_typed_attr_val(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_435(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 448, Ss, Stack, T, Ts, Tzr);
-yeccpars2_435(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-%% yeccpars2_436: see yeccpars2_68
-
-yeccpars2_437(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 447, Ss, Stack, T, Ts, Tzr);
-yeccpars2_437(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_438(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 444, Ss, Stack, T, Ts, Tzr);
-yeccpars2_438(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_438_(Stack),
- yeccgoto_typed_exprs(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-yeccpars2_439(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 440, Ss, Stack, T, Ts, Tzr);
-yeccpars2_439(S, '::', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 441, Ss, Stack, T, Ts, Tzr);
-yeccpars2_439(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_439_(Stack),
- yeccgoto_exprs(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_440: see yeccpars2_45
-
-%% yeccpars2_441: see yeccpars2_322
-
-yeccpars2_442(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_442_(Stack),
- yeccgoto_typed_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_443(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_443_(Stack),
- yeccgoto_typed_exprs(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_444: see yeccpars2_45
-
-yeccpars2_445(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_445_(Stack),
- yeccgoto_typed_exprs(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_446(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_446_(Stack),
- yeccgoto_typed_exprs(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_447(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_447_(Stack),
- yeccgoto_typed_record_fields(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_448(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_448_(Stack),
- yeccgoto_attr_val(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_449(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_,_,_|Nss] = Ss,
- NewStack = yeccpars2_449_(Stack),
- yeccgoto_attribute(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_450: see yeccpars2_431
-
-yeccpars2_451(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_451_(Stack),
- yeccgoto_attr_val(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_452(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_452_(Stack),
- yeccgoto_form(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_453(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_453_(Stack),
- yeccgoto_form(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_454(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 456, Ss, Stack, T, Ts, Tzr);
-yeccpars2_454(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_455(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_455_(Stack),
- yeccgoto_function_clauses(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_456: see yeccpars2_10
-
-yeccpars2_457(S, 'when', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 84, Ss, Stack, T, Ts, Tzr);
-yeccpars2_457(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_457_(Stack),
- yeccpars2_83(458, Cat, [457 | Ss], NewStack, T, Ts, Tzr).
-
-%% yeccpars2_458: see yeccpars2_83
-
-yeccpars2_459(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_|Nss] = Ss,
- NewStack = yeccpars2_459_(Stack),
- yeccgoto_form(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-yeccpars2_460(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 462, Ss, Stack, T, Ts, Tzr);
-yeccpars2_460(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccpars2_461(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_461_(Stack),
- yeccgoto_rule_clauses(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-
-%% yeccpars2_462: see yeccpars2_10
-
-yeccpars2_463(S, 'when', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 84, Ss, Stack, T, Ts, Tzr);
-yeccpars2_463(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_463_(Stack),
- yeccpars2_464(464, Cat, [463 | Ss], NewStack, T, Ts, Tzr).
-
-yeccpars2_464(S, ':-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 290, Ss, Stack, T, Ts, Tzr);
-yeccpars2_464(_, _, _, _, T, _, _) ->
- yeccerror(T).
-
-yeccgoto_add_op(33, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_230(249, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_add_op(313, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_334(403, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_add_op(405, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_334(403, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_argument_list(10=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_12(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_argument_list(29=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_270(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_argument_list(59, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_151(151, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_argument_list(161, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_151(151, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_argument_list(456=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_12(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_argument_list(462=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_12(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_atomic(13=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(20=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(45=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(50=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(51=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(53=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(55=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(56=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(60=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(64=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(66=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(68=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(74=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(75=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(76=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(80=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(84=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(87=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(90=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(97=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(101=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(107=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(109=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(117=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(121=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(127=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(129=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(134=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(146=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(166=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(174=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(176=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(181=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(188=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(191=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(195=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(220=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(222=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(230=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(231=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(234=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(236=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(238=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(248=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(249=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(261=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(272=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(290=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(292=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(428=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(431=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(436=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(440=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(444=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_atomic(450=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_attr_val(292=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_427(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_attribute(0, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_8(8, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_bin_base_type(324, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_364(364, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_bin_element(50, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_186(186, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_bin_element(188, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_186(186, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_bin_elements(50, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_185(185, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_bin_elements(188=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_189(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_bin_unit_type(324, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_363(363, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_bin_unit_type(372, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_374(374, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_binary(13=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(20=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(45=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(50, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_184(184, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(51=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(53=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(55=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(56=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(60=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(64=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(66=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(68=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(74=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(75=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(76=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(80=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(84=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(87=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(90=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(97=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(101=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(107=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(109=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(117=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(121=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(127=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(129, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_133(133, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(134=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(138, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_133(133, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(146=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(166=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(174=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(176=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(181=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(188=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(191, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_133(133, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(195=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(220=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(222=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(230=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(231=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(234=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(236=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(238=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(248=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(249=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(261=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(272=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(290, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_133(133, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(292=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(428=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(431=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(436=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(440=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(444=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary(450=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_binary_comprehension(13=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(20=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(45=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(50=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(51=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(53=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(55=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(56=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(60=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(64=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(66=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(68=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(74=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(75=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(76=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(80=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(84=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(87=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(90=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(97=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(101=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(107=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(109=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(117=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(121=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(127=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(129=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(134=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(146=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(166=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(174=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(176=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(181=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(188=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(191=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(195=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(220=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(222=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(230=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(231=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(234=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(236=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(238=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(248=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(249=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(261=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(272=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(290=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(292=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(428=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(431=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(436=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(440=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(444=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_comprehension(450=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_binary_type(310=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_type(319=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_type(322=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_type(325=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_type(330=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_type(334=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_type(340=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_type(344=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_type(347=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_type(350=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_type(367=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_type(370=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_type(380=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_type(390=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_type(396=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_type(399=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_type(401=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_type(403=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_type(404=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_type(407=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_type(414=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_type(416=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_type(432=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_binary_type(441=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_bit_expr(50, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_183(183, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_bit_expr(188, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_183(183, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_bit_size_expr(195=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_197(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_bit_type(199, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_201(201, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_bit_type(205, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_201(201, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_bit_type_list(199=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_200(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_bit_type_list(205=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_206(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_case_expr(13=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(20=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(45=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(50=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(51=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(53=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(55=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(56=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(60=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(64=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(66=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(68=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(74=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(75=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(76=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(80=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(84=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(87=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(90=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(97=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(101=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(107=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(109=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(117=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(121=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(127=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(129=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(134=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(146=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(166=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(174=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(176=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(181=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(188=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(191=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(195=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(220=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(222=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(230=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(231=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(234=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(236=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(238=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(248=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(249=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(261=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(272=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(290=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(292=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(428=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(431=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(436=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(440=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(444=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_case_expr(450=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_clause_args(10, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_11(11, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_clause_args(456, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_457(457, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_clause_args(462, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_463(463, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_clause_body(83=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_89(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_clause_body(99=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_100(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_clause_body(103=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_104(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_clause_body(105=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_106(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_clause_body(118, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_119(119, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_clause_body(123, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_124(124, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_clause_body(144=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_145(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_clause_body(159=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_160(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_clause_body(287=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_289(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_clause_body(458=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_289(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_clause_guard(11, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_287(287, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_clause_guard(77, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_83(83, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_clause_guard(94, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_83(105, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_clause_guard(98, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_83(99, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_clause_guard(102, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_83(103, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_clause_guard(151, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_83(159, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_clause_guard(457, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_83(458, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_clause_guard(463, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_464(464, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_comp_op(34, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_230(238, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_cr_clause(64, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_79(79, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cr_clause(76, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_79(79, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cr_clause(80, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_79(79, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cr_clause(166, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_79(79, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_cr_clauses(64, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_116(116, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cr_clauses(76, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_78(78, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cr_clauses(80=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_81(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_cr_clauses(166, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_167(167, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_expr(13, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_39(39, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(45, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_209(209, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(51, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_171(171, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(53, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_39(39, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(55, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_165(165, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(56=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_164(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(60, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_39(39, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(64, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_77(77, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(66, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_39(39, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(68, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_39(39, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(74, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_39(39, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(75, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_94(94, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(76, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_77(77, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(80, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_77(77, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(84, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_39(39, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(87, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_39(39, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(90, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_39(39, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(97, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_98(98, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(101, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_102(102, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(107, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_94(94, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(109, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_39(39, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(117, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_83(118, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(121, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_83(123, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(127, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_128(128, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(129, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_132(132, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(134=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_135(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_137(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(138, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_132(132, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(146, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_39(39, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(166, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_77(77, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(174, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_179(179, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(176, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_177(177, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(191, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_132(132, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(220=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_221(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(222=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_223(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(228, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_39(39, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(290, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_132(132, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(292, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_426(426, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(428, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_430(430, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(431, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_39(39, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(436, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_439(439, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(440, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_439(439, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(444, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_439(439, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr(450, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_39(39, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_expr_100(13=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(45=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(51=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(53=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(55=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(56=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(60=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(64=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(66=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(68=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(74=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(75=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(76=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(80=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(84=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(87=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(90=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(97=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(101=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(107=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(109=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(117=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(121=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(127=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(129=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(134=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(146=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(166=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(174=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(176=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(191=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(220=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(222=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(230=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_233(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(231=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_232(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(290=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(292=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(428=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(431=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(436=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(440=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(444=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_100(450=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_expr_150(13, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(45, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(51, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(53, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(55, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(56, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(60, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(64, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(66, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(68, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(74, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(75, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(76, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(80, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(84, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(87, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(90, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(97, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(101, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(107, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(109, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(117, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(121, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(127, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(129, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(134, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(136, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(138, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(146, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(166, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(174, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(176, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(191, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(220, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(222, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(228, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(230, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(231, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(234=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_235(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(290, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(292, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(428, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(431, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(436, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(440, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(444, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_150(450, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_expr_160(13, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(45, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(51, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(53, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(55, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(56, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(60, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(64, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(66, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(68, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(74, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(75, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(76, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(80, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(84, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(87, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(90, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(97, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(101, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(107, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(109, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(117, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(121, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(127, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(129, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(134, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(136, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(138, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(146, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(166, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(174, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(176, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(191, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(220, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(222, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(228, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(230, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(231, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(234, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(236=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_237(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(290, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(292, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(428, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(431, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(436, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(440, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(444, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_160(450, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_expr_200(13, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(45, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(51, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(53, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(55, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(56, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(60, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(64, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(66, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(68, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(74, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(75, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(76, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(80, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(84, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(87, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(90, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(97, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(101, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(107, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(109, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(117, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(121, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(127, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(129, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(134, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(136, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(138, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(146, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(166, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(174, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(176, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(191, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(220, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(222, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(228, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(230, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(231, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(234, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(236, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(290, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(292, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(428, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(431, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(436, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(440, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(444, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_200(450, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_35(35, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_expr_300(13, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(45, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(51, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(53, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(55, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(56, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(60, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(64, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(66, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(68, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(74, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(75, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(76, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(80, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(84, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(87, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(90, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(97, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(101, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(107, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(109, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(117, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(121, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(127, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(129, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(134, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(136, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(138, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(146, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(166, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(174, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(176, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(191, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(220, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(222, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(228, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(230, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(231, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(234, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(236, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(238=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_247(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(248=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_269(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(290, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(292, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(428, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(431, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(436, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(440, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(444, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_300(450, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_34(34, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_expr_400(13, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(45, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(51, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(53, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(55, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(56, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(60, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(64, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(66, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(68, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(74, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(75, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(76, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(80, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(84, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(87, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(90, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(97, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(101, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(107, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(109, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(117, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(121, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(127, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(129, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(134, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(136, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(138, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(146, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(166, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(174, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(176, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(191, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(220, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(222, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(228, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(230, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(231, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(234, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(236, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(238, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(248, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(290, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(292, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(428, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(431, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(436, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(440, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(444, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_400(450, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_33(33, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_expr_500(13, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(45, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(51, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(53, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(55, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(56, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(60, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(64, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(66, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(68, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(74, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(75, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(76, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(80, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(84, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(87, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(90, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(97, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(101, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(107, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(109, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(117, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(121, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(127, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(129, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(134, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(136, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(138, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(146, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(166, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(174, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(176, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(191, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(220, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(222, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(228, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(230, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(231, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(234, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(236, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(238, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(248, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(249, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_260(260, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(290, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(292, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(428, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(431, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(436, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(440, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(444, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_500(450, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_32(32, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_expr_600(13=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(45=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(51=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(53=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(55=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(56=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(60=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(64=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(66=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(68=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(74=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(75=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(76=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(80=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(84=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(87=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(90=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(97=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(101=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(107=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(109=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(117=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(121=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(127=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(129=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(134=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(146=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(166=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(174=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(176=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(191=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(220=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(222=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(230=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(231=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(234=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(236=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(238=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(248=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(249=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(261=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_268(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(290=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(292=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(428=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(431=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(436=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(440=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(444=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_600(450=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_expr_700(13=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(20=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_281(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(45=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(51=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(53=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(55=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(56=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(60=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(64=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(66=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(68=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(74=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(75=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(76=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(80=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(84=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(87=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(90=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(97=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(101=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(107=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(109=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(117=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(121=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(127=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(129=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(134=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(146=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(166=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(174=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(176=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(191=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(220=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(222=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(230=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(231=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(234=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(236=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(238=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(248=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(249=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(261=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(290=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(292=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(428=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(431=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(436=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(440=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(444=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_700(450=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_expr_800(13, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(20, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(45, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(51, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(53, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(55, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(56, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(60, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(64, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(66, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(68, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(74, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(75, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(76, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(80, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(84, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(87, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(90, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(97, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(101, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(107, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(109, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(117, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(121, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(127, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(129, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(134, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(136, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(138, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(146, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(166, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(174, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(176, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(191, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(220, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(222, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(228, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(230, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(231, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(234, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(236, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(238, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(248, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(249, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(261, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(290, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(292, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(428, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(431, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(436, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(440, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(444, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_800(450, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_expr_900(13, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(20, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(45, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(51, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(53, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(55, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(56, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(60, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(64, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(66, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(68, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(74, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(75, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(76, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(80, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(84, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(87, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(90, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(97, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(101, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(107, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(109, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(117, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(121, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(127, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(129, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(134, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(136, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(138, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(146, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(166, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(174, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(176, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(191, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(220, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(222, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(228, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(230, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(231, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(234, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(236, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(238, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(248, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(249, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(261, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(290, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(292, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(428, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(431, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(436, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(440, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(444, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_900(450, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_28(28, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_expr_max(13, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(20, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(45, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(50=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_182(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(51, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(53, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(55, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(56, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(60, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(64, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(66, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(68, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(74, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(75, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(76, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(80, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(84, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(87, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(90, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(97, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(101, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(107, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(109, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(117, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(121, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(127, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(129, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(134, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(136, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(138, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(146, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(166, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(174, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(176, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(181=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_207(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(188=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_182(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(191, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(195=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_196(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(220, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(222, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(228, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(230, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(231, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(234, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(236, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(238, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(248, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(249, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(261, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(272=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_273(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(290, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(292, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(428, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(431, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(436, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(440, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(444, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_expr_max(450, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_27(27, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_exprs(13, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_26(26, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_exprs(53, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_169(169, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_exprs(60, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_86(86, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_exprs(66, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_72(72, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_exprs(68, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_69(69, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_exprs(74, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_113(113, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_exprs(84, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_86(86, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_exprs(87, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_86(86, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_exprs(90=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_91(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_exprs(109, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_111(111, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_exprs(146, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_86(86, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_exprs(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_229(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_exprs(431, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_435(435, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_exprs(436, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_69(69, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_exprs(440=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_229(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_exprs(444=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_446(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_exprs(450=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_451(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_field_type(385, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_387(387, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_field_type(392, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_387(387, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_field_types(385, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_386(386, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_field_types(392=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_393(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_form(0, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_7(7, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_fun_clause(59, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_150(150, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_clause(161, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_150(150, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_fun_clauses(59, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_149(149, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_clauses(161=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_162(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_fun_expr(13=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(20=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(45=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(50=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(51=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(53=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(55=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(56=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(60=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(64=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(66=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(68=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(74=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(75=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(76=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(80=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(84=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(87=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(90=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(97=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(101=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(107=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(109=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(117=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(121=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(127=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(129=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(134=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(146=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(166=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(174=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(176=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(181=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(188=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(191=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(195=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(220=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(222=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(230=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(231=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(234=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(236=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(238=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(248=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(249=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(261=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(272=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(290=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(292=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(428=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(431=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(436=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(440=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(444=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_expr(450=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_fun_type(295, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_309(309, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_type(306, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_309(309, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_type(337=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_339(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_fun_type(421, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_309(309, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_fun_type_100(337, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_338(338, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_function(0, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_6(6, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_function_call(13=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(20=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(45=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(51=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(53=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(55=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(56=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(60=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(64=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(66=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(68=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(74=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(75=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(76=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(80=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(84=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(87=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(90=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(97=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(101=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(107=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(109=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(117=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(121=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(127=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(129=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(134=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(146=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(166=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(174=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(176=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(191=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(220=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(222=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(230=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(231=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(234=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(236=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(238=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(248=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(249=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(261=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(290=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(292=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(428=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(431=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(436=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(440=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(444=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_call(450=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_function_clause(0, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_5(5, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_clause(454, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_5(5, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_function_clauses(0=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_4(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_function_clauses(454=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_455(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_guard(60, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_83(144, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_guard(84=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_85(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_guard(87=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_88(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_guard(146, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_83(144, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_if_clause(60, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_143(143, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_clause(146, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_143(143, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_if_clauses(60, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_142(142, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_clauses(146=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_147(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_if_expr(13=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(20=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(45=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(50=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(51=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(53=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(55=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(56=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(60=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(64=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(66=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(68=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(74=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(75=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(76=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(80=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(84=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(87=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(90=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(97=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(101=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(107=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(109=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(117=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(121=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(127=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(129=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(134=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(146=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(166=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(174=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(176=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(181=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(188=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(191=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(195=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(220=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(222=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(230=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(231=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(234=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(236=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(238=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(248=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(249=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(261=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(272=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(290=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(292=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(428=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(431=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(436=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(440=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(444=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_if_expr(450=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_lc_expr(129, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_131(131, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_lc_expr(138, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_131(131, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_lc_expr(191, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_131(131, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_lc_expr(290, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_131(131, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_lc_exprs(129, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_130(130, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_lc_exprs(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_139(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_lc_exprs(191, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_192(192, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_lc_exprs(290=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_291(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_list(13=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(20=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(45=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(50=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(51=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(53=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(55=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(56=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(60=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(64=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(66=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(68=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(74=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(75=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(76=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(80=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(84=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(87=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(90=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(97=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(101=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(107=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(109=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(117=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(121=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(127=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(129=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(134=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(146=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(166=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(174=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(176=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(181=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(188=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(191=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(195=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(220=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(222=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(230=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(231=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(234=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(236=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(238=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(248=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(249=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(261=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(272=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(290=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(292=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(428=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(431=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(436=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(440=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(444=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list(450=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_list_comprehension(13=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(20=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(45=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(50=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(51=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(53=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(55=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(56=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(60=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(63, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_126(126, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(64=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(66=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(68=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(74=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(75=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(76=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(80=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(84=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(87=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(90=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(97=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(101=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(107=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(109=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(117=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(121=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(127=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(129=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(134=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(146=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(166=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(174=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(176=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(181=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(188=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(191=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(195=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(220=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(222=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(230=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(231=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(234=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(236=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(238=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(248=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(249=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(261=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(272=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(290=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(292=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(428=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(431=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(436=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(440=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(444=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_list_comprehension(450=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_list_op(33, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_230(248, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_mult_op(32, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_230(261, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_mult_op(260, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_230(261, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_mult_op(312, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_334(407, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_mult_op(406, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_334(407, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_opt_bit_size_expr(183, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_194(194, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_opt_bit_type_list(194=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_198(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_prefix_op(13, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(45, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(50, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_181(181, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(51, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(53, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(55, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(56, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(60, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(64, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(66, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(68, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(74, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(75, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(76, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(80, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(84, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(87, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(90, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(97, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(101, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(107, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(109, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(117, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(121, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(127, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(129, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(134, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(136, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(138, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(146, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(166, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(174, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(176, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(188, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_181(181, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(191, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(220, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(222, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(228, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(230, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(231, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(234, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(236, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(238, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(248, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(249, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(261, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(290, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(292, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(310, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_319(319, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(322, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_319(319, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(325, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_319(319, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(330, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_319(319, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(334, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_319(319, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(340, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_319(319, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(344, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_319(319, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(347, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_319(319, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(350, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_319(319, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(380, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_319(319, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(390, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_319(319, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(396, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_319(319, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(399, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_319(319, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(401, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_319(319, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(403, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_319(319, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(404, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_319(319, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(407, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_319(319, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(414, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_319(319, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(416, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_319(319, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(428, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(431, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(432, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_319(319, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(436, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(440, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(441, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_319(319, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(444, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_prefix_op(450, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_query_expr(13=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(20=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(45=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(50=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(51=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(53=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(55=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(56=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(60=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(64=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(66=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(68=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(74=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(75=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(76=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(80=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(84=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(87=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(90=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(97=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(101=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(107=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(109=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(117=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(121=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(127=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(129=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(134=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(146=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(166=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(174=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(176=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(181=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(188=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(191=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(195=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(220=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(222=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(230=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(231=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(234=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(236=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(238=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(248=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(249=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(261=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(272=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(290=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(292=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(428=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(431=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(436=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(440=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(444=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_query_expr(450=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_receive_expr(13=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(20=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(45=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(50=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(51=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(53=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(55=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(56=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(60=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(64=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(66=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(68=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(74=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(75=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(76=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(80=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(84=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(87=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(90=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(97=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(101=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(107=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(109=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(117=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(121=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(127=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(129=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(134=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(146=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(166=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(174=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(176=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(181=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(188=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(191=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(195=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(220=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(222=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(230=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(231=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(234=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(236=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(238=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(248=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(249=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(261=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(272=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(290=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(292=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(428=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(431=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(436=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(440=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(444=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_receive_expr(450=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_record_expr(13, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(20, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(45, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(51, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(53, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(55, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(56, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(60, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(64, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(66, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(68, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(74, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(75, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(76, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(80, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(84, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(87, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(90, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(97, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(101, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(107, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(109, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(117, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(121, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(127, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(129, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(134, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(136, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(138, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(146, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(166, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(174, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(176, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(191, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(220, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(222, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(228, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(230, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(231, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(234, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(236, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(238, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(248, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(249, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(261, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(290, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(292, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(428, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(431, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(436, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(440, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(444, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_expr(450, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_record_field(214, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_216(216, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_field(224, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_216(216, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_record_fields(214, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_215(215, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_fields(224=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_225(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_record_tuple(211=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_212(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_tuple(276=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_277(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_record_tuple(283=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_284(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_rule(0, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_3(3, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_rule_body(287=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_288(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_rule_body(464=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_288(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_rule_clause(0, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_2(2, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_rule_clause(460, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_2(2, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_rule_clauses(0=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_1(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_rule_clauses(460=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_461(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_spec_fun(293, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_295(295, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_spec_fun(296, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_295(306, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_strings(13=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(20=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(45=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(50=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(51=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(53=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(55=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(56=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(60=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(64=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(65=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(66=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(68=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(74=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(75=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(76=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(80=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(84=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(87=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(90=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(97=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(101=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(107=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(109=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(117=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(121=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(127=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(129=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(134=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(146=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(166=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(174=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(176=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(181=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(188=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(191=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(195=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(220=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(222=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(230=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(231=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(234=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(236=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(238=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(248=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(249=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(261=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(272=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(290=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(292=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(428=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(431=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(436=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(440=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(444=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_strings(450=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_tail(171=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_173(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tail(179=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_180(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_top_type(310, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_318(318, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type(322, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_382(382, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type(325, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_357(357, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type(330, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_318(318, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type(340, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_318(318, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type(344=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_345(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type(347, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_318(318, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type(350, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_318(318, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type(380=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_381(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type(390=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_391(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type(396, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_318(318, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type(399=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_400(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type(414=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_415(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type(416, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_318(318, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type(432=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_433(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type(441=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_442(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_top_type_100(310=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_317(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type_100(322=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_317(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type_100(325=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_317(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type_100(330=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_317(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type_100(334=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_335(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type_100(340=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_317(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type_100(344=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_317(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type_100(347=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_317(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type_100(350=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_317(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type_100(380=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_317(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type_100(390=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_317(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type_100(396=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_317(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type_100(399=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_317(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type_100(401=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_402(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type_100(414=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_317(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type_100(416=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_317(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type_100(432=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_317(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_type_100(441=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_317(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_top_types(310, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_316(316, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_types(330, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_331(331, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_types(340, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_316(316, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_types(347, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_354(354, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_types(350, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_351(351, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_types(396=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_397(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_top_types(416, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_417(417, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_try_catch(72=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_73(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_catch(78=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_82(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_try_clause(75, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_93(93, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_clause(107, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_93(93, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_try_clauses(75, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_92(92, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_clauses(107=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_108(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_try_expr(13=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(20=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(45=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(50=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(51=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(53=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(55=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(56=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(60=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(64=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(66=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(68=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(74=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(75=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(76=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(80=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(84=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(87=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(90=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(97=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(101=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(107=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(109=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(117=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(121=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(127=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(129=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(134=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(146=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(166=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(174=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(176=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(181=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(188=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(191=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(195=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(220=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(222=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(230=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(231=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(234=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(236=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(238=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(248=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(249=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(261=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(272=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(290=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(292=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(428=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(431=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(436=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(440=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(444=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_try_expr(450=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_tuple(13=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(20=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(45=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(50=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(51=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(53=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(55=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(56=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(60=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(64=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(66=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(68=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(74=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(75=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(76=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(80=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(84=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(87=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(90=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(97=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(101=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(107=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(109=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(117=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(121=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(127=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(129=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(134=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(136=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(138=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(146=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(166=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(174=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(176=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(181=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(188=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(191=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(195=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(220=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(222=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(228=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(230=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(231=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(234=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(236=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(238=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(248=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(249=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(261=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(272=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(290=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(292=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(428=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(431=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(436=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(440=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(444=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_tuple(450=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_type(310=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_315(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type(319=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_395(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type(322=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_315(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type(325=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_315(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type(330=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_315(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type(334=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_315(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type(340=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_315(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type(344=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_315(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type(347=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_315(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type(350=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_315(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type(367=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_368(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type(370=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_371(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type(380=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_315(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type(390=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_315(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type(396=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_315(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type(399=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_315(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type(401=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_315(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type(403=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_315(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type(404=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_315(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type(407=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_315(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type(414=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_315(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type(416=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_315(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type(432=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_315(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type(441=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_315(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_type_200(310, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_314(314, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_200(322, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_314(314, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_200(325, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_314(314, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_200(330, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_314(314, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_200(334, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_314(314, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_200(340, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_314(314, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_200(344, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_314(314, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_200(347, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_314(314, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_200(350, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_314(314, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_200(380, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_314(314, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_200(390, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_314(314, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_200(396, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_314(314, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_200(399, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_314(314, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_200(401, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_314(314, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_200(414, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_314(314, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_200(416, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_314(314, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_200(432, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_314(314, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_200(441, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_314(314, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_type_300(310, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_313(313, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_300(322, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_313(313, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_300(325, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_313(313, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_300(330, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_313(313, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_300(334, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_313(313, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_300(340, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_313(313, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_300(344, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_313(313, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_300(347, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_313(313, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_300(350, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_313(313, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_300(380, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_313(313, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_300(390, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_313(313, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_300(396, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_313(313, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_300(399, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_313(313, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_300(401, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_313(313, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_300(404, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_405(405, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_300(414, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_313(313, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_300(416, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_313(313, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_300(432, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_313(313, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_300(441, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_313(313, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_type_400(310, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_312(312, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_400(322, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_312(312, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_400(325, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_312(312, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_400(330, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_312(312, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_400(334, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_312(312, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_400(340, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_312(312, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_400(344, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_312(312, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_400(347, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_312(312, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_400(350, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_312(312, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_400(380, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_312(312, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_400(390, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_312(312, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_400(396, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_312(312, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_400(399, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_312(312, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_400(401, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_312(312, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_400(403, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_406(406, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_400(404, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_312(312, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_400(414, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_312(312, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_400(416, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_312(312, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_400(432, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_312(312, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_400(441, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_312(312, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_type_500(310=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_311(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_500(322=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_311(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_500(325=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_311(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_500(330=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_311(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_500(334=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_311(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_500(340=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_311(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_500(344=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_311(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_500(347=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_311(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_500(350=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_311(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_500(380=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_311(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_500(390=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_311(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_500(396=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_311(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_500(399=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_311(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_500(401=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_311(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_500(403=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_311(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_500(404=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_311(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_500(407=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_408(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_500(414=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_311(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_500(416=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_311(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_500(432=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_311(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_500(441=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_311(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_type_guard(409, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_411(411, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_guard(419, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_411(411, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_type_guards(409=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_410(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_guards(419=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_420(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_type_sig(295, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_308(308, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_sig(306, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_308(308, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_sig(421, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_308(308, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_type_sigs(295=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_424(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_sigs(306, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_307(307, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_type_sigs(421=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_422(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_type_spec(293=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_294(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_typed_attr_val(292=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_425(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_typed_attr_val(428, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_429(429, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_typed_expr(436, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_438(438, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_typed_expr(440, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_438(438, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_typed_expr(444, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_438(438, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_typed_exprs(436, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_437(437, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_typed_exprs(440=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_443(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_typed_exprs(444=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_445(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
-yeccgoto_typed_record_fields(431=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_434(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_typed_record_fields(450=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_434(_S, Cat, Ss, Stack, T, Ts, Tzr).
-
--compile({inline,yeccpars2_1_/1}).
--file("erl_parse.yrl", 487).
-yeccpars2_1_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- build_rule ( __1 )
- end | __Stack].
-
--compile({inline,yeccpars2_2_/1}).
--file("erl_parse.yrl", 489).
-yeccpars2_2_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--compile({inline,yeccpars2_4_/1}).
--file("erl_parse.yrl", 197).
-yeccpars2_4_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- build_function ( __1 )
- end | __Stack].
-
--compile({inline,yeccpars2_5_/1}).
--file("erl_parse.yrl", 199).
-yeccpars2_5_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--compile({inline,yeccpars2_11_/1}).
--file("erl_parse.yrl", 209).
-yeccpars2_11_(__Stack0) ->
- [begin
- [ ]
- end | __Stack0].
-
--compile({inline,yeccpars2_12_/1}).
--file("erl_parse.yrl", 206).
-yeccpars2_12_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- element ( 1 , __1 )
- end | __Stack].
-
--compile({inline,yeccpars2_39_/1}).
--file("erl_parse.yrl", 438).
-yeccpars2_39_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8235).
--compile({inline,yeccpars2_46_/1}).
--file("erl_parse.yrl", 434).
-yeccpars2_46_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- { [ ] , ? line ( __1 ) }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8244).
--compile({inline,yeccpars2_70_/1}).
--file("erl_parse.yrl", 325).
-yeccpars2_70_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- { tuple , ? line ( __1 ) , [ ] }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8253).
--compile({inline,yeccpars2_71_/1}).
--file("erl_parse.yrl", 326).
-yeccpars2_71_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { tuple , ? line ( __1 ) , __2 }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8262).
--compile({inline,yeccpars2_73_/1}).
--file("erl_parse.yrl", 408).
-yeccpars2_73_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- build_try ( ? line ( __1 ) , __2 , [ ] , __3 )
- end | __Stack].
-
--compile({inline,yeccpars2_77_/1}).
--file("erl_parse.yrl", 209).
-yeccpars2_77_(__Stack0) ->
- [begin
- [ ]
- end | __Stack0].
-
--compile({inline,yeccpars2_79_/1}).
--file("erl_parse.yrl", 377).
-yeccpars2_79_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--compile({inline,yeccpars2_81_/1}).
--file("erl_parse.yrl", 378).
-yeccpars2_81_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8294).
--compile({inline,yeccpars2_82_/1}).
--file("erl_parse.yrl", 406).
-yeccpars2_82_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- build_try ( ? line ( __1 ) , __2 , __4 , __5 )
- end | __Stack].
-
--compile({inline,yeccpars2_85_/1}).
--file("erl_parse.yrl", 208).
-yeccpars2_85_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- __2
- end | __Stack].
-
--compile({inline,yeccpars2_86_/1}).
--file("erl_parse.yrl", 441).
-yeccpars2_86_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--compile({inline,yeccpars2_88_/1}).
--file("erl_parse.yrl", 442).
-yeccpars2_88_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8327).
--compile({inline,yeccpars2_89_/1}).
--file("erl_parse.yrl", 381).
-yeccpars2_89_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { clause , ? line ( __1 ) , [ __1 ] , __2 , __3 }
- end | __Stack].
-
--compile({inline,yeccpars2_91_/1}).
--file("erl_parse.yrl", 211).
-yeccpars2_91_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- __2
- end | __Stack].
-
--compile({inline,yeccpars2_93_/1}).
--file("erl_parse.yrl", 417).
-yeccpars2_93_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--compile({inline,yeccpars2_94_/1}).
--file("erl_parse.yrl", 209).
-yeccpars2_94_(__Stack0) ->
- [begin
- [ ]
- end | __Stack0].
-
--compile({inline,yeccpars2_98_/1}).
--file("erl_parse.yrl", 209).
-yeccpars2_98_(__Stack0) ->
- [begin
- [ ]
- end | __Stack0].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8366).
--compile({inline,yeccpars2_100_/1}).
--file("erl_parse.yrl", 427).
-yeccpars2_100_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- L = ? line ( __1 ) ,
- { clause , L , [ { tuple , L , [ __1 , __3 , { var , L , '_' } ] } ] , __4 , __5 }
- end | __Stack].
-
--compile({inline,yeccpars2_102_/1}).
--file("erl_parse.yrl", 209).
-yeccpars2_102_(__Stack0) ->
- [begin
- [ ]
- end | __Stack0].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8383).
--compile({inline,yeccpars2_104_/1}).
--file("erl_parse.yrl", 424).
-yeccpars2_104_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- L = ? line ( __1 ) ,
- { clause , L , [ { tuple , L , [ __1 , __3 , { var , L , '_' } ] } ] , __4 , __5 }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8393).
--compile({inline,yeccpars2_106_/1}).
--file("erl_parse.yrl", 421).
-yeccpars2_106_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- L = ? line ( __1 ) ,
- { clause , L , [ { tuple , L , [ { atom , L , throw } , __1 , { var , L , '_' } ] } ] , __2 , __3 }
- end | __Stack].
-
--compile({inline,yeccpars2_108_/1}).
--file("erl_parse.yrl", 418).
-yeccpars2_108_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--compile({inline,yeccpars2_110_/1}).
--file("erl_parse.yrl", 411).
-yeccpars2_110_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { __2 , [ ] }
- end | __Stack].
-
--compile({inline,yeccpars2_112_/1}).
--file("erl_parse.yrl", 413).
-yeccpars2_112_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { __2 , __4 }
- end | __Stack].
-
--compile({inline,yeccpars2_114_/1}).
--file("erl_parse.yrl", 415).
-yeccpars2_114_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { [ ] , __2 }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8435).
--compile({inline,yeccpars2_115_/1}).
--file("erl_parse.yrl", 452).
-yeccpars2_115_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- { string , ? line ( __1 ) , element ( 3 , __1 ) ++ element ( 3 , __2 ) }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8444).
--compile({inline,yeccpars2_120_/1}).
--file("erl_parse.yrl", 386).
-yeccpars2_120_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { 'receive' , ? line ( __1 ) , [ ] , __3 , __4 }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8453).
--compile({inline,yeccpars2_122_/1}).
--file("erl_parse.yrl", 384).
-yeccpars2_122_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { 'receive' , ? line ( __1 ) , __2 }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8462).
--compile({inline,yeccpars2_125_/1}).
--file("erl_parse.yrl", 388).
-yeccpars2_125_(__Stack0) ->
- [__6,__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { 'receive' , ? line ( __1 ) , __2 , __4 , __5 }
- end | __Stack].
-
--compile({inline,yeccpars2_131_/1}).
--file("erl_parse.yrl", 318).
-yeccpars2_131_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8479).
--compile({inline,yeccpars2_135_/1}).
--file("erl_parse.yrl", 323).
-yeccpars2_135_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { b_generate , ? line ( __2 ) , __1 , __3 }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8488).
--compile({inline,yeccpars2_137_/1}).
--file("erl_parse.yrl", 322).
-yeccpars2_137_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { generate , ? line ( __2 ) , __1 , __3 }
- end | __Stack].
-
--compile({inline,yeccpars2_139_/1}).
--file("erl_parse.yrl", 319).
-yeccpars2_139_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8505).
--compile({inline,yeccpars2_140_/1}).
--file("erl_parse.yrl", 315).
-yeccpars2_140_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { lc , ? line ( __1 ) , __2 , __4 }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8514).
--compile({inline,yeccpars2_141_/1}).
--file("erl_parse.yrl", 431).
-yeccpars2_141_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { 'query' , ? line ( __1 ) , __2 }
- end | __Stack].
-
--compile({inline,yeccpars2_143_/1}).
--file("erl_parse.yrl", 367).
-yeccpars2_143_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8531).
--compile({inline,yeccpars2_145_/1}).
--file("erl_parse.yrl", 371).
-yeccpars2_145_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- { clause , ? line ( hd ( hd ( __1 ) ) ) , [ ] , __1 , __2 }
- end | __Stack].
-
--compile({inline,yeccpars2_147_/1}).
--file("erl_parse.yrl", 368).
-yeccpars2_147_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8548).
--compile({inline,yeccpars2_148_/1}).
--file("erl_parse.yrl", 365).
-yeccpars2_148_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { 'if' , ? line ( __1 ) , __2 }
- end | __Stack].
-
--compile({inline,yeccpars2_150_/1}).
--file("erl_parse.yrl", 398).
-yeccpars2_150_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--compile({inline,yeccpars2_151_/1}).
--file("erl_parse.yrl", 209).
-yeccpars2_151_(__Stack0) ->
- [begin
- [ ]
- end | __Stack0].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8572).
--compile({inline,yeccpars2_157_/1}).
--file("erl_parse.yrl", 394).
-yeccpars2_157_(__Stack0) ->
- [__6,__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { 'fun' , ? line ( __1 ) , { function , element ( 3 , __2 ) , element ( 3 , __4 ) , element ( 3 , __6 ) } }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8581).
--compile({inline,yeccpars2_158_/1}).
--file("erl_parse.yrl", 392).
-yeccpars2_158_(__Stack0) ->
- [__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { 'fun' , ? line ( __1 ) , { function , element ( 3 , __2 ) , element ( 3 , __4 ) } }
- end | __Stack].
-
--compile({inline,yeccpars2_160_/1}).
--file("erl_parse.yrl", 402).
-yeccpars2_160_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { Args , Pos } = __1 ,
- { clause , Pos , 'fun' , Args , __2 , __3 }
- end | __Stack].
-
--compile({inline,yeccpars2_162_/1}).
--file("erl_parse.yrl", 399).
-yeccpars2_162_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8607).
--compile({inline,yeccpars2_163_/1}).
--file("erl_parse.yrl", 396).
-yeccpars2_163_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- build_fun ( ? line ( __1 ) , __2 )
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8616).
--compile({inline,yeccpars2_164_/1}).
--file("erl_parse.yrl", 214).
-yeccpars2_164_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- { 'catch' , ? line ( __1 ) , __2 }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8625).
--compile({inline,yeccpars2_168_/1}).
--file("erl_parse.yrl", 375).
-yeccpars2_168_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { 'case' , ? line ( __1 ) , __2 , __4 }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8634).
--compile({inline,yeccpars2_170_/1}).
--file("erl_parse.yrl", 270).
-yeccpars2_170_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { block , ? line ( __1 ) , __2 }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8643).
--compile({inline,yeccpars2_172_/1}).
--file("erl_parse.yrl", 279).
-yeccpars2_172_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- { nil , ? line ( __1 ) }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8652).
--compile({inline,yeccpars2_173_/1}).
--file("erl_parse.yrl", 280).
-yeccpars2_173_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { cons , ? line ( __1 ) , __2 , __3 }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8661).
--compile({inline,yeccpars2_175_/1}).
--file("erl_parse.yrl", 282).
-yeccpars2_175_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- { nil , ? line ( __1 ) }
- end | __Stack].
-
--compile({inline,yeccpars2_178_/1}).
--file("erl_parse.yrl", 283).
-yeccpars2_178_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- __2
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8678).
--compile({inline,yeccpars2_180_/1}).
--file("erl_parse.yrl", 284).
-yeccpars2_180_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { cons , ? line ( __2 ) , __2 , __3 }
- end | __Stack].
-
--compile({inline,yeccpars2_183_/1}).
--file("erl_parse.yrl", 300).
-yeccpars2_183_(__Stack0) ->
- [begin
- default
- end | __Stack0].
-
--compile({inline,yeccpars2_186_/1}).
--file("erl_parse.yrl", 290).
-yeccpars2_186_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8702).
--compile({inline,yeccpars2_187_/1}).
--file("erl_parse.yrl", 287).
-yeccpars2_187_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- { bin , ? line ( __1 ) , [ ] }
- end | __Stack].
-
--compile({inline,yeccpars2_189_/1}).
--file("erl_parse.yrl", 291).
-yeccpars2_189_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8719).
--compile({inline,yeccpars2_190_/1}).
--file("erl_parse.yrl", 288).
-yeccpars2_190_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { bin , ? line ( __1 ) , __2 }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8728).
--compile({inline,yeccpars2_193_/1}).
--file("erl_parse.yrl", 317).
-yeccpars2_193_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { bc , ? line ( __1 ) , __2 , __4 }
- end | __Stack].
-
--compile({inline,yeccpars2_194_/1}).
--file("erl_parse.yrl", 303).
-yeccpars2_194_(__Stack0) ->
- [begin
- default
- end | __Stack0].
-
--compile({inline,yeccpars2_197_/1}).
--file("erl_parse.yrl", 299).
-yeccpars2_197_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- __2
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8752).
--compile({inline,yeccpars2_198_/1}).
--file("erl_parse.yrl", 294).
-yeccpars2_198_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { bin_element , ? line ( __1 ) , __1 , __2 , __3 }
- end | __Stack].
-
--compile({inline,yeccpars2_200_/1}).
--file("erl_parse.yrl", 302).
-yeccpars2_200_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- __2
- end | __Stack].
-
--compile({inline,yeccpars2_201_/1}).
--file("erl_parse.yrl", 306).
-yeccpars2_201_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--compile({inline,yeccpars2_202_/1}).
--file("erl_parse.yrl", 308).
-yeccpars2_202_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- element ( 3 , __1 )
- end | __Stack].
-
--compile({inline,yeccpars2_204_/1}).
--file("erl_parse.yrl", 309).
-yeccpars2_204_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { element ( 3 , __1 ) , element ( 3 , __3 ) }
- end | __Stack].
-
--compile({inline,yeccpars2_206_/1}).
--file("erl_parse.yrl", 305).
-yeccpars2_206_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8801).
--compile({inline,yeccpars2_207_/1}).
--file("erl_parse.yrl", 296).
-yeccpars2_207_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- ? mkop1 ( __1 , __2 )
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8810).
--compile({inline,yeccpars2_208_/1}).
--file("erl_parse.yrl", 256).
-yeccpars2_208_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- { record_field , ? line ( __1 ) , { atom , ? line ( __1 ) , '' } , __2 }
- end | __Stack].
-
--compile({inline,yeccpars2_210_/1}).
--file("erl_parse.yrl", 269).
-yeccpars2_210_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- __2
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8827).
--compile({inline,yeccpars2_212_/1}).
--file("erl_parse.yrl", 340).
-yeccpars2_212_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { record , ? line ( __1 ) , element ( 3 , __2 ) , __3 }
- end | __Stack].
-
--compile({inline,yeccpars2_216_/1}).
--file("erl_parse.yrl", 353).
-yeccpars2_216_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--compile({inline,yeccpars2_219_/1}).
--file("erl_parse.yrl", 350).
-yeccpars2_219_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- [ ]
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8852).
--compile({inline,yeccpars2_221_/1}).
--file("erl_parse.yrl", 356).
-yeccpars2_221_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { record_field , ? line ( __1 ) , __1 , __3 }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8861).
--compile({inline,yeccpars2_223_/1}).
--file("erl_parse.yrl", 357).
-yeccpars2_223_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { record_field , ? line ( __1 ) , __1 , __3 }
- end | __Stack].
-
--compile({inline,yeccpars2_225_/1}).
--file("erl_parse.yrl", 354).
-yeccpars2_225_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--compile({inline,yeccpars2_226_/1}).
--file("erl_parse.yrl", 351).
-yeccpars2_226_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- __2
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8886).
--compile({inline,yeccpars2_227_/1}).
--file("erl_parse.yrl", 338).
-yeccpars2_227_(__Stack0) ->
- [__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { record_index , ? line ( __1 ) , element ( 3 , __2 ) , __4 }
- end | __Stack].
-
--compile({inline,yeccpars2_229_/1}).
--file("erl_parse.yrl", 439).
-yeccpars2_229_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8903).
--compile({inline,yeccpars2_232_/1}).
--file("erl_parse.yrl", 217).
-yeccpars2_232_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { match , ? line ( __2 ) , __1 , __3 }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8912).
--compile({inline,yeccpars2_233_/1}).
--file("erl_parse.yrl", 218).
-yeccpars2_233_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- ? mkop2 ( __1 , __2 , __3 )
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8921).
--compile({inline,yeccpars2_235_/1}).
--file("erl_parse.yrl", 221).
-yeccpars2_235_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- ? mkop2 ( __1 , __2 , __3 )
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8930).
--compile({inline,yeccpars2_237_/1}).
--file("erl_parse.yrl", 224).
-yeccpars2_237_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- ? mkop2 ( __1 , __2 , __3 )
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8939).
--compile({inline,yeccpars2_247_/1}).
--file("erl_parse.yrl", 228).
-yeccpars2_247_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- ? mkop2 ( __1 , __2 , __3 )
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8948).
--compile({inline,yeccpars2_260_/1}).
--file("erl_parse.yrl", 236).
-yeccpars2_260_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- ? mkop2 ( __1 , __2 , __3 )
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8957).
--compile({inline,yeccpars2_268_/1}).
--file("erl_parse.yrl", 240).
-yeccpars2_268_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- ? mkop2 ( __1 , __2 , __3 )
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8966).
--compile({inline,yeccpars2_269_/1}).
--file("erl_parse.yrl", 232).
-yeccpars2_269_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- ? mkop2 ( __1 , __2 , __3 )
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8975).
--compile({inline,yeccpars2_270_/1}).
--file("erl_parse.yrl", 362).
-yeccpars2_270_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- { call , ? line ( __1 ) , __1 , element ( 1 , __2 ) }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8984).
--compile({inline,yeccpars2_273_/1}).
--file("erl_parse.yrl", 252).
-yeccpars2_273_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { remote , ? line ( __2 ) , __1 , __3 }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8993).
--compile({inline,yeccpars2_274_/1}).
--file("erl_parse.yrl", 258).
-yeccpars2_274_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { record_field , ? line ( __2 ) , __1 , __3 }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9002).
--compile({inline,yeccpars2_277_/1}).
--file("erl_parse.yrl", 344).
-yeccpars2_277_(__Stack0) ->
- [__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { record , ? line ( __2 ) , __1 , element ( 3 , __3 ) , __4 }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9011).
--compile({inline,yeccpars2_279_/1}).
--file("erl_parse.yrl", 342).
-yeccpars2_279_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { record_field , ? line ( __2 ) , __1 , element ( 3 , __3 ) , __5 }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9020).
--compile({inline,yeccpars2_280_/1}).
--file("erl_parse.yrl", 435).
-yeccpars2_280_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { __2 , ? line ( __1 ) }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9029).
--compile({inline,yeccpars2_281_/1}).
--file("erl_parse.yrl", 244).
-yeccpars2_281_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- ? mkop1 ( __1 , __2 )
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9038).
--compile({inline,yeccpars2_284_/1}).
--file("erl_parse.yrl", 348).
-yeccpars2_284_(__Stack0) ->
- [__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { record , ? line ( __2 ) , __1 , element ( 3 , __3 ) , __4 }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9047).
--compile({inline,yeccpars2_286_/1}).
--file("erl_parse.yrl", 346).
-yeccpars2_286_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { record_field , ? line ( __2 ) , __1 , element ( 3 , __3 ) , __5 }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9056).
--compile({inline,yeccpars2_288_/1}).
--file("erl_parse.yrl", 493).
-yeccpars2_288_(__Stack0) ->
- [__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { clause , ? line ( __1 ) , element ( 3 , __1 ) , __2 , __3 , __4 }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9065).
--compile({inline,yeccpars2_289_/1}).
--file("erl_parse.yrl", 203).
-yeccpars2_289_(__Stack0) ->
- [__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { clause , ? line ( __1 ) , element ( 3 , __1 ) , __2 , __3 , __4 }
- end | __Stack].
-
--compile({inline,yeccpars2_291_/1}).
--file("erl_parse.yrl", 495).
-yeccpars2_291_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- __2
- end | __Stack].
-
--compile({inline,yeccpars2_294_/1}).
--file("erl_parse.yrl", 75).
-yeccpars2_294_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- build_type_spec ( __2 , __3 )
- end | __Stack].
-
--compile({inline,yeccpars2_300_/1}).
--file("erl_parse.yrl", 81).
-yeccpars2_300_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { __1 , __3 }
- end | __Stack].
-
--compile({inline,yeccpars2_303_/1}).
--file("erl_parse.yrl", 85).
-yeccpars2_303_(__Stack0) ->
- [__6,__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { __1 , __3 , __5 }
- end | __Stack].
-
--compile({inline,yeccpars2_305_/1}).
--file("erl_parse.yrl", 84).
-yeccpars2_305_(__Stack0) ->
- [__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { __1 , __3 }
- end | __Stack].
-
--compile({inline,yeccpars2_308_/1}).
--file("erl_parse.yrl", 99).
-yeccpars2_308_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--compile({inline,yeccpars2_318_/1}).
--file("erl_parse.yrl", 113).
-yeccpars2_318_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9130).
--compile({inline,yeccpars2_332_/1}).
--file("erl_parse.yrl", 152).
-yeccpars2_332_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- { type , ? line ( __1 ) , tuple , [ ] }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9139).
--compile({inline,yeccpars2_333_/1}).
--file("erl_parse.yrl", 153).
-yeccpars2_333_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { type , ? line ( __1 ) , tuple , __2 }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9148).
--compile({inline,yeccpars2_335_/1}).
--file("erl_parse.yrl", 116).
-yeccpars2_335_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { ann_type , ? line ( __1 ) , [ __1 , __3 ] }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9157).
--compile({inline,yeccpars2_341_/1}).
--file("erl_parse.yrl", 159).
-yeccpars2_341_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { type , ? line ( __1 ) , 'fun' , [ ] }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9166).
--compile({inline,yeccpars2_345_/1}).
--file("erl_parse.yrl", 163).
-yeccpars2_345_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { type , ? line ( __1 ) , 'fun' ,
- [ { type , ? line ( __1 ) , any } , __5 ] }
- end | __Stack].
-
--compile({inline,yeccpars2_346_/1}).
--file("erl_parse.yrl", 160).
-yeccpars2_346_(__Stack0) ->
- [__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- __3
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9184).
--compile({inline,yeccpars2_352_/1}).
--file("erl_parse.yrl", 144).
-yeccpars2_352_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { remote_type , ? line ( __1 ) ,
- [ __1 , __3 , [ ] ] }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9194).
--compile({inline,yeccpars2_353_/1}).
--file("erl_parse.yrl", 146).
-yeccpars2_353_(__Stack0) ->
- [__6,__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { remote_type , ? line ( __1 ) ,
- [ __1 , __3 , __5 ] }
- end | __Stack].
-
--compile({inline,yeccpars2_355_/1}).
--file("erl_parse.yrl", 141).
-yeccpars2_355_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- build_gen_type ( __1 )
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9212).
--compile({inline,yeccpars2_356_/1}).
--file("erl_parse.yrl", 142).
-yeccpars2_356_(__Stack0) ->
- [__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { type , ? line ( __1 ) ,
- normalise ( __1 ) , __3 }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9222).
--compile({inline,yeccpars2_358_/1}).
--file("erl_parse.yrl", 148).
-yeccpars2_358_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- { type , ? line ( __1 ) , nil , [ ] }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9231).
--compile({inline,yeccpars2_360_/1}).
--file("erl_parse.yrl", 149).
-yeccpars2_360_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { type , ? line ( __1 ) , list , [ __2 ] }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9240).
--compile({inline,yeccpars2_362_/1}).
--file("erl_parse.yrl", 150).
-yeccpars2_362_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { type , ? line ( __1 ) ,
- nonempty_list , [ __2 ] }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9250).
--compile({inline,yeccpars2_365_/1}).
--file("erl_parse.yrl", 179).
-yeccpars2_365_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- { type , ? line ( __1 ) , binary ,
- [ abstract ( 0 , ? line ( __1 ) ) ,
- abstract ( 0 , ? line ( __1 ) ) ] }
- end | __Stack].
-
--compile({inline,yeccpars2_368_/1}).
--file("erl_parse.yrl", 189).
-yeccpars2_368_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- build_bin_type ( [ __1 ] , __3 )
- end | __Stack].
-
--compile({inline,yeccpars2_371_/1}).
--file("erl_parse.yrl", 191).
-yeccpars2_371_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- build_bin_type ( [ __1 , __3 ] , __5 )
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9277).
--compile({inline,yeccpars2_373_/1}).
--file("erl_parse.yrl", 182).
-yeccpars2_373_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { type , ? line ( __1 ) , binary ,
- [ __2 , abstract ( 0 , ? line ( __1 ) ) ] }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9287).
--compile({inline,yeccpars2_378_/1}).
--file("erl_parse.yrl", 187).
-yeccpars2_378_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { type , ? line ( __1 ) , binary , [ __2 , __4 ] }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9296).
--compile({inline,yeccpars2_379_/1}).
--file("erl_parse.yrl", 184).
-yeccpars2_379_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { type , ? line ( __1 ) , binary ,
- [ abstract ( 0 , ? line ( __1 ) ) , __2 ] }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9306).
--compile({inline,yeccpars2_381_/1}).
--file("erl_parse.yrl", 167).
-yeccpars2_381_(__Stack0) ->
- [__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { type , ? line ( __1 ) , 'fun' ,
- [ { type , ? line ( __1 ) , product , [ ] } , __4 ] }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9316).
--compile({inline,yeccpars2_383_/1}).
--file("erl_parse.yrl", 138).
-yeccpars2_383_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { paren_type , ? line ( __2 ) , [ __2 ] }
- end | __Stack].
-
--compile({inline,yeccpars2_387_/1}).
--file("erl_parse.yrl", 173).
-yeccpars2_387_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9333).
--compile({inline,yeccpars2_389_/1}).
--file("erl_parse.yrl", 154).
-yeccpars2_389_(__Stack0) ->
- [__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { type , ? line ( __1 ) , record , [ __2 ] }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9342).
--compile({inline,yeccpars2_391_/1}).
--file("erl_parse.yrl", 176).
-yeccpars2_391_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { type , ? line ( __1 ) , field_type ,
- [ __1 , __3 ] }
- end | __Stack].
-
--compile({inline,yeccpars2_393_/1}).
--file("erl_parse.yrl", 174).
-yeccpars2_393_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9360).
--compile({inline,yeccpars2_394_/1}).
--file("erl_parse.yrl", 155).
-yeccpars2_394_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { type , ? line ( __1 ) ,
- record , [ __2 | __4 ] }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9370).
--compile({inline,yeccpars2_395_/1}).
--file("erl_parse.yrl", 135).
-yeccpars2_395_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- ? mkop1 ( __1 , skip_paren ( __2 ) )
- end | __Stack].
-
--compile({inline,yeccpars2_397_/1}).
--file("erl_parse.yrl", 114).
-yeccpars2_397_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9387).
--compile({inline,yeccpars2_400_/1}).
--file("erl_parse.yrl", 170).
-yeccpars2_400_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { type , ? line ( __1 ) , 'fun' ,
- [ { type , ? line ( __1 ) , product , __2 } , __5 ] }
- end | __Stack].
-
--compile({inline,yeccpars2_402_/1}).
--file("erl_parse.yrl", 120).
-yeccpars2_402_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- lift_unions ( __1 , __3 )
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9405).
--compile({inline,yeccpars2_405_/1}).
--file("erl_parse.yrl", 122).
-yeccpars2_405_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { type , ? line ( __1 ) , range ,
- [ skip_paren ( __1 ) ,
- skip_paren ( __3 ) ] }
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9416).
--compile({inline,yeccpars2_406_/1}).
--file("erl_parse.yrl", 127).
-yeccpars2_406_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- ? mkop2 ( skip_paren ( __1 ) ,
- __2 , skip_paren ( __3 ) )
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9426).
--compile({inline,yeccpars2_408_/1}).
--file("erl_parse.yrl", 131).
-yeccpars2_408_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- ? mkop2 ( skip_paren ( __1 ) ,
- __2 , skip_paren ( __3 ) )
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9436).
--compile({inline,yeccpars2_410_/1}).
--file("erl_parse.yrl", 103).
-yeccpars2_410_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { type , ? line ( __1 ) , bounded_fun ,
- [ __1 , __3 ] }
- end | __Stack].
-
--compile({inline,yeccpars2_411_/1}).
--file("erl_parse.yrl", 106).
-yeccpars2_411_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--compile({inline,yeccpars2_415_/1}).
--file("erl_parse.yrl", 111).
-yeccpars2_415_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- build_def ( __1 , __3 )
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9462).
--compile({inline,yeccpars2_418_/1}).
--file("erl_parse.yrl", 109).
-yeccpars2_418_(__Stack0) ->
- [__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { type , ? line ( __1 ) , constraint ,
- [ __1 , __3 ] }
- end | __Stack].
-
--compile({inline,yeccpars2_420_/1}).
--file("erl_parse.yrl", 107).
-yeccpars2_420_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--compile({inline,yeccpars2_422_/1}).
--file("erl_parse.yrl", 100).
-yeccpars2_422_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--compile({inline,yeccpars2_423_/1}).
--file("erl_parse.yrl", 78).
-yeccpars2_423_(__Stack0) ->
- [__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { __2 , __3 }
- end | __Stack].
-
--compile({inline,yeccpars2_424_/1}).
--file("erl_parse.yrl", 77).
-yeccpars2_424_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- { __1 , __2 }
- end | __Stack].
-
--compile({inline,yeccpars2_425_/1}).
--file("erl_parse.yrl", 73).
-yeccpars2_425_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- build_typed_attribute ( __2 , __3 )
- end | __Stack].
-
--compile({inline,yeccpars2_426_/1}).
--file("erl_parse.yrl", 193).
-yeccpars2_426_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--compile({inline,yeccpars2_427_/1}).
--file("erl_parse.yrl", 72).
-yeccpars2_427_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- build_attribute ( __2 , __3 )
- end | __Stack].
-
--compile({inline,yeccpars2_433_/1}).
--file("erl_parse.yrl", 88).
-yeccpars2_433_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { type_def , __1 , __3 }
- end | __Stack].
-
--compile({inline,yeccpars2_434_/1}).
--file("erl_parse.yrl", 87).
-yeccpars2_434_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { typed_record , __1 , __3 }
- end | __Stack].
-
--compile({inline,yeccpars2_438_/1}).
--file("erl_parse.yrl", 92).
-yeccpars2_438_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--compile({inline,yeccpars2_439_/1}).
--file("erl_parse.yrl", 438).
-yeccpars2_439_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- [ __1 ]
- end | __Stack].
-
--compile({inline,yeccpars2_442_/1}).
--file("erl_parse.yrl", 97).
-yeccpars2_442_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { typed , __1 , __3 }
- end | __Stack].
-
--compile({inline,yeccpars2_443_/1}).
--file("erl_parse.yrl", 94).
-yeccpars2_443_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--compile({inline,yeccpars2_445_/1}).
--file("erl_parse.yrl", 93).
-yeccpars2_445_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--compile({inline,yeccpars2_446_/1}).
--file("erl_parse.yrl", 95).
-yeccpars2_446_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--file("/ldisk/egil/git/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9592).
--compile({inline,yeccpars2_447_/1}).
--file("erl_parse.yrl", 90).
-yeccpars2_447_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- { tuple , ? line ( __1 ) , __2 }
- end | __Stack].
-
--compile({inline,yeccpars2_448_/1}).
--file("erl_parse.yrl", 195).
-yeccpars2_448_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __2 | __4 ]
- end | __Stack].
-
--compile({inline,yeccpars2_449_/1}).
--file("erl_parse.yrl", 74).
-yeccpars2_449_(__Stack0) ->
- [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
- [begin
- build_typed_attribute ( __2 , __4 )
- end | __Stack].
-
--compile({inline,yeccpars2_451_/1}).
--file("erl_parse.yrl", 194).
-yeccpars2_451_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--compile({inline,yeccpars2_452_/1}).
--file("erl_parse.yrl", 68).
-yeccpars2_452_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- __1
- end | __Stack].
-
--compile({inline,yeccpars2_453_/1}).
--file("erl_parse.yrl", 69).
-yeccpars2_453_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- __1
- end | __Stack].
-
--compile({inline,yeccpars2_455_/1}).
--file("erl_parse.yrl", 200).
-yeccpars2_455_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--compile({inline,yeccpars2_457_/1}).
--file("erl_parse.yrl", 209).
-yeccpars2_457_(__Stack0) ->
- [begin
- [ ]
- end | __Stack0].
-
--compile({inline,yeccpars2_459_/1}).
--file("erl_parse.yrl", 70).
-yeccpars2_459_(__Stack0) ->
- [__2,__1 | __Stack] = __Stack0,
- [begin
- __1
- end | __Stack].
-
--compile({inline,yeccpars2_461_/1}).
--file("erl_parse.yrl", 490).
-yeccpars2_461_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
- [begin
- [ __1 | __3 ]
- end | __Stack].
-
--compile({inline,yeccpars2_463_/1}).
--file("erl_parse.yrl", 209).
-yeccpars2_463_(__Stack0) ->
- [begin
- [ ]
- end | __Stack0].
-
-
--file("erl_parse.yrl", 1094).
diff --git a/bootstrap/lib/stdlib/include/erl_bits.hrl b/bootstrap/lib/stdlib/include/erl_bits.hrl
index aca213c08c..54ebe58585 100644
--- a/bootstrap/lib/stdlib/include/erl_bits.hrl
+++ b/bootstrap/lib/stdlib/include/erl_bits.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/bootstrap/lib/stdlib/include/erl_compile.hrl b/bootstrap/lib/stdlib/include/erl_compile.hrl
index 2e0d90dfad..f779c4382c 100644
--- a/bootstrap/lib/stdlib/include/erl_compile.hrl
+++ b/bootstrap/lib/stdlib/include/erl_compile.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/bootstrap/lib/stdlib/include/ms_transform.hrl b/bootstrap/lib/stdlib/include/ms_transform.hrl
index 2b89a4df2f..9937d48fef 100644
--- a/bootstrap/lib/stdlib/include/ms_transform.hrl
+++ b/bootstrap/lib/stdlib/include/ms_transform.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/bootstrap/lib/stdlib/include/qlc.hrl b/bootstrap/lib/stdlib/include/qlc.hrl
index cccedcbd2c..067fb83060 100644
--- a/bootstrap/lib/stdlib/include/qlc.hrl
+++ b/bootstrap/lib/stdlib/include/qlc.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/configure.in b/configure.in
index 36b33ec399..c8d4561a44 100644
--- a/configure.in
+++ b/configure.in
@@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script.
dnl %CopyrightBegin%
dnl
-dnl Copyright Ericsson AB 1998-2010. All Rights Reserved.
+dnl Copyright Ericsson AB 1998-2011. All Rights Reserved.
dnl
dnl The contents of this file are subject to the Erlang Public License,
dnl Version 1.1, (the "License"); you may not use this file except in
@@ -306,10 +306,6 @@ AS_HELP_STRING([--enable-m32-build],
esac
],enable_m32_build=no)
-AC_ARG_ENABLE(ethread-pre-pentium4-compatibility,
- AS_HELP_STRING([--enable-ethread-pre-pentium4-compatibility],
- [enable compatibility with x86 processors before pentium 4 (back to 486) in the ethread library]))
-
AC_ARG_WITH(libatomic_ops,
AS_HELP_STRING([--with-libatomic_ops=PATH],
[specify and prefer usage of libatomic_ops in the ethread library]))
diff --git a/erts/Makefile.in b/erts/Makefile.in
index 2e63fc469e..8b86fbadf2 100644
--- a/erts/Makefile.in
+++ b/erts/Makefile.in
@@ -16,6 +16,9 @@
#
# %CopyrightEnd%
#
+
+.NOTPARALLEL:
+
include $(ERL_TOP)/make/target.mk
include vsn.mk
diff --git a/erts/aclocal.m4 b/erts/aclocal.m4
index b64380e817..bd228a2d1f 100644
--- a/erts/aclocal.m4
+++ b/erts/aclocal.m4
@@ -125,6 +125,9 @@ AC_DEFUN(LM_FIND_EMU_CC,
ac_cv_prog_emu_cc,
[
AC_TRY_COMPILE([],[
+#ifdef __llvm__
+#error "llvm is currently unable to compile beam_emu.c"
+#endif
__label__ lbl1;
__label__ lbl2;
int x = magic();
@@ -140,7 +143,7 @@ lbl2:
],ac_cv_prog_emu_cc=$CC,ac_cv_prog_emu_cc=no)
if test $ac_cv_prog_emu_cc = no; then
- for ac_progname in emu_cc.sh gcc; do
+ for ac_progname in emu_cc.sh gcc-4.2 gcc; do
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
ac_dummy="$PATH"
for ac_dir in $ac_dummy; do
@@ -679,6 +682,55 @@ AC_SUBST(ERTS_INTERNAL_X_LIBS)
])
+AC_DEFUN(ETHR_CHK_SYNC_OP,
+[
+ AC_MSG_CHECKING([for $3-bit $1()])
+ case "$2" in
+ "1") sync_call="$1(&var);";;
+ "2") sync_call="$1(&var, ($4) 0);";;
+ "3") sync_call="$1(&var, ($4) 0, ($4) 0);";;
+ esac
+ have_sync_op=no
+ AC_TRY_LINK([],
+ [
+ $4 res;
+ volatile $4 var;
+ res = $sync_call
+ ],
+ [have_sync_op=yes])
+ test $have_sync_op = yes && $5
+ AC_MSG_RESULT([$have_sync_op])
+])
+
+AC_DEFUN(ETHR_CHK_INTERLOCKED,
+[
+ ilckd="$1"
+ AC_MSG_CHECKING([for ${ilckd}()])
+ case "$2" in
+ "1") ilckd_call="${ilckd}(var);";;
+ "2") ilckd_call="${ilckd}(var, ($3) 0);";;
+ "3") ilckd_call="${ilckd}(var, ($3) 0, ($3) 0);";;
+ "4") ilckd_call="${ilckd}(var, ($3) 0, ($3) 0, arr);";;
+ esac
+ have_interlocked_op=no
+ AC_TRY_LINK(
+ [
+ #define WIN32_LEAN_AND_MEAN
+ #include <windows.h>
+ #include <intrin.h>
+ ],
+ [
+ volatile $3 *var;
+ volatile $3 arr[2];
+
+ $ilckd_call
+ return 0;
+ ],
+ [have_interlocked_op=yes])
+ test $have_interlocked_op = yes && $4
+ AC_MSG_RESULT([$have_interlocked_op])
+])
+
dnl ----------------------------------------------------------------------
dnl
dnl ERL_FIND_ETHR_LIB
@@ -750,121 +802,41 @@ case "$THR_LIB_NAME" in
AC_DEFINE(ETHR_WIN32_THREADS, 1, [Define if you have win32 threads])
- have_ilckd=no
- AC_MSG_CHECKING([for _InterlockedCompareExchange64()])
- AC_TRY_LINK([
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- ],
- [
- volatile __int64 *var;
- _InterlockedCompareExchange64(var, (__int64) 1, (__int64) 0);
- return 0;
- ],
- have_ilckd=yes)
- AC_MSG_RESULT([$have_ilckd])
- test $have_ilckd = yes && AC_DEFINE(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64, 1, [Define if you have _InterlockedCompareExchange64()])
-
- AC_CHECK_SIZEOF(void *)
- case "$ac_cv_sizeof_void_p-$have_ilckd" in
- 8-no)
- ethr_have_native_atomics=no
- ethr_have_native_spinlock=no;;
- *)
- ethr_have_native_atomics=yes
- ethr_have_native_spinlock=yes;;
- esac
-
- have_ilckd=no
- AC_MSG_CHECKING([for _InterlockedDecrement64()])
- AC_TRY_LINK([
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- ],
- [
- volatile __int64 *var;
- _InterlockedDecrement64(var);
- return 0;
- ],
- have_ilckd=yes)
- AC_MSG_RESULT([$have_ilckd])
- test $have_ilckd = yes && AC_DEFINE(ETHR_HAVE__INTERLOCKEDDECREMENT64, 1, [Define if you have _InterlockedDecrement64()])
-
- have_ilckd=no
- AC_MSG_CHECKING([for _InterlockedIncrement64()])
- AC_TRY_LINK([
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- ],
- [
- volatile __int64 *var;
- _InterlockedIncrement64(var);
- return 0;
- ],
- have_ilckd=yes)
- AC_MSG_RESULT([$have_ilckd])
- test $have_ilckd = yes && AC_DEFINE(ETHR_HAVE__INTERLOCKEDINCREMENT64, 1, [Define if you have _InterlockedIncrement64()])
-
- have_ilckd=no
- AC_MSG_CHECKING([for _InterlockedExchangeAdd64()])
- AC_TRY_LINK([
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- ],
- [
- volatile __int64 *var;
- _InterlockedExchangeAdd64(var, (__int64) 1);
- return 0;
- ],
- have_ilckd=yes)
- AC_MSG_RESULT([$have_ilckd])
- test $have_ilckd = yes && AC_DEFINE(ETHR_HAVE__INTERLOCKEDEXCHANGEADD64, 1, [Define if you have _InterlockedExchangeAdd64()])
-
- have_ilckd=no
- AC_MSG_CHECKING([for _InterlockedExchange64()])
- AC_TRY_LINK([
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- ],
- [
- volatile __int64 *var;
- _InterlockedExchange64(var, (__int64) 1);
- return 0;
- ],
- have_ilckd=yes)
- AC_MSG_RESULT([$have_ilckd])
- test $have_ilckd = yes && AC_DEFINE(ETHR_HAVE__INTERLOCKEDEXCHANGE64, 1, [Define if you have _InterlockedExchange64()])
-
- have_ilckd=no
- AC_MSG_CHECKING([for _InterlockedAnd64()])
- AC_TRY_LINK([
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- ],
- [
- volatile __int64 *var;
- _InterlockedAnd64(var, (__int64) 1);
- return 0;
- ],
- have_ilckd=yes)
- AC_MSG_RESULT([$have_ilckd])
- test $have_ilckd = yes && AC_DEFINE(ETHR_HAVE__INTERLOCKEDAND64, 1, [Define if you have _InterlockedAnd64()])
-
- have_ilckd=no
- AC_MSG_CHECKING([for _InterlockedOr64()])
- AC_TRY_LINK([
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- ],
- [
- volatile __int64 *var;
- _InterlockedOr64(var, (__int64) 1);
- return 0;
- ],
- have_ilckd=yes)
- AC_MSG_RESULT([$have_ilckd])
- test $have_ilckd = yes && AC_DEFINE(ETHR_HAVE__INTERLOCKEDOR64, 1, [Define if you have _InterlockedOr64()])
-
+ ETHR_CHK_INTERLOCKED([_InterlockedDecrement], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT, 1, [Define if you have _InterlockedDecrement()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedDecrement_rel], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT_REL, 1, [Define if you have _InterlockedDecrement_rel()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedIncrement], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT, 1, [Define if you have _InterlockedIncrement()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedIncrement_acq], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT_ACQ, 1, [Define if you have _InterlockedIncrement_acq()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD, 1, [Define if you have _InterlockedExchangeAdd()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd_acq], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD_ACQ, 1, [Define if you have _InterlockedExchangeAdd_acq()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedAnd], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDAND, 1, [Define if you have _InterlockedAnd()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedOr], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDOR, 1, [Define if you have _InterlockedOr()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchange], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGE, 1, [Define if you have _InterlockedExchange()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange], [3], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE, 1, [Define if you have _InterlockedCompareExchange()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange_acq], [3], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_ACQ, 1, [Define if you have _InterlockedCompareExchange_acq()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange_rel], [3], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_REL, 1, [Define if you have _InterlockedCompareExchange_rel()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+
+ ETHR_CHK_INTERLOCKED([_InterlockedDecrement64], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT64, 1, [Define if you have _InterlockedDecrement64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedDecrement64_rel], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT64_REL, 1, [Define if you have _InterlockedDecrement64_rel()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedIncrement64], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT64, 1, [Define if you have _InterlockedIncrement64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedIncrement64_acq], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT64_ACQ, 1, [Define if you have _InterlockedIncrement64_acq()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD64, 1, [Define if you have _InterlockedExchangeAdd64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd64_acq], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD64_ACQ, 1, [Define if you have _InterlockedExchangeAdd64_acq()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedAnd64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDAND64, 1, [Define if you have _InterlockedAnd64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedOr64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDOR64, 1, [Define if you have _InterlockedOr64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchange64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGE64, 1, [Define if you have _InterlockedExchange64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange64], [3], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64, 1, [Define if you have _InterlockedCompareExchange64()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange64_acq], [3], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_ACQ, 1, [Define if you have _InterlockedCompareExchange64_acq()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange64_rel], [3], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_REL, 1, [Define if you have _InterlockedCompareExchange64_rel()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange128], [4], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE128, 1, [Define if you have _InterlockedCompareExchange128()]))
+
+ test "$ethr_have_native_atomics" = "yes" && ethr_have_native_spinlock=yes
;;
pthread)
@@ -1100,35 +1072,51 @@ case "$THR_LIB_NAME" in
AC_MSG_RESULT([$linux_futex])
test $linux_futex = yes && AC_DEFINE(ETHR_HAVE_LINUX_FUTEX, 1, [Define if you have a linux futex implementation.])
- AC_MSG_CHECKING([for GCC atomic operations])
- ethr_have_gcc_atomic_ops=no
- AC_TRY_LINK([],
- [
- long res;
- volatile long val;
- res = __sync_val_compare_and_swap(&val, (long) 1, (long) 0);
- res = __sync_add_and_fetch(&val, (long) 1);
- res = __sync_sub_and_fetch(&val, (long) 1);
- res = __sync_fetch_and_and(&val, (long) 1);
- res = __sync_fetch_and_or(&val, (long) 1);
- ],
- [ethr_have_native_atomics=yes
- ethr_have_gcc_atomic_ops=yes])
- AC_MSG_RESULT([$ethr_have_gcc_atomic_ops])
- test $ethr_have_gcc_atomic_ops = yes && AC_DEFINE(ETHR_HAVE_GCC_ATOMIC_OPS, 1, [Define if you have gcc atomic operations])
+ AC_CHECK_SIZEOF(int)
+ AC_CHECK_SIZEOF(long)
+ AC_CHECK_SIZEOF(long long)
+ AC_CHECK_SIZEOF(__int128_t)
+
+ if test "$ac_cv_sizeof_int" = "4"; then
+ int32="int"
+ elif test "$ac_cv_sizeof_long" = "4"; then
+ int32="long"
+ elif test "$ac_cv_sizeof_long_long" = "4"; then
+ int32="long long"
+ else
+ AC_MSG_ERROR([No 32-bit type found])
+ fi
- case "$host_cpu" in
- sun4u | sparc64 | sun4v)
- ethr_have_native_atomics=yes;;
- i86pc | i*86 | x86_64 | amd64)
- ethr_have_native_atomics=yes;;
- macppc | ppc | "Power Macintosh")
- ethr_have_native_atomics=yes;;
- tile)
- ethr_have_native_atomics=yes;;
- *)
- ;;
- esac
+ if test "$ac_cv_sizeof_int" = "8"; then
+ int64="int"
+ elif test "$ac_cv_sizeof_long" = "8"; then
+ int64="long"
+ elif test "$ac_cv_sizeof_long_long" = "8"; then
+ int64="long long"
+ else
+ AC_MSG_ERROR([No 64-bit type found])
+ fi
+
+ int128=no
+ if test "$ac_cv_sizeof___int128_t" = "16"; then
+ int128="__int128_t"
+ fi
+
+ ETHR_CHK_SYNC_OP([__sync_val_compare_and_swap], [3], [32], [$int32], AC_DEFINE(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP32, 1, [Define if you have __sync_val_compare_and_swap() for 32-bit integers]))
+ test "$have_sync_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_SYNC_OP([__sync_add_and_fetch], [2], [32], [$int32], AC_DEFINE(ETHR_HAVE___SYNC_ADD_AND_FETCH32, 1, [Define if you have __sync_add_and_fetch() for 32-bit integers]))
+ ETHR_CHK_SYNC_OP([__sync_fetch_and_and], [2], [32], [$int32], AC_DEFINE(ETHR_HAVE___SYNC_FETCH_AND_AND32, 1, [Define if you have __sync_fetch_and_and() for 32-bit integers]))
+ ETHR_CHK_SYNC_OP([__sync_fetch_and_or], [2], [32], [$int32], AC_DEFINE(ETHR_HAVE___SYNC_FETCH_AND_OR32, 1, [Define if you have __sync_fetch_and_or() for 32-bit integers]))
+
+ ETHR_CHK_SYNC_OP([__sync_val_compare_and_swap], [3], [64], [$int64], AC_DEFINE(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP64, 1, [Define if you have __sync_val_compare_and_swap() for 64-bit integers]))
+ test "$have_sync_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_SYNC_OP([__sync_add_and_fetch], [2], [64], [$int64], AC_DEFINE(ETHR_HAVE___SYNC_ADD_AND_FETCH64, 1, [Define if you have __sync_add_and_fetch() for 64-bit integers]))
+ ETHR_CHK_SYNC_OP([__sync_fetch_and_and], [2], [64], [$int64], AC_DEFINE(ETHR_HAVE___SYNC_FETCH_AND_AND64, 1, [Define if you have __sync_fetch_and_and() for 64-bit integers]))
+ ETHR_CHK_SYNC_OP([__sync_fetch_and_or], [2], [64], [$int64], AC_DEFINE(ETHR_HAVE___SYNC_FETCH_AND_OR64, 1, [Define if you have __sync_fetch_and_or() for 64-bit integers]))
+
+ if test $int128 != no; then
+ ETHR_CHK_SYNC_OP([__sync_val_compare_and_swap], [3], [128], [$int128], AC_DEFINE(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP128, 1, [Define if you have __sync_val_compare_and_swap() for 128-bit integers]))
+ fi
AC_MSG_CHECKING([for a usable libatomic_ops implementation])
case "x$with_libatomic_ops" in
@@ -1175,6 +1163,34 @@ case "$THR_LIB_NAME" in
AC_MSG_ERROR([No usable libatomic_ops implementation found])
fi
+ case "$host_cpu" in
+ sparc | sun4u | sparc64 | sun4v)
+ case "$with_sparc_memory_order" in
+ "TSO")
+ AC_DEFINE(ETHR_SPARC_TSO, 1, [Define if only run in Sparc TSO mode]);;
+ "PSO")
+ AC_DEFINE(ETHR_SPARC_PSO, 1, [Define if only run in Sparc PSO, or TSO mode]);;
+ "RMO"|"")
+ AC_DEFINE(ETHR_SPARC_RMO, 1, [Define if run in Sparc RMO, PSO, or TSO mode]);;
+ *)
+ AC_MSG_ERROR([Unsupported Sparc memory order: $with_sparc_memory_order]);;
+ esac
+ ethr_have_native_atomics=yes;;
+ i86pc | i*86 | x86_64 | amd64)
+ if test "$enable_x86_out_of_order" = "yes"; then
+ AC_DEFINE(ETHR_X86_OUT_OF_ORDER, 1, [Define if x86/x86_64 out of order instructions should be synchronized])
+ fi
+ ethr_have_native_atomics=yes;;
+ macppc | ppc | "Power Macintosh")
+ ethr_have_native_atomics=yes;;
+ tile)
+ ethr_have_native_atomics=yes;;
+ *)
+ ;;
+ esac
+
+ test ethr_have_native_atomics = "yes" && ethr_have_native_spinlock=yes
+
dnl Restore LIBS
LIBS=$saved_libs
dnl restore CPPFLAGS
@@ -1210,6 +1226,8 @@ AC_CHECK_SIZEOF(long long)
AC_DEFINE_UNQUOTED(ETHR_SIZEOF_LONG_LONG, $ac_cv_sizeof_long_long, [Define to the size of long long])
AC_CHECK_SIZEOF(__int64)
AC_DEFINE_UNQUOTED(ETHR_SIZEOF___INT64, $ac_cv_sizeof___int64, [Define to the size of __int64])
+AC_CHECK_SIZEOF(__int128_t)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF___INT128_T, $ac_cv_sizeof___int128_t, [Define to the size of __int128_t])
case X$erl_xcomp_bigendian in
@@ -1232,6 +1250,10 @@ AC_ARG_ENABLE(native-ethr-impls,
*) disable_native_ethr_impls=no ;;
esac ], disable_native_ethr_impls=no)
+AC_ARG_ENABLE(x86-out-of-order,
+ AS_HELP_STRING([--enable-x86-out-of-order],
+ [enable x86/x84_64 out of order support (default disabled)]))
+
test "X$disable_native_ethr_impls" = "Xyes" &&
AC_DEFINE(ETHR_DISABLE_NATIVE_IMPLS, 1, [Define if you want to disable native ethread implementations])
@@ -1250,56 +1272,100 @@ AC_ARG_WITH(libatomic_ops,
AS_HELP_STRING([--with-libatomic_ops=PATH],
[specify and prefer usage of libatomic_ops in the ethread library]))
-AC_ARG_ENABLE(ethread-pre-pentium4-compatibility,
- AS_HELP_STRING([--enable-ethread-pre-pentium4-compatibility],
- [enable compatibility with x86 processors before pentium 4 (back to 486) in the ethread library]),
-[
- case "$enable_ethread_pre_pentium4_compatibility" in
- yes|no) ;;
- *) enable_ethread_pre_pentium4_compatibility=check;;
- esac
-],
-[enable_ethread_pre_pentium4_compatibility=check])
-
-test "$cross_compiling" != "yes" || enable_ethread_pre_pentium4_compatibility=no
-
-case "$enable_ethread_pre_pentium4_compatibility-$host_cpu" in
- check-i86pc | check-i*86)
- AC_MSG_CHECKING([whether pre pentium 4 compatibility should forced])
- AC_RUN_IFELSE([
-#if defined(__GNUC__)
-# if defined(ETHR_PREFER_LIBATOMIC_OPS_NATIVE_IMPLS)
-# define CHECK_LIBATOMIC_OPS__
-# else
-# define CHECK_GCC_ASM__
-# endif
-#elif defined(ETHR_HAVE_LIBATOMIC_OPS)
-# define CHECK_LIBATOMIC_OPS__
+AC_ARG_WITH(with_sparc_memory_order,
+ AS_HELP_STRING([--with-sparc-memory-order=TSO|PSO|RMO],
+ [specify sparc memory order (defaults to RMO)]))
+
+ETHR_X86_SSE2_ASM=no
+case "$GCC-$ac_cv_sizeof_void_p-$host_cpu" in
+ yes-4-i86pc | yes-4-i*86 | yes-4-x86_64 | yes-4-amd64)
+ AC_MSG_CHECKING([for gcc sse2 asm support])
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -msse2"
+ gcc_sse2_asm=no
+ AC_TRY_COMPILE([],
+ [
+ long long x, *y;
+ __asm__ __volatile__("movq %1, %0\n\t" : "=x"(x) : "m"(*y) : "memory");
+ ],
+ [gcc_sse2_asm=yes])
+ CFLAGS="$save_CFLAGS"
+ AC_MSG_RESULT([$gcc_sse2_asm])
+ if test "$gcc_sse2_asm" = "yes"; then
+ AC_DEFINE(ETHR_GCC_HAVE_SSE2_ASM_SUPPORT, 1, [Define if you use a gcc that supports -msse2 and understand sse2 specific asm statements])
+ ETHR_X86_SSE2_ASM=yes
+ fi
+ ;;
+ *)
+ ;;
+esac
+
+case "$GCC-$host_cpu" in
+ yes-i86pc | yes-i*86 | yes-x86_64 | yes-amd64)
+ gcc_dw_cmpxchg_asm=no
+ AC_MSG_CHECKING([for gcc double word cmpxchg asm support])
+ AC_TRY_COMPILE([],
+ [
+ char xchgd;
+ long new[2], xchg[2], *p;
+ __asm__ __volatile__(
+#if ETHR_SIZEOF_PTR == 4 && defined(__PIC__) && __PIC__
+ "pushl %%ebx\n\t"
+ "movl %8, %%ebx\n\t"
#endif
-#if defined(CHECK_LIBATOMIC_OPS__)
-#include "atomic_ops.h"
+#if ETHR_SIZEOF_PTR == 4
+ "lock; cmpxchg8b %0\n\t"
+#else
+ "lock; cmpxchg16b %0\n\t"
#endif
-int main(void)
-{
-#if defined(CHECK_GCC_ASM__)
- __asm__ __volatile__("mfence" : : : "memory");
-#elif defined(CHECK_LIBATOMIC_OPS__)
- AO_nop_full();
+ "setz %3\n\t"
+#if ETHR_SIZEOF_PTR == 4 && defined(__PIC__) && __PIC__
+ "popl %%ebx\n\t"
#endif
- return 0;
-}
+ : "=m"(*p), "=d"(xchg[1]), "=a"(xchg[0]), "=c"(xchgd)
+ : "m"(*p), "1"(xchg[1]), "2"(xchg[0]), "3"(new[1]),
+#if ETHR_SIZEOF_PTR == 4 && defined(__PIC__) && __PIC__
+ "r"(new[0])
+#else
+ "b"(new[0])
+#endif
+ : "cc", "memory");
+
+ ],
+ [gcc_dw_cmpxchg_asm=yes])
+ if test $gcc_dw_cmpxchg_asm = no && test $ac_cv_sizeof_void_p = 4; then
+ AC_TRY_COMPILE([],
+ [
+ char xchgd;
+ long new[2], xchg[2], *p;
+#if !defined(__PIC__) || !__PIC__
+# error nope
+#endif
+ __asm__ __volatile__(
+ "pushl %%ebx\n\t"
+ "movl (%7), %%ebx\n\t"
+ "movl 4(%7), %%ecx\n\t"
+ "lock; cmpxchg8b %0\n\t"
+ "setz %3\n\t"
+ "popl %%ebx\n\t"
+ : "=m"(*p), "=d"(xchg[1]), "=a"(xchg[0]), "=c"(xchgd)
+ : "m"(*p), "1"(xchg[1]), "2"(xchg[0]), "3"(new)
+ : "cc", "memory");
+
],
- [enable_ethread_pre_pentium4_compatibility=no],
- [enable_ethread_pre_pentium4_compatibility=yes],
- [enable_ethread_pre_pentium4_compatibility=no])
- AC_MSG_RESULT([$enable_ethread_pre_pentium4_compatibility]);;
+ [gcc_dw_cmpxchg_asm=yes])
+ if test "$gcc_dw_cmpxchg_asm" = "yes"; then
+ AC_DEFINE(ETHR_CMPXCHG8B_REGISTER_SHORTAGE, 1, [Define if you get a register shortage with cmpxchg8b and position independent code])
+ fi
+ fi
+ AC_MSG_RESULT([$gcc_dw_cmpxchg_asm])
+ if test "$gcc_dw_cmpxchg_asm" = "yes"; then
+ AC_DEFINE(ETHR_GCC_HAVE_DW_CMPXCHG_ASM_SUPPORT, 1, [Define if you use a gcc that supports the double word cmpxchg instruction])
+ fi;;
*)
;;
esac
-test $enable_ethread_pre_pentium4_compatibility = yes &&
- AC_DEFINE(ETHR_PRE_PENTIUM4_COMPAT, 1, [Define if you want compatibilty with x86 processors before pentium4.])
-
AC_DEFINE(ETHR_HAVE_ETHREAD_DEFINES, 1, \
[Define if you have all ethread defines])
@@ -1309,6 +1375,7 @@ AC_SUBST(ETHR_LIB_NAME)
AC_SUBST(ETHR_DEFS)
AC_SUBST(ETHR_THR_LIB_BASE)
AC_SUBST(ETHR_THR_LIB_BASE_DIR)
+AC_SUBST(ETHR_X86_SSE2_ASM)
])
@@ -1579,11 +1646,11 @@ dnl Freely inspired by AC_TRY_LINK. (Maybe better to create a
dnl AC_LANG_JAVA instead...)
AC_DEFUN(ERL_TRY_LINK_JAVA,
[java_link='$JAVAC conftest.java 1>&AC_FD_CC'
-changequote(�, �)dnl
+changequote(, )dnl
cat > conftest.java <<EOF
-�$1�
+$1
class conftest { public static void main(String[] args) {
- �$2�
+ $2
; return; }}
EOF
changequote([, ])dnl
diff --git a/erts/autoconf/win32.config.cache.static b/erts/autoconf/win32.config.cache.static
index d25b1df9d9..b387db2b22 100755
--- a/erts/autoconf/win32.config.cache.static
+++ b/erts/autoconf/win32.config.cache.static
@@ -96,7 +96,6 @@ ac_cv_func_sbrk=${ac_cv_func_sbrk=no}
ac_cv_func_select=${ac_cv_func_select=no}
ac_cv_func_setlocale=${ac_cv_func_setlocale=yes}
ac_cv_func_setsid=${ac_cv_func_setsid=no}
-ac_cv_func_setvbuf_reversed=${ac_cv_func_setvbuf_reversed=yes}
ac_cv_func_socket=${ac_cv_func_socket=no}
ac_cv_func_strchr=${ac_cv_func_strchr=yes}
ac_cv_func_strerror=${ac_cv_func_strerror=yes}
@@ -124,7 +123,6 @@ ac_cv_header_ieeefp_h=${ac_cv_header_ieeefp_h=no}
ac_cv_header_inttypes_h=${ac_cv_header_inttypes_h=no}
ac_cv_header_langinfo_h=${ac_cv_header_langinfo_h=no}
ac_cv_header_limits_h=${ac_cv_header_limits_h=yes}
-ac_cv_header_mach_o_dyld_h=${ac_cv_header_mach_o_dyld_h=no}
ac_cv_header_malloc_h=${ac_cv_header_malloc_h=yes}
ac_cv_header_memory_h=${ac_cv_header_memory_h=yes}
ac_cv_header_net_errno_h=${ac_cv_header_net_errno_h=no}
diff --git a/erts/configure.in b/erts/configure.in
index fac07f8b6a..d865e675c4 100644
--- a/erts/configure.in
+++ b/erts/configure.in
@@ -191,7 +191,7 @@ AS_HELP_STRING([--disable-kernel-poll], [disable kernel poll support]),
AC_ARG_ENABLE(sctp,
-AS_HELP_STRING([--enable-sctp], [enable sctp support])
+AS_HELP_STRING([--enable-sctp], [enable sctp support (default)])
AS_HELP_STRING([--disable-sctp], [disable sctp support]),
[ case "$enableval" in
no) enable_sctp=no ;;
@@ -259,13 +259,6 @@ AS_HELP_STRING([--enable-m32-build],
esac
],enable_m32_build=no)
-AC_ARG_ENABLE(fixalloc,
-AS_HELP_STRING([--disable-fixalloc], [disable the use of fix_alloc]))
-if test x${enable_fixalloc} = xno ; then
- AC_DEFINE(NO_FIX_ALLOC,[],
- [Define if you don't want the fix allocator in Erlang])
-fi
-
AC_SUBST(PERFCTR_PATH)
AC_ARG_WITH(perfctr,
AS_HELP_STRING([--with-perfctr=PATH],
@@ -914,16 +907,6 @@ fi
AC_SUBST(ERLANG_OSTYPE)
-dnl Which sysv4 would this be, and what is it for???
-dnl XXX: replace with feature tests.
-case $host_os in
- sysv4*)
- AC_DEFINE(SOCKOPT_CONNECT_STAT,[],[Obscure SYSV feature])
- AC_DEFINE(NO_PRAGMA_WEAK,[],[Obscure SYSV feature])
- LIBS="$LIBS -lgen -lc -L /usr/ucblib -lucb"
- ;;
-esac
-
# Check how to export functions from the emulator executable, needed
# when dynamically loaded drivers are loaded (so that they can find
# emulator functions).
@@ -1484,7 +1467,7 @@ AC_CHECK_HEADERS(fcntl.h limits.h unistd.h syslog.h dlfcn.h ieeefp.h \
sys/types.h sys/stropts.h sys/sysctl.h \
sys/ioctl.h sys/time.h sys/uio.h \
sys/socket.h sys/sockio.h sys/socketio.h \
- net/errno.h malloc.h mach-o/dyld.h arpa/nameser.h \
+ net/errno.h malloc.h arpa/nameser.h \
pty.h util.h utmp.h langinfo.h poll.h sdkddkver.h)
AC_CHECK_HEADER(sys/resource.h,
@@ -1503,7 +1486,7 @@ AC_CHECK_HEADER(sys/devpoll.h, have_kernel_poll=/dev/poll)
dnl Check for kernel SCTP support
AC_SUBST(LIBSCTP)
-if test "x$enable_sctp" = "xyes" ; then
+if test "x$enable_sctp" != "xno" ; then
AC_CHECK_HEADER(netinet/sctp.h,
[LIBSCTP=libsctp.so.1
AC_DEFINE(HAVE_SCTP_H, [1],
@@ -1513,8 +1496,21 @@ if test "x$enable_sctp" = "xyes" ; then
#include <sys/socket.h>
#endif
])
+ AC_CHECK_FUNCS([sctp_bindx sctp_peeloff])
AC_CHECK_DECLS([SCTP_UNORDERED, SCTP_ADDR_OVER, SCTP_ABORT,
- SCTP_EOF, SCTP_SENDALL, SCTP_ADDR_CONFIRMED], [], [],
+ SCTP_EOF, SCTP_SENDALL, SCTP_ADDR_CONFIRMED,
+ SCTP_DELAYED_ACK_TIME,
+ SCTP_EMPTY,
+ SCTP_CLOSED, SCTPS_IDLE,
+ SCTP_BOUND, SCTPS_BOUND,
+ SCTP_LISTEN, SCTPS_LISTEN,
+ SCTP_COOKIE_WAIT, SCTPS_COOKIE_WAIT,
+ SCTP_COOKIE_ECHOED, SCTPS_COOKIE_ECHOED,
+ SCTP_ESTABLISHED, SCTPS_ESTABLISHED,
+ SCTP_SHUTDOWN_PENDING, SCTPS_SHUTDOWN_PENDING,
+ SCTP_SHUTDOWN_SENT, SCTPS_SHUTDOWN_SENT,
+ SCTP_SHUTDOWN_RECEIVED, SCTPS_SHUTDOWN_RECEIVED,
+ SCTP_SHUTDOWN_ACK_SENT, SCTPS_SHUTDOWN_ACK_SENT], [], [],
[#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
@@ -1673,6 +1669,15 @@ esac
AC_C_BIGENDIAN
+dnl fdatasync syscall (Unix only)
+AC_CHECK_FUNCS([fdatasync])
+
+dnl Find which C libraries are required to use fdatasync
+dnl TODO: Remove check once SunOS >= 5.11 is required by erts.
+dnl fdatasync requires linking against -lrt on SunOS <= 5.10.
+dnl OpenSolaris 2009.06 is SunOS 5.11 and does not require -lrt.
+AC_SEARCH_LIBS(fdatasync, [rt])
+
dnl ----------------------------------------------------------------------
dnl Checks for library functions.
dnl ----------------------------------------------------------------------
@@ -1800,11 +1805,6 @@ AC_CHECK_FUNCS([ieee_handler fpsetmask finite isnan isinf res_gethostbyname dlop
AC_CHECK_DECLS([posix2time],,,[#include <time.h>])
-if test "X$host" = "Xwin32"; then
- ac_cv_func_setvbuf_reversed=yes
-fi
-AC_FUNC_SETVBUF_REVERSED
-
disable_vfork=false
if test "x$EMU_THR_LIB_NAME" != "x"; then
AC_MSG_CHECKING([if vfork is known to hang multithreaded applications])
@@ -1860,12 +1860,6 @@ fi
dnl Need by run_erl.
AC_CHECK_FUNCS([openpty])
-dnl fdatasync syscall (Unix only)
-AC_CHECK_FUNCS([fdatasync])
-
-dnl Find which C libraries are required to use fdatasync
-AC_SEARCH_LIBS(fdatasync, [rt])
-
AC_CHECK_HEADERS(net/if_dl.h ifaddrs.h netpacket/packet.h)
AC_CHECK_FUNCS([getifaddrs])
@@ -3535,7 +3529,7 @@ AC_SUBST(STATIC_KERBEROS_LIBS)
AC_SUBST(SSL_LINK_WITH_ZLIB)
AC_SUBST(STATIC_ZLIB_LIBS)
-std_ssl_locations="/usr/local /usr/sfw /opt/local /usr /usr/pkg /usr/local/openssl /usr/lib/openssl /usr/openssl /usr/local/ssl /usr/lib/ssl /usr/ssl"
+std_ssl_locations="/usr/local /usr/sfw /usr /opt/local /usr/pkg /usr/local/openssl /usr/lib/openssl /usr/openssl /usr/local/ssl /usr/lib/ssl /usr/ssl"
AC_ARG_WITH(ssl-zlib,
AS_HELP_STRING([--with-ssl-zlib=PATH],
@@ -3722,7 +3716,7 @@ case "$erl_xcomp_without_sysroot-$with_ssl" in
SSL_RUNTIME_LIBDIR="$rdir/lib"
SSL_LIBDIR="$dir/lib"
SSL_CRYPTO_LIBNAME=libeay32
- SSL_CRYPTO_LIBNAME=ssleay32
+ SSL_SSL_LIBNAME=ssleay32
elif test -f "$dir/lib/openssl.lib"; then
SSL_RUNTIME_LIBDIR="$rdir/lib"
SSL_LIBDIR="$dir/lib"
@@ -3904,7 +3898,7 @@ dnl so it is - be adoptable
elif test -f "$with_ssl/lib/libeay32.lib"; then
SSL_LIBDIR="$with_ssl/lib"
SSL_CRYPTO_LIBNAME=libeay32
- SSL_CRYPTO_LIBNAME=ssleay32
+ SSL_SSL_LIBNAME=ssleay32
else
# This probably wont work, but that's what the user said, so...
SSL_LIBDIR="$with_ssl/lib"
@@ -4309,7 +4303,6 @@ dnl Note that the output files are relative to $srcdir
AC_OUTPUT(
emulator/$host/Makefile:emulator/Makefile.in
emulator/zlib/$host/Makefile:emulator/zlib/Makefile.in
- emulator/pcre/$host/Makefile:emulator/pcre/Makefile.in
epmd/src/$host/Makefile:epmd/src/Makefile.in
etc/common/$host/Makefile:etc/common/Makefile.in
include/internal/$host/ethread.mk:include/internal/ethread.mk.in
@@ -4323,7 +4316,7 @@ dnl The ones below should be moved to their respective lib
dnl
../lib/ic/c_src/$host/Makefile:../lib/ic/c_src/Makefile.in
../lib/os_mon/c_src/$host/Makefile:../lib/os_mon/c_src/Makefile.in
- ../lib/ssl/c_src/$host/Makefile:../lib/ssl/c_src/Makefile.in
+dnl ../lib/ssl/c_src/$host/Makefile:../lib/ssl/c_src/Makefile.in
../lib/crypto/c_src/$host/Makefile:../lib/crypto/c_src/Makefile.in
../lib/orber/c_src/$host/Makefile:../lib/orber/c_src/Makefile.in
../lib/runtime_tools/c_src/$host/Makefile:../lib/runtime_tools/c_src/Makefile.in
diff --git a/erts/doc/specs/.gitignore b/erts/doc/specs/.gitignore
new file mode 100644
index 0000000000..322eebcb06
--- /dev/null
+++ b/erts/doc/specs/.gitignore
@@ -0,0 +1 @@
+specs_*.xml
diff --git a/erts/doc/src/Makefile b/erts/doc/src/Makefile
index 6578923fe1..cfa5527474 100644
--- a/erts/doc/src/Makefile
+++ b/erts/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2010. All Rights Reserved.
+# Copyright Ericsson AB 1997-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -16,6 +16,9 @@
#
# %CopyrightEnd%
#
+
+SPECS_ESRC = ../../preloaded/src/
+
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
@@ -43,6 +46,12 @@ XML_REF1_FILES = epmd.xml \
run_erl.xml \
start.xml
+XML_REF3_EFILES = \
+ erl_prim_loader.xml \
+ erlang.xml \
+ init.xml \
+ zlib.xml
+
XML_REF3_FILES = \
driver_entry.xml \
erl_nif.xml \
@@ -98,18 +107,26 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
+SPECS_FILES = $(XML_REF3_EFILES:%.xml=$(SPECDIR)/specs_%.xml)
+
+TOP_SPECS_FILE = specs.xml
+
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
XML_FLAGS +=
+KERNEL_SRC=$(ERL_TOP)/lib/kernel/src
+KERNEL_INCLUDE=$(ERL_TOP)/lib/kernel/include
+SPECS_FLAGS = -I$(KERNEL_SRC) -I$(KERNEL_INCLUDE)
+
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-docs: pdf html man $(INFO_FILE)
+docs: man pdf html $(INFO_FILE)
$(TOP_PDF_FILE): $(XML_FILES)
@@ -132,8 +149,25 @@ clean:
rm -f $(MAN1DIR)/*
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
+ rm -f $(SPECDIR)/*
rm -f errs core *~
+$(SPECDIR)/specs_driver_entry.xml:
+ escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
+ -o$(dir $@) -module driver_entry
+$(SPECDIR)/specs_erl_nif.xml:
+ escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
+ -o$(dir $@) -module erl_nif
+$(SPECDIR)/specs_erl_set_memory_block.xml:
+ escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
+ -o$(dir $@) -module erl_set_memory_block
+$(SPECDIR)/specs_erl_driver.xml:
+ escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
+ -o$(dir $@) -module erl_driver
+$(SPECDIR)/specs_erts_alloc.xml:
+ escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
+ -o$(dir $@) -module erts_alloc
+
# ----------------------------------------------------
# Release Target
# ----------------------------------------------------
diff --git a/erts/doc/src/absform.xml b/erts/doc/src/absform.xml
index 4c84412dd6..88e8b284fb 100644
--- a/erts/doc/src/absform.xml
+++ b/erts/doc/src/absform.xml
@@ -285,7 +285,8 @@
<item>If E is <c><![CDATA[fun Name / Arity]]></c>, then
Rep(E) = <c><![CDATA[{'fun',LINE,{function,Name,Arity}}]]></c>.</item>
<item>If E is <c><![CDATA[fun Module:Name/Arity]]></c>, then
- Rep(E) = <c><![CDATA[{'fun',LINE,{function,Module,Name,Arity}}]]></c>.</item>
+ Rep(E) = <c><![CDATA[{'fun',LINE,{function,Rep(Module),Rep(Name),Rep(Arity)}}]]></c>.
+ (Before the R15 release: Rep(E) = <c><![CDATA[{'fun',LINE,{function,Module,Name,Arity}}]]></c>.)</item>
<item>If E is <c><![CDATA[fun Fc_1 ; ... ; Fc_k end]]></c>
where each <c><![CDATA[Fc_i]]></c> is a function clause then Rep(E) =
<c><![CDATA[{'fun',LINE,{clauses,[Rep(Fc_1), ..., Rep(Fc_k)]}}]]></c>.</item>
diff --git a/erts/doc/src/alt_dist.xml b/erts/doc/src/alt_dist.xml
index 36d83a685b..038950b54d 100644
--- a/erts/doc/src/alt_dist.xml
+++ b/erts/doc/src/alt_dist.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2000</year><year>2010</year>
+ <year>2000</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -377,7 +377,7 @@
( 1) typedef enum {
( 2) portTypeUnknown, /* An uninitialized port */
( 3) portTypeListener, /* A listening port/socket */
-( 4) portTypeAcceptor, /* An intermidiate stage when accepting
+( 4) portTypeAcceptor, /* An intermediate stage when accepting
( 5) on a listen port */
( 6) portTypeConnector, /* An intermediate stage when connecting */
( 7) portTypeCommand, /* A connected open port in command mode */
diff --git a/erts/doc/src/epmd.xml b/erts/doc/src/epmd.xml
index 411e627c85..3e7005410f 100644
--- a/erts/doc/src/epmd.xml
+++ b/erts/doc/src/epmd.xml
@@ -120,7 +120,7 @@
<item>
<p>Let this instance of <c>epmd</c> listen only on the
comma-separated list of IP addresses and on the loopback address
- (which is implicitely added to the list if it has not been
+ (which is implicitly added to the list if it has not been
specified). This can also be set using the
<c><![CDATA[ERL_EPMD_ADDRESS]]></c> environment variable, see the
section <seealso marker="#environment_variables">Environment
@@ -243,7 +243,7 @@
<p>This environment variable may be set to a comma-separated
list of IP addresses, in which case the <c>epmd</c> daemon
will listen only on the specified address(es) and on the
- loopback address (which is implicitely added to the list if it
+ loopback address (which is implicitly added to the list if it
has not been specified). The default behaviour is to listen on
all available IP addresses.</p>
</item>
diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml
index 50f90ec9df..d0a0ceaeba 100644
--- a/erts/doc/src/erl.xml
+++ b/erts/doc/src/erl.xml
@@ -587,6 +587,13 @@
<p>Enables auto load tracing, displaying info while loading
code.</p>
</item>
+ <tag><c><![CDATA[+L]]></c></tag>
+ <item>
+ <p>Don't load information about source filenames and line numbers.
+ This will save some memory, but exceptions will not contain
+ information about the filenames and line numbers.
+ </p>
+ </item>
<tag><marker id="erts_alloc"><c><![CDATA[+MFlag Value]]></c></marker></tag>
<item>
<p>Memory allocator specific flags, see
@@ -1000,7 +1007,7 @@
the <c><![CDATA[-extra]]></c> section, i.e. the end of the command line
following after an <c><![CDATA[-extra]]></c> flag.</p>
</item>
- <tag><c><![CDATA[ERL_ZFLAGS]]></c>and <c><![CDATA[ERL_FLAGS]]></c></tag>
+ <tag><c><![CDATA[ERL_ZFLAGS]]></c> and <c><![CDATA[ERL_FLAGS]]></c></tag>
<item>
<p>The content of these environment variables will be added to the
end of the command line for <c><![CDATA[erl]]></c>.</p>
@@ -1023,7 +1030,7 @@
list of IP addresses, in which case the
<seealso marker="epmd">epmd</seealso> daemon
will listen only on the specified address(es) and on the
- loopback address (which is implicitely added to the list if it
+ loopback address (which is implicitly added to the list if it
has not been specified).</p>
</item>
<tag><c><![CDATA[ERL_EPMD_PORT]]></c></tag>
diff --git a/erts/doc/src/erl_driver.xml b/erts/doc/src/erl_driver.xml
index 2fb03954b6..8e18dd6657 100644
--- a/erts/doc/src/erl_driver.xml
+++ b/erts/doc/src/erl_driver.xml
@@ -1638,12 +1638,19 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len
<fsummary>Cancel an asynchronous call</fsummary>
<desc>
<marker id="driver_async_cancel"></marker>
- <p>This function cancels an asynchronous operation, by removing
- it from the queue. Only functions in the queue can be
- cancelled; if a function is executing, it's too late to
- cancel it. The <c>async_free</c> function is also called.</p>
- <p>The return value is 1 if the operation was removed from the
- queue, otherwise 0.</p>
+ <p>This function used to cancel a scheduled asynchronous operation,
+ if it was still in the queue. It returned 1 if it succeeded, and
+ 0 if it failed.</p>
+ <p>Since it could not guarantee success, it was more or less useless.
+ The user had to implement synchronization of cancellation anyway.
+ It also unnecessarily complicated the implementation. Therefore,
+ as of OTP-R15B <c>driver_async_cancel()</c> is deprecated, and
+ scheduled for removal in OTP-R16. It will currently always fail,
+ and return 0.</p>
+ <warning><p><c>driver_async_cancel()</c> is deferred and will
+ be removed in the OTP-R16 release.</p>
+ </warning>
+
</desc>
</func>
<func>
diff --git a/erts/doc/src/erl_ext_fig.gif b/erts/doc/src/erl_ext_fig.gif
index 14d6bbc871..14d6bbc871 100755..100644
--- a/erts/doc/src/erl_ext_fig.gif
+++ b/erts/doc/src/erl_ext_fig.gif
Binary files differ
diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml
index cdce4ec0b8..8daa67aa87 100644
--- a/erts/doc/src/erl_nif.xml
+++ b/erts/doc/src/erl_nif.xml
@@ -216,14 +216,14 @@ ok
<p/>
<code type="none">
ERL_NIF_TERM term;
- MyStruct* ptr = enif_alloc_resource(my_resource_type, sizeof(MyStruct));
+ MyStruct* obj = enif_alloc_resource(my_resource_type, sizeof(MyStruct));
/* initialize struct ... */
- term = enif_make_resource(env, ptr);
+ term = enif_make_resource(env, obj);
if (keep_a_reference_of_our_own) {
- /* store 'ptr' in static variable, private data or other resource object */
+ /* store 'obj' in static variable, private data or other resource object */
}
else {
enif_release_resource(obj);
@@ -692,6 +692,10 @@ typedef enum {
<fsummary>Determine if a term is an exception</fsummary>
<desc><p>Return true if <c>term</c> is an exception.</p></desc>
</func>
+ <func><name><ret>int</ret><nametext>enif_is_number(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
+ <fsummary>Determine if a term is a number (integer or float)</fsummary>
+ <desc><p>Return true if <c>term</c> is a number.</p></desc>
+ </func>
<func><name><ret>int</ret><nametext>enif_is_fun(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
<fsummary>Determine if a term is a fun</fsummary>
<desc><p>Return true if <c>term</c> is a fun.</p></desc>
@@ -822,6 +826,13 @@ typedef enum {
<desc><p>Create an ordinary list containing the elements of array <c>arr</c>
of length <c>cnt</c>. An empty list is returned if <c>cnt</c> is 0.</p></desc>
</func>
+ <func><name><ret>int</ret><nametext>enif_make_reverse_list(ErlNifEnv* env, ERL_NIF_TERM term, ERL_NIF_TERM *list)</nametext></name>
+ <fsummary>Create the reverse list of the list <c>term</c>.</fsummary>
+ <desc><p>Set <c>*list</c> to the reverse list of the list <c>term</c> and return true,
+ or return false if <c>term</c> is not a list. This function should only be used on
+ short lists as a copy will be created of the list which will not be released until after the
+ nif returns.</p></desc>
+ </func>
<func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_long(ErlNifEnv* env, long int i)</nametext></name>
<fsummary>Create an integer term from a long int</fsummary>
<desc><p>Create an integer term from a <c>long int</c>.</p></desc>
diff --git a/erts/doc/src/erl_prim_loader.xml b/erts/doc/src/erl_prim_loader.xml
index ccaa9b725f..9f5b3f385b 100644
--- a/erts/doc/src/erl_prim_loader.xml
+++ b/erts/doc/src/erl_prim_loader.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -55,33 +55,31 @@
<c>-loader_debug</c> are also experimental</p></warning>
</description>
+ <datatypes>
+ <datatype>
+ <name name="host"/>
+ </datatype>
+ </datatypes>
+
<funcs>
<func>
- <name>start(Id, Loader, Hosts) -> {ok, Pid} | {error, What}</name>
+ <name name="start" arity="3"/>
<fsummary>Start the Erlang low level loader</fsummary>
- <type>
- <v>Id = term()</v>
- <v>Loader = atom() | string()</v>
- <v>Hosts = [Host]</v>
- <v>Host = atom()</v>
- <v>Pid = pid()</v>
- <v>What = term()</v>
- </type>
<desc>
<p>Starts the Erlang low level loader. This function is called
by the <c>init</c> process (and module). The <c>init</c>
- process reads the command line flags <c>-id Id</c>,
- <c>-loader Loader</c>, and <c>-hosts Hosts</c>. These are
+ process reads the command line flags <c>-id <anno>Id</anno></c>,
+ <c>-loader <anno>Loader</anno></c>, and <c>-hosts <anno>Hosts</anno></c>. These are
the arguments supplied to the <c>start/3</c> function.</p>
<p>If <c>-loader</c> is not given, the default loader is
<c>efile</c> which tells the system to read from the file
system.</p>
- <p>If <c>-loader</c> is <c>inet</c>, the <c>-id Id</c>,
- <c>-hosts Hosts</c>, and <c>-setcookie Cookie</c> flags must
- also be supplied. <c>Hosts</c> identifies hosts which this
+ <p>If <c>-loader</c> is <c>inet</c>, the <c>-id <anno>Id</anno></c>,
+ <c>-hosts <anno>Hosts</anno></c>, and <c>-setcookie Cookie</c> flags must
+ also be supplied. <c><anno>Hosts</anno></c> identifies hosts which this
node can contact in order to load modules. One Erlang
runtime system with a <c>erl_boot_server</c> process must be
- started on each of hosts given in <c>Hosts</c> in order to
+ 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
@@ -90,35 +88,26 @@
</desc>
</func>
<func>
- <name>get_file(Filename) -> {ok, Bin, FullName} | error</name>
+ <name name="get_file" arity="1"/>
<fsummary>Get a file</fsummary>
- <type>
- <v>Filename = string()</v>
- <v>Bin = binary()</v>
- <v>FullName = string()</v>
- </type>
<desc>
<p>This function fetches a file using the low level loader.
- <c>Filename</c> is either an absolute file name or just the name
+ <c><anno>Filename</anno></c> is either an absolute file name or just the name
of the file, for example <c>"lists.beam"</c>. If an internal
path is set to the loader, this path is used to find the file.
If a user supplied loader is used, the path can be stripped
off if it is obsolete, and the loader does not use a path.
- <c>FullName</c> is the complete name of the fetched file.
- <c>Bin</c> is the contents of the file as a binary.</p>
+ <c><anno>FullName</anno></c> is the complete name of the fetched file.
+ <c><anno>Bin</anno></c> is the contents of the file as a binary.</p>
- <p>The <c>Filename</c> can also be a file in an archive. For example
- <c>/otp/root/lib/mnesia-4.4.7.ez/mnesia-4.4.7/ebin/mnesia_backup.beam</c>
+ <p>The <c><anno>Filename</anno></c> can also be a file in an archive. For example
+ <c>$OTPROOT/lib/</c><c>mnesia-4.4.7.ez/mnesia-4.4.7/ebin/</c><c>mnesia.beam</c>.
See <seealso marker="kernel:code">code(3)</seealso> about archive files.</p>
</desc>
</func>
<func>
- <name>get_path() -> {ok, Path}</name>
+ <name name="get_path" arity="0"/>
<fsummary>Get the path set in the loader</fsummary>
- <type>
- <v>Path = [Dir]</v>
- <v>Dir = string()</v>
- </type>
<desc>
<p>This function gets the path set in the loader. The path is
set by the <c>init</c> process according to information found
@@ -126,35 +115,26 @@
</desc>
</func>
<func>
- <name>list_dir(Dir) -> {ok, Filenames} | error</name>
+ <name name="list_dir" arity="1"/>
<fsummary>List files in a directory</fsummary>
- <type>
- <v>Dir = name()</v>
- <v>Filenames = [Filename]</v>
- <v>Filename = string()</v>
- </type>
<desc>
<p>Lists all the files in a directory. Returns
- <c>{ok, Filenames}</c> if successful. Otherwise, it returns
- <c>error</c>. <c>Filenames</c> is a list of
+ <c>{ok, <anno>Filenames</anno>}</c> if successful. Otherwise, it returns
+ <c>error</c>. <c><anno>Filenames</anno></c> is a list of
the names of all the files in the directory. The names are
not sorted.</p>
- <p>The <c>Dir</c> can also be a directory in an archive. For example
- <c>/otp/root/lib/mnesia-4.4.7.ez/mnesia-4.4.7/ebin</c>
+ <p>The <c><anno>Dir</anno></c> can also be a directory in an archive. For example
+ <c>$OTPROOT/lib/</c><c>mnesia-4.4.7.ez/mnesia-4.4.7/ebin</c>.
See <seealso marker="kernel:code">code(3)</seealso> about archive files.</p>
</desc>
</func>
<func>
- <name>read_file_info(Filename) -> {ok, FileInfo} | error</name>
+ <name name="read_file_info" arity="1"/>
<fsummary>Get information about a file</fsummary>
- <type>
- <v>Filename = name()</v>
- <v>FileInfo = #file_info{}</v>
- </type>
<desc>
<p>Retrieves information about a file. Returns
- <c>{ok, FileInfo}</c> if successful, otherwise
- <c>error</c>. <c>FileInfo</c> is a record
+ <c>{ok, <anno>FileInfo</anno>}</c> if successful, otherwise
+ <c>error</c>. <c><anno>FileInfo</anno></c> is a record
<c>file_info</c>, defined in the Kernel include file
<c>file.hrl</c>. Include the following directive in the module
from which the function is called:</p>
@@ -162,18 +142,14 @@
-include_lib("kernel/include/file.hrl").</code>
<p>See <seealso marker="kernel:file">file(3)</seealso> for more info about
the record <c>file_info</c>.</p>
- <p>The <c>Filename</c> can also be a file in an archive. For example
- <c>/otp/root/lib/mnesia-4.4.7.ez/mnesia-4.4.7/ebin/mnesia_backup.beam</c>
+ <p>The <c><anno>Filename</anno></c> can also be a file in an archive. For example
+ <c>$OTPROOT/lib/</c><c>mnesia-4.4.7.ez/mnesia-4.4.7/ebin/</c><c>mnesia</c>.
See <seealso marker="kernel:code">code(3)</seealso> about archive files.</p>
</desc>
</func>
<func>
- <name>set_path(Path) -> ok</name>
+ <name name="set_path" arity="1"/>
<fsummary>Set the path of the loader</fsummary>
- <type>
- <v>Path = [Dir]</v>
- <v>Dir = string()</v>
- </type>
<desc>
<p>This function sets the path of the loader if <c>init</c>
interprets a <c>path</c> command in the start script.</p>
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index f98e15cb52..2ea144eb3f 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -48,22 +48,24 @@
"Allowed in guard tests".</p>
</description>
- <section>
- <title>DATA TYPES</title>
- <marker id="iolist_definition"></marker>
- <code type="none">
-ext_binary()
- a binary data object,
- structured according to the Erlang external term format
-
-iodata() = iolist() | binary()
+ <datatypes>
+ <datatype>
+ <name><marker id="type-ext_binary">ext_binary()</marker></name>
+ <desc>
+ <p>A binary data object, structured according to
+ the Erlang external term format.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="timestamp"></name>
+ <desc><p>See <seealso marker="#now/0">now/0</seealso>.</p>
+ </desc>
+ </datatype>
+ </datatypes>
-iolist() = [char() | binary() | iolist()]
- a binary is allowed as the tail of the list</code>
- </section>
<funcs>
<func>
- <name>abs(Number) -> int() | float()</name>
+ <name>abs(Number) -> integer() | float()</name>
<fsummary>Arithmetical absolute value</fsummary>
<type>
<v>Number = number()</v>
@@ -80,7 +82,7 @@ iolist() = [char() | binary() | iolist()]
</desc>
</func>
<func>
- <name>erlang:adler32(Data) -> int()</name>
+ <name>erlang:adler32(Data) -> integer()</name>
<fsummary>Compute adler32 checksum</fsummary>
<type>
<v>Data = iodata()</v>
@@ -90,10 +92,10 @@ iolist() = [char() | binary() | iolist()]
</desc>
</func>
<func>
- <name>erlang:adler32(OldAdler, Data) -> int()</name>
+ <name>erlang:adler32(OldAdler, Data) -> integer()</name>
<fsummary>Compute adler32 checksum</fsummary>
<type>
- <v>OldAdler = int()</v>
+ <v>OldAdler = integer()</v>
<v>Data = iodata()</v>
</type>
<desc>
@@ -112,11 +114,11 @@ iolist() = [char() | binary() | iolist()]
</desc>
</func>
<func>
- <name>erlang:adler32_combine(FirstAdler, SecondAdler, SecondSize) -> int()</name>
+ <name>erlang:adler32_combine(FirstAdler, SecondAdler, SecondSize) -> integer()</name>
<fsummary>Combine two adler32 checksums</fsummary>
<type>
- <v>FirstAdler = SecondAdler = int()</v>
- <v>SecondSize = int()</v>
+ <v>FirstAdler = SecondAdler = integer()</v>
+ <v>SecondSize = integer()</v>
</type>
<desc>
<p>Combines two previously computed adler32 checksums.
@@ -155,20 +157,16 @@ iolist() = [char() | binary() | iolist()]
</desc>
</func>
<func>
- <name>apply(Fun, Args) -> term() | empty()</name>
+ <name name="apply" arity="2"/>
<fsummary>Apply a function to an argument list</fsummary>
- <type>
- <v>Fun = fun()</v>
- <v>Args = [term()]</v>
- </type>
<desc>
- <p>Call a fun, passing the elements in <c>Args</c> as
+ <p>Call a fun, passing the elements in <c><anno>Args</anno></c> as
arguments.</p>
<p>Note: If the number of elements in the arguments are known at
compile-time, the call is better written as
- <c>Fun(Arg1, Arg2, ... ArgN)</c>.</p>
+ <c><anno>Fun</anno>(Arg1, Arg2, ... ArgN)</c>.</p>
<warning>
- <p>Earlier, <c>Fun</c> could also be given as
+ <p>Earlier, <c><anno>Fun</anno></c> could also be given as
<c>{Module, Function}</c>, equivalent to
<c>apply(Module, Function, Args)</c>. This usage is
deprecated and will stop working in a future release of
@@ -177,15 +175,11 @@ iolist() = [char() | binary() | iolist()]
</desc>
</func>
<func>
- <name>apply(Module, Function, Args) -> term() | empty()</name>
+ <name name="apply" arity="3"/>
<fsummary>Apply a function to an argument list</fsummary>
- <type>
- <v>Module = Function = atom()</v>
- <v>Args = [term()]</v>
- </type>
<desc>
<p>Returns the result of applying <c>Function</c> in
- <c>Module</c> to <c>Args</c>. The applied function must
+ <c><anno>Module</anno></c> to <c><anno>Args</anno></c>. The applied function must
be exported from <c>Module</c>. The arity of the function is
the length of <c>Args</c>.</p>
<pre>
@@ -198,7 +192,7 @@ iolist() = [char() | binary() | iolist()]
"Erlang"</pre>
<p>Note: If the number of arguments are known at compile-time,
the call is better written as
- <c>Module:Function(Arg1, Arg2, ..., ArgN)</c>.</p>
+ <c><anno>Module</anno>:<anno>Function</anno>(Arg1, Arg2, ..., ArgN)</c>.</p>
<p>Failure: <c>error_handler:undefined_function/3</c> is called
if the applied function is not exported. The error handler
can be redefined (see
@@ -258,8 +252,8 @@ iolist() = [char() | binary() | iolist()]
<type>
<v>Subject = binary()</v>
<v>PosLen = {Start,Length}</v>
- <v>Start = int()</v>
- <v>Length = int()</v>
+ <v>Start = integer() >= 0</v>
+ <v>Length = integer() >= 0</v>
</type>
<desc>
<p>Extracts the part of the binary described by <c>PosLen</c>.</p>
@@ -291,8 +285,8 @@ iolist() = [char() | binary() | iolist()]
<fsummary>Extracts a part of a binary</fsummary>
<type>
<v>Subject = binary()</v>
- <v>Start = int()</v>
- <v>Length = int()</v>
+ <v>Start = integer() >= 0</v>
+ <v>Length = integer() >= 0</v>
</type>
<desc>
<p>The same as <c>binary_part(Subject, {Pos, Len})</c>.</p>
@@ -390,7 +384,7 @@ iolist() = [char() | binary() | iolist()]
<name>binary_to_term(Binary) -> term()</name>
<fsummary>Decode an Erlang external term format binary</fsummary>
<type>
- <v>Binary = ext_binary()</v>
+ <v>Binary = <seealso marker="#type-ext_binary">ext_binary()</seealso></v>
</type>
<desc>
<p>Returns an Erlang term which is the result of decoding
@@ -411,7 +405,7 @@ iolist() = [char() | binary() | iolist()]
<fsummary>Decode an Erlang external term format binary</fsummary>
<type>
<v>Opts = [safe]</v>
- <v>Binary = ext_binary()</v>
+ <v>Binary = <seealso marker="#type-ext_binary">ext_binary()</seealso></v>
</type>
<desc>
<p>As <c>binary_to_term/1</c>, but takes options that affect decoding
@@ -442,7 +436,7 @@ iolist() = [char() | binary() | iolist()]
</desc>
</func>
<func>
- <name>bit_size(Bitstring) -> int()</name>
+ <name>bit_size(Bitstring) -> integer() >= 0</name>
<fsummary>Return the size of a bitstring</fsummary>
<type>
<v>Bitstring = bitstring()</v>
@@ -461,7 +455,7 @@ iolist() = [char() | binary() | iolist()]
<name>erlang:bump_reductions(Reductions) -> void()</name>
<fsummary>Increment the reduction counter</fsummary>
<type>
- <v>Reductions = int()</v>
+ <v>Reductions = integer() >= 0</v>
</type>
<desc>
<p>This implementation-dependent function increments
@@ -478,7 +472,7 @@ iolist() = [char() | binary() | iolist()]
</desc>
</func>
<func>
- <name>byte_size(Bitstring) -> int()</name>
+ <name>byte_size(Bitstring) -> integer() >= 0</name>
<fsummary>Return the size of a bitstring (or binary)</fsummary>
<type>
<v>Bitstring = bitstring()</v>
@@ -500,7 +494,7 @@ iolist() = [char() | binary() | iolist()]
<fsummary>Cancel a timer</fsummary>
<type>
<v>TimerRef = reference()</v>
- <v>Time = int()</v>
+ <v>Time = integer() >= 0</v>
</type>
<desc>
<p>Cancels a timer, where <c>TimerRef</c> was returned by
@@ -524,7 +518,19 @@ iolist() = [char() | binary() | iolist()]
</func>
<func>
- <name>check_process_code(Pid, Module) -> bool()</name>
+ <name>check_old_code(Module) -> boolean()</name>
+ <fsummary>Check if a module has old code</fsummary>
+ <type>
+ <v>Module = atom()</v>
+ </type>
+ <desc>
+ <p>Returns <c>true</c> if the <c>Module</c> has old code,
+ and <c>false</c> otherwise.</p>
+ <p>See also <seealso marker="kernel:code">code(3)</seealso>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>check_process_code(Pid, Module) -> boolean()</name>
<fsummary>Check if a process is executing old code for a module</fsummary>
<type>
<v>Pid = pid()</v>
@@ -544,16 +550,7 @@ false</pre>
</desc>
</func>
<func>
- <name>concat_binary(ListOfBinaries)</name>
- <fsummary>Concatenate a list of binaries (deprecated)</fsummary>
- <desc>
- <p>Do not use; use
- <seealso marker="#list_to_binary/1">list_to_binary/1</seealso>
- instead.</p>
- </desc>
- </func>
- <func>
- <name>erlang:crc32(Data) -> int()</name>
+ <name>erlang:crc32(Data) -> integer() >= 0</name>
<fsummary>Compute crc32 (IEEE 802.3) checksum</fsummary>
<type>
<v>Data = iodata()</v>
@@ -563,10 +560,10 @@ false</pre>
</desc>
</func>
<func>
- <name>erlang:crc32(OldCrc, Data) -> int()</name>
+ <name>erlang:crc32(OldCrc, Data) -> integer() >= 0</name>
<fsummary>Compute crc32 (IEEE 802.3) checksum</fsummary>
<type>
- <v>OldCrc = int()</v>
+ <v>OldCrc = integer() >= 0</v>
<v>Data = iodata()</v>
</type>
<desc>
@@ -585,11 +582,11 @@ false</pre>
</desc>
</func>
<func>
- <name>erlang:crc32_combine(FirstCrc, SecondCrc, SecondSize) -> int()</name>
+ <name>erlang:crc32_combine(FirstCrc, SecondCrc, SecondSize) -> integer() >= 0</name>
<fsummary>Combine two crc32 (IEEE 802.3) checksums</fsummary>
<type>
- <v>FirstCrc = SecondCrc = int()</v>
- <v>SecondSize = int()</v>
+ <v>FirstCrc = SecondCrc = integer() >= 0</v>
+ <v>SecondSize = integer() >= 0</v>
</type>
<desc>
<p>Combines two previously computed crc32 checksums.
@@ -609,10 +606,10 @@ false</pre>
</desc>
</func>
<func>
- <name>date() -> {Year, Month, Day}</name>
+ <name>date() -> Date</name>
<fsummary>Current date</fsummary>
<type>
- <v>Year = Month = Day = int()</v>
+ <v>Date = <seealso marker="calendar#type-date">calendar:date()</seealso></v>
</type>
<desc>
<p>Returns the current date as <c>{Year, Month, Day}</c>.</p>
@@ -631,20 +628,20 @@ false</pre>
<v>Options = [Opt]</v>
<v>Packet = binary() | HttpPacket</v>
<v>Rest = binary()</v>
- <v>Length = int() | undefined</v>
+ <v>Length = integer() > 0 | undefined</v>
<v>Reason = term()</v>
<v>&nbsp;Type, Opt -- see below</v>
<v></v>
<v>HttpPacket = HttpRequest | HttpResponse | HttpHeader | http_eoh | HttpError</v>
<v>HttpRequest = {http_request, HttpMethod, HttpUri, HttpVersion}</v>
<v>HttpResponse = {http_response, HttpVersion, integer(), HttpString}</v>
- <v>HttpHeader = {http_header, int(), HttpField, Reserved=term(), Value=HttpString}</v>
+ <v>HttpHeader = {http_header, integer(), HttpField, Reserved=term(), Value=HttpString}</v>
<v>HttpError = {http_error, HttpString}</v>
<v>HttpMethod = HttpMethodAtom | HttpString</v>
<v>HttpMethodAtom = 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'TRACE'</v>
- <v>HttpUri = '*' | {absoluteURI, http|https, Host=HttpString, Port=int()|undefined, Path=HttpString} |
+ <v>HttpUri = '*' | {absoluteURI, http|https, Host=HttpString, Port=integer()|undefined, Path=HttpString} |
{scheme, Scheme=HttpString, HttpString} | {abs_path, HttpString} | HttpString</v>
- <v>HttpVersion = {Major=int(), Minor=int()}</v>
+ <v>HttpVersion = {Major=integer(), Minor=integer()}</v>
<v>HttpString = string() | binary()</v>
<v>HttpField = HttpFieldAtom | HttpString</v>
<v>HttpFieldAtom = 'Cache-Control' | 'Connection' | 'Date' | 'Pragma' | 'Transfer-Encoding' | 'Upgrade' | 'Via' | 'Accept' | 'Accept-Charset' | 'Accept-Encoding' | 'Accept-Language' | 'Authorization' | 'From' | 'Host' | 'If-Modified-Since' | 'If-Match' | 'If-None-Match' | 'If-Range' | 'If-Unmodified-Since' | 'Max-Forwards' | 'Proxy-Authorization' | 'Range' | 'Referer' | 'User-Agent' | 'Age' | 'Location' | 'Proxy-Authenticate' | 'Public' | 'Retry-After' | 'Server' | 'Vary' | 'Warning' | 'Www-Authenticate' | 'Allow' | 'Content-Base' | 'Content-Encoding' | 'Content-Language' | 'Content-Length' | 'Content-Location' | 'Content-Md5' | 'Content-Range' | 'Content-Type' | 'Etag' | 'Expires' | 'Last-Modified' | 'Accept-Ranges' | 'Set-Cookie' | 'Set-Cookie2' | 'X-Forwarded-For' | 'Cookie' | 'Keep-Alive' | 'Proxy-Connection'</v>
@@ -719,14 +716,14 @@ false</pre>
</taglist>
<p>The following options are available:</p>
<taglist>
- <tag><c>{packet_size, int()}</c></tag>
+ <tag><c>{packet_size, integer()}</c></tag>
<item><p>Sets the max allowed size of the packet body. If
the packet header indicates that the length of the
packet is longer than the max allowed length, the packet
is considered invalid. Default is 0 which means no
size limit.</p>
</item>
- <tag><c>{line_length, int()}</c></tag>
+ <tag><c>{line_length, integer()}</c></tag>
<item><p>Applies only to line oriented protocols
(<c>line</c>, <c>http</c>). Lines longer than this
will be truncated.</p>
@@ -800,13 +797,12 @@ false</pre>
</desc>
</func>
<func>
- <name>demonitor(MonitorRef, OptionList) -> true|false</name>
+ <name>demonitor(MonitorRef, OptionList) -> boolean()</name>
<fsummary>Stop monitoring</fsummary>
<type>
<v>MonitorRef = reference()</v>
<v>OptionList = [Option]</v>
- <v>Option = flush</v>
- <v>Option = info</v>
+ <v>&nbsp;Option = flush | info</v>
</type>
<desc>
<p>The returned value is <c>true</c> unless <c>info</c> is part
@@ -867,14 +863,11 @@ false</pre>
</desc>
</func>
<func>
- <name>disconnect_node(Node) -> bool() | ignored</name>
+ <name name="disconnect_node" arity="1"/>
<fsummary>Force the disconnection of a node</fsummary>
- <type>
- <v>Node = atom()</v>
- </type>
<desc>
<p>Forces the disconnection of a node. This will appear to
- the node <c>Node</c> as if the local node has crashed. This
+ the node <c><anno>Node</anno></c> as if the local node has crashed. This
BIF is mainly used in the Erlang network authentication
protocols. Returns <c>true</c> if disconnection succeeds,
otherwise <c>false</c>. If the local node is not alive,
@@ -1032,6 +1025,56 @@ b</pre>
</desc>
</func>
<func>
+ <name>erlang:external_size(Term) -> integer() >= 0</name>
+ <fsummary>Calculate the maximum size for a term encoded in the Erlang
+ external term format</fsummary>
+ <type>
+ <v>Term = term()</v>
+ </type>
+ <desc>
+ <p>Calculates, without doing the encoding, the maximum byte size for
+ a term encoded in the Erlang external term format. The following
+ condition applies always:</p>
+ <p>
+ <pre>
+> <input>Size1 = byte_size(term_to_binary(Term)),</input>
+> <input>Size2 = erlang:external_size(Term),</input>
+> <input>true = Size1 =&lt; Size2.</input>
+true
+ </pre>
+ </p>
+ <p>This is equivalent to a call to: <code>erlang:external_size(Term, [])
+ </code></p>
+ </desc>
+ </func>
+ <func>
+ <name>erlang:external_size(Term, [Option]) -> integer() >= 0</name>
+ <fsummary>Calculate the maximum size for a term encoded in the Erlang
+ external term format</fsummary>
+ <type>
+ <v>Term = term()</v>
+ <v>Option = {minor_version, Version}</v>
+ </type>
+ <desc>
+ <p>Calculates, without doing the encoding, the maximum byte size for
+ a term encoded in the Erlang external term format. The following
+ condition applies always:</p>
+ <p>
+ <pre>
+> <input>Size1 = byte_size(term_to_binary(Term, Options)),</input>
+> <input>Size2 = erlang:external_size(Term, Options),</input>
+> <input>true = Size1 =&lt; Size2.</input>
+true
+ </pre>
+ </p>
+ <p>The option <c>{minor_version, Version}</c> specifies how floats
+ are encoded. See
+ <seealso marker="#term_to_binary/2">term_to_binary/2</seealso> for
+ a more detailed description.
+ </p>
+ </desc>
+ </func>
+ <func>
<name>float(Number) -> float()</name>
<fsummary>Convert a number to a float</fsummary>
<type>
@@ -1069,15 +1112,11 @@ b</pre>
</desc>
</func>
<func>
- <name>erlang:fun_info(Fun) -> [{Item, Info}]</name>
+ <name name="fun_info" arity="1"/>
<fsummary>Information about a fun</fsummary>
- <type>
- <v>Fun = fun()</v>
- <v>Item, Info -- see below</v>
- </type>
<desc>
<p>Returns a list containing information about the fun
- <c>Fun</c>. Each element of the list is a tuple. The order of
+ <c><anno>Fun</anno></c>. Each element of the list is a tuple. The order of
the tuples is not defined, and more tuples may be added in a
future release.</p>
<warning>
@@ -1156,11 +1195,16 @@ b</pre>
</item>
<tag><c>{new_uniq, Uniq}</c></tag>
<item>
- <p><c>Uniq</c> (a binary) is a unique value for this fun.</p>
+ <p><c>Uniq</c> (a binary) is a unique value for this fun.
+ It is calculated from the compiled code for the entire module.</p>
</item>
<tag><c>{uniq, Uniq}</c></tag>
<item>
- <p><c>Uniq</c> (an integer) is a unique value for this fun.</p>
+ <p><c>Uniq</c> (an integer) is a unique value for this fun.
+ Starting in the R15 release, this integer is calculated from
+ the compiled code for the entire module. Before R15, this
+ integer was based on only the body of the fun.
+ </p>
</item>
</taglist>
</desc>
@@ -1176,7 +1220,7 @@ b</pre>
<p>Returns information about <c>Fun</c> as specified by
<c>Item</c>, in the form <c>{Item,Info}</c>.</p>
<p>For any fun, <c>Item</c> can be any of the atoms
- <c>module</c>, <c>name</c>, <c>arity</c>, or <c>env</c>.</p>
+ <c>module</c>, <c>name</c>, <c>arity</c>, <c>env</c>, or <c>type</c>.</p>
<p>For a local fun, <c>Item</c> can also be any of the atoms
<c>index</c>, <c>new_index</c>, <c>new_uniq</c>,
<c>uniq</c>, and <c>pid</c>. For an external fun, the value
@@ -1197,11 +1241,11 @@ b</pre>
</desc>
</func>
<func>
- <name>erlang:function_exported(Module, Function, Arity) -> bool()</name>
+ <name>erlang:function_exported(Module, Function, Arity) -> boolean()</name>
<fsummary>Check if a function is exported and loaded</fsummary>
<type>
<v>Module = Function = atom()</v>
- <v>Arity = int()</v>
+ <v>Arity = arity()</v>
</type>
<desc>
<p>Returns <c>true</c> if the module <c>Module</c> is loaded
@@ -1229,7 +1273,7 @@ b</pre>
</desc>
</func>
<func>
- <name>garbage_collect(Pid) -> bool()</name>
+ <name>garbage_collect(Pid) -> boolean()</name>
<fsummary>Force an immediate garbage collection of a process</fsummary>
<type>
<v>Pid = pid()</v>
@@ -1276,11 +1320,8 @@ b</pre>
</desc>
</func>
<func>
- <name>erlang:get_cookie() -> Cookie | nocookie</name>
+ <name name="get_cookie" arity="0"/>
<fsummary>Get the magic cookie of the local node</fsummary>
- <type>
- <v>Cookie = atom()</v>
- </type>
<desc>
<p>Returns the magic cookie of the local node, if the node is
alive; otherwise the atom <c>nocookie</c>.</p>
@@ -1307,17 +1348,18 @@ b</pre>
</desc>
</func>
<func>
- <name>erlang:get_stacktrace() -> [{Module, Function, Arity | Args}]</name>
+ <name>erlang:get_stacktrace() -> [{Module, Function, Arity | Args, Location}]</name>
<fsummary>Get the call stack back-trace of the last exception</fsummary>
<type>
<v>Module = Function = atom()</v>
- <v>Arity = int()</v>
+ <v>Arity = arity()</v>
<v>Args = [term()]</v>
+ <v>Location = [{atom(),term()}]</v>
</type>
<desc>
<p>Get the call stack back-trace (<em>stacktrace</em>) of the last
exception in the calling process as a list of
- <c>{Module,Function,Arity}</c> tuples.
+ <c>{Module,Function,Arity,Location}</c> tuples.
The <c>Arity</c> field in the first tuple may be the argument
list of that function call instead of an arity integer,
depending on the exception.</p>
@@ -1327,6 +1369,25 @@ b</pre>
<p>The stacktrace is the same data as the <c>catch</c> operator
returns, for example:</p>
<p><c>{'EXIT',{badarg,Stacktrace}} = catch abs(x)</c></p>
+ <p><c>Location</c> is a (possibly empty) list of two-tuples that
+ may indicate the location in the source code of the function.
+ The first element is an atom that describes the type of
+ information in the second element. Currently the following
+ items may occur:</p>
+ <taglist>
+ <tag><c>file</c></tag>
+ <item>
+ <p>The second element of the tuple is a string (list of
+ characters) representing the filename of the source file
+ of the function.</p>
+ </item>
+ <tag><c>line</c></tag>
+ <item>
+ <p>The second element of the tuple is the line number
+ (an integer greater than zero) in the source file
+ where the exception occurred or the function was called.</p>
+ </item>
+ </taglist>
<p>See also
<seealso marker="#error/1">erlang:error/1</seealso> and
<seealso marker="#error/2">erlang:error/2</seealso>.</p>
@@ -1379,7 +1440,7 @@ os_prompt%</pre>
<name>halt(Status)</name>
<fsummary>Halt the Erlang runtime system</fsummary>
<type>
- <v>Status = int()>=0 | string()</v>
+ <v>Status = integer() >= 0 | string()</v>
</type>
<desc>
<p><c>Status</c> must be a non-negative integer, or a string.
@@ -1472,7 +1533,7 @@ os_prompt%</pre>
<name>integer_to_list(Integer) -> string()</name>
<fsummary>Text representation of an integer</fsummary>
<type>
- <v>Integer = int()</v>
+ <v>Integer = integer()</v>
</type>
<desc>
<p>Returns a string which corresponds to the text
@@ -1483,15 +1544,11 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>integer_to_list(Integer, Base) -> string()</name>
+ <name name="integer_to_list" arity="2"/>
<fsummary>Text representation of an integer</fsummary>
- <type>
- <v>Integer = int()</v>
- <v>Base = 2..36</v>
- </type>
<desc>
<p>Returns a string which corresponds to the text
- representation of <c>Integer</c> in base <c>Base</c>.</p>
+ representation of <c><anno>Integer</anno></c> in base <c><anno>Base</anno></c>.</p>
<pre>
> <input>integer_to_list(1023, 16).</input>
"3FF"</pre>
@@ -1518,7 +1575,7 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>iolist_size(Item) -> int()</name>
+ <name>iolist_size(Item) -> integer() >= 0</name>
<fsummary>Size of an iolist</fsummary>
<type>
<v>Item = iolist() | binary()</v>
@@ -1533,7 +1590,7 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>is_alive() -> bool()</name>
+ <name>is_alive() -> boolean()</name>
<fsummary>Check whether the local node is alive</fsummary>
<desc>
<p>Returns <c>true</c> if the local node is alive; that is, if
@@ -1542,7 +1599,7 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>is_atom(Term) -> bool()</name>
+ <name>is_atom(Term) -> boolean()</name>
<fsummary>Check whether a term is an atom</fsummary>
<type>
<v>Term = term()</v>
@@ -1554,7 +1611,7 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>is_binary(Term) -> bool()</name>
+ <name>is_binary(Term) -> boolean()</name>
<fsummary>Check whether a term is a binary</fsummary>
<type>
<v>Term = term()</v>
@@ -1569,7 +1626,7 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>is_bitstring(Term) -> bool()</name>
+ <name>is_bitstring(Term) -> boolean()</name>
<fsummary>Check whether a term is a bitstring</fsummary>
<type>
<v>Term = term()</v>
@@ -1582,7 +1639,7 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>is_boolean(Term) -> bool()</name>
+ <name>is_boolean(Term) -> boolean()</name>
<fsummary>Check whether a term is a boolean</fsummary>
<type>
<v>Term = term()</v>
@@ -1595,11 +1652,11 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>erlang:is_builtin(Module, Function, Arity) -> bool()</name>
+ <name>erlang:is_builtin(Module, Function, Arity) -> boolean()</name>
<fsummary>Check if a function is a BIF implemented in C</fsummary>
<type>
<v>Module = Function = atom()</v>
- <v>Arity = int()</v>
+ <v>Arity = arity()</v>
</type>
<desc>
<p>Returns <c>true</c> if <c>Module:Function/Arity</c> is
@@ -1608,7 +1665,7 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>is_float(Term) -> bool()</name>
+ <name>is_float(Term) -> boolean()</name>
<fsummary>Check whether a term is a float</fsummary>
<type>
<v>Term = term()</v>
@@ -1620,7 +1677,7 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>is_function(Term) -> bool()</name>
+ <name>is_function(Term) -> boolean()</name>
<fsummary>Check whether a term is a fun</fsummary>
<type>
<v>Term = term()</v>
@@ -1632,11 +1689,11 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>is_function(Term, Arity) -> bool()</name>
+ <name>is_function(Term, Arity) -> boolean()</name>
<fsummary>Check whether a term is a fun with a given arity</fsummary>
<type>
<v>Term = term()</v>
- <v>Arity = int()</v>
+ <v>Arity = arity()</v>
</type>
<desc>
<p>Returns <c>true</c> if <c>Term</c> is a fun that can be
@@ -1653,7 +1710,7 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>is_integer(Term) -> bool()</name>
+ <name>is_integer(Term) -> boolean()</name>
<fsummary>Check whether a term is an integer</fsummary>
<type>
<v>Term = term()</v>
@@ -1665,7 +1722,7 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>is_list(Term) -> bool()</name>
+ <name>is_list(Term) -> boolean()</name>
<fsummary>Check whether a term is a list</fsummary>
<type>
<v>Term = term()</v>
@@ -1677,7 +1734,7 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>is_number(Term) -> bool()</name>
+ <name>is_number(Term) -> boolean()</name>
<fsummary>Check whether a term is a number</fsummary>
<type>
<v>Term = term()</v>
@@ -1689,7 +1746,7 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>is_pid(Term) -> bool()</name>
+ <name>is_pid(Term) -> boolean()</name>
<fsummary>Check whether a term is a pid</fsummary>
<type>
<v>Term = term()</v>
@@ -1701,7 +1758,7 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>is_port(Term) -> bool()</name>
+ <name>is_port(Term) -> boolean()</name>
<fsummary>Check whether a term is a port</fsummary>
<type>
<v>Term = term()</v>
@@ -1713,7 +1770,7 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>is_process_alive(Pid) -> bool()</name>
+ <name>is_process_alive(Pid) -> boolean()</name>
<fsummary>Check whether a process is alive</fsummary>
<type>
<v>Pid = pid()</v>
@@ -1728,7 +1785,7 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>is_record(Term, RecordTag) -> bool()</name>
+ <name>is_record(Term, RecordTag) -> boolean()</name>
<fsummary>Check whether a term appears to be a record</fsummary>
<type>
<v>Term = term()</v>
@@ -1751,12 +1808,12 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>is_record(Term, RecordTag, Size) -> bool()</name>
+ <name>is_record(Term, RecordTag, Size) -> boolean()</name>
<fsummary>Check whether a term appears to be a record</fsummary>
<type>
<v>Term = term()</v>
<v>RecordTag = atom()</v>
- <v>Size = int()</v>
+ <v>Size = integer()</v>
</type>
<desc>
<p><c>RecordTag</c> must be an atom. Returns <c>true</c> if
@@ -1771,7 +1828,7 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>is_reference(Term) -> bool()</name>
+ <name>is_reference(Term) -> boolean()</name>
<fsummary>Check whether a term is a reference</fsummary>
<type>
<v>Term = term()</v>
@@ -1783,7 +1840,7 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>is_tuple(Term) -> bool()</name>
+ <name>is_tuple(Term) -> boolean()</name>
<fsummary>Check whether a term is a tuple</fsummary>
<type>
<v>Term = term()</v>
@@ -1795,7 +1852,7 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>length(List) -> int()</name>
+ <name>length(List) -> integer() >= 0</name>
<fsummary>Length of a list</fsummary>
<type>
<v>List = [term()]</v>
@@ -1916,7 +1973,7 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>list_to_integer(String) -> int()</name>
+ <name>list_to_integer(String) -> integer()</name>
<fsummary>Convert from text representation to an integer</fsummary>
<type>
<v>String = string()</v>
@@ -1932,19 +1989,15 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>list_to_integer(String, Base) -> int()</name>
+ <name name="list_to_integer" arity="2"/>
<fsummary>Convert from text representation to an integer</fsummary>
- <type>
- <v>String = string()</v>
- <v>Base = 2..36</v>
- </type>
<desc>
<p>Returns an integer whose text representation in base
- <c>Base</c> is <c>String</c>.</p>
+ <c><anno>Base</anno></c> is <c><anno>String</anno></c>.</p>
<pre>
> <input>list_to_integer("3FF", 16).</input>
1023</pre>
- <p>Failure: <c>badarg</c> if <c>String</c> contains a bad
+ <p>Failure: <c>badarg</c> if <c><anno>String</anno></c> contains a bad
representation of an integer.</p>
</desc>
</func>
@@ -2095,12 +2148,10 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>erlang:localtime() -> {Date, Time}</name>
+ <name>erlang:localtime() -> DateTime</name>
<fsummary>Current local date and time</fsummary>
<type>
- <v>Date = {Year, Month, Day}</v>
- <v>Time = {Hour, Minute, Second}</v>
- <v>&nbsp;Year = Month = Day = Hour = Minute = Second = int()</v>
+ <v>DateTime = <seealso marker="calendar#type-datetime">calendar:datetime()</seealso></v>
</type>
<desc>
<p>Returns the current local date and time
@@ -2113,17 +2164,12 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>erlang:localtime_to_universaltime({Date1, Time1}) -> {Date2, Time2}</name>
+ <name name="localtime_to_universaltime" arity="1"/>
<fsummary>Convert from local to Universal Time Coordinated (UTC) date and time</fsummary>
- <type>
- <v>Date1 = Date2 = {Year, Month, Day}</v>
- <v>Time1 = Time2 = {Hour, Minute, Second}</v>
- <v>&nbsp;Year = Month = Day = Hour = Minute = Second = int()</v>
- </type>
<desc>
<p>Converts local date and time to Universal Time Coordinated
(UTC), if this is supported by the underlying OS. Otherwise,
- no conversion is done and <c>{Date1, Time1}</c> is returned.</p>
+ no conversion is done and <c>{<anno>Date1</anno>, <anno>Time1</anno>}</c> is returned.</p>
<pre>
> <input>erlang:localtime_to_universaltime({{1996,11,6},{14,45,17}}).</input>
{{1996,11,6},{13,45,17}}</pre>
@@ -2135,9 +2181,8 @@ os_prompt%</pre>
<name>erlang:localtime_to_universaltime({Date1, Time1}, IsDst) -> {Date2, Time2}</name>
<fsummary>Convert from local to Universal Time Coordinated (UTC) date and time</fsummary>
<type>
- <v>Date1 = Date2 = {Year, Month, Day}</v>
- <v>Time1 = Time2 = {Hour, Minute, Second}</v>
- <v>&nbsp;Year = Month = Day = Hour = Minute = Second = int()</v>
+ <v>Date1 = Date2 = <seealso marker="calendar#type-date">calendar:date()</seealso></v>
+ <v>Time1 = Time2 = <seealso marker="calendar#type-time">calendar:time()</seealso></v>
<v>IsDst = true | false | undefined</v>
</type>
<desc>
@@ -2177,7 +2222,7 @@ os_prompt%</pre>
<name>erlang:make_tuple(Arity, InitialValue) -> tuple()</name>
<fsummary>Create a new tuple of a given arity</fsummary>
<type>
- <v>Arity = int()</v>
+ <v>Arity = arity()</v>
<v>InitialValue = term()</v>
</type>
<desc>
@@ -2192,7 +2237,7 @@ os_prompt%</pre>
<name>erlang:make_tuple(Arity, Default, InitList) -> tuple()</name>
<fsummary>Create a new tuple with given arity and contents</fsummary>
<type>
- <v>Arity = int()</v>
+ <v>Arity = arity()</v>
<v>Default = term()</v>
<v>InitList = [{Position,term()}]</v>
<v>Position = integer()</v>
@@ -2211,14 +2256,11 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>max(Term1, Term2) -> Maximum</name>
+ <name name="max" arity="2"/>
<fsummary>Return the largest of two term</fsummary>
- <type>
- <v>Term1 = Term2 = Maximum = term()</v>
- </type>
<desc>
- <p>Return the largest of <c>Term1</c> and <c>Term2</c>;
- if the terms compares equal, <c>Term1</c> will be returned.</p>
+ <p>Return the largest of <c><anno>Term1</anno></c> and <c><anno>Term2</anno></c>;
+ if the terms compare equal, <c><anno>Term1</anno></c> will be returned.</p>
</desc>
</func>
<func>
@@ -2468,18 +2510,15 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>min(Term1, Term2) -> Minimum</name>
+ <name name="min" arity="2"/>
<fsummary>Return the smallest of two term</fsummary>
- <type>
- <v>Term1 = Term2 = Minimum = term()</v>
- </type>
<desc>
- <p>Return the smallest of <c>Term1</c> and <c>Term2</c>;
- if the terms compare equal, <c>Term1</c> will be returned.</p>
+ <p>Return the smallest of <c><anno>Term1</anno></c> and <c><anno>Term2</anno></c>;
+ if the terms compare equal, <c><anno>Term1</anno></c> will be returned.</p>
</desc>
</func>
<func>
- <name>module_loaded(Module) -> bool()</name>
+ <name>module_loaded(Module) -> boolean()</name>
<fsummary>Check if a module is loaded</fsummary>
<type>
<v>Module = atom()</v>
@@ -2602,7 +2641,7 @@ os_prompt%</pre>
<fsummary>Monitor the status of a node</fsummary>
<type>
<v>Node = node()</v>
- <v>Flag = bool()</v>
+ <v>Flag = boolean()</v>
</type>
<desc>
<p>Monitors the status of the node <c>Node</c>. If <c>Flag</c>
@@ -2628,7 +2667,7 @@ os_prompt%</pre>
<fsummary>Monitor the status of a node</fsummary>
<type>
<v>Node = node()</v>
- <v>Flag = bool()</v>
+ <v>Flag = boolean()</v>
<v>Options = [Option]</v>
<v>Option = allow_passive_connect</v>
</type>
@@ -2711,11 +2750,8 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>nodes() -> Nodes</name>
+ <name name="nodes" arity="0"/>
<fsummary>All visible nodes in the system</fsummary>
- <type>
- <v>Nodes = [node()]</v>
- </type>
<desc>
<p>Returns a list of all visible nodes in the system, excluding
the local node. Same as <c>nodes(visible)</c>.</p>
@@ -2765,11 +2801,12 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>now() -> {MegaSecs, Secs, MicroSecs}</name>
- <fsummary>Elapsed time since 00:00 GMT</fsummary>
+ <name>now() -> timestamp()</name>
<type>
- <v>MegaSecs = Secs = MicroSecs = int()</v>
+ <v>timestamp() = {MegaSecs, Secs, MicroSecs}</v>
+ <v>MegaSecs = Secs = MicroSecs = integer() >= 0</v>
</type>
+ <fsummary>Elapsed time since 00:00 GMT</fsummary>
<desc>
<p>Returns the tuple <c>{MegaSecs, Secs, MicroSecs}</c> which is
the elapsed time since 00:00 GMT, January 1, 1970 (zero hour)
@@ -2792,12 +2829,12 @@ os_prompt%</pre>
<v>PortName = {spawn, Command} | {spawn_driver, Command} | {spawn_executable, FileName} | {fd, In, Out}</v>
<v>&nbsp;Command = string()</v>
<v>&nbsp;FileName = [ FileNameChar ] | binary()</v>
- <v>&nbsp;FileNameChar = int() (1..255 or any Unicode codepoint, see description)</v>
- <v>&nbsp;In = Out = int()</v>
+ <v>&nbsp;FileNameChar = integer() (1..255 or any Unicode codepoint, see description)</v>
+ <v>&nbsp;In = Out = integer()</v>
<v>PortSettings = [Opt]</v>
<v>&nbsp;Opt = {packet, N} | stream | {line, L} | {cd, Dir} | {env, Env} | {args, [ ArgString ]} | {arg0, ArgString} | exit_status | use_stdio | nouse_stdio | stderr_to_stdout | in | out | binary | eof</v>
<v>&nbsp;&nbsp;N = 1 | 2 | 4</v>
- <v>&nbsp;&nbsp;L = int()</v>
+ <v>&nbsp;&nbsp;L = integer()</v>
<v>&nbsp;&nbsp;Dir = string()</v>
<v>&nbsp;&nbsp;ArgString = [ FileNameChar ] | binary()</v>
<v>&nbsp;&nbsp;Env = [{Name, Val}]</v>
@@ -2876,11 +2913,11 @@ os_prompt%</pre>
<seealso marker="stdlib:unicode_usage">stdlib users guide
</seealso> for details.</p>
- <note>The characters in the name (if given as a list)
+ <note><p>The characters in the name (if given as a list)
can only be &gt; 255 if the Erlang VM is started in
Unicode file name translation mode, otherwise the name
of the executable is limited to the ISO-latin-1
- character set.</note>
+ character set.</p></note>
<p>If the <c>Command</c> cannot be run, an error
exception, with the posix error code as the reason, is
@@ -2993,11 +3030,11 @@ os_prompt%</pre>
Unicode translation of arguments, they can be supplied as
binaries in whatever encoding is deemed appropriate.</p>
- <note>The characters in the arguments (if given as a
+ <note><p>The characters in the arguments (if given as a
list of characters) can only be &gt; 255 if the Erlang
VM is started in Unicode file name mode,
otherwise the arguments are limited to the
- ISO-latin-1 character set.</note>
+ ISO-latin-1 character set.</p></note>
<p>If one, for any reason, wants to explicitly set the
program name in the argument vector, the <c>arg0</c>
@@ -3283,7 +3320,7 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>port_command(Port, Data, OptionList) -> true|false</name>
+ <name>port_command(Port, Data, OptionList) -> boolean()</name>
<fsummary>Send data to a port</fsummary>
<type>
<v>Port = port() | atom()</v>
@@ -3399,7 +3436,7 @@ os_prompt%</pre>
<fsummary>Perform a synchronous control operation on a port</fsummary>
<type>
<v>Port = port() | atom()</v>
- <v>Operation = int()</v>
+ <v>Operation = integer()</v>
<v>Data = Res = iodata()</v>
</type>
<desc>
@@ -3423,7 +3460,7 @@ os_prompt%</pre>
<fsummary>Synchronous call to a port with term data</fsummary>
<type>
<v>Port = port() | atom()</v>
- <v>Operation = int()</v>
+ <v>Operation = integer()</v>
<v>Data = term()</v>
</type>
<desc>
@@ -3682,12 +3719,6 @@ os_prompt%</pre>
<tag><c>process_flag(save_calls, N)</c></tag>
<item>
- <p>When there are runnable processes on priority <c>max</c>
- no processes on priority <c>low</c>, <c>normal</c>, or
- <c>high</c> will be selected for execution. As with the
- <c>high</c> priority, processes on lower priorities might
- execute in parallel with processes on priority <c>max</c>.
- </p>
<p><c>N</c> must be an integer in the interval 0..10000.
If <c>N</c> &gt; 0, call saving is made active for the
process, which means that information about the <c>N</c>
@@ -3858,11 +3889,26 @@ os_prompt%</pre>
catches in this process. This <c>InfoTuple</c> may be
changed or removed without prior notice.</p>
</item>
- <tag><c>{current_function, {Module, Function, Args}}</c></tag>
+ <tag><c>{current_function, {Module, Function, Arity}}</c></tag>
<item>
- <p><c>Module</c>, <c>Function</c>, <c>Args</c> is
+ <p><c>Module</c>, <c>Function</c>, <c>Arity</c> is
the current function call of the process.</p>
</item>
+ <tag><c>{current_location, {Module, Function, Arity, Location}}</c></tag>
+ <item>
+ <p><c>Module</c>, <c>Function</c>, <c>Arity</c> is
+ the current function call of the process.
+ <c>Location</c> is a list of two-tuples that describes the
+ location in the source code.
+ </p>
+ </item>
+ <tag><c>{current_stacktrace, Stack}</c></tag>
+ <item>
+ <p>Return the current call stack back-trace (<em>stacktrace</em>)
+ of the process. The stack has the same format as returned by
+ <seealso marker="#get_stacktrace/1">erlang:get_stacktrace/0</seealso>.
+ </p>
+ </item>
<tag><c>{dictionary, Dictionary}</c></tag>
<item>
<p><c>Dictionary</c> is the dictionary of the process.</p>
@@ -4109,7 +4155,7 @@ os_prompt%</pre>
<v>Reason = term()</v>
<v>Stacktrace = [{Module, Function, Arity | Args} | {Fun, Args}]</v>
<v>&nbsp;Module = Function = atom()</v>
- <v>&nbsp;Arity = int()</v>
+ <v>&nbsp;Arity = arity()</v>
<v>&nbsp;Args = [term()]</v>
<v>&nbsp;Fun = [fun()]</v>
</type>
@@ -4129,11 +4175,14 @@ os_prompt%</pre>
equivalent to <c>erlang:Class(Reason)</c>.
<c>Reason</c> is any term and <c>Stacktrace</c> is a list as
returned from <c>get_stacktrace()</c>, that is a list of
- 3-tuples <c>{Module, Function, Arity | Args}</c> where
- <c>Module</c> and <c>Function</c> are atoms and the third
- element is an integer arity or an argument list. The
- stacktrace may also contain <c>{Fun, Args}</c> tuples where
+ 4-tuples <c>{Module, Function, Arity | Args,
+ Location}</c> where <c>Module</c> and <c>Function</c>
+ are atoms and the third element is an integer arity or an
+ argument list. The stacktrace may also contain <c>{Fun,
+ Args, Location}</c> tuples where
<c>Fun</c> is a local fun and <c>Args</c> is an argument list.</p>
+ <p>The <c>Location</c> element at the end is optional.
+ Omitting it is equivalent to specifying an empty list.</p>
<p>The stacktrace is used as the exception stacktrace for the
calling process; it will be truncated to the current
maximum stacktrace depth.</p>
@@ -4146,7 +4195,7 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>erlang:read_timer(TimerRef) -> int() | false</name>
+ <name>erlang:read_timer(TimerRef) -> integer() >= 0 | false</name>
<fsummary>Number of milliseconds remaining for a timer</fsummary>
<type>
<v>TimerRef = reference()</v>
@@ -4262,7 +4311,7 @@ true</pre>
</desc>
</func>
<func>
- <name>round(Number) -> int()</name>
+ <name>round(Number) -> integer()</name>
<fsummary>Return an integer by rounding a number</fsummary>
<type>
<v>Number = number()</v>
@@ -4346,7 +4395,7 @@ true</pre>
<name>erlang:send_after(Time, Dest, Msg) -> TimerRef</name>
<fsummary>Start a timer</fsummary>
<type>
- <v>Time = int()</v>
+ <v>Time = integer() >= 0</v>
<v>&nbsp;0 &lt;= Time &lt;= 4294967295</v>
<v>Dest = pid() | RegName </v>
<v>&nbsp;LocalPid = pid() (of a process, alive or dead, on the local node)</v>
@@ -4375,17 +4424,12 @@ true</pre>
</desc>
</func>
<func>
- <name>erlang:send_nosuspend(Dest, Msg) -> bool()</name>
+ <name name="send_nosuspend" arity="2"/>
<fsummary>Try to send a message without ever blocking</fsummary>
- <type>
- <v>Dest = pid() | port() | RegName | {RegName, Node}</v>
- <v>&nbsp;RegName = atom()</v>
- <v>&nbsp;Node = node()</v>
- <v>Msg = term()</v>
- </type>
+ <type name="dst"/>
<desc>
<p>The same as
- <seealso marker="#send/3">erlang:send(Dest, Msg, [nosuspend])</seealso>, but returns <c>true</c> if
+ <seealso marker="#send/3">erlang:send(<anno>Dest</anno>, <anno>Msg</anno>, [nosuspend])</seealso>, but returns <c>true</c> if
the message was sent and <c>false</c> if the message was not
sent because the sender would have had to be suspended.</p>
<p>This function is intended for send operations towards an
@@ -4393,7 +4437,7 @@ true</pre>
(Erlang) process. If the connection to the remote node
(usually not a real Erlang node, but a node written in C or
Java) is overloaded, this function <em>will not send the message</em> but return <c>false</c> instead.</p>
- <p>The same happens, if <c>Dest</c> refers to a local port that
+ <p>The same happens, if <c><anno>Dest</anno></c> refers to a local port that
is busy. For all other destinations (allowed for the ordinary
send operator <c>'!'</c>) this function sends the message and
returns <c>true</c>.</p>
@@ -4426,18 +4470,12 @@ true</pre>
</desc>
</func>
<func>
- <name>erlang:send_nosuspend(Dest, Msg, Options) -> bool()</name>
+ <name name="send_nosuspend" arity="3"/>
<fsummary>Try to send a message without ever blocking</fsummary>
- <type>
- <v>Dest = pid() | port() | RegName | {RegName, Node}</v>
- <v>&nbsp;RegName = atom()</v>
- <v>&nbsp;Node = node()</v>
- <v>Msg = term()</v>
- <v>Option = noconnect</v>
- </type>
+ <type name="dst"/>
<desc>
<p>The same as
- <seealso marker="#send/3">erlang:send(Dest, Msg, [nosuspend | Options])</seealso>,
+ <seealso marker="#send/3">erlang:send(<anno>Dest</anno>, <anno>Msg</anno>, [nosuspend | <anno>Options</anno>])</seealso>,
but with boolean return value.</p>
<p>This function behaves like
<seealso marker="#send_nosuspend/2">erlang:send_nosuspend/2)</seealso>,
@@ -4462,17 +4500,13 @@ true</pre>
</desc>
</func>
<func>
- <name>erlang:set_cookie(Node, Cookie) -> true</name>
+ <name name="set_cookie" arity="2"/>
<fsummary>Set the magic cookie of a node</fsummary>
- <type>
- <v>Node = node()</v>
- <v>Cookie = atom()</v>
- </type>
<desc>
- <p>Sets the magic cookie of <c>Node</c> to the atom
- <c>Cookie</c>. If <c>Node</c> is the local node, the function
+ <p>Sets the magic cookie of <c><anno>Node</anno></c> to the atom
+ <c><anno>Cookie</anno></c>. If <c><anno>Node</anno></c> is the local node, the function
also sets the cookie of all other unknown nodes to
- <c>Cookie</c> (see
+ <c><anno>Cookie</anno></c> (see
<seealso marker="doc/reference_manual:distributed">Distributed Erlang</seealso> in the Erlang Reference Manual).</p>
<p>Failure: <c>function_clause</c> if the local node is not
alive.</p>
@@ -4497,7 +4531,7 @@ true</pre>
</desc>
</func>
<func>
- <name>size(Item) -> int()</name>
+ <name>size(Item) -> integer() >= 0</name>
<fsummary>Size of a tuple or binary</fsummary>
<type>
<v>Item = tuple() | binary()</v>
@@ -4512,28 +4546,21 @@ true</pre>
</desc>
</func>
<func>
- <name>spawn(Fun) -> pid()</name>
+ <name name="spawn" arity="1"/>
<fsummary>Create a new process with a fun as entry point</fsummary>
- <type>
- <v>Fun = fun()</v>
- </type>
<desc>
<p>Returns the pid of a new process started by the application
- of <c>Fun</c> to the empty list <c>[]</c>. Otherwise works
+ of <c><anno>Fun</anno></c> to the empty list <c>[]</c>. Otherwise works
like <seealso marker="#spawn/3">spawn/3</seealso>.</p>
</desc>
</func>
<func>
- <name>spawn(Node, Fun) -> pid()</name>
+ <name name="spawn" arity="2"/>
<fsummary>Create a new process with a fun as entry point on a given node</fsummary>
- <type>
- <v>Node = node()</v>
- <v>Fun = fun()</v>
- </type>
<desc>
<p>Returns the pid of a new process started by the application
- of <c>Fun</c> to the empty list <c>[]</c> on <c>Node</c>. If
- <c>Node</c> does not exist, a useless pid is returned.
+ of <c><anno>Fun</anno></c> to the empty list <c>[]</c> on <c><anno>Node</anno></c>. If
+ <c><anno>Node</anno></c> does not exist, a useless pid is returned.
Otherwise works like
<seealso marker="#spawn/3">spawn/3</seealso>.</p>
</desc>
@@ -4564,47 +4591,35 @@ true</pre>
</desc>
</func>
<func>
- <name>spawn(Node, Module, Function, Args) -> pid()</name>
+ <name name="spawn" arity="4"/>
<fsummary>Create a new process with a function as entry point on a given node</fsummary>
- <type>
- <v>Node = node()</v>
- <v>Module = Function = atom()</v>
- <v>Args = [term()]</v>
- </type>
<desc>
<p>Returns the pid of a new process started by the application
- of <c>Module:Function</c> to <c>Args</c> on <c>Node</c>. If
- <c>Node</c> does not exists, a useless pid is returned.
+ of <c><anno>Module</anno>:<anno>Function</anno></c> to <c><anno>Args</anno></c> on <c>Node</c>. If
+ <c><anno>Node</anno></c> does not exists, a useless pid is returned.
Otherwise works like
<seealso marker="#spawn/3">spawn/3</seealso>.</p>
</desc>
</func>
<func>
- <name>spawn_link(Fun) -> pid()</name>
+ <name name="spawn_link" arity="1"/>
<fsummary>Create and link to a new process with a fun as entry point</fsummary>
- <type>
- <v>Fun = fun()</v>
- </type>
<desc>
<p>Returns the pid of a new process started by the application
- of <c>Fun</c> to the empty list []. A link is created between
+ of <c><anno>Fun</anno></c> to the empty list []. A link is created between
the calling process and the new process, atomically.
Otherwise works like
<seealso marker="#spawn/3">spawn/3</seealso>.</p>
</desc>
</func>
<func>
- <name>spawn_link(Node, Fun) -> pid()</name>
+ <name name="spawn_link" arity="2"/>
<fsummary>Create and link to a new process with a fun as entry point on a specified node</fsummary>
- <type>
- <v>Node = node()</v>
- <v>Fun = fun()</v>
- </type>
<desc>
<p>Returns the pid of a new process started by the application
- of <c>Fun</c> to the empty list [] on <c>Node</c>. A link is
+ of <c><anno>Fun</anno></c> to the empty list [] on <c><anno>Node</anno></c>. A link is
created between the calling process and the new process,
- atomically. If <c>Node</c> does not exist, a useless pid is
+ atomically. If <c><anno>Node</anno></c> does not exist, a useless pid is
returned (and due to the link, an exit signal with exit
reason <c>noconnection</c> will be received). Otherwise works
like <seealso marker="#spawn/3">spawn/3</seealso>.</p>
@@ -4626,47 +4641,35 @@ true</pre>
</desc>
</func>
<func>
- <name>spawn_link(Node, Module, Function, Args) -> pid()</name>
+ <name name="spawn_link" arity="4"/>
<fsummary>Create and link to a new process with a function as entry point on a given node</fsummary>
- <type>
- <v>Node = node()</v>
- <v>Module = Function = atom()</v>
- <v>Args = [term()]</v>
- </type>
<desc>
<p>Returns the pid of a new process started by the application
- of <c>Module:Function</c> to <c>Args</c> on <c>Node</c>. A
+ of <c><anno>Module</anno>:<anno>Function</anno></c> to <c><anno>Args</anno></c> on <c>Node</c>. A
link is created between the calling process and the new
- process, atomically. If <c>Node</c> does not exist, a useless
+ process, atomically. If <c><anno>Node</anno></c> does not exist, a useless
pid is returned (and due to the link, an exit signal with exit
reason <c>noconnection</c> will be received). Otherwise works
like <seealso marker="#spawn/3">spawn/3</seealso>.</p>
</desc>
</func>
<func>
- <name>spawn_monitor(Fun) -> {pid(),reference()}</name>
+ <name name="spawn_monitor" arity="1"/>
<fsummary>Create and monitor a new process with a fun as entry point</fsummary>
- <type>
- <v>Fun = fun()</v>
- </type>
<desc>
<p>Returns the pid of a new process started by the application
- of <c>Fun</c> to the empty list [] and reference for a monitor
+ of <c><anno>Fun</anno></c> to the empty list [] and reference for a monitor
created to the new process.
Otherwise works like
<seealso marker="#spawn/3">spawn/3</seealso>.</p>
</desc>
</func>
<func>
- <name>spawn_monitor(Module, Function, Args) -> {pid(),reference()}</name>
+ <name name="spawn_monitor" arity="3"/>
<fsummary>Create and monitor a new process with a function as entry point</fsummary>
- <type>
- <v>Module = Function = atom()</v>
- <v>Args = [term()]</v>
- </type>
<desc>
<p>A new process is started by the application
- of <c>Module:Function</c> to <c>Args</c>, and the process is
+ of <c><anno>Module</anno>:<anno>Function</anno></c> to <c><anno>Args</anno></c>, and the process is
monitored at the same time. Returns the pid and a reference
for the monitor.
Otherwise works like
@@ -4674,19 +4677,11 @@ true</pre>
</desc>
</func>
<func>
- <name>spawn_opt(Fun, [Option]) -> pid() | {pid(),reference()}</name>
+ <name name="spawn_opt" arity="2"/>
<fsummary>Create a new process with a fun as entry point</fsummary>
- <type>
- <v>Fun = fun()</v>
- <v>Option = link | monitor | {priority, Level} | {fullsweep_after, Number} | {min_heap_size, Size} | {min_bin_vheap_size, VSize}</v>
- <v>&nbsp;Level = low | normal | high</v>
- <v>&nbsp;Number = int()</v>
- <v>&nbsp;Size = int()</v>
- <v>&nbsp;VSize = int()</v>
- </type>
<desc>
<p>Returns the pid of a new process started by the application
- of <c>Fun</c> to the empty list <c>[]</c>. Otherwise
+ of <c><anno>Fun</anno></c> to the empty list <c>[]</c>. Otherwise
works like
<seealso marker="#spawn_opt/4">spawn_opt/4</seealso>.</p>
<p>If the option <c>monitor</c> is given, the newly created
@@ -4695,37 +4690,19 @@ true</pre>
</desc>
</func>
<func>
- <name>spawn_opt(Node, Fun, [Option]) -> pid()</name>
+ <name name="spawn_opt" arity="3"/>
<fsummary>Create a new process with a fun as entry point on a given node</fsummary>
- <type>
- <v>Node = node()</v>
- <v>Fun = fun()</v>
- <v>Option = link | {priority, Level} | {fullsweep_after, Number} | {min_heap_size, Size} | {min_bin_vheap_size, VSize}</v>
- <v>&nbsp;Level = low | normal | high</v>
- <v>&nbsp;Number = int()</v>
- <v>&nbsp;Size = int()</v>
- <v>&nbsp;VSize = int()</v>
- </type>
<desc>
<p>Returns the pid of a new process started by the application
- of <c>Fun</c> to the empty list <c>[]</c> on <c>Node</c>. If
- <c>Node</c> does not exist, a useless pid is returned.
+ of <c><anno>Fun</anno></c> to the empty list <c>[]</c> on <c><anno>Node</anno></c>. If
+ <c><anno>Node</anno></c> does not exist, a useless pid is returned.
Otherwise works like
<seealso marker="#spawn_opt/4">spawn_opt/4</seealso>.</p>
</desc>
</func>
<func>
- <name>spawn_opt(Module, Function, Args, [Option]) -> pid() | {pid(),reference()}</name>
+ <name name="spawn_opt" arity="4"/>
<fsummary>Create a new process with a function as entry point</fsummary>
- <type>
- <v>Module = Function = atom()</v>
- <v>Args = [term()]</v>
- <v>Option = link | monitor | {priority, Level} | {fullsweep_after, Number} | {min_heap_size, Size} | {min_bin_vheap_size, VSize}</v>
- <v>&nbsp;Level = low | normal | high</v>
- <v>&nbsp;Number = int()</v>
- <v>&nbsp;Size = int()</v>
- <v>&nbsp;VSize = int()</v>
- </type>
<desc>
<p>Works exactly like
<seealso marker="#spawn/3">spawn/3</seealso>, except that an
@@ -4744,17 +4721,17 @@ true</pre>
<p>Monitor the new process (just like
<seealso marker="#monitor/2">monitor/2</seealso> does).</p>
</item>
- <tag><c>{priority, Level}</c></tag>
+ <tag><c>{priority, <anno>Level</anno>}</c></tag>
<item>
<p>Sets the priority of the new process. Equivalent to
executing
- <seealso marker="#process_flag_priority">process_flag(priority, Level)</seealso> in the start function of the new process,
+ <seealso marker="#process_flag_priority">process_flag(priority, <anno>Level</anno>)</seealso> in the start function of the new process,
except that the priority will be set before the process is
selected for execution for the first time. For more information
on priorities see
<seealso marker="#process_flag_priority">process_flag(priority, Level)</seealso>.</p>
</item>
- <tag><c>{fullsweep_after, Number}</c></tag>
+ <tag><c>{fullsweep_after, <anno>Number</anno>}</c></tag>
<item>
<p>This option is only useful for performance tuning.
In general, you should not use this option unless you
@@ -4776,18 +4753,18 @@ true</pre>
<p>Here are a few cases when it could be useful to change
<c>fullsweep_after</c>. Firstly, if binaries that are no
longer used should be thrown away as soon as possible.
- (Set <c>Number</c> to zero.) Secondly, a process that
+ (Set <c><anno>Number</anno></c> to zero.) Secondly, a process that
mostly have short-lived data will be fullsweeped seldom
or never, meaning that the old heap will contain mostly
garbage. To ensure a fullsweep once in a while, set
- <c>Number</c> to a suitable value such as 10 or 20.
+ <c><anno>Number</anno></c> to a suitable value such as 10 or 20.
Thirdly, in embedded systems with limited amount of RAM
and no virtual memory, one might want to preserve memory
- by setting <c>Number</c> to zero. (The value may be set
+ by setting <c><anno>Number</anno></c> to zero. (The value may be set
globally, see
<seealso marker="#system_flag/2">erlang:system_flag/2</seealso>.)</p>
</item>
- <tag><c>{min_heap_size, Size}</c></tag>
+ <tag><c>{min_heap_size, <anno>Size</anno>}</c></tag>
<item>
<p>This option is only useful for performance tuning.
In general, you should not use this option unless you
@@ -4802,9 +4779,9 @@ true</pre>
slow down the system due to worse data locality.
Therefore, it is recommended to use this option only for
fine-tuning an application and to measure the execution
- time with various <c>Size</c> values.</p>
+ time with various <c><anno>Size</anno></c> values.</p>
</item>
- <tag><c>{min_bin_vheap_size, VSize}</c></tag>
+ <tag><c>{min_bin_vheap_size, <anno>VSize</anno>}</c></tag>
<item>
<p>This option is only useful for performance tuning.
In general, you should not use this option unless you
@@ -4818,29 +4795,19 @@ true</pre>
Setting too high value, however, might waste memory.
Therefore, it is recommended to use this option only for
fine-tuning an application and to measure the execution
- time with various <c>VSize</c> values.</p>
+ time with various <c><anno>VSize</anno></c> values.</p>
</item>
</taglist>
</desc>
</func>
<func>
- <name>spawn_opt(Node, Module, Function, Args, [Option]) -> pid()</name>
+ <name name="spawn_opt" arity="5"/>
<fsummary>Create a new process with a function as entry point on a given node</fsummary>
- <type>
- <v>Node = node()</v>
- <v>Module = Function = atom()</v>
- <v>Args = [term()]</v>
- <v>Option = link | {priority, Level} | {fullsweep_after, Number} | {min_heap_size, Size} | {min_bin_vheap_size, VSize}</v>
- <v>&nbsp;Level = low | normal | high</v>
- <v>&nbsp;Number = int()</v>
- <v>&nbsp;Size = int()</v>
- <v>&nbsp;VSize = int()</v>
- </type>
<desc>
<p>Returns the pid of a new process started by the application
- of <c>Module:Function</c> to <c>Args</c> on <c>Node</c>. If
- <c>Node</c> does not exist, a useless pid is returned.
+ of <c><anno>Module</anno>:<anno>Function</anno></c> to <c><anno>Args</anno></c> on <c>Node</c>. If
+ <c><anno>Node</anno></c> does not exist, a useless pid is returned.
Otherwise works like
<seealso marker="#spawn_opt/4">spawn_opt/4</seealso>.</p>
</desc>
@@ -4874,7 +4841,7 @@ true</pre>
<name>erlang:start_timer(Time, Dest, Msg) -> TimerRef</name>
<fsummary>Start a timer</fsummary>
<type>
- <v>Time = int()</v>
+ <v>Time = integer() >= 0</v>
<v>&nbsp;0 &lt;= Time &lt;= 4294967295</v>
<v>Dest = LocalPid | RegName </v>
<v>&nbsp;LocalPid = pid() (of a process, alive or dead, on the local node)</v>
@@ -4983,7 +4950,7 @@ true</pre>
</desc>
</func>
<func>
- <name>erlang:suspend_process(Suspendee, OptList) -> true | false</name>
+ <name>erlang:suspend_process(Suspendee, OptList) -> boolean()</name>
<fsummary>Suspend a process</fsummary>
<type>
<v>Suspendee = pid()</v>
@@ -5083,15 +5050,12 @@ true</pre>
</desc>
</func>
<func>
- <name>erlang:suspend_process(Suspendee) -> true</name>
+ <name name="suspend_process" arity="1"/>
<fsummary>Suspend a process</fsummary>
- <type>
- <v>Suspendee = pid()</v>
- </type>
<desc>
- <p>Suspends the process identified by <c>Suspendee</c>. The
+ <p>Suspends the process identified by <c><anno>Suspendee</anno></c>. The
same as calling
- <seealso marker="#suspend_process/2">erlang:suspend_process(Suspendee, [])</seealso>. For more information see the documentation of <seealso marker="#suspend_process/2">erlang:suspend_process/2</seealso>.
+ <seealso marker="#suspend_process/2">erlang:suspend_process(<anno>Suspendee</anno>, [])</seealso>. For more information see the documentation of <seealso marker="#suspend_process/2">erlang:suspend_process/2</seealso>.
</p>
<warning>
<p>This BIF is intended for debugging only.</p>
@@ -5416,7 +5380,7 @@ true</pre>
<p>Types:</p>
<list type="bulleted">
<item><c>Allocator = undefined | glibc</c></item>
- <item><c>Version = [int()]</c></item>
+ <item><c>Version = [integer()]</c></item>
<item><c>Features = [atom()]</c></item>
<item><c>Settings = [{Subsystem, [{Parameter, Value}]}]</c></item>
<item><c>Subsystem = atom()</c></item>
@@ -5682,7 +5646,7 @@ true</pre>
</item>
<tag><c>fullsweep_after</c></tag>
<item>
- <p>Returns <c>{fullsweep_after, int()}</c> which is the
+ <p>Returns <c>{fullsweep_after, integer()}</c> which is the
<c>fullsweep_after</c> garbage collection setting used
by default. For more information see
<c>garbage_collection</c> described below.</p>
@@ -6013,7 +5977,7 @@ true</pre>
</item>
<tag><c>wordsize</c></tag>
<item>
- <p>Same as <c>{wordsize, internal}</c></p>
+ <p>Same as <c>{wordsize, internal}.</c></p>
</item>
<tag><c>{wordsize, internal}</c></tag>
<item>
@@ -6022,7 +5986,7 @@ true</pre>
and on a pure 64-bit architecture 8 is returned. On a
halfword 64-bit emulator, 4 is returned, as the Erlang
terms are stored using a virtual wordsize of half the
- systems wordsize.</p>
+ system's wordsize.</p>
</item>
<tag><c>{wordsize, external}</c></tag>
<item>
@@ -6050,7 +6014,7 @@ true</pre>
<v>&nbsp;MonitorPid = pid()</v>
<v>&nbsp;Options = [Option]</v>
<v>&nbsp;&nbsp;Option = {long_gc, Time} | {large_heap, Size} | busy_port | busy_dist_port</v>
- <v>&nbsp;&nbsp;&nbsp;Time = Size = int()</v>
+ <v>&nbsp;&nbsp;&nbsp;Time = Size = integer()</v>
</type>
<desc>
<p>Returns the current system monitoring settings set by
@@ -6084,7 +6048,7 @@ true</pre>
<type>
<v>MonitorPid = pid()</v>
<v>Option = {long_gc, Time} | {large_heap, Size} | busy_port | busy_dist_port</v>
- <v>&nbsp;Time = Size = int()</v>
+ <v>&nbsp;Time = Size = integer()</v>
<v>MonSettings = {OldMonitorPid, [Option]}</v>
<v>&nbsp;OldMonitorPid = pid()</v>
</type>
@@ -6314,7 +6278,7 @@ true</pre>
<name>time() -> {Hour, Minute, Second}</name>
<fsummary>Current time</fsummary>
<type>
- <v>Hour = Minute = Second = int()</v>
+ <v>Hour = Minute = Second = integer() >= 0</v>
</type>
<desc>
<p>Returns the current time as <c>{Hour, Minute, Second}</c>.</p>
@@ -6342,11 +6306,11 @@ true</pre>
</desc>
</func>
<func>
- <name>erlang:trace(PidSpec, How, FlagList) -> int()</name>
+ <name>erlang:trace(PidSpec, How, FlagList) -> integer() >= 0</name>
<fsummary>Set trace flags for a process or processes</fsummary>
<type>
<v>PidSpec = pid() | existing | new | all</v>
- <v>How = bool()</v>
+ <v>How = boolean()</v>
<v>FlagList = [Flag]</v>
<v>&nbsp;Flag -- see below</v>
</type>
@@ -6747,7 +6711,7 @@ true</pre>
<type>
<v>PidOrFunc = pid() | new | {Module, Function, Arity} | on_load</v>
<v>&nbsp;Module = Function = atom()</v>
- <v>&nbsp;Arity = int()</v>
+ <v>&nbsp;Arity = arity()</v>
<v>Item, Res -- see below</v>
</type>
<desc>
@@ -6850,7 +6814,7 @@ true</pre>
</desc>
</func>
<func>
- <name>erlang:trace_pattern(MFA, MatchSpec) -> int()</name>
+ <name>erlang:trace_pattern(MFA, MatchSpec) -> integer() >= 0</name>
<fsummary>Set trace patterns for global call tracing</fsummary>
<desc>
<p>The same as
@@ -6859,7 +6823,7 @@ true</pre>
</desc>
</func>
<func>
- <name>erlang:trace_pattern(MFA, MatchSpec, FlagList) -> int()</name>
+ <name>erlang:trace_pattern(MFA, MatchSpec, FlagList) -> integer() >= 0</name>
<fsummary>Set trace patterns for tracing of function calls</fsummary>
<type>
<v>MFA, MatchSpec, FlagList -- see below</v>
@@ -7039,7 +7003,7 @@ true</pre>
</desc>
</func>
<func>
- <name>trunc(Number) -> int()</name>
+ <name>trunc(Number) -> integer()</name>
<fsummary>Return an integer by the truncating a number</fsummary>
<type>
<v>Number = number()</v>
@@ -7053,7 +7017,7 @@ true</pre>
</desc>
</func>
<func>
- <name>tuple_size(Tuple) -> int()</name>
+ <name>tuple_size(Tuple) -> integer() >= 0</name>
<fsummary>Return the size of a tuple</fsummary>
<type>
<v>Tuple = tuple()</v>
@@ -7081,12 +7045,10 @@ true</pre>
</desc>
</func>
<func>
- <name>erlang:universaltime() -> {Date, Time}</name>
+ <name>erlang:universaltime() -> DateTime</name>
<fsummary>Current date and time according to Universal Time Coordinated (UTC)</fsummary>
<type>
- <v>Date = {Year, Month, Day}</v>
- <v>Time = {Hour, Minute, Second}</v>
- <v>&nbsp;Year = Month = Day = Hour = Minute = Second = int()</v>
+ <v>DateTime = <seealso marker="calendar#type-datetime">calendar:datetime()</seealso></v>
</type>
<desc>
<p>Returns the current date and time according to Universal
@@ -7104,9 +7066,8 @@ true</pre>
<name>erlang:universaltime_to_localtime({Date1, Time1}) -> {Date2, Time2}</name>
<fsummary>Convert from Universal Time Coordinated (UTC) to local date and time</fsummary>
<type>
- <v>Date1 = Date2 = {Year, Month, Day}</v>
- <v>Time1 = Time2 = {Hour, Minute, Second}</v>
- <v>&nbsp;Year = Month = Day = Hour = Minute = Second = int()</v>
+ <v>Date1 = Date2 = <seealso marker="calendar#type-date">calendar:date()</seealso></v>
+ <v>Time1 = Time2 = <seealso marker="calendar#type-time">calendar:time()</seealso></v>
</type>
<desc>
<p>Converts Universal Time Coordinated (UTC) date and time to
@@ -7193,7 +7154,7 @@ true</pre>
</desc>
</func>
<func>
- <name>erlang:yield() -> true</name>
+ <name name="yield" arity="0"/>
<fsummary>Let other processes get a chance to execute</fsummary>
<desc>
<p>Voluntarily let other processes (if any) get a chance to
diff --git a/erts/doc/src/erlsrv.xml b/erts/doc/src/erlsrv.xml
index 0dfad2a112..c1ecbc7b77 100644
--- a/erts/doc/src/erlsrv.xml
+++ b/erts/doc/src/erlsrv.xml
@@ -4,7 +4,7 @@
<comref>
<header>
<copyright>
- <year>1998</year><year>2010</year>
+ <year>1998</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -273,7 +273,7 @@
</desc>
</func>
<func>
- <name>erlsrv {start | stop | disable | enable} &lt;service-name></name>
+ <name>erlsrv {start | start_disabled | stop | disable | enable} &lt;service-name></name>
<fsummary>Manipulate the current service status.</fsummary>
<desc>
<p>These commands are only added for convenience, the normal
@@ -287,6 +287,21 @@
service actually is stopped. Enabling a service sets it in
automatic mode, that is started at boot. This command cannot
set the service to manual. </p>
+
+ <p>The <c>start_disabled</c> command operates on a service
+ regardless of if it's enabled/disabled or started/stopped. It
+ does this by first enabling it (regardless of if it's enabled
+ or not), then starting it (if it's not already started) and
+ then disabling it. The result will be a disabled but started
+ service, regardless of its earlier state. This is useful for
+ starting services temporarily during a release upgrade. The
+ difference between using <c>start_disabled</c> and the
+ sequence <c>enable</c>, <c>start</c> and <c>disable</c> is
+ that all other <c>erlsrv</c> commands are locked out during
+ the sequence of operations in <c>start_disable</c>, making the
+ operation atomic from an <c>erlsrv</c> user's point of
+ view.</p>
+
</desc>
</func>
<func>
diff --git a/erts/doc/src/erts_alloc.xml b/erts/doc/src/erts_alloc.xml
index 452e5d990e..3b5ee5391c 100644
--- a/erts/doc/src/erts_alloc.xml
+++ b/erts/doc/src/erts_alloc.xml
@@ -4,7 +4,7 @@
<cref>
<header>
<copyright>
- <year>2002</year><year>2010</year>
+ <year>2002</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -58,11 +58,8 @@
<item>Allocator used for memory blocks that are expected to be
long-lived, for example Erlang code.</item>
<tag><c>fix_alloc</c></tag>
- <item>A very fast allocator used for some fix-sized
- data. <c>fix_alloc</c> manages a set of memory pools from
- which memory blocks are handed out. <c>fix_alloc</c>
- allocates memory pools from <c>ll_alloc</c>. Memory pools
- that have been allocated are never deallocated.</item>
+ <item>A fast allocator used for some frequently used
+ fixed size data types.</item>
<tag><c>std_alloc</c></tag>
<item>Allocator used for most memory blocks not allocated via any of
the other allocators described above.</item>
@@ -83,7 +80,7 @@
where only small blocks are placed. Currently this allocator is
disabled by default.</item>
</taglist>
- <p><c>sys_alloc</c> and <c>fix_alloc</c> are always enabled and
+ <p><c>sys_alloc</c> is always enabled and
cannot be disabled. <c>mseg_alloc</c> is always enabled if it is
available and an allocator that uses it is enabled. All other
allocators can be <seealso marker="#M_e">enabled or disabled</seealso>.
@@ -104,7 +101,7 @@
<marker id="alloc_util"></marker>
<title>The alloc_util framework</title>
<p>Internally a framework called <c>alloc_util</c> is used for
- implementing allocators. <c>sys_alloc</c>, <c>fix_alloc</c>, and
+ implementing allocators. <c>sys_alloc</c>, and
<c>mseg_alloc</c> do not use this framework; hence, the
following does <em>not</em> apply to them.</p>
<p>An allocator manages multiple areas, called carriers, in which
@@ -126,9 +123,8 @@
carrier". Main multiblock carriers are never deallocated. The
size of the main multiblock carrier is determined by the value
of the <seealso marker="#M_mmbcs">mmbcs</seealso> parameter.</p>
- <p> <marker id="mseg_mbc_sizes"></marker>
-
- Sizes of multiblock carriers allocated via <c>mseg_alloc</c> are
+ <p><marker id="mseg_mbc_sizes"></marker>Sizes of multiblock carriers
+ allocated via <c>mseg_alloc</c> are
decided based on the values of the largest multiblock carrier
size (<seealso marker="#M_lmbcs">lmbcs</seealso>), the smallest
multiblock carrier size (<seealso marker="#M_smbcs">smbcs</seealso>),
@@ -157,9 +153,8 @@
<p>Coalescing of free blocks are always performed immediately.
Boundary tags (headers and footers) in free blocks are used
which makes the time complexity for coalescing constant.</p>
- <p> <marker id="strategy"></marker>
-
- The memory allocation strategy used for multiblock carriers by an
+ <p><marker id="strategy"></marker>The memory allocation strategy
+ used for multiblock carriers by an
allocator is configurable via the <seealso marker="#M_as">as</seealso>
parameter. Currently the following strategies are available:</p>
<taglist>
@@ -180,6 +175,14 @@
used. The time complexity is proportional to log N, where
N is the number of free blocks.</p>
</item>
+ <tag>Address order first fit</tag>
+ <item>
+ <p>Strategy: Find the block with the lowest address that satisfies the
+ requested block size.</p>
+ <p>Implementation: A balanced binary search tree is
+ used. The time complexity is proportional to log N, where
+ N is the number of free blocks.</p>
+ </item>
<tag>Good fit</tag>
<item>
<p>Strategy: Try to find the best fit, but settle for the best fit
@@ -206,6 +209,14 @@
This since it will only cause problems for other allocators.</p>
</item>
</taglist>
+ <p>Apart from the ordinary allocators described above a number of
+ pre-allocators are used for some specific data types. These
+ pre-allocators pre-allocate a fixed amount of memory for certain data
+ types when the run-time system starts. As long as there are available
+ pre-allocated memory, it will be used. When no pre-allocated memory is
+ available, memory will be allocated in ordinary allocators. These
+ pre-allocators are typically much faster than the ordinary allocators,
+ but can only satisfy a limited amount of requests.</p>
</section>
<note><p>
@@ -266,18 +277,6 @@
Max cached segments. The maximum number of memory segments
stored in the memory segment cache. Valid range is
0-30. Default value is 5.</item>
- <tag><marker id="MMcci"><c><![CDATA[+MMcci <time>]]></c></marker></tag>
- <item>
- Cache check interval (in milliseconds). The memory segment
- cache is checked for segments to destroy at an interval
- determined by this parameter. Default value is 1000.</item>
- </taglist>
- <p>The following flags are available for configuration of
- <c>fix_alloc</c>:</p>
- <taglist>
- <tag><marker id="MFe"><c>+MFe true</c></marker></tag>
- <item>
- Enable <c>fix_alloc</c>. Note: <c>fix_alloc</c> cannot be disabled.</item>
</taglist>
<p>The following flags are available for configuration of
<c>sys_alloc</c>:</p>
@@ -316,15 +315,15 @@
based on <c>alloc_util</c>. If <c>u</c> is used as subsystem
identifier (i.e., <c><![CDATA[<S> = u]]></c>) all allocators based on
<c>alloc_util</c> will be effected. If <c>B</c>, <c>D</c>, <c>E</c>,
- <c>H</c>, <c>L</c>, <c>R</c>, <c>S</c>, or <c>T</c> is used as
+ <c>F</c>, <c>H</c>, <c>L</c>, <c>R</c>, <c>S</c>, or <c>T</c> is used as
subsystem identifier, only the specific allocator identified will be
effected:</p>
<taglist>
- <tag><marker id="M_as"><c><![CDATA[+M<S>as bf|aobf|gf|af]]></c></marker></tag>
+ <tag><marker id="M_as"><c><![CDATA[+M<S>as bf|aobf|aoff|gf|af]]></c></marker></tag>
<item>
Allocation strategy. Valid strategies are <c>bf</c> (best fit),
- <c>aobf</c> (address order best fit), <c>gf</c> (good fit),
- and <c>af</c> (a fit). See
+ <c>aobf</c> (address order best fit), <c>aoff</c> (address order first fit),
+ <c>gf</c> (good fit), and <c>af</c> (a fit). See
<seealso marker="#strategy">the description of allocation strategies</seealso> in "the <c>alloc_util</c> framework" section.</item>
<tag><marker id="M_asbcst"><c><![CDATA[+M<S>asbcst <size>]]></c></marker></tag>
<item>
@@ -435,26 +434,23 @@
kilobytes). See <seealso marker="#mseg_mbc_sizes">the description
on how sizes for mseg_alloc multiblock carriers are decided</seealso>
in "the <c>alloc_util</c> framework" section.</item>
- <tag><marker id="M_t"><c><![CDATA[+M<S>t true|false|<amount>]]></c></marker></tag>
+ <tag><marker id="M_t"><c><![CDATA[+M<S>t true|false]]></c></marker></tag>
<item>
Multiple, thread specific instances of the allocator.
This option will only have any effect on the runtime system
with SMP support. Default behaviour on the runtime system with
- SMP support (<c>N</c> equals the number of scheduler threads):
+ SMP support:
<taglist>
- <tag><c>temp_alloc</c></tag>
- <item><c>N + 1</c> instances.</item>
<tag><c>ll_alloc</c></tag>
<item><c>1</c> instance.</item>
<tag>Other allocators</tag>
- <item><c>N</c> instances when <c>N</c> is less than or equal to
- <c>16</c>. <c>16</c> instances when <c>N</c> is greater than
- <c>16</c>.</item>
+ <item><c>NoSchedulers+1</c> instances. Each scheduler will use
+ a lock-free instance of its own and other threads will use
+ a common instance.</item>
</taglist>
- <c>temp_alloc</c> will always use <c>N + 1</c> instances when
- this option has been enabled regardless of the amount passed.
- Other allocators will use the same amount of instances as the
- amount passed as long as it isn't greater than <c>N</c>.
+ It was previously (before ERTS version 5.9) possible to configure
+ a smaller amount of thread specific instances than schedulers.
+ This is, however, not possible any more.
</item>
</taglist>
<p>Currently the following flags are available for configuration of
diff --git a/erts/doc/src/init.xml b/erts/doc/src/init.xml
index b0d0cda4fa..d5c43f6e57 100644
--- a/erts/doc/src/init.xml
+++ b/erts/doc/src/init.xml
@@ -47,15 +47,12 @@
</description>
<funcs>
<func>
- <name>boot(BootArgs) -> void()</name>
+ <name name="boot" arity="1"/>
<fsummary>Start the Erlang runtime system</fsummary>
- <type>
- <v>BootArgs = [binary()]</v>
- </type>
<desc>
<p>Starts the Erlang runtime system. This function is called
when the emulator is started and coordinates system start-up.</p>
- <p><c>BootArgs</c> are all command line arguments except
+ <p><c><anno>BootArgs</anno></c> are all command line arguments except
the emulator flags, that is, flags and plain arguments. See
<seealso marker="erts:erl">erl(1)</seealso>.</p>
<p><c>init</c> itself interprets some of the flags, see
@@ -67,17 +64,12 @@
</desc>
</func>
<func>
- <name>get_argument(Flag) -> {ok, Arg} | error</name>
+ <name name="get_argument" arity="1"/>
<fsummary>Get the values associated with a command line user flag</fsummary>
- <type>
- <v>Flag = atom()</v>
- <v>Arg = [Values]</v>
- <v>&nbsp;Values = [string()]</v>
- </type>
<desc>
<p>Returns all values associated with the command line user flag
- <c>Flag</c>. If <c>Flag</c> is provided several times, each
- <c>Values</c> is returned in preserved order.</p>
+ <c><anno>Flag</anno></c>. If <c><anno>Flag</anno></c> is provided several times, each
+ <c><anno>Values</anno></c> is returned in preserved order.</p>
<pre>
% <input>erl -a b c -a d</input>
...
@@ -113,48 +105,37 @@
</desc>
</func>
<func>
- <name>get_arguments() -> Flags</name>
+ <name name="get_arguments" arity="0"/>
<fsummary>Get all command line user flags</fsummary>
- <type>
- <v>Flags = [{Flag, Values}]</v>
- <v>&nbsp;Flag = atom()</v>
- <v>&nbsp;Values = [string()]</v>
- </type>
<desc>
<p>Returns all command line flags, as well as the system
defined flags, see <c>get_argument/1</c>.</p>
</desc>
</func>
<func>
- <name>get_plain_arguments() -> [Arg]</name>
+ <name name="get_plain_arguments" arity="0"/>
<fsummary>Get all non-flag command line arguments</fsummary>
- <type>
- <v>Arg = string()</v>
- </type>
<desc>
<p>Returns any plain command line arguments as a list of strings
(possibly empty).</p>
</desc>
</func>
<func>
- <name>get_status() -> {InternalStatus, ProvidedStatus}</name>
+ <name name="get_status" arity="0"/>
<fsummary>Get system status information</fsummary>
- <type>
- <v>InternalStatus = starting | started | stopping</v>
- <v>ProvidedStatus = term()</v>
- </type>
+ <type name="internal_status"/>
<desc>
<p>The current status of the <c>init</c> process can be
inspected. During system startup (initialization),
- <c>InternalStatus</c> is <c>starting</c>, and
- <c>ProvidedStatus</c> indicates how far the boot script has
+ <c><anno>InternalStatus</anno></c> is <c>starting</c>, and
+ <c><anno>ProvidedStatus</anno></c> indicates how far the boot script has
been interpreted. Each <c>{progress, Info}</c> term
- interpreted in the boot script affects <c>ProvidedStatus</c>,
- that is, <c>ProvidedStatus</c> gets the value of <c>Info</c>.</p>
+ interpreted in the boot script affects <c><anno>ProvidedStatus</anno></c>,
+ that is, <c><anno>ProvidedStatus</anno></c> gets the value of <c>Info</c>.</p>
</desc>
</func>
<func>
- <name>reboot() -> void()</name>
+ <name name="reboot" arity="0"/>
<fsummary>Take down and restart an Erlang node smoothly</fsummary>
<desc>
<p>All applications are taken down smoothly, all code is
@@ -168,7 +149,7 @@
</desc>
</func>
<func>
- <name>restart() -> void()</name>
+ <name name="restart" arity="0"/>
<fsummary>Restart the running Erlang node</fsummary>
<desc>
<p>The system is restarted <em>inside</em> the running Erlang
@@ -183,20 +164,17 @@
</desc>
</func>
<func>
- <name>script_id() -> Id</name>
+ <name name="script_id" arity="0"/>
<fsummary>Get the identity of the used boot script</fsummary>
- <type>
- <v>Id = term()</v>
- </type>
<desc>
<p>Get the identity of the boot script used to boot the system.
- <c>Id</c> can be any Erlang term. In the delivered boot
- scripts, <c>Id</c> is <c>{Name, Vsn}</c>. <c>Name</c> and
+ <c><anno>Id</anno></c> can be any Erlang term. In the delivered boot
+ scripts, <c><anno>Id</anno></c> is <c>{Name, Vsn}</c>. <c>Name</c> and
<c>Vsn</c> are strings.</p>
</desc>
</func>
<func>
- <name>stop() -> void()</name>
+ <name name="stop" arity="0"/>
<fsummary>Take down an Erlang node smoothly</fsummary>
<desc>
<p>All applications are taken down smoothly, all code is
@@ -210,15 +188,12 @@
</desc>
</func>
<func>
- <name>stop(Status) -> void()</name>
+ <name name="stop" arity="1"/>
<fsummary>Take down an Erlang node smoothly</fsummary>
- <type>
- <v>Status = int()>=0 | string()</v>
- </type>
<desc>
<p>All applications are taken down smoothly, all code is
unloaded, and all ports are closed before the system
- terminates by calling <c>halt(Status)</c>. If the
+ terminates by calling <c>halt(<anno>Status</anno>)</c>. If the
<c>-heart</c> command line flag was given, the <c>heart</c>
program is terminated before the Erlang node
terminates. Refer to <c>heart(3)</c> for more
diff --git a/erts/doc/src/make.dep b/erts/doc/src/make.dep
deleted file mode 100644
index 98bac78235..0000000000
--- a/erts/doc/src/make.dep
+++ /dev/null
@@ -1,32 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/gandalf/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: absform.tex alt_dist.tex book.tex crash_dump.tex \
- driver.tex driver_entry.tex epmd.tex erl.tex \
- erl_dist_protocol.tex erl_driver.tex erl_ext_dist.tex \
- erl_prim_loader.tex erl_set_memory_block.tex \
- erlang.tex erlc.tex erlsrv.tex erts_alloc.tex \
- escript.tex inet_cfg.tex init.tex match_spec.tex \
- part.tex ref_man.tex run_erl.tex start.tex \
- start_erl.tex tty.tex werl.tex zlib.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: erl_ext_fig.ps
-
diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml
index 2e6aca2951..4cef9669dd 100644
--- a/erts/doc/src/notes.xml
+++ b/erts/doc/src/notes.xml
@@ -30,29 +30,296 @@
</header>
<p>This document describes the changes made to the ERTS application.</p>
-<section><title>Erts 5.8.4.1</title>
+<section><title>Erts 5.8.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
<item>
<p>
- Fix bug in tracing with matchspec body containing
- <c>enable_trace</c> or <c>disable_trace</c>. Could cause
- emulator crash if trace was altered with
- erlang:trace_pattern by racing process during ongoing
- tracing.</p>
+ Several bugs concerning constant binary constructions
+ such as &lt;&lt;0:4294967295&gt;&gt; have been corrected.
+ Depending on the actual size of the binary and the type
+ of run-time system (32-bit, halfword, 64-bit), such
+ expression could either crash the run-time system or make
+ the loader refuse loading of the module.</p>
<p>
- Own Id: OTP-9422 Aux Id: seq11868 </p>
+ Own Id: OTP-9284</p>
</item>
<item>
<p>
- Fix emulator deadlock in <c>ets:delete</c> on tables with
- <c>write_concurrency</c> caused by race with concurrent
- process that tries to do other operation on the same
- table. Does not apply to <c>ordered_set</c>. Bug exist
- since R14B.</p>
+ The Erlsrv utility failed to stop the erlang machine if
+ no StopAction was defined when the service was stopped.
+ This is now corrected.</p>
+ <p>
+ Own Id: OTP-9344</p>
+ </item>
+ <item>
+ <p>
+ Due to a bug in glibc the runtime system could abort
+ while trying to destroy a mutex. A fix for this was
+ introduced in R14B02. This fix did, however, not solve
+ the problem. The runtime system will now issue a warning
+ instead of aborting.</p>
+ <p>
+ Own Id: OTP-9373 Aux Id: OTP-9009 </p>
+ </item>
+ <item>
+ <p>
+ Replace atom in DRV macro in prim_file with string</p>
+ <p>
+ An experimental version of Dialyzer discovered that the
+ atom that replaced the DRV macro in prim_file ends up in
+ calls to erlang:open_port({spawn, Driver}, Portopts) as
+ the Driver argument. The documentation states that this
+ call requires a string there.</p>
+ <p>
+ This change is also consistent with the one introduced in
+ commit 0f03b1e9d2bef3bc830c31a369261af4c5234727 by Kostis
+ Sagonas.</p>
+ <p>
+ Own Id: OTP-9377</p>
+ </item>
+ <item>
+ <p>
+ Fix typos in the epmd documentation (Thanks to Holger
+ Wei� )</p>
+ <p>
+ Own Id: OTP-9387</p>
+ </item>
+ <item>
+ <p>
+ Fix faulty integer terms created by NIF API from 64-bit
+ integers on halfword emulator. (Thanks to Paolo Negri and
+ Paul Davis)</p>
<p>
- Own Id: OTP-9423 Aux Id: seq11872 </p>
+ Own Id: OTP-9394</p>
+ </item>
+ <item>
+ <p>
+ Fix <c>epmd</c> crash on vxworks caused by faulty
+ argument to select() system call.</p>
+ <p>
+ Own Id: OTP-9427 Aux Id: seq11855 </p>
+ </item>
+ <item>
+ <p>
+ The ets:test_ms function could in rare cases truncate the
+ error messages. This is now corrected.</p>
+ <p>
+ Own Id: OTP-9435</p>
+ </item>
+ <item>
+ <p>
+ Fix bug related to hibernate and HiPE (clear
+ F_HIBERNATE_SCHED flag)</p>
+ <p>
+ F_HIBERNATE_SCHED flag that was introduced in
+ b7ecdcd1ae9e11b8f75e must be cleared in hipe_mode_switch
+ as well. Otherwise, processes running HiPE code that
+ hibernate, wake up and then trap into a BIF will not be
+ rescheduled.(Thanks to Paul Guyot)</p>
+ <p>
+ Own Id: OTP-9452</p>
+ </item>
+ <item>
+ <p>
+ Fix bug in FreeBSD topology detection code (Thanks to
+ Paul Guyot)</p>
+ <p>
+ Own Id: OTP-9453</p>
+ </item>
+ <item>
+ <p>
+ Fix use of logical operator &amp;&amp; with constant
+ operand instead of bitwise &amp; (Thanks to Cristian
+ Greco)</p>
+ <p>
+ Own Id: OTP-9454</p>
+ </item>
+ <item>
+ <p>
+ inet: error if fd does not match socket domain</p>
+ <p>
+ If an IPv4 fd is opened as an IPv6 socket, unexpected
+ behaviour can occur. For example, if an IPv4 UDP socket
+ is opened and passed into Erlang as an IPv6 socket, the
+ first 3 bytes (corresponding to 1 byte representing the
+ protocol family, 2 bytes set to the port) are stripped
+ from the payload. The cause of the UDP payload truncation
+ happens in inet_drv.c:packet_inet_input when a call to
+ inet_get_address fails silently because the family is set
+ to PF_INET6 but the buffer len is the size of an IPv4
+ struct sockaddr_in.</p>
+ <p>
+ (Thanks to Andrew Tunnell-Jones for finding the bug and
+ the test case!)</p>
+ <p>
+ Own Id: OTP-9455</p>
+ </item>
+ <item>
+ <p>
+ erts: use a union to avoid strict aliasing issues</p>
+ <p>
+ Use a union for pointer type conversion to avoid compiler
+ warnings about strict-aliasing violations with gcc-4.1.
+ gcc >= 4.2 does not emit the warning. erts: adapt
+ matrix_nif to R14 erl_nif API changes (Thanks To Tuncer
+ Ayaz)</p>
+ <p>
+ Own Id: OTP-9487</p>
+ </item>
+ <item>
+ <p>
+ fix 64-bit issues in the garbage collection (Thanks to
+ Richard Carlsson)</p>
+ <p>
+ Own Id: OTP-9488</p>
+ </item>
+ <item>
+ <p>
+ epmd: fix compiler warnings</p>
+ <p>
+ Suppress compiler warnings about ignored return values.
+ (Thanks to Michael Santos )</p>
+ <p>
+ Own Id: OTP-9500</p>
+ </item>
+ <item>
+ <p>
+ Fix non-existing function (erlang:disconnect/1) in
+ distributed reference manual (Thanks to Fabian Kr�l)</p>
+ <p>
+ Own Id: OTP-9504</p>
+ </item>
+ <item>
+ <p>
+ Document fdatasync -lrt requirement (SunOS &lt;= 5.10)
+ (Thanks to Tuncer Ayaz)</p>
+ <p>
+ Own Id: OTP-9512</p>
+ </item>
+ <item>
+ <p>
+ Let epmd ignore empty ERL_EPMD_ADDRESS</p>
+ <p>
+ If the environment variable ERL_EPMD_ADDRESS is set to
+ the empty string, empd now behaves like it does by
+ default when ERL_EPMD_ADDRESS is unset. That is, in this
+ case, epmd now listens on all available interfaces
+ instead of using only the loopback interface, which
+ happened because epmd added the loopback address to the
+ (in this case empty) list of addresses specified via
+ ERL_EPMD_ADDRESS.</p>
+ <p>
+ Also, epmd now ignores ERL_EPMD_ADDRESS if it contains
+ only separator characters (comma and space).</p>
+ <p>
+ The same applies to epmd's -address option.(Thanks to
+ Holger Wei�)</p>
+ <p>
+ Own Id: OTP-9525</p>
+ </item>
+ <item>
+ <p>
+ Remove dead code in erl_compile (Thanks to Tuncer Ayaz)</p>
+ <p>
+ Own Id: OTP-9527</p>
+ </item>
+ <item>
+ <p>
+ Add erlang:external_size/2 BIF</p>
+ <p>
+ This BIF's second parameter is a list of options.
+ Currently the only allowed option is {minor_version,
+ Version} where version is either 0 (default) or 1.
+ (Thanks to Filipe David Manana )</p>
+ <p>
+ Own Id: OTP-9528</p>
+ </item>
+ <item>
+ <p>
+ Fix enif_compare on 64bits machines</p>
+ <p>
+ In 64bits machines the Sint type has a size of 8 bytes,
+ while on 32bits machines it has a 4 bytes size.
+ enif_compare was ignoring this and therefore returning
+ incorrect values when the result of the CMP function
+ (which returns a Sint value) doesn't fit in 4 bytes.
+ (Thanks to Filipe David Manana)</p>
+ <p>
+ Own Id: OTP-9533</p>
+ </item>
+ <item>
+ <p>
+ Implement or fix -Werror option</p>
+ <p>
+ If -Werror is enabled and there are warnings no output
+ file is written. Also make sure that error/warning
+ reporting is consistent. (Thanks to Tuncer Ayaz)</p>
+ <p>
+ Own Id: OTP-9536</p>
+ </item>
+ <item>
+ <p>In some rare cases we did not have a run queue when
+ scheduling misc ops. This is now fixed.</p>
+ <p>
+ Own Id: OTP-9537</p>
+ </item>
+ <item>
+ <p>Remove misc. compiler warnings</p>
+ <p>
+ Own Id: OTP-9542</p>
+ </item>
+ <item>
+ <p>
+ Two bugs in gen_sctp has been corrected: getopts/setopts
+ hence also send could only be called from socket owner,
+ and options 'linger', 'rcvbuf' and 'sndbuf' was read from
+ wrong protocol layer hence read wrong values by getopts.</p>
+ <p>
+ Own Id: OTP-9544</p>
+ </item>
+ <item>
+ <p>
+ Erlang/OTP can now be built on MacOS X Lion.</p>
+ <p>
+ Own Id: OTP-9547</p>
+ </item>
+ <item>
+ <p> XML files have been corrected. </p>
+ <p>
+ Own Id: OTP-9550 Aux Id: OTP-9541 </p>
+ </item>
+ <item>
+ <p>
+ Fix potential errors inspired by running cppcheck(1)
+ (Thanks to Christian von Roques)</p>
+ <p>
+ Own Id: OTP-9557</p>
+ </item>
+ <item>
+ <p>When auxiliary work was enqueued on a scheduler, the
+ wakeup of the scheduler in order to handle this work
+ could be lost. Wakeups in order to handle ordinary work
+ were not effected by this bug. The bug only effected
+ runtime systems with SMP support as follows:</p> <list>
+ <item>Deallocation of some ETS data structures could be
+ delayed.</item> <item>On Linux systems not using the NPTL
+ thread library (typically ancient systems with kernel
+ versions prior to 2.6) and Windows systems, the <c>{Port,
+ {exit_status, Status}}</c> message from a terminating
+ port program could be delayed. That is, it only effected
+ port programs which had been started by passing
+ <c>exit_status</c> as an option to
+ <c>open_port/2</c>.</item> </list>
+ <p>
+ Own Id: OTP-9567</p>
+ </item>
+ <item>
+ <p>
+ Handle rare race in the crypto key server functionality</p>
+ <p>
+ Own Id: OTP-9586</p>
</item>
</list>
</section>
@@ -61,16 +328,40 @@
<section><title>Improvements and New Features</title>
<list>
<item>
+ <p> Types and specifications have been added. </p>
+ <p>
+ Own Id: OTP-9356</p>
+ </item>
+ <item>
+ <p>
+ New allocator strategy "address order first fit". May
+ ease the emptying of memory carriers and thereby real
+ release of memory back to the OS.</p>
+ <p>
+ Own Id: OTP-9424</p>
+ </item>
+ <item>
+ <p>
+ The new <c>erlang:check_old_code/1</c> BIF checks whether
+ a module has old code.</p>
+ <p>
+ Own Id: OTP-9495</p>
+ </item>
+ <item>
+ <p> Update documentation and specifications of some of
+ the zlib functions. </p>
+ <p>
+ Own Id: OTP-9506</p>
+ </item>
+ <item>
+ <p>
+ Detect the available CPUs on IRIX</p>
<p>
- The <c>erts_alloc_util</c> framework has been extended
- with functionality for separation of small blocks from
- other blocks in separate carriers. This functionality is
- currently disabled by default, but can be enabled in
- order to finetune memory management. For more information
- see <seealso
- marker="erts:erts_alloc">erts_alloc(3)</seealso>.</p>
+ Add support for querying the number of configured and
+ online processors on SGI systems running IRIX.(Thanks to
+ Holger Wei�)</p>
<p>
- Own Id: OTP-9339 Aux Id: Seq11780 </p>
+ Own Id: OTP-9531</p>
</item>
</list>
</section>
@@ -1996,6 +2287,24 @@
</section>
+<section><title>Erts 5.7.5.2</title>
+
+ <section><title>Known Bugs and Problems</title>
+ <list>
+ <item>
+ <p>
+ Two bugs in gen_sctp has been corrected: getopts/setopts
+ hence also send could only be called from socket owner,
+ and options 'linger', 'rcvbuf' and 'sndbuf' was read from
+ wrong protocol layer hence read wrong values by getopts.</p>
+ <p>
+ Own Id: OTP-9544</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erts 5.7.5.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -4581,7 +4890,7 @@
The race occurred when a process removed a table during
termination simultaneously as another process removed the
same table via <c>ets:delete/1</c> and a third process
- created a table that accidentaly got the same internal
+ created a table that accidentally got the same internal
table index as the table being removed.</p>
<p>
Own Id: OTP-7349</p>
diff --git a/erts/doc/src/specs.xml b/erts/doc/src/specs.xml
new file mode 100644
index 0000000000..e5c2f4783f
--- /dev/null
+++ b/erts/doc/src/specs.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="latin1" ?>
+<specs xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:include href="../specs/specs_erl_prim_loader.xml"/>
+ <xi:include href="../specs/specs_erlang.xml"/>
+ <xi:include href="../specs/specs_init.xml"/>
+ <xi:include href="../specs/specs_zlib.xml"/>
+</specs>
diff --git a/erts/doc/src/start_erl.xml b/erts/doc/src/start_erl.xml
index 21cc901f52..92d87b095a 100644
--- a/erts/doc/src/start_erl.xml
+++ b/erts/doc/src/start_erl.xml
@@ -4,7 +4,7 @@
<comref>
<header>
<copyright>
- <year>1998</year><year>2009</year>
+ <year>1998</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -69,12 +69,29 @@
<c><![CDATA[erl]]></c> program. Everything <em>after</em><c><![CDATA[++]]></c> is
interpreted as options to <c><![CDATA[start_erl]]></c> itself.</item>
<tag>-reldir &lt;release root&gt;</tag>
- <item>Mandatory if the environment variable <c><![CDATA[RELDIR]]></c> is not
- specified. Tells start_erl where the root of the
- release tree is placed in the file-system
- (like &lt;Erlang root&gt;\\releases). The
- <c><![CDATA[start_erl.data]]></c> file is expected to be placed in
- this directory (if not otherwise specified).</item>
+
+ <item>Mandatory if the environment variable
+ <c><![CDATA[RELDIR]]></c> is not specified and no
+ <c>-rootdir</c> option is given. Tells start_erl where the
+ root of the release tree is placed in the file-system (typically
+ &lt;Erlang root&gt;\\releases). The
+ <c><![CDATA[start_erl.data]]></c> file is expected to be
+ placed in this directory (if not otherwise specified). If
+ only the <c>-rootdir</c> option is given, the directory is
+ assumed to be &lt;Erlang root&gt;\\releases.</item>
+
+ <tag>-rootdir &lt;Erlang root directory&gt;</tag>
+
+ <item>Mandatory if <c>-reldir</c> is not given and there is
+ no <c><![CDATA[RELDIR]]></c> in the environment. This
+ specifies the Erlang installation root directory (under
+ which the <c>lib</c>, <c>releases</c> and
+ <c>erts-&lt;Version&gt;</c> directories are placed). If only
+ <c>-reldir</c> (or the environment variable
+ <c><![CDATA[RELDIR]]></c>) is given, the Erlang root is assumed to
+ be the directory exactly one level above the release
+ directory.</item>
+
<tag>-data &lt;data file name&gt;</tag>
<item>Optional, specifies another data file than start_erl.data
in the &lt;release root&gt;. It is specified relative to the
diff --git a/erts/doc/src/zlib.xml b/erts/doc/src/zlib.xml
index b1e768bce9..8917ab5c3a 100644
--- a/erts/doc/src/zlib.xml
+++ b/erts/doc/src/zlib.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2005</year><year>2010</year>
+ <year>2005</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -76,96 +76,92 @@ list_to_binary([Compressed|Last])</pre>
</taglist>
</description>
- <section>
- <title>DATA TYPES</title>
- <code type="none">
-iodata = iolist() | binary()
-
-iolist = [char() | binary() | iolist()]
- a binary is allowed as the tail of the list
-
-zstream = a zlib stream, see open/0</code>
- </section>
+ <datatypes>
+ <datatype>
+ <name name="zstream"/>
+ <desc>
+ <p>A zlib stream, see <seealso marker="#open/0">open/0</seealso>.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="zlevel"/>
+ </datatype>
+ <datatype>
+ <name name="zmemlevel"/>
+ </datatype>
+ <datatype>
+ <name name="zmethod"/>
+ </datatype>
+ <datatype>
+ <name name="zstrategy"/>
+ </datatype>
+ <datatype>
+ <name name="zwindowbits"/>
+ <desc>
+ <p>Normally in the range <c>-15..-9 | 9..15</c>.</p>
+ </desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>open() -> Z </name>
+ <name name="open" arity="0"/>
<fsummary>Open a stream and return a stream reference</fsummary>
- <type>
- <v>Z = zstream()</v>
- </type>
<desc>
<p>Open a zlib stream.</p>
</desc>
</func>
<func>
- <name>close(Z) -> ok</name>
+ <name name="close" arity="1"/>
<fsummary>Close a stream</fsummary>
- <type>
- <v>Z = zstream()</v>
- </type>
<desc>
- <p>Closes the stream referenced by <c>Z</c>.</p>
+ <p>Closes the stream referenced by <c><anno>Z</anno></c>.</p>
</desc>
</func>
<func>
- <name>deflateInit(Z) -> ok</name>
+ <name name="deflateInit" arity="1"/>
<fsummary>Initialize a session for compression</fsummary>
- <type>
- <v>Z = zstream()</v>
- </type>
<desc>
- <p>Same as <c>zlib:deflateInit(Z, default)</c>.</p>
+ <p>Same as <c>zlib:deflateInit(<anno>Z</anno>, default)</c>.</p>
</desc>
</func>
<func>
- <name>deflateInit(Z, Level) -> ok</name>
+ <name name="deflateInit" arity="2"/>
<fsummary>Initialize a session for compression</fsummary>
- <type>
- <v>Z = zstream()</v>
- <v>Level = none | default | best_speed | best_compression | 0..9</v>
- </type>
<desc>
<p>Initialize a zlib stream for compression.</p>
- <p><c>Level</c> decides the compression level to be used, 0
+ <p><c><anno>Level</anno></c> decides the compression level to be used, 0
(<c>none</c>), gives no compression at all, 1
(<c>best_speed</c>) gives best speed and 9
(<c>best_compression</c>) gives best compression.</p>
</desc>
</func>
<func>
- <name>deflateInit(Z, Level, Method, WindowBits, MemLevel, Strategy) -> ok</name>
+ <name name="deflateInit" arity="6"/>
<fsummary>Initialize a session for compression</fsummary>
- <type>
- <v>Z = zstream()</v>
- <v>Level = none | default | best_speed | best_compression | 0..9</v>
- <v>Method = deflated</v>
- <v>WindowBits = 9..15|-9..-15</v>
- <v>MemLevel = 1..9</v>
- <v>Strategy = default|filtered|huffman_only</v>
- </type>
<desc>
<p>Initiates a zlib stream for compression.</p>
- <p>The <c>Level</c> parameter decides the compression level to be
+ <p>The <c><anno>Level</anno></c> parameter decides the compression level to be
used, 0 (<c>none</c>), gives no compression at all, 1
(<c>best_speed</c>) gives best speed and 9
(<c>best_compression</c>) gives best compression.</p>
- <p>The <c>Method</c> parameter decides which compression method to use,
+ <p>The <c><anno>Method</anno></c> parameter decides which compression method to use,
currently the only supported method is <c>deflated</c>.</p>
- <p>The <c>WindowBits</c> parameter is the base two logarithm
+ <p>The <c><anno>WindowBits</anno></c> parameter is the base two logarithm
of the window size (the size of the history buffer). It
should be in the range 9 through 15. Larger values
of this parameter result in better compression at the
expense of memory usage. The default value is 15 if
- <c>deflateInit/2</c>. A negative <c>WindowBits</c>
+ <c>deflateInit/2</c>. A negative <c><anno>WindowBits</anno></c>
value suppresses the zlib header (and checksum) from the
stream. Note that the zlib source mentions this only as a
undocumented feature.</p>
- <p>The <c>MemLevel</c> parameter specifies how much memory
+ <p>The <c><anno>MemLevel</anno></c> parameter specifies how much memory
should be allocated for the internal compression
- state. <c>MemLevel</c>=1 uses minimum memory but is slow and
- reduces compression ratio; <c>MemLevel</c>=9 uses maximum
+ state. <c><anno>MemLevel</anno></c>=1 uses minimum memory but is slow and
+ reduces compression ratio; <c><anno>MemLevel</anno></c>=9 uses maximum
memory for optimal speed. The default value is 8.</p>
- <p>The <c>Strategy</c> parameter is used to tune the
+ <p>The <c><anno>Strategy</anno></c> parameter is used to tune the
compression algorithm. Use the value <c>default</c> for
normal data, <c>filtered</c> for data produced by a filter
(or predictor), or <c>huffman_only</c> to force Huffman
@@ -175,54 +171,43 @@ zstream = a zlib stream, see open/0</code>
tuned to compress them better. The effect of
<c>filtered</c>is to force more Huffman coding and less
string matching; it is somewhat intermediate between
- <c>default</c> and <c>huffman_only</c>. The <c>Strategy</c>
+ <c>default</c> and <c>huffman_only</c>. The <c><anno>Strategy</anno></c>
parameter only affects the compression ratio but not the
correctness of the compressed output even if it is not set
appropriately.</p>
</desc>
</func>
<func>
- <name>deflate(Z, Data) -> Compressed</name>
+ <name name="deflate" arity="2"/>
<fsummary>Compress data</fsummary>
- <type>
- <v>Z = zstream()</v>
- <v>Data = iodata()</v>
- <v>Compressed = iolist()</v>
- </type>
<desc>
- <p>Same as <c>deflate(Z, Data, none)</c>.</p>
+ <p>Same as <c>deflate(<anno>Z</anno>, <anno>Data</anno>, none)</c>.</p>
</desc>
</func>
<func>
- <name>deflate(Z, Data, Flush) -> </name>
+ <name name="deflate" arity="3"/>
<fsummary>Compress data</fsummary>
- <type>
- <v>Z = zstream()</v>
- <v>Data = iodata()</v>
- <v>Flush = none | sync | full | finish</v>
- <v>Compressed = iolist()</v>
- </type>
<desc>
<p><c>deflate/3</c> compresses as much data as possible, and
stops when the input buffer becomes empty. It may introduce
some output latency (reading input without producing any
output) except when forced to flush.</p>
- <p>If the parameter <c>Flush</c> is set to <c>sync</c>, all
+ <p>If the parameter <c><anno>Flush</anno></c> is set to <c>sync</c>, all
pending output is flushed to the output buffer and the
output is aligned on a byte boundary, so that the
decompressor can get all input data available so far.
Flushing may degrade compression for some compression algorithms and so
it should be used only when necessary.</p>
- <p>If <c>Flush</c> is set to <c>full</c>, all output is flushed as with
+ <p>If <c><anno>Flush</anno></c> is set to <c>full</c>, all output is flushed as with
<c>sync</c>, and the compression state is reset so that decompression can
restart from this point if previous compressed data has been damaged or if
random access is desired. Using <c>full</c> too often can seriously degrade
the compression.</p>
- <p>If the parameter <c>Flush</c> is set to <c>finish</c>,
+ <p>If the parameter <c><anno>Flush</anno></c> is set to <c>finish</c>,
pending input is processed, pending output is flushed and
<c>deflate/3</c> returns. Afterwards the only possible
operations on the stream are <c>deflateReset/1</c> or <c>deflateEnd/1</c>.</p>
- <p><c>Flush</c> can be set to <c>finish</c> immediately after
+ <p><c><anno>Flush</anno></c> can be set to <c>finish</c> immediately after
<c>deflateInit</c> if all compression is to be done in one step.</p>
<pre>
@@ -234,13 +219,8 @@ list_to_binary([B1,B2])</pre>
</desc>
</func>
<func>
- <name>deflateSetDictionary(Z, Dictionary) -> Adler32</name>
+ <name name="deflateSetDictionary" arity="2"/>
<fsummary>Initialize the compression dictionary</fsummary>
- <type>
- <v>Z = zstream()</v>
- <v>Dictionary = binary()</v>
- <v>Adler32 = integer()</v>
- </type>
<desc>
<p>Initializes the compression dictionary from the given byte
sequence without producing any compressed output. This
@@ -253,11 +233,8 @@ list_to_binary([B1,B2])</pre>
</desc>
</func>
<func>
- <name>deflateReset(Z) -> ok</name>
+ <name name="deflateReset" arity="1"/>
<fsummary>Reset the deflate session</fsummary>
- <type>
- <v>Z = zstream()</v>
- </type>
<desc>
<p>This function is equivalent to <c>deflateEnd/1</c>
followed by <c>deflateInit/[1|2|6]</c>, but does not free
@@ -267,34 +244,26 @@ list_to_binary([B1,B2])</pre>
</desc>
</func>
<func>
- <name>deflateParams(Z, Level, Strategy) -> ok </name>
+ <name name="deflateParams" arity="3"/>
<fsummary>Dynamicly update deflate parameters</fsummary>
- <type>
- <v>Z = zstream()</v>
- <v>Level = none | default | best_speed | best_compression | 0..9</v>
- <v>Strategy = default|filtered|huffman_only</v>
- </type>
<desc>
<p>Dynamically update the compression level and compression
- strategy. The interpretation of <c>Level</c> and
- <c>Strategy</c> is as in <c>deflateInit/6</c>. This can be
+ strategy. The interpretation of <c><anno>Level</anno></c> and
+ <c><anno>Strategy</anno></c> is as in <c>deflateInit/6</c>. This can be
used to switch between compression and straight copy of the
input data, or to switch to a different kind of input data
requiring a different strategy. If the compression level is
changed, the input available so far is compressed with the
old level (and may be flushed); the new level will take
effect only at the next call of <c>deflate/3</c>.</p>
- <p>Before the call of deflateParams, the stream state must be set as for
+ <p>Before the call of <c>deflateParams</c>, the stream state must be set as for
a call of <c>deflate/3</c>, since the currently available input may have to
be compressed and flushed.</p>
</desc>
</func>
<func>
- <name>deflateEnd(Z) -> ok</name>
+ <name name="deflateEnd" arity="1"/>
<fsummary>End deflate session</fsummary>
- <type>
- <v>Z = zstream()</v>
- </type>
<desc>
<p>End the deflate session and cleans all data used.
Note that this function will throw an <c>data_error</c>
@@ -304,43 +273,31 @@ list_to_binary([B1,B2])</pre>
</desc>
</func>
<func>
- <name>inflateInit(Z) -> ok </name>
+ <name name="inflateInit" arity="1"/>
<fsummary>Initialize a session for decompression</fsummary>
- <type>
- <v>Z = zstream()</v>
- </type>
<desc>
<p>Initialize a zlib stream for decompression.</p>
</desc>
</func>
<func>
- <name>inflateInit(Z, WindowBits) -> ok </name>
+ <name name="inflateInit" arity="2"/>
<fsummary>Initialize a session for decompression</fsummary>
- <type>
- <v>Z = zstream()</v>
- <v>WindowBits = 9..15|-9..-15</v>
- </type>
<desc>
<p>Initialize decompression session on zlib stream.</p>
- <p>The <c>WindowBits</c> parameter is the base two logarithm
+ <p>The <c><anno>WindowBits</anno></c> parameter is the base two logarithm
of the maximum window size (the size of the history buffer).
It should be in the range 9 through 15.
The default value is 15 if <c>inflateInit/1</c> is used.
If a compressed stream with a larger window size is
given as input, inflate() will throw the <c>data_error</c>
- exception. A negative <c>WindowBits</c> value makes zlib ignore the
+ exception. A negative <c><anno>WindowBits</anno></c> value makes zlib ignore the
zlib header (and checksum) from the stream. Note that the zlib
source mentions this only as a undocumented feature.</p>
</desc>
</func>
<func>
- <name>inflate(Z, Data) -> DeCompressed </name>
+ <name name="inflate" arity="2"/>
<fsummary>Decompress data</fsummary>
- <type>
- <v>Z = zstream()</v>
- <v>Data = iodata()</v>
- <v>DeCompressed = iolist()</v>
- </type>
<desc>
<p><c>inflate/2</c> decompresses as much data as possible.
It may some introduce some output latency (reading
@@ -353,12 +310,8 @@ list_to_binary([B1,B2])</pre>
</desc>
</func>
<func>
- <name>inflateSetDictionary(Z, Dictionary) -> ok</name>
+ <name name="inflateSetDictionary" arity="2"/>
<fsummary>Initialize the decompression dictionary</fsummary>
- <type>
- <v>Z = zstream()</v>
- <v>Dictionary = binary()</v>
- </type>
<desc>
<p>Initializes the decompression dictionary from the given
uncompressed byte sequence. This function must be called
@@ -381,11 +334,8 @@ unpack(Z, Compressed, Dict) ->
</desc>
</func>
<func>
- <name>inflateReset(Z) -> ok</name>
+ <name name="inflateReset" arity="1"/>
<fsummary>>Reset the inflate session</fsummary>
- <type>
- <v>Z = zstream()</v>
- </type>
<desc>
<p>This function is equivalent to <c>inflateEnd/1</c> followed
by <c>inflateInit/1</c>, but does not free and reallocate all
@@ -394,11 +344,8 @@ unpack(Z, Compressed, Dict) ->
</desc>
</func>
<func>
- <name>inflateEnd(Z) -> ok</name>
+ <name name="inflateEnd" arity="1"/>
<fsummary>End inflate session</fsummary>
- <type>
- <v>Z = zstream()</v>
- </type>
<desc>
<p>End the inflate session and cleans all data used. Note
that this function will throw a <c>data_error</c> exception
@@ -407,198 +354,132 @@ unpack(Z, Compressed, Dict) ->
</desc>
</func>
<func>
- <name>setBufSize(Z, Size) -> ok</name>
+ <name name="setBufSize" arity="2"/>
<fsummary>Set buffer size</fsummary>
- <type>
- <v>Z = zstream()</v>
- <v>Size = integer()</v>
- </type>
<desc>
<p>Sets the intermediate buffer size.</p>
</desc>
</func>
<func>
- <name>getBufSize(Z) -> Size</name>
+ <name name="getBufSize" arity="1"/>
<fsummary>Get buffer size</fsummary>
- <type>
- <v>Z = zstream()</v>
- <v>Size = integer()</v>
- </type>
<desc>
<p>Get the size of intermediate buffer.</p>
</desc>
</func>
<func>
- <name>crc32(Z) -> CRC</name>
+ <name name="crc32" arity="1"/>
<fsummary>Get current CRC</fsummary>
- <type>
- <v>Z = zstream()</v>
- <v>CRC = integer()</v>
- </type>
<desc>
<p>Get the current calculated CRC checksum.</p>
</desc>
</func>
<func>
- <name>crc32(Z, Binary) -> CRC</name>
+ <name name="crc32" arity="2"/>
<fsummary>Calculate CRC</fsummary>
- <type>
- <v>Z = zstream()</v>
- <v>Binary = binary()</v>
- <v>CRC = integer()</v>
- </type>
<desc>
- <p>Calculate the CRC checksum for <c>Binary</c>.</p>
+ <p>Calculate the CRC checksum for <c><anno>Data</anno></c>.</p>
</desc>
</func>
<func>
- <name>crc32(Z, PrevCRC, Binary) -> CRC </name>
+ <name name="crc32" arity="3"/>
<fsummary>Calculate CRC</fsummary>
- <type>
- <v>Z = zstream()</v>
- <v>PrevCRC = integer()</v>
- <v>Binary = binary()</v>
- <v>CRC = integer()</v>
- </type>
- <desc>
- <p>Update a running CRC checksum for <c>Binary</c>.
- If <c>Binary</c> is the empty binary, this function returns
+ <desc>
+ <p>Update a running CRC checksum for <c><anno>Data</anno></c>.
+ If <c><anno>Data</anno></c> is the empty binary or the empty iolist, this function returns
the required initial value for the crc.</p>
<pre>
-Crc = lists:foldl(fun(Bin,Crc0) ->
- zlib:crc32(Z, Crc0, Bin),
- end, zlib:crc32(Z,&lt;&lt; &gt;&gt;), Bins)</pre>
+Crc = lists:foldl(fun(Data,Crc0) ->
+ zlib:crc32(Z, Crc0, Data),
+ end, zlib:crc32(Z,&lt;&lt; &gt;&gt;), Datas)</pre>
</desc>
</func>
<func>
- <name>crc32_combine(Z, CRC1, CRC2, Size2) -> CRC </name>
+ <name name="crc32_combine" arity="4"/>
<fsummary>Combine two CRC's</fsummary>
- <type>
- <v>Z = zstream()</v>
- <v>CRC = integer()</v>
- <v>CRC1 = integer()</v>
- <v>CRC2 = integer()</v>
- <v>Size2 = integer()</v>
- </type>
- <desc>
- <p>Combine two CRC checksums into one. For two binaries,
- <c>Bin1</c> and <c>Bin2</c> with sizes of <c>Size1</c> and
- <c>Size2</c>, with CRC checksums <c>CRC1</c> and
- <c>CRC2</c>. <c>crc32_combine/4</c> returns the <c>CRC</c>
- checksum of <c>&lt;&lt;Bin1/binary,Bin2/binary&gt;&gt;</c>, requiring
- only <c>CRC1</c>, <c>CRC2</c>, and <c>Size2</c>.
+ <desc>
+ <p>Combine two CRC checksums into one. For two binaries or iolists,
+ <c>Data1</c> and <c>Data2</c> with sizes of <c>Size1</c> and
+ <c><anno>Size2</anno></c>, with CRC checksums <c><anno>CRC1</anno></c> and
+ <c><anno>CRC2</anno></c>. <c>crc32_combine/4</c> returns the <c><anno>CRC</anno></c>
+ checksum of <c>[Data1,Data2]</c>, requiring
+ only <c><anno>CRC1</anno></c>, <c><anno>CRC2</anno></c>, and <c><anno>Size2</anno></c>.
</p>
</desc>
</func>
<func>
- <name>adler32(Z, Binary) -> Checksum</name>
+ <name name="adler32" arity="2"/>
<fsummary>Calculate the adler checksum</fsummary>
- <type>
- <v>Z = zstream()</v>
- <v>Binary = binary()</v>
- <v>Checksum = integer()</v>
- </type>
<desc>
- <p>Calculate the Adler-32 checksum for <c>Binary</c>.</p>
+ <p>Calculate the Adler-32 checksum for <c><anno>Data</anno></c>.</p>
</desc>
</func>
<func>
- <name>adler32(Z, PrevAdler, Binary) -> Checksum</name>
+ <name name="adler32" arity="3"/>
<fsummary>Calculate the adler checksum</fsummary>
- <type>
- <v>Z = zstream()</v>
- <v>PrevAdler = integer()</v>
- <v>Binary = binary()</v>
- <v>Checksum = integer()</v>
- </type>
- <desc>
- <p>Update a running Adler-32 checksum for <c>Binary</c>.
- If <c>Binary</c> is the empty binary, this function returns
+ <desc>
+ <p>Update a running Adler-32 checksum for <c><anno>Data</anno></c>.
+ If <c><anno>Data</anno></c> is the empty binary or the empty iolist, this function returns
the required initial value for the checksum.</p>
<pre>
-Crc = lists:foldl(fun(Bin,Crc0) ->
- zlib:adler32(Z, Crc0, Bin),
- end, zlib:adler32(Z,&lt;&lt; &gt;&gt;), Bins)</pre>
+Crc = lists:foldl(fun(Data,Crc0) ->
+ zlib:adler32(Z, Crc0, Data),
+ end, zlib:adler32(Z,&lt;&lt; &gt;&gt;), Datas)</pre>
</desc>
</func>
<func>
- <name>adler32_combine(Z, Adler1, Adler2, Size2) -> Adler </name>
+ <name name="adler32_combine" arity="4"/>
<fsummary>Combine two Adler-32 checksums</fsummary>
- <type>
- <v>Z = zstream()</v>
- <v>Adler = integer()</v>
- <v>Adler1 = integer()</v>
- <v>Adler2 = integer()</v>
- <v>Size2 = integer()</v>
- </type>
- <desc>
- <p>Combine two Adler-32 checksums into one. For two binaries,
- <c>Bin1</c> and <c>Bin2</c> with sizes of <c>Size1</c> and
- <c>Size2</c>, with Adler-32 checksums <c>Adler1</c> and
- <c>Adler2</c>. <c>adler32_combine/4</c> returns the <c>Adler</c>
- checksum of <c>&lt;&lt;Bin1/binary,Bin2/binary&gt;&gt;</c>, requiring
- only <c>Adler1</c>, <c>Adler2</c>, and <c>Size2</c>.
+ <desc>
+ <p>Combine two Adler-32 checksums into one. For two binaries or iolists,
+ <c>Data1</c> and <c>Data2</c> with sizes of <c>Size1</c> and
+ <c><anno>Size2</anno></c>, with Adler-32 checksums <c><anno>Adler1</anno></c> and
+ <c><anno>Adler2</anno></c>. <c>adler32_combine/4</c> returns the <c><anno>Adler</anno></c>
+ checksum of <c>[Data1,Data2]</c>, requiring
+ only <c><anno>Adler1</anno></c>, <c><anno>Adler2</anno></c>, and <c><anno>Size2</anno></c>.
</p>
</desc>
</func>
<func>
- <name>compress(Binary) -> Compressed </name>
- <fsummary>Compress a binary with standard zlib functionality</fsummary>
- <type>
- <v>Binary = Compressed = binary()</v>
- </type>
+ <name name="compress" arity="1"/>
+ <fsummary>Compress data with standard zlib functionality</fsummary>
<desc>
- <p>Compress a binary (with zlib headers and checksum).</p>
+ <p>Compress data (with zlib headers and checksum).</p>
</desc>
</func>
<func>
- <name>uncompress(Binary) -> Decompressed</name>
- <fsummary>Uncompress a binary with standard zlib functionality</fsummary>
- <type>
- <v>Binary = Decompressed = binary()</v>
- </type>
+ <name name="uncompress" arity="1"/>
+ <fsummary>Uncompress data with standard zlib functionality</fsummary>
<desc>
- <p>Uncompress a binary (with zlib headers and checksum).</p>
+ <p>Uncompress data (with zlib headers and checksum).</p>
</desc>
</func>
<func>
- <name>zip(Binary) -> Compressed</name>
- <fsummary>Compress a binary without the zlib headers</fsummary>
- <type>
- <v>Binary = Compressed = binary()</v>
- </type>
+ <name name="zip" arity="1"/>
+ <fsummary>Compress data without the zlib headers</fsummary>
<desc>
- <p>Compress a binary (without zlib headers and checksum).</p>
+ <p>Compress data (without zlib headers and checksum).</p>
</desc>
</func>
<func>
- <name>unzip(Binary) -> Decompressed</name>
- <fsummary>Uncompress a binary without the zlib headers</fsummary>
- <type>
- <v>Binary = Decompressed = binary()</v>
- </type>
+ <name name="unzip" arity="1"/>
+ <fsummary>Uncompress data without the zlib headers</fsummary>
<desc>
- <p>Uncompress a binary (without zlib headers and checksum).</p>
+ <p>Uncompress data (without zlib headers and checksum).</p>
</desc>
</func>
<func>
- <name>gzip(Data) -> Compressed</name>
- <fsummary>Compress a binary with gz header</fsummary>
- <type>
- <v>Binary = Compressed = binary()</v>
- </type>
+ <name name="gzip" arity="1"/>
+ <fsummary>Compress data with gz header</fsummary>
<desc>
- <p>Compress a binary (with gz headers and checksum).</p>
+ <p>Compress data (with gz headers and checksum).</p>
</desc>
</func>
<func>
- <name>gunzip(Bin) -> Decompressed</name>
- <fsummary>Uncompress a binary with gz header</fsummary>
- <type>
- <v>Binary = Decompressed = binary()</v>
- </type>
+ <name name="gunzip" arity="1"/>
+ <fsummary>Uncompress data with gz header</fsummary>
<desc>
- <p>Uncompress a binary (with gz headers and checksum).</p>
+ <p>Uncompress data (with gz headers and checksum).</p>
</desc>
</func>
</funcs>
diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in
index d9362a2a8f..708d4ca0a3 100644
--- a/erts/emulator/Makefile.in
+++ b/erts/emulator/Makefile.in
@@ -291,7 +291,8 @@ else
LIBS += $(ERL_TOP)/erts/emulator/pcre/obj/$(TARGET)/$(TYPE)/$(LIB_PREFIX)epcre$(LIB_SUFFIX)
endif
-DEPLIBS += $(ERL_TOP)/erts/emulator/pcre/obj/$(TARGET)/$(TYPE)/$(LIB_PREFIX)epcre$(LIB_SUFFIX)
+EPCRE_LIB = $(ERL_TOP)/erts/emulator/pcre/obj/$(TARGET)/$(TYPE)/$(LIB_PREFIX)epcre$(LIB_SUFFIX)
+DEPLIBS += $(EPCRE_LIB)
PERFCTR_PATH=@PERFCTR_PATH@
USE_PERFCTR=@USE_PERFCTR@
@@ -382,7 +383,7 @@ ifeq ($(FLAVOR)-@ERTS_BUILD_SMP_EMU@,smp-no)
all:
@echo '*** Omitted build of emulator with smp support'
else
-all: generate erts_lib zlib pcre $(BINDIR)/$(EMULATOR_EXECUTABLE) $(UNIX_ONLY_BUILDS)
+all: generate erts_lib zlib $(BINDIR)/$(EMULATOR_EXECUTABLE) $(UNIX_ONLY_BUILDS)
ifeq ($(OMIT_OMIT_FP),yes)
@echo '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *'
@echo '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *'
@@ -403,8 +404,8 @@ zlib:
@set -e ; cd zlib && $(MAKE) TYPE=$(TYPE) $(TYPE)
endif
-pcre:
- @set -e ; cd pcre && $(MAKE) TYPE=$(TYPE) $(TYPE)
+
+include pcre/pcre.mk
erts_lib:
cd $(ERL_TOP)/erts/lib_src && $(MAKE) $(TYPE)
@@ -420,9 +421,9 @@ endif
$(RM) -rf $(BINDIR)/child_setup $(BINDIR)/child_setup.*
$(RM) -f $(BINDIR)/hipe_mkliterals $(BINDIR)/hipe_mkliterals.*
@set -e ; cd zlib && $(MAKE) clean
- @set -e ; cd pcre && $(MAKE) clean
+ rm -f $(OBJS) $(OBJDIR)/libepcre.a
-.PHONY: all zlib pcre clean
+.PHONY: all zlib clean
docs:
@@ -467,10 +468,11 @@ release_docs_spec:
# Generated source code. Put in $(TARGET) directory
#
+_create_dirs := $(shell mkdir -p $(CREATE_DIRS))
+
.PHONY : generate
-GENERATE= $(CREATE_DIRS) \
- $(TTF_DIR)/beam_opcodes.h \
+GENERATE= $(TTF_DIR)/beam_opcodes.h \
$(TARGET)/erl_bif_table.c \
$(TARGET)/erl_version.h \
$(TTF_DIR)/driver_tab.c \
@@ -598,11 +600,6 @@ INCLUDES += -I$(ERL_TOP)/erts/etc/vxworks
endif
ifeq ($(TARGET),win32)
-# Usually the same as the default rule, but certain platforms (i.e. win32) mix
-# different compilers
-$(OBJDIR)/beam_emu.o: beam/beam_emu.c
- $(EMU_CC) $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@
-
$(OBJDIR)/dll_sys.o: sys/$(ERLANG_OSTYPE)/sys.c
$(CC) $(CFLAGS) -DERL_RUN_SHARED_LIB=1 $(INCLUDES) -c $< -o $@
@@ -616,6 +613,11 @@ $(OBJDIR)/beam_emu.o: beam/beam_emu.c
$(CC) $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) \
-OPT:Olimit=0 -WOPT:lpre=off:spre=off:epre=off \
$(INCLUDES) -c $< -o $@
+else
+# Usually the same as the default rule, but certain platforms (e.g. win32) mix
+# different compilers
+$(OBJDIR)/beam_emu.o: beam/beam_emu.c
+ $(EMU_CC) $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@
endif
@@ -672,14 +674,8 @@ endif
# rebuilding (is this a good idea?) add a dummy dependency to this target.
#
-ifeq ($(findstring clearmake,$(MAKE)),clearmake)
-BEAMFILE_MAKEFLAG=-T
-else
-BEAMFILE_MAKEFLAG=
-endif
-
$(ERL_TOP)/lib/%.beam:
- cd $(@D)/../src && $(MAKE) $(BEAMFILE_MAKEFLAG) ../ebin/$(@F)
+ cd $(@D)/../src && $(MAKE) ../ebin/$(@F)
# ----------------------------------------------------------------------
@@ -725,7 +721,7 @@ RUN_OBJS = \
$(OBJDIR)/external.o $(OBJDIR)/dist.o \
$(OBJDIR)/binary.o $(OBJDIR)/erl_db.o \
$(OBJDIR)/erl_db_util.o $(OBJDIR)/erl_db_hash.o \
- $(OBJDIR)/erl_db_tree.o $(OBJDIR)/fix_alloc.o \
+ $(OBJDIR)/erl_db_tree.o $(OBJDIR)/erl_thr_progress.o \
$(OBJDIR)/big.o $(OBJDIR)/hash.o \
$(OBJDIR)/index.o $(OBJDIR)/atom.o \
$(OBJDIR)/module.o $(OBJDIR)/export.o \
@@ -742,7 +738,8 @@ RUN_OBJS = \
$(OBJDIR)/erl_bif_re.o $(OBJDIR)/erl_unicode.o \
$(OBJDIR)/packet_parser.o $(OBJDIR)/safe_hash.o \
$(OBJDIR)/erl_zlib.o $(OBJDIR)/erl_nif.o \
- $(OBJDIR)/erl_bif_binary.o
+ $(OBJDIR)/erl_bif_binary.o $(OBJDIR)/erl_ao_firstfit_alloc.o \
+ $(OBJDIR)/erl_thr_queue.o $(OBJDIR)/erl_sched_spec_pre_alloc.o
ifeq ($(TARGET),win32)
DRV_OBJS = \
@@ -857,7 +854,7 @@ $(OBJDIR)/%.o: hipe/%.c
$(BINDIR)/hipe_mkliterals$(TF_MARKER): $(OBJDIR)/hipe_mkliterals.o
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $<
-$(OBJDIR)/hipe_mkliterals.o: $(TTF_DIR)/hipe_x86_asm.h $(TTF_DIR)/hipe_ppc_asm.h
+$(OBJDIR)/hipe_mkliterals.o: $(TTF_DIR)/hipe_x86_asm.h $(TTF_DIR)/hipe_ppc_asm.h $(TTF_DIR)/beam_opcodes.h
$(TTF_DIR)/hipe_literals.h: $(BINDIR)/hipe_mkliterals$(TF_MARKER)
$(BINDIR)/hipe_mkliterals$(TF_MARKER) -c > $@
diff --git a/erts/emulator/beam/atom.c b/erts/emulator/beam/atom.c
index b97705ed96..d7c7f117cf 100644
--- a/erts/emulator/beam/atom.c
+++ b/erts/emulator/beam/atom.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2010. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -75,7 +75,7 @@ void atom_info(int to, void *to_arg)
index_info(to, to_arg, &erts_atom_table);
#ifdef ERTS_ATOM_PUT_OPS_STAT
erts_print(to, to_arg, "atom_put_ops: %ld\n",
- erts_smp_atomic_read(&atom_put_ops));
+ erts_smp_atomic_read_nob(&atom_put_ops));
#endif
if (lock)
@@ -213,7 +213,7 @@ am_atom_put(const char* name, int len)
len = MAX_ATOM_LENGTH;
}
#ifdef ERTS_ATOM_PUT_OPS_STAT
- erts_smp_atomic_inc(&atom_put_ops);
+ erts_smp_atomic_inc_nob(&atom_put_ops);
#endif
a.len = len;
a.name = (byte*)name;
@@ -309,7 +309,7 @@ init_atom_table(void)
rwmtx_opt.lived = ERTS_SMP_RWMTX_LONG_LIVED;
#ifdef ERTS_ATOM_PUT_OPS_STAT
- erts_smp_atomic_init(&atom_put_ops, 0);
+ erts_smp_atomic_init_nob(&atom_put_ops, 0);
#endif
erts_smp_rwmtx_init_opt(&atom_table_lock, &rwmtx_opt, "atom_tab");
diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names
index 68d64fb7b0..71454b3e57 100644
--- a/erts/emulator/beam/atom.names
+++ b/erts/emulator/beam/atom.names
@@ -69,6 +69,8 @@ atom ac
atom active
atom all
atom all_but_first
+atom alloc_info
+atom alloc_sizes
atom allocated
atom allocated_areas
atom allocator
@@ -156,6 +158,8 @@ atom cr
atom crlf
atom creation
atom current_function
+atom current_location
+atom current_stacktrace
atom data
atom debug_flags
atom delay_trap
@@ -553,5 +557,6 @@ atom warning_msg
atom wordsize
atom write_concurrency
atom xor
+atom x86
atom yes
atom yield
diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c
index d76a7d8e9f..bc8c001454 100644
--- a/erts/emulator/beam/beam_bif_load.c
+++ b/erts/emulator/beam/beam_bif_load.c
@@ -33,12 +33,14 @@
#include "beam_catches.h"
#include "erl_binary.h"
#include "erl_nif.h"
+#include "erl_thr_progress.h"
static void set_default_trace_pattern(Eterm module);
static Eterm check_process_code(Process* rp, Module* modp);
static void delete_code(Process *c_p, ErtsProcLocks c_p_locks, Module* modp);
static void delete_export_references(Eterm module);
static int purge_module(int module);
+static void decrement_refc(BeamInstr* code);
static int is_native(BeamInstr* code);
static int any_heap_ref_ptrs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size);
static int any_heap_refs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size);
@@ -49,11 +51,11 @@ load_module_2(BIF_ALIST_2)
{
Eterm reason;
Eterm* hp;
- int i;
int sz;
byte* code;
Eterm res;
byte* temp_alloc = NULL;
+ struct LoaderState* stp;
if (is_not_atom(BIF_ARG_1)) {
error:
@@ -63,49 +65,37 @@ load_module_2(BIF_ALIST_2)
if ((code = erts_get_aligned_binary_bytes(BIF_ARG_2, &temp_alloc)) == NULL) {
goto error;
}
- erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
-
- erts_export_consolidate();
-
hp = HAlloc(BIF_P, 3);
+
+ /*
+ * Read the BEAM file and prepare the module for loading.
+ */
+ stp = erts_alloc_loader_state();
sz = binary_size(BIF_ARG_2);
- if ((i = erts_load_module(BIF_P, 0,
- BIF_P->group_leader, &BIF_ARG_1, code, sz)) < 0) {
- switch (i) {
- case -1: reason = am_badfile; break;
- case -2: reason = am_nofile; break;
- case -3: reason = am_not_purged; break;
- case -4:
- reason = am_atom_put("native_code", sizeof("native_code")-1);
- break;
- case -5:
- {
- /*
- * The module contains an on_load function. The loader
- * has loaded the module as usual, except that the
- * export entries does not point into the module, so it
- * is not possible to call any code in the module.
- */
-
- ERTS_DECL_AM(on_load);
- reason = AM_on_load;
- break;
- }
- default: reason = am_badfile; break;
- }
+ reason = erts_prepare_loading(stp, BIF_P, BIF_P->group_leader,
+ &BIF_ARG_1, code, sz);
+ erts_free_aligned_binary_bytes(temp_alloc);
+ if (reason != NIL) {
res = TUPLE2(hp, am_error, reason);
- goto done;
+ BIF_RET(res);
}
- set_default_trace_pattern(BIF_ARG_1);
- res = TUPLE2(hp, am_module, BIF_ARG_1);
+ /*
+ * Stop all other processes and finish the loading of the module.
+ */
+ erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
+ erts_smp_thr_progress_block();
+
+ reason = erts_finish_loading(stp, BIF_P, 0, &BIF_ARG_1);
+ if (reason != NIL) {
+ res = TUPLE2(hp, am_error, reason);
+ } else {
+ set_default_trace_pattern(BIF_ARG_1);
+ res = TUPLE2(hp, am_module, BIF_ARG_1);
+ }
- done:
- erts_free_aligned_binary_bytes(temp_alloc);
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
-
BIF_RET(res);
}
@@ -118,12 +108,12 @@ BIF_RETTYPE purge_module_1(BIF_ALIST_1)
}
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
erts_export_consolidate();
purge_res = purge_module(atom_val(BIF_ARG_1));
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
if (purge_res < 0) {
@@ -152,16 +142,33 @@ BIF_RETTYPE code_make_stub_module_3(BIF_ALIST_3)
Eterm res;
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
erts_export_consolidate();
res = erts_make_stub_module(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
return res;
}
+BIF_RETTYPE
+check_old_code_1(BIF_ALIST_1)
+{
+ Module* modp;
+
+ if (is_not_atom(BIF_ARG_1)) {
+ BIF_ERROR(BIF_P, BADARG);
+ }
+ modp = erts_get_module(BIF_ARG_1);
+ if (modp == NULL) { /* Doesn't exist. */
+ BIF_RET(am_false);
+ } else if (modp->old_code == NULL) { /* No old code. */
+ BIF_RET(am_false);
+ }
+ BIF_RET(am_true);
+}
+
Eterm
check_process_code_2(BIF_ALIST_2)
{
@@ -175,6 +182,13 @@ check_process_code_2(BIF_ALIST_2)
Eterm res;
if (internal_pid_index(BIF_ARG_1) >= erts_max_processes)
goto error;
+ modp = erts_get_module(BIF_ARG_2);
+ if (modp == NULL) { /* Doesn't exist. */
+ return am_false;
+ } else if (modp->old_code == NULL) { /* No old code. */
+ return am_false;
+ }
+
#ifdef ERTS_SMP
rp = erts_pid2proc_suspend(BIF_P, ERTS_PROC_LOCK_MAIN,
BIF_ARG_1, ERTS_PROC_LOCK_MAIN);
@@ -188,7 +202,6 @@ check_process_code_2(BIF_ALIST_2)
ERTS_BIF_YIELD2(bif_export[BIF_check_process_code_2], BIF_P,
BIF_ARG_1, BIF_ARG_2);
}
- modp = erts_get_module(BIF_ARG_2);
res = check_process_code(rp, modp);
#ifdef ERTS_SMP
if (BIF_P != rp) {
@@ -216,7 +229,7 @@ BIF_RETTYPE delete_module_1(BIF_ALIST_1)
goto badarg;
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
{
Module *modp = erts_get_module(BIF_ARG_1);
@@ -237,7 +250,7 @@ BIF_RETTYPE delete_module_1(BIF_ALIST_1)
}
}
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
if (res == am_badarg) {
@@ -329,7 +342,7 @@ BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2)
}
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
if (BIF_ARG_2 == am_true) {
int i;
@@ -368,7 +381,7 @@ BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2)
modp->catches = BEAM_CATCHES_NIL;
remove_from_address_table(code);
}
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
BIF_RET(am_true);
}
@@ -412,11 +425,6 @@ check_process_code(Process* rp, Module* modp)
#endif
#define INSIDE(a) (start <= (a) && (a) < end)
- if (modp == NULL) { /* Doesn't exist. */
- return am_false;
- } else if (modp->old_code == NULL) { /* No old code. */
- return am_false;
- }
/*
* Pick up limits for the module.
@@ -546,6 +554,7 @@ check_process_code(Process* rp, Module* modp)
} else {
Eterm* literals;
Uint lit_size;
+ struct erl_off_heap_header* oh;
/*
* Try to get rid of constants by by garbage collecting.
@@ -559,7 +568,9 @@ check_process_code(Process* rp, Module* modp)
(void) erts_garbage_collect(rp, 0, rp->arg_reg, rp->arity);
literals = (Eterm *) modp->old_code[MI_LITERALS_START];
lit_size = (Eterm *) modp->old_code[MI_LITERALS_END] - literals;
- erts_garbage_collect_literals(rp, literals, lit_size);
+ oh = (struct erl_off_heap_header *)
+ modp->old_code[MI_LITERALS_OFF_HEAP];
+ erts_garbage_collect_literals(rp, literals, lit_size, oh);
}
}
return am_false;
@@ -637,9 +648,6 @@ purge_module(int module)
* Any code to purge?
*/
if (modp->old_code == 0) {
- if (display_loads) {
- erts_printf("No code to purge for %T\n", make_atom(module));
- }
return -1;
}
@@ -660,6 +668,7 @@ purge_module(int module)
end = (BeamInstr *)((char *)code + modp->old_code_length);
erts_cleanup_funs_on_purge(code, end);
beam_catches_delmod(modp->old_catches, code, modp->old_code_length);
+ decrement_refc(code);
erts_free(ERTS_ALC_T_CODE, (void *) code);
modp->old_code = NULL;
modp->old_code_length = 0;
@@ -669,6 +678,23 @@ purge_module(int module)
}
static void
+decrement_refc(BeamInstr* code)
+{
+ struct erl_off_heap_header* oh =
+ (struct erl_off_heap_header *) code[MI_LITERALS_OFF_HEAP];
+
+ while (oh) {
+ Binary* bptr;
+ ASSERT(thing_subtag(oh->thing_word) == REFC_BINARY_SUBTAG);
+ bptr = ((ProcBin*)oh)->val;
+ if (erts_refc_dectest(&bptr->refc, 0) == 0) {
+ erts_bin_free(bptr);
+ }
+ oh = oh->next;
+ }
+}
+
+static void
remove_from_address_table(BeamInstr* code)
{
int i;
@@ -710,10 +736,10 @@ delete_code(Process *c_p, ErtsProcLocks c_p_locks, Module* modp)
if (modp->code != NULL && modp->code[MI_NUM_BREAKPOINTS] > 0) {
if (c_p && c_p_locks)
erts_smp_proc_unlock(c_p, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
erts_clear_module_break(modp);
modp->code[MI_NUM_BREAKPOINTS] = 0;
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
if (c_p && c_p_locks)
erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_MAIN);
}
@@ -755,7 +781,7 @@ delete_export_references(Eterm module)
}
-int
+Eterm
beam_make_current_old(Process *c_p, ErtsProcLocks c_p_locks, Eterm module)
{
Module* modp = erts_put_module(module);
@@ -766,15 +792,12 @@ beam_make_current_old(Process *c_p, ErtsProcLocks c_p_locks, Eterm module)
*/
if (modp->code != NULL && modp->old_code != NULL) {
- return -3;
+ return am_not_purged;
} else if (modp->old_code == NULL) { /* Make the current version old. */
- if (display_loads) {
- erts_printf("saving old code\n");
- }
delete_code(c_p, c_p_locks, modp);
delete_export_references(module);
}
- return 0;
+ return NIL;
}
static int
diff --git a/erts/emulator/beam/beam_bp.c b/erts/emulator/beam/beam_bp.c
index 31910888d1..dd31376a2d 100644
--- a/erts/emulator/beam/beam_bp.c
+++ b/erts/emulator/beam/beam_bp.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -167,7 +167,7 @@ erts_bp_init(void) {
int
erts_set_trace_break(Eterm mfa[3], int specified, Binary *match_spec,
Eterm tracer_pid) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
return set_break(mfa, specified, match_spec,
(BeamInstr) BeamOp(op_i_trace_breakpoint), 0, tracer_pid);
}
@@ -175,7 +175,7 @@ erts_set_trace_break(Eterm mfa[3], int specified, Binary *match_spec,
int
erts_set_mtrace_break(Eterm mfa[3], int specified, Binary *match_spec,
Eterm tracer_pid) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
return set_break(mfa, specified, match_spec,
(BeamInstr) BeamOp(op_i_mtrace_breakpoint), 0, tracer_pid);
}
@@ -184,7 +184,7 @@ erts_set_mtrace_break(Eterm mfa[3], int specified, Binary *match_spec,
void
erts_set_mtrace_bif(BeamInstr *pc, Binary *match_spec, Eterm tracer_pid) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
set_function_break(NULL, pc, BREAK_IS_BIF, match_spec, (BeamInstr) BeamOp(op_i_mtrace_breakpoint), 0, tracer_pid);
}
@@ -198,35 +198,35 @@ void erts_clear_time_trace_bif(BeamInstr *pc) {
int
erts_set_debug_break(Eterm mfa[3], int specified) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
return set_break(mfa, specified, NULL,
(BeamInstr) BeamOp(op_i_debug_breakpoint), 0, NIL);
}
int
erts_set_count_break(Eterm mfa[3], int specified, enum erts_break_op count_op) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
return set_break(mfa, specified, NULL,
(BeamInstr) BeamOp(op_i_count_breakpoint), count_op, NIL);
}
int
erts_set_time_break(Eterm mfa[3], int specified, enum erts_break_op count_op) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
return set_break(mfa, specified, NULL,
(BeamInstr) BeamOp(op_i_time_breakpoint), count_op, NIL);
}
int
erts_clear_trace_break(Eterm mfa[3], int specified) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
return clear_break(mfa, specified,
(BeamInstr) BeamOp(op_i_trace_breakpoint));
}
int
erts_clear_mtrace_break(Eterm mfa[3], int specified) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
return clear_break(mfa, specified,
(BeamInstr) BeamOp(op_i_mtrace_breakpoint));
}
@@ -238,41 +238,41 @@ erts_clear_mtrace_bif(BeamInstr *pc) {
int
erts_clear_debug_break(Eterm mfa[3], int specified) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
return clear_break(mfa, specified,
(BeamInstr) BeamOp(op_i_debug_breakpoint));
}
int
erts_clear_count_break(Eterm mfa[3], int specified) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
return clear_break(mfa, specified,
(BeamInstr) BeamOp(op_i_count_breakpoint));
}
int
erts_clear_time_break(Eterm mfa[3], int specified) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
return clear_break(mfa, specified,
(BeamInstr) BeamOp(op_i_time_breakpoint));
}
int
erts_clear_break(Eterm mfa[3], int specified) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
return clear_break(mfa, specified, 0);
}
int
erts_clear_module_break(Module *modp) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
ASSERT(modp);
return clear_module_break(modp, NULL, 0, 0);
}
int
erts_clear_function_break(Module *modp, BeamInstr *pc) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
ASSERT(modp);
return clear_function_break(modp, pc, BREAK_IS_ERL, 0);
}
@@ -408,7 +408,7 @@ erts_is_count_break(BeamInstr *pc, Sint *count_ret) {
if (bdc) {
if (count_ret) {
- *count_ret = (Sint) erts_smp_atomic_read(&bdc->acount);
+ *count_ret = (Sint) erts_smp_atomic_read_nob(&bdc->acount);
}
return !0;
}
@@ -612,9 +612,13 @@ static void bp_hash_delete(bp_time_hash_t *hash) {
static void bp_time_diff(bp_data_time_item_t *item, /* out */
process_breakpoint_time_t *pbt, /* in */
Uint ms, Uint s, Uint us) {
- int dms,ds,dus;
+ int ds,dus;
+#ifdef DEBUG
+ int dms;
+
dms = ms - pbt->ms;
+#endif
ds = s - pbt->s;
dus = us - pbt->us;
@@ -622,7 +626,9 @@ static void bp_time_diff(bp_data_time_item_t *item, /* out */
* this is ok.
*/
+#ifdef DEBUG
ASSERT(dms >= 0 || ds >= 0 || dus >= 0);
+#endif
if (dus < 0) {
dus += 1000000;
@@ -958,24 +964,24 @@ static int set_function_break(Module *modp, BeamInstr *pc, int bif,
if (break_op == (BeamInstr) BeamOp(op_i_count_breakpoint)) {
if (count_op == erts_break_stop) {
- count = erts_smp_atomic_read(&bdc->acount);
+ count = erts_smp_atomic_read_nob(&bdc->acount);
if (count >= 0) {
while(1) {
- res = erts_smp_atomic_cmpxchg(&bdc->acount, -count - 1, count);
+ res = erts_smp_atomic_cmpxchg_nob(&bdc->acount, -count - 1, count);
if ((res == count) || count < 0) break;
count = res;
}
}
} else {
/* Reset call counter */
- erts_smp_atomic_set(&bdc->acount, 0);
+ erts_smp_atomic_set_nob(&bdc->acount, 0);
}
} else if (break_op == (BeamInstr) BeamOp(op_i_time_breakpoint)) {
BpDataTime *bdt = (BpDataTime *) bd;
Uint i = 0;
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
if (count_op == erts_break_stop) {
bdt->pause = 1;
@@ -1097,7 +1103,7 @@ static int set_function_break(Module *modp, BeamInstr *pc, int bif,
}
} else if (break_op == (BeamInstr) BeamOp(op_i_count_breakpoint)) {
BpDataCount *bdc = (BpDataCount *) bd;
- erts_smp_atomic_init(&bdc->acount, 0);
+ erts_smp_atomic_init_nob(&bdc->acount, 0);
}
if (bif == BREAK_IS_ERL) {
diff --git a/erts/emulator/beam/beam_bp.h b/erts/emulator/beam/beam_bp.h
index bd8a7249a7..2ec5818688 100644
--- a/erts/emulator/beam/beam_bp.h
+++ b/erts/emulator/beam/beam_bp.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -165,8 +165,8 @@ do { \
bdc = (BpDataCount *) bdc->next; \
ASSERT(bdc); \
bds[ix] = (BpData *) bdc; \
- count = erts_smp_atomic_read(&bdc->acount); \
- if (count >= 0) erts_smp_atomic_inc(&bdc->acount); \
+ count = erts_smp_atomic_read_nob(&bdc->acount); \
+ if (count >= 0) erts_smp_atomic_inc_nob(&bdc->acount); \
*(instr_result) = bdc->orig_instr; \
} while (0)
diff --git a/erts/emulator/beam/beam_catches.c b/erts/emulator/beam/beam_catches.c
index e795b4efbd..a550ec5ad0 100644
--- a/erts/emulator/beam/beam_catches.c
+++ b/erts/emulator/beam/beam_catches.c
@@ -22,21 +22,27 @@
#endif
#include "sys.h"
#include "beam_catches.h"
+#include "global.h"
-/* XXX: should use dynamic reallocation */
-#define TABSIZ (16*1024)
-static struct {
+/* R14B04 has about 380 catches when starting erlang */
+#define DEFAULT_TABSIZE (1024)
+typedef struct {
BeamInstr *cp;
unsigned cdr;
-} beam_catches[TABSIZ];
+} beam_catch_t;
static int free_list;
static unsigned high_mark;
+static unsigned tabsize;
+static beam_catch_t *beam_catches;
void beam_catches_init(void)
{
+ tabsize = DEFAULT_TABSIZE;
free_list = -1;
high_mark = 0;
+
+ beam_catches = erts_alloc(ERTS_ALC_T_CODE, sizeof(beam_catch_t)*DEFAULT_TABSIZE);
}
unsigned beam_catches_cons(BeamInstr *cp, unsigned cdr)
@@ -50,16 +56,21 @@ unsigned beam_catches_cons(BeamInstr *cp, unsigned cdr)
* This avoids the need to initialise the free list in
* beam_catches_init(), which would cost O(TABSIZ) time.
*/
- if( (i = free_list) >= 0 ) {
+ if( free_list >= 0 ) {
+ i = free_list;
free_list = beam_catches[i].cdr;
- } else if( (i = high_mark) < TABSIZ ) {
- high_mark = i + 1;
+ } else if( high_mark < tabsize ) {
+ i = high_mark;
+ high_mark++;
} else {
- fprintf(stderr, "beam_catches_cons: no free slots :-(\r\n");
- exit(1);
+ /* No free slots and table is full: realloc table */
+ tabsize = 2*tabsize;
+ beam_catches = erts_realloc(ERTS_ALC_T_CODE, beam_catches, sizeof(beam_catch_t)*tabsize);
+ i = high_mark;
+ high_mark++;
}
- beam_catches[i].cp = cp;
+ beam_catches[i].cp = cp;
beam_catches[i].cdr = cdr;
return i;
@@ -67,10 +78,8 @@ unsigned beam_catches_cons(BeamInstr *cp, unsigned cdr)
BeamInstr *beam_catches_car(unsigned i)
{
- if( i >= TABSIZ ) {
- fprintf(stderr,
- "beam_catches_car: index %#x is out of range\r\n", i);
- abort();
+ if( i >= tabsize ) {
+ erl_exit(1, "beam_catches_delmod: index %#x is out of range\r\n", i);
}
return beam_catches[i].cp;
}
@@ -80,18 +89,15 @@ void beam_catches_delmod(unsigned head, BeamInstr *code, unsigned code_bytes)
unsigned i, cdr;
for(i = head; i != (unsigned)-1;) {
- if( i >= TABSIZ ) {
- fprintf(stderr,
- "beam_catches_delmod: index %#x is out of range\r\n", i);
- abort();
+ if( i >= tabsize ) {
+ erl_exit(1, "beam_catches_delmod: index %#x is out of range\r\n", i);
}
if( (char*)beam_catches[i].cp - (char*)code >= code_bytes ) {
- fprintf(stderr,
+ erl_exit(1,
"beam_catches_delmod: item %#x has cp %#lx which is not "
"in module's range [%#lx,%#lx[\r\n",
i, (long)beam_catches[i].cp,
(long)code, (long)((char*)code + code_bytes));
- abort();
}
beam_catches[i].cp = 0;
cdr = beam_catches[i].cdr;
diff --git a/erts/emulator/beam/beam_debug.c b/erts/emulator/beam/beam_debug.c
index fffb172c68..8041c92162 100644
--- a/erts/emulator/beam/beam_debug.c
+++ b/erts/emulator/beam/beam_debug.c
@@ -37,6 +37,7 @@
#include "beam_load.h"
#include "beam_bp.h"
#include "erl_binary.h"
+#include "erl_thr_progress.h"
#ifdef ARCH_64
# define HEXF "%016bpX"
@@ -49,15 +50,18 @@ void dbg_bt(Process* p, Eterm* sp);
void dbg_where(BeamInstr* addr, Eterm x0, Eterm* reg);
static int print_op(int to, void *to_arg, int op, int size, BeamInstr* addr);
-Eterm
-erts_debug_same_2(Process* p, Eterm term1, Eterm term2)
+
+BIF_RETTYPE
+erts_debug_same_2(BIF_ALIST_2)
{
- return (term1 == term2) ? am_true : am_false;
+ return (BIF_ARG_1 == BIF_ARG_2) ? am_true : am_false;
}
-Eterm
-erts_debug_flat_size_1(Process* p, Eterm term)
+BIF_RETTYPE
+erts_debug_flat_size_1(BIF_ALIST_1)
{
+ Process* p = BIF_P;
+ Eterm term = BIF_ARG_1;
Uint size = size_object(term);
if (IS_USMALL(0, size)) {
@@ -68,9 +72,13 @@ erts_debug_flat_size_1(Process* p, Eterm term)
}
}
-Eterm
-erts_debug_breakpoint_2(Process* p, Eterm MFA, Eterm bool)
+
+BIF_RETTYPE
+erts_debug_breakpoint_2(BIF_ALIST_2)
{
+ Process* p = BIF_P;
+ Eterm MFA = BIF_ARG_1;
+ Eterm bool = BIF_ARG_2;
Eterm* tp;
Eterm mfa[3];
int i;
@@ -107,7 +115,7 @@ erts_debug_breakpoint_2(Process* p, Eterm MFA, Eterm bool)
}
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
if (bool == am_true) {
res = make_small(erts_set_debug_break(mfa, specified));
@@ -115,7 +123,7 @@ erts_debug_breakpoint_2(Process* p, Eterm MFA, Eterm bool)
res = make_small(erts_clear_debug_break(mfa, specified));
}
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
return res;
@@ -175,9 +183,11 @@ erts_debug_instructions_0(BIF_ALIST_0)
return res;
}
-Eterm
-erts_debug_disassemble_1(Process* p, Eterm addr)
+BIF_RETTYPE
+erts_debug_disassemble_1(BIF_ALIST_1)
{
+ Process* p = BIF_P;
+ Eterm addr = BIF_ARG_1;
erts_dsprintf_buf_t *dsbufp;
Eterm* hp;
Eterm* tp;
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index fb90a7d4f7..9c5450bd48 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -36,6 +36,7 @@
#include "dist.h"
#include "beam_bp.h"
#include "beam_catches.h"
+#include "erl_thr_progress.h"
#ifdef HIPE
#include "hipe_mode_switch.h"
#include "hipe_bif1.h"
@@ -70,7 +71,7 @@ do { \
} \
else \
erts_lc_check_exact(NULL, 0); \
- ERTS_SMP_LC_ASSERT(!ERTS_LC_IS_BLOCKING); \
+ ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking()); \
} while (0)
# define ERTS_SMP_REQ_PROC_MAIN_LOCK(P) \
if ((P)) erts_proc_lc_require_lock((P), ERTS_PROC_LOCK_MAIN)
@@ -303,44 +304,6 @@ extern int count_instructions;
PROCESS_MAIN_CHK_LOCKS((P)); \
ERTS_SMP_UNREQ_PROC_MAIN_LOCK((P))
-#if defined(HYBRID)
-# define POST_BIF_GC_SWAPIN_0(_p, _res) \
- if (((_p)->mbuf) || (MSO(_p).overhead >= BIN_VHEAP_SZ(_p)) ) { \
- _res = erts_gc_after_bif_call((_p), (_res), NULL, 0); \
- } \
- SWAPIN
-
-# define POST_BIF_GC_SWAPIN(_p, _res, _regs, _arity) \
- if (((_p)->mbuf) || (MSO(_p).overhead >= BIN_VHEAP_SZ(_p)) ) { \
- _regs[0] = r(0); \
- _res = erts_gc_after_bif_call((_p), (_res), _regs, (_arity)); \
- r(0) = _regs[0]; \
- } \
- SWAPIN
-#else
-# define POST_BIF_GC_SWAPIN_0(_p, _res) \
- ERTS_SMP_REQ_PROC_MAIN_LOCK((_p)); \
- PROCESS_MAIN_CHK_LOCKS((_p)); \
- ERTS_VERIFY_UNUSED_TEMP_ALLOC((_p)); \
- if (((_p)->mbuf) || (MSO(_p).overhead >= BIN_VHEAP_SZ(_p)) ) { \
- _res = erts_gc_after_bif_call((_p), (_res), NULL, 0); \
- E = (_p)->stop; \
- } \
- HTOP = HEAP_TOP((_p))
-
-# define POST_BIF_GC_SWAPIN(_p, _res, _regs, _arity) \
- ERTS_VERIFY_UNUSED_TEMP_ALLOC((_p)); \
- ERTS_SMP_REQ_PROC_MAIN_LOCK((_p)); \
- PROCESS_MAIN_CHK_LOCKS((_p)); \
- if (((_p)->mbuf) || (MSO(_p).overhead >= BIN_VHEAP_SZ(_p)) ) { \
- _regs[0] = r(0); \
- _res = erts_gc_after_bif_call((_p), (_res), _regs, (_arity)); \
- r(0) = _regs[0]; \
- E = (_p)->stop; \
- } \
- HTOP = HEAP_TOP((_p))
-#endif
-
#define db(N) (N)
#define tb(N) (N)
#define xb(N) (*(Eterm *) (((unsigned char *)reg) + (N)))
@@ -794,11 +757,11 @@ extern int count_instructions;
} \
} while (0)
-#define IsFunction2(F, A, Action) \
- do { \
- if (is_function_2(c_p, F, A) != am_true ) {\
- Action; \
- } \
+#define IsFunction2(F, A, Action) \
+ do { \
+ if (erl_is_function(c_p, F, A) != am_true ) { \
+ Action; \
+ } \
} while (0)
#define IsTupleOfArity(Src, Arity, Fail) \
@@ -1145,26 +1108,11 @@ void process_main(void)
Eterm *tmp_big; /* Temporary buffer for small bignums if !HEAP_ON_C_STACK. */
#endif
-#ifndef ERTS_SMP
-#if !HALFWORD_HEAP
- static Eterm save_reg[ERTS_X_REGS_ALLOCATED];
- /* X registers -- not used directly, but
- * through 'reg', because using it directly
- * needs two instructions on a SPARC,
- * while using it through reg needs only
- * one.
- */
-#endif
/*
- * Floating point registers.
- */
- static FloatDef freg[MAX_REG];
-#else
- /* X regisers and floating point registers are located in
+ * X registers and floating point registers are located in
* scheduler specific data.
*/
register FloatDef *freg;
-#endif
/*
* For keeping the negative old value of 'reds' when call saving is active.
@@ -1201,14 +1149,6 @@ void process_main(void)
init_done = 1;
goto init_emulator;
}
-#ifndef ERTS_SMP
-#if !HALFWORD_HEAP
- reg = save_reg; /* XXX: probably wastes a register on x86 */
-#else
- /* Registers need to be heap allocated (correct memory range) for tracing to work */
- reg = erts_alloc(ERTS_ALC_T_BEAM_REGISTER, ERTS_X_REGS_ALLOCATED * sizeof(Eterm));
-#endif
-#endif
c_p = NULL;
reds_used = 0;
goto do_schedule1;
@@ -1229,10 +1169,8 @@ void process_main(void)
#endif
ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p);
PROCESS_MAIN_CHK_LOCKS(c_p);
-#ifdef ERTS_SMP
- reg = c_p->scheduler_data->save_reg;
- freg = c_p->scheduler_data->freg;
-#endif
+ reg = ERTS_PROC_GET_SCHDATA(c_p)->x_reg_array;
+ freg = ERTS_PROC_GET_SCHDATA(c_p)->f_reg_array;
#if !HEAP_ON_C_STACK
tmp_big = ERTS_PROC_GET_SCHDATA(c_p)->beam_emu_tmp_heap;
#endif
@@ -1566,9 +1504,17 @@ void process_main(void)
PRE_BIF_SWAPOUT(c_p);
c_p->fcalls = FCALLS - 1;
- result = send_2(c_p, r(0), x(1));
+ reg[0] = r(0);
+ result = erl_send(c_p, r(0), x(1));
PreFetch(0, next);
- POST_BIF_GC_SWAPIN(c_p, result, reg, 2);
+ ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p);
+ PROCESS_MAIN_CHK_LOCKS(c_p);
+ if (c_p->mbuf || MSO(c_p).overhead >= BIN_VHEAP_SZ(c_p)) {
+ result = erts_gc_after_bif_call(c_p, result, reg, 2);
+ r(0) = reg[0];
+ E = c_p->stop;
+ }
+ HTOP = HEAP_TOP(c_p);
FCALLS = c_p->fcalls;
if (is_value(result)) {
r(0) = result;
@@ -1576,10 +1522,9 @@ void process_main(void)
NextPF(0, next);
} else if (c_p->freason == TRAP) {
SET_CP(c_p, I+1);
- SET_I(*((BeamInstr **) (BeamInstr) ((c_p)->def_arg_reg + 3)));
+ SET_I(c_p->i);
SWAPIN;
- r(0) = c_p->def_arg_reg[0];
- x(1) = c_p->def_arg_reg[1];
+ r(0) = reg[0];
Dispatch();
}
goto find_func_info;
@@ -2234,16 +2179,16 @@ void process_main(void)
OpCase(bif1_fbsd):
{
- Eterm (*bf)(Process*, Eterm);
- Eterm arg;
+ Eterm (*bf)(Process*, Eterm*);
+ Eterm tmp_reg[1];
Eterm result;
- GetArg1(2, arg);
+ GetArg1(2, tmp_reg[0]);
bf = (BifFunction) Arg(1);
c_p->fcalls = FCALLS;
PROCESS_MAIN_CHK_LOCKS(c_p);
ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- result = (*bf)(c_p, arg);
+ result = (*bf)(c_p, tmp_reg);
ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(result));
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
PROCESS_MAIN_CHK_LOCKS(c_p);
@@ -2262,17 +2207,17 @@ void process_main(void)
OpCase(bif1_body_bsd):
{
- Eterm (*bf)(Process*, Eterm);
+ Eterm (*bf)(Process*, Eterm*);
- Eterm arg;
+ Eterm tmp_reg[1];
Eterm result;
- GetArg1(1, arg);
+ GetArg1(1, tmp_reg[0]);
bf = (BifFunction) Arg(0);
c_p->fcalls = FCALLS;
PROCESS_MAIN_CHK_LOCKS(c_p);
ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- result = (*bf)(c_p, arg);
+ result = (*bf)(c_p, tmp_reg);
ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(result));
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
PROCESS_MAIN_CHK_LOCKS(c_p);
@@ -2281,7 +2226,7 @@ void process_main(void)
if (is_value(result)) {
StoreBifResult(2, result);
}
- reg[0] = arg;
+ reg[0] = tmp_reg[0];
SWAPOUT;
I = handle_error(c_p, I, reg, bf);
goto post_error_handling;
@@ -2405,14 +2350,15 @@ void process_main(void)
*/
OpCase(i_bif2_fbd):
{
- Eterm (*bf)(Process*, Eterm, Eterm);
+ Eterm tmp_reg[2] = {tmp_arg1, tmp_arg2};
+ Eterm (*bf)(Process*, Eterm*);
Eterm result;
bf = (BifFunction) Arg(1);
c_p->fcalls = FCALLS;
PROCESS_MAIN_CHK_LOCKS(c_p);
ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- result = (*bf)(c_p, tmp_arg1, tmp_arg2);
+ result = (*bf)(c_p, tmp_reg);
ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(result));
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
PROCESS_MAIN_CHK_LOCKS(c_p);
@@ -2430,13 +2376,14 @@ void process_main(void)
*/
OpCase(i_bif2_body_bd):
{
- Eterm (*bf)(Process*, Eterm, Eterm);
+ Eterm tmp_reg[2] = {tmp_arg1, tmp_arg2};
+ Eterm (*bf)(Process*, Eterm*);
Eterm result;
bf = (BifFunction) Arg(0);
PROCESS_MAIN_CHK_LOCKS(c_p);
ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- result = (*bf)(c_p, tmp_arg1, tmp_arg2);
+ result = (*bf)(c_p, tmp_reg);
ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(result));
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
PROCESS_MAIN_CHK_LOCKS(c_p);
@@ -2456,77 +2403,9 @@ void process_main(void)
* The most general BIF call. The BIF may build any amount of data
* on the heap. The result is always returned in r(0).
*/
- OpCase(call_bif0_e):
- {
- Eterm (*bf)(Process*, BeamInstr*) = GET_BIF_ADDRESS(Arg(0));
-
- PRE_BIF_SWAPOUT(c_p);
- c_p->fcalls = FCALLS - 1;
- if (FCALLS <= 0) {
- save_calls(c_p, (Export *) Arg(0));
- }
-
- ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- r(0) = (*bf)(c_p, I);
- ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(r(0)));
- ERTS_HOLE_CHECK(c_p);
- POST_BIF_GC_SWAPIN_0(c_p, r(0));
- FCALLS = c_p->fcalls;
- if (is_value(r(0))) {
- CHECK_TERM(r(0));
- Next(1);
- }
- else if (c_p->freason == TRAP) {
- goto call_bif_trap3;
- }
-
- /*
- * Error handling. SWAPOUT is not needed because it was done above.
- */
- ASSERT(c_p->stop == E);
- reg[0] = r(0);
- I = handle_error(c_p, I, reg, bf);
- goto post_error_handling;
- }
-
- OpCase(call_bif1_e):
- {
- Eterm (*bf)(Process*, Eterm, BeamInstr*) = GET_BIF_ADDRESS(Arg(0));
- Eterm result;
- BeamInstr *next;
-
- c_p->fcalls = FCALLS - 1;
- if (FCALLS <= 0) {
- save_calls(c_p, (Export *) Arg(0));
- }
- PreFetch(1, next);
- PRE_BIF_SWAPOUT(c_p);
- ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- result = (*bf)(c_p, r(0), I);
- ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(result));
- ERTS_HOLE_CHECK(c_p);
- POST_BIF_GC_SWAPIN(c_p, result, reg, 1);
- FCALLS = c_p->fcalls;
- if (is_value(result)) {
- r(0) = result;
- CHECK_TERM(r(0));
- NextPF(1, next);
- } else if (c_p->freason == TRAP) {
- goto call_bif_trap3;
- }
-
- /*
- * Error handling. SWAPOUT is not needed because it was done above.
- */
- ASSERT(c_p->stop == E);
- reg[0] = r(0);
- I = handle_error(c_p, I, reg, bf);
- goto post_error_handling;
- }
-
- OpCase(call_bif2_e):
+ OpCase(call_bif_e):
{
- Eterm (*bf)(Process*, Eterm, Eterm, BeamInstr*) = GET_BIF_ADDRESS(Arg(0));
+ Eterm (*bf)(Process*, Eterm*, BeamInstr*) = GET_BIF_ADDRESS(Arg(0));
Eterm result;
BeamInstr *next;
@@ -2536,61 +2415,29 @@ void process_main(void)
save_calls(c_p, (Export *) Arg(0));
}
PreFetch(1, next);
- CHECK_TERM(r(0));
- CHECK_TERM(x(1));
ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- result = (*bf)(c_p, r(0), x(1), I);
- ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(result));
- ERTS_HOLE_CHECK(c_p);
- POST_BIF_GC_SWAPIN(c_p, result, reg, 2);
- FCALLS = c_p->fcalls;
- if (is_value(result)) {
- r(0) = result;
- CHECK_TERM(r(0));
- NextPF(1, next);
- } else if (c_p->freason == TRAP) {
- goto call_bif_trap3;
- }
-
- /*
- * Error handling. SWAPOUT is not needed because it was done above.
- */
- ASSERT(c_p->stop == E);
reg[0] = r(0);
- I = handle_error(c_p, I, reg, bf);
- goto post_error_handling;
- }
-
- OpCase(call_bif3_e):
- {
- Eterm (*bf)(Process*, Eterm, Eterm, Eterm, BeamInstr*) = GET_BIF_ADDRESS(Arg(0));
- Eterm result;
- BeamInstr *next;
-
- PRE_BIF_SWAPOUT(c_p);
- c_p->fcalls = FCALLS - 1;
- if (FCALLS <= 0) {
- save_calls(c_p, (Export *) Arg(0));
- }
- PreFetch(1, next);
- ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- result = (*bf)(c_p, r(0), x(1), x(2), I);
+ result = (*bf)(c_p, reg, I);
ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(result));
ERTS_HOLE_CHECK(c_p);
- POST_BIF_GC_SWAPIN(c_p, result, reg, 3);
+ ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p);
+ PROCESS_MAIN_CHK_LOCKS(c_p);
+ if (c_p->mbuf || MSO(c_p).overhead >= BIN_VHEAP_SZ(c_p)) {
+ Uint arity = ((Export *)Arg(0))->code[2];
+ result = erts_gc_after_bif_call(c_p, result, reg, arity);
+ E = c_p->stop;
+ }
+ HTOP = HEAP_TOP(c_p);
FCALLS = c_p->fcalls;
if (is_value(result)) {
r(0) = result;
CHECK_TERM(r(0));
NextPF(1, next);
} else if (c_p->freason == TRAP) {
- call_bif_trap3:
SET_CP(c_p, I+2);
- SET_I(*((BeamInstr **) (UWord) ((c_p)->def_arg_reg + 3)));
+ SET_I(c_p->i);
SWAPIN;
- r(0) = c_p->def_arg_reg[0];
- x(1) = c_p->def_arg_reg[1];
- x(2) = c_p->def_arg_reg[2];
+ r(0) = reg[0];
Dispatch();
}
@@ -2598,7 +2445,6 @@ void process_main(void)
* Error handling. SWAPOUT is not needed because it was done above.
*/
ASSERT(c_p->stop == E);
- reg[0] = r(0);
I = handle_error(c_p, I, reg, bf);
goto post_error_handling;
}
@@ -3351,64 +3197,23 @@ void process_main(void)
ASSERT(bif_nif_arity <= 3);
ERTS_SMP_UNREQ_PROC_MAIN_LOCK(c_p);
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
- switch (bif_nif_arity) {
- case 3:
- {
- Eterm (*bf)(Process*, Eterm, Eterm, Eterm, BeamInstr*) = vbf;
- ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- nif_bif_result = (*bf)(c_p, r(0), x(1), x(2), I);
- ASSERT(!ERTS_PROC_IS_EXITING(c_p) ||
- is_non_value(nif_bif_result));
- ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
- PROCESS_MAIN_CHK_LOCKS(c_p);
- }
- break;
- case 2:
- {
- Eterm (*bf)(Process*, Eterm, Eterm, BeamInstr*) = vbf;
- ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- nif_bif_result = (*bf)(c_p, r(0), x(1), I);
- ASSERT(!ERTS_PROC_IS_EXITING(c_p) ||
- is_non_value(nif_bif_result));
- ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
- PROCESS_MAIN_CHK_LOCKS(c_p);
- }
- break;
- case 1:
- {
- Eterm (*bf)(Process*, Eterm, BeamInstr*) = vbf;
- ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- nif_bif_result = (*bf)(c_p, r(0), I);
- ASSERT(!ERTS_PROC_IS_EXITING(c_p) ||
- is_non_value(nif_bif_result));
- ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
- PROCESS_MAIN_CHK_LOCKS(c_p);
- }
- break;
- case 0:
- {
- Eterm (*bf)(Process*, BeamInstr*) = vbf;
- ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- nif_bif_result = (*bf)(c_p, I);
- ASSERT(!ERTS_PROC_IS_EXITING(c_p) ||
- is_non_value(nif_bif_result));
- ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
- PROCESS_MAIN_CHK_LOCKS(c_p);
- break;
- }
- default:
- erl_exit(1, "apply_bif: invalid arity: %u\n",
- bif_nif_arity);
+ reg[0] = r(0);
+ {
+ Eterm (*bf)(Process*, Eterm*, BeamInstr*) = vbf;
+ ASSERT(!ERTS_PROC_IS_EXITING(c_p));
+ nif_bif_result = (*bf)(c_p, reg, I);
+ ASSERT(!ERTS_PROC_IS_EXITING(c_p) ||
+ is_non_value(nif_bif_result));
+ ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
+ PROCESS_MAIN_CHK_LOCKS(c_p);
}
apply_bif_or_nif_epilogue:
ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p);
ERTS_HOLE_CHECK(c_p);
if (c_p->mbuf) {
- reg[0] = r(0);
nif_bif_result = erts_gc_after_bif_call(c_p, nif_bif_result,
reg, bif_nif_arity);
- r(0) = reg[0];
}
SWAPIN; /* There might have been a garbage collection. */
FCALLS = c_p->fcalls;
@@ -3419,17 +3224,14 @@ void process_main(void)
c_p->cp = 0;
Goto(*I);
} else if (c_p->freason == TRAP) {
- SET_I(*((BeamInstr **) (UWord) ((c_p)->def_arg_reg + 3)));
- r(0) = c_p->def_arg_reg[0];
- x(1) = c_p->def_arg_reg[1];
- x(2) = c_p->def_arg_reg[2];
+ SET_I(c_p->i);
+ r(0) = reg[0];
if (c_p->flags & F_HIBERNATE_SCHED) {
c_p->flags &= ~F_HIBERNATE_SCHED;
goto do_schedule;
}
Dispatch();
}
- reg[0] = r(0);
I = handle_error(c_p, c_p->cp, reg, vbf);
goto post_error_handling;
}
@@ -3561,7 +3363,7 @@ void process_main(void)
* Operands: NotUsed Live Dst
*/
do_bs_init_bits_known:
- num_bytes = (num_bits+7) >> 3;
+ num_bytes = ((Uint64)num_bits+(Uint64)7) >> 3;
if (num_bits & 7) {
alloc += ERL_SUB_BIN_SIZE;
}
@@ -3992,8 +3794,7 @@ void process_main(void)
* too big numbers).
*/
if (is_not_small(val) || val > make_small(0x10FFFFUL) ||
- (make_small(0xD800UL) <= val && val <= make_small(0xDFFFUL)) ||
- val == make_small(0xFFFEUL) || val == make_small(0xFFFFUL)) {
+ (make_small(0xD800UL) <= val && val <= make_small(0xDFFFUL))) {
goto badarg;
}
Next(2);
@@ -4012,8 +3813,8 @@ void process_main(void)
* the valid range).
*/
if (is_not_small(tmp_arg1) || tmp_arg1 > make_small(0x10FFFFUL) ||
- (make_small(0xD800UL) <= tmp_arg1 && tmp_arg1 <= make_small(0xDFFFUL)) ||
- tmp_arg1 == make_small(0xFFFEUL) || tmp_arg1 == make_small(0xFFFFUL)) {
+ (make_small(0xD800UL) <= tmp_arg1 &&
+ tmp_arg1 <= make_small(0xDFFFUL))) {
ErlBinMatchBuffer *mb = ms_matchbuffer(tmp_arg2);
mb->offset -= 32;
@@ -4888,92 +4689,6 @@ void process_main(void)
}
/*
- * Instructions for allocating on the message area.
- */
-
- OpCase(i_global_cons):
- {
- BeamInstr *next;
-#ifdef HYBRID
- Eterm *hp;
-
- PreFetch(0,next);
- TestGlobalHeap(2,2,hp);
- hp[0] = r(0);
- hp[1] = x(1);
- r(0) = make_list(hp);
-#ifndef INCREMENTAL
- global_htop += 2;
-#endif
- NextPF(0,next);
-#else
- PreFetch(0,next);
- c_p->freason = EXC_INTERNAL_ERROR;
- goto find_func_info;
-#endif
- }
-
- OpCase(i_global_tuple):
- {
- BeamInstr *next;
- int len;
-#ifdef HYBRID
- Eterm list;
- Eterm *hp;
-#endif
-
- if ((len = list_length(r(0))) < 0) {
- goto badarg;
- }
-
- PreFetch(0,next);
-#ifdef HYBRID
- TestGlobalHeap(len + 1,1,hp);
- list = r(0);
- r(0) = make_tuple(hp);
- *hp++ = make_arityval(len);
- while(is_list(list))
- {
- Eterm* cons = list_val(list);
- *hp++ = CAR(cons);
- list = CDR(cons);
- }
-#ifndef INCREMENTAL
- global_htop += len + 1;
-#endif
- NextPF(0,next);
-#else
- c_p->freason = EXC_INTERNAL_ERROR;
- goto find_func_info;
-#endif
- }
-
- OpCase(i_global_copy):
- {
- BeamInstr *next;
- PreFetch(0,next);
-#ifdef HYBRID
- if (!IS_CONST(r(0)))
- {
- BM_SWAP_TIMER(system,copy);
- SWAPOUT;
- reg[0] = r(0);
- reg[1] = NIL;
- r(0) = copy_struct_lazy(c_p,r(0),0);
- ASSERT(ma_src_top == 0);
- ASSERT(ma_dst_top == 0);
- ASSERT(ma_offset_top == 0);
- SWAPIN;
- BM_SWAP_TIMER(copy,system);
- }
- NextPF(0,next);
-#else
- c_p->freason = EXC_INTERNAL_ERROR;
- goto find_func_info;
-#endif
- }
-
- /*
* New floating point instructions.
*/
@@ -5151,10 +4866,8 @@ void process_main(void)
c_p->def_arg_reg[4] = -neg_o_reds;
reg[0] = r(0);
c_p = hipe_mode_switch(c_p, cmd, reg);
-#ifdef ERTS_SMP
- reg = c_p->scheduler_data->save_reg;
- freg = c_p->scheduler_data->freg;
-#endif
+ reg = ERTS_PROC_GET_SCHDATA(c_p)->x_reg_array;
+ freg = ERTS_PROC_GET_SCHDATA(c_p)->f_reg_array;
ERL_BITS_RELOAD_STATEP(c_p);
neg_o_reds = -c_p->def_arg_reg[4];
FCALLS = c_p->fcalls;
@@ -5268,8 +4981,8 @@ void process_main(void)
OpCase(int_code_end):
OpCase(label_L):
- OpCase(too_old_compiler):
OpCase(on_load):
+ OpCase(line_I):
erl_exit(1, "meta op\n");
/*
@@ -5686,6 +5399,25 @@ expand_error_value(Process* c_p, Uint freason, Eterm Value) {
* that c_p->ftrace will point to a cons cell which holds the given args
* and the saved data (encoded as a bignum).
*
+ * There is an issue with line number information. Line number
+ * information is associated with the address *before* an operation
+ * that may fail or be stored stored on the stack. But continuation
+ * pointers point after its call instruction, not before. To avoid
+ * finding the wrong line number, we'll need to adjust them so that
+ * they point at the beginning of the call instruction or inside the
+ * call instruction. Since its impractical to point at the beginning,
+ * we'll do the simplest thing and decrement the continuation pointers
+ * by one.
+ *
+ * Here is an example of what can go wrong. Without the adjustment
+ * of continuation pointers, the call at line 42 below would seem to
+ * be at line 43:
+ *
+ * line 42
+ * call ...
+ * line 43
+ * gc_bif ...
+ *
* (It would be much better to put the arglist - when it exists - in the
* error value instead of in the actual trace; e.g. '{badarg, Args}'
* instead of using 'badarg' with Args in the trace. The arglist may
@@ -5752,7 +5484,7 @@ save_stacktrace(Process* c_p, BeamInstr* pc, Eterm* reg, BifFunction bf,
}
/* Save second stack entry if CP is valid and different from pc */
if (depth > 0 && c_p->cp != 0 && c_p->cp != pc) {
- s->trace[s->depth++] = c_p->cp;
+ s->trace[s->depth++] = c_p->cp - 1;
depth--;
}
s->pc = NULL;
@@ -5772,13 +5504,13 @@ save_stacktrace(Process* c_p, BeamInstr* pc, Eterm* reg, BifFunction bf,
/* Save first stack entry */
ASSERT(c_p->cp);
if (depth > 0) {
- s->trace[s->depth++] = c_p->cp;
+ s->trace[s->depth++] = c_p->cp - 1;
depth--;
}
s->pc = NULL; /* Ignore pc */
} else {
if (depth > 0 && c_p->cp != 0 && c_p->cp != pc) {
- s->trace[s->depth++] = c_p->cp;
+ s->trace[s->depth++] = c_p->cp - 1;
depth--;
}
s->pc = pc;
@@ -5793,24 +5525,31 @@ save_stacktrace(Process* c_p, BeamInstr* pc, Eterm* reg, BifFunction bf,
}
/* Save the actual stack trace */
+ erts_save_stacktrace(c_p, s, depth);
+}
+
+void
+erts_save_stacktrace(Process* p, struct StackTrace* s, int depth)
+{
if (depth > 0) {
Eterm *ptr;
BeamInstr *prev = s->depth ? s->trace[s->depth-1] : NULL;
BeamInstr i_return_trace = beam_return_trace[0];
BeamInstr i_return_to_trace = beam_return_to_trace[0];
+
/*
* Traverse the stack backwards and add all unique continuation
* pointers to the buffer, up to the maximum stack trace size.
*
* Skip trace stack frames.
*/
- ptr = c_p->stop;
- if (ptr < STACK_START(c_p)
- && (is_not_CP(*ptr)|| (*cp_val(*ptr) != i_return_trace &&
- *cp_val(*ptr) != i_return_to_trace))
- && c_p->cp) {
- /* Can not follow cp here - code may be unloaded */
- BeamInstr *cpp = c_p->cp;
+ ptr = p->stop;
+ if (ptr < STACK_START(p) &&
+ (is_not_CP(*ptr)|| (*cp_val(*ptr) != i_return_trace &&
+ *cp_val(*ptr) != i_return_to_trace)) &&
+ p->cp) {
+ /* Cannot follow cp here - code may be unloaded */
+ BeamInstr *cpp = p->cp;
if (cpp == beam_exception_trace || cpp == beam_return_trace) {
/* Skip return_trace parameters */
ptr += 2;
@@ -5819,7 +5558,7 @@ save_stacktrace(Process* c_p, BeamInstr* pc, Eterm* reg, BifFunction bf,
ptr += 1;
}
}
- while (ptr < STACK_START(c_p) && depth > 0) {
+ while (ptr < STACK_START(p) && depth > 0) {
if (is_CP(*ptr)) {
if (*cp_val(*ptr) == i_return_trace) {
/* Skip stack frame variables */
@@ -5834,7 +5573,7 @@ save_stacktrace(Process* c_p, BeamInstr* pc, Eterm* reg, BifFunction bf,
if (cp != prev) {
/* Record non-duplicates only */
prev = cp;
- s->trace[s->depth++] = cp;
+ s->trace[s->depth++] = cp - 1;
depth--;
}
ptr++;
@@ -5902,9 +5641,14 @@ build_stacktrace(Process* c_p, Eterm exc) {
struct StackTrace* s;
Eterm args;
int depth;
- BeamInstr* current;
- Eterm Where = NIL;
- Eterm *next_p = &Where;
+ FunctionInfo fi;
+ FunctionInfo* stk;
+ FunctionInfo* stkp;
+ Eterm res = NIL;
+ Uint heap_size;
+ Eterm* hp;
+ Eterm mfa;
+ int i;
if (! (s = get_trace_from_exc(exc))) {
return NIL;
@@ -5923,64 +5667,56 @@ build_stacktrace(Process* c_p, Eterm exc) {
* saved s->current should already contain the proper value.
*/
if (s->pc != NULL) {
- current = find_function_from_pc(s->pc);
+ erts_lookup_function_info(&fi, s->pc, 1);
+ } else if (GET_EXC_INDEX(s->freason) ==
+ GET_EXC_INDEX(EXC_FUNCTION_CLAUSE)) {
+ erts_lookup_function_info(&fi, s->current, 1);
} else {
- current = s->current;
+ erts_set_current_function(&fi, s->current);
}
+
/*
- * If current is still NULL, default to the initial function
+ * If fi.current is still NULL, default to the initial function
* (e.g. spawn_link(erlang, abs, [1])).
*/
- if (current == NULL) {
- current = c_p->initial;
+ if (fi.current == NULL) {
+ erts_set_current_function(&fi, c_p->initial);
args = am_true; /* Just in case */
} else {
args = get_args_from_exc(exc);
}
- depth = s->depth;
-
/*
- * Add the {M,F,A} for the current function
- * (where A is arity or [Argument]).
+ * Look up all saved continuation pointers and calculate
+ * needed heap space.
*/
- {
- int i;
- Eterm mfa;
- Uint heap_size = 6*(depth+1);
- Eterm* hp = HAlloc(c_p, heap_size);
- Eterm* hp_end = hp + heap_size;
-
- if (args != am_true) {
- /* We have an arglist - use it */
- mfa = TUPLE3(hp, current[0], current[1], args);
- } else {
- Eterm arity = make_small(current[2]);
- mfa = TUPLE3(hp, current[0], current[1], arity);
+ depth = s->depth;
+ stk = stkp = (FunctionInfo *) erts_alloc(ERTS_ALC_T_TMP,
+ depth*sizeof(FunctionInfo));
+ heap_size = fi.needed + 2;
+ for (i = 0; i < depth; i++) {
+ erts_lookup_function_info(stkp, s->trace[i], 1);
+ if (stkp->current) {
+ heap_size += stkp->needed + 2;
+ stkp++;
}
- hp += 4;
- ASSERT(*next_p == NIL);
- *next_p = CONS(hp, mfa, NIL);
- next_p = &CDR(list_val(*next_p));
- hp += 2;
+ }
- /*
- * Finally, we go through the saved continuation pointers.
- */
- for (i = 0; i < depth; i++) {
- BeamInstr *fi = find_function_from_pc((BeamInstr *) s->trace[i]);
- if (fi == NULL) continue;
- mfa = TUPLE3(hp, fi[0], fi[1], make_small(fi[2]));
- hp += 4;
- ASSERT(*next_p == NIL);
- *next_p = CONS(hp, mfa, NIL);
- next_p = &CDR(list_val(*next_p));
- hp += 2;
- }
- ASSERT(hp <= hp_end);
- HRelease(c_p, hp_end, hp);
+ /*
+ * Allocate heap space and build the stacktrace.
+ */
+ hp = HAlloc(c_p, heap_size);
+ while (stkp > stk) {
+ stkp--;
+ hp = erts_build_mfa_item(stkp, hp, am_true, &mfa);
+ res = CONS(hp, mfa, res);
+ hp += 2;
}
- return Where;
+ hp = erts_build_mfa_item(&fi, hp, args, &mfa);
+ res = CONS(hp, mfa, res);
+
+ erts_free(ERTS_ALC_T_TMP, (void *) stk);
+ return res;
}
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index 57fe25453d..e43d364add 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -158,6 +158,7 @@ typedef struct {
#define LITERAL_CHUNK 6
#define ATTR_CHUNK 7
#define COMPILE_CHUNK 8
+#define LINE_CHUNK 9
#define NUM_CHUNK_TYPES (sizeof(chunk_types)/sizeof(chunk_types[0]))
@@ -182,6 +183,7 @@ static Uint chunk_types[] = {
MakeIffId('L', 'i', 't', 'T'), /* 6 */
MakeIffId('A', 't', 't', 'r'), /* 7 */
MakeIffId('C', 'I', 'n', 'f'), /* 8 */
+ MakeIffId('L', 'i', 'n', 'e'), /* 9 */
};
/*
@@ -204,6 +206,7 @@ typedef struct {
Eterm term; /* The tagged term (in the heap). */
Uint heap_size; /* (Exact) size on the heap. */
Uint offset; /* Offset from temporary location to final. */
+ ErlOffHeap off_heap; /* Start of linked list of ProcBins. */
Eterm* heap; /* Heap for term. */
} Literal;
@@ -231,10 +234,19 @@ struct string_patch {
};
/*
+ * This structure associates a code offset with a source code location.
+ */
+
+typedef struct {
+ int pos; /* Position in code */
+ Uint32 loc; /* Location in source code */
+} LineInstr;
+
+/*
* This structure contains all information about the module being loaded.
*/
-typedef struct {
+typedef struct LoaderState {
/*
* The current logical file within the binary.
*/
@@ -276,7 +288,6 @@ typedef struct {
BeamInstr* code; /* Loaded code. */
int ci; /* Current index into loaded code. */
Label* labels;
- BeamInstr new_bs_put_strings; /* Linked list of i_new_bs_put_string instructions. */
StringPatch* string_patches; /* Linked list of position into string table to patch. */
BeamInstr catches; /* Linked list of catch_yf instructions. */
unsigned loaded_size; /* Final size of code when loaded. */
@@ -325,27 +336,58 @@ typedef struct {
Literal* literals; /* Array of literals. */
LiteralPatch* literal_patches; /* Operands that need to be patched. */
Uint total_literal_size; /* Total heap size for all literals. */
+
+ /*
+ * Line table.
+ */
+ BeamInstr* line_item; /* Line items from the BEAM file. */
+ int num_line_items; /* Number of line items. */
+ LineInstr* line_instr; /* Line instructions */
+ int num_line_instrs; /* Maximum number of line instructions */
+ int current_li; /* Current line instruction */
+ int* func_line; /* Mapping from function to first line instr */
+ Eterm* fname; /* List of file names */
+ int num_fnames; /* Number of filenames in fname table */
+ int loc_size; /* Size of location info in bytes (2/4) */
} LoaderState;
-typedef struct {
- unsigned num_functions; /* Number of functions. */
- Eterm* func_tab[1]; /* Pointers to each function. */
-} LoadedCode;
-
-#define GetTagAndValue(Stp, Tag, Val) \
- do { \
- BeamInstr __w; \
- GetByte(Stp, __w); \
- Tag = __w & 0x07; \
- if ((__w & 0x08) == 0) { \
- Val = __w >> 4; \
- } else if ((__w & 0x10) == 0) { \
- Val = ((__w >> 5) << 8); \
- GetByte(Stp, __w); \
- Val |= __w; \
- } else { \
- if (!get_int_val(Stp, __w, &(Val))) goto load_error; \
- } \
+/*
+ * 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
+
+#define LINE_INVALID_LOCATION (0)
+
+/*
+ * Macros for manipulating locations.
+ */
+
+#define IS_VALID_LOCATION(File, Line) \
+ ((unsigned) (File) < 255 && (unsigned) (Line) < ((1 << 24) - 1))
+#define MAKE_LOCATION(File, Line) (((File) << 24) | (Line))
+#define LOC_FILE(Loc) ((Loc) >> 24)
+#define LOC_LINE(Loc) ((Loc) & ((1 << 24)-1))
+
+#define GetTagAndValue(Stp, Tag, Val) \
+ do { \
+ BeamInstr __w; \
+ GetByte(Stp, __w); \
+ Tag = __w & 0x07; \
+ if ((__w & 0x08) == 0) { \
+ Val = __w >> 4; \
+ } else if ((__w & 0x10) == 0) { \
+ Val = ((__w >> 5) << 8); \
+ GetByte(Stp, __w); \
+ Val |= __w; \
+ } else { \
+ int __res = get_tag_and_value(Stp, __w, (Tag), &(Val)); \
+ if (__res < 0) goto load_error; \
+ Tag = (unsigned) __res; \
+ } \
} while (0)
@@ -453,12 +495,10 @@ typedef struct {
} while (0)
-static int bin_load(Process *c_p, ErtsProcLocks c_p_locks,
- Eterm group_leader, Eterm* modp, byte* bytes, int unloaded_size);
-static void init_state(LoaderState* stp);
-static int insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
- Eterm group_leader, Eterm module,
- BeamInstr* code, Uint size, BeamInstr catches);
+static void free_state(LoaderState* stp);
+static Eterm insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
+ Eterm group_leader, Eterm module,
+ BeamInstr* code, Uint size);
static int scan_iff_file(LoaderState* stp, Uint* chunk_types,
Uint num_types, Uint num_mandatory);
static int load_atom_table(LoaderState* stp);
@@ -466,6 +506,7 @@ static int load_import_table(LoaderState* stp);
static int read_export_table(LoaderState* stp);
static int read_lambda_table(LoaderState* stp);
static int read_literal_table(LoaderState* stp);
+static int read_line_table(LoaderState* stp);
static int read_code_header(LoaderState* stp);
static int load_code(LoaderState* stp);
static GenOp* gen_element(LoaderState* stp, GenOpArg Fail, GenOpArg Index,
@@ -489,8 +530,8 @@ static void load_printf(int line, LoaderState* context, char *fmt, ...);
static int transform_engine(LoaderState* st);
static void id_to_string(Uint id, char* s);
static void new_genop(LoaderState* stp);
-static int get_int_val(LoaderState* stp, Uint len_code, BeamInstr* result);
-static int get_erlang_integer(LoaderState* stp, Uint len_code, BeamInstr* result);
+static int get_tag_and_value(LoaderState* stp, Uint len_code,
+ unsigned tag, BeamInstr* result);
static int new_label(LoaderState* stp);
static void new_literal_patch(LoaderState* stp, int pos);
static void new_string_patch(LoaderState* stp, int pos);
@@ -504,6 +545,8 @@ static Eterm native_addresses(Process* p, Eterm mod);
int patch_funentries(Eterm Patchlist);
int patch(Eterm Addresses, Uint fe);
static int safe_mul(UWord a, UWord b, UWord* resp);
+static void lookup_loc(FunctionInfo* fi, BeamInstr* pc,
+ BeamInstr* modp, int idx);
static int must_swap_floats;
@@ -548,7 +591,7 @@ define_file(LoaderState* stp, char* name, int idx)
stp->file_left = stp->chunks[idx].size;
}
-int
+Eterm
erts_load_module(Process *c_p,
ErtsProcLocks c_p_locks,
Eterm group_leader, /* Group leader or NIL if none. */
@@ -557,29 +600,17 @@ erts_load_module(Process *c_p,
* On return, contains the actual module name.
*/
byte* code, /* Points to the code to load */
- int size) /* Size of code to load. */
+ Uint size) /* Size of code to load. */
{
- ErlDrvBinary* bin;
- int result;
+ LoaderState* stp = erts_alloc_loader_state();
+ Eterm retval;
- if (size >= 4 && code[0] == 'F' && code[1] == 'O' &&
- code[2] == 'R' && code[3] == '1') {
- /*
- * The BEAM module is not compressed.
- */
- result = bin_load(c_p, c_p_locks, group_leader, modp, code, size);
- } else {
- /*
- * The BEAM module is compressed (or possibly invalid/corrupted).
- */
- if ((bin = (ErlDrvBinary *) erts_gzinflate_buffer((char*)code, size)) == NULL) {
- return -1;
- }
- result = bin_load(c_p, c_p_locks, group_leader, modp,
- (byte*)bin->orig_bytes, bin->orig_size);
- driver_free_binary(bin);
+ retval = erts_prepare_loading(stp, c_p, group_leader, modp,
+ code, size);
+ if (retval != NIL) {
+ return retval;
}
- return result;
+ return erts_finish_loading(stp, c_p, c_p_locks, modp);
}
/* #define LOAD_MEMORY_HARD_DEBUG 1*/
@@ -594,16 +625,30 @@ extern void check_allocated_block(Uint type, void *blk);
#define CHKBLK(TYPE,BLK) /* nothing */
#endif
-static int
-bin_load(Process *c_p, ErtsProcLocks c_p_locks,
- Eterm group_leader, Eterm* modp, byte* bytes, int unloaded_size)
+Eterm
+erts_prepare_loading(LoaderState* stp, Process *c_p, Eterm group_leader,
+ Eterm* modp, byte* code, Uint unloaded_size)
{
- LoaderState state;
- int rval = -1;
+ Eterm retval = am_badfile;
+ ErlDrvBinary* bin = NULL;
+
+ stp->module = *modp;
+ stp->group_leader = group_leader;
- init_state(&state);
- state.module = *modp;
- state.group_leader = group_leader;
+ /*
+ * Check if the module is compressed (or possibly invalid/corrupted).
+ */
+ if ( !(unloaded_size >= 4 &&
+ code[0] == 'F' && code[1] == 'O' &&
+ code[2] == 'R' && code[3] == '1') ) {
+ bin = (ErlDrvBinary *)
+ erts_gzinflate_buffer((char*)code, unloaded_size);
+ if (bin == NULL) {
+ goto load_error;
+ }
+ code = (byte*)bin->orig_bytes;
+ unloaded_size = bin->orig_size;
+ }
/*
* Scan the IFF file.
@@ -614,11 +659,11 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks,
#endif
CHKALLOC();
- CHKBLK(ERTS_ALC_T_CODE,state.code);
- state.file_name = "IFF header for Beam file";
- state.file_p = bytes;
- state.file_left = unloaded_size;
- if (!scan_iff_file(&state, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY)) {
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
+ stp->file_name = "IFF header for Beam file";
+ stp->file_p = code;
+ stp->file_left = unloaded_size;
+ if (!scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY)) {
goto load_error;
}
@@ -626,19 +671,38 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks,
* Read the header for the code chunk.
*/
- CHKBLK(ERTS_ALC_T_CODE,state.code);
- define_file(&state, "code chunk header", CODE_CHUNK);
- if (!read_code_header(&state)) {
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
+ define_file(stp, "code chunk header", CODE_CHUNK);
+ if (!read_code_header(stp)) {
goto load_error;
}
/*
+ * Initialize code area.
+ */
+ stp->code_buffer_size = erts_next_heap_size(2048 + stp->num_functions, 0);
+ stp->code = (BeamInstr *) erts_alloc(ERTS_ALC_T_CODE,
+ sizeof(BeamInstr) * stp->code_buffer_size);
+
+ stp->code[MI_NUM_FUNCTIONS] = stp->num_functions;
+ stp->ci = MI_FUNCTIONS + stp->num_functions + 1;
+
+ stp->code[MI_ATTR_PTR] = 0;
+ stp->code[MI_ATTR_SIZE] = 0;
+ stp->code[MI_ATTR_SIZE_ON_HEAP] = 0;
+ stp->code[MI_COMPILE_PTR] = 0;
+ stp->code[MI_COMPILE_SIZE] = 0;
+ stp->code[MI_COMPILE_SIZE_ON_HEAP] = 0;
+ stp->code[MI_NUM_BREAKPOINTS] = 0;
+
+
+ /*
* Read the atom table.
*/
- CHKBLK(ERTS_ALC_T_CODE,state.code);
- define_file(&state, "atom table", ATOM_CHUNK);
- if (!load_atom_table(&state)) {
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
+ define_file(stp, "atom table", ATOM_CHUNK);
+ if (!load_atom_table(stp)) {
goto load_error;
}
@@ -646,9 +710,9 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks,
* Read the import table.
*/
- CHKBLK(ERTS_ALC_T_CODE,state.code);
- define_file(&state, "import table", IMP_CHUNK);
- if (!load_import_table(&state)) {
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
+ define_file(stp, "import table", IMP_CHUNK);
+ if (!load_import_table(stp)) {
goto load_error;
}
@@ -656,10 +720,10 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks,
* Read the lambda (fun) table.
*/
- CHKBLK(ERTS_ALC_T_CODE,state.code);
- if (state.chunks[LAMBDA_CHUNK].size > 0) {
- define_file(&state, "lambda (fun) table", LAMBDA_CHUNK);
- if (!read_lambda_table(&state)) {
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
+ if (stp->chunks[LAMBDA_CHUNK].size > 0) {
+ define_file(stp, "lambda (fun) table", LAMBDA_CHUNK);
+ if (!read_lambda_table(stp)) {
goto load_error;
}
}
@@ -668,10 +732,22 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks,
* Read the literal table.
*/
- CHKBLK(ERTS_ALC_T_CODE,state.code);
- if (state.chunks[LITERAL_CHUNK].size > 0) {
- define_file(&state, "literals table (constant pool)", LITERAL_CHUNK);
- if (!read_literal_table(&state)) {
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
+ if (stp->chunks[LITERAL_CHUNK].size > 0) {
+ define_file(stp, "literals table (constant pool)", LITERAL_CHUNK);
+ if (!read_literal_table(stp)) {
+ goto load_error;
+ }
+ }
+
+ /*
+ * Read the line table (if present).
+ */
+
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
+ if (stp->chunks[LINE_CHUNK].size > 0) {
+ define_file(stp, "line table", LINE_CHUNK);
+ if (!read_line_table(stp)) {
goto load_error;
}
}
@@ -680,15 +756,15 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks,
* Load the code chunk.
*/
- CHKBLK(ERTS_ALC_T_CODE,state.code);
- state.file_name = "code chunk";
- state.file_p = state.code_start;
- state.file_left = state.code_size;
- if (!load_code(&state)) {
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
+ stp->file_name = "code chunk";
+ stp->file_p = stp->code_start;
+ stp->file_left = stp->code_size;
+ if (!load_code(stp)) {
goto load_error;
}
- CHKBLK(ERTS_ALC_T_CODE,state.code);
- if (!freeze_code(&state)) {
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
+ if (!freeze_code(stp)) {
goto load_error;
}
@@ -698,9 +774,52 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks,
* loading the code, because it contains labels.)
*/
- CHKBLK(ERTS_ALC_T_CODE,state.code);
- define_file(&state, "export table", EXP_CHUNK);
- if (!read_export_table(&state)) {
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
+ define_file(stp, "export table", EXP_CHUNK);
+ if (!read_export_table(stp)) {
+ goto load_error;
+ }
+
+ /*
+ * Good so far.
+ */
+
+ retval = NIL;
+
+ load_error:
+ if (bin) {
+ driver_free_binary(bin);
+ }
+ if (retval != NIL) {
+ free_state(stp);
+ }
+ return retval;
+}
+
+Eterm
+erts_finish_loading(LoaderState* stp, Process* c_p,
+ ErtsProcLocks c_p_locks, Eterm* modp)
+{
+ Eterm retval;
+
+ /*
+ * No other process may run since we will update the export
+ * table which is not protected by any locks.
+ */
+
+ ERTS_SMP_LC_ASSERT(erts_initialized == 0 ||
+ erts_smp_thr_progress_is_blocking());
+
+ /*
+ * Make current code for the module old and insert the new code
+ * as current. This will fail if there already exists old code
+ * for the module.
+ */
+
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
+ retval = insert_new_code(c_p, c_p_locks, stp->group_leader, stp->module,
+ stp->code, stp->loaded_size);
+ if (retval != NIL) {
goto load_error;
}
@@ -709,88 +828,42 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks,
* exported and imported functions. This can't fail.
*/
- CHKBLK(ERTS_ALC_T_CODE,state.code);
- rval = insert_new_code(c_p, c_p_locks, state.group_leader, state.module,
- state.code, state.loaded_size, state.catches);
- if (rval < 0) {
- goto load_error;
- }
- CHKBLK(ERTS_ALC_T_CODE,state.code);
- final_touch(&state);
+ erts_export_consolidate();
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
+ final_touch(stp);
/*
* Loading succeded.
*/
- CHKBLK(ERTS_ALC_T_CODE,state.code);
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
#if defined(LOAD_MEMORY_HARD_DEBUG) && defined(DEBUG)
erts_fprintf(stderr,"Loaded %T\n",*modp);
#if 0
- debug_dump_code(state.code,state.ci);
+ debug_dump_code(stp->code,stp->ci);
#endif
#endif
- rval = 0;
- state.code = NULL; /* Prevent code from being freed. */
- *modp = state.module;
+ stp->code = NULL; /* Prevent code from being freed. */
+ *modp = stp->module;
/*
* If there is an on_load function, signal an error to
* indicate that the on_load function must be run.
*/
- if (state.on_load) {
- rval = -5;
+ if (stp->on_load) {
+ retval = am_on_load;
}
load_error:
- if (state.code != 0) {
- erts_free(ERTS_ALC_T_CODE, state.code);
- }
- if (state.labels != NULL) {
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.labels);
- }
- if (state.atom != NULL) {
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.atom);
- }
- if (state.import != NULL) {
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.import);
- }
- if (state.export != NULL) {
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.export);
- }
- if (state.lambdas != state.def_lambdas) {
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.lambdas);
- }
- if (state.literals != NULL) {
- int i;
- for (i = 0; i < state.num_literals; i++) {
- if (state.literals[i].heap != NULL) {
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.literals[i].heap);
- }
- }
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.literals);
- }
- while (state.literal_patches != NULL) {
- LiteralPatch* next = state.literal_patches->next;
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.literal_patches);
- state.literal_patches = next;
- }
- while (state.string_patches != NULL) {
- StringPatch* next = state.string_patches->next;
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.string_patches);
- state.string_patches = next;
- }
- while (state.genop_blocks) {
- GenOpBlock* next = state.genop_blocks->next;
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.genop_blocks);
- state.genop_blocks = next;
- }
-
- return rval;
+ free_state(stp);
+ return retval;
}
-
-static void
-init_state(LoaderState* stp)
+LoaderState*
+erts_alloc_loader_state(void)
{
+ LoaderState* stp;
+
+ stp = erts_alloc(ERTS_ALC_T_LOADER_TMP, sizeof(LoaderState));
stp->function = THE_NON_VALUE; /* Function not known yet */
stp->arity = 0;
stp->specific_op = -1;
@@ -814,23 +887,94 @@ init_state(LoaderState* stp)
stp->string_patches = 0;
stp->may_load_nif = 0;
stp->on_load = 0;
+ stp->line_item = 0;
+ stp->line_instr = 0;
+ stp->func_line = 0;
+ stp->fname = 0;
+ return stp;
}
-static int
+static void
+free_state(LoaderState* stp)
+{
+ if (stp->code != 0) {
+ erts_free(ERTS_ALC_T_CODE, stp->code);
+ }
+ if (stp->labels != NULL) {
+ erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->labels);
+ }
+ if (stp->atom != NULL) {
+ erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->atom);
+ }
+ if (stp->import != NULL) {
+ erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->import);
+ }
+ if (stp->export != NULL) {
+ erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->export);
+ }
+ if (stp->lambdas != stp->def_lambdas) {
+ erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->lambdas);
+ }
+ if (stp->literals != NULL) {
+ int i;
+ for (i = 0; i < stp->num_literals; i++) {
+ if (stp->literals[i].heap != NULL) {
+ erts_free(ERTS_ALC_T_LOADER_TMP,
+ (void *) stp->literals[i].heap);
+ }
+ }
+ erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->literals);
+ }
+ while (stp->literal_patches != NULL) {
+ LiteralPatch* next = stp->literal_patches->next;
+ erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->literal_patches);
+ stp->literal_patches = next;
+ }
+ while (stp->string_patches != NULL) {
+ StringPatch* next = stp->string_patches->next;
+ erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->string_patches);
+ stp->string_patches = next;
+ }
+ while (stp->genop_blocks) {
+ GenOpBlock* next = stp->genop_blocks->next;
+ erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->genop_blocks);
+ stp->genop_blocks = next;
+ }
+
+ if (stp->line_item != 0) {
+ erts_free(ERTS_ALC_T_LOADER_TMP, stp->line_item);
+ }
+
+ if (stp->line_instr != 0) {
+ erts_free(ERTS_ALC_T_LOADER_TMP, stp->line_instr);
+ }
+
+ if (stp->func_line != 0) {
+ erts_free(ERTS_ALC_T_LOADER_TMP, stp->func_line);
+ }
+
+ if (stp->fname != 0) {
+ erts_free(ERTS_ALC_T_LOADER_TMP, stp->fname);
+ }
+ erts_free(ERTS_ALC_T_LOADER_TMP, stp);
+}
+
+static Eterm
insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
- Eterm group_leader, Eterm module, BeamInstr* code, Uint size, BeamInstr catches)
+ Eterm group_leader, Eterm module, BeamInstr* code,
+ Uint size)
{
Module* modp;
- int rval;
+ Eterm retval;
int i;
- if ((rval = beam_make_current_old(c_p, c_p_locks, module)) < 0) {
+ if ((retval = beam_make_current_old(c_p, c_p_locks, module)) < 0) {
erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf();
erts_dsprintf(dsbufp,
"Module %T must be purged before loading\n",
module);
erts_send_error_to_logger(group_leader, dsbufp);
- return rval;
+ return retval;
}
/*
@@ -841,7 +985,7 @@ insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
modp = erts_put_module(module);
modp->code = code;
modp->code_length = size;
- modp->catches = catches;
+ modp->catches = BEAM_CATCHES_NIL; /* Will be filled in later. */
/*
* Update address table (used for finding a function from a PC value).
@@ -863,7 +1007,7 @@ insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
modules[i].end = (BeamInstr *) (((byte *)code) + size);
num_loaded_modules++;
mid_module = &modules[num_loaded_modules/2];
- return 0;
+ return NIL;
}
static int
@@ -1276,12 +1420,14 @@ read_literal_table(LoaderState* stp)
GetInt(stp, 4, sz); /* Size of external term format. */
GetString(stp, p, sz);
- if ((heap_size = erts_decode_ext_size(p, sz, 1)) < 0) {
+ if ((heap_size = erts_decode_ext_size(p, sz)) < 0) {
LoadError1(stp, "literal %d: bad external format", i);
}
hp = stp->literals[i].heap = erts_alloc(ERTS_ALC_T_LOADER_TMP,
heap_size*sizeof(Eterm));
- val = erts_decode_ext(&hp, NULL, &p);
+ stp->literals[i].off_heap.first = 0;
+ stp->literals[i].off_heap.overhead = 0;
+ val = erts_decode_ext(&hp, &stp->literals[i].off_heap, &p);
stp->literals[i].heap_size = hp - stp->literals[i].heap;
if (stp->literals[i].heap_size > heap_size) {
erl_exit(1, "overrun by %d word(s) for literal heap, term %d",
@@ -1303,6 +1449,138 @@ read_literal_table(LoaderState* stp)
return 0;
}
+static int
+read_line_table(LoaderState* stp)
+{
+ unsigned version;
+ unsigned flags;
+ int num_line_items;
+ BeamInstr* lp;
+ int i;
+ BeamInstr fname_index;
+ BeamInstr tag;
+
+ /*
+ * If the emulator flag ignoring the line information was given,
+ * return immediately.
+ */
+
+ if (erts_no_line_info) {
+ return 1;
+ }
+
+ /*
+ * Check version of line table.
+ */
+
+ GetInt(stp, 4, version);
+ if (version != 0) {
+ /*
+ * Wrong version. Silently ignore the line number chunk.
+ */
+ return 1;
+ }
+
+ /*
+ * Read the remaining header words. The flag word is reserved
+ * for possible future use; for the moment we ignore it.
+ */
+ GetInt(stp, 4, flags);
+ GetInt(stp, 4, stp->num_line_instrs);
+ GetInt(stp, 4, num_line_items);
+ GetInt(stp, 4, stp->num_fnames);
+
+ /*
+ * Calculate space and allocate memory for the line item table.
+ */
+
+ num_line_items++;
+ lp = (BeamInstr *) erts_alloc(ERTS_ALC_T_LOADER_TMP,
+ num_line_items * sizeof(BeamInstr));
+ stp->line_item = lp;
+ stp->num_line_items = num_line_items;
+
+ /*
+ * The zeroth entry in the line item table is special.
+ * It contains the undefined location.
+ */
+
+ *lp++ = LINE_INVALID_LOCATION;
+ num_line_items--;
+
+ /*
+ * Read all the line items.
+ */
+
+ stp->loc_size = stp->num_fnames ? 4 : 2;
+ fname_index = 0;
+ while (num_line_items-- > 0) {
+ BeamInstr val;
+ BeamInstr loc;
+
+ GetTagAndValue(stp, tag, val);
+ if (tag == TAG_i) {
+ if (IS_VALID_LOCATION(fname_index, val)) {
+ loc = MAKE_LOCATION(fname_index, val);
+ } else {
+ /*
+ * Too many files or huge line number. Silently invalidate
+ * the location.
+ */
+ loc = LINE_INVALID_LOCATION;
+ }
+ *lp++ = loc;
+ if (val > 0xFFFF) {
+ stp->loc_size = 4;
+ }
+ } else if (tag == TAG_a) {
+ if (val > stp->num_fnames) {
+ LoadError2(stp, "file index overflow (%d/%d)",
+ val, stp->num_fnames);
+ }
+ fname_index = val;
+ num_line_items++;
+ } else {
+ LoadError1(stp, "bad tag '%c' (expected 'a' or 'i')",
+ tag_to_letter[tag]);
+ }
+ }
+
+ /*
+ * Read all filenames.
+ */
+
+ if (stp->num_fnames != 0) {
+ stp->fname = (Eterm *) erts_alloc(ERTS_ALC_T_LOADER_TMP,
+ stp->num_fnames *
+ sizeof(Eterm));
+ for (i = 0; i < stp->num_fnames; i++) {
+ byte* fname;
+ Uint n;
+
+ GetInt(stp, 2, n);
+ GetString(stp, fname, n);
+ stp->fname[i] = am_atom_put((char*)fname, n);
+ }
+ }
+
+ /*
+ * Allocate the arrays to be filled while code is being loaded.
+ */
+ stp->line_instr = (LineInstr *) erts_alloc(ERTS_ALC_T_LOADER_TMP,
+ stp->num_line_instrs *
+ sizeof(LineInstr));
+ stp->current_li = 0;
+ stp->func_line = (int *) erts_alloc(ERTS_ALC_T_LOADER_TMP,
+ stp->num_functions *
+ sizeof(int));
+
+ return 1;
+
+ load_error:
+ return 0;
+}
+
static int
read_code_header(LoaderState* stp)
@@ -1337,10 +1615,15 @@ read_code_header(LoaderState* stp)
/*
* Verify the number of the highest opcode used.
*/
-
GetInt(stp, 4, opcode_max);
if (opcode_max > MAX_GENERIC_OPCODE) {
- LoadError2(stp, "use of opcode %d; this emulator supports only up to %d",
+ LoadError2(stp,
+ "This BEAM file was compiled for a later version"
+ " of the run-time system than " ERLANG_OTP_RELEASE ".\n"
+ " To fix this, please recompile this module with an "
+ ERLANG_OTP_RELEASE " compiler.\n"
+ " (Use of opcode %d; this emulator supports "
+ "only up to %d.)",
opcode_max, MAX_GENERIC_OPCODE);
}
@@ -1361,25 +1644,6 @@ read_code_header(LoaderState* stp)
#endif
}
- /*
- * Initialize code area.
- */
- stp->code_buffer_size = erts_next_heap_size(2048 + stp->num_functions, 0);
- stp->code = (BeamInstr *) erts_alloc(ERTS_ALC_T_CODE,
- sizeof(BeamInstr) * stp->code_buffer_size);
-
- stp->code[MI_NUM_FUNCTIONS] = stp->num_functions;
- stp->ci = MI_FUNCTIONS + stp->num_functions + 1;
-
- stp->code[MI_ATTR_PTR] = 0;
- stp->code[MI_ATTR_SIZE] = 0;
- stp->code[MI_ATTR_SIZE_ON_HEAP] = 0;
- stp->code[MI_COMPILE_PTR] = 0;
- stp->code[MI_COMPILE_SIZE] = 0;
- stp->code[MI_COMPILE_SIZE_ON_HEAP] = 0;
- stp->code[MI_NUM_BREAKPOINTS] = 0;
-
- stp->new_bs_put_strings = 0;
stp->catches = 0;
return 1;
@@ -1412,7 +1676,7 @@ load_code(LoaderState* stp)
{
int i;
int ci;
- int last_func_start = 0;
+ int last_func_start = 0; /* Needed by nif loading and line instructions */
char* sign;
int arg; /* Number of current argument. */
int num_specific; /* Number of specific ops for current. */
@@ -1425,6 +1689,14 @@ load_code(LoaderState* stp)
GenOp** last_op_next = NULL;
int arity;
+ /*
+ * The size of the loaded func_info instruction is needed
+ * by both the nif functionality and line instructions.
+ */
+ enum {
+ FUNC_INFO_SZ = 5
+ };
+
code = stp->code;
code_buffer_size = stp->code_buffer_size;
ci = stp->ci;
@@ -1470,46 +1742,15 @@ load_code(LoaderState* stp)
last_op->arity = 0;
ASSERT(arity <= MAX_OPARGS);
-#define GetValue(Stp, First, Val) \
- do { \
- if (((First) & 0x08) == 0) { \
- Val = (First) >> 4; \
- } else if (((First) & 0x10) == 0) { \
- BeamInstr __w; \
- GetByte(Stp, __w); \
- Val = (((First) >> 5) << 8) | __w; \
- } else { \
- if (!get_int_val(Stp, (First), &(Val))) goto load_error; \
- } \
- } while (0)
-
for (arg = 0; arg < arity; arg++) {
- BeamInstr first;
-
- GetByte(stp, first);
- last_op->a[arg].type = first & 0x07;
+ GetTagAndValue(stp, last_op->a[arg].type, last_op->a[arg].val);
switch (last_op->a[arg].type) {
case TAG_i:
- if ((first & 0x08) == 0) {
- last_op->a[arg].val = first >> 4;
- } else if ((first & 0x10) == 0) {
- BeamInstr w;
- GetByte(stp, w);
- ASSERT(first < 0x800);
- last_op->a[arg].val = ((first >> 5) << 8) | w;
- } else {
- int i = get_erlang_integer(stp, first, &(last_op->a[arg].val));
- if (i < 0) {
- goto load_error;
- }
- last_op->a[arg].type = i;
- }
- break;
case TAG_u:
- GetValue(stp, first, last_op->a[arg].val);
+ case TAG_q:
+ case TAG_o:
break;
case TAG_x:
- GetValue(stp, first, last_op->a[arg].val);
if (last_op->a[arg].val == 0) {
last_op->a[arg].type = TAG_r;
} else if (last_op->a[arg].val >= MAX_REG) {
@@ -1518,7 +1759,6 @@ load_code(LoaderState* stp)
}
break;
case TAG_y:
- GetValue(stp, first, last_op->a[arg].val);
if (last_op->a[arg].val >= MAX_REG) {
LoadError1(stp, "invalid y register number: %u",
last_op->a[arg].val);
@@ -1526,7 +1766,6 @@ load_code(LoaderState* stp)
last_op->a[arg].val += CP_SIZE;
break;
case TAG_a:
- GetValue(stp, first, last_op->a[arg].val);
if (last_op->a[arg].val == 0) {
last_op->a[arg].type = TAG_n;
} else if (last_op->a[arg].val >= stp->num_atoms) {
@@ -1536,7 +1775,6 @@ load_code(LoaderState* stp)
}
break;
case TAG_f:
- GetValue(stp, first, last_op->a[arg].val);
if (last_op->a[arg].val == 0) {
last_op->a[arg].type = TAG_p;
} else if (last_op->a[arg].val >= stp->num_labels) {
@@ -1544,7 +1782,6 @@ load_code(LoaderState* stp)
}
break;
case TAG_h:
- GetValue(stp, first, last_op->a[arg].val);
if (last_op->a[arg].val > 65535) {
LoadError1(stp, "invalid range for character data type: %u",
last_op->a[arg].val);
@@ -1552,11 +1789,9 @@ load_code(LoaderState* stp)
break;
case TAG_z:
{
- BeamInstr ext_tag;
unsigned tag;
- GetValue(stp, first, ext_tag);
- switch (ext_tag) {
+ switch (last_op->a[arg].val) {
case 0: /* Floating point number */
{
Eterm* hp;
@@ -1648,7 +1883,8 @@ load_code(LoaderState* stp)
break;
}
default:
- LoadError1(stp, "invalid extended tag %d", ext_tag);
+ LoadError1(stp, "invalid extended tag %d",
+ last_op->a[arg].val);
break;
}
}
@@ -1659,7 +1895,6 @@ load_code(LoaderState* stp)
}
last_op->arity++;
}
-#undef GetValue
ASSERT(arity == last_op->arity);
@@ -1701,14 +1936,6 @@ load_code(LoaderState* stp)
}
/*
- * Special error message instruction.
- */
- if (stp->genop->op == genop_too_old_compiler_0) {
- LoadError0(stp, "please re-compile this module with an "
- ERLANG_OTP_RELEASE " compiler");
- }
-
- /*
* From the collected generic instruction, find the specific
* instruction.
*/
@@ -1759,7 +1986,27 @@ load_code(LoaderState* stp)
ERLANG_OTP_RELEASE " compiler ");
}
- LoadError0(stp, "no specific operation found");
+ /*
+ * Some generic instructions should have a special
+ * error message.
+ */
+ switch (stp->genop->op) {
+ case genop_too_old_compiler_0:
+ LoadError0(stp, "please re-compile this module with an "
+ ERLANG_OTP_RELEASE " compiler");
+ case genop_unsupported_guard_bif_3:
+ {
+ Eterm Mod = (Eterm) stp->genop->a[0].val;
+ Eterm Name = (Eterm) stp->genop->a[1].val;
+ Uint arity = (Uint) stp->genop->a[2].val;
+ FREE_GENOP(stp, stp->genop);
+ stp->genop = 0;
+ LoadError3(stp, "unsupported guard BIF: %T:%T/%d\n",
+ Mod, Name, arity);
+ }
+ default:
+ LoadError0(stp, "no specific operation found");
+ }
}
stp->specific_op = specific;
@@ -2048,7 +2295,6 @@ load_code(LoaderState* stp)
case op_i_func_info_IaaI:
{
Uint offset;
- enum { FINFO_SZ = 5 };
if (function_number >= stp->num_functions) {
LoadError1(stp, "too many functions in module (header said %d)",
@@ -2056,27 +2302,37 @@ load_code(LoaderState* stp)
}
if (stp->may_load_nif) {
- const int finfo_ix = ci - FINFO_SZ;
+ const int finfo_ix = ci - FUNC_INFO_SZ;
enum { MIN_FUNC_SZ = 3 };
if (finfo_ix - last_func_start < MIN_FUNC_SZ && last_func_start) {
/* Must make room for call_nif op */
int pad = MIN_FUNC_SZ - (finfo_ix - last_func_start);
ASSERT(pad > 0 && pad < MIN_FUNC_SZ);
CodeNeed(pad);
- sys_memmove(&code[finfo_ix+pad], &code[finfo_ix], FINFO_SZ*sizeof(BeamInstr));
+ sys_memmove(&code[finfo_ix+pad], &code[finfo_ix],
+ FUNC_INFO_SZ*sizeof(BeamInstr));
sys_memset(&code[finfo_ix], 0, pad*sizeof(BeamInstr));
ci += pad;
stp->labels[last_label].value += pad;
}
}
last_func_start = ci;
+
+ /*
+ * Save current offset of into the line instruction array.
+ */
+
+ if (stp->func_line) {
+ stp->func_line[function_number] = stp->current_li;
+ }
+
/*
* Save context for error messages.
*/
stp->function = code[ci-2];
stp->arity = code[ci-1];
- ASSERT(stp->labels[last_label].value == ci - FINFO_SZ);
+ ASSERT(stp->labels[last_label].value == ci - FUNC_INFO_SZ);
offset = MI_FUNCTIONS + function_number;
code[offset] = stp->labels[last_label].patches;
stp->labels[last_label].patches = offset;
@@ -2099,32 +2355,6 @@ load_code(LoaderState* stp)
stp->on_load = ci;
break;
case op_bs_put_string_II:
- {
- /*
- * At entry:
- *
- * code[ci-3] &&lb_i_new_bs_put_string_II
- * code[ci-2] length of string
- * code[ci-1] offset into string table
- *
- * Since we don't know the address of the string table yet,
- * just check the offset and length for validity, and use
- * the instruction field as a link field to link all put_string
- * instructions into a single linked list. At exit:
- *
- * code[ci-3] pointer to next i_new_bs_put_string instruction (or 0
- * if this is the last)
- */
- Uint offset = code[ci-1];
- Uint len = code[ci-2];
- unsigned strtab_size = stp->chunks[STR_CHUNK].size;
- if (offset > strtab_size || offset + len > strtab_size) {
- LoadError2(stp, "invalid string reference %d, size %d", offset, len);
- }
- code[ci-3] = stp->new_bs_put_strings;
- stp->new_bs_put_strings = ci - 3;
- }
- break;
case op_i_bs_match_string_rfII:
case op_i_bs_match_string_xfII:
new_string_patch(stp, ci-1);
@@ -2139,6 +2369,45 @@ load_code(LoaderState* stp)
stp->catches = ci-3;
break;
+ case op_line_I:
+ if (stp->line_item) {
+ BeamInstr item = code[ci-1];
+ BeamInstr loc;
+ int li;
+ if (item >= stp->num_line_items) {
+ LoadError2(stp, "line instruction index overflow (%d/%d)",
+ item, stp->num_line_items);
+ }
+ li = stp->current_li;
+ if (li >= stp->num_line_instrs) {
+ LoadError2(stp, "line instruction table overflow (%d/%d)",
+ li, stp->num_line_instrs);
+ }
+ loc = stp->line_item[item];
+
+ if (ci - 2 == last_func_start) {
+ /*
+ * This line instruction directly follows the func_info
+ * instruction. Its address must be adjusted to point to
+ * func_info instruction.
+ */
+ stp->line_instr[li].pos = last_func_start - FUNC_INFO_SZ;
+ stp->line_instr[li].loc = stp->line_item[item];
+ stp->current_li++;
+ } else if (li <= stp->func_line[function_number-1] ||
+ stp->line_instr[li-1].loc != loc) {
+ /*
+ * Only store the location if it is different
+ * from the previous location in the same function.
+ */
+ stp->line_instr[li].pos = ci - 2;
+ stp->line_instr[li].loc = stp->line_item[item];
+ stp->current_li++;
+ }
+ }
+ ci -= 2; /* Get rid of the instruction */
+ break;
+
/*
* End of code found.
*/
@@ -2175,6 +2444,8 @@ load_code(LoaderState* stp)
#define no_fpe_signals(St) 0
#endif
+#define never(St) 0
+
/*
* Predicate that tests whether a jump table can be used.
*/
@@ -2562,13 +2833,8 @@ should_gen_heap_bin(LoaderState* stp, GenOpArg Src)
static int
binary_too_big(LoaderState* stp, GenOpArg Size)
{
- return Size.type == TAG_u && ((Size.val >> (8*sizeof(Uint)-3)) != 0);
-}
-
-static int
-binary_too_big_bits(LoaderState* stp, GenOpArg Size)
-{
- return Size.type == TAG_u && (((Size.val+7)/8) >> (8*sizeof(Uint)-3) != 0);
+ return Size.type == TAG_o ||
+ (Size.type == TAG_u && ((Size.val >> (8*sizeof(Uint)-3)) != 0));
}
static GenOp*
@@ -3435,10 +3701,7 @@ gen_guard_bif1(LoaderState* stp, GenOpArg Fail, GenOpArg Live, GenOpArg Bif,
BifFunction bf;
NEW_GENOP(stp, op);
- op->op = genop_i_gc_bif1_5;
- op->arity = 5;
- op->a[0] = Fail;
- op->a[1].type = TAG_u;
+ op->next = NULL;
bf = stp->import[Bif.val].bf;
/* The translations here need to have a reverse counterpart in
beam_emu.c:translate_gc_bif for error handling to work properly. */
@@ -3459,19 +3722,30 @@ gen_guard_bif1(LoaderState* stp, GenOpArg Fail, GenOpArg Live, GenOpArg Bif,
} else if (bf == trunc_1) {
op->a[1].val = (BeamInstr) (void *) erts_gc_trunc_1;
} else {
- abort();
+ op->op = genop_unsupported_guard_bif_3;
+ op->arity = 3;
+ op->a[0].type = TAG_a;
+ op->a[0].val = stp->import[Bif.val].module;
+ op->a[1].type = TAG_a;
+ op->a[1].val = stp->import[Bif.val].function;
+ op->a[2].type = TAG_u;
+ op->a[2].val = stp->import[Bif.val].arity;
+ return op;
}
+ op->op = genop_i_gc_bif1_5;
+ op->arity = 5;
+ op->a[0] = Fail;
+ op->a[1].type = TAG_u;
op->a[2] = Src;
op->a[3] = Live;
op->a[4] = Dst;
- op->next = NULL;
return op;
}
/*
- * This is used by the ops.tab rule that rewrites gc_bifs with two parameters
+ * This is used by the ops.tab rule that rewrites gc_bifs with two parameters.
* The instruction returned is then again rewritten to an i_load instruction
- * folowed by i_gc_bif2_jIId, to handle literals properly.
+ * followed by i_gc_bif2_jIId, to handle literals properly.
* As opposed to the i_gc_bif1_jIsId, the instruction i_gc_bif2_jIId is
* always rewritten, regardless of if there actually are any literals.
*/
@@ -3483,31 +3757,39 @@ gen_guard_bif2(LoaderState* stp, GenOpArg Fail, GenOpArg Live, GenOpArg Bif,
BifFunction bf;
NEW_GENOP(stp, op);
- op->op = genop_ii_gc_bif2_6;
- op->arity = 6;
- op->a[0] = Fail;
- op->a[1].type = TAG_u;
+ op->next = NULL;
bf = stp->import[Bif.val].bf;
/* The translations here need to have a reverse counterpart in
beam_emu.c:translate_gc_bif for error handling to work properly. */
if (bf == binary_part_2) {
op->a[1].val = (BeamInstr) (void *) erts_gc_binary_part_2;
} else {
- abort();
+ op->op = genop_unsupported_guard_bif_3;
+ op->arity = 3;
+ op->a[0].type = TAG_a;
+ op->a[0].val = stp->import[Bif.val].module;
+ op->a[1].type = TAG_a;
+ op->a[1].val = stp->import[Bif.val].function;
+ op->a[2].type = TAG_u;
+ op->a[2].val = stp->import[Bif.val].arity;
+ return op;
}
+ op->op = genop_ii_gc_bif2_6;
+ op->arity = 6;
+ op->a[0] = Fail;
+ op->a[1].type = TAG_u;
op->a[2] = S1;
op->a[3] = S2;
op->a[4] = Live;
op->a[5] = Dst;
- op->next = NULL;
return op;
}
/*
- * This is used by the ops.tab rule that rewrites gc_bifs with three parameters
+ * This is used by the ops.tab rule that rewrites gc_bifs with three parameters.
* The instruction returned is then again rewritten to a move instruction that
* uses r[0] for temp storage, followed by an i_load instruction,
- * folowed by i_gc_bif3_jIsId, to handle literals properly. Rewriting
+ * followed by i_gc_bif3_jIsId, to handle literals properly. Rewriting
* always occur, as with the gc_bif2 counterpart.
*/
static GenOp*
@@ -3518,18 +3800,27 @@ gen_guard_bif3(LoaderState* stp, GenOpArg Fail, GenOpArg Live, GenOpArg Bif,
BifFunction bf;
NEW_GENOP(stp, op);
- op->op = genop_ii_gc_bif3_7;
- op->arity = 7;
- op->a[0] = Fail;
- op->a[1].type = TAG_u;
+ op->next = NULL;
bf = stp->import[Bif.val].bf;
/* The translations here need to have a reverse counterpart in
beam_emu.c:translate_gc_bif for error handling to work properly. */
if (bf == binary_part_3) {
op->a[1].val = (BeamInstr) (void *) erts_gc_binary_part_3;
} else {
- abort();
+ op->op = genop_unsupported_guard_bif_3;
+ op->arity = 3;
+ op->a[0].type = TAG_a;
+ op->a[0].val = stp->import[Bif.val].module;
+ op->a[1].type = TAG_a;
+ op->a[1].val = stp->import[Bif.val].function;
+ op->a[2].type = TAG_u;
+ op->a[2].val = stp->import[Bif.val].arity;
+ return op;
}
+ op->op = genop_ii_gc_bif3_7;
+ op->arity = 7;
+ op->a[0] = Fail;
+ op->a[1].type = TAG_u;
op->a[2] = S1;
op->a[3] = S2;
op->a[4] = S3;
@@ -3600,15 +3891,14 @@ freeze_code(LoaderState* stp)
{
BeamInstr* code = stp->code;
Uint *literal_end = NULL;
- Uint index;
int i;
byte* str_table;
unsigned strtab_size = stp->chunks[STR_CHUNK].size;
unsigned attr_size = stp->chunks[ATTR_CHUNK].size;
unsigned compile_size = stp->chunks[COMPILE_CHUNK].size;
Uint size;
- unsigned catches;
Sint decoded_size;
+ Uint line_size;
/*
* Verify that there was a correct 'FunT' chunk if there were
@@ -3619,13 +3909,19 @@ freeze_code(LoaderState* stp)
LoadError0(stp, stp->lambda_error);
}
-
/*
* Calculate the final size of the code.
*/
-
- size = (stp->ci * sizeof(BeamInstr)) + (stp->total_literal_size * sizeof(Eterm)) +
- strtab_size + attr_size + compile_size;
+ 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;
+ }
+ size = (stp->ci * sizeof(BeamInstr)) +
+ (stp->total_literal_size * sizeof(Eterm)) +
+ strtab_size + attr_size + compile_size + line_size;
/*
* Move the code to its final location.
@@ -3662,6 +3958,8 @@ freeze_code(LoaderState* stp)
Uint* low;
Uint* high;
LiteralPatch* lp;
+ struct erl_off_heap_header* off_heap = 0;
+ struct erl_off_heap_header** off_heap_last = &off_heap;
low = (Uint *) (code+stp->ci);
high = low + stp->total_literal_size;
@@ -3670,6 +3968,7 @@ freeze_code(LoaderState* stp)
ptr = low;
for (i = 0; i < stp->num_literals; i++) {
Uint offset;
+ struct erl_off_heap_header* t_off_heap;
sys_memcpy(ptr, stp->literals[i].heap,
stp->literals[i].heap_size*sizeof(Eterm));
@@ -3684,9 +3983,19 @@ freeze_code(LoaderState* stp)
*ptr++ = offset_ptr(val, offset);
break;
case TAG_PRIMARY_HEADER:
- ptr++;
- if (header_is_thing(val)) {
- ptr += thing_arityval(val);
+ if (header_is_transparent(val)) {
+ ptr++;
+ } else {
+ if (thing_subtag(val) == REFC_BINARY_SUBTAG) {
+ struct erl_off_heap_header* oh;
+
+ oh = (struct erl_off_heap_header*) ptr;
+ if (oh->next) {
+ Eterm** uptr = (Eterm **) (void *) &oh->next;
+ *uptr += offset;
+ }
+ }
+ ptr += 1 + thing_arityval(val);
}
break;
default:
@@ -3695,7 +4004,23 @@ freeze_code(LoaderState* stp)
}
}
ASSERT(ptr == high);
+
+ /*
+ * Re-link the off_heap list for this term onto the
+ * off_heap list for the entire module.
+ */
+ t_off_heap = stp->literals[i].off_heap.first;
+ if (t_off_heap) {
+ t_off_heap = (struct erl_off_heap_header *)
+ offset_ptr((UWord) t_off_heap, offset);
+ while (t_off_heap) {
+ *off_heap_last = t_off_heap;
+ off_heap_last = &t_off_heap->next;
+ t_off_heap = t_off_heap->next;
+ }
+ }
}
+ code[MI_LITERALS_OFF_HEAP] = (BeamInstr) off_heap;
lp = stp->literal_patches;
while (lp != 0) {
BeamInstr* op_ptr;
@@ -3713,21 +4038,72 @@ freeze_code(LoaderState* stp)
}
literal_end += stp->total_literal_size;
}
-
+ CHKBLK(ERTS_ALC_T_CODE,code);
+
/*
- * Place the string table and, optionally, attributes, after the literal heap.
+ * If there is line information, place it here.
*/
- CHKBLK(ERTS_ALC_T_CODE,code);
+ if (stp->line_instr == 0) {
+ code[MI_LINE_TABLE] = (BeamInstr) 0;
+ str_table = (byte *) literal_end;
+ } 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;
+
+ code[MI_LINE_TABLE] = (BeamInstr) line_tab;
+ p = line_tab + MI_LINE_FUNC_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]);
+ }
+ *p++ = (Eterm) (BeamInstr) (first_line_item + num_instrs);
+ ASSERT(p == first_line_item);
+ for (i = 0; i < num_instrs; i++) {
+ *p++ = (Eterm) (BeamInstr) (code + stp->line_instr[i].pos);
+ }
+ *p++ = (Eterm) (BeamInstr) (code + 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[MI_LINE_LOC_TAB] = (Eterm) (BeamInstr) p;
+ line_tab[MI_LINE_LOC_SIZE] = stp->loc_size;
+ if (stp->loc_size == 2) {
+ Uint16* locp = (Uint16 *) p;
+ for (i = 0; i < num_instrs; i++) {
+ *locp++ = (Uint16) stp->line_instr[i].loc;
+ }
+ *locp++ = LINE_INVALID_LOCATION;
+ str_table = (byte *) locp;
+ } else {
+ Uint32* locp = (Uint32 *) p;
+ ASSERT(stp->loc_size == 4);
+ for (i = 0; i < num_instrs; i++) {
+ *locp++ = stp->line_instr[i].loc;
+ }
+ *locp++ = LINE_INVALID_LOCATION;
+ str_table = (byte *) locp;
+ }
- sys_memcpy(literal_end, stp->chunks[STR_CHUNK].start, strtab_size);
+ CHKBLK(ERTS_ALC_T_CODE,code);
+ }
+
+ /*
+ * Place the string table and, optionally, attributes here.
+ */
+ sys_memcpy(str_table, stp->chunks[STR_CHUNK].start, strtab_size);
CHKBLK(ERTS_ALC_T_CODE,code);
- str_table = (byte *) literal_end;
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;
- decoded_size = erts_decode_ext_size(attr, attr_size, 0);
+ decoded_size = erts_decode_ext_size(attr, attr_size);
if (decoded_size < 0) {
LoadError0(stp, "bad external term representation of module attributes");
}
@@ -3745,7 +4121,7 @@ freeze_code(LoaderState* stp)
CHKBLK(ERTS_ALC_T_CODE,code);
code[MI_COMPILE_SIZE] = (BeamInstr) stp->chunks[COMPILE_CHUNK].size;
CHKBLK(ERTS_ALC_T_CODE,code);
- decoded_size = erts_decode_ext_size(compile_info, compile_size, 0);
+ decoded_size = erts_decode_ext_size(compile_info, compile_size);
CHKBLK(ERTS_ALC_T_CODE,code);
if (decoded_size < 0) {
LoadError0(stp, "bad external term representation of compilation information");
@@ -3762,20 +4138,8 @@ freeze_code(LoaderState* stp)
((byte *) code) + size);
/*
- * Go through all i_new_bs_put_strings instructions, restore the pointer to
- * the instruction and convert string offsets to pointers (to the
- * FIRST character).
+ * Patch all instructions that refer to the string table.
*/
-
- index = stp->new_bs_put_strings;
- while (index != 0) {
- Uint next = code[index];
- code[index] = BeamOpCode(op_bs_put_string_II);
- code[index+2] = (BeamInstr) (str_table + code[index+2]);
- index = next;
- }
- CHKBLK(ERTS_ALC_T_CODE,code);
-
{
StringPatch* sp = stp->string_patches;
@@ -3816,21 +4180,6 @@ freeze_code(LoaderState* stp)
CHKBLK(ERTS_ALC_T_CODE,code);
/*
- * Fix all catch_yf instructions.
- */
- index = stp->catches;
- catches = BEAM_CATCHES_NIL;
- while (index != 0) {
- BeamInstr next = code[index];
- code[index] = BeamOpCode(op_catch_yf);
- catches = beam_catches_cons((BeamInstr *)code[index+2], catches);
- code[index+2] = make_catch(catches);
- index = next;
- }
- stp->catches = catches;
- CHKBLK(ERTS_ALC_T_CODE,code);
-
- /*
* Save the updated code pointer and code size.
*/
@@ -3855,6 +4204,26 @@ final_touch(LoaderState* stp)
{
int i;
int on_load = stp->on_load;
+ unsigned catches;
+ Uint index;
+ BeamInstr* code = stp->code;
+ Module* modp;
+
+ /*
+ * Allocate catch indices and fix up all catch_yf instructions.
+ */
+
+ index = stp->catches;
+ catches = BEAM_CATCHES_NIL;
+ while (index != 0) {
+ BeamInstr next = code[index];
+ code[index] = BeamOpCode(op_catch_yf);
+ catches = beam_catches_cons((BeamInstr *)code[index+2], catches);
+ code[index+2] = make_catch(catches);
+ index = next;
+ }
+ modp = erts_put_module(stp->module);
+ modp->catches = catches;
/*
* Export functions.
@@ -3938,6 +4307,7 @@ transform_engine(LoaderState* st)
GenOp* instr;
Uint* pc;
int rval;
+ static Uint restart_fail[1] = {TOP_fail};
ASSERT(gen_opc[st->genop->op].transform != -1);
pc = op_transform + gen_opc[st->genop->op].transform;
@@ -3951,7 +4321,6 @@ transform_engine(LoaderState* st)
ASSERT(restart != NULL);
pc = restart;
ASSERT(*pc < NUM_TOPS); /* Valid instruction? */
- ASSERT(*pc == TOP_try_me_else || *pc == TOP_fail);
instr = st->genop;
#define RETURN(r) rval = (r); goto do_return;
@@ -3964,7 +4333,9 @@ transform_engine(LoaderState* st)
op = *pc++;
switch (op) {
- case TOP_is_op:
+ case TOP_next_instr:
+ instr = instr->next;
+ ap = 0;
if (instr == NULL) {
/*
* We'll need at least one more instruction to decide whether
@@ -4151,10 +4522,6 @@ transform_engine(LoaderState* st)
case TOP_next_arg:
ap++;
break;
- case TOP_next_instr:
- instr = instr->next;
- ap = 0;
- break;
case TOP_commit:
instr = instr->next; /* The next_instr was optimized away. */
@@ -4172,8 +4539,8 @@ transform_engine(LoaderState* st)
#endif
break;
-#if defined(TOP_call)
- case TOP_call:
+#if defined(TOP_call_end)
+ case TOP_call_end:
{
GenOp** lastp;
GenOp* new_instr;
@@ -4210,7 +4577,7 @@ transform_engine(LoaderState* st)
*lastp = st->genop;
st->genop = new_instr;
}
- break;
+ RETURN(TE_OK);
#endif
case TOP_new_instr:
/*
@@ -4219,12 +4586,10 @@ transform_engine(LoaderState* st)
NEW_GENOP(st, instr);
instr->next = st->genop;
st->genop = instr;
+ instr->op = op = *pc++;
+ instr->arity = gen_opc[op].arity;
ap = 0;
break;
- case TOP_store_op:
- instr->op = *pc++;
- instr->arity = *pc++;
- break;
case TOP_store_type:
i = *pc++;
instr->a[ap].type = i;
@@ -4234,21 +4599,25 @@ transform_engine(LoaderState* st)
i = *pc++;
instr->a[ap].val = i;
break;
- case TOP_store_var:
+ case TOP_store_var_next_arg:
i = *pc++;
ASSERT(i < TE_MAX_VARS);
instr->a[ap].type = var[i].type;
instr->a[ap].val = var[i].val;
+ ap++;
break;
case TOP_try_me_else:
restart = pc + 1;
restart += *pc++;
ASSERT(*pc < NUM_TOPS); /* Valid instruction? */
break;
+ case TOP_try_me_else_fail:
+ restart = restart_fail;
+ break;
case TOP_end:
RETURN(TE_OK);
case TOP_fail:
- RETURN(TE_FAIL)
+ RETURN(TE_FAIL);
default:
ASSERT(0);
}
@@ -4317,41 +4686,9 @@ load_printf(int line, LoaderState* context, char *fmt,...)
erts_send_error_to_logger(context->group_leader, dsbufp);
}
-
-static int
-get_int_val(LoaderState* stp, Uint len_code, BeamInstr* result)
-{
- Uint count;
- Uint val;
-
- len_code >>= 5;
- ASSERT(len_code < 8);
- if (len_code == 7) {
- LoadError0(stp, "can't load integers bigger than 8 bytes yet\n");
- }
- count = len_code + 2;
- if (count == 5) {
- Uint msb;
- GetByte(stp, msb);
- if (msb == 0) {
- count--;
- }
- GetInt(stp, 4, *result);
- } else if (count <= 4) {
- GetInt(stp, count, val);
- *result = ((val << 8*(sizeof(val)-count)) >> 8*(sizeof(val)-count));
- } else {
- LoadError1(stp, "too big integer; %d bytes\n", count);
- }
- return 1;
-
- load_error:
- return 0;
-}
-
-
static int
-get_erlang_integer(LoaderState* stp, Uint len_code, BeamInstr* result)
+get_tag_and_value(LoaderState* stp, Uint len_code,
+ unsigned tag, BeamInstr* result)
{
Uint count;
Sint val;
@@ -4371,17 +4708,62 @@ get_erlang_integer(LoaderState* stp, Uint len_code, BeamInstr* result)
if (len_code < 7) {
count = len_code + 2;
} else {
- Uint tag;
+ unsigned sztag;
UWord len_word;
ASSERT(len_code == 7);
- GetTagAndValue(stp, tag, len_word);
- VerifyTag(stp, TAG_u, tag);
+ GetTagAndValue(stp, sztag, len_word);
+ VerifyTag(stp, sztag, TAG_u);
count = len_word + 9;
}
/*
- * Handle values up to the size of an int, meaning either a small or bignum.
+ * The value for tags except TAG_i must be an unsigned integer
+ * fitting in an Uint. If it does not fit, we'll indicate overflow
+ * by changing the tag to TAG_o.
+ */
+
+ if (tag != TAG_i) {
+ if (count == sizeof(Uint)+1) {
+ Uint msb;
+
+ /*
+ * The encoded value has one more byte than an Uint.
+ * It will still fit in an Uint if the most significant
+ * byte is 0.
+ */
+ GetByte(stp, msb);
+ GetInt(stp, sizeof(Uint), *result);
+ if (msb != 0) {
+ /* Overflow: Negative or too big. */
+ return TAG_o;
+ }
+ } else if (count == sizeof(Uint)) {
+ /*
+ * The value must be positive (or the encoded value would
+ * have been one byte longer).
+ */
+ GetInt(stp, count, *result);
+ } else if (count < sizeof(Uint)) {
+ GetInt(stp, count, *result);
+
+ /*
+ * If the sign bit is set, the value is negative
+ * (not allowed).
+ */
+ if (*result & ((Uint)1 << (count*8-1))) {
+ return TAG_o;
+ }
+ } else {
+ GetInt(stp, count, *result);
+ return TAG_o;
+ }
+ return tag;
+ }
+
+ /*
+ * TAG_i: First handle values up to the size of an Uint (i.e. either
+ * a small or a bignum).
*/
if (count <= sizeof(val)) {
@@ -4558,6 +4940,8 @@ new_literal(LoaderState* stp, Eterm** hpp, Uint heap_size)
lit->heap_size = heap_size;
lit->heap = erts_alloc(ERTS_ALC_T_LOADER_TMP, heap_size*sizeof(Eterm));
lit->term = make_boxed(lit->heap);
+ lit->off_heap.first = 0;
+ lit->off_heap.overhead = 0;
*hpp = lit->heap;
return stp->num_literals++;
}
@@ -4836,17 +5220,24 @@ compilation_info_for_module(Process* p, /* Process whose heap to use. */
return result;
}
-
/*
- * Returns a pointer to {module, function, arity}, or NULL if not found.
+ * Find a function from the given pc and fill information in
+ * the FunctionInfo struct. If the full_info is non-zero, fill
+ * in all available information (including location in the
+ * source code). If no function is found, the 'current' field
+ * will be set to NULL.
*/
-BeamInstr *
-find_function_from_pc(BeamInstr* pc)
+
+void
+erts_lookup_function_info(FunctionInfo* fi, BeamInstr* pc, int full_info)
{
Range* low = modules;
Range* high = low + num_loaded_modules;
Range* mid = mid_module;
+ fi->current = NULL;
+ fi->needed = 5;
+ fi->loc = LINE_INVALID_LOCATION;
while (low < high) {
if (pc < mid->start) {
high = mid;
@@ -4863,25 +5254,159 @@ find_function_from_pc(BeamInstr* pc)
high1 = mid1;
} else if (pc < mid1[1]) {
mid_module = mid;
- return mid1[0]+2;
+ fi->current = mid1[0]+2;
+ if (full_info) {
+ BeamInstr** fp = (BeamInstr **) (mid->start +
+ MI_FUNCTIONS);
+ int idx = mid1 - fp;
+ lookup_loc(fi, pc, mid->start, idx);
+ }
+ return;
} else {
low1 = mid1 + 1;
}
}
- return NULL;
+ return;
}
mid = low + (high-low) / 2;
}
- return NULL;
+}
+
+static void
+lookup_loc(FunctionInfo* fi, BeamInstr* orig_pc, BeamInstr* modp, int idx)
+{
+ Eterm* line = (Eterm *) modp[MI_LINE_TABLE];
+ Eterm* low;
+ Eterm* high;
+ Eterm* mid;
+ Eterm pc;
+
+ if (line == 0) {
+ 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];
+ 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];
+
+ if (line[MI_LINE_LOC_SIZE] == 2) {
+ Uint16* loc_table =
+ (Uint16 *) (BeamInstr) line[MI_LINE_LOC_TAB];
+ fi->loc = loc_table[index];
+ } else {
+ Uint32* loc_table =
+ (Uint32 *) (BeamInstr) line[MI_LINE_LOC_TAB];
+ ASSERT(line[MI_LINE_LOC_SIZE] == 4);
+ fi->loc = loc_table[index];
+ }
+ if (fi->loc == LINE_INVALID_LOCATION) {
+ return;
+ }
+ fi->needed += 3+2+3+2;
+ file = LOC_FILE(fi->loc);
+ if (file == 0) {
+ /* Special case: Module name with ".erl" appended */
+ Atom* mod_atom = atom_tab(atom_val(fi->current[0]));
+ fi->needed += 2*(mod_atom->len+4);
+ } else {
+ Atom* ap = atom_tab(atom_val((fi->fname_ptr)[file-1]));
+ fi->needed += 2*ap->len;
+ }
+ return;
+ } else {
+ low = mid + 1;
+ }
+ }
+}
+
+/*
+ * Build a single {M,F,A,Loction} item to be part of
+ * a stack trace.
+ */
+Eterm*
+erts_build_mfa_item(FunctionInfo* fi, Eterm* hp, Eterm args, Eterm* mfa_p)
+{
+ BeamInstr* current = fi->current;
+ Eterm loc = NIL;
+
+ if (fi->loc != LINE_INVALID_LOCATION) {
+ Eterm tuple;
+ int line = LOC_LINE(fi->loc);
+ int file = LOC_FILE(fi->loc);
+ Eterm file_term = NIL;
+
+ if (file == 0) {
+ Atom* ap = atom_tab(atom_val(fi->current[0]));
+ file_term = buf_to_intlist(&hp, ".erl", 4, NIL);
+ file_term = buf_to_intlist(&hp, (char*)ap->name, ap->len, file_term);
+ } else {
+ Atom* ap = atom_tab(atom_val((fi->fname_ptr)[file-1]));
+ file_term = buf_to_intlist(&hp, (char*)ap->name, ap->len, NIL);
+ }
+
+ tuple = TUPLE2(hp, am_line, make_small(line));
+ hp += 3;
+ loc = CONS(hp, tuple, loc);
+ hp += 2;
+ tuple = TUPLE2(hp, am_file, file_term);
+ hp += 3;
+ loc = CONS(hp, tuple, loc);
+ hp += 2;
+ }
+
+ if (is_list(args) || is_nil(args)) {
+ *mfa_p = TUPLE4(hp, current[0], current[1], args, loc);
+ } else {
+ Eterm arity = make_small(current[2]);
+ *mfa_p = TUPLE4(hp, current[0], current[1], arity, loc);
+ }
+ return hp + 5;
+}
+
+/*
+ * Force setting of the current function in a FunctionInfo
+ * structure. No source code location will be associated with
+ * the function.
+ */
+void
+erts_set_current_function(FunctionInfo* fi, BeamInstr* current)
+{
+ fi->current = current;
+ fi->needed = 5;
+ fi->loc = LINE_INVALID_LOCATION;
+}
+
+
+/*
+ * Returns a pointer to {module, function, arity}, or NULL if not found.
+ */
+BeamInstr*
+find_function_from_pc(BeamInstr* pc)
+{
+ FunctionInfo fi;
+
+ erts_lookup_function_info(&fi, pc, 0);
+ return fi.current;
}
/*
* Read a specific chunk from a Beam binary.
*/
-Eterm
-code_get_chunk_2(Process* p, Eterm Bin, Eterm Chunk)
+BIF_RETTYPE
+code_get_chunk_2(BIF_ALIST_2)
{
+ Process* p = BIF_P;
+ Eterm Bin = BIF_ARG_1;
+ Eterm Chunk = BIF_ARG_2;
LoaderState state;
Uint chunk = 0;
ErlSubBin* sb;
@@ -4946,9 +5471,11 @@ code_get_chunk_2(Process* p, Eterm Bin, Eterm Chunk)
* Calculate the MD5 for a module.
*/
-Eterm
-code_module_md5_1(Process* p, Eterm Bin)
+BIF_RETTYPE
+code_module_md5_1(BIF_ALIST_1)
{
+ Process* p = BIF_P;
+ Eterm Bin = BIF_ARG_1;
LoaderState state;
byte* temp_alloc = NULL;
@@ -4998,7 +5525,7 @@ stub_copy_info(LoaderState* stp,
if (size != 0) {
memcpy(info, stp->chunks[chunk].start, size);
*ptr_word = (BeamInstr) info;
- decoded_size = erts_decode_ext_size(info, size, 0);
+ decoded_size = erts_decode_ext_size(info, size);
if (decoded_size < 0) {
return 0;
}
@@ -5205,7 +5732,17 @@ patch_funentries(Eterm Patchlist)
fe = erts_get_fun_entry(Mod, uniq, index);
fe->native_address = (Uint *)native_address;
- erts_refc_dec(&fe->refc, 1);
+
+ /* Deliberate MEMORY LEAK of native fun entries!!!
+ *
+ * Uncomment line below when hipe code upgrade and purging works correctly.
+ * Today we may get cases when old (leaked) native code of a purged module
+ * gets called and tries to create instances of a deleted fun entry.
+ *
+ * Reproduced on a debug emulator with stdlib_test/qlc_SUITE:join_merge
+ *
+ * erts_refc_dec(&fe->refc, 1);
+ */
if (!patch(Addresses, (Uint) fe))
return 0;
@@ -5226,7 +5763,7 @@ patch_funentries(Eterm Patchlist)
Eterm
erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
{
- LoaderState state;
+ LoaderState* stp;
BeamInstr Funcs;
BeamInstr Patchlist;
Eterm* tp;
@@ -5245,10 +5782,10 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
Uint size;
/*
- * Must initialize state.lambdas here because the error handling code
+ * Must initialize stp->lambdas here because the error handling code
* at label 'error' uses it.
*/
- init_state(&state);
+ stp = erts_alloc_loader_state();
if (is_not_atom(Mod)) {
goto error;
@@ -5288,31 +5825,31 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
* Scan the Beam binary and read the interesting sections.
*/
- state.file_name = "IFF header for Beam file";
- state.file_p = bytes;
- state.file_left = size;
- state.module = Mod;
- state.group_leader = p->group_leader;
- state.num_functions = n;
- if (!scan_iff_file(&state, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY)) {
+ stp->file_name = "IFF header for Beam file";
+ stp->file_p = bytes;
+ stp->file_left = size;
+ stp->module = Mod;
+ stp->group_leader = p->group_leader;
+ stp->num_functions = n;
+ if (!scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY)) {
goto error;
}
- define_file(&state, "code chunk header", CODE_CHUNK);
- if (!read_code_header(&state)) {
+ define_file(stp, "code chunk header", CODE_CHUNK);
+ if (!read_code_header(stp)) {
goto error;
}
- define_file(&state, "atom table", ATOM_CHUNK);
- if (!load_atom_table(&state)) {
+ define_file(stp, "atom table", ATOM_CHUNK);
+ if (!load_atom_table(stp)) {
goto error;
}
- define_file(&state, "export table", EXP_CHUNK);
- if (!stub_read_export_table(&state)) {
+ define_file(stp, "export table", EXP_CHUNK);
+ if (!stub_read_export_table(stp)) {
goto error;
}
- if (state.chunks[LAMBDA_CHUNK].size > 0) {
- define_file(&state, "lambda (fun) table", LAMBDA_CHUNK);
- if (!read_lambda_table(&state)) {
+ if (stp->chunks[LAMBDA_CHUNK].size > 0) {
+ define_file(stp, "lambda (fun) table", LAMBDA_CHUNK);
+ if (!read_lambda_table(stp)) {
goto error;
}
}
@@ -5322,8 +5859,8 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
*/
code_size = ((WORDS_PER_FUNCTION+1)*n + MI_FUNCTIONS + 2) * sizeof(BeamInstr);
- code_size += state.chunks[ATTR_CHUNK].size;
- code_size += state.chunks[COMPILE_CHUNK].size;
+ code_size += stp->chunks[ATTR_CHUNK].size;
+ code_size += stp->chunks[COMPILE_CHUNK].size;
code = erts_alloc_fnf(ERTS_ALC_T_CODE, code_size);
if (!code) {
goto error;
@@ -5341,6 +5878,9 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
code[MI_COMPILE_SIZE] = 0;
code[MI_COMPILE_SIZE_ON_HEAP] = 0;
code[MI_NUM_BREAKPOINTS] = 0;
+ code[MI_LITERALS_START] = 0;
+ code[MI_LITERALS_END] = 0;
+ code[MI_LITERALS_OFF_HEAP] = 0;
code[MI_ON_LOAD_FUNCTION_PTR] = 0;
ci = MI_FUNCTIONS + n + 1;
@@ -5413,12 +5953,12 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
*/
info = (byte *) fp;
- info = stub_copy_info(&state, ATTR_CHUNK, info,
+ info = stub_copy_info(stp, ATTR_CHUNK, info,
code+MI_ATTR_PTR, code+MI_ATTR_SIZE_ON_HEAP);
if (info == NULL) {
goto error;
}
- info = stub_copy_info(&state, COMPILE_CHUNK, info,
+ info = stub_copy_info(stp, COMPILE_CHUNK, info,
code+MI_COMPILE_PTR, code+MI_COMPILE_SIZE_ON_HEAP);
if (info == NULL) {
goto error;
@@ -5428,9 +5968,8 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
* Insert the module in the module table.
*/
- rval = insert_new_code(p, 0, p->group_leader, Mod, code, code_size,
- BEAM_CATCHES_NIL);
- if (rval < 0) {
+ rval = insert_new_code(p, 0, p->group_leader, Mod, code, code_size);
+ if (rval != NIL) {
goto error;
}
@@ -5440,18 +5979,13 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
fp = code + ci;
for (i = 0; i < n; i++) {
- stub_final_touch(&state, fp);
+ stub_final_touch(stp, fp);
fp += WORDS_PER_FUNCTION;
}
if (patch_funentries(Patchlist)) {
erts_free_aligned_binary_bytes(temp_alloc);
- if (state.lambdas != state.def_lambdas) {
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.lambdas);
- }
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.labels);
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.atom);
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.export);
+ free_state(stp);
if (bin != NULL) {
driver_free_binary(bin);
}
@@ -5459,27 +5993,7 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
}
error:
- erts_free_aligned_binary_bytes(temp_alloc);
- if (code != NULL) {
- erts_free(ERTS_ALC_T_CODE, code);
- }
- if (state.labels != NULL) {
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.labels);
- }
- if (state.lambdas != state.def_lambdas) {
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.lambdas);
- }
- if (state.atom != NULL) {
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.atom);
- }
- if (state.export != NULL) {
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.export);
- }
- if (bin != NULL) {
- driver_free_binary(bin);
- }
-
-
+ free_state(stp);
BIF_ERROR(p, BADARG);
}
diff --git a/erts/emulator/beam/beam_load.h b/erts/emulator/beam/beam_load.h
index 26e3054c4b..4e22ee4d79 100644
--- a/erts/emulator/beam/beam_load.h
+++ b/erts/emulator/beam/beam_load.h
@@ -23,7 +23,9 @@
#include "beam_opcodes.h"
#include "erl_process.h"
-int beam_make_current_old(Process *c_p, ErtsProcLocks c_p_locks, Eterm module);
+Eterm beam_make_current_old(Process *c_p, ErtsProcLocks c_p_locks,
+ Eterm module);
+
typedef struct gen_op_entry {
char* name;
@@ -101,11 +103,18 @@ extern Uint erts_total_code_size;
*/
#define MI_LITERALS_START 8
#define MI_LITERALS_END 9
+#define MI_LITERALS_OFF_HEAP 10
+
/*
* Pointer to the on_load function (or NULL if none).
*/
-#define MI_ON_LOAD_FUNCTION_PTR 10
+#define MI_ON_LOAD_FUNCTION_PTR 11
+
+/*
+ * Pointer to the line table (or NULL if none).
+ */
+#define MI_LINE_TABLE 12
/*
* Start of function pointer table. This table contains pointers to
@@ -116,5 +125,5 @@ extern Uint erts_total_code_size;
* this table.
*/
-#define MI_FUNCTIONS 11
+#define MI_FUNCTIONS 13
#endif /* _BEAM_LOAD_H */
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index 68b3350d7f..8ab363a1ec 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -36,6 +36,7 @@
#include "beam_bp.h"
#include "erl_db_util.h"
#include "register.h"
+#include "erl_thr_progress.h"
static Export* flush_monitor_message_trap = NULL;
static Export* set_cpu_topology_trap = NULL;
@@ -811,7 +812,7 @@ BIF_RETTYPE spawn_opt_1(BIF_ALIST_1)
so.min_heap_size = H_MIN_SIZE;
so.min_vheap_size = BIN_VH_MIN_SIZE;
so.priority = PRIORITY_NORMAL;
- so.max_gen_gcs = (Uint16) erts_smp_atomic32_read(&erts_max_gen_gcs);
+ so.max_gen_gcs = (Uint16) erts_smp_atomic32_read_nob(&erts_max_gen_gcs);
so.scheduler = 0;
/*
@@ -1107,9 +1108,9 @@ BIF_RETTYPE hibernate_3(BIF_ALIST_3)
/**********************************************************************/
-BIF_RETTYPE get_stacktrace_0(Process* p)
+BIF_RETTYPE get_stacktrace_0(BIF_ALIST_0)
{
- Eterm t = build_stacktrace(p, p->ftrace);
+ Eterm t = build_stacktrace(BIF_P, BIF_P->ftrace);
BIF_RET(t);
}
@@ -1119,10 +1120,10 @@ BIF_RETTYPE get_stacktrace_0(Process* p)
* the process, and the final error value will be {Term,StackTrace}.
*/
-BIF_RETTYPE error_1(Process* p, Eterm term)
+BIF_RETTYPE error_1(BIF_ALIST_1)
{
- p->fvalue = term;
- BIF_ERROR(p, EXC_ERROR);
+ BIF_P->fvalue = BIF_ARG_1;
+ BIF_ERROR(BIF_P, EXC_ERROR);
}
/**********************************************************************/
@@ -1131,12 +1132,12 @@ BIF_RETTYPE error_1(Process* p, Eterm term)
* in the stacktrace.
*/
-BIF_RETTYPE error_2(Process* p, Eterm value, Eterm args)
+BIF_RETTYPE error_2(BIF_ALIST_2)
{
- Eterm* hp = HAlloc(p, 3);
+ Eterm* hp = HAlloc(BIF_P, 3);
- p->fvalue = TUPLE2(hp, value, args);
- BIF_ERROR(p, EXC_ERROR_2);
+ BIF_P->fvalue = TUPLE2(hp, BIF_ARG_1, BIF_ARG_2);
+ BIF_ERROR(BIF_P, EXC_ERROR_2);
}
/**********************************************************************/
@@ -1146,10 +1147,10 @@ BIF_RETTYPE error_2(Process* p, Eterm value, Eterm args)
* It is useful in stub functions for NIFs.
*/
-BIF_RETTYPE nif_error_1(Process* p, Eterm term)
+BIF_RETTYPE nif_error_1(BIF_ALIST_1)
{
- p->fvalue = term;
- BIF_ERROR(p, EXC_ERROR);
+ BIF_P->fvalue = BIF_ARG_1;
+ BIF_ERROR(BIF_P, EXC_ERROR);
}
/**********************************************************************/
@@ -1159,12 +1160,12 @@ BIF_RETTYPE nif_error_1(Process* p, Eterm term)
* It is useful in stub functions for NIFs.
*/
-BIF_RETTYPE nif_error_2(Process* p, Eterm value, Eterm args)
+BIF_RETTYPE nif_error_2(BIF_ALIST_2)
{
- Eterm* hp = HAlloc(p, 3);
+ Eterm* hp = HAlloc(BIF_P, 3);
- p->fvalue = TUPLE2(hp, value, args);
- BIF_ERROR(p, EXC_ERROR_2);
+ BIF_P->fvalue = TUPLE2(hp, BIF_ARG_1, BIF_ARG_2);
+ BIF_ERROR(BIF_P, EXC_ERROR_2);
}
/**********************************************************************/
@@ -1183,14 +1184,19 @@ BIF_RETTYPE exit_1(BIF_ALIST_1)
* If there is an error in the argument format,
* return the atom 'badarg' instead.
*/
-Eterm
-raise_3(Process *c_p, Eterm class, Eterm value, Eterm stacktrace) {
+BIF_RETTYPE raise_3(BIF_ALIST_3)
+{
+ Process *c_p = BIF_P;
+ Eterm class = BIF_ARG_1;
+ Eterm value = BIF_ARG_2;
+ Eterm stacktrace = BIF_ARG_3;
Eterm reason;
Eterm l, *hp, *hp_end, *tp;
int depth, cnt;
size_t sz;
+ int must_copy = 0;
struct StackTrace *s;
-
+
if (class == am_error) {
c_p->fvalue = value;
reason = EXC_ERROR;
@@ -1206,35 +1212,74 @@ raise_3(Process *c_p, Eterm class, Eterm value, Eterm stacktrace) {
/* Check syntax of stacktrace, and count depth.
* Accept anything that can be returned from erlang:get_stacktrace/0,
* as well as a 2-tuple with a fun as first element that the
- * error_handler may need to give us.
+ * error_handler may need to give us. Also allow old-style
+ * MFA three-tuples.
*/
for (l = stacktrace, depth = 0;
is_list(l);
l = CDR(list_val(l)), depth++) {
Eterm t = CAR(list_val(l));
- int arity;
+ Eterm location = NIL;
+
if (is_not_tuple(t)) goto error;
tp = tuple_val(t);
- arity = arityval(tp[0]);
- if ((arity == 3) && is_atom(tp[1]) && is_atom(tp[2])) continue;
- if ((arity == 2) && is_fun(tp[1])) continue;
- goto error;
+ switch (arityval(tp[0])) {
+ case 2:
+ /* {Fun,Args} */
+ if (is_fun(tp[1])) {
+ must_copy = 1;
+ } else {
+ goto error;
+ }
+ break;
+ case 3:
+ /*
+ * One of:
+ * {Fun,Args,Location}
+ * {M,F,A}
+ */
+ if (is_fun(tp[1])) {
+ location = tp[3];
+ } else if (is_atom(tp[1]) && is_atom(tp[2])) {
+ must_copy = 1;
+ } else {
+ goto error;
+ }
+ break;
+ case 4:
+ if (!(is_atom(tp[1]) && is_atom(tp[2]))) {
+ goto error;
+ }
+ location = tp[4];
+ break;
+ default:
+ goto error;
+ }
+ if (is_not_list(location) && is_not_nil(location)) {
+ goto error;
+ }
}
if (is_not_nil(l)) goto error;
/* Create stacktrace and store */
- if (depth <= erts_backtrace_depth) {
+ if (erts_backtrace_depth < depth) {
+ depth = erts_backtrace_depth;
+ must_copy = 1;
+ }
+ if (must_copy) {
+ cnt = depth;
+ c_p->ftrace = NIL;
+ } else {
+ /* No need to copy the stacktrace */
cnt = 0;
c_p->ftrace = stacktrace;
- } else {
- cnt = depth = erts_backtrace_depth;
- c_p->ftrace = NIL;
}
+
tp = &c_p->ftrace;
sz = (offsetof(struct StackTrace, trace) + sizeof(Eterm) - 1)
/ sizeof(Eterm);
- hp = HAlloc(c_p, sz + 2*(cnt + 1));
- hp_end = hp + sz + 2*(cnt + 1);
+ hp = HAlloc(c_p, sz + (2+6)*(cnt + 1));
+ hp_end = hp + sz + (2+6)*(cnt + 1);
s = (struct StackTrace *) hp;
s->header = make_neg_bignum_header(sz - 1);
s->freason = reason;
@@ -1242,13 +1287,29 @@ raise_3(Process *c_p, Eterm class, Eterm value, Eterm stacktrace) {
s->current = NULL;
s->depth = 0;
hp += sz;
- if (cnt > 0) {
+ if (must_copy) {
+ int cnt;
+
/* Copy list up to depth */
for (cnt = 0, l = stacktrace;
cnt < depth;
cnt++, l = CDR(list_val(l))) {
+ Eterm t;
+ Eterm *tpp;
+ int arity;
+
ASSERT(*tp == NIL);
- *tp = CONS(hp, CAR(list_val(l)), *tp);
+ t = CAR(list_val(l));
+ tpp = tuple_val(t);
+ arity = arityval(tpp[0]);
+ if (arity == 2) {
+ t = TUPLE3(hp, tpp[1], tpp[2], NIL);
+ hp += 4;
+ } else if (arity == 3 && is_atom(tpp[1])) {
+ t = TUPLE4(hp, tpp[1], tpp[2], tpp[3], NIL);
+ hp += 5;
+ }
+ *tp = CONS(hp, t, *tp);
tp = &CDR(list_val(*tp));
hp += 2;
}
@@ -1256,7 +1317,7 @@ raise_3(Process *c_p, Eterm class, Eterm value, Eterm stacktrace) {
c_p->ftrace = CONS(hp, c_p->ftrace, make_big((Eterm *) s));
hp += 2;
ASSERT(hp <= hp_end);
-
+ HRelease(c_p, hp_end, hp);
BIF_ERROR(c_p, reason);
error:
@@ -1674,10 +1735,10 @@ BIF_RETTYPE whereis_1(BIF_ALIST_1)
* erlang:'!'/2
*/
-Eterm
-ebif_bang_2(Process* p, Eterm To, Eterm Message)
+BIF_RETTYPE
+ebif_bang_2(BIF_ALIST_2)
{
- return send_2(p, To, Message);
+ return erl_send(BIF_P, BIF_ARG_1, BIF_ARG_2);
}
@@ -2014,8 +2075,13 @@ do_send(Process *p, Eterm to, Eterm msg, int suspend) {
}
-Eterm
-send_3(Process *p, Eterm to, Eterm msg, Eterm opts) {
+BIF_RETTYPE send_3(BIF_ALIST_3)
+{
+ Process *p = BIF_P;
+ Eterm to = BIF_ARG_1;
+ Eterm msg = BIF_ARG_2;
+ Eterm opts = BIF_ARG_3;
+
int connect = !0;
int suspend = !0;
Eterm l = opts;
@@ -2079,8 +2145,13 @@ send_3(Process *p, Eterm to, Eterm msg, Eterm opts) {
BIF_ERROR(p, BADARG);
}
-Eterm
-send_2(Process *p, Eterm to, Eterm msg) {
+BIF_RETTYPE send_2(BIF_ALIST_2)
+{
+ return erl_send(BIF_P, BIF_ARG_1, BIF_ARG_2);
+}
+
+Eterm erl_send(Process *p, Eterm to, Eterm msg)
+{
Sint result = do_send(p, to, msg, !0);
if (result > 0) {
@@ -3256,8 +3327,11 @@ time_to_parts(Eterm date, Sint* year, Sint* month, Sint* day,
/* return the universal time */
BIF_RETTYPE
-localtime_to_universaltime_2(Process *p, Eterm localtime, Eterm dst)
+localtime_to_universaltime_2(BIF_ALIST_2)
{
+ Process *p = BIF_P;
+ Eterm localtime = BIF_ARG_1;
+ Eterm dst = BIF_ARG_2;
Sint year, month, day;
Sint hour, minute, second;
int isdst;
@@ -3417,10 +3491,10 @@ BIF_RETTYPE ports_0(BIF_ALIST_0)
erts_smp_mtx_lock(&ports_snapshot_mtx); /* One snapshot at a time */
- erts_smp_atomic_set(&erts_dead_ports_ptr,
- (erts_aint_t) (port_buf + erts_max_ports));
+ erts_smp_atomic_set_nob(&erts_dead_ports_ptr,
+ (erts_aint_t) (port_buf + erts_max_ports));
- next_ss = erts_smp_atomic32_inctest(&erts_ports_snapshot);
+ next_ss = erts_smp_atomic32_inc_read_relb(&erts_ports_snapshot);
for (i = erts_max_ports-1; i >= 0; i--) {
Port* prt = &erts_port[i];
@@ -3434,8 +3508,8 @@ BIF_RETTYPE ports_0(BIF_ALIST_0)
erts_smp_port_state_unlock(prt);
}
- dead_ports = (Eterm*)erts_smp_atomic_xchg(&erts_dead_ports_ptr,
- (erts_aint_t) NULL);
+ dead_ports = (Eterm*)erts_smp_atomic_xchg_nob(&erts_dead_ports_ptr,
+ (erts_aint_t) NULL);
erts_smp_mtx_unlock(&ports_snapshot_mtx);
ASSERT(pp <= dead_ports);
@@ -3506,9 +3580,10 @@ BIF_RETTYPE erts_debug_display_1(BIF_ALIST_1)
}
-Eterm
-display_string_1(Process* p, Eterm string)
+BIF_RETTYPE display_string_1(BIF_ALIST_1)
{
+ Process* p = BIF_P;
+ Eterm string = BIF_ARG_1;
int len = is_string(string);
char *str;
@@ -3524,8 +3599,7 @@ display_string_1(Process* p, Eterm string)
BIF_RET(am_true);
}
-Eterm
-display_nl_0(Process* p)
+BIF_RETTYPE display_nl_0(BIF_ALIST_0)
{
erts_fprintf(stderr, "\n");
BIF_RET(am_true);
@@ -3589,8 +3663,13 @@ BIF_RETTYPE function_exported_3(BIF_ALIST_3)
/**********************************************************************/
-BIF_RETTYPE is_builtin_3(Process* p, Eterm Mod, Eterm Name, Eterm Arity)
+BIF_RETTYPE is_builtin_3(BIF_ALIST_3)
{
+ Process* p = BIF_P;
+ Eterm Mod = BIF_ARG_1;
+ Eterm Name = BIF_ARG_2;
+ Eterm Arity = BIF_ARG_3;
+
if (is_not_atom(Mod) || is_not_atom(Name) || is_not_small(Arity)) {
BIF_ERROR(p, BADARG);
}
@@ -3655,9 +3734,11 @@ BIF_RETTYPE make_fun_3(BIF_ALIST_3)
BIF_RET(make_export(hp));
}
-Eterm
-fun_to_list_1(Process* p, Eterm fun)
+BIF_RETTYPE fun_to_list_1(BIF_ALIST_1)
{
+ Process* p = BIF_P;
+ Eterm fun = BIF_ARG_1;
+
if (is_not_any_fun(fun))
BIF_ERROR(p, BADARG);
BIF_RET(term2list_dsprintf(p, fun));
@@ -3942,8 +4023,8 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2)
goto error;
}
nval = (n > (Sint) ((Uint16) -1)) ? ((Uint16) -1) : ((Uint16) n);
- oval = (Uint) erts_smp_atomic32_xchg(&erts_max_gen_gcs,
- (erts_aint32_t) nval);
+ oval = (Uint) erts_smp_atomic32_xchg_nob(&erts_max_gen_gcs,
+ (erts_aint32_t) nval);
BIF_RET(make_small(oval));
} else if (BIF_ARG_1 == am_min_heap_size) {
int oval = H_MIN_SIZE;
@@ -3953,11 +4034,11 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2)
}
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
H_MIN_SIZE = erts_next_heap_size(n, 0);
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
BIF_RET(make_small(oval));
@@ -3969,11 +4050,11 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2)
}
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
BIN_VH_MIN_SIZE = erts_next_heap_size(n, 0);
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
BIF_RET(make_small(oval));
@@ -3995,7 +4076,7 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2)
erts_backtrace_depth = n;
BIF_RET(make_small(oval));
} else if (BIF_ARG_1 == am_trace_control_word) {
- BIF_RET(db_set_trace_control_word_1(BIF_P, BIF_ARG_2));
+ BIF_RET(db_set_trace_control_word(BIF_P, BIF_ARG_2));
} else if (BIF_ARG_1 == am_sequential_tracer) {
Eterm old_value = erts_set_system_seq_tracer(BIF_P,
ERTS_PROC_LOCK_MAIN,
@@ -4007,7 +4088,7 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2)
Uint i;
ErlMessage* mp;
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
for (i = 0; i < erts_max_processes; i++) {
if (process_tab[i] != (Process*) 0) {
@@ -4024,7 +4105,7 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2)
}
}
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
BIF_RET(am_true);
@@ -4235,8 +4316,7 @@ void
erts_bif_prep_await_proc_exit_data_trap(Process *c_p, Eterm pid, Eterm ret)
{
if (skip_current_msgq(c_p)) {
- Eterm unused;
- ERTS_BIF_PREP_TRAP3(unused, await_proc_exit_trap, c_p, pid, am_data, ret);
+ ERTS_BIF_PREP_TRAP3_NO_RET(await_proc_exit_trap, c_p, pid, am_data, ret);
}
}
@@ -4244,8 +4324,7 @@ void
erts_bif_prep_await_proc_exit_reason_trap(Process *c_p, Eterm pid)
{
if (skip_current_msgq(c_p)) {
- Eterm unused;
- ERTS_BIF_PREP_TRAP3(unused, await_proc_exit_trap, c_p,
+ ERTS_BIF_PREP_TRAP3_NO_RET(await_proc_exit_trap, c_p,
pid, am_reason, am_undefined);
}
}
@@ -4260,7 +4339,6 @@ erts_bif_prep_await_proc_exit_apply_trap(Process *c_p,
{
ASSERT(is_atom(module) && is_atom(function));
if (skip_current_msgq(c_p)) {
- Eterm unused;
Eterm term;
Eterm *hp;
int i;
@@ -4272,7 +4350,7 @@ erts_bif_prep_await_proc_exit_apply_trap(Process *c_p,
hp += 2;
}
term = TUPLE3(hp, module, function, term);
- ERTS_BIF_PREP_TRAP3(unused, await_proc_exit_trap, c_p, pid, am_apply, term);
+ ERTS_BIF_PREP_TRAP3_NO_RET(await_proc_exit_trap, c_p, pid, am_apply, term);
}
}
@@ -4286,7 +4364,7 @@ void erts_init_bif(void)
erts_smp_spinlock_init(&make_ref_lock, "make_ref");
erts_smp_mtx_init(&ports_snapshot_mtx, "ports_snapshot");
- erts_smp_atomic_init(&erts_dead_ports_ptr, (erts_aint_t) NULL);
+ erts_smp_atomic_init_nob(&erts_dead_ports_ptr, (erts_aint_t) NULL);
/*
* bif_return_trap/1 is a hidden BIF that bifs that need to
diff --git a/erts/emulator/beam/bif.h b/erts/emulator/beam/bif.h
index 8faa09feb8..d20089a9fb 100644
--- a/erts/emulator/beam/bif.h
+++ b/erts/emulator/beam/bif.h
@@ -26,14 +26,14 @@ extern Export* erts_format_cpu_topology_trap;
#define BIF_P A__p
-#define BIF_ALIST_0 Process* A__p
-#define BIF_ALIST_1 Process* A__p, Eterm A_1
-#define BIF_ALIST_2 Process* A__p, Eterm A_1, Eterm A_2
-#define BIF_ALIST_3 Process* A__p, Eterm A_1, Eterm A_2, Eterm A_3
+#define BIF_ALIST_0 Process* A__p, Eterm* BIF__ARGS
+#define BIF_ALIST_1 Process* A__p, Eterm* BIF__ARGS
+#define BIF_ALIST_2 Process* A__p, Eterm* BIF__ARGS
+#define BIF_ALIST_3 Process* A__p, Eterm* BIF__ARGS
-#define BIF_ARG_1 A_1
-#define BIF_ARG_2 A_2
-#define BIF_ARG_3 A_3
+#define BIF_ARG_1 (BIF__ARGS[0])
+#define BIF_ARG_2 (BIF__ARGS[1])
+#define BIF_ARG_3 (BIF__ARGS[2])
#define BUMP_ALL_REDS(p) do { \
if (!ERTS_PROC_GET_SAVED_CALLS_BUF((p))) \
@@ -122,89 +122,106 @@ do { \
} while (0)
-#define ERTS_BIF_PREP_TRAP0(Ret, Trap, Proc) \
-do { \
- (Proc)->arity = 0; \
- *((UWord *) (UWord) ((Proc)->def_arg_reg + 3)) = (UWord) ((Trap)->address); \
- (Proc)->freason = TRAP; \
- (Ret) = THE_NON_VALUE; \
+#define ERTS_BIF_PREP_TRAP0(Ret, Trap, Proc) \
+do { \
+ (Proc)->arity = 0; \
+ (Proc)->i = (BeamInstr*) ((Trap)->address); \
+ (Proc)->freason = TRAP; \
+ (Ret) = THE_NON_VALUE; \
} while (0)
-#define ERTS_BIF_PREP_TRAP1(Ret, Trap, Proc, A0) \
-do { \
- (Proc)->arity = 1; \
- (Proc)->def_arg_reg[0] = (Eterm) (A0); \
- *((UWord *) (UWord) ((Proc)->def_arg_reg + 3)) = (UWord) ((Trap)->address); \
- (Proc)->freason = TRAP; \
- (Ret) = THE_NON_VALUE; \
+#define ERTS_BIF_PREP_TRAP1(Ret, Trap, Proc, A0) \
+do { \
+ Eterm* reg = ERTS_PROC_GET_SCHDATA((Proc))->x_reg_array; \
+ (Proc)->arity = 1; \
+ reg[0] = (Eterm) (A0); \
+ (Proc)->i = (BeamInstr*) ((Trap)->address); \
+ (Proc)->freason = TRAP; \
+ (Ret) = THE_NON_VALUE; \
} while (0)
-#define ERTS_BIF_PREP_TRAP2(Ret, Trap, Proc, A0, A1) \
-do { \
- (Proc)->arity = 2; \
- (Proc)->def_arg_reg[0] = (Eterm) (A0); \
- (Proc)->def_arg_reg[1] = (Eterm) (A1); \
- *((UWord *) (UWord) ((Proc)->def_arg_reg + 3)) = (UWord) ((Trap)->address); \
- (Proc)->freason = TRAP; \
- (Ret) = THE_NON_VALUE; \
+#define ERTS_BIF_PREP_TRAP2(Ret, Trap, Proc, A0, A1) \
+do { \
+ Eterm* reg = ERTS_PROC_GET_SCHDATA((Proc))->x_reg_array; \
+ (Proc)->arity = 2; \
+ reg[0] = (Eterm) (A0); \
+ reg[1] = (Eterm) (A1); \
+ (Proc)->i = (BeamInstr*) ((Trap)->address); \
+ (Proc)->freason = TRAP; \
+ (Ret) = THE_NON_VALUE; \
+} while (0)
+
+#define ERTS_BIF_PREP_TRAP3(Ret, Trap, Proc, A0, A1, A2) \
+do { \
+ Eterm* reg = ERTS_PROC_GET_SCHDATA((Proc))->x_reg_array; \
+ (Proc)->arity = 3; \
+ reg[0] = (Eterm) (A0); \
+ reg[1] = (Eterm) (A1); \
+ reg[2] = (Eterm) (A2); \
+ (Proc)->i = (BeamInstr*) ((Trap)->address); \
+ (Proc)->freason = TRAP; \
+ (Ret) = THE_NON_VALUE; \
} while (0)
-#define ERTS_BIF_PREP_TRAP3(Ret, Trap, Proc, A0, A1, A2)\
+#define ERTS_BIF_PREP_TRAP3_NO_RET(Trap, Proc, A0, A1, A2)\
do { \
+ Eterm* reg = ERTS_PROC_GET_SCHDATA((Proc))->x_reg_array; \
(Proc)->arity = 3; \
- (Proc)->def_arg_reg[0] = (Eterm) (A0); \
- (Proc)->def_arg_reg[1] = (Eterm) (A1); \
- (Proc)->def_arg_reg[2] = (Eterm) (A2); \
- *((UWord *) (UWord) ((Proc)->def_arg_reg + 3)) = (UWord) ((Trap)->address); \
+ reg[0] = (Eterm) (A0); \
+ reg[1] = (Eterm) (A1); \
+ reg[2] = (Eterm) (A2); \
+ (Proc)->i = (BeamInstr*) ((Trap)->address); \
(Proc)->freason = TRAP; \
- (Ret) = THE_NON_VALUE; \
} while (0)
-#define BIF_TRAP0(p, Trap_) do { \
- (p)->arity = 0; \
- *((UWord *) (UWord) ((p)->def_arg_reg + 3)) = (UWord) ((Trap_)->address); \
- (p)->freason = TRAP; \
- return THE_NON_VALUE; \
+#define BIF_TRAP0(p, Trap_) do { \
+ (p)->arity = 0; \
+ (p)->i = (BeamInstr*) ((Trap_)->address); \
+ (p)->freason = TRAP; \
+ return THE_NON_VALUE; \
} while(0)
-#define BIF_TRAP1(Trap_, p, A0) do { \
- (p)->arity = 1; \
- (p)->def_arg_reg[0] = (A0); \
- *((UWord *) (UWord) ((p)->def_arg_reg + 3)) = (UWord) ((Trap_)->address); \
- (p)->freason = TRAP; \
- return THE_NON_VALUE; \
+#define BIF_TRAP1(Trap_, p, A0) do { \
+ Eterm* reg = ERTS_PROC_GET_SCHDATA((p))->x_reg_array; \
+ (p)->arity = 1; \
+ reg[0] = (A0); \
+ (p)->i = (BeamInstr*) ((Trap_)->address); \
+ (p)->freason = TRAP; \
+ return THE_NON_VALUE; \
} while(0)
-#define BIF_TRAP2(Trap_, p, A0, A1) do { \
- (p)->arity = 2; \
- (p)->def_arg_reg[0] = (A0); \
- (p)->def_arg_reg[1] = (A1); \
- *((UWord *) (UWord) ((p)->def_arg_reg + 3)) = (UWord) ((Trap_)->address); \
- (p)->freason = TRAP; \
- return THE_NON_VALUE; \
+#define BIF_TRAP2(Trap_, p, A0, A1) do { \
+ Eterm* reg = ERTS_PROC_GET_SCHDATA((p))->x_reg_array; \
+ (p)->arity = 2; \
+ reg[0] = (A0); \
+ reg[1] = (A1); \
+ (p)->i = (BeamInstr*) ((Trap_)->address); \
+ (p)->freason = TRAP; \
+ return THE_NON_VALUE; \
} while(0)
-#define BIF_TRAP3(Trap_, p, A0, A1, A2) do { \
- (p)->arity = 3; \
- (p)->def_arg_reg[0] = (A0); \
- (p)->def_arg_reg[1] = (A1); \
- (p)->def_arg_reg[2] = (A2); \
- *((UWord *) (UWord) ((p)->def_arg_reg + 3)) = (UWord) ((Trap_)->address); \
- (p)->freason = TRAP; \
- return THE_NON_VALUE; \
+#define BIF_TRAP3(Trap_, p, A0, A1, A2) do { \
+ Eterm* reg = ERTS_PROC_GET_SCHDATA((p))->x_reg_array; \
+ (p)->arity = 3; \
+ reg[0] = (A0); \
+ reg[1] = (A1); \
+ reg[2] = (A2); \
+ (p)->i = (BeamInstr*) ((Trap_)->address); \
+ (p)->freason = TRAP; \
+ return THE_NON_VALUE; \
} while(0)
-#define BIF_TRAP_CODE_PTR_0(p, Code_) do { \
- (p)->arity = 0; \
- *((UWord *) (UWord) ((p)->def_arg_reg + 3)) = (UWord) (Code_); \
- (p)->freason = TRAP; \
- return THE_NON_VALUE; \
+#define BIF_TRAP_CODE_PTR_0(p, Code_) do { \
+ (p)->arity = 0; \
+ (p)->i = (BeamInstr*) (Code_); \
+ (p)->freason = TRAP; \
+ return THE_NON_VALUE; \
} while(0)
-#define BIF_TRAP_CODE_PTR_(p, Code_) do { \
- *((UWord *) (UWord) ((p)->def_arg_reg + 3)) = (UWord) (Code_); \
- (p)->freason = TRAP; \
- return THE_NON_VALUE; \
+#define BIF_TRAP_CODE_PTR_(p, Code_) do { \
+ (p)-> i = (BeamInstr*) (Code_); \
+ (p)->freason = TRAP; \
+ return THE_NON_VALUE; \
} while(0)
extern Export bif_return_trap_export;
diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab
index d9dd80fa8b..987008c937 100644
--- a/erts/emulator/beam/bif.tab
+++ b/erts/emulator/beam/bif.tab
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2010. All Rights Reserved.
+# Copyright Ericsson AB 1996-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -87,6 +87,8 @@ bif erlang:exit/2
bif 'erl.lang.proc':signal/2 ebif_signal_2 exit_2
bif erlang:external_size/1
bif 'erl.lang.term':external_size/1 ebif_external_size_1
+bif erlang:external_size/2
+bif 'erl.lang.term':external_size/2 ebif_external_size_2
ubif erlang:float/1
ubif 'erl.lang.number':to_float/1 ebif_to_float_1 float_1
bif erlang:float_to_list/1
@@ -158,10 +160,6 @@ bif erlang:md5_update/2
bif 'erl.util.crypt.md5':update/2 ebif_md5_update_2
bif erlang:md5_final/1
bif 'erl.util.crypt.md5':final/1 ebif_md5_final_1
-bif erlang:memory/0
-bif 'erl.lang':memory/0 ebif_memory_0
-bif erlang:memory/1
-bif 'erl.lang':memory/1 ebif_memory_1
bif erlang:module_loaded/1
bif 'erl.system.code':is_loaded/1 ebif_is_loaded_1 module_loaded_1
bif erlang:function_exported/3
@@ -802,6 +800,12 @@ bif prim_file:internal_name2native/1
bif prim_file:internal_native2name/1
bif prim_file:internal_normalize_utf8/1
bif file:native_name_encoding/0
+
+#
+# New in R14B04.
+#
+bif erlang:check_old_code/1
+
#
# Obsolete
#
diff --git a/erts/emulator/beam/big.c b/erts/emulator/beam/big.c
index d18de9ae5d..b90ea6b478 100644
--- a/erts/emulator/beam/big.c
+++ b/erts/emulator/beam/big.c
@@ -1584,6 +1584,62 @@ big_to_double(Wterm x, double* resp)
return 0;
}
+/*
+ * Logic has been copied from erl_bif_guard.c and slightly
+ * modified to use a static instead of dynamic heap
+ */
+Eterm
+double_to_big(double x, Eterm *heap)
+{
+ int is_negative;
+ int ds;
+ ErtsDigit* xp;
+ Eterm res;
+ int i;
+ size_t sz;
+ Eterm* hp;
+ double dbase;
+
+ if (x >= 0) {
+ is_negative = 0;
+ } else {
+ is_negative = 1;
+ x = -x;
+ }
+
+ /* Unscale & (calculate exponent) */
+ ds = 0;
+ dbase = ((double) (D_MASK) + 1);
+ while (x >= 1.0) {
+ x /= dbase; /* "shift" right */
+ ds++;
+ }
+ sz = BIG_NEED_SIZE(ds); /* number of words including arity */
+
+ hp = heap;
+ res = make_big(hp);
+ xp = (ErtsDigit*) (hp + 1);
+
+ for (i = ds - 1; i >= 0; i--) {
+ ErtsDigit d;
+
+ x *= dbase; /* "shift" left */
+ d = x; /* trunc */
+ xp[i] = d; /* store digit */
+ x -= d; /* remove integer part */
+ }
+ while ((ds & (BIG_DIGITS_PER_WORD - 1)) != 0) {
+ xp[ds++] = 0;
+ }
+
+ if (is_negative) {
+ *hp = make_neg_bignum_header(sz-1);
+ } else {
+ *hp = make_pos_bignum_header(sz-1);
+ }
+ return res;
+}
+
/*
** Estimate the number of decimal digits (include sign)
diff --git a/erts/emulator/beam/big.h b/erts/emulator/beam/big.h
index 2afc37004f..256f1c2b45 100644
--- a/erts/emulator/beam/big.h
+++ b/erts/emulator/beam/big.h
@@ -140,6 +140,7 @@ Eterm big_lshift(Eterm, Sint, Eterm*);
int big_comp (Wterm, Wterm);
int big_ucomp (Eterm, Eterm);
int big_to_double(Wterm x, double* resp);
+Eterm double_to_big(double, Eterm*);
Eterm small_to_big(Sint, Eterm*);
Eterm uint_to_big(Uint, Eterm*);
Eterm uword_to_big(UWord, Eterm*);
diff --git a/erts/emulator/beam/binary.c b/erts/emulator/beam/binary.c
index 1fb39c6c67..29461877c5 100644
--- a/erts/emulator/beam/binary.c
+++ b/erts/emulator/beam/binary.c
@@ -356,8 +356,10 @@ BIF_RETTYPE erts_list_to_binary_bif(Process *p, Eterm arg)
{
Eterm bin;
Uint size;
- int offset;
byte* bytes;
+#ifdef DEBUG
+ int offset;
+#endif
if (is_nil(arg)) {
BIF_RET(new_binary(p,(byte*)"",0));
@@ -372,7 +374,11 @@ BIF_RETTYPE erts_list_to_binary_bif(Process *p, Eterm arg)
}
bin = new_binary(p, (byte *)NULL, size);
bytes = binary_bytes(bin);
- offset = io_list_to_buf(arg, (char*) bytes, size);
+#ifdef DEBUG
+ offset =
+#endif
+ io_list_to_buf(arg, (char*) bytes, size);
+
ASSERT(offset == 0);
BIF_RET(bin);
diff --git a/erts/emulator/beam/break.c b/erts/emulator/beam/break.c
index b8889e6206..784e55ecd2 100644
--- a/erts/emulator/beam/break.c
+++ b/erts/emulator/beam/break.c
@@ -37,6 +37,7 @@
#include "beam_load.h"
#include "erl_instrument.h"
#include "erl_bif_timer.h"
+#include "erl_thr_progress.h"
/* Forward declarations -- should really appear somewhere else */
static void process_killer(void);
@@ -94,7 +95,7 @@ process_killer(void)
erts_printf("(k)ill (n)ext (r)eturn:\n");
while(1) {
if ((j = sys_get_key(0)) <= 0)
- halt_0(0);
+ erl_exit(0, "");
switch(j) {
case 'k':
if (rp->status == P_WAITING) {
@@ -626,7 +627,7 @@ bin_check(void)
erts_printf("%p orig_size: %bpd, norefs = %bpd\n",
bp->val,
bp->val->orig_size,
- erts_smp_atomic_read(&bp->val->refc));
+ erts_smp_atomic_read_nob(&bp->val->refc));
}
}
if (printed) {
@@ -650,24 +651,23 @@ erl_crash_dump_v(char *file, int line, char* fmt, va_list args)
char dumpnamebuf[MAXPATHLEN];
char* dumpname;
- if (ERTS_IS_CRASH_DUMPING)
+ if (ERTS_SOMEONE_IS_CRASH_DUMPING)
return;
- /* Wait for all threads to block. If all threads haven't blocked
+#ifdef ERTS_SMP
+ /*
+ * Wait for all managed threads to block. If all threads haven't blocked
* after a minute, we go anyway and hope for the best...
*
* We do not release system again. We expect an exit() or abort() after
* dump has been written.
- *
- * NOTE: We allow gc therefore it is important not to lock *any*
- * process locks.
*/
- erts_smp_emergency_block_system(60000, ERTS_BS_FLG_ALLOW_GC);
+ erts_thr_progress_fatal_error_block(60000);
/* Either worked or not... */
/* Allow us to pass certain places without locking... */
-#ifdef ERTS_SMP
- erts_smp_atomic_inc(&erts_writing_erl_crash_dump);
+ erts_smp_atomic32_set_mb(&erts_writing_erl_crash_dump, 1);
+ erts_smp_tsd_set(erts_is_crash_dumping_key, (void *) 1);
#else
erts_writing_erl_crash_dump = 1;
#endif
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index b1cdd0660a..44c5ba1e26 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -41,6 +41,7 @@
#include "bif.h"
#include "external.h"
#include "erl_binary.h"
+#include "erl_thr_progress.h"
/* Turn this on to get printouts of all distribution messages
* which go on the line
@@ -128,8 +129,8 @@ delete_cache(ErtsAtomCache *cache)
{
if (cache) {
erts_free(ERTS_ALC_T_DCACHE, (void *) cache);
- ASSERT(erts_smp_atomic_read(&no_caches) > 0);
- erts_smp_atomic_dec(&no_caches);
+ ASSERT(erts_smp_atomic_read_nob(&no_caches) > 0);
+ erts_smp_atomic_dec_nob(&no_caches);
}
}
@@ -147,7 +148,7 @@ create_cache(DistEntry *dep)
dep->cache = cp = (ErtsAtomCache*) erts_alloc(ERTS_ALC_T_DCACHE,
sizeof(ErtsAtomCache));
- erts_smp_atomic_inc(&no_caches);
+ erts_smp_atomic_inc_nob(&no_caches);
for (i = 0; i < sizeof(cp->in_arr)/sizeof(cp->in_arr[0]); i++) {
cp->in_arr[i] = THE_NON_VALUE;
cp->out_arr[i] = THE_NON_VALUE;
@@ -156,7 +157,7 @@ create_cache(DistEntry *dep)
Uint erts_dist_cache_size(void)
{
- return (Uint) erts_smp_atomic_read(&no_caches)*sizeof(ErtsAtomCache);
+ return (Uint) erts_smp_atomic_read_mb(&no_caches)*sizeof(ErtsAtomCache);
}
static ErtsProcList *
@@ -430,11 +431,11 @@ int erts_do_net_exits(DistEntry *dep, Eterm reason)
erts_smp_rwmtx_rwunlock(&erts_dist_table_rwmtx);
nodename = erts_this_dist_entry->sysname;
- erts_smp_block_system(ERTS_BS_FLG_ALLOW_GC);
+ erts_smp_thr_progress_block();
erts_set_this_node(am_Noname, 0);
erts_is_alive = 0;
send_nodes_mon_msgs(NULL, am_nodedown, nodename, am_visible, nd_reason);
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
}
else { /* recursive call via erts_do_exit_port() will end up here */
@@ -444,7 +445,7 @@ int erts_do_net_exits(DistEntry *dep, Eterm reason)
ErtsMonitor *monitors;
Uint32 flags;
- erts_smp_atomic_set(&dep->dist_cmd_scheduled, 1);
+ erts_smp_atomic_set_mb(&dep->dist_cmd_scheduled, 1);
erts_smp_de_rwlock(dep);
ERTS_SMP_LC_ASSERT(is_internal_port(dep->cid)
@@ -510,7 +511,7 @@ void init_dist(void)
{
init_nodes_monitors();
- erts_smp_atomic_init(&no_caches, 0);
+ erts_smp_atomic_init_nob(&no_caches, 0);
/* Lookup/Install all references to trap functions */
dsend2_trap = trap_function(am_dsend,2);
@@ -596,7 +597,7 @@ static void clear_dist_entry(DistEntry *dep)
suspendees = get_suspended_on_de(dep, ERTS_DE_QFLGS_ALL);
erts_smp_mtx_unlock(&dep->qlock);
- erts_smp_atomic_set(&dep->dist_cmd_scheduled, 0);
+ erts_smp_atomic_set_nob(&dep->dist_cmd_scheduled, 0);
dep->send = NULL;
erts_smp_de_rwunlock(dep);
@@ -967,7 +968,7 @@ int erts_net_message(Port *prt,
res = erts_prepare_dist_ext(&ede, t, len, dep, dep->cache);
if (res >= 0)
- res = ctl_len = erts_decode_dist_ext_size(&ede, 0);
+ res = ctl_len = erts_decode_dist_ext_size(&ede);
else {
#ifdef ERTS_DIST_MSG_DBG
erts_fprintf(stderr, "DIST MSG DEBUG: erts_prepare_dist_ext() failed:\n");
@@ -1775,7 +1776,7 @@ erts_dist_command(Port *prt, int reds_limit)
erts_refc_inc(&dep->refc, 1); /* Otherwise dist_entry might be
removed if port command fails */
- erts_smp_atomic_xchg(&dep->dist_cmd_scheduled, 0);
+ erts_smp_atomic_set_mb(&dep->dist_cmd_scheduled, 0);
erts_smp_de_rlock(dep);
flags = dep->flags;
@@ -2330,11 +2331,11 @@ BIF_RETTYPE setnode_2(BIF_ALIST_2)
#endif
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(ERTS_BS_FLG_ALLOW_GC);
+ erts_smp_thr_progress_block();
erts_set_this_node(BIF_ARG_1, (Uint32) creation);
erts_is_alive = 1;
send_nodes_mon_msgs(NULL, am_nodeup, BIF_ARG_1, am_visible, NIL);
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
BIF_RET(am_true);
@@ -2730,85 +2731,92 @@ BIF_RETTYPE is_alive_0(BIF_ALIST_0)
/**********************************************************************/
/* erlang:monitor_node(Node, Bool, Options) -> Bool */
-BIF_RETTYPE monitor_node_3(BIF_ALIST_3)
+static BIF_RETTYPE
+monitor_node(Process* p, Eterm Node, Eterm Bool, Eterm Options)
{
DistEntry *dep;
ErtsLink *lnk;
Eterm l;
- for (l = BIF_ARG_3; l != NIL && is_list(l); l = CDR(list_val(l))) {
+ for (l = Options; l != NIL && is_list(l); l = CDR(list_val(l))) {
Eterm t = CAR(list_val(l));
/* allow_passive_connect the only available option right now */
if (t != am_allow_passive_connect) {
- BIF_ERROR(BIF_P, BADARG);
+ BIF_ERROR(p, BADARG);
}
}
if (l != NIL) {
- BIF_ERROR(BIF_P, BADARG);
+ BIF_ERROR(p, BADARG);
}
- if (is_not_atom(BIF_ARG_1) ||
- ((BIF_ARG_2 != am_true) && (BIF_ARG_2 != am_false)) ||
+ if (is_not_atom(Node) ||
+ ((Bool != am_true) && (Bool != am_false)) ||
((erts_this_node->sysname == am_Noname)
- && (BIF_ARG_1 != erts_this_node->sysname))) {
- BIF_ERROR(BIF_P, BADARG);
+ && (Node != erts_this_node->sysname))) {
+ BIF_ERROR(p, BADARG);
}
- dep = erts_sysname_to_connected_dist_entry(BIF_ARG_1);
+ dep = erts_sysname_to_connected_dist_entry(Node);
if (!dep) {
do_trap:
- BIF_TRAP3(dmonitor_node_trap, BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
+ BIF_TRAP3(dmonitor_node_trap, p, Node, Bool, Options);
}
if (dep == erts_this_dist_entry)
goto done;
- erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_LINK);
+ erts_smp_proc_lock(p, ERTS_PROC_LOCK_LINK);
erts_smp_de_rlock(dep);
if (ERTS_DE_IS_NOT_CONNECTED(dep)) {
- erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_LINK);
+ erts_smp_proc_unlock(p, ERTS_PROC_LOCK_LINK);
erts_smp_de_runlock(dep);
goto do_trap;
}
erts_smp_de_links_lock(dep);
erts_smp_de_runlock(dep);
- if (BIF_ARG_2 == am_true) {
+ if (Bool == am_true) {
ASSERT(dep->cid != NIL);
lnk = erts_add_or_lookup_link(&(dep->node_links), LINK_NODE,
- BIF_P->id);
+ p->id);
++ERTS_LINK_REFC(lnk);
- lnk = erts_add_or_lookup_link(&(BIF_P->nlinks), LINK_NODE, BIF_ARG_1);
+ lnk = erts_add_or_lookup_link(&(p->nlinks), LINK_NODE, Node);
++ERTS_LINK_REFC(lnk);
}
else {
- lnk = erts_lookup_link(dep->node_links, BIF_P->id);
+ lnk = erts_lookup_link(dep->node_links, p->id);
if (lnk != NULL) {
if ((--ERTS_LINK_REFC(lnk)) == 0) {
erts_destroy_link(erts_remove_link(&(dep->node_links),
- BIF_P->id));
+ p->id));
}
}
- lnk = erts_lookup_link(BIF_P->nlinks, BIF_ARG_1);
+ lnk = erts_lookup_link(p->nlinks, Node);
if (lnk != NULL) {
if ((--ERTS_LINK_REFC(lnk)) == 0) {
- erts_destroy_link(erts_remove_link(&(BIF_P->nlinks),
- BIF_ARG_1));
+ erts_destroy_link(erts_remove_link(&(p->nlinks),
+ Node));
}
}
}
erts_smp_de_links_unlock(dep);
- erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_LINK);
+ erts_smp_proc_unlock(p, ERTS_PROC_LOCK_LINK);
done:
erts_deref_dist_entry(dep);
BIF_RET(am_true);
}
+BIF_RETTYPE monitor_node_3(BIF_ALIST_3)
+{
+ BIF_RET(monitor_node(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3));
+}
+
+
/* monitor_node(Node, Bool) -> Bool */
BIF_RETTYPE monitor_node_2(BIF_ALIST_2)
{
- BIF_RET(monitor_node_3(BIF_P,BIF_ARG_1,BIF_ARG_2,NIL));
+ BIF_RET(monitor_node(BIF_P, BIF_ARG_1, BIF_ARG_2, NIL));
}
BIF_RETTYPE net_kernel_dflag_unicode_io_1(BIF_ALIST_1)
diff --git a/erts/emulator/beam/dist.h b/erts/emulator/beam/dist.h
index 695a4fc3fe..845151c895 100644
--- a/erts/emulator/beam/dist.h
+++ b/erts/emulator/beam/dist.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2010. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -203,7 +203,7 @@ void erts_schedule_dist_command(Port *prt, DistEntry *dist_entry)
id = dep->cid;
}
- if (!erts_smp_atomic_xchg(&dep->dist_cmd_scheduled, 1)) {
+ if (!erts_smp_atomic_xchg_mb(&dep->dist_cmd_scheduled, 1)) {
(void) erts_port_task_schedule(id,
&dep->dist_cmd,
ERTS_PORT_TASK_DIST_CMD,
diff --git a/erts/emulator/beam/erl_afit_alloc.c b/erts/emulator/beam/erl_afit_alloc.c
index d397cd8848..570cc59be2 100644
--- a/erts/emulator/beam/erl_afit_alloc.c
+++ b/erts/emulator/beam/erl_afit_alloc.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2003-2009. All Rights Reserved.
+ * Copyright Ericsson AB 2003-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -65,16 +65,20 @@ erts_afalc_start(AFAllctr_t *afallctr,
AFAllctrInit_t *afinit,
AllctrInit_t *init)
{
- AFAllctr_t nulled_state = {{0}};
- /* {{0}} is used instead of {0}, in order to avoid (an incorrect) gcc
- warning. gcc warns if {0} is used as initializer of a struct when
- the first member is a struct (not if, for example, the third member
- is a struct). */
+ struct {
+ int dummy;
+ AFAllctr_t allctr;
+ } zero = {0};
+ /* The struct with a dummy element first is used in order to avoid (an
+ incorrect) gcc warning. gcc warns if {0} is used as initializer of
+ a struct when the first member is a struct (not if, for example,
+ the third member is a struct). */
+
Allctr_t *allctr = (Allctr_t *) afallctr;
- init->sbmbct = 0; /* Small mbc not supported by afit */
+ sys_memcpy((void *) afallctr, (void *) &zero.allctr, sizeof(AFAllctr_t));
- sys_memcpy((void *) afallctr, (void *) &nulled_state, sizeof(AFAllctr_t));
+ init->sbmbct = 0; /* Small mbc not supported by afit */
allctr->mbc_header_size = sizeof(Carrier_t);
allctr->min_mbc_size = MIN_MBC_SZ;
diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c
index 840534ec5e..140a84d5fc 100644
--- a/erts/emulator/beam/erl_alloc.c
+++ b/erts/emulator/beam/erl_alloc.c
@@ -40,6 +40,8 @@
#include "erl_mseg.h"
#include "erl_monitors.h"
#include "erl_bif_timer.h"
+#include "erl_cpu_topology.h"
+#include "erl_thr_queue.h"
#if defined(ERTS_ALC_T_DRV_SEL_D_STATE) || defined(ERTS_ALC_T_DRV_EV_D_STATE)
#include "erl_check_io.h"
#endif
@@ -50,8 +52,18 @@
#include "erl_bestfit_alloc.h"
#define GET_ERL_AF_ALLOC_IMPL
#include "erl_afit_alloc.h"
+#define GET_ERL_AOFF_ALLOC_IMPL
+#include "erl_ao_firstfit_alloc.h"
-#define ERTS_ALC_DEFAULT_MAX_THR_PREF 16
+
+#if ERTS_MAX_NO_OF_SCHEDULERS > ERTS_AU_MAX_PREF_ALLOC_INSTANCES
+# error "Too many schedulers; cannot create that many pref alloc instances"
+#endif
+
+#define ERTS_ALC_FIX_TYPE_IX(T) \
+ (ERTS_ALC_T2N((T)) - ERTS_ALC_N_MIN_A_FIXED_SIZE)
+
+#define ERTS_ALC_DEFAULT_MAX_THR_PREF ERTS_MAX_NO_OF_SCHEDULERS
#if defined(SMALL_MEMORY) || defined(PURIFY) || defined(VALGRIND)
#define AU_ALLOC_DEFAULT_ENABLE(X) 0
@@ -85,6 +97,8 @@ typedef union {
char align_bfa[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(BFAllctr_t))];
AFAllctr_t afa;
char align_afa[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(AFAllctr_t))];
+ AOFFAllctr_t aoffa;
+ char align_aoffa[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(AOFFAllctr_t))];
} ErtsAllocatorState_t;
static ErtsAllocatorState_t sbmbc_alloc_state;
@@ -101,28 +115,48 @@ static ErtsAllocatorState_t eheap_alloc_state;
static ErtsAllocatorState_t binary_alloc_state;
static ErtsAllocatorState_t ets_alloc_state;
static ErtsAllocatorState_t driver_alloc_state;
+static ErtsAllocatorState_t fix_alloc_state;
-ErtsAlcType_t erts_fix_core_allocator_ix;
-#ifdef ERTS_ALC_N_MIN_A_FIXED_SIZE
-static void *(*fix_core_allocator)(ErtsAlcType_t, void *, Uint);
-static void *fix_core_extra;
-static void *fix_core_alloc(Uint size)
+typedef struct {
+ erts_smp_atomic32_t refc;
+ int only_sz;
+ Uint req_sched;
+ Process *proc;
+ Eterm ref;
+ Eterm ref_heap[REF_THING_SIZE];
+ int allocs[ERTS_ALC_A_MAX-ERTS_ALC_A_MIN+1+2];
+} ErtsAllocInfoReq;
+
+#define ERTS_ALC_INFO_A_ALLOC_UTIL (ERTS_ALC_A_MAX + 1)
+#define ERTS_ALC_INFO_A_MSEG_ALLOC (ERTS_ALC_A_MAX + 2)
+#define ERTS_ALC_INFO_A_MAX ERTS_ALC_INFO_A_MSEG_ALLOC
+
+#if !HALFWORD_HEAP
+ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(aireq,
+ ErtsAllocInfoReq,
+ 5,
+ ERTS_ALC_T_AINFO_REQ)
+#else
+static ERTS_INLINE ErtsAllocInfoReq *
+aireq_alloc(void)
{
- void *res;
- res = (*fix_core_allocator)(ERTS_ALC_T_UNDEF, fix_core_extra, size);
- if (erts_mtrace_enabled)
- erts_mtrace_crr_alloc(res,
- ERTS_ALC_A_FIXED_SIZE,
- erts_fix_core_allocator_ix,
- size);
- return res;
+ return erts_alloc(ERTS_ALC_T_AINFO_REQ, sizeof(ErtsAllocInfoReq));
+}
+
+static ERTS_INLINE void
+aireq_free(ErtsAllocInfoReq *ptr)
+{
+ erts_free(ERTS_ALC_T_AINFO_REQ, ptr);
}
#endif
+ErtsAlcType_t erts_fix_core_allocator_ix;
+
enum allctr_type {
GOODFIT,
BESTFIT,
- AFIT
+ AFIT,
+ AOFIRSTFIT
};
struct au_init {
@@ -134,6 +168,7 @@ struct au_init {
GFAllctrInit_t gf;
BFAllctrInit_t bf;
AFAllctrInit_t af;
+ AOFFAllctrInit_t aoff;
} init;
struct {
int mmbcs;
@@ -147,7 +182,8 @@ struct au_init {
ERTS_DEFAULT_ALLCTR_INIT, \
ERTS_DEFAULT_GF_ALLCTR_INIT, \
ERTS_DEFAULT_BF_ALLCTR_INIT, \
- ERTS_DEFAULT_AF_ALLCTR_INIT \
+ ERTS_DEFAULT_AF_ALLCTR_INIT, \
+ ERTS_DEFAULT_AOFF_ALLCTR_INIT \
}
typedef struct {
@@ -173,6 +209,7 @@ typedef struct {
struct au_init binary_alloc;
struct au_init ets_alloc;
struct au_init driver_alloc;
+ struct au_init fix_alloc;
#if HALFWORD_HEAP
struct au_init sbmbc_low_alloc;
struct au_init std_low_alloc;
@@ -385,46 +422,52 @@ set_default_driver_alloc_opts(struct au_init *ip)
ip->init.util.ts = ERTS_ALC_MTA_DRIVER;
}
+static void
+set_default_fix_alloc_opts(struct au_init *ip,
+ size_t *fix_type_sizes)
+{
+ SET_DEFAULT_ALLOC_OPTS(ip);
+ ip->enable = AU_ALLOC_DEFAULT_ENABLE(1);
+ ip->thr_spec = 1;
+ ip->atype = BESTFIT;
+ ip->init.bf.ao = 1;
+ ip->init.util.name_prefix = "fix_";
+ ip->init.util.fix_type_size = fix_type_sizes;
+ ip->init.util.alloc_no = ERTS_ALC_A_FIXED_SIZE;
+#ifndef SMALL_MEMORY
+ ip->init.util.mmbcs = 128*1024; /* Main carrier size */
+#else
+ ip->init.util.mmbcs = 128*1024; /* Main carrier size */
+#endif
+ ip->init.util.ts = ERTS_ALC_MTA_FIXED_SIZE;
+}
+
#ifdef ERTS_SMP
static void
adjust_tpref(struct au_init *ip, int no_sched)
{
if (ip->thr_spec) {
- Uint allocs;
- if (ip->thr_spec < 0) {/* User specified amount */
- allocs = abs(ip->thr_spec);
- if (allocs > no_sched)
- allocs = no_sched;
- }
- else if (no_sched > ERTS_ALC_DEFAULT_MAX_THR_PREF)
- allocs = ERTS_ALC_DEFAULT_MAX_THR_PREF;
- else
- allocs = no_sched;
- if (allocs <= 1)
- ip->thr_spec = 0;
- else {
- ip->thr_spec = (int) allocs;
- ip->thr_spec *= -1; /* thread preferred */
-
- /* If default ... */
-
- /* ... shrink main multi-block carrier size */
- if (ip->default_.mmbcs)
- ip->init.util.mmbcs /= ERTS_MIN(4, allocs);
- /* ... shrink largest multi-block carrier size */
- if (ip->default_.lmbcs)
- ip->init.util.lmbcs /= ERTS_MIN(2, allocs);
- /* ... shrink smallest multi-block carrier size */
- if (ip->default_.smbcs)
- ip->init.util.smbcs /= ERTS_MIN(4, allocs);
- /* ... and more than three allocators shrink
- max mseg multi-block carriers */
- if (ip->default_.mmmbc && allocs > 2) {
- ip->init.util.mmmbc /= ERTS_MIN(4, allocs - 1);
- if (ip->init.util.mmmbc < 3)
- ip->init.util.mmmbc = 3;
- }
+ ip->thr_spec = no_sched;
+ ip->thr_spec *= -1; /* thread preferred */
+
+ /* If default ... */
+
+ /* ... shrink main multi-block carrier size */
+ if (ip->default_.mmbcs)
+ ip->init.util.mmbcs /= ERTS_MIN(4, no_sched);
+ /* ... shrink largest multi-block carrier size */
+ if (ip->default_.lmbcs)
+ ip->init.util.lmbcs /= ERTS_MIN(2, no_sched);
+ /* ... shrink smallest multi-block carrier size */
+ if (ip->default_.smbcs)
+ ip->init.util.smbcs /= ERTS_MIN(4, no_sched);
+ /* ... and more than three allocators shrink
+ max mseg multi-block carriers */
+ if (ip->default_.mmmbc && no_sched > 2) {
+ ip->init.util.mmmbc /= ERTS_MIN(4, no_sched - 1);
+ if (ip->init.util.mmmbc < 3)
+ ip->init.util.mmmbc = 3;
}
}
}
@@ -434,7 +477,7 @@ adjust_tpref(struct au_init *ip, int no_sched)
static void handle_args(int *, char **, erts_alc_hndl_args_init_t *);
static void
-set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init);
+set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init, int ncpu);
static void
start_au_allocator(ErtsAlcType_t alctr_n,
@@ -448,8 +491,6 @@ refuse_af_strategy(struct au_init *init)
init->atype = GOODFIT;
}
-static void init_thr_ix(int static_ixs);
-
#ifdef HARD_DEBUG
static void hdbg_init(void);
#endif
@@ -458,7 +499,7 @@ void
erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
{
UWord extra_block_size = 0;
- int i;
+ int i, ncpu;
erts_alc_hndl_args_init_t init = {
0,
#if HAVE_ERTS_MSEG
@@ -466,17 +507,38 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
#endif
ERTS_DEFAULT_TRIM_THRESHOLD,
ERTS_DEFAULT_TOP_PAD,
- ERTS_DEFAULT_ALCU_INIT
+ ERTS_DEFAULT_ALCU_INIT,
};
+ size_t fix_type_sizes[ERTS_ALC_NO_FIXED_SIZES] = {0};
+ fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_PROC)]
+ = sizeof(Process);
+#if !HALFWORD_HEAP
+ fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_MONITOR_SH)]
+ = ERTS_MONITOR_SH_SIZE;
+ fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_NLINK_SH)]
+ = ERTS_LINK_SH_SIZE;
+#endif
+ fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_DRV_EV_D_STATE)]
+ = sizeof(ErtsDrvEventDataState);
+ fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_DRV_SEL_D_STATE)]
+ = sizeof(ErtsDrvSelectDataState);
+ fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_MSG_REF)]
+ = sizeof(ErlMessage);
+#ifdef ERTS_SMP
+ fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_THR_Q_EL_SL)]
+ = sizeof(ErtsThrQElement_t);
+#endif
#ifdef HARD_DEBUG
hdbg_init();
#endif
erts_have_sbmbc_alloc = 0;
+ ncpu = eaiop->ncpu;
+ if (ncpu < 1)
+ ncpu = 1;
erts_sys_alloc_init();
- init_thr_ix(erts_no_schedulers);
erts_init_utils_mem();
set_default_sbmbc_alloc_opts(&init.sbmbc_alloc);
@@ -488,20 +550,23 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
set_default_binary_alloc_opts(&init.binary_alloc);
set_default_ets_alloc_opts(&init.ets_alloc);
set_default_driver_alloc_opts(&init.driver_alloc);
+ set_default_fix_alloc_opts(&init.fix_alloc,
+ fix_type_sizes);
if (argc && argv)
handle_args(argc, argv, &init);
- if (erts_no_schedulers <= 1) {
- init.sbmbc_alloc.thr_spec = 0;
- init.sl_alloc.thr_spec = 0;
- init.std_alloc.thr_spec = 0;
- init.ll_alloc.thr_spec = 0;
- init.eheap_alloc.thr_spec = 0;
- init.binary_alloc.thr_spec = 0;
- init.ets_alloc.thr_spec = 0;
- init.driver_alloc.thr_spec = 0;
- }
+#ifndef ERTS_SMP
+ init.sbmbc_alloc.thr_spec = 0;
+ init.sl_alloc.thr_spec = 0;
+ init.std_alloc.thr_spec = 0;
+ init.ll_alloc.thr_spec = 0;
+ init.eheap_alloc.thr_spec = 0;
+ init.binary_alloc.thr_spec = 0;
+ init.ets_alloc.thr_spec = 0;
+ init.driver_alloc.thr_spec = 0;
+ init.fix_alloc.thr_spec = 0;
+#endif
if (init.erts_alloc_config) {
/* Adjust flags that erts_alloc_config won't like */
@@ -514,6 +579,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
init.binary_alloc.thr_spec = 0;
init.ets_alloc.thr_spec = 0;
init.driver_alloc.thr_spec = 0;
+ init.fix_alloc.thr_spec = 0;
}
#ifdef ERTS_SMP
@@ -530,6 +596,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
adjust_tpref(&init.binary_alloc, erts_no_schedulers);
adjust_tpref(&init.ets_alloc, erts_no_schedulers);
adjust_tpref(&init.driver_alloc, erts_no_schedulers);
+ adjust_tpref(&init.fix_alloc, erts_no_schedulers);
#else
/* No thread specific if not smp */
@@ -548,6 +615,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
refuse_af_strategy(&init.binary_alloc);
refuse_af_strategy(&init.ets_alloc);
refuse_af_strategy(&init.driver_alloc);
+ refuse_af_strategy(&init.fix_alloc);
#ifdef ERTS_SMP
if (!init.temp_alloc.thr_spec)
@@ -556,12 +624,14 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
erts_mtrace_pre_init();
#if HAVE_ERTS_MSEG
+ init.mseg.nos = erts_no_schedulers;
erts_mseg_init(&init.mseg);
#endif
erts_alcu_init(&init.alloc_util);
erts_afalc_init();
erts_bfalc_init();
erts_gfalc_init();
+ erts_aoffalc_init();
for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {
erts_allctrs[i].alloc = NULL;
@@ -574,20 +644,6 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
erts_allctrs_info[i].extra = NULL;
}
-#ifdef ERTS_ALC_N_MIN_A_FIXED_SIZE
-#if !defined(PURIFY) && !defined(VALGRIND)
- erts_allctrs[ERTS_ALC_A_FIXED_SIZE].alloc = erts_fix_alloc;
- erts_allctrs[ERTS_ALC_A_FIXED_SIZE].realloc = erts_fix_realloc;
- erts_allctrs[ERTS_ALC_A_FIXED_SIZE].free = erts_fix_free;
- erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].enabled = 1;
-#else
- erts_allctrs[ERTS_ALC_A_FIXED_SIZE].alloc = erts_sys_alloc;
- erts_allctrs[ERTS_ALC_A_FIXED_SIZE].realloc = erts_sys_realloc;
- erts_allctrs[ERTS_ALC_A_FIXED_SIZE].free = erts_sys_free;
- erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].enabled = 0;
-#endif
-#endif
-
erts_allctrs[ERTS_ALC_A_SYSTEM].alloc = erts_sys_alloc;
erts_allctrs[ERTS_ALC_A_SYSTEM].realloc = erts_sys_realloc;
erts_allctrs[ERTS_ALC_A_SYSTEM].free = erts_sys_free;
@@ -597,7 +653,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
/* Init low memory variants by cloning */
init.sbmbc_low_alloc = init.sbmbc_alloc;
init.sbmbc_low_alloc.init.util.name_prefix = "sbmbc_low_";
- init.sbmbc_low_alloc.init.util.alloc_no = ERTS_ALC_A_STANDARD_LOW;
+ init.sbmbc_low_alloc.init.util.alloc_no = ERTS_ALC_A_SBMBC_LOW;
init.sbmbc_low_alloc.init.util.low_mem = 1;
init.std_low_alloc = init.std_alloc;
@@ -612,20 +668,21 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
init.ll_low_alloc.init.util.force = 1;
init.ll_low_alloc.init.util.low_mem = 1;
- set_au_allocator(ERTS_ALC_A_SBMBC_LOW, &init.sbmbc_low_alloc);
- set_au_allocator(ERTS_ALC_A_STANDARD_LOW, &init.std_low_alloc);
- set_au_allocator(ERTS_ALC_A_LONG_LIVED_LOW, &init.ll_low_alloc);
+ set_au_allocator(ERTS_ALC_A_SBMBC_LOW, &init.sbmbc_low_alloc, ncpu);
+ set_au_allocator(ERTS_ALC_A_STANDARD_LOW, &init.std_low_alloc, ncpu);
+ set_au_allocator(ERTS_ALC_A_LONG_LIVED_LOW, &init.ll_low_alloc, ncpu);
#endif /* HALFWORD */
- set_au_allocator(ERTS_ALC_A_TEMPORARY, &init.temp_alloc);
- set_au_allocator(ERTS_ALC_A_SBMBC, &init.sbmbc_alloc);
- set_au_allocator(ERTS_ALC_A_SHORT_LIVED, &init.sl_alloc);
- set_au_allocator(ERTS_ALC_A_STANDARD, &init.std_alloc);
- set_au_allocator(ERTS_ALC_A_LONG_LIVED, &init.ll_alloc);
- set_au_allocator(ERTS_ALC_A_EHEAP, &init.eheap_alloc);
- set_au_allocator(ERTS_ALC_A_BINARY, &init.binary_alloc);
- set_au_allocator(ERTS_ALC_A_ETS, &init.ets_alloc);
- set_au_allocator(ERTS_ALC_A_DRIVER, &init.driver_alloc);
+ set_au_allocator(ERTS_ALC_A_TEMPORARY, &init.temp_alloc, ncpu);
+ set_au_allocator(ERTS_ALC_A_SBMBC, &init.sbmbc_alloc, ncpu);
+ set_au_allocator(ERTS_ALC_A_SHORT_LIVED, &init.sl_alloc, ncpu);
+ set_au_allocator(ERTS_ALC_A_STANDARD, &init.std_alloc, ncpu);
+ set_au_allocator(ERTS_ALC_A_LONG_LIVED, &init.ll_alloc, ncpu);
+ set_au_allocator(ERTS_ALC_A_EHEAP, &init.eheap_alloc, ncpu);
+ set_au_allocator(ERTS_ALC_A_BINARY, &init.binary_alloc, ncpu);
+ set_au_allocator(ERTS_ALC_A_ETS, &init.ets_alloc, ncpu);
+ set_au_allocator(ERTS_ALC_A_DRIVER, &init.driver_alloc, ncpu);
+ set_au_allocator(ERTS_ALC_A_FIXED_SIZE, &init.fix_alloc, ncpu);
for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {
if (!erts_allctrs[i].alloc)
@@ -641,10 +698,6 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
sys_alloc_opt(SYS_ALLOC_OPT_TRIM_THRESHOLD, init.trim_threshold);
sys_alloc_opt(SYS_ALLOC_OPT_TOP_PAD, init.top_pad);
- if (erts_allctrs_info[ERTS_FIX_CORE_ALLOCATOR].enabled)
- erts_fix_core_allocator_ix = ERTS_FIX_CORE_ALLOCATOR;
- else
- erts_fix_core_allocator_ix = ERTS_ALC_A_SYSTEM;
erts_mtrace_init(init.instr.mtrace, init.instr.nodename);
@@ -701,49 +754,40 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
&init.driver_alloc,
&driver_alloc_state);
- fix_core_allocator = erts_allctrs[erts_fix_core_allocator_ix].alloc;
- fix_core_extra = erts_allctrs[erts_fix_core_allocator_ix].extra;
+ start_au_allocator(ERTS_ALC_A_FIXED_SIZE,
+ &init.fix_alloc,
+ &fix_alloc_state);
erts_mtrace_install_wrapper_functions();
extra_block_size += erts_instr_init(init.instr.stat, init.instr.map);
+#if !HALFWORD_HEAP
+ init_aireq_alloc();
+#endif
+
#ifdef DEBUG
extra_block_size += install_debug_functions();
#endif
-#ifdef ERTS_ALC_N_MIN_A_FIXED_SIZE
-
- erts_init_fix_alloc(extra_block_size, fix_core_alloc);
-
+}
-#if !defined(PURIFY) && !defined(VALGRIND)
- erts_set_fix_size(ERTS_ALC_T_PROC, sizeof(Process));
- erts_set_fix_size(ERTS_ALC_T_DB_TABLE, sizeof(DbTable));
- erts_set_fix_size(ERTS_ALC_T_ATOM, sizeof(Atom));
+void
+erts_alloc_late_init(void)
+{
- erts_set_fix_size(ERTS_ALC_T_MODULE, sizeof(Module));
- erts_set_fix_size(ERTS_ALC_T_REG_PROC, sizeof(RegProc));
- erts_set_fix_size(ERTS_ALC_T_FUN_ENTRY, sizeof(ErlFunEntry));
-#ifdef ERTS_ALC_T_DRV_EV_D_STATE
- erts_set_fix_size(ERTS_ALC_T_DRV_EV_D_STATE,
- sizeof(ErtsDrvEventDataState));
-#endif
-#ifdef ERTS_ALC_T_DRV_SEL_D_STATE
- erts_set_fix_size(ERTS_ALC_T_DRV_SEL_D_STATE,
- sizeof(ErtsDrvSelectDataState));
-#endif
-#if !HALFWORD_HEAP
- erts_set_fix_size(ERTS_ALC_T_EXPORT, sizeof(Export));
- erts_set_fix_size(ERTS_ALC_T_MONITOR_SH, ERTS_MONITOR_SH_SIZE*sizeof(Uint));
- erts_set_fix_size(ERTS_ALC_T_NLINK_SH, ERTS_LINK_SH_SIZE*sizeof(Uint));
-#endif
-#endif
-#endif
+}
+static void *
+erts_realloc_fixed_size(ErtsAlcType_t type, void *extra, void *p, Uint size)
+{
+ erl_exit(ERTS_ABORT_EXIT,
+ "Attempt to reallocate a block of the fixed size type %s\n",
+ ERTS_ALC_T2TD(type));
}
+
static void
-set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init)
+set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init, int ncpu)
{
ErtsAllocatorFunctions_t *af = &erts_allctrs[alctr_n];
ErtsAllocatorInfo_t *ai = &erts_allctrs_info[alctr_n];
@@ -755,6 +799,12 @@ set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init)
if (init->init.util.force)
init->enable = 1;
+ tspec->enabled = 0;
+ tspec->dd = 0;
+ tspec->aix = alctr_n;
+ tspec->size = 0;
+ ai->thr_spec = 0;
+
if (!init->enable) {
af->alloc = erts_sys_alloc;
af->realloc = erts_sys_realloc;
@@ -766,14 +816,14 @@ set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init)
return;
}
- tspec->enabled = 0;
- tspec->all_thr_safe = 0;
- ai->thr_spec = 0;
#ifdef USE_THREADS
+#ifdef ERTS_SMP
if (init->thr_spec) {
if (init->thr_spec > 0) {
af->alloc = erts_alcu_alloc_thr_spec;
- if (init->init.util.ramv)
+ if (init->init.util.fix_type_size)
+ af->realloc = erts_realloc_fixed_size;
+ else if (init->init.util.ramv)
af->realloc = erts_alcu_realloc_mv_thr_spec;
else
af->realloc = erts_alcu_realloc_thr_spec;
@@ -781,12 +831,14 @@ set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init)
}
else {
af->alloc = erts_alcu_alloc_thr_pref;
- if (init->init.util.ramv)
+ if (init->init.util.fix_type_size)
+ af->realloc = erts_realloc_fixed_size;
+ else if (init->init.util.ramv)
af->realloc = erts_alcu_realloc_mv_thr_pref;
else
af->realloc = erts_alcu_realloc_thr_pref;
af->free = erts_alcu_free_thr_pref;
- tspec->all_thr_safe = 1;
+ tspec->dd = 1;
}
tspec->enabled = 1;
@@ -794,9 +846,13 @@ set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init)
ai->thr_spec = tspec->size;
}
- else if (init->init.util.ts) {
+ else
+#endif
+ if (init->init.util.ts) {
af->alloc = erts_alcu_alloc_ts;
- if (init->init.util.ramv)
+ if (init->init.util.fix_type_size)
+ af->realloc = erts_realloc_fixed_size;
+ else if (init->init.util.ramv)
af->realloc = erts_alcu_realloc_mv_ts;
else
af->realloc = erts_alcu_realloc_ts;
@@ -806,7 +862,9 @@ set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init)
#endif
{
af->alloc = erts_alcu_alloc;
- if (init->init.util.ramv)
+ if (init->init.util.fix_type_size)
+ af->realloc = erts_realloc_fixed_size;
+ else if (init->init.util.ramv)
af->realloc = erts_alcu_realloc_mv;
else
af->realloc = erts_alcu_realloc;
@@ -829,12 +887,14 @@ start_au_allocator(ErtsAlcType_t alctr_n,
ErtsAllocatorFunctions_t *af = &erts_allctrs[alctr_n];
ErtsAllocatorInfo_t *ai = &erts_allctrs_info[alctr_n];
ErtsAllocatorThrSpec_t *tspec = &erts_allctr_thr_spec[alctr_n];
+ ErtsAlcFixList_t *fix_lists = NULL;
+ size_t fix_list_size = 0;
if (!init->enable)
return;
if (init->thr_spec) {
- void *states = erts_sys_alloc(0,
+ char *states = erts_sys_alloc(0,
NULL,
((sizeof(Allctr_t *)
* (tspec->size + 1))
@@ -846,18 +906,40 @@ start_au_allocator(ErtsAlcType_t alctr_n,
"Failed to allocate allocator states for %salloc\n",
init->init.util.name_prefix);
tspec->allctr = (Allctr_t **) states;
- states = ((char *) states) + sizeof(Allctr_t *) * (tspec->size + 1);
+ states += sizeof(Allctr_t *) * (tspec->size + 1);
states = ((((UWord) states) & ERTS_CACHE_LINE_MASK)
- ? (void *) ((((UWord) states) & ~ERTS_CACHE_LINE_MASK)
+ ? (char *) ((((UWord) states) & ~ERTS_CACHE_LINE_MASK)
+ ERTS_CACHE_LINE_SIZE)
- : (void *) states);
- tspec->allctr[0] = init->thr_spec > 0 ? (Allctr_t *) state : (Allctr_t *) NULL;
+ : (char *) states);
+ tspec->allctr[0] = (Allctr_t *) state;
size = tspec->size;
for (i = 1; i < size; i++)
tspec->allctr[i] = (Allctr_t *)
&((ErtsAllocatorState_t *) states)[i-1];
}
+ if (init->init.util.fix_type_size) {
+ size_t tot_fix_list_size;
+ fix_list_size = sizeof(ErtsAlcFixList_t)*ERTS_ALC_NO_FIXED_SIZES;
+ fix_list_size = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(fix_list_size);
+ tot_fix_list_size = fix_list_size;
+ if (init->thr_spec)
+ tot_fix_list_size *= tspec->size;
+ fix_lists = erts_sys_alloc(0,
+ NULL,
+ (tot_fix_list_size
+ + ERTS_CACHE_LINE_SIZE - 1));
+ if (!fix_lists)
+ erl_exit(ERTS_ABORT_EXIT,
+ "Failed to allocate fix lists for %salloc\n",
+ init->init.util.name_prefix);
+
+ if (((UWord) fix_lists) & ERTS_CACHE_LINE_MASK)
+ fix_lists = ((ErtsAlcFixList_t *)
+ ((((UWord) fix_lists) & ~ERTS_CACHE_LINE_MASK)
+ + ERTS_CACHE_LINE_SIZE));
+ }
+
for (i = 0; i < size; i++) {
void *as;
atype = init->atype;
@@ -868,25 +950,32 @@ start_au_allocator(ErtsAlcType_t alctr_n,
as0 = (void *) tspec->allctr[i];
if (!as0)
continue;
- if (i == 0) {
- if (atype == AFIT)
- atype = GOODFIT;
- init->init.util.ts = 1;
+ if (init->thr_spec < 0) {
+ init->init.util.ts = i == 0;
+ init->init.util.tspec = 0;
+ init->init.util.tpref = -1*init->thr_spec + 1;
}
else {
- if (init->thr_spec < 0) {
+ if (i != 0)
+ init->init.util.ts = 0;
+ else {
+ if (atype == AFIT)
+ atype = GOODFIT;
init->init.util.ts = 1;
- init->init.util.tspec = 0;
- init->init.util.tpref = -1*init->thr_spec;
}
- else {
- init->init.util.ts = 0;
- init->init.util.tspec = init->thr_spec + 1;
- init->init.util.tpref = 0;
- }
- }
+ init->init.util.tspec = init->thr_spec + 1;
+ init->init.util.tpref = 0;
+ }
}
+ if (fix_lists) {
+ init->init.util.fix = fix_lists;
+ fix_lists = ((ErtsAlcFixList_t *)
+ (((char *) fix_lists) + fix_list_size));
+ }
+
+ init->init.util.ix = i;
+
switch (atype) {
case GOODFIT:
as = (void *) erts_gfalc_start((GFAllctr_t *) as0,
@@ -903,6 +992,12 @@ start_au_allocator(ErtsAlcType_t alctr_n,
&init->init.af,
&init->init.util);
break;
+ case AOFIRSTFIT:
+ as = (void *) erts_aoffalc_start((AOFFAllctr_t *) as0,
+ &init->init.aoff,
+ &init->init.util);
+ break;
+
default:
as = NULL;
ASSERT(0);
@@ -916,11 +1011,8 @@ start_au_allocator(ErtsAlcType_t alctr_n,
af->extra = as;
}
- if (init->thr_spec) {
+ if (init->thr_spec)
af->extra = tspec;
- init->init.util.ts = 1;
- }
-
ai->extra = af->extra;
}
@@ -1040,34 +1132,6 @@ get_amount_value(char *param_end, char** argv, int* ip)
return (Uint) tmp;
}
-static int
-get_bool_or_possitive_amount_value(int *bool, Uint *amount,
- char *param_end, char** argv, int* ip)
-{
- char *param = argv[*ip]+1;
- char *value = get_value(param_end, argv, ip);
- if (strcmp(value, "true") == 0) {
- *bool = 1;
- return 1;
- }
- else if (strcmp(value, "false") == 0) {
- *bool = 0;
- return 1;
- }
- else {
- Sint tmp;
- char *rest;
- errno = 0;
- tmp = (Sint) strtol(value, &rest, 10);
- if (errno != 0 || rest == value || tmp <= 0) {
- bad_value(param, param_end, value);
- return -1;
- }
- *amount = (Uint) tmp;
- return 0;
- }
-}
-
static void
handle_au_arg(struct au_init *auip,
char* sub_param,
@@ -1097,6 +1161,9 @@ handle_au_arg(struct au_init *auip,
else if (strcmp("af", alg) == 0) {
auip->atype = AFIT;
}
+ else if (strcmp("aoff", alg) == 0) {
+ auip->atype = AOFIRSTFIT;
+ }
else {
bad_value(param, sub_param + 1, alg);
}
@@ -1179,25 +1246,16 @@ handle_au_arg(struct au_init *auip,
goto bad_switch;
break;
case 't': {
- Uint no;
- int enable;
- int res = get_bool_or_possitive_amount_value(&enable,
- &no,
- sub_param+1,
- argv,
- ip);
- if (res > 0)
- auip->thr_spec = enable ? 1 : 0;
+ int res = get_bool_value(sub_param+1, argv, ip);
+ if (res > 0) {
+ auip->thr_spec = 1;
+ break;
+ }
else if (res == 0) {
- int allocs = (int) no;
- if (allocs < 0)
- allocs = INT_MIN;
- else {
- allocs *= -1;
- }
- auip->thr_spec = allocs;
+ auip->thr_spec = 0;
+ break;
}
- break;
+ goto bad_switch;
}
default:
bad_switch:
@@ -1216,6 +1274,7 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
&init->eheap_alloc,
&init->ll_alloc,
&init->driver_alloc,
+ &init->fix_alloc,
&init->sl_alloc,
&init->temp_alloc
};
@@ -1246,14 +1305,8 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
case 'E':
handle_au_arg(&init->ets_alloc, &argv[i][3], argv, &i);
break;
- case 'F': /* fix_alloc */
- if (has_prefix("e", param+2)) {
- arg = get_value(param+3, argv, &i);
- if (strcmp("true", arg) != 0)
- bad_value(param, param+3, arg);
- }
- else
- bad_param(param, param+2);
+ case 'F':
+ handle_au_arg(&init->fix_alloc, &argv[i][3], argv, &i);
break;
case 'H':
handle_au_arg(&init->eheap_alloc, &argv[i][3], argv, &i);
@@ -1280,12 +1333,6 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
#endif
get_amount_value(argv[i]+6, argv, &i);
}
- else if (has_prefix("cci", argv[i]+3)) {
-#if HAVE_ERTS_MSEG
- init->mseg.cci =
-#endif
- get_amount_value(argv[i]+6, argv, &i);
- }
else {
bad_param(param, param+2);
}
@@ -1371,6 +1418,7 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
set_default_binary_alloc_opts(&init->binary_alloc);
set_default_ets_alloc_opts(&init->ets_alloc);
set_default_driver_alloc_opts(&init->driver_alloc);
+ set_default_driver_alloc_opts(&init->fix_alloc);
init->driver_alloc.enable = 0;
if (strcmp("r9c", arg) == 0) {
@@ -1505,43 +1553,74 @@ static char *type_no_str(ErtsAlcType_t n)
#define type_str(T) type_no_str(ERTS_ALC_T2N((T)))
-erts_tsd_key_t thr_ix_key;
-erts_spinlock_t alloc_thr_ix_lock;
-int last_thr_ix;
-int first_dyn_thr_ix;
-
-static void
-init_thr_ix(int static_ixs)
+void
+erts_alloc_register_scheduler(void *vesdp)
{
- erts_tsd_key_create(&thr_ix_key);
- erts_spinlock_init(&alloc_thr_ix_lock, "alloc_thr_ix_lock");
- last_thr_ix = -4711;
- first_dyn_thr_ix = static_ixs+1;
+ ErtsSchedulerData *esdp = (ErtsSchedulerData *) vesdp;
+ int ix = (int) esdp->no;
+ int aix;
+
+ for (aix = ERTS_ALC_A_MIN; aix <= ERTS_ALC_A_MAX; aix++) {
+ ErtsAllocatorThrSpec_t *tspec = &erts_allctr_thr_spec[aix];
+ esdp->alloc_data.deallctr[aix] = NULL;
+ esdp->alloc_data.pref_ix[aix] = -1;
+ if (tspec->enabled) {
+ if (!tspec->dd)
+ esdp->alloc_data.pref_ix[aix] = ix;
+ else {
+ Allctr_t *allctr = tspec->allctr[ix];
+ ASSERT(allctr);
+ esdp->alloc_data.deallctr[aix] = allctr;
+ esdp->alloc_data.pref_ix[aix] = ix;
+ }
+ }
+ }
}
-int
-erts_alc_get_thr_ix(void)
+void
+erts_alloc_scheduler_handle_delayed_dealloc(void *vesdp,
+ int *need_thr_progress,
+ int *more_work)
{
- int ix = (int)(long) erts_tsd_get(thr_ix_key);
- if (ix == 0) {
- erts_spin_lock(&alloc_thr_ix_lock);
- last_thr_ix++;
- if (last_thr_ix < 0)
- last_thr_ix = first_dyn_thr_ix;
- ix = last_thr_ix;
- erts_spin_unlock(&alloc_thr_ix_lock);
- erts_tsd_set(thr_ix_key, (void *)(long) ix);
+ ErtsSchedulerData *esdp = (ErtsSchedulerData *) vesdp;
+ int aix;
+ for (aix = ERTS_ALC_A_MIN; aix <= ERTS_ALC_A_MAX; aix++) {
+ Allctr_t *allctr;
+ if (esdp)
+ allctr = esdp->alloc_data.deallctr[aix];
+ else {
+ ErtsAllocatorThrSpec_t *tspec = &erts_allctr_thr_spec[aix];
+ if (tspec->enabled && tspec->dd)
+ allctr = tspec->allctr[0];
+ else
+ allctr = NULL;
+ }
+ if (allctr) {
+ erts_alcu_check_delayed_dealloc(allctr,
+ 1,
+ need_thr_progress,
+ more_work);
+ }
}
- ASSERT(ix > 0);
- return ix;
}
-void erts_alloc_reg_scheduler_id(Uint id)
+erts_aint32_t
+erts_alloc_fix_alloc_shrink(int ix, erts_aint32_t flgs)
{
- int ix = (int) id;
- ASSERT(0 < ix && ix <= first_dyn_thr_ix);
- ASSERT(0 == (int) (long) erts_tsd_get(thr_ix_key));
- erts_tsd_set(thr_ix_key, (void *)(long) ix);
+#ifdef ERTS_SMP
+ ErtsAllocatorThrSpec_t *tspec;
+ tspec = &erts_allctr_thr_spec[ERTS_ALC_A_FIXED_SIZE];
+ if (erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].thr_spec && tspec->enabled)
+ return erts_alcu_fix_alloc_shrink(tspec->allctr[ix], flgs);
+ if (ix == 0 && erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].extra)
+ return erts_alcu_fix_alloc_shrink(
+ erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].extra, flgs);
+#else
+ if (ix == 1 && erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].extra)
+ return erts_alcu_fix_alloc_shrink(
+ erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].extra, flgs);
+#endif
+ return 0;
}
static void
@@ -1556,14 +1635,12 @@ erts_alloc_get_verify_unused_temp_alloc(Allctr_t **allctr)
if (erts_allctrs_info[ERTS_ALC_A_TEMPORARY].alloc_util
&& erts_allctrs_info[ERTS_ALC_A_TEMPORARY].thr_spec) {
ErtsAllocatorThrSpec_t *tspec;
+ int ix = ERTS_ALC_GET_THR_IX();
tspec = &erts_allctr_thr_spec[ERTS_ALC_A_TEMPORARY];
- if (!tspec->all_thr_safe) {
- int ix = erts_alc_get_thr_ix();
- if (ix < tspec->size) {
- *allctr = tspec->allctr[ix];
- return erts_alcu_verify_unused;
- }
+ if (ix < tspec->size) {
+ *allctr = tspec->allctr[ix];
+ return erts_alcu_verify_unused;
}
}
@@ -1662,7 +1739,7 @@ erts_realloc_n_enomem(ErtsAlcType_t n, void *ptr, Uint size)
}
static ERTS_INLINE UWord
-alcu_size(ErtsAlcType_t ai)
+alcu_size(ErtsAlcType_t ai, ErtsAlcUFixInfo_t *fi, int fisz)
{
UWord res = 0;
@@ -1672,22 +1749,20 @@ alcu_size(ErtsAlcType_t ai)
if (!erts_allctrs_info[ai].thr_spec) {
Allctr_t *allctr = erts_allctrs_info[ai].extra;
AllctrSize_t asize;
- erts_alcu_current_size(allctr, &asize);
+ erts_alcu_current_size(allctr, &asize, fi, fisz);
res += asize.blocks;
}
else {
ErtsAllocatorThrSpec_t *tspec = &erts_allctr_thr_spec[ai];
int i;
- ASSERT(tspec->all_thr_safe);
-
ASSERT(tspec->enabled);
for (i = tspec->size - 1; i >= 0; i--) {
Allctr_t *allctr = tspec->allctr[i];
AllctrSize_t asize;
if (allctr) {
- erts_alcu_current_size(allctr, &asize);
+ erts_alcu_current_size(allctr, &asize, fi, fisz);
res += asize.blocks;
}
}
@@ -1715,7 +1790,6 @@ alcu_is_low(ErtsAlcType_t ai)
int found_one = 0;
# endif
- ASSERT(tspec->all_thr_safe);
ASSERT(tspec->enabled);
for (i = tspec->size - 1; i >= 0; i--) {
@@ -1739,11 +1813,24 @@ alcu_is_low(ErtsAlcType_t ai)
}
#endif /* HALFWORD */
+static ERTS_INLINE void
+add_fix_values(UWord *ap, UWord *up, ErtsAlcUFixInfo_t *fi, ErtsAlcType_t type)
+{
+ int ix = ERTS_ALC_T2N(type) - ERTS_ALC_N_MIN_A_FIXED_SIZE;
+ ASSERT(0 <= ix && ix < ERTS_ALC_NO_FIXED_SIZES);
+
+ *ap += (UWord) fi[ix].allocated;
+ *up += (UWord) fi[ix].used;
+}
+
Eterm
erts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg)
{
+/*
+ * NOTE! When updating this function, make sure to also update
+ * erlang:memory/[0,1] in $ERL_TOP/erts/preloaded/src/erlang.erl
+ */
#define ERTS_MEM_NEED_ALL_ALCU (!erts_instr_stat && want_tot_or_sys)
- ErtsFixInfo efi;
struct {
int total;
int processes;
@@ -1782,6 +1869,9 @@ erts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg)
Eterm res = THE_NON_VALUE;
ErtsAlcType_t ai;
int only_one_value = 0;
+ ErtsAlcUFixInfo_t fi[ERTS_ALC_NO_FIXED_SIZES] = {{0,0}};
+
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
/* Figure out whats wanted... */
@@ -1951,7 +2041,6 @@ erts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg)
for (ai = ERTS_ALC_A_MIN; ai <= ERTS_ALC_A_MAX; ai++) {
switch (ai) {
case ERTS_ALC_A_SYSTEM:
- case ERTS_ALC_A_FIXED_SIZE:
case ERTS_ALC_A_SBMBC:
#if HALFWORD_HEAP
case ERTS_ALC_A_SBMBC_LOW:
@@ -2011,11 +2100,15 @@ erts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg)
case ERTS_ALC_A_BINARY:
save = &size.binary;
break;
+ case ERTS_ALC_A_FIXED_SIZE:
+ asz = alcu_size(ai, fi, ERTS_ALC_NO_FIXED_SIZES);
+ size.total += asz;
+ continue;
default:
save = NULL;
break;
}
- asz = alcu_size(ai);
+ asz = alcu_size(ai, NULL, 0);
if (save)
*save = asz;
size.total += asz;
@@ -2035,8 +2128,11 @@ erts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg)
if (ERTS_MEM_NEED_ALL_ALCU)
tmp = size.processes;
- else
- tmp = alcu_size(ERTS_ALC_A_EHEAP);
+ else {
+ alcu_size(ERTS_ALC_A_FIXED_SIZE,
+ fi, ERTS_ALC_NO_FIXED_SIZES);
+ tmp = alcu_size(ERTS_ALC_A_EHEAP, NULL, 0);
+ }
tmp += erts_max_processes*sizeof(Process*);
#ifdef HYBRID
tmp += erts_max_processes*sizeof(Process*);
@@ -2046,69 +2142,54 @@ erts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg)
size.processes = size.processes_used = tmp;
-#if HALFWORD_HEAP
- /* BUG: We ignore link and monitor memory */
-#else
- erts_fix_info(ERTS_ALC_T_NLINK_SH, &efi);
- size.processes += efi.total;
- size.processes_used += efi.used;
+ add_fix_values(&size.processes,
+ &size.processes_used,
+ fi,
+ ERTS_ALC_T_PROC);
+#if !HALFWORD_HEAP
+ add_fix_values(&size.processes,
+ &size.processes_used,
+ fi,
+ ERTS_ALC_T_MONITOR_SH);
- erts_fix_info(ERTS_ALC_T_MONITOR_SH, &efi);
- size.processes += efi.total;
- size.processes_used += efi.used;
+ add_fix_values(&size.processes,
+ &size.processes_used,
+ fi,
+ ERTS_ALC_T_NLINK_SH);
#endif
-
- erts_fix_info(ERTS_ALC_T_PROC, &efi);
- size.processes += efi.total;
- size.processes_used += efi.used;
-
- erts_fix_info(ERTS_ALC_T_REG_PROC, &efi);
- size.processes += efi.total;
- size.processes_used += efi.used;
-
+ add_fix_values(&size.processes,
+ &size.processes_used,
+ fi,
+ ERTS_ALC_T_MSG_REF);
}
if (want.atom || want.atom_used) {
Uint reserved_atom_space, atom_space;
erts_atom_get_text_space_sizes(&reserved_atom_space, &atom_space);
size.atom = size.atom_used = atom_table_sz();
- erts_fix_info(ERTS_ALC_T_ATOM, &efi);
- if (want.atom) {
+ if (want.atom)
size.atom += reserved_atom_space;
- size.atom += efi.total;
- }
- if (want.atom_used) {
+ if (want.atom_used)
size.atom_used += atom_space;
- size.atom_used += efi.used;
- }
}
if (!ERTS_MEM_NEED_ALL_ALCU && want.binary)
- size.binary = alcu_size(ERTS_ALC_A_BINARY);
+ size.binary = alcu_size(ERTS_ALC_A_BINARY, NULL, 0);
if (want.code) {
size.code = module_table_sz();
- erts_fix_info(ERTS_ALC_T_MODULE, &efi);
- size.code += efi.used;
size.code += export_table_sz();
-#if HALFWORD_HEAP
size.code += export_list_size() * sizeof(Export);
-#else
- erts_fix_info(ERTS_ALC_T_EXPORT, &efi);
- size.code += efi.used;
-#endif
size.code += erts_fun_table_sz();
- erts_fix_info(ERTS_ALC_T_FUN_ENTRY, &efi);
- size.code += efi.used;
size.code += allocated_modules*sizeof(Range);
size.code += erts_total_code_size;
}
if (want.ets) {
if (!ERTS_MEM_NEED_ALL_ALCU)
- size.ets = alcu_size(ERTS_ALC_A_ETS);
+ size.ets = alcu_size(ERTS_ALC_A_ETS, NULL, 0);
size.ets += erts_get_ets_misc_mem_size();
}
@@ -2181,13 +2262,10 @@ struct aa_values {
Eterm
erts_allocated_areas(int *print_to_p, void *print_to_arg, void *proc)
{
-#define MAX_AA_VALUES \
- (20 + (ERTS_ALC_N_MAX_A_FIXED_SIZE - ERTS_ALC_N_MIN_A_FIXED_SIZE + 1))
-
+#define MAX_AA_VALUES (23)
struct aa_values values[MAX_AA_VALUES];
Eterm res = THE_NON_VALUE;
int i, length;
- ErtsFixInfo efi;
Uint reserved_atom_space, atom_space;
if (proc) {
@@ -2252,6 +2330,11 @@ erts_allocated_areas(int *print_to_p, void *print_to_arg, void *proc)
i++;
values[i].arity = 2;
+ values[i].name = "export_list";
+ values[i].ui[0] = export_list_size() * sizeof(Export);
+ i++;
+
+ values[i].arity = 2;
values[i].name = "register_table";
values[i].ui[0] = process_reg_sz();
i++;
@@ -2296,22 +2379,15 @@ erts_allocated_areas(int *print_to_p, void *print_to_arg, void *proc)
values[i].ui[0] = erts_tot_link_lh_size();
i++;
- {
- Uint n;
-
- for (n = ERTS_ALC_N_MIN_A_FIXED_SIZE;
- n <= ERTS_ALC_N_MAX_A_FIXED_SIZE;
- n++) {
- erts_fix_info(ERTS_ALC_N2T(n), &efi);
-
- values[i].arity = 3;
- values[i].name = ERTS_ALC_N2TD(n);
- values[i].ui[0] = efi.total;
- values[i].ui[1] = efi.used;
- i++;
- }
+ values[i].arity = 2;
+ values[i].name = "process_table";
+ values[i].ui[0] = erts_max_processes*sizeof(Process*);
+ i++;
- }
+ values[i].arity = 2;
+ values[i].name = "ets_misc";
+ values[i].ui[0] = erts_get_ets_misc_mem_size();
+ i++;
length = i;
ASSERT(length <= MAX_AA_VALUES);
@@ -2405,17 +2481,16 @@ erts_alloc_util_allocators(void *proc)
Uint sz;
int i;
/*
- * Currently all allocators except sys_alloc and fix_alloc are
+ * Currently all allocators except sys_alloc are
* alloc_util allocators.
*/
- sz = ((ERTS_ALC_A_MAX + 1 - ERTS_ALC_A_MIN) - 2)*2;
+ sz = ((ERTS_ALC_A_MAX + 1 - ERTS_ALC_A_MIN) - 1)*2;
ASSERT(sz > 0);
hp = HAlloc((Process *) proc, sz);
res = NIL;
for (i = ERTS_ALC_A_MAX; i >= ERTS_ALC_A_MIN; i--) {
switch (i) {
case ERTS_ALC_A_SYSTEM:
- case ERTS_ALC_A_FIXED_SIZE:
break;
default: {
char *alc_str = (char *) ERTS_ALC_A2AD(i);
@@ -2429,267 +2504,12 @@ erts_alloc_util_allocators(void *proc)
return res;
}
-Eterm
-erts_allocator_info_term(void *proc, Eterm which_alloc, int only_sz)
-{
-#define ERTS_AIT_RET(R) \
- do { res = (R); goto done; } while (0)
-#define ERTS_AIT_HALLOC(P, S) \
- do { hp = HAlloc((P), (S)); hp_end = hp + (S); } while (0)
-
- ErtsAlcType_t i;
- Uint sz = 0;
- Uint *hp = NULL;
- Uint *hp_end = NULL;
- Eterm res = am_undefined;
-
- if (is_not_atom(which_alloc))
- goto done;
-
- for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {
- if (erts_is_atom_str((char *) ERTS_ALC_A2AD(i), which_alloc)) {
- if (!erts_allctrs_info[i].enabled)
- ERTS_AIT_RET(am_false);
- else {
- if (erts_allctrs_info[i].alloc_util) {
- Eterm ires, tmp;
- Eterm **hpp;
- Uint *szp;
- Eterm (*info_func)(Allctr_t *,
- int,
- int *,
- void *,
- Uint **,
- Uint *);
-
- info_func = (only_sz
- ? erts_alcu_sz_info
- : erts_alcu_info);
-
- if (erts_allctrs_info[i].thr_spec) {
- ErtsAllocatorThrSpec_t *tspec = &erts_allctr_thr_spec[i];
- int j;
- int block_system = !tspec->all_thr_safe;
-
- if (block_system) {
- erts_smp_proc_unlock(proc, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
- }
- ASSERT(tspec->enabled);
-
- szp = &sz;
- hpp = NULL;
-
- while (1) {
- ires = NIL;
- for (j = tspec->size - 1; j >= 0; j--) {
- Allctr_t *allctr = tspec->allctr[j];
- if (allctr) {
- tmp = erts_bld_tuple(hpp,
- szp,
- 3,
- erts_bld_atom(hpp,
- szp,
- "instance"),
- make_small((Uint) j),
- (*info_func)(allctr,
- hpp != NULL,
- NULL,
- NULL,
- hpp,
- szp));
- ires = erts_bld_cons(hpp, szp, tmp, ires);
- }
- }
- if (hpp)
- break;
- ERTS_AIT_HALLOC((Process *) proc, sz);
- hpp = &hp;
- szp = NULL;
- }
-
- if (block_system) {
- erts_smp_release_system();
- erts_smp_proc_lock(proc, ERTS_PROC_LOCK_MAIN);
- }
- }
- else {
- Allctr_t *allctr = erts_allctrs_info[i].extra;
- szp = &sz;
- hpp = NULL;
- while (1) {
- ires = NIL;
- tmp = erts_bld_tuple(hpp,
- szp,
- 3,
- erts_bld_atom(hpp,
- szp,
- "instance"),
- make_small((Uint) 0),
- (*info_func)(allctr,
- hpp != NULL,
- NULL,
- NULL,
- hpp,
- szp));
- ires = erts_bld_cons(hpp, szp, tmp, ires);
- if (hpp)
- break;
- ERTS_AIT_HALLOC((Process *) proc, sz);
- hpp = &hp;
- szp = NULL;
- }
- }
- ERTS_AIT_RET(ires);
- }
- else {
- Eterm *szp, **hpp;
-
- switch (i) {
- case ERTS_ALC_A_SYSTEM: {
- SysAllocStat sas;
- Eterm opts_am;
- Eterm opts;
- Eterm as[4]; /* Ok even if !HEAP_ON_C_STACK, not really heap data on stack */
- Eterm ts[4]; /* Ok even if !HEAP_ON_C_STACK, not really heap data on stack */
- int l;
-
- if (only_sz)
- ERTS_AIT_RET(NIL);
-
- sys_alloc_stat(&sas);
- opts_am = am_atom_put("options", 7);
-
- szp = &sz;
- hpp = NULL;
-
- restart_sys_alloc:
- l = 0;
- as[l] = am_atom_put("e", 1);
- ts[l++] = am_true;
- as[l] = am_atom_put("m", 1);
- ts[l++] = am_atom_put("libc", 4);
- if(sas.trim_threshold >= 0) {
- as[l] = am_atom_put("tt", 2);
- ts[l++] = erts_bld_uint(hpp, szp,
- (Uint) sas.trim_threshold);
- }
- if(sas.top_pad >= 0) {
- as[l] = am_atom_put("tp", 2);
- ts[l++] = erts_bld_uint(hpp, szp, (Uint) sas.top_pad);
- }
-
- opts = erts_bld_2tup_list(hpp, szp, l, as, ts);
- res = erts_bld_2tup_list(hpp, szp, 1, &opts_am, &opts);
-
- if (szp) {
- ERTS_AIT_HALLOC((Process *) proc, sz);
- szp = NULL;
- hpp = &hp;
- goto restart_sys_alloc;
- }
- ERTS_AIT_RET(res);
- }
- case ERTS_ALC_A_FIXED_SIZE: {
- ErtsAlcType_t n;
- Eterm as[2], vs[2];
-
- if (only_sz)
- ERTS_AIT_RET(NIL);
-
- as[0] = am_atom_put("options", 7);
- as[1] = am_atom_put("pools", 5);
-
- szp = &sz;
- hpp = NULL;
-
- restart_fix_alloc:
-
- vs[0] = erts_bld_cons(hpp, szp,
- erts_bld_tuple(hpp, szp, 2,
- am_atom_put("e",
- 1),
- am_true),
- NIL);
-
- vs[1] = NIL;
- for (n = ERTS_ALC_N_MIN_A_FIXED_SIZE;
- n <= ERTS_ALC_N_MAX_A_FIXED_SIZE;
- n++) {
- ErtsFixInfo efi;
- erts_fix_info(ERTS_ALC_N2T(n), &efi);
-
- vs[1] = erts_bld_cons(
- hpp, szp,
- erts_bld_tuple(
- hpp, szp, 3,
- am_atom_put((char *) ERTS_ALC_N2TD(n),
- strlen(ERTS_ALC_N2TD(n))),
- erts_bld_uint(hpp, szp, efi.total),
- erts_bld_uint(hpp, szp, efi.used)),
- vs[1]);
-
- }
-
- res = erts_bld_2tup_list(hpp, szp, 2, as, vs);
- if (szp) {
- ERTS_AIT_HALLOC((Process *) proc, sz);
- szp = NULL;
- hpp = &hp;
- goto restart_fix_alloc;
- }
- ERTS_AIT_RET(res);
- }
- default:
- ASSERT(0);
- goto done;
- }
- }
- }
- }
- }
-
- if (ERTS_IS_ATOM_STR("mseg_alloc", which_alloc)) {
-#if HAVE_ERTS_MSEG
- if (only_sz)
- ERTS_AIT_RET(NIL);
- erts_mseg_info(NULL, NULL, 0, NULL, &sz);
- if (sz)
- ERTS_AIT_HALLOC((Process *) proc, sz);
- ERTS_AIT_RET(erts_mseg_info(NULL, NULL, 1, &hp, NULL));
-#else
- ERTS_AIT_RET(am_false);
-#endif
-
- }
- else if (ERTS_IS_ATOM_STR("alloc_util", which_alloc)) {
- if (only_sz)
- ERTS_AIT_RET(NIL);
- erts_alcu_au_info_options(NULL, NULL, NULL, &sz);
- if (sz)
- ERTS_AIT_HALLOC((Process *) proc, sz);
- ERTS_AIT_RET(erts_alcu_au_info_options(NULL, NULL, &hp, NULL));
- }
-
- done:
- if (hp) {
- ASSERT(hp_end >= hp);
- HRelease((Process *) proc, hp_end, hp);
- }
- return res;
-
-#undef ERTS_AIT_RET
-#undef ERTS_AIT_HALLOC
-}
-
void
erts_allocator_info(int to, void *arg)
{
ErtsAlcType_t a;
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0)
- || (ERTS_IS_CRASH_DUMPING
- && erts_smp_is_system_blocked(ERTS_BS_FLG_ALLOW_GC)));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
for (a = ERTS_ALC_A_MIN; a <= ERTS_ALC_A_MAX; a++) {
int ai;
@@ -2730,22 +2550,6 @@ erts_allocator_info(int to, void *arg)
erts_print(to, arg, "option tp: %d\n", sas.top_pad);
break;
}
- case ERTS_ALC_A_FIXED_SIZE: {
- ErtsAlcType_t n;
- erts_print(to, arg, "option e: true\n");
-
- for (n = ERTS_ALC_N_MIN_A_FIXED_SIZE;
- n <= ERTS_ALC_N_MAX_A_FIXED_SIZE;
- n++) {
- ErtsFixInfo efi;
- erts_fix_info(ERTS_ALC_N2T(n), &efi);
- erts_print(to, arg, "%s: %lu %lu\n",
- ERTS_ALC_N2TD(n),
- efi.total,
- efi.used);
- }
- break;
- }
default:
ASSERT(0);
break;
@@ -2756,8 +2560,18 @@ erts_allocator_info(int to, void *arg)
}
#if HAVE_ERTS_MSEG
- erts_print(to, arg, "=allocator:mseg_alloc\n");
- erts_mseg_info(&to, arg, 0, NULL, NULL);
+ {
+#ifdef ERTS_SMP
+ int max = (int) erts_no_schedulers;
+#else
+ int max = 0;
+#endif
+ int i;
+ for (i = 0; i <= max; i++) {
+ erts_print(to, arg, "=allocator:mseg_alloc[%d]\n", i);
+ erts_mseg_info(i, &to, arg, 0, NULL, NULL);
+ }
+ }
#endif
erts_print(to, arg, "=allocator:alloc_util\n");
@@ -2811,7 +2625,7 @@ erts_allocator_options(void *proc)
use_mseg++;
#endif
if (erts_allctr_thr_spec[a].enabled)
- allctr = erts_allctr_thr_spec[a].allctr[1];
+ allctr = erts_allctr_thr_spec[a].allctr[0];
else
allctr = erts_allctrs_info[a].extra;
tmp = erts_alcu_info_options(allctr, NULL, NULL, hpp, szp);
@@ -2860,7 +2674,7 @@ erts_allocator_options(void *proc)
#if HAVE_ERTS_MSEG
if (use_mseg) {
atoms[length] = am_atom_put("mseg_alloc", 10);
- terms[length++] = erts_mseg_info_options(NULL, NULL, hpp, szp);
+ terms[length++] = erts_mseg_info_options(0, NULL, NULL, hpp, szp);
}
#endif
@@ -2942,6 +2756,338 @@ erts_allocator_options(void *proc)
return res;
}
+void *erts_alloc_permanent_cache_aligned(ErtsAlcType_t type, Uint size)
+{
+ UWord v = (UWord) erts_alloc(type, size + (ERTS_CACHE_LINE_SIZE-1)
+#ifdef VALGRIND
+ + sizeof(UWord)
+#endif
+ );
+
+#ifdef VALGRIND
+ { /* Link them to avoid Leak_PossiblyLost */
+ static UWord* first_in_list = NULL;
+ *(UWord**)v = first_in_list;
+ first_in_list = (UWord*) v;
+ v += sizeof(UWord);
+ }
+#endif
+
+ if (v & ERTS_CACHE_LINE_MASK) {
+ v = (v & ~ERTS_CACHE_LINE_MASK) + ERTS_CACHE_LINE_SIZE;
+ }
+ ASSERT((v & ERTS_CACHE_LINE_MASK) == 0);
+ return (void*)v;
+}
+
+static void
+reply_alloc_info(void *vair)
+{
+ ErtsAllocInfoReq *air = (ErtsAllocInfoReq *) vair;
+ Uint sched_id = erts_get_scheduler_id();
+ int global_instances = air->req_sched == sched_id;
+ ErtsProcLocks rp_locks;
+ Process *rp = air->proc;
+ Eterm ref_copy = NIL, ai_list, msg;
+ Eterm *hp = NULL, *hp_end = NULL, *hp_start = NULL;
+ Eterm **hpp;
+ Uint sz, *szp;
+ ErlOffHeap *ohp = NULL;
+ ErlHeapFragment *bp = NULL;
+ int i;
+ Eterm (*info_func)(Allctr_t *,
+ int,
+ int *,
+ void *,
+ Uint **,
+ Uint *) = (air->only_sz
+ ? erts_alcu_sz_info
+ : erts_alcu_info);
+
+ rp_locks = air->req_sched == sched_id ? ERTS_PROC_LOCK_MAIN : 0;
+
+ sz = 0;
+ hpp = NULL;
+ szp = &sz;
+
+ while (1) {
+
+ if (hpp)
+ ref_copy = STORE_NC(hpp, ohp, air->ref);
+ else
+ *szp += REF_THING_SIZE;
+
+ ai_list = NIL;
+ for (i = 0; air->allocs[i] != ERTS_ALC_A_INVALID; i++);
+ for (i--; i >= 0; i--) {
+ int ai = air->allocs[i];
+ Allctr_t *allctr;
+ Eterm ainfo;
+ Eterm alloc_atom;
+ if (global_instances) {
+ switch (ai) {
+ case ERTS_ALC_A_SYSTEM: {
+ alloc_atom = erts_bld_atom(hpp, szp, "sys_alloc");
+ ainfo = NIL;
+ if (!air->only_sz) {
+ SysAllocStat sas;
+ if (hpp)
+ sys_alloc_stat(&sas);
+ if (szp) {
+ /* ensure ehough heap */
+ sas.top_pad = INT_MAX;
+ sas.trim_threshold = INT_MAX;
+ }
+ if (sas.top_pad >= 0) {
+ ainfo = erts_bld_cons(
+ hpp, szp,
+ erts_bld_tuple(
+ hpp, szp, 2,
+ erts_bld_atom(hpp, szp, "tp"),
+ erts_bld_uint(
+ hpp, szp,
+ (Uint) sas.top_pad)),
+ ainfo);
+ }
+ if (sas.trim_threshold >= 0) {
+ ainfo = erts_bld_cons(
+ hpp, szp,
+ erts_bld_tuple(
+ hpp, szp, 2,
+ erts_bld_atom(hpp, szp, "tt"),
+ erts_bld_uint(
+ hpp, szp,
+ (Uint) sas.trim_threshold)),
+ ainfo);
+ }
+ ainfo = erts_bld_cons(hpp, szp,
+ erts_bld_tuple(
+ hpp, szp, 2,
+ erts_bld_atom(hpp, szp,
+ "m"),
+ erts_bld_atom(hpp, szp,
+ "libc")),
+ ainfo);
+ ainfo = erts_bld_cons(hpp, szp,
+ erts_bld_tuple(
+ hpp, szp, 2,
+ erts_bld_atom(hpp, szp,
+ "e"),
+ am_true),
+ ainfo);
+ ainfo = erts_bld_tuple(hpp, szp, 2,
+ erts_bld_atom(hpp, szp,
+ "otps"),
+ ainfo);
+ }
+ ainfo = erts_bld_tuple(hpp, szp, 3,
+ alloc_atom,
+ make_small(0),
+ ainfo);
+ break;
+ }
+ case ERTS_ALC_INFO_A_ALLOC_UTIL:
+ alloc_atom = erts_bld_atom(hpp, szp, "alloc_util");
+ ainfo = (air->only_sz
+ ? NIL
+ : erts_alcu_au_info_options(NULL, NULL,
+ hpp, szp));
+ ainfo = erts_bld_tuple(hpp, szp, 3,
+ alloc_atom,
+ make_small(0),
+ ainfo);
+ break;
+ case ERTS_ALC_INFO_A_MSEG_ALLOC:
+ alloc_atom = erts_bld_atom(hpp, szp, "mseg_alloc");
+#if HAVE_ERTS_MSEG
+ ainfo = (air->only_sz
+ ? NIL
+ : erts_mseg_info(0, NULL, NULL, hpp != NULL,
+ hpp, szp));
+ ainfo = erts_bld_tuple(hpp, szp, 3,
+ alloc_atom,
+ make_small(0),
+ ainfo);
+#else
+ ainfo = erts_bld_tuple(hpp, szp, 2, alloc_atom,
+ am_false);
+#endif
+ break;
+ default:
+ alloc_atom = erts_bld_atom(hpp, szp,
+ (char *) ERTS_ALC_A2AD(ai));
+ if (!erts_allctrs_info[ai].enabled)
+ ainfo = erts_bld_tuple(hpp, szp, 2, alloc_atom,
+ am_false);
+ else if (erts_allctrs_info[ai].alloc_util) {
+ if (erts_allctrs_info[ai].thr_spec)
+ allctr = erts_allctr_thr_spec[ai].allctr[0];
+ else
+ allctr = erts_allctrs_info[ai].extra;
+ ainfo = info_func(allctr, hpp != NULL, NULL,
+ NULL, hpp, szp);
+ ainfo = erts_bld_tuple(hpp, szp, 3, alloc_atom,
+ make_small(0), ainfo);
+ }
+ else {
+ erl_exit(ERTS_ABORT_EXIT, "%s:%d: internal error\n",
+ __FILE__, __LINE__);
+ }
+ }
+ ai_list = erts_bld_cons(hpp, szp,
+ ainfo, ai_list);
+ }
+ switch (ai) {
+ case ERTS_ALC_A_SYSTEM:
+ case ERTS_ALC_INFO_A_ALLOC_UTIL:
+ break;
+ case ERTS_ALC_INFO_A_MSEG_ALLOC:
+#if HAVE_ERTS_MSEG && defined(ERTS_SMP)
+ alloc_atom = erts_bld_atom(hpp, szp, "mseg_alloc");
+ ainfo = (air->only_sz
+ ? NIL
+ : erts_mseg_info(sched_id, NULL, NULL,
+ hpp != NULL, hpp, szp));
+ ainfo = erts_bld_tuple(hpp, szp, 3,
+ alloc_atom,
+ make_small(sched_id),
+ ainfo);
+ ai_list = erts_bld_cons(hpp, szp, ainfo, ai_list);
+#endif
+ break;
+ default:
+ if (erts_allctrs_info[ai].thr_spec) {
+ alloc_atom = erts_bld_atom(hpp, szp,
+ (char *) ERTS_ALC_A2AD(ai));
+ allctr = erts_allctr_thr_spec[ai].allctr[sched_id];
+ ainfo = info_func(allctr, hpp != NULL, NULL,
+ NULL, hpp, szp);
+ ai_list = erts_bld_cons(hpp, szp,
+ erts_bld_tuple(
+ hpp, szp,
+ 3,
+ alloc_atom,
+ make_small(sched_id),
+ ainfo),
+ ai_list);
+ }
+ break;
+ }
+ msg = erts_bld_tuple(hpp, szp,
+ 3,
+ ref_copy,
+ make_small(sched_id),
+ ai_list);
+
+ }
+ if (hpp)
+ break;
+
+ hp = erts_alloc_message_heap(sz, &bp, &ohp, rp, &rp_locks);
+ hp_start = hp;
+ hp_end = hp + sz;
+ szp = NULL;
+ hpp = &hp;
+ }
+ if (bp)
+ bp = erts_resize_message_buffer(bp, hp - hp_start, &msg, 1);
+ else {
+ ASSERT(hp);
+ HRelease(rp, hp_end, hp);
+ }
+
+ erts_queue_message(rp, &rp_locks, bp, msg, NIL);
+
+ if (air->req_sched == sched_id)
+ rp_locks &= ~ERTS_PROC_LOCK_MAIN;
+
+ erts_smp_proc_unlock(rp, rp_locks);
+ erts_smp_proc_dec_refc(rp);
+
+ if (erts_smp_atomic32_dec_read_nob(&air->refc) == 0)
+ aireq_free(air);
+}
+
+int
+erts_request_alloc_info(struct process *c_p,
+ Eterm ref,
+ Eterm allocs,
+ int only_sz)
+{
+ ErtsAllocInfoReq *air = aireq_alloc();
+ Eterm req_ai[ERTS_ALC_A_MAX+1+2] = {0};
+ Eterm alist;
+ Eterm *hp;
+ int airix = 0, ai;
+
+ air->req_sched = erts_get_scheduler_id();
+
+ air->only_sz = only_sz;
+
+ air->proc = c_p;
+
+ if (is_not_internal_ref(ref))
+ return 0;
+
+ hp = &air->ref_heap[0];
+ air->ref = STORE_NC(&hp, NULL, ref);
+
+ if (is_not_list(allocs))
+ return 0;
+
+ alist = allocs;
+
+ while (is_list(alist)) {
+ int saved = 0;
+ Eterm* consp = list_val(alist);
+ Eterm alloc = CAR(consp);
+
+ for (ai = ERTS_ALC_A_MIN; ai <= ERTS_ALC_A_MAX; ai++)
+ if (erts_is_atom_str((char *) erts_alc_a2ad[ai], alloc))
+ goto save_alloc;
+ if (erts_is_atom_str("mseg_alloc", alloc)) {
+ ai = ERTS_ALC_INFO_A_MSEG_ALLOC;
+ goto save_alloc;
+ }
+ if (erts_is_atom_str("alloc_util", alloc)) {
+ ai = ERTS_ALC_INFO_A_ALLOC_UTIL;
+ save_alloc:
+ if (req_ai[ai])
+ return 0;
+ air->allocs[airix++] = ai;
+ req_ai[ai] = 1;
+ saved = 1;
+ }
+
+ if (!saved)
+ return 0;
+
+ alist = CDR(consp);
+ }
+
+ if (is_not_nil(alist))
+ return 0;
+
+ air->allocs[airix] = ERTS_ALC_A_INVALID;
+
+ erts_smp_atomic32_init_nob(&air->refc,
+ (erts_aint32_t) erts_no_schedulers);
+
+ erts_smp_proc_add_refc(c_p, (Sint32) erts_no_schedulers);
+
+#ifdef ERTS_SMP
+ if (erts_no_schedulers > 1)
+ erts_schedule_multi_misc_aux_work(1,
+ erts_no_schedulers,
+ reply_alloc_info,
+ (void *) air);
+#endif
+
+ reply_alloc_info((void *) air);
+
+ return 1;
+}
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* Deprecated functions *
* *
@@ -2982,6 +3128,7 @@ unsigned long erts_alc_test(unsigned long op,
case 0x2: return erts_bfalc_test(op, a1, a2);
case 0x3: return erts_afalc_test(op, a1, a2);
case 0x4: return erts_mseg_test(op, a1, a2, a3);
+ case 0x5: return erts_aoffalc_test(op, a1, a2);
case 0xf:
switch (op) {
case 0xf00:
@@ -3061,6 +3208,14 @@ unsigned long erts_alc_test(unsigned long op,
&init.init.af,
&init.init.util);
break;
+ case AOFIRSTFIT:
+ allctr = erts_aoffalc_start((AOFFAllctr_t *)
+ erts_alloc(ERTS_ALC_T_UNDEF,
+ sizeof(AOFFAllctr_t)),
+ &init.init.aoff,
+ &init.init.util);
+ break;
+
default:
ASSERT(0);
allctr = NULL;
@@ -3556,6 +3711,4 @@ install_debug_functions(void)
return FENCE_SZ;
}
-
-
#endif /* #ifdef DEBUG */
diff --git a/erts/emulator/beam/erl_alloc.h b/erts/emulator/beam/erl_alloc.h
index ce792d4d17..f4133cdb1a 100644
--- a/erts/emulator/beam/erl_alloc.h
+++ b/erts/emulator/beam/erl_alloc.h
@@ -43,43 +43,40 @@
# define ERTS_ALC_INLINE
#endif
-#define ERTS_FIX_CORE_ALLOCATOR ERTS_ALC_A_LONG_LIVED
-extern ErtsAlcType_t erts_fix_core_allocator_ix;
-
-typedef struct {
- Uint total;
- Uint used;
-} ErtsFixInfo;
+#define ERTS_ALC_NO_FIXED_SIZES \
+ (ERTS_ALC_N_MAX_A_FIXED_SIZE - ERTS_ALC_N_MIN_A_FIXED_SIZE + 1)
void erts_sys_alloc_init(void);
void *erts_sys_alloc(ErtsAlcType_t, void *, Uint);
void *erts_sys_realloc(ErtsAlcType_t, void *, void *, Uint);
void erts_sys_free(ErtsAlcType_t, void *, void *);
-
-void erts_init_fix_alloc(Uint, void *(*)(Uint));
-Uint erts_get_fix_size(ErtsAlcType_t);
-void erts_set_fix_size(ErtsAlcType_t, Uint);
-void erts_fix_info(ErtsAlcType_t, ErtsFixInfo *);
-void *erts_fix_alloc(ErtsAlcType_t, void *, Uint);
-void *erts_fix_realloc(ErtsAlcType_t, void *, void*, Uint);
-void erts_fix_free(ErtsAlcType_t, void *, void*);
-
-
Eterm erts_memory(int *, void *, void *, Eterm);
Eterm erts_allocated_areas(int *, void *, void *);
Eterm erts_alloc_util_allocators(void *proc);
void erts_allocator_info(int, void *);
-Eterm erts_allocator_info_term(void *proc, Eterm which_alloc, int only_sz);
Eterm erts_allocator_options(void *proc);
+struct process;
+
+int erts_request_alloc_info(struct process *c_p, Eterm ref, Eterm allocs,
+ int only_sz);
+
#define ERTS_ALLOC_INIT_DEF_OPTS_INITER {0}
typedef struct {
- int dummy;
+ int ncpu;
} ErtsAllocInitOpts;
+typedef struct {
+ Allctr_t *deallctr[ERTS_ALC_A_MAX+1];
+ int pref_ix[ERTS_ALC_A_MAX+1];
+ int flist_ix[ERTS_ALC_A_MAX+1];
+ int pre_alc_ix;
+} ErtsSchedAllocData;
+
void erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop);
+void erts_alloc_late_init(void);
#if defined(GET_ERTS_ALC_TEST) || defined(ERTS_ALC_INTERNAL__)
/* Only for testing */
@@ -99,6 +96,14 @@ unsigned long erts_alc_test(unsigned long,
#define ERTS_ALC_MIN_LONG_LIVED_TIME (10*60*1000)
+#if HALFWORD_HEAP
+#define ERTS_IS_SBMBC_ALLOCATOR_NO__(NO) \
+ ((NO) == ERTS_ALC_A_SBMBC || (NO) == ERTS_ALC_A_SBMBC_LOW)
+#else
+#define ERTS_IS_SBMBC_ALLOCATOR_NO__(NO) \
+ ((NO) == ERTS_ALC_A_SBMBC)
+#endif
+
typedef struct {
int alloc_util;
int enabled;
@@ -118,15 +123,19 @@ extern ErtsAllocatorInfo_t erts_allctrs_info[ERTS_ALC_A_MAX+1];
typedef struct {
int enabled;
- int all_thr_safe;
+ int dd;
+ int aix;
int size;
Allctr_t **allctr;
} ErtsAllocatorThrSpec_t;
extern ErtsAllocatorThrSpec_t erts_allctr_thr_spec[ERTS_ALC_A_MAX+1];
-int erts_alc_get_thr_ix(void);
-void erts_alloc_reg_scheduler_id(Uint id);
+void erts_alloc_register_scheduler(void *vesdp);
+void erts_alloc_scheduler_handle_delayed_dealloc(void *vesdp,
+ int *need_thr_progress,
+ int *more_work);
+erts_aint32_t erts_alloc_fix_alloc_shrink(int ix, erts_aint32_t flgs);
__decl_noreturn void erts_alloc_enomem(ErtsAlcType_t,Uint)
__noreturn;
@@ -172,11 +181,11 @@ void *erts_realloc(ErtsAlcType_t type, void *ptr, Uint size);
void erts_free(ErtsAlcType_t type, void *ptr);
void *erts_alloc_fnf(ErtsAlcType_t type, Uint size);
void *erts_realloc_fnf(ErtsAlcType_t type, void *ptr, Uint size);
-void *erts_alloc_permanent_cache_aligned(ErtsAlcType_t type, Uint size);
-
#endif /* #if !ERTS_ALC_DO_INLINE */
+void *erts_alloc_permanent_cache_aligned(ErtsAlcType_t type, Uint size);
+
#ifndef ERTS_CACHE_LINE_SIZE
/* Assume a cache line size of 64 bytes */
# define ERTS_CACHE_LINE_SIZE ((UWord) 64)
@@ -242,20 +251,10 @@ void *erts_realloc_fnf(ErtsAlcType_t type, void *ptr, Uint size)
size);
}
-ERTS_ALC_INLINE
-void *erts_alloc_permanent_cache_aligned(ErtsAlcType_t type, Uint size)
-{
- UWord v = (UWord) erts_alloc(type, size + (ERTS_CACHE_LINE_SIZE-1));
-
- if (v & ERTS_CACHE_LINE_MASK) {
- v = (v & ~ERTS_CACHE_LINE_MASK) + ERTS_CACHE_LINE_SIZE;
- }
- ASSERT((v & ERTS_CACHE_LINE_MASK) == 0);
- return (void*)v;
-}
-
#endif /* #if ERTS_ALC_DO_INLINE || defined(ERTS_ALC_INTERNAL__) */
+#define ERTS_ALC_GET_THR_IX() ((int) erts_get_scheduler_id())
+
typedef void (*erts_alloc_verify_func_t)(Allctr_t *);
erts_alloc_verify_func_t
@@ -440,136 +439,41 @@ NAME##_free(TYPE *p) \
} \
}
-typedef struct {
- void *start;
- void *end;
- int chunks_mem_size;
-} erts_sched_pref_quick_alloc_data_t;
-
-#ifdef DEBUG
-#define ERTS_SPPA_DBG_CHK_IN_CHNK(A, C, P) \
-do { \
- ASSERT((void *) (C) < (void *) (P)); \
- ASSERT((void *) (P) \
- < (void *) (((char *) (C)) + (A)->chunks_mem_size)); \
-} while (0)
-#else
-#define ERTS_SPPA_DBG_CHK_IN_CHNK(A, C, P)
-#endif
+#include "erl_sched_spec_pre_alloc.h"
#define ERTS_SCHED_PREF_PRE_ALLOC_IMPL(NAME, TYPE, PASZ) \
-union erts_qa_##NAME##__ { \
+union erts_sspa_##NAME##__ { \
+ erts_sspa_blk_t next; \
TYPE type; \
- union erts_qa_##NAME##__ *next; \
}; \
-typedef struct { \
- erts_smp_spinlock_t lock; \
- union erts_qa_##NAME##__ *freelist; \
- union erts_qa_##NAME##__ pre_alloced[1]; \
-} erts_qa_##NAME##_chunk__; \
-static erts_sched_pref_quick_alloc_data_t *qa_data_##NAME##__; \
-static ERTS_INLINE erts_qa_##NAME##_chunk__ * \
-get_##NAME##_chunk_ix(int cix) \
-{ \
- char *ptr = (char *) qa_data_##NAME##__->start; \
- ptr += cix*qa_data_##NAME##__->chunks_mem_size; \
- return (erts_qa_##NAME##_chunk__ *) ptr; \
-} \
-static ERTS_INLINE erts_qa_##NAME##_chunk__ * \
-get_##NAME##_chunk_ptr(void *ptr) \
-{ \
- int cix; \
- size_t diff; \
- if (ptr < qa_data_##NAME##__->start || qa_data_##NAME##__->end <= ptr)\
- return NULL; \
- diff = ((char *) ptr) - ((char *) qa_data_##NAME##__->start); \
- cix = diff / qa_data_##NAME##__->chunks_mem_size; \
- return get_##NAME##_chunk_ix(cix); \
-} \
+ \
+static erts_sspa_data_t *sspa_data_##NAME##__; \
+ \
static void \
init_##NAME##_alloc(void) \
{ \
- size_t tot_size; \
- size_t chunk_mem_size; \
- char *chunk_start; \
- int cix; \
- int no_blocks = ERTS_PRE_ALLOC_SIZE((PASZ)); \
- int no_blocks_per_chunk = 2*((no_blocks-1)/erts_no_schedulers + 1); \
- no_blocks = no_blocks_per_chunk * erts_no_schedulers; \
- chunk_mem_size = sizeof(erts_qa_##NAME##_chunk__); \
- chunk_mem_size += (sizeof(union erts_qa_##NAME##__) \
- * (no_blocks_per_chunk - 1)); \
- chunk_mem_size = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(chunk_mem_size); \
- tot_size = sizeof(erts_sched_pref_quick_alloc_data_t); \
- tot_size += ERTS_CACHE_LINE_SIZE - 1; \
- tot_size += chunk_mem_size*erts_no_schedulers; \
- qa_data_##NAME##__ = erts_alloc(ERTS_ALC_T_PRE_ALLOC_DATA,tot_size);\
- chunk_start = (((char *) qa_data_##NAME##__) \
- + sizeof(erts_sched_pref_quick_alloc_data_t)); \
- if ((((UWord) chunk_start) & ERTS_CACHE_LINE_MASK) != ((UWord) 0)) \
- chunk_start = ((char *) \
- ((((UWord) chunk_start) & ~ERTS_CACHE_LINE_MASK) \
- + ERTS_CACHE_LINE_SIZE)); \
- qa_data_##NAME##__->chunks_mem_size = chunk_mem_size; \
- qa_data_##NAME##__->start = (void *) chunk_start; \
- qa_data_##NAME##__->end = (chunk_start \
- + chunk_mem_size*erts_no_schedulers); \
- for (cix = 0; cix < erts_no_schedulers; cix++) { \
- int i; \
- erts_qa_##NAME##_chunk__ *chunk = get_##NAME##_chunk_ix(cix); \
- erts_smp_spinlock_init(&chunk->lock, #NAME "_alloc_lock"); \
- chunk->freelist = &chunk->pre_alloced[0]; \
- for (i = 1; i < no_blocks_per_chunk; i++) { \
- ERTS_PRE_ALLOC_CLOBBER(&chunk->pre_alloced[i-1], \
- union erts_qa_##NAME##__); \
- chunk->pre_alloced[i-1].next = &chunk->pre_alloced[i]; \
- } \
- ERTS_PRE_ALLOC_CLOBBER(&chunk->pre_alloced[no_blocks_per_chunk-1],\
- union erts_qa_##NAME##__); \
- chunk->pre_alloced[no_blocks_per_chunk-1].next = NULL; \
- } \
+ sspa_data_##NAME##__ = \
+ erts_sspa_create(sizeof(union erts_sspa_##NAME##__), \
+ ERTS_PRE_ALLOC_SIZE((PASZ))); \
} \
-static ERTS_INLINE TYPE * \
+ \
+static TYPE * \
NAME##_alloc(void) \
{ \
- int cix = ((int) erts_get_scheduler_id()) - 1; \
- TYPE *res; \
- if (cix < 0) \
- res = NULL; \
- else { \
- erts_qa_##NAME##_chunk__ *chunk = get_##NAME##_chunk_ix(cix); \
- erts_smp_spin_lock(&chunk->lock); \
- if (!chunk->freelist) \
- res = NULL; \
- else { \
- res = &chunk->freelist->type; \
- chunk->freelist = chunk->freelist->next; \
- ERTS_SPPA_DBG_CHK_IN_CHNK(qa_data_##NAME##__, chunk, res); \
- } \
- erts_smp_spin_unlock(&chunk->lock); \
- } \
- return res; \
+ ErtsSchedulerData *esdp = erts_get_scheduler_data(); \
+ if (!esdp) \
+ return NULL; \
+ return (TYPE *) erts_sspa_alloc(sspa_data_##NAME##__, \
+ (int) esdp->no - 1); \
} \
-static ERTS_INLINE int \
+ \
+static int \
NAME##_free(TYPE *p) \
{ \
- erts_qa_##NAME##_chunk__ *chunk; \
- chunk = get_##NAME##_chunk_ptr((void *) p); \
- if (!chunk) \
- return 0; \
- else { \
- union erts_qa_##NAME##__ *up; \
- ERTS_SPPA_DBG_CHK_IN_CHNK(qa_data_##NAME##__, chunk, p); \
- up = ((union erts_qa_##NAME##__ *) \
- (((char *) p) \
- - ((char *) &((union erts_qa_##NAME##__ *) 0)->type))); \
- erts_smp_spin_lock(&chunk->lock); \
- ERTS_PRE_ALLOC_CLOBBER(up, union erts_qa_##NAME##__); \
- up->next = chunk->freelist; \
- chunk->freelist = up; \
- erts_smp_spin_unlock(&chunk->lock); \
- return 1; \
- } \
+ ErtsSchedulerData *esdp = erts_get_scheduler_data(); \
+ return erts_sspa_free(sspa_data_##NAME##__, \
+ esdp ? (int) esdp->no - 1 : -1, \
+ (char *) p); \
}
#ifdef DEBUG
diff --git a/erts/emulator/beam/erl_alloc.types b/erts/emulator/beam/erl_alloc.types
index eda0831441..962db8b831 100644
--- a/erts/emulator/beam/erl_alloc.types
+++ b/erts/emulator/beam/erl_alloc.types
@@ -50,6 +50,15 @@
# command line argument to make_alloc_types. The variable X is false
# after a "+disable X" statement or if it has never been mentioned.
++if smp
++disable threads_no_smp
++else
++if threads
++enable threads_no_smp
++else
++disable threads_no_smp
++endif
++endif
# --- Allocator declarations -------------------------------------------------
#
@@ -133,29 +142,25 @@ class SYSTEM system_data
# should be deallocated before the emulator starts executing Erlang
# code again.
#
-# NOTE: When adding or removing a type which uses the FIXED_SIZE allocator,
-# also add or remove initialization of the type in erts_alloc_init()
-# (erl_alloc.c).
-#
# <TYPE> <ALLOCATOR> <CLASS> <DESCRIPTION>
type SBMBC SBMBC SYSTEM small_block_mbc
type PROC FIXED_SIZE PROCESSES proc
-type ATOM FIXED_SIZE ATOM atom_entry
-type MODULE FIXED_SIZE CODE module_entry
-type REG_PROC FIXED_SIZE PROCESSES reg_proc
+type ATOM LONG_LIVED ATOM atom_entry
+type MODULE LONG_LIVED CODE module_entry
+type REG_PROC STANDARD PROCESSES reg_proc
type LINK_LH STANDARD PROCESSES link_lh
type SUSPEND_MON STANDARD PROCESSES suspend_monitor
type PEND_SUSPEND SHORT_LIVED PROCESSES pending_suspend
type PROC_LIST SHORT_LIVED PROCESSES proc_list
-type FUN_ENTRY FIXED_SIZE CODE fun_entry
+type FUN_ENTRY LONG_LIVED CODE fun_entry
type ATOM_TXT LONG_LIVED ATOM atom_text
type BEAM_REGISTER EHEAP PROCESSES beam_register
type HEAP EHEAP PROCESSES heap
type OLD_HEAP EHEAP PROCESSES old_heap
type HEAP_FRAG EHEAP PROCESSES heap_frag
type TMP_HEAP TEMPORARY PROCESSES tmp_heap
-type MSG_REF SHORT_LIVED PROCESSES msg_ref
+type MSG_REF FIXED_SIZE PROCESSES msg_ref
type MSG_ROOTS TEMPORARY PROCESSES msg_roots
type ROOTSET TEMPORARY PROCESSES root_set
type LOADER_TMP TEMPORARY CODE loader_tmp
@@ -196,10 +201,10 @@ type LINEBUF STANDARD SYSTEM line_buf
type IOQ STANDARD SYSTEM io_queue
type BITS_BUF STANDARD SYSTEM bits_buf
type TMP_DIST_BUF TEMPORARY SYSTEM tmp_dist_buf
-type ASYNC_Q LONG_LIVED SYSTEM async_queue
+type ASYNC_DATA LONG_LIVED SYSTEM internal_async_data
type ESTACK TEMPORARY SYSTEM estack
type PORT_CALL_BUF TEMPORARY SYSTEM port_call_buf
-type DB_TABLE FIXED_SIZE ETS db_tab
+type DB_TABLE ETS ETS db_tab
type DB_FIXATION SHORT_LIVED ETS db_fixation
type DB_FIX_DEL SHORT_LIVED ETS fixed_del
type DB_TABLES LONG_LIVED ETS db_tabs
@@ -256,6 +261,23 @@ type TMP_CPU_IDS SHORT_LIVED SYSTEM tmp_cpu_ids
type EXT_TERM_DATA SHORT_LIVED PROCESSES external_term_data
type ZLIB STANDARD SYSTEM zlib
type CPU_GRPS_MAP LONG_LIVED SYSTEM cpu_groups_map
+type AUX_WORK_TMO LONG_LIVED SYSTEM aux_work_timeouts
+type MISC_AUX_WORK_Q LONG_LIVED SYSTEM misc_aux_work_q
+
++if threads_no_smp
+# Need thread safe allocs, but std_alloc and fix_alloc are not;
+# use driver_alloc which is...
+type THR_Q_EL DRIVER SYSTEM thr_q_element
+type THR_Q_EL_SL DRIVER SYSTEM sl_thr_q_element
+type MISC_AUX_WORK DRIVER SYSTEM misc_aux_work
++else
+type THR_Q_EL STANDARD SYSTEM thr_q_element
+type THR_Q_EL_SL FIXED_SIZE SYSTEM sl_thr_q_element
+type MISC_AUX_WORK SHORT_LIVED SYSTEM misc_aux_work
++endif
+type THR_Q STANDARD SYSTEM thr_queue
+type THR_Q_SL SHORT_LIVED SYSTEM short_lived_thr_queue
+type THR_Q_LL LONG_LIVED SYSTEM long_lived_thr_queue
+if smp
type ASYNC SHORT_LIVED SYSTEM async
@@ -271,8 +293,9 @@ type XPORTS_LIST SHORT_LIVED SYSTEM extra_port_list
type PROC_LCK_WTR LONG_LIVED SYSTEM proc_lock_waiter
type PROC_LCK_QS LONG_LIVED SYSTEM proc_lock_queues
type RUNQ_BLNS LONG_LIVED SYSTEM run_queue_balancing
-type MISC_AUX_WORK_Q LONG_LIVED SYSTEM misc_aux_work_q
-type MISC_AUX_WORK SHORT_LIVED SYSTEM misc_aux_work
+type THR_PRGR_IDATA LONG_LIVED SYSTEM thr_prgr_internal_data
+type THR_PRGR_DATA LONG_LIVED SYSTEM thr_prgr_data
+type T_THR_PRGR_DATA SHORT_LIVED SYSTEM temp_thr_prgr_data
+endif
#
@@ -285,12 +308,6 @@ type ETHR_STD STANDARD SYSTEM ethread_standard
type ETHR_SL SHORT_LIVED SYSTEM ethread_short_lived
type ETHR_LL LONG_LIVED SYSTEM ethread_long_lived
-+ifnot smp
-
-type ARCALLBACK LONG_LIVED SYSTEM async_ready_callback
-
-+endif
-
+endif
+if shared_heap
@@ -346,10 +363,10 @@ type DB_MS_PSDO_PROC LONG_LIVED_LOW ETS db_match_pseudo_proc
type SCHDLR_DATA LONG_LIVED_LOW SYSTEM scheduler_data
type LL_TEMP_TERM LONG_LIVED_LOW SYSTEM ll_temp_term
-# no FIXED_SIZE for low memory
-type EXPORT STANDARD_LOW CODE export_entry
+type EXPORT LONG_LIVED_LOW CODE export_entry
type MONITOR_SH STANDARD_LOW PROCESSES monitor_sh
type NLINK_SH STANDARD_LOW PROCESSES nlink_sh
+type AINFO_REQ STANDARD_LOW SYSTEM alloc_info_request
+else # "fullword"
@@ -362,9 +379,10 @@ type DB_MS_PSDO_PROC LONG_LIVED ETS db_match_pseudo_proc
type SCHDLR_DATA LONG_LIVED SYSTEM scheduler_data
type LL_TEMP_TERM LONG_LIVED SYSTEM ll_temp_term
-type EXPORT FIXED_SIZE CODE export_entry
+type EXPORT LONG_LIVED CODE export_entry
type MONITOR_SH FIXED_SIZE PROCESSES monitor_sh
type NLINK_SH FIXED_SIZE PROCESSES nlink_sh
+type AINFO_REQ SHORT_LIVED SYSTEM alloc_info_request
+endif
diff --git a/erts/emulator/beam/erl_alloc_util.c b/erts/emulator/beam/erl_alloc_util.c
index 19c552d8cd..af386c9197 100644
--- a/erts/emulator/beam/erl_alloc_util.c
+++ b/erts/emulator/beam/erl_alloc_util.c
@@ -46,6 +46,7 @@
#include "erl_alloc_util.h"
#include "erl_mseg.h"
#include "erl_threads.h"
+#include "erl_thr_progress.h"
#ifdef ERTS_ENABLE_LOCK_COUNT
#include "erl_lock_count.h"
@@ -61,6 +62,13 @@
#warning "* * * * * * * * * *"
#endif
+#define ERTS_ALCU_DD_OPS_LIM_HIGH 20
+#define ERTS_ALCU_DD_OPS_LIM_LOW 2
+
+/* Fix alloc limit */
+#define ERTS_ALCU_FIX_MAX_LIST_SZ 1000
+#define ERTS_ALC_FIX_MAX_SHRINK_OPS 30
+
#define ALLOC_ZERO_EQ_NULL 0
static int atoms_initialized = 0;
@@ -269,7 +277,6 @@ static void check_blk_carrier(Allctr_t *, Block_t *);
#define HARD_CHECK_BLK_CARRIER(A, B)
#endif
-
/* Statistics updating ... */
#ifdef DEBUG
@@ -465,26 +472,34 @@ do { \
#ifdef DEBUG
#ifdef USE_THREADS
-#define ERTS_ALCU_DBG_CHK_THR_SPEC(A) \
+#define ERTS_ALCU_DBG_CHK_THR_ACCESS(A) \
do { \
if (!(A)->thread_safe) { \
- if (!(A)->debug.saved_tid) \
+ if (!(A)->debug.saved_tid) { \
(A)->debug.tid = erts_thr_self(); \
+ (A)->debug.saved_tid = 1; \
+ } \
else { \
- ASSERT(ethr_equal_tids((A)->debug.tid, erts_thr_self())); \
+ ERTS_SMP_LC_ASSERT( \
+ ethr_equal_tids((A)->debug.tid, erts_thr_self()) \
+ || erts_thr_progress_is_blocking()); \
} \
} \
} while (0)
#else
-#define ERTS_ALCU_DBG_CHK_THR_SPEC(A)
+#define ERTS_ALCU_DBG_CHK_THR_ACCESS(A)
#endif
#else
-#define ERTS_ALCU_DBG_CHK_THR_SPEC(A)
+#define ERTS_ALCU_DBG_CHK_THR_ACCESS(A)
#endif
static void make_name_atoms(Allctr_t *allctr);
+static Block_t *create_carrier(Allctr_t *, Uint, UWord);
+static void destroy_carrier(Allctr_t *, Block_t *);
+static void mbc_free(Allctr_t *allctr, void *p);
+
/* mseg ... */
@@ -651,6 +666,446 @@ static void destroy_sbmbc(Allctr_t *allctr, Block_t *blk);
static Block_t *create_carrier(Allctr_t *, Uint, UWord);
static void destroy_carrier(Allctr_t *, Block_t *);
+#if 0
+#define ERTS_DBG_CHK_FIX_LIST(A, FIX, IX, B) \
+ do { if ((FIX)) chk_fix_list((A), (FIX), (IX), (B)); } while (0)
+static void
+chk_fix_list(Allctr_t *allctr, ErtsAlcFixList_t *fix, int ix, int before)
+{
+ void *p;
+ int n;
+ for (n = 0, p = fix[ix].list; p; p = *((void **) p))
+ n++;
+ if (n != fix[ix].list_size) {
+ erts_fprintf(stderr, "FOUND IT ts=%d, sched=%d, ix=%d, n=%d, ls=%d %s!\n",
+ allctr->thread_safe, allctr->ix, ix, n, fix[ix].list_size, before ? "before" : "after");
+ abort();
+ }
+}
+#else
+#define ERTS_DBG_CHK_FIX_LIST(A, FIX, IX, B)
+#endif
+
+erts_aint32_t
+erts_alcu_fix_alloc_shrink(Allctr_t *allctr, erts_aint32_t flgs)
+{
+ int all_empty = 1;
+ erts_aint32_t res = 0;
+ int ix, o;
+ ErtsAlcFixList_t *fix = allctr->fix;
+ int flush = flgs == 0;
+
+#ifdef USE_THREADS
+ if (allctr->thread_safe)
+ erts_mtx_lock(&allctr->mutex);
+#endif
+
+ for (ix = 0; ix < ERTS_ALC_NO_FIXED_SIZES; ix++) {
+ ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 1);
+ if (flgs & ERTS_SSI_AUX_WORK_FIX_ALLOC_LOWER_LIM) {
+ fix[ix].limit = fix[ix].max_used;
+ if (fix[ix].limit < fix[ix].used)
+ fix[ix].limit = fix[ix].used;
+ fix[ix].max_used = fix[ix].used;
+ ASSERT(fix[ix].limit >= 0);
+
+ }
+ if (flush) {
+ fix[ix].limit = 0;
+ fix[ix].max_used = fix[ix].used;
+ ASSERT(fix[ix].limit >= 0);
+ }
+ for (o = 0; o < ERTS_ALC_FIX_MAX_SHRINK_OPS || flush; o++) {
+ Block_t *blk;
+ void *ptr;
+
+ if (!flush && fix[ix].limit >= fix[ix].allocated)
+ break;
+ if (fix[ix].list_size == 0)
+ break;
+ ptr = fix[ix].list;
+ fix[ix].list = *((void **) ptr);
+ fix[ix].list_size--;
+
+ blk = UMEM2BLK(ptr);
+
+ if (IS_SBC_BLK(blk))
+ destroy_carrier(allctr, blk);
+ else
+ mbc_free(allctr, ptr);
+
+ fix[ix].allocated--;
+ }
+ if (fix[ix].list_size != 0) {
+ if (fix[ix].limit < fix[ix].allocated)
+ res |= ERTS_SSI_AUX_WORK_FIX_ALLOC_DEALLOC;
+ all_empty = 0;
+ }
+ ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 0);
+ }
+
+ if (all_empty && allctr->fix_shrink_scheduled) {
+ allctr->fix_shrink_scheduled = 0;
+ erts_set_aux_work_timeout(allctr->ix,
+ (ERTS_SSI_AUX_WORK_FIX_ALLOC_LOWER_LIM
+ | ERTS_SSI_AUX_WORK_FIX_ALLOC_DEALLOC),
+ 0);
+ }
+
+#ifdef USE_THREADS
+ if (allctr->thread_safe)
+ erts_mtx_unlock(&allctr->mutex);
+#endif
+
+ return res;
+}
+
+#ifdef ERTS_SMP
+
+#define ERTS_ALCU_DD_FIX_TYPE_OFFS \
+ ((sizeof(ErtsAllctrDDBlock_t)-1)/sizeof(UWord) + 1)
+
+#define ERTS_AU_PREF_ALLOC_IX_MASK \
+ ((((UWord) 1) << ERTS_AU_PREF_ALLOC_BITS) - 1)
+#define ERTS_AU_PREF_ALLOC_SIZE_MASK \
+ ((((UWord) 1) << (sizeof(UWord)*8 - ERTS_AU_PREF_ALLOC_BITS)) - 1)
+
+static ERTS_INLINE int
+get_pref_allctr(void *extra, Allctr_t **allctr)
+{
+ ErtsAllocatorThrSpec_t *tspec = (ErtsAllocatorThrSpec_t *) extra;
+ int pref_ix;
+
+ pref_ix = ERTS_ALC_GET_THR_IX();
+
+ ASSERT(sizeof(UWord) == sizeof(Allctr_t *));
+ ASSERT(0 <= pref_ix && pref_ix < tspec->size);
+
+ *allctr = tspec->allctr[pref_ix];
+ return pref_ix;
+}
+
+static ERTS_INLINE void *
+get_used_allctr(void *extra, void *p, Allctr_t **allctr, UWord *sizep)
+{
+ ErtsAllocatorThrSpec_t *tspec = (ErtsAllocatorThrSpec_t *) extra;
+ void *ptr = (void *) (((char *) p) - sizeof(UWord));
+ UWord ainfo = *((UWord *) ptr);
+ int aix = (int) (ainfo & ERTS_AU_PREF_ALLOC_IX_MASK);
+ *allctr = tspec->allctr[aix];
+ if (sizep)
+ *sizep = ((ainfo >> ERTS_AU_PREF_ALLOC_BITS)
+ & ERTS_AU_PREF_ALLOC_SIZE_MASK);
+ return ptr;
+}
+
+static ERTS_INLINE void *
+put_used_allctr(void *p, int ix, UWord size)
+{
+ UWord ainfo = (size >= ERTS_AU_PREF_ALLOC_SIZE_MASK
+ ? ERTS_AU_PREF_ALLOC_SIZE_MASK
+ : size);
+ ainfo <<= ERTS_AU_PREF_ALLOC_BITS;
+ ainfo |= (UWord) ix;
+ *((UWord *) p) = ainfo;
+ return (void *) (((char *) p) + sizeof(UWord));
+}
+
+static void
+init_dd_queue(ErtsAllctrDDQueue_t *ddq)
+{
+ erts_atomic_init_nob(&ddq->tail.data.marker.atmc_next, ERTS_AINT_NULL);
+ erts_atomic_init_nob(&ddq->tail.data.last,
+ (erts_aint_t) &ddq->tail.data.marker);
+ erts_atomic_init_nob(&ddq->tail.data.um_refc[0], 0);
+ erts_atomic_init_nob(&ddq->tail.data.um_refc[1], 0);
+ erts_atomic32_init_nob(&ddq->tail.data.um_refc_ix, 0);
+ ddq->head.first = &ddq->tail.data.marker;
+ ddq->head.unref_end = &ddq->tail.data.marker;
+ ddq->head.next.thr_progress = erts_thr_progress_current();
+ ddq->head.next.thr_progress_reached = 1;
+ ddq->head.next.um_refc_ix = 1;
+ ddq->head.next.unref_end = &ddq->tail.data.marker;
+ ddq->head.used_marker = 1;
+}
+
+static ERTS_INLINE erts_aint_t
+ddq_managed_thread_enqueue(ErtsAllctrDDQueue_t *ddq, void *ptr)
+{
+ erts_aint_t ilast, itmp;
+ ErtsAllctrDDBlock_t *this = ptr;
+
+ erts_atomic_init_nob(&this->atmc_next, ERTS_AINT_NULL);
+
+ /* Enqueue at end of list... */
+
+ ilast = erts_atomic_read_nob(&ddq->tail.data.last);
+ while (1) {
+ ErtsAllctrDDBlock_t *last = (ErtsAllctrDDBlock_t *) ilast;
+ itmp = erts_atomic_cmpxchg_mb(&last->atmc_next,
+ (erts_aint_t) this,
+ ERTS_AINT_NULL);
+ if (itmp == ERTS_AINT_NULL)
+ break;
+ ilast = itmp;
+ }
+
+ /* Move last pointer forward... */
+ while (1) {
+ if (erts_atomic_read_rb(&this->atmc_next) != ERTS_AINT_NULL) {
+ /* Someone else will move it forward */
+ return erts_atomic_read_rb(&ddq->tail.data.last);
+ }
+ itmp = erts_atomic_cmpxchg_mb(&ddq->tail.data.last,
+ (erts_aint_t) this,
+ ilast);
+ if (ilast == itmp)
+ return (erts_aint_t) this;
+ ilast = itmp;
+ }
+}
+
+static ERTS_INLINE int
+ddq_enqueue(ErtsAlcType_t type, ErtsAllctrDDQueue_t *ddq, void *ptr)
+{
+ erts_aint_t ilast;
+ int um_refc_ix = 0;
+ int managed_thread = erts_thr_progress_is_managed_thread();
+ if (!managed_thread) {
+ um_refc_ix = erts_atomic32_read_acqb(&ddq->tail.data.um_refc_ix);
+ while (1) {
+ int tmp_um_refc_ix;
+ erts_atomic_inc_acqb(&ddq->tail.data.um_refc[um_refc_ix]);
+ tmp_um_refc_ix = erts_atomic32_read_acqb(&ddq->tail.data.um_refc_ix);
+ if (tmp_um_refc_ix == um_refc_ix)
+ break;
+ erts_atomic_dec_relb(&ddq->tail.data.um_refc[um_refc_ix]);
+ um_refc_ix = tmp_um_refc_ix;
+ }
+ }
+
+ ilast = ddq_managed_thread_enqueue(ddq, ptr);
+
+ if (!managed_thread)
+ erts_atomic_dec_relb(&ddq->tail.data.um_refc[um_refc_ix]);
+ return ilast == (erts_aint_t) ptr;
+}
+
+static ERTS_INLINE void *
+ddq_dequeue(ErtsAllctrDDQueue_t *ddq)
+{
+ ErtsAllctrDDBlock_t *blk;
+
+ if (ddq->head.first == ddq->head.unref_end)
+ return NULL;
+
+ blk = ddq->head.first;
+ if (blk == &ddq->tail.data.marker) {
+ ASSERT(ddq->head.used_marker);
+ ddq->head.used_marker = 0;
+ blk = ((ErtsAllctrDDBlock_t *)
+ erts_atomic_read_nob(&blk->atmc_next));
+ if (blk == ddq->head.unref_end) {
+ ddq->head.first = blk;
+ return NULL;
+ }
+ }
+
+ ddq->head.first = ((ErtsAllctrDDBlock_t *)
+ erts_atomic_read_nob(&blk->atmc_next));
+
+ ASSERT(ddq->head.first);
+
+ return (void *) blk;
+}
+
+static int
+ddq_check_incoming(ErtsAllctrDDQueue_t *ddq)
+{
+ erts_aint_t ilast = erts_atomic_read_nob(&ddq->tail.data.last);
+ if (((ErtsAllctrDDBlock_t *) ilast) == &ddq->tail.data.marker
+ && ddq->head.first == &ddq->tail.data.marker) {
+ /* Nothing more to do... */
+ return 0;
+ }
+
+ if (ddq->head.next.thr_progress_reached
+ || erts_thr_progress_has_reached(ddq->head.next.thr_progress)) {
+ int um_refc_ix;
+ ddq->head.next.thr_progress_reached = 1;
+ um_refc_ix = ddq->head.next.um_refc_ix;
+ if (erts_atomic_read_acqb(&ddq->tail.data.um_refc[um_refc_ix]) == 0) {
+ /* Move unreferenced end pointer forward... */
+
+ ddq->head.unref_end = ddq->head.next.unref_end;
+
+ if (!ddq->head.used_marker
+ && ddq->head.unref_end == (ErtsAllctrDDBlock_t *) ilast) {
+ ddq->head.used_marker = 1;
+ ilast = ddq_managed_thread_enqueue(ddq, &ddq->tail.data.marker);
+ }
+
+ if (ddq->head.unref_end == (ErtsAllctrDDBlock_t *) ilast)
+ ERTS_THR_MEMORY_BARRIER;
+ else {
+ ddq->head.next.unref_end = (ErtsAllctrDDBlock_t *) ilast;
+ ERTS_THR_MEMORY_BARRIER;
+ ddq->head.next.thr_progress = erts_thr_progress_later();
+ erts_atomic32_set_relb(&ddq->tail.data.um_refc_ix,
+ um_refc_ix);
+ ddq->head.next.um_refc_ix = um_refc_ix == 0 ? 1 : 0;
+ ddq->head.next.thr_progress_reached = 0;
+ }
+ }
+ }
+ return 1;
+}
+
+static ERTS_INLINE int
+handle_delayed_dealloc(Allctr_t *allctr,
+ int allctr_locked,
+ int use_limit,
+ int ops_limit,
+ int *need_thr_progress,
+ int *need_more_work)
+{
+ int need_thr_prgr = 0;
+ int need_mr_wrk = 0;
+ int have_checked_incoming = 0;
+ int ops = 0;
+ ErtsAlcFixList_t *fix;
+ int res;
+ ErtsAllctrDDQueue_t *ddq;
+
+ if (allctr->thread_safe && !allctr_locked)
+ erts_mtx_lock(&allctr->mutex);
+
+ ERTS_ALCU_DBG_CHK_THR_ACCESS(allctr);
+
+ fix = allctr->fix;
+
+ ddq = &allctr->dd.q;
+
+ res = 0;
+
+ while (1) {
+ Block_t *blk;
+ void *ptr;
+ int ix;
+
+ if (use_limit && ++ops > ops_limit) {
+ if (ddq->head.first != ddq->head.unref_end) {
+ need_mr_wrk = 1;
+ if (need_more_work)
+ *need_more_work |= 1;
+ }
+ break;
+ }
+
+ dequeue:
+ ptr = ddq_dequeue(ddq);
+ if (!ptr) {
+ if (have_checked_incoming)
+ break;
+ need_thr_prgr = ddq_check_incoming(ddq);
+ if (need_thr_progress)
+ *need_thr_progress |= need_thr_prgr;
+ have_checked_incoming = 1;
+ goto dequeue;
+ }
+
+ res = 1;
+
+ INC_CC(allctr->calls.this_free);
+
+ if (fix) {
+ ErtsAlcType_t type;
+
+ type = (ErtsAlcType_t) ((UWord *) ptr)[ERTS_ALCU_DD_FIX_TYPE_OFFS];
+ ix = type - ERTS_ALC_N_MIN_A_FIXED_SIZE;
+ ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 1);
+ fix[ix].used--;
+ if (fix[ix].allocated < fix[ix].limit
+ && fix[ix].list_size < ERTS_ALCU_FIX_MAX_LIST_SZ) {
+ *((void **) ptr) = fix[ix].list;
+ fix[ix].list = ptr;
+ fix[ix].list_size++;
+ if (!allctr->fix_shrink_scheduled) {
+ allctr->fix_shrink_scheduled = 1;
+ erts_set_aux_work_timeout(
+ allctr->ix,
+ (ERTS_SSI_AUX_WORK_FIX_ALLOC_LOWER_LIM
+ | ERTS_SSI_AUX_WORK_FIX_ALLOC_DEALLOC),
+ 1);
+ }
+ ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 0);
+ continue;
+ }
+ fix[ix].allocated--;
+ if (fix[ix].list && fix[ix].allocated > fix[ix].limit) {
+ blk = UMEM2BLK(ptr);
+ if (IS_SBC_BLK(blk))
+ destroy_carrier(allctr, blk);
+ else
+ mbc_free(allctr, ptr);
+ ptr = fix[ix].list;
+ fix[ix].list = *((void **) ptr);
+ fix[ix].list_size--;
+ fix[ix].allocated--;
+ }
+ }
+
+ blk = UMEM2BLK(ptr);
+
+ if (IS_SBC_BLK(blk))
+ destroy_carrier(allctr, blk);
+ else
+ mbc_free(allctr, ptr);
+ ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 0);
+ }
+
+ if (need_thr_progress && !(need_thr_prgr | need_mr_wrk)) {
+ need_thr_prgr = ddq_check_incoming(ddq);
+ *need_thr_progress |= need_thr_prgr;
+ }
+
+ if (allctr->thread_safe && !allctr_locked)
+ erts_mtx_unlock(&allctr->mutex);
+ return res;
+}
+
+static ERTS_INLINE void
+enqueue_dealloc_other_instance(ErtsAlcType_t type, Allctr_t *allctr, void *ptr)
+{
+ if (allctr->fix)
+ ((UWord *) ptr)[ERTS_ALCU_DD_FIX_TYPE_OFFS] = (UWord) type;
+
+ if (ddq_enqueue(type, &allctr->dd.q, ptr))
+ erts_alloc_notify_delayed_dealloc(allctr->ix);
+}
+
+#endif
+
+void
+erts_alcu_check_delayed_dealloc(Allctr_t *allctr,
+ int limit,
+ int *need_thr_progress,
+ int *more_work)
+{
+#ifdef ERTS_SMP
+ handle_delayed_dealloc(allctr,
+ 0,
+ limit,
+ ERTS_ALCU_DD_OPS_LIM_HIGH,
+ need_thr_progress,
+ more_work);
+#endif
+}
+
+#define ERTS_ALCU_HANDLE_DD_IN_OP(Allctr, Locked) \
+ handle_delayed_dealloc((Allctr), (Locked), 1, \
+ ERTS_ALCU_DD_OPS_LIM_LOW, NULL, NULL)
+
/* Multi block carrier alloc/realloc/free ... */
/* NOTE! mbc_alloc() may in case of memory shortage place the requested
@@ -680,8 +1135,21 @@ mbc_alloc_block(Allctr_t *allctr, Uint size, Uint *blk_szp, Uint32 *alcu_flgsp)
}
}
+#ifdef ERTS_SMP
+ if (allctr->dd.use)
+ ERTS_ALCU_HANDLE_DD_IN_OP(allctr, 1);
+#endif
+
blk = (*allctr->get_free_block)(allctr, get_blk_sz, NULL, 0, *alcu_flgsp);
+#ifdef ERTS_SMP
+ if (!blk && allctr->dd.use) {
+ if (ERTS_ALCU_HANDLE_DD_IN_OP(allctr, 1))
+ blk = (*allctr->get_free_block)(allctr, get_blk_sz, NULL, 0,
+ *alcu_flgsp);
+ }
+#endif
+
if (!blk) {
if ((*alcu_flgsp) & ERTS_ALCU_FLG_SBMBC)
blk = create_sbmbc(allctr, get_blk_sz);
@@ -939,6 +1407,11 @@ mbc_realloc(Allctr_t *allctr, void *p, Uint size, Uint32 alcu_flgs)
Uint is_last_blk;
#endif /* #ifndef MBC_REALLOC_ALWAYS_MOVES */
+#ifdef ERTS_SMP
+ if (allctr->dd.use)
+ ERTS_ALCU_HANDLE_DD_IN_OP(allctr, 1);
+#endif
+
ASSERT(p);
ASSERT(size);
ASSERT(size < allctr->sbc_threshold);
@@ -1005,7 +1478,6 @@ mbc_realloc(Allctr_t *allctr, void *p, Uint size, Uint32 alcu_flgs)
cand_blk,
cand_blk_sz,
alcu_flgs);
-
if (new_blk || cand_blk != blk)
goto move_into_new_blk;
}
@@ -1441,7 +1913,7 @@ create_carrier(Allctr_t *allctr, Uint umem_sz, UWord flags)
goto try_sys_alloc;
if (flags & CFLG_FORCE_MSEG)
goto try_mseg;
- if (erts_mseg_no() >= max_mseg_carriers)
+ if (erts_mseg_no(&allctr->mseg_opt) >= max_mseg_carriers)
goto try_sys_alloc;
if (flags & CFLG_SBC) {
if (allctr->sbcs.curr.norm.mseg.no >= allctr->max_mseg_sbcs)
@@ -1840,8 +2312,12 @@ static struct {
Eterm ycs;
/* Eterm sbmbcs; */
+
+ Eterm fix_types;
+
Eterm mbcs;
Eterm sbcs;
+
Eterm sys_alloc_carriers_size;
#if HAVE_ERTS_MSEG
Eterm mseg_alloc_carriers_size;
@@ -1871,6 +2347,8 @@ static struct {
#endif
} am;
+static Eterm fix_type_atoms[ERTS_ALC_NO_FIXED_SIZES];
+
static ERTS_INLINE void atom_init(Eterm *atom, char *name)
{
*atom = am_atom_put(name, strlen(name));
@@ -1891,6 +2369,7 @@ init_atoms(Allctr_t *allctr)
erts_mtx_lock(&init_atoms_mtx);
if (!atoms_initialized) {
+ int ix;
#ifdef DEBUG
Eterm *atom;
@@ -1933,8 +2412,12 @@ init_atoms(Allctr_t *allctr)
AM_INIT(ycs);
/*AM_INIT(sbmbcs);*/
+
+ AM_INIT(fix_types);
+
AM_INIT(mbcs);
AM_INIT(sbcs);
+
AM_INIT(sys_alloc_carriers_size);
#if HAVE_ERTS_MSEG
AM_INIT(mseg_alloc_carriers_size);
@@ -1965,6 +2448,13 @@ init_atoms(Allctr_t *allctr)
ASSERT(*atom != THE_NON_VALUE);
}
#endif
+
+ for (ix = 0; ix < ERTS_ALC_NO_FIXED_SIZES; ix++) {
+ ErtsAlcType_t n = ERTS_ALC_N_MIN_A_FIXED_SIZE + ix;
+ char *name = (char *) ERTS_ALC_N2TD(n);
+ size_t len = strlen(name);
+ fix_type_atoms[ix] = am_atom_put(name, len);
+ }
}
@@ -2043,6 +2533,48 @@ add_4tup(Uint **hpp, Uint *szp, Eterm *lp,
}
static Eterm
+sz_info_fix(Allctr_t *allctr,
+ int *print_to_p,
+ void *print_to_arg,
+ Uint **hpp,
+ Uint *szp)
+{
+ Eterm res;
+ int ix;
+ ErtsAlcFixList_t *fix = allctr->fix;
+
+ ASSERT(fix);
+
+ res = NIL;
+
+ for (ix = ERTS_ALC_NO_FIXED_SIZES-1; ix >= 0; ix--) {
+ ErtsAlcType_t n = ix + ERTS_ALC_N_MIN_A_FIXED_SIZE;
+ Uint alloced = (fix[ix].type_size * fix[ix].allocated);
+ Uint used = fix[ix].type_size*fix[ix].used;
+
+ if (print_to_p) {
+ int to = *print_to_p;
+ void *arg = print_to_arg;
+ erts_print(to,
+ arg,
+ "fix type: %s %bpu %bpu\n",
+ (char *) ERTS_ALC_N2TD(n),
+ alloced,
+ used);
+ }
+
+ if (hpp || szp) {
+ add_3tup(hpp, szp, &res,
+ fix_type_atoms[ix],
+ bld_unstable_uint(hpp, szp, alloced),
+ bld_unstable_uint(hpp, szp, used));
+ }
+ }
+
+ return res;
+}
+
+static Eterm
sz_info_carriers(Allctr_t *allctr,
CarriersStats_t *cs,
char *prefix,
@@ -2590,7 +3122,7 @@ erts_alcu_sz_info(Allctr_t *allctr,
Uint **hpp,
Uint *szp)
{
- Eterm res, sbmbcs, mbcs, sbcs;
+ Eterm res, sbmbcs, mbcs, sbcs, fix = THE_NON_VALUE;
res = THE_NON_VALUE;
@@ -2607,6 +3139,8 @@ erts_alcu_sz_info(Allctr_t *allctr,
erts_mtx_lock(&allctr->mutex);
#endif
+ ERTS_ALCU_DBG_CHK_THR_ACCESS(allctr);
+
if (hpp || szp)
ensure_atoms_initialized(allctr);
@@ -2619,6 +3153,8 @@ erts_alcu_sz_info(Allctr_t *allctr,
update_max_ever_values(&allctr->mbcs);
update_max_ever_values(&allctr->sbcs);
+ if (allctr->fix)
+ fix = sz_info_fix(allctr, print_to_p, print_to_arg, hpp, szp);
sbmbcs = sz_info_carriers(allctr, &allctr->sbmbcs, "sbmbcs ", print_to_p,
print_to_arg, hpp, szp);
mbcs = sz_info_carriers(allctr, &allctr->mbcs, "mbcs ", print_to_p,
@@ -2631,6 +3167,8 @@ erts_alcu_sz_info(Allctr_t *allctr,
add_2tup(hpp, szp, &res, am.sbcs, sbcs);
add_2tup(hpp, szp, &res, am.mbcs, mbcs);
add_2tup(hpp, szp, &res, am.sbmbcs, sbmbcs);
+ if (allctr->fix)
+ add_2tup(hpp, szp, &res, am.fix_types, fix);
}
if (begin_max_period) {
@@ -2656,7 +3194,7 @@ erts_alcu_info(Allctr_t *allctr,
Uint **hpp,
Uint *szp)
{
- Eterm res, sett, sbmbcs, mbcs, sbcs, calls;
+ Eterm res, sett, sbmbcs, mbcs, sbcs, calls, fix = THE_NON_VALUE;
res = THE_NON_VALUE;
@@ -2673,6 +3211,8 @@ erts_alcu_info(Allctr_t *allctr,
erts_mtx_lock(&allctr->mutex);
#endif
+ ERTS_ALCU_DBG_CHK_THR_ACCESS(allctr);
+
if (hpp || szp)
ensure_atoms_initialized(allctr);
@@ -2694,6 +3234,8 @@ erts_alcu_info(Allctr_t *allctr,
}
sett = info_options(allctr, print_to_p, print_to_arg, hpp, szp);
+ if (allctr->fix)
+ fix = sz_info_fix(allctr, print_to_p, print_to_arg, hpp, szp);
sbmbcs = info_carriers(allctr, &allctr->sbmbcs, "sbmbcs ", print_to_p,
print_to_arg, hpp, szp);
mbcs = info_carriers(allctr, &allctr->mbcs, "mbcs ", print_to_p,
@@ -2709,6 +3251,8 @@ erts_alcu_info(Allctr_t *allctr,
add_2tup(hpp, szp, &res, am.sbcs, sbcs);
add_2tup(hpp, szp, &res, am.mbcs, mbcs);
add_2tup(hpp, szp, &res, am.sbmbcs, sbmbcs);
+ if (allctr->fix)
+ add_2tup(hpp, szp, &res, am.fix_types, fix);
add_2tup(hpp, szp, &res, am.options, sett);
add_3tup(hpp, szp, &res,
am.versions,
@@ -2733,7 +3277,7 @@ erts_alcu_info(Allctr_t *allctr,
void
-erts_alcu_current_size(Allctr_t *allctr, AllctrSize_t *size)
+erts_alcu_current_size(Allctr_t *allctr, AllctrSize_t *size, ErtsAlcUFixInfo_t *fi, int fisz)
{
#ifdef USE_THREADS
@@ -2751,6 +3295,18 @@ erts_alcu_current_size(Allctr_t *allctr, AllctrSize_t *size)
size->blocks += allctr->sbmbcs.blocks.curr.size;
size->blocks += allctr->sbcs.blocks.curr.size;
+ if (fi) {
+ int ix;
+ for (ix = 0; ix < fisz; ix++) {
+ if (allctr->fix) {
+ fi[ix].allocated += (allctr->fix[ix].type_size
+ * allctr->fix[ix].allocated);
+ fi[ix].used += (allctr->fix[ix].type_size
+ * allctr->fix[ix].used);
+ }
+ }
+ }
+
#ifdef USE_THREADS
if (allctr->thread_safe)
erts_mtx_unlock(&allctr->mutex);
@@ -2764,12 +3320,16 @@ do_erts_alcu_alloc(ErtsAlcType_t type, void *extra, Uint size)
{
Allctr_t *allctr = (Allctr_t *) extra;
void *res;
+ ErtsAlcFixList_t *fix;
ASSERT(initialized);
ASSERT(allctr);
- ERTS_ALCU_DBG_CHK_THR_SPEC(allctr);
+ ERTS_SMP_LC_ASSERT(!allctr->thread_safe
+ || erts_lc_mtx_is_locked(&allctr->mutex));
+
+ ERTS_ALCU_DBG_CHK_THR_ACCESS(allctr);
#if ALLOC_ZERO_EQ_NULL
if (!size)
@@ -2778,18 +3338,61 @@ do_erts_alcu_alloc(ErtsAlcType_t type, void *extra, Uint size)
INC_CC(allctr->calls.this_alloc);
+ fix = allctr->fix;
+ if (fix) {
+ int ix = type - ERTS_ALC_N_MIN_A_FIXED_SIZE;
+ ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 1);
+ fix[ix].used++;
+ res = fix[ix].list;
+ if (res) {
+ fix[ix].list_size--;
+ fix[ix].list = *((void **) res);
+ if (fix[ix].list && fix[ix].allocated > fix[ix].limit) {
+ void *p = fix[ix].list;
+ Block_t *blk;
+ fix[ix].list = *((void **) p);
+ fix[ix].list_size--;
+ blk = UMEM2BLK(p);
+ if (IS_SBC_BLK(blk))
+ destroy_carrier(allctr, blk);
+ else
+ mbc_free(allctr, p);
+ fix[ix].allocated--;
+ }
+ ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 0);
+ return res;
+ }
+ if (size < 2*sizeof(UWord))
+ size += sizeof(UWord);
+ if (fix[ix].limit < fix[ix].used)
+ fix[ix].limit = fix[ix].used;
+ if (fix[ix].max_used < fix[ix].used)
+ fix[ix].max_used = fix[ix].used;
+ fix[ix].allocated++;
+ }
+
if (size >= allctr->sbc_threshold) {
+ Block_t *blk;
+#ifdef ERTS_SMP
+ if (allctr->dd.use)
+ ERTS_ALCU_HANDLE_DD_IN_OP(allctr, 1);
+#endif
#if HALFWORD_HEAP
- Block_t *blk = create_carrier(allctr, size,
- CFLG_SBC | CFLG_FORCE_MSEG);
+ blk = create_carrier(allctr, size,
+ CFLG_SBC | CFLG_FORCE_MSEG);
#else
- Block_t *blk = create_carrier(allctr, size, CFLG_SBC);
+ blk = create_carrier(allctr, size, CFLG_SBC);
#endif
res = blk ? BLK2UMEM(blk) : NULL;
}
else
res = mbc_alloc(allctr, size);
+ if (!res && fix) {
+ int ix = type - ERTS_ALC_N_MIN_A_FIXED_SIZE;
+ fix[ix].allocated--;
+ fix[ix].used--;
+ }
return res;
}
@@ -2818,29 +3421,28 @@ erts_alcu_alloc_ts(ErtsAlcType_t type, void *extra, Uint size)
return res;
}
+#ifdef ERTS_SMP
+
void *
erts_alcu_alloc_thr_spec(ErtsAlcType_t type, void *extra, Uint size)
{
ErtsAllocatorThrSpec_t *tspec = (ErtsAllocatorThrSpec_t *) extra;
- int ix = erts_alc_get_thr_ix();
+ int ix;
Allctr_t *allctr;
- int unlock;
void *res;
- ASSERT(ix > 0);
- if (ix < tspec->size) {
- allctr = tspec->allctr[ix];
- unlock = 0;
- }
- else {
- allctr = tspec->allctr[0];
- unlock = 1;
+ ix = ERTS_ALC_GET_THR_IX();
+
+ ASSERT(0 <= ix && ix < tspec->size);
+
+ allctr = tspec->allctr[ix];
+
+ if (allctr->thread_safe)
erts_mtx_lock(&allctr->mutex);
- }
res = do_erts_alcu_alloc(type, allctr, size);
- if (unlock)
+ if (allctr->thread_safe)
erts_mtx_unlock(&allctr->mutex);
DEBUG_CHECK_ALIGNMENT(res);
@@ -2851,51 +3453,96 @@ erts_alcu_alloc_thr_spec(ErtsAlcType_t type, void *extra, Uint size)
void *
erts_alcu_alloc_thr_pref(ErtsAlcType_t type, void *extra, Uint size)
{
- ErtsAllocatorThrSpec_t *tspec = (ErtsAllocatorThrSpec_t *) extra;
- int ix = erts_alc_get_thr_ix();
- Allctr_t *allctr;
+ int pref_ix;
+ Allctr_t *pref_allctr;
void *res;
- ASSERT(sizeof(UWord) == sizeof(Allctr_t *));
- ASSERT(ix > 0);
- if (ix >= tspec->size)
- ix = (ix % (tspec->size - 1)) + 1;
- allctr = tspec->allctr[ix];
- erts_mtx_lock(&allctr->mutex);
- res = do_erts_alcu_alloc(type, allctr, size + sizeof(UWord));
- if (res) {
- *((Allctr_t **) res) = allctr;
- res = (void *) (((char *) res) + sizeof(UWord));
- }
- erts_mtx_unlock(&allctr->mutex);
+ pref_ix = get_pref_allctr(extra, &pref_allctr);
+
+ if (pref_allctr->thread_safe)
+ erts_mtx_lock(&pref_allctr->mutex);
+
+ ERTS_ALCU_DBG_CHK_THR_ACCESS(pref_allctr);
+
+ res = do_erts_alcu_alloc(type, pref_allctr, size + sizeof(UWord));
+ if (pref_allctr->thread_safe)
+ erts_mtx_unlock(&pref_allctr->mutex);
+
+ if (res)
+ res = put_used_allctr(res, pref_ix, size);
+
DEBUG_CHECK_ALIGNMENT(res);
+
+
return res;
}
#endif
+#endif
+
/* ------------------------------------------------------------------------- */
static ERTS_INLINE void
do_erts_alcu_free(ErtsAlcType_t type, void *extra, void *p)
{
+ int ix;
Allctr_t *allctr = (Allctr_t *) extra;
ASSERT(initialized);
ASSERT(allctr);
- ERTS_ALCU_DBG_CHK_THR_SPEC(allctr);
+ ERTS_SMP_LC_ASSERT(!allctr->thread_safe
+ || erts_lc_mtx_is_locked(&allctr->mutex));
+
+ ERTS_ALCU_DBG_CHK_THR_ACCESS(allctr);
if (p) {
+ ErtsAlcFixList_t *fix = allctr->fix;
Block_t *blk;
INC_CC(allctr->calls.this_free);
+ if (fix) {
+ ix = type - ERTS_ALC_N_MIN_A_FIXED_SIZE;
+ ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 1);
+ fix[ix].used--;
+ if (fix[ix].allocated < fix[ix].limit
+ && fix[ix].list_size < ERTS_ALCU_FIX_MAX_LIST_SZ) {
+ *((void **) p) = fix[ix].list;
+ fix[ix].list = p;
+ fix[ix].list_size++;
+ if (!allctr->fix_shrink_scheduled) {
+ allctr->fix_shrink_scheduled = 1;
+ erts_set_aux_work_timeout(
+ allctr->ix,
+ (ERTS_SSI_AUX_WORK_FIX_ALLOC_LOWER_LIM
+ | ERTS_SSI_AUX_WORK_FIX_ALLOC_DEALLOC),
+ 1);
+ }
+ ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 0);
+ return;
+ }
+ fix[ix].allocated--;
+ if (fix[ix].list && fix[ix].allocated > fix[ix].limit) {
+ blk = UMEM2BLK(p);
+ if (IS_SBC_BLK(blk))
+ destroy_carrier(allctr, blk);
+ else
+ mbc_free(allctr, p);
+ p = fix[ix].list;
+ fix[ix].list = *((void **) p);
+ fix[ix].list_size--;
+ fix[ix].allocated--;
+ }
+ }
+
blk = UMEM2BLK(p);
if (IS_SBC_BLK(blk))
destroy_carrier(allctr, blk);
else
mbc_free(allctr, p);
+ ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 0);
}
}
@@ -2915,44 +3562,56 @@ erts_alcu_free_ts(ErtsAlcType_t type, void *extra, void *p)
erts_mtx_unlock(&allctr->mutex);
}
+#ifdef ERTS_SMP
+
void
erts_alcu_free_thr_spec(ErtsAlcType_t type, void *extra, void *p)
{
ErtsAllocatorThrSpec_t *tspec = (ErtsAllocatorThrSpec_t *) extra;
- int ix = erts_alc_get_thr_ix();
- int unlock;
+ int ix;
Allctr_t *allctr;
- ASSERT(ix > 0);
- if (ix < tspec->size) {
- allctr = tspec->allctr[ix];
- unlock = 0;
- }
- else {
- allctr = tspec->allctr[0];
- unlock = 1;
+ ix = ERTS_ALC_GET_THR_IX();
+
+ ASSERT(0 <= ix && ix < tspec->size);
+
+ allctr = tspec->allctr[ix];
+
+ if (allctr->thread_safe)
erts_mtx_lock(&allctr->mutex);
- }
do_erts_alcu_free(type, allctr, p);
- if (unlock)
+
+ if (allctr->thread_safe)
erts_mtx_unlock(&allctr->mutex);
}
void
-erts_alcu_free_thr_pref(ErtsAlcType_t type, void *unused, void *p)
+erts_alcu_free_thr_pref(ErtsAlcType_t type, void *extra, void *p)
{
if (p) {
- void *ptr = (void *) (((char *) p) - sizeof(UWord));
- Allctr_t *allctr = *((Allctr_t **) ptr);
- erts_mtx_lock(&allctr->mutex);
- do_erts_alcu_free(type, allctr, ptr);
- erts_mtx_unlock(&allctr->mutex);
+ Allctr_t *pref_allctr, *used_allctr;
+ void *ptr;
+
+ get_pref_allctr(extra, &pref_allctr);
+ ptr = get_used_allctr(extra, p, &used_allctr, NULL);
+ if (pref_allctr != used_allctr)
+ enqueue_dealloc_other_instance(type, used_allctr, ptr);
+ else {
+ if (used_allctr->thread_safe)
+ erts_mtx_lock(&used_allctr->mutex);
+ ERTS_ALCU_DBG_CHK_THR_ACCESS(used_allctr);
+ do_erts_alcu_free(type, used_allctr, ptr);
+ if (used_allctr->thread_safe)
+ erts_mtx_unlock(&used_allctr->mutex);
+ }
}
}
#endif
+#endif
+
/* ------------------------------------------------------------------------- */
static ERTS_INLINE void *
@@ -2970,7 +3629,10 @@ do_erts_alcu_realloc(ErtsAlcType_t type,
ASSERT(allctr);
- ERTS_ALCU_DBG_CHK_THR_SPEC(allctr);
+ ERTS_SMP_LC_ASSERT(!allctr->thread_safe
+ || erts_lc_mtx_is_locked(&allctr->mutex));
+
+ ERTS_ALCU_DBG_CHK_THR_ACCESS(allctr);
if (!p) {
res = do_erts_alcu_alloc(type, extra, size);
@@ -3063,6 +3725,10 @@ do_erts_alcu_realloc(ErtsAlcType_t type,
}
else {
Block_t *new_blk;
+#ifdef ERTS_SMP
+ if (allctr->dd.use)
+ ERTS_ALCU_HANDLE_DD_IN_OP(allctr, 1);
+#endif
if(IS_SBC_BLK(blk)) {
do_carrier_resize:
#if HALFWORD_HEAP
@@ -3166,30 +3832,29 @@ erts_alcu_realloc_mv_ts(ErtsAlcType_t type, void *extra, void *p, Uint size)
return res;
}
+#ifdef ERTS_SMP
+
void *
erts_alcu_realloc_thr_spec(ErtsAlcType_t type, void *extra,
void *ptr, Uint size)
{
ErtsAllocatorThrSpec_t *tspec = (ErtsAllocatorThrSpec_t *) extra;
- int ix = erts_alc_get_thr_ix();
+ int ix;
Allctr_t *allctr;
- int unlock;
void *res;
- ASSERT(ix > 0);
- if (ix < tspec->size) {
- allctr = tspec->allctr[ix];
- unlock = 0;
- }
- else {
- allctr = tspec->allctr[0];
- unlock = 1;
+ ix = ERTS_ALC_GET_THR_IX();
+
+ ASSERT(0 <= ix && ix < tspec->size);
+
+ allctr = tspec->allctr[ix];
+
+ if (allctr->thread_safe)
erts_mtx_lock(&allctr->mutex);
- }
res = do_erts_alcu_realloc(type, allctr, ptr, size, 0);
- if (unlock)
+ if (allctr->thread_safe)
erts_mtx_unlock(&allctr->mutex);
DEBUG_CHECK_ALIGNMENT(res);
@@ -3202,26 +3867,22 @@ erts_alcu_realloc_mv_thr_spec(ErtsAlcType_t type, void *extra,
void *ptr, Uint size)
{
ErtsAllocatorThrSpec_t *tspec = (ErtsAllocatorThrSpec_t *) extra;
- int ix = erts_alc_get_thr_ix();
+ int ix;
Allctr_t *allctr;
- int unlock;
void *res;
- ASSERT(ix > 0);
- if (ix < tspec->size) {
- allctr = tspec->allctr[ix];
- unlock = 0;
- }
- else {
- allctr = tspec->allctr[0];
- unlock = 1;
- erts_mtx_lock(&allctr->mutex);
- }
+ ix = ERTS_ALC_GET_THR_IX();
+
+ ASSERT(0 <= ix && ix < tspec->size);
+ allctr = tspec->allctr[ix];
+
+ if (allctr->thread_safe)
+ erts_mtx_lock(&allctr->mutex);
res = do_erts_alcu_alloc(type, allctr, size);
if (!res) {
- if (unlock)
+ if (allctr->thread_safe)
erts_mtx_unlock(&allctr->mutex);
res = erts_alcu_realloc_thr_spec(type, allctr, ptr, size);
}
@@ -3235,7 +3896,7 @@ erts_alcu_realloc_mv_thr_spec(ErtsAlcType_t type, void *extra,
cpy_size = size;
sys_memcpy(res, ptr, cpy_size);
do_erts_alcu_free(type, allctr, ptr);
- if (unlock)
+ if (allctr->thread_safe)
erts_mtx_unlock(&allctr->mutex);
}
@@ -3244,129 +3905,101 @@ erts_alcu_realloc_mv_thr_spec(ErtsAlcType_t type, void *extra,
return res;
}
-void *
-erts_alcu_realloc_thr_pref(ErtsAlcType_t type, void *extra, void *p, Uint size)
+static ERTS_INLINE void *
+realloc_thr_pref(ErtsAlcType_t type, void *extra, void *p, Uint size,
+ int force_move)
{
- ErtsAllocatorThrSpec_t *tspec = (ErtsAllocatorThrSpec_t *) extra;
- int ix;
+ int pref_ix;
void *ptr, *res;
Allctr_t *pref_allctr, *used_allctr;
+ UWord old_user_size;
if (!p)
return erts_alcu_alloc_thr_pref(type, extra, size);
- ptr = (void *) (((char *) p) - sizeof(UWord));
- used_allctr = *((Allctr_t **) ptr);
+ pref_ix = get_pref_allctr(extra, &pref_allctr);
+ ptr = get_used_allctr(extra, p, &used_allctr, &old_user_size);
- ix = erts_alc_get_thr_ix();
- ASSERT(ix > 0);
- if (ix >= tspec->size)
- ix = (ix % (tspec->size - 1)) + 1;
- pref_allctr = tspec->allctr[ix];
ASSERT(used_allctr && pref_allctr);
- erts_mtx_lock(&used_allctr->mutex);
- res = do_erts_alcu_realloc(type,
- used_allctr,
- ptr,
- size + sizeof(UWord),
- (pref_allctr != used_allctr
- ? ERTS_ALCU_FLG_FAIL_REALLOC_MOVE
- : 0));
- erts_mtx_unlock(&used_allctr->mutex);
- if (res) {
- ASSERT(used_allctr == *((Allctr_t **) res));
- res = (void *) (((char *) res) + sizeof(UWord));
- DEBUG_CHECK_ALIGNMENT(res);
+ if (!force_move && used_allctr == pref_allctr) {
+ if (used_allctr->thread_safe)
+ erts_mtx_lock(&used_allctr->mutex);
+ ERTS_ALCU_DBG_CHK_THR_ACCESS(used_allctr);
+ res = do_erts_alcu_realloc(type,
+ used_allctr,
+ ptr,
+ size + sizeof(UWord),
+ 0);
+ if (used_allctr->thread_safe)
+ erts_mtx_unlock(&used_allctr->mutex);
+ if (res)
+ res = put_used_allctr(res, pref_ix, size);
}
else {
- erts_mtx_lock(&pref_allctr->mutex);
+ if (pref_allctr->thread_safe)
+ erts_mtx_lock(&pref_allctr->mutex);
res = do_erts_alcu_alloc(type, pref_allctr, size + sizeof(UWord));
- erts_mtx_unlock(&pref_allctr->mutex);
+ if (pref_allctr->thread_safe && (!force_move
+ || used_allctr != pref_allctr))
+ erts_mtx_unlock(&pref_allctr->mutex);
if (res) {
Block_t *blk;
size_t cpy_size;
- *((Allctr_t **) res) = pref_allctr;
- res = (void *) (((char *) res) + sizeof(UWord));
+ res = put_used_allctr(res, pref_ix, size);
DEBUG_CHECK_ALIGNMENT(res);
- erts_mtx_lock(&used_allctr->mutex);
blk = UMEM2BLK(ptr);
- cpy_size = BLK_SZ(blk) - ABLK_HDR_SZ - sizeof(UWord);
+ if (old_user_size != ERTS_AU_PREF_ALLOC_SIZE_MASK)
+ cpy_size = old_user_size;
+ else {
+ if (used_allctr->thread_safe && (!force_move
+ || used_allctr != pref_allctr))
+ erts_mtx_lock(&used_allctr->mutex);
+ ERTS_SMP_LC_ASSERT(erts_lc_mtx_is_locked(&used_allctr->mutex));
+ cpy_size = BLK_SZ(blk);
+ if (used_allctr->thread_safe && (!force_move
+ || used_allctr != pref_allctr))
+ erts_mtx_unlock(&used_allctr->mutex);
+ cpy_size -= ABLK_HDR_SZ + sizeof(UWord);
+ }
if (cpy_size > size)
cpy_size = size;
sys_memcpy(res, p, cpy_size);
- do_erts_alcu_free(type, used_allctr, ptr);
- erts_mtx_unlock(&used_allctr->mutex);
+
+ if (!force_move || used_allctr != pref_allctr)
+ enqueue_dealloc_other_instance(type, used_allctr, ptr);
+ else {
+ do_erts_alcu_free(type, used_allctr, ptr);
+ ASSERT(pref_allctr == used_allctr);
+ if (pref_allctr->thread_safe)
+ erts_mtx_unlock(&pref_allctr->mutex);
+ }
}
}
return res;
}
+void *
+erts_alcu_realloc_thr_pref(ErtsAlcType_t type, void *extra, void *p, Uint size)
+{
+ return realloc_thr_pref(type, extra, p, size, 0);
+}
void *
erts_alcu_realloc_mv_thr_pref(ErtsAlcType_t type, void *extra,
void *p, Uint size)
{
- ErtsAllocatorThrSpec_t *tspec = (ErtsAllocatorThrSpec_t *) extra;
- int ix;
- void *ptr, *res;
- Allctr_t *pref_allctr, *used_allctr;
-
- if (!p)
- return erts_alcu_alloc_thr_pref(type, extra, size);
-
- ptr = (void *) (((char *) p) - sizeof(UWord));
- used_allctr = *((Allctr_t **) ptr);
-
- ix = erts_alc_get_thr_ix();
- ASSERT(ix > 0);
- if (ix >= tspec->size)
- ix = (ix % (tspec->size - 1)) + 1;
- pref_allctr = tspec->allctr[ix];
- ASSERT(used_allctr && pref_allctr);
-
- erts_mtx_lock(&pref_allctr->mutex);
- res = do_erts_alcu_alloc(type, pref_allctr, size + sizeof(UWord));
- if (!res) {
- erts_mtx_unlock(&pref_allctr->mutex);
- res = erts_alcu_realloc_thr_pref(type, extra, p, size);
- }
- else {
- Block_t *blk;
- size_t cpy_size;
- Allctr_t *allctr;
-
- *((Allctr_t **) res) = pref_allctr;
- res = (void *) (((char *) res) + sizeof(UWord));
-
- DEBUG_CHECK_ALIGNMENT(res);
-
- if (used_allctr == pref_allctr)
- allctr = pref_allctr;
- else {
- erts_mtx_unlock(&pref_allctr->mutex);
- allctr = used_allctr;
- erts_mtx_lock(&allctr->mutex);
- }
-
- blk = UMEM2BLK(ptr);
- cpy_size = BLK_SZ(blk) - ABLK_HDR_SZ - sizeof(UWord);
- if (cpy_size > size)
- cpy_size = size;
- sys_memcpy(res, p, cpy_size);
- do_erts_alcu_free(type, allctr, ptr);
- erts_mtx_unlock(&allctr->mutex);
- }
-
- return res;
+ return realloc_thr_pref(type, extra, p, size, 1);
}
#endif
+#endif
+
/* ------------------------------------------------------------------------- */
int
@@ -3381,6 +4014,10 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init)
sys_memcpy((void *) &allctr->mseg_opt,
(void *) &erts_mseg_default_opt,
sizeof(ErtsMsegOpt_t));
+#ifdef ERTS_SMP
+ if (init->tspec || init->tpref)
+ allctr->mseg_opt.sched_spec = 1;
+#endif
# if HALFWORD_HEAP
allctr->mseg_opt.low_mem = init->low_mem;
# endif
@@ -3390,6 +4027,7 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init)
if (!allctr->name_prefix)
goto error;
+ allctr->ix = init->ix;
allctr->alloc_no = init->alloc_no;
if (allctr->alloc_no < ERTS_ALC_A_MIN
|| ERTS_ALC_A_MAX < allctr->alloc_no)
@@ -3431,15 +4069,24 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init)
goto error;
allctr->min_block_size = UNIT_CEILING(allctr->min_block_size
+ sizeof(UWord));
+#if ERTS_SMP
+ if (init->tpref) {
+ Uint sz = sizeof(Block_t);
+ sz += ERTS_ALCU_DD_FIX_TYPE_OFFS*sizeof(UWord);
+ if (init->fix)
+ sz += sizeof(UWord);
+ sz = UNIT_CEILING(sz);
+ if (sz > allctr->min_block_size)
+ allctr->min_block_size = sz;
+ }
+#endif
+
allctr->sbmbc_threshold = init->sbmbct;
if (!erts_have_sbmbc_alloc
-#if HALFWORD_HEAP
- || allctr->alloc_no == ERTS_ALC_A_SBMBC_LOW
-#endif
- || allctr->alloc_no == ERTS_ALC_A_SBMBC)
+ || ERTS_IS_SBMBC_ALLOCATOR_NO__(allctr->alloc_no))
allctr->sbmbc_threshold = 0;
if (!allctr->sbmbc_threshold)
@@ -3466,14 +4113,14 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init)
#ifdef ERTS_ENABLE_LOCK_COUNT
erts_mtx_init_x_opt(&allctr->mutex,
- allctr->alloc_no == ERTS_ALC_A_SBMBC
+ ERTS_IS_SBMBC_ALLOCATOR_NO__(allctr->alloc_no)
? "sbmbc_alloc"
: "alcu_allocator",
make_small(allctr->alloc_no),
ERTS_LCNT_LT_ALLOC);
#else
erts_mtx_init_x(&allctr->mutex,
- allctr->alloc_no == ERTS_ALC_A_SBMBC
+ ERTS_IS_SBMBC_ALLOCATOR_NO__(allctr->alloc_no)
? "sbmbc_alloc"
: "alcu_allocator",
make_small(allctr->alloc_no));
@@ -3496,7 +4143,8 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init)
if (allctr->mbc_header_size < sizeof(Carrier_t))
goto error;
-#ifdef USE_THREADS
+#ifdef ERTS_SMP
+ allctr->dd.use = 0;
if (init->tpref) {
allctr->mbc_header_size = (UNIT_CEILING(allctr->mbc_header_size
+ FBLK_FTR_SZ
@@ -3510,6 +4158,9 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init)
+ sizeof(UWord))
- ABLK_HDR_SZ
- sizeof(UWord));
+
+ allctr->dd.use = 1;
+ init_dd_queue(&allctr->dd.q);
}
else
#endif
@@ -3551,6 +4202,21 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init)
}
+ if (init->fix) {
+ int i;
+ allctr->fix = init->fix;
+ allctr->fix_shrink_scheduled = 0;
+ for (i = 0; i < ERTS_ALC_NO_FIXED_SIZES; i++) {
+ allctr->fix[i].max_used = 0;
+ allctr->fix[i].limit = 0;
+ allctr->fix[i].type_size = init->fix_type_size[i];
+ allctr->fix[i].list_size = 0;
+ allctr->fix[i].list = NULL;
+ allctr->fix[i].allocated = 0;
+ allctr->fix[i].used = 0;
+ }
+ }
+
return 1;
error:
diff --git a/erts/emulator/beam/erl_alloc_util.h b/erts/emulator/beam/erl_alloc_util.h
index fed4d3dbe6..df560a0de2 100644
--- a/erts/emulator/beam/erl_alloc_util.h
+++ b/erts/emulator/beam/erl_alloc_util.h
@@ -20,10 +20,13 @@
#ifndef ERL_ALLOC_UTIL__
#define ERL_ALLOC_UTIL__
-#define ERTS_ALCU_VSN_STR "2.2"
+#define ERTS_ALCU_VSN_STR "3.0"
#include "erl_alloc_types.h"
+#define ERTS_AU_PREF_ALLOC_BITS 11
+#define ERTS_AU_MAX_PREF_ALLOC_INSTANCES (1 << ERTS_AU_PREF_ALLOC_BITS)
+
typedef struct Allctr_t_ Allctr_t;
typedef struct {
@@ -35,6 +38,7 @@ typedef struct {
char *name_prefix;
ErtsAlcType_t alloc_no;
int force;
+ int ix;
int ts;
int tspec;
int tpref;
@@ -53,6 +57,9 @@ typedef struct {
UWord mbcgs;
UWord sbmbct;
UWord sbmbcs;
+
+ void *fix;
+ size_t *fix_type_size;
} AllctrInit_t;
typedef struct {
@@ -60,6 +67,11 @@ typedef struct {
UWord carriers;
} AllctrSize_t;
+typedef struct {
+ UWord allocated;
+ UWord used;
+} ErtsAlcUFixInfo_t;
+
#ifndef SMALL_MEMORY
#define ERTS_DEFAULT_ALCU_INIT { \
@@ -71,6 +83,7 @@ typedef struct {
NULL, \
ERTS_ALC_A_INVALID, /* (number) alloc_no: allocator number */\
0, /* (bool) force: force enabled */\
+ 0, /* (number) ix: instance index */\
1, /* (bool) ts: thread safe */\
0, /* (bool) tspec: thread specific */\
0, /* (bool) tpref: thread preferred */\
@@ -88,7 +101,10 @@ typedef struct {
1024*1024, /* (bytes) smbcs: smallest mbc size */\
10, /* (amount) mbcgs: mbc growth stages */\
256, /* (bytes) sbmbct: small block mbc threshold */\
- 8*1024 /* (bytes) sbmbcs: small block mbc size */\
+ 8*1024, /* (bytes) sbmbcs: small block mbc size */ \
+ /* --- Data not options -------------------------------------------- */\
+ NULL, /* (ptr) fix */\
+ NULL /* (ptr) fix_type_size */\
}
#else /* if SMALL_MEMORY */
@@ -102,6 +118,7 @@ typedef struct {
NULL, \
ERTS_ALC_A_INVALID, /* (number) alloc_no: allocator number */\
0, /* (bool) force: force enabled */\
+ 0, /* (number) ix: instance index */\
1, /* (bool) ts: thread safe */\
0, /* (bool) tspec: thread specific */\
0, /* (bool) tpref: thread preferred */\
@@ -118,7 +135,10 @@ typedef struct {
128*1024, /* (bytes) smbcs: smallest mbc size */\
10, /* (amount) mbcgs: mbc growth stages */\
256, /* (bytes) sbmbct: small block mbc threshold */\
- 8*1024 /* (bytes) sbmbcs: small block mbc size */\
+ 8*1024, /* (bytes) sbmbcs: small block mbc size */ \
+ /* --- Data not options -------------------------------------------- */\
+ NULL, /* (ptr) fix */\
+ NULL /* (ptr) fix_type_size */\
}
#endif
@@ -132,6 +152,7 @@ void * erts_alcu_alloc_ts(ErtsAlcType_t, void *, Uint);
void * erts_alcu_realloc_ts(ErtsAlcType_t, void *, void *, Uint);
void * erts_alcu_realloc_mv_ts(ErtsAlcType_t, void *, void *, Uint);
void erts_alcu_free_ts(ErtsAlcType_t, void *, void *);
+#ifdef ERTS_SMP
void * erts_alcu_alloc_thr_spec(ErtsAlcType_t, void *, Uint);
void * erts_alcu_realloc_thr_spec(ErtsAlcType_t, void *, void *, Uint);
void * erts_alcu_realloc_mv_thr_spec(ErtsAlcType_t, void *, void *, Uint);
@@ -141,12 +162,16 @@ void * erts_alcu_realloc_thr_pref(ErtsAlcType_t, void *, void *, Uint);
void * erts_alcu_realloc_mv_thr_pref(ErtsAlcType_t, void *, void *, Uint);
void erts_alcu_free_thr_pref(ErtsAlcType_t, void *, void *);
#endif
+#endif
Eterm erts_alcu_au_info_options(int *, void *, Uint **, Uint *);
Eterm erts_alcu_info_options(Allctr_t *, int *, void *, Uint **, Uint *);
Eterm erts_alcu_sz_info(Allctr_t *, int, int *, void *, Uint **, Uint *);
Eterm erts_alcu_info(Allctr_t *, int, int *, void *, Uint **, Uint *);
void erts_alcu_init(AlcUInit_t *);
-void erts_alcu_current_size(Allctr_t *, AllctrSize_t *);
+void erts_alcu_current_size(Allctr_t *, AllctrSize_t *,
+ ErtsAlcUFixInfo_t *, int);
+void erts_alcu_check_delayed_dealloc(Allctr_t *, int, int *, int *);
+erts_aint32_t erts_alcu_fix_alloc_shrink(Allctr_t *, erts_aint32_t);
#endif
@@ -246,7 +271,74 @@ typedef struct {
} blocks;
} CarriersStats_t;
+#ifdef ERTS_SMP
+
+typedef union ErtsAllctrDDBlock_t_ ErtsAllctrDDBlock_t;
+
+union ErtsAllctrDDBlock_t_ {
+ erts_atomic_t atmc_next;
+ ErtsAllctrDDBlock_t *ptr_next;
+};
+
+typedef struct {
+ ErtsAllctrDDBlock_t marker;
+ erts_atomic_t last;
+ erts_atomic_t um_refc[2];
+ erts_atomic32_t um_refc_ix;
+} ErtsDDTail_t;
+
+typedef struct {
+ /*
+ * This structure needs to be cache line aligned for best
+ * performance.
+ */
+ union {
+ /* Modified by threads returning memory to this allocator */
+ ErtsDDTail_t data;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsDDTail_t))];
+ } tail;
+ /*
+ * Everything below this point is *only* accessed by the
+ * thread owning the allocator.
+ */
+ struct {
+ ErtsAllctrDDBlock_t *first;
+ ErtsAllctrDDBlock_t *unref_end;
+ struct {
+ ErtsThrPrgrVal thr_progress;
+ int thr_progress_reached;
+ int um_refc_ix;
+ ErtsAllctrDDBlock_t *unref_end;
+ } next;
+ int used_marker;
+ } head;
+} ErtsAllctrDDQueue_t;
+
+#endif
+
+typedef struct {
+ size_t type_size;
+ SWord list_size;
+ void *list;
+ SWord max_used;
+ SWord limit;
+ SWord allocated;
+ SWord used;
+} ErtsAlcFixList_t;
+
struct Allctr_t_ {
+#ifdef ERTS_SMP
+ struct {
+ /*
+ * We want the queue at the beginning of
+ * the Allctr_t struct, due to cache line
+ * alignment reasons.
+ */
+ ErtsAllctrDDQueue_t q;
+ int use;
+ int ix;
+ } dd;
+#endif
/* Allocator name prefix */
char * name_prefix;
@@ -254,6 +346,9 @@ struct Allctr_t_ {
/* Allocator number */
ErtsAlcType_t alloc_no;
+ /* Instance index */
+ int ix;
+
/* Alloc, realloc and free names as atoms */
struct {
Eterm alloc;
@@ -278,6 +373,7 @@ struct Allctr_t_ {
Uint mbc_growth_stages;
Uint sbmbc_threshold;
Uint sbmbc_size;
+
#if HAVE_ERTS_MSEG
ErtsMsegOpt_t mseg_opt;
#endif
@@ -315,6 +411,10 @@ struct Allctr_t_ {
void (*check_mbc) (Allctr_t *, Carrier_t *);
#endif
+ int fix_n_base;
+ int fix_shrink_scheduled;
+ ErtsAlcFixList_t *fix;
+
#ifdef USE_THREADS
/* Mutex for this allocator */
erts_mtx_t mutex;
@@ -323,6 +423,7 @@ struct Allctr_t_ {
Allctr_t *prev;
Allctr_t *next;
} ts_list;
+
#endif
int atoms_initialized;
diff --git a/erts/emulator/beam/erl_ao_firstfit_alloc.c b/erts/emulator/beam/erl_ao_firstfit_alloc.c
new file mode 100644
index 0000000000..5bdb752d3a
--- /dev/null
+++ b/erts/emulator/beam/erl_ao_firstfit_alloc.c
@@ -0,0 +1,976 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2003-2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+
+/*
+ * Description: An "address order first fit" allocator
+ * based on a Red-Black (binary search) Tree. The search,
+ * insert, and delete operations are all O(log n) operations
+ * on a Red-Black Tree.
+ * Red-Black Trees are described in "Introduction to Algorithms",
+ * by Thomas H. Cormen, Charles E. Leiserson, and Ronald L. Riverest.
+ *
+ * This module is a callback-module for erl_alloc_util.c
+ *
+ * Algorithm: The tree nodes are free-blocks ordered in address order.
+ * Every node also keeps the size of the largest block in its
+ * sub-tree ('max_size'). By that we can start from root and keep
+ * left (for low addresses) while dismissing entire sub-trees with
+ * too small blocks.
+ *
+ * Authors: Rickard Green/Sverker Eriksson
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include "global.h"
+#define GET_ERL_AOFF_ALLOC_IMPL
+#include "erl_ao_firstfit_alloc.h"
+
+#ifdef DEBUG
+#if 0
+#define HARD_DEBUG
+#endif
+#else
+#undef HARD_DEBUG
+#endif
+
+#define MIN_MBC_SZ (16*1024)
+#define MIN_MBC_FIRST_FREE_SZ (4*1024)
+
+#define TREE_NODE_FLG (((Uint) 1) << 0)
+#define RED_FLG (((Uint) 1) << 1)
+#ifdef HARD_DEBUG
+# define LEFT_VISITED_FLG (((Uint) 1) << 2)
+# define RIGHT_VISITED_FLG (((Uint) 1) << 3)
+#endif
+
+#define IS_RED(N) (((AOFF_RBTree_t *) (N)) \
+ && ((AOFF_RBTree_t *) (N))->flags & RED_FLG)
+#define IS_BLACK(N) (!IS_RED(((AOFF_RBTree_t *) (N))))
+
+#define SET_RED(N) (((AOFF_RBTree_t *) (N))->flags |= RED_FLG)
+#define SET_BLACK(N) (((AOFF_RBTree_t *) (N))->flags &= ~RED_FLG)
+
+#undef ASSERT
+#define ASSERT ASSERT_EXPR
+
+#if 1
+#define RBT_ASSERT ASSERT
+#else
+#define RBT_ASSERT(x)
+#endif
+
+
+/* Types... */
+typedef struct AOFF_RBTree_t_ AOFF_RBTree_t;
+
+struct AOFF_RBTree_t_ {
+ Block_t hdr;
+ Uint flags;
+ AOFF_RBTree_t *parent;
+ AOFF_RBTree_t *left;
+ AOFF_RBTree_t *right;
+ Uint max_sz; /* of all blocks in this sub-tree */
+};
+
+#ifdef HARD_DEBUG
+static AOFF_RBTree_t * check_tree(AOFF_RBTree_t* root, Uint);
+#endif
+
+
+/* Calculate 'max_size' of tree node x by only looking at the direct children
+ * of x and x itself.
+ */
+static ERTS_INLINE Uint node_max_size(AOFF_RBTree_t *x)
+{
+ Uint sz = BLK_SZ(x);
+ if (x->left && x->left->max_sz > sz) {
+ sz = x->left->max_sz;
+ }
+ if (x->right && x->right->max_sz > sz) {
+ sz = x->right->max_sz;
+ }
+ return sz;
+}
+
+/* Set new possibly lower 'max_size' of node and propagate change toward root
+*/
+static ERTS_INLINE void lower_max_size(AOFF_RBTree_t *node,
+ AOFF_RBTree_t* stop_at)
+{
+ AOFF_RBTree_t* x = node;
+ Uint old_max = x->max_sz;
+ Uint new_max = node_max_size(x);
+
+ if (new_max < old_max) {
+ x->max_sz = new_max;
+ while ((x=x->parent) != stop_at && x->max_sz == old_max) {
+ x->max_sz = node_max_size(x);
+ }
+ ASSERT(x == stop_at || x->max_sz > old_max);
+ }
+ else ASSERT(new_max == old_max);
+}
+
+
+/* Prototypes of callback functions */
+static Block_t* aoff_get_free_block(Allctr_t *, Uint, Block_t *, Uint, Uint32 flags);
+static void aoff_link_free_block(Allctr_t *, Block_t*, Uint32 flags);
+static void aoff_unlink_free_block(Allctr_t *allctr, Block_t *del, Uint32 flags);
+
+static Eterm info_options(Allctr_t *, char *, int *, void *, Uint **, Uint *);
+static void init_atoms(void);
+
+
+
+#ifdef DEBUG
+
+/* Destroy all tree fields */
+#define DESTROY_TREE_NODE(N) \
+ sys_memset((void *) (((Block_t *) (N)) + 1), \
+ 0xff, \
+ (sizeof(AOFF_RBTree_t) - sizeof(Block_t)))
+
+#else
+
+#define DESTROY_TREE_NODE(N)
+
+#endif
+
+
+static int atoms_initialized = 0;
+
+void
+erts_aoffalc_init(void)
+{
+ atoms_initialized = 0;
+}
+
+Allctr_t *
+erts_aoffalc_start(AOFFAllctr_t *alc,
+ AOFFAllctrInit_t* aoffinit,
+ AllctrInit_t *init)
+{
+ struct {
+ int dummy;
+ AOFFAllctr_t allctr;
+ } zero = {0};
+ /* The struct with a dummy element first is used in order to avoid (an
+ incorrect) gcc warning. gcc warns if {0} is used as initializer of
+ a struct when the first member is a struct (not if, for example,
+ the third member is a struct). */
+
+ Allctr_t *allctr = (Allctr_t *) alc;
+
+ sys_memcpy((void *) alc, (void *) &zero.allctr, sizeof(AOFFAllctr_t));
+
+ allctr->mbc_header_size = sizeof(Carrier_t);
+ allctr->min_mbc_size = MIN_MBC_SZ;
+ allctr->min_mbc_first_free_size = MIN_MBC_FIRST_FREE_SZ;
+ allctr->min_block_size = sizeof(AOFF_RBTree_t);
+
+ allctr->vsn_str = ERTS_ALC_AOFF_ALLOC_VSN_STR;
+
+
+ /* Callback functions */
+
+ allctr->get_free_block = aoff_get_free_block;
+ allctr->link_free_block = aoff_link_free_block;
+ allctr->unlink_free_block = aoff_unlink_free_block;
+ allctr->info_options = info_options;
+
+ allctr->get_next_mbc_size = NULL;
+ allctr->creating_mbc = NULL;
+ allctr->destroying_mbc = NULL;
+ allctr->init_atoms = init_atoms;
+
+#ifdef ERTS_ALLOC_UTIL_HARD_DEBUG
+ allctr->check_block = NULL;
+ allctr->check_mbc = NULL;
+#endif
+
+ allctr->atoms_initialized = 0;
+
+ if (!erts_alcu_start(allctr, init))
+ return NULL;
+
+ return allctr;
+}
+
+/*
+ * Red-Black Tree operations needed
+ */
+
+static ERTS_INLINE void
+left_rotate(AOFF_RBTree_t **root, AOFF_RBTree_t *x)
+{
+ AOFF_RBTree_t *y = x->right;
+ x->right = y->left;
+ if (y->left)
+ y->left->parent = x;
+ y->parent = x->parent;
+ if (!y->parent) {
+ RBT_ASSERT(*root == x);
+ *root = y;
+ }
+ else if (x == x->parent->left)
+ x->parent->left = y;
+ else {
+ RBT_ASSERT(x == x->parent->right);
+ x->parent->right = y;
+ }
+ y->left = x;
+ x->parent = y;
+
+ y->max_sz = x->max_sz;
+ x->max_sz = node_max_size(x);
+ ASSERT(y->max_sz >= x->max_sz);
+}
+
+static ERTS_INLINE void
+right_rotate(AOFF_RBTree_t **root, AOFF_RBTree_t *x)
+{
+ AOFF_RBTree_t *y = x->left;
+ x->left = y->right;
+ if (y->right)
+ y->right->parent = x;
+ y->parent = x->parent;
+ if (!y->parent) {
+ RBT_ASSERT(*root == x);
+ *root = y;
+ }
+ else if (x == x->parent->right)
+ x->parent->right = y;
+ else {
+ RBT_ASSERT(x == x->parent->left);
+ x->parent->left = y;
+ }
+ y->right = x;
+ x->parent = y;
+ y->max_sz = x->max_sz;
+ x->max_sz = node_max_size(x);
+ ASSERT(y->max_sz >= x->max_sz);
+}
+
+
+/*
+ * Replace node x with node y
+ * NOTE: block header of y is not changed
+ */
+static ERTS_INLINE void
+replace(AOFF_RBTree_t **root, AOFF_RBTree_t *x, AOFF_RBTree_t *y)
+{
+
+ if (!x->parent) {
+ RBT_ASSERT(*root == x);
+ *root = y;
+ }
+ else if (x == x->parent->left)
+ x->parent->left = y;
+ else {
+ RBT_ASSERT(x == x->parent->right);
+ x->parent->right = y;
+ }
+ if (x->left) {
+ RBT_ASSERT(x->left->parent == x);
+ x->left->parent = y;
+ }
+ if (x->right) {
+ RBT_ASSERT(x->right->parent == x);
+ x->right->parent = y;
+ }
+
+ y->flags = x->flags;
+ y->parent = x->parent;
+ y->right = x->right;
+ y->left = x->left;
+
+ y->max_sz = x->max_sz;
+ lower_max_size(y, NULL);
+ DESTROY_TREE_NODE(x);
+}
+
+static void
+tree_insert_fixup(AOFF_RBTree_t** root, AOFF_RBTree_t *blk)
+{
+ AOFF_RBTree_t *x = blk, *y;
+
+ /*
+ * Rearrange the tree so that it satisfies the Red-Black Tree properties
+ */
+
+ RBT_ASSERT(x != *root && IS_RED(x->parent));
+ do {
+
+ /*
+ * x and its parent are both red. Move the red pair up the tree
+ * until we get to the root or until we can separate them.
+ */
+
+ RBT_ASSERT(IS_RED(x));
+ RBT_ASSERT(IS_BLACK(x->parent->parent));
+ RBT_ASSERT(x->parent->parent);
+
+ if (x->parent == x->parent->parent->left) {
+ y = x->parent->parent->right;
+ if (IS_RED(y)) {
+ SET_BLACK(y);
+ x = x->parent;
+ SET_BLACK(x);
+ x = x->parent;
+ SET_RED(x);
+ }
+ else {
+
+ if (x == x->parent->right) {
+ x = x->parent;
+ left_rotate(root, x);
+ }
+
+ RBT_ASSERT(x == x->parent->parent->left->left);
+ RBT_ASSERT(IS_RED(x));
+ RBT_ASSERT(IS_RED(x->parent));
+ RBT_ASSERT(IS_BLACK(x->parent->parent));
+ RBT_ASSERT(IS_BLACK(y));
+
+ SET_BLACK(x->parent);
+ SET_RED(x->parent->parent);
+ right_rotate(root, x->parent->parent);
+
+ RBT_ASSERT(x == x->parent->left);
+ RBT_ASSERT(IS_RED(x));
+ RBT_ASSERT(IS_RED(x->parent->right));
+ RBT_ASSERT(IS_BLACK(x->parent));
+ break;
+ }
+ }
+ else {
+ RBT_ASSERT(x->parent == x->parent->parent->right);
+ y = x->parent->parent->left;
+ if (IS_RED(y)) {
+ SET_BLACK(y);
+ x = x->parent;
+ SET_BLACK(x);
+ x = x->parent;
+ SET_RED(x);
+ }
+ else {
+
+ if (x == x->parent->left) {
+ x = x->parent;
+ right_rotate(root, x);
+ }
+
+ RBT_ASSERT(x == x->parent->parent->right->right);
+ RBT_ASSERT(IS_RED(x));
+ RBT_ASSERT(IS_RED(x->parent));
+ RBT_ASSERT(IS_BLACK(x->parent->parent));
+ RBT_ASSERT(IS_BLACK(y));
+
+ SET_BLACK(x->parent);
+ SET_RED(x->parent->parent);
+ left_rotate(root, x->parent->parent);
+
+ RBT_ASSERT(x == x->parent->right);
+ RBT_ASSERT(IS_RED(x));
+ RBT_ASSERT(IS_RED(x->parent->left));
+ RBT_ASSERT(IS_BLACK(x->parent));
+ break;
+ }
+ }
+ } while (x != *root && IS_RED(x->parent));
+
+ SET_BLACK(*root);
+}
+
+static void
+aoff_unlink_free_block(Allctr_t *allctr, Block_t *del, Uint32 flags)
+{
+ AOFFAllctr_t *alc = (AOFFAllctr_t *) allctr;
+ AOFF_RBTree_t **root = ((flags & ERTS_ALCU_FLG_SBMBC)
+ ? &alc->sbmbc_root : &alc->mbc_root);
+ Uint spliced_is_black;
+ AOFF_RBTree_t *x, *y, *z = (AOFF_RBTree_t *) del;
+ AOFF_RBTree_t null_x; /* null_x is used to get the fixup started when we
+ splice out a node without children. */
+
+ null_x.parent = NULL;
+
+#ifdef HARD_DEBUG
+ check_tree(*root, 0);
+#endif
+
+ /* Remove node from tree... */
+
+ /* Find node to splice out */
+ if (!z->left || !z->right)
+ y = z;
+ else
+ /* Set y to z:s successor */
+ for(y = z->right; y->left; y = y->left);
+ /* splice out y */
+ x = y->left ? y->left : y->right;
+ spliced_is_black = IS_BLACK(y);
+ if (x) {
+ x->parent = y->parent;
+ }
+ else if (spliced_is_black) {
+ x = &null_x;
+ x->flags = 0;
+ SET_BLACK(x);
+ x->right = x->left = NULL;
+ x->max_sz = 0;
+ x->parent = y->parent;
+ y->left = x;
+ }
+
+ if (!y->parent) {
+ RBT_ASSERT(*root == y);
+ *root = x;
+ }
+ else {
+ if (y == y->parent->left) {
+ y->parent->left = x;
+ }
+ else {
+ RBT_ASSERT(y == y->parent->right);
+ y->parent->right = x;
+ }
+ if (y->parent != z) {
+ lower_max_size(y->parent, (y==z ? NULL : z));
+ }
+ }
+ if (y != z) {
+ /* We spliced out the successor of z; replace z by the successor */
+ replace(root, z, y);
+ }
+
+ if (spliced_is_black) {
+ /* We removed a black node which makes the resulting tree
+ violate the Red-Black Tree properties. Fixup tree... */
+
+ while (IS_BLACK(x) && x->parent) {
+
+ /*
+ * x has an "extra black" which we move up the tree
+ * until we reach the root or until we can get rid of it.
+ *
+ * y is the sibbling of x
+ */
+
+ if (x == x->parent->left) {
+ y = x->parent->right;
+ RBT_ASSERT(y);
+ if (IS_RED(y)) {
+ RBT_ASSERT(y->right);
+ RBT_ASSERT(y->left);
+ SET_BLACK(y);
+ RBT_ASSERT(IS_BLACK(x->parent));
+ SET_RED(x->parent);
+ left_rotate(root, x->parent);
+ y = x->parent->right;
+ }
+ RBT_ASSERT(y);
+ RBT_ASSERT(IS_BLACK(y));
+ if (IS_BLACK(y->left) && IS_BLACK(y->right)) {
+ SET_RED(y);
+ x = x->parent;
+ }
+ else {
+ if (IS_BLACK(y->right)) {
+ SET_BLACK(y->left);
+ SET_RED(y);
+ right_rotate(root, y);
+ y = x->parent->right;
+ }
+ RBT_ASSERT(y);
+ if (IS_RED(x->parent)) {
+
+ SET_BLACK(x->parent);
+ SET_RED(y);
+ }
+ RBT_ASSERT(y->right);
+ SET_BLACK(y->right);
+ left_rotate(root, x->parent);
+ x = *root;
+ break;
+ }
+ }
+ else {
+ RBT_ASSERT(x == x->parent->right);
+ y = x->parent->left;
+ RBT_ASSERT(y);
+ if (IS_RED(y)) {
+ RBT_ASSERT(y->right);
+ RBT_ASSERT(y->left);
+ SET_BLACK(y);
+ RBT_ASSERT(IS_BLACK(x->parent));
+ SET_RED(x->parent);
+ right_rotate(root, x->parent);
+ y = x->parent->left;
+ }
+ RBT_ASSERT(y);
+ RBT_ASSERT(IS_BLACK(y));
+ if (IS_BLACK(y->right) && IS_BLACK(y->left)) {
+ SET_RED(y);
+ x = x->parent;
+ }
+ else {
+ if (IS_BLACK(y->left)) {
+ SET_BLACK(y->right);
+ SET_RED(y);
+ left_rotate(root, y);
+ y = x->parent->left;
+ }
+ RBT_ASSERT(y);
+ if (IS_RED(x->parent)) {
+ SET_BLACK(x->parent);
+ SET_RED(y);
+ }
+ RBT_ASSERT(y->left);
+ SET_BLACK(y->left);
+ right_rotate(root, x->parent);
+ x = *root;
+ break;
+ }
+ }
+ }
+ SET_BLACK(x);
+
+ if (null_x.parent) {
+ if (null_x.parent->left == &null_x)
+ null_x.parent->left = NULL;
+ else {
+ RBT_ASSERT(null_x.parent->right == &null_x);
+ null_x.parent->right = NULL;
+ }
+ RBT_ASSERT(!null_x.left);
+ RBT_ASSERT(!null_x.right);
+ }
+ else if (*root == &null_x) {
+ *root = NULL;
+ RBT_ASSERT(!null_x.left);
+ RBT_ASSERT(!null_x.right);
+ }
+ }
+
+ DESTROY_TREE_NODE(del);
+
+#ifdef HARD_DEBUG
+ check_tree(*root, 0);
+#endif
+}
+
+static void
+aoff_link_free_block(Allctr_t *allctr, Block_t *block, Uint32 flags)
+{
+ AOFFAllctr_t *alc = (AOFFAllctr_t *) allctr;
+ AOFF_RBTree_t *blk = (AOFF_RBTree_t *) block;
+ AOFF_RBTree_t **root = ((flags & ERTS_ALCU_FLG_SBMBC)
+ ? &alc->sbmbc_root : &alc->mbc_root);
+ Uint blk_sz = BLK_SZ(blk);
+
+#ifdef HARD_DEBUG
+ check_tree(*root, 0);
+#endif
+
+ blk->flags = 0;
+ blk->left = NULL;
+ blk->right = NULL;
+ blk->max_sz = blk_sz;
+
+ if (!*root) {
+ blk->parent = NULL;
+ SET_BLACK(blk);
+ *root = blk;
+ }
+ else {
+ AOFF_RBTree_t *x = *root;
+ while (1) {
+ if (x->max_sz < blk_sz) {
+ x->max_sz = blk_sz;
+ }
+ if (blk < x) {
+ if (!x->left) {
+ blk->parent = x;
+ x->left = blk;
+ break;
+ }
+ x = x->left;
+ }
+ else {
+ if (!x->right) {
+ blk->parent = x;
+ x->right = blk;
+ break;
+ }
+ x = x->right;
+ }
+
+ }
+
+ /* Insert block into size tree */
+ RBT_ASSERT(blk->parent);
+
+ SET_RED(blk);
+ if (IS_RED(blk->parent))
+ tree_insert_fixup(root, blk);
+ }
+
+#ifdef HARD_DEBUG
+ check_tree(*root, 0);
+#endif
+}
+
+static Block_t *
+aoff_get_free_block(Allctr_t *allctr, Uint size,
+ Block_t *cand_blk, Uint cand_size, Uint32 flags)
+{
+ AOFFAllctr_t *alc = (AOFFAllctr_t *) allctr;
+ AOFF_RBTree_t *x = ((flags & ERTS_ALCU_FLG_SBMBC)
+ ? alc->sbmbc_root : alc->mbc_root);
+ AOFF_RBTree_t *blk = NULL;
+#ifdef HARD_DEBUG
+ AOFF_RBTree_t* dbg_blk = check_tree(x, size);
+#endif
+
+ ASSERT(!cand_blk || cand_size >= size);
+
+ while (x) {
+ if (x->left && x->left->max_sz >= size) {
+ x = x->left;
+ }
+ else if (BLK_SZ(x) >= size) {
+ blk = x;
+ break;
+ }
+ else {
+ x = x->right;
+ }
+ }
+
+#ifdef HARD_DEBUG
+ ASSERT(blk == dbg_blk);
+#endif
+
+ if (!blk)
+ return NULL;
+
+ if (cand_blk && cand_blk < &blk->hdr) {
+ return NULL; /* cand_blk was better */
+ }
+
+ aoff_unlink_free_block(allctr, (Block_t *) blk, flags);
+
+ return (Block_t *) blk;
+}
+
+
+/*
+ * info_options()
+ */
+
+static struct {
+ Eterm as;
+ Eterm aoff;
+#ifdef DEBUG
+ Eterm end_of_atoms;
+#endif
+} am;
+
+static void ERTS_INLINE atom_init(Eterm *atom, char *name)
+{
+ *atom = am_atom_put(name, strlen(name));
+}
+#define AM_INIT(AM) atom_init(&am.AM, #AM)
+
+static void
+init_atoms(void)
+{
+#ifdef DEBUG
+ Eterm *atom;
+#endif
+
+ if (atoms_initialized)
+ return;
+
+#ifdef DEBUG
+ for (atom = (Eterm *) &am; atom <= &am.end_of_atoms; atom++) {
+ *atom = THE_NON_VALUE;
+ }
+#endif
+ AM_INIT(as);
+ AM_INIT(aoff);
+
+#ifdef DEBUG
+ for (atom = (Eterm *) &am; atom < &am.end_of_atoms; atom++) {
+ ASSERT(*atom != THE_NON_VALUE);
+ }
+#endif
+
+ atoms_initialized = 1;
+}
+
+
+#define bld_uint erts_bld_uint
+#define bld_cons erts_bld_cons
+#define bld_tuple erts_bld_tuple
+
+static ERTS_INLINE void
+add_2tup(Uint **hpp, Uint *szp, Eterm *lp, Eterm el1, Eterm el2)
+{
+ *lp = bld_cons(hpp, szp, bld_tuple(hpp, szp, 2, el1, el2), *lp);
+}
+
+static Eterm
+info_options(Allctr_t *allctr,
+ char *prefix,
+ int *print_to_p,
+ void *print_to_arg,
+ Uint **hpp,
+ Uint *szp)
+{
+ Eterm res = THE_NON_VALUE;
+
+ if (print_to_p) {
+ erts_print(*print_to_p,
+ print_to_arg,
+ "%sas: %s\n",
+ prefix,
+ "aoff");
+ }
+
+ if (hpp || szp) {
+
+ if (!atoms_initialized)
+ erl_exit(1, "%s:%d: Internal error: Atoms not initialized",
+ __FILE__, __LINE__);;
+
+ res = NIL;
+ add_2tup(hpp, szp, &res, am.as, am.aoff);
+ }
+
+ return res;
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
+ * NOTE: erts_aoffalc_test() is only supposed to be used for testing. *
+ * *
+ * Keep alloc_SUITE_data/allocator_test.h updated if changes are made *
+ * to erts_aoffalc_test() *
+\* */
+
+unsigned long
+erts_aoffalc_test(unsigned long op, unsigned long a1, unsigned long a2)
+{
+ switch (op) {
+ case 0x500: return (unsigned long) 0; /* IS_AOBF */
+ case 0x501: return (unsigned long) ((AOFFAllctr_t *) a1)->mbc_root;
+ case 0x502: return (unsigned long) ((AOFF_RBTree_t *) a1)->parent;
+ case 0x503: return (unsigned long) ((AOFF_RBTree_t *) a1)->left;
+ case 0x504: return (unsigned long) ((AOFF_RBTree_t *) a1)->right;
+ case 0x506: return (unsigned long) IS_BLACK((AOFF_RBTree_t *) a1);
+ case 0x508: return (unsigned long) 1; /* IS_AOFF */
+ case 0x509: return (unsigned long) ((AOFF_RBTree_t *) a1)->max_sz;
+ default: ASSERT(0); return ~((unsigned long) 0);
+ }
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
+ * Debug functions *
+\* */
+
+
+#ifdef HARD_DEBUG
+
+#define IS_LEFT_VISITED(FB) ((FB)->flags & LEFT_VISITED_FLG)
+#define IS_RIGHT_VISITED(FB) ((FB)->flags & RIGHT_VISITED_FLG)
+
+#define SET_LEFT_VISITED(FB) ((FB)->flags |= LEFT_VISITED_FLG)
+#define SET_RIGHT_VISITED(FB) ((FB)->flags |= RIGHT_VISITED_FLG)
+
+#define UNSET_LEFT_VISITED(FB) ((FB)->flags &= ~LEFT_VISITED_FLG)
+#define UNSET_RIGHT_VISITED(FB) ((FB)->flags &= ~RIGHT_VISITED_FLG)
+
+
+#if 0
+# define PRINT_TREE
+#else
+# undef PRINT_TREE
+#endif
+
+#ifdef PRINT_TREE
+static void print_tree(AOFF_RBTree_t*);
+#endif
+
+/*
+ * Checks that the order between parent and children are correct,
+ * and that the Red-Black Tree properies are satisfied. if size > 0,
+ * check_tree() returns the node that satisfies "address order first fit"
+ *
+ * The Red-Black Tree properies are:
+ * 1. Every node is either red or black.
+ * 2. Every leaf (NIL) is black.
+ * 3. If a node is red, then both its children are black.
+ * 4. Every simple path from a node to a descendant leaf
+ * contains the same number of black nodes.
+ *
+ * + own.max_size == MAX(own.size, left.max_size, right.max_size)
+ */
+
+static AOFF_RBTree_t *
+check_tree(AOFF_RBTree_t* root, Uint size)
+{
+ AOFF_RBTree_t *res = NULL;
+ Sint blacks;
+ Sint curr_blacks;
+ AOFF_RBTree_t *x;
+
+#ifdef PRINT_TREE
+ print_tree(root);
+#endif
+
+ if (!root)
+ return res;
+
+ x = root;
+ ASSERT(IS_BLACK(x));
+ ASSERT(!x->parent);
+ curr_blacks = 1;
+ blacks = -1;
+
+ while (x) {
+ if (!IS_LEFT_VISITED(x)) {
+ SET_LEFT_VISITED(x);
+ if (x->left) {
+ x = x->left;
+ if (IS_BLACK(x))
+ curr_blacks++;
+ continue;
+ }
+ else {
+ if (blacks < 0)
+ blacks = curr_blacks;
+ ASSERT(blacks == curr_blacks);
+ }
+ }
+
+ if (!IS_RIGHT_VISITED(x)) {
+ SET_RIGHT_VISITED(x);
+ if (x->right) {
+ x = x->right;
+ if (IS_BLACK(x))
+ curr_blacks++;
+ continue;
+ }
+ else {
+ if (blacks < 0)
+ blacks = curr_blacks;
+ ASSERT(blacks == curr_blacks);
+ }
+ }
+
+
+ if (IS_RED(x)) {
+ ASSERT(IS_BLACK(x->right));
+ ASSERT(IS_BLACK(x->left));
+ }
+
+ ASSERT(x->parent || x == root);
+
+ if (x->left) {
+ ASSERT(x->left->parent == x);
+ ASSERT(x->left < x);
+ ASSERT(x->left->max_sz <= x->max_sz);
+ }
+
+ if (x->right) {
+ ASSERT(x->right->parent == x);
+ ASSERT(x->right > x);
+ ASSERT(x->right->max_sz <= x->max_sz);
+ }
+ ASSERT(x->max_sz >= BLK_SZ(x));
+ ASSERT(x->max_sz == BLK_SZ(x)
+ || x->max_sz == (x->left ? x->left->max_sz : 0)
+ || x->max_sz == (x->right ? x->right->max_sz : 0));
+
+ if (size && BLK_SZ(x) >= size) {
+ if (!res || x < res) {
+ res = x;
+ }
+ }
+
+ UNSET_LEFT_VISITED(x);
+ UNSET_RIGHT_VISITED(x);
+ if (IS_BLACK(x))
+ curr_blacks--;
+ x = x->parent;
+
+ }
+
+ ASSERT(curr_blacks == 0);
+
+ UNSET_LEFT_VISITED(root);
+ UNSET_RIGHT_VISITED(root);
+
+ return res;
+
+}
+
+
+#ifdef PRINT_TREE
+#define INDENT_STEP 2
+
+#include <stdio.h>
+
+static void
+print_tree_aux(AOFF_RBTree_t *x, int indent)
+{
+ int i;
+
+ if (x) {
+ print_tree_aux(x->right, indent + INDENT_STEP);
+ for (i = 0; i < indent; i++) {
+ putc(' ', stderr);
+ }
+ fprintf(stderr, "%s: sz=%lu addr=0x%lx max_size=%lu\r\n",
+ IS_BLACK(x) ? "BLACK" : "RED",
+ BLK_SZ(x), (Uint)x, x->max_sz);
+ print_tree_aux(x->left, indent + INDENT_STEP);
+ }
+}
+
+
+static void
+print_tree(AOFF_RBTree_t* root)
+{
+ fprintf(stderr, " --- AOFF tree begin ---\r\n");
+ print_tree_aux(root, 0);
+ fprintf(stderr, " --- AOFF tree end ---\r\n");
+}
+
+#endif /* PRINT_TREE */
+
+#endif /* HARD_DEBUG */
+
diff --git a/erts/emulator/beam/erl_ao_firstfit_alloc.h b/erts/emulator/beam/erl_ao_firstfit_alloc.h
new file mode 100644
index 0000000000..6fa626f723
--- /dev/null
+++ b/erts/emulator/beam/erl_ao_firstfit_alloc.h
@@ -0,0 +1,60 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2003-2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+
+#ifndef ERL_AO_FIRSTFIT_ALLOC__
+#define ERL_AO_FIRSTFIT_ALLOC__
+
+#include "erl_alloc_util.h"
+
+#define ERTS_ALC_AOFF_ALLOC_VSN_STR "0.9"
+
+typedef struct AOFFAllctr_t_ AOFFAllctr_t;
+
+typedef struct {
+ int dummy;
+} AOFFAllctrInit_t;
+
+#define ERTS_DEFAULT_AOFF_ALLCTR_INIT {0/*dummy*/}
+
+void erts_aoffalc_init(void);
+Allctr_t *erts_aoffalc_start(AOFFAllctr_t *, AOFFAllctrInit_t*, AllctrInit_t *);
+
+#endif /* #ifndef ERL_AO_FIRSTFIT_ALLOC__ */
+
+
+
+#if defined(GET_ERL_AOFF_ALLOC_IMPL) && !defined(ERL_AOFF_ALLOC_IMPL__)
+#define ERL_AOFF_ALLOC_IMPL__
+
+#define GET_ERL_ALLOC_UTIL_IMPL
+#include "erl_alloc_util.h"
+
+
+struct AOFFAllctr_t_ {
+ Allctr_t allctr; /* Has to be first! */
+
+ struct AOFF_RBTree_t_* mbc_root;
+ struct AOFF_RBTree_t_* sbmbc_root;
+};
+
+unsigned long erts_aoffalc_test(unsigned long, unsigned long, unsigned long);
+
+#endif /* #if defined(GET_ERL_AOFF_ALLOC_IMPL)
+ && !defined(ERL_AOFF_ALLOC_IMPL__) */
diff --git a/erts/emulator/beam/erl_arith.c b/erts/emulator/beam/erl_arith.c
index 64fad9fe0e..5150a8a507 100644
--- a/erts/emulator/beam/erl_arith.c
+++ b/erts/emulator/beam/erl_arith.c
@@ -164,14 +164,14 @@ BIF_RETTYPE bxor_2(BIF_ALIST_2)
BIF_RET(erts_bxor(BIF_P, BIF_ARG_1, BIF_ARG_2));
}
-BIF_RETTYPE bsl_2(Process* p, Eterm arg1, Eterm arg2)
+BIF_RETTYPE bsl_2(BIF_ALIST_2)
{
- BIF_RET(shift(p, arg1, arg2, 0));
+ BIF_RET(shift(BIF_P, BIF_ARG_1, BIF_ARG_2, 0));
}
-BIF_RETTYPE bsr_2(Process* p, Eterm arg1, Eterm arg2)
+BIF_RETTYPE bsr_2(BIF_ALIST_2)
{
- BIF_RET(shift(p, arg1, arg2, 1));
+ BIF_RET(shift(BIF_P, BIF_ARG_1, BIF_ARG_2, 1));
}
static Eterm
diff --git a/erts/emulator/beam/erl_async.c b/erts/emulator/beam/erl_async.c
index 91b64411d4..2dc7237f7c 100644
--- a/erts/emulator/beam/erl_async.c
+++ b/erts/emulator/beam/erl_async.c
@@ -24,10 +24,18 @@
#include "erl_sys_driver.h"
#include "global.h"
#include "erl_threads.h"
+#include "erl_thr_queue.h"
+#include "erl_async.h"
+
+#define ERTS_MAX_ASYNC_READY_CALLS_IN_SEQ 20
+
+#define ERTS_ASYNC_PRINT_JOB 0
+
+#if !defined(ERTS_SMP) && defined(USE_THREADS) && !ERTS_USE_ASYNC_READY_Q
+# error "Need async ready queue in non-smp case"
+#endif
typedef struct _erl_async {
- struct _erl_async* next;
- struct _erl_async* prev;
DE_Handle* hndl; /* The DE_Handle is needed when port is gone */
Eterm port;
long async_id;
@@ -35,345 +43,498 @@ typedef struct _erl_async {
ErlDrvPDL pdl;
void (*async_invoke)(void*);
void (*async_free)(void*);
-} ErlAsync;
+#if ERTS_USE_ASYNC_READY_Q
+ Uint sched_id;
+ union {
+ ErtsThrQPrepEnQ_t *prep_enq;
+ ErtsThrQFinDeQ_t fin_deq;
+ } q;
+#endif
+} ErtsAsync;
+
+#if ERTS_USE_ASYNC_READY_Q
+
+/*
+ * We can do without the enqueue mutex since it isn't needed for
+ * thread safety. Its only purpose is to put async threads to sleep
+ * during a blast of ready async jobs. This in order to reduce
+ * contention on the enqueue end of the async ready queues. During
+ * such a blast without the enqueue mutex much cpu time is consumed
+ * by the async threads without them doing much progress which in turn
+ * slow down progress of scheduler threads.
+ */
+#define ERTS_USE_ASYNC_READY_ENQ_MTX 1
+
+#if ERTS_USE_ASYNC_READY_ENQ_MTX
typedef struct {
- erts_mtx_t mtx;
- erts_cnd_t cv;
- erts_tid_t thr;
- int len;
-#ifndef ERTS_SMP
- int hndl;
+ erts_mtx_t enq_mtx;
+} ErtsAsyncReadyQXData;
+
#endif
- ErlAsync* head;
- ErlAsync* tail;
-#ifdef ERTS_ENABLE_LOCK_CHECK
- int no;
+
+typedef struct {
+#if ERTS_USE_ASYNC_READY_ENQ_MTX
+ union {
+ ErtsAsyncReadyQXData data;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(
+ sizeof(ErtsAsyncReadyQXData))];
+ } x;
#endif
-} AsyncQueue;
+ ErtsThrQ_t thr_q;
+ ErtsThrQFinDeQ_t fin_deq;
+} ErtsAsyncReadyQ;
-static erts_smp_spinlock_t async_id_lock;
-static long async_id = 0;
+typedef union {
+ ErtsAsyncReadyQ arq;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsAsyncReadyQ))];
+} ErtsAlgndAsyncReadyQ;
-#ifndef ERTS_SMP
+#endif /* ERTS_USE_ASYNC_READY_Q */
-erts_mtx_t async_ready_mtx;
-static ErlAsync* async_ready_list = NULL;
+typedef struct {
+ ErtsThrQ_t thr_q;
+ erts_tid_t thr_id;
+} ErtsAsyncQ;
+
+typedef union {
+ ErtsAsyncQ aq;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsAsyncQ))];
+} ErtsAlgndAsyncQ;
+typedef struct {
+ int no_initialized;
+ erts_mtx_t mtx;
+ erts_cnd_t cnd;
+ erts_atomic_t id;
+} ErtsAsyncInit;
+
+typedef struct {
+ union {
+ ErtsAsyncInit data;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsAsyncInit))];
+ } init;
+ ErtsAlgndAsyncQ *queue;
+#if ERTS_USE_ASYNC_READY_Q
+ ErtsAlgndAsyncReadyQ *ready_queue;
#endif
+} ErtsAsyncData;
-/*
-** Initialize worker threads (if supported)
-*/
+int erts_async_max_threads; /* Initialized by erl_init.c */
+int erts_async_thread_suggested_stack_size; /* Initialized by erl_init.c */
-/* Detach from driver */
-static void async_detach(DE_Handle* dh)
-{
- return;
-}
+static ErtsAsyncData *async;
+#ifndef USE_THREADS
-#ifdef USE_THREADS
+void
+erts_init_async(void)
+{
-static AsyncQueue* async_q;
+}
-static void* async_main(void*);
-static void async_add(ErlAsync*, AsyncQueue*);
+#else
-#ifndef ERTS_SMP
-typedef struct ErtsAsyncReadyCallback_ ErtsAsyncReadyCallback;
-struct ErtsAsyncReadyCallback_ {
- struct ErtsAsyncReadyCallback_ *next;
- void (*callback)(void);
-};
+static void *async_main(void *);
-static ErtsAsyncReadyCallback *callbacks;
-static int async_handle;
+static ERTS_INLINE ErtsAsyncQ *
+async_q(int i)
+{
+ return &async->queue[i].aq;
+}
+
+#if ERTS_USE_ASYNC_READY_Q
-int erts_register_async_ready_callback(void (*funcp)(void))
+static ERTS_INLINE ErtsAsyncReadyQ *
+async_ready_q(Uint sched_id)
{
- ErtsAsyncReadyCallback *cb = erts_alloc(ERTS_ALC_T_ARCALLBACK,
- sizeof(ErtsAsyncReadyCallback));
- cb->next = callbacks;
- cb->callback = funcp;
- erts_mtx_lock(&async_ready_mtx);
- callbacks = cb;
- erts_mtx_unlock(&async_ready_mtx);
- return async_handle;
+ return &async->ready_queue[((int)sched_id)-1].arq;
}
+
#endif
-int init_async(int hndl)
+void
+erts_init_async(void)
{
- erts_thr_opts_t thr_opts = ERTS_THR_OPTS_DEFAULT_INITER;
- AsyncQueue* q;
- int i;
+ async = NULL;
+ if (erts_async_max_threads > 0) {
+#if ERTS_USE_ASYNC_READY_Q
+ ErtsThrQInit_t qinit = ERTS_THR_Q_INIT_DEFAULT;
+#endif
+ erts_thr_opts_t thr_opts = ERTS_THR_OPTS_DEFAULT_INITER;
+ char *ptr;
+ size_t tot_size = 0;
+ int i;
+
+ tot_size += ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsAsyncData));
+ tot_size += sizeof(ErtsAlgndAsyncQ)*erts_async_max_threads;
+#if ERTS_USE_ASYNC_READY_Q
+ tot_size += sizeof(ErtsAlgndAsyncReadyQ)*erts_no_schedulers;
+#endif
- thr_opts.detached = 0;
- thr_opts.suggested_stack_size = erts_async_thread_suggested_stack_size;
-
-#ifndef ERTS_SMP
- callbacks = NULL;
- async_handle = hndl;
- erts_mtx_init(&async_ready_mtx, "async_ready");
- async_ready_list = NULL;
-#endif
-
- async_id = 0;
- erts_smp_spinlock_init(&async_id_lock, "async_id");
-
- async_q = q = (AsyncQueue*)
- (erts_async_max_threads
- ? erts_alloc(ERTS_ALC_T_ASYNC_Q,
- erts_async_max_threads * sizeof(AsyncQueue))
- : NULL);
- for (i = 0; i < erts_async_max_threads; i++) {
- q->head = NULL;
- q->tail = NULL;
- q->len = 0;
-#ifndef ERTS_SMP
- q->hndl = hndl;
-#endif
-#ifdef ERTS_ENABLE_LOCK_CHECK
- q->no = i;
-#endif
- erts_mtx_init(&q->mtx, "asyncq");
- erts_cnd_init(&q->cv);
- erts_thr_create(&q->thr, async_main, (void*)q, &thr_opts);
- q++;
- }
- return 0;
-}
+ ptr = erts_alloc_permanent_cache_aligned(ERTS_ALC_T_ASYNC_DATA,
+ tot_size);
+ async = (ErtsAsyncData *) ptr;
+ ptr += ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsAsyncData));
-int exit_async()
-{
- int i;
+ async->init.data.no_initialized = 0;
+ erts_mtx_init(&async->init.data.mtx, "async_init_mtx");
+ erts_cnd_init(&async->init.data.cnd);
+ erts_atomic_init_nob(&async->init.data.id, 0);
- /* terminate threads */
- for (i = 0; i < erts_async_max_threads; i++) {
- ErlAsync* a = (ErlAsync*) erts_alloc(ERTS_ALC_T_ASYNC,
- sizeof(ErlAsync));
- a->port = NIL;
- async_add(a, &async_q[i]);
- }
+ async->queue = (ErtsAlgndAsyncQ *) ptr;
+ ptr += sizeof(ErtsAlgndAsyncQ)*erts_async_max_threads;
- for (i = 0; i < erts_async_max_threads; i++) {
- erts_thr_join(async_q[i].thr, NULL);
- erts_mtx_destroy(&async_q[i].mtx);
- erts_cnd_destroy(&async_q[i].cv);
- }
-#ifndef ERTS_SMP
- erts_mtx_destroy(&async_ready_mtx);
+#if ERTS_USE_ASYNC_READY_Q
+
+ qinit.live.queue = ERTS_THR_Q_LIVE_LONG;
+ qinit.live.objects = ERTS_THR_Q_LIVE_SHORT;
+ qinit.notify = erts_notify_check_async_ready_queue;
+
+ async->ready_queue = (ErtsAlgndAsyncReadyQ *) ptr;
+ ptr += sizeof(ErtsAlgndAsyncReadyQ)*erts_no_schedulers;
+
+ for (i = 1; i <= erts_no_schedulers; i++) {
+ ErtsAsyncReadyQ *arq = async_ready_q(i);
+#if ERTS_USE_ASYNC_READY_ENQ_MTX
+ erts_mtx_init(&arq->x.data.enq_mtx, "async_enq_mtx");
#endif
- if (async_q)
- erts_free(ERTS_ALC_T_ASYNC_Q, (void *) async_q);
- return 0;
+ erts_thr_q_finalize_dequeue_state_init(&arq->fin_deq);
+ qinit.arg = (void *) (SWord) i;
+ erts_thr_q_initialize(&arq->thr_q, &qinit);
+ }
+
+#endif
+
+ /* Create async threads... */
+
+ thr_opts.detached = 0;
+ thr_opts.suggested_stack_size
+ = erts_async_thread_suggested_stack_size;
+
+ for (i = 0; i < erts_async_max_threads; i++) {
+ ErtsAsyncQ *aq = async_q(i);
+ erts_thr_create(&aq->thr_id, async_main, (void*) aq, &thr_opts);
+ }
+
+ /* Wait for async threads to initialize... */
+
+ erts_mtx_lock(&async->init.data.mtx);
+ while (async->init.data.no_initialized != erts_async_max_threads)
+ erts_cnd_wait(&async->init.data.cnd, &async->init.data.mtx);
+ erts_mtx_unlock(&async->init.data.mtx);
+
+ erts_mtx_destroy(&async->init.data.mtx);
+ erts_cnd_destroy(&async->init.data.cnd);
+
+ }
}
+#if ERTS_USE_ASYNC_READY_Q
-static void async_add(ErlAsync* a, AsyncQueue* q)
+void *
+erts_get_async_ready_queue(Uint sched_id)
+{
+ return (void *) async ? async_ready_q(sched_id) : NULL;
+}
+
+#endif
+
+static ERTS_INLINE void async_add(ErtsAsync *a, ErtsAsyncQ* q)
{
if (is_internal_port(a->port)) {
- ERTS_LC_ASSERT(erts_drvportid2port(a->port));
+#if ERTS_USE_ASYNC_READY_Q
+ ErtsAsyncReadyQ *arq = async_ready_q(a->sched_id);
+ a->q.prep_enq = erts_thr_q_prepare_enqueue(&arq->thr_q);
+#endif
/* make sure the driver will stay around */
- driver_lock_driver(internal_port_index(a->port));
+ if (a->hndl)
+ erts_ddll_reference_referenced_driver(a->hndl);
}
- erts_mtx_lock(&q->mtx);
+#if ERTS_ASYNC_PRINT_JOB
+ erts_fprintf(stderr, "-> %ld\n", a->async_id);
+#endif
- if (q->len == 0) {
- q->head = a;
- q->tail = a;
- q->len = 1;
- erts_cnd_signal(&q->cv);
- }
- else { /* no need to signal (since the worker is working) */
- a->next = q->head;
- q->head->prev = a;
- q->head = a;
- q->len++;
- }
- erts_mtx_unlock(&q->mtx);
+ erts_thr_q_enqueue(&q->thr_q, a);
}
-static ErlAsync* async_get(AsyncQueue* q)
+static ERTS_INLINE ErtsAsync *async_get(ErtsThrQ_t *q,
+ erts_tse_t *tse,
+ ErtsThrQPrepEnQ_t **prep_enq)
{
- ErlAsync* a;
+#if ERTS_USE_ASYNC_READY_Q
+ int saved_fin_deq = 0;
+ ErtsThrQFinDeQ_t fin_deq;
+#endif
- erts_mtx_lock(&q->mtx);
- while((a = q->tail) == NULL) {
- erts_cnd_wait(&q->cv, &q->mtx);
- }
+ while (1) {
+ ErtsAsync *a = (ErtsAsync *) erts_thr_q_dequeue(q);
+ if (a) {
+
+#if ERTS_USE_ASYNC_READY_Q
+ *prep_enq = a->q.prep_enq;
+ erts_thr_q_get_finalize_dequeue_data(q, &a->q.fin_deq);
+ if (saved_fin_deq)
+ erts_thr_q_append_finalize_dequeue_data(&a->q.fin_deq, &fin_deq);
+#endif
+
+ return a;
+ }
+
+ if (ERTS_THR_Q_DIRTY != erts_thr_q_clean(q)) {
+ ErtsThrQFinDeQ_t tmp_fin_deq;
+
+ erts_tse_reset(tse);
+
+#if ERTS_USE_ASYNC_READY_Q
+ chk_fin_deq:
+ if (erts_thr_q_get_finalize_dequeue_data(q, &tmp_fin_deq)) {
+ if (!saved_fin_deq) {
+ erts_thr_q_finalize_dequeue_state_init(&fin_deq);
+ saved_fin_deq = 1;
+ }
+ erts_thr_q_append_finalize_dequeue_data(&fin_deq,
+ &tmp_fin_deq);
+ }
+#endif
+
+ switch (erts_thr_q_inspect(q, 1)) {
+ case ERTS_THR_Q_DIRTY:
+ break;
#ifdef ERTS_SMP
- ASSERT(a && q->tail == a);
+ case ERTS_THR_Q_NEED_THR_PRGR: {
+ ErtsThrPrgrVal prgr = erts_thr_q_need_thr_progress(q);
+ erts_thr_progress_wakeup(NULL, prgr);
+ /*
+ * We do no dequeue finalizing in hope that a new async
+ * job will arrive before we are woken due to thread
+ * progress...
+ */
+ erts_tse_wait(tse);
+ break;
+ }
#endif
- if (q->head == q->tail) {
- q->head = q->tail = NULL;
- q->len = 0;
- }
- else {
- q->tail->prev->next = NULL;
- q->tail = q->tail->prev;
- q->len--;
+ case ERTS_THR_Q_CLEAN:
+
+#if ERTS_USE_ASYNC_READY_Q
+ if (saved_fin_deq) {
+ if (erts_thr_q_finalize_dequeue(&fin_deq))
+ goto chk_fin_deq;
+ else
+ saved_fin_deq = 0;
+ }
+#endif
+
+ erts_tse_wait(tse);
+ break;
+
+ default:
+ ASSERT(0);
+ break;
+ }
+
+ }
}
- erts_mtx_unlock(&q->mtx);
- return a;
}
-
-static int async_del(long id)
+static ERTS_INLINE void call_async_ready(ErtsAsync *a)
{
- int i;
- /* scan all queue for an entry with async_id == 'id' */
-
- for (i = 0; i < erts_async_max_threads; i++) {
- ErlAsync* a;
- erts_mtx_lock(&async_q[i].mtx);
-
- a = async_q[i].head;
- while(a != NULL) {
- if (a->async_id == id) {
- if (a->prev != NULL)
- a->prev->next = a->next;
- else
- async_q[i].head = a->next;
- if (a->next != NULL)
- a->next->prev = a->prev;
- else
- async_q[i].tail = a->prev;
- async_q[i].len--;
- erts_mtx_unlock(&async_q[i].mtx);
- if (a->async_free != NULL)
- a->async_free(a->async_data);
- async_detach(a->hndl);
- erts_free(ERTS_ALC_T_ASYNC, a);
- return 1;
- }
- a = a->next;
+ Port *p = erts_id2port_sflgs(a->port,
+ NULL,
+ 0,
+ ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP);
+ if (!p) {
+ if (a->async_free)
+ a->async_free(a->async_data);
+ }
+ else {
+ if (async_ready(p, a->async_data)) {
+ if (a->async_free)
+ a->async_free(a->async_data);
}
- erts_mtx_unlock(&async_q[i].mtx);
+ erts_port_release(p);
}
- return 0;
+ if (a->hndl)
+ erts_ddll_dereference_driver(a->hndl);
}
-static void* async_main(void* arg)
+static ERTS_INLINE void async_reply(ErtsAsync *a, ErtsThrQPrepEnQ_t *prep_enq)
{
- AsyncQueue* q = (AsyncQueue*) arg;
+#if ERTS_USE_ASYNC_READY_Q
+ ErtsAsyncReadyQ *arq;
-#ifdef ERTS_ENABLE_LOCK_CHECK
- {
- char buf[27];
- erts_snprintf(&buf[0], 27, "async %d", q->no);
- erts_lc_set_thread_name(&buf[0]);
- }
+ if (a->pdl)
+ driver_pdl_dec_refc(a->pdl);
+
+#if ERTS_ASYNC_PRINT_JOB
+ erts_fprintf(stderr, "=>> %ld\n", a->async_id);
#endif
- while(1) {
- ErlAsync* a = async_get(q);
+ arq = async_ready_q(a->sched_id);
- if (a->port == NIL) { /* TIME TO DIE SIGNAL */
- erts_free(ERTS_ALC_T_ASYNC, (void *) a);
- break;
- }
- else {
- (*a->async_invoke)(a->async_data);
- /* Major problem if the code for async_invoke
- or async_free is removed during a blocking operation */
+#if ERTS_USE_ASYNC_READY_ENQ_MTX
+ erts_mtx_lock(&arq->x.data.enq_mtx);
+#endif
+
+ erts_thr_q_enqueue_prepared(&arq->thr_q, (void *) a, prep_enq);
+
+#if ERTS_USE_ASYNC_READY_ENQ_MTX
+ erts_mtx_unlock(&arq->x.data.enq_mtx);
+#endif
+
+#else /* ERTS_USE_ASYNC_READY_Q */
+
+ call_async_ready(a);
+ if (a->pdl)
+ driver_pdl_dec_refc(a->pdl);
+ erts_free(ERTS_ALC_T_ASYNC, (void *) a);
+
+#endif /* ERTS_USE_ASYNC_READY_Q */
+}
+
+
+static void
+async_wakeup(void *vtse)
+{
+ erts_tse_set((erts_tse_t *) vtse);
+}
+
+static erts_tse_t *async_thread_init(ErtsAsyncQ *aq)
+{
+ ErtsThrQInit_t qinit = ERTS_THR_Q_INIT_DEFAULT;
+ erts_tse_t *tse = erts_tse_fetch();
#ifdef ERTS_SMP
- {
- Port *p;
- p = erts_id2port_sflgs(a->port,
- NULL,
- 0,
- ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP);
- if (!p) {
- if (a->async_free)
- (*a->async_free)(a->async_data);
- }
- else {
- if (async_ready(p, a->async_data)) {
- if (a->async_free)
- (*a->async_free)(a->async_data);
- }
- async_detach(a->hndl);
- erts_port_release(p);
- }
- if (a->pdl) {
- driver_pdl_dec_refc(a->pdl);
- }
- erts_free(ERTS_ALC_T_ASYNC, (void *) a);
- }
-#else
- if (a->pdl) {
- driver_pdl_dec_refc(a->pdl);
- }
- erts_mtx_lock(&async_ready_mtx);
- a->next = async_ready_list;
- async_ready_list = a;
- erts_mtx_unlock(&async_ready_mtx);
- sys_async_ready(q->hndl);
+ ErtsThrPrgrCallbacks callbacks;
+
+ callbacks.arg = (void *) tse;
+ callbacks.wakeup = async_wakeup;
+ callbacks.prepare_wait = NULL;
+ callbacks.wait = NULL;
+
+ erts_thr_progress_register_unmanaged_thread(&callbacks);
#endif
- }
- }
- return NULL;
+ qinit.live.queue = ERTS_THR_Q_LIVE_LONG;
+ qinit.live.objects = ERTS_THR_Q_LIVE_SHORT;
+ qinit.arg = (void *) tse;
+ qinit.notify = async_wakeup;
+#if ERTS_USE_ASYNC_READY_Q
+ qinit.auto_finalize_dequeue = 0;
+#endif
+
+ erts_thr_q_initialize(&aq->thr_q, &qinit);
+
+ /* Inform main thread that we are done initializing... */
+ erts_mtx_lock(&async->init.data.mtx);
+ async->init.data.no_initialized++;
+ erts_cnd_signal(&async->init.data.cnd);
+ erts_mtx_unlock(&async->init.data.mtx);
+
+ return tse;
}
+static void *async_main(void* arg)
+{
+ ErtsAsyncQ *aq = (ErtsAsyncQ *) arg;
+ erts_tse_t *tse = async_thread_init(aq);
+
+ while (1) {
+ ErtsThrQPrepEnQ_t *prep_enq;
+ ErtsAsync *a = async_get(&aq->thr_q, tse, &prep_enq);
+ if (is_nil(a->port))
+ break; /* Time to die */
+#if ERTS_ASYNC_PRINT_JOB
+ erts_fprintf(stderr, "<- %ld\n", a->async_id);
#endif
-#ifndef ERTS_SMP
+ a->async_invoke(a->async_data);
+
+ async_reply(a, prep_enq);
+ }
+
+ return NULL;
+}
+
+#endif /* USE_THREADS */
-int check_async_ready(void)
+void
+erts_exit_flush_async(void)
{
#ifdef USE_THREADS
- ErtsAsyncReadyCallback *cbs;
+ int i;
+ ErtsAsync a;
+ a.port = NIL;
+ /*
+ * Terminate threads in order to flush queues. We do not
+ * bother to clean everything up since we are about to
+ * terminate the runtime system and a cleanup would only
+ * delay the termination.
+ */
+ for (i = 0; i < erts_async_max_threads; i++)
+ async_add(&a, async_q(i));
+ for (i = 0; i < erts_async_max_threads; i++)
+ erts_thr_join(async->queue[i].aq.thr_id, NULL);
#endif
- ErlAsync* a;
- int count = 0;
+}
- erts_mtx_lock(&async_ready_mtx);
- a = async_ready_list;
- async_ready_list = NULL;
-#ifdef USE_THREADS
- cbs = callbacks;
-#endif
- erts_mtx_unlock(&async_ready_mtx);
-
- while(a != NULL) {
- ErlAsync* a_next = a->next;
- /* Every port not dead */
- Port *p = erts_id2port_sflgs(a->port,
- NULL,
- 0,
- ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP);
- if (!p) {
- if (a->async_free)
- (*a->async_free)(a->async_data);
- }
- else {
- count++;
- if (async_ready(p, a->async_data)) {
- if (a->async_free != NULL)
- (*a->async_free)(a->async_data);
- }
- async_detach(a->hndl);
- erts_port_release(p);
+#if defined(USE_THREADS) && ERTS_USE_ASYNC_READY_Q
+
+int erts_check_async_ready(void *varq)
+{
+ ErtsAsyncReadyQ *arq = (ErtsAsyncReadyQ *) varq;
+ int res = 1;
+ int i;
+
+ for (i = 0; i < ERTS_MAX_ASYNC_READY_CALLS_IN_SEQ; i++) {
+ ErtsAsync *a = (ErtsAsync *) erts_thr_q_dequeue(&arq->thr_q);
+ if (!a) {
+ res = 0;
+ break;
}
+
+#if ERTS_ASYNC_PRINT_JOB
+ erts_fprintf(stderr, "<<= %ld\n", a->async_id);
+#endif
+ erts_thr_q_append_finalize_dequeue_data(&arq->fin_deq, &a->q.fin_deq);
+ call_async_ready(a);
erts_free(ERTS_ALC_T_ASYNC, (void *) a);
- a = a_next;
}
-#ifdef USE_THREADS
- for (; cbs; cbs = cbs->next)
- (*cbs->callback)();
-#endif
- return count;
+
+ erts_thr_q_finalize_dequeue(&arq->fin_deq);
+
+ return res;
}
+int erts_async_ready_clean(void *varq, void *val)
+{
+ ErtsAsyncReadyQ *arq = (ErtsAsyncReadyQ *) varq;
+ ErtsThrQCleanState_t cstate;
+
+ cstate = erts_thr_q_clean(&arq->thr_q);
+
+ if (erts_thr_q_finalize_dequeue(&arq->fin_deq))
+ return ERTS_ASYNC_READY_DIRTY;
+
+ switch (cstate) {
+ case ERTS_THR_Q_DIRTY:
+ return ERTS_ASYNC_READY_DIRTY;
+#ifdef ERTS_SMP
+ case ERTS_THR_Q_NEED_THR_PRGR:
+ *((ErtsThrPrgrVal *) val)
+ = erts_thr_q_need_thr_progress(&arq->thr_q);
+ return ERTS_ASYNC_READY_NEED_THR_PRGR;
#endif
+ case ERTS_THR_Q_CLEAN:
+ break;
+ }
+ return ERTS_ASYNC_READY_CLEAN;
+}
+#endif
/*
** Schedule async_invoke on a worker thread
@@ -393,19 +554,29 @@ long driver_async(ErlDrvPort ix, unsigned int* key,
void (*async_invoke)(void*), void* async_data,
void (*async_free)(void*))
{
- ErlAsync* a = (ErlAsync*) erts_alloc(ERTS_ALC_T_ASYNC, sizeof(ErlAsync));
- Port* prt = erts_drvport2port(ix);
+ ErtsAsync* a;
+ Port* prt;
long id;
unsigned int qix;
+#if ERTS_USE_ASYNC_READY_Q
+ Uint sched_id;
+ sched_id = erts_get_scheduler_id();
+ if (!sched_id)
+ sched_id = 1;
+#endif
+ prt = erts_drvport2port(ix);
if (!prt)
return -1;
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
- a->next = NULL;
- a->prev = NULL;
+ a = (ErtsAsync*) erts_alloc(ERTS_ALC_T_ASYNC, sizeof(ErtsAsync));
+
+#if ERTS_USE_ASYNC_READY_Q
+ a->sched_id = sched_id;
+#endif
a->hndl = (DE_Handle*)prt->drv_ptr->handle;
a->port = prt->id;
a->pdl = NULL;
@@ -413,12 +584,16 @@ long driver_async(ErlDrvPort ix, unsigned int* key,
a->async_invoke = async_invoke;
a->async_free = async_free;
- erts_smp_spin_lock(&async_id_lock);
- async_id = (async_id + 1) & 0x7fffffff;
- if (async_id == 0)
- async_id++;
- id = async_id;
- erts_smp_spin_unlock(&async_id_lock);
+ if (!async)
+ id = 0;
+ else {
+ do {
+ id = erts_atomic_inc_read_nob(&async->init.data.id);
+ } while (id == 0);
+ if (id < 0)
+ id *= -1;
+ ASSERT(id > 0);
+ }
a->async_id = id;
@@ -437,7 +612,7 @@ long driver_async(ErlDrvPort ix, unsigned int* key,
driver_pdl_inc_refc(prt->port_data_lock);
a->pdl = prt->port_data_lock;
}
- async_add(a, &async_q[qix]);
+ async_add(a, async_q(qix));
return id;
}
#endif
@@ -455,10 +630,16 @@ long driver_async(ErlDrvPort ix, unsigned int* key,
int driver_async_cancel(unsigned int id)
{
-#ifdef USE_THREADS
- if (erts_async_max_threads > 0)
- return async_del(id);
-#endif
+ /*
+ * Not supported anymore. Always fail (which is backward
+ * compatible).
+ *
+ * This functionality could be implemented again. However,
+ * it is (and always has been) completely useless since
+ * it doesn't give you any guarantees whatsoever. The user
+ * needs to (and always have had to) synchronize in his/her
+ * own code in order to get any guarantees.
+ */
return 0;
}
diff --git a/erts/emulator/beam/erl_async.h b/erts/emulator/beam/erl_async.h
new file mode 100644
index 0000000000..95374a8fc9
--- /dev/null
+++ b/erts/emulator/beam/erl_async.h
@@ -0,0 +1,66 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#ifndef ERL_ASYNC_H__
+#define ERL_ASYNC_H__
+
+#define ERTS_MAX_NO_OF_ASYNC_THREADS 1024
+extern int erts_async_max_threads;
+#define ERTS_ASYNC_THREAD_MIN_STACK_SIZE 16 /* Kilo words */
+#define ERTS_ASYNC_THREAD_MAX_STACK_SIZE 8192 /* Kilo words */
+extern int erts_async_thread_suggested_stack_size;
+
+#ifdef USE_THREADS
+
+#ifdef ERTS_SMP
+/*
+ * With smp support we can choose to have, or not to
+ * have an async ready queue.
+ */
+#define ERTS_USE_ASYNC_READY_Q 1
+#endif
+
+#ifndef ERTS_SMP
+/* In non-smp case we *need* the async ready queue */
+# undef ERTS_USE_ASYNC_READY_Q
+# define ERTS_USE_ASYNC_READY_Q 1
+#endif
+
+#ifndef ERTS_USE_ASYNC_READY_Q
+# define ERTS_USE_ASYNC_READY_Q 0
+#endif
+
+#if ERTS_USE_ASYNC_READY_Q
+int erts_check_async_ready(void *);
+int erts_async_ready_clean(void *, void *);
+void *erts_get_async_ready_queue(Uint sched_id);
+#define ERTS_ASYNC_READY_CLEAN 0
+#define ERTS_ASYNC_READY_DIRTY 1
+#ifdef ERTS_SMP
+#define ERTS_ASYNC_READY_NEED_THR_PRGR 2
+#endif
+#endif /* ERTS_USE_ASYNC_READY_Q */
+
+#endif /* USE_THREADS */
+
+void erts_init_async(void);
+void erts_exit_flush_async(void);
+
+
+#endif /* ERL_ASYNC_H__ */
diff --git a/erts/emulator/beam/erl_bestfit_alloc.c b/erts/emulator/beam/erl_bestfit_alloc.c
index d9b1170a3d..c50fdeb4e8 100644
--- a/erts/emulator/beam/erl_bestfit_alloc.c
+++ b/erts/emulator/beam/erl_bestfit_alloc.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2003-2009. All Rights Reserved.
+ * Copyright Ericsson AB 2003-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -161,14 +161,18 @@ erts_bfalc_start(BFAllctr_t *bfallctr,
BFAllctrInit_t *bfinit,
AllctrInit_t *init)
{
- BFAllctr_t nulled_state = {{0}};
- /* {{0}} is used instead of {0}, in order to avoid (an incorrect) gcc
- warning. gcc warns if {0} is used as initializer of a struct when
- the first member is a struct (not if, for example, the third member
- is a struct). */
+ struct {
+ int dummy;
+ BFAllctr_t allctr;
+ } zero = {0};
+ /* The struct with a dummy element first is used in order to avoid (an
+ incorrect) gcc warning. gcc warns if {0} is used as initializer of
+ a struct when the first member is a struct (not if, for example,
+ the third member is a struct). */
+
Allctr_t *allctr = (Allctr_t *) bfallctr;
- sys_memcpy((void *) bfallctr, (void *) &nulled_state, sizeof(BFAllctr_t));
+ sys_memcpy((void *) bfallctr, (void *) &zero.allctr, sizeof(BFAllctr_t));
bfallctr->address_order = bfinit->ao;
@@ -979,6 +983,7 @@ erts_bfalc_test(unsigned long op, unsigned long a1, unsigned long a2)
case 0x205: return (unsigned long) ((RBTreeList_t *) a1)->next;
case 0x206: return (unsigned long) IS_BLACK((RBTree_t *) a1);
case 0x207: return (unsigned long) IS_TREE_NODE((RBTree_t *) a1);
+ case 0x208: return (unsigned long) 0; /* IS_AOFF */
default: ASSERT(0); return ~((unsigned long) 0);
}
}
diff --git a/erts/emulator/beam/erl_bestfit_alloc.h b/erts/emulator/beam/erl_bestfit_alloc.h
index faa2d9742e..0c29662852 100644
--- a/erts/emulator/beam/erl_bestfit_alloc.h
+++ b/erts/emulator/beam/erl_bestfit_alloc.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2003-2009. All Rights Reserved.
+ * Copyright Ericsson AB 2003-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
diff --git a/erts/emulator/beam/erl_bif_binary.c b/erts/emulator/beam/erl_bif_binary.c
index 684fa5d12f..6d022e0d11 100644
--- a/erts/emulator/beam/erl_bif_binary.c
+++ b/erts/emulator/beam/erl_bif_binary.c
@@ -65,6 +65,10 @@ static Export binary_copy_trap_export;
static BIF_RETTYPE binary_copy_trap(BIF_ALIST_2);
static Uint max_loop_limit;
+static BIF_RETTYPE
+binary_match(Process *p, Eterm arg1, Eterm arg2, Eterm arg3);
+static BIF_RETTYPE
+binary_matches(Process *p, Eterm arg1, Eterm arg2, Eterm arg3);
void erts_init_bif_binary(void)
{
@@ -1399,6 +1403,12 @@ static BIF_RETTYPE binary_matches_trap(BIF_ALIST_3)
BIF_RETTYPE binary_match_3(BIF_ALIST_3)
{
+ return binary_match(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
+}
+
+static BIF_RETTYPE
+binary_match(Process *p, Eterm arg1, Eterm arg2, Eterm arg3)
+{
Uint hsstart;
Uint hsend;
Eterm *tp;
@@ -1408,17 +1418,17 @@ BIF_RETTYPE binary_match_3(BIF_ALIST_3)
int runres;
Eterm result;
- if (is_not_binary(BIF_ARG_1)) {
+ if (is_not_binary(arg1)) {
goto badarg;
}
- if (parse_match_opts_list(BIF_ARG_3,BIF_ARG_1,&hsstart,&hsend)) {
+ if (parse_match_opts_list(arg3,arg1,&hsstart,&hsend)) {
goto badarg;
}
if (hsend == 0) {
BIF_RET(am_nomatch);
}
- if (is_tuple(BIF_ARG_2)) {
- tp = tuple_val(BIF_ARG_2);
+ if (is_tuple(arg2)) {
+ tp = tuple_val(arg2);
if (arityval(*tp) != 2 || is_not_atom(tp[1])) {
goto badarg;
}
@@ -1437,13 +1447,13 @@ BIF_RETTYPE binary_match_3(BIF_ALIST_3)
goto badarg;
}
bin_term = tp[2];
- } else if (do_binary_match_compile(BIF_ARG_2,&type,&bin)) {
+ } else if (do_binary_match_compile(arg2,&type,&bin)) {
goto badarg;
}
- runres = do_binary_match(BIF_P,BIF_ARG_1,hsstart,hsend,type,bin,NIL,&result);
+ runres = do_binary_match(p,arg1,hsstart,hsend,type,bin,NIL,&result);
if (runres == DO_BIN_MATCH_RESTART && bin_term == NIL) {
- Eterm *hp = HAlloc(BIF_P, PROC_BIN_SIZE);
- bin_term = erts_mk_magic_binary_term(&hp, &MSO(BIF_P), bin);
+ Eterm *hp = HAlloc(p, PROC_BIN_SIZE);
+ bin_term = erts_mk_magic_binary_term(&hp, &MSO(p), bin);
} else if (bin_term == NIL) {
erts_bin_free(bin);
}
@@ -1451,17 +1461,23 @@ BIF_RETTYPE binary_match_3(BIF_ALIST_3)
case DO_BIN_MATCH_OK:
BIF_RET(result);
case DO_BIN_MATCH_RESTART:
- BUMP_ALL_REDS(BIF_P);
- BIF_TRAP3(&binary_match_trap_export, BIF_P, BIF_ARG_1, result, bin_term);
+ BUMP_ALL_REDS(p);
+ BIF_TRAP3(&binary_match_trap_export, p, arg1, result, bin_term);
default:
goto badarg;
}
badarg:
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
BIF_RETTYPE binary_matches_3(BIF_ALIST_3)
{
+ return binary_matches(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
+}
+
+static BIF_RETTYPE
+binary_matches(Process *p, Eterm arg1, Eterm arg2, Eterm arg3)
+{
Uint hsstart, hsend;
Eterm *tp;
Eterm type;
@@ -1470,17 +1486,17 @@ BIF_RETTYPE binary_matches_3(BIF_ALIST_3)
int runres;
Eterm result;
- if (is_not_binary(BIF_ARG_1)) {
+ if (is_not_binary(arg1)) {
goto badarg;
}
- if (parse_match_opts_list(BIF_ARG_3,BIF_ARG_1,&hsstart,&hsend)) {
+ if (parse_match_opts_list(arg3,arg1,&hsstart,&hsend)) {
goto badarg;
}
if (hsend == 0) {
BIF_RET(NIL);
}
- if (is_tuple(BIF_ARG_2)) {
- tp = tuple_val(BIF_ARG_2);
+ if (is_tuple(arg2)) {
+ tp = tuple_val(arg2);
if (arityval(*tp) != 2 || is_not_atom(tp[1])) {
goto badarg;
}
@@ -1499,14 +1515,14 @@ BIF_RETTYPE binary_matches_3(BIF_ALIST_3)
goto badarg;
}
bin_term = tp[2];
- } else if (do_binary_match_compile(BIF_ARG_2,&type,&bin)) {
+ } else if (do_binary_match_compile(arg2,&type,&bin)) {
goto badarg;
}
- runres = do_binary_matches(BIF_P,BIF_ARG_1,hsstart,hsend,type,bin,
+ runres = do_binary_matches(p,arg1,hsstart,hsend,type,bin,
NIL,&result);
if (runres == DO_BIN_MATCH_RESTART && bin_term == NIL) {
- Eterm *hp = HAlloc(BIF_P, PROC_BIN_SIZE);
- bin_term = erts_mk_magic_binary_term(&hp, &MSO(BIF_P), bin);
+ Eterm *hp = HAlloc(p, PROC_BIN_SIZE);
+ bin_term = erts_mk_magic_binary_term(&hp, &MSO(p), bin);
} else if (bin_term == NIL) {
erts_bin_free(bin);
}
@@ -1514,26 +1530,26 @@ BIF_RETTYPE binary_matches_3(BIF_ALIST_3)
case DO_BIN_MATCH_OK:
BIF_RET(result);
case DO_BIN_MATCH_RESTART:
- BUMP_ALL_REDS(BIF_P);
- BIF_TRAP3(&binary_matches_trap_export, BIF_P, BIF_ARG_1, result,
+ BUMP_ALL_REDS(p);
+ BIF_TRAP3(&binary_matches_trap_export, p, arg1, result,
bin_term);
default:
goto badarg;
}
badarg:
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
BIF_RETTYPE binary_match_2(BIF_ALIST_2)
{
- return binary_match_3(BIF_P,BIF_ARG_1,BIF_ARG_2,((Eterm) 0));
+ return binary_match(BIF_P,BIF_ARG_1,BIF_ARG_2,((Eterm) 0));
}
BIF_RETTYPE binary_matches_2(BIF_ALIST_2)
{
- return binary_matches_3(BIF_P,BIF_ARG_1,BIF_ARG_2,((Eterm) 0));
+ return binary_matches(BIF_P,BIF_ARG_1,BIF_ARG_2,((Eterm) 0));
}
diff --git a/erts/emulator/beam/erl_bif_ddll.c b/erts/emulator/beam/erl_bif_ddll.c
index 9631fb50db..b2d5722e9b 100644
--- a/erts/emulator/beam/erl_bif_ddll.c
+++ b/erts/emulator/beam/erl_bif_ddll.c
@@ -142,9 +142,11 @@ static void ddll_no_more_references(void *vdh);
* really load and add as LOADED {ok,loaded} {ok,pending_driver}
* {error, permanent} {error,load_error()}
*/
-BIF_RETTYPE erl_ddll_try_load_3(Process *p, Eterm path_term,
- Eterm name_term, Eterm options)
+BIF_RETTYPE erl_ddll_try_load_3(BIF_ALIST_3)
{
+ Eterm path_term = BIF_ARG_1;
+ Eterm name_term = BIF_ARG_2;
+ Eterm options = BIF_ARG_3;
char *path = NULL;
Uint path_len;
char *name = NULL;
@@ -236,7 +238,7 @@ BIF_RETTYPE erl_ddll_try_load_3(Process *p, Eterm path_term,
sys_strcpy(path+path_len,name);
#if DDLL_SMP
- erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
+ erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
lock_drv_list();
#endif
if ((drv = lookup_driver(name)) != NULL) {
@@ -247,7 +249,7 @@ BIF_RETTYPE erl_ddll_try_load_3(Process *p, Eterm path_term,
} else {
dh = drv->handle;
if (dh->status == ERL_DE_OK) {
- int is_last = is_last_user(dh,p);
+ int is_last = is_last_user(dh, BIF_P);
if (reload == 1 && !is_last) {
/*Want reload if no other users,
but there are others...*/
@@ -261,7 +263,8 @@ BIF_RETTYPE erl_ddll_try_load_3(Process *p, Eterm path_term,
soft_error_term = am_inconsistent;
goto soft_error;
}
- if ((old = find_proc_entry(dh, p, ERL_DE_PROC_LOADED)) ==
+ if ((old = find_proc_entry(dh, BIF_P,
+ ERL_DE_PROC_LOADED)) ==
NULL) {
soft_error_term = am_not_loaded_by_this_process;
goto soft_error;
@@ -272,7 +275,7 @@ BIF_RETTYPE erl_ddll_try_load_3(Process *p, Eterm path_term,
}
/* Reload requested and granted */
dereference_all_processes(dh);
- set_driver_reloading(dh, p, path, name, flags);
+ set_driver_reloading(dh, BIF_P, path, name, flags);
if (dh->flags & ERL_DE_FL_KILL_PORTS) {
kill_ports = 1;
}
@@ -286,7 +289,7 @@ BIF_RETTYPE erl_ddll_try_load_3(Process *p, Eterm path_term,
soft_error_term = am_inconsistent;
goto soft_error;
}
- add_proc_loaded(dh,p);
+ add_proc_loaded(dh, BIF_P);
erts_ddll_reference_driver(dh);
monitor = 0;
ok_term = mkatom("already_loaded");
@@ -308,7 +311,7 @@ BIF_RETTYPE erl_ddll_try_load_3(Process *p, Eterm path_term,
notify_all(dh, drv->name,
ERL_DE_PROC_AWAIT_UNLOAD, am_UP,
am_unload_cancelled);
- add_proc_loaded(dh,p);
+ add_proc_loaded(dh, BIF_P);
erts_ddll_reference_driver(dh);
monitor = 0;
ok_term = mkatom("already_loaded");
@@ -325,7 +328,8 @@ BIF_RETTYPE erl_ddll_try_load_3(Process *p, Eterm path_term,
goto soft_error;
}
/* Load of granted unload... */
- add_proc_loaded_deref(dh,p); /* Dont reference, will happen after reload */
+ /* Don't reference, will happen after reload */
+ add_proc_loaded_deref(dh, BIF_P);
++monitor;
ok_term = am_pending_driver;
} else { /* ERL_DE_PERMANENT */
@@ -345,7 +349,7 @@ BIF_RETTYPE erl_ddll_try_load_3(Process *p, Eterm path_term,
goto soft_error;
} else {
dh->flags = flags;
- add_proc_loaded(dh,p);
+ add_proc_loaded(dh, BIF_P);
first_ddll_reference(dh);
monitor = 0;
ok_term = mkatom("loaded");
@@ -369,7 +373,7 @@ BIF_RETTYPE erl_ddll_try_load_3(Process *p, Eterm path_term,
if (!(prt->status & FREE_PORT_FLAGS) &&
prt->drv_ptr->handle == dh) {
#if DDLL_SMP
- erts_smp_atomic_inc(&prt->refc);
+ erts_smp_atomic_inc_nob(&prt->refc);
/* Extremely rare spinlock */
while(prt->status & ERTS_PORT_SFLG_INITIALIZING) {
erts_smp_port_state_unlock(prt);
@@ -397,18 +401,18 @@ BIF_RETTYPE erl_ddll_try_load_3(Process *p, Eterm path_term,
#if DDLL_SMP
erts_ddll_reference_driver(dh);
unlock_drv_list();
- erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
+ erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
lock_drv_list();
erts_ddll_dereference_driver(dh);
#endif
- p->flags |= F_USING_DDLL;
+ BIF_P->flags |= F_USING_DDLL;
if (monitor) {
- Eterm mref = add_monitor(p, dh, ERL_DE_PROC_AWAIT_LOAD);
- hp = HAlloc(p,4);
+ Eterm mref = add_monitor(BIF_P, dh, ERL_DE_PROC_AWAIT_LOAD);
+ hp = HAlloc(BIF_P, 4);
t = TUPLE3(hp, am_ok, ok_term, mref);
} else {
- hp = HAlloc(p,3);
+ hp = HAlloc(BIF_P, 3);
t = TUPLE2(hp, am_ok, ok_term);
}
#if DDLL_SMP
@@ -416,33 +420,33 @@ BIF_RETTYPE erl_ddll_try_load_3(Process *p, Eterm path_term,
#endif
erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) path);
erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name);
- ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(p));
+ ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(BIF_P));
BIF_RET(t);
soft_error:
#if DDLL_SMP
unlock_drv_list();
- erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
+ erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
#endif
if (do_build_load_error) {
- soft_error_term = build_load_error(p, build_this_load_error);
+ soft_error_term = build_load_error(BIF_P, build_this_load_error);
}
- hp = HAlloc(p,3);
+ hp = HAlloc(BIF_P, 3);
t = TUPLE2(hp, am_error, soft_error_term);
erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) path);
erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name);
- ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(p));
+ ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(BIF_P));
BIF_RET(t);
error:
assert_drv_list_not_locked();
- ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(p));
+ ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(BIF_P));
if (path != NULL) {
erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) path);
}
if (name != NULL) {
erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name);
}
- BIF_ERROR(p,BADARG);
+ BIF_ERROR(BIF_P, BADARG);
}
/*
@@ -481,8 +485,10 @@ BIF_RETTYPE erl_ddll_try_load_3(Process *p, Eterm path_term,
any AWAIT_LOAD-waiters with {'DOWN', ref(), driver, name(), load_cancelled}
If the driver made itself permanent, {'UP', ref(), driver, name(), permanent}
*/
-Eterm erl_ddll_try_unload_2(Process *p, Eterm name_term, Eterm options)
+Eterm erl_ddll_try_unload_2(BIF_ALIST_2)
{
+ Eterm name_term = BIF_ARG_1;
+ Eterm options = BIF_ARG_2;
char *name = NULL;
Eterm ok_term = NIL;
Eterm soft_error_term = NIL;
@@ -495,7 +501,7 @@ Eterm erl_ddll_try_unload_2(Process *p, Eterm name_term, Eterm options)
Eterm l;
int kill_ports = 0;
- erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
+ erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
for(l = options; is_list(l); l = CDR(list_val(l))) {
Eterm opt = CAR(list_val(l));
@@ -548,7 +554,7 @@ Eterm erl_ddll_try_unload_2(Process *p, Eterm name_term, Eterm options)
if (dh->flags & ERL_DE_FL_KILL_PORTS) {
kill_ports = 1;
}
- if ((pe = find_proc_entry(dh, p, ERL_DE_PROC_LOADED)) == NULL) {
+ if ((pe = find_proc_entry(dh, BIF_P, ERL_DE_PROC_LOADED)) == NULL) {
if (num_procs(dh, ERL_DE_PROC_LOADED) > 0) {
soft_error_term = am_not_loaded_by_this_process;
goto soft_error;
@@ -597,7 +603,7 @@ done:
if (!(prt->status & FREE_PORT_FLAGS)
&& prt->drv_ptr->handle == dh) {
#if DDLL_SMP
- erts_smp_atomic_inc(&prt->refc);
+ erts_smp_atomic_inc_nob(&prt->refc);
/* Extremely rare spinlock */
while(prt->status & ERTS_PORT_SFLG_INITIALIZING) {
erts_smp_port_state_unlock(prt);
@@ -624,22 +630,22 @@ done:
#if DDLL_SMP
erts_ddll_reference_driver(dh);
unlock_drv_list();
- erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
+ erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
lock_drv_list();
erts_ddll_dereference_driver(dh);
#endif
erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name);
- p->flags |= F_USING_DDLL;
+ BIF_P->flags |= F_USING_DDLL;
if (monitor > 0) {
- Eterm mref = add_monitor(p, dh, ERL_DE_PROC_AWAIT_UNLOAD);
- hp = HAlloc(p,4);
+ Eterm mref = add_monitor(BIF_P, dh, ERL_DE_PROC_AWAIT_UNLOAD);
+ hp = HAlloc(BIF_P, 4);
t = TUPLE3(hp, am_ok, ok_term, mref);
} else {
- hp = HAlloc(p,3);
+ hp = HAlloc(BIF_P, 3);
t = TUPLE2(hp, am_ok, ok_term);
}
if (kill_ports > 1) {
- ERTS_BIF_CHK_EXITED(p); /* May be exited by port killing */
+ ERTS_BIF_CHK_EXITED(BIF_P); /* May be exited by port killing */
}
#if DDLL_SMP
unlock_drv_list();
@@ -651,8 +657,8 @@ soft_error:
unlock_drv_list();
#endif
erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name);
- erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
- hp = HAlloc(p,3);
+ erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
+ hp = HAlloc(BIF_P, 3);
t = TUPLE2(hp, am_error, soft_error_term);
BIF_RET(t);
@@ -661,21 +667,21 @@ soft_error:
if (name != NULL) {
erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name);
}
- erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
- BIF_ERROR(p,BADARG);
+ erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
+ BIF_ERROR(BIF_P, BADARG);
}
/*
* A shadow of the "real" demonitor BIF
*/
-BIF_RETTYPE erl_ddll_demonitor_1(Process *p, Eterm ref)
+BIF_RETTYPE erl_ddll_demonitor_1(BIF_ALIST_1)
{
- if (is_not_internal_ref(ref)) {
- BIF_ERROR(p, BADARG);
+ if (is_not_internal_ref(BIF_ARG_1)) {
+ BIF_ERROR(BIF_P, BADARG);
}
- if (p->flags & F_USING_DDLL) {
- erts_ddll_remove_monitor(p, ref, ERTS_PROC_LOCK_MAIN);
+ if (BIF_P->flags & F_USING_DDLL) {
+ erts_ddll_remove_monitor(BIF_P, BIF_ARG_1, ERTS_PROC_LOCK_MAIN);
}
BIF_RET(am_true);
}
@@ -683,18 +689,18 @@ BIF_RETTYPE erl_ddll_demonitor_1(Process *p, Eterm ref)
/*
* A shadow of the "real" monitor BIF
*/
-BIF_RETTYPE erl_ddll_monitor_2(Process *p, Eterm dr, Eterm what)
+BIF_RETTYPE erl_ddll_monitor_2(BIF_ALIST_2)
{
- if (dr != am_driver) {
- BIF_ERROR(p,BADARG);
+ if (BIF_ARG_1 != am_driver) {
+ BIF_ERROR(BIF_P, BADARG);
}
- return erts_ddll_monitor_driver(p, what, ERTS_PROC_LOCK_MAIN);
+ return erts_ddll_monitor_driver(BIF_P, BIF_ARG_2, ERTS_PROC_LOCK_MAIN);
}
/*
* Return list of loaded drivers {ok,[string()]}
*/
-Eterm erl_ddll_loaded_drivers_0(Process *p)
+BIF_RETTYPE erl_ddll_loaded_drivers_0(BIF_ALIST_0)
{
Eterm *hp;
int need = 3;
@@ -706,7 +712,7 @@ Eterm erl_ddll_loaded_drivers_0(Process *p)
for (drv = driver_list; drv; drv = drv->next) {
need += sys_strlen(drv->name)*2+2;
}
- hp = HAlloc(p,need);
+ hp = HAlloc(BIF_P, need);
for (drv = driver_list; drv; drv = drv->next) {
Eterm l;
l = buf_to_intlist(&hp, drv->name, sys_strlen(drv->name), NIL);
@@ -726,8 +732,11 @@ Eterm erl_ddll_loaded_drivers_0(Process *p)
* item is processes, driver_options, port_count, linked_in_driver,
* permanent, awaiting_load, awaiting_unload
*/
-Eterm erl_ddll_info_2(Process *p, Eterm name_term, Eterm item)
+BIF_RETTYPE erl_ddll_info_2(BIF_ALIST_2)
{
+ Process *p = BIF_P;
+ Eterm name_term = BIF_ARG_1;
+ Eterm item = BIF_ARG_2;
char *name = NULL;
Eterm res = NIL;
erts_driver_t *drv;
@@ -850,8 +859,10 @@ Eterm erl_ddll_info_2(Process *p, Eterm name_term, Eterm item)
* Backend for erl_ddll:format_error, handles all "soft" errors returned by builtins,
* possibly by calling the system specific error handler
*/
-Eterm erl_ddll_format_error_int_1(Process *p, Eterm code_term)
+BIF_RETTYPE erl_ddll_format_error_int_1(BIF_ALIST_1)
{
+ Process *p = BIF_P;
+ Eterm code_term = BIF_ARG_1;
char *errstring = NULL;
int errint;
int len;
@@ -1054,7 +1065,7 @@ void erts_ddll_proc_dead(Process *p, ErtsProcLocks plocks)
if (!(prt->status & FREE_PORT_FLAGS) &&
prt->drv_ptr->handle == dh) {
#if DDLL_SMP
- erts_smp_atomic_inc(&prt->refc);
+ erts_smp_atomic_inc_nob(&prt->refc);
while(prt->status & ERTS_PORT_SFLG_INITIALIZING) {
erts_smp_port_state_unlock(prt);
erts_smp_port_state_lock(prt);
@@ -1558,14 +1569,14 @@ static int do_load_driver_entry(DE_Handle *dh, char *path, char *name)
if ((res = erts_sys_ddll_load_driver_init(dh->handle,
&init_handle)) != ERL_DE_NO_ERROR) {
- erts_sys_ddll_close(dh->handle);
- return ERL_DE_LOAD_ERROR_NO_INIT;
+ res = ERL_DE_LOAD_ERROR_NO_INIT;
+ goto error;
}
dp = erts_sys_ddll_call_init(init_handle);
if (dp == NULL) {
- erts_sys_ddll_close(dh->handle);
- return ERL_DE_LOAD_ERROR_FAILED_INIT;
+ res = ERL_DE_LOAD_ERROR_FAILED_INIT;
+ goto error;
}
switch (dp->extended_marker) {
@@ -1583,26 +1594,29 @@ static int do_load_driver_entry(DE_Handle *dh, char *path, char *name)
|| dp->handle2 != NULL
|| dp->process_exit != NULL) {
/* Old driver; needs to be recompiled... */
- return ERL_DE_LOAD_ERROR_INCORRECT_VERSION;
+ res = ERL_DE_LOAD_ERROR_INCORRECT_VERSION;
+ goto error;
}
break;
case ERL_DRV_EXTENDED_MARKER:
if (ERL_DRV_EXTENDED_MAJOR_VERSION != dp->major_version
|| ERL_DRV_EXTENDED_MINOR_VERSION < dp->minor_version) {
/* Incompatible driver version */
- return ERL_DE_LOAD_ERROR_INCORRECT_VERSION;
+ res = ERL_DE_LOAD_ERROR_INCORRECT_VERSION;
+ goto error;
}
break;
default:
/* Old driver; needs to be recompiled... */
- return ERL_DE_LOAD_ERROR_INCORRECT_VERSION;
+ res = ERL_DE_LOAD_ERROR_INCORRECT_VERSION;
+ goto error;
}
if (strcmp(name, dp->driver_name) != 0) {
- erts_sys_ddll_close(dh->handle);
- return ERL_DE_LOAD_ERROR_BAD_NAME;
+ res = ERL_DE_LOAD_ERROR_BAD_NAME;
+ goto error;
}
- erts_smp_atomic_init(&(dh->refc), (erts_aint_t) 0);
+ erts_smp_atomic_init_nob(&(dh->refc), (erts_aint_t) 0);
dh->port_count = 0;
dh->full_path = erts_alloc(ERTS_ALC_T_DDLL_HANDLE, sys_strlen(path) + 1);
sys_strcpy(dh->full_path, path);
@@ -1615,11 +1629,14 @@ static int do_load_driver_entry(DE_Handle *dh, char *path, char *name)
*/
erts_free(ERTS_ALC_T_DDLL_HANDLE, dh->full_path);
dh->full_path = NULL;
- erts_sys_ddll_close(dh->handle);
- return ERL_DE_LOAD_ERROR_FAILED_INIT;
+ res = ERL_DE_LOAD_ERROR_FAILED_INIT;
+ goto error;
}
-
return ERL_DE_NO_ERROR;
+
+error:
+ erts_sys_ddll_close(dh->handle);
+ return res;
}
static int do_unload_driver_entry(DE_Handle *dh, Eterm *save_name)
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index f264bf44df..a79feaebdb 100644
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -39,6 +39,8 @@
#include "dist.h"
#include "erl_gc.h"
#include "erl_cpu_topology.h"
+#include "erl_async.h"
+#include "erl_thr_progress.h"
#ifdef HIPE
#include "hipe_arch.h"
#endif
@@ -52,6 +54,9 @@
#include <valgrind/memcheck.h>
#endif
+static Export* alloc_info_trap = NULL;
+static Export* alloc_sizes_trap = NULL;
+
#define DECL_AM(S) Eterm AM_ ## S = am_atom_put(#S, sizeof(#S) - 1)
/* Keep erts_system_version as a global variable for easy access from a core */
@@ -119,6 +124,16 @@ static char erts_system_version[] = ("Erlang " ERLANG_OTP_RELEASE
# define PERFMON_GETPCR _IOR('P', 2, unsigned long long)
#endif
+/* Cached, pre-built {OsType,OsFlavor} and {Major,Minor,Build} tuples */
+static Eterm os_type_tuple;
+static Eterm os_version_tuple;
+
+static BIF_RETTYPE port_info(Process* p, Eterm portid, Eterm item);
+
+static Eterm
+current_function(Process* p, Process* rp, Eterm** hpp, int full_info);
+static Eterm current_stacktrace(Process* p, Process* rp, Eterm** hpp);
+
static Eterm
bld_bin_list(Uint **hpp, Uint *szp, ErlOffHeap* oh)
{
@@ -135,7 +150,7 @@ bld_bin_list(Uint **hpp, Uint *szp, ErlOffHeap* oh)
if (szp)
*szp += 4+2;
if (hpp) {
- Uint refc = (Uint) erts_smp_atomic_read(&pb->val->refc);
+ Uint refc = (Uint) erts_smp_atomic_read_nob(&pb->val->refc);
tuple = TUPLE3(*hpp, val, orig_size, make_small(refc));
res = CONS(*hpp + 4, tuple, res);
*hpp += 4+2;
@@ -554,6 +569,8 @@ static Eterm pi_args[] = {
am_suspending,
am_min_heap_size,
am_min_bin_vheap_size,
+ am_current_location,
+ am_current_stacktrace,
#ifdef HYBRID
am_message_binary
#endif
@@ -602,8 +619,10 @@ pi_arg2ix(Eterm arg)
case am_suspending: return 26;
case am_min_heap_size: return 27;
case am_min_bin_vheap_size: return 28;
+ case am_current_location: return 29;
+ case am_current_stacktrace: return 30;
#ifdef HYBRID
- case am_message_binary: return 29;
+ case am_message_binary: return 31;
#endif
default: return -1;
}
@@ -1006,35 +1025,15 @@ process_info_aux(Process *BIF_P,
break;
case am_current_function:
- if (rp->current == NULL) {
- rp->current = find_function_from_pc(rp->i);
- }
- if (rp->current == NULL) {
- hp = HAlloc(BIF_P, 3);
- res = am_undefined;
- } else {
- BeamInstr* current;
-
- if (rp->current[0] == am_erlang &&
- rp->current[1] == am_process_info &&
- (rp->current[2] == 1 || rp->current[2] == 2) &&
- (current = find_function_from_pc(rp->cp)) != NULL) {
-
- /*
- * The current function is erlang:process_info/2,
- * which is not the answer that the application want.
- * We will use the function pointed into by rp->cp
- * instead.
- */
+ res = current_function(BIF_P, rp, &hp, 0);
+ break;
- rp->current = current;
- }
+ case am_current_location:
+ res = current_function(BIF_P, rp, &hp, 1);
+ break;
- hp = HAlloc(BIF_P, 3+4);
- res = TUPLE3(hp, rp->current[0],
- rp->current[1], make_small(rp->current[2]));
- hp += 4;
- }
+ case am_current_stacktrace:
+ res = current_stacktrace(BIF_P, rp, &hp);
break;
case am_initial_call:
@@ -1608,6 +1607,113 @@ process_info_aux(Process *BIF_P,
}
#undef MI_INC
+static Eterm
+current_function(Process* BIF_P, Process* rp, Eterm** hpp, int full_info)
+{
+ Eterm* hp;
+ Eterm res;
+ FunctionInfo fi;
+
+ if (rp->current == NULL) {
+ erts_lookup_function_info(&fi, rp->i, full_info);
+ rp->current = fi.current;
+ } else if (full_info) {
+ erts_lookup_function_info(&fi, rp->i, full_info);
+ if (fi.current == NULL) {
+ /* Use the current function without location info */
+ erts_set_current_function(&fi, rp->current);
+ }
+ }
+
+ if (BIF_P->id == rp->id) {
+ FunctionInfo fi2;
+
+ /*
+ * The current function is erlang:process_info/{1,2},
+ * which is not the answer that the application want.
+ * We will use the function pointed into by rp->cp
+ * instead if it can be looked up.
+ */
+ erts_lookup_function_info(&fi2, rp->cp, full_info);
+ if (fi2.current) {
+ fi = fi2;
+ rp->current = fi2.current;
+ }
+ }
+
+ /*
+ * Return the result.
+ */
+ if (rp->current == NULL) {
+ hp = HAlloc(BIF_P, 3);
+ res = am_undefined;
+ } else if (full_info) {
+ hp = HAlloc(BIF_P, 3+fi.needed);
+ hp = erts_build_mfa_item(&fi, hp, am_true, &res);
+ } else {
+ hp = HAlloc(BIF_P, 3+4);
+ res = TUPLE3(hp, rp->current[0],
+ rp->current[1], make_small(rp->current[2]));
+ hp += 4;
+ }
+ *hpp = hp;
+ return res;
+}
+
+static Eterm
+current_stacktrace(Process* p, Process* rp, Eterm** hpp)
+{
+ Uint sz;
+ struct StackTrace* s;
+ int depth;
+ FunctionInfo* stk;
+ FunctionInfo* stkp;
+ Uint heap_size;
+ int i;
+ Eterm* hp = *hpp;
+ Eterm mfa;
+ Eterm res = NIL;
+
+ depth = 8;
+ sz = offsetof(struct StackTrace, trace) + sizeof(BeamInstr *)*depth;
+ s = (struct StackTrace *) erts_alloc(ERTS_ALC_T_TMP, sz);
+ s->depth = 0;
+ if (rp->i) {
+ s->trace[s->depth++] = rp->i;
+ depth--;
+ }
+ if (depth > 0 && rp->cp != 0) {
+ s->trace[s->depth++] = rp->cp - 1;
+ depth--;
+ }
+ erts_save_stacktrace(rp, s, depth);
+
+ depth = s->depth;
+ stk = stkp = (FunctionInfo *) erts_alloc(ERTS_ALC_T_TMP,
+ depth*sizeof(FunctionInfo));
+ heap_size = 3;
+ for (i = 0; i < depth; i++) {
+ erts_lookup_function_info(stkp, s->trace[i], 1);
+ if (stkp->current) {
+ heap_size += stkp->needed + 2;
+ stkp++;
+ }
+ }
+
+ hp = HAlloc(p, heap_size);
+ while (stkp > stk) {
+ stkp--;
+ hp = erts_build_mfa_item(stkp, hp, am_true, &mfa);
+ res = CONS(hp, mfa, res);
+ hp += 2;
+ }
+
+ erts_free(ERTS_ALC_T_TMP, stk);
+ erts_free(ERTS_ALC_T_TMP, s);
+ *hpp = hp;
+ return res;
+}
+
#if defined(VALGRIND)
static int check_if_xml(void)
{
@@ -1633,9 +1739,19 @@ info_1_tuple(Process* BIF_P, /* Pointer to current process. */
sel = *tp++;
- if (sel == am_allocator_sizes && arity == 2) {
- return erts_allocator_info_term(BIF_P, *tp, 1);
- } else if (sel == am_wordsize && arity == 2) {
+ if (sel == am_allocator_sizes) {
+ switch (arity) {
+ case 2:
+ ERTS_BIF_PREP_TRAP1(ret, alloc_sizes_trap, BIF_P, *tp);
+ return ret;
+ case 3:
+ if (erts_request_alloc_info(BIF_P, tp[0], tp[1], 1))
+ return am_true;
+ default:
+ goto badarg;
+ }
+ }
+ else if (sel == am_wordsize && arity == 2) {
if (tp[0] == am_internal) {
return make_small(sizeof(Eterm));
}
@@ -1682,8 +1798,17 @@ info_1_tuple(Process* BIF_P, /* Pointer to current process. */
}
else
goto badarg;
- } else if (sel == am_allocator && arity == 2) {
- return erts_allocator_info_term(BIF_P, *tp, 0);
+ } else if (sel == am_allocator) {
+ switch (arity) {
+ case 2:
+ ERTS_BIF_PREP_TRAP1(ret, alloc_info_trap, BIF_P, *tp);
+ return ret;
+ case 3:
+ if (erts_request_alloc_info(BIF_P, tp[0], tp[1], 0))
+ return am_true;
+ default:
+ goto badarg;
+ }
} else if (ERTS_IS_ATOM_STR("internal_cpu_topology", sel) && arity == 2) {
return erts_get_cpu_topology_term(BIF_P, *tp);
} else if (ERTS_IS_ATOM_STR("cpu_topology", sel) && arity == 2) {
@@ -2005,7 +2130,7 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
BIF_RET(am_undefined);
#endif
} else if (BIF_ARG_1 == am_trace_control_word) {
- BIF_RET(db_get_trace_control_word_0(BIF_P));
+ BIF_RET(db_get_trace_control_word(BIF_P));
} else if (ERTS_IS_ATOM_STR("ets_realloc_moves", BIF_ARG_1)) {
BIF_RET((erts_ets_realloc_always_moves) ? am_true : am_false);
} else if (ERTS_IS_ATOM_STR("ets_always_compress", BIF_ARG_1)) {
@@ -2026,7 +2151,7 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
res = TUPLE2(hp, am_sequential_tracer, val);
BIF_RET(res);
} else if (BIF_ARG_1 == am_garbage_collection){
- Uint val = (Uint) erts_smp_atomic32_read(&erts_max_gen_gcs);
+ Uint val = (Uint) erts_smp_atomic32_read_nob(&erts_max_gen_gcs);
Eterm tup;
hp = HAlloc(BIF_P, 3+2 + 3+2 + 3+2);
@@ -2041,7 +2166,7 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
BIF_RET(res);
} else if (BIF_ARG_1 == am_fullsweep_after){
- Uint val = (Uint) erts_smp_atomic32_read(&erts_max_gen_gcs);
+ Uint val = (Uint) erts_smp_atomic32_read_nob(&erts_max_gen_gcs);
hp = HAlloc(BIF_P, 3);
res = TUPLE2(hp, am_fullsweep_after, make_small(val));
BIF_RET(res);
@@ -2065,7 +2190,7 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
/* Need to be the only thread running... */
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
if (BIF_ARG_1 == am_info)
info(ERTS_PRINT_DSBUF, (void *) dsbufp);
@@ -2076,7 +2201,7 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
else
distribution_info(ERTS_PRINT_DSBUF, (void *) dsbufp);
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
ASSERT(dsbufp && dsbufp->str);
@@ -2088,7 +2213,7 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
i = 0;
/* Need to be the only thread running... */
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
for (dep = erts_visible_dist_entries; dep; dep = dep->next)
++i;
for (dep = erts_hidden_dist_entries; dep; dep = dep->next)
@@ -2111,7 +2236,7 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
res = CONS(hp, tpl, res);
hp += 2;
}
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
BIF_RET(res);
} else if (BIF_ARG_1 == am_system_version) {
@@ -2132,16 +2257,7 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
return erts_instr_get_type_info(BIF_P);
}
else if (BIF_ARG_1 == am_os_type) {
- Eterm type = am_atom_put(os_type, strlen(os_type));
- Eterm flav, tup;
- char *buf = erts_alloc(ERTS_ALC_T_TMP, 1024); /* More than enough */
-
- os_flavor(buf, 1024);
- flav = am_atom_put(buf, strlen(buf));
- hp = HAlloc(BIF_P, 3);
- tup = TUPLE2(hp, type, flav);
- erts_free(ERTS_ALC_T_TMP, (void *) buf);
- BIF_RET(tup);
+ BIF_RET(os_type_tuple);
}
else if (BIF_ARG_1 == am_allocator) {
BIF_RET(erts_allocator_options((void *) BIF_P));
@@ -2167,16 +2283,7 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
BIF_RET(am_false);
}
else if (BIF_ARG_1 == am_os_version) {
- int major, minor, build;
- Eterm tup;
-
- os_version(&major, &minor, &build);
- hp = HAlloc(BIF_P, 4);
- tup = TUPLE3(hp,
- make_small(major),
- make_small(minor),
- make_small(build));
- BIF_RET(tup);
+ BIF_RET(os_version_tuple);
}
else if (BIF_ARG_1 == am_version) {
int n = strlen(ERLANG_VERSION);
@@ -2545,14 +2652,90 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
hp = hsz ? HAlloc(BIF_P, hsz) : NULL;
res = erts_bld_uint(&hp, NULL, erts_dist_buf_busy_limit);
BIF_RET(res);
+ } else if (ERTS_IS_ATOM_STR("print_ethread_info", BIF_ARG_1)) {
+#if defined(ETHR_NATIVE_ATOMIC32_IMPL) \
+ || defined(ETHR_NATIVE_ATOMIC64_IMPL) \
+ || defined(ETHR_NATIVE_DW_ATOMIC_IMPL)
+ int i;
+ char **str;
+#endif
+#ifdef ETHR_NATIVE_ATOMIC32_IMPL
+ erts_printf("32-bit native atomics: %s\n",
+ ETHR_NATIVE_ATOMIC32_IMPL);
+ str = ethr_native_atomic32_ops();
+ for (i = 0; str[i]; i++)
+ erts_printf("ethr_native_atomic32_%s()\n", str[i]);
+#endif
+#ifdef ETHR_NATIVE_ATOMIC64_IMPL
+ erts_printf("64-bit native atomics: %s\n",
+ ETHR_NATIVE_ATOMIC64_IMPL);
+ str = ethr_native_atomic64_ops();
+ for (i = 0; str[i]; i++)
+ erts_printf("ethr_native_atomic64_%s()\n", str[i]);
+#endif
+#ifdef ETHR_NATIVE_DW_ATOMIC_IMPL
+ if (ethr_have_native_dw_atomic()) {
+ erts_printf("Double word native atomics: %s\n",
+ ETHR_NATIVE_DW_ATOMIC_IMPL);
+ str = ethr_native_dw_atomic_ops();
+ for (i = 0; str[i]; i++)
+ erts_printf("ethr_native_dw_atomic_%s()\n", str[i]);
+ str = ethr_native_su_dw_atomic_ops();
+ for (i = 0; str[i]; i++)
+ erts_printf("ethr_native_su_dw_atomic_%s()\n", str[i]);
+ }
+#endif
+#ifdef ETHR_NATIVE_SPINLOCK_IMPL
+ erts_printf("Native spin-locks: %s\n", ETHR_NATIVE_SPINLOCK_IMPL);
+#endif
+#ifdef ETHR_NATIVE_RWSPINLOCK_IMPL
+ erts_printf("Native rwspin-locks: %s\n", ETHR_NATIVE_RWSPINLOCK_IMPL);
+#endif
+#ifdef ETHR_X86_RUNTIME_CONF_HAVE_SSE2__
+ erts_printf("SSE2 support: %s\n", (ETHR_X86_RUNTIME_CONF_HAVE_SSE2__
+ ? "yes" : "no"));
+#endif
+#ifdef ETHR_X86_OUT_OF_ORDER
+ erts_printf("x86"
+#ifdef ARCH_64
+ "_64"
+#endif
+ " out of order\n");
+#endif
+#ifdef ETHR_SPARC_TSO
+ erts_printf("Sparc TSO\n");
+#endif
+#ifdef ETHR_SPARC_PSO
+ erts_printf("Sparc PSO\n");
+#endif
+#ifdef ETHR_SPARC_RMO
+ erts_printf("Sparc RMO\n");
+#endif
+#if defined(ETHR_PPC_HAVE_LWSYNC)
+ erts_printf("Have lwsync instruction: yes\n");
+#elif defined(ETHR_PPC_HAVE_NO_LWSYNC)
+ erts_printf("Have lwsync instruction: no\n");
+#elif defined(ETHR_PPC_RUNTIME_CONF_HAVE_LWSYNC__)
+ erts_printf("Have lwsync instruction: %s (runtime test)\n",
+ ETHR_PPC_RUNTIME_CONF_HAVE_LWSYNC__ ? "yes" : "no");
+#endif
+ BIF_RET(am_true);
}
+#ifdef ERTS_SMP
+ else if (ERTS_IS_ATOM_STR("thread_progress", BIF_ARG_1)) {
+ erts_thr_progress_dbg_print_state();
+ BIF_RET(am_true);
+ }
+#endif
BIF_ERROR(BIF_P, BADARG);
}
-Eterm
-port_info_1(Process* p, Eterm pid)
+BIF_RETTYPE
+port_info_1(BIF_ALIST_1)
{
+ Process* p = BIF_P;
+ Eterm pid = BIF_ARG_1;
static Eterm keys[] = {
am_name,
am_links,
@@ -2575,7 +2758,7 @@ port_info_1(Process* p, Eterm pid)
for (i = 0; i < ASIZE(keys); i++) {
Eterm item;
- item = port_info_2(p, pid, keys[i]);
+ item = port_info(p, pid, keys[i]);
if (is_non_value(item)) {
return THE_NON_VALUE;
}
@@ -2584,7 +2767,7 @@ port_info_1(Process* p, Eterm pid)
}
items[i] = item;
}
- reg_name = port_info_2(p, pid, am_registered_name);
+ reg_name = port_info(p, pid, am_registered_name);
/*
* Build the resulting list.
@@ -2620,24 +2803,27 @@ port_info_1(Process* p, Eterm pid)
BIF_RETTYPE port_info_2(BIF_ALIST_2)
{
+ return port_info(BIF_P, BIF_ARG_1, BIF_ARG_2);
+}
+
+static BIF_RETTYPE port_info(Process* p, Eterm portid, Eterm item)
+{
BIF_RETTYPE ret;
- Eterm portid = BIF_ARG_1;
Port *prt;
- Eterm item = BIF_ARG_2;
Eterm res;
Eterm* hp;
int count;
if (is_internal_port(portid))
- prt = erts_id2port(portid, BIF_P, ERTS_PROC_LOCK_MAIN);
+ prt = erts_id2port(portid, p, ERTS_PROC_LOCK_MAIN);
else if (is_atom(portid))
- erts_whereis_name(BIF_P, ERTS_PROC_LOCK_MAIN,
+ erts_whereis_name(p, ERTS_PROC_LOCK_MAIN,
portid, NULL, 0, 0, &prt);
else if (is_external_port(portid)
&& external_port_dist_entry(portid) == erts_this_dist_entry)
BIF_RET(am_undefined);
else {
- BIF_ERROR(BIF_P, BADARG);
+ BIF_ERROR(p, BADARG);
}
if (!prt) {
@@ -2645,7 +2831,7 @@ BIF_RETTYPE port_info_2(BIF_ALIST_2)
}
if (item == am_id) {
- hp = HAlloc(BIF_P, 3);
+ hp = HAlloc(p, 3);
res = make_small(internal_port_number(portid));
}
else if (item == am_links) {
@@ -2657,10 +2843,10 @@ BIF_RETTYPE port_info_2(BIF_ALIST_2)
erts_doforall_links(prt->nlinks, &collect_one_link, &mic);
- hp = HAlloc(BIF_P, 3 + mic.sz);
+ hp = HAlloc(p, 3 + mic.sz);
res = NIL;
for (i = 0; i < mic.mi_i; i++) {
- item = STORE_NC(&hp, &MSO(BIF_P), mic.mi[i].entity);
+ item = STORE_NC(&hp, &MSO(p), mic.mi[i].entity);
res = CONS(hp, item, res);
hp += 2;
}
@@ -2676,11 +2862,11 @@ BIF_RETTYPE port_info_2(BIF_ALIST_2)
erts_doforall_monitors(prt->monitors, &collect_one_origin_monitor, &mic);
- hp = HAlloc(BIF_P, 3 + mic.sz);
+ hp = HAlloc(p, 3 + mic.sz);
res = NIL;
for (i = 0; i < mic.mi_i; i++) {
Eterm t;
- item = STORE_NC(&hp, &MSO(BIF_P), mic.mi[i].entity);
+ item = STORE_NC(&hp, &MSO(p), mic.mi[i].entity);
t = TUPLE2(hp, am_process, item);
hp += 3;
res = CONS(hp, t, res);
@@ -2692,25 +2878,25 @@ BIF_RETTYPE port_info_2(BIF_ALIST_2)
else if (item == am_name) {
count = sys_strlen(prt->name);
- hp = HAlloc(BIF_P, 3 + 2*count);
+ hp = HAlloc(p, 3 + 2*count);
res = buf_to_intlist(&hp, prt->name, count, NIL);
}
else if (item == am_connected) {
- hp = HAlloc(BIF_P, 3);
+ hp = HAlloc(p, 3);
res = prt->connected; /* internal pid */
}
else if (item == am_input) {
Uint hsz = 3;
Uint n = prt->bytes_in;
(void) erts_bld_uint(NULL, &hsz, n);
- hp = HAlloc(BIF_P, hsz);
+ hp = HAlloc(p, hsz);
res = erts_bld_uint(&hp, NULL, n);
}
else if (item == am_output) {
Uint hsz = 3;
Uint n = prt->bytes_out;
(void) erts_bld_uint(NULL, &hsz, n);
- hp = HAlloc(BIF_P, hsz);
+ hp = HAlloc(p, hsz);
res = erts_bld_uint(&hp, NULL, n);
}
else if (item == am_registered_name) {
@@ -2720,7 +2906,7 @@ BIF_RETTYPE port_info_2(BIF_ALIST_2)
ERTS_BIF_PREP_RET(ret, NIL);
goto done;
} else {
- hp = HAlloc(BIF_P, 3);
+ hp = HAlloc(p, 3);
res = reg->name;
}
}
@@ -2732,7 +2918,7 @@ BIF_RETTYPE port_info_2(BIF_ALIST_2)
Uint size = 0;
ErlHeapFragment* bp;
- hp = HAlloc(BIF_P, 3);
+ hp = HAlloc(p, 3);
erts_doforall_links(prt->nlinks, &one_link_size, &size);
@@ -2749,18 +2935,18 @@ BIF_RETTYPE port_info_2(BIF_ALIST_2)
hard to retrieve... */
(void) erts_bld_uint(NULL, &hsz, size);
- hp = HAlloc(BIF_P, hsz);
+ hp = HAlloc(p, hsz);
res = erts_bld_uint(&hp, NULL, size);
}
else if (item == am_queue_size) {
Uint ioq_size = erts_port_ioq_size(prt);
Uint hsz = 3;
(void) erts_bld_uint(NULL, &hsz, ioq_size);
- hp = HAlloc(BIF_P, hsz);
+ hp = HAlloc(p, hsz);
res = erts_bld_uint(&hp, NULL, ioq_size);
}
else if (ERTS_IS_ATOM_STR("locking", item)) {
- hp = HAlloc(BIF_P, 3);
+ hp = HAlloc(p, 3);
#ifndef ERTS_SMP
res = am_false;
#else
@@ -2779,7 +2965,7 @@ BIF_RETTYPE port_info_2(BIF_ALIST_2)
#endif
}
else {
- ERTS_BIF_PREP_ERROR(ret, BIF_P, BADARG);
+ ERTS_BIF_PREP_ERROR(ret, p, BADARG);
goto done;
}
@@ -2793,9 +2979,12 @@ BIF_RETTYPE port_info_2(BIF_ALIST_2)
}
-Eterm
-fun_info_2(Process* p, Eterm fun, Eterm what)
+BIF_RETTYPE
+fun_info_2(BIF_ALIST_2)
{
+ Process* p = BIF_P;
+ Eterm fun = BIF_ARG_1;
+ Eterm what = BIF_ARG_2;
Eterm* hp;
Eterm val;
@@ -2845,7 +3034,7 @@ fun_info_2(Process* p, Eterm fun, Eterm what)
}
break;
case am_refc:
- val = erts_make_integer(erts_smp_atomic_read(&funp->fe->refc), p);
+ val = erts_make_integer(erts_smp_atomic_read_nob(&funp->fe->refc), p);
hp = HAlloc(p, 3);
break;
case am_arity:
@@ -3065,8 +3254,8 @@ BIF_RETTYPE statistics_1(BIF_ALIST_1)
Eterm r1, r2;
Eterm in, out;
Uint hsz = 9;
- Uint bytes_in = (Uint) erts_smp_atomic_read(&erts_bytes_in);
- Uint bytes_out = (Uint) erts_smp_atomic_read(&erts_bytes_out);
+ Uint bytes_in = (Uint) erts_smp_atomic_read_nob(&erts_bytes_in);
+ Uint bytes_out = (Uint) erts_smp_atomic_read_nob(&erts_bytes_out);
(void) erts_bld_uint(NULL, &hsz, bytes_in);
(void) erts_bld_uint(NULL, &hsz, bytes_out);
@@ -3106,26 +3295,6 @@ BIF_RETTYPE statistics_1(BIF_ALIST_1)
BIF_ERROR(BIF_P, BADARG);
}
-BIF_RETTYPE memory_0(BIF_ALIST_0)
-{
- BIF_RETTYPE res = erts_memory(NULL, NULL, BIF_P, THE_NON_VALUE);
- switch (res) {
- case am_badarg: BIF_ERROR(BIF_P, EXC_INTERNAL_ERROR); /* never... */
- case am_notsup: BIF_ERROR(BIF_P, EXC_NOTSUP);
- default: BIF_RET(res);
- }
-}
-
-BIF_RETTYPE memory_1(BIF_ALIST_1)
-{
- BIF_RETTYPE res = erts_memory(NULL, NULL, BIF_P, BIF_ARG_1);
- switch (res) {
- case am_badarg: BIF_ERROR(BIF_P, BADARG);
- case am_notsup: BIF_ERROR(BIF_P, EXC_NOTSUP);
- default: BIF_RET(res);
- }
-}
-
BIF_RETTYPE error_logger_warning_map_0(BIF_ALIST_0)
{
BIF_RET(erts_error_logger_warnings);
@@ -3139,7 +3308,7 @@ BIF_RETTYPE erts_debug_get_internal_state_1(BIF_ALIST_1)
* NOTE: Only supposed to be used for testing, and debugging.
*/
- if (!erts_smp_atomic_read(&available_internal_state)) {
+ if (!erts_smp_atomic_read_nob(&available_internal_state)) {
BIF_ERROR(BIF_P, EXC_UNDEF);
}
@@ -3227,6 +3396,15 @@ BIF_RETTYPE erts_debug_get_internal_state_1(BIF_ALIST_1)
BIF_RET(am_false);
#endif
}
+ else if (ERTS_IS_ATOM_STR("memory", BIF_ARG_1)) {
+ Eterm res;
+ erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
+ erts_smp_thr_progress_block();
+ erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
+ res = erts_memory(NULL, NULL, BIF_P, THE_NON_VALUE);
+ erts_smp_thr_progress_unblock();
+ BIF_RET(res);
+ }
}
else if (is_tuple(BIF_ARG_1)) {
Eterm* tp = tuple_val(BIF_ARG_1);
@@ -3429,6 +3607,7 @@ BIF_RETTYPE erts_debug_get_internal_state_1(BIF_ALIST_1)
static erts_smp_atomic_t hipe_test_reschedule_flag;
+
BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2)
{
/*
@@ -3437,7 +3616,7 @@ BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2)
if (ERTS_IS_ATOM_STR("available_internal_state", BIF_ARG_1)
&& (BIF_ARG_2 == am_true || BIF_ARG_2 == am_false)) {
erts_aint_t on = (erts_aint_t) (BIF_ARG_2 == am_true);
- erts_aint_t prev_on = erts_smp_atomic_xchg(&available_internal_state, on);
+ erts_aint_t prev_on = erts_smp_atomic_xchg_nob(&available_internal_state, on);
if (on) {
erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf();
erts_dsprintf(dsbufp, "Process %T ", BIF_P->id);
@@ -3453,7 +3632,7 @@ BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2)
BIF_RET(prev_on ? am_true : am_false);
}
- if (!erts_smp_atomic_read(&available_internal_state)) {
+ if (!erts_smp_atomic_read_nob(&available_internal_state)) {
BIF_ERROR(BIF_P, EXC_UNDEF);
}
@@ -3479,10 +3658,10 @@ BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2)
if (ms > 0) {
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
if (block)
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
while (erts_milli_sleep((long) ms) != 0);
if (block)
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
}
BIF_RET(am_true);
@@ -3634,14 +3813,14 @@ BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2)
}
else if (ERTS_IS_ATOM_STR("hipe_test_reschedule_suspend", BIF_ARG_1)) {
/* Used by hipe test suites */
- erts_aint_t flag = erts_smp_atomic_read(&hipe_test_reschedule_flag);
+ erts_aint_t flag = erts_smp_atomic_read_nob(&hipe_test_reschedule_flag);
if (!flag && BIF_ARG_2 != am_false) {
- erts_smp_atomic_set(&hipe_test_reschedule_flag, 1);
+ erts_smp_atomic_set_nob(&hipe_test_reschedule_flag, 1);
erts_suspend(BIF_P, ERTS_PROC_LOCK_MAIN, NULL);
ERTS_BIF_YIELD2(bif_export[BIF_erts_debug_set_internal_state_2],
BIF_P, BIF_ARG_1, BIF_ARG_2);
}
- erts_smp_atomic_set(&hipe_test_reschedule_flag, !flag);
+ erts_smp_atomic_set_nob(&hipe_test_reschedule_flag, !flag);
BIF_RET(NIL);
}
else if (ERTS_IS_ATOM_STR("hipe_test_reschedule_resume", BIF_ARG_1)) {
@@ -3692,16 +3871,23 @@ BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2)
}
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
old_use_opt = !erts_disable_proc_not_running_opt;
erts_disable_proc_not_running_opt = !use_opt;
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
BIF_RET(old_use_opt ? am_true : am_false);
#else
BIF_ERROR(BIF_P, EXC_NOTSUP);
#endif
}
+ else if (ERTS_IS_ATOM_STR("wait", BIF_ARG_1)) {
+ if (ERTS_IS_ATOM_STR("deallocations", BIF_ARG_2)) {
+ if (erts_debug_wait_deallocations(BIF_P)) {
+ ERTS_BIF_YIELD_RETURN(BIF_P, am_ok);
+ }
+ }
+ }
}
BIF_ERROR(BIF_P, BADARG);
@@ -3860,7 +4046,7 @@ BIF_RETTYPE erts_debug_lock_counters_1(BIF_ALIST_1)
Eterm* hp;
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
erts_lcnt_set_rt_opt(ERTS_LCNT_OPT_SUSPEND);
data = erts_lcnt_get_data();
@@ -3878,17 +4064,17 @@ BIF_RETTYPE erts_debug_lock_counters_1(BIF_ALIST_1)
erts_lcnt_clear_rt_opt(ERTS_LCNT_OPT_SUSPEND);
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
BIF_RET(res);
} else if (BIF_ARG_1 == am_clear) {
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
erts_lcnt_clear_counters();
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
BIF_RET(am_ok);
@@ -3899,7 +4085,7 @@ BIF_RETTYPE erts_debug_lock_counters_1(BIF_ALIST_1)
case 2:
if (ERTS_IS_ATOM_STR("copy_save", tp[1])) {
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
if (tp[2] == am_true) {
res = erts_lcnt_set_rt_opt(ERTS_LCNT_OPT_COPYSAVE) ? am_true : am_false;
@@ -3909,17 +4095,17 @@ BIF_RETTYPE erts_debug_lock_counters_1(BIF_ALIST_1)
res = erts_lcnt_clear_rt_opt(ERTS_LCNT_OPT_COPYSAVE) ? am_true : am_false;
} else {
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
BIF_ERROR(BIF_P, BADARG);
}
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
BIF_RET(res);
} else if (ERTS_IS_ATOM_STR("process_locks", tp[1])) {
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
if (tp[2] == am_true) {
res = erts_lcnt_set_rt_opt(ERTS_LCNT_OPT_PROCLOCK) ? am_true : am_false;
@@ -3929,11 +4115,11 @@ BIF_RETTYPE erts_debug_lock_counters_1(BIF_ALIST_1)
res = erts_lcnt_set_rt_opt(ERTS_LCNT_OPT_PROCLOCK) ? am_true : am_false;
} else {
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
BIF_ERROR(BIF_P, BADARG);
}
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
BIF_RET(res);
}
@@ -3948,11 +4134,35 @@ BIF_RETTYPE erts_debug_lock_counters_1(BIF_ALIST_1)
BIF_ERROR(BIF_P, BADARG);
}
+static void os_info_init(void)
+{
+ Eterm type = am_atom_put(os_type, strlen(os_type));
+ Eterm flav;
+ int major, minor, build;
+ char* buf = erts_alloc(ERTS_ALC_T_TMP, 1024); /* More than enough */
+ Eterm* hp;
+
+ os_flavor(buf, 1024);
+ flav = am_atom_put(buf, strlen(buf));
+ erts_free(ERTS_ALC_T_TMP, (void *) buf);
+ hp = erts_alloc(ERTS_ALC_T_LL_TEMP_TERM, (3+4)*sizeof(Eterm));
+ os_type_tuple = TUPLE2(hp, type, flav);
+ hp += 3;
+ os_version(&major, &minor, &build);
+ os_version_tuple = TUPLE3(hp,
+ make_small(major),
+ make_small(minor),
+ make_small(build));
+}
+
void
erts_bif_info_init(void)
{
- erts_smp_atomic_init(&available_internal_state, 0);
- erts_smp_atomic_init(&hipe_test_reschedule_flag, 0);
+ erts_smp_atomic_init_nob(&available_internal_state, 0);
+ erts_smp_atomic_init_nob(&hipe_test_reschedule_flag, 0);
+ alloc_info_trap = erts_export_put(am_erlang, am_alloc_info, 1);
+ alloc_sizes_trap = erts_export_put(am_erlang, am_alloc_sizes, 1);
process_info_init();
+ os_info_init();
}
diff --git a/erts/emulator/beam/erl_bif_lists.c b/erts/emulator/beam/erl_bif_lists.c
index 47c48e74d6..1805366cfe 100644
--- a/erts/emulator/beam/erl_bif_lists.c
+++ b/erts/emulator/beam/erl_bif_lists.c
@@ -34,27 +34,7 @@
static Eterm keyfind(int Bif, Process* p, Eterm Key, Eterm Pos, Eterm List);
-/*
- * erlang:'++'/2
- */
-
-Eterm
-ebif_plusplus_2(Process* p, Eterm A, Eterm B)
-{
- return append_2(p, A, B);
-}
-
-/*
- * erlang:'--'/2
- */
-
-Eterm
-ebif_minusminus_2(Process* p, Eterm A, Eterm B)
-{
- return subtract_2(p, A, B);
-}
-
-BIF_RETTYPE append_2(BIF_ALIST_2)
+static BIF_RETTYPE append(Process* p, Eterm A, Eterm B)
{
Eterm list;
Eterm copy;
@@ -63,18 +43,18 @@ BIF_RETTYPE append_2(BIF_ALIST_2)
Eterm* hp;
int i;
- if ((i = list_length(BIF_ARG_1)) < 0) {
- BIF_ERROR(BIF_P, BADARG);
+ if ((i = list_length(A)) < 0) {
+ BIF_ERROR(p, BADARG);
}
if (i == 0) {
- BIF_RET(BIF_ARG_2);
- } else if (is_nil(BIF_ARG_2)) {
- BIF_RET(BIF_ARG_1);
+ BIF_RET(B);
+ } else if (is_nil(B)) {
+ BIF_RET(A);
}
need = 2*i;
- hp = HAlloc(BIF_P, need);
- list = BIF_ARG_1;
+ hp = HAlloc(p, need);
+ list = A;
copy = last = CONS(hp, CAR(list_val(list)), make_list(hp+2));
list = CDR(list_val(list));
hp += 2;
@@ -85,12 +65,31 @@ BIF_RETTYPE append_2(BIF_ALIST_2)
list = CDR(listp);
hp += 2;
}
- CDR(list_val(last)) = BIF_ARG_2;
+ CDR(list_val(last)) = B;
BIF_RET(copy);
}
+/*
+ * erlang:'++'/2
+ */
+
+Eterm
+ebif_plusplus_2(BIF_ALIST_2)
+{
+ return append(BIF_P, BIF_ARG_1, BIF_ARG_2);
+}
+
+BIF_RETTYPE append_2(BIF_ALIST_2)
+{
+ return append(BIF_P, BIF_ARG_1, BIF_ARG_2);
+}
+
+/*
+ * erlang:'--'/2
+ */
+
#define SMALL_VEC_SIZE 10
-BIF_RETTYPE subtract_2(BIF_ALIST_2)
+static Eterm subtract(Process* p, Eterm A, Eterm B)
{
Eterm list;
Eterm* hp;
@@ -103,17 +102,17 @@ BIF_RETTYPE subtract_2(BIF_ALIST_2)
int n;
int m;
- if ((n = list_length(BIF_ARG_1)) < 0) {
- BIF_ERROR(BIF_P, BADARG);
+ if ((n = list_length(A)) < 0) {
+ BIF_ERROR(p, BADARG);
}
- if ((m = list_length(BIF_ARG_2)) < 0) {
- BIF_ERROR(BIF_P, BADARG);
+ if ((m = list_length(B)) < 0) {
+ BIF_ERROR(p, BADARG);
}
if (n == 0)
BIF_RET(NIL);
if (m == 0)
- BIF_RET(BIF_ARG_1);
+ BIF_RET(A);
/* allocate element vector */
if (n <= SMALL_VEC_SIZE)
@@ -123,7 +122,7 @@ BIF_RETTYPE subtract_2(BIF_ALIST_2)
/* PUT ALL ELEMENTS IN VP */
vp = vec_p;
- list = BIF_ARG_1;
+ list = A;
i = n;
while(i--) {
Eterm* listp = list_val(list);
@@ -132,7 +131,7 @@ BIF_RETTYPE subtract_2(BIF_ALIST_2)
}
/* UNMARK ALL DELETED CELLS */
- list = BIF_ARG_2;
+ list = B;
m = 0; /* number of deleted elements */
while(is_list(list)) {
Eterm* listp = list_val(list);
@@ -153,11 +152,11 @@ BIF_RETTYPE subtract_2(BIF_ALIST_2)
if (m == n) /* All deleted ? */
res = NIL;
else if (m == 0) /* None deleted ? */
- res = BIF_ARG_1;
+ res = A;
else { /* REBUILD LIST */
res = NIL;
need = 2*(n - m);
- hp = HAlloc(BIF_P, need);
+ hp = HAlloc(p, need);
vp = vec_p + n - 1;
while(vp >= vec_p) {
if (is_value(*vp)) {
@@ -172,6 +171,16 @@ BIF_RETTYPE subtract_2(BIF_ALIST_2)
BIF_RET(res);
}
+BIF_RETTYPE ebif_minusminus_2(BIF_ALIST_2)
+{
+ return subtract(BIF_P, BIF_ARG_1, BIF_ARG_2);
+}
+
+BIF_RETTYPE subtract_2(BIF_ALIST_2)
+{
+ return subtract(BIF_P, BIF_ARG_1, BIF_ARG_2);
+}
+
BIF_RETTYPE lists_member_2(BIF_ALIST_2)
{
Eterm term;
@@ -278,11 +287,12 @@ BIF_RETTYPE lists_reverse_2(BIF_ALIST_2)
}
BIF_RETTYPE
-lists_keymember_3(Process* p, Eterm Key, Eterm Pos, Eterm List)
+lists_keymember_3(BIF_ALIST_3)
{
Eterm res;
- res = keyfind(BIF_lists_keymember_3, p, Key, Pos, List);
+ res = keyfind(BIF_lists_keymember_3, BIF_P,
+ BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
if (is_value(res) && is_tuple(res)) {
return am_true;
} else {
@@ -291,23 +301,25 @@ lists_keymember_3(Process* p, Eterm Key, Eterm Pos, Eterm List)
}
BIF_RETTYPE
-lists_keysearch_3(Process* p, Eterm Key, Eterm Pos, Eterm List)
+lists_keysearch_3(BIF_ALIST_3)
{
Eterm res;
- res = keyfind(BIF_lists_keysearch_3, p, Key, Pos, List);
+ res = keyfind(BIF_lists_keysearch_3, BIF_P,
+ BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
if (is_non_value(res) || is_not_tuple(res)) {
return res;
} else { /* Tuple */
- Eterm* hp = HAlloc(p, 3);
+ Eterm* hp = HAlloc(BIF_P, 3);
return TUPLE2(hp, am_value, res);
}
}
BIF_RETTYPE
-lists_keyfind_3(Process* p, Eterm Key, Eterm Pos, Eterm List)
+lists_keyfind_3(BIF_ALIST_3)
{
- return keyfind(BIF_lists_keyfind_3, p, Key, Pos, List);
+ return keyfind(BIF_lists_keyfind_3, BIF_P,
+ BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
}
static Eterm
diff --git a/erts/emulator/beam/erl_bif_op.c b/erts/emulator/beam/erl_bif_op.c
index deda7adc1f..13f8b1f63c 100644
--- a/erts/emulator/beam/erl_bif_op.c
+++ b/erts/emulator/beam/erl_bif_op.c
@@ -225,18 +225,23 @@ BIF_RETTYPE is_function_1(BIF_ALIST_1)
BIF_RETTYPE is_function_2(BIF_ALIST_2)
{
+ BIF_RET(erl_is_function(BIF_P, BIF_ARG_1, BIF_ARG_2));
+}
+
+Eterm erl_is_function(Process* p, Eterm arg1, Eterm arg2)
+{
Sint arity;
/*
* Verify argument 2 (arity); arity must be >= 0.
*/
- if (is_small(BIF_ARG_2)) {
- arity = signed_val(BIF_ARG_2);
+ if (is_small(arg2)) {
+ arity = signed_val(arg2);
if (arity < 0) {
error:
- BIF_ERROR(BIF_P, BADARG);
+ BIF_ERROR(p, BADARG);
}
- } else if (is_big(BIF_ARG_2) && !bignum_header_is_neg(*big_val(BIF_ARG_2))) {
+ } else if (is_big(arg2) && !bignum_header_is_neg(*big_val(arg2))) {
/* A positive bignum is OK, but can't possibly match. */
arity = -1;
} else {
@@ -244,20 +249,20 @@ BIF_RETTYPE is_function_2(BIF_ALIST_2)
goto error;
}
- if (is_fun(BIF_ARG_1)) {
- ErlFunThing* funp = (ErlFunThing *) fun_val(BIF_ARG_1);
+ if (is_fun(arg1)) {
+ ErlFunThing* funp = (ErlFunThing *) fun_val(arg1);
if (funp->arity == (Uint) arity) {
BIF_RET(am_true);
}
- } else if (is_export(BIF_ARG_1)) {
- Export* exp = (Export *) EXPAND_POINTER((export_val(BIF_ARG_1))[1]);
+ } else if (is_export(arg1)) {
+ Export* exp = (Export *) EXPAND_POINTER((export_val(arg1))[1]);
if (exp->code[2] == (Uint) arity) {
BIF_RET(am_true);
}
- } else if (is_tuple(BIF_ARG_1)) {
- Eterm* tp = tuple_val(BIF_ARG_1);
+ } else if (is_tuple(arg1)) {
+ Eterm* tp = tuple_val(arg1);
if (tp[0] == make_arityval(2) && is_atom(tp[1]) && is_atom(tp[2])) {
BIF_RET(am_true);
}
diff --git a/erts/emulator/beam/erl_bif_os.c b/erts/emulator/beam/erl_bif_os.c
index 954b1f9729..58d48199fa 100644
--- a/erts/emulator/beam/erl_bif_os.c
+++ b/erts/emulator/beam/erl_bif_os.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1999-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2010. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -53,20 +53,18 @@ BIF_RETTYPE os_timestamp_0(BIF_ALIST_0)
}
-Eterm
-os_getpid_0(Process* p)
+BIF_RETTYPE os_getpid_0(BIF_ALIST_0)
{
char pid_string[21]; /* enough for a 64 bit number */
int n;
Eterm* hp;
sys_get_pid(pid_string); /* In sys.c */
n = sys_strlen(pid_string);
- hp = HAlloc(p, n*2);
+ hp = HAlloc(BIF_P, n*2);
BIF_RET(buf_to_intlist(&hp, pid_string, n, NIL));
}
-Eterm
-os_getenv_0(Process* p)
+BIF_RETTYPE os_getenv_0(BIF_ALIST_0)
{
GETENV_STATE state;
char *cp;
@@ -80,7 +78,7 @@ os_getenv_0(Process* p)
ret = NIL;
while ((cp = getenv_string(&state)) != NULL) {
len = strlen(cp);
- hp = HAlloc(p, len*2+2);
+ hp = HAlloc(BIF_P, len*2+2);
str = buf_to_intlist(&hp, cp, len, NIL);
ret = CONS(hp, str, ret);
}
@@ -90,9 +88,11 @@ os_getenv_0(Process* p)
return ret;
}
-Eterm
-os_getenv_1(Process* p, Eterm key)
+
+BIF_RETTYPE os_getenv_1(BIF_ALIST_1)
{
+ Process* p = BIF_P;
+ Eterm key = BIF_ARG_1;
Eterm str;
int len, res;
char *key_str, *val;
@@ -145,9 +145,11 @@ os_getenv_1(Process* p, Eterm key)
BIF_RET(str);
}
-Eterm
-os_putenv_2(Process* p, Eterm key, Eterm value)
+BIF_RETTYPE os_putenv_2(BIF_ALIST_2)
{
+ Process* p = BIF_P;
+ Eterm key = BIF_ARG_1;
+ Eterm value = BIF_ARG_2;
char def_buf[1024];
char *buf = NULL;
int sep_ix, i, key_len, value_len, tot_len;
diff --git a/erts/emulator/beam/erl_bif_port.c b/erts/emulator/beam/erl_bif_port.c
index 3fd35dd963..6b8f1b21fd 100644
--- a/erts/emulator/beam/erl_bif_port.c
+++ b/erts/emulator/beam/erl_bif_port.c
@@ -48,6 +48,9 @@ static void free_args(char **);
char *erts_default_arg0 = "default";
+static BIF_RETTYPE
+port_call(Process* p, Eterm arg1, Eterm arg2, Eterm arg3);
+
BIF_RETTYPE open_port_2(BIF_ALIST_2)
{
int port_num;
@@ -117,11 +120,9 @@ id_or_name2port(Process *c_p, Eterm id)
#define ERTS_PORT_COMMAND_FLAG_FORCE (((Uint32) 1) << 0)
#define ERTS_PORT_COMMAND_FLAG_NOSUSPEND (((Uint32) 1) << 1)
-static BIF_RETTYPE do_port_command(Process *BIF_P,
- Eterm BIF_ARG_1,
- Eterm BIF_ARG_2,
- Eterm BIF_ARG_3,
- Uint32 flags)
+static BIF_RETTYPE
+do_port_command(Process *BIF_P, Eterm arg1, Eterm arg2, Eterm arg3,
+ Uint32 flags)
{
BIF_RETTYPE res;
Port *p;
@@ -135,7 +136,7 @@ static BIF_RETTYPE do_port_command(Process *BIF_P,
profile_runnable_proc(BIF_P, am_inactive);
}
- p = id_or_name2port(BIF_P, BIF_ARG_1);
+ p = id_or_name2port(BIF_P, arg1);
if (!p) {
if (IS_TRACED_FL(BIF_P, F_TRACE_SCHED_PROCS)) {
trace_virtual_sched(BIF_P, am_in);
@@ -172,13 +173,13 @@ static BIF_RETTYPE do_port_command(Process *BIF_P,
monitor_generic(BIF_P, am_busy_port, p->id);
}
ERTS_BIF_PREP_YIELD3(res, bif_export[BIF_port_command_3], BIF_P,
- BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
+ arg1, arg2, arg3);
}
} else {
int wres;
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
ERTS_SMP_CHK_NO_PROC_LOCKS;
- wres = erts_write_to_port(BIF_P->id, p, BIF_ARG_2);
+ wres = erts_write_to_port(BIF_P->id, p, arg2);
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
if (wres != 0) {
ERTS_BIF_PREP_ERROR(res, BIF_P, BADARG);
@@ -237,11 +238,17 @@ BIF_RETTYPE port_command_3(BIF_ALIST_3)
BIF_RETTYPE port_call_2(BIF_ALIST_2)
{
- return port_call_3(BIF_P,BIF_ARG_1,make_small(0),BIF_ARG_2);
+ return port_call(BIF_P,BIF_ARG_1, make_small(0), BIF_ARG_2);
}
BIF_RETTYPE port_call_3(BIF_ALIST_3)
{
+ return port_call(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
+}
+
+static BIF_RETTYPE
+port_call(Process* c_p, Eterm arg1, Eterm arg2, Eterm arg3)
+{
Uint op;
Port *p;
Uint size;
@@ -266,15 +273,15 @@ BIF_RETTYPE port_call_3(BIF_ALIST_3)
/* trace of port scheduling with virtual process descheduling
* lock wait
*/
- if (IS_TRACED_FL(BIF_P, F_TRACE_SCHED_PROCS)) {
- trace_virtual_sched(BIF_P, am_out);
+ if (IS_TRACED_FL(c_p, F_TRACE_SCHED_PROCS)) {
+ trace_virtual_sched(c_p, am_out);
}
if (erts_system_profile_flags.runnable_procs && erts_system_profile_flags.exclusive) {
- profile_runnable_proc(BIF_P, am_inactive);
+ profile_runnable_proc(c_p, am_inactive);
}
- p = id_or_name2port(BIF_P, BIF_ARG_1);
+ p = id_or_name2port(c_p, arg1);
if (!p) {
error:
if (port_resp != port_result &&
@@ -286,22 +293,22 @@ BIF_RETTYPE port_call_3(BIF_ALIST_3)
/* Need to virtual schedule in the process if there
* was an error.
*/
- if (IS_TRACED_FL(BIF_P, F_TRACE_SCHED_PROCS)) {
- trace_virtual_sched(BIF_P, am_in);
+ if (IS_TRACED_FL(c_p, F_TRACE_SCHED_PROCS)) {
+ trace_virtual_sched(c_p, am_in);
}
if (erts_system_profile_flags.runnable_procs && erts_system_profile_flags.exclusive) {
- profile_runnable_proc(BIF_P, am_active);
+ profile_runnable_proc(c_p, am_active);
}
if (p)
erts_port_release(p);
#ifdef ERTS_SMP
- ERTS_SMP_BIF_CHK_PENDING_EXIT(BIF_P, ERTS_PROC_LOCK_MAIN);
+ ERTS_SMP_BIF_CHK_PENDING_EXIT(c_p, ERTS_PROC_LOCK_MAIN);
#else
- ERTS_BIF_CHK_EXITED(BIF_P);
+ ERTS_BIF_CHK_EXITED(c_p);
#endif
- BIF_ERROR(BIF_P, BADARG);
+ BIF_ERROR(c_p, BADARG);
}
if ((drv = p->drv_ptr) == NULL) {
@@ -310,10 +317,10 @@ BIF_RETTYPE port_call_3(BIF_ALIST_3)
if (drv->call == NULL) {
goto error;
}
- if (!term_to_Uint(BIF_ARG_2, &op)) {
+ if (!term_to_Uint(arg2, &op)) {
goto error;
}
- p->caller = BIF_P->id;
+ p->caller = c_p->id;
/* Lock taken, virtual schedule of port */
if (IS_TRACED_FL(p, F_TRACE_SCHED_PORTS)) {
@@ -323,19 +330,19 @@ BIF_RETTYPE port_call_3(BIF_ALIST_3)
if (erts_system_profile_flags.runnable_ports && !erts_port_is_scheduled(p)) {
profile_runnable_port(p, am_active);
}
- size = erts_encode_ext_size(BIF_ARG_3);
+ size = erts_encode_ext_size(arg3);
if (size > sizeof(port_input))
bytes = erts_alloc(ERTS_ALC_T_PORT_CALL_BUF, size);
endp = bytes;
- erts_encode_ext(BIF_ARG_3, &endp);
+ erts_encode_ext(arg3, &endp);
real_size = endp - bytes;
if (real_size > size) {
erl_exit(1, "%s, line %d: buffer overflow: %d word(s)\n",
__FILE__, __LINE__, endp - (bytes + size));
}
- erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
+ erts_smp_proc_unlock(c_p, ERTS_PROC_LOCK_MAIN);
prc = (char *) port_resp;
fpe_was_unmasked = erts_block_fpe();
ret = drv->call((ErlDrvData)p->drv_data,
@@ -356,7 +363,7 @@ BIF_RETTYPE port_call_3(BIF_ALIST_3)
port_resp = (byte *) prc;
p->caller = NIL;
- erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
+ erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_MAIN);
#ifdef HARDDEBUG
{
int z;
@@ -378,18 +385,18 @@ BIF_RETTYPE port_call_3(BIF_ALIST_3)
/* Error or a binary without magic/ with wrong magic */
goto error;
}
- result_size = erts_decode_ext_size(port_resp, ret, 0);
+ result_size = erts_decode_ext_size(port_resp, ret);
if (result_size < 0) {
goto error;
}
- hp = HAlloc(BIF_P, result_size);
+ hp = HAlloc(c_p, result_size);
hp_end = hp + result_size;
endp = port_resp;
- res = erts_decode_ext(&hp, &MSO(BIF_P), &endp);
+ res = erts_decode_ext(&hp, &MSO(c_p), &endp);
if (res == THE_NON_VALUE) {
goto error;
}
- HRelease(BIF_P, hp_end, hp);
+ HRelease(c_p, hp_end, hp);
if (port_resp != port_result && !(ret_flags & DRIVER_CALL_KEEP_BUFFER)) {
driver_free(port_resp);
}
@@ -398,16 +405,16 @@ BIF_RETTYPE port_call_3(BIF_ALIST_3)
if (p)
erts_port_release(p);
#ifdef ERTS_SMP
- ERTS_SMP_BIF_CHK_PENDING_EXIT(BIF_P, ERTS_PROC_LOCK_MAIN);
+ ERTS_SMP_BIF_CHK_PENDING_EXIT(c_p, ERTS_PROC_LOCK_MAIN);
#else
- ERTS_BIF_CHK_EXITED(BIF_P);
+ ERTS_BIF_CHK_EXITED(c_p);
#endif
- if (IS_TRACED_FL(BIF_P, F_TRACE_SCHED_PROCS)) {
- trace_virtual_sched(BIF_P, am_in);
+ if (IS_TRACED_FL(c_p, F_TRACE_SCHED_PROCS)) {
+ trace_virtual_sched(c_p, am_in);
}
if (erts_system_profile_flags.runnable_procs && erts_system_profile_flags.exclusive) {
- profile_runnable_proc(BIF_P, am_active);
+ profile_runnable_proc(c_p, am_active);
}
return res;
diff --git a/erts/emulator/beam/erl_bif_re.c b/erts/emulator/beam/erl_bif_re.c
index 26891c4348..6b843d2e08 100644
--- a/erts/emulator/beam/erl_bif_re.c
+++ b/erts/emulator/beam/erl_bif_re.c
@@ -45,6 +45,7 @@ static Export *urun_trap_exportp = NULL;
static Export *ucompile_trap_exportp = NULL;
static BIF_RETTYPE re_exec_trap(BIF_ALIST_3);
+static BIF_RETTYPE re_run(Process *p, Eterm arg1, Eterm arg2, Eterm arg3);
static void *erts_erts_pcre_malloc(size_t size) {
return erts_alloc(ERTS_ALC_T_RE_HEAP,size);
@@ -414,8 +415,8 @@ build_compile_result(Process *p, Eterm error_tag, pcre *result, int errcode, con
* Compile BIFs
*/
-BIF_RETTYPE
-re_compile_2(BIF_ALIST_2)
+static BIF_RETTYPE
+re_compile(Process* p, Eterm arg1, Eterm arg2)
{
Uint slen;
char *expr;
@@ -429,43 +430,49 @@ re_compile_2(BIF_ALIST_2)
int unicode = 0;
- if (parse_options(BIF_ARG_2,&options,NULL,&pflags,NULL,NULL)
+ if (parse_options(arg2,&options,NULL,&pflags,NULL,NULL)
< 0) {
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
if (pflags & PARSE_FLAG_UNIQUE_EXEC_OPT) {
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
unicode = (pflags & PARSE_FLAG_UNICODE) ? 1 : 0;
- if (pflags & PARSE_FLAG_UNICODE && !is_binary(BIF_ARG_1)) {
- BIF_TRAP2(ucompile_trap_exportp, BIF_P, BIF_ARG_1, BIF_ARG_2);
+ if (pflags & PARSE_FLAG_UNICODE && !is_binary(arg1)) {
+ BIF_TRAP2(ucompile_trap_exportp, p, arg1, arg2);
}
- if (erts_iolist_size(BIF_ARG_1, &slen)) {
- BIF_ERROR(BIF_P,BADARG);
+ if (erts_iolist_size(arg1, &slen)) {
+ BIF_ERROR(p,BADARG);
}
expr = erts_alloc(ERTS_ALC_T_RE_TMP_BUF, slen + 1);
- if (io_list_to_buf(BIF_ARG_1, expr, slen) != 0) {
+ if (io_list_to_buf(arg1, expr, slen) != 0) {
erts_free(ERTS_ALC_T_RE_TMP_BUF, expr);
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
expr[slen]='\0';
result = erts_pcre_compile2(expr, options, &errcode,
&errstr, &errofset, default_table);
- ret = build_compile_result(BIF_P, am_error, result, errcode,
+ ret = build_compile_result(p, am_error, result, errcode,
errstr, errofset, unicode, 1);
erts_free(ERTS_ALC_T_RE_TMP_BUF, expr);
BIF_RET(ret);
}
BIF_RETTYPE
+re_compile_2(BIF_ALIST_2)
+{
+ return re_compile(BIF_P, BIF_ARG_1, BIF_ARG_2);
+}
+
+BIF_RETTYPE
re_compile_1(BIF_ALIST_1)
{
- return re_compile_2(BIF_P,BIF_ARG_1,NIL);
+ return re_compile(BIF_P, BIF_ARG_1, NIL);
}
/*
@@ -845,8 +852,8 @@ build_capture(Eterm capture_spec[CAPSPEC_SIZE], const pcre *code)
/*
* The actual re:run/2,3 BIFs
*/
-BIF_RETTYPE
-re_run_3(BIF_ALIST_3)
+static BIF_RETTYPE
+re_run(Process *p, Eterm arg1, Eterm arg2, Eterm arg3)
{
const pcre *code_tmp;
RestartContext restart;
@@ -865,15 +872,15 @@ re_run_3(BIF_ALIST_3)
Eterm capture[CAPSPEC_SIZE];
int is_list_cap;
- if (parse_options(BIF_ARG_3,&comp_options,&options,&pflags,&startoffset,capture)
+ if (parse_options(arg3,&comp_options,&options,&pflags,&startoffset,capture)
< 0) {
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
is_list_cap = ((pflags & PARSE_FLAG_CAPTURE_OPT) &&
(capture[CAPSPEC_TYPE] == am_list));
- if (is_not_tuple(BIF_ARG_2) || (arityval(*tuple_val(BIF_ARG_2)) != 4)) {
- if (is_binary(BIF_ARG_2) || is_list(BIF_ARG_2) || is_nil(BIF_ARG_2)) {
+ if (is_not_tuple(arg2) || (arityval(*tuple_val(arg2)) != 4)) {
+ if (is_binary(arg2) || is_list(arg2) || is_nil(arg2)) {
/* Compile from textual RE */
Uint slen;
char *expr;
@@ -884,19 +891,19 @@ re_run_3(BIF_ALIST_3)
int capture_count;
if (pflags & PARSE_FLAG_UNICODE &&
- (!is_binary(BIF_ARG_2) || !is_binary(BIF_ARG_1) ||
+ (!is_binary(arg2) || !is_binary(arg1) ||
(is_list_cap && !(pflags & PARSE_FLAG_GLOBAL)))) {
- BIF_TRAP3(urun_trap_exportp, BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
+ BIF_TRAP3(urun_trap_exportp, p, arg1, arg2, arg3);
}
- if (erts_iolist_size(BIF_ARG_2, &slen)) {
- BIF_ERROR(BIF_P,BADARG);
+ if (erts_iolist_size(arg2, &slen)) {
+ BIF_ERROR(p,BADARG);
}
expr = erts_alloc(ERTS_ALC_T_RE_TMP_BUF, slen + 1);
- if (io_list_to_buf(BIF_ARG_2, expr, slen) != 0) {
+ if (io_list_to_buf(arg2, expr, slen) != 0) {
erts_free(ERTS_ALC_T_RE_TMP_BUF, expr);
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
expr[slen]='\0';
result = erts_pcre_compile2(expr, comp_options, &errcode,
@@ -905,11 +912,11 @@ re_run_3(BIF_ALIST_3)
erts_free(ERTS_ALC_T_RE_TMP_BUF, expr);
/* Compilation error gives badarg except in the compile
function */
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
if (pflags & PARSE_FLAG_GLOBAL) {
Eterm precompiled =
- build_compile_result(BIF_P, am_error,
+ build_compile_result(p, am_error,
result, errcode,
errstr, errofset,
(pflags &
@@ -917,13 +924,13 @@ re_run_3(BIF_ALIST_3)
0);
Eterm *hp,r;
erts_free(ERTS_ALC_T_RE_TMP_BUF, expr);
- hp = HAlloc(BIF_P,4);
- /* BIF_ARG_2 is in the tuple just to make exceptions right */
- r = TUPLE3(hp,BIF_ARG_3,
+ hp = HAlloc(p,4);
+ /* arg2 is in the tuple just to make exceptions right */
+ r = TUPLE3(hp,arg3,
((pflags & PARSE_FLAG_UNIQUE_COMPILE_OPT) ?
am_true :
- am_false), BIF_ARG_2);
- BIF_TRAP3(grun_trap_exportp, BIF_P, BIF_ARG_1, precompiled, r);
+ am_false), arg2);
+ BIF_TRAP3(grun_trap_exportp, p, arg1, precompiled, r);
}
erts_pcre_fullinfo(result, NULL, PCRE_INFO_SIZE, &code_size);
@@ -935,31 +942,31 @@ re_run_3(BIF_ALIST_3)
erts_free(ERTS_ALC_T_RE_TMP_BUF, expr);
/*unicode = (pflags & PARSE_FLAG_UNICODE) ? 1 : 0;*/
} else {
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
} else {
if (pflags & PARSE_FLAG_UNIQUE_COMPILE_OPT) {
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
- tp = tuple_val(BIF_ARG_2);
+ tp = tuple_val(arg2);
if (tp[1] != am_re_pattern || is_not_small(tp[2]) ||
is_not_small(tp[3]) || is_not_binary(tp[4])) {
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
if (unsigned_val(tp[3]) &&
- (!is_binary(BIF_ARG_1) ||
+ (!is_binary(arg1) ||
(is_list_cap && !(pflags & PARSE_FLAG_GLOBAL)))) { /* unicode */
- BIF_TRAP3(urun_trap_exportp, BIF_P, BIF_ARG_1, BIF_ARG_2,
- BIF_ARG_3);
+ BIF_TRAP3(urun_trap_exportp, p, arg1, arg2,
+ arg3);
}
if (pflags & PARSE_FLAG_GLOBAL) {
Eterm *hp,r;
- hp = HAlloc(BIF_P,3);
- r = TUPLE2(hp,BIF_ARG_3,am_false);
- BIF_TRAP3(grun_trap_exportp, BIF_P, BIF_ARG_1, BIF_ARG_2,
+ hp = HAlloc(p,3);
+ r = TUPLE2(hp,arg3,am_false);
+ BIF_TRAP3(grun_trap_exportp, p, arg1, arg2,
r);
}
@@ -968,7 +975,7 @@ re_run_3(BIF_ALIST_3)
if ((code_tmp = (const pcre *)
erts_get_aligned_binary_bytes(tp[4], &temp_alloc)) == NULL) {
erts_free_aligned_binary_bytes(temp_alloc);
- BIF_ERROR(BIF_P, BADARG);
+ BIF_ERROR(p, BADARG);
}
restart.code = erts_alloc(ERTS_ALC_T_RE_SUBJECT, code_size);
memcpy(restart.code, code_tmp, code_size);
@@ -980,7 +987,7 @@ re_run_3(BIF_ALIST_3)
restart.ovector = erts_alloc(ERTS_ALC_T_RE_SUBJECT, ovsize * sizeof(int));
restart.extra.flags = PCRE_EXTRA_TABLES | PCRE_EXTRA_LOOP_LIMIT;
restart.extra.tables = default_table;
- restart.extra.loop_limit = ERTS_BIF_REDS_LEFT(BIF_P) * LOOP_FACTOR;
+ restart.extra.loop_limit = ERTS_BIF_REDS_LEFT(p) * LOOP_FACTOR;
loop_limit_tmp = max_loop_limit; /* To lesser probability of race in debug
situation (erts_debug) */
if (restart.extra.loop_limit > loop_limit_tmp) {
@@ -996,7 +1003,7 @@ re_run_3(BIF_ALIST_3)
if ((restart.ret_info = build_capture(capture,restart.code)) == NULL) {
erts_free(ERTS_ALC_T_RE_SUBJECT, restart.ovector);
erts_free(ERTS_ALC_T_RE_SUBJECT, restart.code);
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
}
@@ -1004,7 +1011,7 @@ re_run_3(BIF_ALIST_3)
copying, also binary returns can be sub binaries in that case */
restart.flags = 0;
- if (is_binary(BIF_ARG_1)) {
+ if (is_binary(arg1)) {
Eterm real_bin;
Uint offset;
Eterm* bptr;
@@ -1012,9 +1019,9 @@ re_run_3(BIF_ALIST_3)
int bitsize;
ProcBin* pb;
- ERTS_GET_REAL_BIN(BIF_ARG_1, real_bin, offset, bitoffs, bitsize);
+ ERTS_GET_REAL_BIN(arg1, real_bin, offset, bitoffs, bitsize);
- slength = binary_size(BIF_ARG_1);
+ slength = binary_size(arg1);
bptr = binary_val(real_bin);
if (bitsize != 0 || bitoffs != 0 || (*bptr != HEADER_PROC_BIN)) {
goto handle_iolist;
@@ -1027,24 +1034,24 @@ re_run_3(BIF_ALIST_3)
restart.flags |= RESTART_FLAG_SUBJECT_IN_BINARY;
} else {
handle_iolist:
- if (erts_iolist_size(BIF_ARG_1, &slength)) {
+ if (erts_iolist_size(arg1, &slength)) {
erts_free(ERTS_ALC_T_RE_SUBJECT, restart.ovector);
erts_free(ERTS_ALC_T_RE_SUBJECT, restart.code);
if (restart.ret_info != NULL) {
erts_free(ERTS_ALC_T_RE_SUBJECT, restart.ret_info);
}
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
restart.subject = erts_alloc(ERTS_ALC_T_RE_SUBJECT, slength);
- if (io_list_to_buf(BIF_ARG_1, restart.subject, slength) != 0) {
+ if (io_list_to_buf(arg1, restart.subject, slength) != 0) {
erts_free(ERTS_ALC_T_RE_SUBJECT, restart.ovector);
erts_free(ERTS_ALC_T_RE_SUBJECT, restart.code);
erts_free(ERTS_ALC_T_RE_SUBJECT, restart.subject);
if (restart.ret_info != NULL) {
erts_free(ERTS_ALC_T_RE_SUBJECT, restart.ret_info);
}
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
}
@@ -1056,7 +1063,7 @@ handle_iolist:
rc = erts_pcre_exec(restart.code, &(restart.extra), restart.subject, slength, startoffset,
options, restart.ovector, ovsize);
ASSERT(loop_count != 0xFFFFFFFF);
- BUMP_REDS(BIF_P, loop_count / LOOP_FACTOR);
+ BUMP_REDS(p, loop_count / LOOP_FACTOR);
if (rc == PCRE_ERROR_LOOP_LIMIT) {
/* Trap */
Binary *mbp = erts_create_magic_binary(sizeof(RestartContext),
@@ -1065,17 +1072,17 @@ handle_iolist:
Eterm magic_bin;
Eterm *hp;
memcpy(restartp,&restart,sizeof(RestartContext));
- BUMP_ALL_REDS(BIF_P);
- hp = HAlloc(BIF_P, PROC_BIN_SIZE);
- magic_bin = erts_mk_magic_binary_term(&hp, &MSO(BIF_P), mbp);
+ BUMP_ALL_REDS(p);
+ hp = HAlloc(p, PROC_BIN_SIZE);
+ magic_bin = erts_mk_magic_binary_term(&hp, &MSO(p), mbp);
BIF_TRAP3(&re_exec_trap_export,
- BIF_P,
- BIF_ARG_1,
- BIF_ARG_2 /* To avoid GC of precompiled code, XXX: not utilized yet */,
+ p,
+ arg1,
+ arg2 /* To avoid GC of precompiled code, XXX: not utilized yet */,
magic_bin);
}
- res = build_exec_return(BIF_P, rc, &restart, BIF_ARG_1);
+ res = build_exec_return(p, rc, &restart, arg1);
cleanup_restart_context(&restart);
@@ -1083,9 +1090,15 @@ handle_iolist:
}
BIF_RETTYPE
+re_run_3(BIF_ALIST_3)
+{
+ return re_run(BIF_P,BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
+}
+
+BIF_RETTYPE
re_run_2(BIF_ALIST_2)
{
- return re_run_3(BIF_P,BIF_ARG_1, BIF_ARG_2, NIL);
+ return re_run(BIF_P,BIF_ARG_1, BIF_ARG_2, NIL);
}
/*
diff --git a/erts/emulator/beam/erl_bif_timer.c b/erts/emulator/beam/erl_bif_timer.c
index db771bd216..a922a33da3 100644
--- a/erts/emulator/beam/erl_bif_timer.c
+++ b/erts/emulator/beam/erl_bif_timer.c
@@ -26,6 +26,7 @@
#include "bif.h"
#include "error.h"
#include "big.h"
+#include "erl_thr_progress.h"
/****************************************************************************
** BIF Timer support
@@ -686,7 +687,7 @@ erts_bif_timer_foreach(void (*func)(Eterm, Eterm, ErlHeapFragment *, void *),
{
int i;
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
for (i = 0; i < TIMER_HASH_VEC_SZ; i++) {
ErtsBifTimer *btm;
diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c
index 0509e51a6f..b0a58c80ea 100644
--- a/erts/emulator/beam/erl_bif_trace.c
+++ b/erts/emulator/beam/erl_bif_trace.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1999-2010. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -37,6 +37,7 @@
#include "erl_version.h"
#include "beam_bp.h"
#include "erl_binary.h"
+#include "erl_thr_progress.h"
#define DECL_AM(S) Eterm AM_ ## S = am_atom_put(#S, sizeof(#S) - 1)
@@ -47,6 +48,11 @@ static Binary *erts_default_meta_match_spec;
static struct trace_pattern_flags erts_default_trace_pattern_flags;
static Eterm erts_default_meta_tracer_pid;
+static Eterm
+trace_pattern(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist);
+static BIF_RETTYPE
+system_monitor(Process *p, Eterm monitor_pid, Eterm list);
+
static void new_seq_trace_token(Process* p); /* help func for seq_trace_2*/
static int already_traced(Process *p, Process *tracee_p, Eterm tracer);
static int port_already_traced(Process *p, Port *tracee_port, Eterm tracer);
@@ -76,13 +82,19 @@ erts_bif_trace_init(void)
*/
Eterm
-trace_pattern_2(Process* p, Eterm MFA, Eterm Pattern)
+trace_pattern_2(BIF_ALIST_2)
{
- return trace_pattern_3(p,MFA,Pattern,NIL);
+ return trace_pattern(BIF_P, BIF_ARG_1, BIF_ARG_2, NIL);
}
Eterm
-trace_pattern_3(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist)
+trace_pattern_3(BIF_ALIST_3)
+{
+ return trace_pattern(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
+}
+
+static Eterm
+trace_pattern(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist)
{
DeclareTmpHeap(mfa,3,p); /* Not really heap here, but might be when setting pattern */
int i;
@@ -97,7 +109,7 @@ trace_pattern_3(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist)
Eterm meta_tracer_pid = p->id;
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
UseTmpHeap(3,p);
/*
@@ -326,7 +338,7 @@ trace_pattern_3(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist)
done:
UnUseTmpHeap(3,p);
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
return make_small(matches);
@@ -336,7 +348,7 @@ trace_pattern_3(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist)
MatchSetUnref(match_prog_set);
UnUseTmpHeap(3,p);
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
BIF_ERROR(p, BADARG);
}
@@ -435,9 +447,12 @@ erts_trace_flags(Eterm List,
return 0;
}
-Eterm
-trace_3(Process* p, Eterm pid_spec, Eterm how, Eterm list)
+Eterm trace_3(BIF_ALIST_3)
{
+ Process* p = BIF_P;
+ Eterm pid_spec = BIF_ARG_1;
+ Eterm how = BIF_ARG_2;
+ Eterm list = BIF_ARG_3;
int on;
Eterm tracer = NIL;
int matches = 0;
@@ -630,7 +645,7 @@ trace_3(Process* p, Eterm pid_spec, Eterm how, Eterm list)
#ifdef ERTS_SMP
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
system_blocked = 1;
#endif
@@ -679,7 +694,7 @@ trace_3(Process* p, Eterm pid_spec, Eterm how, Eterm list)
} else if (tracer != NIL) {
tracee_port->tracer_proc = tracer;
}
- /* matches are not counted for ports since it would violate compability */
+ /* matches are not counted for ports since it would violate compatibility */
/* This could be a reason to modify this function or make a new one. */
}
}
@@ -711,7 +726,7 @@ trace_3(Process* p, Eterm pid_spec, Eterm how, Eterm list)
#ifdef ERTS_SMP
if (system_blocked) {
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
}
#endif
@@ -726,7 +741,7 @@ trace_3(Process* p, Eterm pid_spec, Eterm how, Eterm list)
#ifdef ERTS_SMP
if (system_blocked) {
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
}
#endif
@@ -820,9 +835,11 @@ static int already_traced(Process *c_p, Process *tracee_p, Eterm tracer)
* Return information about a process or an external function being traced.
*/
-Eterm
-trace_info_2(Process* p, Eterm What, Eterm Key)
+Eterm trace_info_2(BIF_ALIST_2)
{
+ Process* p = BIF_P;
+ Eterm What = BIF_ARG_1;
+ Eterm Key = BIF_ARG_2;
Eterm res;
if (What == am_on_load) {
res = trace_info_on_load(p, Key);
@@ -1060,7 +1077,7 @@ trace_info_func(Process* p, Eterm func_spec, Eterm key)
#ifdef ERTS_SMP
if ( (key == am_call_time) || (key == am_all)) {
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
}
#endif
@@ -1068,7 +1085,7 @@ trace_info_func(Process* p, Eterm func_spec, Eterm key)
#ifdef ERTS_SMP
if ( (key == am_call_time) || (key == am_all)) {
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
}
#endif
@@ -1752,23 +1769,20 @@ new_seq_trace_token(Process* p)
}
}
-BIF_RETTYPE seq_trace_info_1(BIF_ALIST_1)
+BIF_RETTYPE erl_seq_trace_info(Process *p, Eterm item)
{
- Eterm item;
Eterm res;
Eterm* hp;
Uint current_flag;
- if (is_not_atom(BIF_ARG_1)) {
- BIF_ERROR(BIF_P, BADARG);
+ if (is_not_atom(item)) {
+ BIF_ERROR(p, BADARG);
}
- item = BIF_ARG_1;
-
- if (SEQ_TRACE_TOKEN(BIF_P) == NIL) {
+ if (SEQ_TRACE_TOKEN(p) == NIL) {
if ((item == am_send) || (item == am_receive) ||
(item == am_print) || (item == am_timestamp)) {
- hp = HAlloc(BIF_P,3);
+ hp = HAlloc(p,3);
res = TUPLE2(hp, item, am_false);
BIF_RET(res);
} else if ((item == am_label) || (item == am_serial)) {
@@ -1778,35 +1792,40 @@ BIF_RETTYPE seq_trace_info_1(BIF_ALIST_1)
}
}
- if (BIF_ARG_1 == am_send) {
+ if (item == am_send) {
current_flag = SEQ_TRACE_SEND;
- } else if (BIF_ARG_1 == am_receive) {
+ } else if (item == am_receive) {
current_flag = SEQ_TRACE_RECEIVE;
- } else if (BIF_ARG_1 == am_print) {
+ } else if (item == am_print) {
current_flag = SEQ_TRACE_PRINT;
- } else if (BIF_ARG_1 == am_timestamp) {
+ } else if (item == am_timestamp) {
current_flag = SEQ_TRACE_TIMESTAMP;
} else {
current_flag = 0;
}
if (current_flag) {
- res = unsigned_val(SEQ_TRACE_TOKEN_FLAGS(BIF_P)) & current_flag ?
+ res = unsigned_val(SEQ_TRACE_TOKEN_FLAGS(p)) & current_flag ?
am_true : am_false;
} else if (item == am_label) {
- res = SEQ_TRACE_TOKEN_LABEL(BIF_P);
+ res = SEQ_TRACE_TOKEN_LABEL(p);
} else if (item == am_serial) {
- hp = HAlloc(BIF_P, 3);
- res = TUPLE2(hp, SEQ_TRACE_TOKEN_LASTCNT(BIF_P), SEQ_TRACE_TOKEN_SERIAL(BIF_P));
+ hp = HAlloc(p, 3);
+ res = TUPLE2(hp, SEQ_TRACE_TOKEN_LASTCNT(p), SEQ_TRACE_TOKEN_SERIAL(p));
} else {
error:
- BIF_ERROR(BIF_P, BADARG);
+ BIF_ERROR(p, BADARG);
}
- hp = HAlloc(BIF_P, 3);
+ hp = HAlloc(p, 3);
res = TUPLE2(hp, item, res);
BIF_RET(res);
}
+BIF_RETTYPE seq_trace_info_1(BIF_ALIST_1)
+{
+ BIF_RET(erl_seq_trace_info(BIF_P, BIF_ARG_1));
+}
+
/*
seq_trace_print(Message) -> true | false
This function passes Message to the system_tracer
@@ -1852,7 +1871,7 @@ void erts_system_monitor_clear(Process *c_p) {
#ifdef ERTS_SMP
if (c_p) {
erts_smp_proc_unlock(c_p, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
}
#endif
erts_set_system_monitor(NIL);
@@ -1862,7 +1881,7 @@ void erts_system_monitor_clear(Process *c_p) {
erts_system_monitor_flags.busy_dist_port = 0;
#ifdef ERTS_SMP
if (c_p) {
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_MAIN);
}
#endif
@@ -1919,23 +1938,35 @@ static Eterm system_monitor_get(Process *p)
}
-BIF_RETTYPE system_monitor_0(Process *p) {
- BIF_RET(system_monitor_get(p));
+BIF_RETTYPE system_monitor_0(BIF_ALIST_0)
+{
+ BIF_RET(system_monitor_get(BIF_P));
}
-BIF_RETTYPE system_monitor_1(Process *p, Eterm spec) {
+BIF_RETTYPE system_monitor_1(BIF_ALIST_1)
+{
+ Process* p = BIF_P;
+ Eterm spec = BIF_ARG_1;
+
if (spec == am_undefined) {
- BIF_RET(system_monitor_2(p, spec, NIL));
+ BIF_RET(system_monitor(p, spec, NIL));
} else if (is_tuple(spec)) {
Eterm *tp = tuple_val(spec);
if (tp[0] != make_arityval(2)) goto error;
- BIF_RET(system_monitor_2(p, tp[1], tp[2]));
+ BIF_RET(system_monitor(p, tp[1], tp[2]));
}
error:
BIF_ERROR(p, BADARG);
}
-BIF_RETTYPE system_monitor_2(Process *p, Eterm monitor_pid, Eterm list) {
+BIF_RETTYPE system_monitor_2(BIF_ALIST_2)
+{
+ return system_monitor(BIF_P, BIF_ARG_1, BIF_ARG_2);
+}
+
+static BIF_RETTYPE
+system_monitor(Process *p, Eterm monitor_pid, Eterm list)
+{
Eterm prev;
int system_blocked = 0;
@@ -1951,7 +1982,7 @@ BIF_RETTYPE system_monitor_2(Process *p, Eterm monitor_pid, Eterm list) {
system_blocked = 1;
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
if (!erts_pid2proc(p, ERTS_PROC_LOCK_MAIN, monitor_pid, 0))
goto error;
@@ -1985,7 +2016,7 @@ BIF_RETTYPE system_monitor_2(Process *p, Eterm monitor_pid, Eterm list) {
erts_system_monitor_flags.busy_port = !!busy_port;
erts_system_monitor_flags.busy_dist_port = !!busy_dist_port;
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
BIF_RET(prev);
}
@@ -1993,7 +2024,7 @@ BIF_RETTYPE system_monitor_2(Process *p, Eterm monitor_pid, Eterm list) {
error:
if (system_blocked) {
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
}
@@ -2006,7 +2037,7 @@ void erts_system_profile_clear(Process *c_p) {
#ifdef ERTS_SMP
if (c_p) {
erts_smp_proc_unlock(c_p, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
}
#endif
erts_set_system_profile(NIL);
@@ -2016,7 +2047,7 @@ void erts_system_profile_clear(Process *c_p) {
erts_system_profile_flags.exclusive = 0;
#ifdef ERTS_SMP
if (c_p) {
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_MAIN);
}
#endif
@@ -2053,11 +2084,16 @@ static Eterm system_profile_get(Process *p) {
}
}
-BIF_RETTYPE system_profile_0(Process *p) {
- BIF_RET(system_profile_get(p));
+BIF_RETTYPE system_profile_0(BIF_ALIST_0)
+{
+ BIF_RET(system_profile_get(BIF_P));
}
-BIF_RETTYPE system_profile_2(Process *p, Eterm profiler, Eterm list) {
+BIF_RETTYPE system_profile_2(BIF_ALIST_2)
+{
+ Process *p = BIF_P;
+ Eterm profiler = BIF_ARG_1;
+ Eterm list = BIF_ARG_2;
Eterm prev;
int system_blocked = 0;
Process *profiler_p = NULL;
@@ -2075,7 +2111,7 @@ BIF_RETTYPE system_profile_2(Process *p, Eterm profiler, Eterm list) {
system_blocked = 1;
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
/* Check if valid process, no locks are taken */
@@ -2117,7 +2153,7 @@ BIF_RETTYPE system_profile_2(Process *p, Eterm profiler, Eterm list) {
erts_system_profile_flags.runnable_procs = !!runnable_procs;
erts_system_profile_flags.exclusive = !!exclusive;
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
BIF_RET(prev);
@@ -2126,7 +2162,7 @@ BIF_RETTYPE system_profile_2(Process *p, Eterm profiler, Eterm list) {
error:
if (system_blocked) {
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
}
diff --git a/erts/emulator/beam/erl_bits.c b/erts/emulator/beam/erl_bits.c
index e56084b9cb..6f7309f493 100644
--- a/erts/emulator/beam/erl_bits.c
+++ b/erts/emulator/beam/erl_bits.c
@@ -76,14 +76,12 @@ struct erl_bits_state ErlBitsState;
#define byte_buf (ErlBitsState.byte_buf_)
#define byte_buf_len (ErlBitsState.byte_buf_len_)
-#ifdef ERTS_SMP
static erts_smp_atomic_t bits_bufs_size;
-#endif
Uint
erts_bits_bufs_size(void)
{
- return 0;
+ return (Uint) erts_smp_atomic_read_nob(&bits_bufs_size);
}
#if !defined(ERTS_SMP)
@@ -109,8 +107,8 @@ erts_bits_destroy_state(ERL_BITS_PROTO_0)
void
erts_init_bits(void)
{
+ erts_smp_atomic_init_nob(&bits_bufs_size, 0);
#if defined(ERTS_SMP)
- erts_smp_atomic_init(&bits_bufs_size, 0);
/* erl_process.c calls erts_bits_init_state() on all state instances */
#else
ERL_BITS_DECLARE_STATEP;
@@ -713,9 +711,7 @@ static void
ERTS_INLINE need_byte_buf(ERL_BITS_PROTO_1(int need))
{
if (byte_buf_len < need) {
-#ifdef ERTS_SMP
- erts_smp_atomic_add(&bits_bufs_size, need - byte_buf_len);
-#endif
+ erts_smp_atomic_add_nob(&bits_bufs_size, need - byte_buf_len);
byte_buf_len = need;
byte_buf = erts_realloc(ERTS_ALC_T_BITS_BUF, byte_buf, byte_buf_len);
}
@@ -849,8 +845,7 @@ erts_bs_put_utf8(ERL_BITS_PROTO_1(Eterm arg))
dst[1] = 0x80 | (val & 0x3F);
num_bits = 16;
} else if (val < 0x10000UL) {
- if ((0xD800 <= val && val <= 0xDFFF) ||
- val == 0xFFFE || val == 0xFFFF) {
+ if (0xD800 <= val && val <= 0xDFFF) {
return 0;
}
dst[0] = 0xE0 | (val >> 12);
@@ -890,8 +885,7 @@ erts_bs_put_utf16(ERL_BITS_PROTO_2(Eterm arg, Uint flags))
return 0;
}
val = unsigned_val(arg);
- if (val > 0x10FFFF || (0xD800 <= val && val <= 0xDFFF) ||
- val == 0xFFFE || val == 0xFFFF) {
+ if (val > 0x10FFFF || (0xD800 <= val && val <= 0xDFFF)) {
return 0;
}
@@ -1656,8 +1650,7 @@ erts_bs_get_utf8(ErlBinMatchBuffer* mb)
return THE_NON_VALUE;
}
result = (((result << 6) + a) << 6) + b - (Eterm) 0x000E2080UL;
- if ((0xD800 <= result && result <= 0xDFFF) ||
- result == 0xFFFE || result == 0xFFFF) {
+ if (0xD800 <= result && result <= 0xDFFF) {
return THE_NON_VALUE;
}
mb->offset += 24;
@@ -1727,9 +1720,6 @@ erts_bs_get_utf16(ErlBinMatchBuffer* mb, Uint flags)
w1 = (src[0] << 8) | src[1];
}
if (w1 < 0xD800 || w1 > 0xDFFF) {
- if (w1 == 0xFFFE || w1 == 0xFFFF) {
- return THE_NON_VALUE;
- }
mb->offset += 16;
return make_small(w1);
} else if (w1 > 0xDBFF) {
diff --git a/erts/emulator/beam/erl_bits.h b/erts/emulator/beam/erl_bits.h
index 0f67733fa4..388d943755 100644
--- a/erts/emulator/beam/erl_bits.h
+++ b/erts/emulator/beam/erl_bits.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1999-2010. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -150,7 +150,7 @@ void erts_bits_destroy_state(ERL_BITS_PROTO_0);
* NBYTES(x) returns the number of bytes needed to store x bits.
*/
-#define NBYTES(x) (((x) + 7) >> 3)
+#define NBYTES(x) (((Uint64)(x) + (Uint64) 7) >> 3)
#define BYTE_OFFSET(ofs) ((Uint) (ofs) >> 3)
#define BIT_OFFSET(ofs) ((ofs) & 7)
diff --git a/erts/emulator/beam/erl_cpu_topology.c b/erts/emulator/beam/erl_cpu_topology.c
index bcf8bcf270..03c0ef904a 100644
--- a/erts/emulator/beam/erl_cpu_topology.c
+++ b/erts/emulator/beam/erl_cpu_topology.c
@@ -487,7 +487,7 @@ erts_sched_check_cpu_bind_post_suspend(ErtsSchedulerData *esdp)
/* Make sure we check if we should bind to a cpu or not... */
if (esdp->run_queue->flags & ERTS_RUNQ_FLG_SHARED_RUNQ)
- erts_smp_atomic32_set(&esdp->chk_cpu_bind, 1);
+ erts_smp_atomic32_set_nob(&esdp->chk_cpu_bind, 1);
else
esdp->run_queue->flags |= ERTS_RUNQ_FLG_CHK_CPU_BIND;
}
@@ -503,7 +503,7 @@ erts_sched_check_cpu_bind(ErtsSchedulerData *esdp)
erts_cpu_groups_callback_call_t *cgcc;
#ifdef ERTS_SMP
if (erts_common_run_queue)
- erts_smp_atomic32_set(&esdp->chk_cpu_bind, 0);
+ erts_smp_atomic32_set_nob(&esdp->chk_cpu_bind, 0);
else {
esdp->run_queue->flags &= ~ERTS_RUNQ_FLG_CHK_CPU_BIND;
}
diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c
index eb50f56502..0079c13287 100644
--- a/erts/emulator/beam/erl_db.c
+++ b/erts/emulator/beam/erl_db.c
@@ -129,8 +129,6 @@ static Uint meta_main_tab_slot_mask; /* The slot index part of an unnamed tab
static Uint meta_main_tab_seq_incr;
static Uint meta_main_tab_seq_cnt = 0; /* To give unique(-ish) table identifiers */
-
-
/*
** The meta hash table of all NAMED ets tables
*/
@@ -202,12 +200,17 @@ static int free_table_cont(Process *p,
int first,
int clean_meta_tab);
static void print_table(int to, void *to_arg, int show, DbTable* tb);
-static BIF_RETTYPE ets_select_delete_1(Process *p, Eterm a1);
-static BIF_RETTYPE ets_select_count_1(Process *p, Eterm a1);
-static BIF_RETTYPE ets_select_trap_1(Process *p, Eterm a1);
-static BIF_RETTYPE ets_delete_trap(Process *p, Eterm a1);
+static BIF_RETTYPE ets_select_delete_1(BIF_ALIST_1);
+static BIF_RETTYPE ets_select_count_1(BIF_ALIST_1);
+static BIF_RETTYPE ets_select_trap_1(BIF_ALIST_1);
+static BIF_RETTYPE ets_delete_trap(BIF_ALIST_1);
static Eterm table_info(Process* p, DbTable* tb, Eterm What);
+static BIF_RETTYPE ets_select1(Process* p, Eterm arg1);
+static BIF_RETTYPE ets_select2(Process* p, Eterm arg1, Eterm arg2);
+static BIF_RETTYPE ets_select3(Process* p, Eterm arg1, Eterm arg2, Eterm arg3);
+
+
/*
* Exported global
*/
@@ -224,21 +227,21 @@ static void
free_dbtable(DbTable* tb)
{
#ifdef HARDDEBUG
- if (erts_smp_atomic_read(&tb->common.memory_size) != sizeof(DbTable)) {
+ if (erts_smp_atomic_read_nob(&tb->common.memory_size) != sizeof(DbTable)) {
erts_fprintf(stderr, "ets: free_dbtable memory remain=%ld fix=%x\n",
- erts_smp_atomic_read(&tb->common.memory_size)-sizeof(DbTable),
+ erts_smp_atomic_read_nob(&tb->common.memory_size)-sizeof(DbTable),
tb->common.fixations);
}
erts_fprintf(stderr, "ets: free_dbtable(%T) deleted!!!\r\n",
tb->common.id);
erts_fprintf(stderr, "ets: free_dbtable: meta_pid_to_tab common.memory_size = %ld\n",
- erts_smp_atomic_read(&meta_pid_to_tab->common.memory_size));
+ erts_smp_atomic_read_nob(&meta_pid_to_tab->common.memory_size));
print_table(ERTS_PRINT_STDOUT, NULL, 1, meta_pid_to_tab);
erts_fprintf(stderr, "ets: free_dbtable: meta_pid_to_fixed_tab common.memory_size = %ld\n",
- erts_smp_atomic_read(&meta_pid_to_fixed_tab->common.memory_size));
+ erts_smp_atomic_read_nob(&meta_pid_to_fixed_tab->common.memory_size));
print_table(ERTS_PRINT_STDOUT, NULL, 1, meta_pid_to_fixed_tab);
#endif
#ifdef ERTS_SMP
@@ -248,6 +251,7 @@ free_dbtable(DbTable* tb)
ASSERT(is_immed(tb->common.heir_data));
erts_db_free(ERTS_ALC_T_DB_TABLE, tb, (void *) tb, sizeof(DbTable));
ERTS_ETS_MISC_MEM_ADD(-sizeof(DbTable));
+ ERTS_THR_MEMORY_BARRIER;
}
#ifdef ERTS_SMP
@@ -276,8 +280,7 @@ static void schedule_free_dbtable(DbTable* tb)
ASSERT(scheds >= 1);
ASSERT(erts_refc_read(&tb->common.ref, 0) == 0);
erts_refc_init(&tb->common.ref, scheds);
- ERTS_THR_MEMORY_BARRIER;
- erts_smp_schedule_misc_aux_work(0, scheds, chk_free_dbtable, tb);
+ erts_schedule_multi_misc_aux_work(0, scheds, chk_free_dbtable, tb);
#else
free_dbtable(tb);
#endif
@@ -1296,7 +1299,9 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2)
Uint32 status;
Sint keypos;
int is_named, is_fine_locked, frequent_read, is_compressed;
+#ifdef DEBUG
int cret;
+#endif
DeclareTmpHeap(meta_tuple,3,BIF_P);
DbTableMethod* meth;
erts_smp_rwmtx_t *mmtl;
@@ -1417,12 +1422,12 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2)
{
DbTable init_tb;
- erts_smp_atomic_init(&init_tb.common.memory_size, 0);
+ erts_smp_atomic_init_nob(&init_tb.common.memory_size, 0);
tb = (DbTable*) erts_db_alloc(ERTS_ALC_T_DB_TABLE,
&init_tb, sizeof(DbTable));
ERTS_ETS_MISC_MEM_ADD(sizeof(DbTable));
- erts_smp_atomic_init(&tb->common.memory_size,
- erts_smp_atomic_read(&init_tb.common.memory_size));
+ erts_smp_atomic_init_nob(&tb->common.memory_size,
+ erts_smp_atomic_read_nob(&init_tb.common.memory_size));
}
tb->common.meth = meth;
@@ -1439,12 +1444,15 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2)
tb->common.owner = BIF_P->id;
set_heir(BIF_P, tb, heir, heir_data);
- erts_smp_atomic_init(&tb->common.nitems, 0);
+ erts_smp_atomic_init_nob(&tb->common.nitems, 0);
tb->common.fixations = NULL;
tb->common.compress = is_compressed;
- cret = meth->db_create(BIF_P, tb);
+#ifdef DEBUG
+ cret =
+#endif
+ meth->db_create(BIF_P, tb);
ASSERT(cret == DB_ERROR_NONE);
erts_smp_spin_lock(&meta_main_tab_main_lock);
@@ -1505,9 +1513,9 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2)
BIF_ARG_1, BIF_ARG_2, ret, BIF_P->id,
BIF_P->initial[0], BIF_P->initial[1], BIF_P->initial[2]);
erts_fprintf(stderr, "ets: new: meta_pid_to_tab common.memory_size = %ld\n",
- erts_smp_atomic_read(&meta_pid_to_tab->common.memory_size));
+ erts_smp_atomic_read_nob(&meta_pid_to_tab->common.memory_size));
erts_fprintf(stderr, "ets: new: meta_pid_to_fixed_tab common.memory_size = %ld\n",
- erts_smp_atomic_read(&meta_pid_to_fixed_tab->common.memory_size));
+ erts_smp_atomic_read_nob(&meta_pid_to_fixed_tab->common.memory_size));
#endif
UseTmpHeap(3,BIF_P);
@@ -1941,8 +1949,10 @@ BIF_RETTYPE ets_delete_object_2(BIF_ALIST_2)
/*
** This is for trapping, cannot be called directly.
*/
-static BIF_RETTYPE ets_select_delete_1(Process *p, Eterm a1)
+static BIF_RETTYPE ets_select_delete_1(BIF_ALIST_1)
{
+ Process *p = BIF_P;
+ Eterm a1 = BIF_ARG_1;
BIF_RETTYPE result;
DbTable* tb;
int cret;
@@ -1996,7 +2006,7 @@ BIF_RETTYPE ets_select_delete_2(BIF_ALIST_2)
if ((tb = db_get_table(BIF_P, BIF_ARG_1, DB_WRITE, LCK_WRITE)) == NULL) {
BIF_ERROR(BIF_P, BADARG);
}
- nitems = erts_smp_atomic_read(&tb->common.nitems);
+ nitems = erts_smp_atomic_read_nob(&tb->common.nitems);
tb->common.meth->db_delete_all_objects(BIF_P, tb);
db_unlock(tb, LCK_WRITE);
BIF_RET(erts_make_integer(nitems,BIF_P));
@@ -2108,7 +2118,7 @@ BIF_RETTYPE ets_slot_2(BIF_ALIST_2)
BIF_RETTYPE ets_match_1(BIF_ALIST_1)
{
- return ets_select_1(BIF_P, BIF_ARG_1);
+ return ets_select1(BIF_P, BIF_ARG_1);
}
BIF_RETTYPE ets_match_2(BIF_ALIST_2)
@@ -2124,7 +2134,7 @@ BIF_RETTYPE ets_match_2(BIF_ALIST_2)
ms = TUPLE3(hp, BIF_ARG_2, NIL, ms);
hp += 4;
ms = CONS(hp, ms, NIL);
- res = ets_select_2(BIF_P, BIF_ARG_1, ms);
+ res = ets_select2(BIF_P, BIF_ARG_1, ms);
UnUseTmpHeap(8,BIF_P);
return res;
}
@@ -2142,7 +2152,7 @@ BIF_RETTYPE ets_match_3(BIF_ALIST_3)
ms = TUPLE3(hp, BIF_ARG_2, NIL, ms);
hp += 4;
ms = CONS(hp, ms, NIL);
- res = ets_select_3(BIF_P, BIF_ARG_1, ms, BIF_ARG_3);
+ res = ets_select3(BIF_P, BIF_ARG_1, ms, BIF_ARG_3);
UnUseTmpHeap(8,BIF_P);
return res;
}
@@ -2150,6 +2160,12 @@ BIF_RETTYPE ets_match_3(BIF_ALIST_3)
BIF_RETTYPE ets_select_3(BIF_ALIST_3)
{
+ return ets_select3(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
+}
+
+static BIF_RETTYPE
+ets_select3(Process* p, Eterm arg1, Eterm arg2, Eterm arg3)
+{
BIF_RETTYPE result;
DbTable* tb;
int cret;
@@ -2160,22 +2176,22 @@ BIF_RETTYPE ets_select_3(BIF_ALIST_3)
CHECK_TABLES();
/* Chunk size strictly greater than 0 */
- if (is_not_small(BIF_ARG_3) || (chunk_size = signed_val(BIF_ARG_3)) <= 0) {
- BIF_ERROR(BIF_P, BADARG);
+ if (is_not_small(arg3) || (chunk_size = signed_val(arg3)) <= 0) {
+ BIF_ERROR(p, BADARG);
}
- if ((tb = db_get_table(BIF_P, BIF_ARG_1, DB_READ, LCK_READ)) == NULL) {
- BIF_ERROR(BIF_P, BADARG);
+ if ((tb = db_get_table(p, arg1, DB_READ, LCK_READ)) == NULL) {
+ BIF_ERROR(p, BADARG);
}
- safety = ITERATION_SAFETY(BIF_P,tb);
+ safety = ITERATION_SAFETY(p,tb);
if (safety == ITER_UNSAFE) {
local_fix_table(tb);
}
- cret = tb->common.meth->db_select_chunk(BIF_P, tb,
- BIF_ARG_2, chunk_size,
+ cret = tb->common.meth->db_select_chunk(p, tb,
+ arg2, chunk_size,
0 /* not reversed */,
&ret);
- if (DID_TRAP(BIF_P,ret) && safety != ITER_SAFE) {
- fix_table_locked(BIF_P, tb);
+ if (DID_TRAP(p,ret) && safety != ITER_SAFE) {
+ fix_table_locked(p, tb);
}
if (safety == ITER_UNSAFE) {
local_unfix_table(tb);
@@ -2187,22 +2203,24 @@ BIF_RETTYPE ets_select_3(BIF_ALIST_3)
ERTS_BIF_PREP_RET(result, ret);
break;
case DB_ERROR_SYSRES:
- ERTS_BIF_PREP_ERROR(result, BIF_P, SYSTEM_LIMIT);
+ ERTS_BIF_PREP_ERROR(result, p, SYSTEM_LIMIT);
break;
default:
- ERTS_BIF_PREP_ERROR(result, BIF_P, BADARG);
+ ERTS_BIF_PREP_ERROR(result, p, BADARG);
break;
}
- erts_match_set_release_result(BIF_P);
+ erts_match_set_release_result(p);
return result;
}
/* We get here instead of in the real BIF when trapping */
-static BIF_RETTYPE ets_select_trap_1(Process *p, Eterm a1)
+static BIF_RETTYPE ets_select_trap_1(BIF_ALIST_1)
{
+ Process *p = BIF_P;
+ Eterm a1 = BIF_ARG_1;
BIF_RETTYPE result;
DbTable* tb;
int cret;
@@ -2247,6 +2265,11 @@ static BIF_RETTYPE ets_select_trap_1(Process *p, Eterm a1)
BIF_RETTYPE ets_select_1(BIF_ALIST_1)
{
+ return ets_select1(BIF_P, BIF_ARG_1);
+}
+
+static BIF_RETTYPE ets_select1(Process *p, Eterm arg1)
+{
BIF_RETTYPE result;
DbTable* tb;
int cret;
@@ -2260,28 +2283,27 @@ BIF_RETTYPE ets_select_1(BIF_ALIST_1)
* Make sure that the table exists.
*/
- if (!is_tuple(BIF_ARG_1)) {
- if (BIF_ARG_1 == am_EOT) {
+ if (!is_tuple(arg1)) {
+ if (arg1 == am_EOT) {
BIF_RET(am_EOT);
}
- BIF_ERROR(BIF_P, BADARG);
+ BIF_ERROR(p, BADARG);
}
- tptr = tuple_val(BIF_ARG_1);
+ tptr = tuple_val(arg1);
if (arityval(*tptr) < 1 ||
- (tb = db_get_table(BIF_P, tptr[1], DB_READ, LCK_READ)) == NULL) {
- BIF_ERROR(BIF_P, BADARG);
+ (tb = db_get_table(p, tptr[1], DB_READ, LCK_READ)) == NULL) {
+ BIF_ERROR(p, BADARG);
}
- safety = ITERATION_SAFETY(BIF_P,tb);
+ safety = ITERATION_SAFETY(p,tb);
if (safety == ITER_UNSAFE) {
local_fix_table(tb);
}
- cret = tb->common.meth->db_select_continue(BIF_P,tb,
- BIF_ARG_1, &ret);
+ cret = tb->common.meth->db_select_continue(p,tb, arg1, &ret);
- if (DID_TRAP(BIF_P,ret) && safety != ITER_SAFE) {
- fix_table_locked(BIF_P, tb);
+ if (DID_TRAP(p,ret) && safety != ITER_SAFE) {
+ fix_table_locked(p, tb);
}
if (safety == ITER_UNSAFE) {
local_unfix_table(tb);
@@ -2293,20 +2315,26 @@ BIF_RETTYPE ets_select_1(BIF_ALIST_1)
ERTS_BIF_PREP_RET(result, ret);
break;
case DB_ERROR_SYSRES:
- ERTS_BIF_PREP_ERROR(result, BIF_P, SYSTEM_LIMIT);
+ ERTS_BIF_PREP_ERROR(result, p, SYSTEM_LIMIT);
break;
default:
- ERTS_BIF_PREP_ERROR(result, BIF_P, BADARG);
+ ERTS_BIF_PREP_ERROR(result, p, BADARG);
break;
}
- erts_match_set_release_result(BIF_P);
+ erts_match_set_release_result(p);
return result;
}
BIF_RETTYPE ets_select_2(BIF_ALIST_2)
{
+ return ets_select2(BIF_P, BIF_ARG_1, BIF_ARG_2);
+}
+
+static BIF_RETTYPE
+ets_select2(Process* p, Eterm arg1, Eterm arg2)
+{
BIF_RETTYPE result;
DbTable* tb;
int cret;
@@ -2319,19 +2347,19 @@ BIF_RETTYPE ets_select_2(BIF_ALIST_2)
* Make sure that the table exists.
*/
- if ((tb = db_get_table(BIF_P, BIF_ARG_1, DB_READ, LCK_READ)) == NULL) {
- BIF_ERROR(BIF_P, BADARG);
+ if ((tb = db_get_table(p, arg1, DB_READ, LCK_READ)) == NULL) {
+ BIF_ERROR(p, BADARG);
}
- safety = ITERATION_SAFETY(BIF_P,tb);
+ safety = ITERATION_SAFETY(p,tb);
if (safety == ITER_UNSAFE) {
local_fix_table(tb);
}
- cret = tb->common.meth->db_select(BIF_P, tb, BIF_ARG_2,
+ cret = tb->common.meth->db_select(p, tb, arg2,
0, &ret);
- if (DID_TRAP(BIF_P,ret) && safety != ITER_SAFE) {
- fix_table_locked(BIF_P, tb);
+ if (DID_TRAP(p,ret) && safety != ITER_SAFE) {
+ fix_table_locked(p, tb);
}
if (safety == ITER_UNSAFE) {
local_unfix_table(tb);
@@ -2343,21 +2371,23 @@ BIF_RETTYPE ets_select_2(BIF_ALIST_2)
ERTS_BIF_PREP_RET(result, ret);
break;
case DB_ERROR_SYSRES:
- ERTS_BIF_PREP_ERROR(result, BIF_P, SYSTEM_LIMIT);
+ ERTS_BIF_PREP_ERROR(result, p, SYSTEM_LIMIT);
break;
default:
- ERTS_BIF_PREP_ERROR(result, BIF_P, BADARG);
+ ERTS_BIF_PREP_ERROR(result, p, BADARG);
break;
}
- erts_match_set_release_result(BIF_P);
+ erts_match_set_release_result(p);
return result;
}
/* We get here instead of in the real BIF when trapping */
-static BIF_RETTYPE ets_select_count_1(Process *p, Eterm a1)
+static BIF_RETTYPE ets_select_count_1(BIF_ALIST_1)
{
+ Process *p = BIF_P;
+ Eterm a1 = BIF_ARG_1;
BIF_RETTYPE result;
DbTable* tb;
int cret;
@@ -2498,7 +2528,7 @@ BIF_RETTYPE ets_select_reverse_3(BIF_ALIST_3)
BIF_RETTYPE ets_select_reverse_1(BIF_ALIST_1)
{
- return ets_select_1(BIF_P, BIF_ARG_1);
+ return ets_select1(BIF_P, BIF_ARG_1);
}
BIF_RETTYPE ets_select_reverse_2(BIF_ALIST_2)
@@ -2552,7 +2582,7 @@ BIF_RETTYPE ets_select_reverse_2(BIF_ALIST_2)
*/
BIF_RETTYPE ets_match_object_1(BIF_ALIST_1)
{
- return ets_select_1(BIF_P, BIF_ARG_1);
+ return ets_select1(BIF_P, BIF_ARG_1);
}
BIF_RETTYPE ets_match_object_2(BIF_ALIST_2)
@@ -2568,7 +2598,7 @@ BIF_RETTYPE ets_match_object_2(BIF_ALIST_2)
ms = TUPLE3(hp, BIF_ARG_2, NIL, ms);
hp += 4;
ms = CONS(hp, ms, NIL);
- res = ets_select_2(BIF_P, BIF_ARG_1, ms);
+ res = ets_select2(BIF_P, BIF_ARG_1, ms);
UnUseTmpHeap(8,BIF_P);
return res;
}
@@ -2586,7 +2616,7 @@ BIF_RETTYPE ets_match_object_3(BIF_ALIST_3)
ms = TUPLE3(hp, BIF_ARG_2, NIL, ms);
hp += 4;
ms = CONS(hp, ms, NIL);
- res = ets_select_3(BIF_P, BIF_ARG_1, ms, BIF_ARG_3);
+ res = ets_select3(BIF_P, BIF_ARG_1, ms, BIF_ARG_3);
UnUseTmpHeap(8,BIF_P);
return res;
}
@@ -2605,7 +2635,9 @@ BIF_RETTYPE ets_info_1(BIF_ALIST_1)
int i;
Eterm* hp;
/*Process* rp = NULL;*/
+ /* If/when we implement lockless private tables:
Eterm owner;
+ */
if ((tb = db_get_table(BIF_P, BIF_ARG_1, DB_INFO, LCK_READ)) == NULL) {
if (is_atom(BIF_ARG_1) || is_small(BIF_ARG_1)) {
@@ -2614,7 +2646,9 @@ BIF_RETTYPE ets_info_1(BIF_ALIST_1)
BIF_ERROR(BIF_P, BADARG);
}
+ /* If/when we implement lockless private tables:
owner = tb->common.owner;
+ */
/* If/when we implement lockless private tables:
if ((tb->common.status & DB_PRIVATE) && owner != BIF_P->id) {
@@ -2790,7 +2824,7 @@ void init_db(void)
}
#endif
- erts_smp_atomic_init(&erts_ets_misc_mem_size, 0);
+ erts_smp_atomic_init_nob(&erts_ets_misc_mem_size, 0);
db_initialize_util();
if (user_requested_db_max_tabs < DB_DEF_MAX_TABS)
@@ -2832,13 +2866,13 @@ void init_db(void)
/*TT*/
/* Create meta table invertion. */
- erts_smp_atomic_init(&init_tb.common.memory_size, 0);
+ erts_smp_atomic_init_nob(&init_tb.common.memory_size, 0);
meta_pid_to_tab = (DbTable*) erts_db_alloc(ERTS_ALC_T_DB_TABLE,
&init_tb,
sizeof(DbTable));
ERTS_ETS_MISC_MEM_ADD(sizeof(DbTable));
- erts_smp_atomic_init(&meta_pid_to_tab->common.memory_size,
- erts_smp_atomic_read(&init_tb.common.memory_size));
+ erts_smp_atomic_init_nob(&meta_pid_to_tab->common.memory_size,
+ erts_smp_atomic_read_nob(&init_tb.common.memory_size));
meta_pid_to_tab->common.id = NIL;
meta_pid_to_tab->common.the_name = am_true;
@@ -2851,7 +2885,7 @@ void init_db(void)
#endif
meta_pid_to_tab->common.keypos = 1;
meta_pid_to_tab->common.owner = NIL;
- erts_smp_atomic_init(&meta_pid_to_tab->common.nitems, 0);
+ erts_smp_atomic_init_nob(&meta_pid_to_tab->common.nitems, 0);
meta_pid_to_tab->common.slot = -1;
meta_pid_to_tab->common.meth = &db_hash;
meta_pid_to_tab->common.compress = 0;
@@ -2864,13 +2898,13 @@ void init_db(void)
erl_exit(1,"Unable to create ets metadata tables.");
}
- erts_smp_atomic_set(&init_tb.common.memory_size, 0);
+ erts_smp_atomic_set_nob(&init_tb.common.memory_size, 0);
meta_pid_to_fixed_tab = (DbTable*) erts_db_alloc(ERTS_ALC_T_DB_TABLE,
&init_tb,
sizeof(DbTable));
ERTS_ETS_MISC_MEM_ADD(sizeof(DbTable));
- erts_smp_atomic_init(&meta_pid_to_fixed_tab->common.memory_size,
- erts_smp_atomic_read(&init_tb.common.memory_size));
+ erts_smp_atomic_init_nob(&meta_pid_to_fixed_tab->common.memory_size,
+ erts_smp_atomic_read_nob(&init_tb.common.memory_size));
meta_pid_to_fixed_tab->common.id = NIL;
meta_pid_to_fixed_tab->common.the_name = am_true;
@@ -2883,7 +2917,7 @@ void init_db(void)
#endif
meta_pid_to_fixed_tab->common.keypos = 1;
meta_pid_to_fixed_tab->common.owner = NIL;
- erts_smp_atomic_init(&meta_pid_to_fixed_tab->common.nitems, 0);
+ erts_smp_atomic_init_nob(&meta_pid_to_fixed_tab->common.nitems, 0);
meta_pid_to_fixed_tab->common.slot = -1;
meta_pid_to_fixed_tab->common.meth = &db_hash;
meta_pid_to_fixed_tab->common.compress = 0;
@@ -3422,7 +3456,7 @@ static void unfix_table_locked(Process* p, DbTable* tb,
unlocked:
if (!IS_FIXED(tb) && IS_HASH_TABLE(tb->common.status)
- && erts_smp_atomic_read(&tb->hash.fixdel) != (erts_aint_t)NULL) {
+ && erts_smp_atomic_read_nob(&tb->hash.fixdel) != (erts_aint_t)NULL) {
#ifdef ERTS_SMP
if (*kind_p == LCK_READ && tb->common.is_thread_safe) {
/* Must have write lock while purging pseudo-deleted (OTP-8166) */
@@ -3520,8 +3554,10 @@ static void free_heir_data(DbTable* tb)
#endif
}
-static BIF_RETTYPE ets_delete_trap(Process *p, Eterm cont)
+static BIF_RETTYPE ets_delete_trap(BIF_ALIST_1)
{
+ Process *p = BIF_P;
+ Eterm cont = BIF_ARG_1;
int trap;
Eterm* ptr = big_val(cont);
DbTable *tb = *((DbTable **) (UWord) (ptr + 1));
@@ -3607,7 +3643,7 @@ static Eterm table_info(Process* p, DbTable* tb, Eterm What)
Eterm ret = THE_NON_VALUE;
if (What == am_size) {
- ret = make_small(erts_smp_atomic_read(&tb->common.nitems));
+ ret = make_small(erts_smp_atomic_read_nob(&tb->common.nitems));
} else if (What == am_type) {
if (tb->common.status & DB_SET) {
ret = am_set;
@@ -3620,7 +3656,7 @@ static Eterm table_info(Process* p, DbTable* tb, Eterm What)
ret = am_bag;
}
} else if (What == am_memory) {
- Uint words = (Uint) ((erts_smp_atomic_read(&tb->common.memory_size)
+ Uint words = (Uint) ((erts_smp_atomic_read_nob(&tb->common.memory_size)
+ sizeof(Uint)
- 1)
/ sizeof(Uint));
@@ -3658,9 +3694,6 @@ static Eterm table_info(Process* p, DbTable* tb, Eterm What)
ret = am_true;
else
ret = am_false;
- } else if (What == am_atom_put("kept_objects",12)) {
- ret = make_small(IS_HASH_TABLE(tb->common.status)
- ? db_kept_items_hash(&tb->hash) : 0);
} else if (What == am_atom_put("safe_fixed",10)) {
#ifdef ERTS_SMP
erts_smp_mtx_lock(&tb->common.fixlock);
@@ -3702,7 +3735,7 @@ static Eterm table_info(Process* p, DbTable* tb, Eterm What)
Eterm* hp;
db_calc_stats_hash(&tb->hash, &stats);
- hp = HAlloc(p, 1 + 6 + FLOAT_SIZE_OBJECT*3);
+ hp = HAlloc(p, 1 + 7 + FLOAT_SIZE_OBJECT*3);
f.fd = stats.avg_chain_len;
avg = make_float(hp);
PUT_DOUBLE(f, hp);
@@ -3717,10 +3750,11 @@ static Eterm table_info(Process* p, DbTable* tb, Eterm What)
std_dev_exp = make_float(hp);
PUT_DOUBLE(f, hp);
hp += FLOAT_SIZE_OBJECT;
- ret = TUPLE6(hp, make_small(erts_smp_atomic_read(&tb->hash.nactive)),
+ ret = TUPLE7(hp, make_small(erts_smp_atomic_read_nob(&tb->hash.nactive)),
avg, std_dev_real, std_dev_exp,
make_small(stats.min_chain_len),
- make_small(stats.max_chain_len));
+ make_small(stats.max_chain_len),
+ make_small(db_kept_items_hash(&tb->hash)));
}
else {
ret = am_false;
@@ -3736,9 +3770,9 @@ static void print_table(int to, void *to_arg, int show, DbTable* tb)
tb->common.meth->db_print(to, to_arg, show, tb);
- erts_print(to, to_arg, "Objects: %d\n", (int)erts_smp_atomic_read(&tb->common.nitems));
+ erts_print(to, to_arg, "Objects: %d\n", (int)erts_smp_atomic_read_nob(&tb->common.nitems));
erts_print(to, to_arg, "Words: %bpu\n",
- (UWord) ((erts_smp_atomic_read(&tb->common.memory_size)
+ (Uint) ((erts_smp_atomic_read_nob(&tb->common.memory_size)
+ sizeof(Uint)
- 1)
/ sizeof(Uint)));
@@ -3764,8 +3798,9 @@ void db_info(int to, void *to_arg, int show) /* Called by break handler */
Uint
erts_get_ets_misc_mem_size(void)
{
+ ERTS_THR_MEMORY_BARRIER;
/* Memory not allocated in ets_alloc */
- return (Uint) erts_smp_atomic_read(&erts_ets_misc_mem_size);
+ return (Uint) erts_smp_atomic_read_nob(&erts_ets_misc_mem_size);
}
/* SMP Note: May only be used when system is locked */
diff --git a/erts/emulator/beam/erl_db.h b/erts/emulator/beam/erl_db.h
index e0bdebcb01..2e5deaf338 100644
--- a/erts/emulator/beam/erl_db.h
+++ b/erts/emulator/beam/erl_db.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2010. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -86,11 +86,11 @@ do { \
erts_aint_t sz__ = (((erts_aint_t) (ALLOC_SZ)) \
- ((erts_aint_t) (FREE_SZ))); \
ASSERT((TAB)); \
- erts_smp_atomic_add(&(TAB)->common.memory_size, sz__); \
+ erts_smp_atomic_add_nob(&(TAB)->common.memory_size, sz__); \
} while (0)
#define ERTS_ETS_MISC_MEM_ADD(SZ) \
- erts_smp_atomic_add(&erts_ets_misc_mem_size, (SZ));
+ erts_smp_atomic_add_nob(&erts_ets_misc_mem_size, (SZ));
ERTS_GLB_INLINE void *erts_db_alloc(ErtsAlcType_t type,
DbTable *tab,
@@ -227,7 +227,7 @@ erts_db_free(ErtsAlcType_t type, DbTable *tab, void *ptr, Uint size)
ERTS_DB_ALC_MEM_UPDATE_(tab, size, 0);
ASSERT(((void *) tab) != ptr
- || erts_smp_atomic_read(&tab->common.memory_size) == 0);
+ || erts_smp_atomic_read_nob(&tab->common.memory_size) == 0);
erts_free(type, ptr);
}
diff --git a/erts/emulator/beam/erl_db_hash.c b/erts/emulator/beam/erl_db_hash.c
index fdc82c8b88..038a667b06 100644
--- a/erts/emulator/beam/erl_db_hash.c
+++ b/erts/emulator/beam/erl_db_hash.c
@@ -105,9 +105,13 @@
#define NSEG_2 256 /* Size of second segment table */
#define NSEG_INC 128 /* Number of segments to grow after that */
-#define SEGTAB(tb) ((struct segment**)erts_smp_atomic_read_acqb(&(tb)->segtab))
-#define NACTIVE(tb) ((int)erts_smp_atomic_read(&(tb)->nactive))
-#define NITEMS(tb) ((int)erts_smp_atomic_read(&(tb)->common.nitems))
+#ifdef ETHR_ORDERED_READ_DEPEND
+#define SEGTAB(tb) ((struct segment**)erts_smp_atomic_read_nob(&(tb)->segtab))
+#else
+#define SEGTAB(tb) ((struct segment**)erts_smp_atomic_read_rb(&(tb)->segtab))
+#endif
+#define NACTIVE(tb) ((int)erts_smp_atomic_read_nob(&(tb)->nactive))
+#define NITEMS(tb) ((int)erts_smp_atomic_read_nob(&(tb)->common.nitems))
#define BUCKET(tb, i) SEGTAB(tb)[(i) >> SEGSZ_EXP]->buckets[(i) & SEGSZ_MASK]
@@ -123,10 +127,10 @@
static ERTS_INLINE Uint hash_to_ix(DbTableHash* tb, HashValue hval)
{
Uint mask = erts_smp_atomic_read_acqb(&tb->szm);
- Uint ix = hval & mask;
- if (ix >= erts_smp_atomic_read(&tb->nactive)) {
+ Uint ix = hval & mask;
+ if (ix >= erts_smp_atomic_read_nob(&tb->nactive)) {
ix &= mask>>1;
- ASSERT(ix < erts_smp_atomic_read(&tb->nactive));
+ ASSERT(ix < erts_smp_atomic_read_nob(&tb->nactive));
}
return ix;
}
@@ -141,14 +145,14 @@ static ERTS_INLINE void add_fixed_deletion(DbTableHash* tb, int ix)
(DbTable *) tb,
sizeof(FixedDeletion));
ERTS_ETS_MISC_MEM_ADD(sizeof(FixedDeletion));
- fixd->slot = ix;
- was_next = erts_smp_atomic_read(&tb->fixdel);
+ fixd->slot = ix;
+ was_next = erts_smp_atomic_read_acqb(&tb->fixdel);
do { /* Lockless atomic insertion in linked list: */
exp_next = was_next;
fixd->next = (FixedDeletion*) exp_next;
- was_next = erts_smp_atomic_cmpxchg(&tb->fixdel,
- (erts_aint_t) fixd,
- exp_next);
+ was_next = erts_smp_atomic_cmpxchg_relb(&tb->fixdel,
+ (erts_aint_t) fixd,
+ exp_next);
}while (was_next != exp_next);
}
@@ -308,15 +312,24 @@ struct ext_segment {
struct segment* segtab[1]; /* The segment table */
};
#define SIZEOF_EXTSEG(NSEGS) \
- (sizeof(struct ext_segment) - sizeof(struct segment*) + sizeof(struct segment*)*(NSEGS))
+ (offsetof(struct ext_segment,segtab) + sizeof(struct segment*)*(NSEGS))
-#ifdef DEBUG
-# include <stddef.h> /* offsetof */
+#if defined(DEBUG) || defined(VALGRIND)
# define EXTSEG(SEGTAB_PTR) \
((struct ext_segment*) (((char*)(SEGTAB_PTR)) - offsetof(struct ext_segment,segtab)))
#endif
+static ERTS_INLINE void SET_SEGTAB(DbTableHash* tb,
+ struct segment** segtab)
+{
+ erts_smp_atomic_set_wb(&tb->segtab, (erts_aint_t) segtab);
+#ifdef VALGRIND
+ tb->top_ptr_to_segment_with_active_segtab = EXTSEG(segtab);
+#endif
+}
+
+
/* How the table segments relate to each other:
ext_segment: ext_segment: "plain" segment
@@ -540,22 +553,24 @@ static void restore_fixdel(DbTableHash* tb, FixedDeletion* fixdel)
{
/*int tries = 0;*/
DEBUG_WAIT();
- if (erts_smp_atomic_cmpxchg(&tb->fixdel, (erts_aint_t)fixdel,
- (erts_aint_t)NULL) != (erts_aint_t)NULL) {
+ if (erts_smp_atomic_cmpxchg_relb(&tb->fixdel,
+ (erts_aint_t) fixdel,
+ (erts_aint_t) NULL) != (erts_aint_t) NULL) {
/* Oboy, must join lists */
FixedDeletion* last = fixdel;
erts_aint_t was_tail;
erts_aint_t exp_tail;
- while (last->next != NULL) last = last->next;
- was_tail = erts_smp_atomic_read(&tb->fixdel);
+ while (last->next != NULL) last = last->next;
+ was_tail = erts_smp_atomic_read_acqb(&tb->fixdel);
do { /* Lockless atomic list insertion */
exp_tail = was_tail;
last->next = (FixedDeletion*) exp_tail;
/*++tries;*/
DEBUG_WAIT();
- was_tail = erts_smp_atomic_cmpxchg(&tb->fixdel, (erts_aint_t)fixdel,
- exp_tail);
+ was_tail = erts_smp_atomic_cmpxchg_relb(&tb->fixdel,
+ (erts_aint_t) fixdel,
+ exp_tail);
}while (was_tail != exp_tail);
}
/*erts_fprintf(stderr,"erl_db_hash: restore_fixdel tries=%d\r\n", tries);*/
@@ -572,7 +587,8 @@ void db_unfix_table_hash(DbTableHash *tb)
|| (erts_smp_lc_rwmtx_is_rlocked(&tb->common.rwlock)
&& !tb->common.is_thread_safe));
restart:
- fixdel = (FixedDeletion*) erts_smp_atomic_xchg(&tb->fixdel, (erts_aint_t)NULL);
+ fixdel = (FixedDeletion*) erts_smp_atomic_xchg_acqb(&tb->fixdel,
+ (erts_aint_t) NULL);
while (fixdel != NULL) {
FixedDeletion *fx = fixdel;
int ix = fx->slot;
@@ -639,14 +655,15 @@ int db_create_hash(Process *p, DbTable *tbl)
{
DbTableHash *tb = &tbl->hash;
- erts_smp_atomic_init(&tb->szm, SEGSZ_MASK);
- erts_smp_atomic_init(&tb->nactive, SEGSZ);
- erts_smp_atomic_init(&tb->fixdel, (erts_aint_t)NULL);
- erts_smp_atomic_init(&tb->segtab, (erts_aint_t) alloc_ext_seg(tb,0,NULL)->segtab);
+ erts_smp_atomic_init_nob(&tb->szm, SEGSZ_MASK);
+ erts_smp_atomic_init_nob(&tb->nactive, SEGSZ);
+ erts_smp_atomic_init_nob(&tb->fixdel, (erts_aint_t)NULL);
+ erts_smp_atomic_init_nob(&tb->segtab, (erts_aint_t)NULL);
+ SET_SEGTAB(tb, alloc_ext_seg(tb,0,NULL)->segtab);
tb->nsegs = NSEG_1;
tb->nslots = SEGSZ;
- erts_smp_atomic_init(&tb->is_resizing, 0);
+ erts_smp_atomic_init_nob(&tb->is_resizing, 0);
#ifdef ERTS_SMP
if (tb->common.type & DB_FINE_LOCKED) {
erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
@@ -663,7 +680,7 @@ int db_create_hash(Process *p, DbTable *tbl)
/* This important property is needed to guarantee that the buckets
* involved in a grow/shrink operation it protected by the same lock:
*/
- ASSERT(erts_smp_atomic_read(&tb->nactive) % DB_HASH_LOCK_CNT == 0);
+ ASSERT(erts_smp_atomic_read_nob(&tb->nactive) % DB_HASH_LOCK_CNT == 0);
}
else { /* coarse locking */
tb->locks = NULL;
@@ -783,7 +800,7 @@ int db_put_hash(DbTable *tbl, Eterm obj, int key_clash_fail)
if (tb->common.status & DB_SET) {
HashDbTerm* bnext = b->next;
if (b->hvalue == INVALID_HASH) {
- erts_smp_atomic_inc(&tb->common.nitems);
+ erts_smp_atomic_inc_nob(&tb->common.nitems);
}
else if (key_clash_fail) {
ret = DB_ERROR_BADKEY;
@@ -811,7 +828,7 @@ int db_put_hash(DbTable *tbl, Eterm obj, int key_clash_fail)
do {
if (db_eq(&tb->common,obj,&q->dbterm)) {
if (q->hvalue == INVALID_HASH) {
- erts_smp_atomic_inc(&tb->common.nitems);
+ erts_smp_atomic_inc_nob(&tb->common.nitems);
q->hvalue = hval;
if (q != b) { /* must move to preserve key insertion order */
*qp = q->next;
@@ -832,7 +849,7 @@ Lnew:
q->hvalue = hval;
q->next = b;
*bp = q;
- nitems = erts_smp_atomic_inctest(&tb->common.nitems);
+ nitems = erts_smp_atomic_inc_read_nob(&tb->common.nitems);
WUNLOCK_HASH(lck);
{
int nactive = NACTIVE(tb);
@@ -1069,7 +1086,7 @@ int db_erase_bag_exact2(DbTable *tbl, Eterm key, Eterm value)
EQ(value, b->dbterm.tpl[2])) {
*bp = b->next;
free_term(tb, b);
- erts_smp_atomic_dec(&tb->common.nitems);
+ erts_smp_atomic_dec_nob(&tb->common.nitems);
b = *bp;
break;
}
@@ -1128,7 +1145,7 @@ int db_erase_hash(DbTable *tbl, Eterm key, Eterm *ret)
}
WUNLOCK_HASH(lck);
if (nitems_diff) {
- erts_smp_atomic_add(&tb->common.nitems, nitems_diff);
+ erts_smp_atomic_add_nob(&tb->common.nitems, nitems_diff);
try_shrink(tb);
}
*ret = am_true;
@@ -1187,7 +1204,7 @@ static int db_erase_object_hash(DbTable *tbl, Eterm object, Eterm *ret)
}
WUNLOCK_HASH(lck);
if (nitems_diff) {
- erts_smp_atomic_add(&tb->common.nitems, nitems_diff);
+ erts_smp_atomic_add_nob(&tb->common.nitems, nitems_diff);
try_shrink(tb);
}
*ret = am_true;
@@ -1798,7 +1815,7 @@ static int db_select_delete_hash(Process *p,
free_term(tb, del);
did_erase = 1;
}
- erts_smp_atomic_dec(&tb->common.nitems);
+ erts_smp_atomic_dec_nob(&tb->common.nitems);
++got;
}
--num_left;
@@ -1909,7 +1926,7 @@ static int db_select_delete_continue_hash(Process *p,
free_term(tb, del);
did_erase = 1;
}
- erts_smp_atomic_dec(&tb->common.nitems);
+ erts_smp_atomic_dec_nob(&tb->common.nitems);
++got;
}
@@ -2064,7 +2081,7 @@ int db_mark_all_deleted_hash(DbTable *tbl)
}while(list != NULL);
}
}
- erts_smp_atomic_set(&tb->common.nitems, 0);
+ erts_smp_atomic_set_nob(&tb->common.nitems, 0);
return DB_ERROR_NONE;
}
@@ -2115,7 +2132,7 @@ static int db_free_table_continue_hash(DbTable *tbl)
{
DbTableHash *tb = &tbl->hash;
int done;
- FixedDeletion* fixdel = (FixedDeletion*) erts_smp_atomic_read(&tb->fixdel);
+ FixedDeletion* fixdel = (FixedDeletion*) erts_smp_atomic_read_acqb(&tb->fixdel);
ERTS_SMP_LC_ASSERT(IS_TAB_WLOCKED(tb));
done = 0;
@@ -2129,11 +2146,11 @@ static int db_free_table_continue_hash(DbTable *tbl)
sizeof(FixedDeletion));
ERTS_ETS_MISC_MEM_ADD(-sizeof(FixedDeletion));
if (++done >= 2*DELETE_RECORD_LIMIT) {
- erts_smp_atomic_set(&tb->fixdel, (erts_aint_t)fixdel);
+ erts_smp_atomic_set_relb(&tb->fixdel, (erts_aint_t)fixdel);
return 0; /* Not done */
}
}
- erts_smp_atomic_set(&tb->fixdel, (erts_aint_t)NULL);
+ erts_smp_atomic_set_relb(&tb->fixdel, (erts_aint_t)NULL);
done /= 2;
while(tb->nslots != 0) {
@@ -2157,7 +2174,7 @@ static int db_free_table_continue_hash(DbTable *tbl)
tb->locks = NULL;
}
#endif
- ASSERT(erts_smp_atomic_read(&tb->common.memory_size) == sizeof(DbTable));
+ ASSERT(erts_smp_atomic_read_nob(&tb->common.memory_size) == sizeof(DbTable));
return 1; /* Done */
}
@@ -2350,7 +2367,7 @@ static int alloc_seg(DbTableHash *tb)
struct ext_segment* eseg;
eseg = (struct ext_segment*) SEGTAB(tb)[seg_ix-1];
MY_ASSERT(eseg!=NULL && eseg->s.is_ext_segment);
- erts_smp_atomic_set_relb(&tb->segtab, (erts_aint_t) eseg->segtab);
+ SET_SEGTAB(tb, eseg->segtab);
tb->nsegs = eseg->nsegs;
}
ASSERT(seg_ix < tb->nsegs);
@@ -2422,7 +2439,7 @@ static int free_seg(DbTableHash *tb, int free_records)
MY_ASSERT(newtop->s.is_ext_segment);
if (newtop->prev_segtab != NULL) {
/* Time to use a smaller segtab */
- erts_smp_atomic_set_relb(&tb->segtab, (erts_aint_t)newtop->prev_segtab);
+ SET_SEGTAB(tb, newtop->prev_segtab);
tb->nsegs = seg_ix;
ASSERT(tb->nsegs == EXTSEG(SEGTAB(tb))->nsegs);
}
@@ -2439,7 +2456,7 @@ static int free_seg(DbTableHash *tb, int free_records)
if (seg_ix > 0) {
if (seg_ix < tb->nsegs) SEGTAB(tb)[seg_ix] = NULL;
} else {
- erts_smp_atomic_set_relb(&tb->segtab, (erts_aint_t)NULL);
+ SET_SEGTAB(tb, NULL);
}
#endif
tb->nslots -= SEGSZ;
@@ -2500,7 +2517,7 @@ static void grow(DbTableHash* tb, int nactive)
int from_ix;
int szm;
- if (erts_smp_atomic_xchg(&tb->is_resizing, 1)) {
+ if (erts_smp_atomic_xchg_acqb(&tb->is_resizing, 1)) {
return; /* already in progress */
}
if (NACTIVE(tb) != nactive) {
@@ -2515,7 +2532,7 @@ static void grow(DbTableHash* tb, int nactive)
}
ASSERT(nactive < tb->nslots);
- szm = erts_smp_atomic_read(&tb->szm);
+ szm = erts_smp_atomic_read_nob(&tb->szm);
if (nactive <= szm) {
from_ix = nactive & (szm >> 1);
} else {
@@ -2532,7 +2549,7 @@ static void grow(DbTableHash* tb, int nactive)
WUNLOCK_HASH(lck);
goto abort;
}
- erts_smp_atomic_inc(&tb->nactive);
+ erts_smp_atomic_inc_nob(&tb->nactive);
if (from_ix == 0) {
erts_smp_atomic_set_relb(&tb->szm, szm);
}
@@ -2577,13 +2594,13 @@ abort:
*/
static void shrink(DbTableHash* tb, int nactive)
{
- if (erts_smp_atomic_xchg(&tb->is_resizing, 1)) {
+ if (erts_smp_atomic_xchg_acqb(&tb->is_resizing, 1)) {
return; /* already in progress */
}
if (NACTIVE(tb) == nactive) {
erts_smp_rwmtx_t* lck;
int src_ix = nactive - 1;
- int low_szm = erts_smp_atomic_read(&tb->szm) >> 1;
+ int low_szm = erts_smp_atomic_read_nob(&tb->szm) >> 1;
int dst_ix = src_ix & low_szm;
ASSERT(dst_ix < src_ix);
@@ -2610,7 +2627,7 @@ static void shrink(DbTableHash* tb, int nactive)
*dst_bp = *src_bp;
*src_bp = NULL;
- erts_smp_atomic_set(&tb->nactive, src_ix);
+ erts_smp_atomic_set_nob(&tb->nactive, src_ix);
if (dst_ix == 0) {
erts_smp_atomic_set_relb(&tb->szm, low_szm);
}
@@ -2746,7 +2763,7 @@ static int db_delete_all_objects_hash(Process* p, DbTable* tbl)
} else {
db_free_table_hash(tbl);
db_create_hash(p, tbl);
- erts_smp_atomic_set(&tbl->hash.common.nitems, 0);
+ erts_smp_atomic_set_nob(&tbl->hash.common.nitems, 0);
}
return 0;
}
diff --git a/erts/emulator/beam/erl_db_hash.h b/erts/emulator/beam/erl_db_hash.h
index e0285fa5ed..23ac493118 100644
--- a/erts/emulator/beam/erl_db_hash.h
+++ b/erts/emulator/beam/erl_db_hash.h
@@ -58,6 +58,9 @@ typedef struct db_table_hash {
#ifdef ERTS_SMP
DbTableHashFineLocks* locks;
#endif
+#ifdef VALGRIND
+ struct ext_segment* top_ptr_to_segment_with_active_segtab;
+#endif
} DbTableHash;
diff --git a/erts/emulator/beam/erl_db_tree.c b/erts/emulator/beam/erl_db_tree.c
index 9a0ba3a418..312050b931 100644
--- a/erts/emulator/beam/erl_db_tree.c
+++ b/erts/emulator/beam/erl_db_tree.c
@@ -49,7 +49,7 @@
#include "erl_db_tree.h"
#define GETKEY_WITH_POS(Keypos, Tplp) (*((Tplp) + Keypos))
-#define NITEMS(tb) ((int)erts_smp_atomic_read(&(tb)->common.nitems))
+#define NITEMS(tb) ((int)erts_smp_atomic_read_nob(&(tb)->common.nitems))
/*
** A stack of this size is enough for an AVL tree with more than
@@ -84,7 +84,7 @@
*/
static DbTreeStack* get_static_stack(DbTableTree* tb)
{
- if (!erts_smp_atomic_xchg(&tb->is_stack_busy, 1)) {
+ if (!erts_smp_atomic_xchg_acqb(&tb->is_stack_busy, 1)) {
return &tb->static_stack;
}
return NULL;
@@ -96,7 +96,7 @@ static DbTreeStack* get_static_stack(DbTableTree* tb)
static DbTreeStack* get_any_stack(DbTableTree* tb)
{
DbTreeStack* stack;
- if (!erts_smp_atomic_xchg(&tb->is_stack_busy, 1)) {
+ if (!erts_smp_atomic_xchg_acqb(&tb->is_stack_busy, 1)) {
return &tb->static_stack;
}
stack = erts_db_alloc(ERTS_ALC_T_DB_STK, (DbTable *) tb,
@@ -110,7 +110,7 @@ static DbTreeStack* get_any_stack(DbTableTree* tb)
static void release_stack(DbTableTree* tb, DbTreeStack* stack)
{
if (stack == &tb->static_stack) {
- ASSERT(erts_smp_atomic_read(&tb->is_stack_busy) == 1);
+ ASSERT(erts_smp_atomic_read_nob(&tb->is_stack_busy) == 1);
erts_smp_atomic_set_relb(&tb->is_stack_busy, 0);
}
else {
@@ -344,8 +344,8 @@ static int do_partly_bound_can_match_lesser(Eterm a, Eterm b,
int *done);
static int do_partly_bound_can_match_greater(Eterm a, Eterm b,
int *done);
-static BIF_RETTYPE ets_select_reverse(Process *p, Eterm a1,
- Eterm a2, Eterm a3);
+static BIF_RETTYPE ets_select_reverse(BIF_ALIST_3);
+
/* Method interface functions */
static int db_first_tree(Process *p, DbTable *tbl,
@@ -478,7 +478,7 @@ int db_create_tree(Process *p, DbTable *tbl)
sizeof(TreeDbTerm *) * STACK_NEED);
tb->static_stack.pos = 0;
tb->static_stack.slot = 0;
- erts_smp_atomic_init(&tb->is_stack_busy, 0);
+ erts_smp_atomic_init_nob(&tb->is_stack_busy, 0);
tb->deletion = 0;
return DB_ERROR_NONE;
}
@@ -613,8 +613,8 @@ static int db_put_tree(DbTable *tbl, Eterm obj, int key_clash_fail)
for (;;)
if (!*this) { /* Found our place */
state = 1;
- if (erts_smp_atomic_inctest(&tb->common.nitems) >= TREE_MAX_ELEMENTS) {
- erts_smp_atomic_dec(&tb->common.nitems);
+ if (erts_smp_atomic_inc_read_nob(&tb->common.nitems) >= TREE_MAX_ELEMENTS) {
+ erts_smp_atomic_dec_nob(&tb->common.nitems);
return DB_ERROR_SYSRES;
}
*this = new_dbterm(tb, obj);
@@ -844,8 +844,12 @@ static int db_slot_tree(Process *p, DbTable *tbl,
-static BIF_RETTYPE ets_select_reverse(Process *p, Eterm a1, Eterm a2, Eterm a3)
+static BIF_RETTYPE ets_select_reverse(BIF_ALIST_3)
{
+ Process *p = BIF_P;
+ Eterm a1 = BIF_ARG_1;
+ Eterm a2 = BIF_ARG_2;
+ Eterm a3 = BIF_ARG_3;
Eterm list;
Eterm result;
Eterm* hp;
@@ -1583,7 +1587,7 @@ static int db_select_delete_continue_tree(Process *p,
sc.max = 1000;
sc.keypos = tb->common.keypos;
- ASSERT(!erts_smp_atomic_read(&tb->is_stack_busy));
+ ASSERT(!erts_smp_atomic_read_nob(&tb->is_stack_busy));
traverse_backwards(tb, &tb->static_stack, lastkey, NULL, &doit_select_delete, &sc);
BUMP_REDS(p, 1000 - sc.max);
@@ -1774,7 +1778,7 @@ static int db_free_table_continue_tree(DbTable *tbl)
(DbTable *) tb,
(void *) tb->static_stack.array,
sizeof(TreeDbTerm *) * STACK_NEED);
- ASSERT(erts_smp_atomic_read(&tb->common.memory_size)
+ ASSERT(erts_smp_atomic_read_nob(&tb->common.memory_size)
== sizeof(DbTable));
}
return result;
@@ -1784,7 +1788,7 @@ static int db_delete_all_objects_tree(Process* p, DbTable* tbl)
{
db_free_table_tree(tbl);
db_create_tree(p, tbl);
- erts_smp_atomic_set(&tbl->tree.common.nitems, 0);
+ erts_smp_atomic_set_nob(&tbl->tree.common.nitems, 0);
return 0;
}
@@ -1866,7 +1870,7 @@ static TreeDbTerm *linkout_tree(DbTableTree *tb,
tstack[tpos++] = this;
state = delsub(this);
}
- erts_smp_atomic_dec(&tb->common.nitems);
+ erts_smp_atomic_dec_nob(&tb->common.nitems);
break;
}
}
@@ -1933,7 +1937,7 @@ static TreeDbTerm *linkout_object_tree(DbTableTree *tb,
tstack[tpos++] = this;
state = delsub(this);
}
- erts_smp_atomic_dec(&tb->common.nitems);
+ erts_smp_atomic_dec_nob(&tb->common.nitems);
break;
}
}
diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c
index e5be1f253a..4821a7d9fb 100644
--- a/erts/emulator/beam/erl_db_util.c
+++ b/erts/emulator/beam/erl_db_util.c
@@ -35,6 +35,7 @@
#include "bif.h"
#include "big.h"
#include "erl_binary.h"
+#include "erl_thr_progress.h"
#include "erl_db_util.h"
@@ -491,11 +492,11 @@ erts_match_set_release_result(Process* c_p)
/* The trace control word. */
-static erts_smp_atomic_t trace_control_word;
+static erts_smp_atomic32_t trace_control_word;
/* This needs to be here, before the bif table... */
-static Eterm db_set_trace_control_word_fake_1(Process *p, Eterm val);
+static Eterm db_set_trace_control_word_fake_1(BIF_ALIST_1);
/*
** The table of callable bif's, i e guard bif's and
@@ -908,14 +909,18 @@ static void db_free_tmp_uncompressed(DbTerm* obj);
/*
** Pseudo BIF:s to be callable from the PAM VM.
*/
-
-BIF_RETTYPE db_get_trace_control_word_0(Process *p)
+BIF_RETTYPE db_get_trace_control_word(Process *p)
{
- Uint32 tcw = (Uint32) erts_smp_atomic_read(&trace_control_word);
+ Uint32 tcw = (Uint32) erts_smp_atomic32_read_acqb(&trace_control_word);
BIF_RET(erts_make_integer((Uint) tcw, p));
}
-BIF_RETTYPE db_set_trace_control_word_1(Process *p, Eterm new)
+BIF_RETTYPE db_get_trace_control_word_0(BIF_ALIST_0)
+{
+ BIF_RET(db_get_trace_control_word(BIF_P));
+}
+
+BIF_RETTYPE db_set_trace_control_word(Process *p, Eterm new)
{
Uint val;
Uint32 old_tcw;
@@ -923,19 +928,27 @@ BIF_RETTYPE db_set_trace_control_word_1(Process *p, Eterm new)
BIF_ERROR(p, BADARG);
if (val != ((Uint32)val))
BIF_ERROR(p, BADARG);
-
- old_tcw = (Uint32) erts_smp_atomic_xchg(&trace_control_word, (erts_aint_t) val);
+
+ old_tcw = (Uint32) erts_smp_atomic32_xchg_relb(&trace_control_word,
+ (erts_aint32_t) val);
BIF_RET(erts_make_integer((Uint) old_tcw, p));
}
-static Eterm db_set_trace_control_word_fake_1(Process *p, Eterm new)
+BIF_RETTYPE db_set_trace_control_word_1(BIF_ALIST_1)
{
+ BIF_RET(db_set_trace_control_word(BIF_P, BIF_ARG_1));
+}
+
+static Eterm db_set_trace_control_word_fake_1(BIF_ALIST_1)
+{
+ Process *p = BIF_P;
+ Eterm new = BIF_ARG_1;
Uint val;
if (!term_to_Uint(new, &val))
BIF_ERROR(p, BADARG);
if (val != ((Uint32)val))
BIF_ERROR(p, BADARG);
- BIF_RET(db_get_trace_control_word_0(p));
+ BIF_RET(db_get_trace_control_word(p));
}
/*
@@ -1249,7 +1262,7 @@ void db_initialize_util(void){
sizeof(DMCGuardBif),
(int (*)(const void *, const void *)) &cmp_guard_bif);
match_pseudo_process_init();
- erts_smp_atomic_init(&trace_control_word, 0);
+ erts_smp_atomic32_init_nob(&trace_control_word, 0);
}
@@ -1703,6 +1716,7 @@ Eterm db_prog_match(Process *c_p, Binary *bprog,
Process *current_scheduled;
ErtsSchedulerData *esdp;
Eterm (*bif)(Process*, ...);
+ Eterm bif_args[3];
int fail_label;
int atomic_trace;
#if HALFWORD_HEAP
@@ -1733,14 +1747,14 @@ Eterm db_prog_match(Process *c_p, Binary *bprog,
if (! atomic_trace) { \
erts_refc_inc(&bprog->refc, 2); \
erts_smp_proc_unlock((p), ERTS_PROC_LOCK_MAIN); \
- erts_smp_block_system(0); \
+ erts_smp_thr_progress_block(); \
atomic_trace = !0; \
} \
} while (0)
#define END_ATOMIC_TRACE(p) \
do { \
if (atomic_trace) { \
- erts_smp_release_system(); \
+ erts_smp_thr_progress_unblock(); \
erts_smp_proc_lock((p), ERTS_PROC_LOCK_MAIN); \
if (erts_refc_dectest(&bprog->refc, 0) == 0) {\
erts_bin_free(bprog); \
@@ -1956,7 +1970,7 @@ restart:
break;
case matchCall0:
bif = (Eterm (*)(Process*, ...)) *pc++;
- t = (*bif)(build_proc);
+ t = (*bif)(build_proc, bif_args);
if (is_non_value(t)) {
if (do_catch)
t = FAIL_TERM;
@@ -1967,7 +1981,7 @@ restart:
break;
case matchCall1:
bif = (Eterm (*)(Process*, ...)) *pc++;
- t = (*bif)(build_proc, esp[-1]);
+ t = (*bif)(build_proc, esp-1);
if (is_non_value(t)) {
if (do_catch)
t = FAIL_TERM;
@@ -1978,7 +1992,9 @@ restart:
break;
case matchCall2:
bif = (Eterm (*)(Process*, ...)) *pc++;
- t = (*bif)(build_proc, esp[-1], esp[-2]);
+ bif_args[0] = esp[-1];
+ bif_args[1] = esp[-2];
+ t = (*bif)(build_proc, bif_args);
if (is_non_value(t)) {
if (do_catch)
t = FAIL_TERM;
@@ -1990,7 +2006,10 @@ restart:
break;
case matchCall3:
bif = (Eterm (*)(Process*, ...)) *pc++;
- t = (*bif)(build_proc, esp[-1], esp[-2], esp[-3]);
+ bif_args[0] = esp[-1];
+ bif_args[1] = esp[-2];
+ bif_args[2] = esp[-3];
+ t = (*bif)(build_proc, bif_args);
if (is_non_value(t)) {
if (do_catch)
t = FAIL_TERM;
@@ -2845,7 +2864,9 @@ void* db_store_term_comp(DbTableCommon *tb, DbTerm* old, Uint offset, Eterm obj)
Uint new_sz = offset + db_size_dbterm_comp(tb, obj);
byte* basep;
DbTerm* newp;
+#ifdef DEBUG
byte* top;
+#endif
ASSERT(tb->compress);
if (old != 0) {
@@ -2867,7 +2888,10 @@ void* db_store_term_comp(DbTableCommon *tb, DbTerm* old, Uint offset, Eterm obj)
}
newp->size = size_object(obj);
- top = copy_to_comp(tb, obj, newp, new_sz);
+#ifdef DEBUG
+ top =
+#endif
+ copy_to_comp(tb, obj, newp, new_sz);
ASSERT(top <= basep + new_sz);
/* ToDo: Maybe realloc if ((basep+new_sz) - top) > WASTED_SPACE_LIMIT */
@@ -4969,7 +4993,7 @@ static Eterm match_spec_test(Process *p, Eterm against, Eterm spec, int trace)
static Eterm seq_trace_fake(Process *p, Eterm arg1)
{
- Eterm result = seq_trace_info_1(p,arg1);
+ Eterm result = erl_seq_trace_info(p, arg1);
if (is_tuple(result) && *tuple_val(result) == 2) {
return (tuple_val(result))[2];
}
diff --git a/erts/emulator/beam/erl_db_util.h b/erts/emulator/beam/erl_db_util.h
index bb1751d309..6a96e174e1 100644
--- a/erts/emulator/beam/erl_db_util.h
+++ b/erts/emulator/beam/erl_db_util.h
@@ -326,8 +326,10 @@ ERTS_GLB_INLINE int db_eq(DbTableCommon* tb, Eterm a, DbTerm* b)
(T)->common.owner == (P)->id)
/* Function prototypes */
-Eterm db_get_trace_control_word_0(Process *p);
-Eterm db_set_trace_control_word_1(Process *p, Eterm val);
+BIF_RETTYPE db_get_trace_control_word(Process* p);
+BIF_RETTYPE db_set_trace_control_word(Process* p, Eterm tcw);
+BIF_RETTYPE db_get_trace_control_word_0(BIF_ALIST_0);
+BIF_RETTYPE db_set_trace_control_word_1(BIF_ALIST_1);
void db_initialize_util(void);
Eterm db_getkey(int keypos, Eterm obj);
diff --git a/erts/emulator/beam/erl_driver.h b/erts/emulator/beam/erl_driver.h
index 401967a8de..ae0c9def90 100644
--- a/erts/emulator/beam/erl_driver.h
+++ b/erts/emulator/beam/erl_driver.h
@@ -28,6 +28,14 @@
# include "config.h"
#endif
+#define ERL_DRV_DEPRECATED_FUNC
+#ifdef __GNUC__
+# if __GNUC__ >= 3
+# undef ERL_DRV_DEPRECATED_FUNC
+# define ERL_DRV_DEPRECATED_FUNC __attribute__((deprecated))
+# endif
+#endif
+
#ifdef SIZEOF_CHAR
# define SIZEOF_CHAR_SAVED__ SIZEOF_CHAR
# undef SIZEOF_CHAR
@@ -582,8 +590,11 @@ EXTERN long driver_async(ErlDrvPort ix,
void* async_data,
void (*async_free)(void*));
-
-EXTERN int driver_async_cancel(unsigned int key);
+/*
+ * driver_async_cancel() is deprecated. It is scheduled for removal
+ * in OTP-R16. For more information see the erl_driver(3) documentation.
+ */
+EXTERN int driver_async_cancel(unsigned int key) ERL_DRV_DEPRECATED_FUNC;
/* Locks the driver in the machine "forever", there is
no unlock function. Note that this is almost never useful, as an open
diff --git a/erts/emulator/beam/erl_drv_thread.c b/erts/emulator/beam/erl_drv_thread.c
index dc578f6d2a..a49a155701 100644
--- a/erts/emulator/beam/erl_drv_thread.c
+++ b/erts/emulator/beam/erl_drv_thread.c
@@ -158,7 +158,9 @@ erl_drv_mutex_create(char *name)
(sizeof(ErlDrvMutex)
+ (name ? sys_strlen(name) + 1 : 0)));
if (dmtx) {
- if (ethr_mutex_init(&dmtx->mtx) != 0) {
+ ethr_mutex_opt opt = ETHR_MUTEX_OPT_DEFAULT_INITER;
+ opt.posix_compliant = 1;
+ if (ethr_mutex_init_opt(&dmtx->mtx, &opt) != 0) {
erts_free(ERTS_ALC_T_DRV_MTX, (void *) dmtx);
dmtx = NULL;
}
@@ -226,7 +228,9 @@ erl_drv_cond_create(char *name)
(sizeof(ErlDrvCond)
+ (name ? sys_strlen(name) + 1 : 0)));
if (dcnd) {
- if (ethr_cond_init(&dcnd->cnd) != 0) {
+ ethr_cond_opt opt = ETHR_COND_OPT_DEFAULT_INITER;
+ opt.posix_compliant = 1;
+ if (ethr_cond_init_opt(&dcnd->cnd, &opt) != 0) {
erts_free(ERTS_ALC_T_DRV_CND, (void *) dcnd);
dcnd = NULL;
}
diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c
index 5edcd667e7..eb2b945877 100644
--- a/erts/emulator/beam/erl_gc.c
+++ b/erts/emulator/beam/erl_gc.c
@@ -100,14 +100,14 @@ 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, int new_sz, Eterm* objv, int nobj);
+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 Uint adjust_after_fullsweep(Process *p, int size_before,
+static Uint adjust_after_fullsweep(Process *p, Uint size_before,
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);
@@ -315,7 +315,12 @@ erts_gc_after_bif_call(Process* p, Eterm result, Eterm* regs, Uint arity)
if (is_non_value(result)) {
if (p->freason == TRAP) {
- cost = erts_garbage_collect(p, 0, p->def_arg_reg, p->arity);
+ #if HIPE
+ if (regs == NULL) {
+ regs = ERTS_PROC_GET_SCHDATA(p)->x_reg_array;
+ }
+ #endif
+ cost = erts_garbage_collect(p, 0, regs, p->arity);
} else {
cost = erts_garbage_collect(p, 0, regs, arity);
}
@@ -357,8 +362,6 @@ erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj)
}
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
- erts_smp_locked_activity_begin(ERTS_ACTIVITY_GC);
-
ERTS_CHK_OFFHEAP(p);
ErtsGcQuickSanityCheck(p);
@@ -392,8 +395,6 @@ erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj)
trace_gc(p, am_gc_end);
}
- erts_smp_locked_activity_end(ERTS_ACTIVITY_GC);
-
if (erts_system_monitor_long_gc != 0) {
Uint ms2, s2, us2;
Sint t;
@@ -441,7 +442,15 @@ erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj)
p->last_old_htop = p->old_htop;
#endif
- return ((int) (HEAP_TOP(p) - HEAP_START(p)) / 10);
+ /* 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;
+ }
}
/*
@@ -469,7 +478,6 @@ erts_garbage_collect_hibernate(Process* p)
p->gcstatus = p->status;
p->status = P_GARBING;
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
- erts_smp_locked_activity_begin(ERTS_ACTIVITY_GC);
ErtsGcQuickSanityCheck(p);
ASSERT(p->mbuf_sz == 0);
ASSERT(p->mbuf == 0);
@@ -583,12 +591,13 @@ erts_garbage_collect_hibernate(Process* p)
erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
p->status = p->gcstatus;
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
- erts_smp_locked_activity_end(ERTS_ACTIVITY_GC);
}
void
-erts_garbage_collect_literals(Process* p, Eterm* literals, Uint lit_size)
+erts_garbage_collect_literals(Process* p, Eterm* literals,
+ Uint lit_size,
+ struct erl_off_heap_header* oh)
{
Uint byte_lit_size = sizeof(Eterm)*lit_size;
Uint old_heap_size;
@@ -599,7 +608,8 @@ erts_garbage_collect_literals(Process* p, Eterm* literals, Uint lit_size)
char* area;
Uint area_size;
Eterm* old_htop;
- int n;
+ Uint n;
+ struct erl_off_heap_header** prev;
/*
* Set GC state.
@@ -608,7 +618,6 @@ erts_garbage_collect_literals(Process* p, Eterm* literals, Uint lit_size)
p->gcstatus = p->status;
p->status = P_GARBING;
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
- erts_smp_locked_activity_begin(ERTS_ACTIVITY_GC);
/*
* We assume that the caller has already done a major collection
@@ -634,6 +643,9 @@ erts_garbage_collect_literals(Process* p, Eterm* literals, Uint lit_size)
offset_heap(temp_lit, lit_size, offs, (char *) literals, byte_lit_size);
offset_heap(p->heap, p->htop - p->heap, offs, (char *) literals, byte_lit_size);
offset_rootset(p, offs, (char *) literals, byte_lit_size, p->arg_reg, p->arity);
+ if (oh) {
+ oh = (struct erl_off_heap_header *) ((Eterm *)(void *) oh + offs);
+ }
/*
* Now the literals are placed in memory that is safe to write into,
@@ -701,6 +713,45 @@ erts_garbage_collect_literals(Process* p, Eterm* literals, Uint lit_size)
p->old_htop = old_htop;
/*
+ * Prepare to sweep binaries. Since all MSOs on the new heap
+ * must be come before MSOs on the old heap, find the end of
+ * current MSO list and use that as a starting point.
+ */
+
+ if (oh) {
+ prev = &MSO(p).first;
+ while (*prev) {
+ prev = &(*prev)->next;
+ }
+ }
+
+ /*
+ * Sweep through all binaries in the temporary literal area.
+ */
+
+ while (oh) {
+ if (IS_MOVED_BOXED(oh->thing_word)) {
+ Binary* bptr;
+ struct erl_off_heap_header* ptr;
+
+ ptr = (struct erl_off_heap_header*) boxed_val(oh->thing_word);
+ ASSERT(thing_subtag(ptr->thing_word) == REFC_BINARY_SUBTAG);
+ bptr = ((ProcBin*)ptr)->val;
+
+ /*
+ * This binary has been copied to the heap.
+ * We must increment its reference count and
+ * link it into the MSO list for the process.
+ */
+
+ erts_refc_inc(&bptr->refc, 1);
+ *prev = ptr;
+ prev = &ptr->next;
+ }
+ oh = oh->next;
+ }
+
+ /*
* We no longer need this temporary area.
*/
erts_free(ERTS_ALC_T_TMP, (void *) temp_lit);
@@ -711,7 +762,6 @@ erts_garbage_collect_literals(Process* p, Eterm* literals, Uint lit_size)
erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
p->status = p->gcstatus;
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
- erts_smp_locked_activity_end(ERTS_ACTIVITY_GC);
}
static int
@@ -731,7 +781,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).
*/
- size_t new_sz = erts_next_heap_size(HEAP_TOP(p) - HEAP_START(p), 1);
+ Uint new_sz = erts_next_heap_size(HEAP_TOP(p) - HEAP_START(p), 1);
/* Create new, empty old_heap */
n_old = (Eterm *) ERTS_HEAP_ALLOC(ERTS_ALC_T_OLD_HEAP,
@@ -871,12 +921,12 @@ minor_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
#endif /* HIPE */
static void
-do_minor(Process *p, int new_sz, Eterm* objv, int nobj)
+do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj)
{
Rootset rootset; /* Rootset for GC (stack, dictionary, etc). */
Roots* roots;
Eterm* n_htop;
- int n;
+ Uint n;
Eterm* ptr;
Eterm val;
Eterm gval;
@@ -1079,14 +1129,14 @@ major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
{
Rootset rootset;
Roots* roots;
- int size_before;
+ Uint size_before;
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;
- int n;
+ Uint n;
Uint new_sz;
Uint fragments = MBUF_SIZE(p) + combined_message_size(p);
ErlMessage *msgp;
@@ -1312,10 +1362,10 @@ major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
}
static Uint
-adjust_after_fullsweep(Process *p, int size_before, int need, Eterm *objv, int nobj)
+adjust_after_fullsweep(Process *p, Uint size_before, int need, Eterm *objv, int nobj)
{
- int wanted, sz, size_after, need_after;
- int stack_size = STACK_SZ_ON_HEAP(p);
+ Uint wanted, sz, size_after, need_after;
+ Uint stack_size = STACK_SZ_ON_HEAP(p);
Uint reclaimed_now;
size_after = (HEAP_TOP(p) - HEAP_START(p));
@@ -1915,8 +1965,8 @@ static void
grow_new_heap(Process *p, Uint new_sz, Eterm* objv, int nobj)
{
Eterm* new_heap;
- int heap_size = HEAP_TOP(p) - HEAP_START(p);
- int stack_size = p->hend - p->stop;
+ Uint heap_size = HEAP_TOP(p) - HEAP_START(p);
+ Uint stack_size = p->hend - p->stop;
Sint offs;
ASSERT(HEAP_SIZE(p) < new_sz);
@@ -1954,10 +2004,10 @@ static void
shrink_new_heap(Process *p, Uint new_sz, Eterm *objv, int nobj)
{
Eterm* new_heap;
- int heap_size = HEAP_TOP(p) - HEAP_START(p);
+ Uint heap_size = HEAP_TOP(p) - HEAP_START(p);
Sint offs;
- int stack_size = p->hend - p->stop;
+ Uint stack_size = p->hend - p->stop;
ASSERT(new_sz < p->heap_sz);
sys_memmove(p->heap + new_sz - stack_size, p->stop, stack_size *
diff --git a/erts/emulator/beam/erl_goodfit_alloc.c b/erts/emulator/beam/erl_goodfit_alloc.c
index 1cc508ac5a..e7d4ac2b67 100644
--- a/erts/emulator/beam/erl_goodfit_alloc.c
+++ b/erts/emulator/beam/erl_goodfit_alloc.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2003-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2003-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -190,16 +190,20 @@ erts_gfalc_start(GFAllctr_t *gfallctr,
GFAllctrInit_t *gfinit,
AllctrInit_t *init)
{
- GFAllctr_t nulled_state = {{0}};
- /* {{0}} is used instead of {0}, in order to avoid (an incorrect) gcc
- warning. gcc warns if {0} is used as initializer of a struct when
- the first member is a struct (not if, for example, the third member
- is a struct). */
+ struct {
+ int dummy;
+ GFAllctr_t allctr;
+ } zero = {0};
+ /* The struct with a dummy element first is used in order to avoid (an
+ incorrect) gcc warning. gcc warns if {0} is used as initializer of
+ a struct when the first member is a struct (not if, for example,
+ the third member is a struct). */
+
Allctr_t *allctr = (Allctr_t *) gfallctr;
- init->sbmbct = 0; /* Small mbc not yet supported by goodfit */
+ sys_memcpy((void *) gfallctr, (void *) &zero.allctr, sizeof(GFAllctr_t));
- sys_memcpy((void *) gfallctr, (void *) &nulled_state, sizeof(GFAllctr_t));
+ init->sbmbct = 0; /* Small mbc not yet supported by goodfit */
allctr->mbc_header_size = sizeof(Carrier_t);
allctr->min_mbc_size = MIN_MBC_SZ;
diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c
index 02efd2adb6..6c4ba2af68 100644
--- a/erts/emulator/beam/erl_init.c
+++ b/erts/emulator/beam/erl_init.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1997-2010. All Rights Reserved.
+ * Copyright Ericsson AB 1997-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -42,6 +42,9 @@
#include "erl_misc_utils.h"
#include "packet_parser.h"
#include "erl_cpu_topology.h"
+#include "erl_thr_progress.h"
+#include "erl_thr_queue.h"
+#include "erl_async.h"
#ifdef HIPE
#include "hipe_mode_switch.h" /* for hipe_mode_switch_init() */
@@ -68,8 +71,11 @@ static void erl_init(int ncpu);
#define ERTS_MIN_COMPAT_REL 7
+static erts_atomic_t exiting;
+
#ifdef ERTS_SMP
-erts_smp_atomic_t erts_writing_erl_crash_dump;
+erts_smp_atomic32_t erts_writing_erl_crash_dump;
+erts_tsd_key_t erts_is_crash_dumping_key;
#else
volatile int erts_writing_erl_crash_dump = 0;
#endif
@@ -86,7 +92,6 @@ int erts_use_sender_punish;
*/
Uint display_items; /* no of items to display in traces etc */
-Uint display_loads; /* print info about loaded modules */
int H_MIN_SIZE; /* The minimum heap grain */
int BIN_VH_MIN_SIZE; /* The minimum binary virtual*/
@@ -98,8 +103,6 @@ int erts_backtrace_depth; /* How many functions to show in a backtrace
* in error codes.
*/
-int erts_async_max_threads; /* number of threads for async support */
-int erts_async_thread_suggested_stack_size;
erts_smp_atomic32_t erts_max_gen_gcs;
Eterm erts_error_logger_warnings; /* What to map warning logs to, am_error,
@@ -126,6 +129,8 @@ int erts_modified_timing_level;
int erts_no_crash_dump = 0; /* Use -d to suppress crash dump. */
+int erts_no_line_info = 0; /* -L: Don't load line information */
+
/*
* Other global variables.
*/
@@ -244,10 +249,6 @@ erl_init(int ncpu)
{
init_benchmarking();
-#ifdef ERTS_SMP
- erts_system_block_init();
-#endif
-
erts_init_monitors();
erts_init_gc();
erts_init_time();
@@ -257,6 +258,8 @@ erl_init(int ncpu)
no_schedulers,
no_schedulers_online);
erts_init_cpu_topology(); /* Must be after init_scheduling */
+ erts_alloc_late_init();
+
H_MIN_SIZE = erts_next_heap_size(H_MIN_SIZE, 0);
BIN_VH_MIN_SIZE = erts_next_heap_size(BIN_VH_MIN_SIZE, 0);
@@ -278,6 +281,7 @@ erl_init(int ncpu)
erts_init_node_tables();
init_dist();
erl_drv_thr_init();
+ erts_init_async();
init_io();
init_copy();
init_load();
@@ -323,7 +327,7 @@ init_shared_memory(int argc, char **argv)
#endif
global_gen_gcs = 0;
- global_max_gen_gcs = (Uint16) erts_smp_atomic32_read(&erts_max_gen_gcs);
+ global_max_gen_gcs = (Uint16) erts_smp_atomic32_read_nob(&erts_max_gen_gcs);
global_gc_flags = erts_default_process_flags;
erts_global_offheap.mso = NULL;
@@ -432,7 +436,7 @@ static void
load_preloaded(void)
{
int i;
- int res;
+ Eterm res;
Preload* preload_p;
Eterm module_name;
byte* code;
@@ -451,8 +455,9 @@ load_preloaded(void)
name);
res = erts_load_module(NULL, 0, NIL, &module_name, code, length);
sys_preload_end(&preload_p[i]);
- if (res < 0)
- erl_exit(1,"Failed loading preloaded module %s\n", name);
+ if (res != NIL)
+ erl_exit(1,"Failed loading preloaded module %s (%T)\n",
+ name, res);
i++;
}
}
@@ -494,8 +499,6 @@ void erts_usage(void)
erts_fprintf(stderr, "-K boolean enable or disable kernel poll\n");
- erts_fprintf(stderr, "-l turn on auto load tracing\n");
-
erts_fprintf(stderr, "-M<X> <Y> memory allocator switches,\n");
erts_fprintf(stderr, " see the erts_alloc(3) documentation for more info.\n");
@@ -606,13 +609,14 @@ early_init(int *argc, char **argv) /*
int max_main_threads;
int max_reader_groups;
int reader_groups;
+ char envbuf[21]; /* enough for any 64-bit integer */
+ size_t envbufsz;
erts_sched_compact_load = 1;
use_multi_run_queue = 1;
erts_printf_eterm_func = erts_printf_term;
erts_disable_tolerant_timeofday = 0;
display_items = 200;
- display_loads = 0;
erts_backtrace_depth = DEFAULT_BACKTRACE_SIZE;
erts_async_max_threads = 0;
erts_async_thread_suggested_stack_size = ERTS_ASYNC_THREAD_MIN_STACK_SIZE;
@@ -644,17 +648,23 @@ early_init(int *argc, char **argv) /*
erts_use_r9_pids_ports = 0;
erts_sys_pre_init();
+ erts_atomic_init_nob(&exiting, 0);
+#ifdef ERTS_SMP
+ erts_thr_progress_pre_init();
+#endif
#ifdef ERTS_ENABLE_LOCK_CHECK
erts_lc_init();
#endif
#ifdef ERTS_SMP
- erts_smp_atomic_init(&erts_writing_erl_crash_dump, 0L);
+ erts_smp_atomic32_init_nob(&erts_writing_erl_crash_dump, 0L);
+ erts_tsd_key_create(&erts_is_crash_dumping_key);
#else
erts_writing_erl_crash_dump = 0;
#endif
- erts_smp_atomic32_init(&erts_max_gen_gcs, (erts_aint32_t) ((Uint16) -1));
+ erts_smp_atomic32_init_nob(&erts_max_gen_gcs,
+ (erts_aint32_t) ((Uint16) -1));
erts_pre_init_process();
#if defined(USE_THREADS) && !defined(ERTS_SMP)
@@ -673,6 +683,16 @@ early_init(int *argc, char **argv) /*
schdlrs = no_schedulers;
schdlrs_onln = no_schedulers_online;
+ envbufsz = sizeof(envbuf);
+
+ /* erts_sys_getenv() not initialized yet; need erts_sys_getenv__() */
+ if (erts_sys_getenv__("ERL_THREAD_POOL_SIZE", envbuf, &envbufsz) == 0)
+ erts_async_max_threads = atoi(envbuf);
+ else
+ erts_async_max_threads = 0;
+ if (erts_async_max_threads > ERTS_MAX_NO_OF_ASYNC_THREADS)
+ erts_async_max_threads = ERTS_MAX_NO_OF_ASYNC_THREADS;
+
if (argc && argv) {
int i = 1;
while (i < *argc) {
@@ -700,6 +720,20 @@ early_init(int *argc, char **argv) /*
}
break;
}
+ case 'A': {
+ /* set number of threads in thread pool */
+ char *arg = get_arg(argv[i]+2, argv[i+1], &i);
+ if (((erts_async_max_threads = atoi(arg)) < 0) ||
+ (erts_async_max_threads > ERTS_MAX_NO_OF_ASYNC_THREADS)) {
+ erts_fprintf(stderr,
+ "bad number of async threads %s\n",
+ arg);
+ erts_usage();
+ VERBOSE(DEBUG_SYSTEM, ("using %d async-threads\n",
+ erts_async_max_threads));
+ }
+ break;
+ }
case 'S' : {
int tot, onln;
char *arg = get_arg(argv[i]+2, argv[i+1], &i);
@@ -765,11 +799,29 @@ early_init(int *argc, char **argv) /*
erts_no_schedulers = (Uint) no_schedulers;
#endif
+ erts_early_init_scheduling(no_schedulers);
+ alloc_opts.ncpu = ncpu;
erts_alloc_init(argc, argv, &alloc_opts); /* Handles (and removes)
-M flags. */
/* Require allocators */
- erts_early_init_scheduling();
+#ifdef ERTS_SMP
+ /*
+ * Thread progress management:
+ *
+ * * Managed threads:
+ * ** Scheduler threads (see erl_process.c)
+ * ** Aux thread (see erl_process.c)
+ * ** Sys message dispatcher thread (see erl_trace.c)
+ *
+ * * Unmanaged threads that need to register:
+ * ** Async threads (see erl_async.c)
+ */
+ erts_thr_progress_init(no_schedulers,
+ no_schedulers+2,
+ erts_async_max_threads);
+#endif
+ erts_thr_q_init();
erts_init_utils();
erts_early_init_cpu_topology(no_schedulers,
&max_main_threads,
@@ -806,10 +858,12 @@ early_init(int *argc, char **argv) /*
#if defined(HIPE)
hipe_signal_init(); /* must be done very early */
#endif
- erl_sys_init();
erl_sys_args(argc, argv);
+ /* Creates threads on Windows that depend on the arguments, so has to be after erl_sys_args */
+ erl_sys_init();
+
erts_ets_realloc_always_moves = 0;
erts_ets_always_compress = 0;
erts_dist_buf_busy_limit = ERTS_DE_BUSY_LIMIT;
@@ -847,7 +901,6 @@ erl_start(int argc, char **argv)
int have_break_handler = 1;
char envbuf[21]; /* enough for any 64-bit integer */
size_t envbufsz;
- int async_max_threads = erts_async_max_threads;
int ncpu = early_init(&argc, argv);
envbufsz = sizeof(envbuf);
@@ -859,12 +912,8 @@ erl_start(int argc, char **argv)
envbufsz = sizeof(envbuf);
if (erts_sys_getenv("ERL_FULLSWEEP_AFTER", envbuf, &envbufsz) == 0) {
Uint16 max_gen_gcs = atoi(envbuf);
- erts_smp_atomic32_set(&erts_max_gen_gcs, (erts_aint32_t) max_gen_gcs);
- }
-
- envbufsz = sizeof(envbuf);
- if (erts_sys_getenv("ERL_THREAD_POOL_SIZE", envbuf, &envbufsz) == 0) {
- async_max_threads = atoi(envbuf);
+ erts_smp_atomic32_set_nob(&erts_max_gen_gcs,
+ (erts_aint32_t) max_gen_gcs);
}
#if (defined(__APPLE__) && defined(__MACH__)) || defined(__DARWIN__)
@@ -932,10 +981,9 @@ erl_start(int argc, char **argv)
erts_fprintf(stderr, "%s unknown flag %s\n", argv[0], argv[i]);
erts_usage();
}
- case 'l':
- display_loads++;
+ case 'L':
+ erts_no_line_info = 1;
break;
-
case 'v':
#ifdef DEBUG
if (argv[i][2] == '\0') {
@@ -1307,17 +1355,8 @@ erl_start(int argc, char **argv)
break;
}
- case 'A':
- /* set number of threads in thread pool */
- arg = get_arg(argv[i]+2, argv[i+1], &i);
- if (((async_max_threads = atoi(arg)) < 0) ||
- (async_max_threads > ERTS_MAX_NO_OF_ASYNC_THREADS)) {
- erts_fprintf(stderr, "bad number of async threads %s\n", arg);
- erts_usage();
- }
-
- VERBOSE(DEBUG_SYSTEM, ("using %d async-threads\n",
- async_max_threads));
+ case 'A': /* Was handled in early init just read past it */
+ (void) get_arg(argv[i]+2, argv[i+1], &i);
break;
case 'a':
@@ -1406,10 +1445,6 @@ erl_start(int argc, char **argv)
i++;
}
-#ifdef USE_THREADS
- erts_async_max_threads = async_max_threads;
-#endif
-
/* Delayed check of +P flag */
if (erts_max_processes < ERTS_MIN_PROCESSES
|| erts_max_processes > ERTS_MAX_PROCESSES
@@ -1455,6 +1490,10 @@ erl_start(int argc, char **argv)
erts_sys_main_thread(); /* May or may not return! */
#else
erts_thr_set_main_status(1, 1);
+#if ERTS_USE_ASYNC_READY_Q
+ erts_get_scheduler_data()->aux_work_data.async_ready.queue
+ = erts_get_async_ready_queue(1);
+#endif
set_main_stack_size();
process_main();
#endif
@@ -1480,6 +1519,29 @@ __decl_noreturn void erts_thr_fatal_error(int err, char *what)
static void
system_cleanup(int exit_code)
{
+ /*
+ * Make sure only one thread exits the runtime system.
+ */
+ if (erts_atomic_inc_read_nob(&exiting) != 1) {
+ /*
+ * Another thread is currently exiting the system;
+ * wait for it to do its job.
+ */
+#ifdef ERTS_SMP
+ if (erts_thr_progress_is_managed_thread()) {
+ /*
+ * The exiting thread might be waiting for
+ * us to block; need to update status...
+ */
+ erts_thr_progress_active(NULL, 0);
+ erts_thr_progress_prepare_wait(NULL);
+ }
+#endif
+ /* Wait forever... */
+ while (1)
+ erts_milli_sleep(10000000);
+ }
+
/* No cleanup wanted if ...
* 1. we are about to do an abnormal exit
* 2. we haven't finished initializing, or
@@ -1499,7 +1561,6 @@ system_cleanup(int exit_code)
#ifdef ERTS_ENABLE_LOCK_CHECK
erts_lc_check_exact(NULL, 0);
#endif
- erts_smp_block_system(ERTS_BS_FLG_ALLOW_GC); /* We never release it... */
#endif
#ifdef HYBRID
@@ -1528,17 +1589,7 @@ system_cleanup(int exit_code)
erts_cleanup_incgc();
#endif
-#if defined(USE_THREADS)
- exit_async();
-#endif
-#if HAVE_ERTS_MSEG
- erts_mseg_exit();
-#endif
-
- /*
- * A lot more cleaning could/should have been done...
- */
-
+ erts_exit_flush_async();
}
/*
@@ -1555,10 +1606,10 @@ __decl_noreturn void erl_exit0(char *file, int line, int n, char *fmt,...)
va_start(args, fmt);
- save_statistics();
-
system_cleanup(n);
+ save_statistics();
+
an = abs(n);
if (erts_mtrace_enabled)
@@ -1595,10 +1646,10 @@ __decl_noreturn void erl_exit(int n, char *fmt,...)
va_start(args, fmt);
- save_statistics();
-
system_cleanup(n);
+ save_statistics();
+
an = abs(n);
if (erts_mtrace_enabled)
diff --git a/erts/emulator/beam/erl_instrument.c b/erts/emulator/beam/erl_instrument.c
index c5615818f2..963c8b3c58 100644
--- a/erts/emulator/beam/erl_instrument.c
+++ b/erts/emulator/beam/erl_instrument.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2003-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2003-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -1152,14 +1152,6 @@ erts_instr_get_type_info(Process *proc)
return res;
}
-#if HALFWORD_HEAP
-#define ERTS_IS_SBMBC_ALLOCATOR_NO__(NO) \
- ((NO) == ERTS_ALC_A_SBMBC || (NO) == ERTS_ALC_A_SBMBC_LOW)
-#else
-#define ERTS_IS_SBMBC_ALLOCATOR_NO__(NO) \
- ((NO) == ERTS_ALC_A_SBMBC)
-#endif
-
Uint
erts_instr_init(int stat, int map_stat)
{
diff --git a/erts/emulator/beam/erl_lock_check.c b/erts/emulator/beam/erl_lock_check.c
index 587d82f2bb..44da6b6c51 100644
--- a/erts/emulator/beam/erl_lock_check.c
+++ b/erts/emulator/beam/erl_lock_check.c
@@ -110,10 +110,6 @@ static erts_lc_lock_order_t erts_lock_order[] = {
{ "fun_tab", NULL },
{ "environ", NULL },
#endif
- { "asyncq", "address" },
-#ifndef ERTS_SMP
- { "async_ready", NULL },
-#endif
{ "efile_drv", "address" },
#if defined(ENABLE_CHILD_WAITER_THREAD) || defined(ERTS_SMP)
{ "child_status", NULL },
@@ -125,7 +121,7 @@ static erts_lc_lock_order_t erts_lock_order[] = {
{ "drv_ev_state", "address" },
{ "safe_hash", "address" },
{ "pollset_rm_list", NULL },
- { "removed_fd_pre_alloc_lock", NULL },
+ { "removed_fd_pre_alloc_lock", "address" },
{ "state_prealloc", NULL },
{ "schdlr_sspnd", NULL },
{ "run_queue", "address" },
@@ -138,6 +134,7 @@ static erts_lc_lock_order_t erts_lock_order[] = {
{ "alcu_init_atoms", NULL },
{ "mseg_init_atoms", NULL },
{ "drv_tsd", NULL },
+ { "async_enq_mtx", NULL },
#ifdef ERTS_SMP
{ "sys_msg_q", NULL },
{ "atom_tab", NULL },
@@ -151,10 +148,8 @@ static erts_lc_lock_order_t erts_lock_order[] = {
{ "mtrace_op", NULL },
{ "instr_x", NULL },
{ "instr", NULL },
- { "fix_alloc", "index" },
{ "alcu_allocator", "index" },
{ "sbmbc_alloc", "index" },
- { "alcu_delayed_free", "index" },
{ "mseg", NULL },
#if HALFWORD_HEAP
{ "pmmap", NULL },
@@ -175,15 +170,12 @@ static erts_lc_lock_order_t erts_lock_order[] = {
{ "timeofday", NULL },
{ "breakpoints", NULL },
{ "pollsets_lock", NULL },
- { "async_id", NULL },
{ "pix_lock", "address" },
{ "run_queues_lists", NULL },
- { "misc_aux_work_queue", "index" },
- { "misc_aux_work_pre_alloc_lock", "address" },
{ "sched_stat", NULL },
{ "run_queue_sleep_list", "address" },
#endif
- { "alloc_thr_ix_lock", NULL },
+ { "async_init_mtx", NULL },
#ifdef ERTS_SMP
{ "proc_lck_qs_alloc", NULL },
#endif
diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c
index 82f272d28a..16be47d540 100644
--- a/erts/emulator/beam/erl_message.c
+++ b/erts/emulator/beam/erl_message.c
@@ -240,7 +240,7 @@ erts_msg_distext2heap(Process *pp,
Sint sz;
*bpp = NULL;
- sz = erts_decode_dist_ext_size(dist_extp, 0);
+ sz = erts_decode_dist_ext_size(dist_extp);
if (sz < 0)
goto decode_error;
if (is_not_nil(*tokenp)) {
@@ -713,7 +713,7 @@ erts_msg_attached_data_size_aux(ErlMessage *msg)
ASSERT(msg->data.dist_ext);
ASSERT(msg->data.dist_ext->heap_size < 0);
- sz = erts_decode_dist_ext_size(msg->data.dist_ext, 0);
+ sz = erts_decode_dist_ext_size(msg->data.dist_ext);
if (sz < 0) {
/* Bad external; remove it */
if (is_not_nil(ERL_MESSAGE_TOKEN(msg))) {
diff --git a/erts/emulator/beam/erl_monitors.c b/erts/emulator/beam/erl_monitors.c
index 9751b5d77c..1a84950120 100644
--- a/erts/emulator/beam/erl_monitors.c
+++ b/erts/emulator/beam/erl_monitors.c
@@ -125,7 +125,7 @@ static ErtsMonitor *create_monitor(Uint type, Eterm ref, Eterm pid, Eterm name)
} else {
n = (ErtsMonitor *) erts_alloc(ERTS_ALC_T_MONITOR_LH,
mon_size*sizeof(Uint));
- erts_smp_atomic_add(&tot_link_lh_size, mon_size*sizeof(Uint));
+ erts_smp_atomic_add_nob(&tot_link_lh_size, mon_size*sizeof(Uint));
}
hp = n->heap;
@@ -156,7 +156,7 @@ static ErtsLink *create_link(Uint type, Eterm pid)
} else {
n = (ErtsLink *) erts_alloc(ERTS_ALC_T_NLINK_LH,
lnk_size*sizeof(Uint));
- erts_smp_atomic_add(&tot_link_lh_size, lnk_size*sizeof(Uint));
+ erts_smp_atomic_add_nob(&tot_link_lh_size, lnk_size*sizeof(Uint));
}
hp = n->heap;
@@ -191,13 +191,13 @@ static ErtsSuspendMonitor *create_suspend_monitor(Eterm pid)
void
erts_init_monitors(void)
{
- erts_smp_atomic_init(&tot_link_lh_size, 0);
+ erts_smp_atomic_init_nob(&tot_link_lh_size, 0);
}
Uint
erts_tot_link_lh_size(void)
{
- return (Uint) erts_smp_atomic_read(&tot_link_lh_size);
+ return (Uint) erts_smp_atomic_read_nob(&tot_link_lh_size);
}
void erts_destroy_monitor(ErtsMonitor *mon)
@@ -222,7 +222,7 @@ void erts_destroy_monitor(ErtsMonitor *mon)
erts_free(ERTS_ALC_T_MONITOR_SH, (void *) mon);
} else {
erts_free(ERTS_ALC_T_MONITOR_LH, (void *) mon);
- erts_smp_atomic_add(&tot_link_lh_size, -1*mon_size*sizeof(Uint));
+ erts_smp_atomic_add_nob(&tot_link_lh_size, -1*mon_size*sizeof(Uint));
}
}
@@ -244,7 +244,7 @@ void erts_destroy_link(ErtsLink *lnk)
erts_free(ERTS_ALC_T_NLINK_SH, (void *) lnk);
} else {
erts_free(ERTS_ALC_T_NLINK_LH, (void *) lnk);
- erts_smp_atomic_add(&tot_link_lh_size, -1*lnk_size*sizeof(Uint));
+ erts_smp_atomic_add_nob(&tot_link_lh_size, -1*lnk_size*sizeof(Uint));
}
}
@@ -948,8 +948,10 @@ static void erts_dump_links(ErtsLink *root, int indent)
erts_destroy_tmp_dsbuf(dsbufp);
}
-Eterm erts_debug_dump_monitors_1(Process *p, Eterm pid)
+Eterm erts_debug_dump_monitors_1(BIF_ALIST_1)
{
+ Process *p = BIF_P;
+ Eterm pid = BIF_ARG_1;
Process *rp;
DistEntry *dep;
rp = erts_pid2proc(p, ERTS_PROC_LOCK_MAIN, pid, ERTS_PROC_LOCK_LINK);
@@ -976,8 +978,10 @@ Eterm erts_debug_dump_monitors_1(Process *p, Eterm pid)
}
}
-Eterm erts_debug_dump_links_1(Process *p, Eterm pid)
+Eterm erts_debug_dump_links_1(BIF_ALIST_1)
{
+ Process *p = BIF_P;
+ Eterm pid = BIF_ARG_1;
Process *rp;
DistEntry *dep;
if (is_internal_port(pid)) {
diff --git a/erts/emulator/beam/erl_mtrace.c b/erts/emulator/beam/erl_mtrace.c
index b1478758a1..358c67bf20 100644
--- a/erts/emulator/beam/erl_mtrace.c
+++ b/erts/emulator/beam/erl_mtrace.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2003-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2003-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -503,12 +503,6 @@ write_trace_header(char *nodename, char *pid, char *hostname)
case ERTS_ALC_A_SYSTEM:
PUT_UI16(tracep, ERTS_MTRACE_SEGMENT_ID);
break;
- case ERTS_ALC_A_FIXED_SIZE:
- if (erts_allctrs_info[ERTS_FIX_CORE_ALLOCATOR].enabled)
- PUT_UI16(tracep, ERTS_FIX_CORE_ALLOCATOR);
- else
- PUT_UI16(tracep, ERTS_ALC_A_SYSTEM);
- break;
default:
PUT_UI16(tracep, ERTS_MTRACE_SEGMENT_ID);
break;
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index 68421b4387..62798bb2c1 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -32,6 +32,7 @@
#include "error.h"
#include "big.h"
#include "beam_bp.h"
+#include "erl_thr_progress.h"
#include <limits.h>
#include <stddef.h> /* offsetof */
@@ -130,10 +131,13 @@ static void pre_nif_noproc(ErlNifEnv* env, struct erl_module_nif* mod_nif)
env->tmp_obj_list = NULL;
}
-/* Temporary object header, auto-deallocated when NIF returns. */
+/* Temporary object header, auto-deallocated when NIF returns
+ * or when independent environment is cleared.
+ */
struct enif_tmp_obj_t {
struct enif_tmp_obj_t* next;
void (*dtor)(struct enif_tmp_obj_t*);
+ ErtsAlcType_t allocator;
/*char data[];*/
};
@@ -244,7 +248,7 @@ ErlNifEnv* enif_alloc_env(void)
msg_env->env.hp_end = phony_heap;
msg_env->env.heap_frag = NULL;
msg_env->env.mod_nif = NULL;
- msg_env->env.tmp_obj_list = (struct enif_tmp_obj_t*) 1; /* invalid non-NULL */
+ msg_env->env.tmp_obj_list = NULL;
msg_env->env.proc = &msg_env->phony_proc;
memset(&msg_env->phony_proc, 0, sizeof(Process));
HEAP_START(&msg_env->phony_proc) = phony_heap;
@@ -289,6 +293,7 @@ void enif_clear_env(ErlNifEnv* env)
menv->env.hp = menv->env.hp_end = HEAP_TOP(p);
ASSERT(!is_offheap(&MSO(p)));
+ free_tmp_objs(env);
}
int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid,
ErlNifEnv* msg_env, ERL_NIF_TERM msg)
@@ -435,24 +440,36 @@ int enif_is_exception(ErlNifEnv* env, ERL_NIF_TERM term)
return term == THE_NON_VALUE;
}
+int enif_is_number(ErlNifEnv* env, ERL_NIF_TERM term)
+{
+ return is_number(term);
+}
+
+static ERTS_INLINE int is_proc_bound(ErlNifEnv* env)
+{
+ return env->mod_nif != NULL;
+}
+
static void aligned_binary_dtor(struct enif_tmp_obj_t* obj)
{
- erts_free_aligned_binary_bytes_extra((byte*)obj,ERTS_ALC_T_TMP);
+ erts_free_aligned_binary_bytes_extra((byte*)obj, obj->allocator);
}
int enif_inspect_binary(ErlNifEnv* env, Eterm bin_term, ErlNifBinary* bin)
{
+ ErtsAlcType_t allocator = is_proc_bound(env) ? ERTS_ALC_T_TMP : ERTS_ALC_T_NIF;
union {
struct enif_tmp_obj_t* tmp;
byte* raw_ptr;
}u;
u.tmp = NULL;
- bin->data = erts_get_aligned_binary_bytes_extra(bin_term, &u.raw_ptr, ERTS_ALC_T_TMP,
+ bin->data = erts_get_aligned_binary_bytes_extra(bin_term, &u.raw_ptr, allocator,
sizeof(struct enif_tmp_obj_t));
if (bin->data == NULL) {
return 0;
}
if (u.tmp != NULL) {
+ u.tmp->allocator = allocator;
u.tmp->next = env->tmp_obj_list;
u.tmp->dtor = &aligned_binary_dtor;
env->tmp_obj_list = u.tmp;
@@ -466,12 +483,13 @@ int enif_inspect_binary(ErlNifEnv* env, Eterm bin_term, ErlNifBinary* bin)
static void tmp_alloc_dtor(struct enif_tmp_obj_t* obj)
{
- erts_free(ERTS_ALC_T_TMP, obj);
+ erts_free(obj->allocator, obj);
}
int enif_inspect_iolist_as_binary(ErlNifEnv* env, Eterm term, ErlNifBinary* bin)
{
struct enif_tmp_obj_t* tobj;
+ ErtsAlcType_t allocator;
Uint sz;
if (is_binary(term)) {
return enif_inspect_binary(env,term,bin);
@@ -486,8 +504,10 @@ int enif_inspect_iolist_as_binary(ErlNifEnv* env, Eterm term, ErlNifBinary* bin)
if (erts_iolist_size(term, &sz)) {
return 0;
}
-
- tobj = erts_alloc(ERTS_ALC_T_TMP, sz + sizeof(struct enif_tmp_obj_t));
+
+ allocator = is_proc_bound(env) ? ERTS_ALC_T_TMP : ERTS_ALC_T_NIF;
+ tobj = erts_alloc(allocator, sz + sizeof(struct enif_tmp_obj_t));
+ tobj->allocator = allocator;
tobj->next = env->tmp_obj_list;
tobj->dtor = &tmp_alloc_dtor;
env->tmp_obj_list = tobj;
@@ -578,7 +598,15 @@ int enif_is_identical(Eterm lhs, Eterm rhs)
int enif_compare(Eterm lhs, Eterm rhs)
{
- return CMP(lhs,rhs);
+ Sint result = CMP(lhs,rhs);
+
+ if (result < 0) {
+ return -1;
+ } else if (result > 0) {
+ return 1;
+ }
+
+ return result;
}
int enif_get_tuple(ErlNifEnv* env, Eterm tpl, int* arity, const Eterm** array)
@@ -668,6 +696,7 @@ Eterm enif_make_sub_binary(ErlNifEnv* env, ERL_NIF_TERM bin_term,
ErlSubBin* sb;
Eterm orig;
Uint offset, bit_offset, bit_size;
+#ifdef DEBUG
unsigned src_size;
ASSERT(is_binary(bin_term));
@@ -675,6 +704,7 @@ Eterm enif_make_sub_binary(ErlNifEnv* env, ERL_NIF_TERM bin_term,
ASSERT(pos <= src_size);
ASSERT(size <= src_size);
ASSERT(pos + size <= src_size);
+#endif
sb = (ErlSubBin*) alloc_heap(env, ERL_SUB_BIN_SIZE);
ERTS_GET_REAL_BIN(bin_term, orig, offset, bit_offset, bit_size);
sb->thing_word = HEADER_SUB_BIN;
@@ -833,8 +863,11 @@ ERL_NIF_TERM enif_make_uint(ErlNifEnv* env, unsigned i)
ERL_NIF_TERM enif_make_long(ErlNifEnv* env, long i)
{
+ if (IS_SSMALL(i)) {
+ return make_small(i);
+ }
#if SIZEOF_LONG == ERTS_SIZEOF_ETERM
- return IS_SSMALL(i) ? make_small(i) : small_to_big(i, alloc_heap(env,2));
+ return small_to_big(i, alloc_heap(env,2));
#elif SIZEOF_LONG == 8
ensure_heap(env,3);
return erts_sint64_to_big(i, &env->hp);
@@ -843,8 +876,11 @@ ERL_NIF_TERM enif_make_long(ErlNifEnv* env, long i)
ERL_NIF_TERM enif_make_ulong(ErlNifEnv* env, unsigned long i)
{
+ if (IS_USMALL(0,i)) {
+ return make_small(i);
+ }
#if SIZEOF_LONG == ERTS_SIZEOF_ETERM
- return IS_USMALL(0,i) ? make_small(i) : uint_to_big(i,alloc_heap(env,2));
+ return uint_to_big(i,alloc_heap(env,2));
#elif SIZEOF_LONG == 8
ensure_heap(env,3);
return erts_uint64_to_big(i, &env->hp);
@@ -1007,6 +1043,29 @@ void enif_system_info(ErlNifSysInfo *sip, size_t si_size)
driver_system_info(sip, si_size);
}
+int enif_make_reverse_list(ErlNifEnv* env, ERL_NIF_TERM term, ERL_NIF_TERM *list) {
+ Eterm *listptr, ret = NIL, *hp;
+
+ if (is_nil(term)) {
+ *list = term;
+ return 1;
+ }
+
+ ret = NIL;
+
+ while (is_not_nil(term)) {
+ if (is_not_list(term)) {
+ return 0;
+ }
+ hp = alloc_heap(env, 2);
+ listptr = list_val(term);
+ ret = CONS(hp, CAR(listptr), ret);
+ term = CDR(listptr);
+ }
+ *list = ret;
+ return 1;
+}
+
ErlNifMutex* enif_mutex_create(char *name) { return erl_drv_mutex_create(name); }
void enif_mutex_destroy(ErlNifMutex *mtx) { erl_drv_mutex_destroy(mtx); }
@@ -1146,7 +1205,7 @@ enif_open_resource_type(ErlNifEnv* env,
ErlNifResourceFlags op = flags;
Eterm module_am, name_am;
- ASSERT(erts_smp_is_system_blocked(0));
+ ASSERT(erts_smp_thr_progress_is_blocking());
ASSERT(module_str == NULL); /* for now... */
module_am = make_atom(env->mod_nif->mod->module);
name_am = enif_make_atom(env, name_str);
@@ -1440,7 +1499,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
/* Block system (is this the right place to do it?) */
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
/* Find calling module */
ASSERT(BIF_P->current != NULL);
@@ -1629,7 +1688,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
erts_sys_ddll_free_error(&errdesc);
}
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
erts_free(ERTS_ALC_T_TMP, lib_name);
BIF_RET(ret);
@@ -1641,7 +1700,7 @@ erts_unload_nif(struct erl_module_nif* lib)
{
ErlNifResourceType* rt;
ErlNifResourceType* next;
- ASSERT(erts_smp_is_system_blocked(0));
+ ASSERT(erts_smp_thr_progress_is_blocking());
ASSERT(lib != NULL);
ASSERT(lib->mod != NULL);
for (rt = resource_type_list.next;
@@ -1701,8 +1760,10 @@ struct readonly_check_t
};
static void add_readonly_check(ErlNifEnv* env, unsigned char* ptr, unsigned sz)
{
- struct readonly_check_t* obj = erts_alloc(ERTS_ALC_T_TMP,
+ ErtsAlcType_t allocator = is_proc_bound(env) ? ERTS_ALC_T_TMP : ERTS_ALC_T_NIF;
+ struct readonly_check_t* obj = erts_alloc(allocator,
sizeof(struct readonly_check_t));
+ obj->hdr.allocator = allocator;
obj->hdr.next = env->tmp_obj_list;
env->tmp_obj_list = &obj->hdr;
obj->hdr.dtor = &readonly_check_dtor;
@@ -1719,7 +1780,7 @@ static void readonly_check_dtor(struct enif_tmp_obj_t* o)
" %x != %x\r\nABORTING\r\n", chksum, obj->checksum);
abort();
}
- erts_free(ERTS_ALC_T_TMP, obj);
+ erts_free(obj->hdr.allocator, obj);
}
static unsigned calc_checksum(unsigned char* ptr, unsigned size)
{
diff --git a/erts/emulator/beam/erl_nif.h b/erts/emulator/beam/erl_nif.h
index d028567faf..fea527f954 100644
--- a/erts/emulator/beam/erl_nif.h
+++ b/erts/emulator/beam/erl_nif.h
@@ -32,9 +32,10 @@
** 2.0: R14A
** 2.1: R14B02 "vm_variant"
** 2.2: R14B03 enif_is_exception
+** 2.3: R15 enif_make_reverse_list
*/
#define ERL_NIF_MAJOR_VERSION 2
-#define ERL_NIF_MINOR_VERSION 2
+#define ERL_NIF_MINOR_VERSION 3
#include <stdlib.h>
diff --git a/erts/emulator/beam/erl_nif_api_funcs.h b/erts/emulator/beam/erl_nif_api_funcs.h
index c991b61abe..6396af09d0 100644
--- a/erts/emulator/beam/erl_nif_api_funcs.h
+++ b/erts/emulator/beam/erl_nif_api_funcs.h
@@ -136,6 +136,8 @@ ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_int64,(ErlNifEnv*, ErlNifSInt64));
ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_uint64,(ErlNifEnv*, ErlNifUInt64));
#endif
ERL_NIF_API_FUNC_DECL(int,enif_is_exception,(ErlNifEnv*, ERL_NIF_TERM term));
+ERL_NIF_API_FUNC_DECL(int,enif_make_reverse_list,(ErlNifEnv*, ERL_NIF_TERM term, ERL_NIF_TERM *list));
+ERL_NIF_API_FUNC_DECL(int,enif_is_number,(ErlNifEnv*, ERL_NIF_TERM term));
/*
** Add new entries here to keep compatibility on Windows!!!
@@ -256,12 +258,207 @@ ERL_NIF_API_FUNC_DECL(int,enif_is_exception,(ErlNifEnv*, ERL_NIF_TERM term));
#endif
# define enif_is_exception ERL_NIF_API_FUNC_MACRO(enif_is_exception)
+# define enif_make_reverse_list ERL_NIF_API_FUNC_MACRO(enif_make_reverse_list)
+# define enif_is_number ERL_NIF_API_FUNC_MACRO(enif_is_number)
/*
** Add new entries here
*/
#endif
+
+#if defined(__GNUC__) && !(defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_))
+
+/* Inline functions for compile time type checking of arguments to
+ variadic functions.
+*/
+
+# define ERL_NIF_INLINE __inline__
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple1(ErlNifEnv* env,
+ ERL_NIF_TERM e1)
+{
+ return enif_make_tuple(env, 1, e1);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple2(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2)
+{
+ return enif_make_tuple(env, 2, e1, e2);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple3(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3)
+{
+ return enif_make_tuple(env, 3, e1, e2, e3);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple4(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3,
+ ERL_NIF_TERM e4)
+{
+ return enif_make_tuple(env, 4, e1, e2, e3, e4);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple5(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3,
+ ERL_NIF_TERM e4,
+ ERL_NIF_TERM e5)
+{
+ return enif_make_tuple(env, 5, e1, e2, e3, e4, e5);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple6(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3,
+ ERL_NIF_TERM e4,
+ ERL_NIF_TERM e5,
+ ERL_NIF_TERM e6)
+{
+ return enif_make_tuple(env, 6, e1, e2, e3, e4, e5, e6);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple7(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3,
+ ERL_NIF_TERM e4,
+ ERL_NIF_TERM e5,
+ ERL_NIF_TERM e6,
+ ERL_NIF_TERM e7)
+{
+ return enif_make_tuple(env, 7, e1, e2, e3, e4, e5, e6, e7);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple8(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3,
+ ERL_NIF_TERM e4,
+ ERL_NIF_TERM e5,
+ ERL_NIF_TERM e6,
+ ERL_NIF_TERM e7,
+ ERL_NIF_TERM e8)
+{
+ return enif_make_tuple(env, 8, e1, e2, e3, e4, e5, e6, e7, e8);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple9(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3,
+ ERL_NIF_TERM e4,
+ ERL_NIF_TERM e5,
+ ERL_NIF_TERM e6,
+ ERL_NIF_TERM e7,
+ ERL_NIF_TERM e8,
+ ERL_NIF_TERM e9)
+{
+ return enif_make_tuple(env, 9, e1, e2, e3, e4, e5, e6, e7, e8, e9);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list1(ErlNifEnv* env,
+ ERL_NIF_TERM e1)
+{
+ return enif_make_list(env, 1, e1);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list2(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2)
+{
+ return enif_make_list(env, 2, e1, e2);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list3(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3)
+{
+ return enif_make_list(env, 3, e1, e2, e3);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list4(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3,
+ ERL_NIF_TERM e4)
+{
+ return enif_make_list(env, 4, e1, e2, e3, e4);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list5(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3,
+ ERL_NIF_TERM e4,
+ ERL_NIF_TERM e5)
+{
+ return enif_make_list(env, 5, e1, e2, e3, e4, e5);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list6(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3,
+ ERL_NIF_TERM e4,
+ ERL_NIF_TERM e5,
+ ERL_NIF_TERM e6)
+{
+ return enif_make_list(env, 6, e1, e2, e3, e4, e5, e6);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list7(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3,
+ ERL_NIF_TERM e4,
+ ERL_NIF_TERM e5,
+ ERL_NIF_TERM e6,
+ ERL_NIF_TERM e7)
+{
+ return enif_make_list(env, 7, e1, e2, e3, e4, e5, e6, e7);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list8(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3,
+ ERL_NIF_TERM e4,
+ ERL_NIF_TERM e5,
+ ERL_NIF_TERM e6,
+ ERL_NIF_TERM e7,
+ ERL_NIF_TERM e8)
+{
+ return enif_make_list(env, 8, e1, e2, e3, e4, e5, e6, e7, e8);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list9(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3,
+ ERL_NIF_TERM e4,
+ ERL_NIF_TERM e5,
+ ERL_NIF_TERM e6,
+ ERL_NIF_TERM e7,
+ ERL_NIF_TERM e8,
+ ERL_NIF_TERM e9)
+{
+ return enif_make_list(env, 9, e1, e2, e3, e4, e5, e6, e7, e8, e9);
+}
+
+# undef ERL_NIF_INLINE
+
+#else /* fallback with macros */
+
#ifndef enif_make_list1
# define enif_make_list1(ENV,E1) enif_make_list(ENV,1,E1)
# define enif_make_list2(ENV,E1,E2) enif_make_list(ENV,2,E1,E2)
@@ -281,6 +478,11 @@ ERL_NIF_API_FUNC_DECL(int,enif_is_exception,(ErlNifEnv*, ERL_NIF_TERM term));
# define enif_make_tuple7(ENV,E1,E2,E3,E4,E5,E6,E7) enif_make_tuple(ENV,7,E1,E2,E3,E4,E5,E6,E7)
# define enif_make_tuple8(ENV,E1,E2,E3,E4,E5,E6,E7,E8) enif_make_tuple(ENV,8,E1,E2,E3,E4,E5,E6,E7,E8)
# define enif_make_tuple9(ENV,E1,E2,E3,E4,E5,E6,E7,E8,E9) enif_make_tuple(ENV,9,E1,E2,E3,E4,E5,E6,E7,E8,E9)
+#endif
+
+#endif /* __GNUC__ && !WIN32 */
+
+#ifndef enif_make_pid
# define enif_make_pid(ENV, PID) ((const ERL_NIF_TERM)((PID)->pid))
diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c
index 6daa127d23..908ba755ed 100644
--- a/erts/emulator/beam/erl_node_tables.c
+++ b/erts/emulator/beam/erl_node_tables.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -26,6 +26,7 @@
#include "dist.h"
#include "big.h"
#include "error.h"
+#include "erl_thr_progress.h"
Hash erts_dist_table;
Hash erts_node_table;
@@ -118,7 +119,7 @@ dist_table_alloc(void *dep_tmpl)
dep->finalized_out_queue.first = NULL;
dep->finalized_out_queue.last = NULL;
- erts_smp_atomic_init(&dep->dist_cmd_scheduled, 0);
+ erts_smp_atomic_init_nob(&dep->dist_cmd_scheduled, 0);
erts_port_task_handle_init(&dep->dist_cmd);
dep->send = NULL;
dep->cache = NULL;
@@ -767,7 +768,7 @@ void erts_init_node_tables(void)
erts_this_dist_entry->finalized_out_queue.first = NULL;
erts_this_dist_entry->finalized_out_queue.last = NULL;
- erts_smp_atomic_init(&erts_this_dist_entry->dist_cmd_scheduled, 0);
+ 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;
@@ -907,7 +908,7 @@ erts_get_node_and_dist_references(struct process *proc)
#endif
erts_smp_proc_unlock(proc, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
/* No need to lock any thing since we are alone... */
if (references_atoms_need_init) {
@@ -951,7 +952,7 @@ erts_get_node_and_dist_references(struct process *proc)
delete_reference_table();
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(proc, ERTS_PROC_LOCK_MAIN);
return res;
}
diff --git a/erts/emulator/beam/erl_port_task.c b/erts/emulator/beam/erl_port_task.c
index e6b55c45e4..87b8e5131b 100644
--- a/erts/emulator/beam/erl_port_task.c
+++ b/erts/emulator/beam/erl_port_task.c
@@ -121,7 +121,7 @@ ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(port_taskq,
static ERTS_INLINE ErtsPortTask *
handle2task(ErtsPortTaskHandle *pthp)
{
- return (ErtsPortTask *) erts_smp_atomic_read(pthp);
+ return (ErtsPortTask *) erts_smp_atomic_read_nob(pthp);
}
static ERTS_INLINE void
@@ -129,7 +129,7 @@ reset_handle(ErtsPortTask *ptp)
{
if (ptp->handle) {
ASSERT(ptp == handle2task(ptp->handle));
- erts_smp_atomic_set(ptp->handle, (erts_aint_t) NULL);
+ erts_smp_atomic_set_nob(ptp->handle, (erts_aint_t) NULL);
}
}
@@ -138,7 +138,7 @@ set_handle(ErtsPortTask *ptp, ErtsPortTaskHandle *pthp)
{
ptp->handle = pthp;
if (pthp) {
- erts_smp_atomic_set(pthp, (erts_aint_t) ptp);
+ erts_smp_atomic_set_nob(pthp, (erts_aint_t) ptp);
ASSERT(ptp == handle2task(ptp->handle));
}
}
@@ -479,8 +479,8 @@ erts_port_task_abort(Eterm id, ErtsPortTaskHandle *pthp)
case ERTS_PORT_TASK_INPUT:
case ERTS_PORT_TASK_OUTPUT:
case ERTS_PORT_TASK_EVENT:
- ASSERT(erts_smp_atomic_read(&erts_port_task_outstanding_io_tasks) > 0);
- erts_smp_atomic_dec(&erts_port_task_outstanding_io_tasks);
+ ASSERT(erts_smp_atomic_read_nob(&erts_port_task_outstanding_io_tasks) > 0);
+ erts_smp_atomic_dec_relb(&erts_port_task_outstanding_io_tasks);
break;
default:
break;
@@ -568,7 +568,7 @@ erts_port_task_schedule(Eterm id,
ErtsRunQueue *xrunq = erts_check_emigration_need(runq, ERTS_PORT_PRIO_LEVEL);
if (xrunq) {
/* Port emigrated ... */
- erts_smp_atomic_set(&pp->run_queue, (erts_aint_t) xrunq);
+ erts_smp_atomic_set_nob(&pp->run_queue, (erts_aint_t) xrunq);
erts_smp_runq_unlock(runq);
runq = xrunq;
}
@@ -594,7 +594,7 @@ erts_port_task_schedule(Eterm id,
case ERTS_PORT_TASK_INPUT:
case ERTS_PORT_TASK_OUTPUT:
case ERTS_PORT_TASK_EVENT:
- erts_smp_atomic_inc(&erts_port_task_outstanding_io_tasks);
+ erts_smp_atomic_inc_relb(&erts_port_task_outstanding_io_tasks);
/* Fall through... */
default:
enqueue_task(pp->sched.taskq, ptp);
@@ -662,7 +662,7 @@ erts_port_task_free_port(Port *pp)
pp->status |= ERTS_PORT_SFLG_FREE_SCHEDULED;
erts_may_save_closed_port(pp);
erts_smp_port_state_unlock(pp);
- ERTS_SMP_LC_ASSERT(erts_smp_atomic_read(&pp->refc) > 1);
+ ERTS_SMP_LC_ASSERT(erts_smp_atomic_read_nob(&pp->refc) > 1);
ptp->type = ERTS_PORT_TASK_FREE;
ptp->event = (ErlDrvEvent) -1;
ptp->event_data = NULL;
@@ -684,9 +684,9 @@ erts_port_task_free_port(Port *pp)
erts_may_save_closed_port(pp);
erts_smp_port_state_unlock(pp);
#ifdef ERTS_SMP
- erts_smp_atomic_dec(&pp->refc); /* Not alive */
+ erts_smp_atomic_dec_nob(&pp->refc); /* Not alive */
#endif
- ERTS_SMP_LC_ASSERT(erts_smp_atomic_read(&pp->refc) > 0); /* Lock */
+ ERTS_SMP_LC_ASSERT(erts_smp_atomic_read_nob(&pp->refc) > 0); /* Lock */
handle_remaining_tasks(runq, pp); /* May release runq lock */
ASSERT(!pp->sched.exe_taskq && (!ptqp || !ptqp->first));
pp->sched.taskq = NULL;
@@ -711,23 +711,6 @@ typedef struct {
int *resp;
} ErtsPortTaskExeBlockData;
-static void
-prepare_for_block(void *vd)
-{
- ErtsPortTaskExeBlockData *d = (ErtsPortTaskExeBlockData *) vd;
- erts_smp_runq_unlock(d->runq);
-}
-
-static void
-resume_after_block(void *vd)
-{
- ErtsPortTaskExeBlockData *d = (ErtsPortTaskExeBlockData *) vd;
- erts_smp_runq_lock(d->runq);
- if (d->resp)
- *d->resp = (erts_smp_atomic_read(&erts_port_task_outstanding_io_tasks)
- != (erts_aint_t) 0);
-}
-
/*
* Run all scheduled tasks for the first port in run queue. If
* new tasks appear while running reschedule port (free task is
@@ -752,11 +735,6 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(runq));
- erts_smp_activity_begin(ERTS_ACTIVITY_IO,
- prepare_for_block,
- resume_after_block,
- (void *) &blk_data);
-
ERTS_PT_CHK_PORTQ(runq);
pp = pop_port(runq);
@@ -832,8 +810,8 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
ASSERT(!ptqp->first
&& (!pp->sched.taskq || !pp->sched.taskq->first));
#ifdef ERTS_SMP
- erts_smp_atomic_dec(&pp->refc); /* Not alive */
- ERTS_SMP_LC_ASSERT(erts_smp_atomic_read(&pp->refc) > 0); /* Lock */
+ erts_smp_atomic_dec_nob(&pp->refc); /* Not alive */
+ ERTS_SMP_LC_ASSERT(erts_smp_atomic_read_nob(&pp->refc) > 0); /* Lock */
#else
erts_port_status_bor_set(pp, ERTS_PORT_SFLG_FREE);
#endif
@@ -906,14 +884,16 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
erts_unblock_fpe(fpe_was_unmasked);
if (io_tasks_executed) {
- ASSERT(erts_smp_atomic_read(&erts_port_task_outstanding_io_tasks) >= io_tasks_executed);
- erts_smp_atomic_add(&erts_port_task_outstanding_io_tasks, -1*io_tasks_executed);
+ ASSERT(erts_smp_atomic_read_nob(&erts_port_task_outstanding_io_tasks)
+ >= io_tasks_executed);
+ erts_smp_atomic_add_relb(&erts_port_task_outstanding_io_tasks,
+ -1*io_tasks_executed);
}
*curr_port_pp = NULL;
#ifdef ERTS_SMP
- ASSERT(runq == (ErtsRunQueue *) erts_smp_atomic_read(&pp->run_queue));
+ ASSERT(runq == (ErtsRunQueue *) erts_smp_atomic_read_nob(&pp->run_queue));
#endif
if (!pp->sched.taskq) {
@@ -940,7 +920,7 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
}
else {
/* Port emigrated ... */
- erts_smp_atomic_set(&pp->run_queue, (erts_aint_t) xrunq);
+ erts_smp_atomic_set_nob(&pp->run_queue, (erts_aint_t) xrunq);
enqueue_port(xrunq, pp);
ASSERT(pp->sched.exe_taskq);
pp->sched.exe_taskq = NULL;
@@ -951,7 +931,7 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
port_was_enqueued = 1;
}
- res = (erts_smp_atomic_read(&erts_port_task_outstanding_io_tasks)
+ res = (erts_smp_atomic_read_nob(&erts_port_task_outstanding_io_tasks)
!= (erts_aint_t) 0);
ERTS_PT_CHK_PRES_PORTQ(runq, pp);
@@ -972,13 +952,13 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
{
erts_aint_t refc;
erts_smp_mtx_unlock(pp->lock);
- refc = erts_smp_atomic_dectest(&pp->refc);
+ refc = erts_smp_atomic_dec_read_nob(&pp->refc);
ASSERT(refc >= 0);
if (refc == 0) {
erts_smp_runq_unlock(runq);
erts_port_cleanup(pp); /* Might aquire runq lock */
erts_smp_runq_lock(runq);
- res = (erts_smp_atomic_read(&erts_port_task_outstanding_io_tasks)
+ res = (erts_smp_atomic_read_nob(&erts_port_task_outstanding_io_tasks)
!= (erts_aint_t) 0);
}
}
@@ -986,10 +966,6 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
done:
blk_data.resp = &res;
- erts_smp_activity_end(ERTS_ACTIVITY_IO,
- prepare_for_block,
- resume_after_block,
- (void *) &blk_data);
ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(runq));
@@ -1107,12 +1083,12 @@ erts_port_migrate(Port *prt, int *prt_locked,
/* Refuse to migrate to a suspended run queue */
if (to_rq->flags & ERTS_RUNQ_FLG_SUSPENDED)
return ERTS_MIGRATE_FAILED_RUNQ_SUSPENDED;
- if (from_rq != (ErtsRunQueue *) erts_smp_atomic_read(&prt->run_queue))
+ if (from_rq != (ErtsRunQueue *) erts_smp_atomic_read_nob(&prt->run_queue))
return ERTS_MIGRATE_FAILED_RUNQ_CHANGED;
if (!ERTS_PORT_IS_IN_RUNQ(from_rq, prt))
return ERTS_MIGRATE_FAILED_NOT_IN_RUNQ;
dequeue_port(from_rq, prt);
- erts_smp_atomic_set(&prt->run_queue, (erts_aint_t) to_rq);
+ erts_smp_atomic_set_nob(&prt->run_queue, (erts_aint_t) to_rq);
enqueue_port(to_rq, prt);
return ERTS_MIGRATE_SUCCESS;
}
@@ -1125,7 +1101,8 @@ erts_port_migrate(Port *prt, int *prt_locked,
void
erts_port_task_init(void)
{
- erts_smp_atomic_init(&erts_port_task_outstanding_io_tasks, (erts_aint_t) 0);
+ erts_smp_atomic_init_nob(&erts_port_task_outstanding_io_tasks,
+ (erts_aint_t) 0);
init_port_task_alloc();
init_port_taskq_alloc();
}
diff --git a/erts/emulator/beam/erl_port_task.h b/erts/emulator/beam/erl_port_task.h
index 3e2c5f07ab..d7104e1143 100644
--- a/erts/emulator/beam/erl_port_task.h
+++ b/erts/emulator/beam/erl_port_task.h
@@ -79,13 +79,13 @@ ERTS_GLB_INLINE int erts_port_task_have_outstanding_io_tasks(void);
ERTS_GLB_INLINE void
erts_port_task_handle_init(ErtsPortTaskHandle *pthp)
{
- erts_smp_atomic_init(pthp, (erts_aint_t) NULL);
+ erts_smp_atomic_init_nob(pthp, (erts_aint_t) NULL);
}
ERTS_GLB_INLINE int
erts_port_task_is_scheduled(ErtsPortTaskHandle *pthp)
{
- return ((void *) erts_smp_atomic_read(pthp)) != NULL;
+ return ((void *) erts_smp_atomic_read_nob(pthp)) != NULL;
}
ERTS_GLB_INLINE void
@@ -102,8 +102,8 @@ erts_port_task_init_sched(ErtsPortTaskSched *ptsp)
ERTS_GLB_INLINE int
erts_port_task_have_outstanding_io_tasks(void)
{
- ERTS_THR_MEMORY_BARRIER;
- return erts_smp_atomic_read(&erts_port_task_outstanding_io_tasks) != 0;
+ return (erts_smp_atomic_read_acqb(&erts_port_task_outstanding_io_tasks)
+ != 0);
}
#endif /* ERTS_INCLUDE_SCHEDULER_INTERNALS */
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index dba57e04ca..a1f5069b2d 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -39,6 +39,9 @@
#include "erl_binary.h"
#include "beam_bp.h"
#include "erl_cpu_topology.h"
+#include "erl_thr_progress.h"
+#include "erl_thr_queue.h"
+#include "erl_async.h"
#define ERTS_RUNQ_CHECK_BALANCE_REDS_PER_SCHED (2000*CONTEXT_REDS)
#define ERTS_RUNQ_CALL_CHECK_BALANCE_REDS \
@@ -125,9 +128,10 @@ ErtsLcPSDLocks erts_psd_required_locks[ERTS_PSD_SIZE];
#endif
#ifdef ERTS_SMP
-
int erts_disable_proc_not_running_opt;
+static ErtsAuxWorkData *aux_thread_aux_work_data;
+
#define ERTS_SCHDLR_SSPND_CHNG_WAITER (((erts_aint32_t) 1) << 0)
#define ERTS_SCHDLR_SSPND_CHNG_MSB (((erts_aint32_t) 1) << 1)
#define ERTS_SCHDLR_SSPND_CHNG_ONLN (((erts_aint32_t) 1) << 2)
@@ -135,15 +139,15 @@ int erts_disable_proc_not_running_opt;
#ifndef DEBUG
#define ERTS_SCHDLR_SSPND_CHNG_SET(VAL, OLD_VAL) \
- erts_smp_atomic32_set(&schdlr_sspnd.changing, (VAL))
+ erts_smp_atomic32_set_nob(&schdlr_sspnd.changing, (VAL))
#else
#define ERTS_SCHDLR_SSPND_CHNG_SET(VAL, OLD_VAL) \
do { \
erts_aint32_t old_val__; \
- old_val__ = erts_smp_atomic32_xchg(&schdlr_sspnd.changing, \
- (VAL)); \
+ old_val__ = erts_smp_atomic32_xchg_nob(&schdlr_sspnd.changing, \
+ (VAL)); \
ASSERT(old_val__ == (OLD_VAL)); \
} while (0)
@@ -159,7 +163,7 @@ static struct {
erts_smp_atomic32_t changing;
erts_smp_atomic32_t active;
struct {
- erts_smp_atomic32_t ongoing;
+ int ongoing;
long wait_active;
ErtsProcList *procs;
} msb; /* Multi Scheduling Block */
@@ -214,8 +218,6 @@ Uint erts_no_run_queues;
ErtsAlignedSchedulerData *erts_aligned_scheduler_data;
-#ifdef ERTS_SMP
-
typedef union {
ErtsSchedulerSleepInfo ssi;
char align[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsSchedulerSleepInfo))];
@@ -223,8 +225,6 @@ typedef union {
static ErtsAlignedSchedulerSleepInfo *aligned_sched_sleep_info;
-#endif
-
#ifndef BM_COUNTERS
static int processes_busy;
#endif
@@ -286,8 +286,9 @@ ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(proclist,
ERTS_ALC_T_PROC_LIST)
#define ERTS_SCHED_SLEEP_INFO_IX(IX) \
- (ASSERT_EXPR(0 <= (IX) && (IX) < erts_no_schedulers), \
- &aligned_sched_sleep_info[(IX)].ssi)
+ (ASSERT_EXPR(-1 <= ((int) (IX)) \
+ && ((int) (IX)) < ((int) erts_no_schedulers)), \
+ &aligned_sched_sleep_info[(IX)].ssi)
#define ERTS_FOREACH_RUNQ(RQVAR, DO) \
do { \
@@ -340,6 +341,66 @@ static void exec_misc_ops(ErtsRunQueue *);
static void print_function_from_pc(int to, void *to_arg, BeamInstr* x);
static int stack_element_dump(int to, void *to_arg, Process* p, Eterm* sp,
int yreg);
+
+static void aux_work_timeout(void *unused);
+static void aux_work_timeout_early_init(int no_schedulers);
+static void aux_work_timeout_late_init(void);
+static void setup_aux_work_timer(void);
+
+#if defined(DEBUG) || 0
+#define ERTS_DBG_CHK_AUX_WORK_VAL(V) dbg_chk_aux_work_val((V))
+static void
+dbg_chk_aux_work_val(erts_aint32_t value)
+{
+ erts_aint32_t valid = 0;
+
+#ifdef ERTS_SSI_AUX_WORK_SET_TMO
+ valid |= ERTS_SSI_AUX_WORK_SET_TMO;
+#endif
+#ifdef ERTS_SSI_AUX_WORK_CHECK_CHILDREN
+ valid |= ERTS_SSI_AUX_WORK_CHECK_CHILDREN;
+#endif
+#ifdef ERTS_SSI_AUX_WORK_MISC
+ valid |= ERTS_SSI_AUX_WORK_MISC;
+#endif
+#ifdef ERTS_SSI_AUX_WORK_MISC_THR_PRGR
+ valid |= ERTS_SSI_AUX_WORK_MISC_THR_PRGR;
+#endif
+#ifdef ERTS_SSI_AUX_WORK_ASYNC_READY
+ valid |= ERTS_SSI_AUX_WORK_ASYNC_READY;
+#endif
+#ifdef ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN
+ valid |= ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN;
+#endif
+
+#ifdef ERTS_SSI_AUX_WORK_FIX_ALLOC_LOWER_LIM
+ valid |= ERTS_SSI_AUX_WORK_FIX_ALLOC_LOWER_LIM;
+#endif
+#ifdef ERTS_SSI_AUX_WORK_FIX_ALLOC_DEALLOC
+ valid |= ERTS_SSI_AUX_WORK_FIX_ALLOC_DEALLOC;
+#endif
+#ifdef ERTS_SSI_AUX_WORK_DD
+ valid |= ERTS_SSI_AUX_WORK_DD;
+#endif
+#ifdef ERTS_SSI_AUX_WORK_DD
+ valid |= ERTS_SSI_AUX_WORK_DD_THR_PRGR;
+#endif
+#ifdef ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK
+ valid |= ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK;
+#endif
+
+ if (~valid & value)
+ erl_exit(ERTS_ABORT_EXIT,
+ "Invalid aux_work value found: 0x%x\n",
+ ~valid & value);
+}
+#define ERTS_DBG_CHK_SSI_AUX_WORK(SSI) \
+ ERTS_DBG_CHK_AUX_WORK_VAL(erts_atomic32_read_nob(&(SSI)->aux_work))
+#else
+#define ERTS_DBG_CHK_AUX_WORK_VAL(V)
+#define ERTS_DBG_CHK_SSI_AUX_WORK(SSI)
+#endif
+
#ifdef ERTS_SMP
static void handle_pending_exiters(ErtsProcList *);
@@ -411,7 +472,7 @@ erts_init_process(int ncpu)
init_proclist_alloc();
- erts_smp_atomic32_init(&process_count, 0);
+ erts_smp_atomic32_init_nob(&process_count, 0);
if (erts_use_r9_pids_ports) {
proc_bits = ERTS_R9_PROC_BITS;
@@ -578,6 +639,13 @@ erts_sched_finish_poke(ErtsSchedulerSleepInfo *ssi, erts_aint32_t flags)
case ERTS_SSI_FLG_POLL_SLEEPING:
erts_sys_schedule_interrupt(1);
break;
+ case ERTS_SSI_FLG_POLL_SLEEPING|ERTS_SSI_FLG_TSE_SLEEPING:
+ /*
+ * Thread progress blocking while poll sleeping; need
+ * to signal on both...
+ */
+ erts_sys_schedule_interrupt(1);
+ /* fall through */
case ERTS_SSI_FLG_TSE_SLEEPING:
erts_tse_set(ssi->event);
break;
@@ -590,189 +658,712 @@ erts_sched_finish_poke(ErtsSchedulerSleepInfo *ssi, erts_aint32_t flags)
}
}
+#endif
+
+static ERTS_INLINE void
+set_aux_work_flags_wakeup_nob(ErtsSchedulerSleepInfo *ssi,
+ erts_aint32_t flgs)
+{
+ erts_aint32_t old_flgs;
+
+ ERTS_DBG_CHK_SSI_AUX_WORK(ssi);
+
+ old_flgs = erts_atomic32_read_nob(&ssi->aux_work);
+ if ((old_flgs & flgs) == 0) {
+
+ old_flgs = erts_atomic32_read_bor_nob(&ssi->aux_work, flgs);
+
+ if ((old_flgs & flgs) == 0) {
+#ifdef ERTS_SMP
+ erts_sched_poke(ssi);
+#else
+ erts_sys_schedule_interrupt(1);
+#endif
+ }
+ }
+}
+
+#if 0 /* Currently not used */
+
+static ERTS_INLINE void
+set_aux_work_flags_wakeup_relb(ErtsSchedulerSleepInfo *ssi,
+ erts_aint32_t flgs)
+{
+ erts_aint32_t old_flgs;
+
+ ERTS_DBG_CHK_SSI_AUX_WORK(ssi);
+
+ old_flgs = erts_atomic32_read_bor_relb(&ssi->aux_work, flgs);
+
+ if ((old_flgs & flgs) == 0) {
+#ifdef ERTS_SMP
+ erts_sched_poke(ssi);
+#else
+ erts_sys_schedule_interrupt(1);
+#endif
+ }
+}
+
+#endif
+
+static ERTS_INLINE erts_aint32_t
+set_aux_work_flags(ErtsSchedulerSleepInfo *ssi, erts_aint32_t flgs)
+{
+ return erts_atomic32_read_bor_nob(&ssi->aux_work, flgs);
+}
+
+static ERTS_INLINE erts_aint32_t
+unset_aux_work_flags(ErtsSchedulerSleepInfo *ssi, erts_aint32_t flgs)
+{
+ return erts_atomic32_read_band_nob(&ssi->aux_work, ~flgs);
+}
+
typedef struct erts_misc_aux_work_t_ erts_misc_aux_work_t;
struct erts_misc_aux_work_t_ {
- erts_misc_aux_work_t *next;
void (*func)(void *);
void *arg;
};
-typedef struct {
- erts_smp_mtx_t mtx;
- erts_misc_aux_work_t *first;
- erts_misc_aux_work_t *last;
-} erts_misc_aux_work_q_t;
+ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(misc_aux_work,
+ erts_misc_aux_work_t,
+ 200,
+ ERTS_ALC_T_MISC_AUX_WORK)
typedef union {
- erts_misc_aux_work_q_t data;
- char align[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(erts_misc_aux_work_q_t))];
+ ErtsThrQ_t q;
+ char align[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsThrQ_t))];
} erts_algnd_misc_aux_work_q_t;
static erts_algnd_misc_aux_work_q_t *misc_aux_work_queues;
-ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(misc_aux_work,
- erts_misc_aux_work_t,
- 200,
- ERTS_ALC_T_MISC_AUX_WORK)
+static void
+notify_aux_work(void *vssi)
+{
+ set_aux_work_flags_wakeup_nob((ErtsSchedulerSleepInfo *) vssi,
+ ERTS_SSI_AUX_WORK_MISC);
+}
static void
init_misc_aux_work(void)
{
int ix;
+ ErtsThrQInit_t qinit = ERTS_THR_Q_INIT_DEFAULT;
+ qinit.notify = notify_aux_work;
init_misc_aux_work_alloc();
misc_aux_work_queues =
erts_alloc_permanent_cache_aligned(ERTS_ALC_T_MISC_AUX_WORK_Q,
- erts_no_schedulers *
- sizeof(erts_algnd_misc_aux_work_q_t));
+ sizeof(erts_algnd_misc_aux_work_q_t)
+ * (erts_no_schedulers+1));
- for (ix = 0; ix < erts_no_schedulers; ix++) {
- erts_smp_mtx_init_x(&misc_aux_work_queues[ix].data.mtx,
- "misc_aux_work_queue",
- make_small(ix + 1));
- misc_aux_work_queues[ix].data.first = NULL;
- misc_aux_work_queues[ix].data.last = NULL;
+#ifdef ERTS_SMP
+ ix = 0; /* aux_thread + schedulers */
+#else
+ ix = 1; /* scheduler only */
+#endif
+
+ for (; ix <= erts_no_schedulers; ix++) {
+ qinit.arg = (void *) ERTS_SCHED_SLEEP_INFO_IX(ix-1);
+ erts_thr_q_initialize(&misc_aux_work_queues[ix].q, &qinit);
}
}
-static void
-handle_misc_aux_work(ErtsSchedulerData *esdp)
-{
- int ix = (int) esdp->no - 1;
- erts_misc_aux_work_t *mawp;
+static erts_aint32_t
+misc_aux_work_clean(ErtsThrQ_t *q,
+ ErtsAuxWorkData *awdp,
+ erts_aint32_t aux_work)
+{
+ switch (erts_thr_q_clean(q)) {
+ case ERTS_THR_Q_DIRTY:
+ set_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_MISC);
+ return aux_work | ERTS_SSI_AUX_WORK_MISC;
+#ifdef ERTS_SMP
+ case ERTS_THR_Q_NEED_THR_PRGR:
+ set_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_MISC_THR_PRGR);
+ erts_thr_progress_wakeup(awdp->esdp,
+ erts_thr_q_need_thr_progress(q));
+#endif
+ case ERTS_THR_Q_CLEAN:
+ break;
+ }
+ return aux_work;
+}
- erts_smp_mtx_lock(&misc_aux_work_queues[ix].data.mtx);
- mawp = misc_aux_work_queues[ix].data.first;
- misc_aux_work_queues[ix].data.first = NULL;
- misc_aux_work_queues[ix].data.last = NULL;
- erts_smp_mtx_unlock(&misc_aux_work_queues[ix].data.mtx);
+static erts_aint32_t
+handle_misc_aux_work(ErtsAuxWorkData *awdp,
+ erts_aint32_t aux_work)
+{
+ ErtsThrQ_t *q = &misc_aux_work_queues[awdp->sched_id].q;
- while (mawp) {
- erts_misc_aux_work_t *free_mawp;
+ unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_MISC);
+ while (1) {
+ erts_misc_aux_work_t *mawp = erts_thr_q_dequeue(q);
+ if (!mawp)
+ break;
mawp->func(mawp->arg);
- free_mawp = mawp;
- mawp = mawp->next;
- misc_aux_work_free(free_mawp);
+ misc_aux_work_free(mawp);
}
+
+ return misc_aux_work_clean(q, awdp, aux_work & ~ERTS_SSI_AUX_WORK_MISC);
+}
+
+#ifdef ERTS_SMP
+
+static erts_aint32_t
+handle_misc_aux_work_thr_prgr(ErtsAuxWorkData *awdp,
+ erts_aint32_t aux_work)
+{
+ if (!erts_thr_progress_has_reached(awdp->misc.thr_prgr))
+ return aux_work;
+
+ unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_MISC_THR_PRGR);
+
+ return misc_aux_work_clean(&misc_aux_work_queues[awdp->sched_id].q,
+ awdp,
+ aux_work & ~ERTS_SSI_AUX_WORK_MISC_THR_PRGR);
+}
+
+#endif
+
+static ERTS_INLINE void
+schedule_misc_aux_work(int sched_id,
+ void (*func)(void *),
+ void *arg)
+{
+ ErtsThrQ_t *q;
+ erts_misc_aux_work_t *mawp;
+
+#ifdef ERTS_SMP
+ ASSERT(0 <= sched_id && sched_id <= erts_no_schedulers);
+#else
+ ASSERT(sched_id == 1);
+#endif
+
+ q = &misc_aux_work_queues[sched_id].q;
+ mawp = misc_aux_work_alloc();
+ mawp->func = func;
+ mawp->arg = arg;
+ erts_thr_q_enqueue(q, mawp);
}
void
-erts_smp_schedule_misc_aux_work(int ignore_self,
- int max_sched,
- void (*func)(void *),
- void *arg)
+erts_schedule_misc_aux_work(int sched_id,
+ void (*func)(void *),
+ void *arg)
{
- int ix, ignore_ix = -1;
+ schedule_misc_aux_work(sched_id, func, arg);
+}
+
+void
+erts_schedule_multi_misc_aux_work(int ignore_self,
+ int max_sched,
+ void (*func)(void *),
+ void *arg)
+{
+ int id, self = 0;
if (ignore_self) {
ErtsSchedulerData *esdp = erts_get_scheduler_data();
if (esdp)
- ignore_ix = (int) esdp->no - 1;
+ self = (int) esdp->no;
}
- ASSERT(0 <= max_sched && max_sched <= erts_no_schedulers);
+ ASSERT(0 < max_sched && max_sched <= erts_no_schedulers);
- for (ix = 0; ix < max_sched; ix++) {
- erts_aint32_t aux_work;
- erts_misc_aux_work_t *mawp;
- ErtsSchedulerSleepInfo *ssi;
- if (ix == ignore_ix)
+ for (id = 1; id <= max_sched; id++) {
+ if (id == self)
continue;
+ schedule_misc_aux_work(id, func, arg);
+ }
+}
- mawp = misc_aux_work_alloc();
+#if ERTS_USE_ASYNC_READY_Q
- mawp->func = func;
- mawp->arg = arg;
- mawp->next = NULL;
+void
+erts_notify_check_async_ready_queue(void *vno)
+{
+ int ix = ((int) (SWord) vno) -1;
+ set_aux_work_flags_wakeup_nob(ERTS_SCHED_SLEEP_INFO_IX(ix),
+ ERTS_SSI_AUX_WORK_ASYNC_READY);
+}
- erts_smp_mtx_lock(&misc_aux_work_queues[ix].data.mtx);
- if (!misc_aux_work_queues[ix].data.last)
- misc_aux_work_queues[ix].data.first = mawp;
- else
- misc_aux_work_queues[ix].data.last->next = mawp;
- misc_aux_work_queues[ix].data.last = mawp;
- erts_smp_mtx_unlock(&misc_aux_work_queues[ix].data.mtx);
-
- ssi = ERTS_SCHED_SLEEP_INFO_IX(ix);
- aux_work = erts_smp_atomic32_bor(&ssi->aux_work,
- ERTS_SSI_AUX_WORK_MISC);
- if ((aux_work & ERTS_SSI_AUX_WORK_MISC) == 0)
- erts_sched_poke(ssi);
- }
+static erts_aint32_t
+handle_async_ready(ErtsAuxWorkData *awdp,
+ erts_aint32_t aux_work)
+{
+ ErtsSchedulerSleepInfo *ssi = awdp->ssi;
+ unset_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_ASYNC_READY);
+ if (erts_check_async_ready(awdp->async_ready.queue)) {
+ if (set_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_ASYNC_READY)
+ & ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN) {
+ unset_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN);
+ aux_work &= ~ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN;
+ }
+ return aux_work;
+ }
+#ifdef ERTS_SMP
+ awdp->async_ready.need_thr_prgr = 0;
+#endif
+ set_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN);
+ return ((aux_work & ~ERTS_SSI_AUX_WORK_ASYNC_READY)
+ | ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN);
+}
+
+static erts_aint32_t
+handle_async_ready_clean(ErtsAuxWorkData *awdp,
+ erts_aint32_t aux_work)
+{
+ void *thr_prgr_p;
+
+#ifdef ERTS_SMP
+ if (awdp->async_ready.need_thr_prgr
+ && !erts_thr_progress_has_reached(awdp->misc.thr_prgr)) {
+ return aux_work & ~ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN;
+ }
+
+ awdp->async_ready.need_thr_prgr = 0;
+ thr_prgr_p = (void *) &awdp->async_ready.thr_prgr;
+#else
+ thr_prgr_p = NULL;
+#endif
+
+ switch (erts_async_ready_clean(awdp->async_ready.queue, thr_prgr_p)) {
+ case ERTS_ASYNC_READY_CLEAN:
+ unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN);
+ return aux_work & ~ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN;
+#ifdef ERTS_SMP
+ case ERTS_ASYNC_READY_NEED_THR_PRGR:
+ erts_thr_progress_wakeup(awdp->esdp,
+ awdp->async_ready.thr_prgr);
+ awdp->async_ready.need_thr_prgr = 1;
+#endif
+ default:
+ return aux_work;
+ }
}
+#endif
+
+static erts_aint32_t
+handle_fix_alloc(ErtsAuxWorkData *awdp, erts_aint32_t aux_work)
+{
+ ErtsSchedulerSleepInfo *ssi = awdp->ssi;
+ erts_aint32_t res;
+
+ unset_aux_work_flags(ssi, (ERTS_SSI_AUX_WORK_FIX_ALLOC_LOWER_LIM
+ | ERTS_SSI_AUX_WORK_FIX_ALLOC_DEALLOC));
+ aux_work &= ~(ERTS_SSI_AUX_WORK_FIX_ALLOC_LOWER_LIM
+ | ERTS_SSI_AUX_WORK_FIX_ALLOC_DEALLOC);
+ res = erts_alloc_fix_alloc_shrink(awdp->sched_id, aux_work);
+ if (res) {
+ set_aux_work_flags(ssi, res);
+ aux_work |= res;
+ }
+
+ return aux_work;
+}
+
+#ifdef ERTS_SMP
+
+void
+erts_alloc_notify_delayed_dealloc(int ix)
+{
+ set_aux_work_flags_wakeup_nob(ERTS_SCHED_SLEEP_INFO_IX(ix-1),
+ ERTS_SSI_AUX_WORK_DD);
+}
+
+static erts_aint32_t
+handle_delayed_dealloc(ErtsAuxWorkData *awdp, erts_aint32_t aux_work)
+{
+ ErtsSchedulerSleepInfo *ssi = awdp->ssi;
+ int need_thr_progress = 0;
+ int more_work = 0;
+
+ unset_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_DD);
+ erts_alloc_scheduler_handle_delayed_dealloc((void *) awdp->esdp,
+ &need_thr_progress,
+ &more_work);
+ if (more_work) {
+ if (set_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_DD)
+ & ERTS_SSI_AUX_WORK_DD_THR_PRGR) {
+ unset_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_DD_THR_PRGR);
+ aux_work &= ~ERTS_SSI_AUX_WORK_DD_THR_PRGR;
+ }
+ return aux_work;
+ }
+
+ if (need_thr_progress) {
+ set_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_DD_THR_PRGR);
+ awdp->dd.thr_prgr = erts_thr_progress_later();
+ erts_thr_progress_wakeup(awdp->esdp, awdp->dd.thr_prgr);
+ }
+ else if (awdp->dd.completed_callback) {
+ awdp->dd.completed_callback(awdp->dd.completed_arg);
+ awdp->dd.completed_callback = NULL;
+ awdp->dd.completed_arg = NULL;
+ }
+ return aux_work & ~ERTS_SSI_AUX_WORK_DD;
+}
+
+static erts_aint32_t
+handle_delayed_dealloc_thr_prgr(ErtsAuxWorkData *awdp, erts_aint32_t aux_work)
+{
+ ErtsSchedulerSleepInfo *ssi;
+ int need_thr_progress;
+ int more_work;
+
+ if (!erts_thr_progress_has_reached(awdp->dd.thr_prgr))
+ return aux_work & ~ERTS_SSI_AUX_WORK_DD_THR_PRGR;
+
+ ssi = awdp->ssi;
+ need_thr_progress = 0;
+ more_work = 0;
+
+ erts_alloc_scheduler_handle_delayed_dealloc((void *) awdp->esdp,
+ &need_thr_progress,
+ &more_work);
+ if (more_work) {
+ set_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_DD);
+ unset_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_DD_THR_PRGR);
+ return ((aux_work & ~ERTS_SSI_AUX_WORK_DD_THR_PRGR)
+ | ERTS_SSI_AUX_WORK_DD);
+ }
+
+ if (need_thr_progress) {
+ awdp->dd.thr_prgr = erts_thr_progress_later();
+ erts_thr_progress_wakeup(awdp->esdp, awdp->dd.thr_prgr);
+ }
+ else {
+ unset_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_DD_THR_PRGR);
+ if (awdp->dd.completed_callback) {
+ awdp->dd.completed_callback(awdp->dd.completed_arg);
+ awdp->dd.completed_callback = NULL;
+ awdp->dd.completed_arg = NULL;
+ }
+ }
+
+ return aux_work & ~ERTS_SSI_AUX_WORK_DD_THR_PRGR;
+}
+
+static erts_atomic32_t completed_dealloc_count;
+
+static void
+completed_dealloc(void *vproc)
+{
+ if (erts_atomic32_dec_read_mb(&completed_dealloc_count) == 0) {
+ erts_resume((Process *) vproc, (ErtsProcLocks) 0);
+ erts_smp_proc_dec_refc((Process *) vproc);
+ }
+}
+
+static void
+setup_completed_dealloc(void *vproc)
+{
+ ErtsSchedulerData *esdp = erts_get_scheduler_data();
+ ErtsAuxWorkData *awdp = (esdp
+ ? &esdp->aux_work_data
+ : aux_thread_aux_work_data);
+ erts_alloc_fix_alloc_shrink(awdp->sched_id, 0);
+ set_aux_work_flags_wakeup_nob(awdp->ssi, ERTS_SSI_AUX_WORK_DD);
+ awdp->dd.completed_callback = completed_dealloc;
+ awdp->dd.completed_arg = vproc;
+}
+
+static void
+prep_setup_completed_dealloc(void *vproc)
+{
+ erts_aint32_t count = (erts_aint32_t) (erts_no_schedulers+1);
+ if (erts_atomic32_dec_read_mb(&completed_dealloc_count) == count) {
+ /* scheduler threads */
+ erts_schedule_multi_misc_aux_work(0,
+ erts_no_schedulers,
+ setup_completed_dealloc,
+ vproc);
+ /* aux_thread */
+ erts_schedule_misc_aux_work(0,
+ setup_completed_dealloc,
+ vproc);
+ }
+}
+
+#endif /* ERTS_SMP */
+
+int
+erts_debug_wait_deallocations(Process *c_p)
+{
+#ifndef ERTS_SMP
+ erts_alloc_fix_alloc_shrink(1, 0);
+ return 1;
+#else
+ /* Only one process at a time can do this */
+ erts_aint32_t count = (erts_aint32_t) (2*(erts_no_schedulers+1));
+ if (0 == erts_atomic32_cmpxchg_mb(&completed_dealloc_count,
+ count,
+ 0)) {
+ erts_suspend(c_p, ERTS_PROC_LOCK_MAIN, NULL);
+ erts_smp_proc_inc_refc(c_p);
+ /* scheduler threads */
+ erts_schedule_multi_misc_aux_work(0,
+ erts_no_schedulers,
+ prep_setup_completed_dealloc,
+ (void *) c_p);
+ /* aux_thread */
+ erts_schedule_misc_aux_work(0,
+ prep_setup_completed_dealloc,
+ (void *) c_p);
+ return 1;
+ }
+ return 0;
+#endif
+}
+
+
#ifdef ERTS_SMP_SCHEDULERS_NEED_TO_CHECK_CHILDREN
void
erts_smp_notify_check_children_needed(void)
{
int i;
+ for (i = 0; i < erts_no_schedulers; i++)
+ set_aux_work_flags_wakeup_nob(ERTS_SCHED_SLEEP_INFO_IX(i),
+ ERTS_SSI_AUX_WORK_CHECK_CHILDREN);
+}
- for (i = 0; i < erts_no_schedulers; i++) {
- erts_aint32_t aux_work;
- ErtsSchedulerSleepInfo *ssi;
- ssi = ERTS_SCHED_SLEEP_INFO_IX(i);
- aux_work = erts_smp_atomic32_bor(&ssi->aux_work,
- ERTS_SSI_AUX_WORK_CHECK_CHILDREN);
- if (!(aux_work & ERTS_SSI_AUX_WORK_CHECK_CHILDREN))
- erts_sched_poke(ssi);
- }
+static erts_aint32_t
+handle_check_children(ErtsAuxWorkData *awdp, erts_aint32_t aux_work)
+{
+ unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_CHECK_CHILDREN);
+ erts_check_children();
+ return aux_work & ~ERTS_SSI_AUX_WORK_CHECK_CHILDREN;
+}
+
+#endif
+
+#ifdef ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK
+
+static erts_aint32_t
+handle_mseg_cache_check(ErtsAuxWorkData *awdp, erts_aint32_t aux_work)
+{
+ unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK);
+ erts_mseg_cache_check();
+ return aux_work & ~ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK;
}
+
#endif
-#ifdef ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK
+static erts_aint32_t
+handle_setup_aux_work_timer(ErtsAuxWorkData *awdp, erts_aint32_t aux_work)
+{
+ unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_SET_TMO);
+ setup_aux_work_timer();
+ return aux_work & ~ERTS_SSI_AUX_WORK_SET_TMO;
+}
+
static ERTS_INLINE erts_aint32_t
-blockable_aux_work(ErtsSchedulerData *esdp,
- ErtsSchedulerSleepInfo *ssi,
- erts_aint32_t aux_work)
+handle_aux_work(ErtsAuxWorkData *awdp, erts_aint32_t aux_work)
{
- if (aux_work & ERTS_SSI_BLOCKABLE_AUX_WORK_MASK) {
- if (aux_work & ERTS_SSI_AUX_WORK_MISC) {
- aux_work = erts_smp_atomic32_band(&ssi->aux_work,
- ~ERTS_SSI_AUX_WORK_MISC);
- aux_work &= ~ERTS_SSI_AUX_WORK_MISC;
- handle_misc_aux_work(esdp);
- }
+ /*
+ * Handlers are *only* allowed to modify flags in return value
+ * and ssi flags that are explicity handled by the handler.
+ * Handlers are, e.g., not allowed to read the ssi flag field and
+ * then unconditionally return that value.
+ */
+ ERTS_DBG_CHK_AUX_WORK_VAL(aux_work);
+ if (aux_work & ERTS_SSI_AUX_WORK_SET_TMO) {
+ aux_work = handle_setup_aux_work_timer(awdp, aux_work);
+ ERTS_DBG_CHK_AUX_WORK_VAL(aux_work);
+ }
+#ifdef ERTS_SMP
+ if (aux_work & ERTS_SSI_AUX_WORK_MISC_THR_PRGR) {
+ aux_work = handle_misc_aux_work_thr_prgr(awdp, aux_work);
+ ERTS_DBG_CHK_AUX_WORK_VAL(aux_work);
+ }
+#endif
+ if (aux_work & ERTS_SSI_AUX_WORK_MISC) {
+ aux_work = handle_misc_aux_work(awdp, aux_work);
+ ERTS_DBG_CHK_AUX_WORK_VAL(aux_work);
+ }
+#if ERTS_USE_ASYNC_READY_Q
+ if (aux_work & ERTS_SSI_AUX_WORK_ASYNC_READY) {
+ aux_work = handle_async_ready(awdp, aux_work);
+ ERTS_DBG_CHK_AUX_WORK_VAL(aux_work);
+ }
+ if (aux_work & ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN) {
+ aux_work = handle_async_ready_clean(awdp, aux_work);
+ ERTS_DBG_CHK_AUX_WORK_VAL(aux_work);
+ }
+#endif
#ifdef ERTS_SMP_SCHEDULERS_NEED_TO_CHECK_CHILDREN
- if (aux_work & ERTS_SSI_AUX_WORK_CHECK_CHILDREN) {
- aux_work = erts_smp_atomic32_band(&ssi->aux_work,
- ~ERTS_SSI_AUX_WORK_CHECK_CHILDREN);
- aux_work &= ~ERTS_SSI_AUX_WORK_CHECK_CHILDREN;
- erts_check_children();
- }
+ if (aux_work & ERTS_SSI_AUX_WORK_CHECK_CHILDREN) {
+ aux_work = handle_check_children(awdp, aux_work);
+ ERTS_DBG_CHK_AUX_WORK_VAL(aux_work);
+ }
+#endif
+ if (aux_work & (ERTS_SSI_AUX_WORK_FIX_ALLOC_LOWER_LIM
+ | ERTS_SSI_AUX_WORK_FIX_ALLOC_DEALLOC)) {
+ aux_work = handle_fix_alloc(awdp, aux_work);
+ ERTS_DBG_CHK_AUX_WORK_VAL(aux_work);
+ }
+#ifdef ERTS_SMP
+ if (aux_work & ERTS_SSI_AUX_WORK_DD) {
+ aux_work = handle_delayed_dealloc(awdp, aux_work);
+ ERTS_DBG_CHK_AUX_WORK_VAL(aux_work);
+ }
+ if (aux_work & ERTS_SSI_AUX_WORK_DD_THR_PRGR) {
+ aux_work = handle_delayed_dealloc_thr_prgr(awdp, aux_work);
+ ERTS_DBG_CHK_AUX_WORK_VAL(aux_work);
+ }
#endif
+#ifdef ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK
+ if (aux_work & ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK) {
+ aux_work = handle_mseg_cache_check(awdp, aux_work);
+ ERTS_DBG_CHK_AUX_WORK_VAL(aux_work);
}
+#endif
+ ERTS_DBG_CHK_AUX_WORK_VAL(aux_work);
return aux_work;
}
-#endif
+typedef struct {
+ union {
+ ErlTimer data;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErlTimer))];
+ } timer;
-#ifdef ERTS_SCHED_NEED_NONBLOCKABLE_AUX_WORK
-static ERTS_INLINE erts_aint32_t
-nonblockable_aux_work(ErtsSchedulerData *esdp,
- ErtsSchedulerSleepInfo *ssi,
- erts_aint32_t aux_work)
+ int initialized;
+ erts_atomic32_t refc;
+ erts_atomic32_t type[1];
+} ErtsAuxWorkTmo;
+
+static ErtsAuxWorkTmo *aux_work_tmo;
+
+static void
+aux_work_timeout_early_init(int no_schedulers)
{
- if (aux_work & ERTS_SSI_NONBLOCKABLE_AUX_WORK_MASK) {
+ int i;
+ UWord p;
+
+ /*
+ * This is done really early. Our own allocators have
+ * not been started yet.
+ */
+
+ p = (UWord) malloc((sizeof(ErtsAuxWorkTmo)
+ + sizeof(erts_atomic32_t)*(no_schedulers+1))
+ + ERTS_CACHE_LINE_SIZE-1);
+ if (p & ERTS_CACHE_LINE_MASK)
+ p = (p & ~ERTS_CACHE_LINE_MASK) + ERTS_CACHE_LINE_SIZE;
+ ASSERT((p & ERTS_CACHE_LINE_MASK) == 0);
+
+ aux_work_tmo = (ErtsAuxWorkTmo *) p;
+ aux_work_tmo->initialized = 0;
+ erts_atomic32_init_nob(&aux_work_tmo->refc, 0);
+ for (i = 0; i <= no_schedulers; i++)
+ erts_atomic32_init_nob(&aux_work_tmo->type[i], 0);
+}
+void
+aux_work_timeout_late_init(void)
+{
+ aux_work_tmo->initialized = 1;
+ if (erts_atomic32_read_nob(&aux_work_tmo->refc)) {
+ aux_work_tmo->timer.data.active = 0;
+ erts_set_timer(&aux_work_tmo->timer.data,
+ aux_work_timeout,
+ NULL,
+ NULL,
+ 1000);
}
}
-#endif
static void
-prepare_for_block(void *vrq)
+aux_work_timeout(void *unused)
{
- erts_smp_runq_unlock((ErtsRunQueue *) vrq);
+ erts_aint32_t refc;
+ int i;
+#ifdef ERTS_SMP
+ i = 0;
+#else
+ i = 1;
+#endif
+
+ for (; i <= erts_no_schedulers; i++) {
+ erts_aint32_t type;
+ type = erts_atomic32_read_acqb(&aux_work_tmo->type[i]);
+ if (type)
+ set_aux_work_flags_wakeup_nob(ERTS_SCHED_SLEEP_INFO_IX(i-1),
+ type);
+ }
+
+ refc = erts_atomic32_read_nob(&aux_work_tmo->refc);
+ ASSERT(refc >= 1);
+ if (refc != 1
+ || 1 != erts_atomic32_cmpxchg_relb(&aux_work_tmo->refc, 0, 1)) {
+ /* Setup next timeout... */
+ aux_work_tmo->timer.data.active = 0;
+ erts_set_timer(&aux_work_tmo->timer.data,
+ aux_work_timeout,
+ NULL,
+ NULL,
+ 1000);
+ }
}
static void
-resume_after_block(void *vrq)
+setup_aux_work_timer(void)
{
- erts_smp_runq_lock((ErtsRunQueue *) vrq);
+#ifndef ERTS_SMP
+ if (!erts_get_scheduler_data())
+ set_aux_work_flags_wakeup_nob(ERTS_SCHED_SLEEP_INFO_IX(0),
+ ERTS_SSI_AUX_WORK_SET_TMO);
+ else
+#endif
+ {
+ aux_work_tmo->timer.data.active = 0;
+ erts_set_timer(&aux_work_tmo->timer.data,
+ aux_work_timeout,
+ NULL,
+ NULL,
+ 1000);
+ }
}
+erts_aint32_t
+erts_set_aux_work_timeout(int ix, erts_aint32_t type, int enable)
+{
+ erts_aint32_t old, refc;
+
+#ifndef ERTS_SMP
+ ix = 1;
#endif
+ ERTS_DBG_CHK_AUX_WORK_VAL(type);
+ ERTS_DBG_CHK_AUX_WORK_VAL(erts_atomic32_read_nob(&aux_work_tmo->type[ix]));
+// erts_fprintf(stderr, "t(%d, 0x%x, %d)\n", ix, type, enable);
+
+ if (!enable) {
+ old = erts_atomic32_read_band_mb(&aux_work_tmo->type[ix], ~type);
+ ERTS_DBG_CHK_AUX_WORK_VAL(erts_atomic32_read_nob(&aux_work_tmo->type[ix]));
+ if (old != 0 && (old & ~type) == 0)
+ erts_atomic32_dec_relb(&aux_work_tmo->refc);
+ return old;
+ }
+
+ old = erts_atomic32_read_bor_mb(&aux_work_tmo->type[ix], type);
+ ERTS_DBG_CHK_AUX_WORK_VAL(erts_atomic32_read_nob(&aux_work_tmo->type[ix]));
+ if (old == 0 && type != 0) {
+ refc = erts_atomic32_inc_read_acqb(&aux_work_tmo->refc);
+ if (refc == 1) {
+ erts_atomic32_inc_acqb(&aux_work_tmo->refc);
+ if (aux_work_tmo->initialized)
+ setup_aux_work_timer();
+ }
+ }
+ return old;
+}
+
+
+
static ERTS_INLINE void
sched_waiting_sys(Uint no, ErtsRunQueue *rq)
{
@@ -801,8 +1392,6 @@ sched_active_sys(Uint no, ErtsRunQueue *rq)
Uint
erts_active_schedulers(void)
{
- /* RRRRRRRRR */
-
Uint as = erts_no_schedulers;
ERTS_ATOMIC_FOREACH_RUNQ(rq, as -= abs(rq->waiting));
@@ -816,7 +1405,7 @@ erts_active_schedulers(void)
static ERTS_INLINE void
clear_sys_scheduling(void)
{
- erts_smp_atomic32_set_relb(&doing_sys_schedule, 0);
+ erts_smp_atomic32_set_mb(&doing_sys_schedule, 0);
}
static ERTS_INLINE int
@@ -883,42 +1472,43 @@ sched_active(Uint no, ErtsRunQueue *rq)
static int ERTS_INLINE
ongoing_multi_scheduling_block(void)
{
- return erts_smp_atomic32_read(&schdlr_sspnd.msb.ongoing) != 0;
+ ERTS_SMP_LC_ASSERT(erts_lc_mtx_is_locked(&schdlr_sspnd.mtx));
+ return schdlr_sspnd.msb.ongoing;
}
static ERTS_INLINE void
empty_runq(ErtsRunQueue *rq)
{
- erts_aint32_t oifls = erts_smp_atomic32_band(&rq->info_flags,
- ~ERTS_RUNQ_IFLG_NONEMPTY);
+ erts_aint32_t oifls = erts_smp_atomic32_read_band_nob(&rq->info_flags,
+ ~ERTS_RUNQ_IFLG_NONEMPTY);
if (oifls & ERTS_RUNQ_IFLG_NONEMPTY) {
#ifdef DEBUG
- erts_aint32_t empty = erts_smp_atomic32_read(&no_empty_run_queues);
+ erts_aint32_t empty = erts_smp_atomic32_read_nob(&no_empty_run_queues);
/*
* For a short period of time no_empty_run_queues may have
* been increased twice for a specific run queue.
*/
ASSERT(0 <= empty && empty < 2*erts_no_run_queues);
#endif
- erts_smp_atomic32_inc(&no_empty_run_queues);
+ erts_smp_atomic32_inc_relb(&no_empty_run_queues);
}
}
static ERTS_INLINE void
non_empty_runq(ErtsRunQueue *rq)
{
- erts_aint32_t oifls = erts_smp_atomic32_bor(&rq->info_flags,
- ERTS_RUNQ_IFLG_NONEMPTY);
+ erts_aint32_t oifls = erts_smp_atomic32_read_bor_nob(&rq->info_flags,
+ ERTS_RUNQ_IFLG_NONEMPTY);
if (!(oifls & ERTS_RUNQ_IFLG_NONEMPTY)) {
#ifdef DEBUG
- erts_aint32_t empty = erts_smp_atomic32_read(&no_empty_run_queues);
+ erts_aint32_t empty = erts_smp_atomic32_read_nob(&no_empty_run_queues);
/*
* For a short period of time no_empty_run_queues may have
* been increased twice for a specific run queue.
*/
ASSERT(0 < empty && empty <= 2*erts_no_run_queues);
#endif
- erts_smp_atomic32_dec(&no_empty_run_queues);
+ erts_smp_atomic32_dec_relb(&no_empty_run_queues);
}
}
@@ -931,7 +1521,7 @@ sched_prep_spin_wait(ErtsSchedulerSleepInfo *ssi)
erts_aint32_t xflgs = 0;
do {
- oflgs = erts_smp_atomic32_cmpxchg(&ssi->flags, nflgs, xflgs);
+ oflgs = erts_smp_atomic32_cmpxchg_acqb(&ssi->flags, nflgs, xflgs);
if (oflgs == xflgs)
return nflgs;
xflgs = oflgs;
@@ -948,7 +1538,7 @@ sched_prep_cont_spin_wait(ErtsSchedulerSleepInfo *ssi)
erts_aint32_t xflgs = ERTS_SSI_FLG_WAITING;
do {
- oflgs = erts_smp_atomic32_cmpxchg(&ssi->flags, nflgs, xflgs);
+ oflgs = erts_smp_atomic32_cmpxchg_acqb(&ssi->flags, nflgs, xflgs);
if (oflgs == xflgs)
return nflgs;
xflgs = oflgs;
@@ -988,9 +1578,13 @@ sched_set_sleeptype(ErtsSchedulerSleepInfo *ssi, erts_aint32_t sleep_type)
if (sleep_type == ERTS_SSI_FLG_TSE_SLEEPING)
erts_tse_reset(ssi->event);
+ else {
+ ASSERT(sleep_type == ERTS_SSI_FLG_POLL_SLEEPING);
+ erts_sys_schedule_interrupt(0);
+ }
while (1) {
- oflgs = erts_smp_atomic32_cmpxchg(&ssi->flags, nflgs, xflgs);
+ oflgs = erts_smp_atomic32_cmpxchg_acqb(&ssi->flags, nflgs, xflgs);
if (oflgs == xflgs)
return nflgs;
if ((oflgs & (ERTS_SSI_FLG_SLEEPING|ERTS_SSI_FLG_WAITING))
@@ -1006,16 +1600,127 @@ sched_set_sleeptype(ErtsSchedulerSleepInfo *ssi, erts_aint32_t sleep_type)
(((FLGS) & (ERTS_SSI_FLG_WAITING|ERTS_SSI_FLG_SUSPENDED)) \
!= ERTS_SSI_FLG_WAITING)
+
+static void
+thr_prgr_wakeup(void *vssi)
+{
+ erts_sched_poke((ErtsSchedulerSleepInfo *) vssi);
+}
+
+static void
+thr_prgr_prep_wait(void *vssi)
+{
+ ErtsSchedulerSleepInfo *ssi = (ErtsSchedulerSleepInfo *) vssi;
+ erts_smp_atomic32_read_bor_acqb(&ssi->flags,
+ ERTS_SSI_FLG_SLEEPING);
+}
+
+static void
+thr_prgr_wait(void *vssi)
+{
+ ErtsSchedulerSleepInfo *ssi = (ErtsSchedulerSleepInfo *) vssi;
+ erts_aint32_t xflgs = ERTS_SSI_FLG_SLEEPING;
+
+ erts_tse_reset(ssi->event);
+
+ while (1) {
+ erts_aint32_t aflgs, nflgs;
+ nflgs = xflgs | ERTS_SSI_FLG_TSE_SLEEPING;
+ aflgs = erts_smp_atomic32_cmpxchg_acqb(&ssi->flags, nflgs, xflgs);
+ if (aflgs == xflgs) {
+ erts_tse_wait(ssi->event);
+ break;
+ }
+ if ((aflgs & ERTS_SSI_FLG_SLEEPING) == 0)
+ break;
+ xflgs = aflgs;
+ }
+}
+
+static void
+thr_prgr_fin_wait(void *vssi)
+{
+ ErtsSchedulerSleepInfo *ssi = (ErtsSchedulerSleepInfo *) vssi;
+ erts_smp_atomic32_read_band_nob(&ssi->flags,
+ ~(ERTS_SSI_FLG_SLEEPING
+ | ERTS_SSI_FLG_TSE_SLEEPING));
+}
+
+static void init_aux_work_data(ErtsAuxWorkData *awdp, ErtsSchedulerData *esdp);
+
+static void *
+aux_thread(void *unused)
+{
+ ErtsAuxWorkData *awdp = aux_thread_aux_work_data;
+ ErtsSchedulerSleepInfo *ssi = ERTS_SCHED_SLEEP_INFO_IX(-1);
+ erts_aint32_t aux_work;
+ ErtsThrPrgrCallbacks callbacks;
+ int thr_prgr_active = 1;
+
+ ssi->event = erts_tse_fetch();
+
+ callbacks.arg = (void *) ssi;
+ callbacks.wakeup = thr_prgr_wakeup;
+ callbacks.prepare_wait = thr_prgr_prep_wait;
+ callbacks.wait = thr_prgr_wait;
+ callbacks.finalize_wait = thr_prgr_fin_wait;
+
+ erts_thr_progress_register_managed_thread(NULL, &callbacks, 1);
+ init_aux_work_data(awdp, NULL);
+ awdp->ssi = ssi;
+
+ sched_prep_spin_wait(ssi);
+
+ while (1) {
+ erts_aint32_t flgs;
+
+ aux_work = erts_atomic32_read_acqb(&ssi->aux_work);
+ if (aux_work) {
+ if (!thr_prgr_active)
+ erts_thr_progress_active(NULL, thr_prgr_active = 1);
+ aux_work = handle_aux_work(awdp, aux_work);
+ if (aux_work && erts_thr_progress_update(NULL))
+ erts_thr_progress_leader_update(NULL);
+ }
+
+ if (!aux_work) {
+ if (thr_prgr_active)
+ erts_thr_progress_active(NULL, thr_prgr_active = 0);
+ erts_thr_progress_prepare_wait(NULL);
+
+ flgs = sched_spin_wait(ssi, 0);
+
+ if (flgs & ERTS_SSI_FLG_SLEEPING) {
+ ASSERT(flgs & ERTS_SSI_FLG_WAITING);
+ flgs = sched_set_sleeptype(ssi, ERTS_SSI_FLG_TSE_SLEEPING);
+ if (flgs & ERTS_SSI_FLG_SLEEPING) {
+ int res;
+ ASSERT(flgs & ERTS_SSI_FLG_TSE_SLEEPING);
+ ASSERT(flgs & ERTS_SSI_FLG_WAITING);
+ do {
+ res = erts_tse_wait(ssi->event);
+ } while (res == EINTR);
+ }
+ }
+ erts_thr_progress_finalize_wait(NULL);
+ }
+
+ flgs = sched_prep_spin_wait(ssi);
+ }
+ return NULL;
+}
+
+#endif /* ERTS_SMP */
+
static void
scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
{
ErtsSchedulerSleepInfo *ssi = esdp->ssi;
int spincount;
+ erts_aint32_t aux_work = 0;
+#ifdef ERTS_SMP
+ int thr_prgr_active = 1;
erts_aint32_t flgs;
-#if defined(ERTS_SCHED_NEED_NONBLOCKABLE_AUX_WORK) \
- || defined(ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK)
- erts_aint32_t aux_work;
-#endif
ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(rq));
@@ -1049,34 +1754,38 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
tse_wait:
-#ifdef ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK
- aux_work = erts_smp_atomic32_read(&ssi->aux_work);
- tse_blockable_aux_work:
- aux_work = blockable_aux_work(esdp, ssi, aux_work);
-#endif
- erts_smp_activity_begin(ERTS_ACTIVITY_WAIT, NULL, NULL, NULL);
-
while (1) {
-#ifdef ERTS_SCHED_NEED_NONBLOCKABLE_AUX_WORK
-#ifndef ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK
- aux_work = erts_smp_atomic32_read(&ssi->aux_work);
-#endif
- nonblockable_aux_work(esdp, ssi, aux_work);
-#endif
+ aux_work = erts_atomic32_read_acqb(&ssi->aux_work);
+ if (aux_work) {
+ if (!thr_prgr_active)
+ erts_thr_progress_active(esdp, thr_prgr_active = 1);
+ aux_work = handle_aux_work(&esdp->aux_work_data, aux_work);
+ if (aux_work && erts_thr_progress_update(esdp))
+ erts_thr_progress_leader_update(esdp);
+ }
- flgs = sched_spin_wait(ssi, spincount);
- if (flgs & ERTS_SSI_FLG_SLEEPING) {
- ASSERT(flgs & ERTS_SSI_FLG_WAITING);
- flgs = sched_set_sleeptype(ssi, ERTS_SSI_FLG_TSE_SLEEPING);
+ if (aux_work)
+ flgs = erts_smp_atomic32_read_acqb(&ssi->flags);
+ else {
+ if (thr_prgr_active)
+ erts_thr_progress_active(esdp, thr_prgr_active = 0);
+ erts_thr_progress_prepare_wait(esdp);
+
+ flgs = sched_spin_wait(ssi, spincount);
if (flgs & ERTS_SSI_FLG_SLEEPING) {
- int res;
- ASSERT(flgs & ERTS_SSI_FLG_TSE_SLEEPING);
ASSERT(flgs & ERTS_SSI_FLG_WAITING);
- do {
- res = erts_tse_wait(ssi->event);
- } while (res == EINTR);
+ flgs = sched_set_sleeptype(ssi, ERTS_SSI_FLG_TSE_SLEEPING);
+ if (flgs & ERTS_SSI_FLG_SLEEPING) {
+ int res;
+ ASSERT(flgs & ERTS_SSI_FLG_TSE_SLEEPING);
+ ASSERT(flgs & ERTS_SSI_FLG_WAITING);
+ do {
+ res = erts_tse_wait(ssi->event);
+ } while (res == EINTR);
+ }
}
+ erts_thr_progress_finalize_wait(esdp);
}
if (!(flgs & ERTS_SSI_FLG_WAITING)) {
@@ -1092,26 +1801,21 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
break;
}
-#ifdef ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK
- aux_work = erts_smp_atomic32_read(&ssi->aux_work);
- if (aux_work & ERTS_SSI_BLOCKABLE_AUX_WORK_MASK) {
- erts_smp_activity_end(ERTS_ACTIVITY_WAIT, NULL, NULL, NULL);
- goto tse_blockable_aux_work;
- }
-#endif
-
}
- erts_smp_activity_end(ERTS_ACTIVITY_WAIT, NULL, NULL, NULL);
-
if (flgs & ~ERTS_SSI_FLG_SUSPENDED)
- erts_smp_atomic32_band(&ssi->flags, ERTS_SSI_FLG_SUSPENDED);
+ erts_smp_atomic32_read_band_nob(&ssi->flags, ERTS_SSI_FLG_SUSPENDED);
+
+ if (!thr_prgr_active)
+ erts_thr_progress_active(esdp, thr_prgr_active = 1);
erts_smp_runq_lock(rq);
sched_active(esdp->no, rq);
}
- else {
+ else
+#endif
+ {
erts_aint_t dt;
erts_smp_atomic32_set_relb(&function_calls, 0);
@@ -1135,30 +1839,32 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
if (dt) erts_bump_timer(dt);
sys_aux_work:
-
-#ifdef ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK
- aux_work = erts_smp_atomic32_read(&ssi->aux_work);
- aux_work = blockable_aux_work(esdp, ssi, aux_work);
+#ifndef ERTS_SMP
+ erts_sys_schedule_interrupt(0);
#endif
-#ifdef ERTS_SCHED_NEED_NONBLOCKABLE_AUX_WORK
-#ifndef ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK
- aux_work = erts_smp_atomic32_read(&ssi->aux_work);
+
+ aux_work = erts_atomic32_read_acqb(&ssi->aux_work);
+ if (aux_work) {
+#ifdef ERTS_SMP
+ if (!thr_prgr_active)
+ erts_thr_progress_active(esdp, thr_prgr_active = 1);
#endif
- nonblockable_aux_work(esdp, ssi, aux_work);
+ aux_work = handle_aux_work(&esdp->aux_work_data, aux_work);
+#ifdef ERTS_SMP
+ if (aux_work && erts_thr_progress_update(esdp))
+ erts_thr_progress_leader_update(esdp);
#endif
+ }
+#ifndef ERTS_SMP
+ if (rq->len != 0 || rq->misc.start)
+ goto sys_woken;
+#else
flgs = erts_smp_atomic32_read_acqb(&ssi->flags);
if (!(flgs & ERTS_SSI_FLG_WAITING)) {
ASSERT(!(flgs & ERTS_SSI_FLG_SLEEPING));
goto sys_woken;
}
- if (!(flgs & ERTS_SSI_FLG_SLEEPING)) {
- flgs = sched_prep_cont_spin_wait(ssi);
- if (!(flgs & ERTS_SSI_FLG_WAITING)) {
- ASSERT(!(flgs & ERTS_SSI_FLG_SLEEPING));
- goto sys_woken;
- }
- }
/*
* If we got new I/O tasks we aren't allowed to
@@ -1175,10 +1881,12 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
goto tse_wait;
}
}
+#endif
}
erts_smp_runq_lock(rq);
+#ifdef ERTS_SMP
/*
* If we got new I/O tasks we aren't allowed to
* sleep in erl_sys_schedule().
@@ -1190,64 +1898,88 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
* Got to check that we still got I/O tasks; otherwise
* we have to wait in erl_sys_schedule() after all...
*/
- if (prepare_for_sys_schedule())
- goto do_sys_schedule;
-
- /*
- * Not allowed to wait in erl_sys_schedule;
- * do tse wait instead...
- */
- sched_change_waiting_sys_to_waiting(esdp->no, rq);
+ if (!prepare_for_sys_schedule()) {
+ /*
+ * Not allowed to wait in erl_sys_schedule;
+ * do tse wait instead...
+ */
+ sched_change_waiting_sys_to_waiting(esdp->no, rq);
+ erts_smp_runq_unlock(rq);
+ spincount = 0;
+ goto tse_wait;
+ }
+ }
+#endif
+ if (aux_work) {
erts_smp_runq_unlock(rq);
- spincount = 0;
- goto tse_wait;
+ goto sys_poll_aux_work;
}
- else {
- do_sys_schedule:
- erts_sys_schedule_interrupt(0);
- flgs = sched_set_sleeptype(ssi, ERTS_SSI_FLG_POLL_SLEEPING);
- if (!(flgs & ERTS_SSI_FLG_SLEEPING)) {
- if (!(flgs & ERTS_SSI_FLG_WAITING))
- goto sys_locked_woken;
- erts_smp_runq_unlock(rq);
- flgs = sched_prep_cont_spin_wait(ssi);
- if (!(flgs & ERTS_SSI_FLG_WAITING)) {
- ASSERT(!(flgs & ERTS_SSI_FLG_SLEEPING));
- goto sys_woken;
- }
- ASSERT(!erts_port_task_have_outstanding_io_tasks());
- goto sys_poll_aux_work;
+#ifdef ERTS_SMP
+ flgs = sched_set_sleeptype(ssi, ERTS_SSI_FLG_POLL_SLEEPING);
+ if (!(flgs & ERTS_SSI_FLG_SLEEPING)) {
+ if (!(flgs & ERTS_SSI_FLG_WAITING)) {
+ ASSERT(!(flgs & ERTS_SSI_FLG_SLEEPING));
+ goto sys_locked_woken;
+ }
+ erts_smp_runq_unlock(rq);
+ flgs = sched_prep_cont_spin_wait(ssi);
+ if (!(flgs & ERTS_SSI_FLG_WAITING)) {
+ ASSERT(!(flgs & ERTS_SSI_FLG_SLEEPING));
+ goto sys_woken;
}
+ ASSERT(!erts_port_task_have_outstanding_io_tasks());
+ goto sys_poll_aux_work;
+ }
- ASSERT(flgs & ERTS_SSI_FLG_POLL_SLEEPING);
- ASSERT(flgs & ERTS_SSI_FLG_WAITING);
+ ASSERT(flgs & ERTS_SSI_FLG_POLL_SLEEPING);
+ ASSERT(flgs & ERTS_SSI_FLG_WAITING);
+#endif
- erts_smp_runq_unlock(rq);
+ erts_smp_runq_unlock(rq);
- ASSERT(!erts_port_task_have_outstanding_io_tasks());
+#ifdef ERTS_SMP
+ if (thr_prgr_active)
+ erts_thr_progress_active(esdp, thr_prgr_active = 0);
+#endif
- erl_sys_schedule(0);
+ ASSERT(!erts_port_task_have_outstanding_io_tasks());
- dt = erts_do_time_read_and_reset();
- if (dt) erts_bump_timer(dt);
+ erl_sys_schedule(0);
- flgs = sched_prep_cont_spin_wait(ssi);
- if (flgs & ERTS_SSI_FLG_WAITING)
- goto sys_aux_work;
+ dt = erts_do_time_read_and_reset();
+ if (dt) erts_bump_timer(dt);
+
+#ifndef ERTS_SMP
+ if (rq->len == 0 && !rq->misc.start)
+ goto sys_aux_work;
+ sys_woken:
+#else
+ flgs = sched_prep_cont_spin_wait(ssi);
+ if (flgs & ERTS_SSI_FLG_WAITING)
+ goto sys_aux_work;
- sys_woken:
+ sys_woken:
+ if (!thr_prgr_active)
+ erts_thr_progress_active(esdp, thr_prgr_active = 1);
+ erts_smp_runq_lock(rq);
+ sys_locked_woken:
+ if (!thr_prgr_active) {
+ erts_smp_runq_unlock(rq);
+ erts_thr_progress_active(esdp, thr_prgr_active = 1);
erts_smp_runq_lock(rq);
- sys_locked_woken:
- clear_sys_scheduling();
- if (flgs & ~ERTS_SSI_FLG_SUSPENDED)
- erts_smp_atomic32_band(&ssi->flags, ERTS_SSI_FLG_SUSPENDED);
- sched_active_sys(esdp->no, rq);
}
+ clear_sys_scheduling();
+ if (flgs & ~ERTS_SSI_FLG_SUSPENDED)
+ erts_smp_atomic32_read_band_nob(&ssi->flags, ERTS_SSI_FLG_SUSPENDED);
+#endif
+ sched_active_sys(esdp->no, rq);
}
ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(rq));
}
+#ifdef ERTS_SMP
+
static ERTS_INLINE erts_aint32_t
ssi_flags_set_wake(ErtsSchedulerSleepInfo *ssi)
{
@@ -1256,7 +1988,7 @@ ssi_flags_set_wake(ErtsSchedulerSleepInfo *ssi)
erts_aint32_t nflgs = 0;
erts_aint32_t xflgs = ERTS_SSI_FLG_SLEEPING|ERTS_SSI_FLG_WAITING;
while (1) {
- oflgs = erts_smp_atomic32_cmpxchg(&ssi->flags, nflgs, xflgs);
+ oflgs = erts_smp_atomic32_cmpxchg_relb(&ssi->flags, nflgs, xflgs);
if (oflgs == xflgs)
return oflgs;
nflgs = oflgs & ERTS_SSI_FLG_SUSPENDED;
@@ -1299,7 +2031,6 @@ wake_scheduler(ErtsRunQueue *rq, int incq, int one)
erts_smp_spin_unlock(&sl->lock);
- ERTS_THR_MEMORY_BARRIER;
flgs = ssi_flags_set_wake(ssi);
erts_sched_finish_poke(ssi, flgs);
@@ -1345,13 +2076,13 @@ init_no_runqs(int active, int used)
{
erts_aint32_t no_runqs = (erts_aint32_t) (active & ERTS_NO_RUNQS_MASK);
no_runqs |= (erts_aint32_t) ((used & ERTS_NO_RUNQS_MASK) << ERTS_NO_USED_RUNQS_SHIFT);
- erts_smp_atomic32_init(&balance_info.no_runqs, no_runqs);
+ erts_smp_atomic32_init_nob(&balance_info.no_runqs, no_runqs);
}
static ERTS_INLINE void
get_no_runqs(int *active, int *used)
{
- erts_aint32_t no_runqs = erts_smp_atomic32_read(&balance_info.no_runqs);
+ erts_aint32_t no_runqs = erts_smp_atomic32_read_nob(&balance_info.no_runqs);
if (active)
*active = (int) (no_runqs & ERTS_NO_RUNQS_MASK);
if (used)
@@ -1361,11 +2092,12 @@ get_no_runqs(int *active, int *used)
static ERTS_INLINE void
set_no_used_runqs(int used)
{
- erts_aint32_t exp = erts_smp_atomic32_read(&balance_info.no_runqs);
+ erts_aint32_t exp = erts_smp_atomic32_read_nob(&balance_info.no_runqs);
while (1) {
erts_aint32_t act, new;
- new = (used << ERTS_NO_USED_RUNQS_SHIFT) | (exp & ERTS_NO_RUNQS_MASK);
- act = erts_smp_atomic32_cmpxchg(&balance_info.no_runqs, new, exp);
+ new = (used & ERTS_NO_RUNQS_MASK) << ERTS_NO_USED_RUNQS_SHIFT;
+ new |= exp & ERTS_NO_RUNQS_MASK;
+ act = erts_smp_atomic32_cmpxchg_nob(&balance_info.no_runqs, new, exp);
if (act == exp)
break;
exp = act;
@@ -1375,11 +2107,12 @@ set_no_used_runqs(int used)
static ERTS_INLINE void
set_no_active_runqs(int active)
{
- erts_aint32_t exp = erts_smp_atomic32_read(&balance_info.no_runqs);
+ erts_aint32_t exp = erts_smp_atomic32_read_nob(&balance_info.no_runqs);
while (1) {
erts_aint32_t act, new;
- new = (exp & (ERTS_NO_RUNQS_MASK << ERTS_NO_USED_RUNQS_SHIFT)) | active;
- act = erts_smp_atomic32_cmpxchg(&balance_info.no_runqs, new, exp);
+ new = exp & (ERTS_NO_RUNQS_MASK << ERTS_NO_USED_RUNQS_SHIFT);
+ new |= active & ERTS_NO_RUNQS_MASK;
+ act = erts_smp_atomic32_cmpxchg_nob(&balance_info.no_runqs, new, exp);
if (act == exp)
break;
exp = act;
@@ -1389,13 +2122,14 @@ set_no_active_runqs(int active)
static ERTS_INLINE int
try_inc_no_active_runqs(int active)
{
- erts_aint32_t exp = erts_smp_atomic32_read(&balance_info.no_runqs);
+ erts_aint32_t exp = erts_smp_atomic32_read_nob(&balance_info.no_runqs);
if (((exp >> ERTS_NO_USED_RUNQS_SHIFT) & ERTS_NO_RUNQS_MASK) < active)
return 0;
if ((exp & ERTS_NO_RUNQS_MASK) + 1 == active) {
erts_aint32_t new, act;
- new = (exp & ~ERTS_NO_RUNQS_MASK) | active;
- act = erts_smp_atomic32_cmpxchg(&balance_info.no_runqs, new, exp);
+ new = exp & (ERTS_NO_RUNQS_MASK << ERTS_NO_USED_RUNQS_SHIFT);
+ new |= active & ERTS_NO_RUNQS_MASK;
+ act = erts_smp_atomic32_cmpxchg_nob(&balance_info.no_runqs, new, exp);
if (act == exp)
return 1;
}
@@ -1411,7 +2145,7 @@ chk_wake_sched(ErtsRunQueue *crq, int ix, int activate)
if (crq->ix == ix)
return 0;
wrq = ERTS_RUNQ_IX(ix);
- iflgs = erts_smp_atomic32_read(&wrq->info_flags);
+ iflgs = erts_smp_atomic32_read_nob(&wrq->info_flags);
if (!(iflgs & (ERTS_RUNQ_IFLG_SUSPENDED|ERTS_RUNQ_IFLG_NONEMPTY))) {
if (activate) {
if (try_inc_no_active_runqs(ix+1)) {
@@ -1653,15 +2387,15 @@ evacuate_run_queue(ErtsRunQueue *evac_rq, ErtsRunQueue *rq)
erts_smp_runq_lock(evac_rq);
- erts_smp_atomic32_bor(&evac_rq->scheduler->ssi->flags,
- ERTS_SSI_FLG_SUSPENDED);
+ erts_smp_atomic32_read_bor_nob(&evac_rq->scheduler->ssi->flags,
+ ERTS_SSI_FLG_SUSPENDED);
evac_rq->flags &= ~ERTS_RUNQ_FLGS_IMMIGRATE_QMASK;
evac_rq->flags |= (ERTS_RUNQ_FLGS_EMIGRATE_QMASK
| ERTS_RUNQ_FLGS_EVACUATE_QMASK
| ERTS_RUNQ_FLG_SUSPENDED);
- erts_smp_atomic32_bor(&evac_rq->info_flags, ERTS_RUNQ_IFLG_SUSPENDED);
+ erts_smp_atomic32_read_bor_nob(&evac_rq->info_flags, ERTS_RUNQ_IFLG_SUSPENDED);
/*
* Need to set up evacuation paths first since we
* may release the run queue lock on evac_rq
@@ -1910,7 +2644,7 @@ static ERTS_INLINE int
check_possible_steal_victim(ErtsRunQueue *rq, int *rq_lockedp, int vix)
{
ErtsRunQueue *vrq = ERTS_RUNQ_IX(vix);
- erts_aint32_t iflgs = erts_smp_atomic32_read(&vrq->info_flags);
+ erts_aint32_t iflgs = erts_smp_atomic32_read_nob(&vrq->info_flags);
if (iflgs & ERTS_RUNQ_IFLG_NONEMPTY)
return try_steal_task_from_victim(rq, rq_lockedp, vrq);
else
@@ -2062,7 +2796,7 @@ check_balance(ErtsRunQueue *c_rq)
int forced, active, current_active, oowc, half_full_scheds, full_scheds,
mmax_len, blnc_no_rqs, qix, pix, freds_hist_ix;
- if (erts_smp_atomic32_xchg(&balance_info.checking_balance, 1)) {
+ if (erts_smp_atomic32_xchg_nob(&balance_info.checking_balance, 1)) {
c_rq->check_balance_reds = INT_MAX;
return;
}
@@ -2070,7 +2804,7 @@ check_balance(ErtsRunQueue *c_rq)
get_no_runqs(NULL, &blnc_no_rqs);
if (blnc_no_rqs == 1) {
c_rq->check_balance_reds = INT_MAX;
- erts_smp_atomic32_set(&balance_info.checking_balance, 0);
+ erts_smp_atomic32_set_nob(&balance_info.checking_balance, 0);
return;
}
@@ -2078,7 +2812,7 @@ check_balance(ErtsRunQueue *c_rq)
if (balance_info.halftime) {
balance_info.halftime = 0;
- erts_smp_atomic32_set(&balance_info.checking_balance, 0);
+ erts_smp_atomic32_set_nob(&balance_info.checking_balance, 0);
ERTS_FOREACH_RUNQ(rq,
{
if (rq->waiting)
@@ -2112,7 +2846,7 @@ check_balance(ErtsRunQueue *c_rq)
erts_smp_mtx_unlock(&balance_info.update_mtx);
erts_smp_runq_lock(c_rq);
c_rq->check_balance_reds = INT_MAX;
- erts_smp_atomic32_set(&balance_info.checking_balance, 0);
+ erts_smp_atomic32_set_nob(&balance_info.checking_balance, 0);
return;
}
@@ -2460,7 +3194,7 @@ erts_fprintf(stderr, "--------------------------------\n");
set_no_active_runqs(active);
balance_info.halftime = 1;
- erts_smp_atomic32_set(&balance_info.checking_balance, 0);
+ erts_smp_atomic32_set_nob(&balance_info.checking_balance, 0);
/* Write migration paths and reset balance statistics in all queues */
for (qix = 0; qix < blnc_no_rqs; qix++) {
@@ -2555,8 +3289,9 @@ erts_debug_nbalance(void)
}
void
-erts_early_init_scheduling(void)
+erts_early_init_scheduling(int no_schedulers)
{
+ aux_work_timeout_early_init(no_schedulers);
wakeup_other_limit = ERTS_WAKEUP_OTHER_LIMIT_MEDIUM;
}
@@ -2577,12 +3312,32 @@ erts_sched_set_wakeup_limit(char *str)
return EINVAL;
return 0;
}
-
+
+static void
+init_aux_work_data(ErtsAuxWorkData *awdp, ErtsSchedulerData *esdp)
+{
+ awdp->sched_id = esdp ? (int) esdp->no : 0;
+ awdp->esdp = esdp;
+ awdp->ssi = esdp ? esdp->ssi : NULL;
+#ifdef ERTS_SMP
+ awdp->misc.thr_prgr = ERTS_THR_PRGR_VAL_WAITING;
+ awdp->dd.thr_prgr = ERTS_THR_PRGR_VAL_WAITING;
+ awdp->dd.completed_callback = NULL;
+ awdp->dd.completed_arg = NULL;
+#endif
+#ifdef ERTS_USE_ASYNC_READY_Q
+#ifdef ERTS_SMP
+ awdp->async_ready.need_thr_prgr = 0;
+ awdp->async_ready.thr_prgr = ERTS_THR_PRGR_VAL_WAITING;
+#endif
+ awdp->async_ready.queue = NULL;
+#endif
+}
void
erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online)
{
- int ix, n;
+ int ix, n, no_ssi;
#ifndef ERTS_SMP
mrq = 0;
@@ -2602,7 +3357,7 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online)
erts_alloc_permanent_cache_aligned(ERTS_ALC_T_RUNQS,
sizeof(ErtsAlignedRunQueue) * n);
#ifdef ERTS_SMP
- erts_smp_atomic32_init(&no_empty_run_queues, 0);
+ erts_smp_atomic32_init_nob(&no_empty_run_queues, 0);
#endif
erts_no_run_queues = n;
@@ -2612,7 +3367,7 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online)
ErtsRunQueue *rq = ERTS_RUNQ_IX(ix);
rq->ix = ix;
- erts_smp_atomic32_init(&rq->info_flags, ERTS_RUNQ_IFLG_NONEMPTY);
+ erts_smp_atomic32_init_nob(&rq->info_flags, ERTS_RUNQ_IFLG_NONEMPTY);
/* make sure that the "extra" id correponds to the schedulers
* id if the esdp->no <-> ix+1 mapping change.
@@ -2692,23 +3447,31 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online)
n = (int) no_schedulers;
erts_no_schedulers = n;
-#ifdef ERTS_SMP
/* Create and initialize scheduler sleep info */
-
+#ifdef ERTS_SMP
+ no_ssi = n+1;
+#else
+ no_ssi = 1;
+#endif
aligned_sched_sleep_info =
- erts_alloc_permanent_cache_aligned(ERTS_ALC_T_SCHDLR_SLP_INFO,
- n * sizeof(ErtsAlignedSchedulerSleepInfo));
-
- for (ix = 0; ix < n; ix++) {
- ErtsSchedulerSleepInfo *ssi = ERTS_SCHED_SLEEP_INFO_IX(ix);
+ erts_alloc_permanent_cache_aligned(
+ ERTS_ALC_T_SCHDLR_SLP_INFO,
+ no_ssi*sizeof(ErtsAlignedSchedulerSleepInfo));
+ for (ix = 0; ix < no_ssi; ix++) {
+ ErtsSchedulerSleepInfo *ssi = &aligned_sched_sleep_info[ix].ssi;
+#ifdef ERTS_SMP
#if 0 /* no need to initialize these... */
ssi->next = NULL;
ssi->prev = NULL;
#endif
- erts_smp_atomic32_init(&ssi->flags, 0);
+ erts_smp_atomic32_init_nob(&ssi->flags, 0);
ssi->event = NULL; /* initialized in sched_thread_func */
- erts_smp_atomic32_init(&ssi->aux_work, 0);
+#endif
+ erts_atomic32_init_nob(&ssi->aux_work, 0);
}
+
+#ifdef ERTS_SMP
+ aligned_sched_sleep_info++;
#endif
/* Create and initialize scheduler specific data */
@@ -2722,17 +3485,20 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online)
#ifdef ERTS_SMP
erts_bits_init_state(&esdp->erl_bits_state);
esdp->match_pseudo_process = NULL;
- esdp->ssi = ERTS_SCHED_SLEEP_INFO_IX(ix);
esdp->free_process = NULL;
-#if HALFWORD_HEAP
- /* Registers need to be heap allocated (correct memory range) for tracing to work */
- esdp->save_reg = erts_alloc(ERTS_ALC_T_BEAM_REGISTER, ERTS_X_REGS_ALLOCATED * sizeof(Eterm));
-#endif
#endif
+ esdp->x_reg_array =
+ erts_alloc_permanent_cache_aligned(ERTS_ALC_T_BEAM_REGISTER,
+ ERTS_X_REGS_ALLOCATED *
+ sizeof(Eterm));
+ esdp->f_reg_array =
+ erts_alloc_permanent_cache_aligned(ERTS_ALC_T_BEAM_REGISTER,
+ MAX_REG * sizeof(FloatDef));
#if !HEAP_ON_C_STACK
esdp->num_tmp_heap_used = 0;
#endif
esdp->no = (Uint) ix+1;
+ esdp->ssi = ERTS_SCHED_SLEEP_INFO_IX(ix);
esdp->current_process = NULL;
esdp->current_port = NULL;
@@ -2751,19 +3517,29 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online)
}
#ifdef ERTS_SMP
- erts_smp_atomic32_init(&esdp->chk_cpu_bind, 0);
+ erts_smp_atomic32_init_nob(&esdp->chk_cpu_bind, 0);
#endif
+ init_aux_work_data(&esdp->aux_work_data, esdp);
}
+ init_misc_aux_work();
+
#ifdef ERTS_SMP
+
+ erts_atomic32_init_nob(&completed_dealloc_count, 0); /* debug only */
+
+ aux_thread_aux_work_data =
+ erts_alloc_permanent_cache_aligned(ERTS_ALC_T_SCHDLR_DATA,
+ sizeof(ErtsAuxWorkData));
+
erts_smp_mtx_init(&schdlr_sspnd.mtx, "schdlr_sspnd");
erts_smp_cnd_init(&schdlr_sspnd.cnd);
- erts_smp_atomic32_init(&schdlr_sspnd.changing, 0);
+ erts_smp_atomic32_init_nob(&schdlr_sspnd.changing, 0);
schdlr_sspnd.online = no_schedulers_online;
schdlr_sspnd.curr_online = no_schedulers;
- erts_smp_atomic32_init(&schdlr_sspnd.msb.ongoing, 0);
- erts_smp_atomic32_init(&schdlr_sspnd.active, no_schedulers);
+ schdlr_sspnd.msb.ongoing = 0;
+ erts_smp_atomic32_init_nob(&schdlr_sspnd.active, no_schedulers);
schdlr_sspnd.msb.procs = NULL;
init_no_runqs(no_schedulers,
erts_common_run_queue ? 1 : no_schedulers_online);
@@ -2772,7 +3548,7 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online)
balance_info.forced_check_balance = 0;
balance_info.halftime = 1;
balance_info.full_reds_history_index = 0;
- erts_smp_atomic32_init(&balance_info.checking_balance, 0);
+ erts_smp_atomic32_init_nob(&balance_info.checking_balance, 0);
balance_info.prev_rise.active_runqs = 0;
balance_info.prev_rise.max_len = 0;
balance_info.prev_rise.reds = 0;
@@ -2781,8 +3557,8 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online)
if (no_schedulers_online < no_schedulers) {
if (erts_common_run_queue) {
for (ix = no_schedulers_online; ix < no_schedulers; ix++)
- erts_smp_atomic32_bor(&ERTS_SCHED_SLEEP_INFO_IX(ix)->flags,
- ERTS_SSI_FLG_SUSPENDED);
+ erts_smp_atomic32_read_bor_nob(&ERTS_SCHED_SLEEP_INFO_IX(ix)->flags,
+ ERTS_SSI_FLG_SUSPENDED);
}
else {
for (ix = no_schedulers_online; ix < erts_no_run_queues; ix++)
@@ -2796,7 +3572,7 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online)
ERTS_SCHDLR_SSPND_CHNG_SET((ERTS_SCHDLR_SSPND_CHNG_ONLN
| ERTS_SCHDLR_SSPND_CHNG_WAITER), 0);
- erts_smp_atomic32_init(&doing_sys_schedule, 0);
+ erts_smp_atomic32_init_nob(&doing_sys_schedule, 0);
init_misc_aux_work();
@@ -2812,11 +3588,13 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online)
erts_no_schedulers = 1;
#endif
- erts_smp_atomic32_init(&function_calls, 0);
+ erts_smp_atomic32_init_nob(&function_calls, 0);
/* init port tasks */
erts_port_task_init();
+ aux_work_timeout_late_init();
+
#ifndef ERTS_SMP
#ifdef ERTS_DO_VERIFY_UNUSED_TEMP_ALLOC
erts_scheduler_data->verify_unused_temp_alloc
@@ -2939,10 +3717,10 @@ int
erts_get_max_no_executing_schedulers(void)
{
#ifdef ERTS_SMP
- if (erts_smp_atomic32_read(&schdlr_sspnd.changing))
+ if (erts_smp_atomic32_read_nob(&schdlr_sspnd.changing))
return (int) erts_no_schedulers;
ERTS_THR_MEMORY_BARRIER;
- return (int) erts_smp_atomic32_read(&schdlr_sspnd.active);
+ return (int) erts_smp_atomic32_read_nob(&schdlr_sspnd.active);
#else
return 1;
#endif
@@ -2951,18 +3729,6 @@ erts_get_max_no_executing_schedulers(void)
#ifdef ERTS_SMP
static void
-susp_sched_prep_block(void *unused)
-{
- erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
-}
-
-static void
-susp_sched_resume_block(void *unused)
-{
- erts_smp_mtx_lock(&schdlr_sspnd.mtx);
-}
-
-static void
scheduler_ix_resume_wake(Uint ix)
{
ErtsSchedulerSleepInfo *ssi = ERTS_SCHED_SLEEP_INFO_IX(ix);
@@ -2972,7 +3738,7 @@ scheduler_ix_resume_wake(Uint ix)
| ERTS_SSI_FLG_SUSPENDED);
erts_aint32_t oflgs;
do {
- oflgs = erts_smp_atomic32_cmpxchg(&ssi->flags, 0, xflgs);
+ oflgs = erts_smp_atomic32_cmpxchg_relb(&ssi->flags, 0, xflgs);
if (oflgs == xflgs) {
erts_sched_finish_poke(ssi, oflgs);
break;
@@ -2991,7 +3757,7 @@ sched_prep_spin_suspended(ErtsSchedulerSleepInfo *ssi, erts_aint32_t xpct)
erts_aint32_t xflgs = xpct;
do {
- oflgs = erts_smp_atomic32_cmpxchg(&ssi->flags, nflgs, xflgs);
+ oflgs = erts_smp_atomic32_cmpxchg_acqb(&ssi->flags, nflgs, xflgs);
if (oflgs == xflgs)
return nflgs;
xflgs = oflgs;
@@ -3041,7 +3807,7 @@ sched_set_suspended_sleeptype(ErtsSchedulerSleepInfo *ssi)
erts_tse_reset(ssi->event);
while (1) {
- oflgs = erts_smp_atomic32_cmpxchg(&ssi->flags, nflgs, xflgs);
+ oflgs = erts_smp_atomic32_cmpxchg_acqb(&ssi->flags, nflgs, xflgs);
if (oflgs == xflgs)
return nflgs;
if ((oflgs & (ERTS_SSI_FLG_SLEEPING
@@ -3066,10 +3832,8 @@ suspend_scheduler(ErtsSchedulerData *esdp)
long active_schedulers;
int curr_online = 1;
int wake = 0;
-#if defined(ERTS_SCHED_NEED_NONBLOCKABLE_AUX_WORK) \
- || defined(ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK)
erts_aint32_t aux_work;
-#endif
+ int thr_prgr_active = 1;
/*
* Schedulers may be suspended in two different ways:
@@ -3096,15 +3860,15 @@ suspend_scheduler(ErtsSchedulerData *esdp)
flgs = sched_prep_spin_suspended(ssi, ERTS_SSI_FLG_SUSPENDED);
if (flgs & ERTS_SSI_FLG_SUSPENDED) {
- active_schedulers = erts_smp_atomic32_dectest(&schdlr_sspnd.active);
+ active_schedulers = erts_smp_atomic32_dec_read_nob(&schdlr_sspnd.active);
ASSERT(active_schedulers >= 1);
- changing = erts_smp_atomic32_read(&schdlr_sspnd.changing);
+ changing = erts_smp_atomic32_read_nob(&schdlr_sspnd.changing);
if (changing & ERTS_SCHDLR_SSPND_CHNG_MSB) {
if (active_schedulers == schdlr_sspnd.msb.wait_active)
wake = 1;
if (active_schedulers == 1) {
- changing = erts_smp_atomic32_band(&schdlr_sspnd.changing,
- ~ERTS_SCHDLR_SSPND_CHNG_MSB);
+ changing = erts_smp_atomic32_read_band_nob(&schdlr_sspnd.changing,
+ ~ERTS_SCHDLR_SSPND_CHNG_MSB);
changing &= ~ERTS_SCHDLR_SSPND_CHNG_MSB;
}
}
@@ -3126,8 +3890,8 @@ suspend_scheduler(ErtsSchedulerData *esdp)
&& schdlr_sspnd.curr_online == schdlr_sspnd.wait_curr_online)
wake = 1;
if (schdlr_sspnd.online == schdlr_sspnd.curr_online) {
- changing = erts_smp_atomic32_band(&schdlr_sspnd.changing,
- ~ERTS_SCHDLR_SSPND_CHNG_ONLN);
+ changing = erts_smp_atomic32_read_band_nob(&schdlr_sspnd.changing,
+ ~ERTS_SCHDLR_SSPND_CHNG_ONLN);
changing &= ~ERTS_SCHDLR_SSPND_CHNG_ONLN;
}
}
@@ -3142,75 +3906,65 @@ suspend_scheduler(ErtsSchedulerData *esdp)
break;
erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
-
-#ifdef ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK
- aux_work = erts_smp_atomic32_read(&ssi->aux_work);
- blockable_aux_work:
- blockable_aux_work(esdp, ssi, aux_work);
-#endif
-
- erts_smp_activity_begin(ERTS_ACTIVITY_WAIT, NULL, NULL, NULL);
while (1) {
erts_aint32_t flgs;
-#ifdef ERTS_SCHED_NEED_NONBLOCKABLE_AUX_WORK
-#ifndef ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK
- aux_work = erts_smp_atomic32_read(&ssi->aux_work);
-#endif
- nonblockable_aux_work(esdp, ssi, aux_work);
-#endif
- flgs = sched_spin_suspended(ssi,
- ERTS_SCHED_SUSPEND_SLEEP_SPINCOUNT);
- if (flgs == (ERTS_SSI_FLG_SLEEPING
- | ERTS_SSI_FLG_WAITING
- | ERTS_SSI_FLG_SUSPENDED)) {
- flgs = sched_set_suspended_sleeptype(ssi);
+ aux_work = erts_atomic32_read_acqb(&ssi->aux_work);
+ if (aux_work) {
+ if (!thr_prgr_active)
+ erts_thr_progress_active(esdp, thr_prgr_active = 1);
+ aux_work = handle_aux_work(&esdp->aux_work_data, aux_work);
+ if (aux_work && erts_thr_progress_update(esdp))
+ erts_thr_progress_leader_update(esdp);
+ }
+
+ if (!aux_work) {
+ if (thr_prgr_active)
+ erts_thr_progress_active(esdp, thr_prgr_active = 0);
+ erts_thr_progress_prepare_wait(esdp);
+ flgs = sched_spin_suspended(ssi,
+ ERTS_SCHED_SUSPEND_SLEEP_SPINCOUNT);
if (flgs == (ERTS_SSI_FLG_SLEEPING
- | ERTS_SSI_FLG_TSE_SLEEPING
| ERTS_SSI_FLG_WAITING
| ERTS_SSI_FLG_SUSPENDED)) {
- int res;
- do {
- res = erts_tse_wait(ssi->event);
- } while (res == EINTR);
+ flgs = sched_set_suspended_sleeptype(ssi);
+ if (flgs == (ERTS_SSI_FLG_SLEEPING
+ | ERTS_SSI_FLG_TSE_SLEEPING
+ | ERTS_SSI_FLG_WAITING
+ | ERTS_SSI_FLG_SUSPENDED)) {
+ int res;
+
+ do {
+ res = erts_tse_wait(ssi->event);
+ } while (res == EINTR);
+ }
}
+ erts_thr_progress_finalize_wait(esdp);
}
flgs = sched_prep_spin_suspended(ssi, (ERTS_SSI_FLG_WAITING
| ERTS_SSI_FLG_SUSPENDED));
if (!(flgs & ERTS_SSI_FLG_SUSPENDED))
break;
- changing = erts_smp_atomic32_read(&schdlr_sspnd.changing);
+ changing = erts_smp_atomic32_read_nob(&schdlr_sspnd.changing);
if (changing & ~ERTS_SCHDLR_SSPND_CHNG_WAITER)
break;
-
-
-#ifdef ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK
- aux_work = erts_smp_atomic32_read(&ssi->aux_work);
- if (aux_work & ERTS_SSI_BLOCKABLE_AUX_WORK_MASK) {
- erts_smp_activity_end(ERTS_ACTIVITY_WAIT, NULL, NULL, NULL);
- goto blockable_aux_work;
- }
-#endif
-
}
- erts_smp_activity_end(ERTS_ACTIVITY_WAIT, NULL, NULL, NULL);
-
erts_smp_mtx_lock(&schdlr_sspnd.mtx);
- changing = erts_smp_atomic32_read(&schdlr_sspnd.changing);
+ changing = erts_smp_atomic32_read_nob(&schdlr_sspnd.changing);
}
- active_schedulers = erts_smp_atomic32_inctest(&schdlr_sspnd.active);
- changing = erts_smp_atomic32_read(&schdlr_sspnd.changing);
+ active_schedulers = erts_smp_atomic32_inc_read_nob(&schdlr_sspnd.active);
+ changing = erts_smp_atomic32_read_nob(&schdlr_sspnd.changing);
if ((changing & ERTS_SCHDLR_SSPND_CHNG_MSB)
&& schdlr_sspnd.online == active_schedulers) {
- erts_smp_atomic32_band(&schdlr_sspnd.changing,
- ~ERTS_SCHDLR_SSPND_CHNG_MSB);
+ erts_smp_atomic32_read_band_nob(&schdlr_sspnd.changing,
+ ~ERTS_SCHDLR_SSPND_CHNG_MSB);
}
ASSERT(no <= schdlr_sspnd.online);
- ASSERT(!erts_smp_atomic32_read(&schdlr_sspnd.msb.ongoing));
+ ASSERT(!ongoing_multi_scheduling_block());
}
@@ -3221,6 +3975,9 @@ suspend_scheduler(ErtsSchedulerData *esdp)
if (erts_system_profile_flags.scheduler)
profile_scheduler(make_small(esdp->no), am_active);
+ if (!thr_prgr_active)
+ erts_thr_progress_active(esdp, thr_prgr_active = 1);
+
erts_smp_runq_lock(esdp->run_queue);
non_empty_runq(esdp->run_queue);
@@ -3239,7 +3996,7 @@ do { \
(RQ)->flags |= (ERTS_RUNQ_FLG_OUT_OF_WORK \
| ERTS_RUNQ_FLG_HALFTIME_OUT_OF_WORK); \
(RQ)->check_balance_reds = ERTS_RUNQ_CALL_CHECK_BALANCE_REDS; \
- erts_smp_atomic32_band(&(RQ)->info_flags, ~ERTS_RUNQ_IFLG_SUSPENDED);\
+ erts_smp_atomic32_read_band_nob(&(RQ)->info_flags, ~ERTS_RUNQ_IFLG_SUSPENDED);\
for (pix__ = 0; pix__ < ERTS_NO_PROC_PRIO_LEVELS; pix__++) { \
(RQ)->procs.prio_info[pix__].max_len = 0; \
(RQ)->procs.prio_info[pix__].reds = 0; \
@@ -3283,7 +4040,7 @@ erts_schedulers_state(Uint *total,
int res;
erts_aint32_t changing;
erts_smp_mtx_lock(&schdlr_sspnd.mtx);
- changing = erts_smp_atomic32_read(&schdlr_sspnd.changing);
+ changing = erts_smp_atomic32_read_nob(&schdlr_sspnd.changing);
if (yield_allowed && (changing & ~ERTS_SCHDLR_SSPND_CHNG_WAITER))
res = ERTS_SCHDLR_SSPND_YIELD_RESTART;
else {
@@ -3303,18 +4060,22 @@ erts_set_schedulers_online(Process *p,
Sint new_no,
Sint *old_no)
{
- int ix, res, no, have_unlocked_plocks;
+ ErtsSchedulerData *esdp;
+ int ix, res, no, have_unlocked_plocks, end_wait;
erts_aint32_t changing;
if (new_no < 1 || erts_no_schedulers < new_no)
return ERTS_SCHDLR_SSPND_EINVAL;
+ esdp = ERTS_PROC_GET_SCHDATA(p);
+ end_wait = 0;
+
erts_smp_mtx_lock(&schdlr_sspnd.mtx);
have_unlocked_plocks = 0;
no = (int) new_no;
- changing = erts_smp_atomic32_read(&schdlr_sspnd.changing);
+ changing = erts_smp_atomic32_read_nob(&schdlr_sspnd.changing);
if (changing) {
res = ERTS_SCHDLR_SSPND_YIELD_RESTART;
}
@@ -3389,8 +4150,8 @@ erts_set_schedulers_online(Process *p,
for (ix = no; ix < online; ix++) {
ErtsSchedulerSleepInfo *ssi;
ssi = ERTS_SCHED_SLEEP_INFO_IX(ix);
- erts_smp_atomic32_bor(&ssi->flags,
- ERTS_SSI_FLG_SUSPENDED);
+ erts_smp_atomic32_read_bor_nob(&ssi->flags,
+ ERTS_SSI_FLG_SUSPENDED);
}
wake_all_schedulers();
}
@@ -3425,27 +4186,37 @@ erts_set_schedulers_online(Process *p,
}
}
- erts_smp_activity_begin(ERTS_ACTIVITY_WAIT,
- susp_sched_prep_block,
- susp_sched_resume_block,
- NULL);
+ if (schdlr_sspnd.curr_online != schdlr_sspnd.wait_curr_online) {
+ erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
+ if (plocks && !have_unlocked_plocks) {
+ have_unlocked_plocks = 1;
+ erts_smp_proc_unlock(p, plocks);
+ }
+ erts_thr_progress_active(esdp, 0);
+ erts_thr_progress_prepare_wait(esdp);
+ end_wait = 1;
+ erts_smp_mtx_lock(&schdlr_sspnd.mtx);
+ }
+
while (schdlr_sspnd.curr_online != schdlr_sspnd.wait_curr_online)
erts_smp_cnd_wait(&schdlr_sspnd.cnd, &schdlr_sspnd.mtx);
- erts_smp_activity_end(ERTS_ACTIVITY_WAIT,
- susp_sched_prep_block,
- susp_sched_resume_block,
- NULL);
+
ASSERT(res != ERTS_SCHDLR_SSPND_DONE
? (ERTS_SCHDLR_SSPND_CHNG_WAITER
- & erts_smp_atomic32_read(&schdlr_sspnd.changing))
+ & erts_smp_atomic32_read_nob(&schdlr_sspnd.changing))
: (ERTS_SCHDLR_SSPND_CHNG_WAITER
- == erts_smp_atomic32_read(&schdlr_sspnd.changing)));
- erts_smp_atomic32_band(&schdlr_sspnd.changing,
- ~ERTS_SCHDLR_SSPND_CHNG_WAITER);
+ == erts_smp_atomic32_read_nob(&schdlr_sspnd.changing)));
+ erts_smp_atomic32_read_band_nob(&schdlr_sspnd.changing,
+ ~ERTS_SCHDLR_SSPND_CHNG_WAITER);
+
}
}
erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
+ if (end_wait) {
+ erts_thr_progress_finalize_wait(esdp);
+ erts_thr_progress_active(esdp, 1);
+ }
if (have_unlocked_plocks)
erts_smp_proc_lock(p, plocks);
@@ -3460,7 +4231,7 @@ erts_block_multi_scheduling(Process *p, ErtsProcLocks plocks, int on, int all)
ErtsProcList *plp;
erts_smp_mtx_lock(&schdlr_sspnd.mtx);
- changing = erts_smp_atomic32_read(&schdlr_sspnd.changing);
+ changing = erts_smp_atomic32_read_nob(&schdlr_sspnd.changing);
if (changing) {
res = ERTS_SCHDLR_SSPND_YIELD_RESTART; /* Yield */
}
@@ -3470,7 +4241,7 @@ erts_block_multi_scheduling(Process *p, ErtsProcLocks plocks, int on, int all)
plp->next = schdlr_sspnd.msb.procs;
schdlr_sspnd.msb.procs = plp;
p->flags |= F_HAVE_BLCKD_MSCHED;
- ASSERT(erts_smp_atomic32_read(&schdlr_sspnd.active) == 1);
+ ASSERT(erts_smp_atomic32_read_nob(&schdlr_sspnd.active) == 1);
ASSERT(p->scheduler_data->no == 1);
res = ERTS_SCHDLR_SSPND_DONE_MSCHED_BLOCKED;
}
@@ -3481,11 +4252,11 @@ erts_block_multi_scheduling(Process *p, ErtsProcLocks plocks, int on, int all)
have_unlocked_plocks = 1;
erts_smp_proc_unlock(p, plocks);
}
- ASSERT(0 == erts_smp_atomic32_read(&schdlr_sspnd.msb.ongoing));
- erts_smp_atomic32_set(&schdlr_sspnd.msb.ongoing, 1);
+ ASSERT(!ongoing_multi_scheduling_block());
+ schdlr_sspnd.msb.ongoing = 1;
if (online == 1) {
res = ERTS_SCHDLR_SSPND_DONE_MSCHED_BLOCKED;
- ASSERT(erts_smp_atomic32_read(&schdlr_sspnd.active) == 1);
+ ASSERT(erts_smp_atomic32_read_nob(&schdlr_sspnd.active) == 1);
ASSERT(p->scheduler_data->no == 1);
}
else {
@@ -3505,8 +4276,8 @@ erts_block_multi_scheduling(Process *p, ErtsProcLocks plocks, int on, int all)
}
if (erts_common_run_queue) {
for (ix = 1; ix < online; ix++)
- erts_smp_atomic32_bor(&ERTS_SCHED_SLEEP_INFO_IX(ix)->flags,
- ERTS_SSI_FLG_SUSPENDED);
+ erts_smp_atomic32_read_bor_nob(&ERTS_SCHED_SLEEP_INFO_IX(ix)->flags,
+ ERTS_SSI_FLG_SUSPENDED);
wake_all_schedulers();
}
else {
@@ -3530,24 +4301,45 @@ erts_block_multi_scheduling(Process *p, ErtsProcLocks plocks, int on, int all)
erts_smp_mtx_unlock(&balance_info.update_mtx);
erts_smp_mtx_lock(&schdlr_sspnd.mtx);
}
- erts_smp_activity_begin(ERTS_ACTIVITY_WAIT,
- susp_sched_prep_block,
- susp_sched_resume_block,
- NULL);
- while (erts_smp_atomic32_read(&schdlr_sspnd.active)
- != schdlr_sspnd.msb.wait_active)
- erts_smp_cnd_wait(&schdlr_sspnd.cnd, &schdlr_sspnd.mtx);
- erts_smp_activity_end(ERTS_ACTIVITY_WAIT,
- susp_sched_prep_block,
- susp_sched_resume_block,
- NULL);
+
+ if (erts_smp_atomic32_read_nob(&schdlr_sspnd.active)
+ != schdlr_sspnd.msb.wait_active) {
+ ErtsSchedulerData *esdp;
+
+ erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
+
+ if (plocks && !have_unlocked_plocks) {
+ have_unlocked_plocks = 1;
+ erts_smp_proc_unlock(p, plocks);
+ }
+
+ esdp = ERTS_PROC_GET_SCHDATA(p);
+
+ erts_thr_progress_active(esdp, 0);
+ erts_thr_progress_prepare_wait(esdp);
+
+ erts_smp_mtx_lock(&schdlr_sspnd.mtx);
+
+ while (erts_smp_atomic32_read_nob(&schdlr_sspnd.active)
+ != schdlr_sspnd.msb.wait_active)
+ erts_smp_cnd_wait(&schdlr_sspnd.cnd,
+ &schdlr_sspnd.mtx);
+
+ erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
+
+ erts_thr_progress_active(esdp, 1);
+ erts_thr_progress_finalize_wait(esdp);
+
+ erts_smp_mtx_lock(&schdlr_sspnd.mtx);
+
+ }
ASSERT(res != ERTS_SCHDLR_SSPND_DONE_MSCHED_BLOCKED
? (ERTS_SCHDLR_SSPND_CHNG_WAITER
- & erts_smp_atomic32_read(&schdlr_sspnd.changing))
+ & erts_smp_atomic32_read_nob(&schdlr_sspnd.changing))
: (ERTS_SCHDLR_SSPND_CHNG_WAITER
- == erts_smp_atomic32_read(&schdlr_sspnd.changing)));
- erts_smp_atomic32_band(&schdlr_sspnd.changing,
- ~ERTS_SCHDLR_SSPND_CHNG_WAITER);
+ == erts_smp_atomic32_read_nob(&schdlr_sspnd.changing)));
+ erts_smp_atomic32_read_band_nob(&schdlr_sspnd.changing,
+ ~ERTS_SCHDLR_SSPND_CHNG_WAITER);
}
plp = proclist_create(p);
plp->next = schdlr_sspnd.msb.procs;
@@ -3614,16 +4406,16 @@ erts_block_multi_scheduling(Process *p, ErtsProcLocks plocks, int on, int all)
});
#endif
p->flags &= ~F_HAVE_BLCKD_MSCHED;
- erts_smp_atomic32_set(&schdlr_sspnd.msb.ongoing, 0);
+ schdlr_sspnd.msb.ongoing = 0;
if (schdlr_sspnd.online == 1) {
/* No schedulers to resume */
- ASSERT(erts_smp_atomic32_read(&schdlr_sspnd.active) == 1);
+ ASSERT(erts_smp_atomic32_read_nob(&schdlr_sspnd.active) == 1);
ERTS_SCHDLR_SSPND_CHNG_SET(0, ERTS_SCHDLR_SSPND_CHNG_MSB);
}
else if (erts_common_run_queue) {
for (ix = 1; ix < schdlr_sspnd.online; ix++)
- erts_smp_atomic32_band(&ERTS_SCHED_SLEEP_INFO_IX(ix)->flags,
- ~ERTS_SSI_FLG_SUSPENDED);
+ erts_smp_atomic32_read_band_nob(&ERTS_SCHED_SLEEP_INFO_IX(ix)->flags,
+ ~ERTS_SSI_FLG_SUSPENDED);
wake_all_schedulers();
}
else {
@@ -3673,7 +4465,7 @@ void
erts_dbg_multi_scheduling_return_trap(Process *p, Eterm return_value)
{
if (return_value == am_blocked) {
- erts_aint32_t active = erts_smp_atomic32_read(&schdlr_sspnd.active);
+ erts_aint32_t active = erts_smp_atomic32_read_nob(&schdlr_sspnd.active);
ASSERT(1 <= active && active <= 2);
ASSERT(ERTS_PROC_GET_SCHDATA(p)->no == 1);
}
@@ -3728,8 +4520,19 @@ erts_multi_scheduling_blockers(Process *p)
static void *
sched_thread_func(void *vesdp)
{
+ ErtsThrPrgrCallbacks callbacks;
+ ErtsSchedulerData *esdp = vesdp;
+ Uint no = esdp->no;
#ifdef ERTS_SMP
- Uint no = ((ErtsSchedulerData *) vesdp)->no;
+ ERTS_SCHED_SLEEP_INFO_IX(no - 1)->event = erts_tse_fetch();
+ callbacks.arg = (void *) esdp->ssi;
+ callbacks.wakeup = thr_prgr_wakeup;
+ callbacks.prepare_wait = thr_prgr_prep_wait;
+ callbacks.wait = thr_prgr_wait;
+ callbacks.finalize_wait = thr_prgr_fin_wait;
+
+ erts_thr_progress_register_managed_thread(esdp, &callbacks, 0);
+ erts_alloc_register_scheduler(vesdp);
#endif
#ifdef ERTS_ENABLE_LOCK_CHECK
{
@@ -3738,65 +4541,71 @@ sched_thread_func(void *vesdp)
erts_lc_set_thread_name(&buf[0]);
}
#endif
- erts_alloc_reg_scheduler_id(no);
erts_tsd_set(sched_data_key, vesdp);
#ifdef ERTS_SMP
+#if HAVE_ERTS_MSEG
+ erts_mseg_late_init();
+#endif
+#if ERTS_USE_ASYNC_READY_Q
+ esdp->aux_work_data.async_ready.queue = erts_get_async_ready_queue(no);
+#endif
- erts_sched_init_check_cpu_bind((ErtsSchedulerData *) vesdp);
+ erts_sched_init_check_cpu_bind(esdp);
erts_proc_lock_prepare_proc_lock_waiter();
- ERTS_SCHED_SLEEP_INFO_IX(no - 1)->event = erts_tse_fetch();
-
-
#endif
- erts_register_blockable_thread();
+
#ifdef HIPE
hipe_thread_signal_init();
#endif
erts_thread_init_float();
+
+ if (no == 1) {
+ erts_thr_progress_active(esdp, 0);
+ erts_thr_progress_prepare_wait(esdp);
+ }
+
erts_smp_mtx_lock(&schdlr_sspnd.mtx);
- ASSERT(erts_smp_atomic32_read(&schdlr_sspnd.changing)
+ ASSERT(erts_smp_atomic32_read_nob(&schdlr_sspnd.changing)
& ERTS_SCHDLR_SSPND_CHNG_ONLN);
if (--schdlr_sspnd.curr_online == schdlr_sspnd.wait_curr_online) {
- erts_smp_atomic32_band(&schdlr_sspnd.changing,
- ~ERTS_SCHDLR_SSPND_CHNG_ONLN);
- if (((ErtsSchedulerData *) vesdp)->no != 1)
+ erts_smp_atomic32_read_band_nob(&schdlr_sspnd.changing,
+ ~ERTS_SCHDLR_SSPND_CHNG_ONLN);
+ if (no != 1)
erts_smp_cnd_signal(&schdlr_sspnd.cnd);
}
- if (((ErtsSchedulerData *) vesdp)->no == 1) {
- if (schdlr_sspnd.curr_online != schdlr_sspnd.wait_curr_online) {
- erts_smp_activity_begin(ERTS_ACTIVITY_WAIT,
- susp_sched_prep_block,
- susp_sched_resume_block,
- NULL);
- while (schdlr_sspnd.curr_online != schdlr_sspnd.wait_curr_online)
- erts_smp_cnd_wait(&schdlr_sspnd.cnd, &schdlr_sspnd.mtx);
- erts_smp_activity_end(ERTS_ACTIVITY_WAIT,
- susp_sched_prep_block,
- susp_sched_resume_block,
- NULL);
- }
+ if (no == 1) {
+ while (schdlr_sspnd.curr_online != schdlr_sspnd.wait_curr_online)
+ erts_smp_cnd_wait(&schdlr_sspnd.cnd, &schdlr_sspnd.mtx);
ERTS_SCHDLR_SSPND_CHNG_SET(0, ERTS_SCHDLR_SSPND_CHNG_WAITER);
}
erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
+ if (no == 1) {
+ erts_thr_progress_finalize_wait(esdp);
+ erts_thr_progress_active(esdp, 1);
+ }
+
#ifdef ERTS_DO_VERIFY_UNUSED_TEMP_ALLOC
- ((ErtsSchedulerData *) vesdp)->verify_unused_temp_alloc
+ esdp->verify_unused_temp_alloc
= erts_alloc_get_verify_unused_temp_alloc(
- &((ErtsSchedulerData *) vesdp)->verify_unused_temp_alloc_data);
+ &esdp->verify_unused_temp_alloc_data);
ERTS_VERIFY_UNUSED_TEMP_ALLOC(NULL);
#endif
process_main();
/* No schedulers should *ever* terminate */
- erl_exit(ERTS_ABORT_EXIT, "Scheduler thread number %beu terminated\n",
- ((ErtsSchedulerData *) vesdp)->no);
+ erl_exit(ERTS_ABORT_EXIT,
+ "Scheduler thread number %beu terminated\n",
+ no);
return NULL;
}
+static ethr_tid aux_tid;
+
void
erts_start_schedulers(void)
{
@@ -3816,8 +4625,6 @@ erts_start_schedulers(void)
res = ENOTSUP;
}
- erts_block_system(0);
-
while (actual < wanted) {
ErtsSchedulerData *esdp = ERTS_SCHEDULER_IX(actual);
actual++;
@@ -3830,7 +4637,12 @@ erts_start_schedulers(void)
}
erts_no_schedulers = actual;
- erts_release_system();
+
+ ERTS_THR_MEMORY_BARRIER;
+
+ res = ethr_thr_create(&aux_tid, aux_thread, NULL, &opts);
+ if (res != 0)
+ erl_exit(1, "Failed to create aux thread\n");
if (actual < 1)
erl_exit(1,
@@ -5191,7 +6003,7 @@ Process *schedule(Process *p, int calls)
input_reductions = INPUT_REDUCTIONS;
}
- ERTS_SMP_LC_ASSERT(!ERTS_LC_IS_BLOCKING);
+ ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking());
/*
* Clean up after the process being scheduled out.
@@ -5218,7 +6030,7 @@ Process *schedule(Process *p, int calls)
reds = ERTS_PROC_MIN_CONTEXT_SWITCH_REDS_COST;
esdp->virtual_reds = 0;
- fcalls = (int) erts_smp_atomic32_addtest(&function_calls, reds);
+ fcalls = (int) erts_smp_atomic32_add_read_acqb(&function_calls, reds);
ASSERT(esdp && esdp == erts_get_scheduler_data());
rq = erts_get_runq_current(esdp);
@@ -5329,7 +6141,8 @@ Process *schedule(Process *p, int calls)
}
- ERTS_SMP_LC_ASSERT(!ERTS_LC_IS_BLOCKING);
+ ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking());
+
check_activities_to_run: {
#ifdef ERTS_SMP
@@ -5339,7 +6152,7 @@ Process *schedule(Process *p, int calls)
check_balance(rq);
}
- ERTS_SMP_LC_ASSERT(!ERTS_LC_IS_BLOCKING);
+ ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking());
ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(rq));
if (rq->flags & ERTS_RUNQ_FLGS_IMMIGRATE_QMASK)
@@ -5353,7 +6166,7 @@ Process *schedule(Process *p, int calls)
if ((rq->flags & ERTS_RUNQ_FLG_SUSPENDED)
|| (erts_smp_atomic32_read_acqb(&esdp->ssi->flags)
& ERTS_SSI_FLG_SUSPENDED)) {
- ASSERT(erts_smp_atomic32_read(&esdp->ssi->flags)
+ ASSERT(erts_smp_atomic32_read_nob(&esdp->ssi->flags)
& ERTS_SSI_FLG_SUSPENDED);
suspend_scheduler(esdp);
}
@@ -5363,42 +6176,38 @@ Process *schedule(Process *p, int calls)
}
}
-#if defined(ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK) \
- || defined(ERTS_SCHED_NEED_NONBLOCKABLE_AUX_WORK)
{
- ErtsSchedulerSleepInfo *ssi = esdp->ssi;
- erts_aint32_t aux_work = erts_smp_atomic32_read(&ssi->aux_work);
- if (aux_work) {
+ erts_aint32_t aux_work;
+ int leader_update = erts_thr_progress_update(esdp);
+ aux_work = erts_atomic32_read_acqb(&esdp->ssi->aux_work);
+ if (aux_work | leader_update) {
erts_smp_runq_unlock(rq);
-#ifdef ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK
- aux_work = blockable_aux_work(esdp, ssi, aux_work);
-#endif
-#ifdef ERTS_SCHED_NEED_NONBLOCKABLE_AUX_WORK
- nonblockable_aux_work(esdp, ssi, aux_work);
-#endif
+ if (leader_update)
+ erts_thr_progress_leader_update(esdp);
+ if (aux_work)
+ handle_aux_work(&esdp->aux_work_data, aux_work);
erts_smp_runq_lock(rq);
}
}
-#endif
-
- erts_smp_chk_system_block(prepare_for_block,
- resume_after_block,
- (void *) rq);
- ERTS_SMP_LC_ASSERT(!ERTS_LC_IS_BLOCKING);
+ ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking());
ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(rq));
-#endif
+#else /* ERTS_SMP */
+ {
+ erts_aint32_t aux_work;
+ aux_work = erts_atomic32_read_acqb(&esdp->ssi->aux_work);
+ if (aux_work)
+ handle_aux_work(&esdp->aux_work_data, aux_work);
+ }
+#endif /* ERTS_SMP */
ASSERT(rq->len == rq->procs.len + rq->ports.info.len);
-#ifndef ERTS_SMP
+ if (rq->len == 0 && !rq->misc.start) {
- if (rq->len == 0 && !rq->misc.start)
- goto do_sys_schedule;
+#ifdef ERTS_SMP
-#else /* ERTS_SMP */
- if (rq->len == 0 && !rq->misc.start) {
ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(rq));
rq->wakeup_other = 0;
@@ -5411,7 +6220,7 @@ Process *schedule(Process *p, int calls)
if ((rq->flags & ERTS_RUNQ_FLG_SUSPENDED)
|| (erts_smp_atomic32_read_acqb(&esdp->ssi->flags)
& ERTS_SSI_FLG_SUSPENDED)) {
- ASSERT(erts_smp_atomic32_read(&esdp->ssi->flags)
+ ASSERT(erts_smp_atomic32_read_nob(&esdp->ssi->flags)
& ERTS_SSI_FLG_SUSPENDED);
non_empty_runq(rq);
goto continue_check_activities_to_run;
@@ -5429,26 +6238,17 @@ Process *schedule(Process *p, int calls)
}
}
+#endif
+
scheduler_wait(&fcalls, esdp, rq);
+#ifdef ERTS_SMP
non_empty_runq(rq);
+#endif
goto check_activities_to_run;
}
- else
-#endif /* ERTS_SMP */
- if (fcalls > input_reductions && prepare_for_sys_schedule()) {
- int runnable;
-
-#ifdef ERTS_SMP
- runnable = 1;
-#else
- do_sys_schedule:
- runnable = rq->len != 0;
- if (!runnable)
- sched_waiting_sys(esdp->no, rq);
-#endif
-
+ else if (fcalls > input_reductions && prepare_for_sys_schedule()) {
/*
* Schedule system-level activities.
*/
@@ -5458,11 +6258,11 @@ Process *schedule(Process *p, int calls)
ASSERT(!erts_port_task_have_outstanding_io_tasks());
-#ifdef ERTS_SMP
- /* erts_sys_schedule_interrupt(0); */
+#if 0 /* Not needed since we wont wait in sys schedule */
+ erts_sys_schedule_interrupt(0);
#endif
erts_smp_runq_unlock(rq);
- erl_sys_schedule(runnable);
+ erl_sys_schedule(1);
dt = erts_do_time_read_and_reset();
if (dt) erts_bump_timer(dt);
#ifdef ERTS_SMP
@@ -5470,8 +6270,6 @@ Process *schedule(Process *p, int calls)
clear_sys_scheduling();
goto continue_check_activities_to_run;
#else
- if (!runnable)
- sched_active_sys(esdp->no, rq);
goto check_activities_to_run;
#endif
}
@@ -5719,14 +6517,14 @@ erts_sched_stat_modify(int what)
int ix;
switch (what) {
case ERTS_SCHED_STAT_MODIFY_ENABLE:
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
erts_sched_stat.enabled = 1;
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
break;
case ERTS_SCHED_STAT_MODIFY_DISABLE:
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
erts_sched_stat.enabled = 1;
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
break;
case ERTS_SCHED_STAT_MODIFY_CLEAR:
erts_smp_spin_lock(&erts_sched_stat.lock);
@@ -5786,18 +6584,10 @@ erts_sched_stat_term(Process *p, int total)
void
erts_schedule_misc_op(void (*func)(void *), void *arg)
{
- ErtsRunQueue *rq = erts_get_runq_current(NULL);
+ ErtsSchedulerData *esdp = erts_get_scheduler_data();
+ ErtsRunQueue *rq = esdp ? esdp->run_queue : ERTS_RUNQ_IX(0);
ErtsMiscOpList *molp = misc_op_list_alloc();
- if (!rq) {
- /*
- * This can only happen when the sys msg dispatcher
- * thread schedules misc ops (this happens *very*
- * seldom; only when trace drivers are unloaded).
- */
- rq = ERTS_RUNQ_IX(0);
- }
-
erts_smp_runq_lock(rq);
while (rq->misc.evac_runq) {
@@ -5889,7 +6679,7 @@ erts_get_exact_total_reductions(Process *c_p, Uint *redsp, Uint *diffp)
* Wait for other schedulers to schedule out their processes
* and update 'reductions'.
*/
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
for (reds = 0, ix = 0; ix < erts_no_run_queues; ix++)
reds += ERTS_RUNQ_IX(ix)->procs.reductions;
if (redsp)
@@ -5897,7 +6687,7 @@ erts_get_exact_total_reductions(Process *c_p, Uint *redsp, Uint *diffp)
if (diffp)
*diffp = reds - last_exact_reductions;
last_exact_reductions = reds;
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_MAIN);
}
@@ -5952,7 +6742,7 @@ erts_test_next_pid(int set, Uint next)
Uint erts_process_count(void)
{
- erts_aint32_t res = erts_smp_atomic32_read(&process_count);
+ erts_aint32_t res = erts_smp_atomic32_read_nob(&process_count);
ASSERT(res >= 0);
return (Uint) res;
}
@@ -6001,7 +6791,7 @@ alloc_process(void)
ASSERT(!process_tab[p_next]);
process_tab[p_next] = p;
- erts_smp_atomic32_inc(&process_count);
+ erts_smp_atomic32_inc_nob(&process_count);
p->id = make_internal_pid(p_serial << p_serial_shift | p_next);
if (p->id == ERTS_INVALID_PID) {
/* Do not use the invalid pid; change serial */
@@ -6127,7 +6917,7 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
p->min_heap_size = H_MIN_SIZE;
p->min_vheap_size = BIN_VH_MIN_SIZE;
p->prio = PRIORITY_NORMAL;
- p->max_gen_gcs = (Uint16) erts_smp_atomic32_read(&erts_max_gen_gcs);
+ p->max_gen_gcs = (Uint16) erts_smp_atomic32_read_nob(&erts_max_gen_gcs);
}
p->skipped = 0;
ASSERT(p->min_heap_size == erts_next_heap_size(p->min_heap_size, 0));
@@ -7584,8 +8374,8 @@ continue_exit_process(Process *p
p->status_flags = 0;
#endif
process_tab[pix] = NULL; /* Time of death! */
- ASSERT(erts_smp_atomic32_read(&process_count) > 0);
- erts_smp_atomic32_dec(&process_count);
+ ASSERT(erts_smp_atomic32_read_nob(&process_count) > 0);
+ erts_smp_atomic32_dec_nob(&process_count);
#ifdef ERTS_SMP
erts_pix_unlock(pix_lock);
@@ -8702,6 +9492,22 @@ init_processes_bif(void)
* Debug stuff
*/
+#if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK)
+int
+erts_dbg_check_halloc_lock(Process *p)
+{
+ if (ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(p))
+ return 1;
+ if (p->id == ERTS_INVALID_PID)
+ return 1;
+ if (p->scheduler_data && p == p->scheduler_data->match_pseudo_process)
+ return 1;
+ if (erts_thr_progress_is_blocking())
+ return 1;
+ return 0;
+}
+#endif
+
Eterm
erts_debug_processes(Process *c_p)
{
diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h
index c7d89d3bb3..f0c86a0851 100644
--- a/erts/emulator/beam/erl_process.h
+++ b/erts/emulator/beam/erl_process.h
@@ -53,11 +53,18 @@ typedef struct process Process;
#include "erl_time.h"
#include "erl_atom_table.h"
#include "external.h"
+#include "erl_mseg.h"
+#include "erl_async.h"
#ifdef HIPE
#include "hipe_process.h"
#endif
+#undef ERL_THR_PROGRESS_TSD_TYPE_ONLY
+#define ERL_THR_PROGRESS_TSD_TYPE_ONLY
+#include "erl_thr_progress.h"
+#undef ERL_THR_PROGRESS_TSD_TYPE_ONLY
+
struct ErtsNodesMonitor_;
struct port;
@@ -243,16 +250,25 @@ typedef enum {
| ERTS_SSI_FLG_WAITING \
| ERTS_SSI_FLG_SUSPENDED)
-#define ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK
-
-#define ERTS_SSI_AUX_WORK_CHECK_CHILDREN (((erts_aint32_t) 1) << 0)
-#define ERTS_SSI_AUX_WORK_MISC (((erts_aint32_t) 1) << 1)
+#define ERTS_SSI_AUX_WORK_SET_TMO (((erts_aint32_t) 1) << 0)
+#define ERTS_SSI_AUX_WORK_CHECK_CHILDREN (((erts_aint32_t) 1) << 1)
+#define ERTS_SSI_AUX_WORK_MISC (((erts_aint32_t) 1) << 2)
+#ifdef ERTS_SMP
+#define ERTS_SSI_AUX_WORK_MISC_THR_PRGR (((erts_aint32_t) 1) << 3)
+#endif
+#define ERTS_SSI_AUX_WORK_FIX_ALLOC_LOWER_LIM (((erts_aint32_t) 1) << 4)
+#define ERTS_SSI_AUX_WORK_FIX_ALLOC_DEALLOC (((erts_aint32_t) 1) << 5)
+#define ERTS_SSI_AUX_WORK_ASYNC_READY (((erts_aint32_t) 1) << 6)
+#define ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN (((erts_aint32_t) 1) << 7)
+#ifdef ERTS_SMP
+#define ERTS_SSI_AUX_WORK_DD (((erts_aint32_t) 1) << 8)
+#define ERTS_SSI_AUX_WORK_DD_THR_PRGR (((erts_aint32_t) 1) << 9)
+#endif
+#define ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK (((erts_aint32_t) 1) << 10)
-#define ERTS_SSI_BLOCKABLE_AUX_WORK_MASK \
- (ERTS_SSI_AUX_WORK_CHECK_CHILDREN \
- | ERTS_SSI_AUX_WORK_MISC)
-#define ERTS_SSI_NONBLOCKABLE_AUX_WORK_MASK \
- (0)
+#if !HAVE_ERTS_MSEG
+# undef ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK
+#endif
typedef struct ErtsSchedulerSleepInfo_ ErtsSchedulerSleepInfo;
@@ -262,11 +278,13 @@ typedef struct {
} ErtsSchedulerSleepList;
struct ErtsSchedulerSleepInfo_ {
+#ifdef ERTS_SMP
ErtsSchedulerSleepInfo *next;
ErtsSchedulerSleepInfo *prev;
erts_smp_atomic32_t flags;
erts_tse_t *event;
- erts_smp_atomic32_t aux_work;
+#endif
+ erts_atomic32_t aux_work;
};
/* times to reschedule low prio process before running */
@@ -387,25 +405,49 @@ do { \
(RQ)->wakeup_other_reds += (REDS); \
} while (0)
-struct ErtsSchedulerData_ {
-
+typedef struct {
+ int sched_id;
+ ErtsSchedulerData *esdp;
+ ErtsSchedulerSleepInfo *ssi;
+ struct {
+ int ix;
#ifdef ERTS_SMP
+ ErtsThrPrgrVal thr_prgr;
+#endif
+ } misc;
+#ifdef ERTS_SMP
+ struct {
+ ErtsThrPrgrVal thr_prgr;
+ void (*completed_callback)(void *);
+ void (*completed_arg)(void *);
+ } dd;
+#endif
+#ifdef ERTS_USE_ASYNC_READY_Q
+ struct {
+#ifdef ERTS_SMP
+ int need_thr_prgr;
+ ErtsThrPrgrVal thr_prgr;
+#endif
+ void *queue;
+ } async_ready;
+#endif
+} ErtsAuxWorkData;
+
+struct ErtsSchedulerData_ {
/*
* Keep X registers first (so we get as many low
* numbered registers as possible in the same cache
* line).
*/
-#if !HALFWORD_HEAP
- Eterm save_reg[ERTS_X_REGS_ALLOCATED]; /* X registers */
-#else
- Eterm *save_reg;
-#endif
- FloatDef freg[MAX_REG]; /* Floating point registers. */
+ Eterm* x_reg_array; /* X registers */
+ FloatDef* f_reg_array; /* Floating point registers. */
+
+#ifdef ERTS_SMP
ethr_tid tid; /* Thread id */
struct erl_bits_state erl_bits_state; /* erl_bits.c state */
void *match_pseudo_process; /* erl_db_util.c:db_prog_match() */
- ErtsSchedulerSleepInfo *ssi;
Process *free_process;
+ ErtsThrPrgrData thr_progress_data;
#endif
#if !HEAP_ON_C_STACK
Eterm tmp_heap[TMP_HEAP_SIZE];
@@ -414,16 +456,19 @@ struct ErtsSchedulerData_ {
Eterm cmp_tmp_heap[CMP_TMP_HEAP_SIZE];
Eterm erl_arith_tmp_heap[ERL_ARITH_TMP_HEAP_SIZE];
#endif
-
+ ErtsSchedulerSleepInfo *ssi;
Process *current_process;
Uint no; /* Scheduler number */
struct port *current_port;
ErtsRunQueue *run_queue;
int virtual_reds;
int cpu_id; /* >= 0 when bound */
+ ErtsAuxWorkData aux_work_data;
ErtsAtomCacheMap atom_cache_map;
+ ErtsSchedAllocData alloc_data;
+
#ifdef ERTS_SMP
/* NOTE: These fields are modified under held mutexes by other threads */
erts_smp_atomic32_t chk_cpu_bind; /* Only used when common run queue */
@@ -1033,7 +1078,7 @@ extern struct erts_system_profile_flags_t erts_system_profile_flags;
void erts_pre_init_process(void);
void erts_late_init_process(void);
-void erts_early_init_scheduling(void);
+void erts_early_init_scheduling(int);
void erts_init_scheduling(int, int, int);
ErtsProcList *erts_proclist_create(Process *);
@@ -1042,6 +1087,9 @@ int erts_proclist_same(ErtsProcList *, Process *);
int erts_sched_set_wakeup_limit(char *str);
+#if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK)
+int erts_dbg_check_halloc_lock(Process *p);
+#endif
#ifdef DEBUG
void erts_dbg_multi_scheduling_return_trap(Process *, Eterm);
#endif
@@ -1059,13 +1107,20 @@ erts_block_multi_scheduling(Process *, ErtsProcLocks, int, int);
int erts_is_multi_scheduling_blocked(void);
Eterm erts_multi_scheduling_blockers(Process *);
void erts_start_schedulers(void);
+void erts_alloc_notify_delayed_dealloc(int);
void erts_smp_notify_check_children_needed(void);
-void
-erts_smp_schedule_misc_aux_work(int ignore_self,
- int max_sched,
- void (*func)(void *),
- void *arg);
#endif
+#if ERTS_USE_ASYNC_READY_Q
+void erts_notify_check_async_ready_queue(void *);
+#endif
+void erts_schedule_misc_aux_work(int sched_id,
+ void (*func)(void *),
+ void *arg);
+void erts_schedule_multi_misc_aux_work(int ignore_self,
+ int max_sched,
+ void (*func)(void *),
+ void *arg);
+erts_aint32_t erts_set_aux_work_timeout(int, erts_aint32_t, int);
void erts_sched_notify_check_cpu_bind(void);
Uint erts_active_schedulers(void);
void erts_init_process(int);
@@ -1149,6 +1204,7 @@ Sint erts_test_next_pid(int, Uint);
Eterm erts_debug_processes(Process *c_p);
Eterm erts_debug_processes_bif_info(Process *c_p);
Uint erts_debug_nbalance(void);
+int erts_debug_wait_deallocations(Process *c_p);
#ifdef ERTS_SMP
# define ERTS_GET_SCHEDULER_DATA_FROM_PROC(PROC) ((PROC)->scheduler_data)
@@ -1219,16 +1275,11 @@ erts_psd_get(Process *p, int ix)
#if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK)
ErtsProcLocks locks = erts_proc_lc_my_proc_locks(p);
if (ERTS_LC_PSD_ANY_LOCK == erts_psd_required_locks[ix].get_locks)
- ERTS_SMP_LC_ASSERT(locks
- || erts_is_system_blocked(0)
- || (ERTS_IS_CRASH_DUMPING
- && erts_is_system_blocked(ERTS_BS_FLG_ALLOW_GC)));
+ ERTS_SMP_LC_ASSERT(locks || erts_thr_progress_is_blocking());
else {
locks &= erts_psd_required_locks[ix].get_locks;
ERTS_SMP_LC_ASSERT(erts_psd_required_locks[ix].get_locks == locks
- || erts_is_system_blocked(0)
- || (ERTS_IS_CRASH_DUMPING
- && erts_is_system_blocked(ERTS_BS_FLG_ALLOW_GC)));
+ || erts_thr_progress_is_blocking());
}
#endif
ASSERT(0 <= ix && ix < ERTS_PSD_SIZE);
@@ -1245,16 +1296,11 @@ erts_psd_set(Process *p, ErtsProcLocks plocks, int ix, void *data)
#if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK)
ErtsProcLocks locks = erts_proc_lc_my_proc_locks(p);
if (ERTS_LC_PSD_ANY_LOCK == erts_psd_required_locks[ix].set_locks)
- ERTS_SMP_LC_ASSERT(locks
- || erts_is_system_blocked(0)
- || (ERTS_IS_CRASH_DUMPING
- && erts_is_system_blocked(ERTS_BS_FLG_ALLOW_GC)));
+ ERTS_SMP_LC_ASSERT(locks || erts_thr_progress_is_blocking());
else {
locks &= erts_psd_required_locks[ix].set_locks;
ERTS_SMP_LC_ASSERT(erts_psd_required_locks[ix].set_locks == locks
- || erts_is_system_blocked(0)
- || (ERTS_IS_CRASH_DUMPING
- && erts_is_system_blocked(ERTS_BS_FLG_ALLOW_GC)));
+ || erts_thr_progress_is_blocking());
}
#endif
ASSERT(0 <= ix && ix < ERTS_PSD_SIZE);
@@ -1600,11 +1646,9 @@ erts_sched_poke(ErtsSchedulerSleepInfo *ssi)
{
erts_aint32_t flags;
ERTS_THR_MEMORY_BARRIER;
- flags = erts_smp_atomic32_read(&ssi->flags);
- ASSERT(!(flags & ERTS_SSI_FLG_SLEEPING)
- || (flags & ERTS_SSI_FLG_WAITING));
+ flags = erts_smp_atomic32_read_nob(&ssi->flags);
if (flags & ERTS_SSI_FLG_SLEEPING) {
- flags = erts_smp_atomic32_band(&ssi->flags, ~ERTS_SSI_FLGS_SLEEP);
+ flags = erts_smp_atomic32_read_band_nob(&ssi->flags, ~ERTS_SSI_FLGS_SLEEP);
erts_sched_finish_poke(ssi, flags);
}
}
diff --git a/erts/emulator/beam/erl_process_dump.c b/erts/emulator/beam/erl_process_dump.c
index 5410bcd495..3550f1396c 100644
--- a/erts/emulator/beam/erl_process_dump.c
+++ b/erts/emulator/beam/erl_process_dump.c
@@ -350,7 +350,7 @@ heap_dump(int to, void *to_arg, Eterm x)
ProcBin* pb = (ProcBin *) binary_val(x);
Binary* val = pb->val;
- if (erts_smp_atomic_xchg(&val->refc, 0) != 0) {
+ if (erts_smp_atomic_xchg_nob(&val->refc, 0) != 0) {
val->flags = (UWord) all_binaries;
all_binaries = val;
}
diff --git a/erts/emulator/beam/erl_process_lock.c b/erts/emulator/beam/erl_process_lock.c
index 72560aa124..b4d20480c5 100644
--- a/erts/emulator/beam/erl_process_lock.c
+++ b/erts/emulator/beam/erl_process_lock.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2007-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2007-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -316,7 +316,7 @@ try_aquire(erts_proc_lock_t *lck, erts_tse_t *wtr)
break;
}
wflg = lock << ERTS_PROC_LOCK_WAITER_SHIFT;
- old_lflgs = ERTS_PROC_LOCK_FLGS_BOR_(lck, wflg | lock);
+ old_lflgs = ERTS_PROC_LOCK_FLGS_BOR_ACQB_(lck, wflg | lock);
if (old_lflgs & lock) {
/* Didn't get the lock */
goto enqueue;
@@ -413,7 +413,7 @@ transfer_locks(Process *p,
do {
erts_tse_t *tmp = wake;
wake = wake->next;
- erts_atomic32_set(&tmp->uaflgs, 0);
+ erts_atomic32_set_nob(&tmp->uaflgs, 0);
erts_tse_set(tmp);
} while (wake);
@@ -509,14 +509,14 @@ wait_for_locks(Process *p,
ASSERT((wtr->uflgs & ~ERTS_PROC_LOCKS_ALL) == 0);
- erts_atomic32_set(&wtr->uaflgs, 1);
+ erts_atomic32_set_nob(&wtr->uaflgs, 1);
erts_pix_unlock(pix_lock);
while (1) {
int res;
erts_tse_reset(wtr);
- if (erts_atomic32_read(&wtr->uaflgs) == 0)
+ if (erts_atomic32_read_nob(&wtr->uaflgs) == 0)
break;
/*
@@ -669,7 +669,9 @@ proc_safelock(Process *a_proc,
ErtsProcLocks b_need_locks)
{
Process *p1, *p2;
+#ifdef ERTS_ENABLE_LOCK_CHECK
Eterm pid1, pid2;
+#endif
erts_pix_lock_t *pix_lck1, *pix_lck2;
ErtsProcLocks need_locks1, have_locks1, need_locks2, have_locks2;
ErtsProcLocks unlock_mask;
@@ -684,24 +686,32 @@ proc_safelock(Process *a_proc,
if (a_proc) {
if (a_proc->id < b_proc->id) {
p1 = a_proc;
+#ifdef ERTS_ENABLE_LOCK_CHECK
pid1 = a_proc->id;
+#endif
pix_lck1 = a_pix_lck;
need_locks1 = a_need_locks;
have_locks1 = a_have_locks;
p2 = b_proc;
+#ifdef ERTS_ENABLE_LOCK_CHECK
pid2 = b_proc->id;
+#endif
pix_lck2 = b_pix_lck;
need_locks2 = b_need_locks;
have_locks2 = b_have_locks;
}
else if (a_proc->id > b_proc->id) {
p1 = b_proc;
+#ifdef ERTS_ENABLE_LOCK_CHECK
pid1 = b_proc->id;
+#endif
pix_lck1 = b_pix_lck;
need_locks1 = b_need_locks;
have_locks1 = b_have_locks;
p2 = a_proc;
+#ifdef ERTS_ENABLE_LOCK_CHECK
pid2 = a_proc->id;
+#endif
pix_lck2 = a_pix_lck;
need_locks2 = a_need_locks;
have_locks2 = a_have_locks;
@@ -710,12 +720,16 @@ proc_safelock(Process *a_proc,
ERTS_LC_ASSERT(a_proc == b_proc);
ERTS_LC_ASSERT(a_proc->id == b_proc->id);
p1 = a_proc;
+#ifdef ERTS_ENABLE_LOCK_CHECK
pid1 = a_proc->id;
+#endif
pix_lck1 = a_pix_lck;
need_locks1 = a_need_locks | b_need_locks;
have_locks1 = a_have_locks | b_have_locks;
p2 = NULL;
+#ifdef ERTS_ENABLE_LOCK_CHECK
pid2 = 0;
+#endif
pix_lck2 = NULL;
need_locks2 = 0;
have_locks2 = 0;
@@ -723,12 +737,16 @@ proc_safelock(Process *a_proc,
}
else {
p1 = b_proc;
+#ifdef ERTS_ENABLE_LOCK_CHECK
pid1 = b_proc->id;
+#endif
pix_lck1 = b_pix_lck;
need_locks1 = b_need_locks;
have_locks1 = b_have_locks;
p2 = NULL;
+#ifdef ERTS_ENABLE_LOCK_CHECK
pid2 = 0;
+#endif
pix_lck2 = NULL;
need_locks2 = 0;
have_locks2 = 0;
@@ -955,7 +973,8 @@ erts_proc_lock_init(Process *p)
{
/* We always start with all locks locked */
#if ERTS_PROC_LOCK_ATOMIC_IMPL
- erts_smp_atomic32_init(&p->lock.flags, (erts_aint32_t) ERTS_PROC_LOCKS_ALL);
+ erts_smp_atomic32_init_nob(&p->lock.flags,
+ (erts_aint32_t) ERTS_PROC_LOCKS_ALL);
#else
p->lock.flags = ERTS_PROC_LOCKS_ALL;
#endif
@@ -974,7 +993,7 @@ erts_proc_lock_init(Process *p)
{
int i;
for (i = 0; i <= ERTS_PROC_LOCK_MAX_BIT; i++)
- erts_smp_atomic32_init(&p->lock.locked[i], (erts_aint32_t) 1);
+ erts_smp_atomic32_init_nob(&p->lock.locked[i], (erts_aint32_t) 1);
}
#endif
}
diff --git a/erts/emulator/beam/erl_process_lock.h b/erts/emulator/beam/erl_process_lock.h
index 355179f084..97f250138e 100644
--- a/erts/emulator/beam/erl_process_lock.h
+++ b/erts/emulator/beam/erl_process_lock.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2007-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2007-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -41,10 +41,10 @@
#define ERTS_PROC_LOCK_SPINLOCK_IMPL 0
#define ERTS_PROC_LOCK_MUTEX_IMPL 0
-#if defined(ETHR_HAVE_OPTIMIZED_ATOMIC_OPS)
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
# undef ERTS_PROC_LOCK_ATOMIC_IMPL
# define ERTS_PROC_LOCK_ATOMIC_IMPL 1
-#elif defined(ETHR_HAVE_OPTIMIZED_SPINLOCK)
+#elif defined(ETHR_HAVE_NATIVE_SPINLOCKS)
# undef ERTS_PROC_LOCK_SPINLOCK_IMPL
# define ERTS_PROC_LOCK_SPINLOCK_IMPL 1
#else
@@ -270,9 +270,11 @@ typedef struct {
#if ERTS_PROC_LOCK_ATOMIC_IMPL
#define ERTS_PROC_LOCK_FLGS_BAND_(L, MSK) \
- ((ErtsProcLocks) erts_smp_atomic32_band(&(L)->flags, (erts_aint32_t) (MSK)))
-#define ERTS_PROC_LOCK_FLGS_BOR_(L, MSK) \
- ((ErtsProcLocks) erts_smp_atomic32_bor(&(L)->flags, (erts_aint32_t) (MSK)))
+ ((ErtsProcLocks) erts_smp_atomic32_read_band_nob(&(L)->flags, \
+ (erts_aint32_t) (MSK)))
+#define ERTS_PROC_LOCK_FLGS_BOR_ACQB_(L, MSK) \
+ ((ErtsProcLocks) erts_smp_atomic32_read_bor_acqb(&(L)->flags, \
+ (erts_aint32_t) (MSK)))
#define ERTS_PROC_LOCK_FLGS_CMPXCHG_ACQB_(L, NEW, EXPECTED) \
((ErtsProcLocks) erts_smp_atomic32_cmpxchg_acqb(&(L)->flags, \
(erts_aint32_t) (NEW), \
@@ -282,7 +284,7 @@ typedef struct {
(erts_aint32_t) (NEW), \
(erts_aint32_t) (EXPECTED)))
#define ERTS_PROC_LOCK_FLGS_READ_(L) \
- ((ErtsProcLocks) erts_smp_atomic32_read(&(L)->flags))
+ ((ErtsProcLocks) erts_smp_atomic32_read_nob(&(L)->flags))
#else /* no opt atomic ops */
@@ -325,7 +327,7 @@ erts_proc_lock_flags_cmpxchg(erts_proc_lock_t *lck, ErtsProcLocks new,
#endif
#define ERTS_PROC_LOCK_FLGS_BAND_(L, MSK) erts_proc_lock_flags_band((L), (MSK))
-#define ERTS_PROC_LOCK_FLGS_BOR_(L, MSK) erts_proc_lock_flags_bor((L), (MSK))
+#define ERTS_PROC_LOCK_FLGS_BOR_ACQB_(L, MSK) erts_proc_lock_flags_bor((L), (MSK))
#define ERTS_PROC_LOCK_FLGS_CMPXCHG_ACQB_(L, NEW, EXPECTED) \
erts_proc_lock_flags_cmpxchg((L), (NEW), (EXPECTED))
#define ERTS_PROC_LOCK_FLGS_CMPXCHG_RELB_(L, NEW, EXPECTED) \
@@ -623,11 +625,11 @@ erts_proc_lock_op_debug(Process *p, ErtsProcLocks locks, int locked)
if (locks & lock) {
erts_aint32_t lock_count;
if (locked) {
- lock_count = erts_smp_atomic32_inctest(&p->lock.locked[i]);
+ lock_count = erts_smp_atomic32_inc_read_nob(&p->lock.locked[i]);
ERTS_LC_ASSERT(lock_count == 1);
}
else {
- lock_count = erts_smp_atomic32_dectest(&p->lock.locked[i]);
+ lock_count = erts_smp_atomic32_dec_read_nob(&p->lock.locked[i]);
ERTS_LC_ASSERT(lock_count == 0);
}
}
@@ -649,7 +651,7 @@ ERTS_GLB_INLINE int erts_smp_proc_trylock(Process *, ErtsProcLocks);
ERTS_GLB_INLINE void erts_smp_proc_inc_refc(Process *);
ERTS_GLB_INLINE void erts_smp_proc_dec_refc(Process *);
-
+ERTS_GLB_INLINE void erts_smp_proc_add_refc(Process *, Sint32);
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
@@ -735,6 +737,21 @@ ERTS_GLB_INLINE void erts_smp_proc_dec_refc(Process *p)
#endif
}
+ERTS_GLB_INLINE void erts_smp_proc_add_refc(Process *p, Sint32 refc)
+{
+#ifdef ERTS_SMP
+ Process *fp;
+ erts_pix_lock_t *pixlck = ERTS_PID2PIXLOCK(p->id);
+ erts_pix_lock(pixlck);
+ ERTS_LC_ASSERT(p->lock.refc > 0);
+ p->lock.refc += refc;
+ fp = p->lock.refc == 0 ? p : NULL;
+ erts_pix_unlock(pixlck);
+ if (fp)
+ erts_free_proc(fp);
+#endif
+}
+
#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */
#ifdef ERTS_SMP
diff --git a/erts/emulator/beam/erl_sched_spec_pre_alloc.c b/erts/emulator/beam/erl_sched_spec_pre_alloc.c
new file mode 100644
index 0000000000..a7ccea7403
--- /dev/null
+++ b/erts/emulator/beam/erl_sched_spec_pre_alloc.c
@@ -0,0 +1,305 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description: Scheduler specific pre-allocators. Each scheduler
+ * thread allocates memory in its own private chunk of
+ * memory. Memory blocks deallocated by remote
+ * schedulers (or other threads) are passed back to
+ * the chunk owner via a lock-free data structure.
+ *
+ * Author: Rickard Green
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef ERTS_SMP
+
+#include "erl_process.h"
+#include "erl_thr_progress.h"
+
+erts_sspa_data_t *
+erts_sspa_create(size_t blk_sz, int pa_size)
+{
+ erts_sspa_data_t *data;
+ size_t tot_size;
+ size_t chunk_mem_size;
+ char *p;
+ char *chunk_start;
+ int cix;
+ int no_blocks = pa_size;
+ int no_blocks_per_chunk;
+
+ if (erts_no_schedulers == 1)
+ no_blocks_per_chunk = no_blocks;
+ else {
+ int extra = (no_blocks - 1)/4 + 1;
+ if (extra == 0)
+ extra = 1;
+ no_blocks_per_chunk = no_blocks;
+ no_blocks_per_chunk += extra*erts_no_schedulers;
+ no_blocks_per_chunk /= erts_no_schedulers;
+ }
+ no_blocks = no_blocks_per_chunk * erts_no_schedulers;
+ chunk_mem_size = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(erts_sspa_chunk_header_t));
+ chunk_mem_size += blk_sz * no_blocks_per_chunk;
+ chunk_mem_size = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(chunk_mem_size);
+ tot_size = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(erts_sspa_data_t));
+ tot_size += chunk_mem_size*erts_no_schedulers;
+
+ p = erts_alloc_permanent_cache_aligned(ERTS_ALC_T_PRE_ALLOC_DATA, tot_size);
+ data = (erts_sspa_data_t *) p;
+ p += ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(erts_sspa_data_t));
+ chunk_start = p;
+
+ data->chunks_mem_size = chunk_mem_size;
+ data->start = chunk_start;
+ data->end = chunk_start + chunk_mem_size*erts_no_schedulers;
+
+ /* Initialize all chunks */
+ for (cix = 0; cix < erts_no_schedulers; cix++) {
+ erts_sspa_chunk_t *chnk = erts_sspa_cix2chunk(data, cix);
+ erts_sspa_chunk_header_t *chdr = &chnk->aligned.header;
+ erts_sspa_blk_t *blk;
+ int i;
+
+ erts_atomic_init_nob(&chdr->tail.data.last, (erts_aint_t) &chdr->tail.data.marker);
+ erts_atomic_init_nob(&chdr->tail.data.marker.next_atmc, ERTS_AINT_NULL);
+ erts_atomic_init_nob(&chdr->tail.data.um_refc[0], 0);
+ erts_atomic_init_nob(&chdr->tail.data.um_refc[1], 0);
+ erts_atomic32_init_nob(&chdr->tail.data.um_refc_ix, 0);
+
+ chdr->head.no_thr_progress_check = 0;
+ chdr->head.used_marker = 1;
+ chdr->head.first = &chdr->tail.data.marker;
+ chdr->head.unref_end = &chdr->tail.data.marker;
+ chdr->head.next.thr_progress = erts_thr_progress_current();
+ chdr->head.next.thr_progress_reached = 1;
+ chdr->head.next.um_refc_ix = 1;
+ chdr->head.next.unref_end = &chdr->tail.data.marker;
+
+ p = &chnk->data[0];
+ chdr->local.first = (erts_sspa_blk_t *) p;
+ blk = (erts_sspa_blk_t *) p;
+ for (i = 0; i < no_blocks_per_chunk; i++) {
+ blk = (erts_sspa_blk_t *) p;
+ p += blk_sz;
+ blk->next_ptr = (erts_sspa_blk_t *) p;
+ }
+
+ blk->next_ptr = NULL;
+ chdr->local.last = blk;
+ chdr->local.cnt = no_blocks_per_chunk;
+ chdr->local.lim = no_blocks_per_chunk / 3;
+
+ ERTS_SSPA_DBG_CHK_LCL(chdr);
+ }
+
+ return data;
+}
+
+static ERTS_INLINE erts_aint_t
+enqueue_remote_managed_thread(erts_sspa_chunk_header_t *chdr,
+ erts_sspa_blk_t *this,
+ int want_last)
+{
+ erts_aint_t ilast, itmp;
+
+ erts_atomic_init_nob(&this->next_atmc, ERTS_AINT_NULL);
+
+ /* Enqueue at end of list... */
+
+ ilast = erts_atomic_read_nob(&chdr->tail.data.last);
+ while (1) {
+ erts_sspa_blk_t *last = (erts_sspa_blk_t *) ilast;
+ itmp = erts_atomic_cmpxchg_mb(&last->next_atmc,
+ (erts_aint_t) this,
+ ERTS_AINT_NULL);
+ if (itmp == ERTS_AINT_NULL)
+ break;
+ ilast = itmp;
+ }
+
+ /* Move last pointer forward... */
+ while (1) {
+ erts_aint_t itmp;
+ if (want_last) {
+ if (erts_atomic_read_rb(&this->next_atmc) != ERTS_AINT_NULL) {
+ /* Someone else will move it forward */
+ return erts_atomic_read_nob(&chdr->tail.data.last);
+ }
+ }
+ else {
+ if (erts_atomic_read_nob(&this->next_atmc) != ERTS_AINT_NULL) {
+ /* Someone else will move it forward */
+ return ERTS_AINT_NULL;
+ }
+ }
+ itmp = erts_atomic_cmpxchg_mb(&chdr->tail.data.last,
+ (erts_aint_t) this,
+ ilast);
+ if (ilast == itmp)
+ return want_last ? (erts_aint_t) this : ERTS_AINT_NULL;
+ ilast = itmp;
+ }
+}
+
+void
+erts_sspa_remote_free(erts_sspa_chunk_header_t *chdr, erts_sspa_blk_t *blk)
+{
+ int um_refc_ix = 0;
+ int managed_thread = erts_thr_progress_is_managed_thread();
+ if (!managed_thread) {
+ um_refc_ix = erts_atomic32_read_acqb(&chdr->tail.data.um_refc_ix);
+ while (1) {
+ int tmp_um_refc_ix;
+ erts_atomic_inc_acqb(&chdr->tail.data.um_refc[um_refc_ix]);
+ tmp_um_refc_ix = erts_atomic32_read_acqb(&chdr->tail.data.um_refc_ix);
+ if (tmp_um_refc_ix == um_refc_ix)
+ break;
+ erts_atomic_dec_relb(&chdr->tail.data.um_refc[um_refc_ix]);
+ um_refc_ix = tmp_um_refc_ix;
+ }
+ }
+
+ (void) enqueue_remote_managed_thread(chdr, blk, 0);
+
+ if (!managed_thread)
+ erts_atomic_dec_relb(&chdr->tail.data.um_refc[um_refc_ix]);
+}
+
+static ERTS_INLINE void
+fetch_remote(erts_sspa_chunk_header_t *chdr, int max)
+{
+ int new_local = 0;
+
+ if (chdr->head.no_thr_progress_check < ERTS_SSPA_FORCE_THR_CHECK_PROGRESS)
+ chdr->head.no_thr_progress_check++;
+ else {
+ erts_aint_t ilast;
+
+ chdr->head.no_thr_progress_check = 0;
+
+ ilast = erts_atomic_read_nob(&chdr->tail.data.last);
+ if (((erts_sspa_blk_t *) ilast) == &chdr->tail.data.marker
+ && chdr->head.first == &chdr->tail.data.marker)
+ return;
+
+ if (chdr->head.next.thr_progress_reached
+ || erts_thr_progress_has_reached(chdr->head.next.thr_progress)) {
+ int um_refc_ix;
+ chdr->head.next.thr_progress_reached = 1;
+ um_refc_ix = chdr->head.next.um_refc_ix;
+ if (erts_atomic_read_acqb(&chdr->tail.data.um_refc[um_refc_ix]) == 0) {
+
+ /* Move unreferenced end pointer forward... */
+
+ chdr->head.unref_end = chdr->head.next.unref_end;
+
+ if (!chdr->head.used_marker
+ && chdr->head.unref_end == (erts_sspa_blk_t *) ilast) {
+ /* Need to equeue marker */
+ chdr->head.used_marker = 1;
+ ilast = enqueue_remote_managed_thread(chdr,
+ &chdr->tail.data.marker,
+ 1);
+ }
+
+ if (chdr->head.unref_end == (erts_sspa_blk_t *) ilast)
+ ERTS_THR_MEMORY_BARRIER;
+ else {
+ chdr->head.next.unref_end = (erts_sspa_blk_t *) ilast;
+ ERTS_THR_MEMORY_BARRIER;
+ chdr->head.next.thr_progress = erts_thr_progress_later();
+ erts_atomic32_set_relb(&chdr->tail.data.um_refc_ix,
+ um_refc_ix);
+ chdr->head.next.um_refc_ix = um_refc_ix == 0 ? 1 : 0;
+ chdr->head.next.thr_progress_reached = 0;
+ }
+ }
+ }
+ }
+
+ if (new_local < max && chdr->head.first != chdr->head.unref_end) {
+ erts_sspa_blk_t *first, *this, *next, *last;
+ first = chdr->head.first;
+ if (first == &chdr->tail.data.marker) {
+ chdr->head.used_marker = 0;
+ first = ((erts_sspa_blk_t *)
+ erts_atomic_read_nob(&first->next_atmc));
+ chdr->head.first = first;
+ }
+ if (first != chdr->head.unref_end) {
+
+ ERTS_SSPA_DBG_CHK_LCL(chdr);
+
+ this = last = first;
+ do {
+ next = (erts_sspa_blk_t *) erts_atomic_read_nob(&this->next_atmc);
+ if (this == &chdr->tail.data.marker)
+ chdr->head.used_marker = 0;
+ else {
+ last->next_ptr = this;
+ last = this;
+ new_local++;
+ }
+ this = next;
+ } while (new_local < max && this != chdr->head.unref_end);
+ chdr->head.first = this;
+ if (!chdr->local.last)
+ chdr->local.first = first;
+ else
+ chdr->local.last->next_ptr = first;
+ chdr->local.last = last;
+ last->next_ptr = NULL;
+ chdr->local.cnt += new_local;
+
+ ERTS_SSPA_DBG_CHK_LCL(chdr);
+ }
+ }
+
+}
+
+erts_sspa_blk_t *
+erts_sspa_process_remote_frees(erts_sspa_chunk_header_t *chdr,
+ erts_sspa_blk_t *old_res)
+{
+ erts_sspa_blk_t *res = old_res;
+
+ fetch_remote(chdr, ERTS_SSPA_MAX_GET_NEW_LOCAL);
+
+ if (!res && chdr->local.first) {
+
+ ERTS_SSPA_DBG_CHK_LCL(chdr);
+
+ res = chdr->local.first;
+ chdr->local.first = res->next_ptr;
+ chdr->local.cnt--;
+ if (!chdr->local.first)
+ chdr->local.last = NULL;
+
+ ERTS_SSPA_DBG_CHK_LCL(chdr);
+ }
+
+ return res;
+}
+
+#endif /* ERTS_SMP */
diff --git a/erts/emulator/beam/erl_sched_spec_pre_alloc.h b/erts/emulator/beam/erl_sched_spec_pre_alloc.h
new file mode 100644
index 0000000000..d36066c399
--- /dev/null
+++ b/erts/emulator/beam/erl_sched_spec_pre_alloc.h
@@ -0,0 +1,239 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description: Scheduler specific pre-allocators. Each scheduler
+ * thread allocates memory in its own private chunk of
+ * memory. Memory blocks deallocated by remote
+ * schedulers (or other threads) are passed back to
+ * the chunk owner via a lock-free data structure.
+ *
+ * Author: Rickard Green
+ */
+
+#ifndef ERTS_SCHED_SPEC_PRE_ALLOC_H__
+#define ERTS_SCHED_SPEC_PRE_ALLOC_H__
+
+#ifdef ERTS_SMP
+
+#undef ERL_THR_PROGRESS_TSD_TYPE_ONLY
+#define ERL_THR_PROGRESS_TSD_TYPE_ONLY
+#include "erl_thr_progress.h"
+#undef ERL_THR_PROGRESS_TSD_TYPE_ONLY
+
+#ifdef DEBUG
+#define ERTS_SPPA_DBG_CHK_IN_CHNK(A, C, P) \
+do { \
+ ASSERT((void *) (C) < (void *) (P)); \
+ ASSERT((void *) (P) \
+ < (void *) (((char *) (C)) + (A)->chunks_mem_size)); \
+} while (0)
+#else
+#define ERTS_SPPA_DBG_CHK_IN_CHNK(A, C, P)
+#endif
+
+#ifdef DEBUG
+extern Uint erts_no_schedulers;
+#endif
+
+#define ERTS_SSPA_FORCE_THR_CHECK_PROGRESS 10
+#define ERTS_SSPA_MAX_GET_NEW_LOCAL 5
+
+typedef struct {
+ char *start;
+ char *end;
+ int chunks_mem_size;
+} erts_sspa_data_t;
+
+typedef union erts_sspa_blk_t_ erts_sspa_blk_t;
+union erts_sspa_blk_t_ {
+ erts_atomic_t next_atmc;
+ erts_sspa_blk_t *next_ptr;
+};
+
+typedef struct {
+ erts_sspa_blk_t *first;
+ erts_sspa_blk_t *last;
+ int cnt;
+ int lim;
+} erts_sspa_local_freelist_t;
+
+typedef struct {
+ erts_sspa_blk_t marker;
+ erts_atomic_t last;
+ erts_atomic_t um_refc[2];
+ erts_atomic32_t um_refc_ix;
+} erts_sspa_tail_t;
+
+typedef struct {
+ /*
+ * This structure needs to be cache line aligned for best
+ * performance.
+ */
+ union {
+ /* Modified by threads returning memory to this chunk */
+ erts_sspa_tail_t data;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(erts_sspa_tail_t))];
+ } tail;
+ /*
+ * Everything below this point is *only* accessed by the
+ * thread owning this chunk.
+ */
+ struct {
+ int no_thr_progress_check;
+ int used_marker;
+ erts_sspa_blk_t *first;
+ erts_sspa_blk_t *unref_end;
+ struct {
+ ErtsThrPrgrVal thr_progress;
+ int thr_progress_reached;
+ int um_refc_ix;
+ erts_sspa_blk_t *unref_end;
+ } next;
+ } head;
+ erts_sspa_local_freelist_t local;
+} erts_sspa_chunk_header_t;
+
+typedef struct {
+ union {
+ erts_sspa_chunk_header_t header;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(
+ sizeof(erts_sspa_chunk_header_t))];
+ } aligned;
+ char data[1];
+} erts_sspa_chunk_t;
+
+#ifdef DEBUG
+ERTS_GLB_INLINE void
+check_local_list(erts_sspa_chunk_header_t *chdr);
+
+#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+ERTS_GLB_INLINE void
+check_local_list(erts_sspa_chunk_header_t *chdr)
+{
+ erts_sspa_blk_t *blk;
+ int n = 0;
+ for (blk = chdr->local.first; blk; blk = blk->next_ptr)
+ n++;
+ ASSERT(n == chdr->local.cnt);
+}
+#endif
+#define ERTS_SSPA_DBG_CHK_LCL(CHDR) check_local_list((CHDR))
+#else
+#define ERTS_SSPA_DBG_CHK_LCL(CHDR)
+#endif
+
+erts_sspa_data_t *erts_sspa_create(size_t blk_sz,
+ int pa_size);
+void erts_sspa_remote_free(erts_sspa_chunk_header_t *chdr,
+ erts_sspa_blk_t *blk);
+erts_sspa_blk_t *erts_sspa_process_remote_frees(erts_sspa_chunk_header_t *chdr,
+ erts_sspa_blk_t *old_res);
+
+ERTS_GLB_INLINE erts_sspa_chunk_t *erts_sspa_cix2chunk(erts_sspa_data_t *data,
+ int cix);
+ERTS_GLB_INLINE int erts_sspa_ptr2cix(erts_sspa_data_t *data, void *ptr);
+ERTS_GLB_INLINE char *erts_sspa_alloc(erts_sspa_data_t *data, int cix);
+ERTS_GLB_INLINE int erts_sspa_free(erts_sspa_data_t *data, int cix, char *blk);
+
+#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+
+ERTS_GLB_INLINE erts_sspa_chunk_t *
+erts_sspa_cix2chunk(erts_sspa_data_t *data, int cix)
+{
+ ASSERT(0 <= cix && cix < erts_no_schedulers);
+ return (erts_sspa_chunk_t *) (data->start + cix*data->chunks_mem_size);
+}
+
+ERTS_GLB_INLINE int
+erts_sspa_ptr2cix(erts_sspa_data_t *data, void *ptr)
+{
+ int cix;
+ size_t diff;
+ if ((char *) ptr < data->start || data->end <= (char *) ptr)
+ return -1;
+ diff = ((char *) ptr) - data->start;
+ cix = (int) diff / data->chunks_mem_size;
+ ASSERT(0 <= cix && cix < erts_no_schedulers);
+ return cix;
+}
+
+ERTS_GLB_INLINE char *
+erts_sspa_alloc(erts_sspa_data_t *data, int cix)
+{
+ erts_sspa_chunk_t *chnk;
+ erts_sspa_chunk_header_t *chdr;
+ erts_sspa_blk_t *res;
+
+ chnk = erts_sspa_cix2chunk(data, cix);
+ chdr = &chnk->aligned.header;
+ res = chdr->local.first;
+ ERTS_SSPA_DBG_CHK_LCL(chdr);
+ if (res) {
+ ERTS_SSPA_DBG_CHK_LCL(chdr);
+ chdr->local.first = res->next_ptr;
+ chdr->local.cnt--;
+ if (!chdr->local.first)
+ chdr->local.last = NULL;
+ ERTS_SSPA_DBG_CHK_LCL(chdr);
+ }
+ if (chdr->local.cnt <= chdr->local.lim)
+ return (char *) erts_sspa_process_remote_frees(chdr, res);
+ else if (chdr->head.no_thr_progress_check < ERTS_SSPA_FORCE_THR_CHECK_PROGRESS)
+ chdr->head.no_thr_progress_check++;
+ ASSERT(res);
+ return (char *) res;
+}
+
+ERTS_GLB_INLINE int
+erts_sspa_free(erts_sspa_data_t *data, int cix, char *cblk)
+{
+ erts_sspa_chunk_t *chnk;
+ erts_sspa_chunk_header_t *chdr;
+ erts_sspa_blk_t *blk = (erts_sspa_blk_t *) cblk;
+ int chnk_cix = erts_sspa_ptr2cix(data, blk);
+
+ if (chnk_cix < 0)
+ return 0;
+
+ chnk = erts_sspa_cix2chunk(data, chnk_cix);
+ chdr = &chnk->aligned.header;
+ if (chnk_cix != cix) {
+ /* Remote chunk */
+ erts_sspa_remote_free(chdr, blk);
+ }
+ else {
+ /* Local chunk */
+ ERTS_SSPA_DBG_CHK_LCL(chdr);
+ blk->next_ptr = chdr->local.first;
+ chdr->local.first = blk;
+ if (!chdr->local.last)
+ chdr->local.last = blk;
+ chdr->local.cnt++;
+ ERTS_SSPA_DBG_CHK_LCL(chdr);
+ }
+
+ return 1;
+}
+
+#endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */
+
+#endif /* ERTS_SMP */
+
+#endif /* ERTS_SCHED_SPEC_PRE_ALLOC_H__ */
diff --git a/erts/emulator/beam/erl_smp.h b/erts/emulator/beam/erl_smp.h
index 287327bfe1..63179dfad4 100644
--- a/erts/emulator/beam/erl_smp.h
+++ b/erts/emulator/beam/erl_smp.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -54,8 +54,9 @@ typedef erts_cnd_t erts_smp_cnd_t;
typedef erts_rwmtx_opt_t erts_smp_rwmtx_opt_t;
typedef erts_rwmtx_t erts_smp_rwmtx_t;
typedef erts_tsd_key_t erts_smp_tsd_key_t;
-typedef erts_atomic_t erts_smp_atomic_t;
-typedef erts_atomic32_t erts_smp_atomic32_t;
+#define erts_smp_dw_atomic_t erts_dw_atomic_t
+#define erts_smp_atomic_t erts_atomic_t
+#define erts_smp_atomic32_t erts_atomic32_t
typedef erts_spinlock_t erts_smp_spinlock_t;
typedef erts_rwlock_t erts_smp_rwlock_t;
void erts_thr_fatal_error(int, char *); /* implemented in erl_init.c */
@@ -83,8 +84,9 @@ typedef struct {
} erts_smp_rwmtx_opt_t;
typedef int erts_smp_rwmtx_t;
typedef int erts_smp_tsd_key_t;
-typedef SWord erts_smp_atomic_t;
-typedef Uint32 erts_smp_atomic32_t;
+#define erts_smp_dw_atomic_t erts_no_dw_atomic_t
+#define erts_smp_atomic_t erts_no_atomic_t
+#define erts_smp_atomic32_t erts_no_atomic32_t
#if __GNUC__ > 2
typedef struct { } erts_smp_spinlock_t;
typedef struct { } erts_smp_rwlock_t;
@@ -160,82 +162,6 @@ ERTS_GLB_INLINE int erts_smp_rwmtx_tryrwlock(erts_smp_rwmtx_t *rwmtx);
ERTS_GLB_INLINE void erts_smp_rwmtx_rwunlock(erts_smp_rwmtx_t *rwmtx);
ERTS_GLB_INLINE int erts_smp_lc_rwmtx_is_rlocked(erts_smp_rwmtx_t *mtx);
ERTS_GLB_INLINE int erts_smp_lc_rwmtx_is_rwlocked(erts_smp_rwmtx_t *mtx);
-ERTS_GLB_INLINE void erts_smp_atomic_init(erts_smp_atomic_t *var,
- erts_aint_t i);
-ERTS_GLB_INLINE void erts_smp_atomic_set(erts_smp_atomic_t *var, erts_aint_t i);
-ERTS_GLB_INLINE erts_aint_t erts_smp_atomic_read(erts_smp_atomic_t *var);
-ERTS_GLB_INLINE erts_aint_t erts_smp_atomic_inctest(erts_smp_atomic_t *incp);
-ERTS_GLB_INLINE erts_aint_t erts_smp_atomic_dectest(erts_smp_atomic_t *decp);
-ERTS_GLB_INLINE void erts_smp_atomic_inc(erts_smp_atomic_t *incp);
-ERTS_GLB_INLINE void erts_smp_atomic_dec(erts_smp_atomic_t *decp);
-ERTS_GLB_INLINE erts_aint_t erts_smp_atomic_addtest(erts_smp_atomic_t *addp,
- erts_aint_t i);
-ERTS_GLB_INLINE void erts_smp_atomic_add(erts_smp_atomic_t *addp,
- erts_aint_t i);
-ERTS_GLB_INLINE erts_aint_t erts_smp_atomic_xchg(erts_smp_atomic_t *xchgp,
- erts_aint_t new);
-ERTS_GLB_INLINE erts_aint_t erts_smp_atomic_cmpxchg(erts_smp_atomic_t *xchgp,
- erts_aint_t new,
- erts_aint_t expected);
-ERTS_GLB_INLINE erts_aint_t erts_smp_atomic_bor(erts_smp_atomic_t *var,
- erts_aint_t mask);
-ERTS_GLB_INLINE erts_aint_t erts_smp_atomic_band(erts_smp_atomic_t *var,
- erts_aint_t mask);
-ERTS_GLB_INLINE erts_aint_t erts_smp_atomic_read_acqb(erts_smp_atomic_t *var);
-ERTS_GLB_INLINE void erts_smp_atomic_set_relb(erts_smp_atomic_t *var,
- erts_aint_t i);
-ERTS_GLB_INLINE void erts_smp_atomic_dec_relb(erts_smp_atomic_t *decp);
-ERTS_GLB_INLINE erts_aint_t erts_smp_atomic_dectest_relb(erts_smp_atomic_t *decp);
-ERTS_GLB_INLINE erts_aint_t erts_smp_atomic_cmpxchg_acqb(erts_smp_atomic_t *xchgp,
- erts_aint_t new,
- erts_aint_t exp);
-ERTS_GLB_INLINE erts_aint_t erts_smp_atomic_cmpxchg_relb(erts_smp_atomic_t *xchgp,
- erts_aint_t new,
- erts_aint_t exp);
-ERTS_GLB_INLINE void
-erts_smp_atomic32_init(erts_smp_atomic32_t *var, erts_aint32_t i);
-ERTS_GLB_INLINE void
-erts_smp_atomic32_set(erts_smp_atomic32_t *var, erts_aint32_t i);
-ERTS_GLB_INLINE erts_aint32_t
-erts_smp_atomic32_read(erts_smp_atomic32_t *var);
-ERTS_GLB_INLINE erts_aint32_t
-erts_smp_atomic32_inctest(erts_smp_atomic32_t *incp);
-ERTS_GLB_INLINE erts_aint32_t
-erts_smp_atomic32_dectest(erts_smp_atomic32_t *decp);
-ERTS_GLB_INLINE void
-erts_smp_atomic32_inc(erts_smp_atomic32_t *incp);
-ERTS_GLB_INLINE void
-erts_smp_atomic32_dec(erts_smp_atomic32_t *decp);
-ERTS_GLB_INLINE erts_aint32_t
-erts_smp_atomic32_addtest(erts_smp_atomic32_t *addp, erts_aint32_t i);
-ERTS_GLB_INLINE void
-erts_smp_atomic32_add(erts_smp_atomic32_t *addp, erts_aint32_t i);
-ERTS_GLB_INLINE erts_aint32_t
-erts_smp_atomic32_xchg(erts_smp_atomic32_t *xchgp, erts_aint32_t new);
-ERTS_GLB_INLINE erts_aint32_t
-erts_smp_atomic32_cmpxchg(erts_smp_atomic32_t *xchgp,
- erts_aint32_t new,
- erts_aint32_t expected);
-ERTS_GLB_INLINE erts_aint32_t
-erts_smp_atomic32_bor(erts_smp_atomic32_t *var, erts_aint32_t mask);
-ERTS_GLB_INLINE erts_aint32_t
-erts_smp_atomic32_band(erts_smp_atomic32_t *var, erts_aint32_t mask);
-ERTS_GLB_INLINE erts_aint32_t
-erts_smp_atomic32_read_acqb(erts_smp_atomic32_t *var);
-ERTS_GLB_INLINE void
-erts_smp_atomic32_set_relb(erts_smp_atomic32_t *var, erts_aint32_t i);
-ERTS_GLB_INLINE void
-erts_smp_atomic32_dec_relb(erts_smp_atomic32_t *decp);
-ERTS_GLB_INLINE erts_aint32_t
-erts_smp_atomic32_dectest_relb(erts_smp_atomic32_t *decp);
-ERTS_GLB_INLINE erts_aint32_t
-erts_smp_atomic32_cmpxchg_acqb(erts_smp_atomic32_t *xchgp,
- erts_aint32_t new,
- erts_aint32_t exp);
-ERTS_GLB_INLINE erts_aint32_t
-erts_smp_atomic32_cmpxchg_relb(erts_smp_atomic32_t *xchgp,
- erts_aint32_t new,
- erts_aint32_t exp);
ERTS_GLB_INLINE void erts_smp_spinlock_init_x(erts_smp_spinlock_t *lock,
char *name,
Eterm extra);
@@ -279,6 +205,429 @@ ERTS_GLB_INLINE void erts_smp_thr_sigmask(int how,
ERTS_GLB_INLINE void erts_smp_thr_sigwait(const sigset_t *set, int *sig);
#endif /* #ifdef ERTS_THR_HAVE_SIG_FUNCS */
+/*
+ * Functions implementing atomic operations with with no (nob),
+ * full (mb), acquire (acqb), release (relb), read (rb), and
+ * write (wb) memory barriers.
+ *
+ * If SMP support has been disabled, they are mapped to functions
+ * that performs the same operation, but aren't atomic and don't
+ * imply memory barriers.
+ */
+
+#ifdef ERTS_SMP
+
+/* Double word size atomics */
+
+#define erts_smp_dw_atomic_init_nob erts_dw_atomic_init_nob
+#define erts_smp_dw_atomic_set_nob erts_dw_atomic_set_nob
+#define erts_smp_dw_atomic_read_nob erts_dw_atomic_read_nob
+#define erts_smp_dw_atomic_cmpxchg_nob erts_dw_atomic_cmpxchg_nob
+
+#define erts_smp_dw_atomic_init_mb erts_dw_atomic_init_mb
+#define erts_smp_dw_atomic_set_mb erts_dw_atomic_set_mb
+#define erts_smp_dw_atomic_read_mb erts_dw_atomic_read_mb
+#define erts_smp_dw_atomic_cmpxchg_mb erts_dw_atomic_cmpxchg_mb
+
+#define erts_smp_dw_atomic_init_acqb erts_dw_atomic_init_acqb
+#define erts_smp_dw_atomic_set_acqb erts_dw_atomic_set_acqb
+#define erts_smp_dw_atomic_read_acqb erts_dw_atomic_read_acqb
+#define erts_smp_dw_atomic_cmpxchg_acqb erts_dw_atomic_cmpxchg_acqb
+
+#define erts_smp_dw_atomic_init_relb erts_dw_atomic_init_relb
+#define erts_smp_dw_atomic_set_relb erts_dw_atomic_set_relb
+#define erts_smp_dw_atomic_read_relb erts_dw_atomic_read_relb
+#define erts_smp_dw_atomic_cmpxchg_relb erts_dw_atomic_cmpxchg_relb
+
+#define erts_smp_dw_atomic_init_rb erts_dw_atomic_init_rb
+#define erts_smp_dw_atomic_set_rb erts_dw_atomic_set_rb
+#define erts_smp_dw_atomic_read_rb erts_dw_atomic_read_rb
+#define erts_smp_dw_atomic_cmpxchg_rb erts_dw_atomic_cmpxchg_rb
+
+#define erts_smp_dw_atomic_init_wb erts_dw_atomic_init_wb
+#define erts_smp_dw_atomic_set_wb erts_dw_atomic_set_wb
+#define erts_smp_dw_atomic_read_wb erts_dw_atomic_read_wb
+#define erts_smp_dw_atomic_cmpxchg_wb erts_dw_atomic_cmpxchg_wb
+
+/* Word size atomics */
+
+#define erts_smp_atomic_init_nob erts_atomic_init_nob
+#define erts_smp_atomic_set_nob erts_atomic_set_nob
+#define erts_smp_atomic_read_nob erts_atomic_read_nob
+#define erts_smp_atomic_inc_read_nob erts_atomic_inc_read_nob
+#define erts_smp_atomic_dec_read_nob erts_atomic_dec_read_nob
+#define erts_smp_atomic_inc_nob erts_atomic_inc_nob
+#define erts_smp_atomic_dec_nob erts_atomic_dec_nob
+#define erts_smp_atomic_add_read_nob erts_atomic_add_read_nob
+#define erts_smp_atomic_add_nob erts_atomic_add_nob
+#define erts_smp_atomic_read_bor_nob erts_atomic_read_bor_nob
+#define erts_smp_atomic_read_band_nob erts_atomic_read_band_nob
+#define erts_smp_atomic_xchg_nob erts_atomic_xchg_nob
+#define erts_smp_atomic_cmpxchg_nob erts_atomic_cmpxchg_nob
+
+#define erts_smp_atomic_init_mb erts_atomic_init_mb
+#define erts_smp_atomic_set_mb erts_atomic_set_mb
+#define erts_smp_atomic_read_mb erts_atomic_read_mb
+#define erts_smp_atomic_inc_read_mb erts_atomic_inc_read_mb
+#define erts_smp_atomic_dec_read_mb erts_atomic_dec_read_mb
+#define erts_smp_atomic_inc_mb erts_atomic_inc_mb
+#define erts_smp_atomic_dec_mb erts_atomic_dec_mb
+#define erts_smp_atomic_add_read_mb erts_atomic_add_read_mb
+#define erts_smp_atomic_add_mb erts_atomic_add_mb
+#define erts_smp_atomic_read_bor_mb erts_atomic_read_bor_mb
+#define erts_smp_atomic_read_band_mb erts_atomic_read_band_mb
+#define erts_smp_atomic_xchg_mb erts_atomic_xchg_mb
+#define erts_smp_atomic_cmpxchg_mb erts_atomic_cmpxchg_mb
+
+#define erts_smp_atomic_init_acqb erts_atomic_init_acqb
+#define erts_smp_atomic_set_acqb erts_atomic_set_acqb
+#define erts_smp_atomic_read_acqb erts_atomic_read_acqb
+#define erts_smp_atomic_inc_read_acqb erts_atomic_inc_read_acqb
+#define erts_smp_atomic_dec_read_acqb erts_atomic_dec_read_acqb
+#define erts_smp_atomic_inc_acqb erts_atomic_inc_acqb
+#define erts_smp_atomic_dec_acqb erts_atomic_dec_acqb
+#define erts_smp_atomic_add_read_acqb erts_atomic_add_read_acqb
+#define erts_smp_atomic_add_acqb erts_atomic_add_acqb
+#define erts_smp_atomic_read_bor_acqb erts_atomic_read_bor_acqb
+#define erts_smp_atomic_read_band_acqb erts_atomic_read_band_acqb
+#define erts_smp_atomic_xchg_acqb erts_atomic_xchg_acqb
+#define erts_smp_atomic_cmpxchg_acqb erts_atomic_cmpxchg_acqb
+
+#define erts_smp_atomic_init_relb erts_atomic_init_relb
+#define erts_smp_atomic_set_relb erts_atomic_set_relb
+#define erts_smp_atomic_read_relb erts_atomic_read_relb
+#define erts_smp_atomic_inc_read_relb erts_atomic_inc_read_relb
+#define erts_smp_atomic_dec_read_relb erts_atomic_dec_read_relb
+#define erts_smp_atomic_inc_relb erts_atomic_inc_relb
+#define erts_smp_atomic_dec_relb erts_atomic_dec_relb
+#define erts_smp_atomic_add_read_relb erts_atomic_add_read_relb
+#define erts_smp_atomic_add_relb erts_atomic_add_relb
+#define erts_smp_atomic_read_bor_relb erts_atomic_read_bor_relb
+#define erts_smp_atomic_read_band_relb erts_atomic_read_band_relb
+#define erts_smp_atomic_xchg_relb erts_atomic_xchg_relb
+#define erts_smp_atomic_cmpxchg_relb erts_atomic_cmpxchg_relb
+
+#define erts_smp_atomic_init_rb erts_atomic_init_rb
+#define erts_smp_atomic_set_rb erts_atomic_set_rb
+#define erts_smp_atomic_read_rb erts_atomic_read_rb
+#define erts_smp_atomic_inc_read_rb erts_atomic_inc_read_rb
+#define erts_smp_atomic_dec_read_rb erts_atomic_dec_read_rb
+#define erts_smp_atomic_inc_rb erts_atomic_inc_rb
+#define erts_smp_atomic_dec_rb erts_atomic_dec_rb
+#define erts_smp_atomic_add_read_rb erts_atomic_add_read_rb
+#define erts_smp_atomic_add_rb erts_atomic_add_rb
+#define erts_smp_atomic_read_bor_rb erts_atomic_read_bor_rb
+#define erts_smp_atomic_read_band_rb erts_atomic_read_band_rb
+#define erts_smp_atomic_xchg_rb erts_atomic_xchg_rb
+#define erts_smp_atomic_cmpxchg_rb erts_atomic_cmpxchg_rb
+
+#define erts_smp_atomic_init_wb erts_atomic_init_wb
+#define erts_smp_atomic_set_wb erts_atomic_set_wb
+#define erts_smp_atomic_read_wb erts_atomic_read_wb
+#define erts_smp_atomic_inc_read_wb erts_atomic_inc_read_wb
+#define erts_smp_atomic_dec_read_wb erts_atomic_dec_read_wb
+#define erts_smp_atomic_inc_wb erts_atomic_inc_wb
+#define erts_smp_atomic_dec_wb erts_atomic_dec_wb
+#define erts_smp_atomic_add_read_wb erts_atomic_add_read_wb
+#define erts_smp_atomic_add_wb erts_atomic_add_wb
+#define erts_smp_atomic_read_bor_wb erts_atomic_read_bor_wb
+#define erts_smp_atomic_read_band_wb erts_atomic_read_band_wb
+#define erts_smp_atomic_xchg_wb erts_atomic_xchg_wb
+#define erts_smp_atomic_cmpxchg_wb erts_atomic_cmpxchg_wb
+
+/* 32-bit atomics */
+
+#define erts_smp_atomic32_init_nob erts_atomic32_init_nob
+#define erts_smp_atomic32_set_nob erts_atomic32_set_nob
+#define erts_smp_atomic32_read_nob erts_atomic32_read_nob
+#define erts_smp_atomic32_inc_read_nob erts_atomic32_inc_read_nob
+#define erts_smp_atomic32_dec_read_nob erts_atomic32_dec_read_nob
+#define erts_smp_atomic32_inc_nob erts_atomic32_inc_nob
+#define erts_smp_atomic32_dec_nob erts_atomic32_dec_nob
+#define erts_smp_atomic32_add_read_nob erts_atomic32_add_read_nob
+#define erts_smp_atomic32_add_nob erts_atomic32_add_nob
+#define erts_smp_atomic32_read_bor_nob erts_atomic32_read_bor_nob
+#define erts_smp_atomic32_read_band_nob erts_atomic32_read_band_nob
+#define erts_smp_atomic32_xchg_nob erts_atomic32_xchg_nob
+#define erts_smp_atomic32_cmpxchg_nob erts_atomic32_cmpxchg_nob
+
+#define erts_smp_atomic32_init_mb erts_atomic32_init_mb
+#define erts_smp_atomic32_set_mb erts_atomic32_set_mb
+#define erts_smp_atomic32_read_mb erts_atomic32_read_mb
+#define erts_smp_atomic32_inc_read_mb erts_atomic32_inc_read_mb
+#define erts_smp_atomic32_dec_read_mb erts_atomic32_dec_read_mb
+#define erts_smp_atomic32_inc_mb erts_atomic32_inc_mb
+#define erts_smp_atomic32_dec_mb erts_atomic32_dec_mb
+#define erts_smp_atomic32_add_read_mb erts_atomic32_add_read_mb
+#define erts_smp_atomic32_add_mb erts_atomic32_add_mb
+#define erts_smp_atomic32_read_bor_mb erts_atomic32_read_bor_mb
+#define erts_smp_atomic32_read_band_mb erts_atomic32_read_band_mb
+#define erts_smp_atomic32_xchg_mb erts_atomic32_xchg_mb
+#define erts_smp_atomic32_cmpxchg_mb erts_atomic32_cmpxchg_mb
+
+#define erts_smp_atomic32_init_acqb erts_atomic32_init_acqb
+#define erts_smp_atomic32_set_acqb erts_atomic32_set_acqb
+#define erts_smp_atomic32_read_acqb erts_atomic32_read_acqb
+#define erts_smp_atomic32_inc_read_acqb erts_atomic32_inc_read_acqb
+#define erts_smp_atomic32_dec_read_acqb erts_atomic32_dec_read_acqb
+#define erts_smp_atomic32_inc_acqb erts_atomic32_inc_acqb
+#define erts_smp_atomic32_dec_acqb erts_atomic32_dec_acqb
+#define erts_smp_atomic32_add_read_acqb erts_atomic32_add_read_acqb
+#define erts_smp_atomic32_add_acqb erts_atomic32_add_acqb
+#define erts_smp_atomic32_read_bor_acqb erts_atomic32_read_bor_acqb
+#define erts_smp_atomic32_read_band_acqb erts_atomic32_read_band_acqb
+#define erts_smp_atomic32_xchg_acqb erts_atomic32_xchg_acqb
+#define erts_smp_atomic32_cmpxchg_acqb erts_atomic32_cmpxchg_acqb
+
+#define erts_smp_atomic32_init_relb erts_atomic32_init_relb
+#define erts_smp_atomic32_set_relb erts_atomic32_set_relb
+#define erts_smp_atomic32_read_relb erts_atomic32_read_relb
+#define erts_smp_atomic32_inc_read_relb erts_atomic32_inc_read_relb
+#define erts_smp_atomic32_dec_read_relb erts_atomic32_dec_read_relb
+#define erts_smp_atomic32_inc_relb erts_atomic32_inc_relb
+#define erts_smp_atomic32_dec_relb erts_atomic32_dec_relb
+#define erts_smp_atomic32_add_read_relb erts_atomic32_add_read_relb
+#define erts_smp_atomic32_add_relb erts_atomic32_add_relb
+#define erts_smp_atomic32_read_bor_relb erts_atomic32_read_bor_relb
+#define erts_smp_atomic32_read_band_relb erts_atomic32_read_band_relb
+#define erts_smp_atomic32_xchg_relb erts_atomic32_xchg_relb
+#define erts_smp_atomic32_cmpxchg_relb erts_atomic32_cmpxchg_relb
+
+#define erts_smp_atomic32_init_rb erts_atomic32_init_rb
+#define erts_smp_atomic32_set_rb erts_atomic32_set_rb
+#define erts_smp_atomic32_read_rb erts_atomic32_read_rb
+#define erts_smp_atomic32_inc_read_rb erts_atomic32_inc_read_rb
+#define erts_smp_atomic32_dec_read_rb erts_atomic32_dec_read_rb
+#define erts_smp_atomic32_inc_rb erts_atomic32_inc_rb
+#define erts_smp_atomic32_dec_rb erts_atomic32_dec_rb
+#define erts_smp_atomic32_add_read_rb erts_atomic32_add_read_rb
+#define erts_smp_atomic32_add_rb erts_atomic32_add_rb
+#define erts_smp_atomic32_read_bor_rb erts_atomic32_read_bor_rb
+#define erts_smp_atomic32_read_band_rb erts_atomic32_read_band_rb
+#define erts_smp_atomic32_xchg_rb erts_atomic32_xchg_rb
+#define erts_smp_atomic32_cmpxchg_rb erts_atomic32_cmpxchg_rb
+
+#define erts_smp_atomic32_init_wb erts_atomic32_init_wb
+#define erts_smp_atomic32_set_wb erts_atomic32_set_wb
+#define erts_smp_atomic32_read_wb erts_atomic32_read_wb
+#define erts_smp_atomic32_inc_read_wb erts_atomic32_inc_read_wb
+#define erts_smp_atomic32_dec_read_wb erts_atomic32_dec_read_wb
+#define erts_smp_atomic32_inc_wb erts_atomic32_inc_wb
+#define erts_smp_atomic32_dec_wb erts_atomic32_dec_wb
+#define erts_smp_atomic32_add_read_wb erts_atomic32_add_read_wb
+#define erts_smp_atomic32_add_wb erts_atomic32_add_wb
+#define erts_smp_atomic32_read_bor_wb erts_atomic32_read_bor_wb
+#define erts_smp_atomic32_read_band_wb erts_atomic32_read_band_wb
+#define erts_smp_atomic32_xchg_wb erts_atomic32_xchg_wb
+#define erts_smp_atomic32_cmpxchg_wb erts_atomic32_cmpxchg_wb
+
+#else /* !ERTS_SMP */
+
+/* Double word size atomics */
+
+#define erts_smp_dw_atomic_init_nob erts_no_dw_atomic_set
+#define erts_smp_dw_atomic_set_nob erts_no_dw_atomic_set
+#define erts_smp_dw_atomic_read_nob erts_no_dw_atomic_read
+#define erts_smp_dw_atomic_cmpxchg_nob erts_no_dw_atomic_cmpxchg
+
+#define erts_smp_dw_atomic_init_mb erts_no_dw_atomic_init
+#define erts_smp_dw_atomic_set_mb erts_no_dw_atomic_set
+#define erts_smp_dw_atomic_read_mb erts_no_dw_atomic_read
+#define erts_smp_dw_atomic_cmpxchg_mb erts_no_dw_atomic_cmpxchg
+
+#define erts_smp_dw_atomic_init_acqb erts_no_dw_atomic_init
+#define erts_smp_dw_atomic_set_acqb erts_no_dw_atomic_set
+#define erts_smp_dw_atomic_read_acqb erts_no_dw_atomic_read
+#define erts_smp_dw_atomic_cmpxchg_acqb erts_no_dw_atomic_cmpxchg
+
+#define erts_smp_dw_atomic_init_relb erts_no_dw_atomic_init
+#define erts_smp_dw_atomic_set_relb erts_no_dw_atomic_set
+#define erts_smp_dw_atomic_read_relb erts_no_dw_atomic_read
+#define erts_smp_dw_atomic_cmpxchg_relb erts_no_dw_atomic_cmpxchg
+
+#define erts_smp_dw_atomic_init_rb erts_no_dw_atomic_init
+#define erts_smp_dw_atomic_set_rb erts_no_dw_atomic_set
+#define erts_smp_dw_atomic_read_rb erts_no_dw_atomic_read
+#define erts_smp_dw_atomic_cmpxchg_rb erts_no_dw_atomic_cmpxchg
+
+#define erts_smp_dw_atomic_init_wb erts_no_dw_atomic_init
+#define erts_smp_dw_atomic_set_wb erts_no_dw_atomic_set
+#define erts_smp_dw_atomic_read_wb erts_no_dw_atomic_read
+#define erts_smp_dw_atomic_cmpxchg_wb erts_no_dw_atomic_cmpxchg
+
+/* Word size atomics */
+
+#define erts_smp_atomic_init_nob erts_no_atomic_set
+#define erts_smp_atomic_set_nob erts_no_atomic_set
+#define erts_smp_atomic_read_nob erts_no_atomic_read
+#define erts_smp_atomic_inc_read_nob erts_no_atomic_inc_read
+#define erts_smp_atomic_dec_read_nob erts_no_atomic_dec_read
+#define erts_smp_atomic_inc_nob erts_no_atomic_inc
+#define erts_smp_atomic_dec_nob erts_no_atomic_dec
+#define erts_smp_atomic_add_read_nob erts_no_atomic_add_read
+#define erts_smp_atomic_add_nob erts_no_atomic_add
+#define erts_smp_atomic_read_bor_nob erts_no_atomic_read_bor
+#define erts_smp_atomic_read_band_nob erts_no_atomic_read_band
+#define erts_smp_atomic_xchg_nob erts_no_atomic_xchg
+#define erts_smp_atomic_cmpxchg_nob erts_no_atomic_cmpxchg
+
+#define erts_smp_atomic_init_mb erts_no_atomic_set
+#define erts_smp_atomic_set_mb erts_no_atomic_set
+#define erts_smp_atomic_read_mb erts_no_atomic_read
+#define erts_smp_atomic_inc_read_mb erts_no_atomic_inc_read
+#define erts_smp_atomic_dec_read_mb erts_no_atomic_dec_read
+#define erts_smp_atomic_inc_mb erts_no_atomic_inc
+#define erts_smp_atomic_dec_mb erts_no_atomic_dec
+#define erts_smp_atomic_add_read_mb erts_no_atomic_add_read
+#define erts_smp_atomic_add_mb erts_no_atomic_add
+#define erts_smp_atomic_read_bor_mb erts_no_atomic_read_bor
+#define erts_smp_atomic_read_band_mb erts_no_atomic_read_band
+#define erts_smp_atomic_xchg_mb erts_no_atomic_xchg
+#define erts_smp_atomic_cmpxchg_mb erts_no_atomic_cmpxchg
+
+#define erts_smp_atomic_init_acqb erts_no_atomic_set
+#define erts_smp_atomic_set_acqb erts_no_atomic_set
+#define erts_smp_atomic_read_acqb erts_no_atomic_read
+#define erts_smp_atomic_inc_read_acqb erts_no_atomic_inc_read
+#define erts_smp_atomic_dec_read_acqb erts_no_atomic_dec_read
+#define erts_smp_atomic_inc_acqb erts_no_atomic_inc
+#define erts_smp_atomic_dec_acqb erts_no_atomic_dec
+#define erts_smp_atomic_add_read_acqb erts_no_atomic_add_read
+#define erts_smp_atomic_add_acqb erts_no_atomic_add
+#define erts_smp_atomic_read_bor_acqb erts_no_atomic_read_bor
+#define erts_smp_atomic_read_band_acqb erts_no_atomic_read_band
+#define erts_smp_atomic_xchg_acqb erts_no_atomic_xchg
+#define erts_smp_atomic_cmpxchg_acqb erts_no_atomic_cmpxchg
+
+#define erts_smp_atomic_init_relb erts_no_atomic_set
+#define erts_smp_atomic_set_relb erts_no_atomic_set
+#define erts_smp_atomic_read_relb erts_no_atomic_read
+#define erts_smp_atomic_inc_read_relb erts_no_atomic_inc_read
+#define erts_smp_atomic_dec_read_relb erts_no_atomic_dec_read
+#define erts_smp_atomic_inc_relb erts_no_atomic_inc
+#define erts_smp_atomic_dec_relb erts_no_atomic_dec
+#define erts_smp_atomic_add_read_relb erts_no_atomic_add_read
+#define erts_smp_atomic_add_relb erts_no_atomic_add
+#define erts_smp_atomic_read_bor_relb erts_no_atomic_read_bor
+#define erts_smp_atomic_read_band_relb erts_no_atomic_read_band
+#define erts_smp_atomic_xchg_relb erts_no_atomic_xchg
+#define erts_smp_atomic_cmpxchg_relb erts_no_atomic_cmpxchg
+
+#define erts_smp_atomic_init_rb erts_no_atomic_set
+#define erts_smp_atomic_set_rb erts_no_atomic_set
+#define erts_smp_atomic_read_rb erts_no_atomic_read
+#define erts_smp_atomic_inc_read_rb erts_no_atomic_inc_read
+#define erts_smp_atomic_dec_read_rb erts_no_atomic_dec_read
+#define erts_smp_atomic_inc_rb erts_no_atomic_inc
+#define erts_smp_atomic_dec_rb erts_no_atomic_dec
+#define erts_smp_atomic_add_read_rb erts_no_atomic_add_read
+#define erts_smp_atomic_add_rb erts_no_atomic_add
+#define erts_smp_atomic_read_bor_rb erts_no_atomic_read_bor
+#define erts_smp_atomic_read_band_rb erts_no_atomic_read_band
+#define erts_smp_atomic_xchg_rb erts_no_atomic_xchg
+#define erts_smp_atomic_cmpxchg_rb erts_no_atomic_cmpxchg
+
+#define erts_smp_atomic_init_wb erts_no_atomic_set
+#define erts_smp_atomic_set_wb erts_no_atomic_set
+#define erts_smp_atomic_read_wb erts_no_atomic_read
+#define erts_smp_atomic_inc_read_wb erts_no_atomic_inc_read
+#define erts_smp_atomic_dec_read_wb erts_no_atomic_dec_read
+#define erts_smp_atomic_inc_wb erts_no_atomic_inc
+#define erts_smp_atomic_dec_wb erts_no_atomic_dec
+#define erts_smp_atomic_add_read_wb erts_no_atomic_add_read
+#define erts_smp_atomic_add_wb erts_no_atomic_add
+#define erts_smp_atomic_read_bor_wb erts_no_atomic_read_bor
+#define erts_smp_atomic_read_band_wb erts_no_atomic_read_band
+#define erts_smp_atomic_xchg_wb erts_no_atomic_xchg
+#define erts_smp_atomic_cmpxchg_wb erts_no_atomic_cmpxchg
+
+/* 32-bit atomics */
+
+#define erts_smp_atomic32_init_nob erts_no_atomic32_set
+#define erts_smp_atomic32_set_nob erts_no_atomic32_set
+#define erts_smp_atomic32_read_nob erts_no_atomic32_read
+#define erts_smp_atomic32_inc_read_nob erts_no_atomic32_inc_read
+#define erts_smp_atomic32_dec_read_nob erts_no_atomic32_dec_read
+#define erts_smp_atomic32_inc_nob erts_no_atomic32_inc
+#define erts_smp_atomic32_dec_nob erts_no_atomic32_dec
+#define erts_smp_atomic32_add_read_nob erts_no_atomic32_add_read
+#define erts_smp_atomic32_add_nob erts_no_atomic32_add
+#define erts_smp_atomic32_read_bor_nob erts_no_atomic32_read_bor
+#define erts_smp_atomic32_read_band_nob erts_no_atomic32_read_band
+#define erts_smp_atomic32_xchg_nob erts_no_atomic32_xchg
+#define erts_smp_atomic32_cmpxchg_nob erts_no_atomic32_cmpxchg
+
+#define erts_smp_atomic32_init_mb erts_no_atomic32_set
+#define erts_smp_atomic32_set_mb erts_no_atomic32_set
+#define erts_smp_atomic32_read_mb erts_no_atomic32_read
+#define erts_smp_atomic32_inc_read_mb erts_no_atomic32_inc_read
+#define erts_smp_atomic32_dec_read_mb erts_no_atomic32_dec_read
+#define erts_smp_atomic32_inc_mb erts_no_atomic32_inc
+#define erts_smp_atomic32_dec_mb erts_no_atomic32_dec
+#define erts_smp_atomic32_add_read_mb erts_no_atomic32_add_read
+#define erts_smp_atomic32_add_mb erts_no_atomic32_add
+#define erts_smp_atomic32_read_bor_mb erts_no_atomic32_read_bor
+#define erts_smp_atomic32_read_band_mb erts_no_atomic32_read_band
+#define erts_smp_atomic32_xchg_mb erts_no_atomic32_xchg
+#define erts_smp_atomic32_cmpxchg_mb erts_no_atomic32_cmpxchg
+
+#define erts_smp_atomic32_init_acqb erts_no_atomic32_set
+#define erts_smp_atomic32_set_acqb erts_no_atomic32_set
+#define erts_smp_atomic32_read_acqb erts_no_atomic32_read
+#define erts_smp_atomic32_inc_read_acqb erts_no_atomic32_inc_read
+#define erts_smp_atomic32_dec_read_acqb erts_no_atomic32_dec_read
+#define erts_smp_atomic32_inc_acqb erts_no_atomic32_inc
+#define erts_smp_atomic32_dec_acqb erts_no_atomic32_dec
+#define erts_smp_atomic32_add_read_acqb erts_no_atomic32_add_read
+#define erts_smp_atomic32_add_acqb erts_no_atomic32_add
+#define erts_smp_atomic32_read_bor_acqb erts_no_atomic32_read_bor
+#define erts_smp_atomic32_read_band_acqb erts_no_atomic32_read_band
+#define erts_smp_atomic32_xchg_acqb erts_no_atomic32_xchg
+#define erts_smp_atomic32_cmpxchg_acqb erts_no_atomic32_cmpxchg
+
+#define erts_smp_atomic32_init_relb erts_no_atomic32_set
+#define erts_smp_atomic32_set_relb erts_no_atomic32_set
+#define erts_smp_atomic32_read_relb erts_no_atomic32_read
+#define erts_smp_atomic32_inc_read_relb erts_no_atomic32_inc_read
+#define erts_smp_atomic32_dec_read_relb erts_no_atomic32_dec_read
+#define erts_smp_atomic32_inc_relb erts_no_atomic32_inc
+#define erts_smp_atomic32_dec_relb erts_no_atomic32_dec
+#define erts_smp_atomic32_add_read_relb erts_no_atomic32_add_read
+#define erts_smp_atomic32_add_relb erts_no_atomic32_add
+#define erts_smp_atomic32_read_bor_relb erts_no_atomic32_read_bor
+#define erts_smp_atomic32_read_band_relb erts_no_atomic32_read_band
+#define erts_smp_atomic32_xchg_relb erts_no_atomic32_xchg
+#define erts_smp_atomic32_cmpxchg_relb erts_no_atomic32_cmpxchg
+
+#define erts_smp_atomic32_init_rb erts_no_atomic32_set
+#define erts_smp_atomic32_set_rb erts_no_atomic32_set
+#define erts_smp_atomic32_read_rb erts_no_atomic32_read
+#define erts_smp_atomic32_inc_read_rb erts_no_atomic32_inc_read
+#define erts_smp_atomic32_dec_read_rb erts_no_atomic32_dec_read
+#define erts_smp_atomic32_inc_rb erts_no_atomic32_inc
+#define erts_smp_atomic32_dec_rb erts_no_atomic32_dec
+#define erts_smp_atomic32_add_read_rb erts_no_atomic32_add_read
+#define erts_smp_atomic32_add_rb erts_no_atomic32_add
+#define erts_smp_atomic32_read_bor_rb erts_no_atomic32_read_bor
+#define erts_smp_atomic32_read_band_rb erts_no_atomic32_read_band
+#define erts_smp_atomic32_xchg_rb erts_no_atomic32_xchg
+#define erts_smp_atomic32_cmpxchg_rb erts_no_atomic32_cmpxchg
+
+#define erts_smp_atomic32_init_wb erts_no_atomic32_set
+#define erts_smp_atomic32_set_wb erts_no_atomic32_set
+#define erts_smp_atomic32_read_wb erts_no_atomic32_read
+#define erts_smp_atomic32_inc_read_wb erts_no_atomic32_inc_read
+#define erts_smp_atomic32_dec_read_wb erts_no_atomic32_dec_read
+#define erts_smp_atomic32_inc_wb erts_no_atomic32_inc
+#define erts_smp_atomic32_dec_wb erts_no_atomic32_dec
+#define erts_smp_atomic32_add_read_wb erts_no_atomic32_add_read
+#define erts_smp_atomic32_add_wb erts_no_atomic32_add
+#define erts_smp_atomic32_read_bor_wb erts_no_atomic32_read_bor
+#define erts_smp_atomic32_read_band_wb erts_no_atomic32_read_band
+#define erts_smp_atomic32_xchg_wb erts_no_atomic32_xchg
+#define erts_smp_atomic32_cmpxchg_wb erts_no_atomic32_cmpxchg
+
+#endif /* !ERTS_SMP */
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
@@ -473,6 +822,16 @@ erts_smp_cnd_wait(erts_smp_cnd_t *cnd, erts_smp_mtx_t *mtx)
#endif
}
+/*
+ * IMPORTANT note about erts_smp_cnd_signal() and erts_smp_cnd_broadcast()
+ *
+ * POSIX allow a call to `pthread_cond_signal' or `pthread_cond_broadcast'
+ * even though the associated mutex/mutexes isn't/aren't locked by the
+ * caller. Our implementation do not allow that in order to avoid a
+ * performance penalty. That is, all associated mutexes *need* to be
+ * locked by the caller of erts_smp_cnd_signal()/erts_smp_cnd_broadcast()!
+ */
+
ERTS_GLB_INLINE void
erts_smp_cnd_signal(erts_smp_cnd_t *cnd)
{
@@ -655,434 +1014,6 @@ erts_smp_lc_rwmtx_is_rwlocked(erts_smp_rwmtx_t *mtx)
}
ERTS_GLB_INLINE void
-erts_smp_atomic_init(erts_smp_atomic_t *var, erts_aint_t i)
-{
-#ifdef ERTS_SMP
- erts_atomic_init(var, i);
-#else
- *var = i;
-#endif
-}
-
-ERTS_GLB_INLINE void
-erts_smp_atomic_set(erts_smp_atomic_t *var, erts_aint_t i)
-{
-#ifdef ERTS_SMP
- erts_atomic_set(var, i);
-#else
- *var = i;
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint_t
-erts_smp_atomic_read(erts_smp_atomic_t *var)
-{
-#ifdef ERTS_SMP
- return erts_atomic_read(var);
-#else
- return *var;
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint_t
-erts_smp_atomic_inctest(erts_smp_atomic_t *incp)
-{
-#ifdef ERTS_SMP
- return erts_atomic_inctest(incp);
-#else
- return ++(*incp);
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint_t
-erts_smp_atomic_dectest(erts_smp_atomic_t *decp)
-{
-#ifdef ERTS_SMP
- return erts_atomic_dectest(decp);
-#else
- return --(*decp);
-#endif
-}
-
-ERTS_GLB_INLINE void
-erts_smp_atomic_inc(erts_smp_atomic_t *incp)
-{
-#ifdef ERTS_SMP
- erts_atomic_inc(incp);
-#else
- ++(*incp);
-#endif
-}
-
-ERTS_GLB_INLINE void
-erts_smp_atomic_dec(erts_smp_atomic_t *decp)
-{
-#ifdef ERTS_SMP
- erts_atomic_dec(decp);
-#else
- --(*decp);
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint_t
-erts_smp_atomic_addtest(erts_smp_atomic_t *addp, erts_aint_t i)
-{
-#ifdef ERTS_SMP
- return erts_atomic_addtest(addp, i);
-#else
- return *addp += i;
-#endif
-}
-
-ERTS_GLB_INLINE void
-erts_smp_atomic_add(erts_smp_atomic_t *addp, erts_aint_t i)
-{
-#ifdef ERTS_SMP
- erts_atomic_add(addp, i);
-#else
- *addp += i;
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint_t
-erts_smp_atomic_xchg(erts_smp_atomic_t *xchgp, erts_aint_t new)
-{
-#ifdef ERTS_SMP
- return erts_atomic_xchg(xchgp, new);
-#else
- erts_aint_t old;
- old = *xchgp;
- *xchgp = new;
- return old;
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint_t
-erts_smp_atomic_cmpxchg(erts_smp_atomic_t *xchgp,
- erts_aint_t new,
- erts_aint_t expected)
-{
-#ifdef ERTS_SMP
- return erts_atomic_cmpxchg(xchgp, new, expected);
-#else
- erts_aint_t old = *xchgp;
- if (old == expected)
- *xchgp = new;
- return old;
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint_t
-erts_smp_atomic_bor(erts_smp_atomic_t *var, erts_aint_t mask)
-{
-#ifdef ERTS_SMP
- return erts_atomic_bor(var, mask);
-#else
- erts_aint_t old;
- old = *var;
- *var |= mask;
- return old;
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint_t
-erts_smp_atomic_band(erts_smp_atomic_t *var, erts_aint_t mask)
-{
-#ifdef ERTS_SMP
- return erts_atomic_band(var, mask);
-#else
- erts_aint_t old;
- old = *var;
- *var &= mask;
- return old;
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint_t
-erts_smp_atomic_read_acqb(erts_smp_atomic_t *var)
-{
-#ifdef ERTS_SMP
- return erts_atomic_read_acqb(var);
-#else
- return *var;
-#endif
-}
-
-ERTS_GLB_INLINE void
-erts_smp_atomic_set_relb(erts_smp_atomic_t *var, erts_aint_t i)
-{
-#ifdef ERTS_SMP
- erts_atomic_set_relb(var, i);
-#else
- *var = i;
-#endif
-}
-
-ERTS_GLB_INLINE void
-erts_smp_atomic_dec_relb(erts_smp_atomic_t *decp)
-{
-#ifdef ERTS_SMP
- erts_atomic_dec_relb(decp);
-#else
- --(*decp);
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint_t
-erts_smp_atomic_dectest_relb(erts_smp_atomic_t *decp)
-{
-#ifdef ERTS_SMP
- return erts_atomic_dectest_relb(decp);
-#else
- return --(*decp);
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint_t
-erts_smp_atomic_cmpxchg_acqb(erts_smp_atomic_t *xchgp,
- erts_aint_t new,
- erts_aint_t exp)
-{
-#ifdef ERTS_SMP
- return erts_atomic_cmpxchg_acqb(xchgp, new, exp);
-#else
- erts_aint_t old = *xchgp;
- if (old == exp)
- *xchgp = new;
- return old;
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint_t
-erts_smp_atomic_cmpxchg_relb(erts_smp_atomic_t *xchgp,
- erts_aint_t new,
- erts_aint_t exp)
-{
-#ifdef ERTS_SMP
- return erts_atomic_cmpxchg_relb(xchgp, new, exp);
-#else
- erts_aint_t old = *xchgp;
- if (old == exp)
- *xchgp = new;
- return old;
-#endif
-}
-
-ERTS_GLB_INLINE void
-erts_smp_atomic32_init(erts_smp_atomic32_t *var, erts_aint32_t i)
-{
-#ifdef ERTS_SMP
- erts_atomic32_init(var, i);
-#else
- *var = i;
-#endif
-}
-
-ERTS_GLB_INLINE void
-erts_smp_atomic32_set(erts_smp_atomic32_t *var, erts_aint32_t i)
-{
-#ifdef ERTS_SMP
- erts_atomic32_set(var, i);
-#else
- *var = i;
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint32_t
-erts_smp_atomic32_read(erts_smp_atomic32_t *var)
-{
-#ifdef ERTS_SMP
- return erts_atomic32_read(var);
-#else
- return *var;
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint32_t
-erts_smp_atomic32_inctest(erts_smp_atomic32_t *incp)
-{
-#ifdef ERTS_SMP
- return erts_atomic32_inctest(incp);
-#else
- return ++(*incp);
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint32_t
-erts_smp_atomic32_dectest(erts_smp_atomic32_t *decp)
-{
-#ifdef ERTS_SMP
- return erts_atomic32_dectest(decp);
-#else
- return --(*decp);
-#endif
-}
-
-ERTS_GLB_INLINE void
-erts_smp_atomic32_inc(erts_smp_atomic32_t *incp)
-{
-#ifdef ERTS_SMP
- erts_atomic32_inc(incp);
-#else
- ++(*incp);
-#endif
-}
-
-ERTS_GLB_INLINE void
-erts_smp_atomic32_dec(erts_smp_atomic32_t *decp)
-{
-#ifdef ERTS_SMP
- erts_atomic32_dec(decp);
-#else
- --(*decp);
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint32_t
-erts_smp_atomic32_addtest(erts_smp_atomic32_t *addp, erts_aint32_t i)
-{
-#ifdef ERTS_SMP
- return erts_atomic32_addtest(addp, i);
-#else
- return *addp += i;
-#endif
-}
-
-ERTS_GLB_INLINE void
-erts_smp_atomic32_add(erts_smp_atomic32_t *addp, erts_aint32_t i)
-{
-#ifdef ERTS_SMP
- erts_atomic32_add(addp, i);
-#else
- *addp += i;
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint32_t
-erts_smp_atomic32_xchg(erts_smp_atomic32_t *xchgp, erts_aint32_t new)
-{
-#ifdef ERTS_SMP
- return erts_atomic32_xchg(xchgp, new);
-#else
- erts_aint32_t old;
- old = *xchgp;
- *xchgp = new;
- return old;
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint32_t
-erts_smp_atomic32_cmpxchg(erts_smp_atomic32_t *xchgp,
- erts_aint32_t new,
- erts_aint32_t expected)
-{
-#ifdef ERTS_SMP
- return erts_atomic32_cmpxchg(xchgp, new, expected);
-#else
- erts_aint32_t old = *xchgp;
- if (old == expected)
- *xchgp = new;
- return old;
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint32_t
-erts_smp_atomic32_bor(erts_smp_atomic32_t *var, erts_aint32_t mask)
-{
-#ifdef ERTS_SMP
- return erts_atomic32_bor(var, mask);
-#else
- erts_aint32_t old;
- old = *var;
- *var |= mask;
- return old;
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint32_t
-erts_smp_atomic32_band(erts_smp_atomic32_t *var, erts_aint32_t mask)
-{
-#ifdef ERTS_SMP
- return erts_atomic32_band(var, mask);
-#else
- erts_aint32_t old;
- old = *var;
- *var &= mask;
- return old;
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint32_t
-erts_smp_atomic32_read_acqb(erts_smp_atomic32_t *var)
-{
-#ifdef ERTS_SMP
- return erts_atomic32_read_acqb(var);
-#else
- return *var;
-#endif
-}
-
-ERTS_GLB_INLINE void
-erts_smp_atomic32_set_relb(erts_smp_atomic32_t *var, erts_aint32_t i)
-{
-#ifdef ERTS_SMP
- erts_atomic32_set_relb(var, i);
-#else
- *var = i;
-#endif
-}
-
-ERTS_GLB_INLINE void
-erts_smp_atomic32_dec_relb(erts_smp_atomic32_t *decp)
-{
-#ifdef ERTS_SMP
- erts_atomic32_dec_relb(decp);
-#else
- --(*decp);
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint32_t
-erts_smp_atomic32_dectest_relb(erts_smp_atomic32_t *decp)
-{
-#ifdef ERTS_SMP
- return erts_atomic32_dectest_relb(decp);
-#else
- return --(*decp);
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint32_t
-erts_smp_atomic32_cmpxchg_acqb(erts_smp_atomic32_t *xchgp,
- erts_aint32_t new,
- erts_aint32_t exp)
-{
-#ifdef ERTS_SMP
- return erts_atomic32_cmpxchg_acqb(xchgp, new, exp);
-#else
- erts_aint32_t old = *xchgp;
- if (old == exp)
- *xchgp = new;
- return old;
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint32_t
-erts_smp_atomic32_cmpxchg_relb(erts_smp_atomic32_t *xchgp,
- erts_aint32_t new,
- erts_aint32_t exp)
-{
-#ifdef ERTS_SMP
- return erts_atomic32_cmpxchg_relb(xchgp, new, exp);
-#else
- erts_aint32_t old = *xchgp;
- if (old == exp)
- *xchgp = new;
- return old;
-#endif
-}
-
-ERTS_GLB_INLINE void
erts_smp_spinlock_init_x(erts_smp_spinlock_t *lock, char *name, Eterm extra)
{
#ifdef ERTS_SMP
@@ -1308,3 +1239,37 @@ erts_smp_thr_sigwait(const sigset_t *set, int *sig)
#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */
#endif /* ERL_SMP_H */
+
+#ifdef ERTS_UNDEF_DEPRECATED_ATOMICS
+
+/* Deprecated functions to replace */
+
+#undef erts_smp_atomic_init
+#undef erts_smp_atomic_set
+#undef erts_smp_atomic_read
+#undef erts_smp_atomic_inctest
+#undef erts_smp_atomic_dectest
+#undef erts_smp_atomic_inc
+#undef erts_smp_atomic_dec
+#undef erts_smp_atomic_addtest
+#undef erts_smp_atomic_add
+#undef erts_smp_atomic_xchg
+#undef erts_smp_atomic_cmpxchg
+#undef erts_smp_atomic_bor
+#undef erts_smp_atomic_band
+
+#undef erts_smp_atomic32_init
+#undef erts_smp_atomic32_set
+#undef erts_smp_atomic32_read
+#undef erts_smp_atomic32_inctest
+#undef erts_smp_atomic32_dectest
+#undef erts_smp_atomic32_inc
+#undef erts_smp_atomic32_dec
+#undef erts_smp_atomic32_addtest
+#undef erts_smp_atomic32_add
+#undef erts_smp_atomic32_xchg
+#undef erts_smp_atomic32_cmpxchg
+#undef erts_smp_atomic32_bor
+#undef erts_smp_atomic32_band
+
+#endif
diff --git a/erts/emulator/beam/erl_term.h b/erts/emulator/beam/erl_term.h
index 1d75fa313c..bc20b2d798 100644
--- a/erts/emulator/beam/erl_term.h
+++ b/erts/emulator/beam/erl_term.h
@@ -331,7 +331,13 @@ _ET_DECLARE_CHECKED(Uint,thing_subtag,Eterm)
* we now use a non-zero bit-pattern in debug mode.
*/
#if ET_DEBUG
-#define THE_NON_VALUE _make_header(0,_TAG_HEADER_FLOAT)
+# ifdef HIPE
+ /* A very large (or negative) value as work-around for ugly hipe-bifs
+ that return untagged integers (eg hipe_bs_put_utf8) */
+# define THE_NON_VALUE _make_header((Uint)~0,_TAG_HEADER_FLOAT)
+# else
+# define THE_NON_VALUE _make_header(0,_TAG_HEADER_FLOAT)
+# endif
#else
#define THE_NON_VALUE (0)
#endif
diff --git a/erts/emulator/beam/erl_thr_progress.c b/erts/emulator/beam/erl_thr_progress.c
new file mode 100644
index 0000000000..9324bcde51
--- /dev/null
+++ b/erts/emulator/beam/erl_thr_progress.c
@@ -0,0 +1,1373 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description: Thread progress information. Used by lock free algorithms
+ * to determine when all involved threads are guaranteed to
+ * have passed a specific point of execution.
+ *
+ * Usage instructions below.
+ *
+ * Author: Rickard Green
+ */
+
+/*
+ * ------ Usage instructions -----------------------------------------------
+ *
+ * This module keeps track of the progress of a set of managed threads. Only
+ * threads that behave well can be allowed to be managed. A managed thread
+ * should update its thread progress frequently. Currently only scheduler
+ * threads and the aux_thread are managed threads. We typically do not want
+ * any async threads as managed threads since they cannot guarantee a
+ * frequent update of thread progress, since they execute user implemented
+ * driver code.
+ *
+ * erts_thr_progress_current() returns the global current thread progress
+ * value of managed threads. I.e., the latest progress value that all
+ * managed threads have reached. Thread progress values are opaque.
+ *
+ * erts_thr_progress_has_reached(VAL) returns a value != 0 if current
+ * global thread progress has reached or passed VAL.
+ *
+ * erts_thr_progress_later() returns a thread progress value in the future
+ * which no managed thread have yet reached.
+ *
+ * All threads issue a full memory barrier when reaching a new thread
+ * progress value. They only reach new thread progress values in specific
+ * controlled states when calling erts_thr_progress_update(). Schedulers
+ * call erts_thr_progress_update() in between execution of processes,
+ * when going to sleep and when waking up.
+ *
+ * Sleeping managed threads are considered to have reached next thread
+ * progress value immediately. They are not woken and do therefore not
+ * issue any memory barriers when reaching a new thread progress value.
+ * A sleeping thread do however immediately issue a memory barrier upon
+ * wakeup.
+ *
+ * Both managed and registered unmanaged threads may request wakeup when
+ * the global thread progress reach a certain value using
+ * erts_thr_progress_wakeup().
+ *
+ * Note that thread progress values are opaque, and that you are only
+ * allowed to use thread progress values retrieved from this API!
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stddef.h> /* offsetof() */
+#include "erl_thr_progress.h"
+#include "global.h"
+
+#ifdef ERTS_SMP
+
+/*
+ * We use a 64-bit value for thread progress. By this wrapping of
+ * the thread progress will more or less never occur.
+ *
+ * On 32-bit systems we therefore need a double word atomic.
+ */
+
+#define ERTS_THR_PRGR_PRINT_LEADER 0
+#define ERTS_THR_PRGR_PRINT_VAL 0
+#define ERTS_THR_PRGR_PRINT_BLOCKERS 0
+
+#define ERTS_THR_PRGR_FTL_ERR_BLCK_POLL_INTERVAL 100
+
+#define ERTS_THR_PRGR_LFLG_BLOCK (((erts_aint32_t) 1) << 31)
+#define ERTS_THR_PRGR_LFLG_NO_LEADER (((erts_aint32_t) 1) << 30)
+#define ERTS_THR_PRGR_LFLG_ACTIVE_MASK (~(ERTS_THR_PRGR_LFLG_NO_LEADER \
+ | ERTS_THR_PRGR_LFLG_BLOCK))
+
+#define ERTS_THR_PRGR_LFLGS_ACTIVE(LFLGS) \
+ ((LFLGS) & ERTS_THR_PRGR_LFLG_ACTIVE_MASK)
+
+#define ERTS_THR_PRGR_LFLGS_ALL_WAITING(LFLGS) \
+ (((LFLGS) & (ERTS_THR_PRGR_LFLG_NO_LEADER \
+ |ERTS_THR_PRGR_LFLG_ACTIVE_MASK)) \
+ == ERTS_THR_PRGR_LFLG_NO_LEADER)
+
+#define read_acqb erts_thr_prgr_read_acqb__
+
+#ifdef ARCH_64
+
+static ERTS_INLINE void
+set_mb(ERTS_THR_PRGR_ATOMIC *atmc, ErtsThrPrgrVal val)
+{
+ erts_atomic_set_mb(atmc, val);
+}
+
+static ERTS_INLINE void
+set_nob(ERTS_THR_PRGR_ATOMIC *atmc, ErtsThrPrgrVal val)
+{
+ erts_atomic_set_nob(atmc, val);
+}
+
+static ERTS_INLINE ErtsThrPrgrVal
+read_nob(ERTS_THR_PRGR_ATOMIC *atmc)
+{
+ return (ErtsThrPrgrVal) erts_atomic_read_nob(atmc);
+}
+
+static ERTS_INLINE void
+init_nob(ERTS_THR_PRGR_ATOMIC *atmc, ErtsThrPrgrVal val)
+{
+ erts_atomic_init_nob(atmc, val);
+}
+
+#else
+
+#undef dw_sint_to_val
+#define dw_sint_to_val erts_thr_prgr_dw_sint_to_val__
+
+static void
+val_to_dw_sint(ethr_dw_sint_t *dw_sint, ErtsThrPrgrVal val)
+{
+#ifdef ETHR_SU_DW_NAINT_T__
+ dw_sint->dw_sint = (ETHR_SU_DW_NAINT_T__) val;
+#else
+ dw_sint->sint[ETHR_DW_SINT_LOW_WORD]
+ = (ethr_sint_t) (val & 0xffffffff);
+ dw_sint->sint[ETHR_DW_SINT_HIGH_WORD]
+ = (ethr_sint_t) ((val >> 32) & 0xffffffff);
+#endif
+}
+
+static ERTS_INLINE void
+set_mb(ERTS_THR_PRGR_ATOMIC *atmc, ErtsThrPrgrVal val)
+{
+ ethr_dw_sint_t dw_sint;
+ val_to_dw_sint(&dw_sint, val);
+ erts_dw_atomic_set_mb(atmc, &dw_sint);
+}
+
+static ERTS_INLINE void
+set_nob(ERTS_THR_PRGR_ATOMIC *atmc, ErtsThrPrgrVal val)
+{
+ ethr_dw_sint_t dw_sint;
+ val_to_dw_sint(&dw_sint, val);
+ erts_dw_atomic_set_nob(atmc, &dw_sint);
+}
+
+static ERTS_INLINE ErtsThrPrgrVal
+read_nob(ERTS_THR_PRGR_ATOMIC *atmc)
+{
+ ethr_dw_sint_t dw_sint;
+ erts_dw_atomic_read_nob(atmc, &dw_sint);
+ return erts_thr_prgr_dw_sint_to_val__(&dw_sint);
+}
+
+static ERTS_INLINE void
+init_nob(ERTS_THR_PRGR_ATOMIC *atmc, ErtsThrPrgrVal val)
+{
+ ethr_dw_sint_t dw_sint;
+ val_to_dw_sint(&dw_sint, val);
+ erts_dw_atomic_init_nob(atmc, &dw_sint);
+}
+
+#endif
+
+/* #define ERTS_THR_PROGRESS_STATE_DEBUG */
+
+#ifdef ERTS_THR_PROGRESS_STATE_DEBUG
+
+#ifdef __GNUC__
+#warning "Thread progress state debug is on"
+#endif
+
+#define ERTS_THR_PROGRESS_STATE_DEBUG_LEADER (((erts_aint32_t) 1) << 0)
+#define ERTS_THR_PROGRESS_STATE_DEBUG_ACTIVE (((erts_aint32_t) 1) << 1)
+
+#define ERTS_THR_PROGRESS_STATE_DEBUG_INIT(ID) \
+ erts_atomic32_init_nob(&intrnl->thr[(ID)].data.state_debug, \
+ ERTS_THR_PROGRESS_STATE_DEBUG_ACTIVE)
+
+#define ERTS_THR_PROGRESS_STATE_DEBUG_SET_ACTIVE(ID, ON) \
+do { \
+ erts_aint32_t state_debug__; \
+ state_debug__ = erts_atomic32_read_nob(&intrnl->thr[(ID)].data.state_debug); \
+ if ((ON)) \
+ state_debug__ |= ERTS_THR_PROGRESS_STATE_DEBUG_ACTIVE; \
+ else \
+ state_debug__ &= ~ERTS_THR_PROGRESS_STATE_DEBUG_ACTIVE; \
+ erts_atomic32_set_nob(&intrnl->thr[(ID)].data.state_debug, state_debug__); \
+} while (0)
+
+#define ERTS_THR_PROGRESS_STATE_DEBUG_SET_LEADER(ID, ON) \
+do { \
+ erts_aint32_t state_debug__; \
+ state_debug__ = erts_atomic32_read_nob(&intrnl->thr[(ID)].data.state_debug); \
+ if ((ON)) \
+ state_debug__ |= ERTS_THR_PROGRESS_STATE_DEBUG_LEADER; \
+ else \
+ state_debug__ &= ~ERTS_THR_PROGRESS_STATE_DEBUG_LEADER; \
+ erts_atomic32_set_nob(&intrnl->thr[(ID)].data.state_debug, state_debug__); \
+} while (0)
+
+#else
+
+#define ERTS_THR_PROGRESS_STATE_DEBUG_INIT(ID)
+#define ERTS_THR_PROGRESS_STATE_DEBUG_SET_ACTIVE(ID, ON)
+#define ERTS_THR_PROGRESS_STATE_DEBUG_SET_LEADER(ID, ON)
+
+#endif /* ERTS_THR_PROGRESS_STATE_DEBUG */
+
+#define ERTS_THR_PRGR_BLCKR_INVALID (~((erts_aint32_t) 0))
+#define ERTS_THR_PRGR_BLCKR_UNMANAGED (((erts_aint32_t) 1) << 31)
+
+#define ERTS_THR_PRGR_BC_FLG_NOT_BLOCKING (((erts_aint32_t) 1) << 31)
+
+#define ERTS_THR_PRGR_BM_BITS 32
+#define ERTS_THR_PRGR_BM_SHIFT 5
+#define ERTS_THR_PRGR_BM_MASK 0x1f
+
+#define ERTS_THR_PRGR_WAKEUP_DATA_MASK (ERTS_THR_PRGR_WAKEUP_DATA_SIZE - 1)
+
+#define ERTS_THR_PRGR_WAKEUP_IX(V) \
+ ((int) ((V) & ERTS_THR_PRGR_WAKEUP_DATA_MASK))
+
+typedef struct {
+ erts_atomic32_t len;
+ int id[1];
+} ErtsThrPrgrManagedWakeupData;
+
+typedef struct {
+ erts_atomic32_t len;
+ int high_sz;
+ int low_sz;
+ erts_atomic32_t *high;
+ erts_atomic32_t *low;
+} ErtsThrPrgrUnmanagedWakeupData;
+
+typedef struct {
+ erts_atomic32_t lflgs;
+ erts_atomic32_t block_count;
+ erts_atomic_t blocker_event;
+ erts_atomic32_t pref_wakeup_used;
+ erts_atomic32_t managed_count;
+ erts_atomic32_t managed_id;
+ erts_atomic32_t unmanaged_id;
+} ErtsThrPrgrMiscData;
+
+typedef struct {
+ ERTS_THR_PRGR_ATOMIC current;
+#ifdef ERTS_THR_PROGRESS_STATE_DEBUG
+ erts_atomic32_t state_debug;
+#endif
+} ErtsThrPrgrElement;
+
+typedef union {
+ ErtsThrPrgrElement data;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsThrPrgrElement))];
+} ErtsThrPrgrArray;
+
+typedef struct {
+ union {
+ ErtsThrPrgrMiscData data;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(
+ sizeof(ErtsThrPrgrMiscData))];
+ } misc;
+ ErtsThrPrgrArray *thr;
+ struct {
+ int no;
+ ErtsThrPrgrCallbacks *callbacks;
+ ErtsThrPrgrManagedWakeupData *data[ERTS_THR_PRGR_WAKEUP_DATA_SIZE];
+ } managed;
+ struct {
+ int no;
+ ErtsThrPrgrCallbacks *callbacks;
+ ErtsThrPrgrUnmanagedWakeupData *data[ERTS_THR_PRGR_WAKEUP_DATA_SIZE];
+ } unmanaged;
+} ErtsThrPrgrInternalData;
+
+static ErtsThrPrgrInternalData *intrnl;
+
+ErtsThrPrgr erts_thr_prgr__;
+
+erts_tsd_key_t erts_thr_prgr_data_key__;
+
+static void handle_wakeup_requests(ErtsThrPrgrVal current);
+static int got_sched_wakeups(void);
+static erts_aint32_t block_thread(ErtsThrPrgrData *tpd);
+
+static ERTS_INLINE void
+wakeup_managed(int id)
+{
+ ErtsThrPrgrCallbacks *cbp = &intrnl->managed.callbacks[id];
+ ASSERT(0 <= id && id < intrnl->managed.no);
+ cbp->wakeup(cbp->arg);
+}
+
+
+static ERTS_INLINE void
+wakeup_unmanaged(int id)
+{
+ ErtsThrPrgrCallbacks *cbp = &intrnl->unmanaged.callbacks[id];
+ ASSERT(0 <= id && id < intrnl->unmanaged.no);
+ cbp->wakeup(cbp->arg);
+}
+
+static ERTS_INLINE ErtsThrPrgrData *
+perhaps_thr_prgr_data(ErtsSchedulerData *esdp)
+{
+ if (esdp)
+ return &esdp->thr_progress_data;
+ else
+ return erts_tsd_get(erts_thr_prgr_data_key__);
+}
+
+static ERTS_INLINE ErtsThrPrgrData *
+thr_prgr_data(ErtsSchedulerData *esdp)
+{
+ ErtsThrPrgrData *tpd = perhaps_thr_prgr_data(esdp);
+ ASSERT(tpd);
+ return tpd;
+}
+
+static void
+init_tmp_thr_prgr_data(ErtsThrPrgrData *tpd)
+{
+ tpd->id = -1;
+ tpd->is_managed = 0;
+ tpd->is_blocking = 0;
+ tpd->is_temporary = 1;
+
+ erts_tsd_set(erts_thr_prgr_data_key__, (void *) tpd);
+}
+
+static ERTS_INLINE ErtsThrPrgrData *
+tmp_thr_prgr_data(ErtsSchedulerData *esdp)
+{
+ ErtsThrPrgrData *tpd = perhaps_thr_prgr_data(esdp);
+
+ if (!tpd) {
+ /*
+ * We only allocate the part up to the wakeup_request field
+ * which is the first field only used by registered threads
+ */
+ tpd = erts_alloc(ERTS_ALC_T_T_THR_PRGR_DATA,
+ offsetof(ErtsThrPrgrData, wakeup_request));
+ init_tmp_thr_prgr_data(tpd);
+ }
+
+ return tpd;
+}
+
+static ERTS_INLINE void
+return_tmp_thr_prgr_data(ErtsThrPrgrData *tpd)
+{
+ if (tpd->is_temporary) {
+ erts_tsd_set(erts_thr_prgr_data_key__, NULL);
+ erts_free(ERTS_ALC_T_T_THR_PRGR_DATA, tpd);
+ }
+}
+
+static ERTS_INLINE int
+block_count_dec(void)
+{
+ erts_aint32_t block_count;
+ block_count = erts_atomic32_dec_read_mb(&intrnl->misc.data.block_count);
+ if (block_count == 0) {
+ erts_tse_t *event;
+ event = ((erts_tse_t*)
+ erts_atomic_read_nob(&intrnl->misc.data.blocker_event));
+ if (event)
+ erts_tse_set(event);
+ return 1;
+ }
+
+ return (block_count & ERTS_THR_PRGR_BC_FLG_NOT_BLOCKING) == 0;
+}
+
+static ERTS_INLINE int
+block_count_inc(void)
+{
+ erts_aint32_t block_count;
+ block_count = erts_atomic32_inc_read_mb(&intrnl->misc.data.block_count);
+ return (block_count & ERTS_THR_PRGR_BC_FLG_NOT_BLOCKING) == 0;
+}
+
+
+void
+erts_thr_progress_pre_init(void)
+{
+ intrnl = NULL;
+ erts_tsd_key_create(&erts_thr_prgr_data_key__);
+ init_nob(&erts_thr_prgr__.current, 0);
+}
+
+void
+erts_thr_progress_init(int no_schedulers, int managed, int unmanaged)
+{
+ int i, j, um_low, um_high;
+ char *ptr;
+ size_t cb_sz, intrnl_sz, thr_arr_sz, m_wakeup_size, um_wakeup_size,
+ tot_size;
+
+ intrnl_sz = sizeof(ErtsThrPrgrInternalData);
+ intrnl_sz = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(intrnl_sz);
+
+ cb_sz = sizeof(ErtsThrPrgrCallbacks)*(managed+unmanaged);
+ cb_sz = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(cb_sz);
+
+ thr_arr_sz = sizeof(ErtsThrPrgrArray)*managed;
+ ASSERT(thr_arr_sz == ERTS_ALC_CACHE_LINE_ALIGN_SIZE(thr_arr_sz));
+
+ m_wakeup_size = sizeof(ErtsThrPrgrManagedWakeupData);
+ m_wakeup_size += (managed - 1)*sizeof(int);
+ m_wakeup_size = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(m_wakeup_size);
+
+ um_low = (unmanaged - 1)/ERTS_THR_PRGR_BM_BITS + 1;
+ um_high = (um_low - 1)/ERTS_THR_PRGR_BM_BITS + 1;
+
+ um_wakeup_size = sizeof(ErtsThrPrgrUnmanagedWakeupData);
+ um_wakeup_size += (um_high + um_low)*sizeof(erts_atomic32_t);
+ um_wakeup_size = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(um_wakeup_size);
+
+ tot_size = intrnl_sz;
+ tot_size += cb_sz;
+ tot_size += thr_arr_sz;
+ tot_size += m_wakeup_size*ERTS_THR_PRGR_WAKEUP_DATA_SIZE;
+ tot_size += um_wakeup_size*ERTS_THR_PRGR_WAKEUP_DATA_SIZE;
+
+ ptr = erts_alloc_permanent_cache_aligned(ERTS_ALC_T_THR_PRGR_IDATA,
+ tot_size);
+
+ intrnl = (ErtsThrPrgrInternalData *) ptr;
+ ptr += intrnl_sz;
+
+ erts_atomic32_init_nob(&intrnl->misc.data.lflgs,
+ ERTS_THR_PRGR_LFLG_NO_LEADER);
+ erts_atomic32_init_nob(&intrnl->misc.data.block_count,
+ (ERTS_THR_PRGR_BC_FLG_NOT_BLOCKING
+ | (erts_aint32_t) managed));
+ erts_atomic_init_nob(&intrnl->misc.data.blocker_event, ERTS_AINT_NULL);
+ erts_atomic32_init_nob(&intrnl->misc.data.pref_wakeup_used, 0);
+ erts_atomic32_init_nob(&intrnl->misc.data.managed_count, 0);
+ erts_atomic32_init_nob(&intrnl->misc.data.managed_id, no_schedulers);
+ erts_atomic32_init_nob(&intrnl->misc.data.unmanaged_id, -1);
+
+ intrnl->thr = (ErtsThrPrgrArray *) ptr;
+ ptr += thr_arr_sz;
+ for (i = 0; i < managed; i++)
+ init_nob(&intrnl->thr[i].data.current, 0);
+
+ intrnl->managed.callbacks = (ErtsThrPrgrCallbacks *) ptr;
+ intrnl->unmanaged.callbacks = &intrnl->managed.callbacks[managed];
+ ptr += cb_sz;
+
+ intrnl->managed.no = managed;
+ for (i = 0; i < managed; i++) {
+ intrnl->managed.callbacks[i].arg = NULL;
+ intrnl->managed.callbacks[i].wakeup = NULL;
+ }
+
+ intrnl->unmanaged.no = unmanaged;
+ for (i = 0; i < unmanaged; i++) {
+ intrnl->unmanaged.callbacks[i].arg = NULL;
+ intrnl->unmanaged.callbacks[i].wakeup = NULL;
+ }
+
+ for (i = 0; i < ERTS_THR_PRGR_WAKEUP_DATA_SIZE; i++) {
+ intrnl->managed.data[i] = (ErtsThrPrgrManagedWakeupData *) ptr;
+ erts_atomic32_init_nob(&intrnl->managed.data[i]->len, 0);
+ ptr += m_wakeup_size;
+ }
+
+ for (i = 0; i < ERTS_THR_PRGR_WAKEUP_DATA_SIZE; i++) {
+ erts_atomic32_t *bm;
+ intrnl->unmanaged.data[i] = (ErtsThrPrgrUnmanagedWakeupData *) ptr;
+ erts_atomic32_init_nob(&intrnl->unmanaged.data[i]->len, 0);
+ bm = (erts_atomic32_t *) (ptr + sizeof(ErtsThrPrgrUnmanagedWakeupData));
+ intrnl->unmanaged.data[i]->high = bm;
+ intrnl->unmanaged.data[i]->high_sz = um_high;
+ for (j = 0; j < um_high; j++)
+ erts_atomic32_init_nob(&intrnl->unmanaged.data[i]->high[j], 0);
+ intrnl->unmanaged.data[i]->low
+ = &intrnl->unmanaged.data[i]->high[um_high];
+ intrnl->unmanaged.data[i]->low_sz = um_low;
+ for (j = 0; j < um_low; j++)
+ erts_atomic32_init_nob(&intrnl->unmanaged.data[i]->low[j], 0);
+ ptr += um_wakeup_size;
+ }
+ ERTS_THR_MEMORY_BARRIER;
+}
+
+static void
+init_wakeup_request_array(ErtsThrPrgrVal *w)
+{
+ int i;
+ ErtsThrPrgrVal current;
+
+ current = read_acqb(&erts_thr_prgr__.current);
+ for (i = 0; i < ERTS_THR_PRGR_WAKEUP_DATA_SIZE; i++) {
+ w[i] = current - ((ErtsThrPrgrVal) (ERTS_THR_PRGR_WAKEUP_DATA_SIZE + i));
+ if (w[i] > current)
+ w[i]--;
+ }
+}
+
+void
+erts_thr_progress_register_unmanaged_thread(ErtsThrPrgrCallbacks *callbacks)
+{
+ ErtsThrPrgrData *tpd = perhaps_thr_prgr_data(NULL);
+ int is_blocking = 0;
+
+ if (tpd) {
+ if (!tpd->is_temporary)
+ erl_exit(ERTS_ABORT_EXIT,
+ "%s:%d:%s(): Double register of thread\n",
+ __FILE__, __LINE__, __func__);
+ is_blocking = tpd->is_blocking;
+ return_tmp_thr_prgr_data(tpd);
+ }
+
+ /*
+ * We only allocate the part up to the leader field
+ * which is the first field only used by managed threads
+ */
+ tpd = erts_alloc(ERTS_ALC_T_THR_PRGR_DATA,
+ offsetof(ErtsThrPrgrData, leader));
+ tpd->id = (int) erts_atomic32_inc_read_nob(&intrnl->misc.data.unmanaged_id);
+ tpd->is_managed = 0;
+ tpd->is_blocking = is_blocking;
+ tpd->is_temporary = 0;
+ ASSERT(tpd->id >= 0);
+ if (tpd->id >= intrnl->unmanaged.no)
+ erl_exit(ERTS_ABORT_EXIT,
+ "%s:%d:%s(): Too many unmanaged registered threads\n",
+ __FILE__, __LINE__, __func__);
+
+ init_wakeup_request_array(&tpd->wakeup_request[0]);
+ erts_tsd_set(erts_thr_prgr_data_key__, (void *) tpd);
+
+ ASSERT(callbacks->wakeup);
+
+ intrnl->unmanaged.callbacks[tpd->id] = *callbacks;
+}
+
+
+void
+erts_thr_progress_register_managed_thread(ErtsSchedulerData *esdp,
+ ErtsThrPrgrCallbacks *callbacks,
+ int pref_wakeup)
+{
+ ErtsThrPrgrData *tpd = perhaps_thr_prgr_data(NULL);
+ int is_blocking = 0, managed;
+
+ if (tpd) {
+ if (!tpd->is_temporary)
+ erl_exit(ERTS_ABORT_EXIT,
+ "%s:%d:%s(): Double register of thread\n",
+ __FILE__, __LINE__, __func__);
+ is_blocking = tpd->is_blocking;
+ return_tmp_thr_prgr_data(tpd);
+ }
+
+ if (esdp)
+ tpd = &esdp->thr_progress_data;
+ else
+ tpd = erts_alloc(ERTS_ALC_T_THR_PRGR_DATA, sizeof(ErtsThrPrgrData));
+
+ if (pref_wakeup
+ && !erts_atomic32_xchg_nob(&intrnl->misc.data.pref_wakeup_used, 1))
+ tpd->id = 0;
+ else if (esdp)
+ tpd->id = (int) esdp->no;
+ else
+ tpd->id = erts_atomic32_inc_read_nob(&intrnl->misc.data.managed_id);
+ ASSERT(tpd->id >= 0);
+ if (tpd->id >= intrnl->managed.no)
+ erl_exit(ERTS_ABORT_EXIT,
+ "%s:%d:%s(): Too many managed registered threads\n",
+ __FILE__, __LINE__, __func__);
+
+ tpd->is_managed = 1;
+ tpd->is_blocking = is_blocking;
+ tpd->is_temporary = 0;
+
+ init_wakeup_request_array(&tpd->wakeup_request[0]);
+
+ ERTS_THR_PROGRESS_STATE_DEBUG_INIT(tpd->id);
+
+ tpd->leader = 0;
+ tpd->active = 1;
+ tpd->previous.local = 0;
+ tpd->previous.current = ERTS_THR_PRGR_VAL_WAITING;
+ erts_tsd_set(erts_thr_prgr_data_key__, (void *) tpd);
+
+ erts_atomic32_inc_nob(&intrnl->misc.data.lflgs);
+
+ ASSERT(callbacks->wakeup);
+ ASSERT(callbacks->prepare_wait);
+ ASSERT(callbacks->wait);
+ ASSERT(callbacks->finalize_wait);
+
+ intrnl->managed.callbacks[tpd->id] = *callbacks;
+
+ callbacks->prepare_wait(callbacks->arg);
+ managed = erts_atomic32_inc_read_relb(&intrnl->misc.data.managed_count);
+ if (managed != intrnl->managed.no) {
+ /* Wait until all managed threads have registered... */
+ do {
+ callbacks->wait(callbacks->arg);
+ callbacks->prepare_wait(callbacks->arg);
+ managed = erts_atomic32_read_acqb(&intrnl->misc.data.managed_count);
+ } while (managed != intrnl->managed.no);
+ }
+ else {
+ int id;
+ /* All managed threads have registered; lets go... */
+ for (id = 0; id < managed; id++)
+ if (id != tpd->id)
+ wakeup_managed(id);
+ }
+ callbacks->finalize_wait(callbacks->arg);
+}
+
+static ERTS_INLINE int
+leader_update(ErtsThrPrgrData *tpd)
+{
+#ifdef ERTS_ENABLE_LOCK_CHECK
+ erts_lc_check_exact(NULL, 0);
+#endif
+ if (!tpd->leader) {
+ /* Probably need to block... */
+ block_thread(tpd);
+ }
+ else {
+ erts_aint32_t lflgs;
+ ErtsThrPrgrVal next;
+ int ix, sz, make_progress;
+
+ if (tpd->previous.current == ERTS_THR_PRGR_VAL_WAITING) {
+ /* Took over as leader from another thread */
+ tpd->previous.current = read_acqb(&erts_thr_prgr__.current);
+ tpd->previous.next = tpd->previous.current;
+ tpd->previous.next++;
+ if (tpd->previous.next == ERTS_THR_PRGR_VAL_WAITING)
+ tpd->previous.next = 0;
+ }
+
+ if (tpd->previous.local == tpd->previous.current) {
+ ErtsThrPrgrVal val = tpd->previous.current + 1;
+ if (val == ERTS_THR_PRGR_VAL_WAITING)
+ val = 0;
+ tpd->previous.local = val;
+ set_mb(&intrnl->thr[tpd->id].data.current, val);
+ }
+
+ next = tpd->previous.next;
+
+ make_progress = 1;
+ sz = intrnl->managed.no;
+ for (ix = 0; ix < sz; ix++) {
+ ErtsThrPrgrVal tmp;
+ tmp = read_nob(&intrnl->thr[ix].data.current);
+ if (tmp != next && tmp != ERTS_THR_PRGR_VAL_WAITING) {
+ make_progress = 0;
+ ASSERT(erts_thr_progress_has_passed__(next, tmp));
+ break;
+ }
+ }
+
+ if (make_progress) {
+ ErtsThrPrgrVal current = next;
+
+ next++;
+ if (next == ERTS_THR_PRGR_VAL_WAITING)
+ next = 0;
+
+ set_nob(&intrnl->thr[tpd->id].data.current, next);
+ set_mb(&erts_thr_prgr__.current, current);
+ tpd->previous.local = next;
+ tpd->previous.next = next;
+ tpd->previous.current = current;
+
+#if ERTS_THR_PRGR_PRINT_VAL
+ if (current % 1000 == 0)
+ erts_fprintf(stderr, "%b64u\n", current);
+#endif
+ handle_wakeup_requests(current);
+ }
+
+ if (tpd->active) {
+ lflgs = erts_atomic32_read_nob(&intrnl->misc.data.lflgs);
+ if (lflgs & ERTS_THR_PRGR_LFLG_BLOCK)
+ (void) block_thread(tpd);
+ }
+ else {
+ tpd->leader = 0;
+ tpd->previous.current = ERTS_THR_PRGR_VAL_WAITING;
+#if ERTS_THR_PRGR_PRINT_LEADER
+ erts_fprintf(stderr, "L <- %d\n", tpd->id);
+#endif
+
+ ERTS_THR_PROGRESS_STATE_DEBUG_SET_LEADER(tpd->id, 0);
+
+ lflgs = erts_atomic32_read_bor_relb(&intrnl->misc.data.lflgs,
+ ERTS_THR_PRGR_LFLG_NO_LEADER);
+ if (lflgs & ERTS_THR_PRGR_LFLG_BLOCK)
+ lflgs = block_thread(tpd);
+ if (ERTS_THR_PRGR_LFLGS_ACTIVE(lflgs) == 0 && got_sched_wakeups())
+ wakeup_managed(0);
+ }
+ }
+
+ return tpd->leader;
+}
+
+static int
+update(ErtsThrPrgrData *tpd)
+{
+ int res;
+ ErtsThrPrgrVal val;
+
+ if (tpd->leader)
+ res = 1;
+ else {
+ erts_aint32_t lflgs;
+ res = 0;
+ val = read_acqb(&erts_thr_prgr__.current);
+ if (tpd->previous.local == val) {
+ val++;
+ if (val == ERTS_THR_PRGR_VAL_WAITING)
+ val = 0;
+ tpd->previous.local = val;
+ set_mb(&intrnl->thr[tpd->id].data.current, val);
+ }
+
+ lflgs = erts_atomic32_read_nob(&intrnl->misc.data.lflgs);
+ if (lflgs & ERTS_THR_PRGR_LFLG_BLOCK)
+ res = 1; /* Need to block in leader_update() */
+
+ if ((lflgs & ERTS_THR_PRGR_LFLG_NO_LEADER)
+ && (tpd->active || ERTS_THR_PRGR_LFLGS_ACTIVE(lflgs) == 0)) {
+ /* Try to take over leadership... */
+ erts_aint32_t olflgs;
+ olflgs = erts_atomic32_read_band_acqb(
+ &intrnl->misc.data.lflgs,
+ ~ERTS_THR_PRGR_LFLG_NO_LEADER);
+ if (olflgs & ERTS_THR_PRGR_LFLG_NO_LEADER) {
+ tpd->leader = 1;
+#if ERTS_THR_PRGR_PRINT_LEADER
+ erts_fprintf(stderr, "L -> %d\n", tpd->id);
+#endif
+ ERTS_THR_PROGRESS_STATE_DEBUG_SET_LEADER(tpd->id, 1);
+ }
+ }
+ res |= tpd->leader;
+ }
+ return res;
+}
+
+int
+erts_thr_progress_update(ErtsSchedulerData *esdp)
+{
+ return update(thr_prgr_data(esdp));
+}
+
+
+int
+erts_thr_progress_leader_update(ErtsSchedulerData *esdp)
+{
+ return leader_update(thr_prgr_data(esdp));
+}
+
+void
+erts_thr_progress_prepare_wait(ErtsSchedulerData *esdp)
+{
+ erts_aint32_t lflgs;
+ ErtsThrPrgrData *tpd = thr_prgr_data(esdp);
+
+#ifdef ERTS_ENABLE_LOCK_CHECK
+ erts_lc_check_exact(NULL, 0);
+#endif
+
+ block_count_dec();
+
+ tpd->previous.local = ERTS_THR_PRGR_VAL_WAITING;
+ set_mb(&intrnl->thr[tpd->id].data.current, ERTS_THR_PRGR_VAL_WAITING);
+
+ lflgs = erts_atomic32_read_nob(&intrnl->misc.data.lflgs);
+ if (ERTS_THR_PRGR_LFLGS_ALL_WAITING(lflgs) && got_sched_wakeups())
+ wakeup_managed(0); /* Someone need to make progress */
+}
+
+void
+erts_thr_progress_finalize_wait(ErtsSchedulerData *esdp)
+{
+ ErtsThrPrgrData *tpd = thr_prgr_data(esdp);
+ ErtsThrPrgrVal current, val;
+
+#ifdef ERTS_ENABLE_LOCK_CHECK
+ erts_lc_check_exact(NULL, 0);
+#endif
+
+ /*
+ * We aren't allowed to continue until our thread
+ * progress is past global current.
+ */
+ val = current = read_acqb(&erts_thr_prgr__.current);
+ while (1) {
+ val++;
+ if (val == ERTS_THR_PRGR_VAL_WAITING)
+ val = 0;
+ tpd->previous.local = val;
+ set_mb(&intrnl->thr[tpd->id].data.current, val);
+ val = read_acqb(&erts_thr_prgr__.current);
+ if (current == val)
+ break;
+ current = val;
+ }
+ if (block_count_inc())
+ block_thread(tpd);
+ if (update(tpd))
+ leader_update(tpd);
+}
+
+void
+erts_thr_progress_active(ErtsSchedulerData *esdp, int on)
+{
+ ErtsThrPrgrData *tpd = thr_prgr_data(esdp);
+
+#ifdef ERTS_ENABLE_LOCK_CHECK
+ erts_lc_check_exact(NULL, 0);
+#endif
+
+ ERTS_THR_PROGRESS_STATE_DEBUG_SET_ACTIVE(tpd->id, on);
+
+ if (on) {
+ ASSERT(!tpd->active);
+ tpd->active = 1;
+ erts_atomic32_inc_nob(&intrnl->misc.data.lflgs);
+ }
+ else {
+ ASSERT(tpd->active);
+ tpd->active = 0;
+ erts_atomic32_dec_nob(&intrnl->misc.data.lflgs);
+ if (update(tpd))
+ leader_update(tpd);
+ }
+
+#ifdef DEBUG
+ {
+ erts_aint32_t n = erts_atomic32_read_nob(&intrnl->misc.data.lflgs);
+ n &= ERTS_THR_PRGR_LFLG_ACTIVE_MASK;
+ ASSERT(tpd->active <= n && n <= intrnl->managed.no);
+ }
+#endif
+
+}
+
+static ERTS_INLINE int
+has_reached_wakeup(ErtsThrPrgrVal wakeup)
+{
+ /*
+ * Exactly the same as erts_thr_progress_has_reached(), but
+ * also verify valid wakeup requests in debug mode.
+ */
+ ErtsThrPrgrVal current;
+
+ current = read_acqb(&erts_thr_prgr__.current);
+
+#if ERTS_THR_PRGR_DBG_CHK_WAKEUP_REQUEST_VALUE
+ {
+ ErtsThrPrgrVal limit;
+ /*
+ * erts_thr_progress_later() returns values which are
+ * equal to 'current + 2'. That is, users should never
+ * get a hold of values larger than that.
+ *
+ * That is, valid values are values less than 'current + 3'.
+ *
+ * Values larger than this won't work with the wakeup
+ * algorithm.
+ */
+
+ limit = current + 3;
+ if (limit == ERTS_THR_PRGR_VAL_WAITING)
+ limit = 0;
+ else if (limit < current) /* Wrapped */
+ limit + 1;
+
+ if (!erts_thr_progress_has_passed__(limit, wakeup))
+ erl_exit(ERTS_ABORT_EXIT,
+ "Invalid wakeup request value found:"
+ " current=%b64u, wakeup=%b64u, limit=%b64u",
+ current, wakeup, limit);
+ }
+#endif
+
+ if (current == wakeup)
+ return 1;
+ return erts_thr_progress_has_passed__(current, wakeup);
+}
+
+static void
+request_wakeup_managed(ErtsThrPrgrData *tpd, ErtsThrPrgrVal value)
+{
+ ErtsThrPrgrManagedWakeupData *mwd;
+ int ix, wix;
+
+ /*
+ * Only managed threads that aren't in waiting state
+ * are allowed to call this function.
+ */
+
+ ASSERT(tpd->is_managed);
+ ASSERT(tpd->previous.local != ERTS_THR_PRGR_VAL_WAITING);
+
+ if (has_reached_wakeup(value))
+ wakeup_managed(tpd->id);
+
+ wix = ERTS_THR_PRGR_WAKEUP_IX(value);
+ if (tpd->wakeup_request[wix] == value)
+ return; /* Already got a request registered */
+
+ ASSERT(erts_thr_progress_has_passed__(value,
+ tpd->wakeup_request[wix]));
+
+
+ if (tpd->previous.local == value) {
+ /*
+ * We have already confirmed this value. We need to request
+ * wakeup for a value later than our latest confirmed value in
+ * order to prevent progress from reaching the requested value
+ * while we are writing the request.
+ *
+ * It is ok to move the wakeup request forward since the only
+ * guarantee we make (and can make) is that the thread will be
+ * woken some time *after* the requested value has been reached.
+ */
+ value++;
+ if (value == ERTS_THR_PRGR_VAL_WAITING)
+ value = 0;
+
+ wix = ERTS_THR_PRGR_WAKEUP_IX(value);
+ if (tpd->wakeup_request[wix] == value)
+ return; /* Already got a request registered */
+
+ ASSERT(erts_thr_progress_has_passed__(value,
+ tpd->wakeup_request[wix]));
+ }
+
+ tpd->wakeup_request[wix] = value;
+
+ mwd = intrnl->managed.data[wix];
+
+ ix = erts_atomic32_inc_read_nob(&mwd->len) - 1;
+ mwd->id[ix] = tpd->id;
+
+ ASSERT(!erts_thr_progress_has_reached(value));
+
+ /*
+ * This thread is guarranteed to issue a full memory barrier:
+ * - after the request has been written, but
+ * - before the global thread progress reach the (possibly
+ * increased) requested wakeup value.
+ */
+}
+
+static void
+request_wakeup_unmanaged(ErtsThrPrgrData *tpd, ErtsThrPrgrVal value)
+{
+ int wix, ix, id, bit;
+ ErtsThrPrgrUnmanagedWakeupData *umwd;
+
+ ASSERT(!tpd->is_managed);
+
+ /*
+ * Thread progress *can* reach and pass our requested value while
+ * we are writing the request.
+ */
+
+ if (has_reached_wakeup(value))
+ wakeup_unmanaged(tpd->id);
+
+ wix = ERTS_THR_PRGR_WAKEUP_IX(value);
+
+ if (tpd->wakeup_request[wix] == value)
+ return; /* Already got a request registered */
+
+ ASSERT(erts_thr_progress_has_passed__(value,
+ tpd->wakeup_request[wix]));
+
+ umwd = intrnl->unmanaged.data[wix];
+
+ id = tpd->id;
+
+ bit = id & ERTS_THR_PRGR_BM_MASK;
+ ix = id >> ERTS_THR_PRGR_BM_SHIFT;
+ ASSERT(0 <= ix && ix < umwd->low_sz);
+ erts_atomic32_read_bor_nob(&umwd->low[ix], 1 << bit);
+
+ bit = ix & ERTS_THR_PRGR_BM_MASK;
+ ix >>= ERTS_THR_PRGR_BM_SHIFT;
+ ASSERT(0 <= ix && ix < umwd->high_sz);
+ erts_atomic32_read_bor_nob(&umwd->high[ix], 1 << bit);
+
+ erts_atomic32_inc_mb(&umwd->len);
+
+ if (erts_thr_progress_has_reached(value))
+ wakeup_unmanaged(tpd->id);
+ else
+ tpd->wakeup_request[wix] = value;
+}
+
+void
+erts_thr_progress_wakeup(ErtsSchedulerData *esdp,
+ ErtsThrPrgrVal value)
+{
+ ErtsThrPrgrData *tpd = thr_prgr_data(esdp);
+ ASSERT(!tpd->is_temporary);
+ if (tpd->is_managed)
+ request_wakeup_managed(tpd, value);
+ else
+ request_wakeup_unmanaged(tpd, value);
+}
+
+static void
+wakeup_unmanaged_threads(ErtsThrPrgrUnmanagedWakeupData *umwd)
+{
+ int hix;
+ for (hix = 0; hix < umwd->high_sz; hix++) {
+ erts_aint32_t hmask = erts_atomic32_read_nob(&umwd->high[hix]);
+ if (hmask) {
+ int hbase = hix << ERTS_THR_PRGR_BM_SHIFT;
+ int hbit;
+ for (hbit = 0; hbit < ERTS_THR_PRGR_BM_BITS; hbit++) {
+ if (hmask & (1 << hbit)) {
+ erts_aint_t lmask;
+ int lix = hbase + hbit;
+ ASSERT(0 <= lix && lix < umwd->low_sz);
+ lmask = erts_atomic32_read_nob(&umwd->low[lix]);
+ if (lmask) {
+ int lbase = lix << ERTS_THR_PRGR_BM_SHIFT;
+ int lbit;
+ for (lbit = 0; lbit < ERTS_THR_PRGR_BM_BITS; lbit++) {
+ if (lmask & (1 << lbit)) {
+ int id = lbase + lbit;
+ wakeup_unmanaged(id);
+ }
+ }
+ erts_atomic32_set_nob(&umwd->low[lix], 0);
+ }
+ }
+ }
+ erts_atomic32_set_nob(&umwd->high[hix], 0);
+ }
+ }
+}
+
+
+static void
+handle_wakeup_requests(ErtsThrPrgrVal current)
+{
+ ErtsThrPrgrManagedWakeupData *mwd;
+ ErtsThrPrgrUnmanagedWakeupData *umwd;
+ int wix, len, i;
+
+ wix = ERTS_THR_PRGR_WAKEUP_IX(current);
+
+ mwd = intrnl->managed.data[wix];
+ len = erts_atomic32_read_nob(&mwd->len);
+ ASSERT(len >= 0);
+ if (len) {
+ for (i = 0; i < len; i++)
+ wakeup_managed(mwd->id[i]);
+ erts_atomic32_set_nob(&mwd->len, 0);
+ }
+
+ umwd = intrnl->unmanaged.data[wix];
+ len = erts_atomic32_read_nob(&umwd->len);
+ ASSERT(len >= 0);
+ if (len) {
+ wakeup_unmanaged_threads(umwd);
+ erts_atomic32_set_nob(&umwd->len, 0);
+ }
+
+}
+
+static int
+got_sched_wakeups(void)
+{
+ int wix;
+
+ ERTS_THR_MEMORY_BARRIER;
+
+ for (wix = 0; wix < ERTS_THR_PRGR_WAKEUP_DATA_SIZE; wix++) {
+ ErtsThrPrgrManagedWakeupData **mwd = intrnl->managed.data;
+ if (erts_atomic32_read_nob(&mwd[wix]->len))
+ return 1;
+ }
+ for (wix = 0; wix < ERTS_THR_PRGR_WAKEUP_DATA_SIZE; wix++) {
+ ErtsThrPrgrUnmanagedWakeupData **umwd = intrnl->unmanaged.data;
+ if (erts_atomic32_read_nob(&umwd[wix]->len))
+ return 1;
+ }
+ return 0;
+}
+
+static erts_aint32_t
+block_thread(ErtsThrPrgrData *tpd)
+{
+ erts_aint32_t lflgs;
+ ErtsThrPrgrCallbacks *cbp = &intrnl->managed.callbacks[tpd->id];
+
+ do {
+ block_count_dec();
+
+ while (1) {
+ cbp->prepare_wait(cbp->arg);
+ lflgs = erts_atomic32_read_nob(&intrnl->misc.data.lflgs);
+ if (lflgs & ERTS_THR_PRGR_LFLG_BLOCK)
+ cbp->wait(cbp->arg);
+ else
+ break;
+ }
+
+ } while (block_count_inc());
+
+ cbp->finalize_wait(cbp->arg);
+
+ return lflgs;
+}
+
+static erts_aint32_t
+thr_progress_block(ErtsThrPrgrData *tpd, int wait)
+{
+ erts_tse_t *event = NULL; /* Remove erroneous warning... sigh... */
+ erts_aint32_t lflgs, bc;
+
+ if (tpd->is_blocking++)
+ return (erts_aint32_t) 0;
+
+ while (1) {
+ lflgs = erts_atomic32_read_bor_nob(&intrnl->misc.data.lflgs,
+ ERTS_THR_PRGR_LFLG_BLOCK);
+ if (lflgs & ERTS_THR_PRGR_LFLG_BLOCK)
+ block_thread(tpd);
+ else
+ break;
+ }
+
+#if ERTS_THR_PRGR_PRINT_BLOCKERS
+ erts_fprintf(stderr, "block(%d)\n", tpd->id);
+#endif
+
+ ASSERT(ERTS_AINT_NULL
+ == erts_atomic_read_nob(&intrnl->misc.data.blocker_event));
+
+ if (wait) {
+ event = erts_tse_fetch();
+ erts_tse_reset(event);
+ erts_atomic_set_nob(&intrnl->misc.data.blocker_event,
+ (erts_aint_t) event);
+ }
+ if (tpd->is_managed)
+ erts_atomic32_dec_nob(&intrnl->misc.data.block_count);
+ bc = erts_atomic32_read_band_mb(&intrnl->misc.data.block_count,
+ ~ERTS_THR_PRGR_BC_FLG_NOT_BLOCKING);
+ bc &= ~ERTS_THR_PRGR_BC_FLG_NOT_BLOCKING;
+ if (wait) {
+ while (bc != 0) {
+ erts_tse_wait(event);
+ erts_tse_reset(event);
+ bc = erts_atomic32_read_acqb(&intrnl->misc.data.block_count);
+ }
+ }
+ return bc;
+
+}
+
+void
+erts_thr_progress_block(void)
+{
+ thr_progress_block(tmp_thr_prgr_data(NULL), 1);
+}
+
+void
+erts_thr_progress_fatal_error_block(SWord timeout)
+{
+ ErtsThrPrgrData tpd_buf;
+ ErtsThrPrgrData *tpd = perhaps_thr_prgr_data(NULL);
+ erts_aint32_t bc;
+ SWord time_left = timeout;
+ SysTimeval to;
+
+ /*
+ * Counting poll intervals may give us a too long timeout
+ * if cpu is busy. If we got tolerant time of day we use it
+ * to prevent this.
+ */
+ if (!erts_disable_tolerant_timeofday) {
+ erts_get_timeval(&to);
+ to.tv_sec += timeout / 1000;
+ to.tv_sec += timeout % 1000;
+ }
+
+ if (!tpd) {
+ /*
+ * We stack allocate since failure to allocate memory may
+ * have caused the problem in the first place. This is ok
+ * since we never complete an unblock after a fatal error
+ * block.
+ */
+ tpd = &tpd_buf;
+ init_tmp_thr_prgr_data(tpd);
+ }
+
+ bc = thr_progress_block(tpd, 0);
+ if (bc == 0)
+ return; /* Succefully blocked all managed threads */
+
+ while (1) {
+ if (erts_milli_sleep(ERTS_THR_PRGR_FTL_ERR_BLCK_POLL_INTERVAL) == 0)
+ time_left -= ERTS_THR_PRGR_FTL_ERR_BLCK_POLL_INTERVAL;
+ bc = erts_atomic32_read_acqb(&intrnl->misc.data.block_count);
+ if (bc == 0)
+ break; /* Succefully blocked all managed threads */
+ if (time_left <= 0)
+ break; /* Timeout */
+ if (!erts_disable_tolerant_timeofday) {
+ SysTimeval now;
+ erts_get_timeval(&now);
+ if (now.tv_sec > to.tv_sec)
+ break; /* Timeout */
+ if (now.tv_sec == to.tv_sec && now.tv_usec >= to.tv_usec)
+ break; /* Timeout */
+ }
+ }
+}
+
+void
+erts_thr_progress_unblock(void)
+{
+ erts_tse_t *event;
+ int id, break_id, sz, wakeup;
+ ErtsThrPrgrData *tpd = thr_prgr_data(NULL);
+
+ ASSERT(tpd->is_blocking);
+ if (--tpd->is_blocking)
+ return;
+
+ sz = intrnl->managed.no;
+
+ wakeup = 1;
+ if (!tpd->is_managed)
+ id = break_id = tpd->id < 0 ? 0 : tpd->id % sz;
+ else {
+ break_id = tpd->id;
+ id = break_id + 1;
+ if (id >= sz)
+ id = 0;
+ if (id == break_id)
+ wakeup = 0;
+ erts_atomic32_inc_nob(&intrnl->misc.data.block_count);
+ }
+
+ event = ((erts_tse_t *)
+ erts_atomic_read_nob(&intrnl->misc.data.blocker_event));
+ ASSERT(event);
+ erts_atomic_set_nob(&intrnl->misc.data.blocker_event, ERTS_AINT_NULL);
+
+ erts_atomic32_read_bor_relb(&intrnl->misc.data.block_count,
+ ERTS_THR_PRGR_BC_FLG_NOT_BLOCKING);
+#if ERTS_THR_PRGR_PRINT_BLOCKERS
+ erts_fprintf(stderr, "unblock(%d)\n", tpd->id);
+#endif
+ erts_atomic32_read_band_mb(&intrnl->misc.data.lflgs,
+ ~ERTS_THR_PRGR_LFLG_BLOCK);
+
+ if (wakeup) {
+ do {
+ ErtsThrPrgrVal tmp;
+ tmp = read_nob(&intrnl->thr[id].data.current);
+ if (tmp != ERTS_THR_PRGR_VAL_WAITING)
+ wakeup_managed(id);
+ if (++id >= sz)
+ id = 0;
+ } while (id != break_id);
+ }
+
+ return_tmp_thr_prgr_data(tpd);
+ erts_tse_return(event);
+}
+
+int
+erts_thr_progress_is_blocking(void)
+{
+ ErtsThrPrgrData *tpd = perhaps_thr_prgr_data(NULL);
+ return tpd && tpd->is_blocking;
+}
+
+void erts_thr_progress_dbg_print_state(void)
+{
+ int id;
+ int sz = intrnl->managed.no;
+
+ erts_fprintf(stderr, "--- thread progress ---\n");
+ erts_fprintf(stderr,"current=%b64u\n", erts_thr_progress_current());
+ for (id = 0; id < sz; id++) {
+ ErtsThrPrgrVal current = read_nob(&intrnl->thr[id].data.current);
+#ifdef ERTS_THR_PROGRESS_STATE_DEBUG
+ erts_aint32_t state_debug;
+ char *active, *leader;
+
+ state_debug = erts_atomic32_read_nob(&intrnl->thr[id].data.state_debug);
+ active = (state_debug & ERTS_THR_PROGRESS_STATE_DEBUG_ACTIVE
+ ? "true"
+ : "false");
+ leader = (state_debug & ERTS_THR_PROGRESS_STATE_DEBUG_LEADER
+ ? "true"
+ : "false");
+#endif
+ if (current == ERTS_THR_PRGR_VAL_WAITING)
+ erts_fprintf(stderr,
+ " id=%d, current=WAITING"
+#ifdef ERTS_THR_PROGRESS_STATE_DEBUG
+ ", active=%s, leader=%s"
+#endif
+ "\n", id
+#ifdef ERTS_THR_PROGRESS_STATE_DEBUG
+ , active, leader
+#endif
+ );
+ else
+ erts_fprintf(stderr,
+ " id=%d, current=%b64u"
+#ifdef ERTS_THR_PROGRESS_STATE_DEBUG
+ ", active=%s, leader=%s"
+#endif
+ "\n", id, current
+#ifdef ERTS_THR_PROGRESS_STATE_DEBUG
+ , active, leader
+#endif
+ );
+ }
+ erts_fprintf(stderr, "-----------------------\n");
+
+
+}
+
+#endif
diff --git a/erts/emulator/beam/erl_thr_progress.h b/erts/emulator/beam/erl_thr_progress.h
new file mode 100644
index 0000000000..68d14174b9
--- /dev/null
+++ b/erts/emulator/beam/erl_thr_progress.h
@@ -0,0 +1,233 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description: Thread progress information. Used by lock free algorithms
+ * to determine when all involved threads are guaranteed to
+ * have passed a specific point of execution.
+ *
+ * Usage instructions can be found in ert_thr_progress.c
+ *
+ * Author: Rickard Green
+ */
+
+#if !defined(ERL_THR_PROGRESS_H__TSD_TYPE__)
+#define ERL_THR_PROGRESS_H__TSD_TYPE__
+
+#include "sys.h"
+
+#ifndef ERTS_SMP
+
+#define erts_smp_thr_progress_block() ((void) 0)
+#define erts_smp_thr_progress_unblock() ((void) 0)
+#define erts_smp_thr_progress_is_blocking() 1
+
+#else /* ERTS_SMP */
+
+#define erts_smp_thr_progress_block erts_thr_progress_block
+#define erts_smp_thr_progress_unblock erts_thr_progress_unblock
+#define erts_smp_thr_progress_is_blocking erts_thr_progress_is_blocking
+
+void erts_thr_progress_fatal_error_block(SWord timeout);
+void erts_thr_progress_block(void);
+void erts_thr_progress_unblock(void);
+int erts_thr_progress_is_blocking(void);
+
+typedef Uint64 ErtsThrPrgrVal;
+
+#define ERTS_THR_PRGR_WAKEUP_DATA_SIZE 4 /* Need to be an even power of 2. */
+
+typedef struct {
+ int id;
+ int is_managed;
+ int is_blocking;
+ int is_temporary;
+
+ /* --- Part below only for registered threads --- */
+
+ ErtsThrPrgrVal wakeup_request[ERTS_THR_PRGR_WAKEUP_DATA_SIZE];
+
+ /* --- Part below only for managed threads --- */
+
+ int leader; /* Needs to be first in the managed threads part */
+ int active;
+ struct {
+ ErtsThrPrgrVal local;
+ ErtsThrPrgrVal next;
+ ErtsThrPrgrVal current;
+ } previous;
+} ErtsThrPrgrData;
+#endif /* ERTS_SMP */
+
+#endif
+
+#if !defined(ERL_THR_PROGRESS_H__) && !defined(ERL_THR_PROGRESS_TSD_TYPE_ONLY)
+#define ERL_THR_PROGRESS_H__
+
+#include "erl_threads.h"
+#include "erl_process.h"
+
+#ifdef ERTS_SMP
+
+#define ERTS_THR_PRGR_VAL_WAITING (~((ErtsThrPrgrVal) 0))
+
+extern erts_tsd_key_t erts_thr_prgr_data_key__;
+
+#ifdef ARCH_64
+# define ERTS_THR_PRGR_ATOMIC erts_atomic_t
+#else /* ARCH_32 */
+# define ERTS_THR_PRGR_ATOMIC erts_dw_atomic_t
+#endif
+
+typedef struct {
+ void *arg;
+ void (*wakeup)(void *);
+ void (*prepare_wait)(void *);
+ void (*wait)(void *);
+ void (*finalize_wait)(void *);
+} ErtsThrPrgrCallbacks;
+
+typedef struct {
+ ERTS_THR_PRGR_ATOMIC current;
+} ErtsThrPrgr;
+
+extern ErtsThrPrgr erts_thr_prgr__;
+
+void erts_thr_progress_pre_init(void);
+void erts_thr_progress_init(int no_schedulers, int managed, int unmanaged);
+void erts_thr_progress_register_managed_thread(ErtsSchedulerData *esdp,
+ ErtsThrPrgrCallbacks *,
+ int);
+void erts_thr_progress_register_unmanaged_thread(ErtsThrPrgrCallbacks *);
+void erts_thr_progress_active(ErtsSchedulerData *esdp, int on);
+void erts_thr_progress_wakeup(ErtsSchedulerData *esdp,
+ ErtsThrPrgrVal value);
+int erts_thr_progress_update(ErtsSchedulerData *esdp);
+int erts_thr_progress_leader_update(ErtsSchedulerData *esdp);
+void erts_thr_progress_prepare_wait(ErtsSchedulerData *esdp);
+void erts_thr_progress_finalize_wait(ErtsSchedulerData *esdp);
+
+void erts_thr_progress_dbg_print_state(void);
+
+#ifdef ARCH_32
+#define ERTS_THR_PRGR_ATOMIC erts_dw_atomic_t
+ERTS_GLB_INLINE ErtsThrPrgrVal erts_thr_prgr_dw_sint_to_val__(ethr_dw_sint_t *dw_sint);
+#endif
+ERTS_GLB_INLINE ErtsThrPrgrVal erts_thr_prgr_read_acqb__(ERTS_THR_PRGR_ATOMIC *atmc);
+
+ERTS_GLB_INLINE int erts_thr_progress_is_managed_thread(void);
+ERTS_GLB_INLINE ErtsThrPrgrVal erts_thr_progress_later(void);
+ERTS_GLB_INLINE ErtsThrPrgrVal erts_thr_progress_current(void);
+ERTS_GLB_INLINE int erts_thr_progress_has_passed__(ErtsThrPrgrVal val1, ErtsThrPrgrVal val2);
+ERTS_GLB_INLINE int erts_thr_progress_has_reached(ErtsThrPrgrVal val);
+
+#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+
+#ifdef ARCH_64
+
+ERTS_GLB_INLINE ErtsThrPrgrVal
+erts_thr_prgr_read_acqb__(ERTS_THR_PRGR_ATOMIC *atmc)
+{
+ return (ErtsThrPrgrVal) erts_atomic_read_acqb(atmc);
+}
+
+#else /* ARCH_32 */
+
+ERTS_GLB_INLINE ErtsThrPrgrVal
+erts_thr_prgr_dw_sint_to_val__(ethr_dw_sint_t *dw_sint)
+{
+#ifdef ETHR_SU_DW_NAINT_T__
+ return (ErtsThrPrgrVal) dw_sint->dw_sint;
+#else
+ ErtsThrPrgrVal res;
+ res = (ErtsThrPrgrVal) ((Uint32) dw_sint->sint[ETHR_DW_SINT_HIGH_WORD]);
+ res <<= 32;
+ res |= (ErtsThrPrgrVal) ((Uint32) dw_sint->sint[ETHR_DW_SINT_LOW_WORD]);
+ return res;
+#endif
+}
+
+ERTS_GLB_INLINE ErtsThrPrgrVal
+erts_thr_prgr_read_acqb__(ERTS_THR_PRGR_ATOMIC *atmc)
+{
+ ethr_dw_sint_t dw_sint;
+ erts_dw_atomic_read_acqb(atmc, &dw_sint);
+ return erts_thr_prgr_dw_sint_to_val__(&dw_sint);
+}
+
+#endif
+
+ERTS_GLB_INLINE int
+erts_thr_progress_is_managed_thread(void)
+{
+ ErtsThrPrgrData *tpd = erts_tsd_get(erts_thr_prgr_data_key__);
+ return tpd && tpd->is_managed;
+}
+
+ERTS_GLB_INLINE ErtsThrPrgrVal
+erts_thr_progress_later(void)
+{
+ ErtsThrPrgrVal val = erts_thr_prgr_read_acqb__(&erts_thr_prgr__.current);
+ if (val == (ERTS_THR_PRGR_VAL_WAITING-((ErtsThrPrgrVal)2)))
+ return ((ErtsThrPrgrVal) 0);
+ else if (val == (ERTS_THR_PRGR_VAL_WAITING-((ErtsThrPrgrVal)1)))
+ return ((ErtsThrPrgrVal) 1);
+ else
+ return val + ((ErtsThrPrgrVal) 2);
+}
+
+ERTS_GLB_INLINE ErtsThrPrgrVal
+erts_thr_progress_current(void)
+{
+ return erts_thr_prgr_read_acqb__(&erts_thr_prgr__.current);
+}
+
+ERTS_GLB_INLINE int
+erts_thr_progress_has_passed__(ErtsThrPrgrVal val1, ErtsThrPrgrVal val0)
+{
+ if ((((((ErtsThrPrgrVal) 1) << 63) & val1)
+ ^ ((((ErtsThrPrgrVal) 1) << 63) & val0)) != 0) {
+ /* May have wrapped... */
+ if (val1 < (((ErtsThrPrgrVal) 1) << 62)
+ && val0 > (((ErtsThrPrgrVal) 3) << 62)) {
+ /*
+ * 'val1' has wrapped but 'val0' has not yet wrapped. While in
+ * these ranges 'current' is considered later than 'val0'.
+ */
+ return 1;
+ }
+ }
+ return val1 > val0;
+}
+
+ERTS_GLB_INLINE int
+erts_thr_progress_has_reached(ErtsThrPrgrVal val)
+{
+ ErtsThrPrgrVal current;
+ current = erts_thr_prgr_read_acqb__(&erts_thr_prgr__.current);
+ if (current == val)
+ return 1;
+ return erts_thr_progress_has_passed__(current, val);
+}
+
+#endif
+
+#endif /* ERTS_SMP */
+
+#endif
diff --git a/erts/emulator/beam/erl_thr_queue.c b/erts/emulator/beam/erl_thr_queue.c
new file mode 100644
index 0000000000..9ac4cd4b8e
--- /dev/null
+++ b/erts/emulator/beam/erl_thr_queue.c
@@ -0,0 +1,745 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description: Lock-free queue for communication between threads.
+ *
+ * Currently only a many-to-one version has been,
+ * implemented, i.e., many threads can enqueue but
+ * only one thread can dequeue at a time. It doesn't
+ * have to be the same thread dequeuing every time, but
+ * synchronization so that only one thread dequeues
+ * at a time has to be provided by other means.
+ *
+ * When/If the need for a many-to-many queue arises,
+ * this implementation can relatively easy be extended
+ * to support that too.
+ *
+ * Usage instructions below.
+ *
+ * Author: Rickard Green
+ */
+
+/*
+ * ------ Usage instructions -----------------------------------------------
+ *
+ * Dequeuing generates garbage that needs to be cleaned up.
+ * erts_thr_q_dequeue() automatically cleans, but garbage may have to be
+ * cleaned up also when the queue is empty. This is done by calling
+ * erts_thr_q_clean(). In the SMP case thread progress may have to be made
+ * before cleaning can continue. If so, erts_thr_q_need_thr_progress() in
+ * combination with erts_thr_progress_wakeup() can be used in order to
+ * request a wakeup at appropriate time.
+ *
+ * Enqueuing implies memory allocation and dequeuing implies memory
+ * deallocation. Memory allocation can be moved to another more suitable
+ * thread using erts_thr_q_prepare_enqueue() together with
+ * erts_thr_q_enqueue_prepared() instead of using erts_thr_q_enqueue().
+ * Memory deallocation can can be moved to another more suitable thread by
+ * disabling auto_finalize_dequeue when initializing the queue and then use
+ * erts_thr_q_get_finalize_dequeue_data() together
+ * erts_thr_q_finalize_dequeue() after dequeuing or cleaning.
+ *
+ * Ending the life of the queue using either erts_thr_q_destroy()
+ * or erts_thr_q_finalize() impies cleaning the queue. Both functions
+ * return the cleaning result and may have to be called multiple times
+ * until the queue is clean. Once one of these functions have been called
+ * enqueuing is not allowed. This has to be synchronized by the user.
+ * If auto_finalize_dequeue has been disabled, the finalize dequeue
+ * functionality has to be called after ending the life of the queue just
+ * as when dequeuing or cleaning on a queue that is alive.
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "erl_thr_queue.h"
+
+#if defined(DEBUG)
+#define ERTS_THR_Q_DBG_CHK_DATA 1
+#else
+#define ERTS_THR_Q_DBG_CHK_DATA 0
+#endif
+
+#define ERTS_THR_Q_MAX_CLEAN_REACHED_HEAD_COUNT 100
+#define ERTS_THR_Q_MAX_SCHED_CLEAN_OPS 50
+#define ERTS_THR_Q_MAX_DEQUEUE_CLEAN_OPS 3
+
+#define ERTS_THR_Q_MAX_FINI_DEQ_OPS 50
+
+#ifdef ERTS_SMP
+ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(sl_element,
+ ErtsThrQElement_t,
+ 1000,
+ ERTS_ALC_T_THR_Q_EL_SL)
+#else
+
+static void
+init_sl_element_alloc(void)
+{
+}
+
+static ErtsThrQElement_t *
+sl_element_alloc(void)
+{
+ return erts_alloc(ERTS_ALC_T_THR_Q_EL_SL,
+ sizeof(ErtsThrQElement_t));
+}
+
+static void
+sl_element_free(ErtsThrQElement_t *p)
+{
+ erts_free(ERTS_ALC_T_THR_Q_EL_SL, p);
+}
+
+#endif
+
+typedef union {
+ ErtsThrQ_t q;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsThrQ_t))];
+} ErtsAlignedThrQ_t;
+
+void
+erts_thr_q_init(void)
+{
+ init_sl_element_alloc();
+}
+
+static void noop_callback(void *arg) { }
+
+void
+erts_thr_q_initialize(ErtsThrQ_t *q, ErtsThrQInit_t *qi)
+{
+#ifndef USE_THREADS
+ q->init = *qi;
+ if (!q->init.notify)
+ q->init.notify = noop_callback;
+ q->first = NULL;
+ q->last = NULL;
+ q->q.blk = NULL;
+#else
+ erts_atomic_init_nob(&q->tail.data.marker.next.atmc, ERTS_AINT_NULL);
+ q->tail.data.marker.data.ptr = NULL;
+ erts_atomic_init_nob(&q->tail.data.last,
+ (erts_aint_t) &q->tail.data.marker);
+ erts_atomic_init_nob(&q->tail.data.um_refc[0], 0);
+ erts_atomic_init_nob(&q->tail.data.um_refc[1], 0);
+ erts_atomic32_init_nob(&q->tail.data.um_refc_ix, 0);
+ q->tail.data.live = qi->live.objects;
+ q->tail.data.arg = qi->arg;
+ q->tail.data.notify = qi->notify;
+ if (!q->tail.data.notify)
+ q->tail.data.notify = noop_callback;
+
+ q->head.head.ptr = &q->tail.data.marker;
+ q->head.live = qi->live.objects;
+ q->head.first = &q->tail.data.marker;
+ q->head.unref_end = &q->tail.data.marker;
+ q->head.clean_reached_head_count = 0;
+ q->head.deq_fini.automatic = qi->auto_finalize_dequeue;
+ q->head.deq_fini.start = NULL;
+ q->head.deq_fini.end = NULL;
+#ifdef ERTS_SMP
+ q->head.next.thr_progress = erts_thr_progress_current();
+ q->head.next.thr_progress_reached = 1;
+#endif
+ q->head.next.um_refc_ix = 1;
+ q->head.next.unref_end = &q->tail.data.marker;
+ q->head.used_marker = 1;
+ q->head.arg = qi->arg;
+ q->head.notify = q->tail.data.notify;
+ q->q.finalizing = 0;
+ q->q.live = qi->live.queue;
+ q->q.blk = NULL;
+#endif
+}
+
+ErtsThrQCleanState_t
+erts_thr_q_finalize(ErtsThrQ_t *q)
+{
+#ifdef USE_THREADS
+ q->q.finalizing = 1;
+#endif
+ while (erts_thr_q_dequeue(q));
+ return erts_thr_q_clean(q);
+}
+
+ErtsThrQ_t *
+erts_thr_q_create(ErtsThrQInit_t *qi)
+{
+ ErtsAlcType_t atype;
+ ErtsThrQ_t *q, *qblk;
+ UWord qw;
+
+ switch (qi->live.queue) {
+ case ERTS_THR_Q_LIVE_SHORT:
+ atype = ERTS_ALC_T_THR_Q_SL;
+ break;
+ case ERTS_THR_Q_LIVE_LONG:
+ atype = ERTS_ALC_T_THR_Q_LL;
+ break;
+ default:
+ atype = ERTS_ALC_T_THR_Q;
+ break;
+ }
+
+ qw = (UWord) erts_alloc(atype,
+ sizeof(ErtsThrQ_t) + (ERTS_CACHE_LINE_SIZE-1));
+ qblk = (ErtsThrQ_t *) qw;
+ if (qw & ERTS_CACHE_LINE_MASK)
+ qw = (qw & ~ERTS_CACHE_LINE_MASK) + ERTS_CACHE_LINE_SIZE;
+ ASSERT((qw & ERTS_CACHE_LINE_MASK) == 0);
+ q = (ErtsThrQ_t *) qw;
+ erts_thr_q_initialize(q, qi);
+ q->q.blk = qblk;
+ return q;
+}
+
+ErtsThrQCleanState_t
+erts_thr_q_destroy(ErtsThrQ_t *q)
+{
+ if (!q->q.blk)
+ erl_exit(ERTS_ABORT_EXIT,
+ "Trying to destroy not created thread queue\n");
+ return erts_thr_q_finalize(q);
+}
+
+#ifdef USE_THREADS
+
+static void
+destroy(ErtsThrQ_t *q)
+{
+ ErtsAlcType_t atype;
+ switch (q->q.live) {
+ case ERTS_THR_Q_LIVE_SHORT:
+ atype = ERTS_ALC_T_THR_Q_SL;
+ break;
+ case ERTS_THR_Q_LIVE_LONG:
+ atype = ERTS_ALC_T_THR_Q_LL;
+ break;
+ default:
+ atype = ERTS_ALC_T_THR_Q;
+ break;
+ }
+ erts_free(atype, q->q.blk);
+}
+
+#endif
+
+static ERTS_INLINE ErtsThrQElement_t *
+element_live_alloc(ErtsThrQLive_t live)
+{
+ switch (live) {
+ case ERTS_THR_Q_LIVE_SHORT:
+ return sl_element_alloc();
+ default:
+ return (ErtsThrQElement_t *) erts_alloc(ERTS_ALC_T_THR_Q_EL,
+ sizeof(ErtsThrQElement_t));
+ }
+}
+
+static ERTS_INLINE ErtsThrQElement_t *
+element_alloc(ErtsThrQ_t *q)
+{
+ ErtsThrQLive_t live;
+#ifdef USE_THREADS
+ live = q->tail.data.live;
+#else
+ live = q->init.live.objects;
+#endif
+ return element_live_alloc(live);
+}
+
+static ERTS_INLINE void
+element_live_free(ErtsThrQLive_t live, ErtsThrQElement_t *el)
+{
+ switch (live) {
+ case ERTS_THR_Q_LIVE_SHORT:
+ sl_element_free(el);
+ break;
+ default:
+ erts_free(ERTS_ALC_T_THR_Q_EL, el);
+ }
+}
+
+static ERTS_INLINE void
+element_free(ErtsThrQ_t *q, ErtsThrQElement_t *el)
+{
+ ErtsThrQLive_t live;
+#ifdef USE_THREADS
+ live = q->head.live;
+#else
+ live = q->init.live.objects;
+#endif
+ element_live_free(live, el);
+}
+
+#ifdef USE_THREADS
+
+static ERTS_INLINE ErtsThrQElement_t *
+enqueue_managed(ErtsThrQ_t *q, ErtsThrQElement_t *this, int want_last)
+{
+ erts_aint_t ilast, itmp;
+
+ erts_atomic_init_nob(&this->next.atmc, ERTS_AINT_NULL);
+ /* Enqueue at end of list... */
+
+ ilast = erts_atomic_read_nob(&q->tail.data.last);
+ while (1) {
+ ErtsThrQElement_t *last = (ErtsThrQElement_t *) ilast;
+ itmp = erts_atomic_cmpxchg_mb(&last->next.atmc,
+ (erts_aint_t) this,
+ ERTS_AINT_NULL);
+ if (itmp == ERTS_AINT_NULL)
+ break;
+ ilast = itmp;
+ }
+
+ /* Move last pointer forward... */
+ while (1) {
+ if (want_last) {
+ if (erts_atomic_read_rb(&this->next.atmc) != ERTS_AINT_NULL) {
+ /* Someone else will move it forward */
+ ilast = erts_atomic_read_rb(&q->tail.data.last);
+ return (ErtsThrQElement_t *) ilast;
+ }
+ }
+ else {
+ if (erts_atomic_read_nob(&this->next.atmc) != ERTS_AINT_NULL) {
+ /* Someone else will move it forward */
+ return NULL;
+ }
+ }
+ itmp = erts_atomic_cmpxchg_mb(&q->tail.data.last,
+ (erts_aint_t) this,
+ ilast);
+ if (ilast == itmp)
+ return want_last ? this : NULL;
+ ilast = itmp;
+ }
+}
+
+static ErtsThrQCleanState_t
+clean(ErtsThrQ_t *q, int max_ops, int do_notify)
+{
+ erts_aint_t ilast;
+ int um_refc_ix;
+ int ops;
+
+ for (ops = 0; ops < max_ops; ops++) {
+ ErtsThrQElement_t *tmp;
+ restart:
+ ASSERT(q->head.first);
+ if (q->head.first == q->head.head.ptr) {
+ q->head.clean_reached_head_count++;
+ if (q->head.clean_reached_head_count
+ >= ERTS_THR_Q_MAX_CLEAN_REACHED_HEAD_COUNT) {
+ q->head.clean_reached_head_count = 0;
+ break;
+ }
+ goto inspect_head;
+ }
+ if (q->head.first == q->head.unref_end)
+ break;
+ if (q->head.first == &q->tail.data.marker) {
+ q->head.used_marker = 0;
+ q->head.first = q->head.first->next.ptr;
+ goto restart;
+ }
+ tmp = q->head.first;
+ q->head.first = q->head.first->next.ptr;
+ if (q->head.deq_fini.automatic)
+ element_free(q, tmp);
+ else {
+ tmp->data.ptr = (void *) (UWord) q->head.live;
+ if (!q->head.deq_fini.start)
+ q->head.deq_fini.start = tmp;
+ else if (q->head.deq_fini.end->next.ptr == &q->tail.data.marker)
+ q->head.deq_fini.end->next.ptr = tmp;
+ q->head.deq_fini.end = tmp;
+ }
+ }
+
+ ilast = erts_atomic_read_nob(&q->tail.data.last);
+ if (q->head.first == ((ErtsThrQElement_t *) ilast)
+ && ((ErtsThrQElement_t *) ilast) == &q->tail.data.marker
+ && q->head.first == &q->tail.data.marker) {
+ /* Empty and clean queue */
+ if (q->q.finalizing)
+ destroy(q);
+ return ERTS_THR_Q_CLEAN;
+ }
+
+#ifdef ERTS_SMP
+ if (q->head.next.thr_progress_reached
+ || erts_thr_progress_has_reached(q->head.next.thr_progress)) {
+ q->head.next.thr_progress_reached = 1;
+#endif
+ um_refc_ix = q->head.next.um_refc_ix;
+ if (erts_atomic_read_acqb(&q->tail.data.um_refc[um_refc_ix]) == 0) {
+ /* Move unreferenced end pointer forward... */
+ q->head.clean_reached_head_count = 0;
+ q->head.unref_end = q->head.next.unref_end;
+
+ if (!q->head.used_marker
+ && q->head.unref_end == (ErtsThrQElement_t *) ilast) {
+ q->head.used_marker = 1;
+ ilast = (erts_aint_t) enqueue_managed(q,
+ &q->tail.data.marker,
+ 1);
+ if (q->head.head.ptr == q->head.unref_end) {
+ ErtsThrQElement_t *next;
+ next = ((ErtsThrQElement_t *)
+ erts_atomic_read_acqb(&q->head.head.ptr->next.atmc));
+ if (next == &q->tail.data.marker) {
+ q->head.head.ptr->next.ptr = &q->tail.data.marker;
+ q->head.head.ptr = &q->tail.data.marker;
+ }
+ }
+ }
+
+ if (q->head.unref_end == (ErtsThrQElement_t *) ilast)
+ ERTS_THR_MEMORY_BARRIER;
+ else {
+ q->head.next.unref_end = (ErtsThrQElement_t *) ilast;
+ ERTS_THR_MEMORY_BARRIER;
+#ifdef ERTS_SMP
+ q->head.next.thr_progress = erts_thr_progress_later();
+#endif
+ erts_atomic32_set_relb(&q->tail.data.um_refc_ix,
+ um_refc_ix);
+ q->head.next.um_refc_ix = um_refc_ix == 0 ? 1 : 0;
+#ifdef ERTS_SMP
+ q->head.next.thr_progress_reached = 0;
+#endif
+ }
+ }
+#ifdef ERTS_SMP
+ }
+#endif
+
+ if (q->head.first == q->head.head.ptr) {
+ inspect_head:
+ if (!q->head.used_marker) {
+ erts_aint_t inext;
+ inext = erts_atomic_read_acqb(&q->head.head.ptr->next.atmc);
+ if (inext == ERTS_AINT_NULL) {
+ q->head.used_marker = 1;
+ (void) enqueue_managed(q, &q->tail.data.marker, 0);
+ inext = erts_atomic_read_acqb(&q->head.head.ptr->next.atmc);
+ if (inext == (erts_aint_t) &q->tail.data.marker) {
+ q->head.head.ptr->next.ptr = &q->tail.data.marker;
+ q->head.head.ptr = &q->tail.data.marker;
+#ifdef ERTS_SMP
+ if (!q->head.next.thr_progress_reached)
+ return ERTS_THR_Q_NEED_THR_PRGR;
+#else
+ if (do_notify)
+ q->head.notify(q->head.arg);
+#endif
+ return ERTS_THR_Q_DIRTY;
+ }
+ }
+ }
+ return ERTS_THR_Q_CLEAN;
+ }
+
+ if (q->head.first != q->head.unref_end) {
+ if (do_notify)
+ q->head.notify(q->head.arg);
+ return ERTS_THR_Q_DIRTY;
+ }
+
+#ifdef ERTS_SMP
+ if (!q->head.next.thr_progress_reached)
+ return ERTS_THR_Q_NEED_THR_PRGR;
+#endif
+
+ return ERTS_THR_Q_CLEAN; /* Waiting for unmanaged threads to complete... */
+}
+
+#endif
+
+ErtsThrQCleanState_t
+erts_thr_q_clean(ErtsThrQ_t *q)
+{
+#ifdef USE_THREADS
+ return clean(q, ERTS_THR_Q_MAX_SCHED_CLEAN_OPS, 0);
+#else
+ return ERTS_THR_Q_CLEAN;
+#endif
+}
+
+ErtsThrQCleanState_t
+erts_thr_q_inspect(ErtsThrQ_t *q, int ensure_empty)
+{
+#ifdef USE_THREADS
+ if (ensure_empty) {
+ erts_aint_t inext;
+ inext = erts_atomic_read_acqb(&q->head.head.ptr->next.atmc);
+ if (inext != ERTS_AINT_NULL) {
+ if (&q->tail.data.marker != (ErtsThrQElement_t *) inext)
+ return ERTS_THR_Q_DIRTY;
+ else {
+ q->head.head.ptr->next.ptr = (ErtsThrQElement_t *) inext;
+ q->head.head.ptr = (ErtsThrQElement_t *) inext;
+ inext = erts_atomic_read_acqb(&q->head.head.ptr->next.atmc);
+ if (inext != ERTS_AINT_NULL)
+ return ERTS_THR_Q_DIRTY;
+ }
+ }
+ }
+
+ if (q->head.first == q->head.head.ptr) {
+ if (!q->head.used_marker) {
+ erts_aint_t inext;
+ inext = erts_atomic_read_acqb(&q->head.head.ptr->next.atmc);
+ if (inext == ERTS_AINT_NULL)
+ return ERTS_THR_Q_DIRTY;
+ }
+ return ERTS_THR_Q_CLEAN;
+ }
+
+ if (q->head.first != q->head.unref_end)
+ return ERTS_THR_Q_DIRTY;
+
+#ifdef ERTS_SMP
+ if (!q->head.next.thr_progress_reached)
+ return ERTS_THR_Q_NEED_THR_PRGR;
+#endif
+#endif
+ return ERTS_THR_Q_CLEAN;
+}
+
+static void
+enqueue(ErtsThrQ_t *q, void *data, ErtsThrQElement_t *this)
+{
+#ifndef USE_THREADS
+ ASSERT(data);
+
+ this->next.ptr = NULL;
+ this->data.ptr = data;
+
+ if (q->last)
+ q->last->next.ptr = this;
+ else {
+ q->first = q->last = this;
+ q->init.notify(q->init.arg);
+ }
+#else
+ int notify;
+ int um_refc_ix = 0;
+#ifdef ERTS_SMP
+ int unmanaged_thread;
+#endif
+
+#if ERTS_THR_Q_DBG_CHK_DATA
+ if (!data)
+ erl_exit(ERTS_ABORT_EXIT, "Missing data in enqueue\n");
+#endif
+
+ ASSERT(!q->q.finalizing);
+
+ this->data.ptr = data;
+
+#ifdef ERTS_SMP
+ unmanaged_thread = !erts_thr_progress_is_managed_thread();
+ if (unmanaged_thread)
+#endif
+ {
+ um_refc_ix = erts_atomic32_read_acqb(&q->tail.data.um_refc_ix);
+ while (1) {
+ int tmp_um_refc_ix;
+ erts_atomic_inc_acqb(&q->tail.data.um_refc[um_refc_ix]);
+ tmp_um_refc_ix = erts_atomic32_read_acqb(&q->tail.data.um_refc_ix);
+ if (tmp_um_refc_ix == um_refc_ix)
+ break;
+ erts_atomic_dec_relb(&q->tail.data.um_refc[um_refc_ix]);
+ um_refc_ix = tmp_um_refc_ix;
+ }
+ }
+
+ notify = this == enqueue_managed(q, this, 1);
+
+
+#ifdef ERTS_SMP
+ if (unmanaged_thread)
+#endif
+ {
+ if (notify)
+ erts_atomic_dec_relb(&q->tail.data.um_refc[um_refc_ix]);
+ else if (erts_atomic_dec_read_relb(&q->tail.data.um_refc[um_refc_ix]) == 0)
+ notify = 1;
+ }
+ if (notify)
+ q->tail.data.notify(q->tail.data.arg);
+#endif
+}
+
+void
+erts_thr_q_enqueue(ErtsThrQ_t *q, void *data)
+{
+ enqueue(q, data, element_alloc(q));
+}
+
+ErtsThrQPrepEnQ_t *
+erts_thr_q_prepare_enqueue(ErtsThrQ_t *q)
+{
+ return (ErtsThrQPrepEnQ_t *) element_alloc(q);
+}
+
+int
+erts_thr_q_get_finalize_dequeue_data(ErtsThrQ_t *q, ErtsThrQFinDeQ_t *fdp)
+{
+#ifndef USE_THREADS
+ return 0;
+#else
+#ifdef DEBUG
+ if (!q->head.deq_fini.start) {
+ ASSERT(!q->head.deq_fini.end);
+ }
+ else {
+ ErtsThrQElement_t *e = q->head.deq_fini.start;
+ ErtsThrQElement_t *end = q->head.deq_fini.end;
+ while (e != end) {
+ ASSERT(q->head.head.ptr != e);
+ ASSERT(q->head.first != e);
+ ASSERT(q->head.unref_end != e);
+ e = e->next.ptr;
+ }
+ }
+#endif
+ fdp->start = q->head.deq_fini.start;
+ fdp->end = q->head.deq_fini.end;
+ if (fdp->end)
+ fdp->end->next.ptr = NULL;
+ q->head.deq_fini.start = NULL;
+ q->head.deq_fini.end = NULL;
+ return fdp->start != NULL;
+#endif
+}
+
+void
+erts_thr_q_append_finalize_dequeue_data(ErtsThrQFinDeQ_t *fdp0,
+ ErtsThrQFinDeQ_t *fdp1)
+{
+#ifdef USE_THREADS
+ if (fdp1->start) {
+ if (fdp0->end)
+ fdp0->end->next.ptr = fdp1->start;
+ else
+ fdp0->start = fdp1->start;
+ fdp0->end = fdp1->end;
+ }
+#endif
+}
+
+
+int erts_thr_q_finalize_dequeue(ErtsThrQFinDeQ_t *state)
+{
+#ifdef USE_THREADS
+ ErtsThrQElement_t *start = state->start;
+ if (start) {
+ ErtsThrQLive_t live;
+ int i;
+ for (i = 0; i < ERTS_THR_Q_MAX_FINI_DEQ_OPS; i++) {
+ ErtsThrQElement_t *tmp;
+ if (!start)
+ break;
+ tmp = start;
+ start = start->next.ptr;
+ live = (ErtsThrQLive_t) (UWord) tmp->data.ptr;
+ element_live_free(live, tmp);
+ }
+ state->start = start;
+ if (start)
+ return 1; /* More to do */
+ state->end = NULL;
+ }
+#endif
+ return 0;
+}
+
+void
+erts_thr_q_finalize_dequeue_state_init(ErtsThrQFinDeQ_t *state)
+{
+#ifdef USE_THREADS
+ state->start = NULL;
+ state->end = NULL;
+#endif
+}
+
+
+void
+erts_thr_q_enqueue_prepared(ErtsThrQ_t *q, void *data, ErtsThrQPrepEnQ_t *prep)
+{
+ ASSERT(prep);
+ enqueue(q, data, (ErtsThrQElement_t *) prep);
+}
+
+void *
+erts_thr_q_dequeue(ErtsThrQ_t *q)
+{
+#ifndef USE_THREADS
+ void *res;
+ ErtsThrQElement_t *tmp;
+
+ if (!q->first)
+ return NULL;
+ tmp = q->first;
+ res = tmp->data.ptr;
+ q->first = tmp->next.ptr;
+ if (!q->first)
+ q->last = NULL;
+
+ element_free(q, tmp);
+
+ return res;
+#else
+ erts_aint_t inext;
+ void *res;
+
+ inext = erts_atomic_read_acqb(&q->head.head.ptr->next.atmc);
+ if (inext == ERTS_AINT_NULL)
+ return NULL;
+ q->head.head.ptr->next.ptr = (ErtsThrQElement_t *) inext;
+ q->head.head.ptr = (ErtsThrQElement_t *) inext;
+ if (q->head.head.ptr == &q->tail.data.marker) {
+ inext = erts_atomic_read_acqb(&q->head.head.ptr->next.atmc);
+ if (inext == ERTS_AINT_NULL)
+ return NULL;
+ q->head.head.ptr->next.ptr = (ErtsThrQElement_t *) inext;
+ q->head.head.ptr = (ErtsThrQElement_t *) inext;
+ }
+ res = q->head.head.ptr->data.ptr;
+#if ERTS_THR_Q_DBG_CHK_DATA
+ q->head.head.ptr->data.ptr = NULL;
+ if (!res)
+ erl_exit(ERTS_ABORT_EXIT, "Missing data in dequeue\n");
+#endif
+ clean(q,
+ (q->head.deq_fini.automatic
+ ? ERTS_THR_Q_MAX_DEQUEUE_CLEAN_OPS
+ : ERTS_THR_Q_MAX_SCHED_CLEAN_OPS), 1);
+ return res;
+#endif
+}
diff --git a/erts/emulator/beam/erl_thr_queue.h b/erts/emulator/beam/erl_thr_queue.h
new file mode 100644
index 0000000000..407c23f5eb
--- /dev/null
+++ b/erts/emulator/beam/erl_thr_queue.h
@@ -0,0 +1,211 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description: Lock-free queue for communication between threads.
+ *
+ * Currently only a many-to-one version has been,
+ * implemented, i.e., many threads can enqueue but
+ * only one thread can dequeue at a time. It doesn't
+ * have to be the same thread dequeuing every time, but
+ * synchronization so that only one thread dequeues
+ * at a time has to be provided by other means.
+ *
+ * When/If the need for a many-to-many queue arises,
+ * this implementation can relatively easy be extended
+ * to support that too.
+ *
+ * Usage instructions can be found in erts_thr_queue.c
+ *
+ * Author: Rickard Green
+ */
+
+#ifndef ERL_THR_QUEUE_H__
+#define ERL_THR_QUEUE_H__
+
+#include "sys.h"
+#include "erl_threads.h"
+#include "erl_alloc.h"
+#include "erl_thr_progress.h"
+
+typedef enum {
+ ERTS_THR_Q_LIVE_UNDEF,
+ ERTS_THR_Q_LIVE_SHORT,
+ ERTS_THR_Q_LIVE_LONG
+} ErtsThrQLive_t;
+
+#define ERTS_THR_Q_INIT_DEFAULT \
+{ \
+ { \
+ ERTS_THR_Q_LIVE_UNDEF, \
+ ERTS_THR_Q_LIVE_SHORT \
+ }, \
+ NULL, \
+ NULL, \
+ 1 \
+}
+
+typedef struct ErtsThrQ_t_ ErtsThrQ_t;
+
+typedef struct {
+ struct {
+ ErtsThrQLive_t queue;
+ ErtsThrQLive_t objects;
+ } live;
+ void *arg;
+ void (*notify)(void *);
+ int auto_finalize_dequeue;
+} ErtsThrQInit_t;
+
+typedef struct ErtsThrQElement_t_ ErtsThrQElement_t;
+typedef struct ErtsThrQElement_t ErtsThrQPrepEnQ_t;
+
+typedef union {
+ erts_atomic_t atmc;
+ ErtsThrQElement_t *ptr;
+} ErtsThrQPtr_t;
+
+struct ErtsThrQElement_t_ {
+ ErtsThrQPtr_t next;
+ union {
+ erts_atomic_t atmc;
+ void *ptr;
+ } data;
+};
+
+typedef struct {
+ ErtsThrQElement_t *start;
+ ErtsThrQElement_t *end;
+} ErtsThrQFinDeQ_t;
+
+typedef enum {
+ ERTS_THR_Q_CLEAN,
+#ifdef ERTS_SMP
+ ERTS_THR_Q_NEED_THR_PRGR,
+#endif
+ ERTS_THR_Q_DIRTY,
+} ErtsThrQCleanState_t;
+
+#ifdef USE_THREADS
+
+typedef struct {
+ ErtsThrQElement_t marker;
+ erts_atomic_t last;
+ erts_atomic_t um_refc[2];
+ erts_atomic32_t um_refc_ix;
+ ErtsThrQLive_t live;
+#ifdef ERTS_SMP
+ erts_atomic32_t thr_prgr_clean_scheduled;
+#endif
+ void *arg;
+ void (*notify)(void *);
+} ErtsThrQTail_t;
+
+struct ErtsThrQ_t_ {
+ /*
+ * This structure needs to be cache line aligned for best
+ * performance.
+ */
+ union {
+ /* Modified by threads enqueuing */
+ ErtsThrQTail_t data;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsThrQTail_t))];
+ } tail;
+ /*
+ * Everything below this point is *only* accessed by the
+ * thread dequeuing.
+ */
+ struct {
+ ErtsThrQPtr_t head;
+ ErtsThrQLive_t live;
+ ErtsThrQElement_t *first;
+ ErtsThrQElement_t *unref_end;
+ int clean_reached_head_count;
+ struct {
+ int automatic;
+ ErtsThrQElement_t *start;
+ ErtsThrQElement_t *end;
+ } deq_fini;
+ struct {
+#ifdef ERTS_SMP
+ ErtsThrPrgrVal thr_progress;
+ int thr_progress_reached;
+#endif
+ int um_refc_ix;
+ ErtsThrQElement_t *unref_end;
+ } next;
+ int used_marker;
+ void *arg;
+ void (*notify)(void *);
+ } head;
+ struct {
+ int finalizing;
+ ErtsThrQLive_t live;
+ void *blk;
+ } q;
+};
+
+#else /* !USE_THREADS */
+
+struct ErtsThrQ_t_ {
+ ErtsThrQInit_t init;
+ ErtsThrQElement_t *first;
+ ErtsThrQElement_t *last;
+ struct {
+ void *blk;
+ } q;
+};
+
+#endif
+
+void erts_thr_q_init(void);
+void erts_thr_q_initialize(ErtsThrQ_t *, ErtsThrQInit_t *);
+ErtsThrQCleanState_t erts_thr_q_finalize(ErtsThrQ_t *);
+ErtsThrQ_t *erts_thr_q_create(ErtsThrQInit_t *);
+ErtsThrQCleanState_t erts_thr_q_destroy(ErtsThrQ_t *);
+ErtsThrQCleanState_t erts_thr_q_clean(ErtsThrQ_t *);
+ErtsThrQCleanState_t erts_thr_q_inspect(ErtsThrQ_t *, int);
+ErtsThrQPrepEnQ_t *erts_thr_q_prepare_enqueue(ErtsThrQ_t *);
+void erts_thr_q_enqueue_prepared(ErtsThrQ_t *, void *, ErtsThrQPrepEnQ_t *);
+void erts_thr_q_enqueue(ErtsThrQ_t *, void *);
+void * erts_thr_q_dequeue(ErtsThrQ_t *);
+int erts_thr_q_get_finalize_dequeue_data(ErtsThrQ_t *,
+ ErtsThrQFinDeQ_t *);
+void erts_thr_q_append_finalize_dequeue_data(ErtsThrQFinDeQ_t *,
+ ErtsThrQFinDeQ_t *);
+int erts_thr_q_finalize_dequeue(ErtsThrQFinDeQ_t *);
+void erts_thr_q_finalize_dequeue_state_init(ErtsThrQFinDeQ_t *);
+
+#ifdef ERTS_SMP
+ERTS_GLB_INLINE ErtsThrPrgrVal erts_thr_q_need_thr_progress(ErtsThrQ_t *q);
+#endif
+
+#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+
+#ifdef ERTS_SMP
+ERTS_GLB_INLINE ErtsThrPrgrVal
+erts_thr_q_need_thr_progress(ErtsThrQ_t *q)
+{
+ return q->head.next.thr_progress;
+}
+#endif
+
+#endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */
+
+#endif /* ERL_THR_QUEUE_H__ */
diff --git a/erts/emulator/beam/erl_threads.h b/erts/emulator/beam/erl_threads.h
index 8c9cace0c5..065e7077c0 100644
--- a/erts/emulator/beam/erl_threads.h
+++ b/erts/emulator/beam/erl_threads.h
@@ -28,6 +28,11 @@
#define ERTS_SPIN_BODY ETHR_SPIN_BODY
#include "sys.h"
+
+typedef struct { SWord sint[2]; } erts_no_dw_atomic_t;
+typedef SWord erts_no_atomic_t;
+typedef Sint32 erts_no_atomic32_t;
+
#ifdef USE_THREADS
#define ETHR_TRY_INLINE_FUNCS
@@ -87,6 +92,8 @@ typedef struct {
#endif
} erts_rwmtx_t;
+#define ERTS_MTX_OPT_DEFAULT_INITER ETHR_MUTEX_OPT_DEFAULT_INITER
+#define ERTS_CND_OPT_DEFAULT_INITER ETHR_COND_OPT_DEFAULT_INITER
#define ERTS_RWMTX_OPT_DEFAULT_INITER ETHR_RWMUTEX_OPT_DEFAULT_INITER
#define ERTS_RWMTX_TYPE_NORMAL ETHR_RWMUTEX_TYPE_NORMAL
#define ERTS_RWMTX_TYPE_FREQUENT_READ ETHR_RWMUTEX_TYPE_FREQUENT_READ
@@ -99,10 +106,12 @@ typedef ethr_rwmutex_opt erts_rwmtx_opt_t;
typedef ethr_tsd_key erts_tsd_key_t;
typedef ethr_ts_event erts_tse_t;
-typedef ethr_sint_t erts_aint_t;
-typedef ethr_atomic_t erts_atomic_t;
-typedef ethr_sint32_t erts_aint32_t;
-typedef ethr_atomic32_t erts_atomic32_t;
+#define erts_dw_aint_t ethr_dw_sint_t
+#define erts_dw_atomic_t ethr_dw_atomic_t
+#define erts_aint_t ethr_sint_t
+#define erts_atomic_t ethr_atomic_t
+#define erts_aint32_t ethr_sint32_t
+#define erts_atomic32_t ethr_atomic32_t
/* spinlock */
typedef struct {
@@ -164,10 +173,12 @@ typedef struct {
typedef int erts_rwmtx_t;
typedef int erts_tsd_key_t;
typedef int erts_tse_t;
-typedef SWord erts_aint_t;
-typedef SWord erts_atomic_t;
-typedef SWord erts_aint32_t;
-typedef SWord erts_atomic32_t;
+#define erts_dw_aint_t erts_no_dw_atomic_t
+#define erts_dw_atomic_t erts_no_dw_atomic_t
+#define erts_aint_t SWord
+#define erts_atomic_t erts_no_atomic_t
+#define erts_aint32_t Sint32
+#define erts_atomic32_t erts_no_atomic32_t
#if __GNUC__ > 2
typedef struct { } erts_spinlock_t;
typedef struct { } erts_rwlock_t;
@@ -184,6 +195,8 @@ typedef struct { int gcc_is_buggy; } erts_rwlock_t;
#endif /* #ifdef USE_THREADS */
+#define ERTS_AINT_NULL ((erts_aint_t) NULL)
+
#define ERTS_AINT_T_MAX (~(((erts_aint_t) 1) << (sizeof(erts_aint_t)*8-1)))
#define ERTS_AINT_T_MIN ((((erts_aint_t) 1) << (sizeof(erts_aint_t)*8-1)))
#define ERTS_AINT32_T_MAX (~(((erts_aint32_t) 1) << (sizeof(erts_aint32_t)*8-1)))
@@ -247,65 +260,51 @@ ERTS_GLB_INLINE int erts_rwmtx_tryrwlock(erts_rwmtx_t *rwmtx);
ERTS_GLB_INLINE void erts_rwmtx_rwunlock(erts_rwmtx_t *rwmtx);
ERTS_GLB_INLINE int erts_lc_rwmtx_is_rlocked(erts_rwmtx_t *mtx);
ERTS_GLB_INLINE int erts_lc_rwmtx_is_rwlocked(erts_rwmtx_t *mtx);
-ERTS_GLB_INLINE void erts_atomic_init(erts_atomic_t *var, erts_aint_t i);
-ERTS_GLB_INLINE void erts_atomic_set(erts_atomic_t *var, erts_aint_t i);
-ERTS_GLB_INLINE erts_aint_t erts_atomic_read(erts_atomic_t *var);
-ERTS_GLB_INLINE erts_aint_t erts_atomic_inctest(erts_atomic_t *incp);
-ERTS_GLB_INLINE erts_aint_t erts_atomic_dectest(erts_atomic_t *decp);
-ERTS_GLB_INLINE void erts_atomic_inc(erts_atomic_t *incp);
-ERTS_GLB_INLINE void erts_atomic_dec(erts_atomic_t *decp);
-ERTS_GLB_INLINE erts_aint_t erts_atomic_addtest(erts_atomic_t *addp,
- erts_aint_t i);
-ERTS_GLB_INLINE void erts_atomic_add(erts_atomic_t *addp, erts_aint_t i);
-ERTS_GLB_INLINE erts_aint_t erts_atomic_xchg(erts_atomic_t *xchgp,
- erts_aint_t new);
-ERTS_GLB_INLINE erts_aint_t erts_atomic_cmpxchg(erts_atomic_t *xchgp,
- erts_aint_t new,
- erts_aint_t expected);
-ERTS_GLB_INLINE erts_aint_t erts_atomic_bor(erts_atomic_t *var,
- erts_aint_t mask);
-ERTS_GLB_INLINE erts_aint_t erts_atomic_band(erts_atomic_t *var,
- erts_aint_t mask);
-ERTS_GLB_INLINE erts_aint_t erts_atomic_read_acqb(erts_atomic_t *var);
-ERTS_GLB_INLINE void erts_atomic_set_relb(erts_atomic_t *var, erts_aint_t i);
-ERTS_GLB_INLINE void erts_atomic_dec_relb(erts_atomic_t *decp);
-ERTS_GLB_INLINE erts_aint_t erts_atomic_dectest_relb(erts_atomic_t *decp);
-ERTS_GLB_INLINE erts_aint_t erts_atomic_cmpxchg_acqb(erts_atomic_t *xchgp,
- erts_aint_t new,
- erts_aint_t exp);
-ERTS_GLB_INLINE erts_aint_t erts_atomic_cmpxchg_relb(erts_atomic_t *xchgp,
- erts_aint_t new,
- erts_aint_t exp);
-ERTS_GLB_INLINE void erts_atomic32_init(erts_atomic32_t *var, erts_aint32_t i);
-ERTS_GLB_INLINE void erts_atomic32_set(erts_atomic32_t *var, erts_aint32_t i);
-ERTS_GLB_INLINE erts_aint32_t erts_atomic32_read(erts_atomic32_t *var);
-ERTS_GLB_INLINE erts_aint32_t erts_atomic32_inctest(erts_atomic32_t *incp);
-ERTS_GLB_INLINE erts_aint32_t erts_atomic32_dectest(erts_atomic32_t *decp);
-ERTS_GLB_INLINE void erts_atomic32_inc(erts_atomic32_t *incp);
-ERTS_GLB_INLINE void erts_atomic32_dec(erts_atomic32_t *decp);
-ERTS_GLB_INLINE erts_aint32_t erts_atomic32_addtest(erts_atomic32_t *addp,
- erts_aint32_t i);
-ERTS_GLB_INLINE void erts_atomic32_add(erts_atomic32_t *addp, erts_aint32_t i);
-ERTS_GLB_INLINE erts_aint32_t erts_atomic32_xchg(erts_atomic32_t *xchgp,
- erts_aint32_t new);
-ERTS_GLB_INLINE erts_aint32_t erts_atomic32_cmpxchg(erts_atomic32_t *xchgp,
- erts_aint32_t new,
- erts_aint32_t expected);
-ERTS_GLB_INLINE erts_aint32_t erts_atomic32_bor(erts_atomic32_t *var,
- erts_aint32_t mask);
-ERTS_GLB_INLINE erts_aint32_t erts_atomic32_band(erts_atomic32_t *var,
- erts_aint32_t mask);
-ERTS_GLB_INLINE erts_aint32_t erts_atomic32_read_acqb(erts_atomic32_t *var);
-ERTS_GLB_INLINE void erts_atomic32_set_relb(erts_atomic32_t *var,
- erts_aint32_t i);
-ERTS_GLB_INLINE void erts_atomic32_dec_relb(erts_atomic32_t *decp);
-ERTS_GLB_INLINE erts_aint32_t erts_atomic32_dectest_relb(erts_atomic32_t *decp);
-ERTS_GLB_INLINE erts_aint32_t erts_atomic32_cmpxchg_acqb(erts_atomic32_t *xchgp,
- erts_aint32_t new,
- erts_aint32_t exp);
-ERTS_GLB_INLINE erts_aint32_t erts_atomic32_cmpxchg_relb(erts_atomic32_t *xchgp,
- erts_aint32_t new,
- erts_aint32_t exp);
+
+ERTS_GLB_INLINE void erts_no_dw_atomic_set(erts_no_dw_atomic_t *var, erts_no_dw_atomic_t *val);
+ERTS_GLB_INLINE void erts_no_dw_atomic_read(erts_no_dw_atomic_t *var, erts_no_dw_atomic_t *val);
+ERTS_GLB_INLINE int erts_no_dw_atomic_cmpxchg(erts_no_dw_atomic_t *var,
+ erts_no_dw_atomic_t *val,
+ erts_no_dw_atomic_t *old_val);
+ERTS_GLB_INLINE void erts_no_atomic_set(erts_no_atomic_t *var, erts_aint_t i);
+ERTS_GLB_INLINE erts_aint_t erts_no_atomic_read(erts_no_atomic_t *var);
+ERTS_GLB_INLINE erts_aint_t erts_no_atomic_inc_read(erts_no_atomic_t *incp);
+ERTS_GLB_INLINE erts_aint_t erts_no_atomic_dec_read(erts_no_atomic_t *decp);
+ERTS_GLB_INLINE void erts_no_atomic_inc(erts_no_atomic_t *incp);
+ERTS_GLB_INLINE void erts_no_atomic_dec(erts_no_atomic_t *decp);
+ERTS_GLB_INLINE erts_aint_t erts_no_atomic_add_read(erts_no_atomic_t *addp,
+ erts_aint_t i);
+ERTS_GLB_INLINE void erts_no_atomic_add(erts_no_atomic_t *addp, erts_aint_t i);
+ERTS_GLB_INLINE erts_aint_t erts_no_atomic_read_bor(erts_no_atomic_t *var,
+ erts_aint_t mask);
+ERTS_GLB_INLINE erts_aint_t erts_no_atomic_read_band(erts_no_atomic_t *var,
+ erts_aint_t mask);
+ERTS_GLB_INLINE erts_aint_t erts_no_atomic_xchg(erts_no_atomic_t *xchgp,
+ erts_aint_t new);
+ERTS_GLB_INLINE erts_aint_t erts_no_atomic_cmpxchg(erts_no_atomic_t *xchgp,
+ erts_aint_t new,
+ erts_aint_t expected);
+ERTS_GLB_INLINE void erts_no_atomic32_set(erts_no_atomic32_t *var,
+ erts_aint32_t i);
+ERTS_GLB_INLINE erts_aint32_t erts_no_atomic32_read(erts_no_atomic32_t *var);
+ERTS_GLB_INLINE erts_aint32_t erts_no_atomic32_inc_read(erts_no_atomic32_t *incp);
+ERTS_GLB_INLINE erts_aint32_t erts_no_atomic32_dec_read(erts_no_atomic32_t *decp);
+ERTS_GLB_INLINE void erts_no_atomic32_inc(erts_no_atomic32_t *incp);
+ERTS_GLB_INLINE void erts_no_atomic32_dec(erts_no_atomic32_t *decp);
+ERTS_GLB_INLINE erts_aint32_t erts_no_atomic32_add_read(erts_no_atomic32_t *addp,
+ erts_aint32_t i);
+ERTS_GLB_INLINE void erts_no_atomic32_add(erts_no_atomic32_t *addp,
+ erts_aint32_t i);
+ERTS_GLB_INLINE erts_aint32_t erts_no_atomic32_read_bor(erts_no_atomic32_t *var,
+ erts_aint32_t mask);
+ERTS_GLB_INLINE erts_aint32_t erts_no_atomic32_read_band(erts_no_atomic32_t *var,
+ erts_aint32_t mask);
+ERTS_GLB_INLINE erts_aint32_t erts_no_atomic32_xchg(erts_no_atomic32_t *xchgp,
+ erts_aint32_t new);
+ERTS_GLB_INLINE erts_aint32_t erts_no_atomic32_cmpxchg(erts_no_atomic32_t *xchgp,
+ erts_aint32_t new,
+ erts_aint32_t expected);
+
ERTS_GLB_INLINE void erts_spinlock_init_x_opt(erts_spinlock_t *lock,
char *name,
Eterm extra,
@@ -362,6 +361,430 @@ ERTS_GLB_INLINE void erts_thr_sigmask(int how, const sigset_t *set,
ERTS_GLB_INLINE void erts_thr_sigwait(const sigset_t *set, int *sig);
#endif /* #ifdef HAVE_ETHR_SIG_FUNCS */
+/*
+ * Functions implementing atomic operations with with no (nob),
+ * full (mb), acquire (acqb), release (relb), read (rb), and
+ * write (wb) memory barriers.
+ *
+ * If thread support has been disabled, they are mapped to
+ * functions that performs the same operation, but aren't atomic
+ * and don't imply memory barriers.
+ */
+
+#ifdef USE_THREADS
+
+/* Double word size atomics */
+
+#define erts_dw_atomic_init_nob ethr_dw_atomic_init
+#define erts_dw_atomic_set_nob ethr_dw_atomic_set
+#define erts_dw_atomic_read_nob ethr_dw_atomic_read
+#define erts_dw_atomic_cmpxchg_nob ethr_dw_atomic_cmpxchg
+
+#define erts_dw_atomic_init_mb ethr_dw_atomic_init_mb
+#define erts_dw_atomic_set_mb ethr_dw_atomic_set_mb
+#define erts_dw_atomic_read_mb ethr_dw_atomic_read_mb
+#define erts_dw_atomic_cmpxchg_mb ethr_dw_atomic_cmpxchg_mb
+
+#define erts_dw_atomic_init_acqb ethr_dw_atomic_init_acqb
+#define erts_dw_atomic_set_acqb ethr_dw_atomic_set_acqb
+#define erts_dw_atomic_read_acqb ethr_dw_atomic_read_acqb
+#define erts_dw_atomic_cmpxchg_acqb ethr_dw_atomic_cmpxchg_acqb
+
+#define erts_dw_atomic_init_relb ethr_dw_atomic_init_relb
+#define erts_dw_atomic_set_relb ethr_dw_atomic_set_relb
+#define erts_dw_atomic_read_relb ethr_dw_atomic_read_relb
+#define erts_dw_atomic_cmpxchg_relb ethr_dw_atomic_cmpxchg_relb
+
+#define erts_dw_atomic_init_rb ethr_dw_atomic_init_rb
+#define erts_dw_atomic_set_rb ethr_dw_atomic_set_rb
+#define erts_dw_atomic_read_rb ethr_dw_atomic_read_rb
+#define erts_dw_atomic_cmpxchg_rb ethr_dw_atomic_cmpxchg_rb
+
+#define erts_dw_atomic_init_wb ethr_dw_atomic_init_wb
+#define erts_dw_atomic_set_wb ethr_dw_atomic_set_wb
+#define erts_dw_atomic_read_wb ethr_dw_atomic_read_wb
+#define erts_dw_atomic_cmpxchg_wb ethr_dw_atomic_cmpxchg_wb
+
+/* Word size atomics */
+
+#define erts_atomic_init_nob ethr_atomic_init
+#define erts_atomic_set_nob ethr_atomic_set
+#define erts_atomic_read_nob ethr_atomic_read
+#define erts_atomic_inc_read_nob ethr_atomic_inc_read
+#define erts_atomic_dec_read_nob ethr_atomic_dec_read
+#define erts_atomic_inc_nob ethr_atomic_inc
+#define erts_atomic_dec_nob ethr_atomic_dec
+#define erts_atomic_add_read_nob ethr_atomic_add_read
+#define erts_atomic_add_nob ethr_atomic_add
+#define erts_atomic_read_bor_nob ethr_atomic_read_bor
+#define erts_atomic_read_band_nob ethr_atomic_read_band
+#define erts_atomic_xchg_nob ethr_atomic_xchg
+#define erts_atomic_cmpxchg_nob ethr_atomic_cmpxchg
+
+#define erts_atomic_init_mb ethr_atomic_init_mb
+#define erts_atomic_set_mb ethr_atomic_set_mb
+#define erts_atomic_read_mb ethr_atomic_read_mb
+#define erts_atomic_inc_read_mb ethr_atomic_inc_read_mb
+#define erts_atomic_dec_read_mb ethr_atomic_dec_read_mb
+#define erts_atomic_inc_mb ethr_atomic_inc_mb
+#define erts_atomic_dec_mb ethr_atomic_dec_mb
+#define erts_atomic_add_read_mb ethr_atomic_add_read_mb
+#define erts_atomic_add_mb ethr_atomic_add_mb
+#define erts_atomic_read_bor_mb ethr_atomic_read_bor_mb
+#define erts_atomic_read_band_mb ethr_atomic_read_band_mb
+#define erts_atomic_xchg_mb ethr_atomic_xchg_mb
+#define erts_atomic_cmpxchg_mb ethr_atomic_cmpxchg_mb
+
+#define erts_atomic_init_acqb ethr_atomic_init_acqb
+#define erts_atomic_set_acqb ethr_atomic_set_acqb
+#define erts_atomic_read_acqb ethr_atomic_read_acqb
+#define erts_atomic_inc_read_acqb ethr_atomic_inc_read_acqb
+#define erts_atomic_dec_read_acqb ethr_atomic_dec_read_acqb
+#define erts_atomic_inc_acqb ethr_atomic_inc_acqb
+#define erts_atomic_dec_acqb ethr_atomic_dec_acqb
+#define erts_atomic_add_read_acqb ethr_atomic_add_read_acqb
+#define erts_atomic_add_acqb ethr_atomic_add_acqb
+#define erts_atomic_read_bor_acqb ethr_atomic_read_bor_acqb
+#define erts_atomic_read_band_acqb ethr_atomic_read_band_acqb
+#define erts_atomic_xchg_acqb ethr_atomic_xchg_acqb
+#define erts_atomic_cmpxchg_acqb ethr_atomic_cmpxchg_acqb
+
+#define erts_atomic_init_relb ethr_atomic_init_relb
+#define erts_atomic_set_relb ethr_atomic_set_relb
+#define erts_atomic_read_relb ethr_atomic_read_relb
+#define erts_atomic_inc_read_relb ethr_atomic_inc_read_relb
+#define erts_atomic_dec_read_relb ethr_atomic_dec_read_relb
+#define erts_atomic_inc_relb ethr_atomic_inc_relb
+#define erts_atomic_dec_relb ethr_atomic_dec_relb
+#define erts_atomic_add_read_relb ethr_atomic_add_read_relb
+#define erts_atomic_add_relb ethr_atomic_add_relb
+#define erts_atomic_read_bor_relb ethr_atomic_read_bor_relb
+#define erts_atomic_read_band_relb ethr_atomic_read_band_relb
+#define erts_atomic_xchg_relb ethr_atomic_xchg_relb
+#define erts_atomic_cmpxchg_relb ethr_atomic_cmpxchg_relb
+
+#define erts_atomic_init_rb ethr_atomic_init_rb
+#define erts_atomic_set_rb ethr_atomic_set_rb
+#define erts_atomic_read_rb ethr_atomic_read_rb
+#define erts_atomic_inc_read_rb ethr_atomic_inc_read_rb
+#define erts_atomic_dec_read_rb ethr_atomic_dec_read_rb
+#define erts_atomic_inc_rb ethr_atomic_inc_rb
+#define erts_atomic_dec_rb ethr_atomic_dec_rb
+#define erts_atomic_add_read_rb ethr_atomic_add_read_rb
+#define erts_atomic_add_rb ethr_atomic_add_rb
+#define erts_atomic_read_bor_rb ethr_atomic_read_bor_rb
+#define erts_atomic_read_band_rb ethr_atomic_read_band_rb
+#define erts_atomic_xchg_rb ethr_atomic_xchg_rb
+#define erts_atomic_cmpxchg_rb ethr_atomic_cmpxchg_rb
+
+#define erts_atomic_init_wb ethr_atomic_init_wb
+#define erts_atomic_set_wb ethr_atomic_set_wb
+#define erts_atomic_read_wb ethr_atomic_read_wb
+#define erts_atomic_inc_read_wb ethr_atomic_inc_read_wb
+#define erts_atomic_dec_read_wb ethr_atomic_dec_read_wb
+#define erts_atomic_inc_wb ethr_atomic_inc_wb
+#define erts_atomic_dec_wb ethr_atomic_dec_wb
+#define erts_atomic_add_read_wb ethr_atomic_add_read_wb
+#define erts_atomic_add_wb ethr_atomic_add_wb
+#define erts_atomic_read_bor_wb ethr_atomic_read_bor_wb
+#define erts_atomic_read_band_wb ethr_atomic_read_band_wb
+#define erts_atomic_xchg_wb ethr_atomic_xchg_wb
+#define erts_atomic_cmpxchg_wb ethr_atomic_cmpxchg_wb
+
+/* 32-bit atomics */
+
+#define erts_atomic32_init_nob ethr_atomic32_init
+#define erts_atomic32_set_nob ethr_atomic32_set
+#define erts_atomic32_read_nob ethr_atomic32_read
+#define erts_atomic32_inc_read_nob ethr_atomic32_inc_read
+#define erts_atomic32_dec_read_nob ethr_atomic32_dec_read
+#define erts_atomic32_inc_nob ethr_atomic32_inc
+#define erts_atomic32_dec_nob ethr_atomic32_dec
+#define erts_atomic32_add_read_nob ethr_atomic32_add_read
+#define erts_atomic32_add_nob ethr_atomic32_add
+#define erts_atomic32_read_bor_nob ethr_atomic32_read_bor
+#define erts_atomic32_read_band_nob ethr_atomic32_read_band
+#define erts_atomic32_xchg_nob ethr_atomic32_xchg
+#define erts_atomic32_cmpxchg_nob ethr_atomic32_cmpxchg
+
+#define erts_atomic32_init_mb ethr_atomic32_init_mb
+#define erts_atomic32_set_mb ethr_atomic32_set_mb
+#define erts_atomic32_read_mb ethr_atomic32_read_mb
+#define erts_atomic32_inc_read_mb ethr_atomic32_inc_read_mb
+#define erts_atomic32_dec_read_mb ethr_atomic32_dec_read_mb
+#define erts_atomic32_inc_mb ethr_atomic32_inc_mb
+#define erts_atomic32_dec_mb ethr_atomic32_dec_mb
+#define erts_atomic32_add_read_mb ethr_atomic32_add_read_mb
+#define erts_atomic32_add_mb ethr_atomic32_add_mb
+#define erts_atomic32_read_bor_mb ethr_atomic32_read_bor_mb
+#define erts_atomic32_read_band_mb ethr_atomic32_read_band_mb
+#define erts_atomic32_xchg_mb ethr_atomic32_xchg_mb
+#define erts_atomic32_cmpxchg_mb ethr_atomic32_cmpxchg_mb
+
+#define erts_atomic32_init_acqb ethr_atomic32_init_acqb
+#define erts_atomic32_set_acqb ethr_atomic32_set_acqb
+#define erts_atomic32_read_acqb ethr_atomic32_read_acqb
+#define erts_atomic32_inc_read_acqb ethr_atomic32_inc_read_acqb
+#define erts_atomic32_dec_read_acqb ethr_atomic32_dec_read_acqb
+#define erts_atomic32_inc_acqb ethr_atomic32_inc_acqb
+#define erts_atomic32_dec_acqb ethr_atomic32_dec_acqb
+#define erts_atomic32_add_read_acqb ethr_atomic32_add_read_acqb
+#define erts_atomic32_add_acqb ethr_atomic32_add_acqb
+#define erts_atomic32_read_bor_acqb ethr_atomic32_read_bor_acqb
+#define erts_atomic32_read_band_acqb ethr_atomic32_read_band_acqb
+#define erts_atomic32_xchg_acqb ethr_atomic32_xchg_acqb
+#define erts_atomic32_cmpxchg_acqb ethr_atomic32_cmpxchg_acqb
+
+#define erts_atomic32_init_relb ethr_atomic32_init_relb
+#define erts_atomic32_set_relb ethr_atomic32_set_relb
+#define erts_atomic32_read_relb ethr_atomic32_read_relb
+#define erts_atomic32_inc_read_relb ethr_atomic32_inc_read_relb
+#define erts_atomic32_dec_read_relb ethr_atomic32_dec_read_relb
+#define erts_atomic32_inc_relb ethr_atomic32_inc_relb
+#define erts_atomic32_dec_relb ethr_atomic32_dec_relb
+#define erts_atomic32_add_read_relb ethr_atomic32_add_read_relb
+#define erts_atomic32_add_relb ethr_atomic32_add_relb
+#define erts_atomic32_read_bor_relb ethr_atomic32_read_bor_relb
+#define erts_atomic32_read_band_relb ethr_atomic32_read_band_relb
+#define erts_atomic32_xchg_relb ethr_atomic32_xchg_relb
+#define erts_atomic32_cmpxchg_relb ethr_atomic32_cmpxchg_relb
+
+#define erts_atomic32_init_rb ethr_atomic32_init_rb
+#define erts_atomic32_set_rb ethr_atomic32_set_rb
+#define erts_atomic32_read_rb ethr_atomic32_read_rb
+#define erts_atomic32_inc_read_rb ethr_atomic32_inc_read_rb
+#define erts_atomic32_dec_read_rb ethr_atomic32_dec_read_rb
+#define erts_atomic32_inc_rb ethr_atomic32_inc_rb
+#define erts_atomic32_dec_rb ethr_atomic32_dec_rb
+#define erts_atomic32_add_read_rb ethr_atomic32_add_read_rb
+#define erts_atomic32_add_rb ethr_atomic32_add_rb
+#define erts_atomic32_read_bor_rb ethr_atomic32_read_bor_rb
+#define erts_atomic32_read_band_rb ethr_atomic32_read_band_rb
+#define erts_atomic32_xchg_rb ethr_atomic32_xchg_rb
+#define erts_atomic32_cmpxchg_rb ethr_atomic32_cmpxchg_rb
+
+#define erts_atomic32_init_wb ethr_atomic32_init_wb
+#define erts_atomic32_set_wb ethr_atomic32_set_wb
+#define erts_atomic32_read_wb ethr_atomic32_read_wb
+#define erts_atomic32_inc_read_wb ethr_atomic32_inc_read_wb
+#define erts_atomic32_dec_read_wb ethr_atomic32_dec_read_wb
+#define erts_atomic32_inc_wb ethr_atomic32_inc_wb
+#define erts_atomic32_dec_wb ethr_atomic32_dec_wb
+#define erts_atomic32_add_read_wb ethr_atomic32_add_read_wb
+#define erts_atomic32_add_wb ethr_atomic32_add_wb
+#define erts_atomic32_read_bor_wb ethr_atomic32_read_bor_wb
+#define erts_atomic32_read_band_wb ethr_atomic32_read_band_wb
+#define erts_atomic32_xchg_wb ethr_atomic32_xchg_wb
+#define erts_atomic32_cmpxchg_wb ethr_atomic32_cmpxchg_wb
+
+#else /* !USE_THREADS */
+
+/* Double word size atomics */
+
+#define erts_dw_atomic_init_nob erts_no_dw_atomic_set
+#define erts_dw_atomic_set_nob erts_no_dw_atomic_set
+#define erts_dw_atomic_read_nob erts_no_dw_atomic_read
+#define erts_dw_atomic_cmpxchg_nob erts_no_dw_atomic_cmpxchg
+
+#define erts_dw_atomic_init_mb erts_no_dw_atomic_init
+#define erts_dw_atomic_set_mb erts_no_dw_atomic_set
+#define erts_dw_atomic_read_mb erts_no_dw_atomic_read
+#define erts_dw_atomic_cmpxchg_mb erts_no_dw_atomic_cmpxchg
+
+#define erts_dw_atomic_init_acqb erts_no_dw_atomic_init
+#define erts_dw_atomic_set_acqb erts_no_dw_atomic_set
+#define erts_dw_atomic_read_acqb erts_no_dw_atomic_read
+#define erts_dw_atomic_cmpxchg_acqb erts_no_dw_atomic_cmpxchg
+
+#define erts_dw_atomic_init_relb erts_no_dw_atomic_init
+#define erts_dw_atomic_set_relb erts_no_dw_atomic_set
+#define erts_dw_atomic_read_relb erts_no_dw_atomic_read
+#define erts_dw_atomic_cmpxchg_relb erts_no_dw_atomic_cmpxchg
+
+#define erts_dw_atomic_init_rb erts_no_dw_atomic_init
+#define erts_dw_atomic_set_rb erts_no_dw_atomic_set
+#define erts_dw_atomic_read_rb erts_no_dw_atomic_read
+#define erts_dw_atomic_cmpxchg_rb erts_no_dw_atomic_cmpxchg
+
+#define erts_dw_atomic_init_wb erts_no_dw_atomic_init
+#define erts_dw_atomic_set_wb erts_no_dw_atomic_set
+#define erts_dw_atomic_read_wb erts_no_dw_atomic_read
+#define erts_dw_atomic_cmpxchg_wb erts_no_dw_atomic_cmpxchg
+
+/* Word size atomics */
+
+#define erts_atomic_init_nob erts_no_atomic_set
+#define erts_atomic_set_nob erts_no_atomic_set
+#define erts_atomic_read_nob erts_no_atomic_read
+#define erts_atomic_inc_read_nob erts_no_atomic_inc_read
+#define erts_atomic_dec_read_nob erts_no_atomic_dec_read
+#define erts_atomic_inc_nob erts_no_atomic_inc
+#define erts_atomic_dec_nob erts_no_atomic_dec
+#define erts_atomic_add_read_nob erts_no_atomic_add_read
+#define erts_atomic_add_nob erts_no_atomic_add
+#define erts_atomic_read_bor_nob erts_no_atomic_read_bor
+#define erts_atomic_read_band_nob erts_no_atomic_read_band
+#define erts_atomic_xchg_nob erts_no_atomic_xchg
+#define erts_atomic_cmpxchg_nob erts_no_atomic_cmpxchg
+
+#define erts_atomic_init_mb erts_no_atomic_set
+#define erts_atomic_set_mb erts_no_atomic_set
+#define erts_atomic_read_mb erts_no_atomic_read
+#define erts_atomic_inc_read_mb erts_no_atomic_inc_read
+#define erts_atomic_dec_read_mb erts_no_atomic_dec_read
+#define erts_atomic_inc_mb erts_no_atomic_inc
+#define erts_atomic_dec_mb erts_no_atomic_dec
+#define erts_atomic_add_read_mb erts_no_atomic_add_read
+#define erts_atomic_add_mb erts_no_atomic_add
+#define erts_atomic_read_bor_mb erts_no_atomic_read_bor
+#define erts_atomic_read_band_mb erts_no_atomic_read_band
+#define erts_atomic_xchg_mb erts_no_atomic_xchg
+#define erts_atomic_cmpxchg_mb erts_no_atomic_cmpxchg
+
+#define erts_atomic_init_acqb erts_no_atomic_set
+#define erts_atomic_set_acqb erts_no_atomic_set
+#define erts_atomic_read_acqb erts_no_atomic_read
+#define erts_atomic_inc_read_acqb erts_no_atomic_inc_read
+#define erts_atomic_dec_read_acqb erts_no_atomic_dec_read
+#define erts_atomic_inc_acqb erts_no_atomic_inc
+#define erts_atomic_dec_acqb erts_no_atomic_dec
+#define erts_atomic_add_read_acqb erts_no_atomic_add_read
+#define erts_atomic_add_acqb erts_no_atomic_add
+#define erts_atomic_read_bor_acqb erts_no_atomic_read_bor
+#define erts_atomic_read_band_acqb erts_no_atomic_read_band
+#define erts_atomic_xchg_acqb erts_no_atomic_xchg
+#define erts_atomic_cmpxchg_acqb erts_no_atomic_cmpxchg
+
+#define erts_atomic_init_relb erts_no_atomic_set
+#define erts_atomic_set_relb erts_no_atomic_set
+#define erts_atomic_read_relb erts_no_atomic_read
+#define erts_atomic_inc_read_relb erts_no_atomic_inc_read
+#define erts_atomic_dec_read_relb erts_no_atomic_dec_read
+#define erts_atomic_inc_relb erts_no_atomic_inc
+#define erts_atomic_dec_relb erts_no_atomic_dec
+#define erts_atomic_add_read_relb erts_no_atomic_add_read
+#define erts_atomic_add_relb erts_no_atomic_add
+#define erts_atomic_read_bor_relb erts_no_atomic_read_bor
+#define erts_atomic_read_band_relb erts_no_atomic_read_band
+#define erts_atomic_xchg_relb erts_no_atomic_xchg
+#define erts_atomic_cmpxchg_relb erts_no_atomic_cmpxchg
+
+#define erts_atomic_init_rb erts_no_atomic_set
+#define erts_atomic_set_rb erts_no_atomic_set
+#define erts_atomic_read_rb erts_no_atomic_read
+#define erts_atomic_inc_read_rb erts_no_atomic_inc_read
+#define erts_atomic_dec_read_rb erts_no_atomic_dec_read
+#define erts_atomic_inc_rb erts_no_atomic_inc
+#define erts_atomic_dec_rb erts_no_atomic_dec
+#define erts_atomic_add_read_rb erts_no_atomic_add_read
+#define erts_atomic_add_rb erts_no_atomic_add
+#define erts_atomic_read_bor_rb erts_no_atomic_read_bor
+#define erts_atomic_read_band_rb erts_no_atomic_read_band
+#define erts_atomic_xchg_rb erts_no_atomic_xchg
+#define erts_atomic_cmpxchg_rb erts_no_atomic_cmpxchg
+
+#define erts_atomic_init_wb erts_no_atomic_set
+#define erts_atomic_set_wb erts_no_atomic_set
+#define erts_atomic_read_wb erts_no_atomic_read
+#define erts_atomic_inc_read_wb erts_no_atomic_inc_read
+#define erts_atomic_dec_read_wb erts_no_atomic_dec_read
+#define erts_atomic_inc_wb erts_no_atomic_inc
+#define erts_atomic_dec_wb erts_no_atomic_dec
+#define erts_atomic_add_read_wb erts_no_atomic_add_read
+#define erts_atomic_add_wb erts_no_atomic_add
+#define erts_atomic_read_bor_wb erts_no_atomic_read_bor
+#define erts_atomic_read_band_wb erts_no_atomic_read_band
+#define erts_atomic_xchg_wb erts_no_atomic_xchg
+#define erts_atomic_cmpxchg_wb erts_no_atomic_cmpxchg
+
+/* 32-bit atomics */
+
+#define erts_atomic32_init_nob erts_no_atomic32_set
+#define erts_atomic32_set_nob erts_no_atomic32_set
+#define erts_atomic32_read_nob erts_no_atomic32_read
+#define erts_atomic32_inc_read_nob erts_no_atomic32_inc_read
+#define erts_atomic32_dec_read_nob erts_no_atomic32_dec_read
+#define erts_atomic32_inc_nob erts_no_atomic32_inc
+#define erts_atomic32_dec_nob erts_no_atomic32_dec
+#define erts_atomic32_add_read_nob erts_no_atomic32_add_read
+#define erts_atomic32_add_nob erts_no_atomic32_add
+#define erts_atomic32_read_bor_nob erts_no_atomic32_read_bor
+#define erts_atomic32_read_band_nob erts_no_atomic32_read_band
+#define erts_atomic32_xchg_nob erts_no_atomic32_xchg
+#define erts_atomic32_cmpxchg_nob erts_no_atomic32_cmpxchg
+
+#define erts_atomic32_init_mb erts_no_atomic32_set
+#define erts_atomic32_set_mb erts_no_atomic32_set
+#define erts_atomic32_read_mb erts_no_atomic32_read
+#define erts_atomic32_inc_read_mb erts_no_atomic32_inc_read
+#define erts_atomic32_dec_read_mb erts_no_atomic32_dec_read
+#define erts_atomic32_inc_mb erts_no_atomic32_inc
+#define erts_atomic32_dec_mb erts_no_atomic32_dec
+#define erts_atomic32_add_read_mb erts_no_atomic32_add_read
+#define erts_atomic32_add_mb erts_no_atomic32_add
+#define erts_atomic32_read_bor_mb erts_no_atomic32_read_bor
+#define erts_atomic32_read_band_mb erts_no_atomic32_read_band
+#define erts_atomic32_xchg_mb erts_no_atomic32_xchg
+#define erts_atomic32_cmpxchg_mb erts_no_atomic32_cmpxchg
+
+#define erts_atomic32_init_acqb erts_no_atomic32_set
+#define erts_atomic32_set_acqb erts_no_atomic32_set
+#define erts_atomic32_read_acqb erts_no_atomic32_read
+#define erts_atomic32_inc_read_acqb erts_no_atomic32_inc_read
+#define erts_atomic32_dec_read_acqb erts_no_atomic32_dec_read
+#define erts_atomic32_inc_acqb erts_no_atomic32_inc
+#define erts_atomic32_dec_acqb erts_no_atomic32_dec
+#define erts_atomic32_add_read_acqb erts_no_atomic32_add_read
+#define erts_atomic32_add_acqb erts_no_atomic32_add
+#define erts_atomic32_read_bor_acqb erts_no_atomic32_read_bor
+#define erts_atomic32_read_band_acqb erts_no_atomic32_read_band
+#define erts_atomic32_xchg_acqb erts_no_atomic32_xchg
+#define erts_atomic32_cmpxchg_acqb erts_no_atomic32_cmpxchg
+
+#define erts_atomic32_init_relb erts_no_atomic32_set
+#define erts_atomic32_set_relb erts_no_atomic32_set
+#define erts_atomic32_read_relb erts_no_atomic32_read
+#define erts_atomic32_inc_read_relb erts_no_atomic32_inc_read
+#define erts_atomic32_dec_read_relb erts_no_atomic32_dec_read
+#define erts_atomic32_inc_relb erts_no_atomic32_inc
+#define erts_atomic32_dec_relb erts_no_atomic32_dec
+#define erts_atomic32_add_read_relb erts_no_atomic32_add_read
+#define erts_atomic32_add_relb erts_no_atomic32_add
+#define erts_atomic32_read_bor_relb erts_no_atomic32_read_bor
+#define erts_atomic32_read_band_relb erts_no_atomic32_read_band
+#define erts_atomic32_xchg_relb erts_no_atomic32_xchg
+#define erts_atomic32_cmpxchg_relb erts_no_atomic32_cmpxchg
+
+#define erts_atomic32_init_rb erts_no_atomic32_set
+#define erts_atomic32_set_rb erts_no_atomic32_set
+#define erts_atomic32_read_rb erts_no_atomic32_read
+#define erts_atomic32_inc_read_rb erts_no_atomic32_inc_read
+#define erts_atomic32_dec_read_rb erts_no_atomic32_dec_read
+#define erts_atomic32_inc_rb erts_no_atomic32_inc
+#define erts_atomic32_dec_rb erts_no_atomic32_dec
+#define erts_atomic32_add_read_rb erts_no_atomic32_add_read
+#define erts_atomic32_add_rb erts_no_atomic32_add
+#define erts_atomic32_read_bor_rb erts_no_atomic32_read_bor
+#define erts_atomic32_read_band_rb erts_no_atomic32_read_band
+#define erts_atomic32_xchg_rb erts_no_atomic32_xchg
+#define erts_atomic32_cmpxchg_rb erts_no_atomic32_cmpxchg
+
+#define erts_atomic32_init_wb erts_no_atomic32_set
+#define erts_atomic32_set_wb erts_no_atomic32_set
+#define erts_atomic32_read_wb erts_no_atomic32_read
+#define erts_atomic32_inc_read_wb erts_no_atomic32_inc_read
+#define erts_atomic32_dec_read_wb erts_no_atomic32_dec_read
+#define erts_atomic32_inc_wb erts_no_atomic32_inc
+#define erts_atomic32_dec_wb erts_no_atomic32_dec
+#define erts_atomic32_add_read_wb erts_no_atomic32_add_read
+#define erts_atomic32_add_wb erts_no_atomic32_add
+#define erts_atomic32_read_bor_wb erts_no_atomic32_read_bor
+#define erts_atomic32_read_band_wb erts_no_atomic32_read_band
+#define erts_atomic32_xchg_wb erts_no_atomic32_xchg
+#define erts_atomic32_cmpxchg_wb erts_no_atomic32_cmpxchg
+
+#endif /* !USE_THREADS */
+
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
ERTS_GLB_INLINE void
@@ -571,8 +994,9 @@ erts_mtx_destroy(erts_mtx_t *mtx)
"Most likely a bug in pthread implementation.";
erts_send_warning_to_logger_str_nogl(warn);
}
+ else
#endif
- erts_thr_fatal_error(res, "destroy mutex");
+ erts_thr_fatal_error(res, "destroy mutex");
}
#endif
}
@@ -675,8 +1099,9 @@ erts_cnd_destroy(erts_cnd_t *cnd)
"Most likely a bug in pthread implementation.";
erts_send_warning_to_logger_str_nogl(warn);
}
+ else
#endif
- erts_thr_fatal_error(res, "destroy condition variable");
+ erts_thr_fatal_error(res, "destroy condition variable");
}
#endif
}
@@ -707,6 +1132,16 @@ erts_cnd_wait(erts_cnd_t *cnd, erts_mtx_t *mtx)
#endif
}
+/*
+ * IMPORTANT note about erts_cnd_signal() and erts_cnd_broadcast()
+ *
+ * POSIX allow a call to `pthread_cond_signal' or `pthread_cond_broadcast'
+ * even though the associated mutex/mutexes isn't/aren't locked by the
+ * caller. Our implementation do not allow that in order to avoid a
+ * performance penalty. That is, all associated mutexes *need* to be
+ * locked by the caller of erts_cnd_signal()/erts_cnd_broadcast()!
+ */
+
ERTS_GLB_INLINE void
erts_cnd_signal(erts_cnd_t *cnd)
{
@@ -810,8 +1245,9 @@ erts_rwmtx_destroy(erts_rwmtx_t *rwmtx)
"Most likely a bug in pthread implementation.";
erts_send_warning_to_logger_str_nogl(warn);
}
+ else
#endif
- erts_thr_fatal_error(res, "destroy rwmutex");
+ erts_thr_fatal_error(res, "destroy rwmutex");
}
#endif
}
@@ -995,428 +1431,206 @@ erts_lc_rwmtx_is_rwlocked(erts_rwmtx_t *mtx)
#endif
}
+/* No atomic ops */
+
ERTS_GLB_INLINE void
-erts_atomic_init(erts_atomic_t *var, erts_aint_t i)
+erts_no_dw_atomic_set(erts_no_dw_atomic_t *var, erts_no_dw_atomic_t *val)
{
-#ifdef USE_THREADS
- ethr_atomic_init(var, i);
-#else
- *var = i;
-#endif
+ var->sint[0] = val->sint[0];
+ var->sint[1] = val->sint[1];
}
ERTS_GLB_INLINE void
-erts_atomic_set(erts_atomic_t *var, erts_aint_t i)
+erts_no_dw_atomic_read(erts_no_dw_atomic_t *var, erts_no_dw_atomic_t *val)
+{
+ val->sint[0] = var->sint[0];
+ val->sint[1] = var->sint[1];
+}
+
+ERTS_GLB_INLINE int erts_no_dw_atomic_cmpxchg(erts_no_dw_atomic_t *var,
+ erts_no_dw_atomic_t *new_val,
+ erts_no_dw_atomic_t *old_val)
+{
+ if (var->sint[0] != old_val->sint[0] || var->sint[1] != old_val->sint[1]) {
+ erts_no_dw_atomic_read(var, old_val);
+ return 0;
+ }
+ else {
+ erts_no_dw_atomic_set(var, new_val);
+ return !0;
+ }
+}
+
+ERTS_GLB_INLINE void
+erts_no_atomic_set(erts_no_atomic_t *var, erts_aint_t i)
{
-#ifdef USE_THREADS
- ethr_atomic_set(var, i);
-#else
*var = i;
-#endif
}
ERTS_GLB_INLINE erts_aint_t
-erts_atomic_read(erts_atomic_t *var)
+erts_no_atomic_read(erts_no_atomic_t *var)
{
-#ifdef USE_THREADS
- return ethr_atomic_read(var);
-#else
return *var;
-#endif
}
ERTS_GLB_INLINE erts_aint_t
-erts_atomic_inctest(erts_atomic_t *incp)
+erts_no_atomic_inc_read(erts_no_atomic_t *incp)
{
-#ifdef USE_THREADS
- return ethr_atomic_inc_read(incp);
-#else
return ++(*incp);
-#endif
}
ERTS_GLB_INLINE erts_aint_t
-erts_atomic_dectest(erts_atomic_t *decp)
+erts_no_atomic_dec_read(erts_no_atomic_t *decp)
{
-#ifdef USE_THREADS
- return ethr_atomic_dec_read(decp);
-#else
return --(*decp);
-#endif
}
ERTS_GLB_INLINE void
-erts_atomic_inc(erts_atomic_t *incp)
+erts_no_atomic_inc(erts_no_atomic_t *incp)
{
-#ifdef USE_THREADS
- ethr_atomic_inc(incp);
-#else
++(*incp);
-#endif
}
ERTS_GLB_INLINE void
-erts_atomic_dec(erts_atomic_t *decp)
+erts_no_atomic_dec(erts_no_atomic_t *decp)
{
-#ifdef USE_THREADS
- ethr_atomic_dec(decp);
-#else
--(*decp);
-#endif
}
ERTS_GLB_INLINE erts_aint_t
-erts_atomic_addtest(erts_atomic_t *addp, erts_aint_t i)
+erts_no_atomic_add_read(erts_no_atomic_t *addp, erts_aint_t i)
{
-#ifdef USE_THREADS
- return ethr_atomic_add_read(addp, i);
-#else
return *addp += i;
-#endif
}
ERTS_GLB_INLINE void
-erts_atomic_add(erts_atomic_t *addp, erts_aint_t i)
+erts_no_atomic_add(erts_no_atomic_t *addp, erts_aint_t i)
{
-#ifdef USE_THREADS
- ethr_atomic_add(addp, i);
-#else
*addp += i;
-#endif
}
ERTS_GLB_INLINE erts_aint_t
-erts_atomic_xchg(erts_atomic_t *xchgp, erts_aint_t new)
+erts_no_atomic_read_bor(erts_no_atomic_t *var, erts_aint_t mask)
{
-#ifdef USE_THREADS
- return ethr_atomic_xchg(xchgp, new);
-#else
- erts_aint_t old = *xchgp;
- *xchgp = new;
- return old;
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint_t
-erts_atomic_cmpxchg(erts_atomic_t *xchgp, erts_aint_t new, erts_aint_t expected)
-{
-#ifdef USE_THREADS
- return ethr_atomic_cmpxchg(xchgp, new, expected);
-#else
- erts_aint_t old = *xchgp;
- if (old == expected)
- *xchgp = new;
- return old;
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint_t
-erts_atomic_bor(erts_atomic_t *var, erts_aint_t mask)
-{
-#ifdef USE_THREADS
- return ethr_atomic_read_bor(var, mask);
-#else
erts_aint_t old;
old = *var;
*var |= mask;
return old;
-#endif
}
ERTS_GLB_INLINE erts_aint_t
-erts_atomic_band(erts_atomic_t *var, erts_aint_t mask)
+erts_no_atomic_read_band(erts_no_atomic_t *var, erts_aint_t mask)
{
-#ifdef USE_THREADS
- return ethr_atomic_read_band(var, mask);
-#else
erts_aint_t old;
old = *var;
*var &= mask;
return old;
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint_t
-erts_atomic_read_acqb(erts_atomic_t *var)
-{
-#ifdef USE_THREADS
- return ethr_atomic_read_acqb(var);
-#else
- return *var;
-#endif
-}
-
-ERTS_GLB_INLINE void
-erts_atomic_set_relb(erts_atomic_t *var, erts_aint_t i)
-{
-#ifdef USE_THREADS
- ethr_atomic_set_relb(var, i);
-#else
- *var = i;
-#endif
-}
-
-ERTS_GLB_INLINE void
-erts_atomic_dec_relb(erts_atomic_t *decp)
-{
-#ifdef USE_THREADS
- ethr_atomic_dec_relb(decp);
-#else
- --(*decp);
-#endif
}
ERTS_GLB_INLINE erts_aint_t
-erts_atomic_dectest_relb(erts_atomic_t *decp)
-{
-#ifdef USE_THREADS
- return ethr_atomic_dec_read_relb(decp);
-#else
- return --(*decp);
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint_t erts_atomic_cmpxchg_acqb(erts_atomic_t *xchgp,
- erts_aint_t new,
- erts_aint_t exp)
+erts_no_atomic_xchg(erts_no_atomic_t *xchgp, erts_aint_t new)
{
-#ifdef USE_THREADS
- return ethr_atomic_cmpxchg_acqb(xchgp, new, exp);
-#else
erts_aint_t old = *xchgp;
- if (old == exp)
- *xchgp = new;
+ *xchgp = new;
return old;
-#endif
}
-ERTS_GLB_INLINE erts_aint_t erts_atomic_cmpxchg_relb(erts_atomic_t *xchgp,
- erts_aint_t new,
- erts_aint_t exp)
+ERTS_GLB_INLINE erts_aint_t
+erts_no_atomic_cmpxchg(erts_no_atomic_t *xchgp,
+ erts_aint_t new,
+ erts_aint_t expected)
{
-#ifdef USE_THREADS
- return ethr_atomic_cmpxchg_relb(xchgp, new, exp);
-#else
erts_aint_t old = *xchgp;
- if (old == exp)
+ if (old == expected)
*xchgp = new;
return old;
-#endif
}
/* atomic32 */
ERTS_GLB_INLINE void
-erts_atomic32_init(erts_atomic32_t *var, erts_aint32_t i)
-{
-#ifdef USE_THREADS
- ethr_atomic32_init(var, i);
-#else
- *var = i;
-#endif
-}
-
-ERTS_GLB_INLINE void
-erts_atomic32_set(erts_atomic32_t *var, erts_aint32_t i)
+erts_no_atomic32_set(erts_no_atomic32_t *var, erts_aint32_t i)
{
-#ifdef USE_THREADS
- ethr_atomic32_set(var, i);
-#else
*var = i;
-#endif
}
ERTS_GLB_INLINE erts_aint32_t
-erts_atomic32_read(erts_atomic32_t *var)
+erts_no_atomic32_read(erts_no_atomic32_t *var)
{
-#ifdef USE_THREADS
- return ethr_atomic32_read(var);
-#else
return *var;
-#endif
}
ERTS_GLB_INLINE erts_aint32_t
-erts_atomic32_inctest(erts_atomic32_t *incp)
+erts_no_atomic32_inc_read(erts_no_atomic32_t *incp)
{
-#ifdef USE_THREADS
- return ethr_atomic32_inc_read(incp);
-#else
return ++(*incp);
-#endif
}
ERTS_GLB_INLINE erts_aint32_t
-erts_atomic32_dectest(erts_atomic32_t *decp)
+erts_no_atomic32_dec_read(erts_no_atomic32_t *decp)
{
-#ifdef USE_THREADS
- return ethr_atomic32_dec_read(decp);
-#else
return --(*decp);
-#endif
}
ERTS_GLB_INLINE void
-erts_atomic32_inc(erts_atomic32_t *incp)
+erts_no_atomic32_inc(erts_no_atomic32_t *incp)
{
-#ifdef USE_THREADS
- ethr_atomic32_inc(incp);
-#else
++(*incp);
-#endif
}
ERTS_GLB_INLINE void
-erts_atomic32_dec(erts_atomic32_t *decp)
+erts_no_atomic32_dec(erts_no_atomic32_t *decp)
{
-#ifdef USE_THREADS
- ethr_atomic32_dec(decp);
-#else
--(*decp);
-#endif
}
ERTS_GLB_INLINE erts_aint32_t
-erts_atomic32_addtest(erts_atomic32_t *addp, erts_aint32_t i)
+erts_no_atomic32_add_read(erts_no_atomic32_t *addp, erts_aint32_t i)
{
-#ifdef USE_THREADS
- return ethr_atomic32_add_read(addp, i);
-#else
return *addp += i;
-#endif
}
ERTS_GLB_INLINE void
-erts_atomic32_add(erts_atomic32_t *addp, erts_aint32_t i)
+erts_no_atomic32_add(erts_no_atomic32_t *addp, erts_aint32_t i)
{
-#ifdef USE_THREADS
- ethr_atomic32_add(addp, i);
-#else
*addp += i;
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint32_t
-erts_atomic32_xchg(erts_atomic32_t *xchgp, erts_aint32_t new)
-{
-#ifdef USE_THREADS
- return ethr_atomic32_xchg(xchgp, new);
-#else
- erts_aint32_t old = *xchgp;
- *xchgp = new;
- return old;
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint32_t
-erts_atomic32_cmpxchg(erts_atomic32_t *xchgp,
- erts_aint32_t new,
- erts_aint32_t expected)
-{
-#ifdef USE_THREADS
- return ethr_atomic32_cmpxchg(xchgp, new, expected);
-#else
- erts_aint32_t old = *xchgp;
- if (old == expected)
- *xchgp = new;
- return old;
-#endif
}
ERTS_GLB_INLINE erts_aint32_t
-erts_atomic32_bor(erts_atomic32_t *var, erts_aint32_t mask)
+erts_no_atomic32_read_bor(erts_no_atomic32_t *var, erts_aint32_t mask)
{
-#ifdef USE_THREADS
- return ethr_atomic32_read_bor(var, mask);
-#else
erts_aint32_t old;
old = *var;
*var |= mask;
return old;
-#endif
}
ERTS_GLB_INLINE erts_aint32_t
-erts_atomic32_band(erts_atomic32_t *var, erts_aint32_t mask)
+erts_no_atomic32_read_band(erts_no_atomic32_t *var, erts_aint32_t mask)
{
-#ifdef USE_THREADS
- return ethr_atomic32_read_band(var, mask);
-#else
erts_aint32_t old;
old = *var;
*var &= mask;
return old;
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint32_t
-erts_atomic32_read_acqb(erts_atomic32_t *var)
-{
-#ifdef USE_THREADS
- return ethr_atomic32_read_acqb(var);
-#else
- return *var;
-#endif
-}
-
-ERTS_GLB_INLINE void
-erts_atomic32_set_relb(erts_atomic32_t *var, erts_aint32_t i)
-{
-#ifdef USE_THREADS
- ethr_atomic32_set_relb(var, i);
-#else
- *var = i;
-#endif
-}
-
-ERTS_GLB_INLINE void
-erts_atomic32_dec_relb(erts_atomic32_t *decp)
-{
-#ifdef USE_THREADS
- ethr_atomic32_dec_relb(decp);
-#else
- --(*decp);
-#endif
-}
-
-ERTS_GLB_INLINE erts_aint32_t
-erts_atomic32_dectest_relb(erts_atomic32_t *decp)
-{
-#ifdef USE_THREADS
- return ethr_atomic32_dec_read_relb(decp);
-#else
- return --(*decp);
-#endif
}
ERTS_GLB_INLINE erts_aint32_t
-erts_atomic32_cmpxchg_acqb(erts_atomic32_t *xchgp,
- erts_aint32_t new,
- erts_aint32_t exp)
+erts_no_atomic32_xchg(erts_no_atomic32_t *xchgp, erts_aint32_t new)
{
-#ifdef USE_THREADS
- return ethr_atomic32_cmpxchg_acqb(xchgp, new, exp);
-#else
erts_aint32_t old = *xchgp;
- if (old == exp)
- *xchgp = new;
+ *xchgp = new;
return old;
-#endif
}
ERTS_GLB_INLINE erts_aint32_t
-erts_atomic32_cmpxchg_relb(erts_atomic32_t *xchgp,
- erts_aint32_t new,
- erts_aint32_t exp)
+erts_no_atomic32_cmpxchg(erts_no_atomic32_t *xchgp,
+ erts_aint32_t new,
+ erts_aint32_t expected)
{
-#ifdef USE_THREADS
- return ethr_atomic32_cmpxchg_relb(xchgp, new, exp);
-#else
erts_aint32_t old = *xchgp;
- if (old == exp)
+ if (old == expected)
*xchgp = new;
return old;
-#endif
}
/* spinlock */
@@ -1496,8 +1710,9 @@ erts_spinlock_destroy(erts_spinlock_t *lock)
"Most likely a bug in pthread implementation.";
erts_send_warning_to_logger_str_nogl(warn);
}
+ else
#endif
- erts_thr_fatal_error(res, "destroy rwlock");
+ erts_thr_fatal_error(res, "destroy rwlock");
}
#else
(void)lock;
@@ -1614,8 +1829,9 @@ erts_rwlock_destroy(erts_rwlock_t *lock)
"Most likely a bug in pthread implementation.";
erts_send_warning_to_logger_str_nogl(warn);
}
+ else
#endif
- erts_thr_fatal_error(res, "destroy rwlock");
+ erts_thr_fatal_error(res, "destroy rwlock");
}
#else
(void)lock;
@@ -1887,3 +2103,37 @@ erts_thr_sigwait(const sigset_t *set, int *sig)
#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */
#endif /* #ifndef ERL_THREAD_H__ */
+
+#ifdef ERTS_UNDEF_DEPRECATED_ATOMICS
+
+/* Deprecated functions to replace */
+
+#undef erts_atomic_init
+#undef erts_atomic_set
+#undef erts_atomic_read
+#undef erts_atomic_inctest
+#undef erts_atomic_dectest
+#undef erts_atomic_inc
+#undef erts_atomic_dec
+#undef erts_atomic_addtest
+#undef erts_atomic_add
+#undef erts_atomic_xchg
+#undef erts_atomic_cmpxchg
+#undef erts_atomic_bor
+#undef erts_atomic_band
+
+#undef erts_atomic32_init
+#undef erts_atomic32_set
+#undef erts_atomic32_read
+#undef erts_atomic32_inctest
+#undef erts_atomic32_dectest
+#undef erts_atomic32_inc
+#undef erts_atomic32_dec
+#undef erts_atomic32_addtest
+#undef erts_atomic32_add
+#undef erts_atomic32_xchg
+#undef erts_atomic32_cmpxchg
+#undef erts_atomic32_bor
+#undef erts_atomic32_band
+
+#endif
diff --git a/erts/emulator/beam/erl_time.h b/erts/emulator/beam/erl_time.h
index d0ad73cd81..7a09d30ff6 100644
--- a/erts/emulator/beam/erl_time.h
+++ b/erts/emulator/beam/erl_time.h
@@ -85,8 +85,8 @@ ERTS_GLB_INLINE void erts_do_time_add(long);
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
-ERTS_GLB_INLINE erts_aint_t erts_do_time_read_and_reset(void) { return erts_smp_atomic_xchg(&do_time, 0L); }
-ERTS_GLB_INLINE void erts_do_time_add(long elapsed) { erts_smp_atomic_add(&do_time, elapsed); }
+ERTS_GLB_INLINE erts_aint_t erts_do_time_read_and_reset(void) { return erts_smp_atomic_xchg_acqb(&do_time, 0L); }
+ERTS_GLB_INLINE void erts_do_time_add(long elapsed) { erts_smp_atomic_add_relb(&do_time, elapsed); }
#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */
diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c
index 8833137112..b487dbf054 100644
--- a/erts/emulator/beam/erl_trace.c
+++ b/erts/emulator/beam/erl_trace.c
@@ -36,6 +36,7 @@
#include "error.h"
#include "erl_binary.h"
#include "erl_bits.h"
+#include "erl_thr_progress.h"
#if 0
#define DEBUG_PRINTOUTS
@@ -159,7 +160,7 @@ static Uint active_sched;
void
erts_system_profile_setup_active_schedulers(void)
{
- ERTS_SMP_LC_ASSERT(erts_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_thr_progress_is_blocking());
active_sched = erts_active_schedulers();
}
@@ -1940,7 +1941,8 @@ trace_proc(Process *c_p, Process *t_p, Eterm what, Eterm data)
Eterm* hp;
int need;
- ERTS_SMP_LC_ASSERT((erts_proc_lc_my_proc_locks(t_p) != 0) || erts_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT((erts_proc_lc_my_proc_locks(t_p) != 0)
+ || erts_thr_progress_is_blocking());
if (is_internal_port(t_p->tracer_proc)) {
#define LOCAL_HEAP_SIZE (5+5)
DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE);
@@ -2092,8 +2094,7 @@ void save_calls(Process *p, Export *e)
* entries instead of the original BIF functions.
*/
Eterm
-erts_bif_trace(int bif_index, Process* p,
- Eterm arg1, Eterm arg2, Eterm arg3, BeamInstr *I)
+erts_bif_trace(int bif_index, Process* p, Eterm* args, BeamInstr* I)
{
Eterm result;
int meta = !!(erts_bif_trace_flags[bif_index] & BIF_TRACE_AS_META);
@@ -2107,10 +2108,10 @@ erts_bif_trace(int bif_index, Process* p,
* no tracing will occur. Doing the whole else branch will
* also do nothing, only slower.
*/
- Eterm (*func)(Process*, Eterm, Eterm, Eterm, BeamInstr*) = bif_table[bif_index].f;
- result = func(p, arg1, arg2, arg3, I);
+ Eterm (*func)(Process*, Eterm*, BeamInstr*) = bif_table[bif_index].f;
+ result = func(p, args, I);
} else {
- Eterm (*func)(Process*, Eterm, Eterm, Eterm, BeamInstr*);
+ Eterm (*func)(Process*, Eterm*, BeamInstr*);
Export* ep = bif_export[bif_index];
Uint32 flags = 0, flags_meta = 0;
int global = !!(erts_bif_trace_flags[bif_index] & BIF_TRACE_AS_GLOBAL);
@@ -2122,8 +2123,6 @@ erts_bif_trace(int bif_index, Process* p,
* export entry */
BeamInstr *cp = p->cp;
- Eterm args[3] = {arg1, arg2, arg3};
-
/*
* Make continuation pointer OK, it is not during direct BIF calls,
* but it is correct during apply of bif.
@@ -2155,7 +2154,7 @@ erts_bif_trace(int bif_index, Process* p,
func = bif_table[bif_index].f;
- result = func(p, arg1, arg2, arg3, I);
+ result = func(p, args, I);
if (applying && (flags & MATCH_SET_RETURN_TO_TRACE)) {
BeamInstr i_return_trace = beam_return_trace[0];
@@ -2745,7 +2744,8 @@ trace_port(Port *t_p, Eterm what, Eterm data) {
Eterm mess;
Eterm* hp;
- ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(t_p) || erts_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(t_p)
+ || erts_thr_progress_is_blocking());
if (is_internal_port(t_p->tracer_proc)) {
#define LOCAL_HEAP_SIZE (5+5)
@@ -3021,8 +3021,6 @@ static ErtsSysMsgQ *sys_message_queue_end;
static erts_tid_t sys_msg_dispatcher_tid;
static erts_cnd_t smq_cnd;
-static int dispatcher_waiting;
-
ERTS_QUALLOC_IMPL(smq_element, ErtsSysMsgQ, 20, ERTS_ALC_T_SYS_MSG_Q)
static void
@@ -3066,18 +3064,6 @@ enqueue_sys_msg(enum ErtsSysMsgType type,
erts_smp_mtx_unlock(&smq_mtx);
}
-static void
-prepare_for_block(void *unused)
-{
- erts_smp_mtx_unlock(&smq_mtx);
-}
-
-static void
-resume_after_block(void *unused)
-{
- erts_smp_mtx_lock(&smq_mtx);
-}
-
void
erts_queue_error_logger_message(Eterm from, Eterm msg, ErlHeapFragment *bp)
{
@@ -3143,10 +3129,10 @@ sys_msg_disp_failure(ErtsSysMsgQ *smqp, Eterm receiver)
&& !erts_system_monitor_flags.busy_port
&& !erts_system_monitor_flags.busy_dist_port)
break; /* Everything is disabled */
- erts_smp_block_system(ERTS_BS_FLG_ALLOW_GC);
+ erts_smp_thr_progress_block();
if (system_monitor == receiver || receiver == NIL)
erts_system_monitor_clear(NULL);
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
break;
case SYS_MSG_TYPE_SYSPROF:
if (receiver == NIL
@@ -3156,11 +3142,11 @@ sys_msg_disp_failure(ErtsSysMsgQ *smqp, Eterm receiver)
&& !erts_system_profile_flags.scheduler)
break;
/* Block system to clear flags */
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
if (system_profile == receiver || receiver == NIL) {
erts_system_profile_clear(NULL);
}
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
break;
case SYS_MSG_TYPE_ERRLGR: {
char *no_elgger = "(no error logger present)";
@@ -3201,22 +3187,68 @@ sys_msg_disp_failure(ErtsSysMsgQ *smqp, Eterm receiver)
}
}
+static void
+sys_msg_dispatcher_wakeup(void *vwait_p)
+{
+ int *wait_p = (int *) vwait_p;
+ erts_smp_mtx_lock(&smq_mtx);
+ *wait_p = 0;
+ erts_smp_cnd_signal(&smq_cnd);
+ erts_smp_mtx_unlock(&smq_mtx);
+}
+
+static void
+sys_msg_dispatcher_prep_wait(void *vwait_p)
+{
+ int *wait_p = (int *) vwait_p;
+ erts_smp_mtx_lock(&smq_mtx);
+ *wait_p = 1;
+ erts_smp_mtx_unlock(&smq_mtx);
+}
+
+static void
+sys_msg_dispatcher_fin_wait(void *vwait_p)
+{
+ int *wait_p = (int *) vwait_p;
+ erts_smp_mtx_lock(&smq_mtx);
+ *wait_p = 0;
+ erts_smp_mtx_unlock(&smq_mtx);
+}
+
+static void
+sys_msg_dispatcher_wait(void *vwait_p)
+{
+ int *wait_p = (int *) vwait_p;
+ erts_smp_mtx_lock(&smq_mtx);
+ while (*wait_p)
+ erts_smp_cnd_wait(&smq_cnd, &smq_mtx);
+ erts_smp_mtx_unlock(&smq_mtx);
+}
+
static void *
sys_msg_dispatcher_func(void *unused)
{
+ ErtsThrPrgrCallbacks callbacks;
ErtsSysMsgQ *local_sys_message_queue = NULL;
+ int wait = 0;
#ifdef ERTS_ENABLE_LOCK_CHECK
erts_lc_set_thread_name("system message dispatcher");
#endif
- erts_register_blockable_thread();
- erts_smp_activity_begin(ERTS_ACTIVITY_IO, NULL, NULL, NULL);
+ callbacks.arg = (void *) &wait;
+ callbacks.wakeup = sys_msg_dispatcher_wakeup;
+ callbacks.prepare_wait = sys_msg_dispatcher_prep_wait;
+ callbacks.wait = sys_msg_dispatcher_wait;
+ callbacks.finalize_wait = sys_msg_dispatcher_fin_wait;
+
+ erts_thr_progress_register_managed_thread(NULL, &callbacks, 0);
while (1) {
+ int end_wait = 0;
ErtsSysMsgQ *smqp;
- ERTS_SMP_LC_ASSERT(!ERTS_LC_IS_BLOCKING);
+ ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking());
erts_smp_mtx_lock(&smq_mtx);
@@ -3228,20 +3260,16 @@ sys_msg_dispatcher_func(void *unused)
}
/* Fetch current trace message queue ... */
- erts_smp_activity_change(ERTS_ACTIVITY_IO,
- ERTS_ACTIVITY_WAIT,
- prepare_for_block,
- resume_after_block,
- NULL);
- dispatcher_waiting = 1;
+ if (!sys_message_queue) {
+ erts_smp_mtx_unlock(&smq_mtx);
+ end_wait = 1;
+ erts_thr_progress_active(NULL, 0);
+ erts_thr_progress_prepare_wait(NULL);
+ erts_smp_mtx_lock(&smq_mtx);
+ }
+
while (!sys_message_queue)
erts_smp_cnd_wait(&smq_cnd, &smq_mtx);
- dispatcher_waiting = 0;
- erts_smp_activity_change(ERTS_ACTIVITY_WAIT,
- ERTS_ACTIVITY_IO,
- prepare_for_block,
- resume_after_block,
- NULL);
local_sys_message_queue = sys_message_queue;
sys_message_queue = NULL;
@@ -3249,6 +3277,11 @@ sys_msg_dispatcher_func(void *unused)
erts_smp_mtx_unlock(&smq_mtx);
+ if (end_wait) {
+ erts_thr_progress_finalize_wait(NULL);
+ erts_thr_progress_active(NULL, 1);
+ }
+
/* Send trace messages ... */
ASSERT(local_sys_message_queue);
@@ -3259,6 +3292,9 @@ sys_msg_dispatcher_func(void *unused)
Process *proc = NULL;
Port *port = NULL;
+ if (erts_thr_progress_update(NULL))
+ erts_thr_progress_leader_update(NULL);
+
#ifdef DEBUG_PRINTOUTS
print_msg_type(smqp);
#endif
@@ -3372,7 +3408,6 @@ sys_msg_dispatcher_func(void *unused)
}
}
- erts_smp_activity_end(ERTS_ACTIVITY_IO, NULL, NULL, NULL);
return NULL;
}
@@ -3422,7 +3457,6 @@ init_sys_msg_dispatcher(void)
sys_message_queue_end = NULL;
erts_smp_cnd_init(&smq_cnd);
erts_smp_mtx_init(&smq_mtx, "sys_msg_q");
- dispatcher_waiting = 0;
erts_smp_thr_create(&sys_msg_dispatcher_tid,
sys_msg_dispatcher_func,
NULL,
diff --git a/erts/emulator/beam/erl_unicode.c b/erts/emulator/beam/erl_unicode.c
index 158eb361a4..fca785a4de 100644
--- a/erts/emulator/beam/erl_unicode.c
+++ b/erts/emulator/beam/erl_unicode.c
@@ -47,7 +47,7 @@ typedef struct _restart_context {
static Uint max_loop_limit;
-static BIF_RETTYPE utf8_to_list(BIF_ALIST_1);
+static BIF_RETTYPE utf8_to_list(Process *p, Eterm arg1);
static BIF_RETTYPE finalize_list_to_list(Process *p,
byte *bytes,
Eterm rest,
@@ -348,12 +348,6 @@ static int copy_utf8_bin(byte *target, byte *source, Uint size,
return copied;
}
- if (((*source) == 0xEF) && (source[1] == 0xBF) &&
- ((source[2] == 0xBE) || (source[2] == 0xBF))) {
- *err_pos = source;
- return copied;
- }
-
*(target++) = *(source++);
*(target++) = *(source++);
*(target++) = *(source++);
@@ -714,9 +708,8 @@ L_Again: /* Restart with sublist, old listend was pushed on stack */
target[(*pos)++] = (((byte) (x & 0x3F)) |
((byte) 0x80));
} else if (x < 0x10000) {
- if ((x >= 0xD800 && x <= 0xDFFF) ||
- (x == 0xFFFE) ||
- (x == 0xFFFF)) { /* Invalid unicode range */
+ if (x >= 0xD800 && x <= 0xDFFF) {
+ /* Invalid unicode range */
*err = 1;
goto done;
}
@@ -1230,10 +1223,6 @@ int erts_analyze_utf8(byte *source, Uint size,
((source[1] & 0x20) != 0)) {
return ERTS_UTF8_ERROR;
}
- if (((*source) == 0xEF) && (source[1] == 0xBF) &&
- ((source[2] == 0xBE) || (source[2] == 0xBF))) {
- return ERTS_UTF8_ERROR;
- }
source += 3;
size -= 3;
} else if (((*source) & ((byte) 0xF8)) == 0xF0) {
@@ -1839,13 +1828,13 @@ static BIF_RETTYPE characters_to_list_trap_4(BIF_ALIST_1)
* Instead of building an utf8 buffer, we analyze the binary given and use that.
*/
-static BIF_RETTYPE utf8_to_list(BIF_ALIST_1)
+static BIF_RETTYPE utf8_to_list(Process* p, Eterm arg)
{
- if (!is_binary(BIF_ARG_1) || aligned_binary_size(BIF_ARG_1) < 0) {
- BIF_ERROR(BIF_P,BADARG);
+ if (!is_binary(arg) || aligned_binary_size(arg) < 0) {
+ BIF_ERROR(p, BADARG);
}
- return do_bif_utf8_to_list(BIF_P, BIF_ARG_1, 0U, 0U, 0U,
- ERTS_UTF8_ANALYZE_MORE,NIL);
+ return do_bif_utf8_to_list(p, arg, 0U, 0U, 0U,
+ ERTS_UTF8_ANALYZE_MORE, NIL);
}
@@ -2166,9 +2155,8 @@ L_Again: /* Restart with sublist, old listend was pushed on stack */
} else if (x < 0x800) {
need += 2;
} else if (x < 0x10000) {
- if ((x >= 0xD800 && x <= 0xDFFF) ||
- (x == 0xFFFE) ||
- (x == 0xFFFF)) { /* Invalid unicode range */
+ if (x >= 0xD800 && x <= 0xDFFF) {
+ /* Invalid unicode range */
DESTROY_ESTACK(stack);
return ((Sint) -1);
}
@@ -2314,9 +2302,7 @@ L_Again: /* Restart with sublist, old listend was pushed on stack */
*p++ = (((byte) (x & 0x3F)) |
((byte) 0x80));
} else if (x < 0x10000) {
- ASSERT(!((x >= 0xD800 && x <= 0xDFFF) ||
- (x == 0xFFFE) ||
- (x == 0xFFFF)));
+ ASSERT(!(x >= 0xD800 && x <= 0xDFFF));
*p++ = (((byte) (x >> 12)) |
((byte) 0xE0));
*p++ = ((((byte) (x >> 6)) & 0x3F) |
diff --git a/erts/emulator/beam/erl_vm.h b/erts/emulator/beam/erl_vm.h
index e7fd144ec3..5dc307e383 100644
--- a/erts/emulator/beam/erl_vm.h
+++ b/erts/emulator/beam/erl_vm.h
@@ -55,7 +55,7 @@
heap data on the C stack or if we use the buffers in the scheduler data. */
#define TMP_HEAP_SIZE 128 /* Number of Eterm in the schedulers
small heap for transient heap data */
-#define CMP_TMP_HEAP_SIZE 2 /* cmp wants its own tmp-heap... */
+#define CMP_TMP_HEAP_SIZE 32 /* cmp wants its own tmp-heap... */
#define ERL_ARITH_TMP_HEAP_SIZE 4 /* as does erl_arith... */
#define BEAM_EMU_TMP_HEAP_SIZE 2 /* and beam_emu... */
@@ -83,11 +83,7 @@
#define CP_SIZE 1
#define ErtsHAllocLockCheck(P) \
- ERTS_SMP_LC_ASSERT((ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks((P))) \
- || ((P)->id == ERTS_INVALID_PID) \
- || ((P)->scheduler_data \
- && (P) == (P)->scheduler_data->match_pseudo_process) \
- || erts_is_system_blocked(0))
+ ERTS_SMP_LC_ASSERT(erts_dbg_check_halloc_lock((P)))
#ifdef DEBUG
diff --git a/erts/emulator/beam/export.c b/erts/emulator/beam/export.c
index 5bc402fe22..18d62dac1d 100644
--- a/erts/emulator/beam/export.c
+++ b/erts/emulator/beam/export.c
@@ -208,7 +208,8 @@ erts_export_put(Eterm mod, Eterm func, unsigned int arity)
Export e;
int ix;
- ERTS_SMP_LC_ASSERT(erts_initialized == 0 || erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_initialized == 0
+ || erts_smp_thr_progress_is_blocking());
ASSERT(is_atom(mod));
ASSERT(is_atom(func));
e.code[0] = mod;
@@ -265,7 +266,8 @@ erts_export_consolidate(void)
HashInfo hi;
#endif
- ERTS_SMP_LC_ASSERT(erts_initialized == 0 || erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_initialized == 0
+ || erts_smp_thr_progress_is_blocking());
export_write_lock();
erts_index_merge(&secondary_export_table, &export_table);
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index 1a102f7187..4b867f2b10 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -88,7 +88,7 @@ static byte* enc_pid(ErtsAtomCacheMap *, Eterm, byte*, Uint32);
static byte* dec_term(ErtsDistExternal *, Eterm**, byte*, ErlOffHeap*, Eterm*);
static byte* dec_atom(ErtsDistExternal *, byte*, Eterm*);
static byte* dec_pid(ErtsDistExternal *, Eterm**, byte*, ErlOffHeap*, Eterm*);
-static Sint decoded_size(byte *ep, byte* endp, int only_heap_bins, int internal_tags);
+static Sint decoded_size(byte *ep, byte* endp, int internal_tags);
static Uint encode_size_struct2(ErtsAtomCacheMap *, Eterm, unsigned);
@@ -459,6 +459,12 @@ Uint erts_encode_ext_size(Eterm term)
+ 1 /* VERSION_MAGIC */;
}
+Uint erts_encode_ext_size_2(Eterm term, unsigned dflags)
+{
+ return encode_size_struct2(NULL, term, TERM_TO_BINARY_DFLAGS|dflags)
+ + 1 /* VERSION_MAGIC */;
+}
+
Uint erts_encode_ext_size_ets(Eterm term)
{
return encode_size_struct2(NULL, term, TERM_TO_BINARY_DFLAGS|DFLAGS_INTERNAL_TAGS);
@@ -804,7 +810,7 @@ bad_dist_ext(ErtsDistExternal *edep)
}
Sint
-erts_decode_dist_ext_size(ErtsDistExternal *edep, int no_refc_bins)
+erts_decode_dist_ext_size(ErtsDistExternal *edep)
{
Sint res;
byte *ep;
@@ -823,7 +829,7 @@ erts_decode_dist_ext_size(ErtsDistExternal *edep, int no_refc_bins)
goto fail;
ep = edep->extp+1;
}
- res = decoded_size(ep, edep->ext_endp, no_refc_bins, 0);
+ res = decoded_size(ep, edep->ext_endp, 0);
if (res >= 0)
return res;
fail:
@@ -831,16 +837,16 @@ erts_decode_dist_ext_size(ErtsDistExternal *edep, int no_refc_bins)
return -1;
}
-Sint erts_decode_ext_size(byte *ext, Uint size, int no_refc_bins)
+Sint erts_decode_ext_size(byte *ext, Uint size)
{
if (size == 0 || *ext != VERSION_MAGIC)
return -1;
- return decoded_size(ext+1, ext+size, no_refc_bins, 0);
+ return decoded_size(ext+1, ext+size, 0);
}
Sint erts_decode_ext_size_ets(byte *ext, Uint size)
{
- Sint sz = decoded_size(ext, ext+size, 0, 1);
+ Sint sz = decoded_size(ext, ext+size, 1);
ASSERT(sz >= 0);
return sz;
}
@@ -962,7 +968,7 @@ BIF_RETTYPE erts_debug_dist_ext_to_term_2(BIF_ALIST_2)
ede.extp = binary_bytes(real_bin)+offset;
ede.ext_endp = ede.extp + size;
- hsz = erts_decode_dist_ext_size(&ede, 0);
+ hsz = erts_decode_dist_ext_size(&ede);
if (hsz < 0)
goto badarg;
@@ -982,16 +988,16 @@ BIF_RETTYPE erts_debug_dist_ext_to_term_2(BIF_ALIST_2)
}
-Eterm
-term_to_binary_1(Process* p, Eterm Term)
+BIF_RETTYPE term_to_binary_1(BIF_ALIST_1)
{
- return erts_term_to_binary(p, Term, 0, TERM_TO_BINARY_DFLAGS);
+ return erts_term_to_binary(BIF_P, BIF_ARG_1, 0, TERM_TO_BINARY_DFLAGS);
}
-
-Eterm
-term_to_binary_2(Process* p, Eterm Term, Eterm Flags)
+BIF_RETTYPE term_to_binary_2(BIF_ALIST_2)
{
+ Process* p = BIF_P;
+ Eterm Term = BIF_ARG_1;
+ Eterm Flags = BIF_ARG_2;
int level = 0;
Uint flags = TERM_TO_BINARY_DFLAGS;
@@ -1100,7 +1106,7 @@ binary2term_prepare(ErtsBinary2TermState *state, byte *data, Sint data_size)
goto error;
size = (Sint) dest_len;
}
- res = decoded_size(state->extp, state->extp + size, 0, 0);
+ res = decoded_size(state->extp, state->extp + size, 0);
if (res < 0)
goto error;
return res;
@@ -1250,8 +1256,11 @@ BIF_RETTYPE binary_to_term_2(BIF_ALIST_2)
}
Eterm
-external_size_1(Process* p, Eterm Term)
+external_size_1(BIF_ALIST_1)
{
+ Process* p = BIF_P;
+ Eterm Term = BIF_ARG_1;
+
Uint size = erts_encode_ext_size(Term);
if (IS_USMALL(0, size)) {
BIF_RET(make_small(size));
@@ -1262,6 +1271,49 @@ external_size_1(Process* p, Eterm Term)
}
Eterm
+external_size_2(BIF_ALIST_2)
+{
+ Uint size;
+ Uint flags = TERM_TO_BINARY_DFLAGS;
+
+ while (is_list(BIF_ARG_2)) {
+ Eterm arg = CAR(list_val(BIF_ARG_2));
+ Eterm* tp;
+
+ if (is_tuple(arg) && *(tp = tuple_val(arg)) == make_arityval(2)) {
+ if (tp[1] == am_minor_version && is_small(tp[2])) {
+ switch (signed_val(tp[2])) {
+ case 0:
+ break;
+ case 1:
+ flags |= DFLAG_NEW_FLOATS;
+ break;
+ default:
+ goto error;
+ }
+ } else {
+ goto error;
+ }
+ } else {
+ error:
+ BIF_ERROR(BIF_P, BADARG);
+ }
+ BIF_ARG_2 = CDR(list_val(BIF_ARG_2));
+ }
+ if (is_not_nil(BIF_ARG_2)) {
+ goto error;
+ }
+
+ size = erts_encode_ext_size_2(BIF_ARG_1, flags);
+ if (IS_USMALL(0, size)) {
+ BIF_RET(make_small(size));
+ } else {
+ Eterm* hp = HAlloc(BIF_P, BIG_UINT_HEAP_SIZE);
+ BIF_RET(uint_to_big(size, hp));
+ }
+}
+
+Eterm
erts_term_to_binary(Process* p, Eterm Term, int level, Uint flags)
{
Uint size;
@@ -2402,7 +2454,7 @@ dec_term_atom_common:
n = get_int32(ep);
ep += 4;
- if (n <= ERL_ONHEAP_BIN_LIMIT || off_heap == NULL) {
+ if (n <= ERL_ONHEAP_BIN_LIMIT) {
ErlHeapBin* hb = (ErlHeapBin *) hp;
hb->thing_word = header_heap_bin(n);
@@ -2440,7 +2492,7 @@ dec_term_atom_common:
n = get_int32(ep);
bitsize = ep[4];
ep += 5;
- if (n <= ERL_ONHEAP_BIN_LIMIT || off_heap == NULL) {
+ if (n <= ERL_ONHEAP_BIN_LIMIT) {
ErlHeapBin* hb = (ErlHeapBin *) hp;
hb->thing_word = header_heap_bin(n);
@@ -3009,7 +3061,7 @@ encode_size_struct2(ErtsAtomCacheMap *acmp, Eterm obj, unsigned dflags)
}
static Sint
-decoded_size(byte *ep, byte* endp, int no_refc_bins, int internal_tags)
+decoded_size(byte *ep, byte* endp, int internal_tags)
{
int heap_size = 0;
int terms;
@@ -3171,7 +3223,7 @@ decoded_size(byte *ep, byte* endp, int no_refc_bins, int internal_tags)
CHKSIZE(4);
n = get_int32(ep);
SKIP2(n, 4);
- if (n <= ERL_ONHEAP_BIN_LIMIT || no_refc_bins) {
+ if (n <= ERL_ONHEAP_BIN_LIMIT) {
heap_size += heap_bin_size(n);
} else {
heap_size += PROC_BIN_SIZE;
@@ -3182,7 +3234,7 @@ decoded_size(byte *ep, byte* endp, int no_refc_bins, int internal_tags)
CHKSIZE(5);
n = get_int32(ep);
SKIP2(n, 5);
- if (n <= ERL_ONHEAP_BIN_LIMIT || no_refc_bins) {
+ if (n <= ERL_ONHEAP_BIN_LIMIT) {
heap_size += heap_bin_size(n) + ERL_SUB_BIN_SIZE;
} else {
heap_size += PROC_BIN_SIZE + ERL_SUB_BIN_SIZE;
diff --git a/erts/emulator/beam/external.h b/erts/emulator/beam/external.h
index d8287b96a4..eddd4571dd 100644
--- a/erts/emulator/beam/external.h
+++ b/erts/emulator/beam/external.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2010. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -160,6 +160,7 @@ Uint erts_encode_dist_ext_size(Eterm, Uint32, ErtsAtomCacheMap *);
void erts_encode_dist_ext(Eterm, byte **, Uint32, ErtsAtomCacheMap *);
Uint erts_encode_ext_size(Eterm);
+Uint erts_encode_ext_size_2(Eterm, unsigned);
Uint erts_encode_ext_size_ets(Eterm);
void erts_encode_ext(Eterm, byte **);
byte* erts_encode_ext_ets(Eterm, byte *, struct erl_off_heap_header** ext_off_heap);
@@ -174,10 +175,10 @@ void *erts_dist_ext_trailer(ErtsDistExternal *);
void erts_destroy_dist_ext_copy(ErtsDistExternal *);
int erts_prepare_dist_ext(ErtsDistExternal *, byte *, Uint,
DistEntry *, ErtsAtomCache *);
-Sint erts_decode_dist_ext_size(ErtsDistExternal *, int);
+Sint erts_decode_dist_ext_size(ErtsDistExternal *);
Eterm erts_decode_dist_ext(Eterm **, ErlOffHeap *, ErtsDistExternal *);
-Sint erts_decode_ext_size(byte*, Uint, int);
+Sint erts_decode_ext_size(byte*, Uint);
Sint erts_decode_ext_size_ets(byte*, Uint);
Eterm erts_decode_ext(Eterm **, ErlOffHeap *, byte**);
Eterm erts_decode_ext_ets(Eterm **, ErlOffHeap *, byte*);
diff --git a/erts/emulator/beam/fix_alloc.c b/erts/emulator/beam/fix_alloc.c
deleted file mode 100644
index 5637281597..0000000000
--- a/erts/emulator/beam/fix_alloc.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1996-2009. All Rights Reserved.
- *
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * %CopyrightEnd%
- */
-/* General purpose Memory allocator for fixed block size objects */
-/* This allocater is at least an order of magnitude faster than malloc() */
-
-
-#define NOPERBLOCK 20
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "sys.h"
-#include "erl_vm.h"
-#include "global.h"
-#include "erl_db.h"
-
-#ifdef ERTS_ALC_N_MIN_A_FIXED_SIZE
-
-#if ERTS_ALC_MTA_FIXED_SIZE
-#include "erl_threads.h"
-#include "erl_smp.h"
-# ifdef ERTS_SMP
-# define FA_LOCK(FA) erts_smp_spin_lock(&(FA)->slck)
-# define FA_UNLOCK(FA) erts_smp_spin_unlock(&(FA)->slck)
-# else
-# define FA_LOCK(FA) erts_mtx_lock(&(FA)->mtx)
-# define FA_UNLOCK(FA) erts_mtx_unlock(&(FA)->mtx)
-# endif
-#else
-# define FA_LOCK(FA)
-# define FA_UNLOCK(FA)
-#endif
-
-typedef union {double d; long l;} align_t;
-
-typedef struct fix_alloc_block {
- struct fix_alloc_block *next;
- align_t mem[1];
-} FixAllocBlock;
-
-typedef struct fix_alloc {
- Uint item_size;
- void *freelist;
- Uint no_free;
- Uint no_blocks;
- FixAllocBlock *blocks;
-#if ERTS_ALC_MTA_FIXED_SIZE
-# ifdef ERTS_SMP
- erts_smp_spinlock_t slck;
-# else
- erts_mtx_t mtx;
-# endif
-#endif
-} FixAlloc;
-
-static void *(*core_alloc)(Uint);
-static Uint xblk_sz;
-
-static FixAlloc **fa;
-#define FA_SZ (1 + ERTS_ALC_N_MAX_A_FIXED_SIZE - ERTS_ALC_N_MIN_A_FIXED_SIZE)
-
-#define FIX_IX(N) ((N) - ERTS_ALC_N_MIN_A_FIXED_SIZE)
-
-#define FIX_POOL_SZ(I_SZ) \
- ((I_SZ)*NOPERBLOCK + sizeof(FixAllocBlock) - sizeof(align_t))
-
-#if defined(DEBUG) && !ERTS_ALC_MTA_FIXED_SIZE
-static int first_time;
-#endif
-
-void erts_init_fix_alloc(Uint extra_block_size,
- void *(*alloc)(Uint))
-{
- int i;
-
- xblk_sz = extra_block_size;
- core_alloc = alloc;
-
- fa = (FixAlloc **) (*core_alloc)(FA_SZ * sizeof(FixAlloc *));
- if (!fa)
- erts_alloc_enomem(ERTS_ALC_T_UNDEF, FA_SZ * sizeof(FixAlloc *));
-
- for (i = 0; i < FA_SZ; i++)
- fa[i] = NULL;
-#if defined(DEBUG) && !ERTS_ALC_MTA_FIXED_SIZE
- first_time = 1;
-#endif
-}
-
-Uint
-erts_get_fix_size(ErtsAlcType_t type)
-{
- Uint i = FIX_IX(ERTS_ALC_T2N(type));
- return i < FA_SZ && fa[i] ? fa[i]->item_size : 0;
-}
-
-void
-erts_set_fix_size(ErtsAlcType_t type, Uint size)
-{
- Uint sz;
- Uint i;
- FixAlloc *fs;
- ErtsAlcType_t t_no = ERTS_ALC_T2N(type);
- sz = xblk_sz + size;
-
-#ifdef DEBUG
- ASSERT(ERTS_ALC_N_MIN_A_FIXED_SIZE <= t_no);
- ASSERT(t_no <= ERTS_ALC_N_MAX_A_FIXED_SIZE);
-#endif
-
- while (sz % sizeof(align_t) != 0) /* Alignment */
- sz++;
-
- i = FIX_IX(t_no);
- fs = (FixAlloc *) (*core_alloc)(sizeof(FixAlloc));
- if (!fs)
- erts_alloc_n_enomem(t_no, sizeof(FixAlloc));
-
- fs->item_size = sz;
- fs->no_blocks = 0;
- fs->no_free = 0;
- fs->blocks = NULL;
- fs->freelist = NULL;
- if (fa[i])
- erl_exit(-1, "Attempt to overwrite existing fix size (%d)", i);
- fa[i] = fs;
-
-#if ERTS_ALC_MTA_FIXED_SIZE
-#ifdef ERTS_SMP
- erts_smp_spinlock_init_x(&fs->slck, "fix_alloc", make_small(i));
-#else
- erts_mtx_init_x(&fs->mtx, "fix_alloc", make_small(i));
-#endif
-#endif
-
-}
-
-void
-erts_fix_info(ErtsAlcType_t type, ErtsFixInfo *efip)
-{
- Uint i;
- FixAlloc *f;
-#ifdef DEBUG
- FixAllocBlock *b;
- void *fp;
-#endif
- Uint real_item_size;
- ErtsAlcType_t t_no = ERTS_ALC_T2N(type);
-
- ASSERT(ERTS_ALC_N_MIN_A_FIXED_SIZE <= t_no);
- ASSERT(t_no <= ERTS_ALC_N_MAX_A_FIXED_SIZE);
-
- i = FIX_IX(t_no);
- f = fa[i];
-
- efip->total = sizeof(FixAlloc *);
- efip->used = 0;
- if (!f)
- return;
-
- real_item_size = f->item_size - xblk_sz;
-
- FA_LOCK(f);
-
- efip->total += sizeof(FixAlloc);
- efip->total += f->no_blocks*FIX_POOL_SZ(real_item_size);
- efip->used = efip->total - f->no_free*real_item_size;
-
-#ifdef DEBUG
- ASSERT(efip->total >= efip->used);
- for(i = 0, b = f->blocks; b; i++, b = b->next);
- ASSERT(f->no_blocks == i);
- for (i = 0, fp = f->freelist; fp; i++, fp = *((void **) fp));
- ASSERT(f->no_free == i);
-#endif
-
- FA_UNLOCK(f);
-
-}
-
-void
-erts_fix_free(ErtsAlcType_t t_no, void *extra, void* ptr)
-{
- Uint i;
- FixAlloc *f;
-
- ASSERT(ERTS_ALC_N_MIN_A_FIXED_SIZE <= t_no);
- ASSERT(t_no <= ERTS_ALC_N_MAX_A_FIXED_SIZE);
-
- i = FIX_IX(t_no);
- f = fa[i];
-
- FA_LOCK(f);
- *((void **) ptr) = f->freelist;
- f->freelist = ptr;
- f->no_free++;
- FA_UNLOCK(f);
-}
-
-
-void *erts_fix_realloc(ErtsAlcType_t t_no, void *extra, void* ptr, Uint size)
-{
- erts_alc_fatal_error(ERTS_ALC_E_NOTSUP, ERTS_ALC_O_REALLOC, t_no);
- return NULL;
-}
-
-void *erts_fix_alloc(ErtsAlcType_t t_no, void *extra, Uint size)
-{
- void *ret;
- int i;
- FixAlloc *f;
-
-#if defined(DEBUG) && !ERTS_ALC_MTA_FIXED_SIZE
- ASSERT(ERTS_ALC_N_MIN_A_FIXED_SIZE <= t_no);
- ASSERT(t_no <= ERTS_ALC_N_MAX_A_FIXED_SIZE);
- if (first_time) { /* Check that all sizes have been initialized */
- int i;
- for (i = 0; i < FA_SZ; i++)
- ASSERT(fa[i]);
- first_time = 0;
- }
-#endif
-
-
- i = FIX_IX(t_no);
- f = fa[i];
-
- ASSERT(f);
- ASSERT(f->item_size >= size);
-
- FA_LOCK(f);
- if (f->freelist == NULL) { /* Gotta alloc some more mem */
- char *ptr;
- FixAllocBlock *bl;
- Uint n;
-
-
- FA_UNLOCK(f);
- bl = (*core_alloc)(FIX_POOL_SZ(f->item_size));
- if (!bl)
- return NULL;
-
- FA_LOCK(f);
- bl->next = f->blocks; /* link in first */
- f->blocks = bl;
-
- n = NOPERBLOCK;
- ptr = (char *) &f->blocks->mem[0];
- while(n--) {
- *((void **) ptr) = f->freelist;
- f->freelist = (void *) ptr;
- ptr += f->item_size;
- }
-#if !ERTS_ALC_MTA_FIXED_SIZE
- ASSERT(f->no_free == 0);
-#endif
- f->no_free += NOPERBLOCK;
- f->no_blocks++;
- }
-
- ret = f->freelist;
- f->freelist = *((void **) f->freelist);
- ASSERT(f->no_free > 0);
- f->no_free--;
-
- FA_UNLOCK(f);
-
- return ret;
-}
-
-#endif /* #ifdef ERTS_ALC_N_MIN_A_FIXED_SIZE */
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index 499bdd77ba..b247576f1c 100644
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -37,16 +37,11 @@
#include "erl_process.h"
#include "erl_sys_driver.h"
#include "erl_debug.h"
+#include "error.h"
typedef struct port Port;
#include "erl_port_task.h"
-#define ERTS_MAX_NO_OF_ASYNC_THREADS 1024
-extern int erts_async_max_threads;
-#define ERTS_ASYNC_THREAD_MIN_STACK_SIZE 16 /* Kilo words */
-#define ERTS_ASYNC_THREAD_MAX_STACK_SIZE 8192 /* Kilo words */
-extern int erts_async_thread_suggested_stack_size;
-
typedef struct erts_driver_t_ erts_driver_t;
#define SMALL_IO_QUEUE 5 /* Number of fixed elements */
@@ -200,10 +195,10 @@ erts_port_runq(Port *prt)
{
#ifdef ERTS_SMP
ErtsRunQueue *rq1, *rq2;
- rq1 = (ErtsRunQueue *) erts_smp_atomic_read(&prt->run_queue);
+ rq1 = (ErtsRunQueue *) erts_smp_atomic_read_nob(&prt->run_queue);
while (1) {
erts_smp_runq_lock(rq1);
- rq2 = (ErtsRunQueue *) erts_smp_atomic_read(&prt->run_queue);
+ rq2 = (ErtsRunQueue *) erts_smp_atomic_read_nob(&prt->run_queue);
if (rq1 == rq2)
return rq1;
erts_smp_runq_unlock(rq1);
@@ -542,10 +537,11 @@ ERTS_GLB_INLINE void erts_may_save_closed_port(Port *prt)
ERTS_SMP_LC_ASSERT(erts_smp_lc_spinlock_is_locked(&prt->state_lck));
if (prt->snapshot != erts_smp_atomic32_read_acqb(&erts_ports_snapshot)) {
/* Dead ports are added from the end of the snapshot buffer */
- Eterm* tombstone = (Eterm*) erts_smp_atomic_addtest(&erts_dead_ports_ptr,
- -(erts_aint_t)sizeof(Eterm));
+ Eterm* tombstone;
+ tombstone = (Eterm*) erts_smp_atomic_add_read_nob(&erts_dead_ports_ptr,
+ -(erts_aint_t)sizeof(Eterm));
ASSERT(tombstone+1 != NULL);
- ASSERT(prt->snapshot == erts_smp_atomic32_read(&erts_ports_snapshot) - 1);
+ ASSERT(prt->snapshot == erts_smp_atomic32_read_nob(&erts_ports_snapshot) - 1);
*tombstone = prt->id;
}
/*else no ongoing snapshot or port was already included or created after snapshot */
@@ -559,7 +555,6 @@ extern Eterm node_cookie;
extern erts_smp_atomic_t erts_bytes_out; /* no bytes written out */
extern erts_smp_atomic_t erts_bytes_in; /* no bytes sent into the system */
extern Uint display_items; /* no of items to display in traces etc */
-extern Uint display_loads; /* print info about loaded modules */
extern int erts_backtrace_depth;
extern erts_smp_atomic32_t erts_max_gen_gcs;
@@ -850,18 +845,41 @@ void erts_queue_monitor_message(Process *,
Eterm,
Eterm);
void erts_init_bif(void);
+Eterm erl_send(Process *p, Eterm to, Eterm msg);
+
+/* erl_bif_op.c */
+
+Eterm erl_is_function(Process* p, Eterm arg1, Eterm arg2);
/* erl_bif_port.c */
/* erl_bif_trace.c */
+Eterm erl_seq_trace_info(Process *p, Eterm arg1);
void erts_system_monitor_clear(Process *c_p);
void erts_system_profile_clear(Process *c_p);
/* beam_load.c */
-int erts_load_module(Process *c_p, ErtsProcLocks c_p_locks,
- Eterm group_leader, Eterm* mod, byte* code, int size);
+typedef struct {
+ BeamInstr* current; /* Pointer to: Mod, Name, Arity */
+ Uint needed; /* Heap space needed for entire tuple */
+ Uint32 loc; /* Location in source code */
+ Eterm* fname_ptr; /* Pointer to fname table */
+} FunctionInfo;
+
+struct LoaderState* erts_alloc_loader_state(void);
+Eterm erts_prepare_loading(struct LoaderState*, Process *c_p,
+ Eterm group_leader, Eterm* modp,
+ byte* code, Uint size);
+Eterm erts_finish_loading(struct LoaderState* stp, Process* c_p,
+ ErtsProcLocks c_p_locks, Eterm* modp);
+Eterm erts_load_module(Process *c_p, ErtsProcLocks c_p_locks,
+ Eterm group_leader, Eterm* mod, byte* code, Uint size);
void init_load(void);
BeamInstr* find_function_from_pc(BeamInstr* pc);
+Eterm* erts_build_mfa_item(FunctionInfo* fi, Eterm* hp,
+ Eterm args, Eterm* mfa_p);
+void erts_lookup_function_info(FunctionInfo* fi, BeamInstr* pc, int full_info);
+void erts_set_current_function(FunctionInfo* fi, BeamInstr* current);
Eterm erts_module_info_0(Process* p, Eterm module);
Eterm erts_module_info_1(Process* p, Eterm module, Eterm what);
Eterm erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info);
@@ -1052,6 +1070,7 @@ void init_emulator(void);
void process_main(void);
Eterm build_stacktrace(Process* c_p, Eterm exc);
Eterm expand_error_value(Process* c_p, Uint freason, Eterm Value);
+void erts_save_stacktrace(Process* p, struct StackTrace* s, int depth);
/* erl_init.c */
@@ -1073,6 +1092,7 @@ extern ErtsModifiedTimings erts_modified_timings[];
#define ERTS_MODIFIED_TIMING_INPUT_REDS \
(erts_modified_timings[erts_modified_timing_level].input_reds)
+extern int erts_no_line_info;
extern Eterm erts_error_logger_warnings;
extern int erts_initialized;
extern int erts_compat_rel;
@@ -1106,7 +1126,9 @@ void erts_init_gc(void);
int erts_garbage_collect(Process*, int, Eterm*, int);
void erts_garbage_collect_hibernate(Process* p);
Eterm erts_gc_after_bif_call(Process* p, Eterm result, Eterm* regs, Uint arity);
-void erts_garbage_collect_literals(Process* p, Eterm* literals, Uint lit_size);
+void erts_garbage_collect_literals(Process* p, Eterm* literals,
+ Uint lit_size,
+ struct erl_off_heap_header* oh);
Uint erts_next_heap_size(Uint, Uint);
Eterm erts_heap_sizes(Process* p);
@@ -1200,11 +1222,11 @@ erts_smp_port_trylock(Port *prt)
#ifdef ERTS_SMP
int res;
- ASSERT(erts_smp_atomic_read(&prt->refc) > 0);
- erts_smp_atomic_inc(&prt->refc);
+ ASSERT(erts_smp_atomic_read_nob(&prt->refc) > 0);
+ erts_smp_atomic_inc_nob(&prt->refc);
res = erts_smp_mtx_trylock(prt->lock);
if (res == EBUSY) {
- erts_smp_atomic_dec(&prt->refc);
+ erts_smp_atomic_dec_nob(&prt->refc);
}
return res;
@@ -1217,8 +1239,8 @@ ERTS_GLB_INLINE void
erts_smp_port_lock(Port *prt)
{
#ifdef ERTS_SMP
- ASSERT(erts_smp_atomic_read(&prt->refc) > 0);
- erts_smp_atomic_inc(&prt->refc);
+ ASSERT(erts_smp_atomic_read_nob(&prt->refc) > 0);
+ erts_smp_atomic_inc_nob(&prt->refc);
erts_smp_mtx_lock(prt->lock);
#endif
}
@@ -1229,7 +1251,7 @@ erts_smp_port_unlock(Port *prt)
#ifdef ERTS_SMP
erts_aint_t refc;
erts_smp_mtx_unlock(prt->lock);
- refc = erts_smp_atomic_dectest(&prt->refc);
+ refc = erts_smp_atomic_dec_read_nob(&prt->refc);
ASSERT(refc >= 0);
if (refc == 0)
erts_port_cleanup(prt);
@@ -1298,7 +1320,7 @@ erts_id2port_sflgs(Eterm id, Process *c_p, ErtsProcLocks c_p_locks, Uint32 sflgs
}
#ifdef ERTS_SMP
else {
- erts_smp_atomic_inc(&prt->refc);
+ erts_smp_atomic_inc_nob(&prt->refc);
erts_smp_port_state_unlock(prt);
if (no_proc_locks)
@@ -1626,8 +1648,7 @@ void monitor_generic(Process *p, Eterm type, Eterm spec);
Uint erts_trace_flag2bit(Eterm flag);
int erts_trace_flags(Eterm List,
Uint *pMask, Eterm *pTracer, int *pCpuTimestamp);
-Eterm erts_bif_trace(int bif_index, Process* p,
- Eterm arg1, Eterm arg2, Eterm arg3, BeamInstr *I);
+Eterm erts_bif_trace(int bif_index, Process* p, Eterm* args, BeamInstr *I);
#ifdef ERTS_SMP
void erts_send_pending_trace_msgs(ErtsSchedulerData *esdp);
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index df5f8b22a3..fff720634d 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -42,6 +42,7 @@
#include "erl_bits.h"
#include "erl_version.h"
#include "error.h"
+#include "erl_async.h"
extern ErlDrvEntry fd_driver_entry;
extern ErlDrvEntry vanilla_driver_entry;
@@ -244,8 +245,8 @@ get_free_port(void)
}
port->status = ERTS_PORT_SFLG_INITIALIZING;
#ifdef ERTS_SMP
- ERTS_SMP_LC_ASSERT(erts_smp_atomic_read(&port->refc) == 0);
- erts_smp_atomic_set(&port->refc, 2); /* Port alive + lock */
+ ERTS_SMP_LC_ASSERT(erts_smp_atomic_read_nob(&port->refc) == 0);
+ erts_smp_atomic_set_nob(&port->refc, 2); /* Port alive + lock */
#endif
erts_smp_port_state_unlock(port);
return num & port_num_mask;
@@ -327,7 +328,7 @@ port_cleanup(Port *prt)
#ifdef ERTS_SMP
ASSERT(prt->status & ERTS_PORT_SFLG_FREE_SCHEDULED);
- ERTS_SMP_LC_ASSERT(erts_smp_atomic_read(&prt->refc) == 0);
+ ERTS_SMP_LC_ASSERT(erts_smp_atomic_read_nob(&prt->refc) == 0);
port_specific = (prt->status & ERTS_PORT_SFLG_PORT_SPECIFIC_LOCK);
@@ -425,11 +426,11 @@ setup_port(Port* prt, Eterm pid, erts_driver_t *driver,
erts_smp_runq_lock(runq);
erts_smp_port_state_lock(prt);
prt->status = ERTS_PORT_SFLG_CONNECTED | xstatus;
- prt->snapshot = erts_smp_atomic32_read(&erts_ports_snapshot);
+ prt->snapshot = erts_smp_atomic32_read_nob(&erts_ports_snapshot);
old_name = prt->name;
prt->name = new_name;
#ifdef ERTS_SMP
- erts_smp_atomic_set(&prt->run_queue, (erts_aint_t) runq);
+ erts_smp_atomic_set_nob(&prt->run_queue, (erts_aint_t) runq);
#endif
ASSERT(!prt->drv_ptr);
prt->drv_ptr = driver;
@@ -590,8 +591,8 @@ erts_open_driver(erts_driver_t* driver, /* Pointer to driver. */
erts_smp_port_state_lock(port);
port->status = ERTS_PORT_SFLG_FREE;
#ifdef ERTS_SMP
- ERTS_SMP_LC_ASSERT(erts_smp_atomic_read(&port->refc) == 2);
- erts_smp_atomic_set(&port->refc, 0);
+ ERTS_SMP_LC_ASSERT(erts_smp_atomic_read_nob(&port->refc) == 2);
+ erts_smp_atomic_set_nob(&port->refc, 0);
#endif
erts_smp_port_state_unlock(port);
return -3;
@@ -1206,7 +1207,7 @@ int erts_write_to_port(Eterm caller_id, Port *p, Eterm list)
}
}
p->bytes_out += size;
- erts_smp_atomic_add(&erts_bytes_out, size);
+ erts_smp_atomic_add_nob(&erts_bytes_out, size);
#ifdef ERTS_SMP
if (p->xports)
@@ -1277,13 +1278,13 @@ void init_io(void)
erts_port = (Port *) erts_alloc(ERTS_ALC_T_PORT_TABLE,
erts_max_ports * sizeof(Port));
- erts_smp_atomic_init(&erts_bytes_out, 0);
- erts_smp_atomic_init(&erts_bytes_in, 0);
+ erts_smp_atomic_init_nob(&erts_bytes_out, 0);
+ erts_smp_atomic_init_nob(&erts_bytes_in, 0);
for (i = 0; i < erts_max_ports; i++) {
erts_port_task_init_sched(&erts_port[i].sched);
#ifdef ERTS_SMP
- erts_smp_atomic_init(&erts_port[i].refc, 0);
+ erts_smp_atomic_init_nob(&erts_port[i].refc, 0);
erts_port[i].lock = NULL;
erts_port[i].xports = NULL;
erts_smp_spinlock_init_x(&erts_port[i].state_lck, "port_state", make_small(i));
@@ -1300,7 +1301,7 @@ void init_io(void)
erts_port[i].port_data_lock = NULL;
}
- erts_smp_atomic32_init(&erts_ports_snapshot, (erts_aint32_t) 0);
+ erts_smp_atomic32_init_nob(&erts_ports_snapshot, (erts_aint32_t) 0);
last_port_num = 0;
erts_smp_spinlock_init(&get_free_port_lck, "get_free_port");
@@ -3253,7 +3254,7 @@ int driver_output_binary(ErlDrvPort ix, char* hbuf, int hlen,
return 0;
prt->bytes_in += (hlen + len);
- erts_smp_atomic_add(&erts_bytes_in, (erts_aint_t) (hlen + len));
+ erts_smp_atomic_add_nob(&erts_bytes_in, (erts_aint_t) (hlen + len));
if (prt->status & ERTS_PORT_SFLG_DISTRIBUTION) {
return erts_net_message(prt,
prt->dist_entry,
@@ -3288,7 +3289,7 @@ int driver_output2(ErlDrvPort ix, char* hbuf, int hlen, char* buf, int len)
return 0;
prt->bytes_in += (hlen + len);
- erts_smp_atomic_add(&erts_bytes_in, (erts_aint_t) (hlen + len));
+ erts_smp_atomic_add_nob(&erts_bytes_in, (erts_aint_t) (hlen + len));
if (prt->status & ERTS_PORT_SFLG_DISTRIBUTION) {
if (len == 0)
return erts_net_message(prt,
@@ -3365,7 +3366,7 @@ int driver_outputv(ErlDrvPort ix, char* hbuf, int hlen, ErlIOVec* vec, int skip)
/* XXX handle distribution !!! */
prt->bytes_in += (hlen + size);
- erts_smp_atomic_add(&erts_bytes_in, (erts_aint_t) (hlen + size));
+ erts_smp_atomic_add_nob(&erts_bytes_in, (erts_aint_t) (hlen + size));
deliver_vec_message(prt, prt->connected, hbuf, hlen, binv, iov, n, size);
return 0;
}
@@ -3539,13 +3540,13 @@ pdl_init(void)
static ERTS_INLINE void
pdl_init_refc(ErlDrvPDL pdl)
{
- erts_atomic_init(&pdl->refc, 1);
+ erts_atomic_init_nob(&pdl->refc, 1);
}
static ERTS_INLINE ErlDrvSInt
pdl_read_refc(ErlDrvPDL pdl)
{
- erts_aint_t refc = erts_atomic_read(&pdl->refc);
+ erts_aint_t refc = erts_atomic_read_nob(&pdl->refc);
ERTS_LC_ASSERT(refc >= 0);
return (ErlDrvSInt) refc;
}
@@ -3553,14 +3554,14 @@ pdl_read_refc(ErlDrvPDL pdl)
static ERTS_INLINE void
pdl_inc_refc(ErlDrvPDL pdl)
{
- erts_atomic_inc(&pdl->refc);
+ erts_atomic_inc_nob(&pdl->refc);
ERTS_LC_ASSERT(driver_pdl_get_refc(pdl) > 1);
}
static ERTS_INLINE ErlDrvSInt
pdl_inctest_refc(ErlDrvPDL pdl)
{
- erts_aint_t refc = erts_atomic_inctest(&pdl->refc);
+ erts_aint_t refc = erts_atomic_inc_read_nob(&pdl->refc);
ERTS_LC_ASSERT(refc > 1);
return (ErlDrvSInt) refc;
}
@@ -3569,7 +3570,7 @@ pdl_inctest_refc(ErlDrvPDL pdl)
static ERTS_INLINE void
pdl_dec_refc(ErlDrvPDL pdl)
{
- erts_atomic_dec(&pdl->refc);
+ erts_atomic_dec_nob(&pdl->refc);
ERTS_LC_ASSERT(driver_pdl_get_refc(pdl) > 0);
}
#endif
@@ -3577,7 +3578,7 @@ pdl_dec_refc(ErlDrvPDL pdl)
static ERTS_INLINE ErlDrvSInt
pdl_dectest_refc(ErlDrvPDL pdl)
{
- erts_aint_t refc = erts_atomic_dectest(&pdl->refc);
+ erts_aint_t refc = erts_atomic_dec_read_nob(&pdl->refc);
ERTS_LC_ASSERT(refc >= 0);
return (ErlDrvSInt) refc;
}
@@ -4579,7 +4580,10 @@ int driver_lock_driver(ErlDrvPort ix)
erts_smp_mtx_lock(&erts_driver_list_lock);
- if (prt == NULL) return -1;
+ if (prt == NULL) {
+ erts_smp_mtx_unlock(&erts_driver_list_lock);
+ return -1;
+ }
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
if ((dh = (DE_Handle*)prt->drv_ptr->handle ) == NULL) {
diff --git a/erts/emulator/beam/module.c b/erts/emulator/beam/module.c
index 91e4ccce70..b93b1ad09a 100644
--- a/erts/emulator/beam/module.c
+++ b/erts/emulator/beam/module.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2010. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -108,7 +108,8 @@ erts_put_module(Eterm mod)
int index;
ASSERT(is_atom(mod));
- ERTS_SMP_LC_ASSERT(erts_initialized == 0 || erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_initialized == 0
+ || erts_smp_thr_progress_is_blocking());
e.module = atom_val(mod);
index = index_put(&module_table, (void*) &e);
return (Module*) erts_index_lookup(&module_table, index);
diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab
index 8a5763b4bb..fc53a88a3a 100644
--- a/erts/emulator/beam/ops.tab
+++ b/erts/emulator/beam/ops.tab
@@ -25,30 +25,12 @@
# instruction transformations; thus, they never occur in BEAM files.
#
-# Special instruction used to generate an error message when
-# trying to load a module compiled by the V1 compiler (R5 & R6).
-# (Specially treated in beam_load.c.)
+# The too_old_compiler/0 instruction is specially handled in beam_load.c
+# to produce a user-friendly message informing the user that the module
+# needs to be re-compiled with a modern compiler.
too_old_compiler/0
-too_old_compiler
-
-#
-# Obsolete instruction usage follow. (Nowdays we use f with
-# a zero label instead of p.)
-#
-
-is_list p S => too_old_compiler
-is_nonempty_list p R => too_old_compiler
-is_nil p R => too_old_compiler
-
-is_tuple p S => too_old_compiler
-test_arity p S Arity => too_old_compiler
-
-is_integer p R => too_old_compiler
-is_float p R => too_old_compiler
-is_atom p R => too_old_compiler
-
-is_eq_exact p S1 S2 => too_old_compiler
+too_old_compiler | never() =>
# In R9C and earlier, the loader used to insert special instructions inside
# the module_info/0,1 functions. (In R10B and later, the compiler inserts
@@ -88,12 +70,42 @@ i_time_breakpoint
i_return_time_trace
i_return_to_trace
i_yield
-i_global_cons
-i_global_tuple
-i_global_copy
return
+#
+# To ensure that a "move Src x(0)" instruction can be combined
+# with the following call instruction, we need to make sure that
+# there is no line/1 instruction between the move and the call.
+#
+
+move S r | line Loc | call_ext Ar Func => \
+ line Loc | move S r | call_ext Ar Func
+move S r | line Loc | call_ext_last Ar Func=u$is_bif D => \
+ line Loc | move S r | call_ext_last Ar Func D
+move S r | line Loc | call_ext_only Ar Func=u$is_bif => \
+ line Loc | move S r | call_ext_only Ar Func
+move S r | line Loc | call Ar Func => \
+ line Loc | move S r | call Ar Func
+
+#
+# A tail-recursive call to an external function (non-BIF) will
+# never be saved on the stack, so there is no reason to keep
+# the line instruction. (The compiler did not remove the line
+# instruction because it cannot tell the difference between
+# BIFs and ordinary Erlang functions.)
+#
+
+line Loc | call_ext_last Ar Func=u$is_not_bif D => \
+ call_ext_last Ar Func D
+line Loc | call_ext_only Ar Func=u$is_not_bif => \
+ call_ext_only Ar Func
+
+line Loc | func_info M F A => func_info M F A | line Loc
+
+line I
+
+
%macro: allocate Allocate -pack
%macro: allocate_zero AllocateZero -pack
%macro: allocate_heap AllocateHeap -pack
@@ -277,8 +289,6 @@ raise s s
badarg j
system_limit j
-move R R =>
-
move C=cxy r | jump Lbl => move_jump Lbl C
%macro: move_jump MoveJump -nonext
@@ -585,8 +595,6 @@ get_tuple_element Reg P Dst => i_get_tuple_element Reg P Dst | original_reg Reg
original_reg Reg Pos =>
-get_tuple_element Reg P Dst => i_get_tuple_element Reg P Dst
-
original_reg/2
extract_next_element D1=xy | original_reg Reg P1 | get_tuple_element Reg P2 D2=xy | \
@@ -837,11 +845,11 @@ call_ext_only u==3 u$func:erlang:apply/3 => i_apply_only
# thus there is no need to generate any return instruction.
#
-call_ext_last u==1 Bif=u$bif:erlang:exit/1 D => call_bif1 Bif
-call_ext_last u==1 Bif=u$bif:erlang:throw/1 D => call_bif1 Bif
+call_ext_last u==1 Bif=u$bif:erlang:exit/1 D => call_bif Bif
+call_ext_last u==1 Bif=u$bif:erlang:throw/1 D => call_bif Bif
-call_ext_only u==1 Bif=u$bif:erlang:exit/1 => call_bif1 Bif
-call_ext_only u==1 Bif=u$bif:erlang:throw/1 => call_bif1 Bif
+call_ext_only u==1 Bif=u$bif:erlang:exit/1 => call_bif Bif
+call_ext_only u==1 Bif=u$bif:erlang:throw/1 => call_bif Bif
#
# The error/1 and error/2 BIFs never execute the instruction following them;
@@ -851,13 +859,13 @@ call_ext_only u==1 Bif=u$bif:erlang:throw/1 => call_bif1 Bif
# the continuation pointer on the stack.
#
-call_ext_last u==1 Bif=u$bif:erlang:error/1 D => call_bif1 Bif
-call_ext_last u==2 Bif=u$bif:erlang:error/2 D => call_bif2 Bif
+call_ext_last u==1 Bif=u$bif:erlang:error/1 D => call_bif Bif
+call_ext_last u==2 Bif=u$bif:erlang:error/2 D => call_bif Bif
call_ext_only Ar=u==1 Bif=u$bif:erlang:error/1 => \
- allocate u Ar | call_bif1 Bif
+ allocate u Ar | call_bif Bif
call_ext_only Ar=u==2 Bif=u$bif:erlang:error/2 => \
- allocate u Ar | call_bif2 Bif
+ allocate u Ar | call_bif Bif
#
# The yield/0 BIF is an instruction
@@ -875,47 +883,18 @@ call_ext_last u==3 u$func:erlang:hibernate/3 D => i_hibernate
call_ext_only u==3 u$func:erlang:hibernate/3 => i_hibernate
#
-# Hybrid memory architecture need special cons and tuple instructions
-# that allocate on the message area. These looks like BIFs in the BEAM code.
-#
-
-call_ext u==2 u$func:hybrid:cons/2 => i_global_cons
-call_ext_last u==2 u$func:hybrid:cons/2 D => i_global_cons | deallocate_return D
-call_ext_only Ar=u==2 u$func:hybrid:cons/2 => i_global_cons | return
-
-call_ext u==1 u$func:hybrid:tuple/1 => i_global_tuple
-call_ext_last u==1 u$func:hybrid:tuple/1 D => i_global_tuple | deallocate_return D
-call_ext_only Ar=u==1 u$func:hybrid:tuple/1 => i_global_tuple | return
-
-call_ext u==1 u$func:hybrid:copy/1 => i_global_copy
-call_ext_last u==1 u$func:hybrid:copy/1 D => i_global_copy | deallocate_return D
-call_ext_only u==1 Ar=u$func:hybrid:copy/1 => i_global_copy | return
-
-#
# The general case for BIFs that have no special instructions.
# A BIF used in the tail must be followed by a return instruction.
#
# To make trapping and stack backtraces work correctly, we make sure that
# the continuation pointer is always stored on the stack.
-call_ext u==0 Bif=u$is_bif => call_bif0 Bif
-call_ext u==1 Bif=u$is_bif => call_bif1 Bif
-call_ext u==2 Bif=u$is_bif => call_bif2 Bif
-call_ext u==3 Bif=$is_bif => call_bif3 Bif
+call_ext u Bif=u$is_bif => call_bif Bif
-call_ext_last u==0 Bif=u$is_bif D => call_bif0 Bif | deallocate_return D
-call_ext_last u==1 Bif=u$is_bif D => call_bif1 Bif | deallocate_return D
-call_ext_last u==2 Bif=u$is_bif D => call_bif2 Bif | deallocate_return D
-call_ext_last u==3 Bif=u$is_bif D => call_bif3 Bif | deallocate_return D
+call_ext_last u Bif=u$is_bif D => call_bif Bif | deallocate_return D
-call_ext_only Ar=u==0 Bif=u$is_bif => \
- allocate u Ar | call_bif0 Bif | deallocate_return u
-call_ext_only Ar=u==1 Bif=u$is_bif => \
- allocate u Ar | call_bif1 Bif | deallocate_return u
-call_ext_only Ar=u==2 Bif=u$is_bif => \
- allocate u Ar | call_bif2 Bif | deallocate_return u
-call_ext_only Ar=u==3 Bif=u$is_bif => \
- allocate u Ar | call_bif3 Bif | deallocate_return u
+call_ext_only Ar=u Bif=u$is_bif => \
+ allocate u Ar | call_bif Bif | deallocate_return u
#
# Any remaining calls are calls to Erlang functions, not BIFs.
@@ -928,9 +907,9 @@ move S=c r | call_ext Ar=u Func=u$is_not_bif => i_move_call_ext S r Func
move S=c r | call_ext_last Ar=u Func=u$is_not_bif D => i_move_call_ext_last Func D S r
move S=c r | call_ext_only Ar=u Func=u$is_not_bif => i_move_call_ext_only Func S r
-call_ext Ar=u Func => i_call_ext Func
-call_ext_last Ar=u Func D => i_call_ext_last Func D
-call_ext_only Ar=u Func => i_call_ext_only Func
+call_ext Ar Func => i_call_ext Func
+call_ext_last Ar Func D => i_call_ext_last Func D
+call_ext_only Ar Func => i_call_ext_only Func
i_apply
i_apply_last P
@@ -942,10 +921,7 @@ i_apply_fun_only
i_hibernate
-call_bif0 e
-call_bif1 e
-call_bif2 e
-call_bif3 e
+call_bif e
#
# Calls to non-building and guard BIFs.
@@ -964,7 +940,7 @@ bif1 p Bif S1 Dst => bif1_body Bif S1 Dst
bif1_body Bif Literal=q Dst => move Literal x | bif1_body Bif x Dst
bif2 p Bif S1 S2 Dst => i_fetch S1 S2 | i_bif2_body Bif Dst
-bif2 Fail=f Bif S1 S2 Dst => i_fetch S1 S2 | i_bif2 Fail Bif Dst
+bif2 Fail Bif S1 S2 Dst => i_fetch S1 S2 | i_bif2 Fail Bif Dst
i_get s d
@@ -1047,8 +1023,8 @@ i_move_call_ext_only e c r
# Fun calls.
-call_fun Arity=u | deallocate D | return => i_call_fun_last Arity D
-call_fun Arity=u => i_call_fun Arity
+call_fun Arity | deallocate D | return => i_call_fun_last Arity D
+call_fun Arity => i_call_fun Arity
i_call_fun I
i_call_fun_last I P
@@ -1236,7 +1212,7 @@ i_bs_init_heap I I I d
i_bs_init_heap_bin_heap I I I d
-bs_init_bits Fail Sz Words Regs Flags Dst | binary_too_big_bits(Sz) => system_limit Fail
+bs_init_bits Fail Sz=o Words Regs Flags Dst => system_limit Fail
bs_init_bits Fail Sz=u Words=u==0 Regs Flags Dst => i_bs_init_bits Sz Regs Dst
bs_init_bits Fail Sz=u Words Regs Flags Dst => i_bs_init_bits_heap Sz Words Regs Dst
@@ -1304,13 +1280,13 @@ i_bs_utf16_size s d
bs_put_utf8 Fail=j Flags=u Literal=q => \
move Literal x | bs_put_utf8 Fail Flags x
-bs_put_utf8 Fail=j u Src=s => i_bs_put_utf8 Fail Src
+bs_put_utf8 Fail u Src=s => i_bs_put_utf8 Fail Src
i_bs_put_utf8 j s
bs_put_utf16 Fail=j Flags=u Literal=q => \
move Literal x | bs_put_utf16 Fail Flags x
-bs_put_utf16 Fail=j Flags=u Src=s => i_bs_put_utf16 Fail Flags Src
+bs_put_utf16 Fail Flags=u Src=s => i_bs_put_utf16 Fail Flags Src
i_bs_put_utf16 j I s
@@ -1475,34 +1451,13 @@ bif1 Fail u$bif:erlang:trunc/1 s d => too_old_compiler
#
# Guard BIFs.
#
-gc_bif1 Fail I Bif=u$bif:erlang:length/1 Src Dst=d => \
- gen_guard_bif1(Fail, I, Bif, Src, Dst)
-
-gc_bif1 Fail I Bif=u$bif:erlang:size/1 Src Dst=d => \
- gen_guard_bif1(Fail, I, Bif, Src, Dst)
-
-gc_bif1 Fail I Bif=u$bif:erlang:bit_size/1 Src Dst=d => \
- gen_guard_bif1(Fail, I, Bif, Src, Dst)
-
-gc_bif1 Fail I Bif=u$bif:erlang:byte_size/1 Src Dst=d => \
- gen_guard_bif1(Fail, I, Bif, Src, Dst)
-
-gc_bif1 Fail I Bif=u$bif:erlang:abs/1 Src Dst=d => \
- gen_guard_bif1(Fail, I, Bif, Src, Dst)
-
-gc_bif1 Fail I Bif=u$bif:erlang:float/1 Src Dst=d => \
+gc_bif1 Fail I Bif Src Dst => \
gen_guard_bif1(Fail, I, Bif, Src, Dst)
-gc_bif1 Fail I Bif=u$bif:erlang:round/1 Src Dst=d => \
- gen_guard_bif1(Fail, I, Bif, Src, Dst)
-
-gc_bif1 Fail I Bif=u$bif:erlang:trunc/1 Src Dst=d => \
- gen_guard_bif1(Fail, I, Bif, Src, Dst)
-
-gc_bif2 Fail I Bif=u$bif:erlang:binary_part/2 S1 S2 Dst=d => \
+gc_bif2 Fail I Bif S1 S2 Dst => \
gen_guard_bif2(Fail, I, Bif, S1, S2, Dst)
-gc_bif3 Fail I Bif=u$bif:erlang:binary_part/3 S1 S2 S3 Dst=d => \
+gc_bif3 Fail I Bif S1 S2 S3 Dst => \
gen_guard_bif3(Fail, I, Bif, S1, S2, S3, Dst)
i_gc_bif1 Fail Bif V=q Live D => move V x | i_gc_bif1 Fail Bif x Live D
@@ -1520,6 +1475,15 @@ ii_gc_bif3/7
ii_gc_bif3 Fail Bif S1 S2 S3 Live D => move S1 x | i_fetch S2 S3 | i_gc_bif3 Fail Bif x Live D
i_gc_bif3 j I s I d
+
+#
+# The following instruction is specially handled in beam_load.c
+# to produce a user-friendly message if an unsupported guard BIF is
+# encountered.
+#
+unsupported_guard_bif/3
+unsupported_guard_bif A B C | never() =>
+
#
# R13B03
#
diff --git a/erts/emulator/beam/safe_hash.c b/erts/emulator/beam/safe_hash.c
index 4c54e19cdb..3326e5cc2a 100644
--- a/erts/emulator/beam/safe_hash.c
+++ b/erts/emulator/beam/safe_hash.c
@@ -61,7 +61,7 @@ static ERTS_INLINE int align_up_pow2(int val)
*/
static void rehash(SafeHash* h, int grow_limit)
{
- if (erts_smp_atomic_xchg(&h->is_rehashing, 1) != 0) {
+ if (erts_smp_atomic_xchg_acqb(&h->is_rehashing, 1) != 0) {
return; /* already in progress */
}
if (h->grow_limit == grow_limit) {
@@ -166,8 +166,8 @@ SafeHash* safe_hash_init(ErtsAlcType_t type, SafeHash* h, char* name, int size,
h->name = name;
h->fun = fun;
set_size(h,size);
- erts_smp_atomic_init(&h->is_rehashing, 0);
- erts_smp_atomic_init(&h->nitems, 0);
+ erts_smp_atomic_init_nob(&h->is_rehashing, 0);
+ erts_smp_atomic_init_nob(&h->nitems, 0);
for (i=0; i<SAFE_HASH_LOCK_CNT; i++) {
erts_smp_mtx_init(&h->lock_vec[i].mtx,"safe_hash");
}
@@ -222,7 +222,7 @@ void* safe_hash_put(SafeHash* h, void* tmpl)
*head = b;
grow_limit = h->grow_limit;
erts_smp_mtx_unlock(lock);
- if (erts_smp_atomic_inctest(&h->nitems) > grow_limit) {
+ if (erts_smp_atomic_inc_read_nob(&h->nitems) > grow_limit) {
rehash(h, grow_limit);
}
return (void*) b;
@@ -245,7 +245,7 @@ void* safe_hash_erase(SafeHash* h, void* tmpl)
if ((b->hvalue == hval) && (h->fun.cmp(tmpl, (void*)b) == 0)) {
*prevp = b->next;
erts_smp_mtx_unlock(lock);
- erts_smp_atomic_dec(&h->nitems);
+ erts_smp_atomic_dec_nob(&h->nitems);
h->fun.free((void*)b);
return tmpl;
}
diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h
index e64c43de6e..f9cbcc5892 100644
--- a/erts/emulator/beam/sys.h
+++ b/erts/emulator/beam/sys.h
@@ -340,7 +340,8 @@ int erts_send_warning_to_logger_str_nogl(char *);
#ifdef ERTS_WANT_BREAK_HANDLING
# ifdef ERTS_SMP
extern erts_smp_atomic32_t erts_break_requested;
-# define ERTS_BREAK_REQUESTED ((int) erts_smp_atomic32_read(&erts_break_requested))
+# define ERTS_BREAK_REQUESTED \
+ ((int) erts_smp_atomic32_read_nob(&erts_break_requested))
# else
extern volatile int erts_break_requested;
# define ERTS_BREAK_REQUESTED erts_break_requested
@@ -354,7 +355,7 @@ void erts_do_break_handling(void);
# else
# ifdef ERTS_SMP
extern erts_smp_atomic32_t erts_got_sigusr1;
-# define ERTS_GOT_SIGUSR1 ((int) erts_smp_atomic32_read(&erts_got_sigusr1))
+# define ERTS_GOT_SIGUSR1 ((int) erts_smp_atomic32_read_mb(&erts_got_sigusr1))
# else
extern volatile int erts_got_sigusr1;
# define ERTS_GOT_SIGUSR1 erts_got_sigusr1
@@ -363,11 +364,15 @@ extern volatile int erts_got_sigusr1;
#endif
#ifdef ERTS_SMP
-extern erts_smp_atomic_t erts_writing_erl_crash_dump;
+extern erts_smp_atomic32_t erts_writing_erl_crash_dump;
+extern erts_tsd_key_t erts_is_crash_dumping_key;
+#define ERTS_SOMEONE_IS_CRASH_DUMPING \
+ ((int) erts_smp_atomic32_read_mb(&erts_writing_erl_crash_dump))
#define ERTS_IS_CRASH_DUMPING \
- ((int) erts_smp_atomic_read(&erts_writing_erl_crash_dump))
+ ((int) (SWord) erts_tsd_get(erts_is_crash_dumping_key))
#else
extern volatile int erts_writing_erl_crash_dump;
+#define ERTS_SOMEONE_IS_CRASH_DUMPING erts_writing_erl_crash_dump
#define ERTS_IS_CRASH_DUMPING erts_writing_erl_crash_dump
#endif
@@ -470,15 +475,6 @@ __decl_noreturn void __noreturn erl_exit(int n, char*, ...);
#define ERTS_ABORT_EXIT (INT_MIN + 1) /* no crash dump; only abort() */
#define ERTS_DUMP_EXIT (127) /* crash dump; then exit() */
-
-#ifndef ERTS_SMP
-int check_async_ready(void);
-#ifdef USE_THREADS
-void sys_async_ready(int hndl);
-int erts_register_async_ready_callback(void (*funcp)(void));
-#endif
-#endif
-
Eterm erts_check_io_info(void *p);
/* Size of misc memory allocated from system dependent code */
@@ -611,13 +607,10 @@ extern char *erts_sys_ddll_error(int code);
* System interfaces for startup.
*/
-
-#ifdef ERTS_SMP
void erts_sys_schedule_interrupt(int set);
+#ifdef ERTS_SMP
void erts_sys_schedule_interrupt_timed(int set, long msec);
void erts_sys_main_thread(void);
-#else
-#define erts_sys_schedule_interrupt(Set)
#endif
extern void erts_sys_prepare_crash_dump(void);
@@ -669,6 +662,8 @@ int erts_sys_putenv(char *key_value, int sep_ix);
*size), a value > 0 if value buffer is too small (*size is set to needed
size), and a value < 0 on failure. */
int erts_sys_getenv(char *key, char *value, size_t *size);
+/* erts_sys_getenv__() is only allowed to be used in early init phase */
+int erts_sys_getenv__(char *key, char *value, size_t *size);
/* Easier to use, but not as efficient, environment functions */
char *erts_read_env(char *key);
@@ -692,291 +687,14 @@ int erts_write_env(char *key, char *value);
int sys_alloc_opt(int, int);
typedef struct {
- Sint trim_threshold;
- Sint top_pad;
- Sint mmap_threshold;
- Sint mmap_max;
+ int trim_threshold;
+ int top_pad;
+ int mmap_threshold;
+ int mmap_max;
} SysAllocStat;
void sys_alloc_stat(SysAllocStat *);
-/* Block the whole system... */
-
-#define ERTS_BS_FLG_ALLOW_GC (((Uint32) 1) << 0)
-#define ERTS_BS_FLG_ALLOW_IO (((Uint32) 1) << 1)
-
-/* Activities... */
-typedef enum {
- ERTS_ACTIVITY_UNDEFINED, /* Undefined activity */
- ERTS_ACTIVITY_WAIT, /* Waiting */
- ERTS_ACTIVITY_GC, /* Garbage collecting */
- ERTS_ACTIVITY_IO /* I/O including message passing to erl procs */
-} erts_activity_t;
-
-#ifdef ERTS_SMP
-
-typedef enum {
- ERTS_ACT_ERR_LEAVE_WAIT_UNLOCKED,
- ERTS_ACT_ERR_LEAVE_UNKNOWN_ACTIVITY,
- ERTS_ACT_ERR_ENTER_UNKNOWN_ACTIVITY
-} erts_activity_error_t;
-
-typedef struct {
- erts_smp_atomic32_t do_block;
- struct {
- erts_smp_atomic32_t wait;
- erts_smp_atomic32_t gc;
- erts_smp_atomic32_t io;
- } in_activity;
-} erts_system_block_state_t;
-
-extern erts_system_block_state_t erts_system_block_state;
-
-int erts_is_system_blocked(erts_activity_t allowed_activities);
-void erts_block_me(void (*prepare)(void *), void (*resume)(void *), void *arg);
-void erts_register_blockable_thread(void);
-void erts_unregister_blockable_thread(void);
-void erts_note_activity_begin(erts_activity_t activity);
-void
-erts_check_block(erts_activity_t old_activity,
- erts_activity_t new_activity,
- int locked,
- void (*prepare)(void *),
- void (*resume)(void *),
- void *arg);
-void erts_block_system(Uint32 allowed_activities);
-int erts_emergency_block_system(long timeout, Uint32 allowed_activities);
-void erts_release_system(void);
-void erts_system_block_init(void);
-void erts_set_activity_error(erts_activity_error_t, char *, int);
-#ifdef ERTS_ENABLE_LOCK_CHECK
-void erts_lc_activity_change_begin(void);
-void erts_lc_activity_change_end(void);
-int erts_lc_is_blocking(void);
-#define ERTS_LC_IS_BLOCKING \
- (erts_smp_pending_system_block() && erts_lc_is_blocking())
-#endif
-#endif
-
-#define erts_smp_activity_begin(NACT, PRP, RSM, ARG) \
- erts_smp_set_activity(ERTS_ACTIVITY_UNDEFINED, \
- (NACT), \
- 0, \
- (PRP), \
- (RSM), \
- (ARG), \
- __FILE__, \
- __LINE__)
-#define erts_smp_activity_change(OACT, NACT, PRP, RSM, ARG) \
- erts_smp_set_activity((OACT), \
- (NACT), \
- 0, \
- (PRP), \
- (RSM), \
- (ARG), \
- __FILE__, \
- __LINE__)
-#define erts_smp_activity_end(OACT, PRP, RSM, ARG) \
- erts_smp_set_activity((OACT), \
- ERTS_ACTIVITY_UNDEFINED, \
- 0, \
- (PRP), \
- (RSM), \
- (ARG), \
- __FILE__, \
- __LINE__)
-
-#define erts_smp_locked_activity_begin(NACT) \
- erts_smp_set_activity(ERTS_ACTIVITY_UNDEFINED, \
- (NACT), \
- 1, \
- NULL, \
- NULL, \
- NULL, \
- __FILE__, \
- __LINE__)
-#define erts_smp_locked_activity_change(OACT, NACT) \
- erts_smp_set_activity((OACT), \
- (NACT), \
- 1, \
- NULL, \
- NULL, \
- NULL, \
- __FILE__, \
- __LINE__)
-#define erts_smp_locked_activity_end(OACT) \
- erts_smp_set_activity((OACT), \
- ERTS_ACTIVITY_UNDEFINED, \
- 1, \
- NULL, \
- NULL, \
- NULL, \
- __FILE__, \
- __LINE__)
-
-
-ERTS_GLB_INLINE int erts_smp_is_system_blocked(erts_activity_t allowed_activities);
-ERTS_GLB_INLINE void erts_smp_block_system(Uint32 allowed_activities);
-ERTS_GLB_INLINE int erts_smp_emergency_block_system(long timeout,
- Uint32 allowed_activities);
-ERTS_GLB_INLINE void erts_smp_release_system(void);
-ERTS_GLB_INLINE int erts_smp_pending_system_block(void);
-ERTS_GLB_INLINE void erts_smp_chk_system_block(void (*prepare)(void *),
- void (*resume)(void *),
- void *arg);
-ERTS_GLB_INLINE void
-erts_smp_set_activity(erts_activity_t old_activity,
- erts_activity_t new_activity,
- int locked,
- void (*prepare)(void *),
- void (*resume)(void *),
- void *arg,
- char *file,
- int line);
-
-#if ERTS_GLB_INLINE_INCL_FUNC_DEF
-
-
-ERTS_GLB_INLINE int
-erts_smp_is_system_blocked(erts_activity_t allowed_activities)
-{
-#ifdef ERTS_SMP
- return erts_is_system_blocked(allowed_activities);
-#else
- return 1;
-#endif
-}
-
-ERTS_GLB_INLINE void
-erts_smp_block_system(Uint32 allowed_activities)
-{
-#ifdef ERTS_SMP
- erts_block_system(allowed_activities);
-#endif
-}
-
-ERTS_GLB_INLINE int
-erts_smp_emergency_block_system(long timeout, Uint32 allowed_activities)
-{
-#ifdef ERTS_SMP
- return erts_emergency_block_system(timeout, allowed_activities);
-#else
- return 0;
-#endif
-}
-
-ERTS_GLB_INLINE void
-erts_smp_release_system(void)
-{
-#ifdef ERTS_SMP
- erts_release_system();
-#endif
-}
-
-ERTS_GLB_INLINE int
-erts_smp_pending_system_block(void)
-{
-#ifdef ERTS_SMP
- return (int) erts_smp_atomic32_read(&erts_system_block_state.do_block);
-#else
- return 0;
-#endif
-}
-
-
-ERTS_GLB_INLINE void
-erts_smp_chk_system_block(void (*prepare)(void *),
- void (*resume)(void *),
- void *arg)
-{
-#ifdef ERTS_SMP
- if (erts_smp_pending_system_block())
- erts_block_me(prepare, resume, arg);
-#endif
-}
-
-ERTS_GLB_INLINE void
-erts_smp_set_activity(erts_activity_t old_activity,
- erts_activity_t new_activity,
- int locked,
- void (*prepare)(void *),
- void (*resume)(void *),
- void *arg,
- char *file,
- int line)
-{
-#ifdef ERTS_SMP
-#ifdef ERTS_ENABLE_LOCK_CHECK
- erts_lc_activity_change_begin();
-#endif
- switch (old_activity) {
- case ERTS_ACTIVITY_UNDEFINED:
- break;
- case ERTS_ACTIVITY_WAIT:
- erts_smp_atomic32_dec(&erts_system_block_state.in_activity.wait);
- if (locked) {
- /* You are not allowed to leave activity waiting
- * without supplying the possibility to block
- * unlocked.
- */
- erts_set_activity_error(ERTS_ACT_ERR_LEAVE_WAIT_UNLOCKED,
- file, line);
- }
- break;
- case ERTS_ACTIVITY_GC:
- erts_smp_atomic32_dec(&erts_system_block_state.in_activity.gc);
- break;
- case ERTS_ACTIVITY_IO:
- erts_smp_atomic32_dec(&erts_system_block_state.in_activity.io);
- break;
- default:
- erts_set_activity_error(ERTS_ACT_ERR_LEAVE_UNKNOWN_ACTIVITY,
- file, line);
- break;
- }
-
- /* We are not allowed to block when going to activity waiting... */
- if (new_activity != ERTS_ACTIVITY_WAIT && erts_smp_pending_system_block())
- erts_check_block(old_activity,new_activity,locked,prepare,resume,arg);
-
- switch (new_activity) {
- case ERTS_ACTIVITY_UNDEFINED:
- break;
- case ERTS_ACTIVITY_WAIT:
- erts_smp_atomic32_inc(&erts_system_block_state.in_activity.wait);
- break;
- case ERTS_ACTIVITY_GC:
- erts_smp_atomic32_inc(&erts_system_block_state.in_activity.gc);
- break;
- case ERTS_ACTIVITY_IO:
- erts_smp_atomic32_inc(&erts_system_block_state.in_activity.io);
- break;
- default:
- erts_set_activity_error(ERTS_ACT_ERR_ENTER_UNKNOWN_ACTIVITY,
- file, line);
- break;
- }
-
- switch (new_activity) {
- case ERTS_ACTIVITY_WAIT:
- case ERTS_ACTIVITY_GC:
- case ERTS_ACTIVITY_IO:
- if (erts_smp_pending_system_block())
- erts_note_activity_begin(new_activity);
- break;
- default:
- break;
- }
-
-#ifdef ERTS_ENABLE_LOCK_CHECK
- erts_lc_activity_change_end();
-#endif
-
-#endif
-}
-
-#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */
-
#if defined(DEBUG) || defined(ERTS_ENABLE_LOCK_CHECK)
#undef ERTS_REFC_DEBUG
#define ERTS_REFC_DEBUG
@@ -1001,27 +719,27 @@ ERTS_GLB_INLINE erts_aint_t erts_refc_read(erts_refc_t *refcp,
ERTS_GLB_INLINE void
erts_refc_init(erts_refc_t *refcp, erts_aint_t val)
{
- erts_smp_atomic_init((erts_smp_atomic_t *) refcp, val);
+ erts_smp_atomic_init_nob((erts_smp_atomic_t *) refcp, val);
}
ERTS_GLB_INLINE void
erts_refc_inc(erts_refc_t *refcp, erts_aint_t min_val)
{
#ifdef ERTS_REFC_DEBUG
- erts_aint_t val = erts_smp_atomic_inctest((erts_smp_atomic_t *) refcp);
+ erts_aint_t val = erts_smp_atomic_inc_read_nob((erts_smp_atomic_t *) refcp);
if (val < min_val)
erl_exit(ERTS_ABORT_EXIT,
"erts_refc_inc(): Bad refc found (refc=%ld < %ld)!\n",
val, min_val);
#else
- erts_smp_atomic_inc((erts_smp_atomic_t *) refcp);
+ erts_smp_atomic_inc_nob((erts_smp_atomic_t *) refcp);
#endif
}
ERTS_GLB_INLINE erts_aint_t
erts_refc_inctest(erts_refc_t *refcp, erts_aint_t min_val)
{
- erts_aint_t val = erts_smp_atomic_inctest((erts_smp_atomic_t *) refcp);
+ erts_aint_t val = erts_smp_atomic_inc_read_nob((erts_smp_atomic_t *) refcp);
#ifdef ERTS_REFC_DEBUG
if (val < min_val)
erl_exit(ERTS_ABORT_EXIT,
@@ -1035,20 +753,20 @@ ERTS_GLB_INLINE void
erts_refc_dec(erts_refc_t *refcp, erts_aint_t min_val)
{
#ifdef ERTS_REFC_DEBUG
- erts_aint_t val = erts_smp_atomic_dectest((erts_smp_atomic_t *) refcp);
+ erts_aint_t val = erts_smp_atomic_dec_read_nob((erts_smp_atomic_t *) refcp);
if (val < min_val)
erl_exit(ERTS_ABORT_EXIT,
"erts_refc_dec(): Bad refc found (refc=%ld < %ld)!\n",
val, min_val);
#else
- erts_smp_atomic_dec((erts_smp_atomic_t *) refcp);
+ erts_smp_atomic_dec_nob((erts_smp_atomic_t *) refcp);
#endif
}
ERTS_GLB_INLINE erts_aint_t
erts_refc_dectest(erts_refc_t *refcp, erts_aint_t min_val)
{
- erts_aint_t val = erts_smp_atomic_dectest((erts_smp_atomic_t *) refcp);
+ erts_aint_t val = erts_smp_atomic_dec_read_nob((erts_smp_atomic_t *) refcp);
#ifdef ERTS_REFC_DEBUG
if (val < min_val)
erl_exit(ERTS_ABORT_EXIT,
@@ -1062,20 +780,20 @@ ERTS_GLB_INLINE void
erts_refc_add(erts_refc_t *refcp, erts_aint_t diff, erts_aint_t min_val)
{
#ifdef ERTS_REFC_DEBUG
- erts_aint_t val = erts_smp_atomic_addtest((erts_smp_atomic_t *) refcp, diff);
+ erts_aint_t val = erts_smp_atomic_add_read_nob((erts_smp_atomic_t *) refcp, diff);
if (val < min_val)
erl_exit(ERTS_ABORT_EXIT,
"erts_refc_add(%ld): Bad refc found (refc=%ld < %ld)!\n",
diff, val, min_val);
#else
- erts_smp_atomic_add((erts_smp_atomic_t *) refcp, diff);
+ erts_smp_atomic_add_nob((erts_smp_atomic_t *) refcp, diff);
#endif
}
ERTS_GLB_INLINE erts_aint_t
erts_refc_read(erts_refc_t *refcp, erts_aint_t min_val)
{
- erts_aint_t val = erts_smp_atomic_read((erts_smp_atomic_t *) refcp);
+ erts_aint_t val = erts_smp_atomic_read_nob((erts_smp_atomic_t *) refcp);
#ifdef ERTS_REFC_DEBUG
if (val < min_val)
erl_exit(ERTS_ABORT_EXIT,
diff --git a/erts/emulator/beam/time.c b/erts/emulator/beam/time.c
index a00faff912..db9a24e0a3 100644
--- a/erts/emulator/beam/time.c
+++ b/erts/emulator/beam/time.c
@@ -108,9 +108,9 @@ static ErlTimer *tiw_min_ptr;
static int itime; /* Constant after init */
erts_smp_atomic_t do_time; /* set at clock interrupt */
-static ERTS_INLINE erts_aint_t do_time_read(void) { return erts_smp_atomic_read(&do_time); }
+static ERTS_INLINE erts_aint_t do_time_read(void) { return erts_smp_atomic_read_acqb(&do_time); }
static ERTS_INLINE erts_aint_t do_time_update(void) { return do_time_read(); }
-static ERTS_INLINE void do_time_init(void) { erts_smp_atomic_init(&do_time, 0L); }
+static ERTS_INLINE void do_time_init(void) { erts_smp_atomic_init_nob(&do_time, 0L); }
/* get the time (in units of itime) to the next timeout,
or -1 if there are no timeouts */
@@ -444,7 +444,7 @@ erts_time_left(ErlTimer *p)
}
#ifdef DEBUG
-void erts_p_slpq()
+void erts_p_slpq(void)
{
int i;
ErlTimer* p;
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c
index a17de717bc..1bd178f280 100644
--- a/erts/emulator/beam/utils.c
+++ b/erts/emulator/beam/utils.c
@@ -42,6 +42,9 @@
#include "erl_threads.h"
#include "erl_smp.h"
#include "erl_time.h"
+#include "erl_thr_progress.h"
+#include "erl_thr_queue.h"
+#include "erl_sched_spec_pre_alloc.h"
#undef M_TRIM_THRESHOLD
#undef M_TOP_PAD
@@ -75,6 +78,7 @@ typedef struct {
#ifdef ERTS_SMP
+#if 0 /* Unused */
static void
dispatch_profile_msg_q(profile_sched_msg_q *psmq)
{
@@ -86,6 +90,7 @@ dispatch_profile_msg_q(profile_sched_msg_q *psmq)
profile_scheduler_q(make_small(msg->scheduler_id), msg->state, am_undefined, msg->Ms, msg->s, msg->us);
}
}
+#endif
#endif
@@ -2642,7 +2647,7 @@ tailrecur_ne:
FloatDef f1, f2;
Eterm big;
#if HEAP_ON_C_STACK
- Eterm big_buf[2]; /* If HEAP_ON_C_STACK */
+ Eterm big_buf[32]; /* If HEAP_ON_C_STACK */
#else
Eterm *big_buf = erts_get_scheduler_data()->cmp_tmp_heap;
#endif
@@ -2653,41 +2658,108 @@ tailrecur_ne:
Eterm aw = a;
Eterm bw = b;
#endif
+#define MAX_LOSSLESS_FLOAT ((double)((1LL << 53) - 2))
+#define MIN_LOSSLESS_FLOAT ((double)(((1LL << 53) - 2)*-1))
b_tag = tag_val_def(bw);
switch(_NUMBER_CODE(a_tag, b_tag)) {
case SMALL_BIG:
- big = small_to_big(signed_val(a), big_buf);
- j = big_comp(big, bw);
+ j = big_sign(bw) ? 1 : -1;
+ break;
+ case BIG_SMALL:
+ j = big_sign(aw) ? -1 : 1;
break;
case SMALL_FLOAT:
- f1.fd = signed_val(a);
GET_DOUBLE(bw, f2);
- j = float_comp(f1.fd, f2.fd);
- break;
- case BIG_SMALL:
- big = small_to_big(signed_val(b), big_buf);
- j = big_comp(aw, big);
+ if (f2.fd < MAX_LOSSLESS_FLOAT && f2.fd > MIN_LOSSLESS_FLOAT) {
+ // Float is within the no loss limit
+ f1.fd = signed_val(aw);
+ j = float_comp(f1.fd, f2.fd);
+#if ERTS_SIZEOF_ETERM == 8
+ } else if (f2.fd > (double) (MAX_SMALL + 1)) {
+ // Float is a positive bignum, i.e. bigger
+ j = -1;
+ } else if (f2.fd < (double) (MIN_SMALL - 1)) {
+ // Float is a negative bignum, i.e. smaller
+ j = 1;
+ } else { // Float is a Sint but less precise
+ j = signed_val(aw) - (Sint) f2.fd;
+ }
+#else
+ } else {
+ // If float is positive it is bigger than small
+ j = (f2.fd > 0.0) ? -1 : 1;
+ }
+#endif // ERTS_SIZEOF_ETERM == 8
break;
case BIG_FLOAT:
- if (big_to_double(aw, &f1.fd) < 0) {
- j = big_sign(a) ? -1 : 1;
+ GET_DOUBLE(bw, f2);
+ if ((f2.fd < (double) (MAX_SMALL + 1))
+ && (f2.fd > (double) (MIN_SMALL - 1))) {
+ // Float is a Sint
+ j = big_sign(aw) ? -1 : 1;
+ } else if ((pow(2.0,(big_arity(aw)-1.0)*D_EXP)-1.0) > fabs(f2.fd)) {
+ // If bignum size shows that it is bigger than the abs float
+ j = big_sign(aw) ? -1 : 1;
+ } else if ((pow(2.0,(big_arity(aw))*D_EXP)-1.0) < fabs(f2.fd)) {
+ // If bignum size shows that it is smaller than the abs float
+ j = f2.fd < 0 ? 1 : -1;
+ } else if (f2.fd < MAX_LOSSLESS_FLOAT && f2.fd > MIN_LOSSLESS_FLOAT) {
+ // Float is within the no loss limit
+ if (big_to_double(aw, &f1.fd) < 0) {
+ j = big_sign(aw) ? -1 : 1;
+ } else {
+ j = float_comp(f1.fd, f2.fd);
+ }
} else {
- GET_DOUBLE(bw, f2);
- j = float_comp(f1.fd, f2.fd);
+ big = double_to_big(f2.fd, big_buf);
+ j = big_comp(aw, big);
}
break;
case FLOAT_SMALL:
GET_DOUBLE(aw, f1);
- f2.fd = signed_val(b);
- j = float_comp(f1.fd, f2.fd);
+ if (f1.fd < MAX_LOSSLESS_FLOAT && f1.fd > MIN_LOSSLESS_FLOAT) {
+ // Float is within the no loss limit
+ f2.fd = signed_val(bw);
+ j = float_comp(f1.fd, f2.fd);
+#if ERTS_SIZEOF_ETERM == 8
+ } else if (f1.fd > (double) (MAX_SMALL + 1)) {
+ // Float is a positive bignum, i.e. bigger
+ j = 1;
+ } else if (f1.fd < (double) (MIN_SMALL - 1)) {
+ // Float is a negative bignum, i.e. smaller
+ j = -1;
+ } else { // Float is a Sint but less precise it
+ j = (Sint) f1.fd - signed_val(bw);
+ }
+#else
+ } else {
+ // If float is positive it is bigger than small
+ j = (f1.fd > 0.0) ? 1 : -1;
+ }
+#endif // ERTS_SIZEOF_ETERM == 8
break;
case FLOAT_BIG:
- if (big_to_double(bw, &f2.fd) < 0) {
- j = big_sign(b) ? 1 : -1;
+ GET_DOUBLE(aw, f1);
+ if ((f1.fd < (double) (MAX_SMALL + 1))
+ && (f1.fd > (double) (MIN_SMALL - 1))) { // Float is a Sint
+ j = big_sign(bw) ? 1 : -1;
+ } else if ((pow(2.0, (big_arity(bw) - 1.0) * D_EXP) - 1.0) > fabs(f1.fd)) {
+ // If bignum size shows that it is bigger than the abs float
+ j = big_sign(bw) ? 1 : -1;
+ } else if ((pow(2.0,(big_arity(bw))*D_EXP)-1.0) < fabs(f1.fd)) {
+ // If bignum size shows that it is smaller than the abs float
+ j = f1.fd < 0 ? -1 : 1;
+ } else if (f1.fd < MAX_LOSSLESS_FLOAT && f1.fd > MIN_LOSSLESS_FLOAT) {
+ // Float is within the no loss limit
+ if (big_to_double(bw, &f2.fd) < 0) {
+ j = big_sign(bw) ? 1 : -1;
+ } else {
+ j = float_comp(f1.fd, f2.fd);
+ }
} else {
- GET_DOUBLE(aw, f1);
- j = float_comp(f1.fd, f2.fd);
+ big = double_to_big(f1.fd, big_buf);
+ j = big_comp(big, bw);
}
break;
default:
@@ -3250,10 +3322,10 @@ erts_cancel_smp_ptimer(ErtsSmpPTimer *ptimer)
#endif
-static Sint trim_threshold;
-static Sint top_pad;
-static Sint mmap_threshold;
-static Sint mmap_max;
+static int trim_threshold;
+static int top_pad;
+static int mmap_threshold;
+static int mmap_max;
Uint tot_bin_allocated;
@@ -3276,8 +3348,8 @@ int
sys_alloc_opt(int opt, int value)
{
#if HAVE_MALLOPT
- Sint m_opt;
- Sint *curr_val;
+ int m_opt;
+ int *curr_val;
switch(opt) {
case SYS_ALLOC_OPT_TRIM_THRESHOLD:
@@ -3317,7 +3389,7 @@ sys_alloc_opt(int opt, int value)
}
if(mallopt(m_opt, value)) {
- *curr_val = (Sint) value;
+ *curr_val = value;
return 1;
}
@@ -3336,686 +3408,6 @@ sys_alloc_stat(SysAllocStat *sasp)
}
-#ifdef ERTS_SMP
-
-/* Local system block state */
-
-struct {
- int emergency;
- long emergency_timeout;
- erts_smp_cnd_t watchdog_cnd;
- erts_smp_tid_t watchdog_tid;
- int threads_to_block;
- int have_blocker;
- erts_smp_tid_t blocker_tid;
- int recursive_block;
- Uint32 allowed_activities;
- erts_smp_tsd_key_t blockable_key;
- erts_smp_mtx_t mtx;
- erts_smp_cnd_t cnd;
-#ifdef ERTS_ENABLE_LOCK_CHECK
- int activity_changing;
- int checking;
-#endif
-} system_block_state;
-
-/* Global system block state */
-erts_system_block_state_t erts_system_block_state;
-
-
-static ERTS_INLINE int
-is_blockable_thread(void)
-{
- return erts_smp_tsd_get(system_block_state.blockable_key) != NULL;
-}
-
-static ERTS_INLINE int
-is_blocker(void)
-{
- return (system_block_state.have_blocker
- && erts_smp_equal_tids(system_block_state.blocker_tid,
- erts_smp_thr_self()));
-}
-
-#ifdef ERTS_ENABLE_LOCK_CHECK
-int
-erts_lc_is_blocking(void)
-{
- int res;
- erts_smp_mtx_lock(&system_block_state.mtx);
- res = erts_smp_pending_system_block() && is_blocker();
- erts_smp_mtx_unlock(&system_block_state.mtx);
- return res;
-}
-#endif
-
-static ERTS_INLINE void
-block_me(void (*prepare)(void *),
- void (*resume)(void *),
- void *arg,
- int mtx_locked,
- int want_to_block,
- int update_act_changing,
- profile_sched_msg_q *psmq)
-{
- if (prepare)
- (*prepare)(arg);
-
- /* Locks might be held... */
-
- if (!mtx_locked)
- erts_smp_mtx_lock(&system_block_state.mtx);
-
- if (erts_smp_pending_system_block() && !is_blocker()) {
- int is_blockable = is_blockable_thread();
- ASSERT(is_blockable);
-
- if (is_blockable)
- system_block_state.threads_to_block--;
-
- if (erts_system_profile_flags.scheduler && psmq) {
- ErtsSchedulerData *esdp = erts_get_scheduler_data();
- if (esdp) {
- profile_sched_msg *msg = NULL;
-
- ASSERT(psmq->n < 2);
- msg = &((psmq->msg)[psmq->n]);
- msg->scheduler_id = esdp->no;
- get_now(&(msg->Ms), &(msg->s), &(msg->us));
- msg->no_schedulers = 0;
- msg->state = am_inactive;
- psmq->n++;
- }
- }
-
-#ifdef ERTS_ENABLE_LOCK_CHECK
- if (update_act_changing)
- system_block_state.activity_changing--;
-#endif
-
- erts_smp_cnd_broadcast(&system_block_state.cnd);
-
- do {
- erts_smp_cnd_wait(&system_block_state.cnd, &system_block_state.mtx);
- } while (erts_smp_pending_system_block()
- && !(want_to_block && !system_block_state.have_blocker));
-
-#ifdef ERTS_ENABLE_LOCK_CHECK
- if (update_act_changing)
- system_block_state.activity_changing++;
-#endif
- if (erts_system_profile_flags.scheduler && psmq) {
- ErtsSchedulerData *esdp = erts_get_scheduler_data();
- if (esdp) {
- profile_sched_msg *msg = NULL;
-
- ASSERT(psmq->n < 2);
- msg = &((psmq->msg)[psmq->n]);
- msg->scheduler_id = esdp->no;
- get_now(&(msg->Ms), &(msg->s), &(msg->us));
- msg->no_schedulers = 0;
- msg->state = am_active;
- psmq->n++;
- }
- }
-
- if (is_blockable)
- system_block_state.threads_to_block++;
- }
-
- if (!mtx_locked)
- erts_smp_mtx_unlock(&system_block_state.mtx);
-
- if (resume)
- (*resume)(arg);
-}
-
-void
-erts_block_me(void (*prepare)(void *),
- void (*resume)(void *),
- void *arg)
-{
- profile_sched_msg_q psmq;
- psmq.n = 0;
- if (prepare)
- (*prepare)(arg);
-
-#ifdef ERTS_ENABLE_LOCK_CHECK
- erts_lc_check_exact(NULL, 0); /* No locks should be locked */
-#endif
-
- block_me(NULL, NULL, NULL, 0, 0, 0, &psmq);
-
- if (erts_system_profile_flags.scheduler && psmq.n > 0)
- dispatch_profile_msg_q(&psmq);
-
- if (resume)
- (*resume)(arg);
-}
-
-void
-erts_register_blockable_thread(void)
-{
- profile_sched_msg_q psmq;
- psmq.n = 0;
- if (!is_blockable_thread()) {
- erts_smp_mtx_lock(&system_block_state.mtx);
- system_block_state.threads_to_block++;
- erts_smp_tsd_set(system_block_state.blockable_key,
- (void *) &erts_system_block_state);
-
- /* Someone might be waiting for us to block... */
- if (erts_smp_pending_system_block())
- block_me(NULL, NULL, NULL, 1, 0, 0, &psmq);
- erts_smp_mtx_unlock(&system_block_state.mtx);
-
- if (erts_system_profile_flags.scheduler && psmq.n > 0)
- dispatch_profile_msg_q(&psmq);
- }
-}
-
-void
-erts_unregister_blockable_thread(void)
-{
- if (is_blockable_thread()) {
- erts_smp_mtx_lock(&system_block_state.mtx);
- system_block_state.threads_to_block--;
- ASSERT(system_block_state.threads_to_block >= 0);
- erts_smp_tsd_set(system_block_state.blockable_key, NULL);
-
- /* Someone might be waiting for us to block... */
- if (erts_smp_pending_system_block())
- erts_smp_cnd_broadcast(&system_block_state.cnd);
- erts_smp_mtx_unlock(&system_block_state.mtx);
- }
-}
-
-void
-erts_note_activity_begin(erts_activity_t activity)
-{
- erts_smp_mtx_lock(&system_block_state.mtx);
- if (erts_smp_pending_system_block()) {
- Uint32 broadcast = 0;
- switch (activity) {
- case ERTS_ACTIVITY_GC:
- broadcast = (system_block_state.allowed_activities
- & ERTS_BS_FLG_ALLOW_GC);
- break;
- case ERTS_ACTIVITY_IO:
- broadcast = (system_block_state.allowed_activities
- & ERTS_BS_FLG_ALLOW_IO);
- break;
- case ERTS_ACTIVITY_WAIT:
- broadcast = 1;
- break;
- default:
- abort();
- break;
- }
- if (broadcast)
- erts_smp_cnd_broadcast(&system_block_state.cnd);
- }
- erts_smp_mtx_unlock(&system_block_state.mtx);
-}
-
-void
-erts_check_block(erts_activity_t old_activity,
- erts_activity_t new_activity,
- int locked,
- void (*prepare)(void *),
- void (*resume)(void *),
- void *arg)
-{
- int do_block;
- profile_sched_msg_q psmq;
-
- psmq.n = 0;
- if (!locked && prepare)
- (*prepare)(arg);
-
- erts_smp_mtx_lock(&system_block_state.mtx);
-
- /* First check if it is ok to block... */
- if (!locked)
- do_block = 1;
- else {
- switch (old_activity) {
- case ERTS_ACTIVITY_UNDEFINED:
- do_block = 0;
- break;
- case ERTS_ACTIVITY_GC:
- do_block = (system_block_state.allowed_activities
- & ERTS_BS_FLG_ALLOW_GC);
- break;
- case ERTS_ACTIVITY_IO:
- do_block = (system_block_state.allowed_activities
- & ERTS_BS_FLG_ALLOW_IO);
- break;
- case ERTS_ACTIVITY_WAIT:
- /* You are not allowed to leave activity waiting
- * without supplying the possibility to block
- * unlocked.
- */
- erts_set_activity_error(ERTS_ACT_ERR_LEAVE_WAIT_UNLOCKED,
- __FILE__, __LINE__);
- do_block = 0;
- break;
- default:
- erts_set_activity_error(ERTS_ACT_ERR_LEAVE_UNKNOWN_ACTIVITY,
- __FILE__, __LINE__);
- do_block = 0;
- break;
- }
- }
-
- if (do_block) {
- /* ... then check if it is necessary to block... */
-
- switch (new_activity) {
- case ERTS_ACTIVITY_UNDEFINED:
- do_block = 1;
- break;
- case ERTS_ACTIVITY_GC:
- do_block = !(system_block_state.allowed_activities
- & ERTS_BS_FLG_ALLOW_GC);
- break;
- case ERTS_ACTIVITY_IO:
- do_block = !(system_block_state.allowed_activities
- & ERTS_BS_FLG_ALLOW_IO);
- break;
- case ERTS_ACTIVITY_WAIT:
- /* No need to block if we are going to wait */
- do_block = 0;
- break;
- default:
- erts_set_activity_error(ERTS_ACT_ERR_ENTER_UNKNOWN_ACTIVITY,
- __FILE__, __LINE__);
- break;
- }
- }
-
- if (do_block) {
-
-#ifdef ERTS_ENABLE_LOCK_CHECK
- if (!locked) {
- /* Only system_block_state.mtx should be held */
- erts_lc_check_exact(&system_block_state.mtx.lc, 1);
- }
-#endif
-
- block_me(NULL, NULL, NULL, 1, 0, 1, &psmq);
-
- }
-
- erts_smp_mtx_unlock(&system_block_state.mtx);
-
- if (erts_system_profile_flags.scheduler && psmq.n > 0)
- dispatch_profile_msg_q(&psmq);
-
- if (!locked && resume)
- (*resume)(arg);
-}
-
-
-
-void
-erts_set_activity_error(erts_activity_error_t error, char *file, int line)
-{
- switch (error) {
- case ERTS_ACT_ERR_LEAVE_WAIT_UNLOCKED:
- erl_exit(1, "%s:%d: Fatal error: Leaving activity waiting without "
- "supplying the possibility to block unlocked.",
- file, line);
- break;
- case ERTS_ACT_ERR_LEAVE_UNKNOWN_ACTIVITY:
- erl_exit(1, "%s:%d: Fatal error: Leaving unknown activity.",
- file, line);
- break;
- case ERTS_ACT_ERR_ENTER_UNKNOWN_ACTIVITY:
- erl_exit(1, "%s:%d: Fatal error: Leaving unknown activity.",
- file, line);
- break;
- default:
- erl_exit(1, "%s:%d: Internal error in erts_smp_set_activity()",
- file, line);
- break;
- }
-
-}
-
-
-static ERTS_INLINE erts_aint32_t
-threads_not_under_control(void)
-{
- erts_aint32_t res = system_block_state.threads_to_block;
-
- /* Waiting is always an allowed activity... */
- res -= erts_smp_atomic32_read(&erts_system_block_state.in_activity.wait);
-
- if (system_block_state.allowed_activities & ERTS_BS_FLG_ALLOW_GC)
- res -= erts_smp_atomic32_read(&erts_system_block_state.in_activity.gc);
-
- if (system_block_state.allowed_activities & ERTS_BS_FLG_ALLOW_IO)
- res -= erts_smp_atomic32_read(&erts_system_block_state.in_activity.io);
-
- if (res < 0) {
- ASSERT(0);
- return 0;
- }
- return res;
-}
-
-/*
- * erts_block_system() blocks all threads registered as blockable.
- * It doesn't return until either all threads have blocked (0 is returned)
- * or it has timed out (ETIMEDOUT) is returned.
- *
- * If allowed activities == 0, blocked threads will release all locks
- * before blocking.
- *
- * If allowed_activities is != 0, erts_block_system() will allow blockable
- * threads to continue executing as long as they are doing an allowed
- * activity. When they are done with the allowed activity they will block,
- * *but* they will block holding locks. Therefore, the thread calling
- * erts_block_system() must *not* try to aquire any locks that might be
- * held by blocked threads holding locks from allowed activities.
- *
- * Currently allowed_activities are:
- * * ERTS_BS_FLG_ALLOW_GC Thread continues with garbage
- * collection and blocks with
- * main process lock on current
- * process locked.
- * * ERTS_BS_FLG_ALLOW_IO Thread continues with I/O
- */
-
-void
-erts_block_system(Uint32 allowed_activities)
-{
- int do_block;
- profile_sched_msg_q psmq;
-
- psmq.n = 0;
-#ifdef ERTS_ENABLE_LOCK_CHECK
- erts_lc_check_exact(NULL, 0); /* No locks should be locked */
-#endif
-
- erts_smp_mtx_lock(&system_block_state.mtx);
-
- do_block = erts_smp_pending_system_block();
- if (do_block
- && system_block_state.have_blocker
- && erts_smp_equal_tids(system_block_state.blocker_tid,
- erts_smp_thr_self())) {
- ASSERT(system_block_state.recursive_block >= 0);
- system_block_state.recursive_block++;
-
- /* You are not allowed to restrict allowed activites
- in a recursive block! */
- ERTS_SMP_LC_ASSERT((system_block_state.allowed_activities
- & ~allowed_activities) == 0);
- }
- else {
-
- erts_smp_atomic32_inc(&erts_system_block_state.do_block);
-
- /* Someone else might be waiting for us to block... */
- if (do_block) {
- do_block_me:
- block_me(NULL, NULL, NULL, 1, 1, 0, &psmq);
- }
-
- ASSERT(!system_block_state.have_blocker);
- system_block_state.have_blocker = 1;
- system_block_state.blocker_tid = erts_smp_thr_self();
- system_block_state.allowed_activities = allowed_activities;
-
- if (is_blockable_thread())
- system_block_state.threads_to_block--;
-
- while (threads_not_under_control() && !system_block_state.emergency)
- erts_smp_cnd_wait(&system_block_state.cnd, &system_block_state.mtx);
-
- if (system_block_state.emergency) {
- system_block_state.have_blocker = 0;
- goto do_block_me;
- }
- }
-
- erts_smp_mtx_unlock(&system_block_state.mtx);
-
- if (erts_system_profile_flags.scheduler && psmq.n > 0 )
- dispatch_profile_msg_q(&psmq);
-}
-
-/*
- * erts_emergency_block_system() should only be called when we are
- * about to write a crash dump...
- */
-
-int
-erts_emergency_block_system(long timeout, Uint32 allowed_activities)
-{
- int res = 0;
- long another_blocker;
-
- erts_smp_mtx_lock(&system_block_state.mtx);
-
- if (system_block_state.emergency) {
- /* Argh... */
- res = EINVAL;
- goto done;
- }
-
- another_blocker = erts_smp_pending_system_block();
- system_block_state.emergency = 1;
- erts_smp_atomic32_inc(&erts_system_block_state.do_block);
-
- if (another_blocker) {
- if (is_blocker()) {
- erts_smp_atomic32_dec(&erts_system_block_state.do_block);
- res = 0;
- goto done;
- }
- /* kick the other blocker */
- erts_smp_cnd_broadcast(&system_block_state.cnd);
- while (system_block_state.have_blocker)
- erts_smp_cnd_wait(&system_block_state.cnd, &system_block_state.mtx);
- }
-
- ASSERT(!system_block_state.have_blocker);
- system_block_state.have_blocker = 1;
- system_block_state.blocker_tid = erts_smp_thr_self();
- system_block_state.allowed_activities = allowed_activities;
-
- if (is_blockable_thread())
- system_block_state.threads_to_block--;
-
- if (timeout < 0) {
- while (threads_not_under_control())
- erts_smp_cnd_wait(&system_block_state.cnd, &system_block_state.mtx);
- }
- else {
- system_block_state.emergency_timeout = timeout;
- erts_smp_cnd_signal(&system_block_state.watchdog_cnd);
-
- while (system_block_state.emergency_timeout >= 0
- && threads_not_under_control()) {
- erts_smp_cnd_wait(&system_block_state.cnd,
- &system_block_state.mtx);
- }
- }
- done:
- erts_smp_mtx_unlock(&system_block_state.mtx);
- return res;
-}
-
-void
-erts_release_system(void)
-{
- long do_block;
- profile_sched_msg_q psmq;
-
- psmq.n = 0;
-
-#ifdef ERTS_ENABLE_LOCK_CHECK
- erts_lc_check_exact(NULL, 0); /* No locks should be locked */
-#endif
-
- erts_smp_mtx_lock(&system_block_state.mtx);
- ASSERT(is_blocker());
-
- ASSERT(system_block_state.recursive_block >= 0);
-
- if (system_block_state.recursive_block)
- system_block_state.recursive_block--;
- else {
- do_block = erts_smp_atomic32_dectest(&erts_system_block_state.do_block);
- system_block_state.have_blocker = 0;
- if (is_blockable_thread())
- system_block_state.threads_to_block++;
- else
- do_block = 0;
-
- /* Someone else might be waiting for us to block... */
- if (do_block)
- block_me(NULL, NULL, NULL, 1, 0, 0, &psmq);
- else
- erts_smp_cnd_broadcast(&system_block_state.cnd);
- }
-
- erts_smp_mtx_unlock(&system_block_state.mtx);
-
- if (erts_system_profile_flags.scheduler && psmq.n > 0)
- dispatch_profile_msg_q(&psmq);
-}
-
-#ifdef ERTS_ENABLE_LOCK_CHECK
-
-void
-erts_lc_activity_change_begin(void)
-{
- erts_smp_mtx_lock(&system_block_state.mtx);
- system_block_state.activity_changing++;
- erts_smp_mtx_unlock(&system_block_state.mtx);
-}
-
-void
-erts_lc_activity_change_end(void)
-{
- erts_smp_mtx_lock(&system_block_state.mtx);
- system_block_state.activity_changing--;
- if (system_block_state.checking && !system_block_state.activity_changing)
- erts_smp_cnd_broadcast(&system_block_state.cnd);
- erts_smp_mtx_unlock(&system_block_state.mtx);
-}
-
-#endif
-
-int
-erts_is_system_blocked(erts_activity_t allowed_activities)
-{
- int blkd;
-
- erts_smp_mtx_lock(&system_block_state.mtx);
- blkd = (erts_smp_pending_system_block()
- && system_block_state.have_blocker
- && erts_smp_equal_tids(system_block_state.blocker_tid,
- erts_smp_thr_self())
- && !(system_block_state.allowed_activities & ~allowed_activities));
-#ifdef ERTS_ENABLE_LOCK_CHECK
- if (blkd) {
- system_block_state.checking = 1;
- while (system_block_state.activity_changing)
- erts_smp_cnd_wait(&system_block_state.cnd, &system_block_state.mtx);
- system_block_state.checking = 0;
- blkd = !threads_not_under_control();
- }
-#endif
- erts_smp_mtx_unlock(&system_block_state.mtx);
- return blkd;
-}
-
-static void *
-emergency_watchdog(void *unused)
-{
- erts_smp_mtx_lock(&system_block_state.mtx);
- while (1) {
- long timeout;
- while (system_block_state.emergency_timeout < 0)
- erts_smp_cnd_wait(&system_block_state.watchdog_cnd, &system_block_state.mtx);
- timeout = system_block_state.emergency_timeout;
- erts_smp_mtx_unlock(&system_block_state.mtx);
-
- if (erts_disable_tolerant_timeofday)
- erts_milli_sleep(timeout);
- else {
- SysTimeval to;
- erts_get_timeval(&to);
- to.tv_sec += timeout / 1000;
- to.tv_usec += timeout % 1000;
-
- while (1) {
- SysTimeval curr;
- erts_milli_sleep(timeout);
- erts_get_timeval(&curr);
- if (curr.tv_sec > to.tv_sec
- || (curr.tv_sec == to.tv_sec && curr.tv_usec >= to.tv_usec)) {
- break;
- }
- timeout = (to.tv_sec - curr.tv_sec)*1000;
- timeout += (to.tv_usec - curr.tv_usec)/1000;
- }
- }
-
- erts_smp_mtx_lock(&system_block_state.mtx);
- system_block_state.emergency_timeout = -1;
- erts_smp_cnd_broadcast(&system_block_state.cnd);
- }
- erts_smp_mtx_unlock(&system_block_state.mtx);
- return NULL;
-}
-
-void
-erts_system_block_init(void)
-{
- erts_smp_thr_opts_t thr_opts = ERTS_SMP_THR_OPTS_DEFAULT_INITER;
- /* Local state... */
- system_block_state.emergency = 0;
- system_block_state.emergency_timeout = -1;
- erts_smp_cnd_init(&system_block_state.watchdog_cnd);
- system_block_state.threads_to_block = 0;
- system_block_state.have_blocker = 0;
- /* system_block_state.block_tid */
- system_block_state.recursive_block = 0;
- system_block_state.allowed_activities = 0;
- erts_smp_tsd_key_create(&system_block_state.blockable_key);
- erts_smp_mtx_init(&system_block_state.mtx, "system_block");
- erts_smp_cnd_init(&system_block_state.cnd);
-#ifdef ERTS_ENABLE_LOCK_CHECK
- system_block_state.activity_changing = 0;
- system_block_state.checking = 0;
-#endif
-
- thr_opts.suggested_stack_size = 8;
- erts_smp_thr_create(&system_block_state.watchdog_tid,
- emergency_watchdog,
- NULL,
- &thr_opts);
-
- /* Global state... */
-
- erts_smp_atomic32_init(&erts_system_block_state.do_block, 0);
- erts_smp_atomic32_init(&erts_system_block_state.in_activity.wait, 0);
- erts_smp_atomic32_init(&erts_system_block_state.in_activity.gc, 0);
- erts_smp_atomic32_init(&erts_system_block_state.in_activity.io, 0);
-
- /* Make sure blockable threads unregister when exiting... */
- erts_smp_install_exit_handler(erts_unregister_blockable_thread);
-}
-
-
-#endif /* #ifdef ERTS_SMP */
-
char *
erts_read_env(char *key)
{
diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c
index f0ff3f54c5..52f1b5312b 100644
--- a/erts/emulator/drivers/common/efile_drv.c
+++ b/erts/emulator/drivers/common/efile_drv.c
@@ -69,6 +69,7 @@
#define FILE_RESP_EOF 8
#define FILE_RESP_FNAME 9
#define FILE_RESP_ALL_DATA 10
+#define FILE_RESP_LFNAME 11
/* Options */
@@ -184,6 +185,7 @@ static ErlDrvSysInfo sys_info;
# define RESBUFSIZE BUFSIZ
#endif
+#define READDIR_CHUNKS (5)
@@ -317,15 +319,16 @@ struct t_preadv {
Sint64 offsets[1];
};
-#define READDIR_BUFSIZE (8*1024)
-#if READDIR_BUFSIZE < (FILENAME_CHARSIZE*2*(MAXPATHLEN+1))
+#define READDIR_BUFSIZE (8*1024)*READDIR_CHUNKS
+#if READDIR_BUFSIZE < (1 + (2 + MAXPATHLEN)*FILENAME_CHARSIZE*READDIR_CHUNKS)
# undef READDIR_BUFSIZE
-# define READDIR_BUFSIZE (FILENAME_CHARSIZE*2*(MAXPATHLEN+1))
+# define READDIR_BUFSIZE (1 + (2 + MAXPATHLEN)*FILENAME_CHARSIZE*READDIR_CHUNKS)
#endif
struct t_readdir_buf {
- struct t_readdir_buf *next;
- char buf[READDIR_BUFSIZE];
+ struct t_readdir_buf *next;
+ size_t n;
+ char buf[READDIR_BUFSIZE];
};
struct t_data
@@ -1598,54 +1601,46 @@ static void invoke_lseek(void *data)
static void invoke_readdir(void *data)
{
struct t_data *d = (struct t_data *) data;
- int s;
char *p = NULL;
- int buf_sz = 0;
- size_t tmp_bs;
+ size_t file_bs;
+ size_t n = 0, total = 0;
+ struct t_readdir_buf *b = NULL;
+ int res = 0;
d->again = 0;
d->errInfo.posix_errno = 0;
- while (1) {
- char *str;
- if (buf_sz < (4 /* sz */ + 1 /* cmd */ +
- FILENAME_CHARSIZE*(MAXPATHLEN + 1))) {
- struct t_readdir_buf *b;
- if (p) {
- put_int32(0, p); /* EOB */
- }
- b = EF_SAFE_ALLOC(sizeof(struct t_readdir_buf));
- b->next = NULL;
- if (d->c.read_dir.last_buf)
- d->c.read_dir.last_buf->next = b;
- else
- d->c.read_dir.first_buf = b;
- d->c.read_dir.last_buf = b;
- p = &b->buf[0];
- buf_sz = READDIR_BUFSIZE - 4/* EOB */;
- }
-
- p[4] = FILE_RESP_FNAME;
- buf_sz -= 4 + 1;
- str = p + 4 + 1;
- ASSERT(buf_sz >= MAXPATHLEN + 1);
- tmp_bs = buf_sz;
- s = efile_readdir(&d->errInfo, d->b, &d->dir_handle, str, &tmp_bs);
-
- if (s) {
- put_int32(tmp_bs + 1 /* 1 byte for opcode */, p);
- p += 4 + tmp_bs + 1;
- ASSERT(p == (str + tmp_bs));
- buf_sz -= tmp_bs;
- }
- else {
- put_int32(1, p);
- p += 4 + 1;
- put_int32(0, p); /* EOB */
- d->result_ok = (d->errInfo.posix_errno == 0);
- break;
+ do {
+ total = READDIR_BUFSIZE;
+ n = 1;
+ b = EF_SAFE_ALLOC(sizeof(struct t_readdir_buf));
+ b->next = NULL;
+
+ if (d->c.read_dir.last_buf) {
+ d->c.read_dir.last_buf->next = b;
+ } else {
+ d->c.read_dir.first_buf = b;
}
- }
+ d->c.read_dir.last_buf = b;
+
+ p = &b->buf[0];
+ p[0] = FILE_RESP_LFNAME;
+ file_bs = READDIR_BUFSIZE - n;
+
+ do {
+ res = efile_readdir(&d->errInfo, d->b, &d->dir_handle, p + n + 2, &file_bs);
+
+ if (res) {
+ put_int16((Uint16)file_bs, p + n);
+ n += 2 + file_bs;
+ file_bs = READDIR_BUFSIZE - n;
+ }
+ } while( res && ((total - n - 2) >= MAXPATHLEN*FILENAME_CHARSIZE));
+
+ b->n = n;
+ } while(res);
+
+ d->result_ok = (d->errInfo.posix_errno == 0);
}
static void invoke_open(void *data)
@@ -2053,30 +2048,24 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data)
free_data(data);
break;
case FILE_READDIR:
- if (!d->result_ok)
+ if (!d->result_ok) {
reply_error(desc, &d->errInfo);
- else {
+ } else {
struct t_readdir_buf *b1 = d->c.read_dir.first_buf;
+ char op = FILE_RESP_LFNAME;
+
TRACE_C('R');
ASSERT(b1);
+
while (b1) {
struct t_readdir_buf *b2 = b1;
char *p = &b1->buf[0];
- int sz = get_int32(p);
- while (sz) { /* 0 == EOB */
- p += 4;
- if (sz - 1 > 0) {
- driver_output2(desc->port, p, 1, p+1, sz-1);
- } else {
- driver_output2(desc->port, p, 1, NULL, 0);
- }
- p += sz;
- sz = get_int32(p);
- }
+ driver_output2(desc->port, p, 1, p + 1, b1->n - 1);
b1 = b1->next;
EF_FREE(b2);
}
-
+ driver_output2(desc->port, &op, 1, NULL, 0);
+
d->c.read_dir.first_buf = NULL;
d->c.read_dir.last_buf = NULL;
}
@@ -2126,6 +2115,7 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data)
cq_execute(desc);
}
+
/*********************************************************************
* Driver entry point -> output
*/
@@ -2246,19 +2236,46 @@ file_output(ErlDrvData e, char* buf, int count)
#endif
{
size_t resbufsize;
- char resbuf[RESBUFSIZE+1];
+ size_t n = 0, total = 0;
+ int res = 0;
+ char resbuf[READDIR_BUFSIZE];
+
EFILE_DIR_HANDLE dir_handle; /* Handle to open directory. */
+ total = READDIR_BUFSIZE;
errInfo.posix_errno = 0;
- dir_handle = NULL;
- resbuf[0] = FILE_RESP_FNAME;
- resbufsize = RESBUFSIZE;
-
- while (efile_readdir(&errInfo, name, &dir_handle,
- resbuf+1, &resbufsize)) {
- driver_output2(desc->port, resbuf, 1, resbuf+1, resbufsize);
- resbufsize = RESBUFSIZE;
- }
+ dir_handle = NULL;
+ resbuf[0] = FILE_RESP_LFNAME;
+
+ /* Fill the buffer with multiple directory listings before sending it to the
+ * receiving process. READDIR_CHUNKS is minimum number of files sent to the
+ * receiver.
+ * Format for each driver_output2:
+ * ------------------------------------
+ * | Type | Len | Filename | ...
+ * | 1 byte | 2 bytes | Len bytes | ...
+ * ------------------------------------
+ */
+
+ do {
+ n = 1;
+ resbufsize = READDIR_BUFSIZE - n;
+
+ do {
+ res = efile_readdir(&errInfo, name, &dir_handle, resbuf + n + 2, &resbufsize);
+
+ if (res) {
+ put_int16((Uint16)resbufsize, resbuf + n);
+ n += 2 + resbufsize;
+ resbufsize = READDIR_BUFSIZE - n;
+ }
+ } while( res && ((total - n - 2) >= MAXPATHLEN*FILENAME_CHARSIZE));
+
+ if (n > 1) {
+ driver_output2(desc->port, resbuf, 1, resbuf + 1, n - 1);
+ }
+ } while(res);
+
if (errInfo.posix_errno != 0) {
reply_error(desc, &errInfo);
return;
@@ -2476,13 +2493,20 @@ file_flush(ErlDrvData e) {
static int
file_control(ErlDrvData e, unsigned int command,
char* buf, int len, char **rbuf, int rlen) {
+ /*
+ * warning: variable ‘desc’ set but not used
+ * [-Wunused-but-set-variable]
+ * ... no kidding ...
+ *
+ *
file_descriptor *desc = (file_descriptor *)e;
switch (command) {
default:
return 0;
- } /* switch (command) */
+ }
ASSERT(0);
- desc = NULL; /* XXX Avoid warning while empty switch */
+ desc = NULL;
+ */
return 0;
}
diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c
index 40c4a0df08..2ff5f744d6 100644
--- a/erts/emulator/drivers/common/inet_drv.c
+++ b/erts/emulator/drivers/common/inet_drv.c
@@ -280,6 +280,57 @@ static unsigned long one_value = 1;
# define SCTP_EOF MSG_EOF
#endif
+/* More Solaris 10 fixes: */
+#if ! HAVE_DECL_SCTP_CLOSED && HAVE_DECL_SCTPS_IDLE
+# define SCTP_CLOSED SCTPS_IDLE
+# undef HAVE_DECL_SCTP_CLOSED
+# define HAVE_DECL_SCTP_CLOSED 1
+#endif
+#if ! HAVE_DECL_SCTP_BOUND && HAVE_DECL_SCTPS_BOUND
+# define SCTP_BOUND SCTPS_BOUND
+# undef HAVE_DECL_SCTP_BOUND
+# define HAVE_DECL_SCTP_BOUND 1
+#endif
+#if ! HAVE_DECL_SCTP_LISTEN && HAVE_DECL_SCTPS_LISTEN
+# define SCTP_LISTEN SCTPS_LISTEN
+# undef HAVE_DECL_SCTP_LISTEN
+# define HAVE_DECL_SCTP_LISTEN 1
+#endif
+#if ! HAVE_DECL_SCTP_COOKIE_WAIT && HAVE_DECL_SCTPS_COOKIE_WAIT
+# define SCTP_COOKIE_WAIT SCTPS_COOKIE_WAIT
+# undef HAVE_DECL_SCTP_COOKIE_WAIT
+# define HAVE_DECL_SCTP_COOKIE_WAIT 1
+#endif
+#if ! HAVE_DECL_SCTP_COOKIE_ECHOED && HAVE_DECL_SCTPS_COOKIE_ECHOED
+# define SCTP_COOKIE_ECHOED SCTPS_COOKIE_ECHOED
+# undef HAVE_DECL_SCTP_COOKIE_ECHOED
+# define HAVE_DECL_SCTP_COOKIE_ECHOED 1
+#endif
+#if ! HAVE_DECL_SCTP_ESTABLISHED && HAVE_DECL_SCTPS_ESTABLISHED
+# define SCTP_ESTABLISHED SCTPS_ESTABLISHED
+# undef HAVE_DECL_SCTP_ESTABLISHED
+# define HAVE_DECL_SCTP_ESTABLISHED 1
+#endif
+#if ! HAVE_DECL_SCTP_SHUTDOWN_PENDING && HAVE_DECL_SCTPS_SHUTDOWN_PENDING
+# define SCTP_SHUTDOWN_PENDING SCTPS_SHUTDOWN_PENDING
+# undef HAVE_DECL_SCTP_SHUTDOWN_PENDING
+# define HAVE_DECL_SCTP_SHUTDOWN_PENDING 1
+#endif
+#if ! HAVE_DECL_SCTP_SHUTDOWN_SENT && HAVE_DECL_SCTPS_SHUTDOWN_SENT
+# define SCTP_SHUTDOWN_SENT SCTPS_SHUTDOWN_SENT
+# undef HAVE_DECL_SCTP_SHUTDOWN_SENT
+# define HAVE_DECL_SCTP_SHUTDOWN_SENT 1
+#endif
+#if ! HAVE_DECL_SCTP_SHUTDOWN_RECEIVED && HAVE_DECL_SCTPS_SHUTDOWN_RECEIVED
+# define SCTP_SHUTDOWN_RECEIVED SCTPS_SHUTDOWN_RECEIVED
+# undef HAVE_DECL_SCTP_SHUTDOWN_RECEIVED
+# define HAVE_DECL_SCTP_SHUTDOWN_RECEIVED 1
+#endif
+#if ! HAVE_DECL_SCTP_SHUTDOWN_ACK_SENT && HAVE_DECL_SCTPS_SHUTDOWN_ACK_SENT
+# define SCTP_SHUTDOWN_ACK_SENT SCTPS_SHUTDOWN_ACK_SENT
+# undef HAVE_DECL_SCTP_SHUTDOWN_ACK_SENT
+# define HAVE_DECL_SCTP_SHUTDOWN_ACK_SENT 1
+#endif
/* New spelling in lksctp 2.6.22 or maybe even earlier:
* adaption -> adaptation
*/
@@ -294,12 +345,13 @@ static unsigned long one_value = 1;
# define sctp_adaptation_layer_event sctp_adaption_layer_event
#endif
-static void *h_libsctp = NULL;
#ifdef __GNUC__
static typeof(sctp_bindx) *p_sctp_bindx = NULL;
+static typeof(sctp_peeloff) *p_sctp_peeloff = NULL;
#else
static int (*p_sctp_bindx)(int sd, struct sockaddr *addrs,
int addrcnt, int flags) = NULL;
+static int (*p_sctp_peeloff)(int sd, sctp_assoc_t assoc_id) = NULL;
#endif
#endif /* SCTP supported */
@@ -427,7 +479,7 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n)
#define INET_AF_ANY 3 /* INADDR_ANY or IN6ADDR_ANY_INIT */
#define INET_AF_LOOPBACK 4 /* INADDR_LOOPBACK or IN6ADDR_LOOPBACK_INIT */
-/* INET_REQ_GETTYPE enumeration */
+/* open and INET_REQ_GETTYPE enumeration */
#define INET_TYPE_STREAM 1
#define INET_TYPE_DGRAM 2
#define INET_TYPE_SEQPACKET 3
@@ -484,16 +536,19 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n)
#define INET_REQ_IFSET 23
#define INET_REQ_SUBSCRIBE 24
#define INET_REQ_GETIFADDRS 25
+#define INET_REQ_ACCEPT 26
+#define INET_REQ_LISTEN 27
/* TCP requests */
-#define TCP_REQ_ACCEPT 40
-#define TCP_REQ_LISTEN 41
+/* #define TCP_REQ_ACCEPT 40 MOVED */
+/* #define TCP_REQ_LISTEN 41 MERGED */
#define TCP_REQ_RECV 42
#define TCP_REQ_UNRECV 43
#define TCP_REQ_SHUTDOWN 44
/* UDP and SCTP requests */
#define PACKET_REQ_RECV 60 /* Common for UDP and SCTP */
-#define SCTP_REQ_LISTEN 61 /* Different from TCP; not for UDP */
+/* #define SCTP_REQ_LISTEN 61 MERGED Different from TCP; not for UDP */
#define SCTP_REQ_BINDX 62 /* Multi-home SCTP bind */
+#define SCTP_REQ_PEELOFF 63
/* INET_REQ_SUBSCRIBE sub-requests */
#define INET_SUBS_EMPTY_OUT_Q 1
@@ -507,7 +562,7 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n)
/* *_REQ_* replies */
#define INET_REP_ERROR 0
#define INET_REP_OK 1
-#define INET_REP_SCTP 2
+#define INET_REP 2
/* INET_REQ_SETOPTS and INET_REQ_GETOPTS options */
#define INET_OPT_REUSEADDR 0 /* enable/disable local address reuse */
@@ -628,10 +683,14 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n)
** End of interface constants.
**--------------------------------------------------------------------------*/
-#define INET_STATE_CLOSED 0
-#define INET_STATE_OPEN (INET_F_OPEN)
-#define INET_STATE_BOUND (INET_STATE_OPEN | INET_F_BOUND)
-#define INET_STATE_CONNECTED (INET_STATE_BOUND | INET_F_ACTIVE)
+#define INET_STATE_CLOSED (0)
+#define INET_STATE_OPEN (INET_F_OPEN)
+#define INET_STATE_BOUND (INET_STATE_OPEN | INET_F_BOUND)
+#define INET_STATE_CONNECTED (INET_STATE_BOUND | INET_F_ACTIVE)
+#define INET_STATE_LISTENING (INET_STATE_BOUND | INET_F_LISTEN)
+#define INET_STATE_CONNECTING (INET_STATE_BOUND | INET_F_CON)
+#define INET_STATE_ACCEPTING (INET_STATE_LISTENING | INET_F_ACC)
+#define INET_STATE_MULTI_ACCEPTING (INET_STATE_ACCEPTING | INET_F_MULTI_CLIENT)
#define IS_OPEN(d) \
(((d)->state & INET_F_OPEN) == INET_F_OPEN)
@@ -674,7 +733,7 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n)
#endif
-#define BIN_REALLOC_LIMIT(x) (((x)*3)/4) /* 75% */
+#define BIN_REALLOC_MARGIN(x) ((x)/4) /* 25% */
/* The general purpose sockaddr */
typedef union {
@@ -809,16 +868,6 @@ typedef struct {
-#define TCP_STATE_CLOSED INET_STATE_CLOSED
-#define TCP_STATE_OPEN (INET_F_OPEN)
-#define TCP_STATE_BOUND (TCP_STATE_OPEN | INET_F_BOUND)
-#define TCP_STATE_CONNECTED (TCP_STATE_BOUND | INET_F_ACTIVE)
-#define TCP_STATE_LISTEN (TCP_STATE_BOUND | INET_F_LISTEN)
-#define TCP_STATE_CONNECTING (TCP_STATE_BOUND | INET_F_CON)
-#define TCP_STATE_ACCEPTING (TCP_STATE_LISTEN | INET_F_ACC)
-#define TCP_STATE_MULTI_ACCEPTING (TCP_STATE_ACCEPTING | INET_F_MULTI_CLIENT)
-
-
#define TCP_MAX_PACKET_SIZE 0x4000000 /* 64 M */
#define MAX_VSIZE 16 /* Max number of entries allowed in an I/O
@@ -874,12 +923,6 @@ static struct erl_drv_entry tcp_inet_driver_entry =
inet_stop_select
};
-#define PACKET_STATE_CLOSED INET_STATE_CLOSED
-#define PACKET_STATE_OPEN (INET_F_OPEN)
-#define PACKET_STATE_BOUND (PACKET_STATE_OPEN | INET_F_BOUND)
-#define SCTP_STATE_LISTEN (PACKET_STATE_BOUND | INET_F_LISTEN)
-#define SCTP_STATE_CONNECTING (PACKET_STATE_BOUND | INET_F_CON)
-#define PACKET_STATE_CONNECTED (PACKET_STATE_BOUND | INET_F_ACTIVE)
static int packet_inet_init(void);
@@ -997,6 +1040,9 @@ static int tcp_inet_input(tcp_descriptor* desc, HANDLE event);
typedef struct {
inet_descriptor inet; /* common data structure (DON'T MOVE) */
int read_packets; /* Number of packets to read per invocation */
+ int i_bufsz; /* current input buffer size */
+ ErlDrvBinary* i_buf; /* current binary buffer */
+ char* i_ptr; /* current pos in buf */
} udp_descriptor;
@@ -1851,6 +1897,26 @@ static int inet_reply_ok(inet_descriptor* desc)
return driver_send_term(desc->port, caller, spec, i);
}
+#ifdef HAVE_SCTP
+static int inet_reply_ok_port(inet_descriptor* desc, ErlDrvTermData dport)
+{
+ ErlDrvTermData spec[2*LOAD_ATOM_CNT + 2*LOAD_PORT_CNT + 2*LOAD_TUPLE_CNT];
+ ErlDrvTermData caller = desc->caller;
+ int i = 0;
+
+ i = LOAD_ATOM(spec, i, am_inet_reply);
+ i = LOAD_PORT(spec, i, desc->dport);
+ i = LOAD_ATOM(spec, i, am_ok);
+ i = LOAD_PORT(spec, i, dport);
+ i = LOAD_TUPLE(spec, i, 2);
+ i = LOAD_TUPLE(spec, i, 3);
+ ASSERT(i == sizeof(spec)/sizeof(*spec));
+
+ desc->caller = 0;
+ return driver_send_term(desc->port, caller, spec, i);
+}
+#endif
+
/* send:
** {inet_reply, S, {error, Reason}}
*/
@@ -2389,14 +2455,19 @@ static ErlDrvTermData am_sctp_rtoinfo, /* Option names */
am_active, am_inactive,
/* For #sctp_status{}: */
- am_empty, am_closed,
+# if HAVE_DECL_SCTP_EMPTY
+ am_empty,
+# endif
+# if HAVE_DECL_SCTP_BOUND
+ am_bound,
+# endif
+# if HAVE_DECL_SCTP_LISTEN
+ am_listen,
+# endif
am_cookie_wait, am_cookie_echoed,
am_established, am_shutdown_pending,
am_shutdown_sent, am_shutdown_received,
am_shutdown_ack_sent;
- /* Not yet implemented in the Linux kernel:
- ** am_bound, am_listen;
- */
/*
** Parsing of "sctp_sndrcvinfo": ancillary data coming with received msgs.
@@ -2665,7 +2736,8 @@ static int sctp_parse_async_event
# ifdef HAVE_STRUCT_SCTP_REMOTE_ERROR_SRE_DATA
chunk = (char*) (&(sptr->sre_data));
# else
- chunk = ((char*)sptr) + sizeof(*sptr);
+ chunk = ((char*) &(sptr->sre_assoc_id))
+ + sizeof(sptr->sre_assoc_id);
# endif
chlen = sptr->sre_length - (chunk - (char *)sptr);
i = sctp_parse_error_chunk(spec, i, chunk, chlen);
@@ -2716,7 +2788,8 @@ static int sctp_parse_async_event
# ifdef HAVE_STRUCT_SCTP_SEND_FAILED_SSF_DATA
chunk = (char*) (&(sptr->ssf_data));
# else
- chunk = ((char*)sptr) + sizeof(*sptr);
+ chunk = ((char*) &(sptr->ssf_assoc_id))
+ + sizeof(sptr->ssf_assoc_id);
# endif
chlen = sptr->ssf_length - (chunk - (char*) sptr);
choff = chunk - bin->orig_bytes;
@@ -3390,8 +3463,15 @@ static void inet_init_sctp(void) {
INIT_ATOM(inactive);
/* For #sctp_status{}: */
+# if HAVE_DECL_SCTP_EMPTY
INIT_ATOM(empty);
- INIT_ATOM(closed);
+# endif
+# if HAVE_DECL_SCTP_BOUND
+ INIT_ATOM(bound);
+# endif
+# if HAVE_DECL_SCTP_LISTEN
+ INIT_ATOM(listen);
+# endif
INIT_ATOM(cookie_wait);
INIT_ATOM(cookie_echoed);
INIT_ATOM(established);
@@ -3399,10 +3479,6 @@ static void inet_init_sctp(void) {
INIT_ATOM(shutdown_sent);
INIT_ATOM(shutdown_received);
INIT_ATOM(shutdown_ack_sent);
- /* Not yet implemented in the Linux kernel:
- ** INIT_ATOM(bound);
- ** INIT_ATOM(listen);
- */
}
#endif /* HAVE_SCTP */
@@ -3453,17 +3529,32 @@ static int inet_init()
/* Check the size of SCTP AssocID -- currently both this driver and the
Erlang part require 32 bit: */
ASSERT(sizeof(sctp_assoc_t)==ASSOC_ID_LEN);
-# ifndef LIBSCTP
-# error LIBSCTP not defined
-# endif
- if (erts_sys_ddll_open_noext(STRINGIFY(LIBSCTP), &h_libsctp, NULL) == 0) {
- void *ptr;
- if (erts_sys_ddll_sym(h_libsctp, "sctp_bindx", &ptr) == 0) {
- p_sctp_bindx = ptr;
- inet_init_sctp();
- add_driver_entry(&sctp_inet_driver_entry);
+# if defined(HAVE_SCTP_BINDX) && defined (HAVE_SCTP_PEELOFF)
+ p_sctp_bindx = sctp_bindx;
+ p_sctp_peeloff = sctp_peeloff;
+ inet_init_sctp();
+ add_driver_entry(&sctp_inet_driver_entry);
+# else
+# ifndef LIBSCTP
+# error LIBSCTP not defined
+# endif
+ {
+ static void *h_libsctp = NULL;
+
+ if (erts_sys_ddll_open_noext(STRINGIFY(LIBSCTP), &h_libsctp, NULL)
+ == 0) {
+ void *ptr;
+ if (erts_sys_ddll_sym(h_libsctp, "sctp_bindx", &ptr) == 0) {
+ p_sctp_bindx = ptr;
+ inet_init_sctp();
+ add_driver_entry(&sctp_inet_driver_entry);
+ if (erts_sys_ddll_sym(h_libsctp, "sctp_peeloff", &ptr) == 0) {
+ p_sctp_peeloff = ptr;
+ }
+ }
}
}
+# endif
#endif
/* remove the dummy inet driver */
@@ -3709,6 +3800,8 @@ static int inet_ctl_fdopen(inet_descriptor* desc, int domain, int type,
/* check that it is a socket and that the socket is bound */
if (IS_SOCKET_ERROR(sock_name(s, (struct sockaddr*) &name, &sz)))
return ctl_error(sock_errno(), rbuf, rsize);
+ if (name.sa.sa_family != domain)
+ return ctl_error(EINVAL, rbuf, rsize);
desc->s = s;
if ((desc->event = sock_create_event(desc)) == INVALID_EVENT)
return ctl_error(sock_errno(), rbuf, rsize);
@@ -4457,6 +4550,7 @@ static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len,
+#if defined(__WIN32__) || defined(HAVE_GETIFADDRS)
/* Latin-1 to utf8 */
static int utf8_len(const char *c, int m) {
@@ -4479,6 +4573,7 @@ static void utf8_encode(const char *c, int m, char *p) {
}
}
}
+#endif
#if defined(__WIN32__)
@@ -6537,7 +6632,7 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen,
struct linger lg;
unsigned int sz = sizeof(lg);
- if (sock_getopt(desc->s, IPPROTO_SCTP, SO_LINGER,
+ if (sock_getopt(desc->s, SOL_SOCKET, SO_LINGER,
&lg, &sz) < 0) continue;
/* Fill in the response: */
PLACE_FOR(spec, i,
@@ -6573,7 +6668,7 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen,
{
case INET_OPT_RCVBUF :
{
- proto = IPPROTO_SCTP;
+ proto = SOL_SOCKET;
type = SO_RCVBUF;
is_int = 1;
tag = am_recbuf;
@@ -6581,7 +6676,7 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen,
}
case INET_OPT_SNDBUF :
{
- proto = IPPROTO_SCTP;
+ proto = SOL_SOCKET;
type = SO_SNDBUF;
is_int = 1;
tag = am_sndbuf;
@@ -6734,7 +6829,7 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen,
2*LOAD_ATOM_CNT + LOAD_INT_CNT + 2*LOAD_TUPLE_CNT);
i = LOAD_ATOM (spec, i, am_sctp_adaptation_layer);
i = LOAD_ATOM (spec, i, am_sctp_setadaptation);
- i = LOAD_INT (spec, i, ad.ssb_adaptation_ind);
+ i = LOAD_INT (spec, i, sock_ntohl(ad.ssb_adaptation_ind));
i = LOAD_TUPLE (spec, i, 2);
i = LOAD_TUPLE (spec, i, 2);
break;
@@ -6877,7 +6972,7 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen,
break;
}
/* The following option is not available in Solaris 10: */
-# ifdef SCTP_DELAYED_ACK_TIME
+# if HAVE_DECL_SCTP_DELAYED_ACK_TIME
case SCTP_OPT_DELAYED_ACK_TIME:
{
struct sctp_assoc_value av;
@@ -6924,7 +7019,7 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen,
switch(st.sstat_state)
{
/* SCTP_EMPTY is not supported on SOLARIS10: */
-# ifdef SCTP_EMPTY
+# if HAVE_DECL_SCTP_EMPTY
case SCTP_EMPTY:
i = LOAD_ATOM (spec, i, am_empty);
break;
@@ -6932,14 +7027,16 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen,
case SCTP_CLOSED:
i = LOAD_ATOM (spec, i, am_closed);
break;
- /* The following states are not supported by Linux Kernel SCTP yet:
+# if HAVE_DECL_SCTP_BOUND
case SCTP_BOUND:
i = LOAD_ATOM (spec, i, am_bound);
break;
+# endif
+# if HAVE_DECL_SCTP_LISTEN
case SCTP_LISTEN:
i = LOAD_ATOM (spec, i, am_listen);
break;
- */
+# endif
case SCTP_COOKIE_WAIT:
i = LOAD_ATOM (spec, i, am_cookie_wait);
break;
@@ -7010,7 +7107,7 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen,
default:
RETURN_ERROR(spec, -EINVAL); /* No more valid options */
}
- /* If we get here one result has been succesfully loaded */
+ /* If we get here one result has been successfully loaded */
length ++;
}
if (buflen != 0) RETURN_ERROR(spec, -EINVAL); /* Optparam mismatch */
@@ -7027,11 +7124,10 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen,
i = LOAD_TUPLE(spec, i, 3);
/* Now, convert "spec" into the returnable term: */
- /* desc->caller = 0; What does it mean? */
- driver_output_term(desc->port, spec, i);
+ driver_send_term(desc->port, driver_caller(desc->port), spec, i);
FREE(spec);
- (*dest)[0] = INET_REP_SCTP;
+ (*dest)[0] = INET_REP;
return 1; /* Response length */
# undef PLACE_FOR
# undef RETURN_ERROR
@@ -7806,22 +7902,22 @@ static tcp_descriptor* tcp_inet_copy(tcp_descriptor* desc,SOCKET s,
static void tcp_close_check(tcp_descriptor* desc)
{
/* XXX:PaN - multiple clients to handle! */
- if (desc->inet.state == TCP_STATE_ACCEPTING) {
+ if (desc->inet.state == INET_STATE_ACCEPTING) {
inet_async_op *this_op = desc->inet.opt;
sock_select(INETP(desc), FD_ACCEPT, 0);
- desc->inet.state = TCP_STATE_LISTEN;
+ desc->inet.state = INET_STATE_LISTENING;
if (this_op != NULL) {
driver_demonitor_process(desc->inet.port, &(this_op->monitor));
}
async_error_am(INETP(desc), am_closed);
}
- else if (desc->inet.state == TCP_STATE_MULTI_ACCEPTING) {
+ else if (desc->inet.state == INET_STATE_MULTI_ACCEPTING) {
int id,req;
ErlDrvTermData caller;
ErlDrvMonitor monitor;
sock_select(INETP(desc), FD_ACCEPT, 0);
- desc->inet.state = TCP_STATE_LISTEN;
+ desc->inet.state = INET_STATE_LISTENING;
while (deq_multi_op(desc,&id,&req,&caller,NULL,&monitor) == 0) {
driver_demonitor_process(desc->inet.port, &monitor);
send_async_error(desc->inet.port, desc->inet.dport, id, caller, am_closed);
@@ -7829,10 +7925,10 @@ static void tcp_close_check(tcp_descriptor* desc)
clean_multi_timers(&(desc->mtd), desc->inet.port);
}
- else if (desc->inet.state == TCP_STATE_CONNECTING) {
+ else if (desc->inet.state == INET_STATE_CONNECTING) {
async_error_am(INETP(desc), am_closed);
}
- else if (desc->inet.state == TCP_STATE_CONNECTED) {
+ else if (desc->inet.state == INET_STATE_CONNECTED) {
async_error_am_all(INETP(desc), am_closed);
}
}
@@ -7864,40 +7960,62 @@ static int tcp_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
{
tcp_descriptor* desc = (tcp_descriptor*)e;
switch(cmd) {
- case INET_REQ_OPEN: /* open socket and return internal index */
+ case INET_REQ_OPEN: { /* open socket and return internal index */
+ int domain;
DEBUGF(("tcp_inet_ctl(%ld): OPEN\r\n", (long)desc->inet.port));
- if ((len == 1) && (buf[0] == INET_AF_INET))
- return
- inet_ctl_open(INETP(desc), AF_INET, SOCK_STREAM, rbuf, rsize);
+ if (len != 2) return ctl_error(EINVAL, rbuf, rsize);
+ switch(buf[0]) {
+ case INET_AF_INET:
+ domain = AF_INET;
+ break;
#if defined(HAVE_IN6) && defined(AF_INET6)
- else if ((len == 1) && (buf[0] == INET_AF_INET6))
- return
- inet_ctl_open(INETP(desc), AF_INET6, SOCK_STREAM, rbuf, rsize);
+ case INET_AF_INET6:
+ domain = AF_INET6;
+ break;
#else
- else if ((len == 1) && (buf[0] == INET_AF_INET6))
- return ctl_xerror("eafnosupport",rbuf,rsize);
+ case INET_AF_INET6:
+ return ctl_xerror("eafnosupport", rbuf, rsize);
+ break;
#endif
- else
+ default:
return ctl_error(EINVAL, rbuf, rsize);
+ }
+ if (buf[1] != INET_TYPE_STREAM) return ctl_error(EINVAL, rbuf, rsize);
+ return inet_ctl_open(INETP(desc), domain, SOCK_STREAM, rbuf, rsize);
+ break;
+ }
- case INET_REQ_FDOPEN: /* pass in an open socket */
- DEBUGF(("tcp_inet_ctl(%ld): FDOPEN\r\n", (long)desc->inet.port));
- if ((len == 5) && (buf[0] == INET_AF_INET))
- return inet_ctl_fdopen(INETP(desc), AF_INET, SOCK_STREAM,
- (SOCKET) get_int32(buf+1), rbuf, rsize);
+ case INET_REQ_FDOPEN: { /* pass in an open socket */
+ int domain;
+ DEBUGF(("tcp_inet_ctl(%ld): FDOPEN\r\n", (long)desc->inet.port));
+ if (len != 6) return ctl_error(EINVAL, rbuf, rsize);
+ switch(buf[0]) {
+ case INET_AF_INET:
+ domain = AF_INET;
+ break;
#if defined(HAVE_IN6) && defined(AF_INET6)
- else if ((len == 5) && (buf[0] == INET_AF_INET6))
- return inet_ctl_fdopen(INETP(desc), AF_INET6, SOCK_STREAM,
- (SOCKET) get_int32(buf+1), rbuf, rsize);
+ case INET_AF_INET6:
+ domain = AF_INET6;
+ break;
+#else
+ case INET_AF_INET6:
+ return ctl_xerror("eafnosupport", rbuf, rsize);
+ break;
#endif
- else
+ default:
return ctl_error(EINVAL, rbuf, rsize);
+ }
+ if (buf[1] != INET_TYPE_STREAM) return ctl_error(EINVAL, rbuf, rsize);
+ return inet_ctl_fdopen(INETP(desc), domain, SOCK_STREAM,
+ (SOCKET) get_int32(buf+2), rbuf, rsize);
+ break;
+ }
- case TCP_REQ_LISTEN: { /* argument backlog */
+ case INET_REQ_LISTEN: { /* argument backlog */
int backlog;
DEBUGF(("tcp_inet_ctl(%ld): LISTEN\r\n", (long)desc->inet.port));
- if (desc->inet.state == TCP_STATE_CLOSED)
+ if (desc->inet.state == INET_STATE_CLOSED)
return ctl_xerror(EXBADPORT, rbuf, rsize);
if (!IS_OPEN(INETP(desc)))
return ctl_xerror(EXBADPORT, rbuf, rsize);
@@ -7908,7 +8026,7 @@ static int tcp_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
backlog = get_int16(buf);
if (IS_SOCKET_ERROR(sock_listen(desc->inet.s, backlog)))
return ctl_error(sock_errno(), rbuf, rsize);
- desc->inet.state = TCP_STATE_LISTEN;
+ desc->inet.state = INET_STATE_LISTENING;
return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize);
}
@@ -7944,13 +8062,13 @@ static int tcp_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
((sock_errno() == ERRNO_BLOCK) || /* Winsock2 */
(sock_errno() == EINPROGRESS))) { /* Unix & OSE!! */
sock_select(INETP(desc), FD_CONNECT, 1);
- desc->inet.state = TCP_STATE_CONNECTING;
+ desc->inet.state = INET_STATE_CONNECTING;
if (timeout != INET_INFINITY)
driver_set_timer(desc->inet.port, timeout);
enq_async(INETP(desc), tbuf, INET_REQ_CONNECT);
}
else if (code == 0) { /* ok we are connected */
- desc->inet.state = TCP_STATE_CONNECTED;
+ desc->inet.state = INET_STATE_CONNECTED;
if (desc->inet.active)
sock_select(INETP(desc), (FD_READ|FD_CLOSE), 1);
enq_async(INETP(desc), tbuf, INET_REQ_CONNECT);
@@ -7962,7 +8080,7 @@ static int tcp_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
return ctl_reply(INET_REP_OK, tbuf, 2, rbuf, rsize);
}
- case TCP_REQ_ACCEPT: { /* do async accept */
+ case INET_REQ_ACCEPT: { /* do async accept */
char tbuf[2];
unsigned timeout;
inet_address remote;
@@ -7972,14 +8090,14 @@ static int tcp_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
DEBUGF(("tcp_inet_ctl(%ld): ACCEPT\r\n", (long)desc->inet.port));
/* INPUT: Timeout(4) */
- if ((desc->inet.state != TCP_STATE_LISTEN && desc->inet.state != TCP_STATE_ACCEPTING &&
- desc->inet.state != TCP_STATE_MULTI_ACCEPTING) || len != 4) {
+ if ((desc->inet.state != INET_STATE_LISTENING && desc->inet.state != INET_STATE_ACCEPTING &&
+ desc->inet.state != INET_STATE_MULTI_ACCEPTING) || len != 4) {
return ctl_error(EINVAL, rbuf, rsize);
}
timeout = get_int32(buf);
- if (desc->inet.state == TCP_STATE_ACCEPTING) {
+ if (desc->inet.state == INET_STATE_ACCEPTING) {
unsigned long time_left = 0;
int oid = 0;
ErlDrvTermData ocaller = ERL_DRV_NIL;
@@ -8008,10 +8126,10 @@ static int tcp_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
mtd = add_multi_timer(&(desc->mtd), desc->inet.port, caller,
timeout, &tcp_inet_multi_timeout);
}
- enq_multi_op(desc, tbuf, TCP_REQ_ACCEPT, caller, mtd, &monitor);
- desc->inet.state = TCP_STATE_MULTI_ACCEPTING;
+ enq_multi_op(desc, tbuf, INET_REQ_ACCEPT, caller, mtd, &monitor);
+ desc->inet.state = INET_STATE_MULTI_ACCEPTING;
return ctl_reply(INET_REP_OK, tbuf, 2, rbuf, rsize);
- } else if (desc->inet.state == TCP_STATE_MULTI_ACCEPTING) {
+ } else if (desc->inet.state == INET_STATE_MULTI_ACCEPTING) {
ErlDrvTermData caller = driver_caller(desc->inet.port);
MultiTimerData *mtd = NULL;
ErlDrvMonitor monitor;
@@ -8023,7 +8141,7 @@ static int tcp_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
mtd = add_multi_timer(&(desc->mtd), desc->inet.port, caller,
timeout, &tcp_inet_multi_timeout);
}
- enq_multi_op(desc, tbuf, TCP_REQ_ACCEPT, caller, mtd, &monitor);
+ enq_multi_op(desc, tbuf, INET_REQ_ACCEPT, caller, mtd, &monitor);
return ctl_reply(INET_REP_OK, tbuf, 2, rbuf, rsize);
} else {
n = sizeof(desc->inet.remote);
@@ -8035,8 +8153,8 @@ static int tcp_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
&monitor) != 0) {
return ctl_xerror("noproc", rbuf, rsize);
}
- enq_async_w_tmo(INETP(desc), tbuf, TCP_REQ_ACCEPT, timeout, &monitor);
- desc->inet.state = TCP_STATE_ACCEPTING;
+ enq_async_w_tmo(INETP(desc), tbuf, INET_REQ_ACCEPT, timeout, &monitor);
+ desc->inet.state = INET_STATE_ACCEPTING;
sock_select(INETP(desc),FD_ACCEPT,1);
if (timeout != INET_INFINITY) {
driver_set_timer(desc->inet.port, timeout);
@@ -8063,8 +8181,8 @@ static int tcp_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
driver_select(accept_desc->inet.port, accept_desc->inet.event,
ERL_DRV_READ, 1);
#endif
- accept_desc->inet.state = TCP_STATE_CONNECTED;
- enq_async(INETP(desc), tbuf, TCP_REQ_ACCEPT);
+ accept_desc->inet.state = INET_STATE_CONNECTED;
+ enq_async(INETP(desc), tbuf, INET_REQ_ACCEPT);
async_ok_port(INETP(desc), accept_desc->inet.dport);
}
return ctl_reply(INET_REP_OK, tbuf, 2, rbuf, rsize);
@@ -8170,7 +8288,7 @@ static void tcp_inet_timeout(ErlDrvData e)
(long)desc->inet.port, desc->inet.s));
if ((state & INET_F_MULTI_CLIENT)) { /* Multi-client always means multi-timers */
fire_multi_timers(&(desc->mtd), desc->inet.port, e);
- } else if ((state & TCP_STATE_CONNECTED) == TCP_STATE_CONNECTED) {
+ } else if ((state & INET_STATE_CONNECTED) == INET_STATE_CONNECTED) {
if (desc->busy_on_send) {
ASSERT(IS_BUSY(INETP(desc)));
desc->inet.caller = desc->inet.busy_caller;
@@ -8190,20 +8308,20 @@ static void tcp_inet_timeout(ErlDrvData e)
async_error_am(INETP(desc), am_timeout);
}
}
- else if ((state & TCP_STATE_CONNECTING) == TCP_STATE_CONNECTING) {
+ else if ((state & INET_STATE_CONNECTING) == INET_STATE_CONNECTING) {
/* assume connect timeout */
/* close the socket since it's not usable (see man pages) */
erl_inet_close(INETP(desc));
async_error_am(INETP(desc), am_timeout);
}
- else if ((state & TCP_STATE_ACCEPTING) == TCP_STATE_ACCEPTING) {
+ else if ((state & INET_STATE_ACCEPTING) == INET_STATE_ACCEPTING) {
inet_async_op *this_op = desc->inet.opt;
/* timer is set on accept */
sock_select(INETP(desc), FD_ACCEPT, 0);
if (this_op != NULL) {
driver_demonitor_process(desc->inet.port, &(this_op->monitor));
}
- desc->inet.state = TCP_STATE_LISTEN;
+ desc->inet.state = INET_STATE_LISTENING;
async_error_am(INETP(desc), am_timeout);
}
DEBUGF(("tcp_inet_timeout(%ld) }\r\n", (long)desc->inet.port));
@@ -8221,7 +8339,7 @@ static void tcp_inet_multi_timeout(ErlDrvData e, ErlDrvTermData caller)
driver_demonitor_process(desc->inet.port, &monitor);
if (desc->multi_first == NULL) {
sock_select(INETP(desc),FD_ACCEPT,0);
- desc->inet.state = TCP_STATE_LISTEN; /* restore state */
+ desc->inet.state = INET_STATE_LISTENING; /* restore state */
}
send_async_error(desc->inet.port, desc->inet.dport, id, caller, am_timeout);
}
@@ -8287,7 +8405,7 @@ static void tcp_inet_process_exit(ErlDrvData e, ErlDrvMonitor *monitorp)
ErlDrvTermData who = driver_get_monitored_process(desc->inet.port,monitorp);
int state = desc->inet.state;
- if ((state & TCP_STATE_MULTI_ACCEPTING) == TCP_STATE_MULTI_ACCEPTING) {
+ if ((state & INET_STATE_MULTI_ACCEPTING) == INET_STATE_MULTI_ACCEPTING) {
int id,req;
MultiTimerData *timeout;
if (remove_multi_op(desc, &id, &req, who, &timeout, NULL) != 0) {
@@ -8298,15 +8416,15 @@ static void tcp_inet_process_exit(ErlDrvData e, ErlDrvMonitor *monitorp)
}
if (desc->multi_first == NULL) {
sock_select(INETP(desc),FD_ACCEPT,0);
- desc->inet.state = TCP_STATE_LISTEN; /* restore state */
+ desc->inet.state = INET_STATE_LISTENING; /* restore state */
}
- } else if ((state & TCP_STATE_ACCEPTING) == TCP_STATE_ACCEPTING) {
+ } else if ((state & INET_STATE_ACCEPTING) == INET_STATE_ACCEPTING) {
int did,drid;
ErlDrvTermData dcaller;
deq_async(INETP(desc), &did, &dcaller, &drid);
driver_cancel_timer(desc->inet.port);
sock_select(INETP(desc),FD_ACCEPT,0);
- desc->inet.state = TCP_STATE_LISTEN; /* restore state */
+ desc->inet.state = INET_STATE_LISTENING; /* restore state */
}
}
@@ -8496,32 +8614,29 @@ static int tcp_deliver(tcp_descriptor* desc, int len)
}
while (len > 0) {
- int code = 0;
+ int code;
inet_input_count(INETP(desc), len);
/* deliver binary? */
if (len*4 >= desc->i_buf->orig_size*3) { /* >=75% */
+ code = tcp_reply_binary_data(desc, desc->i_buf,
+ (desc->i_ptr_start -
+ desc->i_buf->orig_bytes),
+ len);
+ if (code < 0)
+ return code;
+
/* something after? */
if (desc->i_ptr_start + len == desc->i_ptr) { /* no */
- code = tcp_reply_binary_data(desc, desc->i_buf,
- (desc->i_ptr_start -
- desc->i_buf->orig_bytes),
- len);
tcp_clear_input(desc);
}
else { /* move trail to beginning of a new buffer */
- ErlDrvBinary* bin;
+ ErlDrvBinary* bin = alloc_buffer(desc->i_bufsz);
char* ptr_end = desc->i_ptr_start + len;
int sz = desc->i_ptr - ptr_end;
- bin = alloc_buffer(desc->i_bufsz);
memcpy(bin->orig_bytes, ptr_end, sz);
-
- code = tcp_reply_binary_data(desc, desc->i_buf,
- (desc->i_ptr_start-
- desc->i_buf->orig_bytes),
- len);
free_buffer(desc->i_buf);
desc->i_buf = bin;
desc->i_ptr_start = desc->i_buf->orig_bytes;
@@ -8533,17 +8648,15 @@ static int tcp_deliver(tcp_descriptor* desc, int len)
code = tcp_reply_data(desc, desc->i_ptr_start, len);
/* XXX The buffer gets thrown away on error (code < 0) */
/* Windows needs workaround for this in tcp_inet_event... */
+ if (code < 0)
+ return code;
desc->i_ptr_start += len;
if (desc->i_ptr_start == desc->i_ptr)
tcp_clear_input(desc);
else
desc->i_remain = 0;
-
}
- if (code < 0)
- return code;
-
count++;
len = 0;
@@ -8848,8 +8961,8 @@ static void tcp_inet_event(ErlDrvData e, ErlDrvEvent event)
/* socket has input:
-** 1. TCP_STATE_ACCEPTING => non block accept ?
-** 2. TCP_STATE_CONNECTED => read input
+** 1. INET_STATE_ACCEPTING => non block accept ?
+** 2. INET_STATE_CONNECTED => read input
*/
static int tcp_inet_input(tcp_descriptor* desc, HANDLE event)
{
@@ -8858,7 +8971,7 @@ static int tcp_inet_input(tcp_descriptor* desc, HANDLE event)
long port = (long) desc->inet.port; /* Used after driver_exit() */
#endif
DEBUGF(("tcp_inet_input(%ld) {s=%d\r\n", port, desc->inet.s));
- if (desc->inet.state == TCP_STATE_ACCEPTING) {
+ if (desc->inet.state == INET_STATE_ACCEPTING) {
SOCKET s;
unsigned int len;
inet_address remote;
@@ -8873,7 +8986,7 @@ static int tcp_inet_input(tcp_descriptor* desc, HANDLE event)
}
sock_select(INETP(desc),FD_ACCEPT,0);
- desc->inet.state = TCP_STATE_LISTEN; /* restore state */
+ desc->inet.state = INET_STATE_LISTENING; /* restore state */
if (this_op != NULL) {
driver_demonitor_process(desc->inet.port, &(this_op->monitor));
@@ -8913,11 +9026,11 @@ static int tcp_inet_input(tcp_descriptor* desc, HANDLE event)
driver_select(accept_desc->inet.port, accept_desc->inet.event,
ERL_DRV_READ, 1);
#endif
- accept_desc->inet.state = TCP_STATE_CONNECTED;
+ accept_desc->inet.state = INET_STATE_CONNECTED;
ret = async_ok_port(INETP(desc), accept_desc->inet.dport);
goto done;
}
- } else if (desc->inet.state == TCP_STATE_MULTI_ACCEPTING) {
+ } else if (desc->inet.state == INET_STATE_MULTI_ACCEPTING) {
SOCKET s;
unsigned int len;
inet_address remote;
@@ -8929,7 +9042,7 @@ static int tcp_inet_input(tcp_descriptor* desc, HANDLE event)
int times = 0;
#endif
- while (desc->inet.state == TCP_STATE_MULTI_ACCEPTING) {
+ while (desc->inet.state == INET_STATE_MULTI_ACCEPTING) {
len = sizeof(desc->inet.remote);
s = sock_accept(desc->inet.s, (struct sockaddr*) &remote, &len);
@@ -8949,7 +9062,7 @@ static int tcp_inet_input(tcp_descriptor* desc, HANDLE event)
if (desc->multi_first == NULL) {
sock_select(INETP(desc),FD_ACCEPT,0);
- desc->inet.state = TCP_STATE_LISTEN; /* restore state */
+ desc->inet.state = INET_STATE_LISTENING; /* restore state */
}
if (timeout != NULL) {
@@ -8980,7 +9093,7 @@ static int tcp_inet_input(tcp_descriptor* desc, HANDLE event)
driver_select(accept_desc->inet.port, accept_desc->inet.event,
ERL_DRV_READ, 1);
#endif
- accept_desc->inet.state = TCP_STATE_CONNECTED;
+ accept_desc->inet.state = INET_STATE_CONNECTED;
ret = send_async_ok_port(desc->inet.port, desc->inet.dport,
id, caller, accept_desc->inet.dport);
}
@@ -9258,8 +9371,8 @@ static void tcp_inet_drv_input(ErlDrvData data, ErlDrvEvent event)
}
/* socket ready for ouput:
-** 1. TCP_STATE_CONNECTING => non block connect ?
-** 2. TCP_STATE_CONNECTED => write output
+** 1. INET_STATE_CONNECTING => non block connect ?
+** 2. INET_STATE_CONNECTED => write output
*/
static int tcp_inet_output(tcp_descriptor* desc, HANDLE event)
{
@@ -9268,7 +9381,7 @@ static int tcp_inet_output(tcp_descriptor* desc, HANDLE event)
DEBUGF(("tcp_inet_output(%ld) {s=%d\r\n",
(long)desc->inet.port, desc->inet.s));
- if (desc->inet.state == TCP_STATE_CONNECTING) {
+ if (desc->inet.state == INET_STATE_CONNECTING) {
sock_select(INETP(desc),FD_CONNECT,0);
driver_cancel_timer(ix); /* posssibly cancel a timer */
@@ -9288,7 +9401,7 @@ static int tcp_inet_output(tcp_descriptor* desc, HANDLE event)
(struct sockaddr*) &desc->inet.remote, &sz);
if (IS_SOCKET_ERROR(code)) {
- desc->inet.state = TCP_STATE_BOUND; /* restore state */
+ desc->inet.state = INET_STATE_BOUND; /* restore state */
ret = async_error(INETP(desc), sock_errno());
goto done;
}
@@ -9301,15 +9414,15 @@ static int tcp_inet_output(tcp_descriptor* desc, HANDLE event)
(void *)&error, &sz);
if ((code < 0) || error) {
- desc->inet.state = TCP_STATE_BOUND; /* restore state */
+ desc->inet.state = INET_STATE_BOUND; /* restore state */
ret = async_error(INETP(desc), error);
goto done;
}
}
-#endif /* SOCKOPT_CONNECT_STAT */
+#endif /* SO_ERROR */
#endif /* !__WIN32__ */
- desc->inet.state = TCP_STATE_CONNECTED;
+ desc->inet.state = INET_STATE_CONNECTED;
if (desc->inet.active)
sock_select(INETP(desc),(FD_READ|FD_CLOSE),1);
async_ok(INETP(desc));
@@ -9409,6 +9522,59 @@ static int should_use_so_bsdcompat(void)
#endif /* __linux__ */
#endif /* HAVE_SO_BSDCOMPAT */
+
+
+#ifdef HAVE_SCTP
+/* Copy a descriptor, by creating a new port with same settings
+ * as the descriptor desc.
+ * return NULL on error (ENFILE no ports avail)
+ */
+static udp_descriptor* sctp_inet_copy(udp_descriptor* desc, SOCKET s, int* err)
+{
+ ErlDrvPort port = desc->inet.port;
+ udp_descriptor* copy_desc;
+
+ copy_desc = (udp_descriptor*) sctp_inet_start(port, NULL);
+
+ /* Setup event if needed */
+ if ((copy_desc->inet.s = s) != INVALID_SOCKET) {
+ if ((copy_desc->inet.event = sock_create_event(INETP(copy_desc))) ==
+ INVALID_EVENT) {
+ *err = sock_errno();
+ FREE(copy_desc);
+ return NULL;
+ }
+ }
+
+ /* Some flags must be inherited at this point */
+ copy_desc->inet.mode = desc->inet.mode;
+ copy_desc->inet.exitf = desc->inet.exitf;
+ copy_desc->inet.bit8f = desc->inet.bit8f;
+ copy_desc->inet.deliver = desc->inet.deliver;
+ copy_desc->inet.htype = desc->inet.htype;
+ copy_desc->inet.psize = desc->inet.psize;
+ copy_desc->inet.stype = desc->inet.stype;
+ copy_desc->inet.sfamily = desc->inet.sfamily;
+ copy_desc->inet.hsz = desc->inet.hsz;
+ copy_desc->inet.bufsz = desc->inet.bufsz;
+
+ /* The new port will be linked and connected to the caller */
+ port = driver_create_port(port, desc->inet.caller, "sctp_inet",
+ (ErlDrvData) copy_desc);
+ if ((long)port == -1) {
+ *err = ENFILE;
+ FREE(copy_desc);
+ return NULL;
+ }
+ copy_desc->inet.port = port;
+ copy_desc->inet.dport = driver_mk_port(port);
+ *err = 0;
+ return copy_desc;
+}
+#endif
+
+
+
static int packet_inet_init()
{
return 0;
@@ -9427,6 +9593,9 @@ static ErlDrvData packet_inet_start(ErlDrvPort port, char* args, int protocol)
return ERL_DRV_ERROR_ERRNO;
desc->read_packets = INET_PACKET_POLL;
+ desc->i_bufsz = 0;
+ desc->i_buf = NULL;
+ desc->i_ptr = NULL;
return drvd;
}
@@ -9451,6 +9620,10 @@ static void packet_inet_stop(ErlDrvData e)
*/
udp_descriptor * udesc = (udp_descriptor*) e;
inet_descriptor* descr = INETP(udesc);
+ if (udesc->i_buf != NULL) {
+ release_buffer(udesc->i_buf);
+ udesc->i_buf = NULL;
+ }
ASSERT(NO_SUBSCRIBERS(&(descr->empty_out_q_subs)));
inet_stop(descr);
@@ -9475,21 +9648,31 @@ static int packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
udp_descriptor * udesc = (udp_descriptor *) e;
inet_descriptor* desc = INETP(udesc);
int type = SOCK_DGRAM;
- int af;
-#ifdef HAVE_SCTP
- if (IS_SCTP(desc)) type = SOCK_SEQPACKET;
-#endif
+ int af = AF_INET;
switch(cmd) {
case INET_REQ_OPEN: /* open socket and return internal index */
DEBUGF(("packet_inet_ctl(%ld): OPEN\r\n", (long)desc->port));
- if (len != 1) {
+ if (len != 2) {
return ctl_error(EINVAL, rbuf, rsize);
}
switch (buf[0]) {
case INET_AF_INET: af = AF_INET; break;
#if defined(HAVE_IN6) && defined(AF_INET6)
- case INET_AF_INET6: af = AF_INET6; break;
+ case INET_AF_INET6: af = AF_INET6; break;
+#else
+ case INET_AF_INET6:
+ return ctl_xerror("eafnosupport", rbuf, rsize);
+ break;
+#endif
+ default:
+ return ctl_error(EINVAL, rbuf, rsize);
+ }
+ switch (buf[1]) {
+ case INET_TYPE_STREAM: type = SOCK_STREAM; break;
+ case INET_TYPE_DGRAM: type = SOCK_DGRAM; break;
+#ifdef HAVE_SCTP
+ case INET_TYPE_SEQPACKET: type = SOCK_SEQPACKET; break;
#endif
default:
return ctl_error(EINVAL, rbuf, rsize);
@@ -9516,18 +9699,35 @@ static int packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
return replen;
- case INET_REQ_FDOPEN: /* pass in an open (and bound) socket */
+ case INET_REQ_FDOPEN: { /* pass in an open (and bound) socket */
+ SOCKET s;
DEBUGF(("packet inet_ctl(%ld): FDOPEN\r\n", (long)desc->port));
- if ((len == 5) && (buf[0] == INET_AF_INET))
- replen = inet_ctl_fdopen(desc, AF_INET, SOCK_DGRAM,
- (SOCKET)get_int32(buf+1),rbuf,rsize);
+ if (len != 6) {
+ return ctl_error(EINVAL, rbuf, rsize);
+ }
+ switch (buf[0]) {
+ case INET_AF_INET: af = AF_INET; break;
#if defined(HAVE_IN6) && defined(AF_INET6)
- else if ((len == 5) && (buf[0] == INET_AF_INET6))
- replen = inet_ctl_fdopen(desc, AF_INET6, SOCK_DGRAM,
- (SOCKET)get_int32(buf+1),rbuf,rsize);
+ case INET_AF_INET6: af = AF_INET6; break;
+#else
+ case INET_AF_INET6:
+ return ctl_xerror("eafnosupport", rbuf, rsize);
+ break;
#endif
- else
+ default:
return ctl_error(EINVAL, rbuf, rsize);
+ }
+ switch (buf[1]) {
+ case INET_TYPE_STREAM: type = SOCK_STREAM; break;
+ case INET_TYPE_DGRAM: type = SOCK_DGRAM; break;
+#ifdef HAVE_SCTP
+ case INET_TYPE_SEQPACKET: type = SOCK_SEQPACKET; break;
+#endif
+ default:
+ return ctl_error(EINVAL, rbuf, rsize);
+ }
+ s = (SOCKET)get_int32(buf+2);
+ replen = inet_ctl_fdopen(desc, af, type, s, rbuf, rsize);
if ((*rbuf)[0] != INET_REP_ERROR) {
if (desc->active)
@@ -9547,6 +9747,7 @@ static int packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
#endif
}
return replen;
+ }
case INET_REQ_CLOSE:
@@ -9599,14 +9800,14 @@ static int packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
if (IS_SOCKET_ERROR(code) && (sock_errno() == EINPROGRESS)) {
/* XXX: Unix only -- WinSock would have a different cond! */
- desc->state = SCTP_STATE_CONNECTING;
+ desc->state = INET_STATE_CONNECTING;
if (timeout != INET_INFINITY)
driver_set_timer(desc->port, timeout);
enq_async(desc, tbuf, INET_REQ_CONNECT);
}
else if (code == 0) { /* OK we are connected */
sock_select(desc, FD_CONNECT, 0);
- desc->state = PACKET_STATE_CONNECTED;
+ desc->state = INET_STATE_CONNECTED;
enq_async(desc, tbuf, INET_REQ_CONNECT);
async_ok(desc);
}
@@ -9652,11 +9853,11 @@ static int packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
}
#ifdef HAVE_SCTP
- case SCTP_REQ_LISTEN:
+ case INET_REQ_LISTEN:
{ /* LISTEN is only for SCTP sockets, not UDP. This code is borrowed
from the TCP section. Returns: {ok,[]} on success.
*/
- int flag;
+ int backlog;
DEBUGF(("packet_inet_ctl(%ld): LISTEN\r\n", (long)desc->port));
if (!IS_SCTP(desc))
@@ -9666,15 +9867,14 @@ static int packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
if (!IS_BOUND(desc))
return ctl_xerror(EXBADSEQ, rbuf, rsize);
- /* The arg is a binary value: 1:enable, 0:disable */
- if (len != 1)
+ if (len != 2)
return ctl_error(EINVAL, rbuf, rsize);
- flag = get_int8(buf);
+ backlog = get_int16(buf);
- if (IS_SOCKET_ERROR(sock_listen(desc->s, flag)))
+ if (IS_SOCKET_ERROR(sock_listen(desc->s, backlog)))
return ctl_error(sock_errno(), rbuf, rsize);
- desc->state = SCTP_STATE_LISTEN; /* XXX: not used? */
+ desc->state = INET_STATE_LISTENING; /* XXX: not used? */
return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize);
}
@@ -9720,6 +9920,46 @@ static int packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize);
}
+
+ case SCTP_REQ_PEELOFF:
+ {
+ Uint32 assoc_id;
+ udp_descriptor* new_udesc;
+ int err;
+ SOCKET new_socket;
+
+ DEBUGF(("packet_inet_ctl(%ld): PEELOFF\r\n", (long)desc->port));
+ if (!IS_SCTP(desc))
+ return ctl_xerror(EXBADPORT, rbuf, rsize);
+ if (!IS_OPEN(desc))
+ return ctl_xerror(EXBADPORT, rbuf, rsize);
+ if (!IS_BOUND(desc))
+ return ctl_xerror(EXBADSEQ, rbuf, rsize);
+ if (! p_sctp_peeloff)
+ return ctl_error(ENOTSUP, rbuf, rsize);
+
+ if (len != 4)
+ return ctl_error(EINVAL, rbuf, rsize);
+ assoc_id = get_int32(buf);
+
+ new_socket = p_sctp_peeloff(desc->s, assoc_id);
+ if (IS_SOCKET_ERROR(new_socket)) {
+ return ctl_error(sock_errno(), rbuf, rsize);
+ }
+
+ desc->caller = driver_caller(desc->port);
+ if ((new_udesc = sctp_inet_copy(udesc, new_socket, &err)) == NULL) {
+ sock_close(new_socket);
+ desc->caller = 0;
+ return ctl_error(err, rbuf, rsize);
+ }
+ new_udesc->inet.state = INET_STATE_CONNECTED;
+ new_udesc->inet.stype = SOCK_STREAM;
+
+ inet_reply_ok_port(desc, new_udesc->inet.dport);
+ (*rbuf)[0] = INET_REP;
+ return 1;
+ }
#endif /* HAVE_SCTP */
case PACKET_REQ_RECV:
@@ -9739,7 +9979,7 @@ static int packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
if (desc->active || (len != 8))
return ctl_error(EINVAL, rbuf, rsize);
timeout = get_int32(buf);
- /* The 2nd arg, Length(4), is ignored for both UDP ans SCTP protocols,
+ /* The 2nd arg, Length(4), is ignored for both UDP and SCTP protocols,
since they are msg-oriented. */
if (enq_async(desc, tbuf, PACKET_REQ_RECV) < 0)
@@ -9918,12 +10158,8 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event)
{
inet_descriptor* desc = INETP(udesc);
int n;
- unsigned int len;
inet_address other;
char abuf[sizeof(inet_address)]; /* buffer address; enough??? */
- int sz;
- char* ptr;
- ErlDrvBinary* buf; /* binary */
int packet_count = udesc->read_packets;
int count = 0; /* number of packets delivered to owner */
#ifdef HAVE_SCTP
@@ -9934,23 +10170,39 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event)
#endif
while(packet_count--) {
- len = sizeof(other);
- sz = desc->bufsz;
- /* Allocate space for message and address. NB: "bufsz" is in "desc",
- but the "buf" itself is allocated separately:
- */
- if ((buf = alloc_buffer(sz+len)) == NULL)
- return packet_error(udesc, ENOMEM);
- ptr = buf->orig_bytes + len; /* pointer to message part */
+ unsigned int len = sizeof(other);
+
+ /* udesc->i_buf is only kept between SCTP fragments */
+ if (udesc->i_buf == NULL) {
+ udesc->i_bufsz = desc->bufsz + len;
+ if ((udesc->i_buf = alloc_buffer(udesc->i_bufsz)) == NULL)
+ return packet_error(udesc, ENOMEM);
+ /* pointer to message start */
+ udesc->i_ptr = udesc->i_buf->orig_bytes + len;
+ } else {
+ ErlDrvBinary* tmp;
+ int bufsz;
+ bufsz = desc->bufsz + (udesc->i_ptr - udesc->i_buf->orig_bytes);
+ if ((tmp = realloc_buffer(udesc->i_buf, bufsz)) == NULL) {
+ release_buffer(udesc->i_buf);
+ udesc->i_buf = NULL;
+ return packet_error(udesc, ENOMEM);
+ } else {
+ udesc->i_ptr =
+ tmp->orig_bytes + (udesc->i_ptr - udesc->i_buf->orig_bytes);
+ udesc->i_buf = tmp;
+ udesc->i_bufsz = bufsz;
+ }
+ }
/* Note: On Windows NT, recvfrom() fails if the socket is connected. */
#ifdef HAVE_SCTP
/* For SCTP we must use recvmsg() */
if (IS_SCTP(desc)) {
- iov->iov_base = ptr; /* Data will come here */
- iov->iov_len = sz; /* Remaining buffer space */
+ iov->iov_base = udesc->i_ptr; /* Data will come here */
+ iov->iov_len = desc->bufsz; /* Remaining buffer space */
- mhdr.msg_name = &other; /* Peer addr comes into "other" */
+ mhdr.msg_name = &other; /* Peer addr comes into "other" */
mhdr.msg_namelen = len;
mhdr.msg_iov = iov;
mhdr.msg_iovlen = 1;
@@ -9960,42 +10212,28 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event)
/* Do the actual SCTP receive: */
n = sock_recvmsg(desc->s, &mhdr, 0);
+ len = mhdr.msg_namelen;
goto check_result;
}
#endif
/* Use recv() instead on connected sockets. */
if ((desc->state & INET_F_ACTIVE)) {
- n = sock_recv(desc->s, ptr, sz, 0);
+ n = sock_recv(desc->s, udesc->i_ptr, desc->bufsz, 0);
other = desc->remote;
+ goto check_result;
}
- else
- n = sock_recvfrom(desc->s, ptr, sz, 0, &other.sa, &len);
-
-#ifdef HAVE_SCTP
+ n = sock_recvfrom(desc->s, udesc->i_ptr, desc->bufsz,
+ 0, &other.sa, &len);
check_result:
-#endif
/* Analyse the result: */
- if (IS_SOCKET_ERROR(n)
-#ifdef HAVE_SCTP
- || (short_recv = (IS_SCTP(desc) && !(mhdr.msg_flags & MSG_EOR)))
- /* NB: here we check for EOR not being set -- this is an error as
- well, we don't support partial msgs:
- */
-#endif
- ) {
+ if (IS_SOCKET_ERROR(n)) {
int err = sock_errno();
- release_buffer(buf);
if (err != ERRNO_BLOCK) {
+ /* real error */
+ release_buffer(udesc->i_buf);
+ udesc->i_buf = NULL;
if (!desc->active) {
-#ifdef HAVE_SCTP
- if (short_recv) {
- async_error_am(desc, am_short_recv);
- } else {
- async_error(desc, err);
- }
-#else
async_error(desc, err);
-#endif
driver_cancel_timer(desc->port);
sock_select(desc,FD_READ,0);
}
@@ -10003,46 +10241,69 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event)
/* This is for an active desc only: */
packet_error_message(udesc, err);
}
+ return count;
}
- else if (!desc->active)
+ /* would block error - try again */
+ if (!desc->active
+#ifdef HAVE_SCTP
+ || short_recv
+#endif
+ ) {
sock_select(desc,FD_READ,1);
+ }
return count; /* strange, not ready */
}
- else {
- int offs;
- int nsz;
+
+#ifdef HAVE_SCTP
+ if (IS_SCTP(desc) && (short_recv = !(mhdr.msg_flags & MSG_EOR))) {
+ /* SCTP non-final message fragment */
+ inet_input_count(desc, n);
+ udesc->i_ptr += n;
+ continue; /* wait for more fragments */
+ }
+#endif
+
+ {
+ /* message received */
int code;
- unsigned int alen = len;
void * extra = NULL;
+ char * ptr;
inet_input_count(desc, n);
- inet_get_address(desc->sfamily, abuf, &other, &alen);
- /* Copy formatted address to the buffer allocated; "alen" is the
- actual length which must be <= than the original reserved "len".
+ udesc->i_ptr += n;
+ inet_get_address(desc->sfamily, abuf, &other, &len);
+ /* Copy formatted address to the buffer allocated; "len" is the
+ actual length which must be <= than the original reserved.
This means that the addr + data in the buffer are contiguous,
- but they may start not at the "orig_bytes", but with some "offs"
- from them:
+ but they may start not at the "orig_bytes", instead at "ptr":
*/
- ASSERT (alen <= len);
- sys_memcpy(ptr - alen, abuf, alen);
- ptr -= alen;
- nsz = n + alen; /* nsz = data + address */
- offs = ptr - buf->orig_bytes; /* initial pointer offset */
+ ASSERT (len <= sizeof(other));
+ ptr = udesc->i_buf->orig_bytes + sizeof(other) - len;
+ sys_memcpy(ptr, abuf, len);
/* Check if we need to reallocate binary */
if ((desc->mode == INET_MODE_BINARY) &&
- (desc->hsz < n) && (nsz < BIN_REALLOC_LIMIT(sz))) {
+ (desc->hsz < (udesc->i_ptr - ptr)) &&
+ ((udesc->i_ptr - ptr) + BIN_REALLOC_MARGIN(desc->bufsz) >=
+ udesc->i_bufsz)) {
ErlDrvBinary* tmp;
- if ((tmp = realloc_buffer(buf,nsz+offs)) != NULL)
- buf = tmp;
+ int bufsz;
+ bufsz = udesc->i_ptr - udesc->i_buf->orig_bytes;
+ if ((tmp = realloc_buffer(udesc->i_buf, bufsz)) != NULL) {
+ udesc->i_buf = tmp;
+ udesc->i_bufsz = bufsz;
+ }
}
#ifdef HAVE_SCTP
if (IS_SCTP(desc)) extra = &mhdr;
#endif
/* Actual parsing and return of the data received, occur here: */
- code = packet_reply_binary_data(desc, (unsigned int)alen,
- buf, offs, nsz, extra);
- free_buffer(buf);
+ code = packet_reply_binary_data(desc, len, udesc->i_buf,
+ ptr - udesc->i_buf->orig_bytes,
+ udesc->i_ptr - ptr,
+ extra);
+ free_buffer(udesc->i_buf);
+ udesc->i_buf = NULL;
if (code < 0)
return count;
count++;
@@ -10052,7 +10313,17 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event)
return count; /* passive mode (read one packet only) */
}
}
+ } /* while(packet_count--) { */
+
+ /* we ran out of tries (packet_count) either on an active socket
+ * that got that many messages or an SCTP socket that got that
+ * many message fragments but still not the final
+ */
+#ifdef HAVE_SCTP
+ if (short_recv) {
+ sock_select(desc, FD_READ, 1);
}
+#endif
return count;
}
@@ -10062,7 +10333,7 @@ static void packet_inet_drv_output(ErlDrvData e, ErlDrvEvent event)
}
/* UDP/SCTP socket ready for output:
-** This is a Back-End for Non-Block SCTP Connect (SCTP_STATE_CONNECTING)
+** This is a Back-End for Non-Block SCTP Connect (INET_STATE_CONNECTING)
*/
static int packet_inet_output(udp_descriptor* udesc, HANDLE event)
{
@@ -10073,7 +10344,7 @@ static int packet_inet_output(udp_descriptor* udesc, HANDLE event)
DEBUGF(("packet_inet_output(%ld) {s=%d\r\n",
(long)desc->port, desc->s));
- if (desc->state == SCTP_STATE_CONNECTING) {
+ if (desc->state == INET_STATE_CONNECTING) {
sock_select(desc, FD_CONNECT, 0);
driver_cancel_timer(ix); /* posssibly cancel a timer */
@@ -10093,7 +10364,7 @@ static int packet_inet_output(udp_descriptor* udesc, HANDLE event)
(struct sockaddr*) &desc->remote, &sz);
if (IS_SOCKET_ERROR(code)) {
- desc->state = PACKET_STATE_BOUND; /* restore state */
+ desc->state = INET_STATE_BOUND; /* restore state */
ret = async_error(desc, sock_errno());
goto done;
}
@@ -10106,15 +10377,15 @@ static int packet_inet_output(udp_descriptor* udesc, HANDLE event)
(void *)&error, &sz);
if ((code < 0) || error) {
- desc->state = PACKET_STATE_BOUND; /* restore state */
+ desc->state = INET_STATE_BOUND; /* restore state */
ret = async_error(desc, error);
goto done;
}
}
-#endif /* SOCKOPT_CONNECT_STAT */
+#endif /* SO_ERROR */
#endif /* !__WIN32__ */
- desc->state = PACKET_STATE_CONNECTED;
+ desc->state = INET_STATE_CONNECTED;
async_ok(desc);
}
else {
diff --git a/erts/emulator/drivers/unix/ttsl_drv.c b/erts/emulator/drivers/unix/ttsl_drv.c
index d782b044a9..45d39a559f 100644
--- a/erts/emulator/drivers/unix/ttsl_drv.c
+++ b/erts/emulator/drivers/unix/ttsl_drv.c
@@ -242,7 +242,7 @@ static ErlDrvData ttysl_start(ErlDrvPort port, char* buf)
#ifndef HAVE_TERMCAP
return ERL_DRV_ERROR_GENERAL;
#else
- char *s, *t, c, *l;
+ char *s, *t, *l;
int canon, echo, sig; /* Terminal characteristics */
int flag;
extern int using_oldshell; /* set this to let the rest of erts know */
@@ -262,7 +262,6 @@ static ErlDrvData ttysl_start(ErlDrvPort port, char* buf)
s++;
/* Find end of this argument (start of next) and insert NUL. */
if ((t = strchr(s, ' '))) {
- c = *t;
*t = '\0';
}
if ((flag = ((*s == '+') ? 1 : ((*s == '-') ? -1 : 0)))) {
diff --git a/erts/emulator/drivers/win32/win_efile.c b/erts/emulator/drivers/win32/win_efile.c
index 3d59564f7b..931bb196f1 100755..100644
--- a/erts/emulator/drivers/win32/win_efile.c
+++ b/erts/emulator/drivers/win32/win_efile.c
@@ -127,6 +127,8 @@ static int errno_map(DWORD last_error) {
return EBUSY;
case ERROR_NO_PROC_SLOTS:
return EAGAIN;
+ case ERROR_CANT_RESOLVE_FILENAME:
+ return EMLINK;
case ERROR_ARENA_TRASHED:
case ERROR_INVALID_BLOCK:
case ERROR_BAD_ENVIRONMENT:
@@ -1405,7 +1407,7 @@ efile_readlink(Efile_error* errInfo, char* name, char* buffer, size_t size)
DWORD fileAttributes = GetFileAttributesW(wname);
if ((fileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
BOOLEAN success = 0;
- HANDLE h = CreateFileW(wname, GENERIC_READ, 0,NULL, OPEN_EXISTING, 0, NULL);
+ HANDLE h = CreateFileW(wname, GENERIC_READ, 0,NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
int len;
if(h != INVALID_HANDLE_VALUE) {
success = pGetFinalPathNameByHandle(h, wbuffer, size,0);
@@ -1421,7 +1423,7 @@ efile_readlink(Efile_error* errInfo, char* name, char* buffer, size_t size)
if (*wbuffer == L'\\')
*wbuffer = L'/';
CloseHandle(h);
- }
+ }
FreeLibrary(hModule);
if (success) {
return 1;
diff --git a/erts/emulator/hipe/hipe_abi.txt b/erts/emulator/hipe/hipe_abi.txt
index d0ec162342..9d4726de9d 100644
--- a/erts/emulator/hipe/hipe_abi.txt
+++ b/erts/emulator/hipe/hipe_abi.txt
@@ -62,7 +62,7 @@ exceptional condition, it puts an error code in p->freason
and returns THE_NON_VALUE (zero, except in debug mode).
If p->freason == TRAP, then the BIF redirects its call to some
-other function, given by p->def_arg_reg[].
+other function, given by p->i
The BIF and the new callee may have different arities.
The "hipe_${ARCH}_bifs.m4" macro files take care of these issues
diff --git a/erts/emulator/hipe/hipe_amd64_bifs.m4 b/erts/emulator/hipe/hipe_amd64_bifs.m4
index 0ba763cbea..97a8267647 100644
--- a/erts/emulator/hipe/hipe_amd64_bifs.m4
+++ b/erts/emulator/hipe/hipe_amd64_bifs.m4
@@ -20,24 +20,37 @@ changecom(`/*', `*/')dnl
include(`hipe/hipe_amd64_asm.m4')
+#`include' "config.h"
#`include' "hipe_literals.h"
+
`#if THE_NON_VALUE == 0
#define TEST_GOT_EXN testq %rax, %rax
#else
#define TEST_GOT_EXN cmpq $THE_NON_VALUE, %rax
#endif'
-`#define TEST_GOT_MBUF movq P_MBUF(P), %rdx; testq %rdx, %rdx; jnz 3f; 2:
-#define JOIN3(A,B,C) A##B##C
-#define HANDLE_GOT_MBUF(ARITY) 3: call JOIN3(nbif_,ARITY,_gc_after_bif); jmp 2b'
+define(TEST_GOT_MBUF,`movq P_MBUF(P), %rdx # `TEST_GOT_MBUF'
+ testq %rdx, %rdx
+ jnz 3f
+2:')
+define(HANDLE_GOT_MBUF,`
+3: call nbif_$1_gc_after_bif # `HANDLE_GOT_MBUF'
+ jmp 2b')
+
+`#if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP)
+# define CALL_BIF(F) movq $CSYM(F), P_BIF_CALLEE(P); call CSYM(hipe_debug_bif_wrapper)
+#else
+# define CALL_BIF(F) call CSYM(F)
+#endif'
/*
* standard_bif_interface_1(nbif_name, cbif_name)
* standard_bif_interface_2(nbif_name, cbif_name)
* standard_bif_interface_3(nbif_name, cbif_name)
+ * standard_bif_interface_0(nbif_name, cbif_name)
*
- * Generate native interface for a BIF with 1-3 parameters and
+ * Generate native interface for a BIF with 0-3 parameters and
* standard failure mode.
*/
define(standard_bif_interface_1,
@@ -54,7 +67,11 @@ ASYM($1):
/* make the call on the C stack */
SWITCH_ERLANG_TO_C
- call CSYM($2)
+ pushq %rsi
+ movq %rsp, %rsi /* Eterm* BIF__ARGS */
+ sub $(8), %rsp /* stack frame 16-byte alignment */
+ CALL_BIF($2)
+ add $(1*8 + 8), %rsp
TEST_GOT_MBUF
SWITCH_C_TO_ERLANG
@@ -82,7 +99,11 @@ ASYM($1):
/* make the call on the C stack */
SWITCH_ERLANG_TO_C
- call CSYM($2)
+ pushq %rdx
+ pushq %rsi
+ movq %rsp, %rsi /* Eterm* BIF__ARGS */
+ CALL_BIF($2)
+ add $(2*8), %rsp
TEST_GOT_MBUF
SWITCH_C_TO_ERLANG
@@ -111,7 +132,13 @@ ASYM($1):
/* make the call on the C stack */
SWITCH_ERLANG_TO_C
- call CSYM($2)
+ pushq %rcx
+ pushq %rdx
+ pushq %rsi
+ movq %rsp, %rsi /* Eterm* BIF__ARGS */
+ sub $(8), %rsp /* stack frame 16-byte alignment */
+ CALL_BIF($2)
+ add $(3*8 + 8), %rsp
TEST_GOT_MBUF
SWITCH_C_TO_ERLANG
@@ -124,13 +151,7 @@ ASYM($1):
TYPE_FUNCTION(ASYM($1))
#endif')
-/*
- * fail_bif_interface_0(nbif_name, cbif_name)
- *
- * Generate native interface for a BIF with 0 parameters and
- * standard failure mode.
- */
-define(fail_bif_interface_0,
+define(standard_bif_interface_0,
`
#ifndef HAVE_$1
#`define' HAVE_$1
@@ -143,7 +164,7 @@ ASYM($1):
/* make the call on the C stack */
SWITCH_ERLANG_TO_C
- call CSYM($2)
+ CALL_BIF($2)
TEST_GOT_MBUF
SWITCH_C_TO_ERLANG
diff --git a/erts/emulator/hipe/hipe_arm_bifs.m4 b/erts/emulator/hipe/hipe_arm_bifs.m4
index 3664fb6502..e0c6f09796 100644
--- a/erts/emulator/hipe/hipe_arm_bifs.m4
+++ b/erts/emulator/hipe/hipe_arm_bifs.m4
@@ -20,18 +20,27 @@ changecom(`/*', `*/')dnl
include(`hipe/hipe_arm_asm.m4')
+#`include' "config.h"
#`include' "hipe_literals.h"
.text
.p2align 2
-`#define JOIN3(A,B,C) A##B##C
-#define TEST_GOT_MBUF(ARITY) ldr r1, [P, #P_MBUF]; cmp r1, #0; blne JOIN3(nbif_,ARITY,_gc_after_bif)'
+`#if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP)
+# define CALL_BIF(F) mov r14, #F; str r14, [r0, #P_BIF_CALLEE]; bl hipe_debug_bif_wrapper
+#else
+# define CALL_BIF(F) bl F
+#endif'
+
+define(TEST_GOT_MBUF,`ldr r1, [P, #P_MBUF] /* `TEST_GOT_MBUF' */
+ cmp r1, #0
+ blne nbif_$1_gc_after_bif')
/*
* standard_bif_interface_1(nbif_name, cbif_name)
* standard_bif_interface_2(nbif_name, cbif_name)
* standard_bif_interface_3(nbif_name, cbif_name)
+ * standard_bif_interface_0(nbif_name, cbif_name)
*
* Generate native interface for a BIF with 1-3 parameters and
* standard failure mode.
@@ -48,7 +57,9 @@ $1:
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_BIF
- bl $2
+ str r1, [r0, #P_ARG0] /* Store BIF__ARGS in def_arg_reg[] */
+ add r1, r0, #P_ARG0
+ CALL_BIF($2)
TEST_GOT_MBUF(1)
/* Restore registers. Check for exception. */
@@ -73,7 +84,10 @@ $1:
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_BIF
- bl $2
+ str r1, [r0, #P_ARG0] /* Store BIF__ARGS in def_arg_reg[] */
+ str r2, [r0, #P_ARG1]
+ add r1, r0, #P_ARG0
+ CALL_BIF($2)
TEST_GOT_MBUF(2)
/* Restore registers. Check for exception. */
@@ -99,7 +113,11 @@ $1:
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_BIF
- bl $2
+ str r1, [r0, #P_ARG0] /* Store BIF__ARGS in def_arg_reg[] */
+ str r2, [r0, #P_ARG1]
+ str r3, [r0, #P_ARG2]
+ add r1, r0, #P_ARG0
+ CALL_BIF($2)
TEST_GOT_MBUF(3)
/* Restore registers. Check for exception. */
@@ -111,13 +129,7 @@ $1:
.type $1, %function
#endif')
-/*
- * fail_bif_interface_0(nbif_name, cbif_name)
- *
- * Generate native interface for a BIF with 0 parameters and
- * standard failure mode.
- */
-define(fail_bif_interface_0,
+define(standard_bif_interface_0,
`
#ifndef HAVE_$1
#`define' HAVE_$1
@@ -128,7 +140,8 @@ $1:
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_BIF
- bl $2
+ /* ignore empty BIF__ARGS */
+ CALL_BIF($2)
TEST_GOT_MBUF(0)
/* Restore registers. Check for exception. */
diff --git a/erts/emulator/hipe/hipe_bif0.h b/erts/emulator/hipe/hipe_bif0.h
index f02e8862dc..c512d66f9d 100644
--- a/erts/emulator/hipe/hipe_bif0.h
+++ b/erts/emulator/hipe/hipe_bif0.h
@@ -29,7 +29,7 @@ extern Uint *hipe_bifs_find_pc_from_mfa(Eterm mfa);
extern void hipe_mfa_info_table_init(void);
extern void *hipe_get_remote_na(Eterm m, Eterm f, unsigned int a);
-extern Eterm hipe_find_na_or_make_stub(Process*, Eterm, Eterm, Eterm);
+extern BIF_RETTYPE hipe_find_na_or_make_stub(BIF_ALIST_3);
extern int hipe_find_mfa_from_ra(const void *ra, Eterm *m, Eterm *f, unsigned int *a);
#if defined(__powerpc__) || defined(__ppc__) || defined(__powerpc64__) || defined(__arm__)
extern void *hipe_mfa_get_trampoline(Eterm m, Eterm f, unsigned int a);
diff --git a/erts/emulator/hipe/hipe_bif2.c b/erts/emulator/hipe/hipe_bif2.c
index 2660f74a82..ee97541e15 100644
--- a/erts/emulator/hipe/hipe_bif2.c
+++ b/erts/emulator/hipe/hipe_bif2.c
@@ -166,3 +166,26 @@ BIF_RETTYPE hipe_bifs_show_message_area_0(BIF_ALIST_0)
BIF_RET(am_false);
#endif
}
+
+#if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP)
+
+BIF_RETTYPE hipe_debug_bif_wrapper(BIF_ALIST_1);
+
+# define ERTS_SMP_REQ_PROC_MAIN_LOCK(P) \
+ if ((P)) erts_proc_lc_require_lock((P), ERTS_PROC_LOCK_MAIN)
+# define ERTS_SMP_UNREQ_PROC_MAIN_LOCK(P) \
+ if ((P)) erts_proc_lc_unrequire_lock((P), ERTS_PROC_LOCK_MAIN)
+
+BIF_RETTYPE hipe_debug_bif_wrapper(BIF_ALIST_1)
+{
+ typedef BIF_RETTYPE Bif(BIF_ALIST_1);
+ Bif* fp = (Bif*) (BIF_P->hipe.bif_callee);
+ BIF_RETTYPE res;
+ ERTS_SMP_UNREQ_PROC_MAIN_LOCK(BIF_P);
+ res = (*fp)(BIF_P, BIF__ARGS);
+ ERTS_SMP_REQ_PROC_MAIN_LOCK(BIF_P);
+ return res;
+}
+
+#endif /* ERTS_ENABLE_LOCK_CHECK && ERTS_SMP */
+
diff --git a/erts/emulator/hipe/hipe_bif_list.m4 b/erts/emulator/hipe/hipe_bif_list.m4
index 083788997b..48c7c1bc9b 100644
--- a/erts/emulator/hipe/hipe_bif_list.m4
+++ b/erts/emulator/hipe/hipe_bif_list.m4
@@ -70,24 +70,18 @@
****************************************************************/
/*
+ * standard_bif_interface_0(nbif_name, cbif_name)
* standard_bif_interface_1(nbif_name, cbif_name)
* standard_bif_interface_2(nbif_name, cbif_name)
* standard_bif_interface_3(nbif_name, cbif_name)
*
- * A BIF with implicit P parameter, 1-3 ordinary parameters,
+ * A BIF with implicit P parameter, 0-3 ordinary parameters,
* which may fail.
* HP and FCALLS may be read and updated.
* HP_LIMIT, NSP, NSP_LIMIT, and NRA may not be accessed.
*/
/*
- * fail_bif_interface_0(nbif_name, cbif_name)
- *
- * A zero-arity BIF which may fail, otherwise
- * identical to standard_bif_interface_N.
- */
-
-/*
* nofail_primop_interface_0(nbif_name, cbif_name)
* nofail_primop_interface_1(nbif_name, cbif_name)
* nofail_primop_interface_2(nbif_name, cbif_name)
@@ -150,8 +144,7 @@
/*
* Zero-arity BIFs that can fail.
*/
-fail_bif_interface_0(nbif_memory_0, memory_0)
-fail_bif_interface_0(nbif_processes_0, processes_0)
+standard_bif_interface_0(nbif_processes_0, processes_0)
/*
* BIFs and primops that may do a GC (change heap limit and walk the native stack).
@@ -176,10 +169,10 @@ gc_bif_interface_0(nbif_hipe_bifs_nstack_used_size_0, hipe_bifs_nstack_used_size
/*
* Arithmetic operators called indirectly by the HiPE compiler.
*/
-standard_bif_interface_2(nbif_add_2, erts_mixed_plus)
-standard_bif_interface_2(nbif_sub_2, erts_mixed_minus)
-standard_bif_interface_2(nbif_mul_2, erts_mixed_times)
-standard_bif_interface_2(nbif_div_2, erts_mixed_div)
+standard_bif_interface_2(nbif_add_2, splus_2)
+standard_bif_interface_2(nbif_sub_2, sminus_2)
+standard_bif_interface_2(nbif_mul_2, stimes_2)
+standard_bif_interface_2(nbif_div_2, div_2)
standard_bif_interface_2(nbif_intdiv_2, intdiv_2)
standard_bif_interface_2(nbif_rem_2, rem_2)
standard_bif_interface_2(nbif_bsl_2, bsl_2)
@@ -261,11 +254,6 @@ noproc_primop_interface_1(nbif_atomic_inc, hipe_atomic_inc)
',)dnl
/*
- * Implement standard_bif_interface_0 as nofail_primop_interface_0.
- */
-define(standard_bif_interface_0,`nofail_primop_interface_0($1, $2)')
-
-/*
* Standard BIFs.
* BIF_LIST(ModuleAtom,FunctionAtom,Arity,CFun,Index)
*/
diff --git a/erts/emulator/hipe/hipe_mkliterals.c b/erts/emulator/hipe/hipe_mkliterals.c
index bced90785d..61e15f1d58 100644
--- a/erts/emulator/hipe/hipe_mkliterals.c
+++ b/erts/emulator/hipe/hipe_mkliterals.c
@@ -1,9 +1,8 @@
/*
* %CopyrightBegin%
-
- *
+ *
* Copyright Ericsson AB 2001-2011. All Rights Reserved.
- *
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
@@ -212,6 +211,11 @@ static const unsigned int CRCTABLE[256] = {
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
};
+/* For hipe cross compiler. Hard code all values.
+ No calls by hipe compiler to query the running emulator.
+*/
+static int is_xcomp = 0;
+
/*
* The algorithm for calculating the 32 bit CRC checksum is based upon
* documentation and algorithms provided by Dr. Ross N. Williams in the
@@ -243,7 +247,7 @@ crc_update_buf(unsigned int crc_value,
}
static unsigned int
-crc_update_int(unsigned int crc_value, const unsigned int *p)
+crc_update_int(unsigned int crc_value, const int *p)
{
return crc_update_buf(crc_value, p, sizeof *p);
}
@@ -256,7 +260,7 @@ crc_update_int(unsigned int crc_value, const unsigned int *p)
*/
static const struct literal {
const char *name;
- unsigned int value;
+ int value;
} literals[] = {
/* Field offsets in a process struct */
{ "P_HP", offsetof(struct process, htop) },
@@ -289,6 +293,9 @@ static const struct literal {
{ "P_NRA", offsetof(struct process, hipe.nra) },
#endif
{ "P_NARITY", offsetof(struct process, hipe.narity) },
+# if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP)
+ { "P_BIF_CALLEE", offsetof(struct process, hipe.bif_callee) },
+# endif
#endif /* HIPE */
/* process flags bits */
@@ -298,7 +305,7 @@ static const struct literal {
{ "FREASON_TRAP", TRAP },
/* special Erlang constants */
- { "THE_NON_VALUE", THE_NON_VALUE },
+ { "THE_NON_VALUE", (int)THE_NON_VALUE },
/* funs */
#ifdef HIPE
@@ -452,7 +459,7 @@ static const struct rts_param {
unsigned int nr;
const char *name;
unsigned int is_defined;
- unsigned int value;
+ int value;
} rts_params[] = {
{ 1, "P_OFF_HEAP_FUNS",
#if !defined(HYBRID)
@@ -528,12 +535,12 @@ static void compute_crc(void)
static void c_define_literal(FILE *fp, const struct literal *literal)
{
- fprintf(fp, "#define %s %u\n", literal->name, literal->value);
+ fprintf(fp, "#define %s %d\n", literal->name, literal->value);
}
static void e_define_literal(FILE *fp, const struct literal *literal)
{
- fprintf(fp, "-define(%s, %u).\n", literal->name, literal->value);
+ fprintf(fp, "-define(%s, %d).\n", literal->name, literal->value);
}
static void print_literals(FILE *fp, void (*print_literal)(FILE*, const struct literal*))
@@ -560,7 +567,7 @@ static void print_atom_literals(FILE *fp, void (*print_atom_literal)(FILE*, cons
static void c_define_param(FILE *fp, const struct rts_param *param)
{
if (param->is_defined)
- fprintf(fp, "#define %s %u\n", param->name, param->value);
+ fprintf(fp, "#define %s %d\n", param->name, param->value);
}
static void c_case_param(FILE *fp, const struct rts_param *param)
@@ -568,7 +575,7 @@ static void c_case_param(FILE *fp, const struct rts_param *param)
fprintf(fp, " \\\n");
fprintf(fp, "\tcase %u: ", param->nr);
if (param->is_defined)
- fprintf(fp, "value = %u", param->value);
+ fprintf(fp, "value = %d", param->value);
else
fprintf(fp, "is_defined = 0");
fprintf(fp, "; break;");
@@ -576,7 +583,15 @@ static void c_case_param(FILE *fp, const struct rts_param *param)
static void e_define_param(FILE *fp, const struct rts_param *param)
{
- fprintf(fp, "-define(%s, hipe_bifs:get_rts_param(%u)).\n", param->name, param->nr);
+ if (is_xcomp) {
+ if (param->is_defined)
+ fprintf(fp, "-define(%s, %d).\n", param->name, param->value);
+ else
+ fprintf(fp, "-define(%s, []).\n", param->name);
+ }
+ else {
+ fprintf(fp, "-define(%s, hipe_bifs:get_rts_param(%u)).\n", param->name, param->nr);
+ }
}
static void print_params(FILE *fp, void (*print_param)(FILE*,const struct rts_param*))
@@ -613,19 +628,40 @@ static int do_e(FILE *fp, const char* this_exe)
fprintf(fp, "\n");
print_params(fp, e_define_param);
fprintf(fp, "\n");
- fprintf(fp, "-define(HIPE_SYSTEM_CRC, hipe_bifs:system_crc(%u)).\n", literals_crc);
+ if (is_xcomp) {
+ fprintf(fp, "-define(HIPE_SYSTEM_CRC, %u).\n", system_crc);
+ }
+ else {
+ fprintf(fp, "-define(HIPE_SYSTEM_CRC, hipe_bifs:system_crc(%u)).\n",
+ literals_crc);
+ }
return 0;
}
int main(int argc, const char **argv)
{
+ int i;
+ int (*do_func_ptr)(FILE *, const char*) = NULL;
+
compute_crc();
- if (argc == 2) {
- if (strcmp(argv[1], "-c") == 0)
- return do_c(stdout, argv[0]);
- if (strcmp(argv[1], "-e") == 0)
- return do_e(stdout, argv[0]);
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-c") == 0)
+ do_func_ptr = &do_c;
+ else if (strcmp(argv[i], "-e") == 0)
+ do_func_ptr = &do_e;
+ else if (strcmp(argv[i], "-x") == 0)
+ is_xcomp = 1;
+ else
+ goto error;
+ }
+ if (do_func_ptr) {
+ return do_func_ptr(stdout, argv[0]);
}
- fprintf(stderr, "usage: %s [-c | -e] > output-file\n", argv[0]);
+error:
+ fprintf(stderr, "usage: %s [-x] [-c | -e] > output-file\n"
+ "\t-c\tC header file\n"
+ "\t-e\tErlang header file\n"
+ "\t-x\tCross compile. No dependencies to compiling emulator\n",
+ argv[0]);
return 1;
}
diff --git a/erts/emulator/hipe/hipe_mode_switch.c b/erts/emulator/hipe/hipe_mode_switch.c
index 16f8fb1347..4d75883fc5 100644
--- a/erts/emulator/hipe/hipe_mode_switch.c
+++ b/erts/emulator/hipe/hipe_mode_switch.c
@@ -35,6 +35,17 @@
#include "hipe_stack.h"
#include "hipe_bif0.h" /* hipe_mfa_info_table_init() */
+#if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP)
+# define ERTS_SMP_REQ_PROC_MAIN_LOCK(P) \
+ if ((P)) erts_proc_lc_require_lock((P), ERTS_PROC_LOCK_MAIN)
+# define ERTS_SMP_UNREQ_PROC_MAIN_LOCK(P) \
+ if ((P)) erts_proc_lc_unrequire_lock((P), ERTS_PROC_LOCK_MAIN)
+#else
+# define ERTS_SMP_REQ_PROC_MAIN_LOCK(P)
+# define ERTS_SMP_UNREQ_PROC_MAIN_LOCK(P)
+#endif
+
+
/*
* Internal debug support.
* #define HIPE_DEBUG to the desired debug level:
@@ -318,8 +329,8 @@ Process *hipe_mode_switch(Process *p, unsigned cmd, Eterm reg[])
* Native code called a BIF, which "failed" with a TRAP to BEAM.
* Prior to returning, the BIF stored (see BIF_TRAP<N>):
- * the callee's address in p->def_arg_reg[3]
- * the callee's parameters in p->def_arg_reg[0..2]
+ * the callee's address in p->i
+ * the callee's parameters in reg[0..2]
* the callee's arity in p->arity (for BEAM gc purposes)
*
* We need to remove the BIF's parameters from the native
@@ -331,32 +342,25 @@ Process *hipe_mode_switch(Process *p, unsigned cmd, Eterm reg[])
*/
unsigned int i, is_recursive = 0;
- /* Save p->arity, then update it with the original BIF's arity.
- Get rid of any stacked parameters in that call. */
- /* XXX: hipe_call_from_native_is_recursive() copies data to
- reg[], which is useless in the TRAP case. Maybe write a
- specialised hipe_trap_from_native_is_recursive() later. */
if (p->hipe.nsp != NULL) {
- unsigned int callee_arity;
- callee_arity = p->arity;
- p->arity = p->hipe.narity; /* caller's arity */
- is_recursive = hipe_call_from_native_is_recursive(p, reg);
-
- p->i = (Eterm *)(p->def_arg_reg[3]);
- p->arity = callee_arity;
+ is_recursive = hipe_trap_from_native_is_recursive(p);
}
- /* If process is in P_WAITING state, we schedule the next process */
+ /* Schedule next process if current process was hibernated or is waiting
+ for messages */
+ if (p->flags & F_HIBERNATE_SCHED) {
+ p->flags &= ~F_HIBERNATE_SCHED;
+ goto do_schedule;
+ }
if (p->status == P_WAITING) {
+ for (i = 0; i < p->arity; ++i)
+ p->arg_reg[i] = reg[i];
goto do_schedule;
}
- for (i = 0; i < p->arity; ++i)
- reg[i] = p->def_arg_reg[i];
-
if (is_recursive)
hipe_push_beam_trap_frame(p, reg, p->arity);
-
+
result = HIPE_MODE_SWITCH_RES_CALL;
break;
}
@@ -465,10 +469,12 @@ Process *hipe_mode_switch(Process *p, unsigned cmd, Eterm reg[])
#if !(NR_ARG_REGS > 5)
int reds_in = p->def_arg_reg[5];
#endif
+ ERTS_SMP_UNREQ_PROC_MAIN_LOCK(p);
p = schedule(p, reds_in - p->fcalls);
+ ERTS_SMP_REQ_PROC_MAIN_LOCK(p);
#ifdef ERTS_SMP
p->hipe_smp.have_receive_locks = 0;
- reg = p->scheduler_data->save_reg;
+ reg = p->scheduler_data->x_reg_array;
#endif
}
{
@@ -643,7 +649,7 @@ Eterm hipe_build_stacktrace(Process *p, struct StackTrace *s)
if (depth < 1)
return NIL;
- heap_size = 6 * depth; /* each [{M,F,A}|_] is 2+4 == 6 words */
+ heap_size = 7 * depth; /* each [{M,F,A,[]}|_] is 2+5 == 7 words */
hp = HAlloc(p, heap_size);
hp_end = hp + heap_size;
@@ -654,8 +660,8 @@ Eterm hipe_build_stacktrace(Process *p, struct StackTrace *s)
ra = (const void*)s->trace[i];
if (!hipe_find_mfa_from_ra(ra, &m, &f, &a))
continue;
- mfa = TUPLE3(hp, m, f, make_small(a));
- hp += 4;
+ mfa = TUPLE4(hp, m, f, make_small(a), NIL);
+ hp += 5;
next = CONS(hp, mfa, NIL);
*next_p = next;
next_p = &CDR(list_val(next));
diff --git a/erts/emulator/hipe/hipe_native_bif.c b/erts/emulator/hipe/hipe_native_bif.c
index 8d31348496..77dee6f9e9 100644
--- a/erts/emulator/hipe/hipe_native_bif.c
+++ b/erts/emulator/hipe/hipe_native_bif.c
@@ -41,9 +41,9 @@
*/
/* for -Wmissing-prototypes :-( */
-extern Eterm hipe_check_process_code_2(Process*, Eterm, Eterm);
-extern Eterm hipe_garbage_collect_1(Process*, Eterm);
-extern Eterm hipe_show_nstack_1(Process*, Eterm);
+extern Eterm hipe_check_process_code_2(BIF_ALIST_2);
+extern Eterm hipe_garbage_collect_1(BIF_ALIST_1);
+extern Eterm hipe_show_nstack_1(BIF_ALIST_1);
/* Used when a BIF can trigger a stack walk. */
static __inline__ void hipe_set_narity(Process *p, unsigned int arity)
@@ -56,7 +56,7 @@ Eterm hipe_check_process_code_2(BIF_ALIST_2)
Eterm ret;
hipe_set_narity(BIF_P, 2);
- ret = check_process_code_2(BIF_P, BIF_ARG_1, BIF_ARG_2);
+ ret = check_process_code_2(BIF_P, BIF__ARGS);
hipe_set_narity(BIF_P, 0);
return ret;
}
@@ -66,7 +66,7 @@ Eterm hipe_garbage_collect_1(BIF_ALIST_1)
Eterm ret;
hipe_set_narity(BIF_P, 1);
- ret = garbage_collect_1(BIF_P, BIF_ARG_1);
+ ret = garbage_collect_1(BIF_P, BIF__ARGS);
hipe_set_narity(BIF_P, 0);
return ret;
}
@@ -76,7 +76,7 @@ Eterm hipe_show_nstack_1(BIF_ALIST_1)
Eterm ret;
hipe_set_narity(BIF_P, 1);
- ret = hipe_bifs_show_nstack_1(BIF_P, BIF_ARG_1);
+ ret = hipe_bifs_show_nstack_1(BIF_P, BIF__ARGS);
hipe_set_narity(BIF_P, 0);
return ret;
}
@@ -99,8 +99,10 @@ void hipe_gc(Process *p, Eterm need)
* has begun.
* XXX: BUG: native code should check return status
*/
-Eterm hipe_set_timeout(Process *p, Eterm timeout_value)
+BIF_RETTYPE hipe_set_timeout(BIF_ALIST_1)
{
+ Process* p = BIF_P;
+ Eterm timeout_value = BIF_ARG_1;
#if !defined(ARCH_64)
Uint time_val;
#endif
@@ -286,8 +288,13 @@ static struct StackTrace *get_trace_from_exc(Eterm exc)
* This does what the (misnamed) Beam instruction 'raise_ss' does,
* namely, a proper re-throw of an exception that was caught by 'try'.
*/
-Eterm hipe_rethrow(Process *c_p, Eterm exc, Eterm value)
+
+BIF_RETTYPE hipe_rethrow(BIF_ALIST_2)
{
+ Process* c_p = BIF_P;
+ Eterm exc = BIF_ARG_1;
+ Eterm value = BIF_ARG_2;
+
c_p->fvalue = value;
if (c_p->freason == EXC_NULL) {
/* a safety check for the R10-0 case; should not happen */
@@ -334,7 +341,7 @@ char *hipe_bs_allocate(int len)
bptr = erts_bin_nrml_alloc(len);
bptr->flags = 0;
bptr->orig_size = len;
- erts_smp_atomic_init(&bptr->refc, 1);
+ erts_smp_atomic_init_nob(&bptr->refc, 1);
return bptr->orig_bytes;
}
@@ -411,8 +418,12 @@ Eterm hipe_bs_utf8_size(Eterm arg)
return make_small(4);
}
-Eterm hipe_bs_put_utf8(Process *p, Eterm arg, byte *base, unsigned int offset)
+BIF_RETTYPE hipe_bs_put_utf8(BIF_ALIST_3)
{
+ Process* p = BIF_P;
+ Eterm arg = BIF_ARG_1;
+ byte* base = (byte*) BIF_ARG_2;
+ Uint offset = (Uint) BIF_ARG_3;
byte *save_bin_buf;
Uint save_bin_offset;
int res;
@@ -468,13 +479,21 @@ Eterm hipe_bs_put_utf16(Process *p, Eterm arg, byte *base, unsigned int offset,
return new_offset;
}
-Eterm hipe_bs_put_utf16be(Process *p, Eterm arg, byte *base, unsigned int offset)
+BIF_RETTYPE hipe_bs_put_utf16be(BIF_ALIST_3)
{
+ Process *p = BIF_P;
+ Eterm arg = BIF_ARG_1;
+ byte *base = (byte*) BIF_ARG_2;
+ Uint offset = (Uint) BIF_ARG_3;
return hipe_bs_put_utf16(p, arg, base, offset, 0);
}
-Eterm hipe_bs_put_utf16le(Process *p, Eterm arg, byte *base, unsigned int offset)
+BIF_RETTYPE hipe_bs_put_utf16le(BIF_ALIST_3)
{
+ Process *p = BIF_P;
+ Eterm arg = BIF_ARG_1;
+ byte *base = (byte*) BIF_ARG_2;
+ Uint offset = (Uint) BIF_ARG_3;
return hipe_bs_put_utf16(p, arg, base, offset, BSF_LITTLE);
}
@@ -489,8 +508,10 @@ static int validate_unicode(Eterm arg)
return 1;
}
-Eterm hipe_bs_validate_unicode(Process *p, Eterm arg)
+BIF_RETTYPE hipe_bs_validate_unicode(BIF_ALIST_1)
{
+ Process *p = BIF_P;
+ Eterm arg = BIF_ARG_1;
if (!validate_unicode(arg))
BIF_ERROR(p, BADARG);
return NIL;
@@ -584,7 +605,7 @@ void hipe_clear_timeout(Process *c_p)
void hipe_atomic_inc(int *counter)
{
- erts_smp_atomic_inc((erts_smp_atomic_t*)counter);
+ erts_smp_atomic_inc_nob((erts_smp_atomic_t*)counter);
}
#endif
diff --git a/erts/emulator/hipe/hipe_native_bif.h b/erts/emulator/hipe/hipe_native_bif.h
index 13a02b84a2..8c9dec180e 100644
--- a/erts/emulator/hipe/hipe_native_bif.h
+++ b/erts/emulator/hipe/hipe_native_bif.h
@@ -23,6 +23,7 @@
#ifndef HIPE_NATIVE_BIF_H
#define HIPE_NATIVE_BIF_H
+#include "bif.h"
#include "hipe_arch.h"
/*
@@ -71,24 +72,24 @@ AEXTERN(void,nbif_select_msg,(Process*));
AEXTERN(Eterm,nbif_cmp_2,(void));
AEXTERN(Eterm,nbif_eq_2,(void));
-Eterm hipe_nonclosure_address(Process*, Eterm, Uint);
-Eterm hipe_conv_big_to_float(Process*, Eterm);
+BIF_RETTYPE hipe_nonclosure_address(BIF_ALIST_2);
+BIF_RETTYPE hipe_conv_big_to_float(BIF_ALIST_1);
void hipe_fclearerror_error(Process*);
void hipe_select_msg(Process*);
void hipe_gc(Process*, Eterm);
-Eterm hipe_set_timeout(Process*, Eterm);
+BIF_RETTYPE hipe_set_timeout(BIF_ALIST_1);
void hipe_handle_exception(Process*);
-Eterm hipe_rethrow(Process *c_p, Eterm exc, Eterm value);
+BIF_RETTYPE hipe_rethrow(BIF_ALIST_2);
char *hipe_bs_allocate(int);
Binary *hipe_bs_reallocate(Binary*, int);
int hipe_bs_put_small_float(Process*, Eterm, Uint, byte*, unsigned, unsigned);
void hipe_bs_put_bits(Eterm, Uint, byte*, unsigned, unsigned);
Eterm hipe_bs_utf8_size(Eterm);
-Eterm hipe_bs_put_utf8(Process*, Eterm, byte*, unsigned int);
+BIF_RETTYPE hipe_bs_put_utf8(BIF_ALIST_3);
Eterm hipe_bs_utf16_size(Eterm);
-Eterm hipe_bs_put_utf16be(Process*, Eterm, byte*, unsigned int);
-Eterm hipe_bs_put_utf16le(Process*, Eterm, byte*, unsigned int);
-Eterm hipe_bs_validate_unicode(Process*, Eterm);
+BIF_RETTYPE hipe_bs_put_utf16be(BIF_ALIST_3);
+BIF_RETTYPE hipe_bs_put_utf16le(BIF_ALIST_3);
+BIF_RETTYPE hipe_bs_validate_unicode(BIF_ALIST_1);
struct erl_bin_match_buffer;
int hipe_bs_validate_unicode_retract(struct erl_bin_match_buffer*, Eterm);
diff --git a/erts/emulator/hipe/hipe_ppc_asm.m4 b/erts/emulator/hipe/hipe_ppc_asm.m4
index 0eb5c441e6..343402f9f0 100644
--- a/erts/emulator/hipe/hipe_ppc_asm.m4
+++ b/erts/emulator/hipe/hipe_ppc_asm.m4
@@ -31,12 +31,23 @@ define(LOAD,ld)dnl
define(STORE,std)dnl
define(CMPI,cmpdi)dnl
define(WSIZE,8)dnl
+`#define STORE_IA(ADDR, DST, TMP) \
+ addis TMP, 0, ADDR@highest SEMI\
+ ori TMP, TMP, ADDR@higher SEMI\
+ rldicr TMP, TMP, 32, 31 SEMI\
+ oris TMP, TMP, ADDR@h SEMI\
+ ori TMP, TMP, ADDR@l SEMI\
+ std TMP, DST'
',`
/* 32-bit PowerPC */
define(LOAD,lwz)dnl
define(STORE,stw)dnl
define(CMPI,cmpwi)dnl
define(WSIZE,4)dnl
+`#define STORE_IA(ADDR, DST, TMP) \
+ lis TMP, ADDR@ha SEMI\
+ addi TMP, TMP, ADDR@l SEMI\
+ stw TMP, DST'
')dnl
`#define LOAD 'LOAD
`#define STORE 'STORE
diff --git a/erts/emulator/hipe/hipe_ppc_bifs.m4 b/erts/emulator/hipe/hipe_ppc_bifs.m4
index 203fefe1a1..d09551d10d 100644
--- a/erts/emulator/hipe/hipe_ppc_bifs.m4
+++ b/erts/emulator/hipe/hipe_ppc_bifs.m4
@@ -20,21 +20,34 @@ changecom(`/*', `*/')dnl
include(`hipe/hipe_ppc_asm.m4')
+#`include' "config.h"
#`include' "hipe_literals.h"
+`#if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP)
+# define CALL_BIF(F) STORE_IA(CSYM(F), P_BIF_CALLEE(P), r29); bl CSYM(hipe_debug_bif_wrapper)
+#else
+# define CALL_BIF(F) bl CSYM(F)
+#endif'
+
.text
.p2align 2
-`#define TEST_GOT_MBUF LOAD r4, P_MBUF(P) SEMI CMPI r4, 0 SEMI bne- 3f SEMI 2:
-#define JOIN3(A,B,C) A##B##C
-#define HANDLE_GOT_MBUF(ARITY) 3: bl CSYM(JOIN3(nbif_,ARITY,_gc_after_bif)) SEMI b 2b'
+define(TEST_GOT_MBUF,`LOAD r4, P_MBUF(P) # `TEST_GOT_MBUF'
+ CMPI r4, 0
+ bne- 3f
+2:')
+define(HANDLE_GOT_MBUF,`
+3: bl CSYM(nbif_$1_gc_after_bif) # `HANDLE_GOT_MBUF'
+ b 2b')
+
/*
* standard_bif_interface_1(nbif_name, cbif_name)
* standard_bif_interface_2(nbif_name, cbif_name)
* standard_bif_interface_3(nbif_name, cbif_name)
+ * standard_bif_interface_0(nbif_name, cbif_name)
*
- * Generate native interface for a BIF with 1-3 parameters and
+ * Generate native interface for a BIF with 0-3 parameters and
* standard failure mode.
*/
define(standard_bif_interface_1,
@@ -49,7 +62,9 @@ ASYM($1):
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_BIF
- bl CSYM($2)
+ STORE r4, P_ARG0(r3) # Store BIF__ARGS in def_arg_reg[]
+ addi r4, r3, P_ARG0
+ CALL_BIF($2)
TEST_GOT_MBUF
/* Restore registers. Check for exception. */
@@ -77,7 +92,10 @@ ASYM($1):
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_BIF
- bl CSYM($2)
+ STORE r4, P_ARG0(r3) # Store BIF__ARGS in def_arg_reg[]
+ STORE r5, P_ARG1(r3)
+ addi r4, r3, P_ARG0
+ CALL_BIF($2)
TEST_GOT_MBUF
/* Restore registers. Check for exception. */
@@ -106,7 +124,11 @@ ASYM($1):
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_BIF
- bl CSYM($2)
+ STORE r4, P_ARG0(r3) # Store BIF__ARGS in def_arg_reg[]
+ STORE r5, P_ARG1(r3)
+ STORE r6, P_ARG2(r3)
+ addi r4, r3, P_ARG0
+ CALL_BIF($2)
TEST_GOT_MBUF
/* Restore registers. Check for exception. */
@@ -121,13 +143,7 @@ ASYM($1):
TYPE_FUNCTION(ASYM($1))
#endif')
-/*
- * fail_bif_interface_0(nbif_name, cbif_name)
- *
- * Generate native interface for a BIF with 0 parameters and
- * standard failure mode.
- */
-define(fail_bif_interface_0,
+define(standard_bif_interface_0,
`
#ifndef HAVE_$1
#`define' HAVE_$1
@@ -138,7 +154,8 @@ ASYM($1):
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_BIF
- bl CSYM($2)
+ /* ignore empty BIF__ARGS */
+ CALL_BIF($2)
TEST_GOT_MBUF
/* Restore registers. Check for exception. */
@@ -173,7 +190,8 @@ ASYM($1):
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_GC
- bl CSYM($2)
+ /* ignore empty BIF__ARGS */
+ CALL_BIF($2)
TEST_GOT_MBUF
/* Restore registers. */
@@ -196,7 +214,9 @@ ASYM($1):
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_GC
- bl CSYM($2)
+ STORE r4, P_ARG0(r3) # Store BIF__ARGS in def_arg_reg[]
+ addi r4, r3, P_ARG0
+ CALL_BIF($2)
TEST_GOT_MBUF
/* Restore registers. Check for exception. */
@@ -224,7 +244,10 @@ ASYM($1):
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_GC
- bl CSYM($2)
+ STORE r4, P_ARG0(r3) # Store BIF__ARGS in def_arg_reg[]
+ STORE r5, P_ARG1(r3)
+ addi r4, r3, P_ARG0
+ CALL_BIF($2)
TEST_GOT_MBUF
/* Restore registers. Check for exception. */
diff --git a/erts/emulator/hipe/hipe_process.h b/erts/emulator/hipe/hipe_process.h
index 5effacb398..43f47d1a28 100644
--- a/erts/emulator/hipe/hipe_process.h
+++ b/erts/emulator/hipe/hipe_process.h
@@ -42,6 +42,9 @@ struct hipe_process_state {
void (*nra)(void); /* Native code return address. */
#endif
unsigned int narity; /* Arity of BIF call, for stack walks. */
+#if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP)
+ void (*bif_callee)(void); /* When calling BIF's via debug wrapper */
+#endif
};
extern void hipe_arch_print_pcb(struct hipe_process_state *p);
diff --git a/erts/emulator/hipe/hipe_risc_glue.h b/erts/emulator/hipe/hipe_risc_glue.h
index e74023e3e9..cc2671c016 100644
--- a/erts/emulator/hipe/hipe_risc_glue.h
+++ b/erts/emulator/hipe/hipe_risc_glue.h
@@ -199,6 +199,22 @@ hipe_call_from_native_is_recursive(Process *p, Eterm reg[])
return 0;
}
+/* BEAM called native, which called BIF that returned trap
+ * Discard bif parameters.
+ * If tailcall, also clean up native stub continuation. */
+static __inline__ int
+hipe_trap_from_native_is_recursive(Process *p)
+{
+ if (p->hipe.narity > NR_ARG_REGS) {
+ p->hipe.nsp += (p->hipe.narity - NR_ARG_REGS);
+ }
+ if (p->hipe.nra != (void(*)(void))&nbif_return)
+ return 1;
+ hipe_pop_risc_nra_frame(p);
+ return 0;
+}
+
+
/* Native makes a call which needs to unload the parameters.
This differs from hipe_call_from_native_is_recursive() in
that it doesn't check for or pop the BEAM-calls-native frame.
diff --git a/erts/emulator/hipe/hipe_sparc_bifs.m4 b/erts/emulator/hipe/hipe_sparc_bifs.m4
index 03db7f3413..ca5af45d58 100644
--- a/erts/emulator/hipe/hipe_sparc_bifs.m4
+++ b/erts/emulator/hipe/hipe_sparc_bifs.m4
@@ -20,27 +20,42 @@ changecom(`/*', `*/')dnl
include(`hipe/hipe_sparc_asm.m4')
+#`include' "config.h"
#`include' "hipe_literals.h"
.section ".text"
.align 4
+`#if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP)
+# define CALL_BIF(F) set F, %o7; st %o7, [%o0+P_BIF_CALLEE]; call hipe_debug_bif_wrapper
+#else
+# define CALL_BIF(F) call F
+#endif'
+
/*
* Test for exception. This macro executes its delay slot.
*/
-`#define __TEST_GOT_EXN(LABEL) cmp %o0, THE_NON_VALUE; bz,pn %icc, LABEL
-#define TEST_GOT_EXN(ARITY) __TEST_GOT_EXN(JOIN3(nbif_,ARITY,_simple_exception))'
+define(TEST_GOT_EXN,`cmp %o0, THE_NON_VALUE ! `TEST_GOT_EXN'
+ bz,pn %icc, nbif_$1_simple_exception')
-`#define TEST_GOT_MBUF ld [P+P_MBUF], %o1; cmp %o1, 0; bne 3f; nop; 2:
-#define JOIN3(A,B,C) A##B##C
-#define HANDLE_GOT_MBUF(ARITY) 3: call JOIN3(nbif_,ARITY,_gc_after_bif); nop; b 2b; nop'
+define(TEST_GOT_MBUF,`ld [P+P_MBUF], %o1 ! `TEST_GOT_MBUF'
+ cmp %o1, 0
+ bne 3f
+ nop
+2:')
+define(HANDLE_GOT_MBUF,`
+3: call nbif_$1_gc_after_bif ! `HANDLE_GOT_MBUF'
+ nop
+ b 2b
+ nop')
/*
* standard_bif_interface_1(nbif_name, cbif_name)
* standard_bif_interface_2(nbif_name, cbif_name)
* standard_bif_interface_3(nbif_name, cbif_name)
+ * standard_bif_interface_0(nbif_name, cbif_name)
*
- * Generate native interface for a BIF with 1-3 parameters and
+ * Generate native interface for a BIF with 0-3 parameters and
* standard failure mode.
*/
define(standard_bif_interface_1,
@@ -55,7 +70,9 @@ $1:
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_BIF
- call $2
+ st %o1, [%o0+P_ARG0] ! Store BIF__ARGS in def_arg_reg
+ add %o0, P_ARG0, %o1
+ CALL_BIF($2)
nop
TEST_GOT_MBUF
@@ -81,7 +98,10 @@ $1:
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_BIF
- call $2
+ st %o1, [%o0+P_ARG0] ! Store BIF__ARGS in def_arg_reg
+ st %o2, [%o0+P_ARG1]
+ add %o0, P_ARG0, %o1
+ CALL_BIF($2)
nop
TEST_GOT_MBUF
@@ -108,7 +128,11 @@ $1:
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_BIF
- call $2
+ st %o1, [%o0+P_ARG0] ! Store BIF__ARGS in def_arg_reg
+ st %o2, [%o0+P_ARG1]
+ st %o3, [%o0+P_ARG2]
+ add %o0, P_ARG0, %o1
+ CALL_BIF($2)
nop
TEST_GOT_MBUF
@@ -121,13 +145,7 @@ $1:
.type $1, #function
#endif')
-/*
- * fail_bif_interface_0(nbif_name, cbif_name)
- *
- * Generate native interface for a BIF with 0 parameters and
- * standard failure mode.
- */
-define(fail_bif_interface_0,
+define(standard_bif_interface_0,
`
#ifndef HAVE_$1
#`define' HAVE_$1
@@ -138,7 +156,8 @@ $1:
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_BIF
- call $2
+ /* ignore empty BIF__ARGS */
+ CALL_BIF($2)
nop
TEST_GOT_MBUF
@@ -171,7 +190,8 @@ $1:
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_GC
- call $2
+ /* ignore empty BIF__ARGS */
+ CALL_BIF($2)
nop
TEST_GOT_MBUF
@@ -195,7 +215,9 @@ $1:
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_GC
- call $2
+ st %o1, [%o0+P_ARG0] ! Store BIF__ARGS in def_arg_reg
+ add %o0, P_ARG0, %o1
+ CALL_BIF($2)
nop
TEST_GOT_MBUF
@@ -221,7 +243,10 @@ $1:
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_GC
- call $2
+ st %o1, [%o0+P_ARG0] ! Store BIF__ARGS in def_arg_reg
+ st %o2, [%o0+P_ARG1]
+ add %o0, P_ARG0, %o1
+ CALL_BIF($2)
nop
TEST_GOT_MBUF
diff --git a/erts/emulator/hipe/hipe_x86_bifs.m4 b/erts/emulator/hipe/hipe_x86_bifs.m4
index 1bb6488b00..2ea69bde3c 100644
--- a/erts/emulator/hipe/hipe_x86_bifs.m4
+++ b/erts/emulator/hipe/hipe_x86_bifs.m4
@@ -20,6 +20,7 @@ changecom(`/*', `*/')dnl
include(`hipe/hipe_x86_asm.m4')
+#`include' "config.h"
#`include' "hipe_literals.h"
`#if THE_NON_VALUE == 0
@@ -28,16 +29,27 @@ include(`hipe/hipe_x86_asm.m4')
#define TEST_GOT_EXN cmpl $THE_NON_VALUE,%eax
#endif'
-`#define TEST_GOT_MBUF movl P_MBUF(P), %edx; testl %edx, %edx; jnz 3f; 2:
-#define JOIN3(A,B,C) A##B##C
-#define HANDLE_GOT_MBUF(ARITY) 3: call JOIN3(nbif_,ARITY,_gc_after_bif); jmp 2b'
+`#if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP)
+# define CALL_BIF(F) movl $CSYM(F), P_BIF_CALLEE(P); call CSYM(hipe_debug_bif_wrapper)
+#else
+# define CALL_BIF(F) call CSYM(F)
+#endif'
+
+define(TEST_GOT_MBUF,`movl P_MBUF(P), %edx # `TEST_GOT_MBUF'
+ testl %edx, %edx
+ jnz 3f
+2:')
+define(HANDLE_GOT_MBUF,`
+3: call nbif_$1_gc_after_bif # `HANDLE_GOT_MBUF'
+ jmp 2b')
/*
* standard_bif_interface_1(nbif_name, cbif_name)
* standard_bif_interface_2(nbif_name, cbif_name)
* standard_bif_interface_3(nbif_name, cbif_name)
+ * standard_bif_interface_0(nbif_name, cbif_name)
*
- * Generate native interface for a BIF with 1-3 parameters and
+ * Generate native interface for a BIF with 0-3 parameters and
* standard failure mode.
*/
define(standard_bif_interface_1,
@@ -56,8 +68,10 @@ ASYM($1):
/* make the call on the C stack */
NBIF_ARG_REG(0,P)
- NBIF_ARG(1,1,0)
- call CSYM($2)
+ NBIF_ARG(2,1,0)
+ lea 8(%esp), %eax
+ NBIF_ARG_REG(1,%eax) # BIF__ARGS
+ CALL_BIF($2)
TEST_GOT_MBUF
/* switch to native stack */
@@ -88,9 +102,11 @@ ASYM($1):
/* make the call on the C stack */
NBIF_ARG_REG(0,P)
- NBIF_ARG(1,2,0)
- NBIF_ARG(2,2,1)
- call CSYM($2)
+ NBIF_ARG(2,2,0)
+ NBIF_ARG(3,2,1)
+ lea 8(%esp), %eax
+ NBIF_ARG_REG(1,%eax) # BIF__ARGS
+ CALL_BIF($2)
TEST_GOT_MBUF
/* switch to native stack */
@@ -121,10 +137,12 @@ ASYM($1):
/* make the call on the C stack */
NBIF_ARG_REG(0,P)
- NBIF_ARG(1,3,0)
- NBIF_ARG(2,3,1)
- NBIF_ARG(3,3,2)
- call CSYM($2)
+ NBIF_ARG(2,3,0)
+ NBIF_ARG(3,3,1)
+ NBIF_ARG(4,3,2)
+ lea 8(%esp), %eax
+ NBIF_ARG_REG(1,%eax) # BIF__ARGS
+ CALL_BIF($2)
TEST_GOT_MBUF
/* switch to native stack */
@@ -139,13 +157,7 @@ ASYM($1):
TYPE_FUNCTION(ASYM($1))
#endif')
-/*
- * fail_bif_interface_0(nbif_name, cbif_name)
- *
- * Generate native interface for a BIF with 0 parameters and
- * standard failure mode.
- */
-define(fail_bif_interface_0,
+define(standard_bif_interface_0,
`
#ifndef HAVE_$1
#`define' HAVE_$1
@@ -158,7 +170,8 @@ ASYM($1):
/* make the call on the C stack */
NBIF_ARG_REG(0,P)
- call CSYM($2)
+ /* skip BIF__ARGS */
+ CALL_BIF($2)
TEST_GOT_MBUF
/* switch to native stack */
diff --git a/erts/emulator/hipe/hipe_x86_glue.h b/erts/emulator/hipe/hipe_x86_glue.h
index a7b0f164be..b0db93267c 100644
--- a/erts/emulator/hipe/hipe_x86_glue.h
+++ b/erts/emulator/hipe/hipe_x86_glue.h
@@ -186,6 +186,25 @@ hipe_call_from_native_is_recursive(Process *p, Eterm reg[])
return 0;
}
+/* BEAM called native, which called BIF that returned trap
+ * Discard bif parameters.
+ * If tailcall, also clean up native stub continuation. */
+static __inline__ int
+hipe_trap_from_native_is_recursive(Process *p)
+{
+ Eterm nra = *(p->hipe.nsp++);
+
+ if (p->hipe.narity > NR_ARG_REGS) {
+ p->hipe.nsp += (p->hipe.narity - NR_ARG_REGS);
+ }
+ if (nra != (Eterm)nbif_return) {
+ *--(p->hipe.nsp) = nra;
+ return 1;
+ }
+ return 0;
+}
+
+
/* Native makes a call which needs to unload the parameters.
This differs from hipe_call_from_native_is_recursive() in
that it doesn't check for or pop the BEAM-calls-native frame.
diff --git a/erts/emulator/pcre/Makefile b/erts/emulator/pcre/Makefile
deleted file mode 100644
index 72eea01130..0000000000
--- a/erts/emulator/pcre/Makefile
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2008-2009. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-#
-# Invoke with GNU make or clearmake -C gnu.
-#
-
-include $(ERL_TOP)/make/run_make.mk
-
-table:
- $(MAKE) -f $(TARGET)/Makefile $@ \ No newline at end of file
diff --git a/erts/emulator/pcre/Makefile.in b/erts/emulator/pcre/Makefile.in
deleted file mode 100644
index f62700ec4e..0000000000
--- a/erts/emulator/pcre/Makefile.in
+++ /dev/null
@@ -1,165 +0,0 @@
-# Makefile for zlib
-# Copyright (C) 1995-1996 Jean-loup Gailly.
-# For conditions of distribution and use, see copyright notice in zlib.h
-
-# To compile and test, type:
-# ./configure; make test
-# The call of configure is optional if you don't have special requirements
-
-# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type:
-# make install
-# To install in $HOME instead of /usr/local, use:
-# make install prefix=$HOME
-
-# %ExternalCopyright%
-
-ARFLAGS = rc
-
-O = \
-pcre_latin_1_table.o \
-pcre_compile.o \
-pcre_config.o \
-pcre_dfa_exec.o \
-pcre_exec.o \
-pcre_fullinfo.o \
-pcre_get.o \
-pcre_globals.o \
-pcre_info.o \
-pcre_maketables.o \
-pcre_newline.o \
-pcre_ord2utf8.o \
-pcre_refcount.o \
-pcre_study.o \
-pcre_tables.o \
-pcre_try_flipped.o \
-pcre_ucp_searchfuncs.o \
-pcre_valid_utf8.o \
-pcre_version.o \
-pcre_xclass.o
-
-OBJS = $(O:%=$(OBJDIR)/%)
-
-GENINC = pcre_exec_loop_break_cases.inc
-
-#### Begin OTP targets
-
-include $(ERL_TOP)/make/target.mk
-
-# On windows we need a separate zlib during debug build
-ifeq ($(TARGET),win32)
-
-ifeq ($(TYPE),debug)
-CFLAGS = $(subst -O2, -g, @CFLAGS@ @DEFS@ @DEBUG_FLAGS@ @EMU_THR_DEFS@ -DERLANG_INTEGRATION)
-else # debug
-CFLAGS = @CFLAGS@ @DEFS@ @EMU_THR_DEFS@ -DERLANG_INTEGRATION
-endif # debug
-
-else # win32
-
-ifeq ($(TYPE),debug)
-TYPE_FLAGS = @DEBUG_CFLAGS@
-else # debug
-ifeq ($(TYPE),gcov)
-TYPE_FLAGS = -O0 -fprofile-arcs -ftest-coverage
-else # gcov
-TYPE_FLAGS = -O3
-endif # gcov
-endif # debug
-
-CFLAGS = $(TYPE_FLAGS) $(subst -O2,, @CFLAGS@) @DEFS@ @EMU_THR_DEFS@ -DERLANG_INTEGRATION
-
-endif # win32
-
-OBJDIR = $(ERL_TOP)/erts/emulator/pcre/obj/$(TARGET)/$(TYPE)
-
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-ifeq ($(TARGET), win32)
-LIBRARY=$(OBJDIR)/epcre.lib
-else
-LIBRARY=$(OBJDIR)/libepcre.a
-endif
-
-all: $(LIBRARY)
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
-
-tests release_tests:
-
-docs release_docs release_docs_spec:
-
-clean:
- rm -f $(OBJS) $(OBJDIR)/libepcre.a
-
-#### end OTP targets
-
-ifeq ($(TARGET), win32)
-$(LIBRARY): $(OBJS)
- $(AR) -out:$@ $(OBJS)
-else
-$(LIBRARY): $(OBJS)
- $(AR) $(ARFLAGS) $@ $(OBJS)
- -@ ($(RANLIB) $@ || true) 2>/dev/null
-endif
-
-$(OBJDIR)/%.o: %.c
- $(CC) -c $(CFLAGS) -o $@ $<
-
-$(GENINC): pcre_exec.c
- for x in `grep -n COST_CHK pcre_exec.c | grep -v 'COST_CHK(N)' | awk -F: '{print $$1}'`; \
- do \
- N=`expr $$x + 100`; \
- echo "case $$N: goto L_LOOP_COUNT_$${x};"; \
- done > $(GENINC)
-
-table: ./gen_table
- ./gen_table pcre_latin_1_table.c
-
-./gen_table: pcre_make_latin1_default.c make_latin1_table.c
- $(CC) $(CFLAGS) -o gen_table pcre_make_latin1_default.c make_latin1_table.c
-
-# DO NOT DELETE THIS LINE -- make depend depends on it.
-
-$(OBJDIR)/pcre_chartables.o: pcre_chartables.c pcre_internal.h local_config.h \
- pcre.h ucp.h
-$(OBJDIR)/pcre_compile.o: pcre_compile.c pcre_internal.h local_config.h \
- pcre.h ucp.h
-$(OBJDIR)/pcre_config.o: pcre_config.c pcre_internal.h local_config.h pcre.h \
- ucp.h
-$(OBJDIR)/pcre_dfa_exec.o: pcre_dfa_exec.c pcre_internal.h local_config.h \
- pcre.h ucp.h
-$(OBJDIR)/pcre_exec.o: pcre_exec.c pcre_internal.h local_config.h pcre.h ucp.h \
- $(GENINC)
-$(OBJDIR)/pcre_fullinfo.o: pcre_fullinfo.c pcre_internal.h local_config.h \
- pcre.h ucp.h
-$(OBJDIR)/pcre_get.o: pcre_get.c pcre_internal.h local_config.h pcre.h ucp.h
-$(OBJDIR)/pcre_globals.o: pcre_globals.c pcre_internal.h local_config.h \
- pcre.h ucp.h
-$(OBJDIR)/pcre_info.o: pcre_info.c pcre_internal.h local_config.h pcre.h ucp.h
-$(OBJDIR)/pcre_maketables.o: pcre_maketables.c pcre_internal.h local_config.h \
- pcre.h ucp.h
-$(OBJDIR)/pcre_newline.o: pcre_newline.c pcre_internal.h local_config.h \
- pcre.h ucp.h
-$(OBJDIR)/pcre_ord2utf8.o: pcre_ord2utf8.c pcre_internal.h local_config.h \
- pcre.h ucp.h
-$(OBJDIR)/pcre_refcount.o: pcre_refcount.c pcre_internal.h local_config.h \
- pcre.h ucp.h
-$(OBJDIR)/pcre_study.o: pcre_study.c pcre_internal.h local_config.h pcre.h \
- ucp.h
-$(OBJDIR)/pcre_tables.o: pcre_tables.c pcre_internal.h local_config.h pcre.h \
- ucp.h
-$(OBJDIR)/pcre_try_flipped.o: pcre_try_flipped.c pcre_internal.h \
- local_config.h pcre.h ucp.h
-$(OBJDIR)/pcre_ucp_searchfuncs.o: pcre_ucp_searchfuncs.c pcre_internal.h \
- local_config.h pcre.h ucp.h ucpinternal.h ucptable.h
-$(OBJDIR)/pcre_valid_utf8.o: pcre_valid_utf8.c pcre_internal.h local_config.h \
- pcre.h ucp.h
-pcre_version.o: pcre_version.c pcre_internal.h local_config.h pcre.h \
- ucp.h
-$(OBJDIR)/pcre_xclass.o: pcre_xclass.c pcre_internal.h local_config.h pcre.h \
- ucp.h
diff --git a/erts/emulator/pcre/pcre.mk b/erts/emulator/pcre/pcre.mk
new file mode 100644
index 0000000000..b752c11459
--- /dev/null
+++ b/erts/emulator/pcre/pcre.mk
@@ -0,0 +1,113 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+
+ARFLAGS = rc
+
+PCRE_O = \
+pcre_latin_1_table.o \
+pcre_compile.o \
+pcre_config.o \
+pcre_dfa_exec.o \
+pcre_exec.o \
+pcre_fullinfo.o \
+pcre_get.o \
+pcre_globals.o \
+pcre_info.o \
+pcre_maketables.o \
+pcre_newline.o \
+pcre_ord2utf8.o \
+pcre_refcount.o \
+pcre_study.o \
+pcre_tables.o \
+pcre_try_flipped.o \
+pcre_ucp_searchfuncs.o \
+pcre_valid_utf8.o \
+pcre_version.o \
+pcre_xclass.o
+
+PCRE_OBJS = $(PCRE_O:%=$(PCRE_OBJDIR)/%)
+
+GENINC = pcre/pcre_exec_loop_break_cases.inc
+
+PCRE_OBJDIR = $(ERL_TOP)/erts/emulator/pcre/obj/$(TARGET)/$(TYPE)
+
+PCRE_CFLAGS = $(filter-out -DDEBUG,$(CFLAGS)) -DERLANG_INTEGRATION
+
+ifeq ($(TARGET), win32)
+$(EPCRE_LIB): $(PCRE_OBJS)
+ $(AR) -out:$@ $(PCRE_OBJS)
+else
+$(EPCRE_LIB): $(PCRE_OBJS)
+ $(AR) $(ARFLAGS) $@ $(PCRE_OBJS)
+ -@ ($(RANLIB) $@ || true) 2>/dev/null
+endif
+
+$(PCRE_OBJDIR)/%.o: pcre/%.c
+ $(CC) -c $(PCRE_CFLAGS) -o $@ $<
+
+$(GENINC): pcre/pcre_exec.c
+ for x in `grep -n COST_CHK pcre/pcre_exec.c | grep -v 'COST_CHK(N)' | awk -F: '{print $$1}'`; \
+ do \
+ N=`expr $$x + 100`; \
+ echo "case $$N: goto L_LOOP_COUNT_$${x};"; \
+ done > $(GENINC)
+
+# Dependencies.
+
+$(PCRE_OBJDIR)/pcre_chartables.o: pcre/pcre_chartables.c pcre/pcre_internal.h \
+ pcre/local_config.h pcre/pcre.h pcre/ucp.h
+$(PCRE_OBJDIR)/pcre_compile.o: pcre/pcre_compile.c pcre/pcre_internal.h \
+ pcre/local_config.h pcre/pcre.h pcre/ucp.h
+$(PCRE_OBJDIR)/pcre_config.o: pcre/pcre_config.c pcre/pcre_internal.h \
+ pcre/local_config.h pcre/pcre.h pcre/ucp.h
+$(PCRE_OBJDIR)/pcre_dfa_exec.o: pcre/pcre_dfa_exec.c pcre/pcre_internal.h \
+ pcre/local_config.h pcre/pcre.h pcre/ucp.h
+$(PCRE_OBJDIR)/pcre_exec.o: pcre/pcre_exec.c pcre/pcre_internal.h \
+ pcre/local_config.h pcre/pcre.h pcre/ucp.h $(GENINC)
+$(PCRE_OBJDIR)/pcre_fullinfo.o: pcre/pcre_fullinfo.c pcre/pcre_internal.h \
+ pcre/local_config.h pcre/pcre.h pcre/ucp.h
+$(PCRE_OBJDIR)/pcre_get.o: pcre/pcre_get.c pcre/pcre_internal.h \
+ pcre/local_config.h pcre/pcre.h pcre/ucp.h
+$(PCRE_OBJDIR)/pcre_globals.o: pcre/pcre_globals.c pcre/pcre_internal.h \
+ pcre/local_config.h pcre/pcre.h pcre/ucp.h
+$(PCRE_OBJDIR)/pcre_info.o: pcre/pcre_info.c pcre/pcre_internal.h \
+ pcre/local_config.h pcre/pcre.h pcre/ucp.h
+$(PCRE_OBJDIR)/pcre_maketables.o: pcre/pcre_maketables.c pcre/pcre_internal.h \
+ pcre/local_config.h pcre/pcre.h pcre/ucp.h
+$(PCRE_OBJDIR)/pcre_newline.o: pcre/pcre_newline.c pcre/pcre_internal.h \
+ pcre/local_config.h pcre/pcre.h pcre/ucp.h
+$(PCRE_OBJDIR)/pcre_ord2utf8.o: pcre/pcre_ord2utf8.c pcre/pcre_internal.h \
+ pcre/local_config.h pcre/pcre.h pcre/ucp.h
+$(PCRE_OBJDIR)/pcre/pcre_refcount.o: pcre/pcre_refcount.c pcre/pcre_internal.h \
+ pcre/local_config.h pcre/pcre.h pcre/ucp.h
+$(PCRE_OBJDIR)/pcre_study.o: pcre/pcre_study.c pcre/pcre_internal.h \
+ pcre/local_config.h pcre/pcre.h pcre/ucp.h
+$(PCRE_OBJDIR)/pcre_tables.o: pcre/pcre_tables.c pcre/pcre_internal.h \
+ pcre/local_config.h pcre/pcre.h pcre/ucp.h
+$(PCRE_OBJDIR)/pcre_try_flipped.o: pcre/pcre_try_flipped.c pcre/pcre_internal.h \
+ pcre/local_config.h pcre/pcre.h pcre/ucp.h
+$(PCRE_OBJDIR)/pcre_ucp_searchfuncs.o: pcre/pcre_ucp_searchfuncs.c \
+ pcre/pcre_internal.h pcre/local_config.h pcre/pcre.h pcre/ucp.h \
+ pcre/ucpinternal.h pcre/ucptable.h
+$(PCRE_OBJDIR)/pcre_valid_utf8.o: pcre/pcre_valid_utf8.c pcre/pcre_internal.h \
+ pcre/local_config.h pcre/pcre.h pcre/ucp.h
+pcre_version.o: pcre/pcre_version.c pcre/pcre_internal.h pcre/local_config.h \
+ pcre/pcre.h pcre/ucp.h
+$(PCRE_OBJDIR)/pcre/pcre_xclass.o: pcre/pcre_xclass.c pcre/pcre_internal.h \
+ pcre/local_config.h pcre/pcre.h pcre/ucp.h
diff --git a/erts/emulator/sys/common/erl_check_io.c b/erts/emulator/sys/common/erl_check_io.c
index cd4de21d65..ba88fd1d39 100644
--- a/erts/emulator/sys/common/erl_check_io.c
+++ b/erts/emulator/sys/common/erl_check_io.c
@@ -35,6 +35,7 @@
#include "sys.h"
#include "global.h"
#include "erl_check_io.h"
+#include "erl_thr_progress.h"
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
# define ERTS_DRV_EV_STATE_EXTRA_SIZE 128
@@ -66,6 +67,9 @@ typedef char EventStateFlags;
#define ERTS_CIO_POLL_CTL ERTS_POLL_EXPORT(erts_poll_control)
#define ERTS_CIO_POLL_WAIT ERTS_POLL_EXPORT(erts_poll_wait)
+#ifdef ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT
+#define ERTS_CIO_POLL_AS_INTR ERTS_POLL_EXPORT(erts_poll_async_sig_interrupt)
+#endif
#define ERTS_CIO_POLL_INTR ERTS_POLL_EXPORT(erts_poll_interrupt)
#define ERTS_CIO_POLL_INTR_TMD ERTS_POLL_EXPORT(erts_poll_interrupt_timed)
#define ERTS_CIO_NEW_POLLSET ERTS_POLL_EXPORT(erts_poll_create_pollset)
@@ -218,7 +222,7 @@ remember_removed(ErtsDrvEventState *state, struct pollset_info* psi)
#ifdef ERTS_SMP
struct removed_fd *fdlp;
ERTS_SMP_LC_ASSERT(erts_smp_lc_mtx_is_locked(fd_mtx(state->fd)));
- if (erts_smp_atomic_read(&psi->in_poll_wait)) {
+ if (erts_smp_atomic_read_nob(&psi->in_poll_wait)) {
state->remove_cnt++;
ASSERT(state->remove_cnt > 0);
fdlp = removed_fd_alloc();
@@ -333,7 +337,7 @@ grow_drv_ev_state(int min_ix)
new_len = max_fds;
erts_smp_mtx_lock(&drv_ev_state_grow_lock);
- if (erts_smp_atomic_read(&drv_ev_state_len) <= min_ix) {
+ if (erts_smp_atomic_read_nob(&drv_ev_state_len) <= min_ix) {
for (i=0; i<DRV_EV_STATE_LOCK_CNT; i++) { /* lock all fd's */
erts_smp_mtx_lock(&drv_ev_state_locks[i].lck);
}
@@ -343,7 +347,7 @@ grow_drv_ev_state(int min_ix)
sizeof(ErtsDrvEventState)*new_len)
: erts_alloc(ERTS_ALC_T_DRV_EV_STATE,
sizeof(ErtsDrvEventState)*new_len));
- for (i = erts_smp_atomic_read(&drv_ev_state_len); i < new_len; i++) {
+ for (i = erts_smp_atomic_read_nob(&drv_ev_state_len); i < new_len; i++) {
drv_ev_state[i].fd = (ErtsSysFdType) i;
drv_ev_state[i].driver.select = NULL;
drv_ev_state[i].events = 0;
@@ -351,7 +355,7 @@ grow_drv_ev_state(int min_ix)
drv_ev_state[i].type = ERTS_EV_TYPE_NONE;
drv_ev_state[i].flags = 0;
}
- erts_smp_atomic_set(&drv_ev_state_len, new_len);
+ erts_smp_atomic_set_nob(&drv_ev_state_len, new_len);
for (i=0; i<DRV_EV_STATE_LOCK_CNT; i++) {
erts_smp_mtx_unlock(&drv_ev_state_locks[i].lck);
}
@@ -497,7 +501,7 @@ ERTS_CIO_EXPORT(driver_select)(ErlDrvPort ix,
&& erts_lc_is_port_locked(erts_drvport2port(ix)));
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
- if ((unsigned)fd >= (unsigned)erts_smp_atomic_read(&drv_ev_state_len)) {
+ if ((unsigned)fd >= (unsigned)erts_smp_atomic_read_nob(&drv_ev_state_len)) {
if (fd < 0) {
return -1;
}
@@ -709,7 +713,7 @@ ERTS_CIO_EXPORT(driver_event)(ErlDrvPort ix,
&& erts_lc_is_port_locked(erts_drvport2port(ix)));
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
- if ((unsigned)fd >= (unsigned)erts_smp_atomic_read(&drv_ev_state_len)) {
+ if ((unsigned)fd >= (unsigned)erts_smp_atomic_read_nob(&drv_ev_state_len)) {
if (fd < 0)
return -1;
if (fd >= max_fds) {
@@ -1115,6 +1119,14 @@ eready(Eterm id, ErtsDrvEventState *state, ErlDrvEventData event_data)
static void bad_fd_in_pollset( ErtsDrvEventState *, Eterm, Eterm, ErtsPollEvents);
+#ifdef ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT
+void
+ERTS_CIO_EXPORT(erts_check_io_async_sig_interrupt)(void)
+{
+ ERTS_CIO_POLL_AS_INTR(pollset.ps);
+}
+#endif
+
void
ERTS_CIO_EXPORT(erts_check_io_interrupt)(int set)
{
@@ -1153,17 +1165,15 @@ ERTS_CIO_EXPORT(erts_check_io)(int do_wait)
#ifdef ERTS_ENABLE_LOCK_CHECK
erts_lc_check_exact(NULL, 0); /* No locks should be locked */
#endif
- erts_smp_activity_begin(ERTS_ACTIVITY_WAIT, NULL, NULL, NULL);
pollres_len = sizeof(pollres)/sizeof(ErtsPollResFd);
- erts_smp_atomic_set(&pollset.in_poll_wait, 1);
+ erts_smp_atomic_set_nob(&pollset.in_poll_wait, 1);
poll_ret = ERTS_CIO_POLL_WAIT(pollset.ps, pollres, &pollres_len, &wait_time);
#ifdef ERTS_ENABLE_LOCK_CHECK
erts_lc_check_exact(NULL, 0); /* No locks should be locked */
#endif
- erts_smp_activity_end(ERTS_ACTIVITY_WAIT, NULL, NULL, NULL);
erts_deliver_time(); /* sync the machine's idea of time */
@@ -1173,7 +1183,7 @@ ERTS_CIO_EXPORT(erts_check_io)(int do_wait)
#endif
if (poll_ret != 0) {
- erts_smp_atomic_set(&pollset.in_poll_wait, 0);
+ erts_smp_atomic_set_nob(&pollset.in_poll_wait, 0);
forget_removed(&pollset);
if (poll_ret == EAGAIN) {
goto restart;
@@ -1304,7 +1314,7 @@ ERTS_CIO_EXPORT(erts_check_io)(int do_wait)
#endif
}
- erts_smp_atomic_set(&pollset.in_poll_wait, 0);
+ erts_smp_atomic_set_nob(&pollset.in_poll_wait, 0);
forget_removed(&pollset);
}
@@ -1419,7 +1429,7 @@ static void drv_ev_state_free(void *des)
void
ERTS_CIO_EXPORT(erts_init_check_io)(void)
{
- erts_smp_atomic_init(&pollset.in_poll_wait, 0);
+ erts_smp_atomic_init_nob(&pollset.in_poll_wait, 0);
ERTS_CIO_POLL_INIT();
pollset.ps = ERTS_CIO_NEW_POLLSET();
@@ -1441,7 +1451,7 @@ ERTS_CIO_EXPORT(erts_init_check_io)(void)
#endif
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
max_fds = ERTS_CIO_POLL_MAX_FDS();
- erts_smp_atomic_init(&drv_ev_state_len, 0);
+ erts_smp_atomic_init_nob(&drv_ev_state_len, 0);
drv_ev_state = NULL;
erts_smp_mtx_init(&drv_ev_state_grow_lock, "drv_ev_state_grow");
#else
@@ -1479,7 +1489,7 @@ ERTS_CIO_EXPORT(erts_check_io_size)(void)
ERTS_CIO_POLL_INFO(pollset.ps, &pi);
res = pi.memory_size;
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
- res += sizeof(ErtsDrvEventState) * erts_smp_atomic_read(&drv_ev_state_len);
+ res += sizeof(ErtsDrvEventState) * erts_smp_atomic_read_nob(&drv_ev_state_len);
#else
res += safe_hash_table_sz(&drv_ev_state_tab);
{
@@ -1506,7 +1516,7 @@ ERTS_CIO_EXPORT(erts_check_io_info)(void *proc)
ERTS_CIO_POLL_INFO(pollset.ps, &pi);
memory_size = pi.memory_size;
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
- memory_size += sizeof(ErtsDrvEventState) * erts_smp_atomic_read(&drv_ev_state_len);
+ memory_size += sizeof(ErtsDrvEventState) * erts_smp_atomic_read_nob(&drv_ev_state_len);
#else
memory_size += safe_hash_table_sz(&drv_ev_state_tab);
{
@@ -1870,13 +1880,12 @@ ERTS_CIO_EXPORT(erts_check_io_debug)(void)
erts_printf("--- fds in pollset --------------------------------------\n");
-#ifdef ERTS_SMP
-# ifdef ERTS_ENABLE_LOCK_CHECK
+#if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK)
erts_lc_check_exact(NULL, 0); /* No locks should be locked */
-# endif
- erts_block_system(0); /* stop the world to avoid messy locking */
#endif
+ erts_smp_thr_progress_block(); /* stop the world to avoid messy locking */
+
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
counters.epep = erts_alloc(ERTS_ALC_T_TMP, sizeof(ErtsPollEvents)*max_fds);
ERTS_POLL_EXPORT(erts_poll_get_selected_events)(pollset.ps, counters.epep, max_fds);
@@ -1886,7 +1895,7 @@ ERTS_CIO_EXPORT(erts_check_io_debug)(void)
counters.num_errors = 0;
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
- len = erts_smp_atomic_read(&drv_ev_state_len);
+ len = erts_smp_atomic_read_nob(&drv_ev_state_len);
for (fd = 0; fd < len; fd++) {
doit_erts_check_io_debug((void *) &drv_ev_state[fd], (void *) &counters);
}
@@ -1898,9 +1907,7 @@ ERTS_CIO_EXPORT(erts_check_io_debug)(void)
safe_hash_for_each(&drv_ev_state_tab, &doit_erts_check_io_debug, (void *) &counters);
#endif
-#ifdef ERTS_SMP
- erts_release_system();
-#endif
+ erts_smp_thr_progress_unblock();
erts_printf("\n");
erts_printf("used fds=%d\n", counters.used_fds);
diff --git a/erts/emulator/sys/common/erl_check_io.h b/erts/emulator/sys/common/erl_check_io.h
index 9b45a63913..7cc1658062 100644
--- a/erts/emulator/sys/common/erl_check_io.h
+++ b/erts/emulator/sys/common/erl_check_io.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2006-2009. All Rights Reserved.
+ * Copyright Ericsson AB 2006-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -40,6 +40,10 @@ Eterm erts_check_io_info_kp(void *);
Eterm erts_check_io_info_nkp(void *);
int erts_check_io_max_files_kp(void);
int erts_check_io_max_files_nkp(void);
+#ifdef ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT
+void erts_check_io_async_sig_interrupt_kp(void);
+void erts_check_io_async_sig_interrupt_nkp(void);
+#endif
void erts_check_io_interrupt_kp(int);
void erts_check_io_interrupt_nkp(int);
void erts_check_io_interrupt_timed_kp(int, long);
@@ -56,6 +60,9 @@ int erts_check_io_debug_nkp(void);
Uint erts_check_io_size(void);
Eterm erts_check_io_info(void *);
int erts_check_io_max_files(void);
+#ifdef ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT
+void erts_check_io_async_sig_interrupt(void);
+#endif
void erts_check_io_interrupt(int);
void erts_check_io_interrupt_timed(int, long);
void erts_check_io(int);
diff --git a/erts/emulator/sys/common/erl_mseg.c b/erts/emulator/sys/common/erl_mseg.c
index eaef6680dd..49750ff6ce 100644
--- a/erts/emulator/sys/common/erl_mseg.c
+++ b/erts/emulator/sys/common/erl_mseg.c
@@ -36,14 +36,12 @@
#include "erl_threads.h"
#include "erl_mtrace.h"
#include "erl_time.h"
+#include "erl_alloc.h"
#include "big.h"
+#include "erl_thr_progress.h"
#if HAVE_ERTS_MSEG
-#if defined(USE_THREADS) && !defined(ERTS_SMP)
-# define ERTS_THREADS_NO_SMP
-#endif
-
#define SEGTYPE ERTS_MTRACE_SEGMENT_ID
#ifndef HAVE_GETPAGESIZE
@@ -75,16 +73,9 @@
static int atoms_initialized;
-static Uint cache_check_interval;
-
typedef struct mem_kind_t MemKind;
-static void check_cache(void *unused);
static void mseg_clear_cache(MemKind*);
-static int is_cache_check_scheduled;
-#ifdef ERTS_THREADS_NO_SMP
-static int is_cache_check_requested;
-#endif
#if HALFWORD_HEAP
static int initialize_pmmap(void);
@@ -138,7 +129,8 @@ const ErtsMsegOpt_t erts_mseg_default_opt = {
1, /* Use cache */
1, /* Preserv data */
0, /* Absolute shrink threshold */
- 0 /* Relative shrink threshold */
+ 0, /* Relative shrink threshold */
+ 0 /* Scheduler specific */
#if HALFWORD_HEAP
,0 /* need low memory */
#endif
@@ -157,11 +149,10 @@ typedef struct {
Uint32 no;
} CallCounter;
-static int is_init_done;
static Uint page_size;
static Uint page_shift;
-static struct {
+typedef struct {
CallCounter alloc;
CallCounter dealloc;
CallCounter realloc;
@@ -172,7 +163,9 @@ static struct {
#endif
CallCounter clear_cache;
CallCounter check_cache;
-} calls;
+} ErtsMsegCalls;
+
+typedef struct ErtsMsegAllctr_t_ ErtsMsegAllctr_t;
struct mem_kind_t {
cache_desc_t cache_descs[MAX_CACHE_SIZE];
@@ -201,25 +194,84 @@ struct mem_kind_t {
} max_ever;
} segments;
+ ErtsMsegAllctr_t *ma;
const char* name;
MemKind* next;
};/*MemKind*/
+struct ErtsMsegAllctr_t_ {
+ int ix;
+
+ int is_init_done;
+ int is_thread_safe;
+ erts_mtx_t mtx;
+
+ int is_cache_check_scheduled;
+
+ MemKind* mk_list;
+
#if HALFWORD_HEAP
-static MemKind low_mem, hi_mem;
+ MemKind low_mem;
+ MemKind hi_mem;
#else
-static MemKind the_mem;
+ MemKind the_mem;
#endif
-static MemKind* mk_list = NULL;
-static Uint max_cache_size;
-static Uint abs_max_cache_bad_fit;
-static Uint rel_max_cache_bad_fit;
+ Uint max_cache_size;
+ Uint abs_max_cache_bad_fit;
+ Uint rel_max_cache_bad_fit;
+
+ ErtsMsegCalls calls;
#if CAN_PARTLY_DESTROY
-static Uint min_seg_size;
+ Uint min_seg_size;
+#endif
+
+};
+
+typedef union {
+ ErtsMsegAllctr_t mseg_alloc;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsMsegAllctr_t))];
+} ErtsAlgndMsegAllctr_t;
+
+static int no_mseg_allocators;
+static ErtsAlgndMsegAllctr_t *aligned_mseg_allctr;
+
+#ifdef ERTS_SMP
+
+#define ERTS_MSEG_ALLCTR_IX(IX) \
+ (&aligned_mseg_allctr[(IX)].mseg_alloc)
+
+#define ERTS_MSEG_ALLCTR_SS() \
+ ERTS_MSEG_ALLCTR_IX((int) erts_get_scheduler_id())
+
+#define ERTS_MSEG_ALLCTR_OPT(OPT) \
+ ((OPT)->sched_spec ? ERTS_MSEG_ALLCTR_SS() : ERTS_MSEG_ALLCTR_IX(0))
+
+#else
+
+#define ERTS_MSEG_ALLCTR_IX(IX) \
+ (&aligned_mseg_allctr[0].mseg_alloc)
+
+#define ERTS_MSEG_ALLCTR_SS() \
+ (&aligned_mseg_allctr[0].mseg_alloc)
+
+#define ERTS_MSEG_ALLCTR_OPT(OPT) \
+ (&aligned_mseg_allctr[0].mseg_alloc)
+
#endif
+#define ERTS_MSEG_LOCK(MA) \
+do { \
+ if ((MA)->is_thread_safe) \
+ erts_mtx_lock(&(MA)->mtx); \
+} while (0)
+
+#define ERTS_MSEG_UNLOCK(MA) \
+do { \
+ if ((MA)->is_thread_safe) \
+ erts_mtx_unlock(&(MA)->mtx); \
+} while (0)
#define ERTS_MSEG_ALLOC_STAT(C,SZ) \
do { \
@@ -250,104 +302,44 @@ do { \
#define ONE_GIGA (1000000000)
-#define ZERO_CC(CC) (calls.CC.no = 0, calls.CC.giga_no = 0)
+#define ZERO_CC(MA, CC) ((MA)->calls.CC.no = 0, \
+ (MA)->calls.CC.giga_no = 0)
-#define INC_CC(CC) (calls.CC.no == ONE_GIGA - 1 \
- ? (calls.CC.giga_no++, calls.CC.no = 0) \
- : calls.CC.no++)
+#define INC_CC(MA, CC) ((MA)->calls.CC.no == ONE_GIGA - 1 \
+ ? ((MA)->calls.CC.giga_no++, \
+ (MA)->calls.CC.no = 0) \
+ : (MA)->calls.CC.no++)
-#define DEC_CC(CC) (calls.CC.no == 0 \
- ? (calls.CC.giga_no--, \
- calls.CC.no = ONE_GIGA - 1) \
- : calls.CC.no--)
+#define DEC_CC(MA, CC) ((MA)->calls.CC.no == 0 \
+ ? ((MA)->calls.CC.giga_no--, \
+ (MA)->calls.CC.no = ONE_GIGA - 1) \
+ : (MA)->calls.CC.no--)
-static erts_mtx_t mseg_mutex; /* Also needed when !USE_THREADS */
static erts_mtx_t init_atoms_mutex; /* Also needed when !USE_THREADS */
-#ifdef USE_THREADS
-#ifdef ERTS_THREADS_NO_SMP
-static erts_tid_t main_tid;
-static int async_handle = -1;
-#endif
-
-static void thread_safe_init(void)
-{
- erts_mtx_init(&init_atoms_mutex, "mseg_init_atoms");
- erts_mtx_init(&mseg_mutex, "mseg");
-
-#ifdef ERTS_THREADS_NO_SMP
- main_tid = erts_thr_self();
-#endif
-}
-
-#endif
-
-static ErlTimer cache_check_timer;
static ERTS_INLINE void
-schedule_cache_check(void)
-{
- if (!is_cache_check_scheduled && is_init_done) {
-#ifdef ERTS_THREADS_NO_SMP
- if (!erts_equal_tids(erts_thr_self(), main_tid)) {
- if (!is_cache_check_requested) {
- is_cache_check_requested = 1;
- sys_async_ready(async_handle);
- }
- }
- else
-#endif
- {
- cache_check_timer.active = 0;
- erts_set_timer(&cache_check_timer,
- check_cache,
- NULL,
- NULL,
- cache_check_interval);
- is_cache_check_scheduled = 1;
-#ifdef ERTS_THREADS_NO_SMP
- is_cache_check_requested = 0;
-#endif
- }
- }
-}
-
-#ifdef ERTS_THREADS_NO_SMP
-
-static void
-check_schedule_cache_check(void)
+schedule_cache_check(ErtsMsegAllctr_t *ma)
{
- erts_mtx_lock(&mseg_mutex);
- if (is_cache_check_requested
- && !is_cache_check_scheduled) {
- schedule_cache_check();
- }
- erts_mtx_unlock(&mseg_mutex);
-}
-
-#endif
-static void
-mseg_shutdown(void)
-{
- MemKind* mk;
- erts_mtx_lock(&mseg_mutex);
- for (mk=mk_list; mk; mk=mk->next) {
- mseg_clear_cache(mk);
+ if (!ma->is_cache_check_scheduled && ma->is_init_done) {
+ erts_set_aux_work_timeout(ma->ix,
+ ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK,
+ 1);
+ ma->is_cache_check_scheduled = 1;
}
- erts_mtx_unlock(&mseg_mutex);
}
static ERTS_INLINE void *
-mseg_create(MemKind* mk, Uint size)
+mseg_create(ErtsMsegAllctr_t *ma, MemKind* mk, Uint size)
{
void *seg;
ASSERT(size % page_size == 0);
#if HALFWORD_HEAP
- if (mk == &low_mem) {
+ if (mk == &ma->low_mem) {
seg = pmmap(size);
if ((unsigned long) seg & CHECK_POINTER_MASK) {
erts_fprintf(stderr,"Pointer mask failure (0x%08lx)\n",(unsigned long) seg);
@@ -371,18 +363,18 @@ mseg_create(MemKind* mk, Uint size)
#endif
}
- INC_CC(create);
+ INC_CC(ma, create);
return seg;
}
static ERTS_INLINE void
-mseg_destroy(MemKind* mk, void *seg, Uint size)
+mseg_destroy(ErtsMsegAllctr_t *ma, MemKind* mk, void *seg, Uint size)
{
int res;
#if HALFWORD_HEAP
- if (mk == &low_mem) {
+ if (mk == &ma->low_mem) {
res = pmunmap((void *) seg, size);
}
else
@@ -401,14 +393,14 @@ mseg_destroy(MemKind* mk, void *seg, Uint size)
ASSERT(size % page_size == 0);
ASSERT(res == 0);
- INC_CC(destroy);
+ INC_CC(ma, destroy);
}
#if HAVE_MSEG_RECREATE
static ERTS_INLINE void *
-mseg_recreate(MemKind* mk, void *old_seg, Uint old_size, Uint new_size)
+mseg_recreate(ErtsMsegAllctr_t *ma, MemKind* mk, void *old_seg, Uint old_size, Uint new_size)
{
void *new_seg;
@@ -416,7 +408,7 @@ mseg_recreate(MemKind* mk, void *old_seg, Uint old_size, Uint new_size)
ASSERT(new_size % page_size == 0);
#if HALFWORD_HEAP
- if (mk == &low_mem) {
+ if (mk == &ma->low_mem) {
new_seg = (void *) pmremap((void *) old_seg,
(size_t) old_size,
(size_t) new_size);
@@ -447,19 +439,37 @@ mseg_recreate(MemKind* mk, void *old_seg, Uint old_size, Uint new_size)
#endif
}
- INC_CC(recreate);
+ INC_CC(ma, recreate);
return new_seg;
}
#endif /* #if HAVE_MSEG_RECREATE */
+#ifdef DEBUG
+#define ERTS_DBG_MA_CHK_THR_ACCESS(MA) \
+do { \
+ if ((MA)->is_thread_safe) \
+ ERTS_LC_ASSERT(erts_lc_mtx_is_locked(&(MA)->mtx) \
+ || erts_smp_thr_progress_is_blocking() \
+ || ERTS_IS_CRASH_DUMPING); \
+ else \
+ ERTS_LC_ASSERT((MA)->ix == (int) erts_get_scheduler_id() \
+ || erts_smp_thr_progress_is_blocking() \
+ || ERTS_IS_CRASH_DUMPING); \
+} while (0)
+#define ERTS_DBG_MK_CHK_THR_ACCESS(MK) \
+ ERTS_DBG_MA_CHK_THR_ACCESS((MK)->ma)
+#else
+#define ERTS_DBG_MA_CHK_THR_ACCESS(MA)
+#define ERTS_DBG_MK_CHK_THR_ACCESS(MK)
+#endif
static ERTS_INLINE cache_desc_t *
alloc_cd(MemKind* mk)
{
cache_desc_t *cd = mk->free_cache_descs;
- ERTS_LC_ASSERT(erts_lc_mtx_is_locked(&mseg_mutex));
+ ERTS_DBG_MK_CHK_THR_ACCESS(mk);
if (cd)
mk->free_cache_descs = cd->next;
return cd;
@@ -468,7 +478,7 @@ alloc_cd(MemKind* mk)
static ERTS_INLINE void
free_cd(MemKind* mk, cache_desc_t *cd)
{
- ERTS_LC_ASSERT(erts_lc_mtx_is_locked(&mseg_mutex));
+ ERTS_DBG_MK_CHK_THR_ACCESS(mk);
cd->next = mk->free_cache_descs;
mk->free_cache_descs = cd;
}
@@ -477,7 +487,7 @@ free_cd(MemKind* mk, cache_desc_t *cd)
static ERTS_INLINE void
link_cd(MemKind* mk, cache_desc_t *cd)
{
- ERTS_LC_ASSERT(erts_lc_mtx_is_locked(&mseg_mutex));
+ ERTS_DBG_MK_CHK_THR_ACCESS(mk);
if (mk->cache)
mk->cache->prev = cd;
cd->next = mk->cache;
@@ -496,7 +506,7 @@ link_cd(MemKind* mk, cache_desc_t *cd)
static ERTS_INLINE void
end_link_cd(MemKind* mk, cache_desc_t *cd)
{
- ERTS_LC_ASSERT(erts_lc_mtx_is_locked(&mseg_mutex));
+ ERTS_DBG_MK_CHK_THR_ACCESS(mk);
if (mk->cache_end)
mk->cache_end->next = cd;
cd->next = NULL;
@@ -515,7 +525,7 @@ end_link_cd(MemKind* mk, cache_desc_t *cd)
static ERTS_INLINE void
unlink_cd(MemKind* mk, cache_desc_t *cd)
{
- ERTS_LC_ASSERT(erts_lc_mtx_is_locked(&mseg_mutex));
+ ERTS_DBG_MK_CHK_THR_ACCESS(mk);
if (cd->next)
cd->next->prev = cd->prev;
else
@@ -533,7 +543,7 @@ static ERTS_INLINE void
check_cache_limits(MemKind* mk)
{
cache_desc_t *cd;
- ERTS_LC_ASSERT(erts_lc_mtx_is_locked(&mseg_mutex));
+ ERTS_DBG_MK_CHK_THR_ACCESS(mk);
mk->max_cached_seg_size = 0;
mk->min_cached_seg_size = ~((Uint) 0);
for (cd = mk->cache; cd; cd = cd->next) {
@@ -551,7 +561,7 @@ adjust_cache_size(MemKind* mk, int force_check_limits)
int check_limits = force_check_limits;
Sint max_cached = ((Sint) mk->segments.current.watermark
- (Sint) mk->segments.current.no);
- ERTS_LC_ASSERT(erts_lc_mtx_is_locked(&mseg_mutex));
+ ERTS_DBG_MK_CHK_THR_ACCESS(mk);
while (((Sint) mk->cache_size) > max_cached && ((Sint) mk->cache_size) > 0) {
ASSERT(mk->cache_end);
cd = mk->cache_end;
@@ -562,7 +572,7 @@ adjust_cache_size(MemKind* mk, int force_check_limits)
}
if (erts_mtrace_enabled)
erts_mtrace_crr_free(SEGTYPE, SEGTYPE, cd->seg);
- mseg_destroy(mk, cd->seg, cd->size);
+ mseg_destroy(mk->ma, mk, cd->seg, cd->size);
unlink_cd(mk,cd);
free_cd(mk,cd);
}
@@ -571,7 +581,7 @@ adjust_cache_size(MemKind* mk, int force_check_limits)
check_cache_limits(mk);
}
-static void
+static Uint
check_one_cache(MemKind* mk)
{
if (mk->segments.current.watermark > mk->segments.current.no)
@@ -579,23 +589,37 @@ check_one_cache(MemKind* mk)
adjust_cache_size(mk, 0);
if (mk->cache_size)
- schedule_cache_check();
+ schedule_cache_check(mk->ma);
+ return mk->cache_size;
}
-static void check_cache(void* unused)
+static void do_cache_check(ErtsMsegAllctr_t *ma)
{
+ int empty_cache = 1;
MemKind* mk;
- erts_mtx_lock(&mseg_mutex);
- is_cache_check_scheduled = 0;
+ ERTS_MSEG_LOCK(ma);
- for (mk=mk_list; mk; mk=mk->next) {
- check_one_cache(mk);
+ for (mk=ma->mk_list; mk; mk=mk->next) {
+ if (check_one_cache(mk))
+ empty_cache = 0;
+ }
+
+ if (empty_cache) {
+ ma->is_cache_check_scheduled = 0;
+ erts_set_aux_work_timeout(ma->ix,
+ ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK,
+ 0);
}
- INC_CC(check_cache);
+ INC_CC(ma, check_cache);
- erts_mtx_unlock(&mseg_mutex);
+ ERTS_MSEG_UNLOCK(ma);
+}
+
+void erts_mseg_cache_check(void)
+{
+ do_cache_check(ERTS_MSEG_ALLCTR_SS());
}
static void
@@ -611,42 +635,44 @@ mseg_clear_cache(MemKind* mk)
mk->segments.current.watermark = mk->segments.current.no;
- INC_CC(clear_cache);
+ INC_CC(mk->ma, clear_cache);
}
-static ERTS_INLINE MemKind* memkind(const ErtsMsegOpt_t *opt)
+static ERTS_INLINE MemKind* memkind(ErtsMsegAllctr_t *ma,
+ const ErtsMsegOpt_t *opt)
{
#if HALFWORD_HEAP
- return opt->low_mem ? &low_mem : &hi_mem;
+ return opt->low_mem ? &ma->low_mem : &ma->hi_mem;
#else
- return &the_mem;
+ return &ma->the_mem;
#endif
}
static void *
-mseg_alloc(ErtsAlcType_t atype, Uint *size_p, const ErtsMsegOpt_t *opt)
+mseg_alloc(ErtsMsegAllctr_t *ma, ErtsAlcType_t atype, Uint *size_p,
+ const ErtsMsegOpt_t *opt)
{
Uint max, min, diff_size, size;
cache_desc_t *cd, *cand_cd;
void *seg;
- MemKind* mk = memkind(opt);
+ MemKind* mk = memkind(ma, opt);
- INC_CC(alloc);
+ INC_CC(ma, alloc);
size = PAGE_CEILING(*size_p);
#if CAN_PARTLY_DESTROY
- if (size < min_seg_size)
- min_seg_size = size;
+ if (size < ma->min_seg_size)
+ ma->min_seg_size = size;
#endif
if (!opt->cache) {
create_seg:
adjust_cache_size(mk,0);
- seg = mseg_create(mk, size);
+ seg = mseg_create(ma, mk, size);
if (!seg) {
mseg_clear_cache(mk);
- seg = mseg_create(mk, size);
+ seg = mseg_create(ma, mk, size);
if (!seg)
size = 0;
}
@@ -667,10 +693,10 @@ mseg_alloc(ErtsAlcType_t atype, Uint *size_p, const ErtsMsegOpt_t *opt)
diff_size = mk->min_cached_seg_size - size;
- if (diff_size > abs_max_cache_bad_fit)
+ if (diff_size > ma->abs_max_cache_bad_fit)
goto create_seg;
- if (100*PAGES(diff_size) > rel_max_cache_bad_fit*PAGES(size))
+ if (100*PAGES(diff_size) > ma->rel_max_cache_bad_fit*PAGES(size))
goto create_seg;
}
@@ -708,8 +734,8 @@ mseg_alloc(ErtsAlcType_t atype, Uint *size_p, const ErtsMsegOpt_t *opt)
diff_size = cand_cd->size - size;
- if (diff_size > abs_max_cache_bad_fit
- || 100*PAGES(diff_size) > rel_max_cache_bad_fit*PAGES(size)) {
+ if (diff_size > ma->abs_max_cache_bad_fit
+ || 100*PAGES(diff_size) > ma->rel_max_cache_bad_fit*PAGES(size)) {
if (mk->max_cached_seg_size < cand_cd->size)
mk->max_cached_seg_size = cand_cd->size;
if (mk->min_cached_seg_size > cand_cd->size)
@@ -740,18 +766,18 @@ mseg_alloc(ErtsAlcType_t atype, Uint *size_p, const ErtsMsegOpt_t *opt)
static void
-mseg_dealloc(ErtsAlcType_t atype, void *seg, Uint size,
+mseg_dealloc(ErtsMsegAllctr_t *ma, ErtsAlcType_t atype, void *seg, Uint size,
const ErtsMsegOpt_t *opt)
{
- MemKind* mk = memkind(opt);
+ MemKind* mk = memkind(ma, opt);
cache_desc_t *cd;
ERTS_MSEG_DEALLOC_STAT(mk,size);
- if (!opt->cache || max_cache_size == 0) {
+ if (!opt->cache || ma->max_cache_size == 0) {
if (erts_mtrace_enabled)
erts_mtrace_crr_free(atype, SEGTYPE, seg);
- mseg_destroy(mk, seg, size);
+ mseg_destroy(ma, mk, seg, size);
}
else {
int check_limits = 0;
@@ -769,7 +795,7 @@ mseg_dealloc(ErtsAlcType_t atype, void *seg, Uint size,
}
if (erts_mtrace_enabled)
erts_mtrace_crr_free(SEGTYPE, SEGTYPE, cd->seg);
- mseg_destroy(mk, cd->seg, cd->size);
+ mseg_destroy(ma, mk, cd->seg, cd->size);
unlink_cd(mk,cd);
free_cd(mk,cd);
}
@@ -790,33 +816,34 @@ mseg_dealloc(ErtsAlcType_t atype, void *seg, Uint size,
if (check_limits)
check_cache_limits(mk);
- schedule_cache_check();
+ schedule_cache_check(ma);
}
- INC_CC(dealloc);
+ INC_CC(ma, dealloc);
}
static void *
-mseg_realloc(ErtsAlcType_t atype, void *seg, Uint old_size, Uint *new_size_p,
- const ErtsMsegOpt_t *opt)
+mseg_realloc(ErtsMsegAllctr_t *ma, ErtsAlcType_t atype, void *seg,
+ Uint old_size, Uint *new_size_p, const ErtsMsegOpt_t *opt)
{
- MemKind* mk = memkind(opt);
+ MemKind* mk;
void *new_seg;
Uint new_size;
if (!seg || !old_size) {
- new_seg = mseg_alloc(atype, new_size_p, opt);
- DEC_CC(alloc);
+ new_seg = mseg_alloc(ma, atype, new_size_p, opt);
+ DEC_CC(ma, alloc);
return new_seg;
}
if (!(*new_size_p)) {
- mseg_dealloc(atype, seg, old_size, opt);
- DEC_CC(dealloc);
+ mseg_dealloc(ma, atype, seg, old_size, opt);
+ DEC_CC(ma, dealloc);
return NULL;
}
+ mk = memkind(ma, opt);
new_seg = seg;
new_size = PAGE_CEILING(*new_size_p);
@@ -826,8 +853,8 @@ mseg_realloc(ErtsAlcType_t atype, void *seg, Uint old_size, Uint *new_size_p,
Uint shrink_sz = old_size - new_size;
#if CAN_PARTLY_DESTROY
- if (new_size < min_seg_size)
- min_seg_size = new_size;
+ if (new_size < ma->min_seg_size)
+ ma->min_seg_size = new_size;
#endif
if (shrink_sz < opt->abs_shrink_th
@@ -838,7 +865,7 @@ mseg_realloc(ErtsAlcType_t atype, void *seg, Uint old_size, Uint *new_size_p,
#if CAN_PARTLY_DESTROY
- if (shrink_sz > min_seg_size
+ if (shrink_sz > ma->min_seg_size
&& mk->free_cache_descs
&& opt->cache) {
cache_desc_t *cd;
@@ -857,7 +884,7 @@ mseg_realloc(ErtsAlcType_t atype, void *seg, Uint old_size, Uint *new_size_p,
new_size);
erts_mtrace_crr_alloc(cd->seg, SEGTYPE, SEGTYPE, cd->size);
}
- schedule_cache_check();
+ schedule_cache_check(ma);
}
else {
if (erts_mtrace_enabled)
@@ -866,7 +893,7 @@ mseg_realloc(ErtsAlcType_t atype, void *seg, Uint old_size, Uint *new_size_p,
SEGTYPE,
seg,
new_size);
- mseg_destroy(mk, ((char *) seg) + new_size, shrink_sz);
+ mseg_destroy(ma, mk, ((char *) seg) + new_size, shrink_sz);
}
#elif HAVE_MSEG_RECREATE
@@ -875,14 +902,14 @@ mseg_realloc(ErtsAlcType_t atype, void *seg, Uint old_size, Uint *new_size_p,
#else
- new_seg = mseg_alloc(atype, &new_size, opt);
+ new_seg = mseg_alloc(ma, atype, &new_size, opt);
if (!new_seg)
new_size = old_size;
else {
sys_memcpy(((char *) new_seg),
((char *) seg),
MIN(new_size, old_size));
- mseg_dealloc(atype, seg, old_size, opt);
+ mseg_dealloc(ma, atype, seg, old_size, opt);
}
#endif
@@ -892,34 +919,34 @@ mseg_realloc(ErtsAlcType_t atype, void *seg, Uint old_size, Uint *new_size_p,
else {
if (!opt->preserv) {
- mseg_dealloc(atype, seg, old_size, opt);
- new_seg = mseg_alloc(atype, &new_size, opt);
+ mseg_dealloc(ma, atype, seg, old_size, opt);
+ new_seg = mseg_alloc(ma, atype, &new_size, opt);
}
else {
#if HAVE_MSEG_RECREATE
#if !CAN_PARTLY_DESTROY
do_recreate:
#endif
- new_seg = mseg_recreate(mk, (void *) seg, old_size, new_size);
+ new_seg = mseg_recreate(ma, mk, (void *) seg, old_size, new_size);
if (erts_mtrace_enabled)
erts_mtrace_crr_realloc(new_seg, atype, SEGTYPE, seg, new_size);
if (!new_seg)
new_size = old_size;
#else
- new_seg = mseg_alloc(atype, &new_size, opt);
+ new_seg = mseg_alloc(ma, atype, &new_size, opt);
if (!new_seg)
new_size = old_size;
else {
sys_memcpy(((char *) new_seg),
((char *) seg),
MIN(new_size, old_size));
- mseg_dealloc(atype, seg, old_size, opt);
+ mseg_dealloc(ma, atype, seg, old_size, opt);
}
#endif
}
}
- INC_CC(realloc);
+ INC_CC(ma, realloc);
*new_size_p = new_size;
@@ -937,7 +964,6 @@ static struct {
Eterm amcbf;
Eterm rmcbf;
Eterm mcs;
- Eterm cci;
Eterm memkind;
Eterm name;
@@ -973,13 +999,13 @@ static void ERTS_INLINE atom_init(Eterm *atom, char *name)
#define AM_INIT(AM) atom_init(&am.AM, #AM)
static void
-init_atoms(void)
+init_atoms(ErtsMsegAllctr_t *ma)
{
#ifdef DEBUG
Eterm *atom;
#endif
- erts_mtx_unlock(&mseg_mutex);
+ ERTS_MSEG_UNLOCK(ma);
erts_mtx_lock(&init_atoms_mutex);
if (!atoms_initialized) {
@@ -997,7 +1023,6 @@ init_atoms(void)
AM_INIT(amcbf);
AM_INIT(rmcbf);
AM_INIT(mcs);
- AM_INIT(cci);
AM_INIT(status);
AM_INIT(cached_segments);
@@ -1025,7 +1050,7 @@ init_atoms(void)
#endif
}
- erts_mtx_lock(&mseg_mutex);
+ ERTS_MSEG_LOCK(ma);
atoms_initialized = 1;
erts_mtx_unlock(&init_atoms_mutex);
}
@@ -1082,7 +1107,8 @@ add_4tup(Uint **hpp, Uint *szp, Eterm *lp,
}
static Eterm
-info_options(char *prefix,
+info_options(ErtsMsegAllctr_t *ma,
+ char *prefix,
int *print_to_p,
void *print_to_arg,
Uint **hpp,
@@ -1093,30 +1119,26 @@ info_options(char *prefix,
if (print_to_p) {
int to = *print_to_p;
void *arg = print_to_arg;
- erts_print(to, arg, "%samcbf: %beu\n", prefix, abs_max_cache_bad_fit);
- erts_print(to, arg, "%srmcbf: %beu\n", prefix, rel_max_cache_bad_fit);
- erts_print(to, arg, "%smcs: %beu\n", prefix, max_cache_size);
- erts_print(to, arg, "%scci: %beu\n", prefix, cache_check_interval);
+ erts_print(to, arg, "%samcbf: %beu\n", prefix, ma->abs_max_cache_bad_fit);
+ erts_print(to, arg, "%srmcbf: %beu\n", prefix, ma->rel_max_cache_bad_fit);
+ erts_print(to, arg, "%smcs: %beu\n", prefix, ma->max_cache_size);
}
if (hpp || szp) {
if (!atoms_initialized)
- init_atoms();
+ init_atoms(ma);
res = NIL;
add_2tup(hpp, szp, &res,
- am.cci,
- bld_uint(hpp, szp, cache_check_interval));
- add_2tup(hpp, szp, &res,
am.mcs,
- bld_uint(hpp, szp, max_cache_size));
+ bld_uint(hpp, szp, ma->max_cache_size));
add_2tup(hpp, szp, &res,
am.rmcbf,
- bld_uint(hpp, szp, rel_max_cache_bad_fit));
+ bld_uint(hpp, szp, ma->rel_max_cache_bad_fit));
add_2tup(hpp, szp, &res,
am.amcbf,
- bld_uint(hpp, szp, abs_max_cache_bad_fit));
+ bld_uint(hpp, szp, ma->abs_max_cache_bad_fit));
}
@@ -1124,18 +1146,18 @@ info_options(char *prefix,
}
static Eterm
-info_calls(int *print_to_p, void *print_to_arg, Uint **hpp, Uint *szp)
+info_calls(ErtsMsegAllctr_t *ma, int *print_to_p, void *print_to_arg, Uint **hpp, Uint *szp)
{
Eterm res = THE_NON_VALUE;
if (print_to_p) {
-#define PRINT_CC(TO, TOA, CC) \
- if (calls.CC.giga_no == 0) \
- erts_print(TO, TOA, "mseg_%s calls: %b32u\n", #CC, calls.CC.no); \
- else \
+#define PRINT_CC(TO, TOA, CC) \
+ if (ma->calls.CC.giga_no == 0) \
+ erts_print(TO, TOA, "mseg_%s calls: %b32u\n", #CC, ma->calls.CC.no); \
+ else \
erts_print(TO, TOA, "mseg_%s calls: %b32u%09b32u\n", #CC, \
- calls.CC.giga_no, calls.CC.no)
+ ma->calls.CC.giga_no, ma->calls.CC.no)
int to = *print_to_p;
void *arg = print_to_arg;
@@ -1161,48 +1183,48 @@ info_calls(int *print_to_p, void *print_to_arg, Uint **hpp, Uint *szp)
add_3tup(hpp, szp, &res,
am.mseg_check_cache,
- bld_unstable_uint(hpp, szp, calls.check_cache.giga_no),
- bld_unstable_uint(hpp, szp, calls.check_cache.no));
+ bld_unstable_uint(hpp, szp, ma->calls.check_cache.giga_no),
+ bld_unstable_uint(hpp, szp, ma->calls.check_cache.no));
add_3tup(hpp, szp, &res,
am.mseg_clear_cache,
- bld_unstable_uint(hpp, szp, calls.clear_cache.giga_no),
- bld_unstable_uint(hpp, szp, calls.clear_cache.no));
+ bld_unstable_uint(hpp, szp, ma->calls.clear_cache.giga_no),
+ bld_unstable_uint(hpp, szp, ma->calls.clear_cache.no));
#if HAVE_MSEG_RECREATE
add_3tup(hpp, szp, &res,
am.mseg_recreate,
- bld_unstable_uint(hpp, szp, calls.recreate.giga_no),
- bld_unstable_uint(hpp, szp, calls.recreate.no));
+ bld_unstable_uint(hpp, szp, ma->calls.recreate.giga_no),
+ bld_unstable_uint(hpp, szp, ma->calls.recreate.no));
#endif
add_3tup(hpp, szp, &res,
am.mseg_destroy,
- bld_unstable_uint(hpp, szp, calls.destroy.giga_no),
- bld_unstable_uint(hpp, szp, calls.destroy.no));
+ bld_unstable_uint(hpp, szp, ma->calls.destroy.giga_no),
+ bld_unstable_uint(hpp, szp, ma->calls.destroy.no));
add_3tup(hpp, szp, &res,
am.mseg_create,
- bld_unstable_uint(hpp, szp, calls.create.giga_no),
- bld_unstable_uint(hpp, szp, calls.create.no));
+ bld_unstable_uint(hpp, szp, ma->calls.create.giga_no),
+ bld_unstable_uint(hpp, szp, ma->calls.create.no));
add_3tup(hpp, szp, &res,
am.mseg_realloc,
- bld_unstable_uint(hpp, szp, calls.realloc.giga_no),
- bld_unstable_uint(hpp, szp, calls.realloc.no));
+ bld_unstable_uint(hpp, szp, ma->calls.realloc.giga_no),
+ bld_unstable_uint(hpp, szp, ma->calls.realloc.no));
add_3tup(hpp, szp, &res,
am.mseg_dealloc,
- bld_unstable_uint(hpp, szp, calls.dealloc.giga_no),
- bld_unstable_uint(hpp, szp, calls.dealloc.no));
+ bld_unstable_uint(hpp, szp, ma->calls.dealloc.giga_no),
+ bld_unstable_uint(hpp, szp, ma->calls.dealloc.no));
add_3tup(hpp, szp, &res,
am.mseg_alloc,
- bld_unstable_uint(hpp, szp, calls.alloc.giga_no),
- bld_unstable_uint(hpp, szp, calls.alloc.no));
+ bld_unstable_uint(hpp, szp, ma->calls.alloc.giga_no),
+ bld_unstable_uint(hpp, szp, ma->calls.alloc.no));
}
return res;
}
static Eterm
-info_status(MemKind* mk, int *print_to_p, void *print_to_arg,
+info_status(ErtsMsegAllctr_t *ma, MemKind* mk, int *print_to_p, void *print_to_arg,
int begin_new_max_period, Uint **hpp, Uint *szp)
{
Eterm res = THE_NON_VALUE;
@@ -1258,7 +1280,7 @@ info_status(MemKind* mk, int *print_to_p, void *print_to_arg,
return res;
}
-static Eterm info_memkind(MemKind* mk, int *print_to_p, void *print_to_arg,
+static Eterm info_memkind(ErtsMsegAllctr_t *ma, MemKind* mk, int *print_to_p, void *print_to_arg,
int begin_max_per, Uint **hpp, Uint *szp)
{
Eterm res = THE_NON_VALUE;
@@ -1274,8 +1296,8 @@ static Eterm info_memkind(MemKind* mk, int *print_to_p, void *print_to_arg,
atoms[2] = am.calls;
values[0] = erts_bld_string(hpp, szp, mk->name);
}
- values[1] = info_status(mk, print_to_p, print_to_arg, begin_max_per, hpp, szp);
- values[2] = info_calls(print_to_p, print_to_arg, hpp, szp);
+ values[1] = info_status(ma, mk, print_to_p, print_to_arg, begin_max_per, hpp, szp);
+ values[2] = info_calls(ma, print_to_p, print_to_arg, hpp, szp);
if (hpp || szp)
res = bld_2tup_list(hpp, szp, 3, atoms, values);
@@ -1285,7 +1307,7 @@ static Eterm info_memkind(MemKind* mk, int *print_to_p, void *print_to_arg,
static Eterm
-info_version(int *print_to_p, void *print_to_arg, Uint **hpp, Uint *szp)
+info_version(ErtsMsegAllctr_t *ma, int *print_to_p, void *print_to_arg, Uint **hpp, Uint *szp)
{
Eterm res = THE_NON_VALUE;
@@ -1306,56 +1328,64 @@ info_version(int *print_to_p, void *print_to_arg, Uint **hpp, Uint *szp)
\* */
Eterm
-erts_mseg_info_options(int *print_to_p, void *print_to_arg,
+erts_mseg_info_options(int ix,
+ int *print_to_p, void *print_to_arg,
Uint **hpp, Uint *szp)
{
+ ErtsMsegAllctr_t *ma = ERTS_MSEG_ALLCTR_IX(ix);
Eterm res;
- erts_mtx_lock(&mseg_mutex);
+ ERTS_MSEG_LOCK(ma);
- res = info_options("option ", print_to_p, print_to_arg, hpp, szp);
+ ERTS_DBG_MA_CHK_THR_ACCESS(ma);
- erts_mtx_unlock(&mseg_mutex);
+ res = info_options(ma, "option ", print_to_p, print_to_arg, hpp, szp);
+
+ ERTS_MSEG_UNLOCK(ma);
return res;
}
Eterm
-erts_mseg_info(int *print_to_p,
+erts_mseg_info(int ix,
+ int *print_to_p,
void *print_to_arg,
int begin_max_per,
Uint **hpp,
Uint *szp)
{
+ ErtsMsegAllctr_t *ma = ERTS_MSEG_ALLCTR_IX(ix);
Eterm res = THE_NON_VALUE;
Eterm atoms[4];
Eterm values[4];
Uint n = 0;
- erts_mtx_lock(&mseg_mutex);
+ ERTS_MSEG_LOCK(ma);
+
+ ERTS_DBG_MA_CHK_THR_ACCESS(ma);
if (hpp || szp) {
if (!atoms_initialized)
- init_atoms();
+ init_atoms(ma);
atoms[0] = am.version;
atoms[1] = am.options;
atoms[2] = am.memkind;
atoms[3] = am.memkind;
}
- values[n++] = info_version(print_to_p, print_to_arg, hpp, szp);
- values[n++] = info_options("option ", print_to_p, print_to_arg, hpp, szp);
+ values[n++] = info_version(ma, print_to_p, print_to_arg, hpp, szp);
+ values[n++] = info_options(ma, "option ", print_to_p, print_to_arg, hpp, szp);
#if HALFWORD_HEAP
- values[n++] = info_memkind(&low_mem, print_to_p, print_to_arg, begin_max_per, hpp, szp);
- values[n++] = info_memkind(&hi_mem, print_to_p, print_to_arg, begin_max_per, hpp, szp);
+ values[n++] = info_memkind(ma, &ma->low_mem, print_to_p, print_to_arg, begin_max_per, hpp, szp);
+ values[n++] = info_memkind(ma, &ma->hi_mem, print_to_p, print_to_arg, begin_max_per, hpp, szp);
#else
- values[n++] = info_memkind(&the_mem, print_to_p, print_to_arg, begin_max_per, hpp, szp);
+ values[n++] = info_memkind(ma, &ma->the_mem, print_to_p, print_to_arg, begin_max_per, hpp, szp);
#endif
if (hpp || szp)
res = bld_2tup_list(hpp, szp, n, atoms, values);
- erts_mtx_unlock(&mseg_mutex);
+ ERTS_MSEG_UNLOCK(ma);
return res;
}
@@ -1363,10 +1393,12 @@ erts_mseg_info(int *print_to_p,
void *
erts_mseg_alloc_opt(ErtsAlcType_t atype, Uint *size_p, const ErtsMsegOpt_t *opt)
{
+ ErtsMsegAllctr_t *ma = ERTS_MSEG_ALLCTR_OPT(opt);
void *seg;
- erts_mtx_lock(&mseg_mutex);
- seg = mseg_alloc(atype, size_p, opt);
- erts_mtx_unlock(&mseg_mutex);
+ ERTS_MSEG_LOCK(ma);
+ ERTS_DBG_MA_CHK_THR_ACCESS(ma);
+ seg = mseg_alloc(ma, atype, size_p, opt);
+ ERTS_MSEG_UNLOCK(ma);
return seg;
}
@@ -1377,12 +1409,14 @@ erts_mseg_alloc(ErtsAlcType_t atype, Uint *size_p)
}
void
-erts_mseg_dealloc_opt(ErtsAlcType_t atype, void *seg, Uint size,
- const ErtsMsegOpt_t *opt)
+erts_mseg_dealloc_opt(ErtsAlcType_t atype, void *seg,
+ Uint size, const ErtsMsegOpt_t *opt)
{
- erts_mtx_lock(&mseg_mutex);
- mseg_dealloc(atype, seg, size, opt);
- erts_mtx_unlock(&mseg_mutex);
+ ErtsMsegAllctr_t *ma = ERTS_MSEG_ALLCTR_OPT(opt);
+ ERTS_MSEG_LOCK(ma);
+ ERTS_DBG_MA_CHK_THR_ACCESS(ma);
+ mseg_dealloc(ma, atype, seg, size, opt);
+ ERTS_MSEG_UNLOCK(ma);
}
void
@@ -1392,44 +1426,60 @@ erts_mseg_dealloc(ErtsAlcType_t atype, void *seg, Uint size)
}
void *
-erts_mseg_realloc_opt(ErtsAlcType_t atype, void *seg, Uint old_size,
- Uint *new_size_p, const ErtsMsegOpt_t *opt)
+erts_mseg_realloc_opt(ErtsAlcType_t atype, void *seg,
+ Uint old_size, Uint *new_size_p,
+ const ErtsMsegOpt_t *opt)
{
+ ErtsMsegAllctr_t *ma = ERTS_MSEG_ALLCTR_OPT(opt);
void *new_seg;
- erts_mtx_lock(&mseg_mutex);
- new_seg = mseg_realloc(atype, seg, old_size, new_size_p, opt);
- erts_mtx_unlock(&mseg_mutex);
+ ERTS_MSEG_LOCK(ma);
+ ERTS_DBG_MA_CHK_THR_ACCESS(ma);
+ new_seg = mseg_realloc(ma, atype, seg, old_size, new_size_p, opt);
+ ERTS_MSEG_UNLOCK(ma);
return new_seg;
}
void *
-erts_mseg_realloc(ErtsAlcType_t atype, void *seg, Uint old_size,
- Uint *new_size_p)
+erts_mseg_realloc(ErtsAlcType_t atype, void *seg,
+ Uint old_size, Uint *new_size_p)
{
- return erts_mseg_realloc_opt(atype, seg, old_size, new_size_p, &erts_mseg_default_opt);
+ return erts_mseg_realloc_opt(atype, seg, old_size, new_size_p,
+ &erts_mseg_default_opt);
}
void
erts_mseg_clear_cache(void)
{
+ ErtsMsegAllctr_t *ma = ERTS_MSEG_ALLCTR_SS();
MemKind* mk;
- erts_mtx_lock(&mseg_mutex);
- for (mk=mk_list; mk; mk=mk->next) {
+
+start:
+
+ ERTS_MSEG_LOCK(ma);
+ ERTS_DBG_MA_CHK_THR_ACCESS(ma);
+ for (mk=ma->mk_list; mk; mk=mk->next) {
mseg_clear_cache(mk);
}
- erts_mtx_unlock(&mseg_mutex);
+ ERTS_MSEG_UNLOCK(ma);
+
+ if (ma->ix != 0) {
+ ma = ERTS_MSEG_ALLCTR_IX(0);
+ goto start;
+ }
}
Uint
-erts_mseg_no(void)
+erts_mseg_no(const ErtsMsegOpt_t *opt)
{
+ ErtsMsegAllctr_t *ma = ERTS_MSEG_ALLCTR_OPT(opt);
MemKind* mk;
Uint n = 0;
- erts_mtx_lock(&mseg_mutex);
- for (mk=mk_list; mk; mk=mk->next) {
+ ERTS_MSEG_LOCK(ma);
+ ERTS_DBG_MA_CHK_THR_ACCESS(ma);
+ for (mk=ma->mk_list; mk; mk=mk->next) {
n += mk->segments.current.no;
}
- erts_mtx_unlock(&mseg_mutex);
+ ERTS_MSEG_UNLOCK(ma);
return n;
}
@@ -1439,7 +1489,7 @@ erts_mseg_unit_size(void)
return page_size;
}
-static void mem_kind_init(MemKind* mk, const char* name)
+static void mem_kind_init(ErtsMsegAllctr_t *ma, MemKind* mk, const char* name)
{
unsigned i;
@@ -1450,10 +1500,10 @@ static void mem_kind_init(MemKind* mk, const char* name)
mk->cache_size = 0;
mk->cache_hits = 0;
- if (max_cache_size > 0) {
- for (i = 0; i < max_cache_size - 1; i++)
+ if (ma->max_cache_size > 0) {
+ for (i = 0; i < ma->max_cache_size - 1; i++)
mk->cache_descs[i].next = &mk->cache_descs[i + 1];
- mk->cache_descs[max_cache_size - 1].next = NULL;
+ mk->cache_descs[ma->max_cache_size - 1].next = NULL;
mk->free_cache_descs = &mk->cache_descs[0];
}
else
@@ -1467,30 +1517,38 @@ static void mem_kind_init(MemKind* mk, const char* name)
mk->segments.max_ever.no = 0;
mk->segments.max_ever.sz = 0;
+ mk->ma = ma;
mk->name = name;
- mk->next = mk_list;
- mk_list = mk;
+ mk->next = ma->mk_list;
+ ma->mk_list = mk;
}
+
+
void
erts_mseg_init(ErtsMsegInit_t *init)
{
- atoms_initialized = 0;
- is_init_done = 0;
+ int i;
+ UWord x;
- /* Options ... */
+#ifdef ERTS_SMP
+ no_mseg_allocators = init->nos + 1;
+#else
+ no_mseg_allocators = 1;
+#endif
- abs_max_cache_bad_fit = init->amcbf;
- rel_max_cache_bad_fit = init->rmcbf;
- max_cache_size = init->mcs;
- cache_check_interval = init->cci;
+ x = (UWord) malloc(sizeof(ErtsAlgndMsegAllctr_t)
+ *no_mseg_allocators
+ + (ERTS_CACHE_LINE_SIZE-1));
+ if (x & ERTS_CACHE_LINE_MASK)
+ x = (x & ~ERTS_CACHE_LINE_MASK) + ERTS_CACHE_LINE_SIZE;
+ ASSERT((x & ERTS_CACHE_LINE_MASK) == 0);
+ aligned_mseg_allctr = (ErtsAlgndMsegAllctr_t *) x;
- /* */
+ atoms_initialized = 0;
-#ifdef USE_THREADS
- thread_safe_init();
-#endif
+ erts_mtx_init(&init_atoms_mutex, "mseg_init_atoms");
#if HAVE_MMAP && !defined(MAP_ANON)
mmap_fd = open("/dev/zero", O_RDWR);
@@ -1512,34 +1570,55 @@ erts_mseg_init(ErtsMsegInit_t *init)
page_shift++;
}
- sys_memzero((void *) &calls, sizeof(calls));
+ for (i = 0; i < no_mseg_allocators; i++) {
+ ErtsMsegAllctr_t *ma = ERTS_MSEG_ALLCTR_IX(i);
-#if CAN_PARTLY_DESTROY
- min_seg_size = ~((Uint) 0);
-#endif
+ ma->ix = i;
+
+ ma->is_init_done = 0;
+
+ if (i != 0)
+ ma->is_thread_safe = 0;
+ else {
+ ma->is_thread_safe = 1;
+ erts_mtx_init(&ma->mtx, "mseg");
+ }
+
+ ma->is_cache_check_scheduled = 0;
+
+ /* Options ... */
+
+ ma->abs_max_cache_bad_fit = init->amcbf;
+ ma->rel_max_cache_bad_fit = init->rmcbf;
+ ma->max_cache_size = init->mcs;
- if (max_cache_size > MAX_CACHE_SIZE)
- max_cache_size = MAX_CACHE_SIZE;
+ if (ma->max_cache_size > MAX_CACHE_SIZE)
+ ma->max_cache_size = MAX_CACHE_SIZE;
+
+ ma->mk_list = NULL;
#if HALFWORD_HEAP
- mem_kind_init(&low_mem, "low memory");
- mem_kind_init(&hi_mem, "high memory");
+ mem_kind_init(ma, &ma->low_mem, "low memory");
+ mem_kind_init(ma, &ma->hi_mem, "high memory");
#else
- mem_kind_init(&the_mem, "all memory");
+ mem_kind_init(ma, &ma->the_mem, "all memory");
#endif
- is_cache_check_scheduled = 0;
-#ifdef ERTS_THREADS_NO_SMP
- is_cache_check_requested = 0;
+ sys_memzero((void *) &ma->calls, sizeof(ErtsMsegCalls));
+
+#if CAN_PARTLY_DESTROY
+ ma->min_seg_size = ~((Uint) 0);
#endif
+ }
}
-static ERTS_INLINE Uint tot_cache_size(void)
+static ERTS_INLINE Uint tot_cache_size(ErtsMsegAllctr_t *ma)
{
MemKind* mk;
Uint sz = 0;
- for (mk=mk_list; mk; mk=mk->next) {
+ ERTS_DBG_MA_CHK_THR_ACCESS(ma);
+ for (mk=ma->mk_list; mk; mk=mk->next) {
sz += mk->cache_size;
}
return sz;
@@ -1552,25 +1631,13 @@ static ERTS_INLINE Uint tot_cache_size(void)
void
erts_mseg_late_init(void)
{
-#ifdef ERTS_THREADS_NO_SMP
- int handle =
- erts_register_async_ready_callback(
- check_schedule_cache_check);
-#endif
- erts_mtx_lock(&mseg_mutex);
- is_init_done = 1;
-#ifdef ERTS_THREADS_NO_SMP
- async_handle = handle;
-#endif
- if (tot_cache_size())
- schedule_cache_check();
- erts_mtx_unlock(&mseg_mutex);
-}
-
-void
-erts_mseg_exit(void)
-{
- mseg_shutdown();
+ ErtsMsegAllctr_t *ma = ERTS_MSEG_ALLCTR_SS();
+ ERTS_MSEG_LOCK(ma);
+ ERTS_DBG_MA_CHK_THR_ACCESS(ma);
+ ma->is_init_done = 1;
+ if (tot_cache_size(ma))
+ schedule_cache_check(ma);
+ ERTS_MSEG_UNLOCK(ma);
}
#endif /* #if HAVE_ERTS_MSEG */
@@ -1599,12 +1666,13 @@ erts_mseg_test(unsigned long op,
erts_mseg_clear_cache();
return (unsigned long) 0;
case 0x405:
- return (unsigned long) erts_mseg_no();
+ return (unsigned long) erts_mseg_no(&erts_mseg_default_opt);
case 0x406: {
+ ErtsMsegAllctr_t *ma = ERTS_MSEG_ALLCTR_IX(0);
unsigned long res;
- erts_mtx_lock(&mseg_mutex);
- res = (unsigned long) tot_cache_size();
- erts_mtx_unlock(&mseg_mutex);
+ ERTS_MSEG_LOCK(ma);
+ res = (unsigned long) tot_cache_size(ma);
+ ERTS_MSEG_UNLOCK(ma);
return res;
}
#else /* #if HAVE_ERTS_MSEG */
diff --git a/erts/emulator/sys/common/erl_mseg.h b/erts/emulator/sys/common/erl_mseg.h
index 8f116030a8..741080fb78 100644
--- a/erts/emulator/sys/common/erl_mseg.h
+++ b/erts/emulator/sys/common/erl_mseg.h
@@ -44,7 +44,7 @@ typedef struct {
Uint amcbf;
Uint rmcbf;
Uint mcs;
- Uint cci;
+ Uint nos;
} ErtsMsegInit_t;
#define ERTS_MSEG_INIT_DEFAULT_INITIALIZER \
@@ -60,6 +60,7 @@ typedef struct {
int preserv;
UWord abs_shrink_th;
UWord rel_shrink_th;
+ int sched_spec;
#if HALFWORD_HEAP
int low_mem;
#endif
@@ -75,14 +76,14 @@ void *erts_mseg_realloc(ErtsAlcType_t, void *, Uint, Uint *);
void *erts_mseg_realloc_opt(ErtsAlcType_t, void *, Uint, Uint *,
const ErtsMsegOpt_t *);
void erts_mseg_clear_cache(void);
-Uint erts_mseg_no(void);
+void erts_mseg_cache_check(void);
+Uint erts_mseg_no( const ErtsMsegOpt_t *);
Uint erts_mseg_unit_size(void);
void erts_mseg_init(ErtsMsegInit_t *init);
void erts_mseg_late_init(void); /* Have to be called after all allocators,
threads and timers have been initialized. */
-void erts_mseg_exit(void);
-Eterm erts_mseg_info_options(int *, void*, Uint **, Uint *);
-Eterm erts_mseg_info(int *, void*, int, Uint **, Uint *);
+Eterm erts_mseg_info_options(int, int *, void*, Uint **, Uint *);
+Eterm erts_mseg_info(int, int *, void*, int, Uint **, Uint *);
#endif /* #if HAVE_ERTS_MSEG */
diff --git a/erts/emulator/sys/common/erl_poll.c b/erts/emulator/sys/common/erl_poll.c
index f5c785d683..80db2055a2 100644
--- a/erts/emulator/sys/common/erl_poll.c
+++ b/erts/emulator/sys/common/erl_poll.c
@@ -68,6 +68,7 @@
# endif
# endif
#endif
+#include "erl_thr_progress.h"
#include "erl_driver.h"
#include "erl_alloc.h"
@@ -114,7 +115,7 @@
#endif
#define ERTS_POLL_USE_WAKEUP_PIPE \
- (ERTS_POLL_ASYNC_INTERRUPT_SUPPORT || defined(ERTS_SMP))
+ (ERTS_POLL_ASYNC_INTERRUPT_SUPPORT || defined(USE_THREADS))
#ifdef ERTS_SMP
@@ -124,11 +125,11 @@
erts_smp_mtx_unlock(&(PS)->mtx)
#define ERTS_POLLSET_SET_POLLED_CHK(PS) \
- ((int) erts_atomic32_xchg(&(PS)->polled, (erts_aint32_t) 1))
+ ((int) erts_atomic32_xchg_nob(&(PS)->polled, (erts_aint32_t) 1))
#define ERTS_POLLSET_UNSET_POLLED(PS) \
- erts_atomic32_set(&(PS)->polled, (erts_aint32_t) 0)
+ erts_atomic32_set_nob(&(PS)->polled, (erts_aint32_t) 0)
#define ERTS_POLLSET_IS_POLLED(PS) \
- ((int) erts_atomic32_read(&(PS)->polled))
+ ((int) erts_atomic32_read_nob(&(PS)->polled))
#else
@@ -142,11 +143,11 @@
#if ERTS_POLL_USE_UPDATE_REQUESTS_QUEUE
#define ERTS_POLLSET_SET_HAVE_UPDATE_REQUESTS(PS) \
- erts_smp_atomic32_set(&(PS)->have_update_requests, (erts_aint32_t) 1)
+ erts_smp_atomic32_set_nob(&(PS)->have_update_requests, (erts_aint32_t) 1)
#define ERTS_POLLSET_UNSET_HAVE_UPDATE_REQUESTS(PS) \
- erts_smp_atomic32_set(&(PS)->have_update_requests, (erts_aint32_t) 0)
+ erts_smp_atomic32_set_nob(&(PS)->have_update_requests, (erts_aint32_t) 0)
#define ERTS_POLLSET_HAVE_UPDATE_REQUESTS(PS) \
- ((int) erts_smp_atomic32_read(&(PS)->have_update_requests))
+ ((int) erts_smp_atomic32_read_nob(&(PS)->have_update_requests))
#else
#define ERTS_POLLSET_SET_HAVE_UPDATE_REQUESTS(PS)
#define ERTS_POLLSET_UNSET_HAVE_UPDATE_REQUESTS(PS)
@@ -261,7 +262,6 @@ struct ErtsPollSet_ {
#ifdef ERTS_SMP
erts_atomic32_t polled;
erts_smp_mtx_t mtx;
-#elif ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
#endif
#if ERTS_POLL_USE_WAKEUP_PIPE
int wake_fds[2];
@@ -269,10 +269,8 @@ struct ErtsPollSet_ {
#if ERTS_POLL_USE_FALLBACK
int fallback_used;
#endif
-#ifdef ERTS_SMP
+#if defined(USE_THREADS) || ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
erts_atomic32_t wakeup_state;
-#elif ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
- volatile int wakeup_state;
#endif
erts_smp_atomic32_t timeout;
#ifdef ERTS_POLL_COUNT_AVOIDED_WAKEUPS
@@ -345,21 +343,16 @@ static void print_misc_debug_info(void);
static ERTS_INLINE void
reset_wakeup_state(ErtsPollSet ps)
{
-#ifdef ERTS_SMP
- erts_atomic32_set(&ps->wakeup_state, ERTS_POLL_NOT_WOKEN);
- ERTS_THR_MEMORY_BARRIER;
-#elif ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
- ps->wakeup_state = 0;
+#if defined(USE_THREADS) || ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
+ erts_atomic32_set_mb(&ps->wakeup_state, ERTS_POLL_NOT_WOKEN);
#endif
}
static ERTS_INLINE int
is_woken(ErtsPollSet ps)
{
-#ifdef ERTS_SMP
+#if defined(USE_THREADS) || ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
return erts_atomic32_read_acqb(&ps->wakeup_state) != ERTS_POLL_NOT_WOKEN;
-#elif ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
- return ps->wakeup_state != ERTS_POLL_NOT_WOKEN;
#else
return 0;
#endif
@@ -368,13 +361,9 @@ is_woken(ErtsPollSet ps)
static ERTS_INLINE int
is_interrupted_reset(ErtsPollSet ps)
{
-#ifdef ERTS_SMP
- return (erts_atomic32_xchg(&ps->wakeup_state, ERTS_POLL_NOT_WOKEN)
+#if defined(USE_THREADS) || ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
+ return (erts_atomic32_xchg_nob(&ps->wakeup_state, ERTS_POLL_NOT_WOKEN)
== ERTS_POLL_WOKEN_INTR);
-#elif ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
- int res = ps->wakeup_state == ERTS_POLL_WOKEN_INTR;
- ps->wakeup_state = ERTS_POLL_NOT_WOKEN;
- return res;
#else
return 0;
#endif
@@ -383,16 +372,13 @@ is_interrupted_reset(ErtsPollSet ps)
static ERTS_INLINE void
woke_up(ErtsPollSet ps)
{
-#ifdef ERTS_SMP
- erts_aint32_t wakeup_state = erts_atomic32_read(&ps->wakeup_state);
+#if defined(USE_THREADS) || ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
+ erts_aint32_t wakeup_state = erts_atomic32_read_nob(&ps->wakeup_state);
if (wakeup_state == ERTS_POLL_NOT_WOKEN)
- (void) erts_atomic32_cmpxchg(&ps->wakeup_state,
- ERTS_POLL_WOKEN,
- ERTS_POLL_NOT_WOKEN);
- ASSERT(erts_atomic32_read(&ps->wakeup_state) != ERTS_POLL_NOT_WOKEN);
-#elif ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
- if (ps->wakeup_state == ERTS_POLL_NOT_WOKEN)
- ps->wakeup_state = ERTS_POLL_WOKEN;
+ (void) erts_atomic32_cmpxchg_nob(&ps->wakeup_state,
+ ERTS_POLL_WOKEN,
+ ERTS_POLL_NOT_WOKEN);
+ ASSERT(erts_atomic32_read_nob(&ps->wakeup_state) != ERTS_POLL_NOT_WOKEN);
#endif
}
@@ -403,28 +389,27 @@ woke_up(ErtsPollSet ps)
#if ERTS_POLL_USE_WAKEUP_PIPE
static ERTS_INLINE void
-wake_poller(ErtsPollSet ps, int interrupted)
+wake_poller(ErtsPollSet ps, int interrupted, int async_signal_safe)
{
int wake;
-#ifdef ERTS_SMP
- erts_aint32_t wakeup_state;
- if (!interrupted)
- wakeup_state = erts_atomic32_cmpxchg_relb(&ps->wakeup_state,
- ERTS_POLL_WOKEN,
- ERTS_POLL_NOT_WOKEN);
+ if (async_signal_safe)
+ wake = 1;
else {
- /*
- * We might unnecessarily write to the pipe, however,
- * that isn't problematic.
- */
- wakeup_state = erts_atomic32_read(&ps->wakeup_state);
- erts_atomic32_set_relb(&ps->wakeup_state, ERTS_POLL_WOKEN_INTR);
+ erts_aint32_t wakeup_state;
+ if (!interrupted)
+ wakeup_state = erts_atomic32_cmpxchg_relb(&ps->wakeup_state,
+ ERTS_POLL_WOKEN,
+ ERTS_POLL_NOT_WOKEN);
+ else {
+ /*
+ * We might unnecessarily write to the pipe, however,
+ * that isn't problematic.
+ */
+ wakeup_state = erts_atomic32_read_nob(&ps->wakeup_state);
+ erts_atomic32_set_relb(&ps->wakeup_state, ERTS_POLL_WOKEN_INTR);
+ }
+ wake = wakeup_state == ERTS_POLL_NOT_WOKEN;
}
- wake = wakeup_state == ERTS_POLL_NOT_WOKEN;
-#elif ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
- wake = ps->wakeup_state == ERTS_POLL_NOT_WOKEN;
- ps->wakeup_state = interrupted ? ERTS_POLL_WOKEN_INTR : ERTS_POLL_NOT_WOKEN;
-#endif
/*
* NOTE: This function might be called from signal handlers in the
* non-smp case; therefore, it has to be async-signal safe in
@@ -439,9 +424,17 @@ wake_poller(ErtsPollSet ps, int interrupted)
res = write(ps->wake_fds[1], "!", 1);
} while (res < 0 && errno == EINTR);
if (res <= 0 && errno != ERRNO_BLOCK) {
- fatal_error_async_signal_safe(__FILE__
- ":XXX:wake_poller(): "
- "Failed to write on wakeup pipe\n");
+ if (async_signal_safe)
+ fatal_error_async_signal_safe(__FILE__
+ ":XXX:wake_poller(): "
+ "Failed to write on wakeup pipe\n");
+ else
+ fatal_error("%s:%d:wake_poller(): "
+ "Failed to write to wakeup pipe fd=%d: "
+ "%s (%d)\n",
+ __FILE__, __LINE__,
+ ps->wake_fds[1],
+ erl_errno_id(errno), errno);
}
}
}
@@ -449,11 +442,18 @@ wake_poller(ErtsPollSet ps, int interrupted)
static ERTS_INLINE void
cleanup_wakeup_pipe(ErtsPollSet ps)
{
+#if ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
+ int intr = 0;
+#endif
int fd = ps->wake_fds[0];
int res;
do {
char buf[32];
res = read(fd, buf, sizeof(buf));
+#if ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
+ if (res > 0)
+ intr = 1;
+#endif
} while (res > 0 || (res < 0 && errno == EINTR));
if (res < 0 && errno != ERRNO_BLOCK) {
fatal_error("%s:%d:cleanup_wakeup_pipe(): "
@@ -463,6 +463,10 @@ cleanup_wakeup_pipe(ErtsPollSet ps)
fd,
erl_errno_id(errno), errno);
}
+#if ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
+ if (intr)
+ erts_atomic32_set_nob(&ps->wakeup_state, ERTS_POLL_WOKEN_INTR);
+#endif
}
static void
@@ -839,7 +843,7 @@ write_batch_buf(ErtsPollSet ps, ErtsPollBatchBuf *bbp)
ps->fds_status[fd].flags |= ERTS_POLL_FD_FLG_USEFLBCK;
ASSERT(ps->fds_status[fd].used_events);
ps->fds_status[fd].used_events = 0;
- erts_smp_atomic_dec(&ps->no_of_user_fds);
+ erts_smp_atomic_dec_nob(&ps->no_of_user_fds);
update_fallback_pollset(ps, fd);
ASSERT(ps->fds_status[fd].flags & ERTS_POLL_FD_FLG_INFLBCK);
break;
@@ -889,11 +893,11 @@ batch_update_pollset(ErtsPollSet ps, int fd, ErtsPollBatchBuf *bbp)
events = ERTS_POLL_EV_E2N(ps->fds_status[fd].events);
if (!events) {
buf[buf_len].events = POLLREMOVE;
- erts_smp_atomic_dec(&ps->no_of_user_fds);
+ erts_smp_atomic_dec_nob(&ps->no_of_user_fds);
}
else if (!ps->fds_status[fd].used_events) {
buf[buf_len].events = events;
- erts_smp_atomic_inc(&ps->no_of_user_fds);
+ erts_smp_atomic_inc_nob(&ps->no_of_user_fds);
}
else {
if ((ps->fds_status[fd].flags & ERTS_POLL_FD_FLG_RST)
@@ -983,12 +987,12 @@ batch_update_pollset(ErtsPollSet ps, int fd, ErtsPollBatchBuf *bbp)
}
if (used_events) {
if (!events) {
- erts_smp_atomic_dec(&ps->no_of_user_fds);
+ erts_smp_atomic_dec_nob(&ps->no_of_user_fds);
}
}
else {
if (events)
- erts_smp_atomic_inc(&ps->no_of_user_fds);
+ erts_smp_atomic_inc_nob(&ps->no_of_user_fds);
}
ASSERT((events & ~(ERTS_POLL_EV_IN|ERTS_POLL_EV_OUT)) == 0);
ASSERT((used_events & ~(ERTS_POLL_EV_IN|ERTS_POLL_EV_OUT)) == 0);
@@ -1062,7 +1066,7 @@ update_pollset(ErtsPollSet ps, int fd)
epe.data.fd = epe_templ.data.fd;
res = epoll_ctl(ps->kp_fd, EPOLL_CTL_DEL, fd, &epe);
} while (res != 0 && errno == EINTR);
- erts_smp_atomic_dec(&ps->no_of_user_fds);
+ erts_smp_atomic_dec_nob(&ps->no_of_user_fds);
ps->fds_status[fd].used_events = 0;
}
@@ -1070,11 +1074,11 @@ update_pollset(ErtsPollSet ps, int fd)
/* A note on EPOLL_CTL_DEL: linux kernel versions before 2.6.9
need a non-NULL event pointer even though it is ignored... */
op = EPOLL_CTL_DEL;
- erts_smp_atomic_dec(&ps->no_of_user_fds);
+ erts_smp_atomic_dec_nob(&ps->no_of_user_fds);
}
else if (!ps->fds_status[fd].used_events) {
op = EPOLL_CTL_ADD;
- erts_smp_atomic_inc(&ps->no_of_user_fds);
+ erts_smp_atomic_inc_nob(&ps->no_of_user_fds);
}
else {
op = EPOLL_CTL_MOD;
@@ -1124,7 +1128,7 @@ update_pollset(ErtsPollSet ps, int fd)
/* Fall through ... */
case EPOLL_CTL_ADD: {
ps->fds_status[fd].flags |= ERTS_POLL_FD_FLG_USEFLBCK;
- erts_smp_atomic_dec(&ps->no_of_user_fds);
+ erts_smp_atomic_dec_nob(&ps->no_of_user_fds);
#if ERTS_POLL_USE_CONCURRENT_UPDATE
if (!*update_fallback) {
*update_fallback = 1;
@@ -1212,7 +1216,7 @@ static int update_pollset(ErtsPollSet ps, int fd)
#if ERTS_POLL_USE_FALLBACK
ASSERT(ps->fds_status[fd].flags & ERTS_POLL_FD_FLG_INFLBCK);
#endif
- erts_smp_atomic_dec(&ps->no_of_user_fds);
+ erts_smp_atomic_dec_nob(&ps->no_of_user_fds);
last_pix = --ps->no_poll_fds;
if (pix != last_pix) {
/* Move last pix to this pix */
@@ -1239,7 +1243,7 @@ static int update_pollset(ErtsPollSet ps, int fd)
ASSERT(!(ps->fds_status[fd].flags & ERTS_POLL_FD_FLG_INFLBCK)
|| fd == ps->kp_fd);
#endif
- erts_smp_atomic_inc(&ps->no_of_user_fds);
+ erts_smp_atomic_inc_nob(&ps->no_of_user_fds);
ps->fds_status[fd].pix = pix = ps->no_poll_fds++;
if (pix >= ps->poll_fds_len)
grow_poll_fds(ps, pix);
@@ -1290,7 +1294,7 @@ static int update_pollset(ErtsPollSet ps, int fd)
if (!ps->fds_status[fd].used_events) {
ASSERT(events);
- erts_smp_atomic_inc(&ps->no_of_user_fds);
+ erts_smp_atomic_inc_nob(&ps->no_of_user_fds);
#if ERTS_POLL_USE_FALLBACK
ps->no_select_fds++;
ps->fds_status[fd].flags |= ERTS_POLL_FD_FLG_INFLBCK;
@@ -1298,7 +1302,7 @@ static int update_pollset(ErtsPollSet ps, int fd)
}
else if (!events) {
ASSERT(ps->fds_status[fd].used_events);
- erts_smp_atomic_dec(&ps->no_of_user_fds);
+ erts_smp_atomic_dec_nob(&ps->no_of_user_fds);
ps->fds_status[fd].events = events;
#if ERTS_POLL_USE_FALLBACK
ps->no_select_fds--;
@@ -1497,7 +1501,7 @@ ERTS_POLL_EXPORT(erts_poll_controlv)(ErtsPollSet ps,
#ifdef ERTS_SMP
if (final_do_wake)
- wake_poller(ps, 0);
+ wake_poller(ps, 0, 0);
#endif /* ERTS_SMP */
}
@@ -1520,7 +1524,7 @@ ERTS_POLL_EXPORT(erts_poll_control)(ErtsPollSet ps,
#ifdef ERTS_SMP
if (*do_wake) {
- wake_poller(ps, 0);
+ wake_poller(ps, 0, 0);
}
#endif /* ERTS_SMP */
@@ -1893,10 +1897,10 @@ save_poll_result(ErtsPollSet ps, ErtsPollResFd pr[], int max_res,
}
static ERTS_INLINE int
-check_fd_events(ErtsPollSet ps, SysTimeval *tv, int max_res, int *ps_locked)
+check_fd_events(ErtsPollSet ps, SysTimeval *tv, int max_res)
{
- ASSERT(!*ps_locked);
- if (erts_smp_atomic_read(&ps->no_of_user_fds) == 0
+ int res;
+ if (erts_smp_atomic_read_nob(&ps->no_of_user_fds) == 0
&& tv->tv_usec == 0 && tv->tv_sec == 0) {
/* Nothing to poll and zero timeout; done... */
return 0;
@@ -1915,16 +1919,23 @@ check_fd_events(ErtsPollSet ps, SysTimeval *tv, int max_res, int *ps_locked)
timeout = INT_MAX;
if (max_res > ps->res_events_len)
grow_res_events(ps, max_res);
- return epoll_wait(ps->kp_fd, ps->res_events, max_res, (int)timeout);
+#ifdef ERTS_SMP
+ if (timeout)
+ erts_thr_progress_prepare_wait(NULL);
+#endif
+ res = epoll_wait(ps->kp_fd, ps->res_events, max_res, (int)timeout);
#elif ERTS_POLL_USE_KQUEUE /* --- kqueue ------------------------------ */
struct timespec ts;
- ts.tv_sec = tv->tv_sec;
- ts.tv_nsec = tv->tv_usec*1000;
if (max_res > ps->res_events_len)
grow_res_events(ps, max_res);
- return kevent(ps->kp_fd, NULL, 0, ps->res_events, max_res, &ts);
+#ifdef ERTS_SMP
+ if (timeout)
+ erts_thr_progress_prepare_wait(NULL);
+#endif
+ ts.tv_sec = tv->tv_sec;
+ ts.tv_nsec = tv->tv_usec*1000;
+ res = kevent(ps->kp_fd, NULL, 0, ps->res_events, max_res, &ts);
#endif /* ----------------------------------------- */
-
}
else /* use fallback (i.e. poll() or select()) */
#endif /* ERTS_POLL_USE_FALLBACK */
@@ -1937,7 +1948,7 @@ check_fd_events(ErtsPollSet ps, SysTimeval *tv, int max_res, int *ps_locked)
* the maximum number of file descriptors in the poll set.
*/
struct dvpoll poll_res;
- int nfds = (int) erts_smp_atomic_read(&ps->no_of_user_fds);
+ int nfds = (int) erts_smp_atomic_read_nob(&ps->no_of_user_fds);
#ifdef ERTS_SMP
nfds++; /* Wakeup pipe */
#endif
@@ -1947,22 +1958,38 @@ check_fd_events(ErtsPollSet ps, SysTimeval *tv, int max_res, int *ps_locked)
if (poll_res.dp_nfds > ps->res_events_len)
grow_res_events(ps, poll_res.dp_nfds);
poll_res.dp_fds = ps->res_events;
+#ifdef ERTS_SMP
+ if (timeout)
+ erts_thr_progress_prepare_wait(NULL);
+#endif
poll_res.dp_timeout = (int) timeout;
- return ioctl(ps->kp_fd, DP_POLL, &poll_res);
+ res = ioctl(ps->kp_fd, DP_POLL, &poll_res);
#elif ERTS_POLL_USE_POLL /* --- poll -------------------------------- */
if (timeout > INT_MAX)
timeout = INT_MAX;
- return poll(ps->poll_fds, ps->no_poll_fds, (int) timeout);
+#ifdef ERTS_SMP
+ if (timeout)
+ erts_thr_progress_prepare_wait(NULL);
+#endif
+ res = poll(ps->poll_fds, ps->no_poll_fds, (int) timeout);
#elif ERTS_POLL_USE_SELECT /* --- select ------------------------------ */
- int res;
+ SysTimeval to = *tv;
+
ps->res_input_fds = ps->input_fds;
ps->res_output_fds = ps->output_fds;
+
+#ifdef ERTS_SMP
+ if (to.tv_sec || to.tv_usec)
+ erts_thr_progress_prepare_wait(NULL);
+#endif
res = select(ps->max_fd + 1,
&ps->res_input_fds,
&ps->res_output_fds,
NULL,
- tv);
+ &to);
#ifdef ERTS_SMP
+ if (to.tv_sec || to.tv_usec)
+ erts_thr_progress_finalize_wait(NULL);
if (res < 0
&& errno == EBADF
&& ERTS_POLLSET_HAVE_UPDATE_REQUESTS(ps)) {
@@ -1978,15 +2005,16 @@ check_fd_events(ErtsPollSet ps, SysTimeval *tv, int max_res, int *ps_locked)
* have triggered, we fake an EAGAIN error and let the caller
* restart us.
*/
- SysTimeval zero_tv = {0, 0};
- *ps_locked = 1;
+ to.tv_sec = 0;
+ to.tv_usec = 0;
ERTS_POLLSET_LOCK(ps);
handle_update_requests(ps);
+ ERTS_POLLSET_UNLOCK(ps);
res = select(ps->max_fd + 1,
&ps->res_input_fds,
&ps->res_output_fds,
NULL,
- &zero_tv);
+ &to);
if (res == 0) {
errno = EAGAIN;
res = -1;
@@ -1996,6 +2024,11 @@ check_fd_events(ErtsPollSet ps, SysTimeval *tv, int max_res, int *ps_locked)
return res;
#endif /* ----------------------------------------- */
}
+#ifdef ERTS_SMP
+ if (timeout)
+ erts_thr_progress_finalize_wait(NULL);
+#endif
+ return res;
}
}
@@ -2007,7 +2040,9 @@ ERTS_POLL_EXPORT(erts_poll_wait)(ErtsPollSet ps,
{
int res, no_fds;
int ebadf = 0;
- int ps_locked;
+#ifdef ERTS_SMP
+ int ps_locked = 0;
+#endif
SysTimeval *tvp;
SysTimeval itv;
@@ -2049,8 +2084,7 @@ ERTS_POLL_EXPORT(erts_poll_wait)(ErtsPollSet ps,
}
#endif
- ps_locked = 0;
- res = check_fd_events(ps, tvp, no_fds, &ps_locked);
+ res = check_fd_events(ps, tvp, no_fds);
woke_up(ps);
@@ -2072,10 +2106,8 @@ ERTS_POLL_EXPORT(erts_poll_wait)(ErtsPollSet ps,
#endif
#ifdef ERTS_SMP
- if (!ps_locked) {
- ps_locked = 1;
- ERTS_POLLSET_LOCK(ps);
- }
+ ps_locked = 1;
+ ERTS_POLLSET_LOCK(ps);
#endif
no_fds = save_poll_result(ps, pr, no_fds, res, ebadf);
@@ -2111,19 +2143,26 @@ ERTS_POLL_EXPORT(erts_poll_wait)(ErtsPollSet ps,
void
ERTS_POLL_EXPORT(erts_poll_interrupt)(ErtsPollSet ps, int set)
{
-#if ERTS_POLL_ASYNC_INTERRUPT_SUPPORT || defined(ERTS_SMP)
- /*
- * NOTE: This function might be called from signal handlers in the
- * non-smp case; therefore, it has to be async-signal safe in
- * the non-smp case.
- */
+#if defined(USE_THREADS)
if (!set)
reset_wakeup_state(ps);
else
- wake_poller(ps, 1);
+ wake_poller(ps, 1, 0);
#endif
}
+#if ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
+void
+ERTS_POLL_EXPORT(erts_poll_async_sig_interrupt)(ErtsPollSet ps)
+{
+ /*
+ * NOTE: This function is called from signal handlers, it,
+ * therefore, it has to be async-signal safe.
+ */
+ wake_poller(ps, 1, 1);
+}
+#endif
+
/*
* erts_poll_interrupt_timed():
* If 'set' != 0, interrupt thread blocked in erts_poll_wait() if it
@@ -2139,14 +2178,14 @@ ERTS_POLL_EXPORT(erts_poll_interrupt_timed)(ErtsPollSet ps,
reset_wakeup_state(ps);
else {
if (erts_smp_atomic32_read_acqb(&ps->timeout) > (erts_aint32_t) msec)
- wake_poller(ps, 1);
+ wake_poller(ps, 1, 0);
#ifdef ERTS_POLL_COUNT_AVOIDED_WAKEUPS
else {
if (ERTS_POLLSET_IS_POLLED(ps))
- erts_smp_atomic_inc(&ps->no_avoided_wakeups);
- erts_smp_atomic_inc(&ps->no_avoided_interrupts);
+ erts_smp_atomic_inc_nob(&ps->no_avoided_wakeups);
+ erts_smp_atomic_inc_nob(&ps->no_avoided_interrupts);
}
- erts_smp_atomic_inc(&ps->no_interrupt_timed);
+ erts_smp_atomic_inc_nob(&ps->no_interrupt_timed);
#endif
}
#endif
@@ -2208,7 +2247,7 @@ ERTS_POLL_EXPORT(erts_poll_create_pollset)(void)
ps->internal_fd_limit = 0;
ps->fds_status = NULL;
ps->fds_status_len = 0;
- erts_smp_atomic_init(&ps->no_of_user_fds, 0);
+ erts_smp_atomic_init_nob(&ps->no_of_user_fds, 0);
#if ERTS_POLL_USE_KERNEL_POLL
ps->kp_fd = -1;
#if ERTS_POLL_USE_EPOLL
@@ -2260,16 +2299,14 @@ ERTS_POLL_EXPORT(erts_poll_create_pollset)(void)
ps->update_requests.next = NULL;
ps->update_requests.len = 0;
ps->curr_upd_req_block = &ps->update_requests;
- erts_smp_atomic32_init(&ps->have_update_requests, 0);
+ erts_smp_atomic32_init_nob(&ps->have_update_requests, 0);
#endif
#ifdef ERTS_SMP
- erts_atomic32_init(&ps->polled, 0);
+ erts_atomic32_init_nob(&ps->polled, 0);
erts_smp_mtx_init(&ps->mtx, "pollset");
#endif
-#ifdef ERTS_SMP
- erts_atomic32_init(&ps->wakeup_state, (erts_aint32_t) 0);
-#elif ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
- ps->wakeup_state = 0;
+#if defined(USE_THREADS) || ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
+ erts_atomic32_init_nob(&ps->wakeup_state, (erts_aint32_t) 0);
#endif
#if ERTS_POLL_USE_WAKEUP_PIPE
create_wakeup_pipe(ps);
@@ -2291,11 +2328,11 @@ ERTS_POLL_EXPORT(erts_poll_create_pollset)(void)
ps->internal_fd_limit = kp_fd + 1;
ps->kp_fd = kp_fd;
#endif
- erts_smp_atomic32_init(&ps->timeout, ERTS_AINT32_T_MAX);
+ erts_smp_atomic32_init_nob(&ps->timeout, ERTS_AINT32_T_MAX);
#ifdef ERTS_POLL_COUNT_AVOIDED_WAKEUPS
- erts_smp_atomic_init(&ps->no_avoided_wakeups, 0);
- erts_smp_atomic_init(&ps->no_avoided_interrupts, 0);
- erts_smp_atomic_init(&ps->no_interrupt_timed, 0);
+ erts_smp_atomic_init_nob(&ps->no_avoided_wakeups, 0);
+ erts_smp_atomic_init_nob(&ps->no_avoided_interrupts, 0);
+ erts_smp_atomic_init_nob(&ps->no_interrupt_timed, 0);
#endif
#if ERTS_POLL_USE_UPDATE_REQUESTS_QUEUE
handle_update_requests(ps);
@@ -2303,7 +2340,7 @@ ERTS_POLL_EXPORT(erts_poll_create_pollset)(void)
#if ERTS_POLL_USE_FALLBACK
ps->fallback_used = 0;
#endif
- erts_smp_atomic_set(&ps->no_of_user_fds, 0); /* Don't count wakeup pipe and fallback fd */
+ erts_smp_atomic_set_nob(&ps->no_of_user_fds, 0); /* Don't count wakeup pipe and fallback fd */
erts_smp_spin_lock(&pollsets_lock);
ps->next = pollsets;
@@ -2449,7 +2486,7 @@ ERTS_POLL_EXPORT(erts_poll_info)(ErtsPollSet ps, ErtsPollInfo *pip)
pip->memory_size = size;
- pip->poll_set_size = (int) erts_smp_atomic_read(&ps->no_of_user_fds);
+ pip->poll_set_size = (int) erts_smp_atomic_read_nob(&ps->no_of_user_fds);
#ifdef ERTS_SMP
pip->poll_set_size++; /* Wakeup pipe */
#endif
@@ -2507,9 +2544,9 @@ ERTS_POLL_EXPORT(erts_poll_info)(ErtsPollSet ps, ErtsPollInfo *pip)
pip->max_fds = max_fds;
#ifdef ERTS_POLL_COUNT_AVOIDED_WAKEUPS
- pip->no_avoided_wakeups = erts_smp_atomic_read(&ps->no_avoided_wakeups);
- pip->no_avoided_interrupts = erts_smp_atomic_read(&ps->no_avoided_interrupts);
- pip->no_interrupt_timed = erts_smp_atomic_read(&ps->no_interrupt_timed);
+ pip->no_avoided_wakeups = erts_smp_atomic_read_nob(&ps->no_avoided_wakeups);
+ pip->no_avoided_interrupts = erts_smp_atomic_read_nob(&ps->no_avoided_interrupts);
+ pip->no_interrupt_timed = erts_smp_atomic_read_nob(&ps->no_interrupt_timed);
#endif
ERTS_POLLSET_UNLOCK(ps);
@@ -2529,7 +2566,7 @@ fatal_error(char *format, ...)
{
va_list ap;
- if (ERTS_IS_CRASH_DUMPING || ERTS_GOT_SIGUSR1) {
+ if (ERTS_SOMEONE_IS_CRASH_DUMPING || ERTS_GOT_SIGUSR1) {
/*
* Crash dump writing and reception of sigusr1 (which will
* result in a crash dump) closes all file descriptors. This
@@ -2549,7 +2586,7 @@ fatal_error(char *format, ...)
static void
fatal_error_async_signal_safe(char *error_str)
{
- if (ERTS_IS_CRASH_DUMPING || ERTS_GOT_SIGUSR1) {
+ if (ERTS_SOMEONE_IS_CRASH_DUMPING || ERTS_GOT_SIGUSR1) {
/* See comment above in fatal_error() */
return;
}
diff --git a/erts/emulator/sys/common/erl_poll.h b/erts/emulator/sys/common/erl_poll.h
index 725a77a152..e0296c6a33 100644
--- a/erts/emulator/sys/common/erl_poll.h
+++ b/erts/emulator/sys/common/erl_poll.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2006-2009. All Rights Reserved.
+ * Copyright Ericsson AB 2006-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -216,6 +216,9 @@ typedef struct {
#endif
} ErtsPollInfo;
+#ifdef ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT
+void ERTS_POLL_EXPORT(erts_poll_async_sig_interrupt)(ErtsPollSet);
+#endif
void ERTS_POLL_EXPORT(erts_poll_interrupt)(ErtsPollSet,
int);
void ERTS_POLL_EXPORT(erts_poll_interrupt_timed)(ErtsPollSet,
diff --git a/erts/emulator/sys/unix/erl_unix_sys.h b/erts/emulator/sys/unix/erl_unix_sys.h
index d8d51b192c..9a5ed9f5bc 100644
--- a/erts/emulator/sys/unix/erl_unix_sys.h
+++ b/erts/emulator/sys/unix/erl_unix_sys.h
@@ -129,10 +129,12 @@
#define HAVE_ERTS_CHECK_IO_DEBUG
int erts_check_io_debug(void);
-
-#ifndef ENABLE_CHILD_WAITER_THREAD
+#ifndef ERTS_SMP
# undef ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT
# define ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT
+#endif
+
+#ifndef ENABLE_CHILD_WAITER_THREAD
# ifdef ERTS_SMP
# define ERTS_SMP_SCHEDULERS_NEED_TO_CHECK_CHILDREN
void erts_check_children(void);
diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c
index bafbbb0f6c..c6b63350e5 100644
--- a/erts/emulator/sys/unix/sys.c
+++ b/erts/emulator/sys/unix/sys.c
@@ -52,6 +52,7 @@
#define ERTS_WANT_GOT_SIGUSR1
#define WANT_NONBLOCKING /* must define this to pull in defs from sys.h */
#include "sys.h"
+#include "erl_thr_progress.h"
#if defined(__APPLE__) && defined(__MACH__) && !defined(__DARWIN__)
#define __DARWIN__ 1
@@ -127,7 +128,6 @@ static ErtsSysReportExit *report_exit_list;
static ErtsSysReportExit *report_exit_transit_list;
#endif
-extern int check_async_ready(void);
extern int driver_interrupt(int, int);
extern void do_break(void);
@@ -167,12 +167,12 @@ static int debug_log = 0;
#ifdef ERTS_SMP
erts_smp_atomic32_t erts_got_sigusr1;
#define ERTS_SET_GOT_SIGUSR1 \
- erts_smp_atomic32_set(&erts_got_sigusr1, 1)
+ erts_smp_atomic32_set_mb(&erts_got_sigusr1, 1)
#define ERTS_UNSET_GOT_SIGUSR1 \
- erts_smp_atomic32_set(&erts_got_sigusr1, 0)
+ erts_smp_atomic32_set_mb(&erts_got_sigusr1, 0)
static erts_smp_atomic32_t have_prepared_crash_dump;
#define ERTS_PREPARED_CRASH_DUMP \
- ((int) erts_smp_atomic32_xchg(&have_prepared_crash_dump, 1))
+ ((int) erts_smp_atomic32_xchg_nob(&have_prepared_crash_dump, 1))
#else
volatile int erts_got_sigusr1;
#define ERTS_SET_GOT_SIGUSR1 (erts_got_sigusr1 = 1)
@@ -242,9 +242,9 @@ static int max_files = -1;
#ifdef ERTS_SMP
erts_smp_atomic32_t erts_break_requested;
#define ERTS_SET_BREAK_REQUESTED \
- erts_smp_atomic32_set(&erts_break_requested, (erts_aint32_t) 1)
+ erts_smp_atomic32_set_nob(&erts_break_requested, (erts_aint32_t) 1)
#define ERTS_UNSET_BREAK_REQUESTED \
- erts_smp_atomic32_set(&erts_break_requested, (erts_aint32_t) 0)
+ erts_smp_atomic32_set_nob(&erts_break_requested, (erts_aint32_t) 0)
#else
volatile int erts_break_requested = 0;
#define ERTS_SET_BREAK_REQUESTED (erts_break_requested = 1)
@@ -263,6 +263,7 @@ int erts_use_kernel_poll = 0;
struct {
int (*select)(ErlDrvPort, ErlDrvEvent, int, int);
int (*event)(ErlDrvPort, ErlDrvEvent, ErlDrvEventData);
+ void (*check_io_as_interrupt)(void);
void (*check_io_interrupt)(int);
void (*check_io_interrupt_tmd)(int, long);
void (*check_io)(int);
@@ -302,6 +303,9 @@ init_check_io(void)
if (erts_use_kernel_poll) {
io_func.select = driver_select_kp;
io_func.event = driver_event_kp;
+#ifdef ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT
+ io_func.check_io_as_interrupt = erts_check_io_async_sig_interrupt_kp;
+#endif
io_func.check_io_interrupt = erts_check_io_interrupt_kp;
io_func.check_io_interrupt_tmd = erts_check_io_interrupt_timed_kp;
io_func.check_io = erts_check_io_kp;
@@ -314,6 +318,9 @@ init_check_io(void)
else {
io_func.select = driver_select_nkp;
io_func.event = driver_event_nkp;
+#ifdef ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT
+ io_func.check_io_as_interrupt = erts_check_io_async_sig_interrupt_nkp;
+#endif
io_func.check_io_interrupt = erts_check_io_interrupt_nkp;
io_func.check_io_interrupt_tmd = erts_check_io_interrupt_timed_nkp;
io_func.check_io = erts_check_io_nkp;
@@ -325,6 +332,11 @@ init_check_io(void)
}
}
+#ifdef ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT
+#define ERTS_CHK_IO_AS_INTR() (*io_func.check_io_as_interrupt)()
+#else
+#define ERTS_CHK_IO_AS_INTR() (*io_func.check_io_interrupt)(1)
+#endif
#define ERTS_CHK_IO_INTR (*io_func.check_io_interrupt)
#define ERTS_CHK_IO_INTR_TMD (*io_func.check_io_interrupt_tmd)
#define ERTS_CHK_IO (*io_func.check_io)
@@ -339,6 +351,11 @@ init_check_io(void)
max_files = erts_check_io_max_files();
}
+#ifdef ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT
+#define ERTS_CHK_IO_AS_INTR() erts_check_io_async_sig_interrupt()
+#else
+#define ERTS_CHK_IO_AS_INTR() erts_check_io_interrupt(1)
+#endif
#define ERTS_CHK_IO_INTR erts_check_io_interrupt
#define ERTS_CHK_IO_INTR_TMD erts_check_io_interrupt_timed
#define ERTS_CHK_IO erts_check_io
@@ -346,13 +363,13 @@ init_check_io(void)
#endif
-#ifdef ERTS_SMP
void
erts_sys_schedule_interrupt(int set)
{
ERTS_CHK_IO_INTR(set);
}
+#ifdef ERTS_SMP
void
erts_sys_schedule_interrupt_timed(int set, long msec)
{
@@ -364,7 +381,7 @@ Uint
erts_sys_misc_mem_sz(void)
{
Uint res = ERTS_CHK_IO_SZ();
- res += erts_smp_atomic_read(&sys_misc_mem_sz);
+ res += erts_smp_atomic_read_mb(&sys_misc_mem_sz);
return res;
}
@@ -509,9 +526,9 @@ erts_sys_pre_init(void)
#endif
}
#ifdef ERTS_SMP
- erts_smp_atomic32_init(&erts_break_requested, 0);
- erts_smp_atomic32_init(&erts_got_sigusr1, 0);
- erts_smp_atomic32_init(&have_prepared_crash_dump, 0);
+ erts_smp_atomic32_init_nob(&erts_break_requested, 0);
+ erts_smp_atomic32_init_nob(&erts_got_sigusr1, 0);
+ erts_smp_atomic32_init_nob(&have_prepared_crash_dump, 0);
#else
erts_break_requested = 0;
erts_got_sigusr1 = 0;
@@ -521,13 +538,12 @@ erts_sys_pre_init(void)
children_died = 0;
#endif
#endif /* USE_THREADS */
- erts_smp_atomic_init(&sys_misc_mem_sz, 0);
+ erts_smp_atomic_init_nob(&sys_misc_mem_sz, 0);
}
void
erl_sys_init(void)
{
- erts_smp_rwmtx_init(&environ_rwmtx, "environ");
#if !DISABLE_VFORK
{
int res;
@@ -553,7 +569,7 @@ erl_sys_init(void)
+ sizeof(CHILD_SETUP_PROG_NAME)
+ 1);
child_setup_prog = erts_alloc(ERTS_ALC_T_CS_PROG_PATH, csp_path_sz);
- erts_smp_atomic_add(&sys_misc_mem_sz, csp_path_sz);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, csp_path_sz);
sprintf(child_setup_prog,
"%s%c%s",
bindir,
@@ -732,7 +748,7 @@ break_requested(void)
erl_exit(ERTS_INTR_EXIT, "");
ERTS_SET_BREAK_REQUESTED;
- ERTS_CHK_IO_INTR(1); /* Make sure we don't sleep in poll */
+ ERTS_CHK_IO_AS_INTR(); /* Make sure we don't sleep in poll */
}
/* set up signal handlers for break and quit */
@@ -932,18 +948,13 @@ void
os_flavor(char* namebuf, /* Where to return the name. */
unsigned size) /* Size of name buffer. */
{
- static int called = 0;
- static struct utsname uts; /* Information about the system. */
-
- if (!called) {
- char* s;
+ struct utsname uts; /* Information about the system. */
+ char* s;
- (void) uname(&uts);
- called = 1;
- for (s = uts.sysname; *s; s++) {
- if (isupper((int) *s)) {
- *s = tolower((int) *s);
- }
+ (void) uname(&uts);
+ for (s = uts.sysname; *s; s++) {
+ if (isupper((int) *s)) {
+ *s = tolower((int) *s);
}
}
strcpy(namebuf, uts.sysname);
@@ -1108,31 +1119,6 @@ struct erl_drv_entry vanilla_driver_entry = {
stop_select
};
-#if defined(USE_THREADS) && !defined(ERTS_SMP)
-static int async_drv_init(void);
-static ErlDrvData async_drv_start(ErlDrvPort, char*, SysDriverOpts*);
-static void async_drv_stop(ErlDrvData);
-static void async_drv_input(ErlDrvData, ErlDrvEvent);
-
-/* INTERNAL use only */
-
-struct erl_drv_entry async_driver_entry = {
- async_drv_init,
- async_drv_start,
- async_drv_stop,
- NULL,
- async_drv_input,
- NULL,
- "async",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
-};
-#endif
-
/* Handle SIGCHLD signals. */
#if (defined(SIG_SIGSET) || defined(SIG_SIGNAL))
static RETSIGTYPE onchld(void)
@@ -1146,7 +1132,7 @@ static RETSIGTYPE onchld(int signum)
smp_sig_notify('C');
#else
children_died = 1;
- ERTS_CHK_IO_INTR(1); /* Make sure we don't sleep in poll */
+ ERTS_CHK_IO_AS_INTR(); /* Make sure we don't sleep in poll */
#endif
}
@@ -1216,8 +1202,8 @@ static int spawn_init()
sys_sigset(SIGPIPE, SIG_IGN); /* Ignore - we'll handle the write failure */
driver_data = (struct driver_data *)
erts_alloc(ERTS_ALC_T_DRV_TAB, max_files * sizeof(struct driver_data));
- erts_smp_atomic_add(&sys_misc_mem_sz,
- max_files * sizeof(struct driver_data));
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz,
+ max_files * sizeof(struct driver_data));
for (i = 0; i < max_files; i++)
driver_data[i].pid = -1;
@@ -1925,8 +1911,8 @@ static void clear_fd_data(int fd)
{
if (fd_data[fd].sz > 0) {
erts_free(ERTS_ALC_T_FD_ENTRY_BUF, (void *) fd_data[fd].buf);
- ASSERT(erts_smp_atomic_read(&sys_misc_mem_sz) >= fd_data[fd].sz);
- erts_smp_atomic_add(&sys_misc_mem_sz, -1*fd_data[fd].sz);
+ ASSERT(erts_smp_atomic_read_nob(&sys_misc_mem_sz) >= fd_data[fd].sz);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, -1*fd_data[fd].sz);
}
fd_data[fd].buf = NULL;
fd_data[fd].sz = 0;
@@ -2261,7 +2247,7 @@ static void ready_input(ErlDrvData e, ErlDrvEvent ready_fd)
port_inp_failure(port_num, ready_fd, -1);
}
else {
- erts_smp_atomic_add(&sys_misc_mem_sz, h);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, h);
sys_memcpy(buf, cpos, bytes_left);
fd_data[ready_fd].buf = buf;
fd_data[ready_fd].sz = h;
@@ -2317,87 +2303,6 @@ static void stop_select(ErlDrvEvent fd, void* _)
close((int)fd);
}
-/*
-** Async opertation support
-*/
-#if defined(USE_THREADS) && !defined(ERTS_SMP)
-static void
-sys_async_ready_failed(int fd, int r, int err)
-{
- char buf[120];
- sprintf(buf, "sys_async_ready(): Fatal error: fd=%d, r=%d, errno=%d\n",
- fd, r, err);
- erts_silence_warn_unused_result(write(2, buf, strlen(buf)));
- abort();
-}
-
-/* called from threads !! */
-void sys_async_ready(int fd)
-{
- int r;
- while (1) {
- r = write(fd, "0", 1); /* signal main thread fd MUST be async_fd[1] */
- if (r == 1) {
- DEBUGF(("sys_async_ready(): r = 1\r\n"));
- break;
- }
- if (r < 0 && errno == EINTR) {
- DEBUGF(("sys_async_ready(): r = %d\r\n", r));
- continue;
- }
- sys_async_ready_failed(fd, r, errno);
- }
-}
-
-static int async_drv_init(void)
-{
- async_fd[0] = -1;
- async_fd[1] = -1;
- return 0;
-}
-
-static ErlDrvData async_drv_start(ErlDrvPort port_num,
- char* name, SysDriverOpts* opts)
-{
- if (async_fd[0] != -1)
- return ERL_DRV_ERROR_GENERAL;
- if (pipe(async_fd) < 0)
- return ERL_DRV_ERROR_GENERAL;
-
- DEBUGF(("async_drv_start: %d\r\n", port_num));
-
- SET_NONBLOCKING(async_fd[0]);
- driver_select(port_num, async_fd[0], ERL_DRV_READ, 1);
-
- if (init_async(async_fd[1]) < 0)
- return ERL_DRV_ERROR_GENERAL;
- return (ErlDrvData)port_num;
-}
-
-static void async_drv_stop(ErlDrvData e)
-{
- int port_num = (int)(long)e;
-
- DEBUGF(("async_drv_stop: %d\r\n", port_num));
-
- exit_async();
-
- driver_select(port_num, async_fd[0], ERL_DRV_READ, 0);
-
- close(async_fd[0]);
- close(async_fd[1]);
- async_fd[0] = async_fd[1] = -1;
-}
-
-
-static void async_drv_input(ErlDrvData e, ErlDrvEvent fd)
-{
- char *buf[32];
- DEBUGF(("async_drv_input\r\n"));
- while (read((int) fd, (void *) buf, 32) > 0); /* fd MUST be async_fd[0] */
- check_async_ready(); /* invoke all async_ready */
-}
-#endif
void erts_do_break_handling(void)
{
@@ -2409,11 +2314,7 @@ void erts_do_break_handling(void)
* therefore, make sure that all threads but this one are blocked before
* proceeding!
*/
- erts_smp_block_system(0);
- /*
- * NOTE: since we allow gc we are not allowed to lock
- * (any) process main locks while blocking system...
- */
+ erts_smp_thr_progress_block();
/* during break we revert to initial settings */
/* this is done differently for oldshell */
@@ -2441,7 +2342,7 @@ void erts_do_break_handling(void)
tcsetattr(0,TCSANOW,&temp_mode);
}
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
}
/* Fills in the systems representation of the jam/beam process identifier.
@@ -2465,7 +2366,7 @@ erts_sys_putenv(char *buffer, int sep_ix)
#else
Uint sz = strlen(buffer)+1;
env = erts_alloc(ERTS_ALC_T_PUTENV_STR, sz);
- erts_smp_atomic_add(&sys_misc_mem_sz, sz);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, sz);
strcpy(env,buffer);
#endif
erts_smp_rwmtx_rwlock(&environ_rwmtx);
@@ -2475,12 +2376,10 @@ erts_sys_putenv(char *buffer, int sep_ix)
}
int
-erts_sys_getenv(char *key, char *value, size_t *size)
+erts_sys_getenv__(char *key, char *value, size_t *size)
{
- char *orig_value;
int res;
- erts_smp_rwmtx_rlock(&environ_rwmtx);
- orig_value = getenv(key);
+ char *orig_value = getenv(key);
if (!orig_value)
res = -1;
else {
@@ -2495,6 +2394,15 @@ erts_sys_getenv(char *key, char *value, size_t *size)
res = 0;
}
}
+ return res;
+}
+
+int
+erts_sys_getenv(char *key, char *value, size_t *size)
+{
+ int res;
+ erts_smp_rwmtx_rlock(&environ_rwmtx);
+ res = erts_sys_getenv__(key, value, size);
erts_smp_rwmtx_runlock(&environ_rwmtx);
return res;
}
@@ -2504,33 +2412,8 @@ sys_init_io(void)
{
fd_data = (struct fd_data *)
erts_alloc(ERTS_ALC_T_FD_TAB, max_files * sizeof(struct fd_data));
- erts_smp_atomic_add(&sys_misc_mem_sz,
- max_files * sizeof(struct fd_data));
-
-#ifdef USE_THREADS
-#ifdef ERTS_SMP
- if (init_async(-1) < 0)
- erl_exit(1, "Failed to initialize async-threads\n");
-#else
- {
- /* This is speical stuff, starting a driver from the
- * system routines, but is a nice way of handling stuff
- * the erlang way
- */
- SysDriverOpts dopts;
- int ret;
-
- sys_memset((void*)&dopts, 0, sizeof(SysDriverOpts));
- add_driver_entry(&async_driver_entry);
- ret = erts_open_driver(NULL, NIL, "async", &dopts, NULL);
- DEBUGF(("open_driver = %d\n", ret));
- if (ret < 0)
- erl_exit(1, "Failed to open async driver\n");
- erts_port[ret].status |= ERTS_PORT_SFLG_IMMORTAL;
- }
-#endif
-#endif
-
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz,
+ max_files * sizeof(struct fd_data));
}
#if (0) /* unused? */
@@ -2757,15 +2640,7 @@ initiate_report_exit_status(ErtsSysReportExit *rep, int status)
rep->next = report_exit_transit_list;
rep->status = status;
report_exit_transit_list = rep;
- /*
- * We need the scheduler thread to call check_children().
- * If the scheduler thread is sleeping in a poll with a
- * timeout, we need to wake the scheduler thread. We use the
- * functionality of the async driver to do this, instead of
- * implementing yet another driver doing the same thing. A
- * little bit ugly, but it works...
- */
- sys_async_ready(async_fd[1]);
+ erts_sys_schedule_interrupt(1);
}
static int check_children(void)
@@ -2852,20 +2727,11 @@ erl_sys_schedule(int runnable)
{
#ifdef ERTS_SMP
ERTS_CHK_IO(!runnable);
- ERTS_SMP_LC_ASSERT(!ERTS_LC_IS_BLOCKING);
#else
- ERTS_CHK_IO_INTR(0);
- if (runnable) {
- ERTS_CHK_IO(0); /* Poll for I/O */
- check_async_ready(); /* Check async completions */
- } else {
- int wait_for_io = !check_async_ready();
- if (wait_for_io)
- wait_for_io = !check_children();
- ERTS_CHK_IO(wait_for_io);
- }
- (void) check_children();
+ ERTS_CHK_IO(runnable ? 0 : !check_children());
#endif
+ ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking());
+ (void) check_children();
}
@@ -2893,8 +2759,8 @@ smp_sig_notify(char c)
static void *
signal_dispatcher_thread_func(void *unused)
{
- int initialized = 0;
#if !CHLDWTHR
+ int initialized = 0;
int notify_check_children = 0;
#endif
#ifdef ERTS_ENABLE_LOCK_CHECK
@@ -2922,20 +2788,20 @@ signal_dispatcher_thread_func(void *unused)
* to other threads.
*
* NOTE 2: The signal dispatcher thread is not a blockable
- * thread (i.e., it hasn't called
- * erts_register_blockable_thread()). This is
- * intentional. We want to be able to interrupt
- * writing of a crash dump by hitting C-c twice.
- * Since it isn't a blockable thread it is important
- * that it doesn't change the state of any data that
- * a blocking thread expects to have exclusive access
- * to (unless the signal dispatcher itself explicitly
- * is blocking all blockable threads).
+ * thread (i.e., not a thread managed by the
+ * erl_thr_progress module). This is intentional.
+ * We want to be able to interrupt writing of a crash
+ * dump by hitting C-c twice. Since it isn't a
+ * blockable thread it is important that it doesn't
+ * change the state of any data that a blocking thread
+ * expects to have exclusive access to (unless the
+ * signal dispatcher itself explicitly is blocking all
+ * blockable threads).
*/
switch (buf[i]) {
case 0: /* Emulator initialized */
- initialized = 1;
#if !CHLDWTHR
+ initialized = 1;
if (!notify_check_children)
#endif
break;
@@ -2970,7 +2836,7 @@ signal_dispatcher_thread_func(void *unused)
buf[i]);
}
}
- ERTS_SMP_LC_ASSERT(!ERTS_LC_IS_BLOCKING);
+ ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking());
}
return NULL;
}
@@ -3090,6 +2956,8 @@ erl_sys_args(int* argc, char** argv)
{
int i, j;
+ erts_smp_rwmtx_init(&environ_rwmtx, "environ");
+
i = 1;
ASSERT(argc && argv);
@@ -3151,4 +3019,5 @@ erl_sys_args(int* argc, char** argv)
argv[j++] = argv[i];
}
*argc = j;
+
}
diff --git a/erts/emulator/sys/vxworks/sys.c b/erts/emulator/sys/vxworks/sys.c
index c6e7b65f32..d6d1fe64e0 100644
--- a/erts/emulator/sys/vxworks/sys.c
+++ b/erts/emulator/sys/vxworks/sys.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1997-2010. All Rights Reserved.
+ * Copyright Ericsson AB 1997-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -238,6 +238,12 @@ erl_sys_args(int* argc, char** argv)
ASSERT(max_files <= erts_vxworks_max_files);
}
+void
+erts_sys_schedule_interrupt(int set)
+{
+ erts_check_io_interrupt(set);
+}
+
/*
* Called from schedule() when it runs out of runnable processes,
* or when Erlang code has performed INPUT_REDUCTIONS reduction
@@ -246,7 +252,6 @@ erl_sys_args(int* argc, char** argv)
void
erl_sys_schedule(int runnable)
{
- erts_check_io_interrupt(0);
erts_check_io(!runnable);
}
@@ -309,7 +314,7 @@ static void request_break(void)
fprintf(stderr,"break!\n");
#endif
erts_break_requested = 1;
- erts_check_io_interrupt(1); /* Make sure we don't sleep in erts_poll_wait */
+ erts_check_io_async_sig_interrupt(1); /* Make sure we don't sleep in erts_poll_wait */
}
static void do_quit(void)
@@ -1515,6 +1520,12 @@ erts_sys_getenv(char *key, char *value, size_t *size)
return res;
}
+int
+erts_sys_getenv__(char *key, char *value, size_t *size)
+{
+ return erts_sys_getenv(key, value, size);
+}
+
void
sys_init_io(void)
{
@@ -2025,9 +2036,6 @@ int erl_memory_show(int p0, int p1, int p2, int p3, int p4, int p5,
erts_printf("The memory block used by elib is save_malloc'ed "
"at 0x%08x.\n", (unsigned int) alloc_pool_ptr);
}
-#ifdef NO_FIX_ALLOC
- erts_printf("Fix_alloc is disabled in this build\n");
-#endif
erts_printf("Statistics from elib_malloc:\n");
ELIB_LOCK;
diff --git a/erts/emulator/sys/win32/erl_poll.c b/erts/emulator/sys/win32/erl_poll.c
index 074e2e247f..ab4ef05118 100644
--- a/erts/emulator/sys/win32/erl_poll.c
+++ b/erts/emulator/sys/win32/erl_poll.c
@@ -309,9 +309,9 @@ struct ErtsPollSet_ {
#ifdef ERTS_SMP
extern erts_smp_atomic32_t erts_break_requested;
#define ERTS_SET_BREAK_REQUESTED \
- erts_smp_atomic32_set(&erts_break_requested, (erts_aint32_t) 1)
+ erts_smp_atomic32_set_nob(&erts_break_requested, (erts_aint32_t) 1)
#define ERTS_UNSET_BREAK_REQUESTED \
- erts_smp_atomic32_set(&erts_break_requested, (erts_aint32_t) 0)
+ erts_smp_atomic32_set_nob(&erts_break_requested, (erts_aint32_t) 0)
#else
extern volatile int erts_break_requested;
#define ERTS_SET_BREAK_REQUESTED (erts_break_requested = 1)
@@ -371,19 +371,19 @@ do { \
static ERTS_INLINE int
is_io_ready(ErtsPollSet ps)
{
- return erts_atomic32_read(&ps->wakeup_state) == ERTS_POLL_WOKEN_IO_READY;
+ return erts_atomic32_read_nob(&ps->wakeup_state) == ERTS_POLL_WOKEN_IO_READY;
}
static ERTS_INLINE void
woke_up(ErtsPollSet ps)
{
- if (erts_atomic32_read(&ps->wakeup_state) == ERTS_POLL_NOT_WOKEN)
- erts_atomic32_cmpxchg(&ps->wakeup_state,
- ERTS_POLL_WOKEN_TIMEDOUT,
- ERTS_POLL_NOT_WOKEN);
+ if (erts_atomic32_read_nob(&ps->wakeup_state) == ERTS_POLL_NOT_WOKEN)
+ erts_atomic32_cmpxchg_nob(&ps->wakeup_state,
+ ERTS_POLL_WOKEN_TIMEDOUT,
+ ERTS_POLL_NOT_WOKEN);
#ifdef DEBUG
{
- erts_aint32_t wakeup_state = erts_atomic32_read(&ps->wakeup_state);
+ erts_aint32_t wakeup_state = erts_atomic32_read_nob(&ps->wakeup_state);
switch (wakeup_state) {
case ERTS_POLL_WOKEN_IO_READY:
case ERTS_POLL_WOKEN_INTR:
@@ -401,7 +401,7 @@ static ERTS_INLINE int
wakeup_cause(ErtsPollSet ps)
{
int res;
- erts_aint32_t wakeup_state = erts_atomic32_read(&ps->wakeup_state);
+ erts_aint32_t wakeup_state = erts_atomic32_read_nob(&ps->wakeup_state);
switch (wakeup_state) {
case ERTS_POLL_WOKEN_IO_READY:
res = 0;
@@ -439,7 +439,7 @@ poll_wait_timeout(ErtsPollSet ps, SysTimeval *tvp)
* by ResetEvent().
*/
ERTS_THR_MEMORY_BARRIER;
- if (erts_atomic32_read(&ps->wakeup_state) != ERTS_POLL_NOT_WOKEN)
+ if (erts_atomic32_read_nob(&ps->wakeup_state) != ERTS_POLL_NOT_WOKEN)
return (DWORD) 0;
if (timeout > ERTS_AINT32_T_MAX) /* Also prevents DWORD overflow */
@@ -455,17 +455,17 @@ wake_poller(ErtsPollSet ps, int io_ready)
erts_aint32_t wakeup_state;
if (io_ready) {
/* We may set the event multiple times. This is, however, harmless. */
- wakeup_state = erts_atomic32_read(&ps->wakeup_state);
+ wakeup_state = erts_atomic32_read_nob(&ps->wakeup_state);
erts_atomic32_set_relb(&ps->wakeup_state, ERTS_POLL_WOKEN_IO_READY);
}
else {
ERTS_THR_MEMORY_BARRIER;
- wakeup_state = erts_atomic32_read(&ps->wakeup_state);
+ wakeup_state = erts_atomic32_read_nob(&ps->wakeup_state);
while (wakeup_state != ERTS_POLL_WOKEN_IO_READY
&& wakeup_state != ERTS_POLL_WOKEN_INTR) {
- erts_aint32_t act = erts_atomic32_cmpxchg(&ps->wakeup_state,
- ERTS_POLL_WOKEN_INTR,
- wakeup_state);
+ erts_aint32_t act = erts_atomic32_cmpxchg_nob(&ps->wakeup_state,
+ ERTS_POLL_WOKEN_INTR,
+ wakeup_state);
if (act == wakeup_state) {
wakeup_state = act;
break;
@@ -488,13 +488,13 @@ wake_poller(ErtsPollSet ps, int io_ready)
static ERTS_INLINE void
reset_io_ready(ErtsPollSet ps)
{
- erts_atomic32_set(&ps->wakeup_state, ERTS_POLL_NOT_WOKEN);
+ erts_atomic32_set_nob(&ps->wakeup_state, ERTS_POLL_NOT_WOKEN);
}
static ERTS_INLINE void
restore_io_ready(ErtsPollSet ps)
{
- erts_atomic32_set(&ps->wakeup_state, ERTS_POLL_WOKEN_IO_READY);
+ erts_atomic32_set_nob(&ps->wakeup_state, ERTS_POLL_WOKEN_IO_READY);
}
/*
@@ -511,12 +511,12 @@ static ERTS_INLINE void
reset_interrupt(ErtsPollSet ps)
{
/* We need to keep io-ready if set */
- erts_aint32_t wakeup_state = erts_atomic32_read(&ps->wakeup_state);
+ erts_aint32_t wakeup_state = erts_atomic32_read_nob(&ps->wakeup_state);
while (wakeup_state != ERTS_POLL_WOKEN_IO_READY
&& wakeup_state != ERTS_POLL_NOT_WOKEN) {
- erts_aint32_t act = erts_atomic32_cmpxchg(&ps->wakeup_state,
- ERTS_POLL_NOT_WOKEN,
- wakeup_state);
+ erts_aint32_t act = erts_atomic32_cmpxchg_nob(&ps->wakeup_state,
+ ERTS_POLL_NOT_WOKEN,
+ wakeup_state);
if (wakeup_state == act)
break;
wakeup_state = act;
@@ -692,7 +692,7 @@ static void *break_waiter(void *param)
case WAIT_OBJECT_0:
ResetEvent(harr[0]);
erts_mtx_lock(&break_waiter_lock);
- erts_atomic32_set(&break_waiter_state,BREAK_WAITER_GOT_BREAK);
+ erts_atomic32_set_nob(&break_waiter_state,BREAK_WAITER_GOT_BREAK);
ERTS_THR_MEMORY_BARRIER;
SetEvent(break_happened_event);
erts_mtx_unlock(&break_waiter_lock);
@@ -700,7 +700,7 @@ static void *break_waiter(void *param)
case (WAIT_OBJECT_0+1):
ResetEvent(harr[1]);
erts_mtx_lock(&break_waiter_lock);
- erts_atomic32_set(&break_waiter_state,BREAK_WAITER_GOT_HALT);
+ erts_atomic32_set_nob(&break_waiter_state,BREAK_WAITER_GOT_HALT);
ERTS_THR_MEMORY_BARRIER;
SetEvent(break_happened_event);
erts_mtx_unlock(&break_waiter_lock);
@@ -1153,23 +1153,29 @@ int erts_poll_wait(ErtsPollSet ps,
/*HARDDEBUGF(("timeout = %ld",(long) timeout));*/
- if (timeout > 0 && !erts_atomic32_read(&break_waiter_state)) {
+ if (timeout > 0 && !erts_atomic32_read_nob(&break_waiter_state)) {
HANDLE harr[2] = {ps->event_io_ready, break_happened_event};
int num_h = 2;
HARDDEBUGF(("Start waiting %d [%d]",num_h, (int) timeout));
ERTS_POLLSET_UNLOCK(ps);
+#ifdef ERTS_SMP
+ erts_thr_progress_prepare_wait(NULL);
+#endif
WaitForMultipleObjects(num_h, harr, FALSE, timeout);
+#ifdef ERTS_SMP
+ erts_thr_progress_finalize_wait(NULL);
+#endif
ERTS_POLLSET_LOCK(ps);
HARDDEBUGF(("Stop waiting %d [%d]",num_h, (int) timeout));
woke_up(ps);
}
ERTS_UNSET_BREAK_REQUESTED;
- if(erts_atomic32_read(&break_waiter_state)) {
+ if(erts_atomic32_read_nob(&break_waiter_state)) {
erts_mtx_lock(&break_waiter_lock);
- break_state = erts_atomic32_read(&break_waiter_state);
- erts_atomic32_set(&break_waiter_state,0);
+ break_state = erts_atomic32_read_nob(&break_waiter_state);
+ erts_atomic32_set_nob(&break_waiter_state,0);
ResetEvent(break_happened_event);
erts_mtx_unlock(&break_waiter_lock);
switch (break_state) {
@@ -1236,7 +1242,7 @@ int erts_poll_wait(ErtsPollSet ps,
erts_mtx_unlock(&w->mtx);
}
done:
- erts_smp_atomic32_set(&ps->timeout, ERTS_AINT32_T_MAX);
+ erts_smp_atomic32_set_nob(&ps->timeout, ERTS_AINT32_T_MAX);
*len = num;
ERTS_POLLSET_UNLOCK(ps);
HARDTRACEF(("Out erts_poll_wait"));
@@ -1316,11 +1322,11 @@ ErtsPollSet erts_poll_create_pollset(void)
ps->standby_wait_event = CreateManualEvent(FALSE);
ps->restore_events = 0;
- erts_atomic32_init(&ps->wakeup_state, ERTS_POLL_NOT_WOKEN);
+ erts_atomic32_init_nob(&ps->wakeup_state, ERTS_POLL_NOT_WOKEN);
#ifdef ERTS_SMP
erts_smp_mtx_init(&ps->mtx, "pollset");
#endif
- erts_smp_atomic32_init(&ps->timeout, ERTS_AINT32_T_MAX);
+ erts_smp_atomic32_init_nob(&ps->timeout, ERTS_AINT32_T_MAX);
HARDTRACEF(("Out erts_poll_create_pollset"));
return ps;
@@ -1372,7 +1378,7 @@ void erts_poll_init(void)
erts_mtx_init(&break_waiter_lock,"break_waiter_lock");
break_happened_event = CreateManualEvent(FALSE);
- erts_atomic32_init(&break_waiter_state, 0);
+ erts_atomic32_init_nob(&break_waiter_state, 0);
erts_thr_create(&thread, &break_waiter, NULL, NULL);
ERTS_UNSET_BREAK_REQUESTED;
diff --git a/erts/emulator/sys/win32/sys.c b/erts/emulator/sys/win32/sys.c
index a2159d063c..6f33ef7ad6 100644
--- a/erts/emulator/sys/win32/sys.c
+++ b/erts/emulator/sys/win32/sys.c
@@ -198,7 +198,7 @@ Uint
erts_sys_misc_mem_sz(void)
{
Uint res = (Uint) erts_check_io_size();
- res += (Uint) erts_smp_atomic_read(&sys_misc_mem_sz);
+ res += (Uint) erts_smp_atomic_read_mb(&sys_misc_mem_sz);
return res;
}
@@ -216,6 +216,9 @@ void sys_tty_reset(int exit_code)
void erl_sys_args(int* argc, char** argv)
{
char *event_name;
+
+ erts_sys_env_init();
+
nohup = get_and_remove_option(argc, argv, "-nohup");
#ifdef DEBUG
@@ -566,51 +569,6 @@ struct erl_drv_entry vanilla_driver_entry = {
stop_select
};
-#if defined(USE_THREADS) && !defined(ERTS_SMP)
-
-static int async_drv_init(void);
-static ErlDrvData async_drv_start(ErlDrvPort, char*, SysDriverOpts*);
-static void async_drv_stop(ErlDrvData);
-static void async_drv_input(ErlDrvData, ErlDrvEvent);
-
-/* INTERNAL use only */
-
-void null_output(ErlDrvData drv_data, char* buf, int len)
-{
-}
-
-void null_ready_output(ErlDrvData drv_data, ErlDrvEvent event)
-{
-}
-
-struct erl_drv_entry async_driver_entry = {
- async_drv_init,
- async_drv_start,
- async_drv_stop,
- null_output,
- async_drv_input,
- null_ready_output,
- "async",
- NULL, /* finish */
- NULL, /* handle */
- NULL, /* control */
- NULL, /* timeout */
- NULL, /* outputv */
- NULL, /* ready_async */
- NULL, /* flush */
- NULL, /* call */
- NULL, /* event */
- ERL_DRV_EXTENDED_MARKER,
- ERL_DRV_EXTENDED_MAJOR_VERSION,
- ERL_DRV_EXTENDED_MINOR_VERSION,
- 0, /* ERL_DRV_FLAGs */
- NULL,
- NULL, /* process_exit */
- stop_select
-};
-
-#endif
-
/*
* Initialises a DriverData structure.
*
@@ -648,7 +606,7 @@ new_driver_data(int port_num, int packet_bytes, int wait_objs_required, int use_
erts_smp_mtx_unlock(&sys_driver_data_lock);
return NULL;
}
- erts_smp_atomic_add(&sys_misc_mem_sz, dp->inBufSize);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, dp->inBufSize);
dp->outBufSize = 0;
dp->outbuf = NULL;
dp->port_num = port_num;
@@ -733,8 +691,8 @@ release_driver_data(DriverData* dp)
#endif
if (dp->inbuf != NULL) {
- ASSERT(erts_smp_atomic_read(&sys_misc_mem_sz) >= dp->inBufSize);
- erts_smp_atomic_add(&sys_misc_mem_sz, -1*dp->inBufSize);
+ ASSERT(erts_smp_atomic_read_nob(&sys_misc_mem_sz) >= dp->inBufSize);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, -1*dp->inBufSize);
DRV_BUF_FREE(dp->inbuf);
dp->inBufSize = 0;
dp->inbuf = NULL;
@@ -742,8 +700,8 @@ release_driver_data(DriverData* dp)
ASSERT(dp->inBufSize == 0);
if (dp->outbuf != NULL) {
- ASSERT(erts_smp_atomic_read(&sys_misc_mem_sz) >= dp->outBufSize);
- erts_smp_atomic_add(&sys_misc_mem_sz, -1*dp->outBufSize);
+ ASSERT(erts_smp_atomic_read_nob(&sys_misc_mem_sz) >= dp->outBufSize);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, -1*dp->outBufSize);
DRV_BUF_FREE(dp->outbuf);
dp->outBufSize = 0;
dp->outbuf = NULL;
@@ -1162,7 +1120,8 @@ spawn_init(void)
#endif
driver_data = (struct driver_data *)
erts_alloc(ERTS_ALC_T_DRV_TAB, max_files * sizeof(struct driver_data));
- erts_smp_atomic_add(&sys_misc_mem_sz, max_files*sizeof(struct driver_data));
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz,
+ max_files*sizeof(struct driver_data));
for (i = 0; i < max_files; i++)
driver_data[i].port_num = PORT_FREE;
@@ -1698,7 +1657,7 @@ create_child_process
static int create_pipe(HANDLE *phRead, HANDLE *phWrite, BOOL inheritRead, BOOL overlapped_io)
{
SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
- char pipe_name[128]; /* Name of pipe. */
+ char pipe_name[256]; /* Name of pipe. */
Uint calls;
/*
@@ -1735,9 +1694,9 @@ static int create_pipe(HANDLE *phRead, HANDLE *phWrite, BOOL inheritRead, BOOL o
* Otherwise, create named pipes.
*/
- calls = (Uint) erts_smp_atomic_inctest(&pipe_creation_counter);
- sprintf(pipe_name, "\\\\.\\pipe\\erlang44_%d_%d",
- getpid(), calls);
+ calls = (UWord) erts_smp_atomic_inc_read_nob(&pipe_creation_counter);
+ erts_snprintf(pipe_name, sizeof(pipe_name),
+ "\\\\.\\pipe\\erlang44_%d_%bpu", getpid(), calls);
DEBUGF(("Creating pipe %s\n", pipe_name));
sa.bInheritHandle = inheritRead;
@@ -2529,7 +2488,7 @@ output(ErlDrvData drv_data, char* buf, int len)
}
dp->outBufSize = pb+len;
- erts_smp_atomic_add(&sys_misc_mem_sz, dp->outBufSize);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, dp->outBufSize);
/*
* Store header bytes (if any).
@@ -2558,8 +2517,8 @@ output(ErlDrvData drv_data, char* buf, int len)
} else {
dp->out.ov.Offset += pb+len; /* For vanilla driver. */
/* XXX OffsetHigh should be changed too. */
- ASSERT(erts_smp_atomic_read(&sys_misc_mem_sz) >= dp->outBufSize);
- erts_smp_atomic_add(&sys_misc_mem_sz, -1*dp->outBufSize);
+ ASSERT(erts_smp_atomic_read_nob(&sys_misc_mem_sz) >= dp->outBufSize);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, -1*dp->outBufSize);
DRV_BUF_FREE(dp->outbuf);
dp->outBufSize = 0;
dp->outbuf = NULL;
@@ -2673,9 +2632,9 @@ ready_input(ErlDrvData drv_data, ErlDrvEvent ready_event)
error = ERROR_NOT_ENOUGH_MEMORY;
break; /* Break out of loop into error handler. */
}
- ASSERT(erts_smp_atomic_read(&sys_misc_mem_sz) >= dp->inBufSize);
- erts_smp_atomic_add(&sys_misc_mem_sz,
- dp->totalNeeded - dp->inBufSize);
+ ASSERT(erts_smp_atomic_read_nob(&sys_misc_mem_sz) >= dp->inBufSize);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz,
+ dp->totalNeeded - dp->inBufSize);
dp->inBufSize = dp->totalNeeded;
dp->inbuf = new_buf;
}
@@ -2771,12 +2730,12 @@ ready_output(ErlDrvData drv_data, ErlDrvEvent ready_event)
DEBUGF(("ready_output(%d, 0x%x)\n", drv_data, ready_event));
set_busy_port(dp->port_num, 0);
if (!(dp->outbuf)) {
- /* Happens because event sometimes get signalled during a succesful
+ /* Happens because event sometimes get signalled during a successful
write... */
return;
}
- ASSERT(erts_smp_atomic_read(&sys_misc_mem_sz) >= dp->outBufSize);
- erts_smp_atomic_add(&sys_misc_mem_sz, -1*dp->outBufSize);
+ ASSERT(erts_smp_atomic_read_nob(&sys_misc_mem_sz) >= dp->outBufSize);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, -1*dp->outBufSize);
DRV_BUF_FREE(dp->outbuf);
dp->outBufSize = 0;
dp->outbuf = NULL;
@@ -2824,30 +2783,6 @@ sys_init_io(void)
We estimate the number to twice the amount of ports.
We really dont know on windows, do we? */
max_files = 2*erts_max_ports;
-
-#ifdef USE_THREADS
-#ifdef ERTS_SMP
- if (init_async(-1) < 0)
- erl_exit(1, "Failed to initialize async-threads\n");
-#else
- {
- /* This is special stuff, starting a driver from the
- * system routines, but is a nice way of handling stuff
- * the erlang way
- */
- SysDriverOpts dopts;
- int ret;
-
- sys_memset((void*)&dopts, 0, sizeof(SysDriverOpts));
- add_driver_entry(&async_driver_entry);
- ret = erts_open_driver(NULL, NIL, "async", &dopts, NULL);
- DEBUGF(("open_driver = %d\n", ret));
- if (ret < 0)
- erl_exit(1, "Failed to open async driver\n");
- erts_port[ret].status |= ERTS_PORT_SFLG_IMMORTAL;
- }
-#endif
-#endif
}
#ifdef ERTS_SMP
@@ -2926,8 +2861,8 @@ Preload* sys_preloaded(void)
(num_preloaded+1)*sizeof(Preload));
res_name = erts_alloc(ERTS_ALC_T_PRELOADED,
(num_preloaded+1)*sizeof(unsigned));
- erts_smp_atomic_add(&sys_misc_mem_sz,
- (num_preloaded+1)*sizeof(Preload)
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz,
+ (num_preloaded+1)*sizeof(Preload)
+ (num_preloaded+1)*sizeof(unsigned));
for (i = 0; i < num_preloaded; i++) {
int n;
@@ -2939,7 +2874,7 @@ Preload* sys_preloaded(void)
n = GETWORD(data);
data += 2;
preloaded[i].name = erts_alloc(ERTS_ALC_T_PRELOADED, n+1);
- erts_smp_atomic_add(&sys_misc_mem_sz, n+1);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, n+1);
sys_memcpy(preloaded[i].name, data, n);
preloaded[i].name[n] = '\0';
data += n;
@@ -3281,7 +3216,7 @@ erts_sys_pre_init(void)
#endif
}
#endif
- erts_smp_atomic_init(&sys_misc_mem_sz, 0);
+ erts_smp_atomic_init_nob(&sys_misc_mem_sz, 0);
}
void noinherit_std_handle(DWORD type)
@@ -3297,8 +3232,6 @@ void erl_sys_init(void)
{
HANDLE handle;
- erts_sys_env_init();
-
noinherit_std_handle(STD_OUTPUT_HANDLE);
noinherit_std_handle(STD_INPUT_HANDLE);
noinherit_std_handle(STD_ERROR_HANDLE);
@@ -3310,7 +3243,7 @@ void erl_sys_init(void)
erts_smp_tsd_key_create(&win32_errstr_key);
InitializeCriticalSection(&htbc_lock);
#endif
- erts_smp_atomic_init(&pipe_creation_counter,0);
+ erts_smp_atomic_init_nob(&pipe_creation_counter,0);
/*
* Test if we have named pipes or not.
*/
@@ -3360,13 +3293,13 @@ void erl_sys_init(void)
SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
}
-#ifdef ERTS_SMP
void
erts_sys_schedule_interrupt(int set)
{
erts_check_io_interrupt(set);
}
+#ifdef ERTS_SMP
void
erts_sys_schedule_interrupt_timed(int set, long msec)
{
@@ -3382,76 +3315,7 @@ erts_sys_schedule_interrupt_timed(int set, long msec)
void
erl_sys_schedule(int runnable)
{
-#ifdef ERTS_SMP
erts_check_io(!runnable);
- ERTS_SMP_LC_ASSERT(!ERTS_LC_IS_BLOCKING);
-#else
- erts_check_io_interrupt(0);
- if (runnable) {
- erts_check_io(0); /* Poll for I/O */
- check_async_ready(); /* Check async completions */
- } else {
- erts_check_io(check_async_ready() ? 0 : 1);
- }
-#endif
-}
-
-#if defined(USE_THREADS) && !defined(ERTS_SMP)
-/*
- * Async operation support.
- */
-
-static ErlDrvEvent async_drv_event;
-
-void
-sys_async_ready(int fd)
-{
- SetEvent((HANDLE)async_drv_event);
-}
-
-static int
-async_drv_init(void)
-{
- async_drv_event = (ErlDrvEvent) NULL;
- return 0;
-}
-
-static ErlDrvData
-async_drv_start(ErlDrvPort port_num, char* name, SysDriverOpts* opts)
-{
- if (async_drv_event != (ErlDrvEvent) NULL) {
- return ERL_DRV_ERROR_GENERAL;
- }
- if ((async_drv_event = (ErlDrvEvent)CreateAutoEvent(FALSE)) == (ErlDrvEvent) NULL) {
- return ERL_DRV_ERROR_GENERAL;
- }
-
- driver_select(port_num, async_drv_event, ERL_DRV_READ|ERL_DRV_USE, 1);
- if (init_async(async_drv_event) < 0) {
- return ERL_DRV_ERROR_GENERAL;
- }
- return (ErlDrvData)port_num;
-}
-
-static void
-async_drv_stop(ErlDrvData port_num)
-{
- exit_async();
- driver_select((ErlDrvPort)port_num, async_drv_event, ERL_DRV_READ|ERL_DRV_USE, 0);
- /*CloseHandle((HANDLE)async_drv_event);*/
- async_drv_event = (ErlDrvEvent) NULL;
+ ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking());
}
-
-static void
-async_drv_input(ErlDrvData port_num, ErlDrvEvent e)
-{
- check_async_ready();
-
- /*
- * Our event is auto-resetting.
- */
-}
-
-#endif
-
diff --git a/erts/emulator/sys/win32/sys_env.c b/erts/emulator/sys/win32/sys_env.c
index 02c8433a10..7acc7f07ee 100644
--- a/erts/emulator/sys/win32/sys_env.c
+++ b/erts/emulator/sys/win32/sys_env.c
@@ -55,19 +55,17 @@ erts_sys_putenv(char *key_value, int sep_ix)
}
int
-erts_sys_getenv(char *key, char *value, size_t *size)
+erts_sys_getenv__(char *key, char *value, size_t *size)
{
size_t req_size = 0;
int res = 0;
DWORD new_size;
- erts_smp_rwmtx_rlock(&environ_rwmtx);
SetLastError(0);
new_size = GetEnvironmentVariable((LPCTSTR) key,
(LPTSTR) value,
(DWORD) *size);
res = !new_size && GetLastError() == ERROR_ENVVAR_NOT_FOUND ? -1 : 0;
- erts_smp_rwmtx_runlock(&environ_rwmtx);
if (res < 0)
return res;
res = new_size > *size ? 1 : 0;
@@ -75,6 +73,16 @@ erts_sys_getenv(char *key, char *value, size_t *size)
return res;
}
+int
+erts_sys_getenv(char *key, char *value, size_t *size)
+{
+ int res;
+ erts_smp_rwmtx_rlock(&environ_rwmtx);
+ res = erts_sys_getenv__(key, value, size);
+ erts_smp_rwmtx_runlock(&environ_rwmtx);
+ return res;
+}
+
struct win32_getenv_state {
char *env;
char *next;
diff --git a/erts/emulator/sys/win32/sys_interrupt.c b/erts/emulator/sys/win32/sys_interrupt.c
index 943c338794..93aaa23f97 100644
--- a/erts/emulator/sys/win32/sys_interrupt.c
+++ b/erts/emulator/sys/win32/sys_interrupt.c
@@ -21,6 +21,7 @@
*/
#include "sys.h"
#include "erl_alloc.h"
+#include "erl_thr_progress.h"
#include "erl_driver.h"
#include "../../drivers/win32/win_con.h"
@@ -33,9 +34,9 @@
#ifdef ERTS_SMP
erts_smp_atomic32_t erts_break_requested;
#define ERTS_SET_BREAK_REQUESTED \
- erts_smp_atomic32_set(&erts_break_requested, (erts_aint32_t) 1)
+ erts_smp_atomic32_set_nob(&erts_break_requested, (erts_aint32_t) 1)
#define ERTS_UNSET_BREAK_REQUESTED \
- erts_smp_atomic32_set(&erts_break_requested, (erts_aint32_t) 0)
+ erts_smp_atomic32_set_nob(&erts_break_requested, (erts_aint32_t) 0)
#else
volatile int erts_break_requested = 0;
#define ERTS_SET_BREAK_REQUESTED (erts_break_requested = 1)
@@ -52,14 +53,14 @@ void erts_do_break_handling(void)
* therefore, make sure that all threads but this one are blocked before
* proceeding!
*/
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
/* call the break handling function, reset the flag */
do_break();
ResetEvent(erts_sys_break_event);
ERTS_UNSET_BREAK_REQUESTED;
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
}
diff --git a/erts/emulator/test/alloc_SUITE_data/allocator_test.h b/erts/emulator/test/alloc_SUITE_data/allocator_test.h
index b869a4079c..8b34375980 100644
--- a/erts/emulator/test/alloc_SUITE_data/allocator_test.h
+++ b/erts/emulator/test/alloc_SUITE_data/allocator_test.h
@@ -82,15 +82,17 @@ typedef void* erts_cond;
#define NO_OF_BKTS ((Ulong) ALC_TEST0(0x102))
#define FIND_BKT(A, I) ((int) ALC_TEST2(0x103, (A), (I)))
-/* From erl_bestfit_alloc.c */
-#define IS_AOBF(A) ((Ulong) ALC_TEST1(0x200, (A)))
-#define RBT_ROOT(A) ((RBT_t *) ALC_TEST1(0x201, (A)))
-#define RBT_PARENT(T) ((RBT_t *) ALC_TEST1(0x202, (T)))
-#define RBT_LEFT(T) ((RBT_t *) ALC_TEST1(0x203, (T)))
-#define RBT_RIGHT(T) ((RBT_t *) ALC_TEST1(0x204, (T)))
-#define RBT_NEXT(T) ((RBTL_t *) ALC_TEST1(0x205, (T)))
-#define RBT_IS_BLACK(T) ((Ulong) ALC_TEST1(0x206, (T)))
-#define RBT_IS_TREE(T) ((Ulong) ALC_TEST1(0x207, (T)))
+/* From erl_bestfit_alloc.c and erl_ao_firstfit_alloc.c */
+#define IS_AOBF(A) ((Ulong) ALC_TEST1(RBT_OP(0), (A)))
+#define RBT_ROOT(A) ((RBT_t *) ALC_TEST1(RBT_OP(1), (A)))
+#define RBT_PARENT(T) ((RBT_t *) ALC_TEST1(RBT_OP(2), (T)))
+#define RBT_LEFT(T) ((RBT_t *) ALC_TEST1(RBT_OP(3), (T)))
+#define RBT_RIGHT(T) ((RBT_t *) ALC_TEST1(RBT_OP(4), (T)))
+#define RBT_NEXT(T) ((RBTL_t *) ALC_TEST1(RBT_OP(5), (T)))
+#define RBT_IS_BLACK(T) ((Ulong) ALC_TEST1(RBT_OP(6), (T)))
+#define RBT_IS_TREE(T) ((Ulong) ALC_TEST1(RBT_OP(7), (T)))
+#define IS_AOFF(A) ((Ulong) ALC_TEST1(RBT_OP(8), (A)))
+#define RBT_MAX_SZ(T) ((Ulong) ALC_TEST1(RBT_OP(9), (T)))
/* From erl_mseg.c */
#define HAVE_MSEG() ((int) ALC_TEST0(0x400))
diff --git a/erts/emulator/test/alloc_SUITE_data/coalesce.c b/erts/emulator/test/alloc_SUITE_data/coalesce.c
index c84da97d35..6f35d3279b 100644
--- a/erts/emulator/test/alloc_SUITE_data/coalesce.c
+++ b/erts/emulator/test/alloc_SUITE_data/coalesce.c
@@ -267,7 +267,7 @@ void
testcase_run(TestCaseState_t *tcs)
{
char *argv_org[] = {"-tmmbcs1024", "-tsbct2048", "-trmbcmt100", "-tas", NULL, NULL};
- char *alg[] = {"af", "gf", "bf", "aobf", NULL};
+ char *alg[] = {"af", "gf", "bf", "aobf", "aoff", NULL};
int i;
for (i = 0; alg[i]; i++) {
diff --git a/erts/emulator/test/alloc_SUITE_data/rbtree.c b/erts/emulator/test/alloc_SUITE_data/rbtree.c
index c97e0aac1a..4e7f821baf 100644
--- a/erts/emulator/test/alloc_SUITE_data/rbtree.c
+++ b/erts/emulator/test/alloc_SUITE_data/rbtree.c
@@ -34,6 +34,14 @@ typedef struct {
#define PRINT_TREE
#endif
+/* Ugly hack to steer the test code towards the right allocator */
+#define RBT_OP(CMD) (current_rbt_type_op_base + (CMD))
+static enum {
+ BESTFIT_OP_BASE = 0x200,
+ AO_FIRSTFIT_OP_BASE = 0x500
+}current_rbt_type_op_base;
+
+
#ifdef PRINT_TREE
#define INDENT_STEP 5
@@ -65,12 +73,11 @@ print_tree_aux(TestCaseState_t *tcs, RBT_t *x, int indent)
static void
-print_tree(TestCaseState_t *tcs, RBT_t *root, int aobf)
+print_tree(TestCaseState_t *tcs, RBT_t *root)
{
- char *type = aobf ? "Size-Adress" : "Size";
- testcase_printf(tcs, " --- %s tree begin ---\r\n", type);
+ testcase_printf(tcs, " --- Tree begin ---\r\n");
print_tree_aux(tcs, root, 0);
- testcase_printf(tcs, " --- %s tree end ---\r\n", type);
+ testcase_printf(tcs, " --- Tree end ---\r\n");
}
#endif
@@ -78,7 +85,8 @@ print_tree(TestCaseState_t *tcs, RBT_t *root, int aobf)
static RBT_t *
check_tree(TestCaseState_t *tcs, Allctr_t *alc, Ulong size)
{
- int i, max_i, address_order;
+ enum { BF, AOBF, AOFF }type;
+ int i, max_i;
char stk[128];
RBT_t *root, *x, *y, *res;
Ulong x_sz, y_sz, is_x_black;
@@ -86,11 +94,14 @@ check_tree(TestCaseState_t *tcs, Allctr_t *alc, Ulong size)
res = NULL;
- address_order = IS_AOBF(alc);
+ if (IS_AOBF(alc)) type = AOBF;
+ else if (IS_AOFF(alc)) type = AOFF;
+ else type = BF;
+
root = RBT_ROOT(alc);
#ifdef PRINT_TREE
- print_tree(tcs, root, address_order);
+ print_tree(tcs, root);
#endif
max_i = i = -1;
@@ -165,12 +176,18 @@ check_tree(TestCaseState_t *tcs, Allctr_t *alc, Ulong size)
if (y) {
y_sz = BLK_SZ(y);
ASSERT(tcs, RBT_PARENT(y) == x);
- if (address_order) {
+ switch (type) {
+ case AOBF:
ASSERT(tcs, y_sz < x_sz || (y_sz == x_sz && y < x));
- }
- else {
+ break;
+ case BF:
ASSERT(tcs, RBT_IS_TREE(y));
ASSERT(tcs, y_sz < x_sz);
+ break;
+ case AOFF:
+ ASSERT(tcs, y < x);
+ ASSERT(tcs, RBT_MAX_SZ(y) <= RBT_MAX_SZ(x));
+ break;
}
}
@@ -178,16 +195,22 @@ check_tree(TestCaseState_t *tcs, Allctr_t *alc, Ulong size)
if (y) {
y_sz = BLK_SZ(y);
ASSERT(tcs, RBT_PARENT(y) == x);
- if (address_order) {
+ switch (type) {
+ case AOBF:
ASSERT(tcs, y_sz > x_sz || (y_sz == x_sz && y > x));
- }
- else {
+ break;
+ case BF:
ASSERT(tcs, RBT_IS_TREE(y));
ASSERT(tcs, y_sz > x_sz);
+ break;
+ case AOFF:
+ ASSERT(tcs, y > x);
+ ASSERT(tcs, RBT_MAX_SZ(y) <= RBT_MAX_SZ(x));
+ break;
}
}
- if (!address_order) {
+ if (type == BF) {
Ulong l_sz;
RBTL_t *l = RBT_NEXT(x);
for (l = RBT_NEXT(x); l; l = RBT_NEXT(l)) {
@@ -202,13 +225,20 @@ check_tree(TestCaseState_t *tcs, Allctr_t *alc, Ulong size)
res = x;
else {
y_sz = BLK_SZ(res);
- if (address_order) {
+ switch (type) {
+ case AOBF:
if (x_sz < y_sz || (x_sz == y_sz && x < res))
res = x;
- }
- else {
- if (!res || x_sz < y_sz)
+ break;
+ case BF:
+ if (x_sz < y_sz)
res = x;
+ break;
+ case AOFF:
+ if (x < res) {
+ res = x;
+ }
+ break;
}
}
}
@@ -257,7 +287,7 @@ static void
test_it(TestCaseState_t *tcs)
{
int i;
- Allctr_t a = ((rbtree_test_data *) tcs->extra)->allocator;
+ Allctr_t* a = ((rbtree_test_data *) tcs->extra)->allocator;
void **blk = ((rbtree_test_data *) tcs->extra)->blk;
void **fence = ((rbtree_test_data *) tcs->extra)->fence;
Ulong min_blk_sz;
@@ -338,6 +368,7 @@ testcase_run(TestCaseState_t *tcs)
{
char *argv1[] = {"-tasbf", NULL};
char *argv2[] = {"-tasaobf", NULL};
+ char *argv3[] = {"-tasaoff", NULL};
Allctr_t *a;
rbtree_test_data *td;
@@ -355,6 +386,7 @@ testcase_run(TestCaseState_t *tcs)
testcase_printf(tcs, "Starting test of best fit...\n");
+ current_rbt_type_op_base = BESTFIT_OP_BASE;
td->allocator = a = START_ALC("rbtree_bf_", 0, argv1);
ASSERT(tcs, a);
@@ -371,6 +403,7 @@ testcase_run(TestCaseState_t *tcs)
testcase_printf(tcs, "Starting test of address order best fit...\n");
+ current_rbt_type_op_base = BESTFIT_OP_BASE;
td->allocator = a = START_ALC("rbtree_aobf_", 0, argv2);
ASSERT(tcs, a);
@@ -383,4 +416,19 @@ testcase_run(TestCaseState_t *tcs)
testcase_printf(tcs, "Address order best fit test succeeded!\n");
+ /* Address order first fit... */
+
+ testcase_printf(tcs, "Starting test of address order first fit...\n");
+
+ current_rbt_type_op_base = AO_FIRSTFIT_OP_BASE;
+ td->allocator = a = START_ALC("rbtree_aoff_", 0, argv3);
+
+ ASSERT(tcs, a);
+
+ test_it(tcs);
+
+ STOP_ALC(a);
+ td->allocator = NULL;
+
+ testcase_printf(tcs, "Address order first fit test succeeded!\n");
}
diff --git a/erts/emulator/test/binary_SUITE.erl b/erts/emulator/test/binary_SUITE.erl
index 4e82381fba..d9fc876482 100644
--- a/erts/emulator/test/binary_SUITE.erl
+++ b/erts/emulator/test/binary_SUITE.erl
@@ -33,7 +33,6 @@
%% erlang:external_size/1
%% size(Binary)
%% iolist_size/1
-%% concat_binary/1
%% split_binary/2
%% hash(Binary, N)
%% phash(Binary, N)
@@ -47,7 +46,7 @@
init_per_testcase/2, end_per_testcase/2,
copy_terms/1, conversions/1, deep_lists/1, deep_bitstr_lists/1,
bad_list_to_binary/1, bad_binary_to_list/1,
- t_split_binary/1, bad_split/1, t_concat_binary/1,
+ t_split_binary/1, bad_split/1,
terms/1, terms_float/1, external_size/1, t_iolist_size/1,
t_hash/1,
bad_size/1,
@@ -68,7 +67,7 @@ suite() -> [{ct_hooks,[ts_install_cth]},
all() ->
[copy_terms, conversions, deep_lists, deep_bitstr_lists,
- t_split_binary, bad_split, t_concat_binary,
+ t_split_binary, bad_split,
bad_list_to_binary, bad_binary_to_list, terms,
terms_float, external_size, t_iolist_size,
bad_binary_to_term_2, safe_binary_to_term2,
@@ -93,7 +92,6 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-
init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
Config.
@@ -381,41 +379,6 @@ bad_split(Config) when is_list(Config) ->
bad_split(Bin, Pos) ->
{'EXIT',{badarg,_}} = (catch split_binary(Bin, Pos)).
-%% Tests concat_binary/2 and size/1.
-
-t_concat_binary(suite) -> [];
-t_concat_binary(Config) when is_list(Config) ->
- test_concat([]),
-
- test_concat([[]]),
- test_concat([[], []]),
- test_concat([[], [], []]),
-
- test_concat([[1], []]),
- test_concat([[], [2]]),
- test_concat([[], [3], []]),
-
- test_concat([[1, 2, 3], [4, 5, 6, 7]]),
- test_concat([[1, 2, 3], [4, 5, 6, 7], [9, 10]]),
-
- test_concat([lists:seq(0, 255), lists:duplicate(1024, $@),
- lists:duplicate(2048, $a),
- lists:duplicate(4000, $b)]),
- ok.
-
-test_concat(Lists) ->
- test_concat(Lists, 0, [], []).
-
-test_concat([List|Rest], Size, Combined, Binaries) ->
- ?line Bin = list_to_binary(List),
- ?line test_concat(Rest, Size+length(List), Combined++List, [Bin|Binaries]);
-test_concat([], Size, Combined, Binaries0) ->
- ?line Binaries = lists:reverse(Binaries0),
- ?line Bin = concat_binary(Binaries),
- ?line Size = size(Bin),
- ?line Size = iolist_size(Bin),
- ?line Combined = binary_to_list(Bin).
-
t_hash(doc) -> "Test hash/2 with different type of binaries.";
t_hash(Config) when is_list(Config) ->
test_hash([]),
@@ -478,6 +441,11 @@ terms(Config) when is_list(Config) ->
Sz when is_integer(Sz), size(Bin) =< Sz ->
ok
end,
+ Bin1 = term_to_binary(Term, [{minor_version, 1}]),
+ case erlang:external_size(Bin1, [{minor_version, 1}]) of
+ Sz1 when is_integer(Sz1), size(Bin1) =< Sz1 ->
+ ok
+ end,
Term = binary_to_term(Bin),
Term = binary_to_term(Bin, [safe]),
Unaligned = make_unaligned_sub_binary(Bin),
@@ -510,7 +478,12 @@ terms_float(Config) when is_list(Config) ->
Term = binary_to_term(Bin0),
Bin1 = term_to_binary(Term, [{minor_version,1}]),
Term = binary_to_term(Bin1),
- true = size(Bin1) < size(Bin0)
+ true = size(Bin1) < size(Bin0),
+ Size0 = erlang:external_size(Term),
+ Size00 = erlang:external_size(Term, [{minor_version, 0}]),
+ Size1 = erlang:external_size(Term, [{minor_version, 1}]),
+ true = (Size0 =:= Size00),
+ true = Size1 < Size0
end).
external_size(Config) when is_list(Config) ->
@@ -526,7 +499,9 @@ external_size(Config) when is_list(Config) ->
io:format(" Aligned size: ~p\n", [Sz1]),
io:format("Unaligned size: ~p\n", [Sz2]),
?line ?t:fail()
- end.
+ end,
+ ?line erlang:external_size(Bin) =:= erlang:external_size(Bin, [{minor_version, 1}]),
+ ?line erlang:external_size(Unaligned) =:= erlang:external_size(Unaligned, [{minor_version, 1}]).
external_size_1(Term, Size0, Limit) when Size0 < Limit ->
case erlang:external_size(Term) of
diff --git a/erts/emulator/test/bs_construct_SUITE.erl b/erts/emulator/test/bs_construct_SUITE.erl
index 1959803385..7fdf36711b 100644
--- a/erts/emulator/test/bs_construct_SUITE.erl
+++ b/erts/emulator/test/bs_construct_SUITE.erl
@@ -553,6 +553,11 @@ huge_float_check({'EXIT',{badarg,_}}) -> ok.
huge_binary(Config) when is_list(Config) ->
?line 16777216 = size(<<0:(id(1 bsl 26)),(-1):(id(1 bsl 26))>>),
+ ?line garbage_collect(),
+ ?line id(<<0:((1 bsl 32)-1)>>),
+ ?line garbage_collect(),
+ ?line id(<<0:(id((1 bsl 32)-1))>>),
+ ?line garbage_collect(),
ok.
system_limit(Config) when is_list(Config) ->
@@ -565,6 +570,10 @@ system_limit(Config) when is_list(Config) ->
?line {'EXIT',{system_limit,_}} =
(catch <<(id(<<>>))/binary,0:(id(1 bsl 100))>>),
+ %% Would fail to load.
+ ?line {'EXIT',{system_limit,_}} = (catch <<0:(1 bsl 67)>>),
+ ?line {'EXIT',{system_limit,_}} = (catch <<0:((1 bsl 64)+1)>>),
+
case WordSize of
4 ->
system_limit_32();
@@ -581,6 +590,14 @@ system_limit_32() ->
?line {'EXIT',{system_limit,_}} = (catch <<0:(id(8)),42:536870912/unit:8>>),
?line {'EXIT',{system_limit,_}} =
(catch <<0:(id(8)),42:(id(536870912))/unit:8>>),
+
+ %% The size would be silently truncated, resulting in a crash.
+ ?line {'EXIT',{system_limit,_}} = (catch <<0:(1 bsl 35)>>),
+ ?line {'EXIT',{system_limit,_}} = (catch <<0:((1 bsl 32)+1)>>),
+
+ %% Would fail to load.
+ ?line {'EXIT',{system_limit,_}} = (catch <<0:(1 bsl 43)>>),
+ ?line {'EXIT',{system_limit,_}} = (catch <<0:((1 bsl 40)+1)>>),
ok.
badarg(Config) when is_list(Config) ->
diff --git a/erts/emulator/test/bs_match_misc_SUITE.erl b/erts/emulator/test/bs_match_misc_SUITE.erl
index b022f96740..15427661f3 100644
--- a/erts/emulator/test/bs_match_misc_SUITE.erl
+++ b/erts/emulator/test/bs_match_misc_SUITE.erl
@@ -23,7 +23,7 @@
bound_var/1,bound_tail/1,t_float/1,little_float/1,sean/1,
kenneth/1,encode_binary/1,native/1,happi/1,
size_var/1,wiger/1,x0_context/1,huge_float_field/1,
- writable_binary_matched/1,otp_7198/1]).
+ writable_binary_matched/1,otp_7198/1,unordered_bindings/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -33,7 +33,7 @@ all() ->
[bound_var, bound_tail, t_float, little_float, sean,
kenneth, encode_binary, native, happi, size_var, wiger,
x0_context, huge_float_field, writable_binary_matched,
- otp_7198].
+ otp_7198, unordered_bindings].
groups() ->
[].
@@ -553,5 +553,15 @@ otp_7198_scan(<<C, Rest/binary>>, TokAcc) when
otp_7198_scan(Rest, [{'KEYWORD', C} | TokAcc])
end.
+unordered_bindings(Config) when is_list(Config) ->
+ {<<1,2,3,4>>,<<42,42>>,<<3,3,3>>} =
+ unordered_bindings(4, 2, 3, <<1,2,3,4, 42,42, 3,3,3, 3>>),
+ ok.
+
+unordered_bindings(CompressedLength, HashSize, PadLength, T) ->
+ <<Content:CompressedLength/binary,Mac:HashSize/binary,
+ Padding:PadLength/binary,PadLength>> = T,
+ {Content,Mac,Padding}.
+
id(I) -> I.
diff --git a/erts/emulator/test/bs_utf_SUITE.erl b/erts/emulator/test/bs_utf_SUITE.erl
index 72c656c400..4ab7d674a6 100644
--- a/erts/emulator/test/bs_utf_SUITE.erl
+++ b/erts/emulator/test/bs_utf_SUITE.erl
@@ -64,8 +64,7 @@ end_per_group(_GroupName, Config) ->
utf8_roundtrip(Config) when is_list(Config) ->
?line utf8_roundtrip(0, 16#D7FF),
- ?line utf8_roundtrip(16#E000, 16#FFFD),
- ?line utf8_roundtrip(16#10000, 16#10FFFF),
+ ?line utf8_roundtrip(16#E000, 16#10FFFF),
ok.
utf8_roundtrip(First, Last) when First =< Last ->
@@ -91,8 +90,7 @@ utf16_roundtrip(Config) when is_list(Config) ->
do_utf16_roundtrip(Fun) ->
do_utf16_roundtrip(0, 16#D7FF, Fun),
- do_utf16_roundtrip(16#E000, 16#FFFD, Fun),
- do_utf16_roundtrip(16#10000, 16#10FFFF, Fun).
+ do_utf16_roundtrip(16#E000, 16#10FFFF, Fun).
do_utf16_roundtrip(First, Last, Fun) when First =< Last ->
Fun(First),
@@ -129,8 +127,7 @@ utf32_roundtrip(Config) when is_list(Config) ->
do_utf32_roundtrip(Fun) ->
do_utf32_roundtrip(0, 16#D7FF, Fun),
- do_utf32_roundtrip(16#E000, 16#FFFD, Fun),
- do_utf32_roundtrip(16#10000, 16#10FFFF, Fun).
+ do_utf32_roundtrip(16#E000, 16#10FFFF, Fun).
do_utf32_roundtrip(First, Last, Fun) when First =< Last ->
Fun(First),
@@ -158,7 +155,6 @@ utf32_little_roundtrip(Char) ->
utf8_illegal_sequences(Config) when is_list(Config) ->
?line fail_range(16#10FFFF+1, 16#10FFFF+512), %Too large.
?line fail_range(16#D800, 16#DFFF), %Reserved for UTF-16.
- ?line fail_range(16#FFFE, 16#FFFF), %Non-characters.
%% Illegal first character.
?line [fail(<<I,16#8F,16#8F,16#8F>>) || I <- lists:seq(16#80, 16#BF)],
@@ -251,7 +247,6 @@ fail_1(_) -> ok.
utf16_illegal_sequences(Config) when is_list(Config) ->
?line utf16_fail_range(16#10FFFF+1, 16#10FFFF+512), %Too large.
?line utf16_fail_range(16#D800, 16#DFFF), %Reserved for UTF-16.
- ?line utf16_fail_range(16#FFFE, 16#FFFF), %Non-characters.
?line lonely_hi_surrogate(16#D800, 16#DFFF),
?line leading_lo_surrogate(16#DC00, 16#DFFF),
@@ -300,7 +295,6 @@ leading_lo_surrogate(_, _, _) -> ok.
utf32_illegal_sequences(Config) when is_list(Config) ->
?line utf32_fail_range(16#10FFFF+1, 16#10FFFF+512), %Too large.
?line utf32_fail_range(16#D800, 16#DFFF), %Reserved for UTF-16.
- ?line utf32_fail_range(16#FFFE, 16#FFFF), %Non-characters.
?line utf32_fail_range(-100, -1),
ok.
diff --git a/erts/emulator/test/busy_port_SUITE.erl b/erts/emulator/test/busy_port_SUITE.erl
index 8365e1c540..3a29fd4d68 100644
--- a/erts/emulator/test/busy_port_SUITE.erl
+++ b/erts/emulator/test/busy_port_SUITE.erl
@@ -20,7 +20,7 @@
-module(busy_port_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_group/2,end_per_group/2,end_per_testcase/2,
io_to_busy/1, message_order/1, send_3/1,
system_monitor/1, no_trap_exit/1,
no_trap_exit_unlinked/1, trap_exit/1, multiple_writers/1,
@@ -53,6 +53,20 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
+end_per_testcase(_Case, Config) when is_list(Config) ->
+ case whereis(busy_drv_server) of
+ undefined ->
+ ok;
+ Pid when is_pid(Pid) ->
+ Ref = monitor(process, Pid),
+ unlink(Pid),
+ exit(Pid, kill),
+ receive
+ {'DOWN',Ref,process,Pid,_} ->
+ ok
+ end
+ end,
+ Config.
%% Tests I/O operations to a busy port, to make sure a suspended send
%% operation is correctly restarted. This used to crash Beam.
@@ -495,12 +509,12 @@ hs_busy_pcmd(Prt, Opts, StartFun, EndFun) ->
P = spawn_link(fun () ->
erlang:yield(),
Tester ! {self(), doing_port_command},
- Start = os:timestamp(),
+ Start = now(),
Res = try {return,
port_command(Prt, [], Opts)}
catch Exception:Error -> {Exception, Error}
end,
- End = os:timestamp(),
+ End = now(),
Time = round(timer:now_diff(End, Start)/1000),
Tester ! {self(), port_command_result, Res, Time}
end),
diff --git a/erts/emulator/test/call_trace_SUITE.erl b/erts/emulator/test/call_trace_SUITE.erl
index 93fdc157f7..3e2bee06d1 100644
--- a/erts/emulator/test/call_trace_SUITE.erl
+++ b/erts/emulator/test/call_trace_SUITE.erl
@@ -934,6 +934,10 @@ exception_nocatch(Config) when is_list(Config) ->
exception_nocatch().
exception_nocatch() ->
+ Deep4LocThrow = get_deep_4_loc({throw,[42]}),
+ Deep4LocError = get_deep_4_loc({error,[42]}),
+ Deep4LocBadmatch = get_deep_4_loc({'=',[a,b]}),
+
Prog = [{'_',[],[{exception_trace}]}],
?line 1 = erlang:trace_pattern({?MODULE,deep_1,'_'}, Prog),
?line 1 = erlang:trace_pattern({?MODULE,deep_2,'_'}, Prog),
@@ -959,8 +963,9 @@ exception_nocatch() ->
{trace,t2,exception_from,{erlang,throw,1},
{error,{nocatch,Q2}}}],
exception_from, {error,{nocatch,Q2}}),
- ?line expect({trace,T2,exit,{{nocatch,Q2},[{erlang,throw,[Q2]},
- {?MODULE,deep_4,1}]}}),
+ ?line expect({trace,T2,exit,{{nocatch,Q2},[{erlang,throw,[Q2],[]},
+ {?MODULE,deep_4,1,
+ Deep4LocThrow}]}}),
?line Q3 = {dump,[dump,{dump}]},
?line T3 =
exception_nocatch(?LINE, error, [Q3], 4,
@@ -968,18 +973,29 @@ exception_nocatch() ->
{trace,t3,exception_from,{erlang,error,1},
{error,Q3}}],
exception_from, {error,Q3}),
- ?line expect({trace,T3,exit,{Q3,[{erlang,error,[Q3]},
- {?MODULE,deep_4,1}]}}),
+ ?line expect({trace,T3,exit,{Q3,[{erlang,error,[Q3],[]},
+ {?MODULE,deep_4,1,Deep4LocError}]}}),
?line T4 =
exception_nocatch(?LINE, '=', [17,4711], 5, [],
exception_from, {error,{badmatch,4711}}),
- ?line expect({trace,T4,exit,{{badmatch,4711},[{?MODULE,deep_4,1}]}}),
+ ?line expect({trace,T4,exit,{{badmatch,4711},
+ [{?MODULE,deep_4,1,Deep4LocBadmatch}]}}),
%%
?line erlang:trace_pattern({?MODULE,'_','_'}, false),
?line erlang:trace_pattern({erlang,'_','_'}, false),
?line expect(),
?line ok.
+get_deep_4_loc(Arg) ->
+ try
+ deep_4(Arg),
+ ?t:fail(should_not_return_to_here)
+ catch
+ _:_ ->
+ [{?MODULE,deep_4,1,Loc0}|_] = erlang:get_stacktrace(),
+ Loc0
+ end.
+
exception_nocatch(Line, B, Q, N, Extra, Tag, R) ->
?line io:format("== Subtest: ~w", [Line]),
?line Go = make_ref(),
diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl
index a062cea117..2f9b01cc92 100644
--- a/erts/emulator/test/code_SUITE.erl
+++ b/erts/emulator/test/code_SUITE.erl
@@ -20,28 +20,34 @@
-module(code_SUITE).
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
- new_binary_types/1,t_check_process_code/1,t_check_process_code_ets/1,
+ new_binary_types/1,
+ t_check_process_code/1,t_check_old_code/1,
+ t_check_process_code_ets/1,
external_fun/1,get_chunk/1,module_md5/1,make_stub/1,
- make_stub_many_funs/1,constant_pools/1,
- false_dependency/1,coverage/1]).
+ make_stub_many_funs/1,constant_pools/1,constant_refc_binaries/1,
+ false_dependency/1,coverage/1,fun_confusion/1]).
+-define(line_trace, 1).
-include_lib("test_server/include/test_server.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[new_binary_types, t_check_process_code,
- t_check_process_code_ets, external_fun, get_chunk,
+ t_check_process_code_ets, t_check_old_code, external_fun, get_chunk,
module_md5, make_stub, make_stub_many_funs,
- constant_pools, false_dependency, coverage].
+ constant_pools, constant_refc_binaries, false_dependency,
+ coverage, fun_confusion].
groups() ->
[].
init_per_suite(Config) ->
+ erts_debug:set_internal_state(available_internal_state, true),
Config.
end_per_suite(_Config) ->
+ catch erts_debug:set_internal_state(available_internal_state, false),
ok.
init_per_group(_GroupName, Config) ->
@@ -248,9 +254,36 @@ fun_refc(F) ->
Count.
+%% Test the erlang:check_old_code/1 BIF.
+t_check_old_code(Config) when is_list(Config) ->
+ ?line Data = ?config(data_dir, Config),
+ ?line File = filename:join(Data, "my_code_test"),
+
+ ?line erlang:purge_module(my_code_test),
+ ?line erlang:delete_module(my_code_test),
+ ?line catch erlang:purge_module(my_code_test),
+
+ ?line false = erlang:check_old_code(my_code_test),
+
+ ?line {ok,my_code_test,Code} = compile:file(File, [binary]),
+ ?line {module,my_code_test} = code:load_binary(my_code_test, File, Code),
+
+ ?line false = erlang:check_old_code(my_code_test),
+ ?line {module,my_code_test} = code:load_binary(my_code_test, File, Code),
+ ?line true = erlang:check_old_code(my_code_test),
+
+ ?line true = erlang:purge_module(my_code_test),
+ ?line true = erlang:delete_module(my_code_test),
+ ?line true = erlang:purge_module(my_code_test),
+
+ ?line {'EXIT',_} = (catch erlang:check_old_code([])),
+
+ ok.
+
external_fun(Config) when is_list(Config) ->
?line false = erlang:function_exported(another_code_test, x, 1),
- ?line ExtFun = erlang:make_fun(id(another_code_test), x, 1),
+ AnotherCodeTest = id(another_code_test),
+ ExtFun = fun AnotherCodeTest:x/1,
?line {'EXIT',{undef,_}} = (catch ExtFun(answer)),
?line false = erlang:function_exported(another_code_test, x, 1),
?line false = lists:member(another_code_test, erlang:loaded()),
@@ -375,7 +408,7 @@ make_stub_many_funs(Config) when is_list(Config) ->
constant_pools(Config) when is_list(Config) ->
?line Data = ?config(data_dir, Config),
?line File = filename:join(Data, "literals"),
- ?line {ok,literals,Code} = compile:file(File, [report,binary,constant_pool]),
+ ?line {ok,literals,Code} = compile:file(File, [report,binary]),
?line {module,literals} = erlang:load_module(literals,
make_sub_binary(Code)),
@@ -446,6 +479,131 @@ create_old_heap() ->
create_old_heap()
end.
+constant_refc_binaries(Config) when is_list(Config) ->
+ wait_for_memory_deallocations(),
+ Bef = memory_binary(),
+ io:format("Binary data (bytes) before test: ~p\n", [Bef]),
+
+ %% Compile the the literals module.
+ Data = ?config(data_dir, Config),
+ File = filename:join(Data, "literals"),
+ {ok,literals,Code} = compile:file(File, [report,binary]),
+
+ %% Load the code and make sure that the binary is a refc binary.
+ {module,literals} = erlang:load_module(literals, Code),
+ Bin = literals:binary(),
+ Sz = byte_size(Bin),
+ Check = erlang:md5(Bin),
+ io:format("Size of literal refc binary: ~p\n", [Sz]),
+ {refc_binary,Sz,_,_} = erts_debug:get_internal_state({binary_info,Bin}),
+ true = erlang:delete_module(literals),
+ false = erlang:check_process_code(self(), literals),
+ true = erlang:purge_module(literals),
+
+ %% Now try to provoke a memory leak.
+ provoke_mem_leak(10, Code, Check),
+
+ %% Calculate the change in allocated binary data.
+ erlang:garbage_collect(),
+ wait_for_memory_deallocations(),
+ Aft = memory_binary(),
+ io:format("Binary data (bytes) after test: ~p", [Aft]),
+ Diff = Aft - Bef,
+ if
+ Diff < 0 ->
+ io:format("~p less bytes", [abs(Diff)]);
+ Diff > 0 ->
+ io:format("~p more bytes", [Diff]);
+ true ->
+ ok
+ end,
+
+ %% Test for leaks. We must accept some natural variations in
+ %% the size of allocated binaries.
+ if
+ Diff > 64*1024 ->
+ ?t:fail(binary_leak);
+ true ->
+ ok
+ end.
+
+memory_binary() ->
+ try
+ erlang:memory(binary)
+ catch
+ error:notsup ->
+ 0
+ end.
+
+provoke_mem_leak(0, _, _) -> ok;
+provoke_mem_leak(N, Code, Check) ->
+ {module,literals} = erlang:load_module(literals, Code),
+
+ %% Create several processes with references to the literal binary.
+ Self = self(),
+ Pids = [spawn_link(fun() ->
+ create_binaries(Self, NumRefs, Check)
+ end) || NumRefs <- lists:seq(1, 10)],
+ [receive {started,Pid} -> ok end || Pid <- Pids],
+
+ %% Make the code old and remove references to the constant pool
+ %% in all processes.
+ true = erlang:delete_module(literals),
+ Ms = [spawn_monitor(fun() ->
+ false = erlang:check_process_code(Pid, literals)
+ end) || Pid <- Pids],
+ [receive
+ {'DOWN',R,process,P,normal} ->
+ ok
+ end || {P,R} <- Ms],
+
+ %% Purge the code.
+ true = erlang:purge_module(literals),
+
+ %% Tell the processes that the code has been purged.
+ [begin
+ monitor(process, Pid),
+ Pid ! purged
+ end || Pid <- Pids],
+
+ %% Wait for all processes to terminate.
+ [receive
+ {'DOWN',_,process,Pid,normal} ->
+ ok
+ end || Pid <- Pids],
+
+ %% We now expect that the binary has been deallocated.
+ provoke_mem_leak(N-1, Code, Check).
+
+create_binaries(Parent, NumRefs, Check) ->
+ Bin = literals:binary(),
+ Bins = lists:duplicate(NumRefs, Bin),
+ {bits,Bits} = literals:bits(),
+ Parent ! {started,self()},
+ receive
+ purged ->
+ %% The code has been purged. Now make sure that
+ %% the binaries haven't been corrupted.
+ Check = erlang:md5(Bin),
+ [Bin = B || B <- Bins],
+ <<42:13,Bin/binary>> = Bits,
+
+ %% Remove all references to the binaries
+ %% Doing it explicitly like this ensures that
+ %% the binaries are gone when the parent process
+ %% receives the 'DOWN' message.
+ erlang:garbage_collect()
+ end.
+
+wait_for_memory_deallocations() ->
+ try
+ erts_debug:set_internal_state(wait, deallocations)
+ catch
+ error:undef ->
+ erts_debug:set_internal_state(available_internal_state, true),
+ wait_for_memory_deallocations()
+ end.
+
%% OTP-7559: c_p->cp could contain garbage and create a false dependency
%% to a module in a process. (Thanks to Richard Carlsson.)
false_dependency(Config) when is_list(Config) ->
@@ -527,6 +685,30 @@ coverage(Config) when is_list(Config) ->
?line {'EXIT',{badarg,_}} = (catch erlang:module_loaded(42)),
ok.
+fun_confusion(Config) when is_list(Config) ->
+ Data = ?config(data_dir, Config),
+ Src = filename:join(Data, "fun_confusion"),
+ Mod = fun_confusion,
+
+ %% Load first version of module.
+ compile_load(Mod, Src, 1),
+ F1 = Mod:f(),
+ 1 = F1(),
+
+ %% Load second version of module.
+ compile_load(Mod, Src, 2),
+ F2 = Mod:f(),
+
+ %% F1 should refer to the old code, not the newly loaded code.
+ 1 = F1(),
+ 2 = F2(),
+ ok.
+
+compile_load(Mod, Src, Ver) ->
+ {ok,Mod,Code1} = compile:file(Src, [binary,{d,version,Ver}]),
+ {module,Mod} = code:load_binary(Mod, "fun_confusion.beam", Code1),
+ ok.
+
%% Utilities.
make_sub_binary(Bin) when is_binary(Bin) ->
diff --git a/erts/emulator/test/code_SUITE_data/fun_confusion.erl b/erts/emulator/test/code_SUITE_data/fun_confusion.erl
new file mode 100644
index 0000000000..16000861df
--- /dev/null
+++ b/erts/emulator/test/code_SUITE_data/fun_confusion.erl
@@ -0,0 +1,31 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(fun_confusion).
+
+-export([f/0]).
+
+f() ->
+ fun() -> version() end.
+
+version() ->
+ %% Changing the value returned here should change
+ %% the identity of the fun in f/0.
+ ?version.
+
diff --git a/erts/emulator/test/code_SUITE_data/literals.erl b/erts/emulator/test/code_SUITE_data/literals.erl
index 9f99b1a780..d9cb8938db 100644
--- a/erts/emulator/test/code_SUITE_data/literals.erl
+++ b/erts/emulator/test/code_SUITE_data/literals.erl
@@ -18,7 +18,7 @@
%%
-module(literals).
--export([a/0,b/0,huge_bignum/0]).
+-export([a/0,b/0,huge_bignum/0,binary/0,unused_binaries/0,bits/0]).
a() ->
{a,42.0,[7,38877938333399637266518333334747]}.
@@ -81,3 +81,22 @@ b() ->
huge_bignum() ->
36#9987333333392789234879423987243987423432879423879234897423879423874328794323248423872348742323487423987423879243872347824374238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR07373767667987769707660766789076874238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR0737376766798779987333333392789234879423987243987423432879423879234897423879423874328794323248423872348742323487423987423879243872347824374238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR07373767667987769707660766789076874238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR07373767667987779JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR07373767667987769707660766789076874238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR0737376766798779987333333392789234879423987243987423432879423879234897423879423874328794323248423872348742323487423987423879243872347824374238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR07373767667987769707660766789076874238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR073737676679877.
+
+-define(TIMES_FOUR(X), X,X,X,X).
+-define(BYTES_256, 0:256,1:256,2:256,3:256, 4:256,5:256,6:256,7:256).
+-define(KB_1, ?TIMES_FOUR(?BYTES_256)).
+-define(KB_4, ?TIMES_FOUR(?KB_1)).
+-define(KB_16, ?TIMES_FOUR(?KB_4)).
+-define(KB_64, ?TIMES_FOUR(?KB_16)).
+-define(KB_128, ?TIMES_FOUR(?KB_64)).
+-define(MB_1, ?TIMES_FOUR(?KB_128)).
+
+binary() ->
+ %% Too big to be a heap binary.
+ <<?MB_1>>.
+
+unused_binaries() ->
+ {<<?KB_128>>,<<?BYTES_256>>}.
+
+bits() ->
+ {bits,<<42:13,?MB_1>>}.
diff --git a/erts/emulator/test/distribution_SUITE.erl b/erts/emulator/test/distribution_SUITE.erl
index 4bebae51cc..19281f6d58 100644
--- a/erts/emulator/test/distribution_SUITE.erl
+++ b/erts/emulator/test/distribution_SUITE.erl
@@ -173,15 +173,20 @@ bulk_sendsend(Terms, BinSize) ->
Ratio = if MonitorCount2 == 0 -> MonitorCount1 / 1.0;
true -> MonitorCount1 / MonitorCount2
end,
- %% A somewhat arbitrary ratio, but hopefully one that will accomodate
- %% a wide range of CPU speeds.
- true = (Ratio > 8.0),
- {comment,
- integer_to_list(Rate1) ++ " K/s, " ++
- integer_to_list(Rate2) ++ " K/s, " ++
- integer_to_list(MonitorCount1) ++ " monitor msgs, " ++
- integer_to_list(MonitorCount2) ++ " monitor msgs, " ++
- float_to_list(Ratio) ++ " monitor ratio"}.
+ Comment = integer_to_list(Rate1) ++ " K/s, " ++
+ integer_to_list(Rate2) ++ " K/s, " ++
+ integer_to_list(MonitorCount1) ++ " monitor msgs, " ++
+ integer_to_list(MonitorCount2) ++ " monitor msgs, " ++
+ float_to_list(Ratio) ++ " monitor ratio",
+ if
+ %% A somewhat arbitrary ratio, but hopefully one that will
+ %% accommodate a wide range of CPU speeds.
+ Ratio > 8.0 ->
+ {comment,Comment};
+ true ->
+ io:put_chars(Comment),
+ ?line ?t:fail(ratio_too_low)
+ end.
bulk_sendsend2(Terms, BinSize, BusyBufSize) ->
?line Dog = test_server:timetrap(test_server:seconds(30)),
@@ -331,7 +336,7 @@ receiver2(Num, TotSize) ->
link_to_busy(doc) -> "Test that link/1 to a busy distribution port works.";
link_to_busy(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(30)),
+ ?line Dog = test_server:timetrap(test_server:seconds(60)),
?line {ok, Node} = start_node(link_to_busy),
?line Recv = spawn(Node, erlang, apply, [fun sink/1, [link_to_busy_sink]]),
@@ -378,7 +383,7 @@ tail_applied_linker(Pid) ->
exit_to_busy(doc) -> "Test that exit/2 to a busy distribution port works.";
exit_to_busy(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(30)),
+ ?line Dog = test_server:timetrap(test_server:seconds(60)),
?line {ok, Node} = start_node(exit_to_busy),
Tracer = case os:getenv("TRACE_BUSY_DIST_PORT") of
@@ -1597,8 +1602,8 @@ bad_dist_ext_control(Config) when is_list(Config) ->
?line stop_node(Victim).
bad_dist_ext_connection_id(Config) when is_list(Config) ->
- ?line {ok, Offender} = start_node(bad_dist_ext_receive_offender),
- ?line {ok, Victim} = start_node(bad_dist_ext_receive_victim),
+ ?line {ok, Offender} = start_node(bad_dist_ext_connection_id_offender),
+ ?line {ok, Victim} = start_node(bad_dist_ext_connection_id_victim),
?line start_node_monitors([Offender,Victim]),
?line Parent = self(),
diff --git a/erts/emulator/test/driver_SUITE.erl b/erts/emulator/test/driver_SUITE.erl
index f6cf01ce16..c07dbc5871 100644
--- a/erts/emulator/test/driver_SUITE.erl
+++ b/erts/emulator/test/driver_SUITE.erl
@@ -75,7 +75,9 @@
smp_select/1,
driver_select_use/1,
thread_mseg_alloc_cache_clean/1,
- otp_9302/1]).
+ otp_9302/1,
+ thr_free_drv/1,
+ async_blast/1]).
-export([bin_prefix/2]).
@@ -143,7 +145,9 @@ all() ->
otp_6879, caller, many_events, missing_callbacks,
smp_select, driver_select_use,
thread_mseg_alloc_cache_clean,
- otp_9302].
+ otp_9302,
+ thr_free_drv,
+ async_blast].
groups() ->
[{timer, [],
@@ -1590,7 +1594,7 @@ otp_6879(Config) when is_list(Config) ->
end
end,
Procs),
- %% Also try it when input exeeds default buffer (256 bytes)
+ %% Also try it when input exceeds default buffer (256 bytes)
?line Data = lists:seq(1, 1000),
?line case open_port({spawn, Drv}, []) of
Port when is_port(Port) ->
@@ -1792,7 +1796,7 @@ driver_select_use0(Config) ->
thread_mseg_alloc_cache_clean(Config) when is_list(Config) ->
case {erlang:system_info(threads),
- erlang:system_info({allocator,mseg_alloc}),
+ mseg_inst_info(0),
driver_alloc_sbct()} of
{_, false, _} ->
?line {skipped, "No mseg_alloc"};
@@ -1804,13 +1808,13 @@ thread_mseg_alloc_cache_clean(Config) when is_list(Config) ->
?line {skipped, "driver_alloc() using too large single block threshold"};
{_, _, 0} ->
?line {skipped, "driver_alloc() using too low single block threshold"};
- {true, MsegAllocInfo, SBCT} ->
+ {true, _MsegAllocInfo, SBCT} ->
?line DrvName = 'thr_alloc_drv',
?line Path = ?config(data_dir, Config),
?line erl_ddll:start(),
?line ok = load_driver(Path, DrvName),
?line Port = open_port({spawn, DrvName}, []),
- ?line CCI = mseg_alloc_cci(MsegAllocInfo),
+ ?line CCI = 1000,
?line ?t:format("CCI = ~p~n", [CCI]),
?line CCC = mseg_alloc_ccc(),
?line ?t:format("CCC = ~p~n", [CCC]),
@@ -1831,7 +1835,7 @@ mseg_alloc_cci(MsegAllocInfo) ->
?line CCI.
mseg_alloc_ccc() ->
- mseg_alloc_ccc(erlang:system_info({allocator,mseg_alloc})).
+ mseg_alloc_ccc(mseg_inst_info(0)).
mseg_alloc_ccc(MsegAllocInfo) ->
?line {value,{memkind, MKL}} = lists:keysearch(memkind,1,MsegAllocInfo),
@@ -1841,7 +1845,7 @@ mseg_alloc_ccc(MsegAllocInfo) ->
?line GigaCCC*1000000000 + CCC.
mseg_alloc_cached_segments() ->
- mseg_alloc_cached_segments(erlang:system_info({allocator,mseg_alloc})).
+ mseg_alloc_cached_segments(mseg_inst_info(0)).
mseg_alloc_cached_segments(MsegAllocInfo) ->
MemName = case is_halfword_vm() of
@@ -1859,6 +1863,13 @@ mseg_alloc_cached_segments(MsegAllocInfo) ->
= lists:keysearch(cached_segments, 1, SL),
?line CS.
+mseg_inst_info(I) ->
+ {value, {instance, I, Value}}
+ = lists:keysearch(I,
+ 2,
+ erlang:system_info({allocator,mseg_alloc})),
+ Value.
+
is_halfword_vm() ->
case {erlang:system_info({wordsize, internal}),
erlang:system_info({wordsize, external})} of
@@ -1902,18 +1913,105 @@ otp_9302(Config) when is_list(Config) ->
?line port_command(Port, ""),
?line {msg, block} = get_port_msg(Port, infinity),
?line {msg, job} = get_port_msg(Port, infinity),
- ?line case erlang:system_info(thread_pool_size) of
- 0 ->
- {msg, cancel} = get_port_msg(Port, infinity);
- _ ->
- ok
- end,
- ?line {msg, job} = get_port_msg(Port, infinity),
+ ?line C = case erlang:system_info(thread_pool_size) of
+ 0 ->
+ ?line {msg, cancel} = get_port_msg(Port, infinity),
+ ?line {msg, job} = get_port_msg(Port, infinity),
+ ?line false;
+ _ ->
+ case get_port_msg(Port, infinity) of
+ {msg, cancel} -> %% Cancel always fail in Rel >= 15
+ ?line {msg, job} = get_port_msg(Port, infinity),
+ ?line false;
+ {msg, job} ->
+ ?line ok,
+ ?line true
+ end
+ end,
?line {msg, end_of_jobs} = get_port_msg(Port, infinity),
?line no_msg = get_port_msg(Port, 2000),
?line port_close(Port),
+ ?line case C of
+ true ->
+ ?line {comment, "Async job cancelled"};
+ false ->
+ ?line {comment, "Async job not cancelled"}
+ end.
+
+thr_free_drv(Config) when is_list(Config) ->
+ ?line Path = ?config(data_dir, Config),
+ ?line erl_ddll:start(),
+ ?line ok = load_driver(Path, thr_free_drv),
+ ?line MemBefore = driver_alloc_size(),
+% io:format("SID=~p", [erlang:system_info(scheduler_id)]),
+ ?line Port = open_port({spawn, thr_free_drv}, []),
+ ?line MemPeek = driver_alloc_size(),
+ ?line true = is_port(Port),
+ ?line ok = thr_free_drv_control(Port, 0),
+ ?line port_close(Port),
+ ?line MemAfter = driver_alloc_size(),
+ ?line io:format("MemPeek=~p~n", [MemPeek]),
+ ?line io:format("MemBefore=~p, MemAfter=~p~n", [MemBefore, MemAfter]),
+ ?line MemBefore = MemAfter,
+ ?line case MemPeek of
+ undefined -> ok;
+ _ ->
+ ?line true = MemPeek > MemBefore
+ end,
?line ok.
+thr_free_drv_control(Port, N) ->
+ case erlang:port_control(Port, 0, "") of
+ "done" ->
+ ok;
+ "more" ->
+ erlang:yield(),
+% io:format("N=~p, SID=~p", [N, erlang:system_info(scheduler_id)]),
+ thr_free_drv_control(Port, N+1)
+ end.
+
+async_blast(Config) when is_list(Config) ->
+ ?line Path = ?config(data_dir, Config),
+ ?line erl_ddll:start(),
+ ?line ok = load_driver(Path, async_blast_drv),
+ ?line SchedOnln = erlang:system_info(schedulers_online),
+ ?line MemBefore = driver_alloc_size(),
+ ?line Start = os:timestamp(),
+ ?line Blast = fun () ->
+ Port = open_port({spawn, async_blast_drv}, []),
+ true = is_port(Port),
+ port_command(Port, ""),
+ receive
+ {Port, done} ->
+ ok
+ end,
+ port_close(Port)
+ end,
+ ?line Ps = lists:map(fun (N) ->
+ spawn_opt(Blast,
+ [{scheduler,
+ (N rem SchedOnln)+ 1},
+ monitor])
+ end,
+ lists:seq(1, 100)),
+ ?line MemMid = driver_alloc_size(),
+ ?line lists:foreach(fun ({Pid, Mon}) ->
+ receive
+ {'DOWN',Mon,process,Pid,_} -> ok
+ end
+ end, Ps),
+ ?line End = os:timestamp(),
+ ?line MemAfter = driver_alloc_size(),
+ ?line io:format("MemBefore=~p, MemMid=~p, MemAfter=~p~n",
+ [MemBefore, MemMid, MemAfter]),
+ ?line AsyncBlastTime = timer:now_diff(End,Start)/1000000,
+ ?line io:format("AsyncBlastTime=~p~n", [AsyncBlastTime]),
+ ?line MemBefore = MemAfter,
+ ?line erlang:display({async_blast_time, AsyncBlastTime}),
+ ?line ok.
+
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Utilities
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2077,3 +2175,33 @@ start_node(Config) when is_list(Config) ->
stop_node(Node) ->
?t:stop_node(Node).
+
+wait_deallocations() ->
+ try
+ erts_debug:set_internal_state(wait, deallocations)
+ catch error:undef ->
+ erts_debug:set_internal_state(available_internal_state, true),
+ wait_deallocations()
+ end.
+
+driver_alloc_size() ->
+ wait_deallocations(),
+ case erlang:system_info({allocator_sizes, driver_alloc}) of
+ false ->
+ undefined;
+ MemInfo ->
+ CS = lists:foldl(
+ fun ({instance, _, L}, Acc) ->
+ {value,{_,SBMBCS}} = lists:keysearch(sbmbcs, 1, L),
+ {value,{_,MBCS}} = lists:keysearch(mbcs, 1, L),
+ {value,{_,SBCS}} = lists:keysearch(sbcs, 1, L),
+ [SBMBCS,MBCS,SBCS | Acc]
+ end,
+ [],
+ MemInfo),
+ lists:foldl(
+ fun(L, Sz0) ->
+ {value,{_,Sz,_,_}} = lists:keysearch(blocks_size, 1, L),
+ Sz0+Sz
+ end, 0, CS)
+ end.
diff --git a/erts/emulator/test/driver_SUITE_data/Makefile.src b/erts/emulator/test/driver_SUITE_data/Makefile.src
index 5b3ba1557e..dd48f6a0f7 100644
--- a/erts/emulator/test/driver_SUITE_data/Makefile.src
+++ b/erts/emulator/test/driver_SUITE_data/Makefile.src
@@ -12,7 +12,9 @@ MISC_DRVS = outputv_drv@dll@ \
many_events_drv@dll@ \
missing_callback_drv@dll@ \
thr_alloc_drv@dll@ \
- otp_9302_drv@dll@
+ otp_9302_drv@dll@ \
+ thr_free_drv@dll@ \
+ async_blast_drv@dll@
SYS_INFO_DRVS = sys_info_1_0_drv@dll@ \
sys_info_1_1_drv@dll@ \
diff --git a/erts/emulator/test/driver_SUITE_data/async_blast_drv.c b/erts/emulator/test/driver_SUITE_data/async_blast_drv.c
new file mode 100644
index 0000000000..3821f7e3dc
--- /dev/null
+++ b/erts/emulator/test/driver_SUITE_data/async_blast_drv.c
@@ -0,0 +1,124 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include "erl_driver.h"
+
+#define NO_ASYNC_JOBS 10000
+
+static void stop(ErlDrvData drv_data);
+static ErlDrvData start(ErlDrvPort port,
+ char *command);
+static void output(ErlDrvData drv_data,
+ char *buf, int len);
+static void ready_async(ErlDrvData drv_data,
+ ErlDrvThreadData thread_data);
+
+static ErlDrvEntry async_blast_drv_entry = {
+ NULL /* init */,
+ start,
+ stop,
+ output,
+ NULL /* ready_input */,
+ NULL /* ready_output */,
+ "async_blast_drv",
+ NULL /* finish */,
+ NULL /* handle */,
+ NULL /* control */,
+ NULL /* timeout */,
+ NULL /* outputv */,
+ ready_async,
+ NULL /* flush */,
+ NULL /* call */,
+ NULL /* event */,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ ERL_DRV_FLAG_USE_PORT_LOCKING,
+ NULL /* handle2 */,
+ NULL /* handle_monitor */
+};
+
+typedef struct {
+ ErlDrvPort port;
+ ErlDrvTermData caller;
+ int counter;
+} async_blast_data_t;
+
+
+DRIVER_INIT(async_blast_drv)
+{
+ return &async_blast_drv_entry;
+}
+
+static void stop(ErlDrvData drv_data)
+{
+ driver_free((void *) drv_data);
+}
+
+static ErlDrvData start(ErlDrvPort port,
+ char *command)
+{
+ async_blast_data_t *abd;
+
+ abd = driver_alloc(sizeof(async_blast_data_t));
+ if (!abd)
+ return ERL_DRV_ERROR_GENERAL;
+
+ abd->port = port;
+ abd->counter = 0;
+ return (ErlDrvData) abd;
+}
+
+static void async_invoke(void *data)
+{
+
+}
+#include <stdio.h>
+
+static void ready_async(ErlDrvData drv_data,
+ ErlDrvThreadData thread_data)
+{
+ async_blast_data_t *abd = (async_blast_data_t *) drv_data;
+ if (--abd->counter == 0) {
+ ErlDrvTermData spec[] = {
+ ERL_DRV_PORT, driver_mk_port(abd->port),
+ ERL_DRV_ATOM, driver_mk_atom("done"),
+ ERL_DRV_TUPLE, 2
+ };
+ driver_send_term(abd->port, abd->caller,
+ spec, sizeof(spec)/sizeof(spec[0]));
+ }
+}
+
+static void output(ErlDrvData drv_data,
+ char *buf, int len)
+{
+ async_blast_data_t *abd = (async_blast_data_t *) drv_data;
+ if (abd->counter == 0) {
+ int i;
+ abd->caller = driver_caller(abd->port);
+ abd->counter = NO_ASYNC_JOBS;
+ for (i = 0; i < NO_ASYNC_JOBS; i++) {
+ if (0 > driver_async(abd->port, NULL, async_invoke, NULL, NULL)) {
+ driver_failure_atom(abd->port, "driver_async_failed");
+ break;
+ }
+ }
+ }
+}
diff --git a/erts/emulator/test/driver_SUITE_data/thr_free_drv.c b/erts/emulator/test/driver_SUITE_data/thr_free_drv.c
new file mode 100644
index 0000000000..622a62ebea
--- /dev/null
+++ b/erts/emulator/test/driver_SUITE_data/thr_free_drv.c
@@ -0,0 +1,241 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include "erl_driver.h"
+
+#define BLOCKS_PER_THREAD 100000
+#define NO_THREADS 10
+#define BLOCKS_PER_CTRL 1000
+
+typedef struct {
+ ErlDrvMutex *mtx;
+ ErlDrvCond *cnd;
+ int b;
+ int *go;
+ int *skip;
+ void *blocks[BLOCKS_PER_THREAD];
+} test_thread_data;
+
+typedef struct {
+ ErlDrvPort port;
+ int b;
+ int go;
+ int skip;
+ test_thread_data ttd[NO_THREADS+1];
+ ErlDrvTid tids[NO_THREADS+1];
+} test_data;
+
+static ErlDrvData start(ErlDrvPort port, char *command);
+static void stop(ErlDrvData data);
+static int control(ErlDrvData drv_data, unsigned int command, char *buf,
+ int len, char **rbuf, int rlen);
+
+static ErlDrvEntry thr_free_drv_entry = {
+ NULL /* init */,
+ start,
+ stop,
+ NULL /* output */,
+ NULL /* ready_input */,
+ NULL /* ready_output */,
+ "thr_free_drv",
+ NULL /* finish */,
+ NULL /* handle */,
+ control,
+ NULL /* timeout */,
+ NULL /* outputv */,
+ NULL /* ready_async */,
+ NULL /* flush */,
+ NULL /* call */,
+ NULL /* event */,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ ERL_DRV_FLAG_USE_PORT_LOCKING,
+ NULL /* handle2 */,
+ NULL /* handle_monitor */
+};
+
+DRIVER_INIT(thr_free_drv)
+{
+ return &thr_free_drv_entry;
+}
+
+void *
+test_thread(void *vttd)
+{
+ test_thread_data *ttd = (test_thread_data *) vttd;
+ int i, skip;
+
+ erl_drv_mutex_lock(ttd->mtx);
+
+ while (!*ttd->go)
+ erl_drv_cond_wait(ttd->cnd, ttd->mtx);
+ skip = *ttd->skip;
+ erl_drv_mutex_unlock(ttd->mtx);
+
+ if (!skip) {
+ for (i = 0; i < BLOCKS_PER_THREAD; i++)
+ driver_free(ttd->blocks[i]);
+ }
+ return NULL;
+}
+
+ErlDrvData start(ErlDrvPort port, char *command)
+{
+ int join = 0, t, b, res;
+ test_thread_data *ttd;
+ test_data *td = driver_alloc(sizeof(test_data));
+ if (!td)
+ return ERL_DRV_ERROR_GENERAL;
+ ttd = td->ttd;
+ for (b = 0; b < BLOCKS_PER_THREAD; b++)
+ for (t = 0; t <= NO_THREADS; t++)
+ ttd[t].blocks[b] = NULL;
+ ttd[0].mtx = NULL;
+ ttd[0].cnd = NULL;
+
+ for (b = 0; b < BLOCKS_PER_THREAD; b++) {
+ for (t = 0; t <= NO_THREADS; t++) {
+ ttd[t].blocks[b] = driver_alloc(1);
+ if (ttd[t].blocks[b] == NULL)
+ goto fail;
+ }
+ }
+
+ td->b = -1;
+ td->go = 0;
+ td->skip = 0;
+
+ ttd[0].mtx = erl_drv_mutex_create("test_mutex");
+ if (!ttd[0].mtx)
+ goto fail;
+ ttd[0].cnd = erl_drv_cond_create("test_cnd");
+ if (!ttd[0].cnd)
+ goto fail;
+ ttd[0].go = &td->go;
+ ttd[0].skip = &td->skip;
+
+ for (t = 1; t <= NO_THREADS; t++) {
+ ttd[t].mtx = ttd[0].mtx;
+ ttd[t].cnd = ttd[0].cnd;
+ ttd[t].go = ttd[0].go;
+ ttd[t].skip = ttd[0].skip;
+ res = erl_drv_thread_create("test_thread",
+ &td->tids[t],
+ test_thread,
+ &ttd[t],
+ NULL);
+ if (res != 0)
+ goto fail;
+ join = t;
+ }
+
+ td->port = port;
+
+ return (ErlDrvData) td;
+
+fail:
+
+ if (join) {
+ erl_drv_mutex_lock(ttd[0].mtx);
+ td->go = 1;
+ td->skip = 1;
+ erl_drv_cond_broadcast(ttd[0].cnd);
+ erl_drv_mutex_unlock(ttd[0].mtx);
+ for (t = 1; t <= join; t++)
+ erl_drv_thread_join(td->tids[t], NULL);
+ }
+
+ if (ttd[0].mtx)
+ erl_drv_mutex_destroy(ttd[0].mtx);
+ if (ttd[0].cnd)
+ erl_drv_cond_destroy(ttd[0].cnd);
+
+ for (b = 0; b < BLOCKS_PER_THREAD; b++) {
+ for (t = 0; t <= NO_THREADS; t++) {
+ if (ttd[t].blocks[b] != NULL)
+ driver_free(ttd[t].blocks[b]);
+ }
+ }
+
+ return ERL_DRV_ERROR_GENERAL;
+}
+
+static void stop(ErlDrvData drv_data)
+{
+ test_data *td = (test_data *) drv_data;
+ int t, b;
+ for (t = 1; t <= NO_THREADS; t++)
+ erl_drv_thread_join(td->tids[t], NULL);
+ for (b = 0; b < BLOCKS_PER_THREAD; b++) {
+ if (td->ttd[0].blocks[b])
+ driver_free(td->ttd[0].blocks[b]);
+ }
+ erl_drv_mutex_destroy(td->ttd[0].mtx);
+ erl_drv_cond_destroy(td->ttd[0].cnd);
+ driver_free(td);
+}
+
+static int control(ErlDrvData drv_data, unsigned int command, char *buf,
+ int len, char **rbuf, int rlen)
+{
+ test_data *td = (test_data *) drv_data;
+ char *result = "failure";
+ int i, b;
+ int res;
+ int result_len;
+
+ if (td->b == -1) {
+ erl_drv_mutex_lock(td->ttd[0].mtx);
+ td->go = 1;
+ erl_drv_cond_broadcast(td->ttd[0].cnd);
+ erl_drv_mutex_unlock(td->ttd[0].mtx);
+ td->b = 0;
+ }
+
+ for (i = 0, b = td->b; i < BLOCKS_PER_CTRL && b < BLOCKS_PER_THREAD; i++, b++) {
+ driver_free(td->ttd[0].blocks[b]);
+ td->ttd[0].blocks[b] = NULL;
+ }
+
+ td->b = b;
+ if (b >= BLOCKS_PER_THREAD)
+ result = "done";
+ else
+ result = "more";
+
+ result_len = strlen(result);
+ if (result_len <= rlen) {
+ memcpy(*rbuf, result, result_len);
+ return result_len;
+ }
+ else {
+ *rbuf = driver_alloc(result_len);
+ if (!*rbuf) {
+ driver_failure_posix(td->port, ENOMEM);
+ return 0;
+ }
+ else {
+ memcpy(*rbuf, result, result_len);
+ return result_len;
+ }
+ }
+}
diff --git a/erts/emulator/test/exception_SUITE.erl b/erts/emulator/test/exception_SUITE.erl
index 9d6fc9521d..109cec25cb 100644
--- a/erts/emulator/test/exception_SUITE.erl
+++ b/erts/emulator/test/exception_SUITE.erl
@@ -23,9 +23,10 @@
init_per_group/2,end_per_group/2,
badmatch/1, pending_errors/1, nil_arith/1,
stacktrace/1, nested_stacktrace/1, raise/1, gunilla/1, per/1,
- exception_with_heap_frag/1]).
+ exception_with_heap_frag/1, line_numbers/1]).
-export([bad_guy/2]).
+-export([crash/1]).
-include_lib("test_server/include/test_server.hrl").
-import(lists, [foreach/2]).
@@ -35,7 +36,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[badmatch, pending_errors, nil_arith, stacktrace,
nested_stacktrace, raise, gunilla, per,
- exception_with_heap_frag].
+ exception_with_heap_frag, line_numbers].
groups() ->
[].
@@ -141,14 +142,20 @@ pending_exit_message(Args, Expected) ->
end,
process_flag(trap_exit, false).
-pending({badarg, [{erlang,Bif,BifArgs},{?MODULE,Func,Arity}|_]}, Func, Args, _Code)
- when is_atom(Bif), is_list(BifArgs), length(Args) == Arity ->
+pending({badarg,[{erlang,Bif,BifArgs,Loc1},
+ {?MODULE,Func,Arity,Loc2}|_]},
+ Func, Args, _Code)
+ when is_atom(Bif), is_list(BifArgs), length(Args) =:= Arity,
+ is_list(Loc1), is_list(Loc2) ->
ok;
-pending({undef,[{non_existing_module,foo,[]}|_]}, _, _, _) ->
+pending({undef,[{non_existing_module,foo,[],Loc}|_]}, _, _, _)
+ when is_list(Loc) ->
ok;
-pending({function_clause,[{?MODULE,Func,Args}|_]}, Func, Args, _Code) ->
+pending({function_clause,[{?MODULE,Func,Args,Loc}|_]}, Func, Args, _Code)
+ when is_list(Loc) ->
ok;
-pending({Code,[{?MODULE,Func,Arity}|_]}, Func, Args, Code) when length(Args) == Arity ->
+pending({Code,[{?MODULE,Func,Arity,Loc}|_]}, Func, Args, Code)
+ when length(Args) =:= Arity, is_list(Loc) ->
ok;
pending(Reason, _Function, _Args, _Code) ->
test_server:fail({bad_exit_reason,Reason}).
@@ -255,24 +262,24 @@ stacktrace(Conf) when is_list(Conf) ->
?line {_,Mref} = spawn_monitor(fun() -> exit({Tag,erlang:get_stacktrace()}) end),
?line {Tag,[]} = receive {'DOWN',Mref,_,_,Info} -> Info end,
V = [make_ref()|self()],
- ?line {value2,{caught1,badarg,[{erlang,abs,[V]}|_]=St1}} =
+ ?line {value2,{caught1,badarg,[{erlang,abs,[V],_}|_]=St1}} =
stacktrace_1({'abs',V}, error, {value,V}),
?line St1 = erase(stacktrace1),
?line St1 = erase(stacktrace2),
?line St1 = erlang:get_stacktrace(),
- ?line {caught2,{error,badarith},[{?MODULE,my_add,2}|_]=St2} =
+ ?line {caught2,{error,badarith},[{?MODULE,my_add,2,_}|_]=St2} =
stacktrace_1({'div',{1,0}}, error, {'add',{0,a}}),
- ?line [{?MODULE,my_div,2}|_] = erase(stacktrace1),
+ ?line [{?MODULE,my_div,2,_}|_] = erase(stacktrace1),
?line St2 = erase(stacktrace2),
?line St2 = erlang:get_stacktrace(),
- ?line {caught2,{error,{try_clause,V}},[{?MODULE,stacktrace_1,3}|_]=St3} =
+ ?line {caught2,{error,{try_clause,V}},[{?MODULE,stacktrace_1,3,_}|_]=St3} =
stacktrace_1({value,V}, error, {value,V}),
?line St3 = erase(stacktrace1),
?line St3 = erase(stacktrace2),
?line St3 = erlang:get_stacktrace(),
- ?line {caught2,{throw,V},[{?MODULE,foo,1}|_]=St4} =
+ ?line {caught2,{throw,V},[{?MODULE,foo,1,_}|_]=St4} =
stacktrace_1({value,V}, error, {throw,V}),
- ?line [{?MODULE,stacktrace_1,3}|_] = erase(stacktrace1),
+ ?line [{?MODULE,stacktrace_1,3,_}|_] = erase(stacktrace1),
?line St4 = erase(stacktrace2),
?line St4 = erlang:get_stacktrace(),
@@ -280,8 +287,8 @@ stacktrace(Conf) when is_list(Conf) ->
?line stacktrace_2()
catch
error:{badmatch,_} ->
- [{?MODULE,stacktrace_2,0},
- {?MODULE,stacktrace,1}|_] =
+ [{?MODULE,stacktrace_2,0,_},
+ {?MODULE,stacktrace,1,_}|_] =
erlang:get_stacktrace(),
ok
end.
@@ -315,15 +322,15 @@ nested_stacktrace(Conf) when is_list(Conf) ->
nested_stacktrace_1({{value,{V,x1}},void,{V,x1}},
{void,void,void}),
?line {caught1,
- [{?MODULE,my_add,2}|_],
+ [{?MODULE,my_add,2,_}|_],
value2,
- [{?MODULE,my_add,2}|_]} =
+ [{?MODULE,my_add,2,_}|_]} =
nested_stacktrace_1({{'add',{V,x1}},error,badarith},
{{value,{V,x2}},void,{V,x2}}),
?line {caught1,
- [{?MODULE,my_add,2}|_],
- {caught2,[{erlang,abs,[V]}|_]},
- [{erlang,abs,[V]}|_]} =
+ [{?MODULE,my_add,2,_}|_],
+ {caught2,[{erlang,abs,[V],_}|_]},
+ [{erlang,abs,[V],_}|_]} =
nested_stacktrace_1({{'add',{V,x1}},error,badarith},
{{'abs',V},error,badarg}),
ok.
@@ -362,14 +369,14 @@ raise(Conf) when is_list(Conf) ->
end,
?line A = erlang:get_stacktrace(),
?line A = get(raise),
- ?line [{?MODULE,my_div,2}|_] = A,
+ ?line [{?MODULE,my_div,2,_}|_] = A,
%%
N = 8, % Must be even
?line N = erlang:system_flag(backtrace_depth, N),
+ ?line B = odd_even(N, []),
?line try even(N)
catch error:function_clause -> ok
end,
- ?line B = odd_even(N, []),
?line B = erlang:get_stacktrace(),
%%
?line C0 = odd_even(N+1, []),
@@ -387,19 +394,12 @@ raise(Conf) when is_list(Conf) ->
odd_even(N, R) when is_integer(N), N > 1 ->
odd_even(N-1,
[if (N rem 2) == 0 ->
- {?MODULE,even,1};
+ {?MODULE,even,1,[{file,"odd_even.erl"},{line,3}]};
true ->
- {?MODULE,odd,1}
+ {?MODULE,odd,1,[{file,"odd_even.erl"},{line,6}]}
end|R]);
odd_even(1, R) ->
- [{?MODULE,odd,[1]}|R].
-
-even(N) when is_integer(N), N > 1, (N rem 2) == 0 ->
- odd(N-1)++[N].
-
-odd(N) when is_integer(N), N > 1, (N rem 2) == 1 ->
- even(N-1)++[N].
-
+ [{?MODULE,odd,[1],[{file,"odd_even.erl"},{line,5}]}|R].
foo({value,Value}) -> Value;
foo({'div',{A,B}}) ->
@@ -526,4 +526,186 @@ do_exception_with_heap_frag(Bin, [Sz|Sizes]) ->
do_exception_with_heap_frag(Bin, Sizes);
do_exception_with_heap_frag(_, []) -> ok.
+line_numbers(Config) when is_list(Config) ->
+ {'EXIT',{{case_clause,bad_tag},
+ [{?MODULE,line1,2,
+ [{file,"fake_file.erl"},{line,3}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch line1(bad_tag, 0)),
+ {'EXIT',{badarith,
+ [{?MODULE,line1,2,
+ [{file,"fake_file.erl"},{line,5}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch line1(a, not_an_integer)),
+ {'EXIT',{{badmatch,{ok,1}},
+ [{?MODULE,line1,2,
+ [{file,"fake_file.erl"},{line,7}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch line1(a, 0)),
+ {'EXIT',{crash,
+ [{?MODULE,crash,1,
+ [{file,"fake_file.erl"},{line,14}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch line1(a, 41)),
+
+ ModFile = ?MODULE_STRING++".erl",
+ [{?MODULE,maybe_crash,1,[{file,"call.erl"},{line,28}]},
+ {?MODULE,call1,0,[{file,"call.erl"},{line,14}]},
+ {?MODULE,close_calls,1,[{file,"call.erl"},{line,5}]},
+ {?MODULE,line_numbers,1,[{file,ModFile},{line,_}]}|_] =
+ close_calls(call1),
+ [{?MODULE,maybe_crash,1,[{file,"call.erl"},{line,28}]},
+ {?MODULE,call2,0,[{file,"call.erl"},{line,18}]},
+ {?MODULE,close_calls,1,[{file,"call.erl"},{line,6}]},
+ {?MODULE,line_numbers,1,[{file,ModFile},{line,_}]}|_] =
+ close_calls(call2),
+ [{?MODULE,maybe_crash,1,[{file,"call.erl"},{line,28}]},
+ {?MODULE,call3,0,[{file,"call.erl"},{line,22}]},
+ {?MODULE,close_calls,1,[{file,"call.erl"},{line,7}]},
+ {?MODULE,line_numbers,1,[{file,ModFile},{line,_}]}|_] =
+ close_calls(call3),
+ no_crash = close_calls(other),
+
+ <<0,0>> = build_binary1(16),
+ {'EXIT',{badarg,
+ [{?MODULE,build_binary1,1,
+ [{file,"bit_syntax.erl"},{line,72503}]},
+ {?MODULE,line_numbers,1,
+ [{file,ModFile},{line,_}]}|_]}} =
+ (catch build_binary1(bad_size)),
+
+ <<7,1,2,3>> = build_binary2(8, <<1,2,3>>),
+ {'EXIT',{badarg,
+ [{?MODULE,build_binary2,2,
+ [{file,"bit_syntax.erl"},{line,72507}]},
+ {?MODULE,line_numbers,1,
+ [{file,ModFile},{line,_}]}|_]}} =
+ (catch build_binary2(bad_size, <<>>)),
+ {'EXIT',{badarg,
+ [{erlang,bit_size,[bad_binary],[]},
+ {?MODULE,build_binary2,2,
+ [{file,"bit_syntax.erl"},{line,72507}]},
+ {?MODULE,line_numbers,1,
+ [{file,ModFile},{line,_}]}|_]}} =
+ (catch build_binary2(8, bad_binary)),
+
+ {'EXIT',{function_clause,
+ [{?MODULE,do_call_abs,[y,y],
+ [{file,"gc_bif.erl"},{line,18}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch do_call_abs(y, y)),
+ {'EXIT',{badarg,
+ [{erlang,abs,[[]],[]},
+ {?MODULE,do_call_abs,2,
+ [{file,"gc_bif.erl"},{line,19}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch do_call_abs(x, [])),
+
+ {'EXIT',{{badmatch,"42"},
+ [{MODULE,applied_bif_1,1,[{file,"applied_bif.erl"},{line,5}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch applied_bif_1(42)),
+
+ {'EXIT',{{badmatch,{current_location,
+ {?MODULE,applied_bif_2,0,
+ [{file,"applied_bif.erl"},{line,9}]}}},
+ [{MODULE,applied_bif_2,0,[{file,"applied_bif.erl"},{line,10}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch applied_bif_2()),
+
+ ok.
+
id(I) -> I.
+
+-file("odd_even.erl", 1). %Line 1
+even(N) when is_integer(N), N > 1, (N rem 2) == 0 ->
+ odd(N-1)++[N]. %Line 3
+
+odd(N) when is_integer(N), N > 1, (N rem 2) == 1 ->
+ even(N-1)++[N]. %Line 6
+
+%%
+%% If the compiler removes redundant line instructions (any
+%% line instruction with the same location as the previous),
+%% and the loader also removes line instructions before
+%% tail-recursive calls to external functions, then the
+%% badmatch exception in line 7 below will be reported as
+%% occurring in line 6.
+%%
+%% That means that any removal of redundant line instructions
+%% must all be done in the compiler OR in the loader.
+%%
+-file("fake_file.erl", 1). %Line 1
+line1(Tag, X) -> %Line 2
+ case Tag of %Line 3
+ a ->
+ Y = X + 1, %Line 5
+ Res = id({ok,Y}), %Line 6
+ ?MODULE:crash({ok,42} = Res); %Line 7
+ b ->
+ x = id(x), %Line 9
+ ok %Line 10
+ end. %Line 11
+
+crash(_) -> %Line 13
+ erlang:error(crash). %Line 14
+
+-file("call.erl", 1). %Line 1
+close_calls(Where) -> %Line 2
+ put(where_to_crash, Where), %Line 3
+ try
+ call1(), %Line 5
+ call2(), %Line 6
+ call3(), %Line 7
+ no_crash %Line 8
+ catch error:crash ->
+ erlang:get_stacktrace() %Line 10
+ end. %Line 11
+
+call1() -> %Line 13
+ maybe_crash(call1), %Line 14
+ ok. %Line 15
+
+call2() -> %Line 17
+ maybe_crash(call2), %Line 18
+ ok. %Line 19
+
+call3() -> %Line 21
+ maybe_crash(call3), %Line 22
+ ok. %Line 23
+
+maybe_crash(Name) -> %Line 25
+ case get(where_to_crash) of %Line 26
+ Name ->
+ erlang:error(crash); %Line 28
+ _ ->
+ ok %Line 30
+ end.
+
+-file("bit_syntax.erl", 72500). %Line 72500
+build_binary1(Size) -> %Line 72501
+ id(42), %Line 72502
+ <<0:Size>>. %Line 72503
+
+build_binary2(Size, Bin) -> %Line 72505
+ id(0), %Line 72506
+ <<7:Size,Bin/binary>>. %Line 72507
+
+-file("gc_bif.erl", 17).
+do_call_abs(x, Arg) -> %Line 18
+ abs(Arg). %Line 19
+
+%% Make sure a BIF that is applied does not leave the p->cp
+%% set (and thus generating an extra entry on the stack).
+
+-file("applied_bif.erl", 1).
+%% Explicit apply.
+applied_bif_1(I) -> %Line 3
+ L = apply(erlang, integer_to_list, [I]), %Line 4
+ fail = L, %Line 5
+ ok. %Line 6
+%% Implicit apply.
+applied_bif_2() -> %Line 8
+ R = process_info(self(), current_location), %Line 9
+ fail = R, %Line 10
+ ok. %Line 11
diff --git a/erts/emulator/test/float_SUITE.erl b/erts/emulator/test/float_SUITE.erl
index 736510339f..46466427c5 100644
--- a/erts/emulator/test/float_SUITE.erl
+++ b/erts/emulator/test/float_SUITE.erl
@@ -25,7 +25,7 @@
init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
fpe/1,fp_drv/1,fp_drv_thread/1,denormalized/1,match/1,
- bad_float_unpack/1]).
+ bad_float_unpack/1,cmp_zero/1, cmp_integer/1, cmp_bignum/1]).
-export([otp_7178/1]).
@@ -41,10 +41,10 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[fpe, fp_drv, fp_drv_thread, otp_7178, denormalized,
- match, bad_float_unpack].
+ match, bad_float_unpack, {group, comparison}].
groups() ->
- [].
+ [{comparison, [parallel], [cmp_zero, cmp_integer, cmp_bignum]}].
init_per_suite(Config) ->
Config.
@@ -187,6 +187,101 @@ bad_float_unpack(Config) when is_list(Config) ->
bad_float_unpack_match(<<F:64/float>>) -> F;
bad_float_unpack_match(<<I:64/integer-signed>>) -> I.
+cmp_zero(_Config) ->
+ cmp(0.5e-323,0).
+
+cmp_integer(_Config) ->
+ Axis = (1 bsl 53)-2.0, %% The point where floating points become unprecise
+ span_cmp(Axis,2,200),
+ cmp(Axis*Axis,round(Axis)).
+
+cmp_bignum(_Config) ->
+ span_cmp((1 bsl 58) - 1.0),%% Smallest bignum float
+
+ %% Test when the big num goes from I to I+1 in size
+ [span_cmp((1 bsl (32*I)) - 1.0) || I <- lists:seq(2,30)],
+
+ %% Test bignum greater then largest float
+ cmp((1 bsl (64*16)) - 1, (1 bsl (64*15)) * 1.0),
+ %% Test when num is much larger then float
+ [cmp((1 bsl (32*I)) - 1, (1 bsl (32*(I-2))) * 1.0) || I <- lists:seq(3,30)],
+ %% Test when float is much larger than num
+ [cmp((1 bsl (64*15)) * 1.0, (1 bsl (32*(I)))) || I <- lists:seq(1,29)],
+
+ %% Test that all int == float works as they should
+ [true = 1 bsl N == (1 bsl N)*1.0 || N <- lists:seq(0, 1023)],
+ [true = (1 bsl N)*-1 == (1 bsl N)*-1.0 || N <- lists:seq(0, 1023)].
+
+span_cmp(Axis) ->
+ span_cmp(Axis, 25).
+span_cmp(Axis, Length) ->
+ span_cmp(Axis, round(Axis) bsr 52, Length).
+span_cmp(Axis, Incr, Length) ->
+ [span_cmp(Axis, Incr, Length, 1 bsl (1 bsl I)) || I <- lists:seq(0,6)].
+%% This function creates tests around number axis. Both <, > and == is tested
+%% for both negative and positive numbers.
+%%
+%% Axis: The number around which to do the tests eg. (1 bsl 58) - 1.0
+%% Incr: How much to increment the test numbers inbetween each test.
+%% Length: Length/2 is the number of Incr away from Axis to test on the
+%% negative and positive plane.
+%% Diff: How much the float and int should differ when comparing
+span_cmp(Axis, Incr, Length, Diff) ->
+ [begin
+ cmp(round(Axis*-1.0)+Diff+I*Incr,Axis*-1.0+I*Incr),
+ cmp(Axis*-1.0+I*Incr,round(Axis*-1.0)-Diff+I*Incr)
+ end || I <- lists:seq((Length div 2)*-1,(Length div 2))],
+ [begin
+ cmp(round(Axis)+Diff+I*Incr,Axis+I*Incr),
+ cmp(Axis+I*Incr,round(Axis)-Diff+I*Incr)
+ end || I <- lists:seq((Length div 2)*-1,(Length div 2))].
+
+cmp(Big,Small) when is_float(Big) ->
+ BigGtSmall = lists:flatten(
+ io_lib:format("~f > ~p",[Big,Small])),
+ BigLtSmall = lists:flatten(
+ io_lib:format("~f < ~p",[Big,Small])),
+ BigEqSmall = lists:flatten(
+ io_lib:format("~f == ~p",[Big,Small])),
+ SmallGtBig = lists:flatten(
+ io_lib:format("~p > ~f",[Small,Big])),
+ SmallLtBig = lists:flatten(
+ io_lib:format("~p < ~f",[Small,Big])),
+ SmallEqBig = lists:flatten(
+ io_lib:format("~p == ~f",[Small,Big])),
+ cmp(Big,Small,BigGtSmall,BigLtSmall,SmallGtBig,SmallLtBig,
+ SmallEqBig,BigEqSmall);
+cmp(Big,Small) when is_float(Small) ->
+ BigGtSmall = lists:flatten(
+ io_lib:format("~p > ~f",[Big,Small])),
+ BigLtSmall = lists:flatten(
+ io_lib:format("~p < ~f",[Big,Small])),
+ BigEqSmall = lists:flatten(
+ io_lib:format("~p == ~f",[Big,Small])),
+ SmallGtBig = lists:flatten(
+ io_lib:format("~f > ~p",[Small,Big])),
+ SmallLtBig = lists:flatten(
+ io_lib:format("~f < ~p",[Small,Big])),
+ SmallEqBig = lists:flatten(
+ io_lib:format("~f == ~p",[Small,Big])),
+ cmp(Big,Small,BigGtSmall,BigLtSmall,SmallGtBig,SmallLtBig,
+ SmallEqBig,BigEqSmall).
+
+cmp(Big,Small,BigGtSmall,BigLtSmall,SmallGtBig,SmallLtBig,
+ SmallEqBig,BigEqSmall) ->
+ {_,_,_,true} = {Big,Small,BigGtSmall,
+ Big > Small},
+ {_,_,_,false} = {Big,Small,BigLtSmall,
+ Big < Small},
+ {_,_,_,false} = {Big,Small,SmallGtBig,
+ Small > Big},
+ {_,_,_,true} = {Big,Small,SmallLtBig,
+ Small < Big},
+ {_,_,_,false} = {Big,Small,SmallEqBig,
+ Small == Big},
+ {_,_,_,false} = {Big,Small,BigEqSmall,
+ Big == Small}.
+
id(I) -> I.
start_node(Config) when is_list(Config) ->
diff --git a/erts/emulator/test/fun_SUITE.erl b/erts/emulator/test/fun_SUITE.erl
index 7795efe57e..559e540016 100644
--- a/erts/emulator/test/fun_SUITE.erl
+++ b/erts/emulator/test/fun_SUITE.erl
@@ -647,17 +647,11 @@ refc_dist_1() ->
%% Fun is passed in an exit signal. Wait until it is gone.
?line wait_until(fun () -> 4 =/= fun_refc(F2) end),
?line 3 = fun_refc(F2),
- erts_debug:set_internal_state(available_internal_state, true),
- ?line F_refc = case erts_debug:get_internal_state(force_heap_frags) of
- false -> 3;
- true -> 2 % GC after bif already decreased it
- end,
- ?line F_refc = fun_refc(F),
- erts_debug:set_internal_state(available_internal_state, false),
+ ?line true = erlang:garbage_collect(),
+ ?line 2 = fun_refc(F),
refc_dist_send(Node, F).
refc_dist_send(Node, F) ->
- ?line true = erlang:garbage_collect(),
?line Pid = spawn_link(Node,
fun() -> receive
{To,Fun} when is_function(Fun) ->
diff --git a/erts/emulator/test/guard_SUITE.erl b/erts/emulator/test/guard_SUITE.erl
index f41324c2cc..a5df9b59a0 100644
--- a/erts/emulator/test/guard_SUITE.erl
+++ b/erts/emulator/test/guard_SUITE.erl
@@ -421,7 +421,7 @@ try_gbif(Id, X, Y) ->
try_fail_gbif(Id, X, Y) ->
case catch guard_bif(Id, X, Y) of
- {'EXIT', {function_clause,[{?MODULE,guard_bif,[Id,X,Y]}|_]}} ->
+ {'EXIT',{function_clause,[{?MODULE,guard_bif,[Id,X,Y],_}|_]}} ->
io:format("guard_bif(~p, ~p, ~p) -- ok", [Id,X,Y]);
Other ->
?line ok = io:format("guard_bif(~p, ~p, ~p) -- bad result: ~p\n",
@@ -493,9 +493,9 @@ type_tests(Test, [Type|T], Allowed) ->
end;
false ->
case catch type_test(Test, Value) of
- {'EXIT', {function_clause, {?MODULE,type_test,[Test,Value]}}} ->
- ok;
- {'EXIT', {function_clause,[{?MODULE,type_test,[Test,Value]}|_]}} ->
+ {'EXIT',{function_clause,
+ [{?MODULE,type_test,[Test,Value],Loc}|_]}}
+ when is_list(Loc) ->
ok;
{'EXIT',Other} ->
?line test_server:fail({unexpected_error_reason,Other});
diff --git a/erts/emulator/test/hibernate_SUITE.erl b/erts/emulator/test/hibernate_SUITE.erl
index 203fa6b48e..82a0aad189 100644
--- a/erts/emulator/test/hibernate_SUITE.erl
+++ b/erts/emulator/test/hibernate_SUITE.erl
@@ -25,16 +25,16 @@
init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
basic/1,dynamic_call/1,min_heap_size/1,bad_args/1,
- messages_in_queue/1,undefined_mfa/1, no_heap/1]).
+ messages_in_queue/1,undefined_mfa/1,no_heap/1,wake_up_and_bif_trap/1]).
%% Used by test cases.
--export([basic_hibernator/1,dynamic_call_hibernator/2,messages_in_queue_restart/2, no_heap_loop/0]).
+-export([basic_hibernator/1,dynamic_call_hibernator/2,messages_in_queue_restart/2, no_heap_loop/0,characters_to_list_trap/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[basic, dynamic_call, min_heap_size, bad_args, messages_in_queue,
- undefined_mfa, no_heap].
+ undefined_mfa, no_heap, wake_up_and_bif_trap].
groups() ->
[].
@@ -384,6 +384,31 @@ clean_dict() ->
lists:foreach(fun ({Key, _}) -> erase(Key) end, Dict).
%%
+%% Wake up and then immediatly bif trap with a lengthy computation.
+%%
+
+wake_up_and_bif_trap(doc) -> [];
+wake_up_and_bif_trap(suite) -> [];
+wake_up_and_bif_trap(Config) when is_list(Config) ->
+ ?line Self = self(),
+ ?line Pid = spawn_link(fun() -> erlang:hibernate(?MODULE, characters_to_list_trap, [Self]) end),
+ ?line Pid ! wakeup,
+ ?line receive
+ {ok, Pid0} when Pid0 =:= Pid -> ok
+ after 5000 ->
+ ?line ?t:fail(process_blocked)
+ end,
+ ?line unlink(Pid),
+ ?line exit(Pid, bye).
+
+%% Lengthy computation that traps (in characters_to_list_trap_3).
+characters_to_list_trap(Parent) ->
+ Bin0 = <<"abcdefghijklmnopqrstuvwxz0123456789">>,
+ Bin = binary:copy(Bin0, 1500),
+ unicode:characters_to_list(Bin),
+ Parent ! {ok, self()}.
+
+%%
%% Misc
%%
diff --git a/erts/emulator/test/match_spec_SUITE.erl b/erts/emulator/test/match_spec_SUITE.erl
index 2b21fa58f4..461773114e 100644
--- a/erts/emulator/test/match_spec_SUITE.erl
+++ b/erts/emulator/test/match_spec_SUITE.erl
@@ -27,8 +27,9 @@
destructive_in_test_bif/1, guard_exceptions/1,
unary_plus/1, unary_minus/1, moving_labels/1]).
-export([fpe/1]).
+-export([otp_9422/1]).
--export([runner/2]).
+-export([runner/2, loop_runner/3]).
-export([f1/1, f2/2, f3/2, fn/1, fn/2, fn/3]).
-export([do_boxed_and_small/0]).
@@ -57,7 +58,8 @@ all() ->
trace_control_word, silent, silent_no_ms, ms_trace2,
ms_trace3, boxed_and_small, destructive_in_test_bif,
guard_exceptions, unary_plus, unary_minus, fpe,
- moving_labels];
+ moving_labels,
+ otp_9422];
true -> [not_run]
end.
@@ -208,6 +210,43 @@ test_3(Config) when is_list(Config) ->
?line collect(P1, [{trace, P1, call, {?MODULE, f2, [a, b]}, [true]}]),
?line ok.
+otp_9422(doc) -> [];
+otp_9422(Config) when is_list(Config) ->
+ Laps = 1000,
+ ?line Fun1 = fun() -> otp_9422_tracee() end,
+ ?line P1 = spawn_link(?MODULE, loop_runner, [self(), Fun1, Laps]),
+ io:format("spawned ~p as tracee\n", [P1]),
+
+ ?line erlang:trace(P1, true, [call, silent]),
+
+ ?line Fun2 = fun() -> otp_9422_trace_changer() end,
+ ?line P2 = spawn_link(?MODULE, loop_runner, [self(), Fun2, Laps]),
+ io:format("spawned ~p as trace_changer\n", [P2]),
+
+ start_collect(P1),
+ start_collect(P2),
+
+ %%receive after 10*1000 -> ok end,
+
+ stop_collect(P1),
+ stop_collect(P2),
+ ok.
+
+otp_9422_tracee() ->
+ ?MODULE:f1(a),
+ ?MODULE:f1(b),
+ ?MODULE:f1(c).
+
+otp_9422_trace_changer() ->
+ Pat1 = [{[a], [], [{enable_trace, arity}]}],
+ ?line erlang:trace_pattern({?MODULE, f1, 1}, Pat1),
+ Pat2 = [{[b], [], [{disable_trace, arity}]}],
+ ?line erlang:trace_pattern({?MODULE, f1, 1}, Pat2).
+
+
+
+
+
bad_match_spec_bin(Config) when is_list(Config) ->
{'EXIT',{badarg,_}} = (catch ets:match_spec_run([1], <<>>)),
B0 = <<1,2>>,
@@ -932,6 +971,24 @@ runner(Collector, Fun) ->
Collector ! {gone, self()}
end.
+loop_runner(Collector, Fun, Laps) ->
+ receive
+ {go, Collector} ->
+ go
+ end,
+ loop_runner_cont(Collector, Fun, 0, Laps).
+
+loop_runner_cont(_Collector, _Fun, Laps, Laps) ->
+ receive
+ {done, Collector} ->
+ io:format("loop_runner ~p exit after ~p laps\n", [self(), Laps]),
+ Collector ! {gone, self()}
+ end;
+loop_runner_cont(Collector, Fun, N, Laps) ->
+ Fun(),
+ loop_runner_cont(Collector, Fun, N+1, Laps).
+
+
f1(X) ->
{X}.
diff --git a/erts/emulator/test/mtx_SUITE.erl b/erts/emulator/test/mtx_SUITE.erl
index e0a7878bd8..879d2f61dd 100644
--- a/erts/emulator/test/mtx_SUITE.erl
+++ b/erts/emulator/test/mtx_SUITE.erl
@@ -62,16 +62,29 @@ init_per_suite(Config) when is_list(Config) ->
Config.
end_per_suite(Config) when is_list(Config) ->
+ catch erts_debug:set_internal_state(available_internal_state, false),
Config.
init_per_testcase(_Case, Config) ->
Dog = ?t:timetrap(?t:minutes(15)),
+ %% Wait for deallocations to complete since we measure
+ %% runtime in test cases.
+ wait_deallocations(),
[{watchdog, Dog}|Config].
end_per_testcase(_Func, Config) ->
Dog = ?config(watchdog, Config),
?t:timetrap_cancel(Dog).
+wait_deallocations() ->
+ try
+ erts_debug:set_internal_state(wait, deallocations)
+ catch
+ error:undef ->
+ erts_debug:set_internal_state(available_internal_state, true),
+ wait_deallocations()
+ end.
+
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
diff --git a/erts/emulator/test/mtx_SUITE_data/mtx_SUITE.c b/erts/emulator/test/mtx_SUITE_data/mtx_SUITE.c
index 818023211c..7c8137dc83 100644
--- a/erts/emulator/test/mtx_SUITE_data/mtx_SUITE.c
+++ b/erts/emulator/test/mtx_SUITE_data/mtx_SUITE.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -552,13 +552,19 @@ create_rwlock(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
static ERL_NIF_TERM
rwlock_op(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
- rwlock_resource_t *rwlr;
+ /*
+ * Use a union for pointer type conversion to avoid compiler warnings
+ * about strict-aliasing violations with gcc-4.1. gcc >= 4.2 does not
+ * emit the warning.
+ * TODO: Reconsider use of union once gcc-4.1 is obsolete?
+ */
+ union { void* vp; rwlock_resource_t *p; } rwlr;
int blocking, write, wait_locked, wait_unlocked;
if (argc != 5)
goto badarg;
- if (!enif_get_resource(env, argv[0], enif_priv_data(env), (void **) &rwlr))
+ if (!enif_get_resource(env, argv[0], enif_priv_data(env), &rwlr.vp))
goto badarg;
blocking = get_bool(env, argv[1]);
@@ -581,22 +587,22 @@ rwlock_op(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
if (write) {
if (blocking)
- RWMUTEX_WLOCK(rwlr->rwlock);
+ RWMUTEX_WLOCK(rwlr.p->rwlock);
else
- while (EBUSY == RWMUTEX_TRYWLOCK(rwlr->rwlock));
- if (rwlr->lock_check) {
- ASSERT(!ATOMIC_READ(&rwlr->is_locked));
- ATOMIC_SET(&rwlr->is_locked, -1);
+ while (EBUSY == RWMUTEX_TRYWLOCK(rwlr.p->rwlock));
+ if (rwlr.p->lock_check) {
+ ASSERT(!ATOMIC_READ(&rwlr.p->is_locked));
+ ATOMIC_SET(&rwlr.p->is_locked, -1);
}
}
else {
if (blocking)
- RWMUTEX_RLOCK(rwlr->rwlock);
+ RWMUTEX_RLOCK(rwlr.p->rwlock);
else
- while (EBUSY == RWMUTEX_TRYRLOCK(rwlr->rwlock));
- if (rwlr->lock_check) {
- ASSERT(ATOMIC_READ(&rwlr->is_locked) >= 0);
- ATOMIC_INC(&rwlr->is_locked);
+ while (EBUSY == RWMUTEX_TRYRLOCK(rwlr.p->rwlock));
+ if (rwlr.p->lock_check) {
+ ASSERT(ATOMIC_READ(&rwlr.p->is_locked) >= 0);
+ ATOMIC_INC(&rwlr.p->is_locked);
}
}
@@ -604,18 +610,18 @@ rwlock_op(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
milli_sleep(wait_locked);
if (write) {
- if (rwlr->lock_check) {
- ASSERT(ATOMIC_READ(&rwlr->is_locked) == -1);
- ATOMIC_SET(&rwlr->is_locked, 0);
+ if (rwlr.p->lock_check) {
+ ASSERT(ATOMIC_READ(&rwlr.p->is_locked) == -1);
+ ATOMIC_SET(&rwlr.p->is_locked, 0);
}
- RWMUTEX_WUNLOCK(rwlr->rwlock);
+ RWMUTEX_WUNLOCK(rwlr.p->rwlock);
}
else {
- if (rwlr->lock_check) {
- ASSERT(ATOMIC_READ(&rwlr->is_locked) > 0);
- ATOMIC_DEC(&rwlr->is_locked);
+ if (rwlr.p->lock_check) {
+ ASSERT(ATOMIC_READ(&rwlr.p->is_locked) > 0);
+ ATOMIC_DEC(&rwlr.p->is_locked);
}
- RWMUTEX_RUNLOCK(rwlr->rwlock);
+ RWMUTEX_RUNLOCK(rwlr.p->rwlock);
}
if (wait_unlocked)
diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl
index b9b964f526..370363bf9e 100644
--- a/erts/emulator/test/nif_SUITE.erl
+++ b/erts/emulator/test/nif_SUITE.erl
@@ -35,7 +35,9 @@
resource_takeover/1,
threading/1, send/1, send2/1, send3/1, send_threaded/1, neg/1,
is_checks/1,
- get_length/1, make_atom/1, make_string/1]).
+ get_length/1, make_atom/1, make_string/1, reverse_list_test/1,
+ otp_9668/1
+ ]).
-export([many_args_100/100]).
@@ -60,7 +62,9 @@ all() ->
iolist_as_binary, resource, resource_binary,
resource_takeover, threading, send, send2, send3,
send_threaded, neg, is_checks, get_length, make_atom,
- make_string].
+ make_string,reverse_list_test,
+ otp_9668
+ ].
groups() ->
[].
@@ -257,10 +261,54 @@ types(Config) when is_list(Config) ->
end,
[{},{ok},{{}},{[],{}},{1,2,3,4,5}]),
Stuff = [[],{},0,0.0,(1 bsl 100),(fun()-> ok end),make_ref(),self()],
- [eq_cmp(A,clone(B)) || A<-Stuff, B<-Stuff],
+ [eq_cmp(A,clone(B)) || A<-Stuff, B<-Stuff],
+
+ {IntSz, LongSz} = type_sizes(),
+ UintMax = (1 bsl (IntSz*8)) - 1,
+ IntMax = UintMax bsr 1,
+ IntMin = -(IntMax+1),
+ UlongMax = (1 bsl (LongSz*8)) - 1,
+ LongMax = UlongMax bsr 1,
+ LongMin = -(LongMax+1),
+ Uint64Max = (1 bsl 64) - 1,
+ Int64Max = Uint64Max bsr 1,
+ Int64Min = -(Int64Max+1),
+ Limits = [{IntMin,IntMax},{0,UintMax},{LongMin,LongMax},{0,UlongMax},{Int64Min,Int64Max},{0,Uint64Max}],
+ io:format("Limits = ~p\n", [Limits]),
+ lists:foreach(fun(I) ->
+ R1 = echo_int(I),
+ %%io:format("echo_int(~p) -> ~p\n", [I, R1]),
+ R2 = my_echo_int(I, Limits),
+ ?line R1 = R2,
+ ?line true = (R1 =:= R2),
+ ?line true = (R1 == R2)
+ end, int_list()),
+
?line verify_tmpmem(TmpMem),
+ ?line true = (compare(-1294536544000, -1178704800000) < 0),
+ ?line true = (compare(-1178704800000, -1294536544000) > 0),
+ ?line true = (compare(-295147905179352825856, -36893488147419103232) < 0),
+ ?line true = (compare(-36893488147419103232, -295147905179352825856) > 0),
+ ?line true = (compare(-29514790517935282585612345678, -36893488147419103232) < 0),
+ ?line true = (compare(-36893488147419103232, -29514790517935282585612345678) > 0),
ok.
+int_list() ->
+ Start = 1 bsl 200,
+ int_list([Start], -Start).
+int_list([N | _]=List, End) when N<End ->
+ List;
+int_list([N | _]=List, End) ->
+ int_list([N - (1 + (abs(N) div 3)) | List], End).
+
+my_echo_int(I, Limits) ->
+ lists:map(fun({Min,Max}) ->
+ if I < Min -> false;
+ I > Max -> false;
+ true -> I
+ end
+ end, Limits).
+
clone(X) ->
binary_to_term(term_to_binary(X)).
@@ -1121,7 +1169,28 @@ is_checks(Config) when is_list(Config) ->
?line ensure_lib_loaded(Config, 1),
?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
self(), hd(erlang:ports()), [], [1,9,9,8],
- {hejsan, "hejsan", [$h,"ejs",<<"an">>]}),
+ {hejsan, "hejsan", [$h,"ejs",<<"an">>]}, 12),
+ ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
+ self(), hd(erlang:ports()), [], [1,9,9,8],
+ {hejsan, "hejsan", [$h,"ejs",<<"an">>]}, -12),
+ ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
+ self(), hd(erlang:ports()), [], [1,9,9,8],
+ {hejsan, "hejsan", [$h,"ejs",<<"an">>]}, 18446744073709551617),
+ ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
+ self(), hd(erlang:ports()), [], [1,9,9,8],
+ {hejsan, "hejsan", [$h,"ejs",<<"an">>]}, -18446744073709551617),
+ ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
+ self(), hd(erlang:ports()), [], [1,9,9,8],
+ {hejsan, "hejsan", [$h,"ejs",<<"an">>]}, 99.146),
+ ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
+ self(), hd(erlang:ports()), [], [1,9,9,8],
+ {hejsan, "hejsan", [$h,"ejs",<<"an">>]}, -99.146),
+ ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
+ self(), hd(erlang:ports()), [], [1,9,9,8],
+ {hejsan, "hejsan", [$h,"ejs",<<"an">>]}, 18446744073709551616.2e2),
+ ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
+ self(), hd(erlang:ports()), [], [1,9,9,8],
+ {hejsan, "hejsan", [$h,"ejs",<<"an">>]}, -18446744073709551616.2e2),
try
?line error = check_is_exception(),
?line throw(expected_badarg)
@@ -1164,6 +1233,27 @@ make_string(Config) when is_list(Config) ->
AStringWithAccents = [$E,$r,$l,$a,$n,$g,$ ,16#e4,$r,$ ,$e,$t,$t,$ ,$g,$e,$n,$e,$r,$e,$l,$l,$t,$ ,$p,$r,$o,$g,$r,$a,$m,$s,$p,$r,16#e5,$k],
?line Strings = {A0String,A0String,A0String,A0String0, AStringWithAccents}.
+reverse_list_test(Config) ->
+ ?line ensure_lib_loaded(Config, 1),
+ List = lists:seq(1,100),
+ RevList = lists:reverse(List),
+ ?line RevList = reverse_list(List),
+ ?line badarg = reverse_list(foo).
+
+otp_9668(doc) -> ["Memory leak of tmp-buffer when inspecting iolist or unaligned binary in unbound environment"];
+otp_9668(Config) ->
+ ensure_lib_loaded(Config, 1),
+ TmpMem = tmpmem(),
+ IOList = ["This",' ',<<"is">>,' ',[<<"an iolist">>,'.']],
+ otp_9668_nif(IOList),
+
+ <<_:5/bitstring,UnalignedBin:10/binary,_/bitstring>> = <<"Abuse me as unaligned">>,
+ otp_9668_nif(UnalignedBin),
+
+ ?line verify_tmpmem(TmpMem),
+ ok.
+
+
tmpmem() ->
case erlang:system_info({allocator,temp_alloc}) of
false -> undefined;
@@ -1252,7 +1342,7 @@ get_resource(_,_) -> ?nif_stub.
release_resource(_) -> ?nif_stub.
last_resource_dtor_call() -> ?nif_stub.
make_new_resource(_,_) -> ?nif_stub.
-check_is(_,_,_,_,_,_,_,_,_,_) -> ?nif_stub.
+check_is(_,_,_,_,_,_,_,_,_,_,_) -> ?nif_stub.
check_is_exception() -> ?nif_stub.
length_test(_,_,_,_,_) -> ?nif_stub.
make_atoms() -> ?nif_stub.
@@ -1270,6 +1360,10 @@ send_blob_thread(_,_,_) -> ?nif_stub.
join_send_thread(_) -> ?nif_stub.
copy_blob(_) -> ?nif_stub.
send_term(_,_) -> ?nif_stub.
+reverse_list(_) -> ?nif_stub.
+echo_int(_) -> ?nif_stub.
+type_sizes() -> ?nif_stub.
+otp_9668_nif(_) -> ?nif_stub.
nif_stub_error(Line) ->
exit({nif_not_loaded,module,?MODULE,line,Line}).
diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
index 0bb93daa33..7d7903af25 100644
--- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
+++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
@@ -28,6 +28,7 @@
static int static_cntA; /* zero by default */
static int static_cntB = NIF_SUITE_LIB_VER * 100;
+static ERL_NIF_TERM atom_false;
static ERL_NIF_TERM atom_self;
static ERL_NIF_TERM atom_ok;
static ERL_NIF_TERM atom_join;
@@ -40,7 +41,18 @@ typedef struct
CallInfo* call_history;
NifModPrivData* nif_mod;
union { ErlNifResourceType* t; long l; } rt_arr[2];
-}PrivData;
+} PrivData;
+
+/*
+ * Use a union for pointer type conversion to avoid compiler warnings
+ * about strict-aliasing violations with gcc-4.1. gcc >= 4.2 does not
+ * emit the warning.
+ * TODO: Reconsider use of union once gcc-4.1 is obsolete?
+ */
+typedef union {
+ void* vp;
+ struct make_term_info* p;
+} mti_t;
void add_call(ErlNifEnv* env, PrivData* data, const char* func_name)
{
@@ -103,7 +115,7 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
msgenv_resource_type = enif_open_resource_type(env,NULL,"nif_SUITE.msgenv",
msgenv_dtor,
ERL_NIF_RT_CREATE, NULL);
-
+ atom_false = enif_make_atom(env,"false");
atom_self = enif_make_atom(env,"self");
atom_ok = enif_make_atom(env,"ok");
atom_join = enif_make_atom(env,"join");
@@ -481,6 +493,45 @@ error:
return enif_make_atom(env,"error");
}
+static ERL_NIF_TERM echo_int(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ int sint;
+ unsigned uint;
+ long slong;
+ unsigned long ulong;
+ ErlNifSInt64 sint64;
+ ErlNifUInt64 uint64;
+ ERL_NIF_TERM sint_term = atom_false, uint_term = atom_false;
+ ERL_NIF_TERM slong_term = atom_false, ulong_term = atom_false;
+ ERL_NIF_TERM sint64_term = atom_false, uint64_term = atom_false;
+
+ if (enif_get_int(env, argv[0], &sint)) {
+ sint_term = enif_make_int(env, sint);
+ }
+ if (enif_get_uint(env, argv[0], &uint)) {
+ uint_term = enif_make_uint(env, uint);
+ }
+ if (enif_get_long(env, argv[0], &slong)) {
+ slong_term = enif_make_long(env, slong);
+ }
+ if (enif_get_ulong(env, argv[0], &ulong)) {
+ ulong_term = enif_make_ulong(env, ulong);
+ }
+ if (enif_get_int64(env, argv[0], &sint64)) {
+ sint64_term = enif_make_int64(env, sint64);
+ }
+ if (enif_get_uint64(env, argv[0], &uint64)) {
+ uint64_term = enif_make_uint64(env, uint64);
+ }
+ return enif_make_list6(env, sint_term, uint_term, slong_term, ulong_term, sint64_term, uint64_term);
+}
+
+static ERL_NIF_TERM type_sizes(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ return enif_make_tuple2(env, enif_make_int(env, sizeof(int)),
+ enif_make_int(env, sizeof(long)));
+}
+
static ERL_NIF_TERM tuple_2_list(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
int arity = -1;
@@ -667,7 +718,7 @@ static ERL_NIF_TERM get_resource_type(ErlNifEnv* env, int argc, const ERL_NIF_TE
static ERL_NIF_TERM alloc_resource(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary data_bin;
- union { ErlNifResourceType* t; long l;} type;
+ union { ErlNifResourceType* t; long l; } type;
union { void* p; long l;} data;
if (!enif_get_long(env, argv[0], &type.l)
|| !enif_inspect_binary(env, argv[1], &data_bin)
@@ -691,7 +742,7 @@ static ERL_NIF_TERM make_resource(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
static ERL_NIF_TERM make_new_resource(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary data_bin;
- union { ErlNifResourceType* t; long l;} type;
+ union { ErlNifResourceType* t; long l; } type;
void* data;
ERL_NIF_TERM ret;
if (!enif_get_long(env, argv[0], &type.l)
@@ -709,7 +760,7 @@ static ERL_NIF_TERM make_new_resource(ErlNifEnv* env, int argc, const ERL_NIF_TE
static ERL_NIF_TERM make_new_resource_binary(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary data_bin;
- union { struct binary_resource* p; void* vp; long l;} br;
+ union { struct binary_resource* p; void* vp; long l; } br;
void* buf;
ERL_NIF_TERM ret;
if (!enif_inspect_binary(env, argv[0], &data_bin)
@@ -781,6 +832,7 @@ static ERL_NIF_TERM release_resource(ErlNifEnv* env, int argc, const ERL_NIF_TER
* argv[7] an empty list
* argv[8] a non-empty list
* argv[9] a tuple
+ * argv[10] a number (small, big integer or float)
*/
static ERL_NIF_TERM check_is(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
@@ -797,6 +849,7 @@ static ERL_NIF_TERM check_is(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
if (!enif_is_list(env, argv[7])) return enif_make_badarg(env);
if (!enif_is_list(env, argv[8])) return enif_make_badarg(env);
if (!enif_is_tuple(env, argv[9])) return enif_make_badarg(env);
+ if (!enif_is_number(env, argv[10])) return enif_make_badarg(env);
return ok_atom;
}
@@ -1229,10 +1282,7 @@ static void msgenv_dtor(ErlNifEnv* env, void* obj)
static ERL_NIF_TERM clear_msgenv(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
- union {
- void* vp;
- struct make_term_info* p;
- }mti;
+ mti_t mti;
if (!enif_get_resource(env, argv[0], msgenv_resource_type, &mti.vp)) {
return enif_make_badarg(env);
}
@@ -1245,7 +1295,7 @@ static ERL_NIF_TERM clear_msgenv(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
static ERL_NIF_TERM grow_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
- union { void* vp; struct make_term_info* p; }mti;
+ mti_t mti;
ERL_NIF_TERM term;
if (!enif_get_resource(env, argv[0], msgenv_resource_type, &mti.vp)
|| (argc>2 && !enif_get_uint(env,argv[2], &mti.p->n))) {
@@ -1261,7 +1311,7 @@ static ERL_NIF_TERM grow_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
static ERL_NIF_TERM send_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
- union { void* vp; struct make_term_info* p; }mti;
+ mti_t mti;
ErlNifPid to;
ERL_NIF_TERM copy;
int res;
@@ -1276,7 +1326,7 @@ static ERL_NIF_TERM send_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
static ERL_NIF_TERM send3_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
- union { void* vp; struct make_term_info* p; }mti;
+ mti_t mti;
ErlNifPid to;
ERL_NIF_TERM copy;
int res;
@@ -1294,7 +1344,7 @@ static ERL_NIF_TERM send3_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
void* threaded_sender(void *arg)
{
- union { void* vp; struct make_term_info* p; }mti;
+ mti_t mti;
mti.vp = arg;
enif_mutex_lock(mti.p->mtx);
@@ -1309,7 +1359,7 @@ void* threaded_sender(void *arg)
static ERL_NIF_TERM send_blob_thread(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
- union { void* vp; struct make_term_info* p; }mti;
+ mti_t mti;
ERL_NIF_TERM copy;
if (!enif_get_resource(env, argv[0], msgenv_resource_type, &mti.vp)
|| !enif_get_local_pid(env,argv[1], &mti.p->to_pid)) {
@@ -1335,7 +1385,7 @@ static ERL_NIF_TERM send_blob_thread(ErlNifEnv* env, int argc, const ERL_NIF_TER
static ERL_NIF_TERM join_send_thread(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
- union { void* vp; struct make_term_info* p; }mti;
+ mti_t mti;
int err;
if (!enif_get_resource(env, argv[0], msgenv_resource_type, &mti.vp)) {
return enif_make_badarg(env);
@@ -1352,7 +1402,7 @@ static ERL_NIF_TERM join_send_thread(ErlNifEnv* env, int argc, const ERL_NIF_TER
static ERL_NIF_TERM copy_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
- union { void* vp; struct make_term_info* p; }mti;
+ mti_t mti;
if (!enif_get_resource(env, argv[0], msgenv_resource_type, &mti.vp)) {
return enif_make_badarg(env);
}
@@ -1373,6 +1423,34 @@ static ERL_NIF_TERM send_term(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
return enif_make_int(env, ret);
}
+static ERL_NIF_TERM reverse_list(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
+ ERL_NIF_TERM rev_list;
+
+ if(!enif_make_reverse_list(env, argv[0], &rev_list))
+ return enif_make_atom(env, "badarg");
+ return rev_list;
+}
+
+static ERL_NIF_TERM otp_9668_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ /* Inspect in process independent env */
+ ErlNifEnv* myenv = enif_alloc_env();
+ ERL_NIF_TERM mycopy = enif_make_copy(myenv, argv[0]);
+ ErlNifBinary obin, cbin;
+
+ if ((enif_inspect_binary(env, argv[0], &obin)
+ && enif_inspect_binary(myenv, mycopy, &cbin))
+ ||
+ (enif_inspect_iolist_as_binary(env, argv[0], &obin)
+ && enif_inspect_iolist_as_binary(myenv, mycopy, &cbin)))
+ {
+ assert(obin.size == cbin.size);
+ assert(memcmp(obin.data, cbin.data, obin.size) == 0);
+ }
+ enif_free_env(myenv);
+ return atom_ok;
+}
+
static ErlNifFunc nif_funcs[] =
{
{"lib_version", 0, lib_version},
@@ -1399,7 +1477,7 @@ static ErlNifFunc nif_funcs[] =
{"release_resource", 1, release_resource},
{"last_resource_dtor_call", 0, last_resource_dtor_call},
{"make_new_resource", 2, make_new_resource},
- {"check_is", 10, check_is},
+ {"check_is", 11, check_is},
{"check_is_exception", 0, check_is_exception},
{"length_test", 5, length_test},
{"make_atoms", 0, make_atoms},
@@ -1417,7 +1495,11 @@ static ErlNifFunc nif_funcs[] =
{"send_blob_thread", 3, send_blob_thread},
{"join_send_thread", 1, join_send_thread},
{"copy_blob", 1, copy_blob},
- {"send_term", 2, send_term}
+ {"send_term", 2, send_term},
+ {"reverse_list",1, reverse_list},
+ {"echo_int", 1, echo_int},
+ {"type_sizes", 0, type_sizes},
+ {"otp_9668_nif", 1, otp_9668_nif}
};
ERL_NIF_INIT(nif_SUITE,nif_funcs,load,reload,upgrade,unload)
diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl
index eac56a867d..0a1ef5a78f 100644
--- a/erts/emulator/test/port_SUITE.erl
+++ b/erts/emulator/test/port_SUITE.erl
@@ -724,6 +724,8 @@ open_ports(Name, Settings) ->
[];
system_limit ->
[];
+ enomem ->
+ [];
Other ->
?line test_server:fail({open_ports, Other})
end;
diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl
index f68e712268..fdc55a4cc5 100644
--- a/erts/emulator/test/process_SUITE.erl
+++ b/erts/emulator/test/process_SUITE.erl
@@ -35,7 +35,7 @@
self_exit/1, normal_suicide_exit/1, abnormal_suicide_exit/1,
t_exit_2_catch/1, trap_exit_badarg/1, trap_exit_badarg_in_bif/1,
exit_and_timeout/1, exit_twice/1,
- t_process_info/1, process_info_other_msg/1,
+ t_process_info/1, process_info_other/1, process_info_other_msg/1,
process_info_other_dist_msg/1,
process_info_2_list/1, process_info_lock_reschedule/1,
process_info_lock_reschedule2/1,
@@ -64,7 +64,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[spawn_with_binaries, t_exit_1, {group, t_exit_2},
trap_exit_badarg, trap_exit_badarg_in_bif,
- t_process_info, process_info_other_msg,
+ t_process_info, process_info_other, process_info_other_msg,
process_info_other_dist_msg, process_info_2_list,
process_info_lock_reschedule,
process_info_lock_reschedule2,
@@ -258,7 +258,9 @@ trap_exit_badarg() ->
?line Pid = fun_spawn(fun() -> bad_guy(kb_128()) end),
?line Garbage = kb_128(),
?line receive
- {'EXIT', Pid, {badarg,[{erlang,abs,[Garbage]},{?MODULE,bad_guy,1}|_]}} ->
+ {'EXIT',Pid,{badarg,[{erlang,abs,[Garbage],Loc1},
+ {?MODULE,bad_guy,1,Loc2}|_]}}
+ when is_list(Loc1), is_list(Loc2) ->
ok;
Other ->
?line ok = io:format("Bad EXIT message: ~P", [Other, 30]),
@@ -410,7 +412,7 @@ etwice_high(Low) ->
exit(Low, first),
exit(Low, second).
-%% Tests the process_info/1 BIF.
+%% Tests the process_info/2 BIF.
t_process_info(Config) when is_list(Config) ->
?line [] = process_info(self(), registered_name),
?line register(my_name, self()),
@@ -418,13 +420,100 @@ t_process_info(Config) when is_list(Config) ->
?line {status, running} = process_info(self(), status),
?line {min_heap_size, 233} = process_info(self(), min_heap_size),
?line {min_bin_vheap_size, 46368} = process_info(self(), min_bin_vheap_size),
- ?line {current_function, {?MODULE, t_process_info, 1}} =
+ ?line {current_function,{?MODULE,t_process_info,1}} =
process_info(self(), current_function),
+ ?line {current_function,{?MODULE,t_process_info,1}} =
+ apply(erlang, process_info, [self(),current_function]),
+
+ %% current_location and current_stacktrace
+ {Line1,Res1} = {?LINE,process_info(self(), current_location)},
+ verify_loc(Line1, Res1),
+ {Line2,Res2} = {?LINE,apply(erlang, process_info,
+ [self(),current_location])},
+ verify_loc(Line2, Res2),
+ pi_stacktrace([{?MODULE,t_process_info,1,?LINE}]),
+
?line Gleader = group_leader(),
?line {group_leader, Gleader} = process_info(self(), group_leader),
?line {'EXIT',{badarg,_Info}} = (catch process_info('not_a_pid')),
ok.
+pi_stacktrace(Expected0) ->
+ {Line,Res} = {?LINE,erlang:process_info(self(), current_stacktrace)},
+ {current_stacktrace,Stack} = Res,
+ Expected = [{?MODULE,pi_stacktrace,1,Line}|Expected0],
+ pi_stacktrace_1(Stack, Expected).
+
+pi_stacktrace_1([{M,F,A,Loc}|Stk], [{M,F,A,Line}|Exp]) ->
+ case Loc of
+ [] ->
+ %% No location info for some reason (+L, native code).
+ io:format("Missing location information for ~w:~w/~w",
+ [M,F,A]),
+ ok;
+ [_|_] ->
+ Line = proplists:get_value(line, Loc),
+ File = proplists:get_value(file, Loc),
+ File = ?MODULE_STRING ++ ".erl"
+ end,
+ pi_stacktrace_1(Stk, Exp);
+pi_stacktrace_1([_|_], []) -> ok.
+
+verify_loc(Line, {current_location,{?MODULE,t_process_info=F,1=A,Loc}}) ->
+ case Loc of
+ [] ->
+ %% No location info for some reason (+L, native code).
+ io:format("Missing location information for ~w:~w/~w",
+ [?MODULE,F,A]),
+ ok;
+ [_|_] ->
+ Line = proplists:get_value(line, Loc),
+ File = proplists:get_value(file, Loc),
+ File = ?MODULE_STRING ++ ".erl"
+ end.
+
+process_info_other(Config) when is_list(Config) ->
+ Self = self(),
+ Pid = spawn_link(fun() -> process_info_looper(Self) end),
+ receive after 1 -> ok end,
+ pio_current_location(10000, Pid, 0, 0),
+ pio_current_stacktrace().
+
+pio_current_location(0, _, Pi, Looper) ->
+ io:format("~w call(s) to erlang:process_info/2", [Pi]),
+ io:format("~w call(s) to ~w:process_info_looper/1", [Looper,?MODULE]);
+pio_current_location(N, Pid, Pi, Looper) ->
+ erlang:yield(),
+ {current_location,Where} = process_info(Pid, current_location),
+ case Where of
+ {erlang,process_info,2,[]} ->
+ pio_current_location(N-1, Pid, Pi+1, Looper);
+ {?MODULE,process_info_looper,1,Loc} when is_list(Loc) ->
+ pio_current_location(N-1, Pid, Pi, Looper+1)
+ end.
+
+pio_current_stacktrace() ->
+ L = [begin
+ {current_stacktrace,Stk} = process_info(P, current_stacktrace),
+ {P,Stk}
+ end || P <- processes()],
+ [erlang:garbage_collect(P) || {P,_} <- L],
+ erlang:garbage_collect(),
+ [verify_stacktrace(Stk) || {_,Stk} <- L],
+ ok.
+
+verify_stacktrace([{M,F,A,Loc}|T])
+ when is_atom(M),
+ is_atom(F),
+ is_integer(A),
+ is_list(Loc) ->
+ verify_stacktrace(T);
+verify_stacktrace([]) -> ok.
+
+process_info_looper(Parent) ->
+ process_info(Parent, current_location),
+ process_info_looper(Parent).
+
%% Tests the process_info/1 BIF on another process with messages.
process_info_other_msg(Config) when is_list(Config) ->
Self = self(),
diff --git a/erts/emulator/test/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl
index f16d0ea429..debb54579b 100644
--- a/erts/emulator/test/scheduler_SUITE.erl
+++ b/erts/emulator/test/scheduler_SUITE.erl
@@ -87,8 +87,17 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-
+init_per_testcase(update_cpu_info, Config) ->
+ case os:find_executable("taskset") of
+ false ->
+ {skip,"Could not find 'taskset' in path"};
+ _ ->
+ init_per_tc(update_cpu_info, Config)
+ end;
init_per_testcase(Case, Config) when is_list(Config) ->
+ init_per_tc(Case, Config).
+
+init_per_tc(Case, Config) ->
Dog = ?t:timetrap(?DEFAULT_TIMEOUT),
process_flag(priority, max),
erlang:display({'------------', ?MODULE, Case, '------------'}),
@@ -1030,7 +1039,7 @@ sbt_test(Config, CpuTCmd, ClBt, Bt, LP) ->
?line ok.
scheduler_suspend(Config) when is_list(Config) ->
- ?line Dog = ?t:timetrap(?t:minutes(2)),
+ ?line Dog = ?t:timetrap(?t:minutes(5)),
?line lists:foreach(fun (S) -> scheduler_suspend_test(Config, S) end,
[64, 32, 16, default]),
?line ?t:timetrap_cancel(Dog),
diff --git a/erts/emulator/test/system_info_SUITE.erl b/erts/emulator/test/system_info_SUITE.erl
index 9b782b35a2..0350eb671d 100644
--- a/erts/emulator/test/system_info_SUITE.erl
+++ b/erts/emulator/test/system_info_SUITE.erl
@@ -37,7 +37,7 @@
init_per_group/2,end_per_group/2,
init_per_testcase/2, end_per_testcase/2]).
--export([process_count/1, system_version/1, misc_smoke_tests/1, heap_size/1, wordsize/1]).
+-export([process_count/1, system_version/1, misc_smoke_tests/1, heap_size/1, wordsize/1, memory/1]).
-define(DEFAULT_TIMEOUT, ?t:minutes(2)).
@@ -45,7 +45,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[process_count, system_version, misc_smoke_tests,
- heap_size, wordsize].
+ heap_size, wordsize, memory].
groups() ->
[].
@@ -187,3 +187,312 @@ wordsize(Config) when is_list(Config) ->
Other ->
exit({unexpected_wordsizes,Other})
end.
+
+memory(doc) -> ["Verify that erlang:memory/0 and memory results in crashdump produce are similar"];
+memory(Config) when is_list(Config) ->
+ %%
+ %% Verify that erlang:memory/0 and memory results in
+ %% crashdump produce are similar.
+ %%
+ %% erlang:memory/0 requests information from each scheduler
+ %% thread and puts the information together in erlang code
+ %% (erlang.erl).
+ %%
+ %% When a crash dump is written we cannot use the
+ %% erlang:memory/0 implementation. The crashdump implementation
+ %% is a pure C implementation inspecting all allocator instances
+ %% after the system has been blocked (erts_memory() in erl_alloc.c).
+ %%
+ %% Since we got two implementations, modifications can easily
+ %% cause them to produce different results.
+ %%
+ %% erts_debug:get_internal_state(memory) blocks the system and
+ %% execute the same code as the crash dump writing uses.
+ %%
+
+ erts_debug:set_internal_state(available_internal_state, true),
+ %% Use a large heap size on the controling process in
+ %% order to avoid changes in its heap size during
+ %% comparisons.
+ MinHeapSize = process_flag(min_heap_size, 1024*1024),
+ Prio = process_flag(priority, max),
+ try
+ erlang:memory(), %% first call will init stat atoms
+ garbage_collect(), %% blow up heap
+ memory_test(Config)
+ catch
+ error:notsup -> {skipped, "erlang:memory() not supported"}
+ after
+ process_flag(min_heap_size, MinHeapSize),
+ process_flag(priority, Prio),
+ catch erts_debug:set_internal_state(available_internal_state, false)
+ end.
+
+memory_test(_Config) ->
+
+ MWs = spawn_mem_workers(),
+
+ DPs = mem_workers_call(MWs,
+ fun () ->
+ mapn(fun (_) ->
+ spawn(fun () ->
+ receive
+ after infinity ->
+ ok
+ end
+ end)
+ end,
+ 1000 div erlang:system_info(schedulers_online))
+ end,
+ []),
+ cmp_memory(MWs, "spawn procs"),
+
+ Ps = lists:flatten(DPs),
+
+ mem_workers_call(MWs,
+ fun () ->
+ lists:foreach(fun (P) -> link(P) end, Ps)
+ end,
+ []),
+ cmp_memory(MWs, "link procs"),
+ mem_workers_call(MWs,
+ fun () ->
+ lists:foreach(fun (P) -> unlink(P) end, Ps)
+ end,
+ []),
+ cmp_memory(MWs, "unlink procs"),
+
+ DMs = mem_workers_call(MWs,
+ fun () ->
+ lists:map(fun (P) ->
+ monitor(process, P)
+ end, Ps)
+ end,
+ []),
+ cmp_memory(MWs, "monitor procs"),
+ Ms = lists:flatten(DMs),
+ mem_workers_call(MWs,
+ fun () ->
+ lists:foreach(fun (M) ->
+ demonitor(M)
+ end, Ms)
+ end,
+ []),
+ cmp_memory(MWs, "demonitor procs"),
+
+ mem_workers_call(MWs,
+ fun () ->
+ lists:foreach(fun (P) ->
+ P ! {a, "message", make_ref()}
+ end, Ps)
+ end,
+ []),
+ cmp_memory(MWs, "message procs"),
+
+ mem_workers_call(MWs,
+ fun () ->
+ Mons = lists:map(fun (P) ->
+ exit(P, kill),
+ monitor(process, P)
+ end,
+ Ps),
+ lists:foreach(fun (Mon) ->
+ receive
+ {'DOWN', Mon, _, _, _} -> ok
+ end
+ end,
+ Mons)
+ end, []),
+ cmp_memory(MWs, "kill procs"),
+
+ mem_workers_call(MWs,
+ fun () ->
+ put(binary_data,
+ mapn(fun (_) -> list_to_binary(lists:duplicate(256,$?)) end, 100))
+ end,
+ []),
+
+ cmp_memory(MWs, "store binary data"),
+
+ mem_workers_call(MWs,
+ fun () ->
+ put(binary_data, false),
+ garbage_collect()
+ end,
+ []),
+ cmp_memory(MWs, "release binary data"),
+
+ mem_workers_call(MWs,
+ fun () ->
+ list_to_atom("an ugly atom "++integer_to_list(erlang:system_info(scheduler_id))),
+ list_to_atom("another ugly atom "++integer_to_list(erlang:system_info(scheduler_id))),
+ list_to_atom("yet another ugly atom "++integer_to_list(erlang:system_info(scheduler_id)))
+ end,
+ []),
+ cmp_memory(MWs, "new atoms"),
+
+
+ mem_workers_call(MWs,
+ fun () ->
+ T = ets:new(?MODULE, []),
+ ets:insert(T, {gurka, lists:seq(1,10000)}),
+ ets:insert(T, {banan, lists:seq(1,1024)}),
+ ets:insert(T, {appelsin, make_ref()}),
+ put(ets_id, T)
+ end,
+ []),
+ cmp_memory(MWs, "store ets data"),
+
+ mem_workers_call(MWs,
+ fun () ->
+ ets:delete(get(ets_id)),
+ put(ets_id, false)
+ end,
+ []),
+ cmp_memory(MWs, "remove ets data"),
+
+ lists:foreach(fun (MW) ->
+ unlink(MW),
+ Mon = monitor(process, MW),
+ exit(MW, kill),
+ receive
+ {'DOWN', Mon, _, _, _} -> ok
+ end
+ end,
+ MWs),
+ ok.
+
+mem_worker() ->
+ receive
+ {call, From, Fun, Args} ->
+ From ! {reply, self(), apply(Fun, Args)},
+ mem_worker();
+ {cast, _From, Fun, Args} ->
+ apply(Fun, Args),
+ mem_worker()
+ end.
+
+mem_workers_call(MWs, Fun, Args) ->
+ lists:foreach(fun (MW) ->
+ MW ! {call, self(), Fun, Args}
+ end,
+ MWs),
+ lists:map(fun (MW) ->
+ receive
+ {reply, MW, Res} ->
+ Res
+ end
+ end,
+ MWs).
+
+mem_workers_cast(MWs, Fun, Args) ->
+ lists:foreach(fun (MW) ->
+ MW ! {cast, self(), Fun, Args}
+ end,
+ MWs).
+
+spawn_mem_workers() ->
+ spawn_mem_workers(erlang:system_info(schedulers_online)).
+
+spawn_mem_workers(0) ->
+ [];
+spawn_mem_workers(N) ->
+ [spawn_opt(fun () -> mem_worker() end,
+ [{scheduler, N rem erlang:system_info(schedulers_online) + 1},
+ link]) | spawn_mem_workers(N-1)].
+
+
+
+mem_get(X, Mem) ->
+ case lists:keyfind(X, 1, Mem) of
+ {X, Val} -> Val;
+ false -> false
+ end.
+
+cmp_memory(What, Mem1, Mem2, 1) ->
+ R1 = mem_get(What, Mem1),
+ R2 = mem_get(What, Mem2),
+ true = R1 == R2;
+cmp_memory(What, Mem1, Mem2, RelDiff) ->
+ %% We allow RealDiff diff
+ R1 = mem_get(What, Mem1),
+ R2 = mem_get(What, Mem2),
+ case R1 == R2 of
+ true ->
+ ok;
+ false ->
+ case R1 > R2 of
+ true ->
+ true = R2*RelDiff > R1;
+ false ->
+ true = R1*RelDiff > R2
+ end
+ end.
+
+pos_int(Val) when Val >= 0 ->
+ Val;
+pos_int(Val) ->
+ exit({not_pos_int, Val}).
+
+check_sane_memory(Mem) ->
+ Tot = pos_int(mem_get(total, Mem)),
+ Proc = pos_int(mem_get(processes, Mem)),
+ ProcUsed = pos_int(mem_get(processes_used, Mem)),
+ Sys = pos_int(mem_get(system, Mem)),
+ Atom = pos_int(mem_get(atom, Mem)),
+ AtomUsed = pos_int(mem_get(atom_used, Mem)),
+ Bin = pos_int(mem_get(binary, Mem)),
+ Code = pos_int(mem_get(code, Mem)),
+ Ets = pos_int(mem_get(ets, Mem)),
+
+ Tot = Proc + Sys,
+ true = Sys > Atom + Bin + Code + Ets,
+ true = Proc >= ProcUsed,
+ true = Atom >= AtomUsed,
+
+ case mem_get(maximum, Mem) of
+ false -> ok;
+ Max -> true = pos_int(Max) >= Tot
+ end,
+ ok.
+
+cmp_memory(MWs, Str) ->
+ erlang:display(Str),
+ lists:foreach(fun (MW) -> garbage_collect(MW) end, MWs),
+ garbage_collect(),
+ erts_debug:set_internal_state(wait, deallocations),
+
+ EDM = erts_debug:get_internal_state(memory),
+ EM = erlang:memory(),
+
+ io:format("~s:~n"
+ "erlang:memory() = ~p~n"
+ "crash dump memory = ~p~n",
+ [Str, EM, EDM]),
+
+ ?line check_sane_memory(EM),
+ ?line check_sane_memory(EDM),
+
+ %% We expect these to always give us exactly the same result
+
+ ?line cmp_memory(atom, EM, EDM, 1),
+ ?line cmp_memory(atom_used, EM, EDM, 1),
+ ?line cmp_memory(binary, EM, EDM, 1),
+ ?line cmp_memory(code, EM, EDM, 1),
+ ?line cmp_memory(ets, EM, EDM, 1),
+
+ %% Total, processes, processes_used, and system will seldom
+ %% give us exactly the same result since the two readings
+ %% aren't taken atomically.
+
+ ?line cmp_memory(total, EM, EDM, 1.05),
+ ?line cmp_memory(processes, EM, EDM, 1.05),
+ ?line cmp_memory(processes_used, EM, EDM, 1.05),
+ ?line cmp_memory(system, EM, EDM, 1.05),
+
+ ok.
+
+mapn(_Fun, 0) ->
+ [];
+mapn(Fun, N) ->
+ [Fun(N) | mapn(Fun, N-1)].
diff --git a/erts/emulator/test/trace_local_SUITE.erl b/erts/emulator/test/trace_local_SUITE.erl
index 091e960610..32e2a98e3c 100644
--- a/erts/emulator/test/trace_local_SUITE.erl
+++ b/erts/emulator/test/trace_local_SUITE.erl
@@ -767,8 +767,8 @@ exception_test(Opts, Func0, Args0) ->
end,
?line R1 = exc_slave(ExcOpts, Func, Args),
- ?line Stack2 = [{?MODULE,exc_top,3},{?MODULE,slave,2}],
- ?line Stack3 = [{?MODULE,exc,2}|Stack2],
+ ?line Stack2 = [{?MODULE,exc_top,3,[]},{?MODULE,slave,2,[]}],
+ ?line Stack3 = [{?MODULE,exc,2,[]}|Stack2],
?line Rs =
case x_exc_top(ExcOpts, Func, Args) of % Emulation
{crash,{Reason,Stack}}=R when is_list(Stack) ->
@@ -789,21 +789,29 @@ exception_test(Opts, Func0, Args0) ->
end,
?line expect({nm}).
-exception_validate(R1, [R2|Rs]) ->
+exception_validate(R0, Rs0) ->
+ R = clean_location(R0),
+ Rs = [clean_location(E) || E <- Rs0],
+ exception_validate_1(R, Rs).
+
+exception_validate_1(R1, [R2|Rs]) ->
case [R1|R2] of
[R|R] ->
ok;
- [{crash,{badarg,[{lists,reverse,[L1a,L1b]}|T]}}|
- {crash,{badarg,[{lists,reverse,[L2a,L2b]}|T]}}] ->
+ [{crash,{badarg,[{lists,reverse,[L1a,L1b],_}|T]}}|
+ {crash,{badarg,[{lists,reverse,[L2a,L2b],_}|T]}}] ->
same({crash,{badarg,[{lists,reverse,
- [lists:reverse(L1b, L1a),[]]}|T]}},
+ [lists:reverse(L1b, L1a),[]],[]}|T]}},
{crash,{badarg,[{lists,reverse,
- [lists:reverse(L2b, L2a),[]]}|T]}});
+ [lists:reverse(L2b, L2a),[]],[]}|T]}});
_ when is_list(Rs), Rs =/= [] ->
exception_validate(R1, Rs)
end.
-
+clean_location({crash,{Reason,Stk0}}) ->
+ Stk = [{M,F,A,[]} || {M,F,A,_} <- Stk0],
+ {crash,{Reason,Stk}};
+clean_location(Term) -> Term.
%%% Tracee target functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%
@@ -1057,10 +1065,10 @@ x_exc_exception(_Rtt, M, F, _, Arity, CR) ->
x_exc_stacktrace() ->
x_exc_stacktrace(erlang:get_stacktrace()).
%% Truncate stacktrace to below exc/2
-x_exc_stacktrace([{?MODULE,x_exc,4}|_]) -> [];
-x_exc_stacktrace([{?MODULE,x_exc_func,4}|_]) -> [];
-x_exc_stacktrace([{?MODULE,x_exc_body,4}|_]) -> [];
-x_exc_stacktrace([{?MODULE,exc,2}|_]) -> [];
+x_exc_stacktrace([{?MODULE,x_exc,4,_}|_]) -> [];
+x_exc_stacktrace([{?MODULE,x_exc_func,4,_}|_]) -> [];
+x_exc_stacktrace([{?MODULE,x_exc_body,4,_}|_]) -> [];
+x_exc_stacktrace([{?MODULE,exc,2,_}|_]) -> [];
x_exc_stacktrace([H|T]) ->
[H|x_exc_stacktrace(T)].
diff --git a/erts/emulator/utils/beam_makeops b/erts/emulator/utils/beam_makeops
index e7c57142c0..58c36c3bdc 100755
--- a/erts/emulator/utils/beam_makeops
+++ b/erts/emulator/utils/beam_makeops
@@ -2,7 +2,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1998-2010. All Rights Reserved.
+# Copyright Ericsson AB 1998-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -67,6 +67,10 @@ my $max_gen_operands = 8;
# Must be even. The beam_load.c file must be updated, too.
my $max_spec_operands = 6;
+# The maximum number of primitive genop_types.
+
+my $max_genop_types = 16;
+
my %gen_opnum;
my %num_specific;
my %gen_to_spec;
@@ -101,12 +105,14 @@ my %match_engine_ops; # All opcodes for the match engine.
my %gen_transform_offset;
my @transformations;
my @call_table;
+my %call_table;
my @pred_table;
+my %pred_table;
# Operand types for generic instructions.
my $compiler_types = "uiaxyfhz";
-my $loader_types = "nprvlq";
+my $loader_types = "nprvlqo";
my $genop_types = $compiler_types . $loader_types;
#
@@ -142,34 +148,67 @@ my %arg_size = ('r' => 0, # x(0) - x register zero
my %type_bit;
my @tag_type;
+sub define_type_bit {
+ my($tag,$val) = @_;
+ defined $type_bit{$tag} and
+ sanity("the tag '$tag' has already been defined with the value ",
+ $type_bit{$tag});
+ $type_bit{$tag} = $val;
+}
+
{
my($bit) = 1;
my(%bit);
foreach (split('', $genop_types)) {
push(@tag_type, $_);
- $type_bit{$_} = $bit;
+ define_type_bit($_, $bit);
$bit{$_} = $bit;
$bit *= 2;
}
# Composed types.
- $type_bit{'d'} = $type_bit{'x'} | $type_bit{'y'} | $type_bit{'r'};
- $type_bit{'c'} = $type_bit{'i'} | $type_bit{'a'} | $type_bit{'n'} | $type_bit{'q'};
- $type_bit{'s'} = $type_bit{'d'} | $type_bit{'i'} | $type_bit{'a'} | $type_bit{'n'};
- $type_bit{'j'} = $type_bit{'f'} | $type_bit{'p'};
+ define_type_bit('d', $type_bit{'x'} | $type_bit{'y'} | $type_bit{'r'});
+ define_type_bit('c', $type_bit{'i'} | $type_bit{'a'} |
+ $type_bit{'n'} | $type_bit{'q'});
+ define_type_bit('s', $type_bit{'d'} | $type_bit{'i'} |
+ $type_bit{'a'} | $type_bit{'n'});
+ define_type_bit('j', $type_bit{'f'} | $type_bit{'p'});
# Aliases (for matching purposes).
- $type_bit{'I'} = $type_bit{'u'};
- $type_bit{'t'} = $type_bit{'u'};
- $type_bit{'A'} = $type_bit{'u'};
- $type_bit{'L'} = $type_bit{'u'};
- $type_bit{'b'} = $type_bit{'u'};
- $type_bit{'N'} = $type_bit{'u'};
- $type_bit{'U'} = $type_bit{'u'};
- $type_bit{'e'} = $type_bit{'u'};
- $type_bit{'P'} = $type_bit{'u'};
- $type_bit{'Q'} = $type_bit{'u'};
+ define_type_bit('I', $type_bit{'u'});
+ define_type_bit('t', $type_bit{'u'});
+ define_type_bit('A', $type_bit{'u'});
+ define_type_bit('L', $type_bit{'u'});
+ define_type_bit('b', $type_bit{'u'});
+ define_type_bit('N', $type_bit{'u'});
+ define_type_bit('U', $type_bit{'u'});
+ define_type_bit('e', $type_bit{'u'});
+ define_type_bit('P', $type_bit{'u'});
+ define_type_bit('Q', $type_bit{'u'});
+}
+
+#
+# Pre-define the 'fail' instruction. It is used internally
+# by the 'try_me_else_fail' instruction.
+#
+$match_engine_ops{'TOP_fail'} = 1;
+
+#
+# Sanity checks.
+#
+
+{
+ if (@tag_type > $max_genop_types) {
+ sanity("\$max_genop_types is $max_genop_types, ",
+ "but there are ", scalar(@tag_type),
+ " primitive tags defined\n");
+ }
+
+ foreach my $tag (@tag_type) {
+ sanity("tag '$tag': primitive tags must be named with lowercase letters")
+ unless $tag =~ /^[a-z]$/;
+ }
}
#
@@ -436,12 +475,12 @@ sub emulator_output {
#
my(@bits) = (0) x ($max_spec_operands/2);
- my($shift) = 16;
my($i);
for ($i = 0; $i < $max_spec_operands && defined $args[$i]; $i++) {
my $t = $args[$i];
if (defined $type_bit{$t}) {
- $bits[int($i/2)] |= $type_bit{$t} << (16*($i%2));
+ my $shift = $max_genop_types * ($i % 2);
+ $bits[int($i/2)] |= $type_bit{$t} << $shift;
}
}
@@ -753,6 +792,10 @@ sub error {
die $where, @message, "\n";
}
+sub sanity {
+ die "internal error: ", @_, "\n";
+}
+
sub comment {
my($lang, @comments) = @_;
my($prefix);
@@ -1269,7 +1312,8 @@ sub tr_gen {
foreach $ref (@g) {
my($line, $orig_transform, $from_ref, $to_ref) = @$ref;
- my $so_far = tr_gen_from($line, @$from_ref);
+ my $used_ref = used_vars($from_ref, $to_ref);
+ my $so_far = tr_gen_from($line, $used_ref, @$from_ref);
tr_gen_to($line, $orig_transform, $so_far, @$to_ref);
}
@@ -1278,9 +1322,22 @@ sub tr_gen {
#
my($offset) = 0;
print "Uint op_transform[] = {\n";
- foreach $key (keys %gen_transform) {
+ foreach $key (sort keys %gen_transform) {
$gen_transform_offset{$key} = $offset;
- foreach $instr (@{$gen_transform{$key}}) {
+ my @instr = @{$gen_transform{$key}};
+
+ #
+ # If the last instruction is 'fail', remove it and
+ # convert the previous 'try_me_else' to 'try_me_else_fail'.
+ #
+ if (is_instr($instr[$#instr], 'fail')) {
+ pop(@instr);
+ my $i = $#instr;
+ $i-- while !is_instr($instr[$i], 'try_me_else');
+ $instr[$i] = make_op('', 'try_me_else_fail');
+ }
+
+ foreach $instr (@instr) {
my($size, $instr_ref, $comment) = @$instr;
my($op, @args) = @$instr_ref;
print " ";
@@ -1307,8 +1364,48 @@ sub tr_gen {
print "};\n\n";
}
+sub used_vars {
+ my($from_ref,$to_ref) = @_;
+ my %used;
+ my %seen;
+
+ foreach my $ref (@$from_ref) {
+ my($name,$arity,@ops) = @$ref;
+ if ($name =~ /^[.]/) {
+ foreach my $var (@ops) {
+ $used{$var} = 1;
+ }
+ } else {
+ # Any variable that is used at least twice on the
+ # left-hand side is used. (E.g. "move R R".)
+ foreach my $op (@ops) {
+ my($var, $type, $type_val) = @$op;
+ next if $var eq '';
+ $used{$var} = 1 if $seen{$var};
+ $seen{$var} = 1;
+ }
+ }
+ }
+
+ foreach my $ref (@$to_ref) {
+ my($name, $arity, @ops) = @$ref;
+ if ($name =~ /^[.]/) {
+ foreach my $var (@ops) {
+ $used{$var} = 1;
+ }
+ } else {
+ foreach my $op (@ops) {
+ my($var, $type, $type_val) = @$op;
+ next if $var eq '';
+ $used{$var} = 1;
+ }
+ }
+ }
+ \%used;
+}
+
sub tr_gen_from {
- my($line, @tr) = @_;
+ my($line,$used_ref,@tr) = @_;
my(%var) = ();
my(%var_type);
my($var_num) = 0;
@@ -1318,25 +1415,30 @@ sub tr_gen_from {
my(@fix_pred_funcs);
my($op, $ref); # Loop variables.
my $where = "left side of transformation in line $line: ";
+ my %var_used = %$used_ref;
+ my $may_fail = 0;
+ my $is_first = 1;
foreach $ref (@tr) {
my($name, $arity, @ops) = @$ref;
my($key) = "$name/$arity";
my($opnum);
+ $may_fail = 1 unless $is_first;
+ $is_first = 0;
+
#
# A name starting with a period is a C pred function to be called.
#
if ($name =~ /^\.(\w+)/) {
$name = $1;
+ $may_fail = 1;
my $var;
my(@args);
- my $next_instr = pop(@code); # Get rid of 'next_instr'
push(@fix_pred_funcs, scalar(@code));
push(@code, [$name, @ops]);
- push(@code, $next_instr);
next;
}
@@ -1348,17 +1450,21 @@ sub tr_gen_from {
unless defined $gen_opnum{$name,$arity};
$opnum = $gen_opnum{$name,$arity};
- push(@code, &make_op("$name/$arity", 'is_op', $opnum));
+ push(@code, make_op("$name/$arity", 'next_instr', $opnum));
$min_window++;
foreach $op (@ops) {
my($var, $type, $type_val, $cond, $val) = @$op;
+ my $ignored_var = "$var (ignored)";
if ($type ne '' && $type ne '*') {
+ $may_fail = 1;
+
#
# The is_bif, is_not_bif, and is_func instructions have
# their own built-in type test and don't need to
# be guarded with a type test instruction.
#
+ $ignored_var = '';
unless ($cond eq 'is_bif' or
$cond eq 'is_not_bif' or
$cond eq 'is_func') {
@@ -1372,7 +1478,7 @@ sub tr_gen_from {
push(@code, &make_op($types, 'is_type', $type_mask));
} else {
$cond = '';
- push(@code, &make_op($types, 'is_type_eq',
+ push(@code, &make_op("$types== $val", 'is_type_eq',
$type_mask, $val));
}
}
@@ -1380,46 +1486,55 @@ sub tr_gen_from {
if ($cond eq 'is_func') {
my($m, $f, $a) = split(/:/, $val);
+ $ignored_var = '';
+ $may_fail = 1;
push(@code, &make_op('', "$cond", "am_$m",
"am_$f", $a));
} elsif ($cond ne '') {
+ $ignored_var = '';
+ $may_fail = 1;
push(@code, &make_op('', "$cond", $val));
}
if ($var ne '') {
if (defined $var{$var}) {
+ $ignored_var = '';
+ $may_fail = 1;
push(@code, &make_op($var, 'is_same_var', $var{$var}));
} elsif ($type eq '*') {
#
# Reserve a hole for a 'rest_args' instruction.
#
+ $ignored_var = '';
push(@fix_rest_args, scalar(@code));
push(@code, $var);
- } else {
+ } elsif ($var_used{$var}) {
+ $ignored_var = '';
$var_type{$var} = 'scalar';
$var{$var} = $var_num;
$var_num++;
push(@code, &make_op($var, 'set_var', $var{$var}));
}
}
- if (is_set_var_instr($code[$#code])) {
+ if (is_instr($code[$#code], 'set_var')) {
my $ref = pop @code;
my $comment = $ref->[2];
my $var = $ref->[1][1];
push(@code, make_op($comment, 'set_var_next_arg', $var));
} else {
- push(@code, &make_op('', 'next_arg'));
+ push(@code, &make_op($ignored_var, 'next_arg'));
}
}
- push(@code, &make_op('', 'next_instr'));
- pop(@code) if $code[$#code]->[1][0] eq 'next_arg';
+
+ # Remove redundant 'next_arg' instructions before the end
+ # of the instruction.
+ pop(@code) while is_instr($code[$#code], 'next_arg');
}
#
# Insert the commit operation.
#
- pop(@code); # Get rid of 'next_instr'
- push(@code, &make_op('', 'commit'));
+ push(@code, make_op($may_fail ? '' : 'always reached', 'commit'));
#
# If there is an rest_args instruction, we must insert its correct
@@ -1449,9 +1564,8 @@ sub tr_gen_from {
push(@args, "var+$var{$var}");
}
}
- splice(@code, $index, 1, &make_op("$name()",
- 'pred', scalar(@pred_table)));
- push(@pred_table, [$name, @args]);
+ my $pi = tr_next_index(\@pred_table, \%pred_table, $name, @args);
+ splice(@code, $index, 1, make_op("$name()", 'pred', $pi));
}
$te_max_vars = $var_num
@@ -1468,6 +1582,10 @@ sub tr_gen_to {
my($op, $ref); # Loop variables.
my($where) = "right side of transformation in line $line: ";
+ my $last_instr = $code[$#code];
+ my $cannot_fail = is_instr($last_instr, 'commit') &&
+ (get_comment($last_instr) =~ /^always/);
+
foreach $ref (@tr) {
my($name, $arity, @ops) = @$ref;
@@ -1489,9 +1607,10 @@ sub tr_gen_to {
push(@args, "var+$var{$var}");
}
}
- pop(@code); # Get rid of 'next_instr'
- push(@code, &make_op("$name()", 'call', scalar(@call_table)));
- push(@call_table, [$name, @args]);
+ pop(@code); # Get rid of 'commit' instruction
+ my $index = tr_next_index(\@call_table, \%call_table,
+ $name, @args);
+ push(@code, make_op("$name()", 'call_end', $index));
last;
}
@@ -1508,27 +1627,27 @@ sub tr_gen_to {
# Create code to build the generic instruction.
#
- push(@code, &make_op('', 'new_instr'));
- push(@code, &make_op("$name/$arity", 'store_op', $opnum, $arity));
+ push(@code, make_op("$name/$arity", 'new_instr', $opnum));
foreach $op (@ops) {
my($var, $type, $type_val) = @$op;
if ($var ne '') {
&error($where, "variable '$var' unbound")
unless defined $var{$var};
- push(@code, &make_op($var, 'store_var', $var{$var}));
+ push(@code, &make_op($var, 'store_var_next_arg', $var{$var}));
} elsif ($type ne '') {
push(@code, &make_op('', 'store_type', "TAG_$type"));
if ($type_val) {
push(@code, &make_op('', 'store_val', $type_val));
}
+ push(@code, make_op('', 'next_arg'));
}
- push(@code, &make_op('', 'next_arg'));
}
- pop(@code) if $code[$#code]->[1][0] eq 'next_arg';
+ pop(@code) if is_instr($code[$#code], 'next_arg');
}
- push(@code, &make_op('', 'end'));
+ push(@code, make_op('', 'end'))
+ unless is_instr($code[$#code], 'call_end');
#
# Chain together all codes segments having the same first operation.
@@ -1540,11 +1659,20 @@ sub tr_gen_to {
$min_window{$key} = $min_window
if $min_window{$key} > $min_window;
- pop(@{$gen_transform{$key}})
+ my $prev_last;
+ $prev_last = pop(@{$gen_transform{$key}})
if defined @{$gen_transform{$key}}; # Fail
- my(@prefix) = (&make_op($comment), &make_op('', 'try_me_else', &tr_code_len(@code)));
- unshift(@code, @prefix);
- push(@{$gen_transform{$key}}, @code, &make_op('', 'fail'));
+
+ if ($prev_last && !is_instr($prev_last, 'fail')) {
+ error("Line $line: A previous transformation shadows '$orig_transform'");
+ }
+ unless ($cannot_fail) {
+ unshift(@code, make_op('', 'try_me_else',
+ tr_code_len(@code)));
+ push(@code, make_op(""), make_op("$key", 'fail'));
+ }
+ unshift(@code, make_op($comment));
+ push(@{$gen_transform{$key}}, @code),
}
sub tr_code_len {
@@ -1562,21 +1690,38 @@ sub make_op {
[scalar(@op), [@op], $comment];
}
-sub is_set_var_instr {
- my($ref) = @_;
+sub is_instr {
+ my($ref,$op) = @_;
return 0 unless ref($ref) eq 'ARRAY';
- $ref->[1][0] eq 'set_var';
+ $ref->[1][0] eq $op;
+}
+
+sub get_comment {
+ my($ref,$op) = @_;
+ return '' unless ref($ref) eq 'ARRAY';
+ $ref->[2];
+}
+
+sub tr_next_index {
+ my($lref,$href,$name,@args) = @_;
+ my $code = "RVAL = $name(" . join(', ', 'st', @args) . "); break;\n";
+ my $index;
+
+ if (defined $$href{$code}) {
+ $index = $$href{$code};
+ } else {
+ $index = scalar(@$lref);
+ push(@$lref, $code);
+ $$href{$code} = $index;
+ }
+ $index;
}
sub tr_gen_call {
my(@call_table) = @_;
my($i);
- print "\n";
for ($i = 0; $i < @call_table; $i++) {
- my $ref = $call_table[$i];
- my($name, @args) = @$ref;
- print "case $i: RVAL = $name(", join(', ', 'st', @args), "); break;\n";
+ print "case $i: $call_table[$i]";
}
- print "\n";
}
diff --git a/erts/emulator/utils/make_preload b/erts/emulator/utils/make_preload
index d0671e998d..d22f08f993 100755
--- a/erts/emulator/utils/make_preload
+++ b/erts/emulator/utils/make_preload
@@ -88,6 +88,7 @@ foreach $file (@ARGV) {
print "unsigned char preloaded_$module", "[] = {\n";
for ($i = 0; $i < length($_); $i++) {
if ($i % 8 == 0 && $comment ne '') {
+ $comment =~ s@/\*@..@g; # Comment start -- avoid warning.
$comment =~ s@\*/@..@g; # Comment terminator.
print " /* $comment */\n ";
$comment = '';
diff --git a/erts/emulator/utils/make_tables b/erts/emulator/utils/make_tables
index 918ef62094..91efb4c023 100755
--- a/erts/emulator/utils/make_tables
+++ b/erts/emulator/utils/make_tables
@@ -181,8 +181,7 @@ for ($i = 0; $i < @bif; $i++) {
print "\n";
for ($i = 0; $i < @bif; $i++) {
- my $arity = $bif[$i]->[2];
- my $args = join(', ', 'Process*', ('Eterm') x $arity);
+ my $args = join(', ', 'Process*', 'Eterm*');
print "Eterm $bif[$i]->[3]($args);\n";
print "Eterm wrap_$bif[$i]->[3]($args, UWord *I);\n";
}
@@ -219,28 +218,10 @@ for ($i = 0; $i < @bif; $i++) {
next if $bif[$i]->[3] eq $bif[$i]->[4]; # Skip unwrapped bifs
my $arity = $bif[$i]->[2];
my $func = $bif[$i]->[3];
- my $arg;
print "Eterm\n";
- print "wrap_$func(Process* p";
- for ($arg = 1; $arg <= $arity; $arg++) {
- print ", Eterm arg$arg";
- }
- print ", UWord *I)\n";
+ print "wrap_$func(Process* p, Eterm* args, UWord* I)\n";
print "{\n";
- print " return erts_bif_trace($i, p";
- for ($arg = 1; $arg <= 3; $arg++) {
- if ($arg <= $arity) {
- print ", arg$arg";
- #} elsif ($arg == ($arity + 1)) {
- # # Place I in correct position
- # print ", (Eterm) I";
- } else {
- print ", 0";
- }
- }
- # I is always last, as well as in the correct position
- # Note that "last" and "correct position" may be the same...
- print ", I);\n";
+ print " return erts_bif_trace($i, p, args, I);\n";
print "}\n\n";
}
@@ -261,19 +242,9 @@ for ($i = 0; $i < @bif; $i++) {
my $orig_func = $1;
$orig_func = $implementation[$i] if $implementation[$i];
print "Eterm\n";
- print "$func(Process* p";
- for ($arg = 1; $arg <= $arity; $arg++) {
- print ", Eterm arg$arg";
- }
- print ")\n";
+ print "$func(Process* p, Eterm* BIF__ARGS)\n";
print "{\n";
- print " return $orig_func(p";
- for ($arg = 1; $arg <= 3; $arg++) {
- if ($arg <= $arity) {
- print ", arg$arg";
- }
- }
- print ");\n";
+ print " return $orig_func(p, BIF__ARGS);\n";
print "}\n\n";
}
diff --git a/erts/emulator/valgrind/suppress.patched.3.6.0 b/erts/emulator/valgrind/suppress.patched.3.6.0
new file mode 100644
index 0000000000..2647949672
--- /dev/null
+++ b/erts/emulator/valgrind/suppress.patched.3.6.0
@@ -0,0 +1,307 @@
+# Valgrind suppression file updated to support the patched
+# Valgrind used in daily builds on ahmed.
+
+{
+ libc internal error
+ Memcheck:Addr8
+ obj:/lib64/ld-2.3.5.so
+}
+{
+ libc internal error
+ Memcheck:Addr8
+ fun:_dl_start
+}
+{
+ libc internal error
+ Memcheck:Addr8
+ fun:__libc_start_main
+ obj:*
+}
+{
+ libc internal error
+ Memcheck:Addr4
+ fun:__sigjmp_save
+ fun:__libc_start_main
+ obj:*
+}
+{
+ libc internal error
+ Memcheck:Addr8
+ fun:__sigsetjmp
+ fun:__libc_start_main
+ obj:*
+}
+{
+ Intentional error in testcase
+ Memcheck:Param
+ pipe(filedes)
+ fun:pipe
+ fun:chkio_drv_timeout
+}
+{
+ Intentional error in testcase
+ Memcheck:Param
+ pipe(filedes)
+ fun:pipe
+ fun:io_ready_exit_drv_control
+ fun:erts_port_control
+ fun:port_control_3
+ fun:process_main
+}
+{
+ Leak in libc putenv
+ Memcheck:Leak
+ fun:malloc
+ fun:realloc
+ fun:__add_to_environ
+ fun:putenv
+ fun:erts_sys_putenv
+ fun:os_putenv_2
+ fun:process_main
+}
+{
+Leak in libc putenv
+Memcheck:Leak
+fun:malloc
+fun:erts_sys_alloc
+...
+fun:erts_alloc
+fun:erts_sys_putenv
+fun:os_putenv_2
+fun:process_main
+}
+{
+ erronous warning
+ Memcheck:Leak
+ fun:malloc
+ fun:erts_sys_alloc
+ ...
+ fun:fix_core_alloc
+ fun:erts_init_fix_alloc
+ fun:erts_alloc_init
+ fun:early_init
+ fun:erl_start
+}
+{
+ pthread internal error
+ Memcheck:Param
+ futex(utime)
+ fun:__lll_mutex_unlock_wake
+}
+{
+ libc internal error
+ Memcheck:Param
+ socketcall.sendto(msg)
+ ...
+ fun:getifaddrs
+}
+{
+inet_drv; pointer inside allocated block
+Memcheck:Leak
+PossiblyLost
+fun:realloc
+fun:erts_sys_realloc
+...
+fun:erts_realloc_fnf
+fun:erts_bin_realloc_fnf
+fun:driver_realloc_binary
+}
+{
+inet_drv; pointer inside allocated block
+Memcheck:Leak
+PossiblyLost
+fun:malloc
+fun:erts_sys_alloc
+...
+fun:erts_alloc_fnf
+fun:erts_bin_drv_alloc_fnf
+fun:driver_alloc_binary
+}
+{
+pthread leak or erroneous valgrind warning
+Memcheck:Leak
+fun:calloc
+fun:allocate_dtv
+fun:_dl_allocate_tls
+fun:pthread_create@@GLIBC_2.2.5
+}
+{
+pthread leak or erroneous valgrind warning
+Memcheck:Leak
+fun:calloc
+fun:_dl_allocate_tls
+fun:pthread_create@@GLIBC_2.2.5
+}
+{
+zlib; ok according to zlib developers
+Memcheck:Cond
+fun:longest_match
+fun:deflate_slow
+fun:deflate
+}
+{
+zlib; ok according to zlib developers
+Memcheck:Cond
+fun:longest_match
+fun:deflate_fast
+fun:deflate
+}
+{
+zlib; ok accordnig to zlib (this one popped up with valgrind-3.6.0)
+Memcheck:Cond
+fun:deflate_slow
+fun:deflate
+fun:zlib_deflate
+fun:zlib_ctl
+}
+{
+No leak; pointer into block
+Memcheck:Leak
+fun:malloc
+fun:erts_sys_alloc
+...
+fun:erts_alloc
+fun:erts_init_scheduling
+fun:erl_init
+fun:erl_start
+fun:main
+}
+{
+No leak; pointer into block
+Memcheck:Leak
+PossiblyLost
+fun:malloc
+fun:erts_sys_alloc
+...
+fun:erts_alloc
+fun:init_db
+fun:erl_init
+fun:erl_start
+fun:main
+}
+{
+No leak; sometimes pointer into block
+Memcheck:Leak
+PossiblyLost
+fun:malloc
+fun:erts_sys_alloc
+...
+fun:erts_alloc_fnf
+fun:driver_alloc
+fun:get_bufstk
+fun:alloc_buffer
+}
+{
+ Crypto internal...
+Memcheck:Cond
+obj:*/crypto.valgrind.*
+}
+{
+ Crypto internal...
+Memcheck:Cond
+obj:*/libcrypto.*
+}
+{
+ Crypto internal...
+Memcheck:Cond
+obj:*/openssl.*
+}
+{
+ Crypto internal...
+Memcheck:Cond
+obj:*/ssleay.*
+}
+{
+ Crypto internal...
+Memcheck:Value8
+obj:*/crypto.valgrind.*
+}
+{
+ Crypto internal...
+Memcheck:Value8
+obj:*/libcrypto.*
+}
+{
+ Crypto internal...
+Memcheck:Value8
+obj:*/openssl.*
+}
+{
+ Crypto internal...
+Memcheck:Value8
+obj:*/ssleay.*
+}
+{
+ Crypto internal...
+ Memcheck:Cond
+ fun:memset
+ fun:BN_lshift
+ fun:BN_div
+ fun:BN_MONT_CTX_set
+ fun:BN_is_prime_fasttest_ex
+ fun:BN_generate_prime_ex
+ fun:DH_generate_parameters_ex
+ fun:DH_generate_parameters
+ fun:dh_generate_parameters_nif
+ fun:process_main
+ fun:sched_thread_func
+ fun:thr_wrapper
+}
+{
+ Crypto internal...
+ Memcheck:Cond
+ fun:memset
+ fun:BN_lshift
+ fun:BN_div
+ fun:BN_nnmod
+ fun:BN_mod_inverse
+ fun:BN_MONT_CTX_set
+ fun:BN_is_prime_fasttest_ex
+ fun:BN_generate_prime_ex
+ fun:DH_generate_parameters_ex
+ fun:DH_generate_parameters
+ fun:dh_generate_parameters_nif
+ fun:process_main
+}
+{
+ Crypto internal...
+ Memcheck:Value8
+ fun:BN_mod_exp_mont_consttime
+ fun:generate_key
+ fun:dh_generate_key_nif
+ fun:process_main
+ fun:sched_thread_func
+ fun:thr_wrapper
+ fun:start_thread
+ fun:clone
+}
+
+{
+erts_bits_init_state; Why is this needed?
+Memcheck:Leak
+PossiblyLost
+fun:malloc
+fun:erts_sys_alloc
+...
+fun:erts_alloc
+fun:erts_bits_init_state
+fun:erts_init_scheduling
+fun:erl_init
+fun:erl_start
+fun:main
+}
+
+{
+Prebuilt constant terms in os_info_init
+Memcheck:Leak
+PossiblyLost
+fun:malloc
+fun:erts_sys_alloc
+...
+fun:erts_alloc
+fun:os_info_init
+fun:erts_bif_info_init
+fun:erl_init
+fun:erl_start
+fun:main
+}
diff --git a/erts/emulator/valgrind/suppress.standard b/erts/emulator/valgrind/suppress.standard
new file mode 100644
index 0000000000..d759038c97
--- /dev/null
+++ b/erts/emulator/valgrind/suppress.standard
@@ -0,0 +1,268 @@
+{
+ libc internal error
+ Memcheck:Addr8
+ obj:/lib64/ld-2.3.5.so
+}
+{
+ libc internal error
+ Memcheck:Addr8
+ fun:_dl_start
+}
+{
+ libc internal error
+ Memcheck:Addr8
+ fun:__libc_start_main
+ obj:*
+}
+{
+ libc internal error
+ Memcheck:Addr4
+ fun:__sigjmp_save
+ fun:__libc_start_main
+ obj:*
+}
+{
+ libc internal error
+ Memcheck:Addr8
+ fun:__sigsetjmp
+ fun:__libc_start_main
+ obj:*
+}
+{
+ Intentional error in testcase
+ Memcheck:Param
+ pipe(filedes)
+ fun:pipe
+ fun:chkio_drv_timeout
+}
+{
+ Intentional error in testcase
+ Memcheck:Param
+ pipe(filedes)
+ fun:pipe
+ fun:io_ready_exit_drv_control
+ fun:erts_port_control
+ fun:port_control_3
+ fun:process_main
+}
+{
+ Leak in libc putenv
+ Memcheck:Leak
+ fun:malloc
+ fun:realloc
+ fun:__add_to_environ
+ fun:putenv
+ fun:erts_sys_putenv
+ fun:os_putenv_2
+ fun:process_main
+}
+{
+Leak in libc putenv
+Memcheck:Leak
+fun:malloc
+fun:erts_sys_alloc
+...
+fun:erts_alloc
+fun:erts_sys_putenv
+fun:os_putenv_2
+fun:process_main
+}
+{
+ erronous warning
+ Memcheck:Leak
+ fun:malloc
+ fun:erts_sys_alloc
+ fun:fix_core_alloc
+ fun:erts_init_fix_alloc
+ fun:erts_alloc_init
+ fun:early_init
+ fun:erl_start
+}
+{
+ pthread internal error
+ Memcheck:Param
+ futex(utime)
+ fun:__lll_mutex_unlock_wake
+}
+{
+ libc internal error
+ Memcheck:Param
+ socketcall.sendto(msg)
+ ...
+ fun:getifaddrs
+}
+{
+inet_drv; pointer inside allocated block
+Memcheck:Leak
+fun:realloc
+fun:erts_sys_realloc
+...
+fun:erts_realloc_fnf
+fun:erts_bin_realloc_fnf
+fun:driver_realloc_binary
+}
+{
+inet_drv; pointer inside allocated block
+Memcheck:Leak
+fun:malloc
+fun:erts_sys_alloc
+...
+fun:erts_alloc_fnf
+fun:erts_bin_drv_alloc_fnf
+fun:driver_alloc_binary
+}
+{
+pthread leak or erroneous valgrind warning
+Memcheck:Leak
+fun:calloc
+fun:allocate_dtv
+fun:_dl_allocate_tls
+fun:pthread_create@@GLIBC_2.2.5
+}
+{
+zlib; ok according to zlib developers
+Memcheck:Cond
+fun:longest_match
+fun:deflate_slow
+fun:deflate
+}
+{
+zlib; ok according to zlib developers
+Memcheck:Cond
+fun:longest_match
+fun:deflate_fast
+fun:deflate
+}
+{
+No leak; pointer into block
+Memcheck:Leak
+fun:malloc
+fun:erts_sys_alloc
+...
+fun:erts_alloc
+fun:erts_init_scheduling
+fun:erl_init
+fun:erl_start
+fun:main
+}
+{
+No leak; pointer into block
+Memcheck:Leak
+fun:malloc
+fun:erts_sys_alloc
+...
+fun:erts_alloc
+fun:init_db
+fun:erl_init
+fun:erl_start
+fun:main
+}
+{
+No leak; sometimes pointer into block
+Memcheck:Leak
+fun:malloc
+fun:erts_sys_alloc
+...
+fun:erts_alloc_fnf
+fun:driver_alloc
+fun:get_bufstk
+fun:alloc_buffer
+}
+{
+ Crypto internal...
+Memcheck:Cond
+obj:*/crypto.valgrind.*
+}
+{
+ Crypto internal...
+Memcheck:Cond
+obj:*/libcrypto.*
+}
+{
+ Crypto internal...
+Memcheck:Cond
+obj:*/openssl.*
+}
+{
+ Crypto internal...
+Memcheck:Cond
+obj:*/ssleay.*
+}
+{
+ Crypto internal...
+Memcheck:Value8
+obj:*/crypto.valgrind.*
+}
+{
+ Crypto internal...
+Memcheck:Value8
+obj:*/libcrypto.*
+}
+{
+ Crypto internal...
+Memcheck:Value8
+obj:*/openssl.*
+}
+{
+ Crypto internal...
+Memcheck:Value8
+obj:*/ssleay.*
+}
+{
+ Crypto internal...
+ Memcheck:Cond
+ fun:memset
+ fun:BN_lshift
+ fun:BN_div
+ fun:BN_MONT_CTX_set
+ fun:BN_is_prime_fasttest_ex
+ fun:BN_generate_prime_ex
+ fun:DH_generate_parameters_ex
+ fun:DH_generate_parameters
+ fun:dh_generate_parameters_nif
+ fun:process_main
+ fun:sched_thread_func
+ fun:thr_wrapper
+}
+{
+ Crypto internal...
+ Memcheck:Cond
+ fun:memset
+ fun:BN_lshift
+ fun:BN_div
+ fun:BN_nnmod
+ fun:BN_mod_inverse
+ fun:BN_MONT_CTX_set
+ fun:BN_is_prime_fasttest_ex
+ fun:BN_generate_prime_ex
+ fun:DH_generate_parameters_ex
+ fun:DH_generate_parameters
+ fun:dh_generate_parameters_nif
+ fun:process_main
+}
+{
+ Crypto internal...
+ Memcheck:Value8
+ fun:BN_mod_exp_mont_consttime
+ fun:generate_key
+ fun:dh_generate_key_nif
+ fun:process_main
+ fun:sched_thread_func
+ fun:thr_wrapper
+ fun:start_thread
+ fun:clone
+}
+
+{
+Prebuilt constant terms in os_info_init (PossiblyLost)
+Memcheck:Leak
+fun:malloc
+fun:erts_sys_alloc
+...
+fun:erts_alloc
+fun:os_info_init
+fun:erts_bif_info_init
+fun:erl_init
+fun:erl_start
+fun:main
+}
diff --git a/erts/epmd/src/epmd.c b/erts/epmd/src/epmd.c
index 08576d923f..2267f9b12b 100644
--- a/erts/epmd/src/epmd.c
+++ b/erts/epmd/src/epmd.c
@@ -324,7 +324,11 @@ static void run_daemon(EpmdVars *g)
}
/* move cwd to root to make sure we are not on a mounted filesystem */
- chdir("/");
+ if (chdir("/") < 0)
+ {
+ dbg_perror(g,"epmd: chdir() failed");
+ epmd_cleanup_exit(g,1);
+ }
umask(0);
diff --git a/erts/epmd/src/epmd_cli.c b/erts/epmd/src/epmd_cli.c
index ac55ba6bb6..74408e3ebe 100644
--- a/erts/epmd/src/epmd_cli.c
+++ b/erts/epmd/src/epmd_cli.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2010. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -104,7 +104,10 @@ void epmd_call(EpmdVars *g,int what)
fd = conn_to_epmd(g);
put_int16(1,buf);
buf[2] = what;
- write(fd,buf,3);
+ if (write(fd, buf, 3) != 3) {
+ printf("epmd: Can't write to epmd\n");
+ epmd_cleanup_exit(g,1);
+ }
if (read(fd,(char *)&i,4) != 4) {
if (!g->silent)
printf("epmd: no response from local epmd\n");
diff --git a/erts/epmd/src/epmd_int.h b/erts/epmd/src/epmd_int.h
index 2a0de4df9c..14d05c3f19 100644
--- a/erts/epmd/src/epmd_int.h
+++ b/erts/epmd/src/epmd_int.h
@@ -2,7 +2,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2010. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -240,6 +240,14 @@
#define put_int16(i, s) {((unsigned char*)(s))[0] = ((i) >> 8) & 0xff; \
((unsigned char*)(s))[1] = (i) & 0xff;}
+#if defined(__GNUC__)
+# define EPMD_INLINE __inline__
+#elif defined(__WIN32__)
+# define EPMD_INLINE __inline
+#else
+# define EPMD_INLINE
+#endif
+
/* ************************************************************************ */
/* Stuctures used by server */
@@ -295,6 +303,7 @@ typedef struct {
unsigned delay_write;
int max_conn;
int active_conn;
+ int select_fd_top;
char *progname;
Connection *conn;
Nodes nodes;
diff --git a/erts/epmd/src/epmd_srv.c b/erts/epmd/src/epmd_srv.c
index 4d9b454f97..da575affa1 100644
--- a/erts/epmd/src/epmd_srv.c
+++ b/erts/epmd/src/epmd_srv.c
@@ -80,6 +80,13 @@ static int reply(EpmdVars*,int,char *,int);
static void dbg_print_buf(EpmdVars*,char *,int);
static void print_names(EpmdVars*);
+static EPMD_INLINE void select_fd_set(EpmdVars* g, int fd)
+{
+ FD_SET(fd, &g->orig_read_mask);
+ if (fd >= g->select_fd_top) {
+ g->select_fd_top = fd + 1;
+ }
+}
void run(EpmdVars *g)
{
@@ -95,7 +102,8 @@ void run(EpmdVars *g)
dbg_printf(g,2,"try to initiate listening port %d", g->port);
- if (g->addresses != NULL)
+ if (g->addresses != NULL && /* String contains non-separator characters if: */
+ g->addresses[strspn(g->addresses," ,")] != '\000')
{
char *tmp;
char *token;
@@ -171,6 +179,7 @@ void run(EpmdVars *g)
g->max_conn -= num_sockets;
FD_ZERO(&g->orig_read_mask);
+ g->select_fd_top = 0;
for (i = 0; i < num_sockets; i++)
{
@@ -232,14 +241,14 @@ void run(EpmdVars *g)
dbg_perror(g,"failed to listen on socket");
epmd_cleanup_exit(g,1);
}
- FD_SET(listensock[i],&g->orig_read_mask);
+ select_fd_set(g, listensock[i]);
}
dbg_tty_printf(g,2,"entering the main select() loop");
select_again:
while(1)
- {
+ {
fd_set read_mask = g->orig_read_mask;
struct timeval timeout;
int ret;
@@ -251,7 +260,8 @@ void run(EpmdVars *g)
timeout.tv_sec = (g->packet_timeout < IDLE_TIMEOUT) ? 1 : IDLE_TIMEOUT;
timeout.tv_usec = 0;
- if ((ret = select(g->max_conn,&read_mask,(fd_set *)0,(fd_set *)0,&timeout)) < 0) {
+ if ((ret = select(g->select_fd_top,
+ &read_mask, (fd_set *)0,(fd_set *)0,&timeout)) < 0) {
dbg_perror(g,"error in select ");
switch (errno) {
case EAGAIN:
@@ -821,7 +831,7 @@ static int conn_open(EpmdVars *g,int fd)
s = &g->conn[i];
/* From now on we want to know if there are data to be read */
- FD_SET(fd, &g->orig_read_mask);
+ select_fd_set(g, fd);
s->fd = fd;
s->open = EPMD_TRUE;
@@ -886,6 +896,7 @@ int epmd_conn_close(EpmdVars *g,Connection *s)
dbg_tty_printf(g,2,"closing connection on file descriptor %d",s->fd);
FD_CLR(s->fd,&g->orig_read_mask);
+ /* we don't bother lowering g->select_fd_top */
close(s->fd); /* Sometimes already closed but close anyway */
s->open = EPMD_FALSE;
if (s->buf != NULL) { /* Should never be NULL but test anyway */
@@ -1115,7 +1126,7 @@ static Node *node_reg2(EpmdVars *g,
node->extralen = extralen;
memcpy(node->extra,extra,extralen);
strcpy(node->symname,name);
- FD_SET(fd,&g->orig_read_mask);
+ select_fd_set(g, fd);
if (highvsn == 0) {
dbg_tty_printf(g,1,"registering '%s:%d', port %d",
diff --git a/erts/etc/common/erlc.c b/erts/etc/common/erlc.c
index 35c360a99d..23f009ff4d 100644
--- a/erts/etc/common/erlc.c
+++ b/erts/etc/common/erlc.c
@@ -185,6 +185,7 @@ main(int argc, char** argv)
* Push initial arguments.
*/
+ PUSH("+sbtu");
PUSH("-noinput");
PUSH2("-mode", "minimal");
PUSH2("-boot", "start_clean");
diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c
index 95cb688b29..19b3bb82ef 100644
--- a/erts/etc/common/erlexec.c
+++ b/erts/etc/common/erlexec.c
@@ -67,6 +67,7 @@ static const char plusM_au_allocs[]= {
'C', /* sbmbc_alloc */
'D', /* std_alloc */
'E', /* ets_alloc */
+ 'F', /* fix_alloc */
'H', /* eheap_alloc */
'L', /* ll_alloc */
'R', /* driver_alloc */
@@ -110,8 +111,6 @@ static char *plusM_other_switches[] = {
"Mamcbf",
"Mrmcbf",
"Mmcs",
- "Mcci",
- "Fe",
"Ye",
"Ym",
"Ytp",
diff --git a/erts/etc/win32/Install.c b/erts/etc/win32/Install.c
index 6e60512f6d..d680b67dd6 100644
--- a/erts/etc/win32/Install.c
+++ b/erts/etc/win32/Install.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2003-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2003-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -213,6 +213,9 @@ int main(int argc, char **argv)
fprintf(stderr,"Cannot continue installation, bailing out.\n");
exit(1);
}
+
+ /* OBS!!! If the format of the init file is changed, do not forget
+ to update release_handler:write_ini_file(...) */
ini_file = create_init_file();
ini_section = create_init_section("erlang");
add_init_section(ini_file,ini_section);
diff --git a/erts/etc/win32/erlsrv/erlsrv_interactive.c b/erts/etc/win32/erlsrv/erlsrv_interactive.c
index 13e029b364..736eabac79 100644
--- a/erts/etc/win32/erlsrv/erlsrv_interactive.c
+++ b/erts/etc/win32/erlsrv/erlsrv_interactive.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -135,7 +135,12 @@ void print_last_error(void){
fprintf(stderr,"Error: %s",mes);
LocalFree(mes);
}
-
+
+static int get_last_error(void)
+{
+ return (last_error) ? last_error : GetLastError();
+}
+
static BOOL install_service(void){
SC_HANDLE scm;
SC_HANDLE service;
@@ -508,7 +513,7 @@ int do_usage(char *arg0){
"\t[{-sn[ame] | -n[ame]} [<nodename>]]\n"
"\t[-d[ebugtype] [{new|reuse|console}]]\n"
"\t[-ar[gs] [<limited erl arguments>]]\n\n"
- "%s {start | stop | disable | enable} <servicename>\n\n"
+ "%s {start | start_disabled | stop | disable | enable} <servicename>\n\n"
"%s remove <servicename>\n\n"
"%s rename <servicename> <servicename>\n\n"
"%s list [<servicename>]\n\n"
@@ -561,6 +566,45 @@ int do_manage(int argc,char **argv){
return 0;
}
}
+ if(!_stricmp(action,"start_disabled")){
+ if(!enable_service()){
+ fprintf(stderr,"%s: Failed to enable service %s.\n",
+ argv[0],service_name);
+ print_last_error();
+ return 1;
+ }
+ if(!start_service() && get_last_error() != ERROR_SERVICE_ALREADY_RUNNING){
+ fprintf(stderr,"%s: Failed to start service %s.\n",
+ argv[0],service_name);
+ print_last_error();
+ goto failure_starting;
+ }
+
+ if(!wait_service_trans(SERVICE_STOPPED, SERVICE_START_PENDING,
+ SERVICE_RUNNING, 60)){
+ fprintf(stderr,"%s: Failed to start service %s.\n",
+ argv[0],service_name);
+ print_last_error();
+ goto failure_starting;
+ }
+
+ if(!disable_service()){
+ fprintf(stderr,"%s: Failed to disable service %s.\n",
+ argv[0],service_name);
+ print_last_error();
+ return 1;
+ }
+ printf("%s: Service %s started.\n",
+ argv[0],service_name);
+ return 0;
+ failure_starting:
+ if(!disable_service()){
+ fprintf(stderr,"%s: Failed to disable service %s.\n",
+ argv[0],service_name);
+ print_last_error();
+ }
+ return 1;
+ }
if(!_stricmp(action,"stop")){
if(!stop_service()){
fprintf(stderr,"%s: Failed to stop service %s.\n",
@@ -841,6 +885,7 @@ int do_add_or_set(int argc, char **argv){
argv[0], service_name);
return 0;
}
+
int do_rename(int argc, char **argv){
RegEntry *current = empty_reg_tab();
RegEntry *dummy = empty_reg_tab();
@@ -1129,35 +1174,131 @@ void read_arguments(int *pargc, char ***pargv){
*pargc = argc;
*pargv = argv;
}
+
+/* Create a free-for-all ACL to set on the semaphore */
+PACL get_acl(PSECURITY_DESCRIPTOR secdescp)
+{
+ DWORD acl_length = 0;
+ PSID auth_users_sidp = NULL;
+ PACL aclp = NULL;
+ SID_IDENTIFIER_AUTHORITY ntauth = SECURITY_NT_AUTHORITY;
+
+ if(!InitializeSecurityDescriptor(secdescp, SECURITY_DESCRIPTOR_REVISION)) {
+ return NULL;
+ }
+
+ if(!AllocateAndInitializeSid(&ntauth,
+ 1,
+ SECURITY_AUTHENTICATED_USER_RID,
+ 0, 0, 0, 0, 0, 0, 0,
+ &auth_users_sidp)) {
+ return NULL;
+ }
+
+ acl_length = sizeof(ACL) +
+ sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) +
+ GetLengthSid(auth_users_sidp);
+
+ if((aclp = (PACL) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, acl_length)) == NULL) {
+ FreeSid(auth_users_sidp);
+ return NULL;
+ }
+
+ if(!InitializeAcl(aclp, acl_length, ACL_REVISION)) {
+ FreeSid(auth_users_sidp);
+ HeapFree(GetProcessHeap(), 0, aclp);
+ return NULL;
+ }
+
+ if(!AddAccessAllowedAce(aclp, ACL_REVISION, SEMAPHORE_ALL_ACCESS, auth_users_sidp)) {
+ FreeSid(auth_users_sidp);
+ HeapFree(GetProcessHeap(), 0, aclp);
+ return NULL;
+ }
+
+ if(!SetSecurityDescriptorDacl(secdescp, TRUE, aclp, FALSE)) {
+ FreeSid(auth_users_sidp);
+ HeapFree(GetProcessHeap(), 0, aclp);
+ return NULL;
+ }
+ return aclp;
+}
+
+static HANDLE lock_semaphore = NULL;
+
+int take_lock(void) {
+ SECURITY_ATTRIBUTES attr;
+ PACL aclp;
+ SECURITY_DESCRIPTOR secdesc;
+
+ if ((aclp = get_acl(&secdesc)) == NULL) {
+ return -1;
+ }
+
+ memset(&attr,0,sizeof(attr));
+ attr.nLength = sizeof(attr);
+ attr.lpSecurityDescriptor = &secdesc;
+ attr.bInheritHandle = FALSE;
+
+ if ((lock_semaphore = CreateSemaphore(&attr, 1, 1, ERLSRV_INTERACTIVE_GLOBAL_SEMAPHORE)) == NULL) {
+ return -1;
+ }
+
+ if (WaitForSingleObject(lock_semaphore,INFINITE) != WAIT_OBJECT_0) {
+ return -1;
+ }
+
+ HeapFree(GetProcessHeap(), 0, aclp);
+ return 0;
+}
+
+void release_lock(void) {
+ ReleaseSemaphore(lock_semaphore,1,NULL);
+}
+
int interactive_main(int argc, char **argv){
char *action = argv[1];
-
+ int res;
+
+ if (take_lock() != 0) {
+ fprintf(stderr,"%s: unable to acquire global lock (%s).\n",argv[0],
+ ERLSRV_INTERACTIVE_GLOBAL_SEMAPHORE);
+ return 1;
+ }
+
if(!_stricmp(action,"readargs")){
- read_arguments(&argc,&argv);
- action = argv[1];
+ read_arguments(&argc,&argv);
+ action = argv[1];
}
if(!_stricmp(action,"set") || !_stricmp(action,"add"))
- return do_add_or_set(argc,argv);
- if(!_stricmp(action,"rename"))
- return do_rename(argc,argv);
- if(!_stricmp(action,"remove"))
- return do_remove(argc,argv);
- if(!_stricmp(action,"list"))
- return do_list(argc,argv);
- if(!_stricmp(action,"start") ||
- !_stricmp(action,"stop") ||
- !_stricmp(action,"enable") ||
- !_stricmp(action,"disable"))
- return do_manage(argc,argv);
- if(_stricmp(action,"?") &&
- _stricmp(action,"/?") &&
- _stricmp(action,"-?") &&
- *action != 'h' &&
- *action != 'H')
+ res = do_add_or_set(argc,argv);
+ else if(!_stricmp(action,"rename"))
+ res = do_rename(argc,argv);
+ else if(!_stricmp(action,"remove"))
+ res = do_remove(argc,argv);
+ else if(!_stricmp(action,"list"))
+ res = do_list(argc,argv);
+ else if(!_stricmp(action,"start") ||
+ !_stricmp(action,"start_disabled") ||
+ !_stricmp(action,"stop") ||
+ !_stricmp(action,"enable") ||
+ !_stricmp(action,"disable"))
+ res = do_manage(argc,argv);
+ else if(_stricmp(action,"?") &&
+ _stricmp(action,"/?") &&
+ _stricmp(action,"-?") &&
+ *action != 'h' &&
+ *action != 'H') {
fprintf(stderr,"%s: action %s not implemented.\n",argv[0],action);
- do_usage(argv[0]);
- return 1;
+ do_usage(argv[0]);
+ res = 1;
+ } else {
+ do_usage(argv[0]);
+ res = 0;
+ }
+ release_lock();
+ return res;
}
diff --git a/erts/etc/win32/erlsrv/erlsrv_interactive.h b/erts/etc/win32/erlsrv/erlsrv_interactive.h
index deacf81899..23e69e508d 100644
--- a/erts/etc/win32/erlsrv/erlsrv_interactive.h
+++ b/erts/etc/win32/erlsrv/erlsrv_interactive.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -19,6 +19,8 @@
#ifndef _ERLSRV_INTERACTIVE_H
#define _ERLSRV_INTERACTIVE_H
+#define ERLSRV_INTERACTIVE_GLOBAL_SEMAPHORE "{468d6954-e355-415f-968f-d257cb0feef4}"
+
int interactive_main(int argc, char **argv);
#endif /* _ERLSRV_INTERACTIVE_H */
diff --git a/erts/etc/win32/nsis/erlang_uninst.ico b/erts/etc/win32/nsis/erlang_uninst.ico
index edbd8a6f2c..edbd8a6f2c 100755..100644
--- a/erts/etc/win32/nsis/erlang_uninst.ico
+++ b/erts/etc/win32/nsis/erlang_uninst.ico
Binary files differ
diff --git a/erts/etc/win32/start_erl.c b/erts/etc/win32/start_erl.c
index dcf8c8b281..28c8e55bd3 100644
--- a/erts/etc/win32/start_erl.c
+++ b/erts/etc/win32/start_erl.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -44,6 +44,8 @@ char *progname;
#endif
#define RELEASE_SUBDIR "\\releases"
+#define ERTS_SUBDIR_PREFIX "\\erts-"
+#define BIN_SUBDIR "\\bin"
#define REGISTRY_BASE "Software\\Ericsson\\Erlang\\"
#define DEFAULT_DATAFILE "start_erl.data"
@@ -101,7 +103,8 @@ void exit_help(char *err)
printf("Usage:\n%s\n"
" [<erlang options>] ++\n"
" [-data <datafile>]\n"
- " [-reldir <releasedir>]\n"
+ " {-rootdir <erlang root directory> | \n"
+ " -reldir <releasedir>}\n"
" [-bootflags <bootflagsfile>]\n"
" [-noconfig]\n", progname);
@@ -177,8 +180,9 @@ void split_commandline(void)
*/
char * unquote_optionarg(char *str, char **strp)
{
- char *newstr = (char *)malloc(strlen(str)+1); /* This one is realloc:ed later */
- int i=0, inquote=0;
+ char *newstr = (char *)malloc(strlen(str)+1); /* This one is
+ realloc:ed later */
+ int i = 0, inquote = 0;
assert(newstr);
assert(str);
@@ -223,8 +227,8 @@ char * unquote_optionarg(char *str, char **strp)
/*
- * Parses MyCommandLine and tries to fill in all the required option variables
- * (one way or another).
+ * Parses MyCommandLine and tries to fill in all the required option
+ * variables (in one way or another).
*/
void parse_commandline(void)
{
@@ -237,6 +241,11 @@ void parse_commandline(void)
*cmdline++;
if( strnicmp(cmdline, "data", 4) == 0) {
DataFileName = unquote_optionarg(cmdline+4, &cmdline);
+ } else if( strnicmp(cmdline, "rootdir", 7) == 0) {
+ RootDir = unquote_optionarg(cmdline+7, &cmdline);
+#ifdef _DEBUG
+ fprintf(stderr, "RootDir: '%s'\n", RootDir);
+#endif
} else if( strnicmp(cmdline, "reldir", 6) == 0) {
RelDir = unquote_optionarg(cmdline+6, &cmdline);
#ifdef _DEBUG
@@ -266,8 +275,8 @@ void parse_commandline(void)
* Read the data file specified and get the version and release number
* from it.
*
- * This function also construct the correct RegistryKey from the version information
- * retrieved.
+ * This function also construct the correct RegistryKey from the version
+ * information retrieved.
*/
void read_datafile(void)
{
@@ -325,88 +334,6 @@ void read_datafile(void)
/*
- * Read the registry keys we need
- */
-void read_registry_keys(void)
-{
- HKEY hReg;
- ULONG lLen;
-
- /* Create the RegistryKey name */
- RegistryKey = (char *) malloc(strlen(REGISTRY_BASE) +
- strlen(Version) + 1);
- assert(RegistryKey);
- sprintf(RegistryKey, REGISTRY_BASE "%s", Version);
-
- /* We always need to find BinDir */
- if( (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- RegistryKey,
- 0,
- KEY_READ,
- &hReg)) != ERROR_SUCCESS ) {
- exit_help("Could not open registry key.");
- }
-
- /* First query size of data */
- if( (RegQueryValueEx(hReg,
- "Bindir",
- NULL,
- NULL,
- NULL,
- &lLen)) != ERROR_SUCCESS) {
- exit_help("Failed to query BinDir of release.\n");
- }
-
- /* Allocate enough space */
- BinDir = (char *)malloc(lLen+1);
- assert(BinDir);
- /* Retrieve the value */
- if( (RegQueryValueEx(hReg,
- "Bindir",
- NULL,
- NULL,
- (unsigned char *) BinDir,
- &lLen)) != ERROR_SUCCESS) {
- exit_help("Failed to query BinDir of release (2).\n");
- }
-
-#ifdef _DEBUG
- fprintf(stderr, "Bindir: '%s'\n", BinDir);
-#endif
-
- /* We also need the rootdir, in case we need to build RelDir later */
-
- /* First query size of data */
- if( (RegQueryValueEx(hReg,
- "Rootdir",
- NULL,
- NULL,
- NULL,
- &lLen)) != ERROR_SUCCESS) {
- exit_help("Failed to query RootDir of release.\n");
- }
-
- /* Allocate enough space */
- RootDir = (char *) malloc(lLen+1);
- assert(RootDir);
- /* Retrieve the value */
- if( (RegQueryValueEx(hReg,
- "Rootdir",
- NULL,
- NULL,
- (unsigned char *) RootDir,
- &lLen)) != ERROR_SUCCESS) {
- exit_help("Failed to query RootDir of release (2).\n");
- }
-
-#ifdef _DEBUG
- fprintf(stderr, "Rootdir: '%s'\n", RootDir);
-#endif
-
- RegCloseKey(hReg);
-}
-
-/*
* Read the bootflags. This file contains extra command line options to erl.exe
*/
void read_bootflags(void)
@@ -424,7 +351,8 @@ void read_bootflags(void)
exit_help("Need -reldir when -bootflags "
"filename has relative path.");
} else {
- newname = (char *)malloc(strlen(BootFlagsFile)+strlen(RelDir)+strlen(Release)+3);
+ newname = (char *)malloc(strlen(BootFlagsFile)+
+ strlen(RelDir)+strlen(Release)+3);
assert(newname);
sprintf(newname, "%s\\%s\\%s", RelDir, Release, BootFlagsFile);
free(BootFlagsFile);
@@ -436,8 +364,6 @@ void read_bootflags(void)
fprintf(stderr, "BootFlagsFile: '%s'\n", BootFlagsFile);
#endif
-
-
if( (fp=fopen(BootFlagsFile, "rb")) == NULL) {
exit_help("Could not open BootFlags file.");
}
@@ -605,32 +531,49 @@ void complete_options(void)
sz = nsz;
}
if (RelDir == NULL) {
- if(DataFileName){
- /* Needs to be absolute for this to work, but we
- can try... */
- read_datafile();
- read_registry_keys();
- } else {
- /* Impossible to find all data... */
- exit_help("Need either Release directory or an absolute "
- "datafile name.");
- }
- /* Ok, construct our own RelDir from RootDir */
- RelDir = (char *) malloc(strlen(RootDir)+strlen(RELEASE_SUBDIR)+1);
- assert(RelDir);
- sprintf(RelDir, "%s" RELEASE_SUBDIR, RootDir);
+ if (!RootDir) {
+ /* Impossible to find all data... */
+ exit_help("Need either Root directory nor Release directory.");
+ }
+ /* Ok, construct our own RelDir from RootDir */
+ RelDir = (char *) malloc(strlen(RootDir)+strlen(RELEASE_SUBDIR)+1);
+ assert(RelDir);
+ sprintf(RelDir, "%s" RELEASE_SUBDIR, RootDir);
+ read_datafile();
} else {
read_datafile();
- read_registry_keys();
}
} else {
read_datafile();
- read_registry_keys();
}
+ if( !RootDir ) {
+ /* Try to construct RootDir from RelDir */
+ char *p;
+ RootDir = malloc(strlen(RelDir)+1);
+ strcpy(RootDir,RelDir);
+ p = RootDir+strlen(RootDir)-1;
+ if (p >= RootDir && (*p == '/' || *p == '\\'))
+ --p;
+ while (p >= RootDir && *p != '/' && *p != '\\')
+ --p;
+ if (p <= RootDir) { /* Empty RootDir is also an error */
+ exit_help("Cannot determine Root directory from "
+ "Release directory.");
+ }
+ *p = '\0';
+ }
+
+
+ BinDir = (char *) malloc(strlen(RootDir)+strlen(ERTS_SUBDIR_PREFIX)+
+ strlen(Version)+strlen(BIN_SUBDIR)+1);
+ assert(BinDir);
+ sprintf(BinDir, "%s" ERTS_SUBDIR_PREFIX "%s" BIN_SUBDIR, RootDir, Version);
+
read_bootflags();
#ifdef _DEBUG
fprintf(stderr, "RelDir: '%s'\n", RelDir);
+ fprintf(stderr, "BinDir: '%s'\n", BinDir);
#endif
}
diff --git a/erts/example/matrix_nif.c b/erts/example/matrix_nif.c
index c5e01dade5..404329e36c 100644
--- a/erts/example/matrix_nif.c
+++ b/erts/example/matrix_nif.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -31,7 +31,19 @@ typedef struct
unsigned nrows;
unsigned ncols;
double* data;
-}Matrix;
+} Matrix;
+
+/*
+ * Use a union for pointer type conversion to avoid compiler warnings
+ * about strict-aliasing violations with gcc-4.1. gcc >= 4.2 does not
+ * emit the warning.
+ * TODO: Reconsider use of union once gcc-4.1 is obsolete?
+ */
+typedef union
+{
+ void* vp;
+ Matrix* p;
+} mx_t;
#define POS(MX, ROW, COL) ((MX)->data[(ROW)* (MX)->ncols + (COL)])
@@ -44,8 +56,9 @@ static ErlNifResourceType* resource_type = NULL;
static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
{
- ErlNifResourceType* rt = enif_open_resource_type(env, "matrix_nif_example",
- matrix_dtor,
+ ErlNifResourceType* rt = enif_open_resource_type(env, NULL,
+ "matrix_nif_example",
+ matrix_dtor,
ERL_NIF_RT_CREATE, NULL);
if (rt == NULL) {
return -1;
@@ -90,12 +103,12 @@ static ERL_NIF_TERM create(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
}
ret = enif_make_resource(env, mx);
- enif_release_resource(env, mx);
+ enif_release_resource(mx);
return ret;
badarg:
if (mx != NULL) {
- enif_release_resource(env,mx);
+ enif_release_resource(mx);
}
return enif_make_badarg(env);
}
@@ -104,14 +117,14 @@ badarg:
static ERL_NIF_TERM pos(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
/* pos(Matrix, Row, Column) -> float() */
- Matrix* mx;
+ mx_t mx;
unsigned i, j;
- if (!enif_get_resource(env, argv[0], resource_type, (void**)&mx) ||
- !enif_get_uint(env, argv[1], &i) || (--i >= mx->nrows) ||
- !enif_get_uint(env, argv[2], &j) || (--j >= mx->ncols)) {
+ if (!enif_get_resource(env, argv[0], resource_type, &mx.vp) ||
+ !enif_get_uint(env, argv[1], &i) || (--i >= mx.p->nrows) ||
+ !enif_get_uint(env, argv[2], &j) || (--j >= mx.p->ncols)) {
return enif_make_badarg(env);
}
- return enif_make_double(env, POS(mx, i,j));
+ return enif_make_double(env, POS(mx.p, i,j));
}
static ERL_NIF_TERM add(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -119,37 +132,38 @@ static ERL_NIF_TERM add(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
/* add(Matrix_A, Matrix_B) -> Matrix_Sum */
unsigned i, j;
ERL_NIF_TERM ret;
- Matrix* mxA = NULL;
- Matrix* mxB = NULL;
- Matrix* mxS = NULL;
+ mx_t mxA, mxB, mxS;
+ mxA.p = NULL;
+ mxB.p = NULL;
+ mxS.p = NULL;
- if (!enif_get_resource(env, argv[0], resource_type, (void**)&mxA) ||
- !enif_get_resource(env, argv[1], resource_type, (void**)&mxB) ||
- mxA->nrows != mxB->nrows ||
- mxB->ncols != mxB->ncols) {
+ if (!enif_get_resource(env, argv[0], resource_type, &mxA.vp) ||
+ !enif_get_resource(env, argv[1], resource_type, &mxB.vp) ||
+ mxA.p->nrows != mxB.p->nrows ||
+ mxB.p->ncols != mxB.p->ncols) {
return enif_make_badarg(env);
}
- mxS = alloc_matrix(env, mxA->nrows, mxA->ncols);
- for (i = 0; i < mxA->nrows; i++) {
- for (j = 0; j < mxA->ncols; j++) {
- POS(mxS, i, j) = POS(mxA, i, j) + POS(mxB, i, j);
+ mxS.p = alloc_matrix(env, mxA.p->nrows, mxA.p->ncols);
+ for (i = 0; i < mxA.p->nrows; i++) {
+ for (j = 0; j < mxA.p->ncols; j++) {
+ POS(mxS.p, i, j) = POS(mxA.p, i, j) + POS(mxB.p, i, j);
}
}
- ret = enif_make_resource(env, mxS);
- enif_release_resource(env, mxS);
+ ret = enif_make_resource(env, mxS.p);
+ enif_release_resource(mxS.p);
return ret;
}
static ERL_NIF_TERM size_of(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
/* size(Matrix) -> {Nrows, Ncols} */
- Matrix* mx;
- if (!enif_get_resource(env, argv[0], resource_type, (void**)&mx)) {
+ mx_t mx;
+ if (!enif_get_resource(env, argv[0], resource_type, &mx.vp)) {
return enif_make_badarg(env);
}
- return enif_make_tuple2(env, enif_make_uint(env, mx->nrows),
- enif_make_uint(env, mx->ncols));
+ return enif_make_tuple2(env, enif_make_uint(env, mx.p->nrows),
+ enif_make_uint(env, mx.p->ncols));
}
static ERL_NIF_TERM to_term(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -157,16 +171,17 @@ static ERL_NIF_TERM to_term(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
/* to_term(Matrix) -> [[first row], [second row], ...,[last row]] */
unsigned i, j;
ERL_NIF_TERM res;
- Matrix* mx = NULL;
+ mx_t mx;
+ mx.p = NULL;
- if (!enif_get_resource(env, argv[0], resource_type, (void**)&mx)) {
+ if (!enif_get_resource(env, argv[0], resource_type, &mx.vp)) {
return enif_make_badarg(env);
}
res = enif_make_list(env, 0);
- for (i = mx->nrows; i-- > 0; ) {
+ for (i = mx.p->nrows; i-- > 0; ) {
ERL_NIF_TERM row = enif_make_list(env, 0);
- for (j = mx->ncols; j-- > 0; ) {
- row = enif_make_list_cell(env, enif_make_double(env, POS(mx,i,j)),
+ for (j = mx.p->ncols; j-- > 0; ) {
+ row = enif_make_list_cell(env, enif_make_double(env, POS(mx.p,i,j)),
row);
}
res = enif_make_list_cell(env, row, res);
@@ -183,17 +198,17 @@ static int get_number(ErlNifEnv* env, ERL_NIF_TERM term, double* dp)
static Matrix* alloc_matrix(ErlNifEnv* env, unsigned nrows, unsigned ncols)
{
- Matrix* mx = enif_alloc_resource(env, resource_type, sizeof(Matrix));
+ Matrix* mx = enif_alloc_resource(resource_type, sizeof(Matrix));
mx->nrows = nrows;
mx->ncols = ncols;
- mx->data = enif_alloc(env, nrows*ncols*sizeof(double));
+ mx->data = enif_alloc(nrows*ncols*sizeof(double));
return mx;
}
static void matrix_dtor(ErlNifEnv* env, void* obj)
{
Matrix* mx = (Matrix*) obj;
- enif_free(env, mx->data);
+ enif_free(mx->data);
mx->data = NULL;
}
diff --git a/erts/include/internal/ethr_atomics.h b/erts/include/internal/ethr_atomics.h
index 1caf4d0567..0f3c26f1df 100644
--- a/erts/include/internal/ethr_atomics.h
+++ b/erts/include/internal/ethr_atomics.h
@@ -1,7 +1,16 @@
/*
+ * --------------- DO NOT EDIT THIS FILE! ---------------
+ * This file was automatically generated by the
+ * $ERL_TOP/erts/lib_src/utils/make_atomics_api script.
+ * If you need to make changes, edit the script and
+ * regenerate this file.
+ * --------------- DO NOT EDIT THIS FILE! ---------------
+ */
+
+/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010. All Rights Reserved.
+ * Copyright Ericsson AB 2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -18,709 +27,8818 @@
*/
/*
- * Description: The ethread atomic API
+ * Description: The ethread atomics API
* Author: Rickard Green
*/
-#ifndef ETHR_ATOMIC_H__
-#define ETHR_ATOMIC_H__
+/*
+ * This file maps native atomic implementations to ethread
+ * API atomics. If no native atomic implementation
+ * is available, a less efficient fallback is used instead.
+ * The API consists of 32-bit size, word size (pointer size),
+ * and double word size atomics.
+ *
+ * The following atomic operations are implemented for
+ * 32-bit size, and word size atomics:
+ * - cmpxchg
+ * - xchg
+ * - set
+ * - init
+ * - add_read
+ * - read
+ * - inc_read
+ * - dec_read
+ * - add
+ * - inc
+ * - dec
+ * - read_band
+ * - read_bor
+ *
+ * The following atomic operations are implemented for
+ * double word size atomics:
+ * - cmpxchg
+ * - set
+ * - read
+ * - init
+ *
+ * Appart from a function implementing the atomic operation
+ * with unspecified memory barrier semantics, there are
+ * functions implementing each operation with the following
+ * memory barrier semantics:
+ * - rb (read barrier)
+ * - wb (write barrier)
+ * - acqb (acquire barrier)
+ * - relb (release barrier)
+ * - mb (full memory barrier)
+ *
+ * We implement all of these operation/barrier
+ * combinations, regardless of whether they are useful
+ * or not (some of them are useless).
+ *
+ * Double word size atomic functions are on the followning
+ * form:
+ * ethr_dw_atomic_<OP>[_<BARRIER>]
+ *
+ * Word size atomic functions are on the followning
+ * form:
+ * ethr_atomic_<OP>[_<BARRIER>]
+ *
+ * 32-bit size atomic functions are on the followning
+ * form:
+ * ethr_atomic32_<OP>[_<BARRIER>]
+ *
+ * Apart from the operation/barrier functions
+ * described above also 'addr' functions are implemented
+ * which return the actual memory address used of the
+ * atomic variable. The 'addr' functions have no barrier
+ * versions.
+ *
+ * The native atomic implementation does not need to
+ * implement all operation/barrier combinations.
+ * Functions that have no native implementation will be
+ * constructed from existing native functionality. These
+ * functions will perform the wanted operation and will
+ * produce sufficient memory barriers, but may
+ * in some cases be less efficient than pure native
+ * versions.
+ *
+ * When we create ethread API operation/barrier functions by
+ * adding barriers before and after native operations it is
+ * assumed that:
+ * - A native read operation begins, and ends with a load.
+ * - A native set operation begins, and ends with a store.
+ * - An init operation begins with either a load, or a store,
+ * and ends with either a load, or a store.
+ * - All other operations begins with a load, and ends with
+ * either a load, or a store.
+ *
+ * This is the minimum functionality that a native
+ * implementation needs to provide:
+ *
+ * - Functions that need to be implemented:
+ *
+ * - ethr_native_[dw_|su_dw_]atomic[BITS]_addr
+ * - ethr_native_[dw_|su_dw_]atomic[BITS]_cmpxchg[_<BARRIER>]
+ * (at least one cmpxchg of optional barrier)
+ *
+ * - Macros that needs to be defined:
+ *
+ * A macro informing about the presence of the native
+ * implementation:
+ *
+ * - ETHR_HAVE_NATIVE_[DW_|SU_DW_]ATOMIC[BITS]
+ *
+ * A macro naming (a string constant) the implementation:
+ *
+ * - ETHR_NATIVE_[DW_]ATOMIC[BITS]_IMPL
+ *
+ * Each implemented native atomic function has to
+ * be accompanied by a defined macro on the following
+ * form informing about its presence:
+ *
+ * - ETHR_HAVE_ETHR_NATIVE_[DW_|SU_DW_]ATOMIC[BITS]_<OP>[_<BARRIER>]
+ *
+ * A (sparc-v9 style) membar macro:
+ *
+ * - ETHR_MEMBAR(B)
+ *
+ * Which takes a combination of the following macros
+ * or:ed (using |) together:
+ *
+ * - ETHR_LoadLoad
+ * - ETHR_LoadStore
+ * - ETHR_StoreLoad
+ * - ETHR_StoreStore
+ *
+ */
-#if !defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_ATOMIC_IMPL__)
-# define ETHR_NEED_ATOMIC_PROTOTYPES__
-#endif
+#ifndef ETHR_ATOMICS_H__
+#define ETHR_ATOMICS_H__
-#ifndef ETHR_HAVE_NATIVE_ATOMICS
+#undef ETHR_AMC_FALLBACK__
+#undef ETHR_AMC_NO_ATMCS__
+#undef ETHR_AMC_ATMC_T__
+#undef ETHR_AMC_ATMC_FUNC__
+
+/* -- 32-bit atomics -- */
+
+#undef ETHR_NAINT32_T__
+#undef ETHR_NATMC32_FUNC__
+#undef ETHR_NATMC32_ADDR_FUNC__
+#undef ETHR_NATMC32_BITS__
+#if defined(ETHR_HAVE_NATIVE_ATOMIC32)
+# define ETHR_NEED_NATMC32_ADDR
+# define ETHR_NATMC32_ADDR_FUNC__ ethr_native_atomic32_addr
+typedef ethr_native_atomic32_t ethr_atomic32_t;
+# define ETHR_NAINT32_T__ ethr_sint32_t
+# define ETHR_NATMC32_FUNC__(X) ethr_native_atomic32_ ## X
+# define ETHR_NATMC32_BITS__ 32
+#elif defined(ETHR_HAVE_NATIVE_ATOMIC64)
+# define ETHR_NEED_NATMC64_ADDR
+#ifdef ETHR_BIGENDIAN
+# define ETHR_NATMC32_ADDR_FUNC__(VAR) \
+ (((ethr_sint32_t *) ethr_native_atomic64_addr((VAR))) + 1)
+#else
+# define ETHR_NATMC32_ADDR_FUNC__(VAR) \
+ ((ethr_sint32_t *) ethr_native_atomic64_addr((VAR)))
+#endif
+typedef ethr_native_atomic64_t ethr_atomic32_t;
+# define ETHR_NAINT32_T__ ethr_sint64_t
+# define ETHR_NATMC32_FUNC__(X) ethr_native_atomic64_ ## X
+# define ETHR_NATMC32_BITS__ 64
+#else
/*
- * No native atomic implementation available. :(
+ * No native atomics usable for 32-bits atomics :(
* Use fallback...
*/
typedef ethr_sint32_t ethr_atomic32_t;
-typedef ethr_sint_t ethr_atomic_t;
-#else
-/*
- * Map ethread native atomics to ethread API atomics.
- *
- * We do at least have a native atomic implementation that
- * can handle integers of a size larger than or equal to
- * the size of pointers.
- */
+#endif
-/* -- Pointer size atomics -- */
+#undef ETHR_ATMC32_INLINE__
+#ifdef ETHR_NATMC32_BITS__
+# ifdef ETHR_TRY_INLINE_FUNCS
+# define ETHR_ATMC32_INLINE__
+# endif
+# define ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS
+#endif
+
+#if !defined(ETHR_ATMC32_INLINE__) || defined(ETHR_ATOMIC_IMPL__)
+# define ETHR_NEED_ATMC32_PROTOTYPES__
+#endif
+
+#ifndef ETHR_INLINE_ATMC32_FUNC_NAME_
+# define ETHR_INLINE_ATMC32_FUNC_NAME_(X) X
+#endif
+
+#undef ETHR_ATMC32_FUNC__
+#define ETHR_ATMC32_FUNC__(X) ETHR_INLINE_ATMC32_FUNC_NAME_(ethr_atomic32_ ## X)
+
+
+/* -- Word size atomics -- */
+
+#undef ETHR_NEED_NATMC32_ADDR
+#undef ETHR_NEED_NATMC64_ADDR
#undef ETHR_NAINT_T__
#undef ETHR_NATMC_FUNC__
#undef ETHR_NATMC_ADDR_FUNC__
-#if ETHR_SIZEOF_PTR == 8
-# if defined(ETHR_HAVE_NATIVE_ATOMIC64)
-# define ETHR_NATMC_ADDR_FUNC__ ethr_native_atomic64_addr
+#undef ETHR_NATMC_BITS__
+#if ETHR_SIZEOF_PTR == 8 && defined(ETHR_HAVE_NATIVE_ATOMIC64)
+# ifndef ETHR_NEED_NATMC64_ADDR
+# define ETHR_NEED_NATMC64_ADDR
+# endif
+# define ETHR_NATMC_ADDR_FUNC__ ethr_native_atomic64_addr
typedef ethr_native_atomic64_t ethr_atomic_t;
-# define ETHR_NAINT_T__ ethr_sint64_t
-# define ETHR_NATMC_FUNC__(X) ethr_native_atomic64_ ## X
-# else
-# error "Missing native atomic implementation"
+# define ETHR_NAINT_T__ ethr_sint64_t
+# define ETHR_NATMC_FUNC__(X) ethr_native_atomic64_ ## X
+# define ETHR_NATMC_BITS__ 64
+#elif ETHR_SIZEOF_PTR == 4 && defined(ETHR_HAVE_NATIVE_ATOMIC32)
+# ifndef ETHR_NEED_NATMC64_ADDR
+# define ETHR_NEED_NATMC32_ADDR
# endif
-#elif ETHR_SIZEOF_PTR == 4
# define ETHR_NATMC_ADDR_FUNC__ ethr_native_atomic32_addr
-# ifdef ETHR_HAVE_NATIVE_ATOMIC32
typedef ethr_native_atomic32_t ethr_atomic_t;
-# define ETHR_NAINT_T__ ethr_sint32_t
-# define ETHR_NATMC_FUNC__(X) ethr_native_atomic32_ ## X
-# elif defined(ETHR_HAVE_NATIVE_ATOMIC64)
+# define ETHR_NAINT_T__ ethr_sint32_t
+# define ETHR_NATMC_FUNC__(X) ethr_native_atomic32_ ## X
+# define ETHR_NATMC_BITS__ 32
+#elif ETHR_SIZEOF_PTR == 4 && defined(ETHR_HAVE_NATIVE_ATOMIC64)
+# ifndef ETHR_NEED_NATMC64_ADDR
+# define ETHR_NEED_NATMC64_ADDR
+# endif
+#ifdef ETHR_BIGENDIAN
+# define ETHR_NATMC_ADDR_FUNC__(VAR) \
+ (((ethr_sint32_t *) ethr_native_atomic64_addr((VAR))) + 1)
+#else
+# define ETHR_NATMC_ADDR_FUNC__(VAR) \
+ ((ethr_sint32_t *) ethr_native_atomic64_addr((VAR)))
+#endif
typedef ethr_native_atomic64_t ethr_atomic_t;
-# define ETHR_NATMC_T__ ethr_native_atomic64_t
-# define ETHR_NAINT_T__ ethr_sint64_t
-# define ETHR_NATMC_FUNC__(X) ethr_native_atomic64_ ## X
+# define ETHR_NATMC_T__ ethr_native_atomic64_t
+# define ETHR_NAINT_T__ ethr_sint64_t
+# define ETHR_NATMC_FUNC__(X) ethr_native_atomic64_ ## X
+# define ETHR_NATMC_BITS__ 64
+#else
+/*
+ * No native atomics usable for pointer size atomics :(
+ * Use fallback...
+ */
+
+# if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+# define ETHR_AMC_FALLBACK__
+# define ETHR_AMC_NO_ATMCS__ 2
+# define ETHR_AMC_SINT_T__ ethr_sint32_t
+# define ETHR_AMC_ATMC_T__ ethr_atomic32_t
+# define ETHR_AMC_ATMC_FUNC__(X) ETHR_INLINE_ATMC32_FUNC_NAME_(ethr_atomic32_ ## X)
+typedef struct {
+ ETHR_AMC_ATMC_T__ atomic[ETHR_AMC_NO_ATMCS__];
+} ethr_amc_t;
+typedef struct {
+ ethr_amc_t amc;
+ ethr_sint_t sint;
+} ethr_atomic_t;
+# else /* locked fallback */
+typedef ethr_sint_t ethr_atomic_t;
+# endif
+#endif
+
+#undef ETHR_ATMC_INLINE__
+#ifdef ETHR_NATMC_BITS__
+# ifdef ETHR_TRY_INLINE_FUNCS
+# define ETHR_ATMC_INLINE__
+# endif
+# define ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS
+#endif
+
+#if !defined(ETHR_ATMC_INLINE__) || defined(ETHR_ATOMIC_IMPL__)
+# define ETHR_NEED_ATMC_PROTOTYPES__
+#endif
+
+#ifndef ETHR_INLINE_ATMC_FUNC_NAME_
+# define ETHR_INLINE_ATMC_FUNC_NAME_(X) X
+#endif
+
+#undef ETHR_ATMC_FUNC__
+#define ETHR_ATMC_FUNC__(X) ETHR_INLINE_ATMC_FUNC_NAME_(ethr_atomic_ ## X)
+
+/* -- Double word atomics -- */
+
+#undef ETHR_SU_DW_NAINT_T__
+#undef ETHR_SU_DW_NATMC_FUNC__
+#undef ETHR_SU_DW_NATMC_ADDR_FUNC__
+#undef ETHR_DW_NATMC_FUNC__
+#undef ETHR_DW_NATMC_ADDR_FUNC__
+#undef ETHR_DW_NATMC_BITS__
+#if defined(ETHR_HAVE_NATIVE_DW_ATOMIC) || defined(ETHR_HAVE_NATIVE_SU_DW_ATOMIC)
+# define ETHR_NEED_DW_NATMC_ADDR
+# define ETHR_DW_NATMC_ADDR_FUNC__ ethr_native_dw_atomic_addr
+# define ETHR_NATIVE_DW_ATOMIC_T__ ethr_native_dw_atomic_t
+# define ETHR_DW_NATMC_FUNC__(X) ethr_native_dw_atomic_ ## X
+# define ETHR_SU_DW_NATMC_FUNC__(X) ethr_native_su_dw_atomic_ ## X
+# if ETHR_SIZEOF_PTR == 8
+# define ETHR_DW_NATMC_BITS__ 128
+# elif ETHR_SIZEOF_PTR == 4
+# define ETHR_DW_NATMC_BITS__ 64
# else
-# error "Missing native atomic implementation"
+# error "Word size not supported"
+# endif
+# ifdef ETHR_NATIVE_SU_DW_SINT_T
+# define ETHR_SU_DW_NAINT_T__ ETHR_NATIVE_SU_DW_SINT_T
# endif
+#elif ETHR_SIZEOF_PTR == 4 && defined(ETHR_HAVE_NATIVE_ATOMIC64)
+# define ETHR_HAVE_NATIVE_SU_DW_ATOMIC
+# ifndef ETHR_NEED_NATMC64_ADDR
+# define ETHR_NEED_NATMC64_ADDR
+# endif
+# define ETHR_DW_NATMC_ADDR_FUNC__(VAR) \
+ ((ethr_dw_sint_t *) ethr_native_atomic64_addr((VAR)))
+# define ETHR_NATIVE_DW_ATOMIC_T__ ethr_native_atomic64_t
+# define ETHR_SU_DW_NAINT_T__ ethr_sint64_t
+# define ETHR_SU_DW_NATMC_FUNC__(X) ethr_native_atomic64_ ## X
+# define ETHR_DW_NATMC_BITS__ 64
#endif
-/* -- 32-bit atomics -- */
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+#define ETHR_DW_ATOMIC_FUNC__(X) ethr_dw_atomic_ ## X ## _fallback__
+#else
+#define ETHR_DW_ATOMIC_FUNC__(X) ethr_dw_atomic_ ## X
+#endif
-#undef ETHR_NAINT32_T__
-#undef ETHR_NATMC32_FUNC__
-#if defined(ETHR_HAVE_NATIVE_ATOMIC32)
-typedef ethr_native_atomic32_t ethr_atomic32_t;
-# define ETHR_NAINT32_T__ ethr_sint32_t
-# define ETHR_NATMC32_FUNC__(X) ethr_native_atomic32_ ## X
-#elif defined(ETHR_HAVE_NATIVE_ATOMIC64)
-typedef ethr_native_atomic64_t ethr_atomic32_t;
-# define ETHR_NAINT32_T__ ethr_sint64_t
-# define ETHR_NATMC32_FUNC__(X) ethr_native_atomic64_ ## X
+#if !defined(ETHR_DW_NATMC_BITS__) || defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+# define ETHR_NEED_DW_FALLBACK__
+#endif
+
+#if defined(ETHR_NEED_DW_FALLBACK__)
+/*
+ * No native atomics usable for double word atomics :(
+ * Use fallback...
+ */
+
+# ifndef ETHR_AMC_FALLBACK__
+# if ETHR_SIZEOF_PTR == 8 && defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+# define ETHR_AMC_FALLBACK__
+# define ETHR_AMC_NO_ATMCS__ 1
+# define ETHR_AMC_SINT_T__ ethr_sint_t
+# define ETHR_AMC_ATMC_T__ ethr_atomic_t
+# define ETHR_AMC_ATMC_FUNC__(X) ETHR_INLINE_ATMC_FUNC_NAME_(ethr_atomic_ ## X)
+# elif defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+# define ETHR_AMC_FALLBACK__
+# define ETHR_AMC_NO_ATMCS__ 2
+# define ETHR_AMC_SINT_T__ ethr_sint32_t
+# define ETHR_AMC_ATMC_T__ ethr_atomic32_t
+# define ETHR_AMC_ATMC_FUNC__(X) ETHR_INLINE_ATMC32_FUNC_NAME_(ethr_atomic32_ ## X)
+# endif
+# ifdef ETHR_AMC_FALLBACK__
+typedef struct {
+ ETHR_AMC_ATMC_T__ atomic[ETHR_AMC_NO_ATMCS__];
+} ethr_amc_t;
+# endif
+# endif
+
+typedef struct {
+#ifdef ETHR_AMC_FALLBACK__
+ ethr_amc_t amc;
+#endif
+ ethr_sint_t sint[2];
+} ethr_dw_atomic_fallback_t;
+
+#endif
+
+typedef union {
+#ifdef ETHR_NATIVE_DW_ATOMIC_T__
+ ETHR_NATIVE_DW_ATOMIC_T__ native;
+#endif
+#ifdef ETHR_NEED_DW_FALLBACK__
+ ethr_dw_atomic_fallback_t fallback;
+#endif
+ ethr_sint_t sint[2];
+} ethr_dw_atomic_t;
+
+typedef union {
+#ifdef ETHR_SU_DW_NAINT_T__
+ ETHR_SU_DW_NAINT_T__ dw_sint;
+#endif
+ ethr_sint_t sint[2];
+} ethr_dw_sint_t;
+
+#ifdef ETHR_BIGENDIAN
+# define ETHR_DW_SINT_LOW_WORD 1
+# define ETHR_DW_SINT_HIGH_WORD 0
#else
-# error "Missing native atomic implementation"
+# define ETHR_DW_SINT_LOW_WORD 0
+# define ETHR_DW_SINT_HIGH_WORD 1
#endif
+#undef ETHR_DW_ATMC_INLINE__
+#ifdef ETHR_DW_NATMC_BITS__
+# ifdef ETHR_TRY_INLINE_FUNCS
+# define ETHR_ATMC32_INLINE__
+# endif
+# define ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS
#endif
-#ifdef ETHR_NEED_ATOMIC_PROTOTYPES__
-ethr_sint_t *ethr_atomic_addr(ethr_atomic_t *);
-void ethr_atomic_init(ethr_atomic_t *, ethr_sint_t);
-void ethr_atomic_set(ethr_atomic_t *, ethr_sint_t);
-ethr_sint_t ethr_atomic_read(ethr_atomic_t *);
-ethr_sint_t ethr_atomic_inc_read(ethr_atomic_t *);
-ethr_sint_t ethr_atomic_dec_read(ethr_atomic_t *);
-void ethr_atomic_inc(ethr_atomic_t *);
-void ethr_atomic_dec(ethr_atomic_t *);
-ethr_sint_t ethr_atomic_add_read(ethr_atomic_t *, ethr_sint_t);
-void ethr_atomic_add(ethr_atomic_t *, ethr_sint_t);
-ethr_sint_t ethr_atomic_read_band(ethr_atomic_t *, ethr_sint_t);
-ethr_sint_t ethr_atomic_read_bor(ethr_atomic_t *, ethr_sint_t);
-ethr_sint_t ethr_atomic_xchg(ethr_atomic_t *, ethr_sint_t);
-ethr_sint_t ethr_atomic_cmpxchg(ethr_atomic_t *, ethr_sint_t, ethr_sint_t);
-ethr_sint_t ethr_atomic_read_acqb(ethr_atomic_t *);
-ethr_sint_t ethr_atomic_inc_read_acqb(ethr_atomic_t *);
-void ethr_atomic_set_relb(ethr_atomic_t *, ethr_sint_t);
-void ethr_atomic_dec_relb(ethr_atomic_t *);
-ethr_sint_t ethr_atomic_dec_read_relb(ethr_atomic_t *);
-ethr_sint_t ethr_atomic_cmpxchg_acqb(ethr_atomic_t *, ethr_sint_t, ethr_sint_t);
-ethr_sint_t ethr_atomic_cmpxchg_relb(ethr_atomic_t *, ethr_sint_t, ethr_sint_t);
-
-ethr_sint32_t *ethr_atomic32_addr(ethr_atomic32_t *);
-void ethr_atomic32_init(ethr_atomic32_t *, ethr_sint32_t);
-void ethr_atomic32_set(ethr_atomic32_t *, ethr_sint32_t);
-ethr_sint32_t ethr_atomic32_read(ethr_atomic32_t *);
-ethr_sint32_t ethr_atomic32_inc_read(ethr_atomic32_t *);
-ethr_sint32_t ethr_atomic32_dec_read(ethr_atomic32_t *);
-void ethr_atomic32_inc(ethr_atomic32_t *);
-void ethr_atomic32_dec(ethr_atomic32_t *);
-ethr_sint32_t ethr_atomic32_add_read(ethr_atomic32_t *, ethr_sint32_t);
-void ethr_atomic32_add(ethr_atomic32_t *, ethr_sint32_t);
-ethr_sint32_t ethr_atomic32_read_band(ethr_atomic32_t *, ethr_sint32_t);
-ethr_sint32_t ethr_atomic32_read_bor(ethr_atomic32_t *, ethr_sint32_t);
-ethr_sint32_t ethr_atomic32_xchg(ethr_atomic32_t *, ethr_sint32_t);
-ethr_sint32_t ethr_atomic32_cmpxchg(ethr_atomic32_t *,
- ethr_sint32_t,
- ethr_sint32_t);
-ethr_sint32_t ethr_atomic32_read_acqb(ethr_atomic32_t *);
-ethr_sint32_t ethr_atomic32_inc_read_acqb(ethr_atomic32_t *);
-void ethr_atomic32_set_relb(ethr_atomic32_t *, ethr_sint32_t);
-void ethr_atomic32_dec_relb(ethr_atomic32_t *);
-ethr_sint32_t ethr_atomic32_dec_read_relb(ethr_atomic32_t *);
-ethr_sint32_t ethr_atomic32_cmpxchg_acqb(ethr_atomic32_t *,
- ethr_sint32_t,
- ethr_sint32_t);
-ethr_sint32_t ethr_atomic32_cmpxchg_relb(ethr_atomic32_t *,
- ethr_sint32_t,
- ethr_sint32_t);
+#if !defined(ETHR_DW_ATMC_INLINE__) || defined(ETHR_ATOMIC_IMPL__)
+# define ETHR_NEED_DW_ATMC_PROTOTYPES__
#endif
-int ethr_init_atomics(void);
+#ifndef ETHR_INLINE_DW_ATMC_FUNC_NAME_
+# define ETHR_INLINE_DW_ATMC_FUNC_NAME_(X) X
+#endif
+
+#undef ETHR_DW_ATMC_FUNC__
+#define ETHR_DW_ATMC_FUNC__(X) ETHR_INLINE_DW_ATMC_FUNC_NAME_(ethr_dw_atomic_ ## X)
+
+#if defined(ETHR_NEED_DW_ATMC_PROTOTYPES__)
+int ethr_have_native_dw_atomic(void);
+#endif
+#if defined(ETHR_DW_ATMC_INLINE__) || defined(ETHR_ATOMIC_IMPL__)
+static ETHR_INLINE int
+ETHR_INLINE_DW_ATMC_FUNC_NAME_(ethr_have_native_dw_atomic)(void)
+{
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ return ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__;
+#elif defined(ETHR_DW_NATMC_BITS__)
+ return 1;
+#else
+ return 0;
+#endif
+}
+#endif
+
+/* -- Misc -- */
#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_ATOMIC_IMPL__)
+/*
+ * Unusual values are used by read() fallbacks implemented via cmpxchg().
+ * We want to use an unusual value in hope that it is more efficient
+ * not to match the value in memory.
+ *
+ * - Negative integer values are probably more unusual.
+ * - Very large absolute integer values are probably more unusual.
+ * - Odd pointers are probably more unusual (only char pointers can be odd).
+ */
+# define ETHR_UNUSUAL_SINT32_VAL__ ((ethr_sint32_t) 0x81818181)
+# if ETHR_SIZEOF_PTR == 4
+# define ETHR_UNUSUAL_SINT_VAL__ ((ethr_sint_t) ETHR_UNUSUAL_SINT32_VAL__)
+# elif ETHR_SIZEOF_PTR == 8
+# define ETHR_UNUSUAL_SINT_VAL__ ((ethr_sint_t) 0x8181818181818181L)
+# else
+# error "Word size not supported"
+# endif
+# if defined(ETHR_NEED_DW_NATMC_ADDR) && !defined(ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_ADDR)
+# error "No ethr_native_dw_atomic_addr() available"
+# endif
+# if defined(ETHR_NEED_NATMC32_ADDR) && !defined(ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADDR)
+# error "No ethr_native_atomic32_addr() available"
+# endif
+# if defined(ETHR_NEED_NATMC64_ADDR) && !defined(ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADDR)
+# error "No ethr_native_atomic64_addr() available"
+# endif
+#endif
+
+#if defined(__GNUC__)
+# ifndef ETHR_COMPILER_BARRIER
+# define ETHR_COMPILER_BARRIER __asm__ __volatile__("" : : : "memory")
+# endif
+#elif defined(ETHR_WIN32_THREADS)
+# ifndef ETHR_COMPILER_BARRIER
+# include <intrin.h>
+# pragma intrinsic(_ReadWriteBarrier)
+# define ETHR_COMPILER_BARRIER _ReadWriteBarrier()
+# endif
+#endif
-#ifndef ETHR_HAVE_NATIVE_ATOMICS
+void ethr_compiler_barrier_fallback(void);
+#ifndef ETHR_COMPILER_BARRIER
+# define ETHR_COMPILER_BARRIER ethr_compiler_barrier_fallback()
+#endif
+
+int ethr_init_atomics(void);
+
+/* info */
+char **ethr_native_atomic32_ops(void);
+char **ethr_native_atomic64_ops(void);
+char **ethr_native_dw_atomic_ops(void);
+char **ethr_native_su_dw_atomic_ops(void);
+
+#if !defined(ETHR_DW_NATMC_BITS__) && !defined(ETHR_NATMC_BITS__) && !defined(ETHR_NATMC32_BITS__)
/*
- * Fallbacks for atomics used in absence of a native implementation.
+ * ETHR_*MEMORY_BARRIER orders between locked and atomic accesses only,
+ * i.e. when no native atomic implementation exist and only our lock
+ * based atomic fallback is used, a noop is sufficient.
*/
+# undef ETHR_MEMORY_BARRIER
+# undef ETHR_WRITE_MEMORY_BARRIER
+# undef ETHR_READ_MEMORY_BARRIER
+# undef ETHR_READ_DEPEND_MEMORY_BARRIER
+# undef ETHR_MEMBAR
+# define ETHR_MEMBAR(B) do { } while (0)
+#endif
+
+#ifndef ETHR_MEMBAR
+# error "No ETHR_MEMBAR defined"
+#endif
-#define ETHR_ATOMIC_ADDR_BITS 10
-#define ETHR_ATOMIC_ADDR_SHIFT 6
+#define ETHR_MEMORY_BARRIER ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore)
+#define ETHR_WRITE_MEMORY_BARRIER ETHR_MEMBAR(ETHR_StoreStore)
+#define ETHR_READ_MEMORY_BARRIER ETHR_MEMBAR(ETHR_LoadLoad)
+#ifdef ETHR_READ_DEPEND_MEMORY_BARRIER
+# undef ETHR_ORDERED_READ_DEPEND
+#else
+# define ETHR_READ_DEPEND_MEMORY_BARRIER ETHR_COMPILER_BARRIER
+# define ETHR_ORDERED_READ_DEPEND
+#endif
-typedef struct {
- union {
- ethr_spinlock_t lck;
- char buf[ETHR_CACHE_LINE_SIZE];
- } u;
-} ethr_atomic_protection_t;
-extern ethr_atomic_protection_t ethr_atomic_protection__[1 << ETHR_ATOMIC_ADDR_BITS];
+/* ---------- Double word size atomic implementation ---------- */
+
+
+#ifdef ETHR_NEED_DW_ATMC_PROTOTYPES__
+ethr_sint_t *ethr_dw_atomic_addr(ethr_dw_atomic_t *var);
+int ethr_dw_atomic_cmpxchg(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
+int ethr_dw_atomic_cmpxchg_rb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
+int ethr_dw_atomic_cmpxchg_wb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
+int ethr_dw_atomic_cmpxchg_acqb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
+int ethr_dw_atomic_cmpxchg_relb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
+int ethr_dw_atomic_cmpxchg_mb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
+void ethr_dw_atomic_set(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ethr_dw_atomic_set_rb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ethr_dw_atomic_set_wb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ethr_dw_atomic_set_acqb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ethr_dw_atomic_set_relb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ethr_dw_atomic_set_mb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ethr_dw_atomic_read(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ethr_dw_atomic_read_rb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ethr_dw_atomic_read_wb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ethr_dw_atomic_read_acqb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ethr_dw_atomic_read_relb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ethr_dw_atomic_read_mb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ethr_dw_atomic_init(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ethr_dw_atomic_init_rb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ethr_dw_atomic_init_wb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ethr_dw_atomic_init_acqb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ethr_dw_atomic_init_relb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ethr_dw_atomic_init_mb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ethr_sint_t *ETHR_DW_ATOMIC_FUNC__(addr)(ethr_dw_atomic_t *var);
+int ETHR_DW_ATOMIC_FUNC__(cmpxchg)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
+int ETHR_DW_ATOMIC_FUNC__(cmpxchg_rb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
+int ETHR_DW_ATOMIC_FUNC__(cmpxchg_wb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
+int ETHR_DW_ATOMIC_FUNC__(cmpxchg_acqb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
+int ETHR_DW_ATOMIC_FUNC__(cmpxchg_relb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
+int ETHR_DW_ATOMIC_FUNC__(cmpxchg_mb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
+void ETHR_DW_ATOMIC_FUNC__(set)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ETHR_DW_ATOMIC_FUNC__(set_rb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ETHR_DW_ATOMIC_FUNC__(set_wb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ETHR_DW_ATOMIC_FUNC__(set_acqb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ETHR_DW_ATOMIC_FUNC__(set_relb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ETHR_DW_ATOMIC_FUNC__(set_mb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ETHR_DW_ATOMIC_FUNC__(read)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ETHR_DW_ATOMIC_FUNC__(read_rb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ETHR_DW_ATOMIC_FUNC__(read_wb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ETHR_DW_ATOMIC_FUNC__(read_acqb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ETHR_DW_ATOMIC_FUNC__(read_relb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ETHR_DW_ATOMIC_FUNC__(read_mb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ETHR_DW_ATOMIC_FUNC__(init)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ETHR_DW_ATOMIC_FUNC__(init_rb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ETHR_DW_ATOMIC_FUNC__(init_wb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ETHR_DW_ATOMIC_FUNC__(init_acqb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ETHR_DW_ATOMIC_FUNC__(init_relb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ETHR_DW_ATOMIC_FUNC__(init_mb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+#endif
+#endif /* ETHR_NEED_DW_ATMC_PROTOTYPES__ */
+
+#if (defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) \
+ && (defined(ETHR_DW_ATMC_INLINE__) || defined(ETHR_ATOMIC_IMPL__)))
+
+#if !defined(ETHR_DW_NATMC_BITS__)
+# error "Missing native atomic implementation"
+#elif defined(ETHR_HAVE_NATIVE_DW_ATOMIC) || defined(ETHR_HAVE_NATIVE_SU_DW_ATOMIC)
+# undef ETHR_HAVE_SU_DW_NATMC_CMPXCHG
+# undef ETHR_HAVE_DW_NATMC_CMPXCHG
+# ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_CMPXCHG
+# define ETHR_HAVE_DW_NATMC_CMPXCHG 1
+# endif
+# ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_CMPXCHG
+# define ETHR_HAVE_SU_DW_NATMC_CMPXCHG 1
+# endif
+# undef ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RB
+# undef ETHR_HAVE_DW_NATMC_CMPXCHG_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_CMPXCHG_RB
+# define ETHR_HAVE_DW_NATMC_CMPXCHG_RB 1
+# endif
+# ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_CMPXCHG_RB
+# define ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RB 1
+# endif
+# undef ETHR_HAVE_SU_DW_NATMC_CMPXCHG_WB
+# undef ETHR_HAVE_DW_NATMC_CMPXCHG_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_CMPXCHG_WB
+# define ETHR_HAVE_DW_NATMC_CMPXCHG_WB 1
+# endif
+# ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_CMPXCHG_WB
+# define ETHR_HAVE_SU_DW_NATMC_CMPXCHG_WB 1
+# endif
+# undef ETHR_HAVE_SU_DW_NATMC_CMPXCHG_ACQB
+# undef ETHR_HAVE_DW_NATMC_CMPXCHG_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_CMPXCHG_ACQB
+# define ETHR_HAVE_DW_NATMC_CMPXCHG_ACQB 1
+# endif
+# ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_CMPXCHG_ACQB
+# define ETHR_HAVE_SU_DW_NATMC_CMPXCHG_ACQB 1
+# endif
+# undef ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RELB
+# undef ETHR_HAVE_DW_NATMC_CMPXCHG_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_CMPXCHG_RELB
+# define ETHR_HAVE_DW_NATMC_CMPXCHG_RELB 1
+# endif
+# ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_CMPXCHG_RELB
+# define ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RELB 1
+# endif
+# undef ETHR_HAVE_SU_DW_NATMC_CMPXCHG_MB
+# undef ETHR_HAVE_DW_NATMC_CMPXCHG_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_CMPXCHG_MB
+# define ETHR_HAVE_DW_NATMC_CMPXCHG_MB 1
+# endif
+# ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_CMPXCHG_MB
+# define ETHR_HAVE_SU_DW_NATMC_CMPXCHG_MB 1
+# endif
+# undef ETHR_HAVE_SU_DW_NATMC_SET
+# undef ETHR_HAVE_DW_NATMC_SET
+# ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_SET
+# define ETHR_HAVE_DW_NATMC_SET 1
+# endif
+# ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_SET
+# define ETHR_HAVE_SU_DW_NATMC_SET 1
+# endif
+# undef ETHR_HAVE_SU_DW_NATMC_SET_RB
+# undef ETHR_HAVE_DW_NATMC_SET_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_SET_RB
+# define ETHR_HAVE_DW_NATMC_SET_RB 1
+# endif
+# ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_SET_RB
+# define ETHR_HAVE_SU_DW_NATMC_SET_RB 1
+# endif
+# undef ETHR_HAVE_SU_DW_NATMC_SET_WB
+# undef ETHR_HAVE_DW_NATMC_SET_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_SET_WB
+# define ETHR_HAVE_DW_NATMC_SET_WB 1
+# endif
+# ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_SET_WB
+# define ETHR_HAVE_SU_DW_NATMC_SET_WB 1
+# endif
+# undef ETHR_HAVE_SU_DW_NATMC_SET_ACQB
+# undef ETHR_HAVE_DW_NATMC_SET_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_SET_ACQB
+# define ETHR_HAVE_DW_NATMC_SET_ACQB 1
+# endif
+# ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_SET_ACQB
+# define ETHR_HAVE_SU_DW_NATMC_SET_ACQB 1
+# endif
+# undef ETHR_HAVE_SU_DW_NATMC_SET_RELB
+# undef ETHR_HAVE_DW_NATMC_SET_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_SET_RELB
+# define ETHR_HAVE_DW_NATMC_SET_RELB 1
+# endif
+# ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_SET_RELB
+# define ETHR_HAVE_SU_DW_NATMC_SET_RELB 1
+# endif
+# undef ETHR_HAVE_SU_DW_NATMC_SET_MB
+# undef ETHR_HAVE_DW_NATMC_SET_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_SET_MB
+# define ETHR_HAVE_DW_NATMC_SET_MB 1
+# endif
+# ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_SET_MB
+# define ETHR_HAVE_SU_DW_NATMC_SET_MB 1
+# endif
+# undef ETHR_HAVE_SU_DW_NATMC_READ
+# undef ETHR_HAVE_DW_NATMC_READ
+# ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_READ
+# define ETHR_HAVE_DW_NATMC_READ 1
+# endif
+# ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_READ
+# define ETHR_HAVE_SU_DW_NATMC_READ 1
+# endif
+# undef ETHR_HAVE_SU_DW_NATMC_READ_RB
+# undef ETHR_HAVE_DW_NATMC_READ_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_READ_RB
+# define ETHR_HAVE_DW_NATMC_READ_RB 1
+# endif
+# ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_READ_RB
+# define ETHR_HAVE_SU_DW_NATMC_READ_RB 1
+# endif
+# undef ETHR_HAVE_SU_DW_NATMC_READ_WB
+# undef ETHR_HAVE_DW_NATMC_READ_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_READ_WB
+# define ETHR_HAVE_DW_NATMC_READ_WB 1
+# endif
+# ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_READ_WB
+# define ETHR_HAVE_SU_DW_NATMC_READ_WB 1
+# endif
+# undef ETHR_HAVE_SU_DW_NATMC_READ_ACQB
+# undef ETHR_HAVE_DW_NATMC_READ_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_READ_ACQB
+# define ETHR_HAVE_DW_NATMC_READ_ACQB 1
+# endif
+# ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_READ_ACQB
+# define ETHR_HAVE_SU_DW_NATMC_READ_ACQB 1
+# endif
+# undef ETHR_HAVE_SU_DW_NATMC_READ_RELB
+# undef ETHR_HAVE_DW_NATMC_READ_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_READ_RELB
+# define ETHR_HAVE_DW_NATMC_READ_RELB 1
+# endif
+# ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_READ_RELB
+# define ETHR_HAVE_SU_DW_NATMC_READ_RELB 1
+# endif
+# undef ETHR_HAVE_SU_DW_NATMC_READ_MB
+# undef ETHR_HAVE_DW_NATMC_READ_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_READ_MB
+# define ETHR_HAVE_DW_NATMC_READ_MB 1
+# endif
+# ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_READ_MB
+# define ETHR_HAVE_SU_DW_NATMC_READ_MB 1
+# endif
+# undef ETHR_HAVE_SU_DW_NATMC_INIT
+# undef ETHR_HAVE_DW_NATMC_INIT
+# ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_INIT
+# define ETHR_HAVE_DW_NATMC_INIT 1
+# endif
+# ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_INIT
+# define ETHR_HAVE_SU_DW_NATMC_INIT 1
+# endif
+# undef ETHR_HAVE_SU_DW_NATMC_INIT_RB
+# undef ETHR_HAVE_DW_NATMC_INIT_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_INIT_RB
+# define ETHR_HAVE_DW_NATMC_INIT_RB 1
+# endif
+# ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_INIT_RB
+# define ETHR_HAVE_SU_DW_NATMC_INIT_RB 1
+# endif
+# undef ETHR_HAVE_SU_DW_NATMC_INIT_WB
+# undef ETHR_HAVE_DW_NATMC_INIT_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_INIT_WB
+# define ETHR_HAVE_DW_NATMC_INIT_WB 1
+# endif
+# ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_INIT_WB
+# define ETHR_HAVE_SU_DW_NATMC_INIT_WB 1
+# endif
+# undef ETHR_HAVE_SU_DW_NATMC_INIT_ACQB
+# undef ETHR_HAVE_DW_NATMC_INIT_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_INIT_ACQB
+# define ETHR_HAVE_DW_NATMC_INIT_ACQB 1
+# endif
+# ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_INIT_ACQB
+# define ETHR_HAVE_SU_DW_NATMC_INIT_ACQB 1
+# endif
+# undef ETHR_HAVE_SU_DW_NATMC_INIT_RELB
+# undef ETHR_HAVE_DW_NATMC_INIT_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_INIT_RELB
+# define ETHR_HAVE_DW_NATMC_INIT_RELB 1
+# endif
+# ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_INIT_RELB
+# define ETHR_HAVE_SU_DW_NATMC_INIT_RELB 1
+# endif
+# undef ETHR_HAVE_SU_DW_NATMC_INIT_MB
+# undef ETHR_HAVE_DW_NATMC_INIT_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_INIT_MB
+# define ETHR_HAVE_DW_NATMC_INIT_MB 1
+# endif
+# ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_INIT_MB
+# define ETHR_HAVE_SU_DW_NATMC_INIT_MB 1
+# endif
+#elif ETHR_DW_NATMC_BITS__ == 64
+# undef ETHR_HAVE_DW_NATMC_CMPXCHG
+# undef ETHR_HAVE_SU_DW_NATMC_CMPXCHG
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG
+# define ETHR_HAVE_SU_DW_NATMC_CMPXCHG 1
+# endif
+# undef ETHR_HAVE_DW_NATMC_CMPXCHG_RB
+# undef ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_RB
+# define ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RB 1
+# endif
+# undef ETHR_HAVE_DW_NATMC_CMPXCHG_WB
+# undef ETHR_HAVE_SU_DW_NATMC_CMPXCHG_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_WB
+# define ETHR_HAVE_SU_DW_NATMC_CMPXCHG_WB 1
+# endif
+# undef ETHR_HAVE_DW_NATMC_CMPXCHG_ACQB
+# undef ETHR_HAVE_SU_DW_NATMC_CMPXCHG_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_ACQB
+# define ETHR_HAVE_SU_DW_NATMC_CMPXCHG_ACQB 1
+# endif
+# undef ETHR_HAVE_DW_NATMC_CMPXCHG_RELB
+# undef ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_RELB
+# define ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RELB 1
+# endif
+# undef ETHR_HAVE_DW_NATMC_CMPXCHG_MB
+# undef ETHR_HAVE_SU_DW_NATMC_CMPXCHG_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_MB
+# define ETHR_HAVE_SU_DW_NATMC_CMPXCHG_MB 1
+# endif
+# undef ETHR_HAVE_DW_NATMC_SET
+# undef ETHR_HAVE_SU_DW_NATMC_SET
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET
+# define ETHR_HAVE_SU_DW_NATMC_SET 1
+# endif
+# undef ETHR_HAVE_DW_NATMC_SET_RB
+# undef ETHR_HAVE_SU_DW_NATMC_SET_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET_RB
+# define ETHR_HAVE_SU_DW_NATMC_SET_RB 1
+# endif
+# undef ETHR_HAVE_DW_NATMC_SET_WB
+# undef ETHR_HAVE_SU_DW_NATMC_SET_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET_WB
+# define ETHR_HAVE_SU_DW_NATMC_SET_WB 1
+# endif
+# undef ETHR_HAVE_DW_NATMC_SET_ACQB
+# undef ETHR_HAVE_SU_DW_NATMC_SET_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET_ACQB
+# define ETHR_HAVE_SU_DW_NATMC_SET_ACQB 1
+# endif
+# undef ETHR_HAVE_DW_NATMC_SET_RELB
+# undef ETHR_HAVE_SU_DW_NATMC_SET_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET_RELB
+# define ETHR_HAVE_SU_DW_NATMC_SET_RELB 1
+# endif
+# undef ETHR_HAVE_DW_NATMC_SET_MB
+# undef ETHR_HAVE_SU_DW_NATMC_SET_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET_MB
+# define ETHR_HAVE_SU_DW_NATMC_SET_MB 1
+# endif
+# undef ETHR_HAVE_DW_NATMC_READ
+# undef ETHR_HAVE_SU_DW_NATMC_READ
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ
+# define ETHR_HAVE_SU_DW_NATMC_READ 1
+# endif
+# undef ETHR_HAVE_DW_NATMC_READ_RB
+# undef ETHR_HAVE_SU_DW_NATMC_READ_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ_RB
+# define ETHR_HAVE_SU_DW_NATMC_READ_RB 1
+# endif
+# undef ETHR_HAVE_DW_NATMC_READ_WB
+# undef ETHR_HAVE_SU_DW_NATMC_READ_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ_WB
+# define ETHR_HAVE_SU_DW_NATMC_READ_WB 1
+# endif
+# undef ETHR_HAVE_DW_NATMC_READ_ACQB
+# undef ETHR_HAVE_SU_DW_NATMC_READ_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ_ACQB
+# define ETHR_HAVE_SU_DW_NATMC_READ_ACQB 1
+# endif
+# undef ETHR_HAVE_DW_NATMC_READ_RELB
+# undef ETHR_HAVE_SU_DW_NATMC_READ_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ_RELB
+# define ETHR_HAVE_SU_DW_NATMC_READ_RELB 1
+# endif
+# undef ETHR_HAVE_DW_NATMC_READ_MB
+# undef ETHR_HAVE_SU_DW_NATMC_READ_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ_MB
+# define ETHR_HAVE_SU_DW_NATMC_READ_MB 1
+# endif
+# undef ETHR_HAVE_DW_NATMC_INIT
+# undef ETHR_HAVE_SU_DW_NATMC_INIT
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INIT
+# define ETHR_HAVE_SU_DW_NATMC_INIT 1
+# endif
+# undef ETHR_HAVE_DW_NATMC_INIT_RB
+# undef ETHR_HAVE_SU_DW_NATMC_INIT_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INIT_RB
+# define ETHR_HAVE_SU_DW_NATMC_INIT_RB 1
+# endif
+# undef ETHR_HAVE_DW_NATMC_INIT_WB
+# undef ETHR_HAVE_SU_DW_NATMC_INIT_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INIT_WB
+# define ETHR_HAVE_SU_DW_NATMC_INIT_WB 1
+# endif
+# undef ETHR_HAVE_DW_NATMC_INIT_ACQB
+# undef ETHR_HAVE_SU_DW_NATMC_INIT_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INIT_ACQB
+# define ETHR_HAVE_SU_DW_NATMC_INIT_ACQB 1
+# endif
+# undef ETHR_HAVE_DW_NATMC_INIT_RELB
+# undef ETHR_HAVE_SU_DW_NATMC_INIT_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INIT_RELB
+# define ETHR_HAVE_SU_DW_NATMC_INIT_RELB 1
+# endif
+# undef ETHR_HAVE_DW_NATMC_INIT_MB
+# undef ETHR_HAVE_SU_DW_NATMC_INIT_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INIT_MB
+# define ETHR_HAVE_SU_DW_NATMC_INIT_MB 1
+# endif
+#else
+# error "Invalid native atomic size"
+#endif
+
-#define ETHR_ATOMIC_PTR2LCK__(PTR) \
-(&ethr_atomic_protection__[((((ethr_uint_t) (PTR)) >> ETHR_ATOMIC_ADDR_SHIFT) \
- & ((1 << ETHR_ATOMIC_ADDR_BITS) - 1))].u.lck)
+#if defined(ETHR_HAVE_NATIVE_DW_ATOMIC)
+#if (!defined(ETHR_HAVE_DW_NATMC_CMPXCHG) \
+ && !defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RB) \
+ && !defined(ETHR_HAVE_DW_NATMC_CMPXCHG_WB) \
+ && !defined(ETHR_HAVE_DW_NATMC_CMPXCHG_ACQB) \
+ && !defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RELB) \
+ && !defined(ETHR_HAVE_DW_NATMC_CMPXCHG_MB))
+# error "No native cmpxchg() op available"
+#endif
+
+
+/*
+ * Read op used together with cmpxchg() fallback when no native op present.
+ */
+#if defined(ETHR_HAVE_DW_NATMC_READ)
+#define ETHR_DW_NATMC_CMPXCHG_FALLBACK_READ__(VAR, VAL) \
+ ETHR_DW_NATMC_FUNC__(read)(VAR, VAL)
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ)
+#define ETHR_DW_NATMC_CMPXCHG_FALLBACK_READ__(VAR, VAL) \
+ VAL.dw_sint = ETHR_SU_DW_NATMC_FUNC__(read)(VAR)
+#elif defined(ETHR_HAVE_DW_NATMC_READ_RB)
+#define ETHR_DW_NATMC_CMPXCHG_FALLBACK_READ__(VAR, VAL) \
+ ETHR_DW_NATMC_FUNC__(read_rb)(VAR, VAL)
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_RB)
+#define ETHR_DW_NATMC_CMPXCHG_FALLBACK_READ__(VAR, VAL) \
+ VAL.dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_rb)(VAR)
+#elif defined(ETHR_HAVE_DW_NATMC_READ_WB)
+#define ETHR_DW_NATMC_CMPXCHG_FALLBACK_READ__(VAR, VAL) \
+ ETHR_DW_NATMC_FUNC__(read_wb)(VAR, VAL)
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_WB)
+#define ETHR_DW_NATMC_CMPXCHG_FALLBACK_READ__(VAR, VAL) \
+ VAL.dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_wb)(VAR)
+#elif defined(ETHR_HAVE_DW_NATMC_READ_ACQB)
+#define ETHR_DW_NATMC_CMPXCHG_FALLBACK_READ__(VAR, VAL) \
+ ETHR_DW_NATMC_FUNC__(read_acqb)(VAR, VAL)
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_ACQB)
+#define ETHR_DW_NATMC_CMPXCHG_FALLBACK_READ__(VAR, VAL) \
+ VAL.dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_acqb)(VAR)
+#elif defined(ETHR_HAVE_DW_NATMC_READ_RELB)
+#define ETHR_DW_NATMC_CMPXCHG_FALLBACK_READ__(VAR, VAL) \
+ ETHR_DW_NATMC_FUNC__(read_relb)(VAR, VAL)
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_RELB)
+#define ETHR_DW_NATMC_CMPXCHG_FALLBACK_READ__(VAR, VAL) \
+ VAL.dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_relb)(VAR)
+#elif defined(ETHR_HAVE_DW_NATMC_READ_MB)
+#define ETHR_DW_NATMC_CMPXCHG_FALLBACK_READ__(VAR, VAL) \
+ ETHR_DW_NATMC_FUNC__(read_mb)(VAR, VAL)
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_MB)
+#define ETHR_DW_NATMC_CMPXCHG_FALLBACK_READ__(VAR, VAL) \
+ VAL.dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_mb)(VAR)
+#else
+/*
+ * We have no native read() op; guess zero and then use the
+ * the atomics actual value returned from cmpxchg().
+ */
+#define ETHR_DW_NATMC_CMPXCHG_FALLBACK_READ__(VAR, VAL) \
+do { \
+ VAL.sint[0] = (ethr_sint_t) 0; \
+ VAL.sint[1] = (ethr_sint_t) 0; \
+} while (0)
+#endif
-#define ETHR_ATOMIC_OP_FALLBACK_IMPL__(AP, EXPS) \
-do { \
- ethr_spinlock_t *slp__ = ETHR_ATOMIC_PTR2LCK__((AP)); \
- ethr_spin_lock(slp__); \
- { EXPS; } \
- ethr_spin_unlock(slp__); \
+/*
+ * Native cmpxchg() fallback used when no native op present.
+ */
+#define ETHR_DW_NATMC_CMPXCHG_FALLBACK__(CMPXCHG, VAR, AVAL, OPS) \
+do { \
+ int res__; \
+ ethr_dw_sint_t AVAL, exp_act__; \
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK_READ__(VAR, exp_act__); \
+ do { \
+ AVAL.sint[0] = exp_act__.sint[0]; \
+ AVAL.sint[1] = exp_act__.sint[1]; \
+ { OPS; } \
+ res__ = CMPXCHG(VAR, AVAL.sint, exp_act__.sint); \
+ } while (__builtin_expect(res__ == 0, 0)); \
} while (0)
+
+#elif defined(ETHR_HAVE_NATIVE_SU_DW_ATOMIC)
+
+#if (!defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG) \
+ && !defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RB) \
+ && !defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_WB) \
+ && !defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_ACQB) \
+ && !defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RELB) \
+ && !defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_MB))
+# error "No native cmpxchg() op available"
+#endif
+
+
+/*
+ * Read op used together with cmpxchg() fallback when no native op present.
+ */
+#if defined(ETHR_HAVE_SU_DW_NATMC_READ)
+#define ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK_READ__(VAR) \
+ ETHR_SU_DW_NATMC_FUNC__(read)(VAR)
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_RB)
+#define ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK_READ__(VAR) \
+ ETHR_SU_DW_NATMC_FUNC__(read_rb)(VAR)
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_WB)
+#define ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK_READ__(VAR) \
+ ETHR_SU_DW_NATMC_FUNC__(read_wb)(VAR)
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_ACQB)
+#define ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK_READ__(VAR) \
+ ETHR_SU_DW_NATMC_FUNC__(read_acqb)(VAR)
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_RELB)
+#define ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK_READ__(VAR) \
+ ETHR_SU_DW_NATMC_FUNC__(read_relb)(VAR)
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_MB)
+#define ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK_READ__(VAR) \
+ ETHR_SU_DW_NATMC_FUNC__(read_mb)(VAR)
+#else
+/*
+ * We have no native read() op; guess zero and then use the
+ * the atomics actual value returned from cmpxchg().
+ */
+#define ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK_READ__(VAR) \
+ ((ETHR_SU_DW_NAINT_T__) 0)
+#endif
+
+/*
+ * Native cmpxchg() fallback used when no native op present.
+ */
+#define ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(CMPXCHG, VAR, AVAL, OPS) \
+do { \
+ ETHR_SU_DW_NAINT_T__ AVAL; \
+ ETHR_SU_DW_NAINT_T__ new__, act__, exp__; \
+ act__ = ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK_READ__(VAR); \
+ do { \
+ exp__ = act__; \
+ AVAL = (ETHR_SU_DW_NAINT_T__) act__; \
+ { OPS; } \
+ new__ = (ETHR_SU_DW_NAINT_T__) AVAL; \
+ act__ = CMPXCHG(VAR, new__, exp__); \
+ } while (__builtin_expect(act__ != exp__, 0)); \
+} while (0)
+
+
+#else
+# error "?!?"
+#endif
+
+
+
+/* --- addr() --- */
+
+static ETHR_INLINE ethr_sint_t *ETHR_DW_ATMC_FUNC__(addr)(ethr_dw_atomic_t *var)
+{
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__) {
+#endif
+
+ return (ethr_sint_t *) ETHR_DW_NATMC_ADDR_FUNC__((&var->native));
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ } else { return ETHR_DW_ATOMIC_FUNC__(addr)(var); }
+#endif
+
+}
+
+
+/* --- cmpxchg() --- */
+
+
+static ETHR_INLINE int ETHR_DW_ATMC_FUNC__(cmpxchg)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val)
+{
+ int res;
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__) {
+#endif
+
+#if defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG)
+ ETHR_SU_DW_NAINT_T__ act;
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg)(&var->native, val->dw_sint, old_val->dw_sint);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RB)
+ ETHR_SU_DW_NAINT_T__ act;
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_rb)(&var->native, val->dw_sint, old_val->dw_sint);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_WB)
+ ETHR_SU_DW_NAINT_T__ act;
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_wb)(&var->native, val->dw_sint, old_val->dw_sint);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_ACQB)
+ ETHR_SU_DW_NAINT_T__ act;
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_acqb)(&var->native, val->dw_sint, old_val->dw_sint);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RELB)
+ ETHR_SU_DW_NAINT_T__ act;
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_relb)(&var->native, val->dw_sint, old_val->dw_sint);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_MB)
+ ETHR_SU_DW_NAINT_T__ act;
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_mb)(&var->native, val->dw_sint, old_val->dw_sint);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG)
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg)(&var->native, val->sint, old_val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RB)
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_rb)(&var->native, val->sint, old_val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_WB)
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_wb)(&var->native, val->sint, old_val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_ACQB)
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_acqb)(&var->native, val->sint, old_val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RELB)
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_relb)(&var->native, val->sint, old_val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_MB)
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_mb)(&var->native, val->sint, old_val->sint);
+#else
+#error "Missing implementation of ethr_dw_atomic_cmpxchg()!"
+#endif
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ } else { res = ETHR_DW_ATOMIC_FUNC__(cmpxchg)(var, val, old_val); }
+#endif
+
+ return res;
+}
+
+static ETHR_INLINE int ETHR_DW_ATMC_FUNC__(cmpxchg_rb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val)
+{
+ int res;
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__) {
+#endif
+
+#if defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RB)
+ ETHR_SU_DW_NAINT_T__ act;
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_rb)(&var->native, val->dw_sint, old_val->dw_sint);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG)
+ ETHR_SU_DW_NAINT_T__ act;
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg)(&var->native, val->dw_sint, old_val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_MB)
+ ETHR_SU_DW_NAINT_T__ act;
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_mb)(&var->native, val->dw_sint, old_val->dw_sint);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_WB)
+ ETHR_SU_DW_NAINT_T__ act;
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_wb)(&var->native, val->dw_sint, old_val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_ACQB)
+ ETHR_SU_DW_NAINT_T__ act;
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_acqb)(&var->native, val->dw_sint, old_val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RELB)
+ ETHR_SU_DW_NAINT_T__ act;
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_relb)(&var->native, val->dw_sint, old_val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RB)
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_rb)(&var->native, val->sint, old_val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG)
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg)(&var->native, val->sint, old_val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_MB)
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_mb)(&var->native, val->sint, old_val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_WB)
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_wb)(&var->native, val->sint, old_val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_ACQB)
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_acqb)(&var->native, val->sint, old_val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RELB)
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_relb)(&var->native, val->sint, old_val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+#error "Missing implementation of ethr_dw_atomic_cmpxchg_rb()!"
+#endif
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ } else { res = ETHR_DW_ATOMIC_FUNC__(cmpxchg_rb)(var, val, old_val); }
+#endif
+
+ return res;
+}
+
+static ETHR_INLINE int ETHR_DW_ATMC_FUNC__(cmpxchg_wb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val)
+{
+ int res;
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__) {
+#endif
+
+#if defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_WB)
+ ETHR_SU_DW_NAINT_T__ act;
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_wb)(&var->native, val->dw_sint, old_val->dw_sint);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG)
+ ETHR_SU_DW_NAINT_T__ act;
+ ETHR_MEMBAR(ETHR_StoreStore);
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg)(&var->native, val->dw_sint, old_val->dw_sint);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_MB)
+ ETHR_SU_DW_NAINT_T__ act;
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_mb)(&var->native, val->dw_sint, old_val->dw_sint);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RB)
+ ETHR_SU_DW_NAINT_T__ act;
+ ETHR_MEMBAR(ETHR_StoreStore);
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_rb)(&var->native, val->dw_sint, old_val->dw_sint);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_ACQB)
+ ETHR_SU_DW_NAINT_T__ act;
+ ETHR_MEMBAR(ETHR_StoreStore);
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_acqb)(&var->native, val->dw_sint, old_val->dw_sint);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RELB)
+ ETHR_SU_DW_NAINT_T__ act;
+ ETHR_MEMBAR(ETHR_StoreStore);
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_relb)(&var->native, val->dw_sint, old_val->dw_sint);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_WB)
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_wb)(&var->native, val->sint, old_val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg)(&var->native, val->sint, old_val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_MB)
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_mb)(&var->native, val->sint, old_val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_rb)(&var->native, val->sint, old_val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_acqb)(&var->native, val->sint, old_val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_relb)(&var->native, val->sint, old_val->sint);
+#else
+#error "Missing implementation of ethr_dw_atomic_cmpxchg_wb()!"
+#endif
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ } else { res = ETHR_DW_ATOMIC_FUNC__(cmpxchg_wb)(var, val, old_val); }
+#endif
+
+ return res;
+}
+
+static ETHR_INLINE int ETHR_DW_ATMC_FUNC__(cmpxchg_acqb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val)
+{
+ int res;
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__) {
+#endif
+
+#if defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_ACQB)
+ ETHR_SU_DW_NAINT_T__ act;
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_acqb)(&var->native, val->dw_sint, old_val->dw_sint);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RB)
+ ETHR_SU_DW_NAINT_T__ act;
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_rb)(&var->native, val->dw_sint, old_val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG)
+ ETHR_SU_DW_NAINT_T__ act;
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg)(&var->native, val->dw_sint, old_val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_MB)
+ ETHR_SU_DW_NAINT_T__ act;
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_mb)(&var->native, val->dw_sint, old_val->dw_sint);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_WB)
+ ETHR_SU_DW_NAINT_T__ act;
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_wb)(&var->native, val->dw_sint, old_val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RELB)
+ ETHR_SU_DW_NAINT_T__ act;
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_relb)(&var->native, val->dw_sint, old_val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_ACQB)
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_acqb)(&var->native, val->sint, old_val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RB)
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_rb)(&var->native, val->sint, old_val->sint);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG)
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg)(&var->native, val->sint, old_val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_MB)
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_mb)(&var->native, val->sint, old_val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_WB)
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_wb)(&var->native, val->sint, old_val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RELB)
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_relb)(&var->native, val->sint, old_val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+#error "Missing implementation of ethr_dw_atomic_cmpxchg_acqb()!"
+#endif
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ } else { res = ETHR_DW_ATOMIC_FUNC__(cmpxchg_acqb)(var, val, old_val); }
+#endif
+
+ return res;
+}
+
+static ETHR_INLINE int ETHR_DW_ATMC_FUNC__(cmpxchg_relb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val)
+{
+ int res;
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__) {
+#endif
+
+#if defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RELB)
+ ETHR_SU_DW_NAINT_T__ act;
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_relb)(&var->native, val->dw_sint, old_val->dw_sint);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_WB)
+ ETHR_SU_DW_NAINT_T__ act;
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_wb)(&var->native, val->dw_sint, old_val->dw_sint);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG)
+ ETHR_SU_DW_NAINT_T__ act;
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg)(&var->native, val->dw_sint, old_val->dw_sint);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_MB)
+ ETHR_SU_DW_NAINT_T__ act;
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_mb)(&var->native, val->dw_sint, old_val->dw_sint);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RB)
+ ETHR_SU_DW_NAINT_T__ act;
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_rb)(&var->native, val->dw_sint, old_val->dw_sint);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_ACQB)
+ ETHR_SU_DW_NAINT_T__ act;
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_acqb)(&var->native, val->dw_sint, old_val->dw_sint);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RELB)
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_relb)(&var->native, val->sint, old_val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_wb)(&var->native, val->sint, old_val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg)(&var->native, val->sint, old_val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_MB)
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_mb)(&var->native, val->sint, old_val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_rb)(&var->native, val->sint, old_val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_acqb)(&var->native, val->sint, old_val->sint);
+#else
+#error "Missing implementation of ethr_dw_atomic_cmpxchg_relb()!"
+#endif
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ } else { res = ETHR_DW_ATOMIC_FUNC__(cmpxchg_relb)(var, val, old_val); }
+#endif
+
+ return res;
+}
+
+static ETHR_INLINE int ETHR_DW_ATMC_FUNC__(cmpxchg_mb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val)
+{
+ int res;
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__) {
+#endif
+
+#if defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_MB)
+ ETHR_SU_DW_NAINT_T__ act;
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_mb)(&var->native, val->dw_sint, old_val->dw_sint);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RELB)
+ ETHR_SU_DW_NAINT_T__ act;
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_relb)(&var->native, val->dw_sint, old_val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_ACQB)
+ ETHR_SU_DW_NAINT_T__ act;
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_acqb)(&var->native, val->dw_sint, old_val->dw_sint);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_WB)
+ ETHR_SU_DW_NAINT_T__ act;
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_wb)(&var->native, val->dw_sint, old_val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RB)
+ ETHR_SU_DW_NAINT_T__ act;
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg_rb)(&var->native, val->dw_sint, old_val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG)
+ ETHR_SU_DW_NAINT_T__ act;
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ act = ETHR_SU_DW_NATMC_FUNC__(cmpxchg)(&var->native, val->dw_sint, old_val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ res = (act == old_val->dw_sint);
+ old_val->dw_sint = act;
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_MB)
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_mb)(&var->native, val->sint, old_val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RELB)
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_relb)(&var->native, val->sint, old_val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_acqb)(&var->native, val->sint, old_val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_wb)(&var->native, val->sint, old_val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg_rb)(&var->native, val->sint, old_val->sint);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = ETHR_DW_NATMC_FUNC__(cmpxchg)(&var->native, val->sint, old_val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+#error "Missing implementation of ethr_dw_atomic_cmpxchg_mb()!"
+#endif
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ } else { res = ETHR_DW_ATOMIC_FUNC__(cmpxchg_mb)(var, val, old_val); }
+#endif
+
+ return res;
+}
+
+
+/* --- set() --- */
+
+
+static ETHR_INLINE void ETHR_DW_ATMC_FUNC__(set)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__) {
+#endif
+
+#if defined(ETHR_HAVE_SU_DW_NATMC_SET)
+ ETHR_SU_DW_NATMC_FUNC__(set)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET_RB)
+ ETHR_SU_DW_NATMC_FUNC__(set_rb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET_WB)
+ ETHR_SU_DW_NATMC_FUNC__(set_wb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET_ACQB)
+ ETHR_SU_DW_NATMC_FUNC__(set_acqb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET_RELB)
+ ETHR_SU_DW_NATMC_FUNC__(set_relb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET_MB)
+ ETHR_SU_DW_NATMC_FUNC__(set_mb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_DW_NATMC_SET)
+ ETHR_DW_NATMC_FUNC__(set)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_RB)
+ ETHR_DW_NATMC_FUNC__(set_rb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_WB)
+ ETHR_DW_NATMC_FUNC__(set_wb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_ACQB)
+ ETHR_DW_NATMC_FUNC__(set_acqb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_RELB)
+ ETHR_DW_NATMC_FUNC__(set_relb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_MB)
+ ETHR_DW_NATMC_FUNC__(set_mb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG)
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg), &var->native, aval, aval = val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RB)
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_rb), &var->native, aval, aval = val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_WB)
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_wb), &var->native, aval, aval = val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_ACQB)
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_acqb), &var->native, aval, aval = val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RELB)
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_relb), &var->native, aval, aval = val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_MB)
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_mb), &var->native, aval, aval = val->dw_sint);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG)
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RB)
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_rb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_WB)
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_wb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_ACQB)
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_acqb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RELB)
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_relb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_MB)
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_mb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+#else
+#error "Missing implementation of ethr_dw_atomic_set()!"
+#endif
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ } else { ETHR_DW_ATOMIC_FUNC__(set)(var, val); }
+#endif
+
+}
+
+static ETHR_INLINE void ETHR_DW_ATMC_FUNC__(set_rb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__) {
+#endif
+
+#if defined(ETHR_HAVE_SU_DW_NATMC_SET_RB)
+ ETHR_SU_DW_NATMC_FUNC__(set_rb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET)
+ ETHR_SU_DW_NATMC_FUNC__(set)(&var->native, val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET_MB)
+ ETHR_SU_DW_NATMC_FUNC__(set_mb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET_WB)
+ ETHR_SU_DW_NATMC_FUNC__(set_wb)(&var->native, val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET_ACQB)
+ ETHR_SU_DW_NATMC_FUNC__(set_acqb)(&var->native, val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET_RELB)
+ ETHR_SU_DW_NATMC_FUNC__(set_relb)(&var->native, val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_RB)
+ ETHR_DW_NATMC_FUNC__(set_rb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_SET)
+ ETHR_DW_NATMC_FUNC__(set)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_MB)
+ ETHR_DW_NATMC_FUNC__(set_mb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_WB)
+ ETHR_DW_NATMC_FUNC__(set_wb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_ACQB)
+ ETHR_DW_NATMC_FUNC__(set_acqb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_RELB)
+ ETHR_DW_NATMC_FUNC__(set_relb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RB)
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_rb), &var->native, aval, aval = val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG)
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg), &var->native, aval, aval = val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_MB)
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_mb), &var->native, aval, aval = val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_WB)
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_wb), &var->native, aval, aval = val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_ACQB)
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_acqb), &var->native, aval, aval = val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RELB)
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_relb), &var->native, aval, aval = val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RB)
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_rb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG)
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_MB)
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_mb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_WB)
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_wb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_ACQB)
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_acqb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RELB)
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_relb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+#error "Missing implementation of ethr_dw_atomic_set_rb()!"
+#endif
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ } else { ETHR_DW_ATOMIC_FUNC__(set_rb)(var, val); }
+#endif
+
+}
+
+static ETHR_INLINE void ETHR_DW_ATMC_FUNC__(set_wb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__) {
+#endif
+
+#if defined(ETHR_HAVE_SU_DW_NATMC_SET_WB)
+ ETHR_SU_DW_NATMC_FUNC__(set_wb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_SU_DW_NATMC_FUNC__(set)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET_MB)
+ ETHR_SU_DW_NATMC_FUNC__(set_mb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_SU_DW_NATMC_FUNC__(set_rb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_SU_DW_NATMC_FUNC__(set_acqb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_SU_DW_NATMC_FUNC__(set_relb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_WB)
+ ETHR_DW_NATMC_FUNC__(set_wb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_SET)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_DW_NATMC_FUNC__(set)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_MB)
+ ETHR_DW_NATMC_FUNC__(set_mb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_DW_NATMC_FUNC__(set_rb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_DW_NATMC_FUNC__(set_acqb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_DW_NATMC_FUNC__(set_relb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_WB)
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_wb), &var->native, aval, aval = val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg), &var->native, aval, aval = val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_MB)
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_mb), &var->native, aval, aval = val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_rb), &var->native, aval, aval = val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_acqb), &var->native, aval, aval = val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_relb), &var->native, aval, aval = val->dw_sint);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_WB)
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_wb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_MB)
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_mb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_rb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_acqb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_relb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+#else
+#error "Missing implementation of ethr_dw_atomic_set_wb()!"
+#endif
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ } else { ETHR_DW_ATOMIC_FUNC__(set_wb)(var, val); }
+#endif
+
+}
+
+static ETHR_INLINE void ETHR_DW_ATMC_FUNC__(set_acqb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__) {
+#endif
+
+#if defined(ETHR_HAVE_SU_DW_NATMC_SET_ACQB)
+ ETHR_SU_DW_NATMC_FUNC__(set_acqb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET_RB)
+ ETHR_SU_DW_NATMC_FUNC__(set_rb)(&var->native, val->dw_sint);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET)
+ ETHR_SU_DW_NATMC_FUNC__(set)(&var->native, val->dw_sint);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET_MB)
+ ETHR_SU_DW_NATMC_FUNC__(set_mb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET_WB)
+ ETHR_SU_DW_NATMC_FUNC__(set_wb)(&var->native, val->dw_sint);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET_RELB)
+ ETHR_SU_DW_NATMC_FUNC__(set_relb)(&var->native, val->dw_sint);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_ACQB)
+ ETHR_DW_NATMC_FUNC__(set_acqb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_RB)
+ ETHR_DW_NATMC_FUNC__(set_rb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_SET)
+ ETHR_DW_NATMC_FUNC__(set)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_MB)
+ ETHR_DW_NATMC_FUNC__(set_mb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_WB)
+ ETHR_DW_NATMC_FUNC__(set_wb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_RELB)
+ ETHR_DW_NATMC_FUNC__(set_relb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_ACQB)
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_acqb), &var->native, aval, aval = val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RB)
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_rb), &var->native, aval, aval = val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG)
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg), &var->native, aval, aval = val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_MB)
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_mb), &var->native, aval, aval = val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_WB)
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_wb), &var->native, aval, aval = val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RELB)
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_relb), &var->native, aval, aval = val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_ACQB)
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_acqb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RB)
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_rb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG)
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_MB)
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_mb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_WB)
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_wb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RELB)
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_relb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+#error "Missing implementation of ethr_dw_atomic_set_acqb()!"
+#endif
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ } else { ETHR_DW_ATOMIC_FUNC__(set_acqb)(var, val); }
+#endif
+
+}
+
+static ETHR_INLINE void ETHR_DW_ATMC_FUNC__(set_relb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__) {
+#endif
+
+#if defined(ETHR_HAVE_SU_DW_NATMC_SET_RELB)
+ ETHR_SU_DW_NATMC_FUNC__(set_relb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET_WB)
+ ETHR_MEMBAR(ETHR_LoadStore);
+ ETHR_SU_DW_NATMC_FUNC__(set_wb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_SU_DW_NATMC_FUNC__(set)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET_MB)
+ ETHR_SU_DW_NATMC_FUNC__(set_mb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET_RB)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_SU_DW_NATMC_FUNC__(set_rb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET_ACQB)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_SU_DW_NATMC_FUNC__(set_acqb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_RELB)
+ ETHR_DW_NATMC_FUNC__(set_relb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_WB)
+ ETHR_MEMBAR(ETHR_LoadStore);
+ ETHR_DW_NATMC_FUNC__(set_wb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_SET)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_DW_NATMC_FUNC__(set)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_MB)
+ ETHR_DW_NATMC_FUNC__(set_mb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_RB)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_DW_NATMC_FUNC__(set_rb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_ACQB)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_DW_NATMC_FUNC__(set_acqb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RELB)
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_relb), &var->native, aval, aval = val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_wb), &var->native, aval, aval = val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg), &var->native, aval, aval = val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_MB)
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_mb), &var->native, aval, aval = val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_rb), &var->native, aval, aval = val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_acqb), &var->native, aval, aval = val->dw_sint);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RELB)
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_relb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_wb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_MB)
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_mb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_rb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_acqb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+#else
+#error "Missing implementation of ethr_dw_atomic_set_relb()!"
+#endif
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ } else { ETHR_DW_ATOMIC_FUNC__(set_relb)(var, val); }
+#endif
+
+}
+
+static ETHR_INLINE void ETHR_DW_ATMC_FUNC__(set_mb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__) {
+#endif
+
+#if defined(ETHR_HAVE_SU_DW_NATMC_SET_MB)
+ ETHR_SU_DW_NATMC_FUNC__(set_mb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET_RELB)
+ ETHR_SU_DW_NATMC_FUNC__(set_relb)(&var->native, val->dw_sint);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET_ACQB)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_SU_DW_NATMC_FUNC__(set_acqb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET_WB)
+ ETHR_MEMBAR(ETHR_LoadStore);
+ ETHR_SU_DW_NATMC_FUNC__(set_wb)(&var->native, val->dw_sint);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET_RB)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_SU_DW_NATMC_FUNC__(set_rb)(&var->native, val->dw_sint);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_SET)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_SU_DW_NATMC_FUNC__(set)(&var->native, val->dw_sint);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_MB)
+ ETHR_DW_NATMC_FUNC__(set_mb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_RELB)
+ ETHR_DW_NATMC_FUNC__(set_relb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_ACQB)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_DW_NATMC_FUNC__(set_acqb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_WB)
+ ETHR_MEMBAR(ETHR_LoadStore);
+ ETHR_DW_NATMC_FUNC__(set_wb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_SET_RB)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_DW_NATMC_FUNC__(set_rb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_SET)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_DW_NATMC_FUNC__(set)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_MB)
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_mb), &var->native, aval, aval = val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RELB)
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_relb), &var->native, aval, aval = val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_acqb), &var->native, aval, aval = val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_wb), &var->native, aval, aval = val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg_rb), &var->native, aval, aval = val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_SU_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_SU_DW_NATMC_FUNC__(cmpxchg), &var->native, aval, aval = val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_MB)
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_mb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RELB)
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_relb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_acqb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_wb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg_rb), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_DW_NATMC_CMPXCHG_FALLBACK__(ETHR_DW_NATMC_FUNC__(cmpxchg), &var->native, aval, aval.sint[0] = val->sint[0]; aval.sint[1] = val->sint[1]);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+#error "Missing implementation of ethr_dw_atomic_set_mb()!"
+#endif
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ } else { ETHR_DW_ATOMIC_FUNC__(set_mb)(var, val); }
+#endif
+
+}
+
+
+/* --- read() --- */
+
+
+static ETHR_INLINE void ETHR_DW_ATMC_FUNC__(read)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__) {
+#endif
+
+#if defined(ETHR_HAVE_SU_DW_NATMC_READ)
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read)(&var->native);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_RB)
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_rb)(&var->native);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_WB)
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_wb)(&var->native);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_ACQB)
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_acqb)(&var->native);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_RELB)
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_relb)(&var->native);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_MB)
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_mb)(&var->native);
+#elif defined(ETHR_HAVE_DW_NATMC_READ)
+ ETHR_DW_NATMC_FUNC__(read)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_RB)
+ ETHR_DW_NATMC_FUNC__(read_rb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_WB)
+ ETHR_DW_NATMC_FUNC__(read_wb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_ACQB)
+ ETHR_DW_NATMC_FUNC__(read_acqb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_RELB)
+ ETHR_DW_NATMC_FUNC__(read_relb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_MB)
+ ETHR_DW_NATMC_FUNC__(read_mb)(&var->native, val->sint);
+#else
+ ethr_dw_sint_t tmp;
+ tmp.sint[0] = ETHR_UNUSUAL_SINT_VAL__;
+ tmp.sint[1] = ETHR_UNUSUAL_SINT_VAL__;
+ val->sint[0] = ETHR_UNUSUAL_SINT_VAL__;
+ val->sint[1] = ETHR_UNUSUAL_SINT_VAL__;
+ (void) ETHR_DW_ATMC_FUNC__(cmpxchg)(var, &tmp, val);
+#endif
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ } else { ETHR_DW_ATOMIC_FUNC__(read)(var, val); }
+#endif
+
+}
+
+static ETHR_INLINE void ETHR_DW_ATMC_FUNC__(read_rb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__) {
+#endif
+
+#if defined(ETHR_HAVE_SU_DW_NATMC_READ_RB)
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_rb)(&var->native);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ)
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read)(&var->native);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_MB)
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_mb)(&var->native);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_WB)
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_wb)(&var->native);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_ACQB)
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_acqb)(&var->native);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_RELB)
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_relb)(&var->native);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_RB)
+ ETHR_DW_NATMC_FUNC__(read_rb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_READ)
+ ETHR_DW_NATMC_FUNC__(read)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_MB)
+ ETHR_DW_NATMC_FUNC__(read_mb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_WB)
+ ETHR_DW_NATMC_FUNC__(read_wb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_ACQB)
+ ETHR_DW_NATMC_FUNC__(read_acqb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_RELB)
+ ETHR_DW_NATMC_FUNC__(read_relb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ ethr_dw_sint_t tmp;
+ tmp.sint[0] = ETHR_UNUSUAL_SINT_VAL__;
+ tmp.sint[1] = ETHR_UNUSUAL_SINT_VAL__;
+ val->sint[0] = ETHR_UNUSUAL_SINT_VAL__;
+ val->sint[1] = ETHR_UNUSUAL_SINT_VAL__;
+ (void) ETHR_DW_ATMC_FUNC__(cmpxchg_rb)(var, &tmp, val);
+#endif
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ } else { ETHR_DW_ATOMIC_FUNC__(read_rb)(var, val); }
+#endif
+
+}
+
+static ETHR_INLINE void ETHR_DW_ATMC_FUNC__(read_wb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__) {
+#endif
+
+#if defined(ETHR_HAVE_SU_DW_NATMC_READ_WB)
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_wb)(&var->native);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read)(&var->native);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_MB)
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_mb)(&var->native);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_rb)(&var->native);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_acqb)(&var->native);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_relb)(&var->native);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_WB)
+ ETHR_DW_NATMC_FUNC__(read_wb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_READ)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_DW_NATMC_FUNC__(read)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_MB)
+ ETHR_DW_NATMC_FUNC__(read_mb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_DW_NATMC_FUNC__(read_rb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_DW_NATMC_FUNC__(read_acqb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_DW_NATMC_FUNC__(read_relb)(&var->native, val->sint);
+#else
+ ethr_dw_sint_t tmp;
+ tmp.sint[0] = ETHR_UNUSUAL_SINT_VAL__;
+ tmp.sint[1] = ETHR_UNUSUAL_SINT_VAL__;
+ val->sint[0] = ETHR_UNUSUAL_SINT_VAL__;
+ val->sint[1] = ETHR_UNUSUAL_SINT_VAL__;
+ (void) ETHR_DW_ATMC_FUNC__(cmpxchg_wb)(var, &tmp, val);
+#endif
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ } else { ETHR_DW_ATOMIC_FUNC__(read_wb)(var, val); }
+#endif
+
+}
+
+static ETHR_INLINE void ETHR_DW_ATMC_FUNC__(read_acqb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__) {
+#endif
+
+#if defined(ETHR_HAVE_SU_DW_NATMC_READ_ACQB)
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_acqb)(&var->native);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_RB)
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_rb)(&var->native);
+ ETHR_MEMBAR(ETHR_LoadStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ)
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read)(&var->native);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_MB)
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_mb)(&var->native);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_WB)
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_wb)(&var->native);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_RELB)
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_relb)(&var->native);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_ACQB)
+ ETHR_DW_NATMC_FUNC__(read_acqb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_RB)
+ ETHR_DW_NATMC_FUNC__(read_rb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadStore);
+#elif defined(ETHR_HAVE_DW_NATMC_READ)
+ ETHR_DW_NATMC_FUNC__(read)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_MB)
+ ETHR_DW_NATMC_FUNC__(read_mb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_WB)
+ ETHR_DW_NATMC_FUNC__(read_wb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_RELB)
+ ETHR_DW_NATMC_FUNC__(read_relb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#else
+ ethr_dw_sint_t tmp;
+ tmp.sint[0] = ETHR_UNUSUAL_SINT_VAL__;
+ tmp.sint[1] = ETHR_UNUSUAL_SINT_VAL__;
+ val->sint[0] = ETHR_UNUSUAL_SINT_VAL__;
+ val->sint[1] = ETHR_UNUSUAL_SINT_VAL__;
+ (void) ETHR_DW_ATMC_FUNC__(cmpxchg_acqb)(var, &tmp, val);
+#endif
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ } else { ETHR_DW_ATOMIC_FUNC__(read_acqb)(var, val); }
+#endif
+
+}
+
+static ETHR_INLINE void ETHR_DW_ATMC_FUNC__(read_relb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__) {
+#endif
+
+#if defined(ETHR_HAVE_SU_DW_NATMC_READ_RELB)
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_relb)(&var->native);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_wb)(&var->native);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read)(&var->native);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_MB)
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_mb)(&var->native);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_rb)(&var->native);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_acqb)(&var->native);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_RELB)
+ ETHR_DW_NATMC_FUNC__(read_relb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_DW_NATMC_FUNC__(read_wb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_READ)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_DW_NATMC_FUNC__(read)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_MB)
+ ETHR_DW_NATMC_FUNC__(read_mb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_DW_NATMC_FUNC__(read_rb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_DW_NATMC_FUNC__(read_acqb)(&var->native, val->sint);
+#else
+ ethr_dw_sint_t tmp;
+ tmp.sint[0] = ETHR_UNUSUAL_SINT_VAL__;
+ tmp.sint[1] = ETHR_UNUSUAL_SINT_VAL__;
+ val->sint[0] = ETHR_UNUSUAL_SINT_VAL__;
+ val->sint[1] = ETHR_UNUSUAL_SINT_VAL__;
+ (void) ETHR_DW_ATMC_FUNC__(cmpxchg_relb)(var, &tmp, val);
+#endif
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ } else { ETHR_DW_ATOMIC_FUNC__(read_relb)(var, val); }
+#endif
+
+}
+
+static ETHR_INLINE void ETHR_DW_ATMC_FUNC__(read_mb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__) {
+#endif
+
+#if defined(ETHR_HAVE_SU_DW_NATMC_READ_MB)
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_mb)(&var->native);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_RELB)
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_relb)(&var->native);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_acqb)(&var->native);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_wb)(&var->native);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read_rb)(&var->native);
+ ETHR_MEMBAR(ETHR_LoadStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_READ)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ val->dw_sint = ETHR_SU_DW_NATMC_FUNC__(read)(&var->native);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_MB)
+ ETHR_DW_NATMC_FUNC__(read_mb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_RELB)
+ ETHR_DW_NATMC_FUNC__(read_relb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_DW_NATMC_FUNC__(read_acqb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_DW_NATMC_FUNC__(read_wb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#elif defined(ETHR_HAVE_DW_NATMC_READ_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_DW_NATMC_FUNC__(read_rb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadStore);
+#elif defined(ETHR_HAVE_DW_NATMC_READ)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_DW_NATMC_FUNC__(read)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#else
+ ethr_dw_sint_t tmp;
+ tmp.sint[0] = ETHR_UNUSUAL_SINT_VAL__;
+ tmp.sint[1] = ETHR_UNUSUAL_SINT_VAL__;
+ val->sint[0] = ETHR_UNUSUAL_SINT_VAL__;
+ val->sint[1] = ETHR_UNUSUAL_SINT_VAL__;
+ (void) ETHR_DW_ATMC_FUNC__(cmpxchg_mb)(var, &tmp, val);
+#endif
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ } else { ETHR_DW_ATOMIC_FUNC__(read_mb)(var, val); }
+#endif
+
+}
+
+
+/* --- init() --- */
+
+
+static ETHR_INLINE void ETHR_DW_ATMC_FUNC__(init)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__) {
+#endif
+
+#if defined(ETHR_HAVE_SU_DW_NATMC_INIT)
+ ETHR_SU_DW_NATMC_FUNC__(init)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT_RB)
+ ETHR_SU_DW_NATMC_FUNC__(init_rb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT_WB)
+ ETHR_SU_DW_NATMC_FUNC__(init_wb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT_ACQB)
+ ETHR_SU_DW_NATMC_FUNC__(init_acqb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT_RELB)
+ ETHR_SU_DW_NATMC_FUNC__(init_relb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT_MB)
+ ETHR_SU_DW_NATMC_FUNC__(init_mb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT)
+ ETHR_DW_NATMC_FUNC__(init)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_RB)
+ ETHR_DW_NATMC_FUNC__(init_rb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_WB)
+ ETHR_DW_NATMC_FUNC__(init_wb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_ACQB)
+ ETHR_DW_NATMC_FUNC__(init_acqb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_RELB)
+ ETHR_DW_NATMC_FUNC__(init_relb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_MB)
+ ETHR_DW_NATMC_FUNC__(init_mb)(&var->native, val->sint);
+#else
+ ETHR_DW_ATMC_FUNC__(set)(var, val);
+#endif
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ } else { ETHR_DW_ATOMIC_FUNC__(init)(var, val); }
+#endif
+
+}
+
+static ETHR_INLINE void ETHR_DW_ATMC_FUNC__(init_rb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__) {
+#endif
+
+#if defined(ETHR_HAVE_SU_DW_NATMC_INIT_RB)
+ ETHR_SU_DW_NATMC_FUNC__(init_rb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT)
+ ETHR_SU_DW_NATMC_FUNC__(init)(&var->native, val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT_MB)
+ ETHR_SU_DW_NATMC_FUNC__(init_mb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT_WB)
+ ETHR_SU_DW_NATMC_FUNC__(init_wb)(&var->native, val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT_ACQB)
+ ETHR_SU_DW_NATMC_FUNC__(init_acqb)(&var->native, val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT_RELB)
+ ETHR_SU_DW_NATMC_FUNC__(init_relb)(&var->native, val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_RB)
+ ETHR_DW_NATMC_FUNC__(init_rb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT)
+ ETHR_DW_NATMC_FUNC__(init)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_MB)
+ ETHR_DW_NATMC_FUNC__(init_mb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_WB)
+ ETHR_DW_NATMC_FUNC__(init_wb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_ACQB)
+ ETHR_DW_NATMC_FUNC__(init_acqb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_RELB)
+ ETHR_DW_NATMC_FUNC__(init_relb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ ETHR_DW_ATMC_FUNC__(set_rb)(var, val);
+#endif
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ } else { ETHR_DW_ATOMIC_FUNC__(init_rb)(var, val); }
+#endif
+
+}
+
+static ETHR_INLINE void ETHR_DW_ATMC_FUNC__(init_wb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__) {
+#endif
+
+#if defined(ETHR_HAVE_SU_DW_NATMC_INIT_WB)
+ ETHR_SU_DW_NATMC_FUNC__(init_wb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_SU_DW_NATMC_FUNC__(init)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT_MB)
+ ETHR_SU_DW_NATMC_FUNC__(init_mb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_SU_DW_NATMC_FUNC__(init_rb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_SU_DW_NATMC_FUNC__(init_acqb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_SU_DW_NATMC_FUNC__(init_relb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_WB)
+ ETHR_DW_NATMC_FUNC__(init_wb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_DW_NATMC_FUNC__(init)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_MB)
+ ETHR_DW_NATMC_FUNC__(init_mb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_DW_NATMC_FUNC__(init_rb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_DW_NATMC_FUNC__(init_acqb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_DW_NATMC_FUNC__(init_relb)(&var->native, val->sint);
+#else
+ ETHR_DW_ATMC_FUNC__(set_wb)(var, val);
+#endif
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ } else { ETHR_DW_ATOMIC_FUNC__(init_wb)(var, val); }
+#endif
+
+}
+
+static ETHR_INLINE void ETHR_DW_ATMC_FUNC__(init_acqb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__) {
+#endif
+
+#if defined(ETHR_HAVE_SU_DW_NATMC_INIT_ACQB)
+ ETHR_SU_DW_NATMC_FUNC__(init_acqb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT_RB)
+ ETHR_SU_DW_NATMC_FUNC__(init_rb)(&var->native, val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT)
+ ETHR_SU_DW_NATMC_FUNC__(init)(&var->native, val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT_MB)
+ ETHR_SU_DW_NATMC_FUNC__(init_mb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT_WB)
+ ETHR_SU_DW_NATMC_FUNC__(init_wb)(&var->native, val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT_RELB)
+ ETHR_SU_DW_NATMC_FUNC__(init_relb)(&var->native, val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_ACQB)
+ ETHR_DW_NATMC_FUNC__(init_acqb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_RB)
+ ETHR_DW_NATMC_FUNC__(init_rb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT)
+ ETHR_DW_NATMC_FUNC__(init)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_MB)
+ ETHR_DW_NATMC_FUNC__(init_mb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_WB)
+ ETHR_DW_NATMC_FUNC__(init_wb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_RELB)
+ ETHR_DW_NATMC_FUNC__(init_relb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_DW_ATMC_FUNC__(set_acqb)(var, val);
+#endif
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ } else { ETHR_DW_ATOMIC_FUNC__(init_acqb)(var, val); }
+#endif
+
+}
+
+static ETHR_INLINE void ETHR_DW_ATMC_FUNC__(init_relb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__) {
+#endif
+
+#if defined(ETHR_HAVE_SU_DW_NATMC_INIT_RELB)
+ ETHR_SU_DW_NATMC_FUNC__(init_relb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad);
+ ETHR_SU_DW_NATMC_FUNC__(init_wb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_SU_DW_NATMC_FUNC__(init)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT_MB)
+ ETHR_SU_DW_NATMC_FUNC__(init_mb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_SU_DW_NATMC_FUNC__(init_rb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_SU_DW_NATMC_FUNC__(init_acqb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_RELB)
+ ETHR_DW_NATMC_FUNC__(init_relb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad);
+ ETHR_DW_NATMC_FUNC__(init_wb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_DW_NATMC_FUNC__(init)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_MB)
+ ETHR_DW_NATMC_FUNC__(init_mb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_DW_NATMC_FUNC__(init_rb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_DW_NATMC_FUNC__(init_acqb)(&var->native, val->sint);
+#else
+ ETHR_DW_ATMC_FUNC__(set_relb)(var, val);
+#endif
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ } else { ETHR_DW_ATOMIC_FUNC__(init_relb)(var, val); }
+#endif
+
+}
+
+static ETHR_INLINE void ETHR_DW_ATMC_FUNC__(init_mb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__) {
+#endif
+
+#if defined(ETHR_HAVE_SU_DW_NATMC_INIT_MB)
+ ETHR_SU_DW_NATMC_FUNC__(init_mb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT_RELB)
+ ETHR_SU_DW_NATMC_FUNC__(init_relb)(&var->native, val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_SU_DW_NATMC_FUNC__(init_acqb)(&var->native, val->dw_sint);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad);
+ ETHR_SU_DW_NATMC_FUNC__(init_wb)(&var->native, val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_SU_DW_NATMC_FUNC__(init_rb)(&var->native, val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_SU_DW_NATMC_INIT)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_SU_DW_NATMC_FUNC__(init)(&var->native, val->dw_sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_MB)
+ ETHR_DW_NATMC_FUNC__(init_mb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_RELB)
+ ETHR_DW_NATMC_FUNC__(init_relb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_DW_NATMC_FUNC__(init_acqb)(&var->native, val->sint);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad);
+ ETHR_DW_NATMC_FUNC__(init_wb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_DW_NATMC_FUNC__(init_rb)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_DW_NATMC_INIT)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_DW_NATMC_FUNC__(init)(&var->native, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_DW_ATMC_FUNC__(set_mb)(var, val);
+#endif
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ } else { ETHR_DW_ATOMIC_FUNC__(init_mb)(var, val); }
+#endif
+
+}
+
+#endif /* ETHR_DW_ATMC_INLINE__ */
+
+
+/* ---------- Word size atomic implementation ---------- */
+
+
+#ifdef ETHR_NEED_ATMC_PROTOTYPES__
+ethr_sint_t *ethr_atomic_addr(ethr_atomic_t *var);
+ethr_sint_t ethr_atomic_cmpxchg(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val);
+ethr_sint_t ethr_atomic_cmpxchg_rb(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val);
+ethr_sint_t ethr_atomic_cmpxchg_wb(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val);
+ethr_sint_t ethr_atomic_cmpxchg_acqb(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val);
+ethr_sint_t ethr_atomic_cmpxchg_relb(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val);
+ethr_sint_t ethr_atomic_cmpxchg_mb(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val);
+ethr_sint_t ethr_atomic_xchg(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_xchg_rb(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_xchg_wb(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_xchg_acqb(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_xchg_relb(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_xchg_mb(ethr_atomic_t *var, ethr_sint_t val);
+void ethr_atomic_set(ethr_atomic_t *var, ethr_sint_t val);
+void ethr_atomic_set_rb(ethr_atomic_t *var, ethr_sint_t val);
+void ethr_atomic_set_wb(ethr_atomic_t *var, ethr_sint_t val);
+void ethr_atomic_set_acqb(ethr_atomic_t *var, ethr_sint_t val);
+void ethr_atomic_set_relb(ethr_atomic_t *var, ethr_sint_t val);
+void ethr_atomic_set_mb(ethr_atomic_t *var, ethr_sint_t val);
+void ethr_atomic_init(ethr_atomic_t *var, ethr_sint_t val);
+void ethr_atomic_init_rb(ethr_atomic_t *var, ethr_sint_t val);
+void ethr_atomic_init_wb(ethr_atomic_t *var, ethr_sint_t val);
+void ethr_atomic_init_acqb(ethr_atomic_t *var, ethr_sint_t val);
+void ethr_atomic_init_relb(ethr_atomic_t *var, ethr_sint_t val);
+void ethr_atomic_init_mb(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_add_read(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_add_read_rb(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_add_read_wb(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_add_read_acqb(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_add_read_relb(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_add_read_mb(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_read(ethr_atomic_t *var);
+ethr_sint_t ethr_atomic_read_rb(ethr_atomic_t *var);
+ethr_sint_t ethr_atomic_read_wb(ethr_atomic_t *var);
+ethr_sint_t ethr_atomic_read_acqb(ethr_atomic_t *var);
+ethr_sint_t ethr_atomic_read_relb(ethr_atomic_t *var);
+ethr_sint_t ethr_atomic_read_mb(ethr_atomic_t *var);
+ethr_sint_t ethr_atomic_inc_read(ethr_atomic_t *var);
+ethr_sint_t ethr_atomic_inc_read_rb(ethr_atomic_t *var);
+ethr_sint_t ethr_atomic_inc_read_wb(ethr_atomic_t *var);
+ethr_sint_t ethr_atomic_inc_read_acqb(ethr_atomic_t *var);
+ethr_sint_t ethr_atomic_inc_read_relb(ethr_atomic_t *var);
+ethr_sint_t ethr_atomic_inc_read_mb(ethr_atomic_t *var);
+ethr_sint_t ethr_atomic_dec_read(ethr_atomic_t *var);
+ethr_sint_t ethr_atomic_dec_read_rb(ethr_atomic_t *var);
+ethr_sint_t ethr_atomic_dec_read_wb(ethr_atomic_t *var);
+ethr_sint_t ethr_atomic_dec_read_acqb(ethr_atomic_t *var);
+ethr_sint_t ethr_atomic_dec_read_relb(ethr_atomic_t *var);
+ethr_sint_t ethr_atomic_dec_read_mb(ethr_atomic_t *var);
+void ethr_atomic_add(ethr_atomic_t *var, ethr_sint_t val);
+void ethr_atomic_add_rb(ethr_atomic_t *var, ethr_sint_t val);
+void ethr_atomic_add_wb(ethr_atomic_t *var, ethr_sint_t val);
+void ethr_atomic_add_acqb(ethr_atomic_t *var, ethr_sint_t val);
+void ethr_atomic_add_relb(ethr_atomic_t *var, ethr_sint_t val);
+void ethr_atomic_add_mb(ethr_atomic_t *var, ethr_sint_t val);
+void ethr_atomic_inc(ethr_atomic_t *var);
+void ethr_atomic_inc_rb(ethr_atomic_t *var);
+void ethr_atomic_inc_wb(ethr_atomic_t *var);
+void ethr_atomic_inc_acqb(ethr_atomic_t *var);
+void ethr_atomic_inc_relb(ethr_atomic_t *var);
+void ethr_atomic_inc_mb(ethr_atomic_t *var);
+void ethr_atomic_dec(ethr_atomic_t *var);
+void ethr_atomic_dec_rb(ethr_atomic_t *var);
+void ethr_atomic_dec_wb(ethr_atomic_t *var);
+void ethr_atomic_dec_acqb(ethr_atomic_t *var);
+void ethr_atomic_dec_relb(ethr_atomic_t *var);
+void ethr_atomic_dec_mb(ethr_atomic_t *var);
+ethr_sint_t ethr_atomic_read_band(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_read_band_rb(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_read_band_wb(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_read_band_acqb(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_read_band_relb(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_read_band_mb(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_read_bor(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_read_bor_rb(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_read_bor_wb(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_read_bor_acqb(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_read_bor_relb(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_read_bor_mb(ethr_atomic_t *var, ethr_sint_t val);
+#endif /* ETHR_NEED_ATMC_PROTOTYPES__ */
+
+#if (defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS) \
+ && (defined(ETHR_ATMC_INLINE__) || defined(ETHR_ATOMIC_IMPL__)))
+
+#if !defined(ETHR_NATMC_BITS__)
+# error "Missing native atomic implementation"
+#elif ETHR_NATMC_BITS__ == 64
+# undef ETHR_HAVE_NATMC_CMPXCHG
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG
+# define ETHR_HAVE_NATMC_CMPXCHG 1
+# endif
+# undef ETHR_HAVE_NATMC_CMPXCHG_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_RB
+# define ETHR_HAVE_NATMC_CMPXCHG_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_CMPXCHG_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_WB
+# define ETHR_HAVE_NATMC_CMPXCHG_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_CMPXCHG_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_ACQB
+# define ETHR_HAVE_NATMC_CMPXCHG_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_CMPXCHG_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_RELB
+# define ETHR_HAVE_NATMC_CMPXCHG_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_CMPXCHG_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_MB
+# define ETHR_HAVE_NATMC_CMPXCHG_MB 1
+# endif
+# undef ETHR_HAVE_NATMC_XCHG
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_XCHG
+# define ETHR_HAVE_NATMC_XCHG 1
+# endif
+# undef ETHR_HAVE_NATMC_XCHG_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_XCHG_RB
+# define ETHR_HAVE_NATMC_XCHG_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_XCHG_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_XCHG_WB
+# define ETHR_HAVE_NATMC_XCHG_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_XCHG_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_XCHG_ACQB
+# define ETHR_HAVE_NATMC_XCHG_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_XCHG_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_XCHG_RELB
+# define ETHR_HAVE_NATMC_XCHG_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_XCHG_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_XCHG_MB
+# define ETHR_HAVE_NATMC_XCHG_MB 1
+# endif
+# undef ETHR_HAVE_NATMC_SET
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET
+# define ETHR_HAVE_NATMC_SET 1
+# endif
+# undef ETHR_HAVE_NATMC_SET_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET_RB
+# define ETHR_HAVE_NATMC_SET_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_SET_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET_WB
+# define ETHR_HAVE_NATMC_SET_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_SET_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET_ACQB
+# define ETHR_HAVE_NATMC_SET_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_SET_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET_RELB
+# define ETHR_HAVE_NATMC_SET_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_SET_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET_MB
+# define ETHR_HAVE_NATMC_SET_MB 1
+# endif
+# undef ETHR_HAVE_NATMC_INIT
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INIT
+# define ETHR_HAVE_NATMC_INIT 1
+# endif
+# undef ETHR_HAVE_NATMC_INIT_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INIT_RB
+# define ETHR_HAVE_NATMC_INIT_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_INIT_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INIT_WB
+# define ETHR_HAVE_NATMC_INIT_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_INIT_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INIT_ACQB
+# define ETHR_HAVE_NATMC_INIT_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_INIT_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INIT_RELB
+# define ETHR_HAVE_NATMC_INIT_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_INIT_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INIT_MB
+# define ETHR_HAVE_NATMC_INIT_MB 1
+# endif
+# undef ETHR_HAVE_NATMC_ADD_RETURN
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RETURN
+# define ETHR_HAVE_NATMC_ADD_RETURN 1
+# endif
+# undef ETHR_HAVE_NATMC_ADD_RETURN_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RETURN_RB
+# define ETHR_HAVE_NATMC_ADD_RETURN_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_ADD_RETURN_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RETURN_WB
+# define ETHR_HAVE_NATMC_ADD_RETURN_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_ADD_RETURN_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RETURN_ACQB
+# define ETHR_HAVE_NATMC_ADD_RETURN_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_ADD_RETURN_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RETURN_RELB
+# define ETHR_HAVE_NATMC_ADD_RETURN_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_ADD_RETURN_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RETURN_MB
+# define ETHR_HAVE_NATMC_ADD_RETURN_MB 1
+# endif
+# undef ETHR_HAVE_NATMC_READ
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ
+# define ETHR_HAVE_NATMC_READ 1
+# endif
+# undef ETHR_HAVE_NATMC_READ_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ_RB
+# define ETHR_HAVE_NATMC_READ_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_READ_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ_WB
+# define ETHR_HAVE_NATMC_READ_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_READ_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ_ACQB
+# define ETHR_HAVE_NATMC_READ_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_READ_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ_RELB
+# define ETHR_HAVE_NATMC_READ_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_READ_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ_MB
+# define ETHR_HAVE_NATMC_READ_MB 1
+# endif
+# undef ETHR_HAVE_NATMC_INC_RETURN
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RETURN
+# define ETHR_HAVE_NATMC_INC_RETURN 1
+# endif
+# undef ETHR_HAVE_NATMC_INC_RETURN_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RETURN_RB
+# define ETHR_HAVE_NATMC_INC_RETURN_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_INC_RETURN_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RETURN_WB
+# define ETHR_HAVE_NATMC_INC_RETURN_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_INC_RETURN_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RETURN_ACQB
+# define ETHR_HAVE_NATMC_INC_RETURN_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_INC_RETURN_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RETURN_RELB
+# define ETHR_HAVE_NATMC_INC_RETURN_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_INC_RETURN_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RETURN_MB
+# define ETHR_HAVE_NATMC_INC_RETURN_MB 1
+# endif
+# undef ETHR_HAVE_NATMC_DEC_RETURN
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RETURN
+# define ETHR_HAVE_NATMC_DEC_RETURN 1
+# endif
+# undef ETHR_HAVE_NATMC_DEC_RETURN_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RETURN_RB
+# define ETHR_HAVE_NATMC_DEC_RETURN_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_DEC_RETURN_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RETURN_WB
+# define ETHR_HAVE_NATMC_DEC_RETURN_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_DEC_RETURN_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RETURN_ACQB
+# define ETHR_HAVE_NATMC_DEC_RETURN_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_DEC_RETURN_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RETURN_RELB
+# define ETHR_HAVE_NATMC_DEC_RETURN_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_DEC_RETURN_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RETURN_MB
+# define ETHR_HAVE_NATMC_DEC_RETURN_MB 1
+# endif
+# undef ETHR_HAVE_NATMC_ADD
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD
+# define ETHR_HAVE_NATMC_ADD 1
+# endif
+# undef ETHR_HAVE_NATMC_ADD_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RB
+# define ETHR_HAVE_NATMC_ADD_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_ADD_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_WB
+# define ETHR_HAVE_NATMC_ADD_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_ADD_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_ACQB
+# define ETHR_HAVE_NATMC_ADD_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_ADD_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RELB
+# define ETHR_HAVE_NATMC_ADD_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_ADD_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_MB
+# define ETHR_HAVE_NATMC_ADD_MB 1
+# endif
+# undef ETHR_HAVE_NATMC_INC
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC
+# define ETHR_HAVE_NATMC_INC 1
+# endif
+# undef ETHR_HAVE_NATMC_INC_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RB
+# define ETHR_HAVE_NATMC_INC_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_INC_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_WB
+# define ETHR_HAVE_NATMC_INC_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_INC_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_ACQB
+# define ETHR_HAVE_NATMC_INC_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_INC_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RELB
+# define ETHR_HAVE_NATMC_INC_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_INC_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_MB
+# define ETHR_HAVE_NATMC_INC_MB 1
+# endif
+# undef ETHR_HAVE_NATMC_DEC
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC
+# define ETHR_HAVE_NATMC_DEC 1
+# endif
+# undef ETHR_HAVE_NATMC_DEC_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RB
+# define ETHR_HAVE_NATMC_DEC_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_DEC_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_WB
+# define ETHR_HAVE_NATMC_DEC_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_DEC_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_ACQB
+# define ETHR_HAVE_NATMC_DEC_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_DEC_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RELB
+# define ETHR_HAVE_NATMC_DEC_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_DEC_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_MB
+# define ETHR_HAVE_NATMC_DEC_MB 1
+# endif
+# undef ETHR_HAVE_NATMC_AND_RETOLD
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_AND_RETOLD
+# define ETHR_HAVE_NATMC_AND_RETOLD 1
+# endif
+# undef ETHR_HAVE_NATMC_AND_RETOLD_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_AND_RETOLD_RB
+# define ETHR_HAVE_NATMC_AND_RETOLD_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_AND_RETOLD_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_AND_RETOLD_WB
+# define ETHR_HAVE_NATMC_AND_RETOLD_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_AND_RETOLD_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_AND_RETOLD_ACQB
+# define ETHR_HAVE_NATMC_AND_RETOLD_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_AND_RETOLD_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_AND_RETOLD_RELB
+# define ETHR_HAVE_NATMC_AND_RETOLD_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_AND_RETOLD_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_AND_RETOLD_MB
+# define ETHR_HAVE_NATMC_AND_RETOLD_MB 1
+# endif
+# undef ETHR_HAVE_NATMC_OR_RETOLD
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_OR_RETOLD
+# define ETHR_HAVE_NATMC_OR_RETOLD 1
+# endif
+# undef ETHR_HAVE_NATMC_OR_RETOLD_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_OR_RETOLD_RB
+# define ETHR_HAVE_NATMC_OR_RETOLD_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_OR_RETOLD_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_OR_RETOLD_WB
+# define ETHR_HAVE_NATMC_OR_RETOLD_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_OR_RETOLD_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_OR_RETOLD_ACQB
+# define ETHR_HAVE_NATMC_OR_RETOLD_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_OR_RETOLD_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_OR_RETOLD_RELB
+# define ETHR_HAVE_NATMC_OR_RETOLD_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_OR_RETOLD_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_OR_RETOLD_MB
+# define ETHR_HAVE_NATMC_OR_RETOLD_MB 1
+# endif
+#elif ETHR_NATMC_BITS__ == 32
+# undef ETHR_HAVE_NATMC_CMPXCHG
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG
+# define ETHR_HAVE_NATMC_CMPXCHG 1
+# endif
+# undef ETHR_HAVE_NATMC_CMPXCHG_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG_RB
+# define ETHR_HAVE_NATMC_CMPXCHG_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_CMPXCHG_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG_WB
+# define ETHR_HAVE_NATMC_CMPXCHG_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_CMPXCHG_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG_ACQB
+# define ETHR_HAVE_NATMC_CMPXCHG_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_CMPXCHG_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG_RELB
+# define ETHR_HAVE_NATMC_CMPXCHG_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_CMPXCHG_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG_MB
+# define ETHR_HAVE_NATMC_CMPXCHG_MB 1
+# endif
+# undef ETHR_HAVE_NATMC_XCHG
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_XCHG
+# define ETHR_HAVE_NATMC_XCHG 1
+# endif
+# undef ETHR_HAVE_NATMC_XCHG_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_XCHG_RB
+# define ETHR_HAVE_NATMC_XCHG_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_XCHG_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_XCHG_WB
+# define ETHR_HAVE_NATMC_XCHG_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_XCHG_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_XCHG_ACQB
+# define ETHR_HAVE_NATMC_XCHG_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_XCHG_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_XCHG_RELB
+# define ETHR_HAVE_NATMC_XCHG_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_XCHG_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_XCHG_MB
+# define ETHR_HAVE_NATMC_XCHG_MB 1
+# endif
+# undef ETHR_HAVE_NATMC_SET
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET
+# define ETHR_HAVE_NATMC_SET 1
+# endif
+# undef ETHR_HAVE_NATMC_SET_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET_RB
+# define ETHR_HAVE_NATMC_SET_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_SET_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET_WB
+# define ETHR_HAVE_NATMC_SET_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_SET_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET_ACQB
+# define ETHR_HAVE_NATMC_SET_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_SET_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET_RELB
+# define ETHR_HAVE_NATMC_SET_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_SET_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET_MB
+# define ETHR_HAVE_NATMC_SET_MB 1
+# endif
+# undef ETHR_HAVE_NATMC_INIT
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INIT
+# define ETHR_HAVE_NATMC_INIT 1
+# endif
+# undef ETHR_HAVE_NATMC_INIT_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INIT_RB
+# define ETHR_HAVE_NATMC_INIT_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_INIT_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INIT_WB
+# define ETHR_HAVE_NATMC_INIT_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_INIT_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INIT_ACQB
+# define ETHR_HAVE_NATMC_INIT_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_INIT_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INIT_RELB
+# define ETHR_HAVE_NATMC_INIT_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_INIT_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INIT_MB
+# define ETHR_HAVE_NATMC_INIT_MB 1
+# endif
+# undef ETHR_HAVE_NATMC_ADD_RETURN
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RETURN
+# define ETHR_HAVE_NATMC_ADD_RETURN 1
+# endif
+# undef ETHR_HAVE_NATMC_ADD_RETURN_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RETURN_RB
+# define ETHR_HAVE_NATMC_ADD_RETURN_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_ADD_RETURN_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RETURN_WB
+# define ETHR_HAVE_NATMC_ADD_RETURN_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_ADD_RETURN_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RETURN_ACQB
+# define ETHR_HAVE_NATMC_ADD_RETURN_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_ADD_RETURN_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RETURN_RELB
+# define ETHR_HAVE_NATMC_ADD_RETURN_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_ADD_RETURN_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RETURN_MB
+# define ETHR_HAVE_NATMC_ADD_RETURN_MB 1
+# endif
+# undef ETHR_HAVE_NATMC_READ
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ
+# define ETHR_HAVE_NATMC_READ 1
+# endif
+# undef ETHR_HAVE_NATMC_READ_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ_RB
+# define ETHR_HAVE_NATMC_READ_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_READ_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ_WB
+# define ETHR_HAVE_NATMC_READ_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_READ_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ_ACQB
+# define ETHR_HAVE_NATMC_READ_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_READ_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ_RELB
+# define ETHR_HAVE_NATMC_READ_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_READ_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ_MB
+# define ETHR_HAVE_NATMC_READ_MB 1
+# endif
+# undef ETHR_HAVE_NATMC_INC_RETURN
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RETURN
+# define ETHR_HAVE_NATMC_INC_RETURN 1
+# endif
+# undef ETHR_HAVE_NATMC_INC_RETURN_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RETURN_RB
+# define ETHR_HAVE_NATMC_INC_RETURN_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_INC_RETURN_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RETURN_WB
+# define ETHR_HAVE_NATMC_INC_RETURN_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_INC_RETURN_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RETURN_ACQB
+# define ETHR_HAVE_NATMC_INC_RETURN_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_INC_RETURN_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RETURN_RELB
+# define ETHR_HAVE_NATMC_INC_RETURN_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_INC_RETURN_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RETURN_MB
+# define ETHR_HAVE_NATMC_INC_RETURN_MB 1
+# endif
+# undef ETHR_HAVE_NATMC_DEC_RETURN
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RETURN
+# define ETHR_HAVE_NATMC_DEC_RETURN 1
+# endif
+# undef ETHR_HAVE_NATMC_DEC_RETURN_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RETURN_RB
+# define ETHR_HAVE_NATMC_DEC_RETURN_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_DEC_RETURN_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RETURN_WB
+# define ETHR_HAVE_NATMC_DEC_RETURN_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_DEC_RETURN_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RETURN_ACQB
+# define ETHR_HAVE_NATMC_DEC_RETURN_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_DEC_RETURN_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RETURN_RELB
+# define ETHR_HAVE_NATMC_DEC_RETURN_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_DEC_RETURN_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RETURN_MB
+# define ETHR_HAVE_NATMC_DEC_RETURN_MB 1
+# endif
+# undef ETHR_HAVE_NATMC_ADD
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD
+# define ETHR_HAVE_NATMC_ADD 1
+# endif
+# undef ETHR_HAVE_NATMC_ADD_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RB
+# define ETHR_HAVE_NATMC_ADD_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_ADD_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_WB
+# define ETHR_HAVE_NATMC_ADD_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_ADD_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_ACQB
+# define ETHR_HAVE_NATMC_ADD_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_ADD_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RELB
+# define ETHR_HAVE_NATMC_ADD_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_ADD_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_MB
+# define ETHR_HAVE_NATMC_ADD_MB 1
+# endif
+# undef ETHR_HAVE_NATMC_INC
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC
+# define ETHR_HAVE_NATMC_INC 1
+# endif
+# undef ETHR_HAVE_NATMC_INC_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RB
+# define ETHR_HAVE_NATMC_INC_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_INC_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_WB
+# define ETHR_HAVE_NATMC_INC_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_INC_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_ACQB
+# define ETHR_HAVE_NATMC_INC_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_INC_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RELB
+# define ETHR_HAVE_NATMC_INC_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_INC_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_MB
+# define ETHR_HAVE_NATMC_INC_MB 1
+# endif
+# undef ETHR_HAVE_NATMC_DEC
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC
+# define ETHR_HAVE_NATMC_DEC 1
+# endif
+# undef ETHR_HAVE_NATMC_DEC_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RB
+# define ETHR_HAVE_NATMC_DEC_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_DEC_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_WB
+# define ETHR_HAVE_NATMC_DEC_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_DEC_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_ACQB
+# define ETHR_HAVE_NATMC_DEC_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_DEC_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RELB
+# define ETHR_HAVE_NATMC_DEC_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_DEC_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_MB
+# define ETHR_HAVE_NATMC_DEC_MB 1
+# endif
+# undef ETHR_HAVE_NATMC_AND_RETOLD
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_AND_RETOLD
+# define ETHR_HAVE_NATMC_AND_RETOLD 1
+# endif
+# undef ETHR_HAVE_NATMC_AND_RETOLD_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_AND_RETOLD_RB
+# define ETHR_HAVE_NATMC_AND_RETOLD_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_AND_RETOLD_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_AND_RETOLD_WB
+# define ETHR_HAVE_NATMC_AND_RETOLD_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_AND_RETOLD_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_AND_RETOLD_ACQB
+# define ETHR_HAVE_NATMC_AND_RETOLD_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_AND_RETOLD_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_AND_RETOLD_RELB
+# define ETHR_HAVE_NATMC_AND_RETOLD_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_AND_RETOLD_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_AND_RETOLD_MB
+# define ETHR_HAVE_NATMC_AND_RETOLD_MB 1
+# endif
+# undef ETHR_HAVE_NATMC_OR_RETOLD
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_OR_RETOLD
+# define ETHR_HAVE_NATMC_OR_RETOLD 1
+# endif
+# undef ETHR_HAVE_NATMC_OR_RETOLD_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_OR_RETOLD_RB
+# define ETHR_HAVE_NATMC_OR_RETOLD_RB 1
+# endif
+# undef ETHR_HAVE_NATMC_OR_RETOLD_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_OR_RETOLD_WB
+# define ETHR_HAVE_NATMC_OR_RETOLD_WB 1
+# endif
+# undef ETHR_HAVE_NATMC_OR_RETOLD_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_OR_RETOLD_ACQB
+# define ETHR_HAVE_NATMC_OR_RETOLD_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC_OR_RETOLD_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_OR_RETOLD_RELB
+# define ETHR_HAVE_NATMC_OR_RETOLD_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC_OR_RETOLD_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_OR_RETOLD_MB
+# define ETHR_HAVE_NATMC_OR_RETOLD_MB 1
+# endif
+#else
+# error "Invalid native atomic size"
#endif
+#if (!defined(ETHR_HAVE_NATMC_CMPXCHG) \
+ && !defined(ETHR_HAVE_NATMC_CMPXCHG_RB) \
+ && !defined(ETHR_HAVE_NATMC_CMPXCHG_WB) \
+ && !defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB) \
+ && !defined(ETHR_HAVE_NATMC_CMPXCHG_RELB) \
+ && !defined(ETHR_HAVE_NATMC_CMPXCHG_MB))
+# error "No native cmpxchg() op available"
+#endif
+
+
/*
- * --- Pointer size atomics ---------------------------------------------------
+ * Read op used together with cmpxchg() fallback when no native op present.
*/
+#if defined(ETHR_HAVE_NATMC_READ)
+#define ETHR_NATMC_CMPXCHG_FALLBACK_READ__(VAR) \
+ ETHR_NATMC_FUNC__(read)(VAR)
+#elif defined(ETHR_HAVE_NATMC_READ_RB)
+#define ETHR_NATMC_CMPXCHG_FALLBACK_READ__(VAR) \
+ ETHR_NATMC_FUNC__(read_rb)(VAR)
+#elif defined(ETHR_HAVE_NATMC_READ_WB)
+#define ETHR_NATMC_CMPXCHG_FALLBACK_READ__(VAR) \
+ ETHR_NATMC_FUNC__(read_wb)(VAR)
+#elif defined(ETHR_HAVE_NATMC_READ_ACQB)
+#define ETHR_NATMC_CMPXCHG_FALLBACK_READ__(VAR) \
+ ETHR_NATMC_FUNC__(read_acqb)(VAR)
+#elif defined(ETHR_HAVE_NATMC_READ_RELB)
+#define ETHR_NATMC_CMPXCHG_FALLBACK_READ__(VAR) \
+ ETHR_NATMC_FUNC__(read_relb)(VAR)
+#elif defined(ETHR_HAVE_NATMC_READ_MB)
+#define ETHR_NATMC_CMPXCHG_FALLBACK_READ__(VAR) \
+ ETHR_NATMC_FUNC__(read_mb)(VAR)
+#else
+/*
+ * We have no native read() op; guess zero and then use the
+ * the atomics actual value returned from cmpxchg().
+ */
+#define ETHR_NATMC_CMPXCHG_FALLBACK_READ__(VAR) \
+ ((ETHR_NAINT_T__) 0)
+#endif
+
+/*
+ * Native cmpxchg() fallback used when no native op present.
+ */
+#define ETHR_NATMC_CMPXCHG_FALLBACK__(CMPXCHG, VAR, AVAL, OPS) \
+do { \
+ ethr_sint_t AVAL; \
+ ETHR_NAINT_T__ new__, act__, exp__; \
+ act__ = ETHR_NATMC_CMPXCHG_FALLBACK_READ__(VAR); \
+ do { \
+ exp__ = act__; \
+ AVAL = (ethr_sint_t) act__; \
+ { OPS; } \
+ new__ = (ETHR_NAINT_T__) AVAL; \
+ act__ = CMPXCHG(VAR, new__, exp__); \
+ } while (__builtin_expect(act__ != exp__, 0)); \
+} while (0)
+
+
+
+/* --- addr() --- */
-static ETHR_INLINE ethr_sint_t *
-ETHR_INLINE_FUNC_NAME_(ethr_atomic_addr)(ethr_atomic_t *var)
+static ETHR_INLINE ethr_sint_t *ETHR_ATMC_FUNC__(addr)(ethr_atomic_t *var)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
return (ethr_sint_t *) ETHR_NATMC_ADDR_FUNC__(var);
+
+}
+
+
+/* --- cmpxchg() --- */
+
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(cmpxchg)(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val)
+{
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_CMPXCHG)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_rb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_wb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_acqb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_relb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_mb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
#else
- return (ethr_sint_t *) var;
+#error "Missing implementation of ethr_atomic_cmpxchg()!"
#endif
+ return res;
}
-static ETHR_INLINE void
-ETHR_INLINE_FUNC_NAME_(ethr_atomic_init)(ethr_atomic_t *var, ethr_sint_t i)
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(cmpxchg_rb)(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- ETHR_NATMC_FUNC__(init)(var, (ETHR_NAINT_T__) i);
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_rb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_mb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_wb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_acqb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_relb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
#else
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = i);
+#error "Missing implementation of ethr_atomic_cmpxchg_rb()!"
#endif
+ return res;
}
-static ETHR_INLINE void
-ETHR_INLINE_FUNC_NAME_(ethr_atomic_set)(ethr_atomic_t *var, ethr_sint_t i)
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(cmpxchg_wb)(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- ETHR_NATMC_FUNC__(set)(var, (ETHR_NAINT_T__) i);
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_wb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_mb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_rb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_acqb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_relb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
#else
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = i);
+#error "Missing implementation of ethr_atomic_cmpxchg_wb()!"
#endif
+ return res;
}
-static ETHR_INLINE ethr_sint_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic_read)(ethr_atomic_t *var)
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(cmpxchg_acqb)(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return (ethr_sint_t) ETHR_NATMC_FUNC__(read)(var);
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_acqb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_rb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_mb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_wb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_relb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
#else
+#error "Missing implementation of ethr_atomic_cmpxchg_acqb()!"
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(cmpxchg_relb)(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val)
+{
ethr_sint_t res;
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var);
+#if defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_relb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_wb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_mb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_rb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_acqb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+#else
+#error "Missing implementation of ethr_atomic_cmpxchg_relb()!"
+#endif
return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(cmpxchg_mb)(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val)
+{
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_mb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_relb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_acqb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_wb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_rb)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg)(var, (ETHR_NAINT_T__) val, (ETHR_NAINT_T__) old_val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+#error "Missing implementation of ethr_atomic_cmpxchg_mb()!"
#endif
+ return res;
}
-static ETHR_INLINE void
-ETHR_INLINE_FUNC_NAME_(ethr_atomic_add)(ethr_atomic_t *var, ethr_sint_t incr)
+
+/* --- xchg() --- */
+
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(xchg)(ethr_atomic_t *var, ethr_sint_t val)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- ETHR_NATMC_FUNC__(add)(var, (ETHR_NAINT_T__) incr);
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_XCHG)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_XCHG_RB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_XCHG_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_wb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_XCHG_ACQB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_XCHG_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_relb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_XCHG_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_rb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_wb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_relb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_mb), var, aval, res = aval; aval = val);
#else
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += incr);
+#error "Missing implementation of ethr_atomic_xchg()!"
#endif
-}
-
-static ETHR_INLINE ethr_sint_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic_add_read)(ethr_atomic_t *var, ethr_sint_t i)
+ return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(xchg_rb)(ethr_atomic_t *var, ethr_sint_t val)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return (ethr_sint_t) ETHR_NATMC_FUNC__(add_return)(var, (ETHR_NAINT_T__) i);
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_XCHG_RB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_XCHG)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_XCHG_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_XCHG_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_wb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_XCHG_ACQB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_acqb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_XCHG_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_relb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_rb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg), var, aval, res = aval; aval = val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_mb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_wb), var, aval, res = aval; aval = val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval = val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_relb), var, aval, res = aval; aval = val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
#else
+#error "Missing implementation of ethr_atomic_xchg_rb()!"
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(xchg_wb)(ethr_atomic_t *var, ethr_sint_t val)
+{
ethr_sint_t res;
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += i; res = *var);
+#if defined(ETHR_HAVE_NATMC_XCHG_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_wb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_XCHG)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_XCHG_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_XCHG_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_XCHG_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_XCHG_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_relb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_wb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_mb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_rb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_relb), var, aval, res = aval; aval = val);
+#else
+#error "Missing implementation of ethr_atomic_xchg_wb()!"
+#endif
return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(xchg_acqb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_XCHG_ACQB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_XCHG_RB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_rb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_XCHG)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_XCHG_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_XCHG_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_wb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_XCHG_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_relb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_rb), var, aval, res = aval; aval = val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg), var, aval, res = aval; aval = val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_mb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_wb), var, aval, res = aval; aval = val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_relb), var, aval, res = aval; aval = val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+#error "Missing implementation of ethr_atomic_xchg_acqb()!"
#endif
+ return res;
}
-static ETHR_INLINE void
-ETHR_INLINE_FUNC_NAME_(ethr_atomic_inc)(ethr_atomic_t *var)
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(xchg_relb)(ethr_atomic_t *var, ethr_sint_t val)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- ETHR_NATMC_FUNC__(inc)(var);
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_XCHG_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_relb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_XCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_wb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_XCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_XCHG_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_XCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_XCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_relb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_wb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_mb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_rb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval = val);
#else
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, ++(*var));
+#error "Missing implementation of ethr_atomic_xchg_relb()!"
#endif
+ return res;
}
-static ETHR_INLINE void
-ETHR_INLINE_FUNC_NAME_(ethr_atomic_dec)(ethr_atomic_t *var)
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(xchg_mb)(ethr_atomic_t *var, ethr_sint_t val)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- ETHR_NATMC_FUNC__(dec)(var);
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_XCHG_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_XCHG_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_relb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_XCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_XCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_wb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_XCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg_rb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_XCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(xchg)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_mb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_relb), var, aval, res = aval; aval = val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_wb), var, aval, res = aval; aval = val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_rb), var, aval, res = aval; aval = val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg), var, aval, res = aval; aval = val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+#error "Missing implementation of ethr_atomic_xchg_mb()!"
+#endif
+ return res;
+}
+
+
+/* --- set() --- */
+
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(set)(ethr_atomic_t *var, ethr_sint_t val)
+{
+#if defined(ETHR_HAVE_NATMC_SET)
+ ETHR_NATMC_FUNC__(set)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_SET_RB)
+ ETHR_NATMC_FUNC__(set_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_SET_WB)
+ ETHR_NATMC_FUNC__(set_wb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_SET_ACQB)
+ ETHR_NATMC_FUNC__(set_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_SET_RELB)
+ ETHR_NATMC_FUNC__(set_relb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_SET_MB)
+ ETHR_NATMC_FUNC__(set_mb)(var, (ETHR_NAINT_T__) val);
+#else
+ (void) ETHR_ATMC_FUNC__(xchg)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(set_rb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+#if defined(ETHR_HAVE_NATMC_SET_RB)
+ ETHR_NATMC_FUNC__(set_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_SET)
+ ETHR_NATMC_FUNC__(set)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_SET_MB)
+ ETHR_NATMC_FUNC__(set_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_SET_WB)
+ ETHR_NATMC_FUNC__(set_wb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_SET_ACQB)
+ ETHR_NATMC_FUNC__(set_acqb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_SET_RELB)
+ ETHR_NATMC_FUNC__(set_relb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ (void) ETHR_ATMC_FUNC__(xchg_rb)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(set_wb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+#if defined(ETHR_HAVE_NATMC_SET_WB)
+ ETHR_NATMC_FUNC__(set_wb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_SET)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(set)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_SET_MB)
+ ETHR_NATMC_FUNC__(set_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_SET_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(set_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_SET_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(set_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_SET_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(set_relb)(var, (ETHR_NAINT_T__) val);
+#else
+ (void) ETHR_ATMC_FUNC__(xchg_wb)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(set_acqb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+#if defined(ETHR_HAVE_NATMC_SET_ACQB)
+ ETHR_NATMC_FUNC__(set_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_SET_RB)
+ ETHR_NATMC_FUNC__(set_rb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_SET)
+ ETHR_NATMC_FUNC__(set)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_SET_MB)
+ ETHR_NATMC_FUNC__(set_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_SET_WB)
+ ETHR_NATMC_FUNC__(set_wb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_SET_RELB)
+ ETHR_NATMC_FUNC__(set_relb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ (void) ETHR_ATMC_FUNC__(xchg_acqb)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(set_relb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+#if defined(ETHR_HAVE_NATMC_SET_RELB)
+ ETHR_NATMC_FUNC__(set_relb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_SET_WB)
+ ETHR_MEMBAR(ETHR_LoadStore);
+ ETHR_NATMC_FUNC__(set_wb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_SET)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(set)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_SET_MB)
+ ETHR_NATMC_FUNC__(set_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_SET_RB)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(set_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_SET_ACQB)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(set_acqb)(var, (ETHR_NAINT_T__) val);
+#else
+ (void) ETHR_ATMC_FUNC__(xchg_relb)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(set_mb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+#if defined(ETHR_HAVE_NATMC_SET_MB)
+ ETHR_NATMC_FUNC__(set_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_SET_RELB)
+ ETHR_NATMC_FUNC__(set_relb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_SET_ACQB)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(set_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_SET_WB)
+ ETHR_MEMBAR(ETHR_LoadStore);
+ ETHR_NATMC_FUNC__(set_wb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_SET_RB)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(set_rb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_SET)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(set)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ (void) ETHR_ATMC_FUNC__(xchg_mb)(var, val);
+#endif
+}
+
+
+/* --- init() --- */
+
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(init)(ethr_atomic_t *var, ethr_sint_t val)
+{
+#if defined(ETHR_HAVE_NATMC_INIT)
+ ETHR_NATMC_FUNC__(init)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_INIT_RB)
+ ETHR_NATMC_FUNC__(init_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_INIT_WB)
+ ETHR_NATMC_FUNC__(init_wb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_INIT_ACQB)
+ ETHR_NATMC_FUNC__(init_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_INIT_RELB)
+ ETHR_NATMC_FUNC__(init_relb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_INIT_MB)
+ ETHR_NATMC_FUNC__(init_mb)(var, (ETHR_NAINT_T__) val);
+#else
+ ETHR_ATMC_FUNC__(set)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(init_rb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+#if defined(ETHR_HAVE_NATMC_INIT_RB)
+ ETHR_NATMC_FUNC__(init_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_INIT)
+ ETHR_NATMC_FUNC__(init)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_INIT_MB)
+ ETHR_NATMC_FUNC__(init_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_INIT_WB)
+ ETHR_NATMC_FUNC__(init_wb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_INIT_ACQB)
+ ETHR_NATMC_FUNC__(init_acqb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_INIT_RELB)
+ ETHR_NATMC_FUNC__(init_relb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ ETHR_ATMC_FUNC__(set_rb)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(init_wb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+#if defined(ETHR_HAVE_NATMC_INIT_WB)
+ ETHR_NATMC_FUNC__(init_wb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_INIT)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(init)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_INIT_MB)
+ ETHR_NATMC_FUNC__(init_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_INIT_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(init_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_INIT_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(init_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_INIT_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(init_relb)(var, (ETHR_NAINT_T__) val);
+#else
+ ETHR_ATMC_FUNC__(set_wb)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(init_acqb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+#if defined(ETHR_HAVE_NATMC_INIT_ACQB)
+ ETHR_NATMC_FUNC__(init_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_INIT_RB)
+ ETHR_NATMC_FUNC__(init_rb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_INIT)
+ ETHR_NATMC_FUNC__(init)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_INIT_MB)
+ ETHR_NATMC_FUNC__(init_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_INIT_WB)
+ ETHR_NATMC_FUNC__(init_wb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_INIT_RELB)
+ ETHR_NATMC_FUNC__(init_relb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_ATMC_FUNC__(set_acqb)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(init_relb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+#if defined(ETHR_HAVE_NATMC_INIT_RELB)
+ ETHR_NATMC_FUNC__(init_relb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_INIT_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(init_wb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_INIT)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(init)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_INIT_MB)
+ ETHR_NATMC_FUNC__(init_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_INIT_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(init_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_INIT_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(init_acqb)(var, (ETHR_NAINT_T__) val);
+#else
+ ETHR_ATMC_FUNC__(set_relb)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(init_mb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+#if defined(ETHR_HAVE_NATMC_INIT_MB)
+ ETHR_NATMC_FUNC__(init_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_INIT_RELB)
+ ETHR_NATMC_FUNC__(init_relb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_INIT_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(init_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_INIT_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(init_wb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_INIT_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(init_rb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_INIT)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(init)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_ATMC_FUNC__(set_mb)(var, val);
+#endif
+}
+
+
+/* --- add_read() --- */
+
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(add_read)(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_ADD_RETURN)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN_RB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_wb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN_ACQB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_relb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_rb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_wb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_acqb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_relb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_mb), var, aval, aval += val; res = aval);
+#else
+#error "Missing implementation of ethr_atomic_add_read()!"
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(add_read_rb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_ADD_RETURN_RB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_wb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN_ACQB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_acqb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_relb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_rb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg), var, aval, aval += val; res = aval);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_mb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_wb), var, aval, aval += val; res = aval);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_acqb), var, aval, aval += val; res = aval);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_relb), var, aval, aval += val; res = aval);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+#error "Missing implementation of ethr_atomic_add_read_rb()!"
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(add_read_wb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_ADD_RETURN_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_wb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_relb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_wb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_mb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_rb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_acqb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_relb), var, aval, aval += val; res = aval);
+#else
+#error "Missing implementation of ethr_atomic_add_read_wb()!"
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(add_read_acqb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_ADD_RETURN_ACQB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN_RB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_rb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_wb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_relb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_acqb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_rb), var, aval, aval += val; res = aval);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg), var, aval, aval += val; res = aval);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_mb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_wb), var, aval, aval += val; res = aval);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_relb), var, aval, aval += val; res = aval);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+#error "Missing implementation of ethr_atomic_add_read_acqb()!"
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(add_read_relb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_ADD_RETURN_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_relb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_wb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_relb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_wb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_mb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_rb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_acqb), var, aval, aval += val; res = aval);
#else
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, --(*var));
+#error "Missing implementation of ethr_atomic_add_read_relb()!"
#endif
+ return res;
}
-static ETHR_INLINE ethr_sint_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic_inc_read)(ethr_atomic_t *var)
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(add_read_mb)(ethr_atomic_t *var, ethr_sint_t val)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return)(var);
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_ADD_RETURN_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_relb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_wb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return_rb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_ADD_RETURN)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(add_return)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_mb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_relb), var, aval, aval += val; res = aval);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_acqb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_wb), var, aval, aval += val; res = aval);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_rb), var, aval, aval += val; res = aval);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg), var, aval, aval += val; res = aval);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
#else
+#error "Missing implementation of ethr_atomic_add_read_mb()!"
+#endif
+ return res;
+}
+
+
+/* --- read() --- */
+
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(read)(ethr_atomic_t *var)
+{
ethr_sint_t res;
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = ++(*var));
+#if defined(ETHR_HAVE_NATMC_READ)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read)(var);
+#elif defined(ETHR_HAVE_NATMC_READ_RB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_rb)(var);
+#elif defined(ETHR_HAVE_NATMC_READ_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_wb)(var);
+#elif defined(ETHR_HAVE_NATMC_READ_ACQB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC_READ_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_relb)(var);
+#elif defined(ETHR_HAVE_NATMC_READ_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_mb)(var);
+#else
+ res = ETHR_ATMC_FUNC__(cmpxchg)(var, (ethr_sint_t) ETHR_UNUSUAL_SINT_VAL__, (ethr_sint_t) ETHR_UNUSUAL_SINT_VAL__);
+#endif
return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(read_rb)(ethr_atomic_t *var)
+{
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_READ_RB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_rb)(var);
+#elif defined(ETHR_HAVE_NATMC_READ)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_READ_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_mb)(var);
+#elif defined(ETHR_HAVE_NATMC_READ_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_READ_ACQB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_acqb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_READ_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ res = ETHR_ATMC_FUNC__(cmpxchg_rb)(var, (ethr_sint_t) ETHR_UNUSUAL_SINT_VAL__, (ethr_sint_t) ETHR_UNUSUAL_SINT_VAL__);
#endif
+ return res;
}
-static ETHR_INLINE ethr_sint_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic_dec_read)(ethr_atomic_t *var)
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(read_wb)(ethr_atomic_t *var)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return)(var);
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_READ_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_wb)(var);
+#elif defined(ETHR_HAVE_NATMC_READ)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read)(var);
+#elif defined(ETHR_HAVE_NATMC_READ_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_mb)(var);
+#elif defined(ETHR_HAVE_NATMC_READ_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_rb)(var);
+#elif defined(ETHR_HAVE_NATMC_READ_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC_READ_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_relb)(var);
#else
+ res = ETHR_ATMC_FUNC__(cmpxchg_wb)(var, (ethr_sint_t) ETHR_UNUSUAL_SINT_VAL__, (ethr_sint_t) ETHR_UNUSUAL_SINT_VAL__);
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(read_acqb)(ethr_atomic_t *var)
+{
ethr_sint_t res;
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = --(*var));
+#if defined(ETHR_HAVE_NATMC_READ_ACQB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC_READ_RB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_rb)(var);
+ ETHR_MEMBAR(ETHR_LoadStore);
+#elif defined(ETHR_HAVE_NATMC_READ)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#elif defined(ETHR_HAVE_NATMC_READ_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_mb)(var);
+#elif defined(ETHR_HAVE_NATMC_READ_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#elif defined(ETHR_HAVE_NATMC_READ_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#else
+ res = ETHR_ATMC_FUNC__(cmpxchg_acqb)(var, (ethr_sint_t) ETHR_UNUSUAL_SINT_VAL__, (ethr_sint_t) ETHR_UNUSUAL_SINT_VAL__);
+#endif
return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(read_relb)(ethr_atomic_t *var)
+{
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_READ_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_relb)(var);
+#elif defined(ETHR_HAVE_NATMC_READ_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_wb)(var);
+#elif defined(ETHR_HAVE_NATMC_READ)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read)(var);
+#elif defined(ETHR_HAVE_NATMC_READ_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_mb)(var);
+#elif defined(ETHR_HAVE_NATMC_READ_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_rb)(var);
+#elif defined(ETHR_HAVE_NATMC_READ_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_acqb)(var);
+#else
+ res = ETHR_ATMC_FUNC__(cmpxchg_relb)(var, (ethr_sint_t) ETHR_UNUSUAL_SINT_VAL__, (ethr_sint_t) ETHR_UNUSUAL_SINT_VAL__);
#endif
+ return res;
}
-static ETHR_INLINE ethr_sint_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic_read_band)(ethr_atomic_t *var,
- ethr_sint_t mask)
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(read_mb)(ethr_atomic_t *var)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold)(var,
- (ETHR_NAINT_T__) mask);
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_READ_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_mb)(var);
+#elif defined(ETHR_HAVE_NATMC_READ_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#elif defined(ETHR_HAVE_NATMC_READ_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC_READ_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#elif defined(ETHR_HAVE_NATMC_READ_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read_rb)(var);
+ ETHR_MEMBAR(ETHR_LoadStore);
+#elif defined(ETHR_HAVE_NATMC_READ)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(read)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
#else
+ res = ETHR_ATMC_FUNC__(cmpxchg_mb)(var, (ethr_sint_t) ETHR_UNUSUAL_SINT_VAL__, (ethr_sint_t) ETHR_UNUSUAL_SINT_VAL__);
+#endif
+ return res;
+}
+
+
+/* --- inc_read() --- */
+
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(inc_read)(ethr_atomic_t *var)
+{
ethr_sint_t res;
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var &= mask);
+#if defined(ETHR_HAVE_NATMC_INC_RETURN)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN_RB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_rb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_wb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN_ACQB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_relb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_mb)(var);
+#else
+ res = ETHR_ATMC_FUNC__(add_read)(var, (ethr_sint_t) 1);
+#endif
return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(inc_read_rb)(ethr_atomic_t *var)
+{
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_INC_RETURN_RB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_rb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_mb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN_ACQB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_acqb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ res = ETHR_ATMC_FUNC__(add_read_rb)(var, (ethr_sint_t) 1);
#endif
+ return res;
}
-static ETHR_INLINE ethr_sint_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic_read_bor)(ethr_atomic_t *var,
- ethr_sint_t mask)
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(inc_read_wb)(ethr_atomic_t *var)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold)(var,
- (ETHR_NAINT_T__) mask);
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_INC_RETURN_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_wb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_mb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_rb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_relb)(var);
#else
+ res = ETHR_ATMC_FUNC__(add_read_wb)(var, (ethr_sint_t) 1);
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(inc_read_acqb)(ethr_atomic_t *var)
+{
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_INC_RETURN_ACQB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN_RB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_rb)(var);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_mb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ res = ETHR_ATMC_FUNC__(add_read_acqb)(var, (ethr_sint_t) 1);
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(inc_read_relb)(ethr_atomic_t *var)
+{
ethr_sint_t res;
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var |= mask);
+#if defined(ETHR_HAVE_NATMC_INC_RETURN_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_relb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_wb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_mb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_rb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_acqb)(var);
+#else
+ res = ETHR_ATMC_FUNC__(add_read_relb)(var, (ethr_sint_t) 1);
+#endif
return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(inc_read_mb)(ethr_atomic_t *var)
+{
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_INC_RETURN_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_mb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_rb)(var);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_INC_RETURN)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ res = ETHR_ATMC_FUNC__(add_read_mb)(var, (ethr_sint_t) 1);
#endif
+ return res;
}
-static ETHR_INLINE ethr_sint_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic_xchg)(ethr_atomic_t *var, ethr_sint_t new)
+
+/* --- dec_read() --- */
+
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(dec_read)(ethr_atomic_t *var)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return (ethr_sint_t) ETHR_NATMC_FUNC__(xchg)(var,
- (ETHR_NAINT_T__) new);
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_DEC_RETURN)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN_RB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_rb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_wb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN_ACQB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_relb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_mb)(var);
#else
+ res = ETHR_ATMC_FUNC__(add_read)(var, (ethr_sint_t) -1);
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(dec_read_rb)(ethr_atomic_t *var)
+{
ethr_sint_t res;
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var = new);
+#if defined(ETHR_HAVE_NATMC_DEC_RETURN_RB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_rb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_mb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN_ACQB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_acqb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ res = ETHR_ATMC_FUNC__(add_read_rb)(var, (ethr_sint_t) -1);
+#endif
return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(dec_read_wb)(ethr_atomic_t *var)
+{
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_DEC_RETURN_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_wb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_mb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_rb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_relb)(var);
+#else
+ res = ETHR_ATMC_FUNC__(add_read_wb)(var, (ethr_sint_t) -1);
#endif
+ return res;
}
-static ETHR_INLINE ethr_sint_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic_cmpxchg)(ethr_atomic_t *var,
- ethr_sint_t new,
- ethr_sint_t exp)
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(dec_read_acqb)(ethr_atomic_t *var)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg)(var,
- (ETHR_NAINT_T__) new,
- (ETHR_NAINT_T__) exp);
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_DEC_RETURN_ACQB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN_RB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_rb)(var);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_mb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
#else
+ res = ETHR_ATMC_FUNC__(add_read_acqb)(var, (ethr_sint_t) -1);
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(dec_read_relb)(ethr_atomic_t *var)
+{
ethr_sint_t res;
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var,
- {
- res = *var;
- if (__builtin_expect(res == exp, 1))
- *var = new;
- });
+#if defined(ETHR_HAVE_NATMC_DEC_RETURN_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_relb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_wb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_mb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_rb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_acqb)(var);
+#else
+ res = ETHR_ATMC_FUNC__(add_read_relb)(var, (ethr_sint_t) -1);
+#endif
return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(dec_read_mb)(ethr_atomic_t *var)
+{
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_DEC_RETURN_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_mb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_rb)(var);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_DEC_RETURN)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ res = ETHR_ATMC_FUNC__(add_read_mb)(var, (ethr_sint_t) -1);
#endif
+ return res;
}
-/*
- * Important memory barrier requirements.
- *
- * The following atomic operations *must* supply a memory barrier of
- * at least the type specified by its suffix:
- * _acqb = acquire barrier
- * _relb = release barrier
- */
-static ETHR_INLINE ethr_sint_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic_read_acqb)(ethr_atomic_t *var)
+/* --- add() --- */
+
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(add)(ethr_atomic_t *var, ethr_sint_t val)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return (ethr_sint_t) ETHR_NATMC_FUNC__(read_acqb)(var);
+#if defined(ETHR_HAVE_NATMC_ADD)
+ ETHR_NATMC_FUNC__(add)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RB)
+ ETHR_NATMC_FUNC__(add_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_WB)
+ ETHR_NATMC_FUNC__(add_wb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_ACQB)
+ ETHR_NATMC_FUNC__(add_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RELB)
+ ETHR_NATMC_FUNC__(add_relb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_MB)
+ ETHR_NATMC_FUNC__(add_mb)(var, (ETHR_NAINT_T__) val);
#else
- return ETHR_INLINE_FUNC_NAME_(ethr_atomic_read)(var);
+ (void) ETHR_ATMC_FUNC__(add_read)(var, val);
#endif
}
-static ETHR_INLINE ethr_sint_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic_inc_read_acqb)(ethr_atomic_t *var)
+static ETHR_INLINE void ETHR_ATMC_FUNC__(add_rb)(ethr_atomic_t *var, ethr_sint_t val)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return (ethr_sint_t) ETHR_NATMC_FUNC__(inc_return_acqb)(var);
+#if defined(ETHR_HAVE_NATMC_ADD_RB)
+ ETHR_NATMC_FUNC__(add_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD)
+ ETHR_NATMC_FUNC__(add)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_ADD_MB)
+ ETHR_NATMC_FUNC__(add_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_WB)
+ ETHR_NATMC_FUNC__(add_wb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_ADD_ACQB)
+ ETHR_NATMC_FUNC__(add_acqb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_ADD_RELB)
+ ETHR_NATMC_FUNC__(add_relb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
#else
- return ETHR_INLINE_FUNC_NAME_(ethr_atomic_inc_read)(var);
+ (void) ETHR_ATMC_FUNC__(add_read_rb)(var, val);
#endif
}
-static ETHR_INLINE void
-ETHR_INLINE_FUNC_NAME_(ethr_atomic_set_relb)(ethr_atomic_t *var,
- ethr_sint_t val)
+static ETHR_INLINE void ETHR_ATMC_FUNC__(add_wb)(ethr_atomic_t *var, ethr_sint_t val)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- ETHR_NATMC_FUNC__(set_relb)(var, (ETHR_NAINT_T__) val);
+#if defined(ETHR_HAVE_NATMC_ADD_WB)
+ ETHR_NATMC_FUNC__(add_wb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(add)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_MB)
+ ETHR_NATMC_FUNC__(add_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(add_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(add_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(add_relb)(var, (ETHR_NAINT_T__) val);
#else
- ETHR_INLINE_FUNC_NAME_(ethr_atomic_set)(var, val);
+ (void) ETHR_ATMC_FUNC__(add_read_wb)(var, val);
#endif
}
-static ETHR_INLINE void
-ETHR_INLINE_FUNC_NAME_(ethr_atomic_dec_relb)(ethr_atomic_t *var)
+static ETHR_INLINE void ETHR_ATMC_FUNC__(add_acqb)(ethr_atomic_t *var, ethr_sint_t val)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
+#if defined(ETHR_HAVE_NATMC_ADD_ACQB)
+ ETHR_NATMC_FUNC__(add_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RB)
+ ETHR_NATMC_FUNC__(add_rb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_ADD)
+ ETHR_NATMC_FUNC__(add)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_ADD_MB)
+ ETHR_NATMC_FUNC__(add_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_WB)
+ ETHR_NATMC_FUNC__(add_wb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_ADD_RELB)
+ ETHR_NATMC_FUNC__(add_relb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ (void) ETHR_ATMC_FUNC__(add_read_acqb)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(add_relb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+#if defined(ETHR_HAVE_NATMC_ADD_RELB)
+ ETHR_NATMC_FUNC__(add_relb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(add_wb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(add)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_MB)
+ ETHR_NATMC_FUNC__(add_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(add_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(add_acqb)(var, (ETHR_NAINT_T__) val);
+#else
+ (void) ETHR_ATMC_FUNC__(add_read_relb)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(add_mb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+#if defined(ETHR_HAVE_NATMC_ADD_MB)
+ ETHR_NATMC_FUNC__(add_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_RELB)
+ ETHR_NATMC_FUNC__(add_relb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_ADD_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(add_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_ADD_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(add_wb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_ADD_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(add_rb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_ADD)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(add)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ (void) ETHR_ATMC_FUNC__(add_read_mb)(var, val);
+#endif
+}
+
+
+/* --- inc() --- */
+
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(inc)(ethr_atomic_t *var)
+{
+#if defined(ETHR_HAVE_NATMC_INC)
+ ETHR_NATMC_FUNC__(inc)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RB)
+ ETHR_NATMC_FUNC__(inc_rb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_WB)
+ ETHR_NATMC_FUNC__(inc_wb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_ACQB)
+ ETHR_NATMC_FUNC__(inc_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RELB)
+ ETHR_NATMC_FUNC__(inc_relb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_MB)
+ ETHR_NATMC_FUNC__(inc_mb)(var);
+#else
+ (void) ETHR_ATMC_FUNC__(inc_read)(var);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(inc_rb)(ethr_atomic_t *var)
+{
+#if defined(ETHR_HAVE_NATMC_INC_RB)
+ ETHR_NATMC_FUNC__(inc_rb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC)
+ ETHR_NATMC_FUNC__(inc)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_INC_MB)
+ ETHR_NATMC_FUNC__(inc_mb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_WB)
+ ETHR_NATMC_FUNC__(inc_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_INC_ACQB)
+ ETHR_NATMC_FUNC__(inc_acqb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_INC_RELB)
+ ETHR_NATMC_FUNC__(inc_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ (void) ETHR_ATMC_FUNC__(inc_read_rb)(var);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(inc_wb)(ethr_atomic_t *var)
+{
+#if defined(ETHR_HAVE_NATMC_INC_WB)
+ ETHR_NATMC_FUNC__(inc_wb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(inc)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_MB)
+ ETHR_NATMC_FUNC__(inc_mb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(inc_rb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(inc_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(inc_relb)(var);
+#else
+ (void) ETHR_ATMC_FUNC__(inc_read_wb)(var);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(inc_acqb)(ethr_atomic_t *var)
+{
+#if defined(ETHR_HAVE_NATMC_INC_ACQB)
+ ETHR_NATMC_FUNC__(inc_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RB)
+ ETHR_NATMC_FUNC__(inc_rb)(var);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_INC)
+ ETHR_NATMC_FUNC__(inc)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_INC_MB)
+ ETHR_NATMC_FUNC__(inc_mb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_WB)
+ ETHR_NATMC_FUNC__(inc_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_INC_RELB)
+ ETHR_NATMC_FUNC__(inc_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ (void) ETHR_ATMC_FUNC__(inc_read_acqb)(var);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(inc_relb)(ethr_atomic_t *var)
+{
+#if defined(ETHR_HAVE_NATMC_INC_RELB)
+ ETHR_NATMC_FUNC__(inc_relb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(inc_wb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(inc)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_MB)
+ ETHR_NATMC_FUNC__(inc_mb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(inc_rb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(inc_acqb)(var);
+#else
+ (void) ETHR_ATMC_FUNC__(inc_read_relb)(var);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(inc_mb)(ethr_atomic_t *var)
+{
+#if defined(ETHR_HAVE_NATMC_INC_MB)
+ ETHR_NATMC_FUNC__(inc_mb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_RELB)
+ ETHR_NATMC_FUNC__(inc_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_INC_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(inc_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC_INC_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(inc_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_INC_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(inc_rb)(var);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_INC)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(inc)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ (void) ETHR_ATMC_FUNC__(inc_read_mb)(var);
+#endif
+}
+
+
+/* --- dec() --- */
+
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(dec)(ethr_atomic_t *var)
+{
+#if defined(ETHR_HAVE_NATMC_DEC)
+ ETHR_NATMC_FUNC__(dec)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RB)
+ ETHR_NATMC_FUNC__(dec_rb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_WB)
+ ETHR_NATMC_FUNC__(dec_wb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_ACQB)
+ ETHR_NATMC_FUNC__(dec_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RELB)
+ ETHR_NATMC_FUNC__(dec_relb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_MB)
+ ETHR_NATMC_FUNC__(dec_mb)(var);
+#else
+ (void) ETHR_ATMC_FUNC__(dec_read)(var);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(dec_rb)(ethr_atomic_t *var)
+{
+#if defined(ETHR_HAVE_NATMC_DEC_RB)
+ ETHR_NATMC_FUNC__(dec_rb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC)
+ ETHR_NATMC_FUNC__(dec)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_DEC_MB)
+ ETHR_NATMC_FUNC__(dec_mb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_WB)
+ ETHR_NATMC_FUNC__(dec_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_DEC_ACQB)
+ ETHR_NATMC_FUNC__(dec_acqb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_DEC_RELB)
+ ETHR_NATMC_FUNC__(dec_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ (void) ETHR_ATMC_FUNC__(dec_read_rb)(var);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(dec_wb)(ethr_atomic_t *var)
+{
+#if defined(ETHR_HAVE_NATMC_DEC_WB)
+ ETHR_NATMC_FUNC__(dec_wb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(dec)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_MB)
+ ETHR_NATMC_FUNC__(dec_mb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(dec_rb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(dec_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_FUNC__(dec_relb)(var);
+#else
+ (void) ETHR_ATMC_FUNC__(dec_read_wb)(var);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(dec_acqb)(ethr_atomic_t *var)
+{
+#if defined(ETHR_HAVE_NATMC_DEC_ACQB)
+ ETHR_NATMC_FUNC__(dec_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RB)
+ ETHR_NATMC_FUNC__(dec_rb)(var);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_DEC)
+ ETHR_NATMC_FUNC__(dec)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_DEC_MB)
+ ETHR_NATMC_FUNC__(dec_mb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_WB)
+ ETHR_NATMC_FUNC__(dec_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_DEC_RELB)
+ ETHR_NATMC_FUNC__(dec_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ (void) ETHR_ATMC_FUNC__(dec_read_acqb)(var);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(dec_relb)(ethr_atomic_t *var)
+{
+#if defined(ETHR_HAVE_NATMC_DEC_RELB)
+ ETHR_NATMC_FUNC__(dec_relb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(dec_wb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(dec)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_MB)
+ ETHR_NATMC_FUNC__(dec_mb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(dec_rb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(dec_acqb)(var);
+#else
+ (void) ETHR_ATMC_FUNC__(dec_read_relb)(var);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC_FUNC__(dec_mb)(ethr_atomic_t *var)
+{
+#if defined(ETHR_HAVE_NATMC_DEC_MB)
+ ETHR_NATMC_FUNC__(dec_mb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_RELB)
ETHR_NATMC_FUNC__(dec_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_DEC_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(dec_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC_DEC_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(dec_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_DEC_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(dec_rb)(var);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_DEC)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_FUNC__(dec)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ (void) ETHR_ATMC_FUNC__(dec_read_mb)(var);
+#endif
+}
+
+
+/* --- read_band() --- */
+
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(read_band)(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_AND_RETOLD)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD_RB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_wb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD_ACQB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_relb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_rb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_wb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_relb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_mb), var, aval, res = aval; aval &= val);
+#else
+#error "Missing implementation of ethr_atomic_read_band()!"
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(read_band_rb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_AND_RETOLD_RB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_wb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD_ACQB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_acqb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_relb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_rb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg), var, aval, res = aval; aval &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_mb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_wb), var, aval, res = aval; aval &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_relb), var, aval, res = aval; aval &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+#error "Missing implementation of ethr_atomic_read_band_rb()!"
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(read_band_wb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_AND_RETOLD_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_wb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_relb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_wb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_mb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_rb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_relb), var, aval, res = aval; aval &= val);
#else
- ETHR_INLINE_FUNC_NAME_(ethr_atomic_dec)(var);
+#error "Missing implementation of ethr_atomic_read_band_wb()!"
#endif
+ return res;
}
-static ETHR_INLINE ethr_sint_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic_dec_read_relb)(ethr_atomic_t *var)
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(read_band_acqb)(ethr_atomic_t *var, ethr_sint_t val)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return (ethr_sint_t) ETHR_NATMC_FUNC__(dec_return_relb)(var);
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_AND_RETOLD_ACQB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD_RB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_rb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_wb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_relb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_rb), var, aval, res = aval; aval &= val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg), var, aval, res = aval; aval &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_mb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_wb), var, aval, res = aval; aval &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_relb), var, aval, res = aval; aval &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
#else
- return ETHR_INLINE_FUNC_NAME_(ethr_atomic_dec_read)(var);
+#error "Missing implementation of ethr_atomic_read_band_acqb()!"
#endif
+ return res;
}
-static ETHR_INLINE ethr_sint_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic_cmpxchg_acqb)(ethr_atomic_t *var,
- ethr_sint_t new,
- ethr_sint_t exp)
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(read_band_relb)(ethr_atomic_t *var, ethr_sint_t val)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_acqb)(var,
- (ETHR_NAINT_T__) new,
- (ETHR_NAINT_T__) exp);
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_AND_RETOLD_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_relb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_wb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_relb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_wb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_mb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_rb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval &= val);
#else
- return ETHR_INLINE_FUNC_NAME_(ethr_atomic_cmpxchg)(var, new, exp);
+#error "Missing implementation of ethr_atomic_read_band_relb()!"
#endif
+ return res;
}
-static ETHR_INLINE ethr_sint_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic_cmpxchg_relb)(ethr_atomic_t *var,
- ethr_sint_t new,
- ethr_sint_t exp)
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(read_band_mb)(ethr_atomic_t *var, ethr_sint_t val)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return (ethr_sint_t) ETHR_NATMC_FUNC__(cmpxchg_relb)(var,
- (ETHR_NAINT_T__) new,
- (ETHR_NAINT_T__) exp);
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_AND_RETOLD_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_relb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_wb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold_rb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_AND_RETOLD)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(and_retold)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_mb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_relb), var, aval, res = aval; aval &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_wb), var, aval, res = aval; aval &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_rb), var, aval, res = aval; aval &= val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg), var, aval, res = aval; aval &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
#else
- return ETHR_INLINE_FUNC_NAME_(ethr_atomic_cmpxchg)(var, new, exp);
+#error "Missing implementation of ethr_atomic_read_band_mb()!"
#endif
+ return res;
}
+
+/* --- read_bor() --- */
+
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(read_bor)(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_OR_RETOLD)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD_RB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_wb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD_ACQB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_relb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_rb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_wb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_relb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_mb), var, aval, res = aval; aval |= val);
+#else
+#error "Missing implementation of ethr_atomic_read_bor()!"
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(read_bor_rb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_OR_RETOLD_RB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_wb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD_ACQB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_acqb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_relb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_rb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg), var, aval, res = aval; aval |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_mb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_wb), var, aval, res = aval; aval |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_relb), var, aval, res = aval; aval |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+#error "Missing implementation of ethr_atomic_read_bor_rb()!"
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(read_bor_wb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_OR_RETOLD_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_wb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_relb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_wb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_mb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_rb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_relb), var, aval, res = aval; aval |= val);
+#else
+#error "Missing implementation of ethr_atomic_read_bor_wb()!"
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(read_bor_acqb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_OR_RETOLD_ACQB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD_RB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_rb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD_WB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_wb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_relb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_rb), var, aval, res = aval; aval |= val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg), var, aval, res = aval; aval |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_mb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_wb), var, aval, res = aval; aval |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_relb), var, aval, res = aval; aval |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+#error "Missing implementation of ethr_atomic_read_bor_acqb()!"
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(read_bor_relb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_OR_RETOLD_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_relb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_wb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_rb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_relb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_wb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_mb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_rb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval |= val);
+#else
+#error "Missing implementation of ethr_atomic_read_bor_relb()!"
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(read_bor_mb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+#if defined(ETHR_HAVE_NATMC_OR_RETOLD_MB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_mb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD_RELB)
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_relb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_acqb)(var, (ETHR_NAINT_T__) val);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_wb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold_rb)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_OR_RETOLD)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint_t) ETHR_NATMC_FUNC__(or_retold)(var, (ETHR_NAINT_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_MB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_mb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RELB)
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_relb), var, aval, res = aval; aval |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_wb), var, aval, res = aval; aval |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg_rb), var, aval, res = aval; aval |= val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC_CMPXCHG_FALLBACK__(ETHR_NATMC_FUNC__(cmpxchg), var, aval, res = aval; aval |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+#error "Missing implementation of ethr_atomic_read_bor_mb()!"
+#endif
+ return res;
+}
+
+#endif /* ETHR_ATMC_INLINE__ */
+
+
+/* ---------- 32-bit atomic implementation ---------- */
+
+
+#ifdef ETHR_NEED_ATMC32_PROTOTYPES__
+ethr_sint32_t *ethr_atomic32_addr(ethr_atomic32_t *var);
+ethr_sint32_t ethr_atomic32_cmpxchg(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val);
+ethr_sint32_t ethr_atomic32_cmpxchg_rb(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val);
+ethr_sint32_t ethr_atomic32_cmpxchg_wb(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val);
+ethr_sint32_t ethr_atomic32_cmpxchg_acqb(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val);
+ethr_sint32_t ethr_atomic32_cmpxchg_relb(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val);
+ethr_sint32_t ethr_atomic32_cmpxchg_mb(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val);
+ethr_sint32_t ethr_atomic32_xchg(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_xchg_rb(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_xchg_wb(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_xchg_acqb(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_xchg_relb(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_xchg_mb(ethr_atomic32_t *var, ethr_sint32_t val);
+void ethr_atomic32_set(ethr_atomic32_t *var, ethr_sint32_t val);
+void ethr_atomic32_set_rb(ethr_atomic32_t *var, ethr_sint32_t val);
+void ethr_atomic32_set_wb(ethr_atomic32_t *var, ethr_sint32_t val);
+void ethr_atomic32_set_acqb(ethr_atomic32_t *var, ethr_sint32_t val);
+void ethr_atomic32_set_relb(ethr_atomic32_t *var, ethr_sint32_t val);
+void ethr_atomic32_set_mb(ethr_atomic32_t *var, ethr_sint32_t val);
+void ethr_atomic32_init(ethr_atomic32_t *var, ethr_sint32_t val);
+void ethr_atomic32_init_rb(ethr_atomic32_t *var, ethr_sint32_t val);
+void ethr_atomic32_init_wb(ethr_atomic32_t *var, ethr_sint32_t val);
+void ethr_atomic32_init_acqb(ethr_atomic32_t *var, ethr_sint32_t val);
+void ethr_atomic32_init_relb(ethr_atomic32_t *var, ethr_sint32_t val);
+void ethr_atomic32_init_mb(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_add_read(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_add_read_rb(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_add_read_wb(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_add_read_acqb(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_add_read_relb(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_add_read_mb(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_read(ethr_atomic32_t *var);
+ethr_sint32_t ethr_atomic32_read_rb(ethr_atomic32_t *var);
+ethr_sint32_t ethr_atomic32_read_wb(ethr_atomic32_t *var);
+ethr_sint32_t ethr_atomic32_read_acqb(ethr_atomic32_t *var);
+ethr_sint32_t ethr_atomic32_read_relb(ethr_atomic32_t *var);
+ethr_sint32_t ethr_atomic32_read_mb(ethr_atomic32_t *var);
+ethr_sint32_t ethr_atomic32_inc_read(ethr_atomic32_t *var);
+ethr_sint32_t ethr_atomic32_inc_read_rb(ethr_atomic32_t *var);
+ethr_sint32_t ethr_atomic32_inc_read_wb(ethr_atomic32_t *var);
+ethr_sint32_t ethr_atomic32_inc_read_acqb(ethr_atomic32_t *var);
+ethr_sint32_t ethr_atomic32_inc_read_relb(ethr_atomic32_t *var);
+ethr_sint32_t ethr_atomic32_inc_read_mb(ethr_atomic32_t *var);
+ethr_sint32_t ethr_atomic32_dec_read(ethr_atomic32_t *var);
+ethr_sint32_t ethr_atomic32_dec_read_rb(ethr_atomic32_t *var);
+ethr_sint32_t ethr_atomic32_dec_read_wb(ethr_atomic32_t *var);
+ethr_sint32_t ethr_atomic32_dec_read_acqb(ethr_atomic32_t *var);
+ethr_sint32_t ethr_atomic32_dec_read_relb(ethr_atomic32_t *var);
+ethr_sint32_t ethr_atomic32_dec_read_mb(ethr_atomic32_t *var);
+void ethr_atomic32_add(ethr_atomic32_t *var, ethr_sint32_t val);
+void ethr_atomic32_add_rb(ethr_atomic32_t *var, ethr_sint32_t val);
+void ethr_atomic32_add_wb(ethr_atomic32_t *var, ethr_sint32_t val);
+void ethr_atomic32_add_acqb(ethr_atomic32_t *var, ethr_sint32_t val);
+void ethr_atomic32_add_relb(ethr_atomic32_t *var, ethr_sint32_t val);
+void ethr_atomic32_add_mb(ethr_atomic32_t *var, ethr_sint32_t val);
+void ethr_atomic32_inc(ethr_atomic32_t *var);
+void ethr_atomic32_inc_rb(ethr_atomic32_t *var);
+void ethr_atomic32_inc_wb(ethr_atomic32_t *var);
+void ethr_atomic32_inc_acqb(ethr_atomic32_t *var);
+void ethr_atomic32_inc_relb(ethr_atomic32_t *var);
+void ethr_atomic32_inc_mb(ethr_atomic32_t *var);
+void ethr_atomic32_dec(ethr_atomic32_t *var);
+void ethr_atomic32_dec_rb(ethr_atomic32_t *var);
+void ethr_atomic32_dec_wb(ethr_atomic32_t *var);
+void ethr_atomic32_dec_acqb(ethr_atomic32_t *var);
+void ethr_atomic32_dec_relb(ethr_atomic32_t *var);
+void ethr_atomic32_dec_mb(ethr_atomic32_t *var);
+ethr_sint32_t ethr_atomic32_read_band(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_read_band_rb(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_read_band_wb(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_read_band_acqb(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_read_band_relb(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_read_band_mb(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_read_bor(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_read_bor_rb(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_read_bor_wb(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_read_bor_acqb(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_read_bor_relb(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_read_bor_mb(ethr_atomic32_t *var, ethr_sint32_t val);
+#endif /* ETHR_NEED_ATMC32_PROTOTYPES__ */
+
+#if (defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS) \
+ && (defined(ETHR_ATMC32_INLINE__) || defined(ETHR_ATOMIC_IMPL__)))
+
+#if !defined(ETHR_NATMC32_BITS__)
+# error "Missing native atomic implementation"
+#elif ETHR_NATMC32_BITS__ == 64
+# undef ETHR_HAVE_NATMC32_CMPXCHG
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG
+# define ETHR_HAVE_NATMC32_CMPXCHG 1
+# endif
+# undef ETHR_HAVE_NATMC32_CMPXCHG_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_RB
+# define ETHR_HAVE_NATMC32_CMPXCHG_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_CMPXCHG_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_WB
+# define ETHR_HAVE_NATMC32_CMPXCHG_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_CMPXCHG_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_ACQB
+# define ETHR_HAVE_NATMC32_CMPXCHG_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_CMPXCHG_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_RELB
+# define ETHR_HAVE_NATMC32_CMPXCHG_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_CMPXCHG_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_MB
+# define ETHR_HAVE_NATMC32_CMPXCHG_MB 1
+# endif
+# undef ETHR_HAVE_NATMC32_XCHG
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_XCHG
+# define ETHR_HAVE_NATMC32_XCHG 1
+# endif
+# undef ETHR_HAVE_NATMC32_XCHG_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_XCHG_RB
+# define ETHR_HAVE_NATMC32_XCHG_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_XCHG_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_XCHG_WB
+# define ETHR_HAVE_NATMC32_XCHG_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_XCHG_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_XCHG_ACQB
+# define ETHR_HAVE_NATMC32_XCHG_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_XCHG_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_XCHG_RELB
+# define ETHR_HAVE_NATMC32_XCHG_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_XCHG_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_XCHG_MB
+# define ETHR_HAVE_NATMC32_XCHG_MB 1
+# endif
+# undef ETHR_HAVE_NATMC32_SET
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET
+# define ETHR_HAVE_NATMC32_SET 1
+# endif
+# undef ETHR_HAVE_NATMC32_SET_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET_RB
+# define ETHR_HAVE_NATMC32_SET_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_SET_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET_WB
+# define ETHR_HAVE_NATMC32_SET_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_SET_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET_ACQB
+# define ETHR_HAVE_NATMC32_SET_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_SET_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET_RELB
+# define ETHR_HAVE_NATMC32_SET_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_SET_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET_MB
+# define ETHR_HAVE_NATMC32_SET_MB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INIT
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INIT
+# define ETHR_HAVE_NATMC32_INIT 1
+# endif
+# undef ETHR_HAVE_NATMC32_INIT_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INIT_RB
+# define ETHR_HAVE_NATMC32_INIT_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INIT_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INIT_WB
+# define ETHR_HAVE_NATMC32_INIT_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INIT_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INIT_ACQB
+# define ETHR_HAVE_NATMC32_INIT_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INIT_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INIT_RELB
+# define ETHR_HAVE_NATMC32_INIT_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INIT_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INIT_MB
+# define ETHR_HAVE_NATMC32_INIT_MB 1
+# endif
+# undef ETHR_HAVE_NATMC32_ADD_RETURN
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RETURN
+# define ETHR_HAVE_NATMC32_ADD_RETURN 1
+# endif
+# undef ETHR_HAVE_NATMC32_ADD_RETURN_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RETURN_RB
+# define ETHR_HAVE_NATMC32_ADD_RETURN_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_ADD_RETURN_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RETURN_WB
+# define ETHR_HAVE_NATMC32_ADD_RETURN_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_ADD_RETURN_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RETURN_ACQB
+# define ETHR_HAVE_NATMC32_ADD_RETURN_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_ADD_RETURN_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RETURN_RELB
+# define ETHR_HAVE_NATMC32_ADD_RETURN_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_ADD_RETURN_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RETURN_MB
+# define ETHR_HAVE_NATMC32_ADD_RETURN_MB 1
+# endif
+# undef ETHR_HAVE_NATMC32_READ
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ
+# define ETHR_HAVE_NATMC32_READ 1
+# endif
+# undef ETHR_HAVE_NATMC32_READ_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ_RB
+# define ETHR_HAVE_NATMC32_READ_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_READ_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ_WB
+# define ETHR_HAVE_NATMC32_READ_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_READ_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ_ACQB
+# define ETHR_HAVE_NATMC32_READ_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_READ_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ_RELB
+# define ETHR_HAVE_NATMC32_READ_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_READ_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ_MB
+# define ETHR_HAVE_NATMC32_READ_MB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INC_RETURN
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RETURN
+# define ETHR_HAVE_NATMC32_INC_RETURN 1
+# endif
+# undef ETHR_HAVE_NATMC32_INC_RETURN_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RETURN_RB
+# define ETHR_HAVE_NATMC32_INC_RETURN_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INC_RETURN_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RETURN_WB
+# define ETHR_HAVE_NATMC32_INC_RETURN_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INC_RETURN_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RETURN_ACQB
+# define ETHR_HAVE_NATMC32_INC_RETURN_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INC_RETURN_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RETURN_RELB
+# define ETHR_HAVE_NATMC32_INC_RETURN_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INC_RETURN_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RETURN_MB
+# define ETHR_HAVE_NATMC32_INC_RETURN_MB 1
+# endif
+# undef ETHR_HAVE_NATMC32_DEC_RETURN
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RETURN
+# define ETHR_HAVE_NATMC32_DEC_RETURN 1
+# endif
+# undef ETHR_HAVE_NATMC32_DEC_RETURN_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RETURN_RB
+# define ETHR_HAVE_NATMC32_DEC_RETURN_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_DEC_RETURN_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RETURN_WB
+# define ETHR_HAVE_NATMC32_DEC_RETURN_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_DEC_RETURN_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RETURN_ACQB
+# define ETHR_HAVE_NATMC32_DEC_RETURN_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_DEC_RETURN_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RETURN_RELB
+# define ETHR_HAVE_NATMC32_DEC_RETURN_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_DEC_RETURN_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RETURN_MB
+# define ETHR_HAVE_NATMC32_DEC_RETURN_MB 1
+# endif
+# undef ETHR_HAVE_NATMC32_ADD
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD
+# define ETHR_HAVE_NATMC32_ADD 1
+# endif
+# undef ETHR_HAVE_NATMC32_ADD_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RB
+# define ETHR_HAVE_NATMC32_ADD_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_ADD_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_WB
+# define ETHR_HAVE_NATMC32_ADD_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_ADD_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_ACQB
+# define ETHR_HAVE_NATMC32_ADD_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_ADD_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RELB
+# define ETHR_HAVE_NATMC32_ADD_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_ADD_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_MB
+# define ETHR_HAVE_NATMC32_ADD_MB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INC
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC
+# define ETHR_HAVE_NATMC32_INC 1
+# endif
+# undef ETHR_HAVE_NATMC32_INC_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RB
+# define ETHR_HAVE_NATMC32_INC_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INC_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_WB
+# define ETHR_HAVE_NATMC32_INC_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INC_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_ACQB
+# define ETHR_HAVE_NATMC32_INC_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INC_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RELB
+# define ETHR_HAVE_NATMC32_INC_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INC_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_MB
+# define ETHR_HAVE_NATMC32_INC_MB 1
+# endif
+# undef ETHR_HAVE_NATMC32_DEC
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC
+# define ETHR_HAVE_NATMC32_DEC 1
+# endif
+# undef ETHR_HAVE_NATMC32_DEC_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RB
+# define ETHR_HAVE_NATMC32_DEC_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_DEC_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_WB
+# define ETHR_HAVE_NATMC32_DEC_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_DEC_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_ACQB
+# define ETHR_HAVE_NATMC32_DEC_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_DEC_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RELB
+# define ETHR_HAVE_NATMC32_DEC_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_DEC_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_MB
+# define ETHR_HAVE_NATMC32_DEC_MB 1
+# endif
+# undef ETHR_HAVE_NATMC32_AND_RETOLD
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_AND_RETOLD
+# define ETHR_HAVE_NATMC32_AND_RETOLD 1
+# endif
+# undef ETHR_HAVE_NATMC32_AND_RETOLD_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_AND_RETOLD_RB
+# define ETHR_HAVE_NATMC32_AND_RETOLD_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_AND_RETOLD_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_AND_RETOLD_WB
+# define ETHR_HAVE_NATMC32_AND_RETOLD_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_AND_RETOLD_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_AND_RETOLD_ACQB
+# define ETHR_HAVE_NATMC32_AND_RETOLD_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_AND_RETOLD_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_AND_RETOLD_RELB
+# define ETHR_HAVE_NATMC32_AND_RETOLD_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_AND_RETOLD_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_AND_RETOLD_MB
+# define ETHR_HAVE_NATMC32_AND_RETOLD_MB 1
+# endif
+# undef ETHR_HAVE_NATMC32_OR_RETOLD
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_OR_RETOLD
+# define ETHR_HAVE_NATMC32_OR_RETOLD 1
+# endif
+# undef ETHR_HAVE_NATMC32_OR_RETOLD_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_OR_RETOLD_RB
+# define ETHR_HAVE_NATMC32_OR_RETOLD_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_OR_RETOLD_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_OR_RETOLD_WB
+# define ETHR_HAVE_NATMC32_OR_RETOLD_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_OR_RETOLD_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_OR_RETOLD_ACQB
+# define ETHR_HAVE_NATMC32_OR_RETOLD_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_OR_RETOLD_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_OR_RETOLD_RELB
+# define ETHR_HAVE_NATMC32_OR_RETOLD_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_OR_RETOLD_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_OR_RETOLD_MB
+# define ETHR_HAVE_NATMC32_OR_RETOLD_MB 1
+# endif
+#elif ETHR_NATMC32_BITS__ == 32
+# undef ETHR_HAVE_NATMC32_CMPXCHG
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG
+# define ETHR_HAVE_NATMC32_CMPXCHG 1
+# endif
+# undef ETHR_HAVE_NATMC32_CMPXCHG_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG_RB
+# define ETHR_HAVE_NATMC32_CMPXCHG_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_CMPXCHG_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG_WB
+# define ETHR_HAVE_NATMC32_CMPXCHG_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_CMPXCHG_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG_ACQB
+# define ETHR_HAVE_NATMC32_CMPXCHG_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_CMPXCHG_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG_RELB
+# define ETHR_HAVE_NATMC32_CMPXCHG_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_CMPXCHG_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG_MB
+# define ETHR_HAVE_NATMC32_CMPXCHG_MB 1
+# endif
+# undef ETHR_HAVE_NATMC32_XCHG
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_XCHG
+# define ETHR_HAVE_NATMC32_XCHG 1
+# endif
+# undef ETHR_HAVE_NATMC32_XCHG_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_XCHG_RB
+# define ETHR_HAVE_NATMC32_XCHG_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_XCHG_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_XCHG_WB
+# define ETHR_HAVE_NATMC32_XCHG_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_XCHG_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_XCHG_ACQB
+# define ETHR_HAVE_NATMC32_XCHG_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_XCHG_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_XCHG_RELB
+# define ETHR_HAVE_NATMC32_XCHG_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_XCHG_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_XCHG_MB
+# define ETHR_HAVE_NATMC32_XCHG_MB 1
+# endif
+# undef ETHR_HAVE_NATMC32_SET
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET
+# define ETHR_HAVE_NATMC32_SET 1
+# endif
+# undef ETHR_HAVE_NATMC32_SET_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET_RB
+# define ETHR_HAVE_NATMC32_SET_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_SET_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET_WB
+# define ETHR_HAVE_NATMC32_SET_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_SET_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET_ACQB
+# define ETHR_HAVE_NATMC32_SET_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_SET_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET_RELB
+# define ETHR_HAVE_NATMC32_SET_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_SET_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET_MB
+# define ETHR_HAVE_NATMC32_SET_MB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INIT
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INIT
+# define ETHR_HAVE_NATMC32_INIT 1
+# endif
+# undef ETHR_HAVE_NATMC32_INIT_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INIT_RB
+# define ETHR_HAVE_NATMC32_INIT_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INIT_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INIT_WB
+# define ETHR_HAVE_NATMC32_INIT_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INIT_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INIT_ACQB
+# define ETHR_HAVE_NATMC32_INIT_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INIT_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INIT_RELB
+# define ETHR_HAVE_NATMC32_INIT_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INIT_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INIT_MB
+# define ETHR_HAVE_NATMC32_INIT_MB 1
+# endif
+# undef ETHR_HAVE_NATMC32_ADD_RETURN
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RETURN
+# define ETHR_HAVE_NATMC32_ADD_RETURN 1
+# endif
+# undef ETHR_HAVE_NATMC32_ADD_RETURN_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RETURN_RB
+# define ETHR_HAVE_NATMC32_ADD_RETURN_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_ADD_RETURN_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RETURN_WB
+# define ETHR_HAVE_NATMC32_ADD_RETURN_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_ADD_RETURN_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RETURN_ACQB
+# define ETHR_HAVE_NATMC32_ADD_RETURN_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_ADD_RETURN_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RETURN_RELB
+# define ETHR_HAVE_NATMC32_ADD_RETURN_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_ADD_RETURN_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RETURN_MB
+# define ETHR_HAVE_NATMC32_ADD_RETURN_MB 1
+# endif
+# undef ETHR_HAVE_NATMC32_READ
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ
+# define ETHR_HAVE_NATMC32_READ 1
+# endif
+# undef ETHR_HAVE_NATMC32_READ_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ_RB
+# define ETHR_HAVE_NATMC32_READ_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_READ_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ_WB
+# define ETHR_HAVE_NATMC32_READ_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_READ_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ_ACQB
+# define ETHR_HAVE_NATMC32_READ_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_READ_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ_RELB
+# define ETHR_HAVE_NATMC32_READ_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_READ_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ_MB
+# define ETHR_HAVE_NATMC32_READ_MB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INC_RETURN
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RETURN
+# define ETHR_HAVE_NATMC32_INC_RETURN 1
+# endif
+# undef ETHR_HAVE_NATMC32_INC_RETURN_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RETURN_RB
+# define ETHR_HAVE_NATMC32_INC_RETURN_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INC_RETURN_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RETURN_WB
+# define ETHR_HAVE_NATMC32_INC_RETURN_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INC_RETURN_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RETURN_ACQB
+# define ETHR_HAVE_NATMC32_INC_RETURN_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INC_RETURN_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RETURN_RELB
+# define ETHR_HAVE_NATMC32_INC_RETURN_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INC_RETURN_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RETURN_MB
+# define ETHR_HAVE_NATMC32_INC_RETURN_MB 1
+# endif
+# undef ETHR_HAVE_NATMC32_DEC_RETURN
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RETURN
+# define ETHR_HAVE_NATMC32_DEC_RETURN 1
+# endif
+# undef ETHR_HAVE_NATMC32_DEC_RETURN_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RETURN_RB
+# define ETHR_HAVE_NATMC32_DEC_RETURN_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_DEC_RETURN_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RETURN_WB
+# define ETHR_HAVE_NATMC32_DEC_RETURN_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_DEC_RETURN_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RETURN_ACQB
+# define ETHR_HAVE_NATMC32_DEC_RETURN_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_DEC_RETURN_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RETURN_RELB
+# define ETHR_HAVE_NATMC32_DEC_RETURN_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_DEC_RETURN_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RETURN_MB
+# define ETHR_HAVE_NATMC32_DEC_RETURN_MB 1
+# endif
+# undef ETHR_HAVE_NATMC32_ADD
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD
+# define ETHR_HAVE_NATMC32_ADD 1
+# endif
+# undef ETHR_HAVE_NATMC32_ADD_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RB
+# define ETHR_HAVE_NATMC32_ADD_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_ADD_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_WB
+# define ETHR_HAVE_NATMC32_ADD_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_ADD_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_ACQB
+# define ETHR_HAVE_NATMC32_ADD_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_ADD_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RELB
+# define ETHR_HAVE_NATMC32_ADD_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_ADD_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_MB
+# define ETHR_HAVE_NATMC32_ADD_MB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INC
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC
+# define ETHR_HAVE_NATMC32_INC 1
+# endif
+# undef ETHR_HAVE_NATMC32_INC_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RB
+# define ETHR_HAVE_NATMC32_INC_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INC_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_WB
+# define ETHR_HAVE_NATMC32_INC_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INC_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_ACQB
+# define ETHR_HAVE_NATMC32_INC_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INC_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RELB
+# define ETHR_HAVE_NATMC32_INC_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_INC_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_MB
+# define ETHR_HAVE_NATMC32_INC_MB 1
+# endif
+# undef ETHR_HAVE_NATMC32_DEC
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC
+# define ETHR_HAVE_NATMC32_DEC 1
+# endif
+# undef ETHR_HAVE_NATMC32_DEC_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RB
+# define ETHR_HAVE_NATMC32_DEC_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_DEC_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_WB
+# define ETHR_HAVE_NATMC32_DEC_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_DEC_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_ACQB
+# define ETHR_HAVE_NATMC32_DEC_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_DEC_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RELB
+# define ETHR_HAVE_NATMC32_DEC_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_DEC_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_MB
+# define ETHR_HAVE_NATMC32_DEC_MB 1
+# endif
+# undef ETHR_HAVE_NATMC32_AND_RETOLD
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_AND_RETOLD
+# define ETHR_HAVE_NATMC32_AND_RETOLD 1
+# endif
+# undef ETHR_HAVE_NATMC32_AND_RETOLD_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_AND_RETOLD_RB
+# define ETHR_HAVE_NATMC32_AND_RETOLD_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_AND_RETOLD_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_AND_RETOLD_WB
+# define ETHR_HAVE_NATMC32_AND_RETOLD_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_AND_RETOLD_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_AND_RETOLD_ACQB
+# define ETHR_HAVE_NATMC32_AND_RETOLD_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_AND_RETOLD_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_AND_RETOLD_RELB
+# define ETHR_HAVE_NATMC32_AND_RETOLD_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_AND_RETOLD_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_AND_RETOLD_MB
+# define ETHR_HAVE_NATMC32_AND_RETOLD_MB 1
+# endif
+# undef ETHR_HAVE_NATMC32_OR_RETOLD
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_OR_RETOLD
+# define ETHR_HAVE_NATMC32_OR_RETOLD 1
+# endif
+# undef ETHR_HAVE_NATMC32_OR_RETOLD_RB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_OR_RETOLD_RB
+# define ETHR_HAVE_NATMC32_OR_RETOLD_RB 1
+# endif
+# undef ETHR_HAVE_NATMC32_OR_RETOLD_WB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_OR_RETOLD_WB
+# define ETHR_HAVE_NATMC32_OR_RETOLD_WB 1
+# endif
+# undef ETHR_HAVE_NATMC32_OR_RETOLD_ACQB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_OR_RETOLD_ACQB
+# define ETHR_HAVE_NATMC32_OR_RETOLD_ACQB 1
+# endif
+# undef ETHR_HAVE_NATMC32_OR_RETOLD_RELB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_OR_RETOLD_RELB
+# define ETHR_HAVE_NATMC32_OR_RETOLD_RELB 1
+# endif
+# undef ETHR_HAVE_NATMC32_OR_RETOLD_MB
+# ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_OR_RETOLD_MB
+# define ETHR_HAVE_NATMC32_OR_RETOLD_MB 1
+# endif
+#else
+# error "Invalid native atomic size"
+#endif
+
+#if (!defined(ETHR_HAVE_NATMC32_CMPXCHG) \
+ && !defined(ETHR_HAVE_NATMC32_CMPXCHG_RB) \
+ && !defined(ETHR_HAVE_NATMC32_CMPXCHG_WB) \
+ && !defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB) \
+ && !defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB) \
+ && !defined(ETHR_HAVE_NATMC32_CMPXCHG_MB))
+# error "No native cmpxchg() op available"
+#endif
+
+
/*
- * --- 32-bit atomics ---------------------------------------------------------
+ * Read op used together with cmpxchg() fallback when no native op present.
*/
+#if defined(ETHR_HAVE_NATMC32_READ)
+#define ETHR_NATMC32_CMPXCHG_FALLBACK_READ__(VAR) \
+ ETHR_NATMC32_FUNC__(read)(VAR)
+#elif defined(ETHR_HAVE_NATMC32_READ_RB)
+#define ETHR_NATMC32_CMPXCHG_FALLBACK_READ__(VAR) \
+ ETHR_NATMC32_FUNC__(read_rb)(VAR)
+#elif defined(ETHR_HAVE_NATMC32_READ_WB)
+#define ETHR_NATMC32_CMPXCHG_FALLBACK_READ__(VAR) \
+ ETHR_NATMC32_FUNC__(read_wb)(VAR)
+#elif defined(ETHR_HAVE_NATMC32_READ_ACQB)
+#define ETHR_NATMC32_CMPXCHG_FALLBACK_READ__(VAR) \
+ ETHR_NATMC32_FUNC__(read_acqb)(VAR)
+#elif defined(ETHR_HAVE_NATMC32_READ_RELB)
+#define ETHR_NATMC32_CMPXCHG_FALLBACK_READ__(VAR) \
+ ETHR_NATMC32_FUNC__(read_relb)(VAR)
+#elif defined(ETHR_HAVE_NATMC32_READ_MB)
+#define ETHR_NATMC32_CMPXCHG_FALLBACK_READ__(VAR) \
+ ETHR_NATMC32_FUNC__(read_mb)(VAR)
+#else
+/*
+ * We have no native read() op; guess zero and then use the
+ * the atomics actual value returned from cmpxchg().
+ */
+#define ETHR_NATMC32_CMPXCHG_FALLBACK_READ__(VAR) \
+ ((ETHR_NAINT32_T__) 0)
+#endif
+
+/*
+ * Native cmpxchg() fallback used when no native op present.
+ */
+#define ETHR_NATMC32_CMPXCHG_FALLBACK__(CMPXCHG, VAR, AVAL, OPS) \
+do { \
+ ethr_sint32_t AVAL; \
+ ETHR_NAINT32_T__ new__, act__, exp__; \
+ act__ = ETHR_NATMC32_CMPXCHG_FALLBACK_READ__(VAR); \
+ do { \
+ exp__ = act__; \
+ AVAL = (ethr_sint32_t) act__; \
+ { OPS; } \
+ new__ = (ETHR_NAINT32_T__) AVAL; \
+ act__ = CMPXCHG(VAR, new__, exp__); \
+ } while (__builtin_expect(act__ != exp__, 0)); \
+} while (0)
-static ETHR_INLINE ethr_sint32_t *
-ETHR_INLINE_FUNC_NAME_(ethr_atomic32_addr)(ethr_atomic32_t *var)
+
+
+/* --- addr() --- */
+
+static ETHR_INLINE ethr_sint32_t *ETHR_ATMC32_FUNC__(addr)(ethr_atomic32_t *var)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return ethr_native_atomic32_addr(var);
+ return (ethr_sint32_t *) ETHR_NATMC32_ADDR_FUNC__(var);
+
+}
+
+
+/* --- cmpxchg() --- */
+
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(cmpxchg)(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val)
+{
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_rb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_wb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_acqb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_relb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_mb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
#else
- return (ethr_sint32_t *) var;
+#error "Missing implementation of ethr_atomic32_cmpxchg()!"
#endif
+ return res;
}
-static ETHR_INLINE void
-ETHR_INLINE_FUNC_NAME_(ethr_atomic32_init)(ethr_atomic32_t *var,
- ethr_sint32_t i)
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(cmpxchg_rb)(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- ETHR_NATMC32_FUNC__(init)(var, (ETHR_NAINT32_T__) i);
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_rb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_mb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_wb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_acqb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_relb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
#else
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = i);
+#error "Missing implementation of ethr_atomic32_cmpxchg_rb()!"
#endif
+ return res;
}
-static ETHR_INLINE void
-ETHR_INLINE_FUNC_NAME_(ethr_atomic32_set)(ethr_atomic32_t *var, ethr_sint32_t i)
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(cmpxchg_wb)(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- ETHR_NATMC32_FUNC__(set)(var, (ETHR_NAINT32_T__) i);
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_wb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_mb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_rb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_acqb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_relb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
#else
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = i);
+#error "Missing implementation of ethr_atomic32_cmpxchg_wb()!"
#endif
+ return res;
}
-static ETHR_INLINE ethr_sint32_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic32_read)(ethr_atomic32_t *var)
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(cmpxchg_acqb)(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return (ethr_sint32_t) ETHR_NATMC32_FUNC__(read)(var);
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_acqb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_rb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_mb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_wb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_relb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
#else
+#error "Missing implementation of ethr_atomic32_cmpxchg_acqb()!"
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(cmpxchg_relb)(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val)
+{
ethr_sint32_t res;
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var);
+#if defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_relb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_wb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_mb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_rb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_acqb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+#else
+#error "Missing implementation of ethr_atomic32_cmpxchg_relb()!"
+#endif
return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(cmpxchg_mb)(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val)
+{
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_mb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_relb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_acqb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_wb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg_rb)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg)(var, (ETHR_NAINT32_T__) val, (ETHR_NAINT32_T__) old_val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+#error "Missing implementation of ethr_atomic32_cmpxchg_mb()!"
#endif
+ return res;
}
-static ETHR_INLINE void
-ETHR_INLINE_FUNC_NAME_(ethr_atomic32_add)(ethr_atomic32_t *var,
- ethr_sint32_t incr)
+
+/* --- xchg() --- */
+
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(xchg)(ethr_atomic32_t *var, ethr_sint32_t val)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- ETHR_NATMC32_FUNC__(add)(var, (ETHR_NAINT32_T__) incr);
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_XCHG)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_XCHG_RB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_XCHG_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_wb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_XCHG_ACQB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_XCHG_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_relb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_XCHG_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_rb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_wb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_relb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_mb), var, aval, res = aval; aval = val);
#else
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += incr);
+#error "Missing implementation of ethr_atomic32_xchg()!"
#endif
-}
-
-static ETHR_INLINE ethr_sint32_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic32_add_read)(ethr_atomic32_t *var,
- ethr_sint32_t i)
+ return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(xchg_rb)(ethr_atomic32_t *var, ethr_sint32_t val)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return (ethr_sint32_t)
- ETHR_NATMC32_FUNC__(add_return)(var, (ETHR_NAINT32_T__) i);
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_XCHG_RB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_XCHG)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_XCHG_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_XCHG_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_wb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_XCHG_ACQB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_acqb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_XCHG_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_relb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_rb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg), var, aval, res = aval; aval = val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_mb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_wb), var, aval, res = aval; aval = val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval = val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_relb), var, aval, res = aval; aval = val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
#else
+#error "Missing implementation of ethr_atomic32_xchg_rb()!"
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(xchg_wb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
ethr_sint32_t res;
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += i; res = *var);
+#if defined(ETHR_HAVE_NATMC32_XCHG_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_wb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_XCHG)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_XCHG_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_XCHG_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_XCHG_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_XCHG_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_relb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_wb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_mb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_rb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_relb), var, aval, res = aval; aval = val);
+#else
+#error "Missing implementation of ethr_atomic32_xchg_wb()!"
+#endif
return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(xchg_acqb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_XCHG_ACQB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_XCHG_RB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_rb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_XCHG)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_XCHG_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_XCHG_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_wb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_XCHG_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_relb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_rb), var, aval, res = aval; aval = val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg), var, aval, res = aval; aval = val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_mb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_wb), var, aval, res = aval; aval = val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_relb), var, aval, res = aval; aval = val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+#error "Missing implementation of ethr_atomic32_xchg_acqb()!"
#endif
+ return res;
}
-static ETHR_INLINE void
-ETHR_INLINE_FUNC_NAME_(ethr_atomic32_inc)(ethr_atomic32_t *var)
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(xchg_relb)(ethr_atomic32_t *var, ethr_sint32_t val)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- ETHR_NATMC32_FUNC__(inc)(var);
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_XCHG_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_relb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_XCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_wb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_XCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_XCHG_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_XCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_XCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_relb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_wb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_mb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_rb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval = val);
#else
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, ++(*var));
+#error "Missing implementation of ethr_atomic32_xchg_relb()!"
#endif
+ return res;
}
-static ETHR_INLINE void
-ETHR_INLINE_FUNC_NAME_(ethr_atomic32_dec)(ethr_atomic32_t *var)
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(xchg_mb)(ethr_atomic32_t *var, ethr_sint32_t val)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- ETHR_NATMC32_FUNC__(dec)(var);
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_XCHG_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_XCHG_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_relb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_XCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_XCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_wb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_XCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg_rb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_XCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_mb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_relb), var, aval, res = aval; aval = val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval = val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_wb), var, aval, res = aval; aval = val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_rb), var, aval, res = aval; aval = val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg), var, aval, res = aval; aval = val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+#error "Missing implementation of ethr_atomic32_xchg_mb()!"
+#endif
+ return res;
+}
+
+
+/* --- set() --- */
+
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(set)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#if defined(ETHR_HAVE_NATMC32_SET)
+ ETHR_NATMC32_FUNC__(set)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_SET_RB)
+ ETHR_NATMC32_FUNC__(set_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_SET_WB)
+ ETHR_NATMC32_FUNC__(set_wb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_SET_ACQB)
+ ETHR_NATMC32_FUNC__(set_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_SET_RELB)
+ ETHR_NATMC32_FUNC__(set_relb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_SET_MB)
+ ETHR_NATMC32_FUNC__(set_mb)(var, (ETHR_NAINT32_T__) val);
+#else
+ (void) ETHR_ATMC32_FUNC__(xchg)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(set_rb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#if defined(ETHR_HAVE_NATMC32_SET_RB)
+ ETHR_NATMC32_FUNC__(set_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_SET)
+ ETHR_NATMC32_FUNC__(set)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_SET_MB)
+ ETHR_NATMC32_FUNC__(set_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_SET_WB)
+ ETHR_NATMC32_FUNC__(set_wb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_SET_ACQB)
+ ETHR_NATMC32_FUNC__(set_acqb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_SET_RELB)
+ ETHR_NATMC32_FUNC__(set_relb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ (void) ETHR_ATMC32_FUNC__(xchg_rb)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(set_wb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#if defined(ETHR_HAVE_NATMC32_SET_WB)
+ ETHR_NATMC32_FUNC__(set_wb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_SET)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(set)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_SET_MB)
+ ETHR_NATMC32_FUNC__(set_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_SET_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(set_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_SET_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(set_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_SET_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(set_relb)(var, (ETHR_NAINT32_T__) val);
+#else
+ (void) ETHR_ATMC32_FUNC__(xchg_wb)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(set_acqb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#if defined(ETHR_HAVE_NATMC32_SET_ACQB)
+ ETHR_NATMC32_FUNC__(set_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_SET_RB)
+ ETHR_NATMC32_FUNC__(set_rb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_SET)
+ ETHR_NATMC32_FUNC__(set)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_SET_MB)
+ ETHR_NATMC32_FUNC__(set_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_SET_WB)
+ ETHR_NATMC32_FUNC__(set_wb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_SET_RELB)
+ ETHR_NATMC32_FUNC__(set_relb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ (void) ETHR_ATMC32_FUNC__(xchg_acqb)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(set_relb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#if defined(ETHR_HAVE_NATMC32_SET_RELB)
+ ETHR_NATMC32_FUNC__(set_relb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_SET_WB)
+ ETHR_MEMBAR(ETHR_LoadStore);
+ ETHR_NATMC32_FUNC__(set_wb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_SET)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(set)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_SET_MB)
+ ETHR_NATMC32_FUNC__(set_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_SET_RB)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(set_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_SET_ACQB)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(set_acqb)(var, (ETHR_NAINT32_T__) val);
+#else
+ (void) ETHR_ATMC32_FUNC__(xchg_relb)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(set_mb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#if defined(ETHR_HAVE_NATMC32_SET_MB)
+ ETHR_NATMC32_FUNC__(set_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_SET_RELB)
+ ETHR_NATMC32_FUNC__(set_relb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_SET_ACQB)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(set_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_SET_WB)
+ ETHR_MEMBAR(ETHR_LoadStore);
+ ETHR_NATMC32_FUNC__(set_wb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_SET_RB)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(set_rb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_SET)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(set)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ (void) ETHR_ATMC32_FUNC__(xchg_mb)(var, val);
+#endif
+}
+
+
+/* --- init() --- */
+
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(init)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#if defined(ETHR_HAVE_NATMC32_INIT)
+ ETHR_NATMC32_FUNC__(init)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_INIT_RB)
+ ETHR_NATMC32_FUNC__(init_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_INIT_WB)
+ ETHR_NATMC32_FUNC__(init_wb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_INIT_ACQB)
+ ETHR_NATMC32_FUNC__(init_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_INIT_RELB)
+ ETHR_NATMC32_FUNC__(init_relb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_INIT_MB)
+ ETHR_NATMC32_FUNC__(init_mb)(var, (ETHR_NAINT32_T__) val);
#else
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, --(*var));
+ ETHR_ATMC32_FUNC__(set)(var, val);
#endif
}
-static ETHR_INLINE ethr_sint32_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic32_inc_read)(ethr_atomic32_t *var)
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(init_rb)(ethr_atomic32_t *var, ethr_sint32_t val)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return)(var);
+#if defined(ETHR_HAVE_NATMC32_INIT_RB)
+ ETHR_NATMC32_FUNC__(init_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_INIT)
+ ETHR_NATMC32_FUNC__(init)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_INIT_MB)
+ ETHR_NATMC32_FUNC__(init_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_INIT_WB)
+ ETHR_NATMC32_FUNC__(init_wb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_INIT_ACQB)
+ ETHR_NATMC32_FUNC__(init_acqb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_INIT_RELB)
+ ETHR_NATMC32_FUNC__(init_relb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
#else
+ ETHR_ATMC32_FUNC__(set_rb)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(init_wb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#if defined(ETHR_HAVE_NATMC32_INIT_WB)
+ ETHR_NATMC32_FUNC__(init_wb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_INIT)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(init)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_INIT_MB)
+ ETHR_NATMC32_FUNC__(init_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_INIT_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(init_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_INIT_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(init_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_INIT_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(init_relb)(var, (ETHR_NAINT32_T__) val);
+#else
+ ETHR_ATMC32_FUNC__(set_wb)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(init_acqb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#if defined(ETHR_HAVE_NATMC32_INIT_ACQB)
+ ETHR_NATMC32_FUNC__(init_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_INIT_RB)
+ ETHR_NATMC32_FUNC__(init_rb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_INIT)
+ ETHR_NATMC32_FUNC__(init)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_INIT_MB)
+ ETHR_NATMC32_FUNC__(init_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_INIT_WB)
+ ETHR_NATMC32_FUNC__(init_wb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_INIT_RELB)
+ ETHR_NATMC32_FUNC__(init_relb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_ATMC32_FUNC__(set_acqb)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(init_relb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#if defined(ETHR_HAVE_NATMC32_INIT_RELB)
+ ETHR_NATMC32_FUNC__(init_relb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_INIT_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(init_wb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_INIT)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(init)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_INIT_MB)
+ ETHR_NATMC32_FUNC__(init_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_INIT_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(init_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_INIT_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(init_acqb)(var, (ETHR_NAINT32_T__) val);
+#else
+ ETHR_ATMC32_FUNC__(set_relb)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(init_mb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#if defined(ETHR_HAVE_NATMC32_INIT_MB)
+ ETHR_NATMC32_FUNC__(init_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_INIT_RELB)
+ ETHR_NATMC32_FUNC__(init_relb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_INIT_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(init_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_INIT_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(init_wb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_INIT_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(init_rb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_INIT)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(init)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_ATMC32_FUNC__(set_mb)(var, val);
+#endif
+}
+
+
+/* --- add_read() --- */
+
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(add_read)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
ethr_sint32_t res;
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = ++(*var));
+#if defined(ETHR_HAVE_NATMC32_ADD_RETURN)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN_RB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_wb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN_ACQB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_relb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_rb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_wb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_acqb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_relb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_mb), var, aval, aval += val; res = aval);
+#else
+#error "Missing implementation of ethr_atomic32_add_read()!"
+#endif
return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(add_read_rb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_ADD_RETURN_RB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_wb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN_ACQB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_acqb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_relb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_rb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg), var, aval, aval += val; res = aval);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_mb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_wb), var, aval, aval += val; res = aval);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_acqb), var, aval, aval += val; res = aval);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_relb), var, aval, aval += val; res = aval);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+#error "Missing implementation of ethr_atomic32_add_read_rb()!"
#endif
+ return res;
}
-static ETHR_INLINE ethr_sint32_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic32_dec_read)(ethr_atomic32_t *var)
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(add_read_wb)(ethr_atomic32_t *var, ethr_sint32_t val)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return)(var);
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_ADD_RETURN_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_wb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_relb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_wb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_mb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_rb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_acqb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_relb), var, aval, aval += val; res = aval);
#else
+#error "Missing implementation of ethr_atomic32_add_read_wb()!"
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(add_read_acqb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
ethr_sint32_t res;
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = --(*var));
+#if defined(ETHR_HAVE_NATMC32_ADD_RETURN_ACQB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN_RB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_rb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_wb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_relb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_acqb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_rb), var, aval, aval += val; res = aval);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg), var, aval, aval += val; res = aval);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_mb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_wb), var, aval, aval += val; res = aval);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_relb), var, aval, aval += val; res = aval);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+#error "Missing implementation of ethr_atomic32_add_read_acqb()!"
+#endif
return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(add_read_relb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_ADD_RETURN_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_relb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_wb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_relb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_wb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_mb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_rb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_acqb), var, aval, aval += val; res = aval);
+#else
+#error "Missing implementation of ethr_atomic32_add_read_relb()!"
#endif
+ return res;
}
-static ETHR_INLINE ethr_sint32_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic32_read_band)(ethr_atomic32_t *var,
- ethr_sint32_t mask)
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(add_read_mb)(ethr_atomic32_t *var, ethr_sint32_t val)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return (ethr_sint32_t)
- ETHR_NATMC32_FUNC__(and_retold)(var, (ETHR_NAINT32_T__) mask);
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_ADD_RETURN_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_relb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_wb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return_rb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RETURN)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(add_return)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_mb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_relb), var, aval, aval += val; res = aval);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_acqb), var, aval, aval += val; res = aval);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_wb), var, aval, aval += val; res = aval);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_rb), var, aval, aval += val; res = aval);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg), var, aval, aval += val; res = aval);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
#else
+#error "Missing implementation of ethr_atomic32_add_read_mb()!"
+#endif
+ return res;
+}
+
+
+/* --- read() --- */
+
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(read)(ethr_atomic32_t *var)
+{
ethr_sint32_t res;
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var &= mask);
+#if defined(ETHR_HAVE_NATMC32_READ)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read)(var);
+#elif defined(ETHR_HAVE_NATMC32_READ_RB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_rb)(var);
+#elif defined(ETHR_HAVE_NATMC32_READ_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_wb)(var);
+#elif defined(ETHR_HAVE_NATMC32_READ_ACQB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC32_READ_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_relb)(var);
+#elif defined(ETHR_HAVE_NATMC32_READ_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_mb)(var);
+#else
+ res = ETHR_ATMC32_FUNC__(cmpxchg)(var, (ethr_sint32_t) ETHR_UNUSUAL_SINT32_VAL__, (ethr_sint32_t) ETHR_UNUSUAL_SINT32_VAL__);
+#endif
return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(read_rb)(ethr_atomic32_t *var)
+{
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_READ_RB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_rb)(var);
+#elif defined(ETHR_HAVE_NATMC32_READ)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_READ_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_mb)(var);
+#elif defined(ETHR_HAVE_NATMC32_READ_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_READ_ACQB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_acqb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_READ_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ res = ETHR_ATMC32_FUNC__(cmpxchg_rb)(var, (ethr_sint32_t) ETHR_UNUSUAL_SINT32_VAL__, (ethr_sint32_t) ETHR_UNUSUAL_SINT32_VAL__);
#endif
+ return res;
}
-static ETHR_INLINE ethr_sint32_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic32_read_bor)(ethr_atomic32_t *var,
- ethr_sint32_t mask)
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(read_wb)(ethr_atomic32_t *var)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return
- (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold)(var,
- (ETHR_NAINT32_T__) mask);
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_READ_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_wb)(var);
+#elif defined(ETHR_HAVE_NATMC32_READ)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read)(var);
+#elif defined(ETHR_HAVE_NATMC32_READ_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_mb)(var);
+#elif defined(ETHR_HAVE_NATMC32_READ_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_rb)(var);
+#elif defined(ETHR_HAVE_NATMC32_READ_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC32_READ_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_relb)(var);
#else
+ res = ETHR_ATMC32_FUNC__(cmpxchg_wb)(var, (ethr_sint32_t) ETHR_UNUSUAL_SINT32_VAL__, (ethr_sint32_t) ETHR_UNUSUAL_SINT32_VAL__);
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(read_acqb)(ethr_atomic32_t *var)
+{
ethr_sint32_t res;
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var |= mask);
+#if defined(ETHR_HAVE_NATMC32_READ_ACQB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC32_READ_RB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_rb)(var);
+ ETHR_MEMBAR(ETHR_LoadStore);
+#elif defined(ETHR_HAVE_NATMC32_READ)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#elif defined(ETHR_HAVE_NATMC32_READ_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_mb)(var);
+#elif defined(ETHR_HAVE_NATMC32_READ_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#elif defined(ETHR_HAVE_NATMC32_READ_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#else
+ res = ETHR_ATMC32_FUNC__(cmpxchg_acqb)(var, (ethr_sint32_t) ETHR_UNUSUAL_SINT32_VAL__, (ethr_sint32_t) ETHR_UNUSUAL_SINT32_VAL__);
+#endif
return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(read_relb)(ethr_atomic32_t *var)
+{
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_READ_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_relb)(var);
+#elif defined(ETHR_HAVE_NATMC32_READ_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_wb)(var);
+#elif defined(ETHR_HAVE_NATMC32_READ)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read)(var);
+#elif defined(ETHR_HAVE_NATMC32_READ_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_mb)(var);
+#elif defined(ETHR_HAVE_NATMC32_READ_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_rb)(var);
+#elif defined(ETHR_HAVE_NATMC32_READ_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_acqb)(var);
+#else
+ res = ETHR_ATMC32_FUNC__(cmpxchg_relb)(var, (ethr_sint32_t) ETHR_UNUSUAL_SINT32_VAL__, (ethr_sint32_t) ETHR_UNUSUAL_SINT32_VAL__);
#endif
+ return res;
}
-static ETHR_INLINE ethr_sint32_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic32_xchg)(ethr_atomic32_t *var,
- ethr_sint32_t new)
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(read_mb)(ethr_atomic32_t *var)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return (ethr_sint32_t) ETHR_NATMC32_FUNC__(xchg)(var,
- (ETHR_NAINT32_T__) new);
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_READ_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_mb)(var);
+#elif defined(ETHR_HAVE_NATMC32_READ_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#elif defined(ETHR_HAVE_NATMC32_READ_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC32_READ_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#elif defined(ETHR_HAVE_NATMC32_READ_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_rb)(var);
+ ETHR_MEMBAR(ETHR_LoadStore);
+#elif defined(ETHR_HAVE_NATMC32_READ)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(read)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
#else
+ res = ETHR_ATMC32_FUNC__(cmpxchg_mb)(var, (ethr_sint32_t) ETHR_UNUSUAL_SINT32_VAL__, (ethr_sint32_t) ETHR_UNUSUAL_SINT32_VAL__);
+#endif
+ return res;
+}
+
+
+/* --- inc_read() --- */
+
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(inc_read)(ethr_atomic32_t *var)
+{
ethr_sint32_t res;
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var = new);
+#if defined(ETHR_HAVE_NATMC32_INC_RETURN)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN_RB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_rb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_wb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN_ACQB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_relb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_mb)(var);
+#else
+ res = ETHR_ATMC32_FUNC__(add_read)(var, (ethr_sint32_t) 1);
+#endif
return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(inc_read_rb)(ethr_atomic32_t *var)
+{
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_INC_RETURN_RB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_rb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_mb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN_ACQB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_acqb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ res = ETHR_ATMC32_FUNC__(add_read_rb)(var, (ethr_sint32_t) 1);
#endif
+ return res;
}
-static ETHR_INLINE ethr_sint32_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic32_cmpxchg)(ethr_atomic32_t *var,
- ethr_sint32_t new,
- ethr_sint32_t exp)
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(inc_read_wb)(ethr_atomic32_t *var)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return (ethr_sint32_t) ETHR_NATMC32_FUNC__(cmpxchg)(var,
- (ETHR_NAINT32_T__) new,
- (ETHR_NAINT32_T__) exp);
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_INC_RETURN_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_wb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_mb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_rb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_relb)(var);
#else
+ res = ETHR_ATMC32_FUNC__(add_read_wb)(var, (ethr_sint32_t) 1);
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(inc_read_acqb)(ethr_atomic32_t *var)
+{
ethr_sint32_t res;
- ETHR_ATOMIC_OP_FALLBACK_IMPL__(var,
- {
- res = *var;
- if (__builtin_expect(res == exp, 1))
- *var = new;
- });
+#if defined(ETHR_HAVE_NATMC32_INC_RETURN_ACQB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN_RB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_rb)(var);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_mb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ res = ETHR_ATMC32_FUNC__(add_read_acqb)(var, (ethr_sint32_t) 1);
+#endif
return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(inc_read_relb)(ethr_atomic32_t *var)
+{
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_INC_RETURN_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_relb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_wb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_mb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_rb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_acqb)(var);
+#else
+ res = ETHR_ATMC32_FUNC__(add_read_relb)(var, (ethr_sint32_t) 1);
#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(inc_read_mb)(ethr_atomic32_t *var)
+{
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_INC_RETURN_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_mb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_rb)(var);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_INC_RETURN)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ res = ETHR_ATMC32_FUNC__(add_read_mb)(var, (ethr_sint32_t) 1);
+#endif
+ return res;
}
-/*
- * Important memory barrier requirements.
- *
- * The following atomic operations *must* supply a memory barrier of
- * at least the type specified by its suffix:
- * _acqb = acquire barrier
- * _relb = release barrier
- */
-static ETHR_INLINE ethr_sint32_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic32_read_acqb)(ethr_atomic32_t *var)
+/* --- dec_read() --- */
+
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(dec_read)(ethr_atomic32_t *var)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return (ethr_sint32_t) ETHR_NATMC32_FUNC__(read_acqb)(var);
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_DEC_RETURN)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN_RB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_rb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_wb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN_ACQB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_relb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_mb)(var);
#else
- return ETHR_INLINE_FUNC_NAME_(ethr_atomic32_read)(var);
+ res = ETHR_ATMC32_FUNC__(add_read)(var, (ethr_sint32_t) -1);
#endif
+ return res;
}
-static ETHR_INLINE ethr_sint32_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic32_inc_read_acqb)(ethr_atomic32_t *var)
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(dec_read_rb)(ethr_atomic32_t *var)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return (ethr_sint32_t) ETHR_NATMC32_FUNC__(inc_return_acqb)(var);
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_DEC_RETURN_RB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_rb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_mb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN_ACQB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_acqb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
#else
- return ETHR_INLINE_FUNC_NAME_(ethr_atomic32_inc_read)(var);
+ res = ETHR_ATMC32_FUNC__(add_read_rb)(var, (ethr_sint32_t) -1);
#endif
+ return res;
}
-static ETHR_INLINE void
-ETHR_INLINE_FUNC_NAME_(ethr_atomic32_set_relb)(ethr_atomic32_t *var,
- ethr_sint32_t val)
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(dec_read_wb)(ethr_atomic32_t *var)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- ETHR_NATMC32_FUNC__(set_relb)(var, (ETHR_NAINT32_T__) val);
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_DEC_RETURN_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_wb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_mb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_rb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_relb)(var);
+#else
+ res = ETHR_ATMC32_FUNC__(add_read_wb)(var, (ethr_sint32_t) -1);
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(dec_read_acqb)(ethr_atomic32_t *var)
+{
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_DEC_RETURN_ACQB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN_RB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_rb)(var);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_mb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
#else
- ETHR_INLINE_FUNC_NAME_(ethr_atomic32_set)(var, val);
+ res = ETHR_ATMC32_FUNC__(add_read_acqb)(var, (ethr_sint32_t) -1);
#endif
+ return res;
}
-static ETHR_INLINE void
-ETHR_INLINE_FUNC_NAME_(ethr_atomic32_dec_relb)(ethr_atomic32_t *var)
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(dec_read_relb)(ethr_atomic32_t *var)
+{
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_DEC_RETURN_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_relb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_wb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_mb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_rb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_acqb)(var);
+#else
+ res = ETHR_ATMC32_FUNC__(add_read_relb)(var, (ethr_sint32_t) -1);
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(dec_read_mb)(ethr_atomic32_t *var)
+{
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_DEC_RETURN_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_mb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_rb)(var);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RETURN)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ res = ETHR_ATMC32_FUNC__(add_read_mb)(var, (ethr_sint32_t) -1);
+#endif
+ return res;
+}
+
+
+/* --- add() --- */
+
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(add)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#if defined(ETHR_HAVE_NATMC32_ADD)
+ ETHR_NATMC32_FUNC__(add)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RB)
+ ETHR_NATMC32_FUNC__(add_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_WB)
+ ETHR_NATMC32_FUNC__(add_wb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_ACQB)
+ ETHR_NATMC32_FUNC__(add_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RELB)
+ ETHR_NATMC32_FUNC__(add_relb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_MB)
+ ETHR_NATMC32_FUNC__(add_mb)(var, (ETHR_NAINT32_T__) val);
+#else
+ (void) ETHR_ATMC32_FUNC__(add_read)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(add_rb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#if defined(ETHR_HAVE_NATMC32_ADD_RB)
+ ETHR_NATMC32_FUNC__(add_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD)
+ ETHR_NATMC32_FUNC__(add)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_ADD_MB)
+ ETHR_NATMC32_FUNC__(add_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_WB)
+ ETHR_NATMC32_FUNC__(add_wb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_ADD_ACQB)
+ ETHR_NATMC32_FUNC__(add_acqb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RELB)
+ ETHR_NATMC32_FUNC__(add_relb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ (void) ETHR_ATMC32_FUNC__(add_read_rb)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(add_wb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#if defined(ETHR_HAVE_NATMC32_ADD_WB)
+ ETHR_NATMC32_FUNC__(add_wb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(add)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_MB)
+ ETHR_NATMC32_FUNC__(add_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(add_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(add_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(add_relb)(var, (ETHR_NAINT32_T__) val);
+#else
+ (void) ETHR_ATMC32_FUNC__(add_read_wb)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(add_acqb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#if defined(ETHR_HAVE_NATMC32_ADD_ACQB)
+ ETHR_NATMC32_FUNC__(add_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RB)
+ ETHR_NATMC32_FUNC__(add_rb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_ADD)
+ ETHR_NATMC32_FUNC__(add)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_ADD_MB)
+ ETHR_NATMC32_FUNC__(add_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_WB)
+ ETHR_NATMC32_FUNC__(add_wb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RELB)
+ ETHR_NATMC32_FUNC__(add_relb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ (void) ETHR_ATMC32_FUNC__(add_read_acqb)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(add_relb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#if defined(ETHR_HAVE_NATMC32_ADD_RELB)
+ ETHR_NATMC32_FUNC__(add_relb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(add_wb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(add)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_MB)
+ ETHR_NATMC32_FUNC__(add_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(add_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(add_acqb)(var, (ETHR_NAINT32_T__) val);
+#else
+ (void) ETHR_ATMC32_FUNC__(add_read_relb)(var, val);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(add_mb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#if defined(ETHR_HAVE_NATMC32_ADD_MB)
+ ETHR_NATMC32_FUNC__(add_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RELB)
+ ETHR_NATMC32_FUNC__(add_relb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_ADD_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(add_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_ADD_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(add_wb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_ADD_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(add_rb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_ADD)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(add)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ (void) ETHR_ATMC32_FUNC__(add_read_mb)(var, val);
+#endif
+}
+
+
+/* --- inc() --- */
+
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(inc)(ethr_atomic32_t *var)
+{
+#if defined(ETHR_HAVE_NATMC32_INC)
+ ETHR_NATMC32_FUNC__(inc)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RB)
+ ETHR_NATMC32_FUNC__(inc_rb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_WB)
+ ETHR_NATMC32_FUNC__(inc_wb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_ACQB)
+ ETHR_NATMC32_FUNC__(inc_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RELB)
+ ETHR_NATMC32_FUNC__(inc_relb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_MB)
+ ETHR_NATMC32_FUNC__(inc_mb)(var);
+#else
+ (void) ETHR_ATMC32_FUNC__(inc_read)(var);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(inc_rb)(ethr_atomic32_t *var)
+{
+#if defined(ETHR_HAVE_NATMC32_INC_RB)
+ ETHR_NATMC32_FUNC__(inc_rb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC)
+ ETHR_NATMC32_FUNC__(inc)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_INC_MB)
+ ETHR_NATMC32_FUNC__(inc_mb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_WB)
+ ETHR_NATMC32_FUNC__(inc_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_INC_ACQB)
+ ETHR_NATMC32_FUNC__(inc_acqb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_INC_RELB)
+ ETHR_NATMC32_FUNC__(inc_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ (void) ETHR_ATMC32_FUNC__(inc_read_rb)(var);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(inc_wb)(ethr_atomic32_t *var)
+{
+#if defined(ETHR_HAVE_NATMC32_INC_WB)
+ ETHR_NATMC32_FUNC__(inc_wb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(inc)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_MB)
+ ETHR_NATMC32_FUNC__(inc_mb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(inc_rb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(inc_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(inc_relb)(var);
+#else
+ (void) ETHR_ATMC32_FUNC__(inc_read_wb)(var);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(inc_acqb)(ethr_atomic32_t *var)
+{
+#if defined(ETHR_HAVE_NATMC32_INC_ACQB)
+ ETHR_NATMC32_FUNC__(inc_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RB)
+ ETHR_NATMC32_FUNC__(inc_rb)(var);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_INC)
+ ETHR_NATMC32_FUNC__(inc)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_INC_MB)
+ ETHR_NATMC32_FUNC__(inc_mb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_WB)
+ ETHR_NATMC32_FUNC__(inc_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_INC_RELB)
+ ETHR_NATMC32_FUNC__(inc_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ (void) ETHR_ATMC32_FUNC__(inc_read_acqb)(var);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(inc_relb)(ethr_atomic32_t *var)
+{
+#if defined(ETHR_HAVE_NATMC32_INC_RELB)
+ ETHR_NATMC32_FUNC__(inc_relb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(inc_wb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(inc)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_MB)
+ ETHR_NATMC32_FUNC__(inc_mb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(inc_rb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(inc_acqb)(var);
+#else
+ (void) ETHR_ATMC32_FUNC__(inc_read_relb)(var);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(inc_mb)(ethr_atomic32_t *var)
+{
+#if defined(ETHR_HAVE_NATMC32_INC_MB)
+ ETHR_NATMC32_FUNC__(inc_mb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_RELB)
+ ETHR_NATMC32_FUNC__(inc_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_INC_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(inc_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC32_INC_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(inc_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_INC_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(inc_rb)(var);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_INC)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(inc)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ (void) ETHR_ATMC32_FUNC__(inc_read_mb)(var);
+#endif
+}
+
+
+/* --- dec() --- */
+
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(dec)(ethr_atomic32_t *var)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
+#if defined(ETHR_HAVE_NATMC32_DEC)
+ ETHR_NATMC32_FUNC__(dec)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RB)
+ ETHR_NATMC32_FUNC__(dec_rb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_WB)
+ ETHR_NATMC32_FUNC__(dec_wb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_ACQB)
+ ETHR_NATMC32_FUNC__(dec_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RELB)
+ ETHR_NATMC32_FUNC__(dec_relb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_MB)
+ ETHR_NATMC32_FUNC__(dec_mb)(var);
+#else
+ (void) ETHR_ATMC32_FUNC__(dec_read)(var);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(dec_rb)(ethr_atomic32_t *var)
+{
+#if defined(ETHR_HAVE_NATMC32_DEC_RB)
+ ETHR_NATMC32_FUNC__(dec_rb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC)
+ ETHR_NATMC32_FUNC__(dec)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_DEC_MB)
+ ETHR_NATMC32_FUNC__(dec_mb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_WB)
+ ETHR_NATMC32_FUNC__(dec_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_DEC_ACQB)
+ ETHR_NATMC32_FUNC__(dec_acqb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RELB)
+ ETHR_NATMC32_FUNC__(dec_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ (void) ETHR_ATMC32_FUNC__(dec_read_rb)(var);
+#endif
+}
+
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(dec_wb)(ethr_atomic32_t *var)
+{
+#if defined(ETHR_HAVE_NATMC32_DEC_WB)
+ ETHR_NATMC32_FUNC__(dec_wb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(dec)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_MB)
+ ETHR_NATMC32_FUNC__(dec_mb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(dec_rb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_FUNC__(dec_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
ETHR_NATMC32_FUNC__(dec_relb)(var);
#else
- ETHR_INLINE_FUNC_NAME_(ethr_atomic32_dec)(var);
+ (void) ETHR_ATMC32_FUNC__(dec_read_wb)(var);
#endif
}
-static ETHR_INLINE ethr_sint32_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic32_dec_read_relb)(ethr_atomic32_t *var)
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(dec_acqb)(ethr_atomic32_t *var)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return (ethr_sint32_t) ETHR_NATMC32_FUNC__(dec_return_relb)(var);
+#if defined(ETHR_HAVE_NATMC32_DEC_ACQB)
+ ETHR_NATMC32_FUNC__(dec_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RB)
+ ETHR_NATMC32_FUNC__(dec_rb)(var);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_DEC)
+ ETHR_NATMC32_FUNC__(dec)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_DEC_MB)
+ ETHR_NATMC32_FUNC__(dec_mb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_WB)
+ ETHR_NATMC32_FUNC__(dec_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RELB)
+ ETHR_NATMC32_FUNC__(dec_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
#else
- return ETHR_INLINE_FUNC_NAME_(ethr_atomic32_dec_read)(var);
+ (void) ETHR_ATMC32_FUNC__(dec_read_acqb)(var);
#endif
}
-static ETHR_INLINE ethr_sint32_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic32_cmpxchg_acqb)(ethr_atomic32_t *var,
- ethr_sint32_t new,
- ethr_sint32_t exp)
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(dec_relb)(ethr_atomic32_t *var)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return (ethr_sint32_t)
- ETHR_NATMC32_FUNC__(cmpxchg_acqb)(var,
- (ETHR_NAINT32_T__) new,
- (ETHR_NAINT32_T__) exp);
+#if defined(ETHR_HAVE_NATMC32_DEC_RELB)
+ ETHR_NATMC32_FUNC__(dec_relb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(dec_wb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(dec)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_MB)
+ ETHR_NATMC32_FUNC__(dec_mb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(dec_rb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(dec_acqb)(var);
#else
- return ETHR_INLINE_FUNC_NAME_(ethr_atomic32_cmpxchg)(var, new, exp);
+ (void) ETHR_ATMC32_FUNC__(dec_read_relb)(var);
#endif
}
-static ETHR_INLINE ethr_sint32_t
-ETHR_INLINE_FUNC_NAME_(ethr_atomic32_cmpxchg_relb)(ethr_atomic32_t *var,
- ethr_sint32_t new,
- ethr_sint32_t exp)
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(dec_mb)(ethr_atomic32_t *var)
{
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
- return (ethr_sint32_t)
- ETHR_NATMC32_FUNC__(cmpxchg_relb)(var,
- (ETHR_NAINT32_T__) new,
- (ETHR_NAINT32_T__) exp);
+#if defined(ETHR_HAVE_NATMC32_DEC_MB)
+ ETHR_NATMC32_FUNC__(dec_mb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RELB)
+ ETHR_NATMC32_FUNC__(dec_relb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_DEC_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(dec_acqb)(var);
+#elif defined(ETHR_HAVE_NATMC32_DEC_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(dec_wb)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_DEC_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(dec_rb)(var);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_DEC)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_FUNC__(dec)(var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
#else
- return ETHR_INLINE_FUNC_NAME_(ethr_atomic32_cmpxchg)(var, new, exp);
+ (void) ETHR_ATMC32_FUNC__(dec_read_mb)(var);
#endif
}
-#endif /* ETHR_TRY_INLINE_FUNCS */
+/* --- read_band() --- */
-#undef ETHR_NAINT_T__
-#undef ETHR_NATMC_FUNC__
-#undef ETHR_NATMC_ADDR_FUNC__
-#undef ETHR_NAINT32_T__
-#undef ETHR_NATMC32_FUNC__
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(read_band)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_AND_RETOLD)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD_RB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_wb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD_ACQB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_relb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_rb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_wb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_relb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_mb), var, aval, res = aval; aval &= val);
+#else
+#error "Missing implementation of ethr_atomic32_read_band()!"
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(read_band_rb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_AND_RETOLD_RB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_wb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD_ACQB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_acqb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_relb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_rb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg), var, aval, res = aval; aval &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_mb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_wb), var, aval, res = aval; aval &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_relb), var, aval, res = aval; aval &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+#error "Missing implementation of ethr_atomic32_read_band_rb()!"
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(read_band_wb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_AND_RETOLD_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_wb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_relb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_wb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_mb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_rb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_relb), var, aval, res = aval; aval &= val);
+#else
+#error "Missing implementation of ethr_atomic32_read_band_wb()!"
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(read_band_acqb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_AND_RETOLD_ACQB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD_RB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_rb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_wb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_relb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_rb), var, aval, res = aval; aval &= val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg), var, aval, res = aval; aval &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_mb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_wb), var, aval, res = aval; aval &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_relb), var, aval, res = aval; aval &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+#error "Missing implementation of ethr_atomic32_read_band_acqb()!"
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(read_band_relb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_AND_RETOLD_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_relb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_wb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_relb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_wb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_mb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_rb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval &= val);
+#else
+#error "Missing implementation of ethr_atomic32_read_band_relb()!"
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(read_band_mb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_AND_RETOLD_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_relb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_wb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold_rb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_AND_RETOLD)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(and_retold)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_mb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_relb), var, aval, res = aval; aval &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval &= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_wb), var, aval, res = aval; aval &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_rb), var, aval, res = aval; aval &= val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg), var, aval, res = aval; aval &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+#error "Missing implementation of ethr_atomic32_read_band_mb()!"
+#endif
+ return res;
+}
+
+
+/* --- read_bor() --- */
+
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(read_bor)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_OR_RETOLD)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD_RB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_wb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD_ACQB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_relb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_rb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_wb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_relb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_mb), var, aval, res = aval; aval |= val);
+#else
+#error "Missing implementation of ethr_atomic32_read_bor()!"
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(read_bor_rb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_OR_RETOLD_RB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_wb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD_ACQB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_acqb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_relb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_rb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg), var, aval, res = aval; aval |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_mb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_wb), var, aval, res = aval; aval |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_relb), var, aval, res = aval; aval |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+#error "Missing implementation of ethr_atomic32_read_bor_rb()!"
+#endif
+ return res;
+}
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(read_bor_wb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_OR_RETOLD_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_wb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_relb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_wb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_mb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_rb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_relb), var, aval, res = aval; aval |= val);
+#else
+#error "Missing implementation of ethr_atomic32_read_bor_wb()!"
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(read_bor_acqb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_OR_RETOLD_ACQB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD_RB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_rb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD_WB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_wb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_relb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_rb), var, aval, res = aval; aval |= val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg), var, aval, res = aval; aval |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_mb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_wb), var, aval, res = aval; aval |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_relb), var, aval, res = aval; aval |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+#error "Missing implementation of ethr_atomic32_read_bor_acqb()!"
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(read_bor_relb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_OR_RETOLD_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_relb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_wb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_rb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_relb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_wb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_mb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_rb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval |= val);
+#else
+#error "Missing implementation of ethr_atomic32_read_bor_relb()!"
+#endif
+ return res;
+}
+
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(read_bor_mb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+#if defined(ETHR_HAVE_NATMC32_OR_RETOLD_MB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_mb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD_RELB)
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_relb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_acqb)(var, (ETHR_NAINT32_T__) val);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_wb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold_rb)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_OR_RETOLD)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = (ethr_sint32_t) ETHR_NATMC32_FUNC__(or_retold)(var, (ETHR_NAINT32_T__) val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_MB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_mb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RELB)
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_relb), var, aval, res = aval; aval |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_ACQB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_acqb), var, aval, res = aval; aval |= val);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_WB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_wb), var, aval, res = aval; aval |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG_RB)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg_rb), var, aval, res = aval; aval |= val);
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#elif defined(ETHR_HAVE_NATMC32_CMPXCHG)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_NATMC32_CMPXCHG_FALLBACK__(ETHR_NATMC32_FUNC__(cmpxchg), var, aval, res = aval; aval |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+#error "Missing implementation of ethr_atomic32_read_bor_mb()!"
#endif
+ return res;
+}
+
+#endif /* ETHR_ATMC32_INLINE__ */
+
+#endif /* ETHR_ATOMICS_H__ */
diff --git a/erts/include/internal/ethr_internal.h b/erts/include/internal/ethr_internal.h
index e9c3daf783..c9b1db5b46 100644
--- a/erts/include/internal/ethr_internal.h
+++ b/erts/include/internal/ethr_internal.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -63,5 +63,9 @@ int ethr_late_init_common__(ethr_late_init_data *lid);
void ethr_run_exit_handlers__(void);
void ethr_ts_event_destructor__(void *vtsep);
+#if defined(ETHR_X86_RUNTIME_CONF__)
+int ethr_x86_have_cpuid__(void);
+void ethr_x86_cpuid__(int *eax, int *ebx, int *ecx, int *edx);
+#endif
#endif
diff --git a/erts/include/internal/ethr_mutex.h b/erts/include/internal/ethr_mutex.h
index fadaf1e2a4..86a1e9fbdf 100644
--- a/erts/include/internal/ethr_mutex.h
+++ b/erts/include/internal/ethr_mutex.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -22,6 +22,23 @@
* Author: Rickard Green
*/
+/*
+ * IMPORTANT note about ethr_cond_signal() and ethr_cond_broadcast()
+ *
+ * POSIX allow a call to `pthread_cond_signal' or `pthread_cond_broadcast'
+ * even though the associated mutex/mutexes isn't/aren't locked by the
+ * caller. We do not allow that by default in order to avoid a performance
+ * penalty on some platforms.
+ *
+ * Mutexes and condition variables can, however, be initialized as POSIX
+ * compliant. When initialized as such ethr_cond_signal(), and
+ * ethr_cond_broadcast() are allowed to be called even though the associated
+ * mutexes aren't locked. This will, however, incur a performance penalty on
+ * some platforms.
+ *
+ * POSIX compliant mutexes and condition variables *need* to be used together.
+ */
+
#ifndef ETHR_MUTEX_H__
#define ETHR_MUTEX_H__
@@ -40,6 +57,14 @@
#endif
#endif
+/* #define ETHR_DBG_WIN_MTX_WITH_PTHREADS */
+#ifdef ETHR_DBG_WIN_MTX_WITH_PTHREADS
+typedef pthread_mutex_t CRITICAL_SECTION;
+int TryEnterCriticalSection(CRITICAL_SECTION *);
+void EnterCriticalSection(CRITICAL_SECTION *);
+void LeaveCriticalSection(CRITICAL_SECTION *);
+#endif
+
#ifdef ETHR_MTX_HARD_DEBUG
# ifdef __GNUC__
# warning ETHR_MTX_HARD_DEBUG
@@ -54,6 +79,10 @@
# endif
#endif
+#ifndef ETHR_INLINE_MTX_FUNC_NAME_
+# define ETHR_INLINE_MTX_FUNC_NAME_(X) X
+#endif
+
#if defined(ETHR_USE_OWN_RWMTX_IMPL__) || defined(ETHR_USE_OWN_MTX_IMPL__)
#ifdef ETHR_DEBUG
@@ -136,13 +165,19 @@ struct ethr_mutex_base_ {
typedef struct {
int main_spincount;
int aux_spincount;
+ int posix_compliant;
} ethr_mutex_opt;
+#define ETHR_MUTEX_OPT_DEFAULT_INITER {-1, -1, 0}
+
typedef struct {
int main_spincount;
int aux_spincount;
+ int posix_compliant;
} ethr_cond_opt;
+#define ETHR_COND_OPT_DEFAULT_INITER {-1, -1, 0}
+
#ifdef ETHR_USE_OWN_MTX_IMPL__
typedef struct ethr_mutex_ ethr_mutex;
@@ -175,7 +210,7 @@ struct ethr_cond_ {
#endif
};
-#else /* pthread */
+#elif defined(ETHR_PTHREADS) && !defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS)
typedef struct ethr_mutex_ ethr_mutex;
struct ethr_mutex_ {
@@ -193,7 +228,36 @@ struct ethr_cond_ {
#endif
};
-#endif /* pthread */
+#elif defined(ETHR_WIN32_THREADS) || defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS)
+# define ETHR_WIN_MUTEX__
+
+typedef struct ethr_mutex_ ethr_mutex;
+struct ethr_mutex_ {
+ int posix_compliant;
+ CRITICAL_SECTION cs;
+ ethr_ts_event *wakeups;
+ ethr_atomic32_t have_wakeups; /* only when posix compliant */
+ ethr_atomic32_t locked; /* only when posix compliant */
+ ethr_spinlock_t lock; /* only when posix compliant */
+#if ETHR_XCHK
+ int initialized;
+#endif
+};
+
+typedef struct ethr_cond_ ethr_cond;
+struct ethr_cond_ {
+ int posix_compliant;
+ CRITICAL_SECTION cs;
+ ethr_ts_event *waiters;
+ int spincount;
+#if ETHR_XCHK
+ int initialized;
+#endif
+};
+
+#else
+# error "no mutex implementation"
+#endif
int ethr_mutex_init_opt(ethr_mutex *, ethr_mutex_opt *);
int ethr_mutex_init(ethr_mutex *);
@@ -505,7 +569,7 @@ void ethr_mutex_lock_wait__(ethr_mutex *, ethr_sint32_t);
void ethr_mutex_unlock_wake__(ethr_mutex *, ethr_sint32_t);
static ETHR_INLINE int
-ETHR_INLINE_FUNC_NAME_(ethr_mutex_trylock)(ethr_mutex *mtx)
+ETHR_INLINE_MTX_FUNC_NAME_(ethr_mutex_trylock)(ethr_mutex *mtx)
{
ethr_sint32_t act;
int res;
@@ -529,7 +593,7 @@ ETHR_INLINE_FUNC_NAME_(ethr_mutex_trylock)(ethr_mutex *mtx)
}
static ETHR_INLINE void
-ETHR_INLINE_FUNC_NAME_(ethr_mutex_lock)(ethr_mutex *mtx)
+ETHR_INLINE_MTX_FUNC_NAME_(ethr_mutex_lock)(ethr_mutex *mtx)
{
ethr_sint32_t act;
ETHR_MTX_HARD_DEBUG_FENCE_CHK(mtx);
@@ -549,7 +613,7 @@ ETHR_INLINE_FUNC_NAME_(ethr_mutex_lock)(ethr_mutex *mtx)
}
static ETHR_INLINE void
-ETHR_INLINE_FUNC_NAME_(ethr_mutex_unlock)(ethr_mutex *mtx)
+ETHR_INLINE_MTX_FUNC_NAME_(ethr_mutex_unlock)(ethr_mutex *mtx)
{
ethr_sint32_t act;
ETHR_COMPILER_BARRIER;
@@ -569,12 +633,12 @@ ETHR_INLINE_FUNC_NAME_(ethr_mutex_unlock)(ethr_mutex *mtx)
#endif /* ETHR_TRY_INLINE_FUNCS */
-#else /* pthread_mutex */
+#elif defined(ETHR_PTHREADS) && !defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS)
#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_MUTEX_IMPL__)
static ETHR_INLINE int
-ETHR_INLINE_FUNC_NAME_(ethr_mutex_trylock)(ethr_mutex *mtx)
+ETHR_INLINE_MTX_FUNC_NAME_(ethr_mutex_trylock)(ethr_mutex *mtx)
{
int res;
res = pthread_mutex_trylock(&mtx->pt_mtx);
@@ -584,7 +648,7 @@ ETHR_INLINE_FUNC_NAME_(ethr_mutex_trylock)(ethr_mutex *mtx)
}
static ETHR_INLINE void
-ETHR_INLINE_FUNC_NAME_(ethr_mutex_lock)(ethr_mutex *mtx)
+ETHR_INLINE_MTX_FUNC_NAME_(ethr_mutex_lock)(ethr_mutex *mtx)
{
int res = pthread_mutex_lock(&mtx->pt_mtx);
if (res != 0)
@@ -592,7 +656,7 @@ ETHR_INLINE_FUNC_NAME_(ethr_mutex_lock)(ethr_mutex *mtx)
}
static ETHR_INLINE void
-ETHR_INLINE_FUNC_NAME_(ethr_mutex_unlock)(ethr_mutex *mtx)
+ETHR_INLINE_MTX_FUNC_NAME_(ethr_mutex_unlock)(ethr_mutex *mtx)
{
int res = pthread_mutex_unlock(&mtx->pt_mtx);
if (res != 0)
@@ -601,7 +665,54 @@ ETHR_INLINE_FUNC_NAME_(ethr_mutex_unlock)(ethr_mutex *mtx)
#endif /* ETHR_TRY_INLINE_FUNCS */
-#endif /* pthread_mutex */
+#elif defined(ETHR_WIN32_THREADS) || defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS)
+
+#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_MUTEX_IMPL__)
+
+static ETHR_INLINE int
+ETHR_INLINE_MTX_FUNC_NAME_(ethr_mutex_trylock)(ethr_mutex *mtx)
+{
+ if (!TryEnterCriticalSection(&mtx->cs))
+ return EBUSY;
+ if (mtx->posix_compliant)
+ ethr_atomic32_set(&mtx->locked, 1);
+ return 0;
+}
+
+static ETHR_INLINE void
+ETHR_INLINE_MTX_FUNC_NAME_(ethr_mutex_lock)(ethr_mutex *mtx)
+{
+ EnterCriticalSection(&mtx->cs);
+ if (mtx->posix_compliant)
+ ethr_atomic32_set(&mtx->locked, 1);
+}
+
+void ethr_mutex_cond_wakeup__(ethr_mutex *mtx);
+
+static ETHR_INLINE void
+ETHR_INLINE_MTX_FUNC_NAME_(ethr_mutex_unlock)(ethr_mutex *mtx)
+{
+ if (mtx->posix_compliant) {
+ ethr_atomic32_set_mb(&mtx->locked, 0);
+ if (ethr_atomic32_read_acqb(&mtx->have_wakeups))
+ goto cond_wakeup;
+ else
+ goto leave_cs;
+ }
+
+ if (mtx->wakeups) {
+ cond_wakeup:
+ ethr_mutex_cond_wakeup__(mtx);
+ }
+ else {
+ leave_cs:
+ LeaveCriticalSection(&mtx->cs);
+ }
+}
+
+#endif /* ETHR_TRY_INLINE_FUNCS */
+
+#endif
#ifdef ETHR_USE_OWN_RWMTX_IMPL__
@@ -615,7 +726,7 @@ ETHR_INLINE_FUNC_NAME_(ethr_mutex_unlock)(ethr_mutex *mtx)
#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_MUTEX_IMPL__)
static ETHR_INLINE int
-ETHR_INLINE_FUNC_NAME_(ethr_rwmutex_tryrlock)(ethr_rwmutex *rwmtx)
+ETHR_INLINE_MTX_FUNC_NAME_(ethr_rwmutex_tryrlock)(ethr_rwmutex *rwmtx)
{
int res = pthread_rwlock_tryrdlock(&rwmtx->pt_rwlock);
if (res != 0 && res != EBUSY)
@@ -624,7 +735,7 @@ ETHR_INLINE_FUNC_NAME_(ethr_rwmutex_tryrlock)(ethr_rwmutex *rwmtx)
}
static ETHR_INLINE void
-ETHR_INLINE_FUNC_NAME_(ethr_rwmutex_rlock)(ethr_rwmutex *rwmtx)
+ETHR_INLINE_MTX_FUNC_NAME_(ethr_rwmutex_rlock)(ethr_rwmutex *rwmtx)
{
int res = pthread_rwlock_rdlock(&rwmtx->pt_rwlock);
if (res != 0)
@@ -632,7 +743,7 @@ ETHR_INLINE_FUNC_NAME_(ethr_rwmutex_rlock)(ethr_rwmutex *rwmtx)
}
static ETHR_INLINE void
-ETHR_INLINE_FUNC_NAME_(ethr_rwmutex_runlock)(ethr_rwmutex *rwmtx)
+ETHR_INLINE_MTX_FUNC_NAME_(ethr_rwmutex_runlock)(ethr_rwmutex *rwmtx)
{
int res = pthread_rwlock_unlock(&rwmtx->pt_rwlock);
if (res != 0)
@@ -640,7 +751,7 @@ ETHR_INLINE_FUNC_NAME_(ethr_rwmutex_runlock)(ethr_rwmutex *rwmtx)
}
static ETHR_INLINE int
-ETHR_INLINE_FUNC_NAME_(ethr_rwmutex_tryrwlock)(ethr_rwmutex *rwmtx)
+ETHR_INLINE_MTX_FUNC_NAME_(ethr_rwmutex_tryrwlock)(ethr_rwmutex *rwmtx)
{
int res = pthread_rwlock_trywrlock(&rwmtx->pt_rwlock);
if (res != 0 && res != EBUSY)
@@ -649,7 +760,7 @@ ETHR_INLINE_FUNC_NAME_(ethr_rwmutex_tryrwlock)(ethr_rwmutex *rwmtx)
}
static ETHR_INLINE void
-ETHR_INLINE_FUNC_NAME_(ethr_rwmutex_rwlock)(ethr_rwmutex *rwmtx)
+ETHR_INLINE_MTX_FUNC_NAME_(ethr_rwmutex_rwlock)(ethr_rwmutex *rwmtx)
{
int res = pthread_rwlock_wrlock(&rwmtx->pt_rwlock);
if (res != 0)
@@ -657,7 +768,7 @@ ETHR_INLINE_FUNC_NAME_(ethr_rwmutex_rwlock)(ethr_rwmutex *rwmtx)
}
static ETHR_INLINE void
-ETHR_INLINE_FUNC_NAME_(ethr_rwmutex_rwunlock)(ethr_rwmutex *rwmtx)
+ETHR_INLINE_MTX_FUNC_NAME_(ethr_rwmutex_rwunlock)(ethr_rwmutex *rwmtx)
{
int res = pthread_rwlock_unlock(&rwmtx->pt_rwlock);
if (res != 0)
diff --git a/erts/include/internal/ethr_optimized_fallbacks.h b/erts/include/internal/ethr_optimized_fallbacks.h
index 8e04692856..45399d18e6 100644
--- a/erts/include/internal/ethr_optimized_fallbacks.h
+++ b/erts/include/internal/ethr_optimized_fallbacks.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -18,152 +18,172 @@
*/
/*
- * Description: "Optimized" fallbacks used when native ops are missing
+ * Description: Optimized fallbacks used when native ops are missing
* Author: Rickard Green
*/
#ifndef ETHR_OPTIMIZED_FALLBACKS_H__
#define ETHR_OPTIMIZED_FALLBACKS_H__
-#ifdef ETHR_HAVE_NATIVE_ATOMICS
-#define ETHR_HAVE_OPTIMIZED_ATOMIC_OPS 1
+#if defined(ETHR_HAVE_NATIVE_SPINLOCKS)
+
+#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_AUX_IMPL__)
+
+static ETHR_INLINE int
+ethr_native_spinlock_destroy(ethr_native_spinlock_t *lock)
+{
+ return 0;
+}
+
#endif
-#ifdef ETHR_HAVE_NATIVE_SPINLOCKS
-#define ETHR_HAVE_OPTIMIZED_SPINLOCKS 1
#elif defined(ETHR_HAVE_PTHREAD_SPIN_LOCK)
-/* --- Optimized spinlocks using pthread spinlocks -------------------------- */
-#define ETHR_HAVE_OPTIMIZED_SPINLOCKS 1
+/* --- Native spinlocks using pthread spinlocks -------------------------- */
+#define ETHR_HAVE_NATIVE_SPINLOCKS 1
+
+#define ETHR_NATIVE_SPINLOCK_IMPL "pthread"
-typedef pthread_spinlock_t ethr_opt_spinlock_t;
+typedef pthread_spinlock_t ethr_native_spinlock_t;
#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_AUX_IMPL__)
-static ETHR_INLINE int
-ethr_opt_spinlock_init(ethr_opt_spinlock_t *lock)
+static ETHR_INLINE void
+ethr_native_spinlock_init(ethr_native_spinlock_t *lock)
{
- return pthread_spin_init((pthread_spinlock_t *) lock, 0);
+ int err = pthread_spin_init((pthread_spinlock_t *) lock, 0);
+ if (err)
+ ETHR_FATAL_ERROR__(err);
}
static ETHR_INLINE int
-ethr_opt_spinlock_destroy(ethr_opt_spinlock_t *lock)
+ethr_native_spinlock_destroy(ethr_native_spinlock_t *lock)
{
return pthread_spin_destroy((pthread_spinlock_t *) lock);
}
-
-static ETHR_INLINE int
-ethr_opt_spin_unlock(ethr_opt_spinlock_t *lock)
+static ETHR_INLINE void
+ethr_native_spin_unlock(ethr_native_spinlock_t *lock)
{
- return pthread_spin_unlock((pthread_spinlock_t *) lock);
+ int err = pthread_spin_unlock((pthread_spinlock_t *) lock);
+ if (err)
+ ETHR_FATAL_ERROR__(err);
}
-static ETHR_INLINE int
-ethr_opt_spin_lock(ethr_opt_spinlock_t *lock)
+static ETHR_INLINE void
+ethr_native_spin_lock(ethr_native_spinlock_t *lock)
{
- return pthread_spin_lock((pthread_spinlock_t *) lock);
+ int err = pthread_spin_lock((pthread_spinlock_t *) lock);
+ if (err)
+ ETHR_FATAL_ERROR__(err);
}
#endif
-#elif defined(ETHR_HAVE_NATIVE_ATOMICS)
+#elif defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
/* --- Native spinlocks using native atomics -------------------------------- */
#define ETHR_HAVE_NATIVE_SPINLOCKS 1
-#define ETHR_HAVE_OPTIMIZED_SPINLOCKS 1
-
-#if defined(ETHR_HAVE_NATIVE_ATOMIC32)
-typedef ethr_native_atomic32_t ethr_native_spinlock_t;
-# define ETHR_NATMC_FUNC__(X) ethr_native_atomic32_ ## X
-#elif defined(ETHR_HAVE_NATIVE_ATOMIC64)
-typedef ethr_native_atomic64_t ethr_native_spinlock_t;
-# define ETHR_NATMC_FUNC__(X) ethr_native_atomic64_ ## X
-#else
-# error "Missing native atomic implementation"
-#endif
+
+#define ETHR_NATIVE_SPINLOCK_IMPL "native-atomics"
+
+typedef ethr_atomic32_t ethr_native_spinlock_t;
#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_AUX_IMPL__)
+#undef ETHR_NSPN_AOP__
+#define ETHR_NSPN_AOP__(X) ETHR_INLINE_ATMC32_FUNC_NAME_(ethr_atomic32_ ## X)
+
static ETHR_INLINE void
ethr_native_spinlock_init(ethr_native_spinlock_t *lock)
{
- ETHR_NATMC_FUNC__(init)(lock, 0);
+ ETHR_NSPN_AOP__(init)(lock, 0);
+}
+
+static ETHR_INLINE int
+ethr_native_spinlock_destroy(ethr_native_spinlock_t *lock)
+{
+ return ETHR_NSPN_AOP__(read)(lock) == 0 ? 0 : EBUSY;
}
static ETHR_INLINE void
ethr_native_spin_unlock(ethr_native_spinlock_t *lock)
{
- ETHR_COMPILER_BARRIER;
- ETHR_ASSERT(ETHR_NATMC_FUNC__(read)(lock) == 1);
- ETHR_NATMC_FUNC__(set_relb)(lock, 0);
+ ETHR_ASSERT(ETHR_NSPN_AOP__(read)(lock) == 1);
+ ETHR_NSPN_AOP__(set_relb)(lock, 0);
}
static ETHR_INLINE void
ethr_native_spin_lock(ethr_native_spinlock_t *lock)
{
- while (ETHR_NATMC_FUNC__(cmpxchg_acqb)(lock, 1, 0) != 0) {
- while (ETHR_NATMC_FUNC__(read)(lock) != 0)
+ while (ETHR_NSPN_AOP__(cmpxchg_acqb)(lock, 1, 0) != 0) {
+ while (ETHR_NSPN_AOP__(read)(lock) != 0)
ETHR_SPIN_BODY;
}
ETHR_COMPILER_BARRIER;
}
-#endif
+#undef ETHR_NSPN_AOP__
-#undef ETHR_NATMC_FUNC__
+#endif
#endif
-#ifdef ETHR_HAVE_NATIVE_RWSPINLOCKS
-#define ETHR_HAVE_OPTIMIZED_RWSPINLOCKS 1
-#elif defined(ETHR_HAVE_NATIVE_ATOMICS)
+#if defined(ETHR_HAVE_NATIVE_RWSPINLOCKS)
+
+#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_AUX_IMPL__)
+
+static ETHR_INLINE int
+ethr_native_rwlock_destroy(ethr_native_rwlock_t *lock)
+{
+ return 0;
+}
+
+#endif
+
+#elif defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
/* --- Native rwspinlocks using native atomics ------------------------------ */
#define ETHR_HAVE_NATIVE_RWSPINLOCKS 1
-#define ETHR_HAVE_OPTIMIZED_RWSPINLOCKS 1
+#define ETHR_NATIVE_RWSPINLOCK_IMPL "native-atomics"
-#if defined(ETHR_HAVE_NATIVE_ATOMIC32)
-typedef ethr_native_atomic32_t ethr_native_rwlock_t;
-# define ETHR_NAINT_T__ ethr_sint32_t
+typedef ethr_atomic32_t ethr_native_rwlock_t;
# define ETHR_WLOCK_FLAG__ (((ethr_sint32_t) 1) << 30)
-# define ETHR_NATMC_FUNC__(X) ethr_native_atomic32_ ## X
-#elif defined(ETHR_HAVE_NATIVE_ATOMIC64)
-typedef ethr_native_atomic64_t ethr_native_rwlock_t;
-# define ETHR_NAINT_T__ ethr_sint64_t
-# define ETHR_WLOCK_FLAG__ (((ethr_sint64_t) 1) << 62)
-# define ETHR_NATMC_FUNC__(X) ethr_native_atomic64_ ## X
-#else
-# error "Missing native atomic implementation"
-#endif
#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_AUX_IMPL__)
+#undef ETHR_NRWSPN_AOP__
+#define ETHR_NRWSPN_AOP__(X) ETHR_INLINE_ATMC32_FUNC_NAME_(ethr_atomic32_ ## X)
+
static ETHR_INLINE void
ethr_native_rwlock_init(ethr_native_rwlock_t *lock)
{
- ETHR_NATMC_FUNC__(init)(lock, 0);
+ ETHR_NRWSPN_AOP__(init)(lock, 0);
+}
+
+static ETHR_INLINE int
+ethr_native_rwlock_destroy(ethr_native_rwlock_t *lock)
+{
+ return ETHR_NRWSPN_AOP__(read)(lock) == 0 ? 0 : EBUSY;
}
static ETHR_INLINE void
ethr_native_read_unlock(ethr_native_rwlock_t *lock)
{
- ETHR_COMPILER_BARRIER;
-#ifdef DEBUG
- ETHR_ASSERT(ETHR_NATMC_FUNC__(read)(lock) >= 0);
-#endif
- ETHR_NATMC_FUNC__(dec_relb)(lock);
+ ETHR_ASSERT(ETHR_NRWSPN_AOP__(read)(lock) >= 0);
+ ETHR_NRWSPN_AOP__(dec_relb)(lock);
}
static ETHR_INLINE void
ethr_native_read_lock(ethr_native_rwlock_t *lock)
{
- ETHR_NAINT_T__ act, exp = 0;
+ ethr_sint32_t act, exp = 0;
while (1) {
- act = ETHR_NATMC_FUNC__(cmpxchg_acqb)(lock, exp+1, exp);
+ act = ETHR_NRWSPN_AOP__(cmpxchg_acqb)(lock, exp+1, exp);
if (act == exp)
break;
+ /* Wait for writer to leave */
while (act & ETHR_WLOCK_FLAG__) {
ETHR_SPIN_BODY;
- act = ETHR_NATMC_FUNC__(read)(lock);
+ act = ETHR_NRWSPN_AOP__(read)(lock);
}
exp = act;
}
@@ -173,36 +193,37 @@ ethr_native_read_lock(ethr_native_rwlock_t *lock)
static ETHR_INLINE void
ethr_native_write_unlock(ethr_native_rwlock_t *lock)
{
- ETHR_COMPILER_BARRIER;
- ETHR_ASSERT(ETHR_NATMC_FUNC__(read)(lock) == ETHR_WLOCK_FLAG__);
- ETHR_NATMC_FUNC__(set_relb)(lock, 0);
+ ETHR_ASSERT(ETHR_NRWSPN_AOP__(read)(lock) == ETHR_WLOCK_FLAG__);
+ ETHR_NRWSPN_AOP__(set_relb)(lock, 0);
}
static ETHR_INLINE void
ethr_native_write_lock(ethr_native_rwlock_t *lock)
{
- ETHR_NAINT_T__ act, exp = 0;
+ ethr_sint32_t act, exp = 0;
while (1) {
- act = ETHR_NATMC_FUNC__(cmpxchg_acqb)(lock, exp|ETHR_WLOCK_FLAG__, exp);
+ act = ETHR_NRWSPN_AOP__(cmpxchg_acqb)(lock, exp|ETHR_WLOCK_FLAG__, exp);
if (act == exp)
break;
- ETHR_SPIN_BODY;
- exp = act & ~ETHR_WLOCK_FLAG__;
+ /* Wait for writer to leave */
+ while (act & ETHR_WLOCK_FLAG__) {
+ ETHR_SPIN_BODY;
+ act = ETHR_NRWSPN_AOP__(read)(lock);
+ }
+ exp = act;
}
act |= ETHR_WLOCK_FLAG__;
/* Wait for readers to leave */
while (act != ETHR_WLOCK_FLAG__) {
ETHR_SPIN_BODY;
- act = ETHR_NATMC_FUNC__(read_acqb)(lock);
+ act = ETHR_NRWSPN_AOP__(read_acqb)(lock);
}
ETHR_COMPILER_BARRIER;
}
-#endif
+#undef ETHR_NRWSPN_AOP__
-#undef ETHR_NAINT_T__
-#undef ETHR_NATMC_FUNC__
-#undef ETHR_WLOCK_FLAG__
+#endif
#endif
diff --git a/erts/include/internal/ethread.h b/erts/include/internal/ethread.h
index 4cd95faf6a..142c26c0ca 100644
--- a/erts/include/internal/ethread.h
+++ b/erts/include/internal/ethread.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -33,10 +33,6 @@
#include <stdlib.h>
#include "erl_errno.h"
-#undef ETHR_HAVE_OPTIMIZED_ATOMIC_OPS
-#undef ETHR_HAVE_OPTIMIZED_SPINLOCK
-#undef ETHR_HAVE_OPTIMIZED_RWSPINLOCK
-
#if defined(DEBUG)
# define ETHR_DEBUG
#endif
@@ -68,7 +64,7 @@
#endif
/* Assume 64-byte cache line size */
-#define ETHR_CACHE_LINE_SIZE ((ethr_uint_t) 64)
+#define ETHR_CACHE_LINE_SIZE 64
#define ETHR_CACHE_LINE_MASK (ETHR_CACHE_LINE_SIZE - 1)
#define ETHR_CACHE_LINE_ALIGN_SIZE(SZ) \
@@ -195,7 +191,6 @@ typedef DWORD ethr_tsd_key;
#undef ETHR_HAVE_ETHR_SIG_FUNCS
#define ETHR_USE_OWN_RWMTX_IMPL__
-#define ETHR_USE_OWN_MTX_IMPL__
#define ETHR_YIELD() (Sleep(0), 0)
@@ -251,13 +246,90 @@ typedef ethr_sint64_t ethr_sint_t;
typedef ethr_uint64_t ethr_uint_t;
#endif
-/* __builtin_expect() is needed by both native atomics code
- * and the fallback code */
-#if !defined(__GNUC__) || (__GNUC__ < 2) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
+#if defined(ETHR_SIZEOF___INT128_T) && ETHR_SIZEOF___INT128_T == 16
+#define ETHR_HAVE_INT128_T
+typedef __int128_t ethr_sint128_t;
+typedef __uint128_t ethr_uint128_t;
+#endif
+
+#define ETHR_FATAL_ERROR__(ERR) \
+ ethr_fatal_error__(__FILE__, __LINE__, __func__, (ERR))
+
+ETHR_PROTO_NORETURN__ ethr_fatal_error__(const char *file,
+ int line,
+ const char *func,
+ int err);
+
+#if !defined(__GNUC__)
+# define ETHR_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) 0
+#elif !defined(__GNUC_MINOR__)
+# define ETHR_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) \
+ ((__GNUC__ << 24) >= (((MAJ) << 24) | ((MIN) << 12) | (PL)))
+#elif !defined(__GNUC_PATCHLEVEL__)
+# define ETHR_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) \
+ (((__GNUC__ << 24) | (__GNUC_MINOR__ << 12)) >= (((MAJ) << 24) | ((MIN) << 12) | (PL)))
+#else
+# define ETHR_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) \
+ (((__GNUC__ << 24) | (__GNUC_MINOR__ << 12) | __GNUC_PATCHLEVEL__) >= (((MAJ) << 24) | ((MIN) << 12) | (PL)))
+#endif
+
+#if !ETHR_AT_LEAST_GCC_VSN__(2, 96, 0)
#define __builtin_expect(X, Y) (X)
#endif
-/* For CPU-optimised atomics, spinlocks, and rwlocks. */
+#if ETHR_AT_LEAST_GCC_VSN__(3, 1, 1)
+# define ETHR_CHOOSE_EXPR __builtin_choose_expr
+#else
+# define ETHR_CHOOSE_EXPR(B, E1, E2) ((B) ? (E1) : (E2))
+#endif
+
+#if ((defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) \
+ || (defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64))))
+# define ETHR_X86_RUNTIME_CONF__
+
+# define ETHR_X86_RUNTIME_CONF_HAVE_DW_CMPXCHG__ \
+ (__builtin_expect(ethr_runtime__.conf.have_dw_cmpxchg != 0, 1))
+# define ETHR_X86_RUNTIME_CONF_HAVE_NO_DW_CMPXCHG__ \
+ (__builtin_expect(ethr_runtime__.conf.have_dw_cmpxchg == 0, 0))
+# define ETHR_X86_RUNTIME_CONF_HAVE_SSE2__ \
+ (__builtin_expect(ethr_runtime__.conf.have_sse2 != 0, 1))
+# define ETHR_X86_RUNTIME_CONF_HAVE_NO_SSE2__ \
+ (__builtin_expect(ethr_runtime__.conf.have_sse2 == 0, 0))
+#endif
+
+#if (defined(__GNUC__) \
+ && !defined(ETHR_PPC_HAVE_LWSYNC) \
+ && !defined(ETHR_PPC_HAVE_NO_LWSYNC) \
+ && (defined(__powerpc__) || defined(__ppc__) || defined(__powerpc64__)))
+# define ETHR_PPC_RUNTIME_CONF__
+
+# define ETHR_PPC_RUNTIME_CONF_HAVE_LWSYNC__ \
+ (__builtin_expect(ethr_runtime__.conf.have_lwsync != 0, 1))
+# define ETHR_PPC_RUNTIME_CONF_HAVE_NO_LWSYNC__ \
+ (__builtin_expect(ethr_runtime__.conf.have_lwsync == 0, 0))
+#endif
+
+typedef struct {
+#if defined(ETHR_X86_RUNTIME_CONF__)
+ int have_dw_cmpxchg;
+ int have_sse2;
+#endif
+#if defined(ETHR_PPC_RUNTIME_CONF__)
+ int have_lwsync;
+#endif
+ int dummy;
+} ethr_runtime_conf_t;
+
+
+typedef union {
+ ethr_runtime_conf_t conf;
+ char pad__[ETHR_CACHE_LINE_ALIGN_SIZE(sizeof(ethr_runtime_conf_t))+ETHR_CACHE_LINE_SIZE];
+} ethr_runtime_t;
+
+
+extern ethr_runtime_t ethr_runtime__;
+
+/* For native CPU-optimised atomics, spinlocks, and rwlocks. */
#if !defined(ETHR_DISABLE_NATIVE_IMPLS)
# if defined(__GNUC__)
# if defined(ETHR_PREFER_GCC_NATIVE_IMPLS)
@@ -265,7 +337,7 @@ typedef ethr_uint64_t ethr_uint_t;
# elif defined(ETHR_PREFER_LIBATOMIC_OPS_NATIVE_IMPLS)
# include "libatomic_ops/ethread.h"
# endif
-# ifndef ETHR_HAVE_NATIVE_ATOMICS
+# if !defined(ETHR_HAVE_NATIVE_ATOMIC32) && !defined(ETHR_HAVE_NATIVE_ATOMIC64)
# if ETHR_SIZEOF_PTR == 4
# if defined(__i386__)
# include "i386/ethread.h"
@@ -283,8 +355,10 @@ typedef ethr_uint64_t ethr_uint_t;
# include "sparc64/ethread.h"
# endif
# endif
+#if 0
# include "gcc/ethread.h"
# include "libatomic_ops/ethread.h"
+#endif
# endif
# elif defined(ETHR_HAVE_LIBATOMIC_OPS)
# include "libatomic_ops/ethread.h"
@@ -293,10 +367,9 @@ typedef ethr_uint64_t ethr_uint_t;
# endif
#endif /* !ETHR_DISABLE_NATIVE_IMPLS */
+#include "ethr_atomics.h" /* The atomics API */
+
#if defined(__GNUC__)
-# ifndef ETHR_COMPILER_BARRIER
-# define ETHR_COMPILER_BARRIER __asm__ __volatile__("" : : : "memory")
-# endif
# ifndef ETHR_SPIN_BODY
# if defined(__i386__) || defined(__x86_64__)
# define ETHR_SPIN_BODY __asm__ __volatile__("rep;nop" : : : "memory")
@@ -309,11 +382,6 @@ typedef ethr_uint64_t ethr_uint_t;
# endif
# endif
#elif defined(ETHR_WIN32_THREADS)
-# ifndef ETHR_COMPILER_BARRIER
-# include <intrin.h>
-# pragma intrinsic(_ReadWriteBarrier)
-# define ETHR_COMPILER_BARRIER _ReadWriteBarrier()
-# endif
# ifndef ETHR_SPIN_BODY
# define ETHR_SPIN_BODY do {YieldProcessor();ETHR_COMPILER_BARRIER;} while(0)
# endif
@@ -321,43 +389,6 @@ typedef ethr_uint64_t ethr_uint_t;
#define ETHR_YIELD_AFTER_BUSY_LOOPS 50
-#ifndef ETHR_HAVE_NATIVE_ATOMICS
-/*
- * ETHR_*MEMORY_BARRIER orders between locked and atomic accesses only,
- * i.e. when our lock based atomic fallback is used, a noop is sufficient.
- */
-#define ETHR_MEMORY_BARRIER do { } while (0)
-#define ETHR_WRITE_MEMORY_BARRIER do { } while (0)
-#define ETHR_READ_MEMORY_BARRIER do { } while (0)
-#define ETHR_READ_DEPEND_MEMORY_BARRIER do { } while (0)
-#endif
-
-#ifndef ETHR_WRITE_MEMORY_BARRIER
-# define ETHR_WRITE_MEMORY_BARRIER ETHR_MEMORY_BARRIER
-# define ETHR_WRITE_MEMORY_BARRIER_IS_FULL
-#endif
-#ifndef ETHR_READ_MEMORY_BARRIER
-# define ETHR_READ_MEMORY_BARRIER ETHR_MEMORY_BARRIER
-# define ETHR_READ_MEMORY_BARRIER_IS_FULL
-#endif
-#ifndef ETHR_READ_DEPEND_MEMORY_BARRIER
-# define ETHR_READ_DEPEND_MEMORY_BARRIER ETHR_COMPILER_BARRIER
-# define ETHR_READ_DEPEND_MEMORY_BARRIER_IS_COMPILER_BARRIER
-#endif
-
-#define ETHR_FATAL_ERROR__(ERR) \
- ethr_fatal_error__(__FILE__, __LINE__, __func__, (ERR))
-
-ETHR_PROTO_NORETURN__ ethr_fatal_error__(const char *file,
- int line,
- const char *func,
- int err);
-
-void ethr_compiler_barrier_fallback(void);
-#ifndef ETHR_COMPILER_BARRIER
-# define ETHR_COMPILER_BARRIER ethr_compiler_barrier_fallback()
-#endif
-
#ifndef ETHR_SPIN_BODY
# define ETHR_SPIN_BODY ETHR_COMPILER_BARRIER
#endif
@@ -460,8 +491,6 @@ void ethr_compiler_barrier(void);
#if defined(ETHR_HAVE_NATIVE_SPINLOCKS)
typedef ethr_native_spinlock_t ethr_spinlock_t;
-#elif defined(ETHR_HAVE_OPTIMIZED_SPINLOCKS)
-typedef ethr_opt_spinlock_t ethr_spinlock_t;
#elif defined(__WIN32__)
typedef CRITICAL_SECTION ethr_spinlock_t;
#else
@@ -483,8 +512,6 @@ ETHR_INLINE_FUNC_NAME_(ethr_spinlock_init)(ethr_spinlock_t *lock)
#ifdef ETHR_HAVE_NATIVE_SPINLOCKS
ethr_native_spinlock_init(lock);
return 0;
-#elif defined(ETHR_HAVE_OPTIMIZED_SPINLOCKS)
- return ethr_opt_spinlock_init((ethr_opt_spinlock_t *) lock);
#elif defined(__WIN32__)
if (!InitializeCriticalSectionAndSpinCount((CRITICAL_SECTION *) lock, INT_MAX))
return ethr_win_get_errno__();
@@ -498,9 +525,7 @@ static ETHR_INLINE int
ETHR_INLINE_FUNC_NAME_(ethr_spinlock_destroy)(ethr_spinlock_t *lock)
{
#ifdef ETHR_HAVE_NATIVE_SPINLOCKS
- return 0;
-#elif defined(ETHR_HAVE_OPTIMIZED_SPINLOCKS)
- return ethr_opt_spinlock_destroy((ethr_opt_spinlock_t *) lock);
+ return ethr_native_spinlock_destroy(lock);
#elif defined(__WIN32__)
DeleteCriticalSection((CRITICAL_SECTION *) lock);
return 0;
@@ -514,10 +539,6 @@ ETHR_INLINE_FUNC_NAME_(ethr_spin_unlock)(ethr_spinlock_t *lock)
{
#ifdef ETHR_HAVE_NATIVE_SPINLOCKS
ethr_native_spin_unlock(lock);
-#elif defined(ETHR_HAVE_OPTIMIZED_SPINLOCKS)
- int err = ethr_opt_spin_unlock((ethr_opt_spinlock_t *) lock);
- if (err)
- ETHR_FATAL_ERROR__(err);
#elif defined(__WIN32__)
LeaveCriticalSection((CRITICAL_SECTION *) lock);
#else
@@ -532,10 +553,6 @@ ETHR_INLINE_FUNC_NAME_(ethr_spin_lock)(ethr_spinlock_t *lock)
{
#ifdef ETHR_HAVE_NATIVE_SPINLOCKS
ethr_native_spin_lock(lock);
-#elif defined(ETHR_HAVE_OPTIMIZED_SPINLOCKS)
- int err = ethr_opt_spin_lock((ethr_opt_spinlock_t *) lock);
- if (err)
- ETHR_FATAL_ERROR__(err);
#elif defined(__WIN32__)
EnterCriticalSection((CRITICAL_SECTION *) lock);
#else
@@ -547,8 +564,6 @@ ETHR_INLINE_FUNC_NAME_(ethr_spin_lock)(ethr_spinlock_t *lock)
#endif /* ETHR_TRY_INLINE_FUNCS */
-#include "ethr_atomics.h"
-
typedef struct ethr_ts_event_ ethr_ts_event; /* Needed by ethr_mutex.h */
#if defined(ETHR_WIN32_THREADS)
diff --git a/erts/include/internal/ethread_header_config.h.in b/erts/include/internal/ethread_header_config.h.in
index f394d790d2..dd3599f86d 100644
--- a/erts/include/internal/ethread_header_config.h.in
+++ b/erts/include/internal/ethread_header_config.h.in
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -32,6 +32,9 @@
/* Define to the size of __int64 */
#undef ETHR_SIZEOF___INT64
+/* Define to the size of __int128_t */
+#undef ETHR_SIZEOF___INT128_T
+
/* Define if bigendian */
#undef ETHR_BIGENDIAN
@@ -69,8 +72,44 @@
/* Define if you have a linux futex implementation. */
#undef ETHR_HAVE_LINUX_FUTEX
-/* Define if you have gcc atomic operations */
-#undef ETHR_HAVE_GCC_ATOMIC_OPS
+/* Define if x86/x86_64 out of order instructions should be synchronized */
+#undef ETHR_X86_OUT_OF_ORDER
+
+/* Define if only run in Sparc TSO mode */
+#undef ETHR_SPARC_TSO
+
+/* Define if only run in Sparc PSO, or TSO mode */
+#undef ETHR_SPARC_PSO
+
+/* Define if run in Sparc RMO, PSO, or TSO mode */
+#undef ETHR_SPARC_RMO
+
+/* Define if you have __sync_add_and_fetch() for 32-bit integers */
+#undef ETHR_HAVE___SYNC_ADD_AND_FETCH32
+
+/* Define if you have __sync_add_and_fetch() for 64-bit integers */
+#undef ETHR_HAVE___SYNC_ADD_AND_FETCH64
+
+/* Define if you have __sync_fetch_and_and() for 32-bit integers */
+#undef ETHR_HAVE___SYNC_FETCH_AND_AND32
+
+/* Define if you have __sync_fetch_and_and() for 64-bit integers */
+#undef ETHR_HAVE___SYNC_FETCH_AND_AND64
+
+/* Define if you have __sync_fetch_and_or() for 32-bit integers */
+#undef ETHR_HAVE___SYNC_FETCH_AND_OR32
+
+/* Define if you have __sync_fetch_and_or() for 64-bit integers */
+#undef ETHR_HAVE___SYNC_FETCH_AND_OR64
+
+/* Define if you have __sync_val_compare_and_swap() for 32-bit integers */
+#undef ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP32
+
+/* Define if you have __sync_val_compare_and_swap() for 64-bit integers */
+#undef ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP64
+
+/* Define if you have __sync_val_compare_and_swap() for 128-bit integers */
+#undef ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP128
/* Define if you prefer gcc native ethread implementations */
#undef ETHR_PREFER_GCC_NATIVE_IMPLS
@@ -90,8 +129,14 @@
/* Define if sched_yield() returns an int. */
#undef ETHR_SCHED_YIELD_RET_INT
-/* Define if you want compatibilty with x86 processors before pentium4. */
-#undef ETHR_PRE_PENTIUM4_COMPAT
+/* Define if you use a gcc that supports -msse2 and understand sse2 specific asm statements */
+#undef ETHR_GCC_HAVE_SSE2_ASM_SUPPORT
+
+/* Define if you use a gcc that supports the double word cmpxchg instruction */
+#undef ETHR_GCC_HAVE_DW_CMPXCHG_ASM_SUPPORT
+
+/* Define if you get a register shortage with cmpxchg8b and position independent code */
+#undef ETHR_CMPXCHG8B_REGISTER_SHORTAGE
/* Define if you have the pthread_rwlockattr_setkind_np() function. */
#undef ETHR_HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP
@@ -115,23 +160,74 @@
/* Define to the size of AO_t if libatomic_ops is used */
#undef ETHR_SIZEOF_AO_T
+/* Define if you have _InterlockedAnd() */
+#undef ETHR_HAVE__INTERLOCKEDAND
+
+/* Define if you have _InterlockedAnd64() */
+#undef ETHR_HAVE__INTERLOCKEDAND64
+
+/* Define if you have _InterlockedCompareExchange() */
+#undef ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE
+
/* Define if you have _InterlockedCompareExchange64() */
#undef ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64
+/* Define if you have _InterlockedCompareExchange64_acq() */
+#undef ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_ACQ
+
+/* Define if you have _InterlockedCompareExchange64_rel() */
+#undef ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_REL
+
+/* Define if you have _InterlockedCompareExchange_acq() */
+#undef ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_ACQ
+
+/* Define if you have _InterlockedCompareExchange_rel() */
+#undef ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_REL
+
+/* Define if you have _InterlockedDecrement() */
+#undef ETHR_HAVE__INTERLOCKEDDECREMENT
+
/* Define if you have _InterlockedDecrement64() */
#undef ETHR_HAVE__INTERLOCKEDDECREMENT64
-/* Define if you have _InterlockedIncrement64() */
-#undef ETHR_HAVE__INTERLOCKEDINCREMENT64
+/* Define if you have _InterlockedDecrement64_rel() */
+#undef ETHR_HAVE__INTERLOCKEDDECREMENT64_REL
-/* Define if you have _InterlockedExchangeAdd64() */
-#undef ETHR_HAVE__INTERLOCKEDEXCHANGEADD64
+/* Define if you have _InterlockedDecrement_rel() */
+#undef ETHR_HAVE__INTERLOCKEDDECREMENT_REL
+
+/* Define if you have _InterlockedExchange() */
+#undef ETHR_HAVE__INTERLOCKEDEXCHANGE
/* Define if you have _InterlockedExchange64() */
#undef ETHR_HAVE__INTERLOCKEDEXCHANGE64
-/* Define if you have _InterlockedAnd64() */
-#undef ETHR_HAVE__INTERLOCKEDAND64
+/* Define if you have _InterlockedExchangeAdd() */
+#undef ETHR_HAVE__INTERLOCKEDEXCHANGEADD
+
+/* Define if you have _InterlockedExchangeAdd64() */
+#undef ETHR_HAVE__INTERLOCKEDEXCHANGEADD64
+
+/* Define if you have _InterlockedExchangeAdd64_acq() */
+#undef ETHR_HAVE__INTERLOCKEDEXCHANGEADD64_ACQ
+
+/* Define if you have _InterlockedExchangeAdd_acq() */
+#undef ETHR_HAVE__INTERLOCKEDEXCHANGEADD_ACQ
+
+/* Define if you have _InterlockedIncrement() */
+#undef ETHR_HAVE__INTERLOCKEDINCREMENT
+
+/* Define if you have _InterlockedIncrement64() */
+#undef ETHR_HAVE__INTERLOCKEDINCREMENT64
+
+/* Define if you have _InterlockedIncrement64_acq() */
+#undef ETHR_HAVE__INTERLOCKEDINCREMENT64_ACQ
+
+/* Define if you have _InterlockedIncrement_acq() */
+#undef ETHR_HAVE__INTERLOCKEDINCREMENT_ACQ
+
+/* Define if you have _InterlockedOr() */
+#undef ETHR_HAVE__INTERLOCKEDOR
/* Define if you have _InterlockedOr64() */
#undef ETHR_HAVE__INTERLOCKEDOR64
diff --git a/erts/include/internal/gcc/ethr_atomic.h b/erts/include/internal/gcc/ethr_atomic.h
index 16935084b1..f598f8537b 100644
--- a/erts/include/internal/gcc/ethr_atomic.h
+++ b/erts/include/internal/gcc/ethr_atomic.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -25,11 +25,15 @@
#undef ETHR_INCLUDE_ATOMIC_IMPL__
#if !defined(ETHR_GCC_ATOMIC32_H__) && defined(ETHR_ATOMIC_WANT_32BIT_IMPL__)
#define ETHR_GCC_ATOMIC32_H__
-#define ETHR_INCLUDE_ATOMIC_IMPL__ 4
+#if defined(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP32)
+# define ETHR_INCLUDE_ATOMIC_IMPL__ 4
+#endif
#undef ETHR_ATOMIC_WANT_32BIT_IMPL__
#elif !defined(ETHR_GCC_ATOMIC64_H__) && defined(ETHR_ATOMIC_WANT_64BIT_IMPL__)
#define ETHR_GCC_ATOMIC64_H__
-#define ETHR_INCLUDE_ATOMIC_IMPL__ 8
+#if defined(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP64)
+# define ETHR_INCLUDE_ATOMIC_IMPL__ 8
+#endif
#undef ETHR_ATOMIC_WANT_64BIT_IMPL__
#endif
@@ -45,58 +49,38 @@
# define ETHR_READ_AND_SET_WITHOUT_SYNC_OP__ 1
#endif
-#if defined(__x86_64__) || (defined(__i386__) \
- && !defined(ETHR_PRE_PENTIUM4_COMPAT))
-# define ETHR_READ_ACQB_AND_SET_RELB_COMPILER_BARRIER_ONLY__ 1
-#else
-# define ETHR_READ_ACQB_AND_SET_RELB_COMPILER_BARRIER_ONLY__ 0
-#endif
-
-/*
- * According to the documentation this is what we want:
- * #define ETHR_MEMORY_BARRIER __sync_synchronize()
- * However, __sync_synchronize() is known to erroneously be
- * a noop on at least some platforms with some gcc versions.
- * This has suposedly been fixed in some gcc version, but we
- * don't know from which version. Therefore, we only use
- * it when it has been verified to work. Otherwise
- * we use a workaround.
- */
-#if defined(__mips__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
-/* __sync_synchronize() has been verified to work here */
-#define ETHR_MEMORY_BARRIER __sync_synchronize()
-#define ETHR_READ_DEPEND_MEMORY_BARRIER __sync_synchronize()
-#elif defined(__x86_64__) || (defined(__i386__) \
- && !defined(ETHR_PRE_PENTIUM4_COMPAT))
-/* Use fence instructions directly instead of workaround */
-#define ETHR_MEMORY_BARRIER __asm__ __volatile__("mfence" : : : "memory")
-#define ETHR_WRITE_MEMORY_BARRIER __asm__ __volatile__("sfence" : : : "memory")
-#define ETHR_READ_MEMORY_BARRIER __asm__ __volatile__("lfence" : : : "memory")
-#define ETHR_READ_DEPEND_MEMORY_BARRIER __asm__ __volatile__("" : : : "memory")
-#else
-/* Workaround */
-#define ETHR_MEMORY_BARRIER \
-do { \
- volatile ethr_sint32_t x___ = 0; \
- (void) __sync_val_compare_and_swap(&x___, (ethr_sint32_t) 0, (ethr_sint32_t) 1); \
-} while (0)
-#define ETHR_READ_DEPEND_MEMORY_BARRIER ETHR_MEMORY_BARRIER
-#endif
-
-#define ETHR_COMPILER_BARRIER __asm__ __volatile__("" : : : "memory")
-
#endif /* ETHR_GCC_ATOMIC_COMMON__ */
#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
#define ETHR_HAVE_NATIVE_ATOMIC32 1
+#define ETHR_NATIVE_ATOMIC32_IMPL "gcc"
#define ETHR_NATMC_FUNC__(X) ethr_native_atomic32_ ## X
#define ETHR_ATMC_T__ ethr_native_atomic32_t
#define ETHR_AINT_T__ ethr_sint32_t
+#if defined(ETHR_HAVE___SYNC_ADD_AND_FETCH32)
+# define ETHR_HAVE___SYNC_ADD_AND_FETCH
+#endif
+#if defined(ETHR_HAVE___SYNC_FETCH_AND_AND32)
+# define ETHR_HAVE___SYNC_FETCH_AND_AND
+#endif
+#if defined(ETHR_HAVE___SYNC_FETCH_AND_OR32)
+# define ETHR_HAVE___SYNC_FETCH_AND_OR
+#endif
#elif ETHR_INCLUDE_ATOMIC_IMPL__ == 8
#define ETHR_HAVE_NATIVE_ATOMIC64 1
+#define ETHR_NATIVE_ATOMIC64_IMPL "gcc"
#define ETHR_NATMC_FUNC__(X) ethr_native_atomic64_ ## X
#define ETHR_ATMC_T__ ethr_native_atomic64_t
#define ETHR_AINT_T__ ethr_sint64_t
+#if defined(ETHR_HAVE___SYNC_ADD_AND_FETCH64)
+# define ETHR_HAVE___SYNC_ADD_AND_FETCH
+#endif
+#if defined(ETHR_HAVE___SYNC_FETCH_AND_AND64)
+# define ETHR_HAVE___SYNC_FETCH_AND_AND
+#endif
+#if defined(ETHR_HAVE___SYNC_FETCH_AND_OR64)
+# define ETHR_HAVE___SYNC_FETCH_AND_OR
+#endif
#else
#error "Unsupported integer size"
#endif
@@ -108,183 +92,120 @@ typedef struct {
#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_ATOMIC_IMPL__)
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADDR 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADDR 1
+#endif
+
static ETHR_INLINE ETHR_AINT_T__ *
ETHR_NATMC_FUNC__(addr)(ETHR_ATMC_T__ *var)
{
return (ETHR_AINT_T__ *) &var->counter;
}
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(set)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ value)
-{
#if ETHR_READ_AND_SET_WITHOUT_SYNC_OP__
- var->counter = value;
+
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET 1
#else
- /*
- * Unfortunately no __sync_store() or similar exist in the gcc atomic
- * op interface. We therefore have to simulate it this way...
- */
- ETHR_AINT_T__ act = 0, exp;
- do {
- exp = act;
- act = __sync_val_compare_and_swap(&var->counter, exp, value);
- } while (act != exp);
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET 1
#endif
-}
static ETHR_INLINE void
-ETHR_NATMC_FUNC__(init)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ value)
+ETHR_NATMC_FUNC__(set)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ value)
{
- ETHR_NATMC_FUNC__(set)(var, value);
+ var->counter = value;
}
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(read)(ETHR_ATMC_T__ *var)
-{
+#endif /* ETHR_READ_AND_SET_WITHOUT_SYNC_OP__ */
+
#if ETHR_READ_AND_SET_WITHOUT_SYNC_OP__
- return var->counter;
+
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ 1
#else
- /*
- * Unfortunately no __sync_fetch() or similar exist in the gcc atomic
- * op interface. We therefore have to simulate it this way...
- */
- return __sync_add_and_fetch(&var->counter, (ETHR_AINT_T__) 0);
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ 1
#endif
-}
-
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(add)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ incr)
-{
- (void) __sync_add_and_fetch(&var->counter, incr);
-}
static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(add_return)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ incr)
+ETHR_NATMC_FUNC__(read)(ETHR_ATMC_T__ *var)
{
- return __sync_add_and_fetch(&var->counter, incr);
+ return var->counter;
}
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(inc)(ETHR_ATMC_T__ *var)
-{
- (void) __sync_add_and_fetch(&var->counter, (ETHR_AINT_T__) 1);
-}
+#endif /* ETHR_READ_AND_SET_WITHOUT_SYNC_OP__ */
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(dec)(ETHR_ATMC_T__ *var)
-{
- (void) __sync_sub_and_fetch(&var->counter, (ETHR_AINT_T__) 1);
-}
+#if defined(ETHR_HAVE___SYNC_ADD_AND_FETCH)
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(inc_return)(ETHR_ATMC_T__ *var)
-{
- return __sync_add_and_fetch(&var->counter, (ETHR_AINT_T__) 1);
-}
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RETURN_MB 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RETURN_MB 1
+#endif
static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(dec_return)(ETHR_ATMC_T__ *var)
+ETHR_NATMC_FUNC__(add_return_mb)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ incr)
{
- return __sync_sub_and_fetch(&var->counter, (ETHR_AINT_T__) 1);
+ return __sync_add_and_fetch(&var->counter, incr);
}
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(and_retold)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ mask)
-{
- return __sync_fetch_and_and(&var->counter, mask);
-}
+#endif
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(or_retold)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ mask)
-{
- return (ETHR_AINT_T__) __sync_fetch_and_or(&var->counter, mask);
-}
+#if defined(ETHR_HAVE___SYNC_FETCH_AND_AND)
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(cmpxchg)(ETHR_ATMC_T__ *var,
- ETHR_AINT_T__ new,
- ETHR_AINT_T__ old)
-{
- return __sync_val_compare_and_swap(&var->counter, old, new);
-}
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_AND_RETOLD_MB 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_AND_RETOLD_MB 1
+#endif
static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(xchg)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ new)
+ETHR_NATMC_FUNC__(and_retold_mb)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ mask)
{
- ETHR_AINT_T__ exp, act = 0;
- do {
- exp = act;
- act = __sync_val_compare_and_swap(&var->counter, exp, new);
- } while (act != exp);
- return act;
+ return __sync_fetch_and_and(&var->counter, mask);
}
-/*
- * Atomic ops with at least specified barriers.
- */
-
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(read_acqb)(ETHR_ATMC_T__ *var)
-{
-#if ETHR_READ_ACQB_AND_SET_RELB_COMPILER_BARRIER_ONLY__
- ETHR_AINT_T__ val = var->counter;
- ETHR_COMPILER_BARRIER;
- return val;
-#else
- return __sync_add_and_fetch(&var->counter, (ETHR_AINT_T__) 0);
#endif
-}
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(set_relb)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ i)
-{
-#if ETHR_READ_ACQB_AND_SET_RELB_COMPILER_BARRIER_ONLY__
- ETHR_COMPILER_BARRIER;
- var->counter = i;
+#if defined(ETHR_HAVE___SYNC_FETCH_AND_OR)
+
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_OR_RETOLD_MB 1
#else
- (void) ETHR_NATMC_FUNC__(xchg)(var, i);
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_OR_RETOLD_MB 1
#endif
-}
static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(inc_return_acqb)(ETHR_ATMC_T__ *var)
-{
- return ETHR_NATMC_FUNC__(inc_return)(var);
-}
-
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(dec_relb)(ETHR_ATMC_T__ *var)
+ETHR_NATMC_FUNC__(or_retold_mb)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ mask)
{
- ETHR_NATMC_FUNC__(dec)(var);
+ return (ETHR_AINT_T__) __sync_fetch_and_or(&var->counter, mask);
}
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(dec_return_relb)(ETHR_ATMC_T__ *var)
-{
- return ETHR_NATMC_FUNC__(dec_return)(var);
-}
+#endif
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(cmpxchg_acqb)(ETHR_ATMC_T__ *var,
- ETHR_AINT_T__ new,
- ETHR_AINT_T__ old)
-{
- return ETHR_NATMC_FUNC__(cmpxchg)(var, new, old);
-}
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG_MB 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_MB 1
+#endif
static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(cmpxchg_relb)(ETHR_ATMC_T__ *var,
- ETHR_AINT_T__ new,
- ETHR_AINT_T__ old)
+ETHR_NATMC_FUNC__(cmpxchg_mb)(ETHR_ATMC_T__ *var,
+ ETHR_AINT_T__ new,
+ ETHR_AINT_T__ old)
{
- return ETHR_NATMC_FUNC__(cmpxchg)(var, new, old);
+ return __sync_val_compare_and_swap(&var->counter, old, new);
}
-#endif
+#endif /* ETHR_TRY_INLINE_FUNCS */
#undef ETHR_NATMC_FUNC__
#undef ETHR_ATMC_T__
#undef ETHR_AINT_T__
#undef ETHR_AINT_SUFFIX__
+#undef ETHR_HAVE___SYNC_ADD_AND_FETCH
+#undef ETHR_HAVE___SYNC_FETCH_AND_AND
+#undef ETHR_HAVE___SYNC_FETCH_AND_OR
#endif
diff --git a/erts/include/internal/gcc/ethr_dw_atomic.h b/erts/include/internal/gcc/ethr_dw_atomic.h
new file mode 100644
index 0000000000..6736f9c547
--- /dev/null
+++ b/erts/include/internal/gcc/ethr_dw_atomic.h
@@ -0,0 +1,115 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description: Native double word atomics using gcc's builtins
+ * Author: Rickard Green
+ */
+
+#undef ETHR_INCLUDE_DW_ATOMIC_IMPL__
+#ifndef ETHR_GCC_DW_ATOMIC_H__
+# define ETHR_GCC_DW_ATOMIC_H__
+# if ((ETHR_SIZEOF_PTR == 4 \
+ && defined(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP64)) \
+ || (ETHR_SIZEOF_PTR == 8 \
+ && defined(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP128) \
+ && defined(ETHR_HAVE_INT128_T)))
+# define ETHR_INCLUDE_DW_ATOMIC_IMPL__
+# endif
+#endif
+
+#ifdef ETHR_INCLUDE_DW_ATOMIC_IMPL__
+# define ETHR_HAVE_NATIVE_SU_DW_ATOMIC
+# define ETHR_NATIVE_DW_ATOMIC_IMPL "gcc"
+
+# if defined(__i386__) || defined(__x86_64__)
+/*
+ * If ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__ is defined, it will be used
+ * at runtime in order to determine if native or fallback implementation
+ * should be used.
+ */
+# define ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__ \
+ ETHR_X86_RUNTIME_CONF_HAVE_DW_CMPXCHG__
+# endif
+
+# if ETHR_SIZEOF_PTR == 4
+# define ETHR_DW_NATMC_ALIGN_MASK__ 0x7
+# define ETHR_NATIVE_SU_DW_SINT_T ethr_sint64_t
+# elif ETHR_SIZEOF_PTR == 8
+# define ETHR_DW_NATMC_ALIGN_MASK__ 0xf
+# define ETHR_NATIVE_SU_DW_SINT_T ethr_sint128_t
+# endif
+
+typedef volatile ETHR_NATIVE_SU_DW_SINT_T * ethr_native_dw_ptr_t;
+
+/*
+ * We need 16 byte aligned memory in 64-bit mode, and 8 byte aligned
+ * memory in 32-bit mode. 16 byte aligned malloc in 64-bit mode is
+ * not common, and at least some glibc malloc implementations
+ * only 4 byte align in 32-bit mode.
+ *
+ * This code assumes 8 byte aligned memory in 64-bit mode, and 4 byte
+ * aligned memory in 32-bit mode. A malloc implementation that does
+ * not adhere to these alignment requirements is seriously broken,
+ * and we wont bother trying to work around it.
+ *
+ * Since memory alignment may be off by one word we need to align at
+ * runtime. We, therefore, need an extra word allocated.
+ */
+#define ETHR_DW_NATMC_MEM__(VAR) \
+ (&var->c[(int) ((ethr_uint_t) &(VAR)->c[0]) & ETHR_DW_NATMC_ALIGN_MASK__])
+typedef union {
+ volatile ETHR_NATIVE_SU_DW_SINT_T dw_sint;
+ volatile ethr_sint_t sint[3];
+ volatile char c[ETHR_SIZEOF_PTR*3];
+} ethr_native_dw_atomic_t;
+
+#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_ATOMIC_IMPL__)
+
+# ifdef ETHR_DEBUG
+# define ETHR_DW_DBG_ALIGNED__(PTR) \
+ ETHR_ASSERT((((ethr_uint_t) (PTR)) & ETHR_DW_NATMC_ALIGN_MASK__) == 0);
+# else
+# define ETHR_DW_DBG_ALIGNED__(PTR)
+# endif
+
+#define ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_ADDR
+static ETHR_INLINE ethr_sint_t *
+ethr_native_dw_atomic_addr(ethr_native_dw_atomic_t *var)
+{
+ return (ethr_sint_t *) ETHR_DW_NATMC_MEM__(var);
+}
+
+
+#define ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_CMPXCHG_MB
+
+static ETHR_INLINE ETHR_NATIVE_SU_DW_SINT_T
+ethr_native_su_dw_atomic_cmpxchg_mb(ethr_native_dw_atomic_t *var,
+ ETHR_NATIVE_SU_DW_SINT_T new,
+ ETHR_NATIVE_SU_DW_SINT_T old)
+{
+ ethr_native_dw_ptr_t p = (ethr_native_dw_ptr_t) ETHR_DW_NATMC_MEM__(var);
+ ETHR_DW_DBG_ALIGNED__(p);
+ return __sync_val_compare_and_swap(p, old, new);
+}
+
+#endif /* ETHR_TRY_INLINE_FUNCS */
+
+#endif /* ETHR_GCC_DW_ATOMIC_H__ */
+
diff --git a/erts/include/internal/gcc/ethr_membar.h b/erts/include/internal/gcc/ethr_membar.h
new file mode 100644
index 0000000000..7d428fc68e
--- /dev/null
+++ b/erts/include/internal/gcc/ethr_membar.h
@@ -0,0 +1,73 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description: Memory barriers when using gcc's builtins
+ * Author: Rickard Green
+ */
+
+#ifndef ETHR_GCC_MEMBAR_H__
+#define ETHR_GCC_MEMBAR_H__
+
+#define ETHR_LoadLoad (1 << 0)
+#define ETHR_LoadStore (1 << 1)
+#define ETHR_StoreLoad (1 << 2)
+#define ETHR_StoreStore (1 << 3)
+
+/*
+ * According to the documentation __sync_synchronize() will
+ * issue a full memory barrier. However, __sync_synchronize()
+ * is known to erroneously be a noop on at least some
+ * platforms with some gcc versions. This has suposedly been
+ * fixed in some gcc version, but we don't know from which
+ * version. Therefore, we only use it when it has been
+ * verified to work. Otherwise we use the workaround
+ * below.
+ */
+
+#if defined(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP32)
+# define ETHR_MB_T__ ethr_sint32_t
+#elif defined(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP64)
+# define ETHR_MB_T__ ethr_sint64_t
+#else
+# error "No __sync_val_compare_and_swap"
+#endif
+#define ETHR_SYNC_SYNCHRONIZE_WORKAROUND__ \
+do { \
+ volatile ETHR_MB_T__ x___ = 0; \
+ (void) __sync_val_compare_and_swap(&x___, (ETHR_MB_T__) 0, (ETHR_MB_T__) 1); \
+} while (0)
+
+#define ETHR_COMPILER_BARRIER __asm__ __volatile__("" : : : "memory")
+
+#if defined(__mips__) && ETHR_AT_LEAST_GCC_VSN__(4, 2, 0)
+# define ETHR_MEMBAR(B) __sync_synchronize()
+# define ETHR_READ_DEPEND_MEMORY_BARRIER __sync_synchronize()
+#elif ((defined(__powerpc__) || defined(__ppc__)) \
+ && ETHR_AT_LEAST_GCC_VSN__(4, 1, 2))
+# define ETHR_MEMBAR(B) __sync_synchronize()
+#else /* Use workaround */
+# define ETHR_MEMBAR(B) \
+ ETHR_SYNC_SYNCHRONIZE_WORKAROUND__
+# define ETHR_READ_DEPEND_MEMORY_BARRIER \
+ ETHR_SYNC_SYNCHRONIZE_WORKAROUND__
+#endif
+
+
+#endif /* ETHR_GCC_MEMBAR_H__ */
diff --git a/erts/include/internal/gcc/ethread.h b/erts/include/internal/gcc/ethread.h
index 392a1aa2b2..fcfdc39441 100644
--- a/erts/include/internal/gcc/ethread.h
+++ b/erts/include/internal/gcc/ethread.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -25,16 +25,24 @@
#ifndef ETHREAD_GCC_H__
#define ETHREAD_GCC_H__
-#if !defined(ETHR_HAVE_NATIVE_ATOMICS) && defined(ETHR_HAVE_GCC_ATOMIC_OPS)
-#define ETHR_HAVE_NATIVE_ATOMICS 1
+#ifndef ETHR_MEMBAR
+# include "ethr_membar.h"
+#endif
+
+#if !defined(ETHR_HAVE_NATIVE_ATOMIC32)
+# define ETHR_ATOMIC_WANT_32BIT_IMPL__
+# include "ethr_atomic.h"
+#endif
-#define ETHR_ATOMIC_WANT_32BIT_IMPL__
-#include "ethr_atomic.h"
-#if ETHR_SIZEOF_PTR == 8
+#if ETHR_SIZEOF_PTR == 8 && !defined(ETHR_HAVE_NATIVE_ATOMIC64)
# define ETHR_ATOMIC_WANT_64BIT_IMPL__
# include "ethr_atomic.h"
#endif
+#if (!defined(ETHR_HAVE_NATIVE_DW_ATOMIC) \
+ && !(ETHR_SIZEOF_PTR == 4 && defined(ETHR_HAVE_NATIVE_ATOMIC64)) \
+ && !(ETHR_SIZEOF_PTR == 8 && defined(ETHR_HAVE_NATIVE_ATOMIC128)))
+# include "ethr_dw_atomic.h"
#endif
#endif
diff --git a/erts/include/internal/i386/atomic.h b/erts/include/internal/i386/atomic.h
index 4e402f261a..fc1b619935 100644
--- a/erts/include/internal/i386/atomic.h
+++ b/erts/include/internal/i386/atomic.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -25,53 +25,42 @@
*/
#undef ETHR_INCLUDE_ATOMIC_IMPL__
-#if !defined(ETHR_X86_ATOMIC32_H__) && defined(ETHR_ATOMIC_WANT_32BIT_IMPL__)
-#define ETHR_X86_ATOMIC32_H__
-#define ETHR_INCLUDE_ATOMIC_IMPL__ 4
-#undef ETHR_ATOMIC_WANT_32BIT_IMPL__
-#elif !defined(ETHR_X86_ATOMIC64_H__) && defined(ETHR_ATOMIC_WANT_64BIT_IMPL__)
-#define ETHR_X86_ATOMIC64_H__
-#define ETHR_INCLUDE_ATOMIC_IMPL__ 8
-#undef ETHR_ATOMIC_WANT_64BIT_IMPL__
+#if !defined(ETHR_X86_ATOMIC32_H__) \
+ && defined(ETHR_ATOMIC_WANT_32BIT_IMPL__)
+# define ETHR_X86_ATOMIC32_H__
+# define ETHR_INCLUDE_ATOMIC_IMPL__ 4
+# undef ETHR_ATOMIC_WANT_32BIT_IMPL__
+#elif !defined(ETHR_X86_ATOMIC64_H__) \
+ && defined(ETHR_ATOMIC_WANT_64BIT_IMPL__)
+# define ETHR_X86_ATOMIC64_H__
+# define ETHR_INCLUDE_ATOMIC_IMPL__ 8
+# undef ETHR_ATOMIC_WANT_64BIT_IMPL__
#endif
#ifdef ETHR_INCLUDE_ATOMIC_IMPL__
-#ifndef ETHR_X86_ATOMIC_COMMON__
-#define ETHR_X86_ATOMIC_COMMON__
-
-#define ETHR_ATOMIC_HAVE_INC_DEC_INSTRUCTIONS 1
-
-#if defined(__x86_64__) || !defined(ETHR_PRE_PENTIUM4_COMPAT)
-#define ETHR_MEMORY_BARRIER __asm__ __volatile__("mfence" : : : "memory")
-#define ETHR_WRITE_MEMORY_BARRIER __asm__ __volatile__("sfence" : : : "memory")
-#define ETHR_READ_MEMORY_BARRIER __asm__ __volatile__("lfence" : : : "memory")
-#define ETHR_READ_DEPEND_MEMORY_BARRIER __asm__ __volatile__("" : : : "memory")
-#else
-#define ETHR_MEMORY_BARRIER \
-do { \
- volatile ethr_sint32_t x___ = 0; \
- __asm__ __volatile__("lock; incl %0" : "=m"(x___) : "m"(x___) : "memory"); \
-} while (0)
-#endif
-
-#endif /* ETHR_X86_ATOMIC_COMMON__ */
-
-#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
-#define ETHR_HAVE_NATIVE_ATOMIC32 1
-#define ETHR_NATMC_FUNC__(X) ethr_native_atomic32_ ## X
-#define ETHR_ATMC_T__ ethr_native_atomic32_t
-#define ETHR_AINT_T__ ethr_sint32_t
-#define ETHR_AINT_SUFFIX__ "l"
-#elif ETHR_INCLUDE_ATOMIC_IMPL__ == 8
-#define ETHR_HAVE_NATIVE_ATOMIC64 1
-#define ETHR_NATMC_FUNC__(X) ethr_native_atomic64_ ## X
-#define ETHR_ATMC_T__ ethr_native_atomic64_t
-#define ETHR_AINT_T__ ethr_sint64_t
-#define ETHR_AINT_SUFFIX__ "q"
-#else
-#error "Unsupported integer size"
-#endif
+# ifndef ETHR_X86_ATOMIC_COMMON__
+# define ETHR_X86_ATOMIC_COMMON__
+# define ETHR_ATOMIC_HAVE_INC_DEC_INSTRUCTIONS 1
+# endif /* ETHR_X86_ATOMIC_COMMON__ */
+
+# if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_NATIVE_ATOMIC32 1
+# define ETHR_NATIVE_ATOMIC32_IMPL "ethread"
+# define ETHR_NATMC_FUNC__(X) ethr_native_atomic32_ ## X
+# define ETHR_ATMC_T__ ethr_native_atomic32_t
+# define ETHR_AINT_T__ ethr_sint32_t
+# define ETHR_AINT_SUFFIX__ "l"
+# elif ETHR_INCLUDE_ATOMIC_IMPL__ == 8
+# define ETHR_HAVE_NATIVE_ATOMIC64 1
+# define ETHR_NATIVE_ATOMIC64_IMPL "ethread"
+# define ETHR_NATMC_FUNC__(X) ethr_native_atomic64_ ## X
+# define ETHR_ATMC_T__ ethr_native_atomic64_t
+# define ETHR_AINT_T__ ethr_sint64_t
+# define ETHR_AINT_SUFFIX__ "q"
+# else
+# error "Unsupported integer size"
+# endif
/* An atomic is an aligned ETHR_AINT_T__ accessed via locked operations.
*/
@@ -81,87 +70,28 @@ typedef struct {
#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_ATOMIC_IMPL__)
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADDR 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADDR 1
+#endif
+
static ETHR_INLINE ETHR_AINT_T__ *
ETHR_NATMC_FUNC__(addr)(ETHR_ATMC_T__ *var)
{
return (ETHR_AINT_T__ *) &var->counter;
}
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(init)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ i)
-{
- var->counter = i;
-}
-
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(set)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ i)
-{
- var->counter = i;
-}
-
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(read)(ETHR_ATMC_T__ *var)
-{
- return var->counter;
-}
-
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(add)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ incr)
-{
- __asm__ __volatile__(
- "lock; add" ETHR_AINT_SUFFIX__ " %1, %0"
- : "=m"(var->counter)
- : "ir"(incr), "m"(var->counter));
-}
-
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(inc)(ETHR_ATMC_T__ *var)
-{
- __asm__ __volatile__(
- "lock; inc" ETHR_AINT_SUFFIX__ " %0"
- : "=m"(var->counter)
- : "m"(var->counter));
-}
-
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(dec)(ETHR_ATMC_T__ *var)
-{
- __asm__ __volatile__(
- "lock; dec" ETHR_AINT_SUFFIX__ " %0"
- : "=m"(var->counter)
- : "m"(var->counter));
-}
-
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(add_return)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ incr)
-{
- ETHR_AINT_T__ tmp;
-
- tmp = incr;
- __asm__ __volatile__(
- "lock; xadd" ETHR_AINT_SUFFIX__ " %0, %1" /* xadd didn't exist prior to the 486 */
- : "=r"(tmp)
- : "m"(var->counter), "0"(tmp));
- /* now tmp is the atomic's previous value */
- return tmp + incr;
-}
-
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(inc_return)(ETHR_ATMC_T__ *var)
-{
- return ETHR_NATMC_FUNC__(add_return)(var, (ETHR_AINT_T__) 1);
-}
-
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(dec_return)(ETHR_ATMC_T__ *var)
-{
- return ETHR_NATMC_FUNC__(add_return)(var, (ETHR_AINT_T__) -1);
-}
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG_MB 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_MB 1
+#endif
static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(cmpxchg)(ETHR_ATMC_T__ *var,
- ETHR_AINT_T__ new,
- ETHR_AINT_T__ old)
+ETHR_NATMC_FUNC__(cmpxchg_mb)(ETHR_ATMC_T__ *var,
+ ETHR_AINT_T__ new,
+ ETHR_AINT_T__ old)
{
__asm__ __volatile__(
"lock; cmpxchg" ETHR_AINT_SUFFIX__ " %2, %3"
@@ -171,110 +101,148 @@ ETHR_NATMC_FUNC__(cmpxchg)(ETHR_ATMC_T__ *var,
return old;
}
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(and_retold)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ mask)
-{
- ETHR_AINT_T__ tmp, old;
-
- tmp = var->counter;
- do {
- old = tmp;
- tmp = ETHR_NATMC_FUNC__(cmpxchg)(var, tmp & mask, tmp);
- } while (__builtin_expect(tmp != old, 0));
- /* now tmp is the atomic's previous value */
- return tmp;
-}
-
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(or_retold)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ mask)
-{
- ETHR_AINT_T__ tmp, old;
-
- tmp = var->counter;
- do {
- old = tmp;
- tmp = ETHR_NATMC_FUNC__(cmpxchg)(var, tmp | mask, tmp);
- } while (__builtin_expect(tmp != old, 0));
- /* now tmp is the atomic's previous value */
- return tmp;
-}
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_XCHG_MB 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_XCHG_MB 1
+#endif
static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(xchg)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ val)
+ETHR_NATMC_FUNC__(xchg_mb)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ val)
{
ETHR_AINT_T__ tmp = val;
__asm__ __volatile__(
"xchg" ETHR_AINT_SUFFIX__ " %0, %1"
: "=r"(tmp)
- : "m"(var->counter), "0"(tmp));
+ : "m"(var->counter), "0"(tmp)
+ : "memory");
/* now tmp is the atomic's previous value */
return tmp;
}
-/*
- * Atomic ops with at least specified barriers.
- */
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET 1
+#endif
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(read_acqb)(ETHR_ATMC_T__ *var)
+static ETHR_INLINE void
+ETHR_NATMC_FUNC__(set)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ i)
{
- ETHR_AINT_T__ val;
-#if defined(__x86_64__) || !defined(ETHR_PRE_PENTIUM4_COMPAT)
- val = var->counter;
+ var->counter = i;
+}
+
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET_RELB 1
#else
- val = ETHR_NATMC_FUNC__(add_return)(var, 0);
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET_RELB 1
#endif
- __asm__ __volatile__("" : : : "memory");
- return val;
-}
static ETHR_INLINE void
ETHR_NATMC_FUNC__(set_relb)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ i)
{
- __asm__ __volatile__("" : : : "memory");
-#if defined(__x86_64__) || !defined(ETHR_PRE_PENTIUM4_COMPAT)
- var->counter = i;
+#if defined(_M_IX86)
+ if (ETHR_X86_RUNTIME_CONF_HAVE_NO_SSE2__)
+ (void) ETHR_NATMC_FUNC__(xchg_mb)(var, i);
+ else
+#endif /* _M_IX86 */
+ {
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ var->counter = i;
+ }
+}
+
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET_MB 1
#else
- (void) ETHR_NATMC_FUNC__(xchg)(var, i);
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET_MB 1
#endif
+
+static ETHR_INLINE void
+ETHR_NATMC_FUNC__(set_mb)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ i)
+{
+ (void) ETHR_NATMC_FUNC__(xchg_mb)(var, i);
}
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ 1
+#endif
+
static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(inc_return_acqb)(ETHR_ATMC_T__ *var)
+ETHR_NATMC_FUNC__(read)(ETHR_ATMC_T__ *var)
{
- ETHR_AINT_T__ res = ETHR_NATMC_FUNC__(inc_return)(var);
- __asm__ __volatile__("" : : : "memory");
- return res;
+ return var->counter;
}
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_MB 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_MB 1
+#endif
+
static ETHR_INLINE void
-ETHR_NATMC_FUNC__(dec_relb)(ETHR_ATMC_T__ *var)
+ETHR_NATMC_FUNC__(add_mb)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ incr)
{
- __asm__ __volatile__("" : : : "memory");
- ETHR_NATMC_FUNC__(dec)(var);
-}
+ __asm__ __volatile__(
+ "lock; add" ETHR_AINT_SUFFIX__ " %1, %0"
+ : "=m"(var->counter)
+ : "ir"(incr), "m"(var->counter)
+ : "memory");
+}
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(dec_return_relb)(ETHR_ATMC_T__ *var)
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_MB 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_MB 1
+#endif
+
+static ETHR_INLINE void
+ETHR_NATMC_FUNC__(inc_mb)(ETHR_ATMC_T__ *var)
{
- __asm__ __volatile__("" : : : "memory");
- return ETHR_NATMC_FUNC__(dec_return)(var);
+ __asm__ __volatile__(
+ "lock; inc" ETHR_AINT_SUFFIX__ " %0"
+ : "=m"(var->counter)
+ : "m"(var->counter)
+ : "memory");
}
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(cmpxchg_acqb)(ETHR_ATMC_T__ *var,
- ETHR_AINT_T__ new,
- ETHR_AINT_T__ old)
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_MB 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_MB 1
+#endif
+
+static ETHR_INLINE void
+ETHR_NATMC_FUNC__(dec_mb)(ETHR_ATMC_T__ *var)
{
- return ETHR_NATMC_FUNC__(cmpxchg)(var, new, old);
+ __asm__ __volatile__(
+ "lock; dec" ETHR_AINT_SUFFIX__ " %0"
+ : "=m"(var->counter)
+ : "m"(var->counter)
+ : "memory");
}
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RETURN_MB 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RETURN_MB 1
+#endif
+
static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(cmpxchg_relb)(ETHR_ATMC_T__ *var,
- ETHR_AINT_T__ new,
- ETHR_AINT_T__ old)
+ETHR_NATMC_FUNC__(add_return_mb)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ incr)
{
- return ETHR_NATMC_FUNC__(cmpxchg)(var, new, old);
+ ETHR_AINT_T__ tmp;
+
+ tmp = incr;
+ __asm__ __volatile__(
+ "lock; xadd" ETHR_AINT_SUFFIX__ " %0, %1" /* xadd didn't exist prior to the 486 */
+ : "=r"(tmp)
+ : "m"(var->counter), "0"(tmp)
+ : "memory");
+ /* now tmp is the atomic's previous value */
+ return tmp + incr;
}
#endif /* ETHR_TRY_INLINE_FUNCS */
diff --git a/erts/include/internal/i386/ethr_dw_atomic.h b/erts/include/internal/i386/ethr_dw_atomic.h
new file mode 100644
index 0000000000..9fb89bbe43
--- /dev/null
+++ b/erts/include/internal/i386/ethr_dw_atomic.h
@@ -0,0 +1,278 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description: Native double word atomics for x86/x86_64
+ * Author: Rickard Green
+ */
+
+#ifndef ETHR_X86_DW_ATOMIC_H__
+#define ETHR_X86_DW_ATOMIC_H__
+
+#ifdef ETHR_GCC_HAVE_DW_CMPXCHG_ASM_SUPPORT
+
+#define ETHR_HAVE_NATIVE_DW_ATOMIC
+#define ETHR_NATIVE_DW_ATOMIC_IMPL "ethread"
+
+/*
+ * If ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__ is defined, it will be used
+ * at runtime in order to determine if native or fallback implementation
+ * should be used.
+ */
+#define ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__ \
+ ETHR_X86_RUNTIME_CONF_HAVE_DW_CMPXCHG__
+
+#if ETHR_SIZEOF_PTR == 4
+typedef volatile ethr_sint64_t * ethr_native_dw_ptr_t;
+# define ETHR_DW_NATMC_ALIGN_MASK__ 0x7
+# define ETHR_DW_CMPXCHG_SFX__ "8b"
+# define ETHR_NATIVE_SU_DW_SINT_T ethr_sint64_t
+#else
+#ifdef ETHR_HAVE_INT128_T
+# define ETHR_NATIVE_SU_DW_SINT_T ethr_sint128_t
+typedef volatile ethr_sint128_t * ethr_native_dw_ptr_t;
+#else
+typedef struct {
+ ethr_sint64_t sint64[2];
+} ethr_native_sint128_t__;
+typedef volatile ethr_native_sint128_t__ * ethr_native_dw_ptr_t;
+#endif
+# define ETHR_DW_NATMC_ALIGN_MASK__ 0xf
+# define ETHR_DW_CMPXCHG_SFX__ "16b"
+#endif
+
+/*
+ * We need 16 byte aligned memory in 64-bit mode, and 8 byte aligned
+ * memory in 32-bit mode. 16 byte aligned malloc in 64-bit mode is
+ * not common, and at least some glibc malloc implementations
+ * only 4 byte align in 32-bit mode.
+ *
+ * This code assumes 8 byte aligned memory in 64-bit mode, and 4 byte
+ * aligned memory in 32-bit mode. A malloc implementation that does
+ * not adhere to these alignment requirements is seriously broken,
+ * and we wont bother trying to work around it.
+ *
+ * Since memory alignment may be off by one word we need to align at
+ * runtime. We, therefore, need an extra word allocated.
+ */
+#define ETHR_DW_NATMC_MEM__(VAR) \
+ (&var->c[(int) ((ethr_uint_t) &(VAR)->c[0]) & ETHR_DW_NATMC_ALIGN_MASK__])
+typedef union {
+#ifdef ETHR_NATIVE_SU_DW_SINT_T
+ volatile ETHR_NATIVE_SU_DW_SINT_T dw_sint;
+#endif
+ volatile ethr_sint_t sint[3];
+ volatile char c[ETHR_SIZEOF_PTR*3];
+} ethr_native_dw_atomic_t;
+
+
+#if (defined(ETHR_TRY_INLINE_FUNCS) \
+ || defined(ETHR_ATOMIC_IMPL__) \
+ || defined(ETHR_X86_SSE2_ASM_C__)) \
+ && ETHR_SIZEOF_PTR == 4 \
+ && defined(ETHR_GCC_HAVE_SSE2_ASM_SUPPORT)
+ethr_sint64_t
+ethr_sse2_native_su_dw_atomic_read(ethr_native_dw_atomic_t *var);
+void
+ethr_sse2_native_su_dw_atomic_set(ethr_native_dw_atomic_t *var,
+ ethr_sint64_t val);
+#endif
+
+#if (defined(ETHR_TRY_INLINE_FUNCS) \
+ || defined(ETHR_ATOMIC_IMPL__) \
+ || defined(ETHR_X86_SSE2_ASM_C__))
+# ifdef ETHR_DEBUG
+# define ETHR_DW_DBG_ALIGNED__(PTR) \
+ ETHR_ASSERT((((ethr_uint_t) (PTR)) & ETHR_DW_NATMC_ALIGN_MASK__) == 0);
+# else
+# define ETHR_DW_DBG_ALIGNED__(PTR)
+# endif
+#endif
+
+#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_ATOMIC_IMPL__)
+
+#define ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_ADDR
+static ETHR_INLINE ethr_sint_t *
+ethr_native_dw_atomic_addr(ethr_native_dw_atomic_t *var)
+{
+ return (ethr_sint_t *) ETHR_DW_NATMC_MEM__(var);
+}
+
+#if ETHR_SIZEOF_PTR == 4 && defined(__PIC__) && __PIC__
+/*
+ * When position independent code is used in 32-bit mode, the EBX register
+ * is used for storage of global offset table address, and we may not
+ * use it as input or output in an asm. We need to save and restore the
+ * EBX register explicitly (for some reason gcc doesn't provide this
+ * service to us).
+ */
+# define ETHR_NO_CLOBBER_EBX__ 1
+#else
+# define ETHR_NO_CLOBBER_EBX__ 0
+#endif
+
+#if ETHR_NO_CLOBBER_EBX__ && !defined(ETHR_CMPXCHG8B_REGISTER_SHORTAGE)
+/* When no optimization is on, we'll run into a register shortage */
+# if defined(ETHR_DEBUG) || defined(DEBUG) || defined(VALGRIND) \
+ || defined(GCOV) || defined(PURIFY) || defined(PURECOV)
+# define ETHR_CMPXCHG8B_REGISTER_SHORTAGE 1
+# else
+# define ETHR_CMPXCHG8B_REGISTER_SHORTAGE 0
+# endif
+#endif
+
+
+#define ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_CMPXCHG_MB
+
+static ETHR_INLINE int
+ethr_native_dw_atomic_cmpxchg_mb(ethr_native_dw_atomic_t *var,
+ ethr_sint_t *new,
+ ethr_sint_t *xchg)
+{
+ ethr_native_dw_ptr_t p = (ethr_native_dw_ptr_t) ETHR_DW_NATMC_MEM__(var);
+ char xchgd;
+
+ ETHR_DW_DBG_ALIGNED__(p);
+
+ __asm__ __volatile__(
+#if ETHR_NO_CLOBBER_EBX__
+ "pushl %%ebx\n\t"
+# if ETHR_CMPXCHG8B_REGISTER_SHORTAGE
+ "movl (%7), %%ebx\n\t"
+ "movl 4(%7), %%ecx\n\t"
+# else
+ "movl %8, %%ebx\n\t"
+# endif
+#endif
+ "lock; cmpxchg" ETHR_DW_CMPXCHG_SFX__ " %0\n\t"
+ "setz %3\n\t"
+#if ETHR_NO_CLOBBER_EBX__
+ "popl %%ebx\n\t"
+#endif
+ : "=m"(*p), "=d"(xchg[1]), "=a"(xchg[0]), "=c"(xchgd)
+ : "m"(*p), "1"(xchg[1]), "2"(xchg[0]),
+#if ETHR_NO_CLOBBER_EBX__
+# if ETHR_CMPXCHG8B_REGISTER_SHORTAGE
+ "3"(new)
+# else
+ "3"(new[1]),
+ "r"(new[0])
+# endif
+#else
+ "3"(new[1]),
+ "b"(new[0])
+#endif
+ : "cc", "memory");
+
+ return (int) xchgd;
+}
+
+#undef ETHR_NO_CLOBBER_EBX__
+
+#if ETHR_SIZEOF_PTR == 4 && defined(ETHR_GCC_HAVE_SSE2_ASM_SUPPORT)
+
+typedef union {
+ ethr_sint64_t sint64;
+ ethr_sint_t sint[2];
+} ethr_dw_atomic_no_sse2_convert_t;
+
+#define ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_READ
+
+static ETHR_INLINE ethr_sint64_t
+ethr_native_su_dw_atomic_read(ethr_native_dw_atomic_t *var)
+{
+ if (ETHR_X86_RUNTIME_CONF_HAVE_SSE2__)
+ return ethr_sse2_native_su_dw_atomic_read(var);
+ else {
+ ethr_sint_t new[2];
+ ethr_dw_atomic_no_sse2_convert_t xchg;
+ new[0] = new[1] = xchg.sint[0] = xchg.sint[1] = 0x83838383;
+ (void) ethr_native_dw_atomic_cmpxchg_mb(var, new, xchg.sint);
+ return xchg.sint64;
+ }
+}
+
+#define ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_SET
+
+static ETHR_INLINE void
+ethr_native_su_dw_atomic_set(ethr_native_dw_atomic_t *var,
+ ethr_sint64_t val)
+{
+ if (ETHR_X86_RUNTIME_CONF_HAVE_SSE2__)
+ ethr_sse2_native_su_dw_atomic_set(var, val);
+ else {
+ ethr_sint_t xchg[2] = {0, 0};
+ ethr_dw_atomic_no_sse2_convert_t new;
+ new.sint64 = val;
+ while (!ethr_native_dw_atomic_cmpxchg_mb(var, new.sint, xchg));
+ }
+}
+
+#endif /* ETHR_SIZEOF_PTR == 4 */
+
+#endif /* ETHR_TRY_INLINE_FUNCS */
+
+#if defined(ETHR_X86_SSE2_ASM_C__) \
+ && ETHR_SIZEOF_PTR == 4 \
+ && defined(ETHR_GCC_HAVE_SSE2_ASM_SUPPORT)
+
+/*
+ * 8-byte aligned loads and stores of 64-bit values are atomic from
+ * pentium and forward. An ordinary volatile load or store in 32-bit
+ * mode generates two 32-bit operations (at least with gcc-4.1.2 using
+ * -msse2). In order to guarantee one 64-bit load/store operation
+ * from/to memory we load/store via an xmm register using movq.
+ *
+ * Load/store can be achieved using cmpxchg8b, however, using movq is
+ * much faster. Unfortunately we cannot do the same thing in 64-bit
+ * mode; instead, we have to do loads and stores via cmpxchg16b.
+ *
+ * We do not inline these, but instead compile these into a separate
+ * object file using -msse2. This since we don't want to use -msse2 for
+ * the whole system. If we detect sse2 support (pentium4 and forward)
+ * at runtime, we use them; otherwise, we fall back to using cmpxchg8b
+ * for loads and stores. This way the binary can be moved between
+ * processors with and without sse2 support.
+ */
+
+ethr_sint64_t
+ethr_sse2_native_su_dw_atomic_read(ethr_native_dw_atomic_t *var)
+{
+ ethr_native_dw_ptr_t p = (ethr_native_dw_ptr_t) ETHR_DW_NATMC_MEM__(var);
+ ethr_sint64_t val;
+ ETHR_DW_DBG_ALIGNED__(p);
+ __asm__ __volatile__("movq %1, %0\n\t" : "=x"(val) : "m"(*p) : "memory");
+ return val;
+}
+
+void
+ethr_sse2_native_su_dw_atomic_set(ethr_native_dw_atomic_t *var,
+ ethr_sint64_t val)
+{
+ ethr_native_dw_ptr_t p = (ethr_native_dw_ptr_t) ETHR_DW_NATMC_MEM__(var);
+ ETHR_DW_DBG_ALIGNED__(p);
+ __asm__ __volatile__("movq %1, %0\n\t" : "=m"(*p) : "x"(val) : "memory");
+}
+
+#endif /* ETHR_X86_SSE2_ASM_C__ */
+
+#endif /* ETHR_GCC_HAVE_DW_CMPXCHG_ASM_SUPPORT */
+
+#endif /* ETHR_X86_DW_ATOMIC_H__ */
+
diff --git a/erts/include/internal/i386/ethr_membar.h b/erts/include/internal/i386/ethr_membar.h
new file mode 100644
index 0000000000..92d9de7f3f
--- /dev/null
+++ b/erts/include/internal/i386/ethr_membar.h
@@ -0,0 +1,114 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description: Memory barriers for x86/x86-64
+ * Author: Rickard Green
+ */
+
+#ifndef ETHR_X86_MEMBAR_H__
+#define ETHR_X86_MEMBAR_H__
+
+#define ETHR_LoadLoad (1 << 0)
+#define ETHR_LoadStore (1 << 1)
+#define ETHR_StoreLoad (1 << 2)
+#define ETHR_StoreStore (1 << 3)
+
+#define ETHR_NO_SSE2_MEMORY_BARRIER__ \
+do { \
+ volatile ethr_sint32_t x__ = 0; \
+ __asm__ __volatile__ ("lock; orl $0x0, %0\n\t" \
+ : "=m"(x__) \
+ : "m"(x__) \
+ : "memory"); \
+} while (0)
+
+static __inline__ void
+ethr_cfence__(void)
+{
+ __asm__ __volatile__ ("" : : : "memory");
+}
+
+static __inline__ void
+ethr_mfence__(void)
+{
+#if ETHR_SIZEOF_PTR == 4
+ if (ETHR_X86_RUNTIME_CONF_HAVE_NO_SSE2__)
+ ETHR_NO_SSE2_MEMORY_BARRIER__;
+ else
+#endif
+ __asm__ __volatile__ ("mfence\n\t" : : : "memory");
+}
+
+static __inline__ void
+ethr_sfence__(void)
+{
+#if ETHR_SIZEOF_PTR == 4
+ if (ETHR_X86_RUNTIME_CONF_HAVE_NO_SSE2__)
+ ETHR_NO_SSE2_MEMORY_BARRIER__;
+ else
+#endif
+ __asm__ __volatile__ ("sfence\n\t" : : : "memory");
+}
+
+static __inline__ void
+ethr_lfence__(void)
+{
+#if ETHR_SIZEOF_PTR == 4
+ if (ETHR_X86_RUNTIME_CONF_HAVE_NO_SSE2__)
+ ETHR_NO_SSE2_MEMORY_BARRIER__;
+ else
+#endif
+ __asm__ __volatile__ ("lfence\n\t" : : : "memory");
+}
+
+#define ETHR_X86_OUT_OF_ORDER_MEMBAR(B) \
+ ETHR_CHOOSE_EXPR((B) == ETHR_StoreStore, \
+ ethr_sfence__(), \
+ ETHR_CHOOSE_EXPR((B) == ETHR_LoadLoad, \
+ ethr_lfence__(), \
+ ethr_mfence__()))
+
+#ifdef ETHR_X86_OUT_OF_ORDER
+
+#define ETHR_MEMBAR(B) \
+ ETHR_X86_OUT_OF_ORDER_MEMBAR((B))
+
+#else /* !ETHR_X86_OUT_OF_ORDER (the default) */
+
+/*
+ * We assume that only stores before loads may be reordered. That is,
+ * we assume that *no* instructions like these are used:
+ * - CLFLUSH,
+ * - streaming stores executed with non-temporal move,
+ * - string operations, or
+ * - other instructions which aren't LoadLoad, LoadStore, and StoreStore
+ * ordered by themselves
+ * If such instructions are used, either insert memory barriers
+ * using ETHR_X86_OUT_OF_ORDER_MEMBAR() at appropriate places, or
+ * define ETHR_X86_OUT_OF_ORDER. For more info see Intel 64 and IA-32
+ * Architectures Software Developer's Manual; Vol 3A; Chapter 8.2.2.
+ */
+
+#define ETHR_MEMBAR(B) \
+ ETHR_CHOOSE_EXPR((B) & ETHR_StoreLoad, ethr_mfence__(), ethr_cfence__())
+
+#endif /* !ETHR_X86_OUT_OF_ORDER */
+
+#endif /* ETHR_X86_MEMBAR_H__ */
diff --git a/erts/include/internal/i386/ethread.h b/erts/include/internal/i386/ethread.h
index b5a17caefb..80e4dc7b99 100644
--- a/erts/include/internal/i386/ethread.h
+++ b/erts/include/internal/i386/ethread.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -24,17 +24,15 @@
#ifndef ETHREAD_I386_ETHREAD_H
#define ETHREAD_I386_ETHREAD_H
+#include "ethr_membar.h"
#define ETHR_ATOMIC_WANT_32BIT_IMPL__
#include "atomic.h"
#if ETHR_SIZEOF_PTR == 8
# define ETHR_ATOMIC_WANT_64BIT_IMPL__
# include "atomic.h"
#endif
+#include "ethr_dw_atomic.h"
#include "spinlock.h"
#include "rwlock.h"
-#define ETHR_HAVE_NATIVE_ATOMICS 1
-#define ETHR_HAVE_NATIVE_SPINLOCKS 1
-#define ETHR_HAVE_NATIVE_RWSPINLOCKS 1
-
#endif /* ETHREAD_I386_ETHREAD_H */
diff --git a/erts/include/internal/i386/rwlock.h b/erts/include/internal/i386/rwlock.h
index be47f459ce..1a8cd7da0c 100644
--- a/erts/include/internal/i386/rwlock.h
+++ b/erts/include/internal/i386/rwlock.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -26,6 +26,9 @@
#ifndef ETHREAD_I386_RWLOCK_H
#define ETHREAD_I386_RWLOCK_H
+#define ETHR_HAVE_NATIVE_RWSPINLOCKS 1
+#define ETHR_NATIVE_RWSPINLOCK_IMPL "ethread"
+
/* XXX: describe the algorithm */
typedef struct {
volatile int lock;
diff --git a/erts/include/internal/i386/spinlock.h b/erts/include/internal/i386/spinlock.h
index 0325324895..a84fba91b1 100644
--- a/erts/include/internal/i386/spinlock.h
+++ b/erts/include/internal/i386/spinlock.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -24,6 +24,9 @@
#ifndef ETHREAD_I386_SPINLOCK_H
#define ETHREAD_I386_SPINLOCK_H
+#define ETHR_HAVE_NATIVE_SPINLOCKS 1
+#define ETHR_NATIVE_SPINLOCK_IMPL "ethread"
+
/* A spinlock is the low byte of an aligned 32-bit integer.
* A non-zero value means that the lock is locked.
*/
@@ -46,16 +49,20 @@ ethr_native_spin_unlock(ethr_native_spinlock_t *lock)
* On i386 this needs to be a locked operation
* to avoid Pentium Pro errata 66 and 92.
*/
-#if defined(__x86_64__) || !defined(ETHR_PRE_PENTIUM4_COMPAT)
- __asm__ __volatile__("" : : : "memory");
- *(unsigned char*)&lock->lock = 0;
-#else
- char tmp = 0;
- __asm__ __volatile__(
- "xchgb %b0, %1"
- : "=q"(tmp), "=m"(lock->lock)
- : "0"(tmp) : "memory");
+#if !defined(__x86_64__)
+ if (ETHR_X86_RUNTIME_CONF_HAVE_NO_SSE2__) {
+ char tmp = 0;
+ __asm__ __volatile__(
+ "xchgb %b0, %1"
+ : "=q"(tmp), "=m"(lock->lock)
+ : "0"(tmp) : "memory");
+ }
+ else
#endif
+ {
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ *(unsigned char*)&lock->lock = 0;
+ }
}
static ETHR_INLINE int
diff --git a/erts/include/internal/libatomic_ops/ethr_atomic.h b/erts/include/internal/libatomic_ops/ethr_atomic.h
index 93bc06036f..fb1288c330 100644
--- a/erts/include/internal/libatomic_ops/ethr_atomic.h
+++ b/erts/include/internal/libatomic_ops/ethr_atomic.h
@@ -25,16 +25,6 @@
#ifndef ETHR_LIBATOMIC_OPS_ATOMIC_H__
#define ETHR_LIBATOMIC_OPS_ATOMIC_H__
-#if !defined(ETHR_HAVE_NATIVE_ATOMICS) && defined(ETHR_HAVE_LIBATOMIC_OPS)
-#define ETHR_HAVE_NATIVE_ATOMICS 1
-
-#if (defined(__i386__) && !defined(ETHR_PRE_PENTIUM4_COMPAT)) \
- || defined(__x86_64__)
-#define AO_USE_PENTIUM4_INSTRS
-#endif
-
-#include "atomic_ops.h"
-
/*
* libatomic_ops can be downloaded from:
* http://www.hpl.hp.com/research/linux/atomic_ops/
@@ -46,21 +36,18 @@
* - AO_store()
* - AO_compare_and_swap()
*
- * The `AO_t' type also have to be at least as large as the `void *' type.
*/
-#if ETHR_SIZEOF_AO_T < ETHR_SIZEOF_PTR
-#error The AO_t type is too small
-#endif
-
#if ETHR_SIZEOF_AO_T == 4
#define ETHR_HAVE_NATIVE_ATOMIC32 1
+#define ETHR_NATIVE_ATOMIC32_IMPL "libatomic_ops"
#define ETHR_NATMC_FUNC__(X) ethr_native_atomic32_ ## X
#define ETHR_ATMC_T__ ethr_native_atomic32_t
#define ETHR_AINT_T__ ethr_sint32_t
#define ETHR_AINT_SUFFIX__ "l"
#elif ETHR_SIZEOF_AO_T == 8
#define ETHR_HAVE_NATIVE_ATOMIC64 1
+#define ETHR_NATIVE_ATOMIC64_IMPL "libatomic_ops"
#define ETHR_NATMC_FUNC__(X) ethr_native_atomic64_ ## X
#define ETHR_ATMC_T__ ethr_native_atomic64_t
#define ETHR_AINT_T__ ethr_sint64_t
@@ -69,61 +56,29 @@
#error "Unsupported integer size"
#endif
-#if ETHR_SIZEOF_AO_T == 8
-typedef union {
- volatile AO_t counter;
- ethr_sint32_t sint32[2];
-} ETHR_ATMC_T__;
-#else
typedef struct {
volatile AO_t counter;
} ETHR_ATMC_T__;
-#endif
-#define ETHR_MEMORY_BARRIER AO_nop_full()
-#ifdef AO_HAVE_nop_write
-# define ETHR_WRITE_MEMORY_BARRIER AO_nop_write()
-#else
-# define ETHR_WRITE_MEMORY_BARRIER ETHR_MEMORY_BARRIER
-#endif
-#ifdef AO_HAVE_nop_read
-# define ETHR_READ_MEMORY_BARRIER AO_nop_read()
-#else
-# define ETHR_READ_MEMORY_BARRIER ETHR_MEMORY_BARRIER
-#endif
-#ifdef AO_NO_DD_ORDERING
-# define ETHR_READ_DEPEND_MEMORY_BARRIER ETHR_READ_MEMORY_BARRIER
+#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_ATOMIC_IMPL__)
+
+#if ETHR_SIZEOF_AO_T == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADDR 1
#else
-# define ETHR_READ_DEPEND_MEMORY_BARRIER AO_compiler_barrier()
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADDR 1
#endif
-#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_ATOMIC_IMPL__)
-
static ETHR_INLINE ETHR_AINT_T__ *
ETHR_NATMC_FUNC__(addr)(ETHR_ATMC_T__ *var)
{
return (ETHR_AINT_T__ *) &var->counter;
}
-#if ETHR_SIZEOF_AO_T == 8
-/*
- * We also need to provide an ethr_native_atomic32_addr(), since
- * this 64-bit implementation will be used implementing 32-bit
- * native atomics.
- */
-
-static ETHR_INLINE ethr_sint32_t *
-ethr_native_atomic32_addr(ETHR_ATMC_T__ *var)
-{
- ETHR_ASSERT(((void *) &var->sint32[0]) == ((void *) &var->counter));
-#ifdef ETHR_BIGENDIAN
- return &var->sint32[1];
+#if ETHR_SIZEOF_AO_T == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET 1
#else
- return &var->sint32[0];
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET 1
#endif
-}
-
-#endif /* ETHR_SIZEOF_AO_T == 8 */
static ETHR_INLINE void
ETHR_NATMC_FUNC__(set)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ value)
@@ -131,197 +86,198 @@ ETHR_NATMC_FUNC__(set)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ value)
AO_store(&var->counter, (AO_t) value);
}
+#ifdef AO_HAVE_store_release
+
+#if ETHR_SIZEOF_AO_T == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET_RELB 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET_RELB 1
+#endif
+
static ETHR_INLINE void
-ETHR_NATMC_FUNC__(init)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ value)
+ETHR_NATMC_FUNC__(set_relb)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ value)
{
- ETHR_NATMC_FUNC__(set)(var, value);
+ AO_store_release(&var->counter, (AO_t) value);
}
+#endif
+
+#if ETHR_SIZEOF_AO_T == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ 1
+#endif
+
static ETHR_INLINE ETHR_AINT_T__
ETHR_NATMC_FUNC__(read)(ETHR_ATMC_T__ *var)
{
return (ETHR_AINT_T__) AO_load(&var->counter);
}
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(add_return)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ incr)
-{
-#ifdef AO_HAVE_fetch_and_add_full
- return ((ETHR_AINT_T__) AO_fetch_and_add_full(&var->counter, (AO_t) incr)) + incr;
+#ifdef AO_HAVE_load_acquire
+
+#if ETHR_SIZEOF_AO_T == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ_ACQB 1
#else
- while (1) {
- AO_t exp = AO_load(&var->counter);
- AO_t new = exp + (AO_t) incr;
- if (AO_compare_and_swap_full(&var->counter, exp, new))
- return (ETHR_AINT_T__) new;
- }
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ_ACQB 1
#endif
-}
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(add)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ incr)
+static ETHR_INLINE ETHR_AINT_T__
+ETHR_NATMC_FUNC__(read_acqb)(ETHR_ATMC_T__ *var)
{
- (void) ETHR_NATMC_FUNC__(add_return)(var, incr);
+ return (ETHR_AINT_T__) AO_load_acquire(&var->counter);
}
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(inc_return)(ETHR_ATMC_T__ *var)
-{
-#ifdef AO_HAVE_fetch_and_add1_full
- return ((ETHR_AINT_T__) AO_fetch_and_add1_full(&var->counter)) + 1;
-#else
- return ETHR_NATMC_FUNC__(add_return)(var, 1);
#endif
-}
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(inc)(ETHR_ATMC_T__ *var)
-{
- (void) ETHR_NATMC_FUNC__(inc_return)(var);
-}
+#ifdef AO_HAVE_fetch_and_add
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(dec_return)(ETHR_ATMC_T__ *var)
-{
-#ifdef AO_HAVE_fetch_and_sub1_full
- return ((ETHR_AINT_T__) AO_fetch_and_sub1_full(&var->counter)) - 1;
+#if ETHR_SIZEOF_AO_T == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RETURN 1
#else
- return ETHR_NATMC_FUNC__(add_return)(var, -1);
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RETURN 1
#endif
-}
-
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(dec)(ETHR_ATMC_T__ *var)
-{
- (void) ETHR_NATMC_FUNC__(dec_return)(var);
-}
static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(and_retold)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ mask)
+ETHR_NATMC_FUNC__(add_return)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ incr)
{
- while (1) {
- AO_t exp = AO_load(&var->counter);
- AO_t new = exp & ((AO_t) mask);
- if (AO_compare_and_swap_full(&var->counter, exp, new))
- return (ETHR_AINT_T__) exp;
- }
+ return ((ETHR_AINT_T__) AO_fetch_and_add(&var->counter, (AO_t) incr)) + incr;
}
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(or_retold)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ mask)
-{
- while (1) {
- AO_t exp = AO_load(&var->counter);
- AO_t new = exp | ((AO_t) mask);
- if (AO_compare_and_swap_full(&var->counter, exp, new))
- return (ETHR_AINT_T__) exp;
- }
-}
+#endif
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(cmpxchg)(ETHR_ATMC_T__ *var,
- ETHR_AINT_T__ new,
- ETHR_AINT_T__ exp)
-{
- ETHR_AINT_T__ act;
- do {
- if (AO_compare_and_swap_full(&var->counter, (AO_t) exp, (AO_t) new))
- return exp;
- act = (ETHR_AINT_T__) AO_load(&var->counter);
- } while (act == exp);
- return act;
-}
+#ifdef AO_HAVE_fetch_and_add1
+
+#if ETHR_SIZEOF_AO_T == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RETURN 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RETURN 1
+#endif
static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(xchg)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ new)
+ETHR_NATMC_FUNC__(inc_return)(ETHR_ATMC_T__ *var)
{
- while (1) {
- AO_t exp = AO_load(&var->counter);
- if (AO_compare_and_swap_full(&var->counter, exp, (AO_t) new))
- return (ETHR_AINT_T__) exp;
- }
+ return ((ETHR_AINT_T__) AO_fetch_and_add1(&var->counter)) + 1;
}
-/*
- * Atomic ops with at least specified barriers.
- */
+#endif
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(read_acqb)(ETHR_ATMC_T__ *var)
-{
-#ifdef AO_HAVE_load_acquire
- return (ETHR_AINT_T__) AO_load_acquire(&var->counter);
+#ifdef AO_HAVE_fetch_and_add1_acquire
+
+#if ETHR_SIZEOF_AO_T == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RETURN_ACQB 1
#else
- ETHR_AINT_T__ res = ETHR_NATMC_FUNC__(read)(var);
- ETHR_MEMORY_BARRIER;
- return res;
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RETURN_ACQB 1
#endif
-}
static ETHR_INLINE ETHR_AINT_T__
ETHR_NATMC_FUNC__(inc_return_acqb)(ETHR_ATMC_T__ *var)
{
-#ifdef AO_HAVE_fetch_and_add1_acquire
return ((ETHR_AINT_T__) AO_fetch_and_add1_acquire(&var->counter)) + 1;
+}
+
+#endif
+
+#ifdef AO_HAVE_fetch_and_sub1
+
+#if ETHR_SIZEOF_AO_T == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RETURN 1
#else
- ETHR_AINT_T__ res = ETHR_NATMC_FUNC__(add_return)(var, 1);
- return res;
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RETURN 1
#endif
-}
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(set_relb)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ value)
+static ETHR_INLINE ETHR_AINT_T__
+ETHR_NATMC_FUNC__(dec_return)(ETHR_ATMC_T__ *var)
{
-#ifdef AO_HAVE_store_release
- AO_store_release(&var->counter, (AO_t) value);
+ return ((ETHR_AINT_T__) AO_fetch_and_sub1(&var->counter)) - 1;
+}
+
+#endif
+
+#ifdef AO_HAVE_fetch_and_sub1_release
+
+#if ETHR_SIZEOF_AO_T == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RETURN_RELB 1
#else
- ETHR_MEMORY_BARRIER;
- ETHR_NATMC_FUNC__(set)(var, value);
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RETURN_RELB 1
#endif
-}
static ETHR_INLINE ETHR_AINT_T__
ETHR_NATMC_FUNC__(dec_return_relb)(ETHR_ATMC_T__ *var)
{
-#ifdef AO_HAVE_fetch_and_sub1_release
return ((ETHR_AINT_T__) AO_fetch_and_sub1_release(&var->counter)) - 1;
+}
+
+#endif
+
+#ifdef AO_HAVE_compare_and_swap
+
+#if ETHR_SIZEOF_AO_T == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG 1
#else
- return ETHR_NATMC_FUNC__(dec_return)(var);
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG 1
#endif
-}
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(dec_relb)(ETHR_ATMC_T__ *var)
+static ETHR_INLINE ETHR_AINT_T__
+ETHR_NATMC_FUNC__(cmpxchg)(ETHR_ATMC_T__ *var,
+ ETHR_AINT_T__ new,
+ ETHR_AINT_T__ exp)
{
- (void) ETHR_NATMC_FUNC__(dec_return_relb)(var);
+ ETHR_AINT_T__ act;
+ do {
+ if (AO_compare_and_swap(&var->counter, (AO_t) exp, (AO_t) new))
+ return exp;
+ act = (ETHR_AINT_T__) AO_load(&var->counter);
+ } while (act == exp);
+ return act;
}
+#endif
+
+#ifdef AO_HAVE_compare_and_swap_acquire
+
+#if ETHR_SIZEOF_AO_T == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG_ACQB 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_ACQB 1
+#endif
+
static ETHR_INLINE ETHR_AINT_T__
ETHR_NATMC_FUNC__(cmpxchg_acqb)(ETHR_ATMC_T__ *var,
ETHR_AINT_T__ new,
ETHR_AINT_T__ exp)
{
-#ifdef AO_HAVE_compare_and_swap_acquire
ETHR_AINT_T__ act;
do {
if (AO_compare_and_swap_acquire(&var->counter, (AO_t) exp, (AO_t) new))
return exp;
+#ifdef AO_HAVE_load_acquire
+ act = (ETHR_AINT_T__) AO_load_acquire(&var->counter);
+#else
act = (ETHR_AINT_T__) AO_load(&var->counter);
+#endif
} while (act == exp);
+#ifndef AO_HAVE_load_acquire
AO_nop_full();
+#endif
return act;
+}
+
+#endif
+
+#ifdef AO_HAVE_compare_and_swap_release
+
+#if ETHR_SIZEOF_AO_T == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG_RELB 1
#else
- ETHR_AINT_T__ act = ETHR_NATMC_FUNC__(cmpxchg)(var, new, exp);
- return act;
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_RELB 1
#endif
-}
static ETHR_INLINE ETHR_AINT_T__
ETHR_NATMC_FUNC__(cmpxchg_relb)(ETHR_ATMC_T__ *var,
ETHR_AINT_T__ new,
ETHR_AINT_T__ exp)
{
-#ifdef AO_HAVE_compare_and_swap_release
ETHR_AINT_T__ act;
do {
if (AO_compare_and_swap_release(&var->counter, (AO_t) exp, (AO_t) new))
@@ -329,11 +285,9 @@ ETHR_NATMC_FUNC__(cmpxchg_relb)(ETHR_ATMC_T__ *var,
act = (ETHR_AINT_T__) AO_load(&var->counter);
} while (act == exp);
return act;
-#else
- return ETHR_NATMC_FUNC__(cmpxchg)(var, new, exp);
-#endif
}
+#endif
#endif /* ETHR_TRY_INLINE_FUNCS */
@@ -341,6 +295,4 @@ ETHR_NATMC_FUNC__(cmpxchg_relb)(ETHR_ATMC_T__ *var,
#undef ETHR_ATMC_T__
#undef ETHR_AINT_T__
-#endif /* !defined(ETHR_HAVE_NATIVE_ATOMICS) && defined(ETHR_HAVE_LIBATOMIC_OPS) */
-
#endif /* ETHR_LIBATOMIC_OPS_ATOMIC_H__ */
diff --git a/erts/include/internal/libatomic_ops/ethr_membar.h b/erts/include/internal/libatomic_ops/ethr_membar.h
new file mode 100644
index 0000000000..b8530a0094
--- /dev/null
+++ b/erts/include/internal/libatomic_ops/ethr_membar.h
@@ -0,0 +1,75 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description: Memory barriers when using libatomic_ops
+ * Author: Rickard Green
+ */
+
+#ifndef ETHR_LIBATOMIC_OPS_MEMBAR_H__
+#define ETHR_LIBATOMIC_OPS_MEMBAR_H__
+
+#define ETHR_LoadLoad (1 << 0)
+#define ETHR_LoadStore (1 << 1)
+#define ETHR_StoreLoad (1 << 2)
+#define ETHR_StoreStore (1 << 3)
+
+#ifndef AO_HAVE_nop_full
+# error "No AO_nop_full()"
+#endif
+
+static __inline__ void
+ethr_mb__(void)
+{
+ AO_nop_full();
+}
+
+static __inline__ void
+ethr_rb__(void)
+{
+#ifdef AO_HAVE_nop_read
+ AO_nop_read();
+#else
+ AO_nop_full();
+#endif
+}
+
+static __inline__ void
+ethr_wb__(void)
+{
+#ifdef AO_HAVE_nop_write
+ AO_nop_write();
+#else
+ AO_nop_full();
+#endif
+}
+
+#define ETHR_MEMBAR(B) \
+ ETHR_CHOOSE_EXPR((B) == ETHR_StoreStore, \
+ ethr_wb__(), \
+ ETHR_CHOOSE_EXPR((B) == ETHR_LoadLoad, \
+ ethr_rb__(), \
+ ethr_mb__()))
+
+#define ETHR_COMPILER_BARRIER AO_compiler_barrier()
+#ifdef AO_NO_DD_ORDERING
+# define ETHR_READ_DEPEND_MEMORY_BARRIER ETHR_READ_MEMORY_BARRIER
+#endif
+
+#endif /* ETHR_LIBATOMIC_OPS_MEMBAR_H__ */
diff --git a/erts/include/internal/libatomic_ops/ethread.h b/erts/include/internal/libatomic_ops/ethread.h
index ee73ba73bc..e1fdd588bb 100644
--- a/erts/include/internal/libatomic_ops/ethread.h
+++ b/erts/include/internal/libatomic_ops/ethread.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -25,6 +25,18 @@
#ifndef ETHREAD_LIBATOMIC_OPS_H__
#define ETHREAD_LIBATOMIC_OPS_H__
+#if (defined(ETHR_HAVE_LIBATOMIC_OPS) \
+ && ((ETHR_SIZEOF_AO_T == 4 && !defined(ETHR_HAVE_NATIVE_ATOMIC32)) \
+ || (ETHR_SIZEOF_AO_T == 8 && !defined(ETHR_HAVE_NATIVE_ATOMIC64))))
+
+#if defined(__x86_64__)
+#define AO_USE_PENTIUM4_INSTRS
+#endif
+
+#include "atomic_ops.h"
+#include "ethr_membar.h"
#include "ethr_atomic.h"
#endif
+
+#endif
diff --git a/erts/include/internal/ppc32/atomic.h b/erts/include/internal/ppc32/atomic.h
index 522f433649..6001620677 100644
--- a/erts/include/internal/ppc32/atomic.h
+++ b/erts/include/internal/ppc32/atomic.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -29,27 +29,31 @@
#define ETHREAD_PPC_ATOMIC_H
#define ETHR_HAVE_NATIVE_ATOMIC32 1
+#define ETHR_NATIVE_ATOMIC32_IMPL "ethread"
typedef struct {
volatile ethr_sint32_t counter;
} ethr_native_atomic32_t;
-#define ETHR_MEMORY_BARRIER __asm__ __volatile__("sync" : : : "memory")
-
#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_ATOMIC_IMPL__)
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADDR 1
+
static ETHR_INLINE ethr_sint32_t *
ethr_native_atomic32_addr(ethr_native_atomic32_t *var)
{
return (ethr_sint32_t *) &var->counter;
}
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET 1
+
static ETHR_INLINE void
-ethr_native_atomic32_init(ethr_native_atomic32_t *var, ethr_sint32_t i)
+ethr_native_atomic32_set(ethr_native_atomic32_t *var, ethr_sint32_t i)
{
var->counter = i;
}
-#define ethr_native_atomic32_set(v, i) ethr_native_atomic32_init((v), (i))
+
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ 1
static ETHR_INLINE ethr_sint32_t
ethr_native_atomic32_read(ethr_native_atomic32_t *var)
@@ -57,57 +61,68 @@ ethr_native_atomic32_read(ethr_native_atomic32_t *var)
return var->counter;
}
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RETURN 1
+
static ETHR_INLINE ethr_sint32_t
ethr_native_atomic32_add_return(ethr_native_atomic32_t *var, ethr_sint32_t incr)
{
ethr_sint32_t tmp;
__asm__ __volatile__(
- "eieio\n\t"
"1:\t"
"lwarx %0,0,%1\n\t"
"add %0,%2,%0\n\t"
"stwcx. %0,0,%1\n\t"
"bne- 1b\n\t"
- "isync"
: "=&r"(tmp)
: "r"(&var->counter), "r"(incr)
: "cc", "memory");
return tmp;
}
-static ETHR_INLINE void
-ethr_native_atomic32_add(ethr_native_atomic32_t *var, ethr_sint32_t incr)
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RETURN_ACQB 1
+
+static ETHR_INLINE ethr_sint32_t
+ethr_native_atomic32_add_return_acqb(ethr_native_atomic32_t *var, ethr_sint32_t incr)
{
- /* XXX: could use weaker version here w/o eieio+isync */
- (void)ethr_native_atomic32_add_return(var, incr);
+ ethr_sint32_t res;
+ res = ethr_native_atomic32_add_return(var, incr);
+ __asm__ __volatile("isync\n\t" : : : "memory");
+ return res;
}
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RETURN 1
+
static ETHR_INLINE ethr_sint32_t
ethr_native_atomic32_inc_return(ethr_native_atomic32_t *var)
{
ethr_sint32_t tmp;
__asm__ __volatile__(
- "eieio\n\t"
"1:\t"
"lwarx %0,0,%1\n\t"
"addic %0,%0,1\n\t" /* due to addi's (rA|0) behaviour */
"stwcx. %0,0,%1\n\t"
"bne- 1b\n\t"
- "isync"
: "=&r"(tmp)
: "r"(&var->counter)
: "cc", "memory");
return tmp;
}
-static ETHR_INLINE void
-ethr_native_atomic32_inc(ethr_native_atomic32_t *var)
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RETURN_ACQB 1
+
+static ETHR_INLINE ethr_sint32_t
+ethr_native_atomic32_inc_return_acqb(ethr_native_atomic32_t *var)
{
- /* XXX: could use weaker version here w/o eieio+isync */
- (void)ethr_native_atomic32_inc_return(var);
+ ethr_sint32_t res;
+ res = ethr_native_atomic32_inc_return(var);
+ __asm__ __volatile("isync\n\t" : : : "memory");
+ return res;
}
+
+
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RETURN 1
static ETHR_INLINE ethr_sint32_t
ethr_native_atomic32_dec_return(ethr_native_atomic32_t *var)
@@ -115,82 +130,120 @@ ethr_native_atomic32_dec_return(ethr_native_atomic32_t *var)
ethr_sint32_t tmp;
__asm__ __volatile__(
- "eieio\n\t"
"1:\t"
"lwarx %0,0,%1\n\t"
"addic %0,%0,-1\n\t"
"stwcx. %0,0,%1\n\t"
"bne- 1b\n\t"
- "isync"
: "=&r"(tmp)
: "r"(&var->counter)
: "cc", "memory");
return tmp;
}
-static ETHR_INLINE void
-ethr_native_atomic32_dec(ethr_native_atomic32_t *var)
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RETURN_ACQB 1
+
+static ETHR_INLINE ethr_sint32_t
+ethr_native_atomic32_dec_return_acqb(ethr_native_atomic32_t *var)
{
- /* XXX: could use weaker version here w/o eieio+isync */
- (void)ethr_native_atomic32_dec_return(var);
+ ethr_sint32_t res;
+ res = ethr_native_atomic32_dec_return(var);
+ __asm__ __volatile("isync\n\t" : : : "memory");
+ return res;
}
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_AND_RETOLD 1
+
static ETHR_INLINE ethr_sint32_t
ethr_native_atomic32_and_retold(ethr_native_atomic32_t *var, ethr_sint32_t mask)
{
ethr_sint32_t old, new;
__asm__ __volatile__(
- "eieio\n\t"
"1:\t"
"lwarx %0,0,%2\n\t"
"and %1,%0,%3\n\t"
"stwcx. %1,0,%2\n\t"
"bne- 1b\n\t"
- "isync"
: "=&r"(old), "=&r"(new)
: "r"(&var->counter), "r"(mask)
: "cc", "memory");
return old;
}
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_AND_RETOLD_ACQB 1
+
+static ETHR_INLINE ethr_sint32_t
+ethr_native_atomic32_and_retold_acqb(ethr_native_atomic32_t *var, ethr_sint32_t mask)
+{
+ ethr_sint32_t res;
+ res = ethr_native_atomic32_and_retold(var, mask);
+ __asm__ __volatile("isync\n\t" : : : "memory");
+ return res;
+}
+
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_OR_RETOLD 1
+
static ETHR_INLINE ethr_sint32_t
ethr_native_atomic32_or_retold(ethr_native_atomic32_t *var, ethr_sint32_t mask)
{
ethr_sint32_t old, new;
__asm__ __volatile__(
- "eieio\n\t"
"1:\t"
"lwarx %0,0,%2\n\t"
"or %1,%0,%3\n\t"
"stwcx. %1,0,%2\n\t"
"bne- 1b\n\t"
- "isync"
: "=&r"(old), "=&r"(new)
: "r"(&var->counter), "r"(mask)
: "cc", "memory");
return old;
}
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_OR_RETOLD_ACQB 1
+
+static ETHR_INLINE ethr_sint32_t
+ethr_native_atomic32_or_retold_acqb(ethr_native_atomic32_t *var, ethr_sint32_t mask)
+{
+ ethr_sint32_t res;
+ res = ethr_native_atomic32_or_retold(var, mask);
+ __asm__ __volatile("isync\n\t" : : : "memory");
+ return res;
+}
+
+
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_XCHG 1
+
static ETHR_INLINE ethr_sint32_t
ethr_native_atomic32_xchg(ethr_native_atomic32_t *var, ethr_sint32_t val)
{
ethr_sint32_t tmp;
__asm__ __volatile__(
- "eieio\n\t"
"1:\t"
"lwarx %0,0,%1\n\t"
"stwcx. %2,0,%1\n\t"
"bne- 1b\n\t"
- "isync"
: "=&r"(tmp)
: "r"(&var->counter), "r"(val)
: "cc", "memory");
return tmp;
}
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_XCHG_ACQB 1
+
+static ETHR_INLINE ethr_sint32_t
+ethr_native_atomic32_xchg_acqb(ethr_native_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+ res = ethr_native_atomic32_xchg(var, val);
+ __asm__ __volatile("isync\n\t" : : : "memory");
+ return res;
+}
+
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG 1
+
static ETHR_INLINE ethr_sint32_t
ethr_native_atomic32_cmpxchg(ethr_native_atomic32_t *var,
ethr_sint32_t new,
@@ -199,14 +252,12 @@ ethr_native_atomic32_cmpxchg(ethr_native_atomic32_t *var,
ethr_sint32_t old;
__asm__ __volatile__(
- "eieio\n\t"
"1:\t"
"lwarx %0,0,%2\n\t"
"cmpw 0,%0,%3\n\t"
"bne 2f\n\t"
"stwcx. %1,0,%2\n\t"
"bne- 1b\n\t"
- "isync\n"
"2:"
: "=&r"(old)
: "r"(new), "r"(&var->counter), "r"(expected)
@@ -215,25 +266,30 @@ ethr_native_atomic32_cmpxchg(ethr_native_atomic32_t *var,
return old;
}
-/*
- * Atomic ops with at least specified barriers.
- */
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG_ACQB 1
-static ETHR_INLINE long
-ethr_native_atomic32_read_acqb(ethr_native_atomic32_t *var)
+static ETHR_INLINE ethr_sint32_t
+ethr_native_atomic32_cmpxchg_acqb(ethr_native_atomic32_t *var,
+ ethr_sint32_t new,
+ ethr_sint32_t expected)
{
- long res = ethr_native_atomic32_read(var);
- ETHR_MEMORY_BARRIER;
- return res;
-}
+ ethr_sint32_t old;
-#define ethr_native_atomic32_set_relb ethr_native_atomic32_xchg
-#define ethr_native_atomic32_inc_return_acqb ethr_native_atomic32_inc_return
-#define ethr_native_atomic32_dec_relb ethr_native_atomic32_dec_return
-#define ethr_native_atomic32_dec_return_relb ethr_native_atomic32_dec_return
+ __asm__ __volatile__(
+ "1:\t"
+ "lwarx %0,0,%2\n\t"
+ "cmpw 0,%0,%3\n\t"
+ "bne 2f\n\t"
+ "stwcx. %1,0,%2\n\t"
+ "bne- 1b\n\t"
+ "isync\n"
+ "2:"
+ : "=&r"(old)
+ : "r"(new), "r"(&var->counter), "r"(expected)
+ : "cc", "memory");
-#define ethr_native_atomic32_cmpxchg_acqb ethr_native_atomic32_cmpxchg
-#define ethr_native_atomic32_cmpxchg_relb ethr_native_atomic32_cmpxchg
+ return old;
+}
#endif /* ETHR_TRY_INLINE_FUNCS */
diff --git a/erts/include/internal/ppc32/ethr_membar.h b/erts/include/internal/ppc32/ethr_membar.h
new file mode 100644
index 0000000000..ff5cc86bfb
--- /dev/null
+++ b/erts/include/internal/ppc32/ethr_membar.h
@@ -0,0 +1,63 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description: Memory barriers for PowerPC
+ * Author: Rickard Green
+ */
+
+#ifndef ETHR_PPC_MEMBAR_H__
+#define ETHR_PPC_MEMBAR_H__
+
+#define ETHR_LoadLoad (1 << 0)
+#define ETHR_LoadStore (1 << 1)
+#define ETHR_StoreLoad (1 << 2)
+#define ETHR_StoreStore (1 << 3)
+
+static __inline__ void
+ethr_lwsync__(void)
+{
+#ifdef ETHR_PPC_HAVE_NO_LWSYNC
+ __asm__ __volatile__ ("sync\n\t" : : : "memory");
+#else
+#ifndef ETHR_PPC_HAVE_LWSYNC
+ if (ETHR_PPC_RUNTIME_CONF_HAVE_NO_LWSYNC__)
+ __asm__ __volatile__ ("sync\n\t" : : : "memory");
+ else
+#endif
+ __asm__ __volatile__ ("lwsync\n\t" : : : "memory");
+#endif
+}
+
+static __inline__ void
+ethr_sync__(void)
+{
+ __asm__ __volatile__ ("sync\n\t" : : : "memory");
+}
+
+/*
+ * According to the "memory barrier intstructions" section of
+ * http://www.ibm.com/developerworks/systems/articles/powerpc.html
+ * we want to use sync when a StoreLoad is needed and lwsync for
+ * everything else.
+ */
+#define ETHR_MEMBAR(B) \
+ ETHR_CHOOSE_EXPR((B) & ETHR_StoreLoad, ethr_sync__(), ethr_lwsync__())
+
+#endif
diff --git a/erts/include/internal/ppc32/ethread.h b/erts/include/internal/ppc32/ethread.h
index 3b619e9d01..e41c83c5da 100644
--- a/erts/include/internal/ppc32/ethread.h
+++ b/erts/include/internal/ppc32/ethread.h
@@ -24,12 +24,9 @@
#ifndef ETHREAD_PPC32_ETHREAD_H
#define ETHREAD_PPC32_ETHREAD_H
+#include "ethr_membar.h"
#include "atomic.h"
#include "spinlock.h"
#include "rwlock.h"
-#define ETHR_HAVE_NATIVE_ATOMICS 1
-#define ETHR_HAVE_NATIVE_SPINLOCKS 1
-#define ETHR_HAVE_NATIVE_RWSPINLOCKS 1
-
#endif /* ETHREAD_PPC32_ETHREAD_H */
diff --git a/erts/include/internal/ppc32/rwlock.h b/erts/include/internal/ppc32/rwlock.h
index 19ec26ab68..311f000b69 100644
--- a/erts/include/internal/ppc32/rwlock.h
+++ b/erts/include/internal/ppc32/rwlock.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -23,12 +23,14 @@
*
* Based on the examples in Appendix E of Motorola's
* "Programming Environments Manual For 32-Bit Implementations
- * of the PowerPC Architecture". Uses eieio instead of sync
- * in the unlock sequence, as suggested in the manual.
+ * of the PowerPC Architecture".
*/
#ifndef ETHREAD_PPC_RWLOCK_H
#define ETHREAD_PPC_RWLOCK_H
+#define ETHR_HAVE_NATIVE_RWSPINLOCKS 1
+#define ETHR_NATIVE_RWSPINLOCK_IMPL "ethread"
+
/* Unlocked if zero, read-locked if negative, write-locked if +1. */
typedef struct {
volatile int lock;
@@ -47,9 +49,10 @@ ethr_native_read_unlock(ethr_native_rwlock_t *lock)
{
int tmp;
- /* this is eieio + ethr_native_atomic_inc() - isync */
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+
+ /* this is ethr_native_atomic_inc() - isync */
__asm__ __volatile__(
- "eieio\n\t"
"1:\t"
"lwarx %0,0,%1\n\t"
"addic %0,%0,1\n\t"
@@ -105,7 +108,7 @@ ethr_native_read_lock(ethr_native_rwlock_t *lock)
static ETHR_INLINE void
ethr_native_write_unlock(ethr_native_rwlock_t *lock)
{
- __asm__ __volatile__("eieio" : : : "memory");
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
lock->lock = 0;
}
diff --git a/erts/include/internal/ppc32/spinlock.h b/erts/include/internal/ppc32/spinlock.h
index c8460a3e8a..4c95ec9efb 100644
--- a/erts/include/internal/ppc32/spinlock.h
+++ b/erts/include/internal/ppc32/spinlock.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -23,12 +23,14 @@
*
* Based on the examples in Appendix E of Motorola's
* "Programming Environments Manual For 32-Bit Implementations
- * of the PowerPC Architecture". Uses eieio instead of sync
- * in the unlock sequence, as suggested in the manual.
+ * of the PowerPC Architecture".
*/
#ifndef ETHREAD_PPC_SPINLOCK_H
#define ETHREAD_PPC_SPINLOCK_H
+#define ETHR_HAVE_NATIVE_SPINLOCKS 1
+#define ETHR_NATIVE_SPINLOCK_IMPL "ethread"
+
/* Unlocked if zero, locked if non-zero. */
typedef struct {
volatile unsigned int lock;
@@ -45,7 +47,7 @@ ethr_native_spinlock_init(ethr_native_spinlock_t *lock)
static ETHR_INLINE void
ethr_native_spin_unlock(ethr_native_spinlock_t *lock)
{
- __asm__ __volatile__("eieio" : : : "memory");
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
lock->lock = 0;
}
diff --git a/erts/include/internal/pthread/ethr_event.h b/erts/include/internal/pthread/ethr_event.h
index 4c29b28536..d0a77990cc 100644
--- a/erts/include/internal/pthread/ethr_event.h
+++ b/erts/include/internal/pthread/ethr_event.h
@@ -21,7 +21,7 @@
* Author: Rickard Green
*/
-#if defined(ETHR_HAVE_LINUX_FUTEX) && defined(ETHR_HAVE_NATIVE_ATOMICS)
+#if defined(ETHR_HAVE_LINUX_FUTEX) && defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
/* --- Linux futex implementation of ethread events ------------------------- */
#define ETHR_LINUX_FUTEX_IMPL__
@@ -62,8 +62,7 @@ static void ETHR_INLINE
ETHR_INLINE_FUNC_NAME_(ethr_event_set)(ethr_event *e)
{
ethr_sint32_t val;
- ETHR_MEMORY_BARRIER;
- val = ethr_atomic32_xchg(&e->futex, ETHR_EVENT_ON__);
+ val = ethr_atomic32_xchg_mb(&e->futex, ETHR_EVENT_ON__);
if (val == ETHR_EVENT_OFF_WAITER__) {
int res = ETHR_FUTEX__(&e->futex, ETHR_FUTEX_WAKE__, 1);
if (res != 0)
@@ -99,8 +98,7 @@ static void ETHR_INLINE
ETHR_INLINE_FUNC_NAME_(ethr_event_set)(ethr_event *e)
{
ethr_sint32_t val;
- ETHR_MEMORY_BARRIER;
- val = ethr_atomic32_xchg(&e->state, ETHR_EVENT_ON__);
+ val = ethr_atomic32_xchg_mb(&e->state, ETHR_EVENT_ON__);
if (val == ETHR_EVENT_OFF_WAITER__) {
int res = pthread_mutex_lock(&e->mtx);
if (res != 0)
diff --git a/erts/include/internal/sparc32/atomic.h b/erts/include/internal/sparc32/atomic.h
index c297522ab1..fe1daaa9cf 100644
--- a/erts/include/internal/sparc32/atomic.h
+++ b/erts/include/internal/sparc32/atomic.h
@@ -35,23 +35,16 @@
#ifdef ETHR_INCLUDE_ATOMIC_IMPL__
-#ifndef ETHR_SPARC_V9_ATOMIC_COMMON__
-#define ETHR_SPARC_V9_ATOMIC_COMMON__
-
-#define ETHR_MEMORY_BARRIER \
- __asm__ __volatile__("membar #LoadLoad|#LoadStore|#StoreLoad|#StoreStore\n" \
- : : : "memory")
-
-#endif /* ETHR_SPARC_V9_ATOMIC_COMMON__ */
-
#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
#define ETHR_HAVE_NATIVE_ATOMIC32 1
+#define ETHR_NATIVE_ATOMIC32_IMPL "ethread"
#define ETHR_NATMC_FUNC__(X) ethr_native_atomic32_ ## X
#define ETHR_ATMC_T__ ethr_native_atomic32_t
#define ETHR_AINT_T__ ethr_sint32_t
#define ETHR_CAS__ "cas"
#elif ETHR_INCLUDE_ATOMIC_IMPL__ == 8
#define ETHR_HAVE_NATIVE_ATOMIC64 1
+#define ETHR_NATIVE_ATOMIC64_IMPL "ethread"
#define ETHR_NATMC_FUNC__(X) ethr_native_atomic64_ ## X
#define ETHR_ATMC_T__ ethr_native_atomic64_t
#define ETHR_AINT_T__ ethr_sint64_t
@@ -66,17 +59,23 @@ typedef struct {
#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_ATOMIC_IMPL__)
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADDR 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADDR 1
+#endif
+
static ETHR_INLINE ETHR_AINT_T__ *
ETHR_NATMC_FUNC__(addr)(ETHR_ATMC_T__ *var)
{
return (ETHR_AINT_T__ *) &var->counter;
}
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(init)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ i)
-{
- var->counter = i;
-}
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET 1
+#endif
static ETHR_INLINE void
ETHR_NATMC_FUNC__(set)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ i)
@@ -84,182 +83,49 @@ ETHR_NATMC_FUNC__(set)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ i)
var->counter = i;
}
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ 1
+#endif
+
static ETHR_INLINE ETHR_AINT_T__
ETHR_NATMC_FUNC__(read)(ETHR_ATMC_T__ *var)
{
return var->counter;
}
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(add_return)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ incr)
-{
- ETHR_AINT_T__ old, tmp;
-
- __asm__ __volatile__("membar #LoadLoad|#StoreLoad\n" : : : "memory");
- do {
- old = var->counter;
- tmp = old+incr;
- __asm__ __volatile__(
- ETHR_CAS__ " [%2], %1, %0"
- : "=&r"(tmp)
- : "r"(old), "r"(&var->counter), "0"(tmp)
- : "memory");
- } while (__builtin_expect(old != tmp, 0));
- __asm__ __volatile__("membar #StoreLoad|#StoreStore" : : : "memory");
- return old+incr;
-}
-
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(add)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ incr)
-{
- (void)ETHR_NATMC_FUNC__(add_return)(var, incr);
-}
-
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(inc_return)(ETHR_ATMC_T__ *var)
-{
- return ETHR_NATMC_FUNC__(add_return)(var, 1);
-}
-
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(inc)(ETHR_ATMC_T__ *var)
-{
- (void)ETHR_NATMC_FUNC__(add_return)(var, 1);
-}
-
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(dec_return)(ETHR_ATMC_T__ *var)
-{
- return ETHR_NATMC_FUNC__(add_return)(var, -1);
-}
-
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(dec)(ETHR_ATMC_T__ *var)
-{
- (void)ETHR_NATMC_FUNC__(add_return)(var, -1);
-}
-
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(and_retold)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ mask)
-{
- ETHR_AINT_T__ old, tmp;
-
- __asm__ __volatile__("membar #LoadLoad|#StoreLoad\n" : : : "memory");
- do {
- old = var->counter;
- tmp = old & mask;
- __asm__ __volatile__(
- ETHR_CAS__ " [%2], %1, %0"
- : "=&r"(tmp)
- : "r"(old), "r"(&var->counter), "0"(tmp)
- : "memory");
- } while (__builtin_expect(old != tmp, 0));
- __asm__ __volatile__("membar #StoreLoad|#StoreStore" : : : "memory");
- return old;
-}
-
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(or_retold)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ mask)
-{
- ETHR_AINT_T__ old, tmp;
-
- __asm__ __volatile__("membar #LoadLoad|#StoreLoad\n" : : : "memory");
- do {
- old = var->counter;
- tmp = old | mask;
- __asm__ __volatile__(
- ETHR_CAS__ " [%2], %1, %0"
- : "=&r"(tmp)
- : "r"(old), "r"(&var->counter), "0"(tmp)
- : "memory");
- } while (__builtin_expect(old != tmp, 0));
- __asm__ __volatile__("membar #StoreLoad|#StoreStore" : : : "memory");
- return old;
-}
-
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(xchg)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ val)
-{
- ETHR_AINT_T__ old, new;
-
- __asm__ __volatile__("membar #LoadLoad|#StoreLoad" : : : "memory");
- do {
- old = var->counter;
- new = val;
- __asm__ __volatile__(
- ETHR_CAS__ " [%2], %1, %0"
- : "=&r"(new)
- : "r"(old), "r"(&var->counter), "0"(new)
- : "memory");
- } while (__builtin_expect(old != new, 0));
- __asm__ __volatile__("membar #StoreLoad|#StoreStore" : : : "memory");
- return old;
-}
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG 1
+#endif
static ETHR_INLINE ETHR_AINT_T__
ETHR_NATMC_FUNC__(cmpxchg)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ new, ETHR_AINT_T__ old)
{
- __asm__ __volatile__("membar #LoadLoad|#StoreLoad\n" : : : "memory");
__asm__ __volatile__(
ETHR_CAS__ " [%2], %1, %0"
: "=&r"(new)
: "r"(old), "r"(&var->counter), "0"(new)
: "memory");
- __asm__ __volatile__("membar #StoreLoad|#StoreStore" : : : "memory");
return new;
}
-/*
- * Atomic ops with at least specified barriers.
- */
-
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(read_acqb)(ETHR_ATMC_T__ *var)
-{
- ETHR_AINT_T__ res = ETHR_NATMC_FUNC__(read)(var);
- __asm__ __volatile__("membar #LoadLoad|#LoadStore" : : : "memory");
- return res;
-}
-
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(set_relb)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ i)
-{
- __asm__ __volatile__("membar #LoadStore|#StoreStore" : : : "memory");
- ETHR_NATMC_FUNC__(set)(var, i);
-}
-
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(inc_return_acqb)(ETHR_ATMC_T__ *var)
-{
- ETHR_AINT_T__ res = ETHR_NATMC_FUNC__(inc_return)(var);
- return res;
-}
-
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(dec_relb)(ETHR_ATMC_T__ *var)
-{
- ETHR_NATMC_FUNC__(dec)(var);
-}
-
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(dec_return_relb)(ETHR_ATMC_T__ *var)
-{
- return ETHR_NATMC_FUNC__(dec_return)(var);
-}
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG_ACQB 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_ACQB 1
+#endif
static ETHR_INLINE ETHR_AINT_T__
ETHR_NATMC_FUNC__(cmpxchg_acqb)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ new, ETHR_AINT_T__ old)
{
ETHR_AINT_T__ res = ETHR_NATMC_FUNC__(cmpxchg)(var, new, old);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
return res;
}
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(cmpxchg_relb)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ new, ETHR_AINT_T__ old)
-{
- return ETHR_NATMC_FUNC__(cmpxchg)(var, new, old);
-}
-
#endif /* ETHR_TRY_INLINE_FUNCS */
#undef ETHR_NATMC_FUNC__
diff --git a/erts/include/internal/sparc32/ethr_membar.h b/erts/include/internal/sparc32/ethr_membar.h
new file mode 100644
index 0000000000..6eb0c5a1d6
--- /dev/null
+++ b/erts/include/internal/sparc32/ethr_membar.h
@@ -0,0 +1,115 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description: Memory barriers for sparc-v9
+ * Author: Rickard Green
+ */
+
+#ifndef ETHR_SPARC_V9_MEMBAR_H__
+#define ETHR_SPARC_V9_MEMBAR_H__
+
+#if defined(ETHR_SPARC_TSO)
+/* --- Total Store Order ------------------------------------------------ */
+
+#define ETHR_LoadLoad 0
+#define ETHR_LoadStore 0
+#define ETHR_StoreLoad 1
+#define ETHR_StoreStore 0
+
+static __inline__ void
+ethr_cb__(void)
+{
+ __asm__ __volatile__ ("" : : : "memory");
+}
+
+static __inline__ void
+ethr_StoreLoad__(void)
+{
+ __asm__ __volatile__ ("membar #StoreLoad\n\t" : : : "memory");
+}
+
+
+#define ETHR_MEMBAR(B) \
+ ETHR_CHOOSE_EXPR((B), ethr_StoreLoad__(), ethr_cb__())
+
+#elif defined(ETHR_SPARC_PSO)
+/* --- Partial Store Order ---------------------------------------------- */
+
+#define ETHR_LoadLoad 0
+#define ETHR_LoadStore 0
+#define ETHR_StoreLoad (1 << 0)
+#define ETHR_StoreStore (1 << 1)
+
+static __inline__ void
+ethr_cb__(void)
+{
+ __asm__ __volatile__ ("" : : : "memory");
+}
+
+static __inline__ void
+ethr_StoreLoad__(void)
+{
+ __asm__ __volatile__ ("membar #StoreLoad\n\t" : : : "memory");
+}
+
+static __inline__ void
+ethr_StoreStore__(void)
+{
+ __asm__ __volatile__ ("membar #StoreStore\n\t" : : : "memory");
+}
+
+static __inline__ void
+ethr_StoreLoad_StoreStore__(void)
+{
+ __asm__ __volatile__ ("membar #StoreLoad|StoreStore\n\t" : : : "memory");
+}
+
+#define ETHR_MEMBAR(B) \
+ ETHR_CHOOSE_EXPR( \
+ (B) == ETHR_StoreLoad, \
+ ethr_StoreLoad__(), \
+ ETHR_CHOOSE_EXPR( \
+ (B) == ETHR_StoreStore, \
+ ethr_StoreStore__(), \
+ ETHR_CHOOSE_EXPR( \
+ (B) == (ETHR_StoreLoad|ETHR_StoreStore), \
+ ethr_StoreLoad_StoreStore__(), \
+ ethr_cb__())))
+
+#elif defined(ETHR_SPARC_RMO)
+/* --- Relaxed Memory Order --------------------------------------------- */
+
+# define ETHR_LoadLoad #LoadLoad
+# define ETHR_LoadStore #LoadStore
+# define ETHR_StoreLoad #StoreLoad
+# define ETHR_StoreStore #StoreStore
+
+# define ETHR_MEMBAR_AUX__(B) \
+ __asm__ __volatile__("membar " #B "\n\t" : : : "memory")
+
+# define ETHR_MEMBAR(B) ETHR_MEMBAR_AUX__(B)
+
+#else
+
+# error "No memory order defined"
+
+#endif
+
+#endif
diff --git a/erts/include/internal/sparc32/ethread.h b/erts/include/internal/sparc32/ethread.h
index aea9794390..5ad92d3da7 100644
--- a/erts/include/internal/sparc32/ethread.h
+++ b/erts/include/internal/sparc32/ethread.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -24,6 +24,7 @@
#ifndef ETHREAD_SPARC32_ETHREAD_H
#define ETHREAD_SPARC32_ETHREAD_H
+#include "ethr_membar.h"
#define ETHR_ATOMIC_WANT_32BIT_IMPL__
#include "atomic.h"
#if ETHR_SIZEOF_PTR == 8
@@ -33,8 +34,4 @@
#include "spinlock.h"
#include "rwlock.h"
-#define ETHR_HAVE_NATIVE_ATOMICS 1
-#define ETHR_HAVE_NATIVE_SPINLOCKS 1
-#define ETHR_HAVE_NATIVE_RWSPINLOCKS 1
-
#endif /* ETHREAD_SPARC32_ETHREAD_H */
diff --git a/erts/include/internal/sparc32/rwlock.h b/erts/include/internal/sparc32/rwlock.h
index 465ec96866..8b6f2e9c57 100644
--- a/erts/include/internal/sparc32/rwlock.h
+++ b/erts/include/internal/sparc32/rwlock.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -24,6 +24,9 @@
#ifndef ETHREAD_SPARC32_RWLOCK_H
#define ETHREAD_SPARC32_RWLOCK_H
+#define ETHR_HAVE_NATIVE_RWSPINLOCKS 1
+#define ETHR_NATIVE_RWSPINLOCK_IMPL "ethread"
+
/* Unlocked if zero, read-locked if positive, write-locked if -1. */
typedef struct {
volatile int lock;
@@ -42,7 +45,7 @@ ethr_native_read_unlock(ethr_native_rwlock_t *lock)
{
unsigned int old, new;
- __asm__ __volatile__("membar #LoadLoad|#StoreLoad");
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
do {
old = lock->lock;
new = old-1;
@@ -70,7 +73,7 @@ ethr_native_read_trylock(ethr_native_rwlock_t *lock)
: "r"(old), "r"(&lock->lock), "0"(new)
: "memory");
} while (__builtin_expect(old != new, 0));
- __asm__ __volatile__("membar #StoreLoad|#StoreStore");
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
return 1;
}
@@ -87,7 +90,7 @@ ethr_native_read_lock(ethr_native_rwlock_t *lock)
if (__builtin_expect(ethr_native_read_trylock(lock) != 0, 1))
break;
do {
- __asm__ __volatile__("membar #LoadLoad");
+ ETHR_MEMBAR(ETHR_LoadLoad);
} while (ethr_native_read_is_locked(lock));
}
}
@@ -95,7 +98,7 @@ ethr_native_read_lock(ethr_native_rwlock_t *lock)
static ETHR_INLINE void
ethr_native_write_unlock(ethr_native_rwlock_t *lock)
{
- __asm__ __volatile__("membar #LoadStore|#StoreStore");
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
lock->lock = 0;
}
@@ -115,7 +118,7 @@ ethr_native_write_trylock(ethr_native_rwlock_t *lock)
: "r"(old), "r"(&lock->lock), "0"(new)
: "memory");
} while (__builtin_expect(old != new, 0));
- __asm__ __volatile__("membar #StoreLoad|#StoreStore");
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
return 1;
}
@@ -132,7 +135,7 @@ ethr_native_write_lock(ethr_native_rwlock_t *lock)
if (__builtin_expect(ethr_native_write_trylock(lock) != 0, 1))
break;
do {
- __asm__ __volatile__("membar #LoadLoad");
+ ETHR_MEMBAR(ETHR_LoadLoad);
} while (ethr_native_write_is_locked(lock));
}
}
diff --git a/erts/include/internal/sparc32/spinlock.h b/erts/include/internal/sparc32/spinlock.h
index 493d514210..d4e36e09cf 100644
--- a/erts/include/internal/sparc32/spinlock.h
+++ b/erts/include/internal/sparc32/spinlock.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -24,6 +24,9 @@
#ifndef ETHR_SPARC32_SPINLOCK_H
#define ETHR_SPARC32_SPINLOCK_H
+#define ETHR_HAVE_NATIVE_SPINLOCKS 1
+#define ETHR_NATIVE_SPINLOCK_IMPL "ethread"
+
/* Locked with ldstub, so unlocked when 0 and locked when non-zero. */
typedef struct {
volatile unsigned char lock;
@@ -40,7 +43,7 @@ ethr_native_spinlock_init(ethr_native_spinlock_t *lock)
static ETHR_INLINE void
ethr_native_spin_unlock(ethr_native_spinlock_t *lock)
{
- __asm__ __volatile__("membar #LoadStore|#StoreStore");
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
lock->lock = 0;
}
@@ -51,10 +54,10 @@ ethr_native_spin_trylock(ethr_native_spinlock_t *lock)
__asm__ __volatile__(
"ldstub [%1], %0\n\t"
- "membar #StoreLoad|#StoreStore"
: "=r"(prev)
: "r"(&lock->lock)
: "memory");
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
return prev == 0;
}
@@ -71,7 +74,7 @@ ethr_native_spin_lock(ethr_native_spinlock_t *lock)
if (__builtin_expect(ethr_native_spin_trylock(lock) != 0, 1))
break;
do {
- __asm__ __volatile__("membar #LoadLoad");
+ ETHR_MEMBAR(ETHR_LoadLoad);
} while (ethr_native_spin_is_locked(lock));
}
}
diff --git a/erts/include/internal/tile/atomic.h b/erts/include/internal/tile/atomic.h
index 5697afda25..1f1553c346 100644
--- a/erts/include/internal/tile/atomic.h
+++ b/erts/include/internal/tile/atomic.h
@@ -25,6 +25,7 @@
#define ETHREAD_TILE_ATOMIC_H
#define ETHR_HAVE_NATIVE_ATOMIC32 1
+#define ETHR_NATIVE_ATOMIC32_IMPL "tilera"
#include <atomic.h>
@@ -34,27 +35,25 @@ typedef struct {
volatile ethr_sint32_t counter;
} ethr_native_atomic32_t;
-#define ETHR_MEMORY_BARRIER __insn_mf()
-
#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_ATOMIC_IMPL__)
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADDR 1
+
static ETHR_INLINE ethr_sint32_t *
ethr_native_atomic32_addr(ethr_native_atomic32_t *var)
{
return (ethr_sint32_t *) &var->counter;
}
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INIT 1
+
static ETHR_INLINE void
ethr_native_atomic32_init(ethr_native_atomic32_t *var, ethr_sint32_t i)
{
var->counter = i;
}
-static ETHR_INLINE void
-ethr_native_atomic32_set(ethr_native_atomic32_t *var, ethr_sint32_t i)
-{
- atomic_exchange_acq(&var->counter, i);
-}
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ 1
static ETHR_INLINE ethr_sint32_t
ethr_native_atomic32_read(ethr_native_atomic32_t *var)
@@ -62,139 +61,80 @@ ethr_native_atomic32_read(ethr_native_atomic32_t *var)
return var->counter;
}
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ_ACQB 1
+
+static ETHR_INLINE ethr_sint32_t
+ethr_native_atomic32_read_acqb(ethr_native_atomic32_t *var)
+{
+ return atomic_compare_and_exchange_val_acq(&var->counter,
+ 0x81818181,
+ 0x81818181);
+}
+
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD 1
+
static ETHR_INLINE void
ethr_native_atomic32_add(ethr_native_atomic32_t *var, ethr_sint32_t incr)
{
- ETHR_MEMORY_BARRIER;
atomic_add(&var->counter, incr);
- ETHR_MEMORY_BARRIER;
-}
-
+}
+
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC 1
+
static ETHR_INLINE void
ethr_native_atomic32_inc(ethr_native_atomic32_t *var)
{
- ETHR_MEMORY_BARRIER;
atomic_increment(&var->counter);
- ETHR_MEMORY_BARRIER;
}
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC 1
+
static ETHR_INLINE void
ethr_native_atomic32_dec(ethr_native_atomic32_t *var)
{
- ETHR_MEMORY_BARRIER;
atomic_decrement(&var->counter);
- ETHR_MEMORY_BARRIER;
}
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RETURN 1
+
static ETHR_INLINE ethr_sint32_t
ethr_native_atomic32_add_return(ethr_native_atomic32_t *var, ethr_sint32_t incr)
{
- ethr_sint32_t res;
- ETHR_MEMORY_BARRIER;
- res = atomic_exchange_and_add(&var->counter, incr) + incr;
- ETHR_MEMORY_BARRIER;
- return res;
+ return atomic_exchange_and_add(&var->counter, incr) + incr;
}
-static ETHR_INLINE ethr_sint32_t
-ethr_native_atomic32_inc_return(ethr_native_atomic32_t *var)
-{
- return ethr_native_atomic32_add_return(var, 1);
-}
-
-static ETHR_INLINE ethr_sint32_t
-ethr_native_atomic32_dec_return(ethr_native_atomic32_t *var)
-{
- return ethr_native_atomic32_add_return(var, -1);
-}
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_AND_RETOLD 1
static ETHR_INLINE ethr_sint32_t
ethr_native_atomic32_and_retold(ethr_native_atomic32_t *var, ethr_sint32_t mask)
{
- ethr_sint32_t res;
- ETHR_MEMORY_BARRIER;
- res = atomic_and_val(&var->counter, mask);
- ETHR_MEMORY_BARRIER;
- return res;
+ return atomic_and_val(&var->counter, mask);
}
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_OR_RETOLD 1
+
static ETHR_INLINE ethr_sint32_t
ethr_native_atomic32_or_retold(ethr_native_atomic32_t *var, ethr_sint32_t mask)
{
- ethr_sint32_t res;
- ETHR_MEMORY_BARRIER;
- res = atomic_or_val(&var->counter, mask);
- ETHR_MEMORY_BARRIER;
- return res;
+ return atomic_or_val(&var->counter, mask);
}
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_XCHG_ACQB 1
+
static ETHR_INLINE ethr_sint32_t
-ethr_native_atomic32_xchg(ethr_native_atomic32_t *var, ethr_sint32_t val)
+ethr_native_atomic32_xchg_acqb(ethr_native_atomic32_t *var, ethr_sint32_t val)
{
- ETHR_MEMORY_BARRIER;
return atomic_exchange_acq(&var->counter, val);
}
-static ETHR_INLINE ethr_sint32_t
-ethr_native_atomic32_cmpxchg(ethr_native_atomic32_t *var,
- ethr_sint32_t new,
- ethr_sint32_t expected)
-{
- ETHR_MEMORY_BARRIER;
- return atomic_compare_and_exchange_val_acq(&var->counter, new, expected);
-}
-
-/*
- * Atomic ops with at least specified barriers.
- */
-
-static ETHR_INLINE ethr_sint32_t
-ethr_native_atomic32_read_acqb(ethr_native_atomic32_t *var)
-{
- ethr_sint32_t res = ethr_native_atomic32_read(var);
- ETHR_MEMORY_BARRIER;
- return res;
-}
-
-static ETHR_INLINE ethr_sint32_t
-ethr_native_atomic32_inc_return_acqb(ethr_native_atomic32_t *var)
-{
- return ethr_native_atomic32_inc_return(var);
-}
-
-static ETHR_INLINE void
-ethr_native_atomic32_set_relb(ethr_native_atomic32_t *var, ethr_sint32_t val)
-{
- ETHR_MEMORY_BARRIER;
- ethr_native_atomic32_set(var, val);
-}
-
-static ETHR_INLINE void
-ethr_native_atomic32_dec_relb(ethr_native_atomic32_t *var)
-{
- ethr_native_atomic32_dec(var);
-}
-
-static ETHR_INLINE ethr_sint32_t
-ethr_native_atomic32_dec_return_relb(ethr_native_atomic32_t *var)
-{
- return ethr_native_atomic32_dec_return(var);
-}
+#define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG_ACQB 1
static ETHR_INLINE ethr_sint32_t
ethr_native_atomic32_cmpxchg_acqb(ethr_native_atomic32_t *var,
ethr_sint32_t new,
- ethr_sint32_t exp)
+ ethr_sint32_t expected)
{
- return ethr_native_atomic32_cmpxchg(var, new, exp);
-}
-
-static ETHR_INLINE ethr_sint32_t
-ethr_native_atomic32_cmpxchg_relb(ethr_native_atomic32_t *var,
- ethr_sint32_t new,
- ethr_sint32_t exp)
-{
- return ethr_native_atomic32_cmpxchg(var, new, exp);
+ return atomic_compare_and_exchange_val_acq(&var->counter, new, expected);
}
#endif /* ETHR_TRY_INLINE_FUNCS */
diff --git a/lib/ssl/c_src/esock_winsock.h b/erts/include/internal/tile/ethr_membar.h
index 069782a18d..7cb4f3cf9a 100644
--- a/lib/ssl/c_src/esock_winsock.h
+++ b/erts/include/internal/tile/ethr_membar.h
@@ -1,8 +1,8 @@
-/*<copyright>
- * <year>2003-2008</year>
- * <holder>Ericsson AB, All Rights Reserved</holder>
- *</copyright>
- *<legalnotice>
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2011. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
@@ -14,23 +14,22 @@
* the License for the specific language governing rights and limitations
* under the License.
*
- * The Initial Developer of the Original Code is Ericsson AB.
- *</legalnotice>
+ * %CopyrightEnd%
*/
+
/*
- * Purpose: Control winsock version and setting of FD_SETSIZE.
- *
+ * Description: Memory barriers for TILE64/TILEPro
+ * Author: Rickard Green
*/
-/* Maybe set FD_SETSIZE */
+#ifndef ETHR_TILE_MEMBAR_H__
+#define ETHR_TILE_MEMBAR_H__
-#ifdef ESOCK_WINSOCK2
-#include <winsock2.h>
-#else
-#include <winsock.h>
-/* These are defined in winsock2.h but not in winsock.h */
-#define SD_RECEIVE 0x00
-#define SD_SEND 0x01
-#define SD_BOTH 0x02
-#endif
+#define ETHR_LoadLoad (1 << 0)
+#define ETHR_LoadStore (1 << 1)
+#define ETHR_StoreLoad (1 << 2)
+#define ETHR_StoreStore (1 << 3)
+#define ETHR_MEMBAR(B) __insn_mf()
+
+#endif
diff --git a/erts/include/internal/tile/ethread.h b/erts/include/internal/tile/ethread.h
index 2de4d42bc6..7f579b50e7 100644
--- a/erts/include/internal/tile/ethread.h
+++ b/erts/include/internal/tile/ethread.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2009. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -23,8 +23,7 @@
#ifndef ETHREAD_TILE_ETHREAD_H
#define ETHREAD_TILE_ETHREAD_H
+#include "ethr_membar.h"
#include "atomic.h"
-#define ETHR_HAVE_NATIVE_ATOMICS 1
-
#endif /* ETHREAD_TILE_ETHREAD_H */
diff --git a/erts/include/internal/win/ethr_atomic.h b/erts/include/internal/win/ethr_atomic.h
index 60def01a7e..e11f1abf47 100644
--- a/erts/include/internal/win/ethr_atomic.h
+++ b/erts/include/internal/win/ethr_atomic.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -24,364 +24,408 @@
#undef ETHR_INCLUDE_ATOMIC_IMPL__
#if !defined(ETHR_WIN_ATOMIC32_H__) && defined(ETHR_ATOMIC_WANT_32BIT_IMPL__)
-#define ETHR_WIN_ATOMIC32_H__
-#define ETHR_INCLUDE_ATOMIC_IMPL__ 4
-#undef ETHR_ATOMIC_WANT_32BIT_IMPL__
+# define ETHR_WIN_ATOMIC32_H__
+# if (defined(ETHR_MEMBAR) \
+ && defined(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE) \
+ && defined(ETHR_HAVE__INTERLOCKEDEXCHANGE))
+# define ETHR_INCLUDE_ATOMIC_IMPL__ 4
+# endif
+# undef ETHR_ATOMIC_WANT_32BIT_IMPL__
#elif !defined(ETHR_WIN_ATOMIC64_H__) && defined(ETHR_ATOMIC_WANT_64BIT_IMPL__)
-#define ETHR_WIN_ATOMIC64_H__
-#ifdef ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64
-/* _InterlockedCompareExchange64() required... */
-#define ETHR_INCLUDE_ATOMIC_IMPL__ 8
+# define ETHR_WIN_ATOMIC64_H__
+# if (defined(ETHR_MEMBAR) \
+ && (defined(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64) \
+ || defined(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_ACQ) \
+ || defined(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_REL)))
+# define ETHR_INCLUDE_ATOMIC_IMPL__ 8
+# endif
+# undef ETHR_ATOMIC_WANT_64BIT_IMPL__
#endif
-#undef ETHR_ATOMIC_WANT_64BIT_IMPL__
+
+#if !defined(_MSC_VER) || _MSC_VER < 1400
+# undef ETHR_INCLUDE_ATOMIC_IMPL__
#endif
#ifdef ETHR_INCLUDE_ATOMIC_IMPL__
-#if defined(_MSC_VER) && _MSC_VER >= 1400
+# ifndef ETHR_WIN_ATOMIC_COMMON__
+# define ETHR_WIN_ATOMIC_COMMON__
+
+# if defined(_M_IX86) || defined(_M_AMD64) || defined(_M_IA64)
+# define ETHR_READ_AND_SET_WITHOUT_INTERLOCKED_OP__ 1
+# else
+# define ETHR_READ_AND_SET_WITHOUT_INTERLOCKED_OP__ 0
+# endif
+
+# endif /* ETHR_WIN_ATOMIC_COMMON__ */
+
+# if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+
+# define ETHR_HAVE_NATIVE_ATOMIC32 1
+# define ETHR_NATIVE_ATOMIC32_IMPL "windows-interlocked"
+
+# ifdef ETHR_HAVE__INTERLOCKEDDECREMENT
+# define ETHR_WIN_HAVE_DEC
+# pragma intrinsic(_InterlockedDecrement)
+# endif
+# ifdef ETHR_HAVE__INTERLOCKEDDECREMENT_REL
+# define ETHR_WIN_HAVE_DEC_REL
+# pragma intrinsic(_InterlockedDecrement_rel)
+# endif
+# ifdef ETHR_HAVE__INTERLOCKEDINCREMENT
+# define ETHR_WIN_HAVE_INC
+# pragma intrinsic(_InterlockedIncrement)
+# endif
+# ifdef ETHR_HAVE__INTERLOCKEDINCREMENT_ACQ
+# define ETHR_WIN_HAVE_INC_ACQ
+# pragma intrinsic(_InterlockedIncrement_acq)
+# endif
+# ifdef ETHR_HAVE__INTERLOCKEDEXCHANGEADD
+# define ETHR_WIN_HAVE_XCHG_ADD
+# pragma intrinsic(_InterlockedExchangeAdd)
+# endif
+# ifdef ETHR_HAVE__INTERLOCKEDEXCHANGEADD_ACQ
+# define ETHR_WIN_HAVE_XCHG_ADD_ACQ
+# pragma intrinsic(_InterlockedExchangeAdd_acq)
+# endif
+# ifdef ETHR_HAVE__INTERLOCKEDEXCHANGE
+# define ETHR_WIN_HAVE_XCHG
+# pragma intrinsic(_InterlockedExchange)
+# endif
+# ifdef ETHR_HAVE__INTERLOCKEDAND
+# define ETHR_WIN_HAVE_AND
+# pragma intrinsic(_InterlockedAnd)
+# endif
+# ifdef ETHR_HAVE__INTERLOCKEDOR
+# define ETHR_WIN_HAVE_OR
+# pragma intrinsic(_InterlockedOr)
+# endif
+# ifdef ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE
+# define ETHR_WIN_HAVE_CMPXCHG
+# pragma intrinsic(_InterlockedCompareExchange)
+# endif
+# ifdef ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_ACQ
+# define ETHR_WIN_HAVE_CMPXCHG_ACQ
+# pragma intrinsic(_InterlockedCompareExchange_acq)
+# endif
+# ifdef ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_REL
+# define ETHR_WIN_HAVE_CMPXCHG_REL
+# pragma intrinsic(_InterlockedCompareExchange_rel)
+# endif
+
+# define ETHR_ILCKD__(X) _Interlocked ## X
+# define ETHR_ILCKD_ACQ__(X) _Interlocked ## X ## _acq
+# define ETHR_ILCKD_REL__(X) _Interlocked ## X ## _rel
+
+# define ETHR_NATMC_FUNC__(X) ethr_native_atomic32_ ## X
+# define ETHR_ATMC_T__ ethr_native_atomic32_t
+# define ETHR_AINT_T__ ethr_sint32_t
+
+# elif ETHR_INCLUDE_ATOMIC_IMPL__ == 8
+
+# define ETHR_HAVE_NATIVE_ATOMIC64 1
+# define ETHR_NATIVE_ATOMIC64_IMPL "windows-interlocked"
+
+# ifdef ETHR_HAVE__INTERLOCKEDDECREMENT64
+# define ETHR_WIN_HAVE_DEC
+# pragma intrinsic(_InterlockedDecrement64)
+# endif
+# ifdef ETHR_HAVE__INTERLOCKEDDECREMENT64_REL
+# define ETHR_WIN_HAVE_DEC_REL
+# pragma intrinsic(_InterlockedDecrement64_rel)
+# endif
+# ifdef ETHR_HAVE__INTERLOCKEDINCREMENT64_ACQ
+# define ETHR_WIN_HAVE_INC_ACQ
+# pragma intrinsic(_InterlockedIncrement64_acq)
+# endif
+# ifdef ETHR_HAVE__INTERLOCKEDINCREMENT64
+# define ETHR_WIN_HAVE_INC
+# pragma intrinsic(_InterlockedIncrement64)
+# endif
+# ifdef ETHR_HAVE__INTERLOCKEDEXCHANGEADD64
+# define ETHR_WIN_HAVE_XCHG_ADD
+# pragma intrinsic(_InterlockedExchangeAdd64)
+# endif
+# ifdef ETHR_HAVE__INTERLOCKEDEXCHANGEADD64_ACQ
+# define ETHR_WIN_HAVE_XCHG_ADD_ACQ
+# pragma intrinsic(_InterlockedExchangeAdd64_acq)
+# endif
+# ifdef ETHR_HAVE__INTERLOCKEDEXCHANGE64
+# define ETHR_WIN_HAVE_XCHG
+# pragma intrinsic(_InterlockedExchange64)
+# endif
+# ifdef ETHR_HAVE__INTERLOCKEDAND64
+# define ETHR_WIN_HAVE_AND
+# pragma intrinsic(_InterlockedAnd64)
+# endif
+# ifdef ETHR_HAVE__INTERLOCKEDOR64
+# define ETHR_WIN_HAVE_OR
+# pragma intrinsic(_InterlockedOr64)
+# endif
+# ifdef ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64
+# define ETHR_WIN_HAVE_CMPXCHG
+# pragma intrinsic(_InterlockedCompareExchange64)
+# endif
+# ifdef ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_ACQ
+# define ETHR_WIN_HAVE_CMPXCHG_ACQ
+# pragma intrinsic(_InterlockedCompareExchange64_acq)
+# endif
+# ifdef ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_REL
+# define ETHR_WIN_HAVE_CMPXCHG_REL
+# pragma intrinsic(_InterlockedCompareExchange64_rel)
+# endif
+
+# define ETHR_ILCKD__(X) _Interlocked ## X ## 64
+# define ETHR_ILCKD_ACQ__(X) _Interlocked ## X ## 64_acq
+# define ETHR_ILCKD_REL__(X) _Interlocked ## X ## 64_rel
+
+# define ETHR_NATMC_FUNC__(X) ethr_native_atomic64_ ## X
+# define ETHR_ATMC_T__ ethr_native_atomic64_t
+# define ETHR_AINT_T__ ethr_sint64_t
+
+# else
+# error "Unsupported integer size"
+# endif
-#ifndef ETHR_WIN_ATOMIC_COMMON__
-#define ETHR_WIN_ATOMIC_COMMON__
+typedef struct {
+ volatile ETHR_AINT_T__ value;
+} ETHR_ATMC_T__;
-#define ETHR_HAVE_NATIVE_ATOMICS 1
+#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_ATOMIC_IMPL__)
-#if defined(_M_IX86) || defined(_M_AMD64) || defined(_M_IA64)
-# define ETHR_READ_AND_SET_WITHOUT_INTERLOCKED_OP__ 1
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADDR 1
#else
-# define ETHR_READ_AND_SET_WITHOUT_INTERLOCKED_OP__ 0
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADDR 1
#endif
-#if defined(_M_AMD64) || (defined(_M_IX86) \
- && !defined(ETHR_PRE_PENTIUM4_COMPAT))
-# define ETHR_READ_ACQB_AND_SET_RELB_COMPILER_BARRIER_ONLY__ 1
-#else
-# define ETHR_READ_ACQB_AND_SET_RELB_COMPILER_BARRIER_ONLY__ 0
-#endif
-/*
- * No configure test checking for interlocked acquire/release
- * versions have been written, yet. It should define
- * ETHR_HAVE_INTERLOCKED_ACQUIRE_RELEASE_BARRIERS if, and
- * only if, all used interlocked operations with barriers
- * exists.
- *
- * Note, that these are pure optimizations for the itanium
- * processor.
- */
+static ETHR_INLINE ETHR_AINT_T__ *
+ETHR_NATMC_FUNC__(addr)(ETHR_ATMC_T__ *var)
+{
+ return (ETHR_AINT_T__ *) &var->value;
+}
-#include <intrin.h>
-#undef ETHR_COMPILER_BARRIER
-#define ETHR_COMPILER_BARRIER _ReadWriteBarrier()
-#pragma intrinsic(_ReadWriteBarrier)
-#pragma intrinsic(_InterlockedCompareExchange)
-
-#if defined(_M_AMD64) || (defined(_M_IX86) \
- && !defined(ETHR_PRE_PENTIUM4_COMPAT))
-#include <emmintrin.h>
-#include <mmintrin.h>
-#pragma intrinsic(_mm_mfence)
-#define ETHR_MEMORY_BARRIER _mm_mfence()
-#pragma intrinsic(_mm_sfence)
-#define ETHR_WRITE_MEMORY_BARRIER _mm_sfence()
-#pragma intrinsic(_mm_lfence)
-#define ETHR_READ_MEMORY_BARRIER _mm_lfence()
-#define ETHR_READ_DEPEND_MEMORY_BARRIER ETHR_COMPILER_BARRIER
+#if ETHR_READ_AND_SET_WITHOUT_INTERLOCKED_OP__
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET 1
#else
-
-#define ETHR_MEMORY_BARRIER \
-do { \
- volatile long x___ = 0; \
- _InterlockedCompareExchange(&x___, (long) 1, (long) 0); \
-} while (0)
-
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET 1
#endif
-#endif /* ETHR_WIN_ATOMIC_COMMON__ */
+static ETHR_INLINE void
+ETHR_NATMC_FUNC__(set)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ i)
+{
+ var->value = i;
+}
#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET_RELB 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET_RELB 1
+#endif
-#define ETHR_HAVE_NATIVE_ATOMIC32 1
+static ETHR_INLINE void
+ETHR_NATMC_FUNC__(set_relb)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ i)
+{
+#if defined(_M_IX86)
+ if (ETHR_X86_RUNTIME_CONF_HAVE_NO_SSE2__)
+ (void) ETHR_ILCKD__(Exchange)(&var->value, i);
+ else
+#endif /* _M_IX86 */
+ {
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ var->value = i;
+ }
+}
-/*
- * All used operations available as 32-bit intrinsics
- */
+#endif /* ETHR_READ_AND_SET_WITHOUT_INTERLOCKED_OP__ */
-#pragma intrinsic(_InterlockedDecrement)
-#pragma intrinsic(_InterlockedIncrement)
-#pragma intrinsic(_InterlockedExchangeAdd)
-#pragma intrinsic(_InterlockedExchange)
-#pragma intrinsic(_InterlockedAnd)
-#pragma intrinsic(_InterlockedOr)
-#ifdef ETHR_HAVE_INTERLOCKED_ACQUIRE_RELEASE_BARRIERS
-#pragma intrinsic(_InterlockedExchangeAdd_acq)
-#pragma intrinsic(_InterlockedIncrement_acq)
-#pragma intrinsic(_InterlockedDecrement_rel)
-#pragma intrinsic(_InterlockedCompareExchange_acq)
-#pragma intrinsic(_InterlockedCompareExchange_rel)
-#endif
+#if defined(ETHR_WIN_HAVE_XCHG)
-#define ETHR_ILCKD__(X) _Interlocked ## X
-#ifdef ETHR_HAVE_INTERLOCKED_ACQUIRE_RELEASE_BARRIERS
-#define ETHR_ILCKD_ACQ__(X) _Interlocked ## X ## _acq
-#define ETHR_ILCKD_REL__(X) _Interlocked ## X ## _rel
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET_MB 1
#else
-#define ETHR_ILCKD_ACQ__(X) _Interlocked ## X
-#define ETHR_ILCKD_REL__(X) _Interlocked ## X
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET_MB 1
#endif
-#define ETHR_NATMC_FUNC__(X) ethr_native_atomic32_ ## X
-#define ETHR_ATMC_T__ ethr_native_atomic32_t
-#define ETHR_AINT_T__ ethr_sint32_t
-
-#elif ETHR_INCLUDE_ATOMIC_IMPL__ == 8
+static ETHR_INLINE void
+ETHR_NATMC_FUNC__(set_mb)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ i)
+{
+ (void) ETHR_ILCKD__(Exchange)(&var->value, i);
+}
-#define ETHR_HAVE_NATIVE_ATOMIC64 1
+#endif
-/*
- * _InterlockedCompareExchange64() is required. The other may not
- * be available, but if so, we can generate them.
- */
-#pragma intrinsic(_InterlockedCompareExchange64)
+#if ETHR_READ_AND_SET_WITHOUT_INTERLOCKED_OP__
-#if ETHR_READ_AND_SET_WITHOUT_INTERLOCKED_OP__
-#define ETHR_OWN_ILCKD_INIT_VAL__(PTR) *(PTR)
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ 1
#else
-#define ETHR_OWN_ILCKD_INIT_VAL__(PTR) (__int64) 0
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ 1
#endif
-#define ETHR_OWN_ILCKD_BODY_IMPL__(FUNC, PTR, NEW, ACT, EXP, OPS, RET) \
-{ \
- __int64 NEW, ACT, EXP; \
- ACT = ETHR_OWN_ILCKD_INIT_VAL__(PTR); \
- do { \
- EXP = ACT; \
- { OPS; } \
- ACT = _InterlockedCompareExchange64(PTR, NEW, EXP); \
- } while (ACT != EXP); \
- return RET; \
+static ETHR_INLINE ETHR_AINT_T__
+ETHR_NATMC_FUNC__(read)(ETHR_ATMC_T__ *var)
+{
+ return var->value;
}
-#define ETHR_OWN_ILCKD_1_IMPL__(FUNC, NEW, ACT, EXP, OPS, RET) \
-static __forceinline __int64 \
-FUNC(__int64 volatile *ptr) \
-ETHR_OWN_ILCKD_BODY_IMPL__(FUNC, ptr, NEW, ACT, EXP, OPS, RET)
-
-#define ETHR_OWN_ILCKD_2_IMPL__(FUNC, NEW, ACT, EXP, OPS, ARG, RET) \
-static __forceinline __int64 \
-FUNC(__int64 volatile *ptr, __int64 ARG) \
-ETHR_OWN_ILCKD_BODY_IMPL__(FUNC, ptr, NEW, ACT, EXP, OPS, RET)
+#endif /* ETHR_READ_AND_SET_WITHOUT_INTERLOCKED_OP__ */
+#if defined(ETHR_WIN_HAVE_XCHG_ADD)
-#ifdef ETHR_HAVE__INTERLOCKEDDECREMENT64
-#pragma intrinsic(_InterlockedDecrement64)
-#else
-ETHR_OWN_ILCKD_1_IMPL__(_InterlockedDecrement64, new, act, exp,
- new = act - 1, new)
-#endif
-#ifdef ETHR_HAVE__INTERLOCKEDINCREMENT64
-#pragma intrinsic(_InterlockedIncrement64)
-#else
-ETHR_OWN_ILCKD_1_IMPL__(_InterlockedIncrement64, new, act, exp,
- new = act + 1, new)
-#endif
-#ifdef ETHR_HAVE__INTERLOCKEDEXCHANGEADD64
-#pragma intrinsic(_InterlockedExchangeAdd64)
-#else
-ETHR_OWN_ILCKD_2_IMPL__(_InterlockedExchangeAdd64, new, act, exp,
- new = act + arg, arg, act)
-#endif
-#ifdef ETHR_HAVE__INTERLOCKEDEXCHANGE64
-#pragma intrinsic(_InterlockedExchange64)
-#else
-ETHR_OWN_ILCKD_2_IMPL__(_InterlockedExchange64, new, act, exp,
- new = arg, arg, act)
-#endif
-#ifdef ETHR_HAVE__INTERLOCKEDAND64
-#pragma intrinsic(_InterlockedAnd64)
-#else
-ETHR_OWN_ILCKD_2_IMPL__(_InterlockedAnd64, new, act, exp,
- new = act & arg, arg, act)
-#endif
-#ifdef ETHR_HAVE__INTERLOCKEDOR64
-#pragma intrinsic(_InterlockedOr64)
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RETURN_MB 1
#else
-ETHR_OWN_ILCKD_2_IMPL__(_InterlockedOr64, new, act, exp,
- new = act | arg, arg, act)
-#endif
-#ifdef ETHR_HAVE_INTERLOCKED_ACQUIRE_RELEASE_BARRIERS
-#pragma intrinsic(_InterlockedExchangeAdd64_acq)
-#pragma intrinsic(_InterlockedIncrement64_acq)
-#pragma intrinsic(_InterlockedDecrement64_rel)
-#pragma intrinsic(_InterlockedCompareExchange64_acq)
-#pragma intrinsic(_InterlockedCompareExchange64_rel)
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RETURN_MB 1
#endif
-#define ETHR_ILCKD__(X) _Interlocked ## X ## 64
-#ifdef ETHR_HAVE_INTERLOCKED_ACQUIRE_RELEASE_BARRIERS
-#define ETHR_ILCKD_ACQ__(X) _Interlocked ## X ## 64_acq
-#define ETHR_ILCKD_REL__(X) _Interlocked ## X ## 64_rel
-#else
-#define ETHR_ILCKD_ACQ__(X) _Interlocked ## X ## 64
-#define ETHR_ILCKD_REL__(X) _Interlocked ## X ## 64
+static ETHR_INLINE ETHR_AINT_T__
+ETHR_NATMC_FUNC__(add_return_mb)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ i)
+{
+ return ETHR_ILCKD__(ExchangeAdd)(&var->value, i) + i;
+}
+
#endif
-#define ETHR_NATMC_FUNC__(X) ethr_native_atomic64_ ## X
-#define ETHR_ATMC_T__ ethr_native_atomic64_t
-#define ETHR_AINT_T__ ethr_sint64_t
+#if defined(ETHR_WIN_HAVE_INC)
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RETURN_MB 1
#else
-#error "Unsupported integer size"
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RETURN_MB 1
#endif
-typedef struct {
- volatile ETHR_AINT_T__ value;
-} ETHR_ATMC_T__;
-
-#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_ATOMIC_IMPL__)
-
-static ETHR_INLINE ETHR_AINT_T__ *
-ETHR_NATMC_FUNC__(addr)(ETHR_ATMC_T__ *var)
+static ETHR_INLINE ETHR_AINT_T__
+ETHR_NATMC_FUNC__(inc_return_mb)(ETHR_ATMC_T__ *var)
{
- return (ETHR_AINT_T__ *) &var->value;
+ return ETHR_ILCKD__(Increment)(&var->value);
}
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(init)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ i)
-{
-#if ETHR_READ_AND_SET_WITHOUT_INTERLOCKED_OP__
- var->value = i;
-#else
- (void) ETHR_ILCKD__(Exchange)(&var->value, i);
#endif
-}
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(set)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ i)
-{
-#if ETHR_READ_AND_SET_WITHOUT_INTERLOCKED_OP__
- var->value = i;
+#if defined(ETHR_WIN_HAVE_INC_ACQ)
+
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RETURN_ACQB 1
#else
- (void) ETHR_ILCKD__(Exchange)(&var->value, i);
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RETURN_ACQB 1
#endif
-}
static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(read)(ETHR_ATMC_T__ *var)
+ETHR_NATMC_FUNC__(inc_return_acqb)(ETHR_ATMC_T__ *var)
{
-#if ETHR_READ_AND_SET_WITHOUT_INTERLOCKED_OP__
- return var->value;
-#else
- return ETHR_ILCKD__(ExchangeAdd)(&var->value, (ETHR_AINT_T__) 0);
-#endif
+ return ETHR_ILCKD_ACQ__(Increment)(&var->value);
}
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(add)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ incr)
-{
- (void) ETHR_ILCKD__(ExchangeAdd)(&var->value, incr);
-}
+#endif
+
+#if defined(ETHR_WIN_HAVE_DEC)
+
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RETURN_MB 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RETURN_MB 1
+#endif
static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(add_return)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ i)
+ETHR_NATMC_FUNC__(dec_return_mb)(ETHR_ATMC_T__ *var)
{
- return ETHR_ILCKD__(ExchangeAdd)(&var->value, i) + i;
+ return ETHR_ILCKD__(Decrement)(&var->value);
}
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(inc)(ETHR_ATMC_T__ *var)
-{
- (void) ETHR_ILCKD__(Increment)(&var->value);
-}
+#endif
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(dec)(ETHR_ATMC_T__ *var)
-{
- (void) ETHR_ILCKD__(Decrement)(&var->value);
-}
+#if defined(ETHR_WIN_HAVE_DEC_REL)
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(inc_return)(ETHR_ATMC_T__ *var)
-{
- return ETHR_ILCKD__(Increment)(&var->value);
-}
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RETURN_RELB 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RETURN_RELB 1
+#endif
static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(dec_return)(ETHR_ATMC_T__ *var)
+ETHR_NATMC_FUNC__(dec_return_relb)(ETHR_ATMC_T__ *var)
{
- return ETHR_ILCKD__(Decrement)(&var->value);
+ return ETHR_ILCKD_REL__(Decrement)(&var->value);
}
+#endif
+
+#if defined(ETHR_WIN_HAVE_AND)
+
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_AND_RETOLD_MB 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_AND_RETOLD_MB 1
+#endif
+
static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(and_retold)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ mask)
+ETHR_NATMC_FUNC__(and_retold_mb)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ mask)
{
return ETHR_ILCKD__(And)(&var->value, mask);
}
+#endif
+
+#if defined(ETHR_WIN_HAVE_OR)
+
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_OR_RETOLD_MB 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_OR_RETOLD_MB 1
+#endif
+
static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(or_retold)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ mask)
+ETHR_NATMC_FUNC__(or_retold_mb)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ mask)
{
return ETHR_ILCKD__(Or)(&var->value, mask);
}
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(cmpxchg)(ETHR_ATMC_T__ *var,
- ETHR_AINT_T__ new,
- ETHR_AINT_T__ old)
-{
- return ETHR_ILCKD__(CompareExchange)(&var->value, new, old);
-}
+#endif
+#if defined(ETHR_WIN_HAVE_XCHG)
+
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_XCHG_MB 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_XCHG_MB 1
+#endif
static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(xchg)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ new)
+ETHR_NATMC_FUNC__(xchg_mb)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ new)
{
return ETHR_ILCKD__(Exchange)(&var->value, new);
}
-/*
- * Atomic ops with at least specified barriers.
- */
+#endif
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(read_acqb)(ETHR_ATMC_T__ *var)
-{
-#if ETHR_READ_ACQB_AND_SET_RELB_COMPILER_BARRIER_ONLY__
- ETHR_AINT_T__ val = var->value;
- ETHR_COMPILER_BARRIER;
- return val;
+#if defined(ETHR_WIN_HAVE_CMPXCHG)
+
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG_MB 1
#else
- return ETHR_ILCKD_ACQ__(ExchangeAdd)(&var->value, (ETHR_AINT_T__) 0);
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_MB 1
#endif
-}
static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(inc_return_acqb)(ETHR_ATMC_T__ *var)
+ETHR_NATMC_FUNC__(cmpxchg_mb)(ETHR_ATMC_T__ *var,
+ ETHR_AINT_T__ new,
+ ETHR_AINT_T__ old)
{
- return ETHR_ILCKD_ACQ__(Increment)(&var->value);
+ return ETHR_ILCKD__(CompareExchange)(&var->value, new, old);
}
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(set_relb)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ i)
-{
-#if ETHR_READ_ACQB_AND_SET_RELB_COMPILER_BARRIER_ONLY__
- ETHR_COMPILER_BARRIER;
- var->value = i;
-#else
- (void) ETHR_ILCKD_REL__(Exchange)(&var->value, i);
#endif
-}
-static ETHR_INLINE void
-ETHR_NATMC_FUNC__(dec_relb)(ETHR_ATMC_T__ *var)
-{
- (void) ETHR_ILCKD_REL__(Decrement)(&var->value);
-}
+#if defined(ETHR_WIN_HAVE_CMPXCHG_ACQ)
-static ETHR_INLINE ETHR_AINT_T__
-ETHR_NATMC_FUNC__(dec_return_relb)(ETHR_ATMC_T__ *var)
-{
- return ETHR_ILCKD_REL__(Decrement)(&var->value);
-}
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG_ACQB 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_ACQB 1
+#endif
static ETHR_INLINE ETHR_AINT_T__
ETHR_NATMC_FUNC__(cmpxchg_acqb)(ETHR_ATMC_T__ *var,
@@ -391,6 +435,16 @@ ETHR_NATMC_FUNC__(cmpxchg_acqb)(ETHR_ATMC_T__ *var,
return ETHR_ILCKD_ACQ__(CompareExchange)(&var->value, new, old);
}
+#endif
+
+#if defined(ETHR_WIN_HAVE_CMPXCHG_REL)
+
+#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG_RELB 1
+#else
+# define ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_RELB 1
+#endif
+
static ETHR_INLINE ETHR_AINT_T__
ETHR_NATMC_FUNC__(cmpxchg_relb)(ETHR_ATMC_T__ *var,
ETHR_AINT_T__ new,
@@ -399,6 +453,8 @@ ETHR_NATMC_FUNC__(cmpxchg_relb)(ETHR_ATMC_T__ *var,
return ETHR_ILCKD_REL__(CompareExchange)(&var->value, new, old);
}
+#endif
+
#endif /* ETHR_TRY_INLINE_FUNCS */
#undef ETHR_ILCKD__
@@ -408,8 +464,17 @@ ETHR_NATMC_FUNC__(cmpxchg_relb)(ETHR_ATMC_T__ *var,
#undef ETHR_ATMC_T__
#undef ETHR_AINT_T__
#undef ETHR_READ_AND_SET_WITHOUT_INTERLOCKED_OP__
-#undef ETHR_READ_ACQB_AND_SET_RELB_COMPILER_BARRIER_ONLY__
-
-#endif /* _MSC_VER */
+#undef ETHR_WIN_HAVE_CMPXCHG
+#undef ETHR_WIN_HAVE_DEC
+#undef ETHR_WIN_HAVE_INC
+#undef ETHR_WIN_HAVE_XCHG_ADD
+#undef ETHR_WIN_HAVE_XCHG
+#undef ETHR_WIN_HAVE_AND
+#undef ETHR_WIN_HAVE_OR
+#undef ETHR_WIN_HAVE_XCHG_ADD_ACQ
+#undef ETHR_WIN_HAVE_INC_ACQ
+#undef ETHR_WIN_HAVE_DEC_REL
+#undef ETHR_WIN_HAVE_CMPXCHG_ACQ
+#undef ETHR_WIN_HAVE_CMPXCHG_REL
#endif /* ETHR_INCLUDE_ATOMIC_IMPL__ */
diff --git a/erts/include/internal/win/ethr_dw_atomic.h b/erts/include/internal/win/ethr_dw_atomic.h
new file mode 100644
index 0000000000..a3e7ffc3aa
--- /dev/null
+++ b/erts/include/internal/win/ethr_dw_atomic.h
@@ -0,0 +1,154 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description: Native double word atomics for windows
+ * Author: Rickard Green
+ */
+
+#undef ETHR_INCLUDE_DW_ATOMIC_IMPL__
+#ifndef ETHR_X86_DW_ATOMIC_H__
+# define ETHR_X86_DW_ATOMIC_H__
+# if ((ETHR_SIZEOF_PTR == 4 \
+ && defined(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64)) \
+ || (ETHR_SIZEOF_PTR == 8 \
+ && defined(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE128)))
+# define ETHR_INCLUDE_DW_ATOMIC_IMPL__
+# endif
+#endif
+
+#ifdef ETHR_INCLUDE_DW_ATOMIC_IMPL__
+
+# if ETHR_SIZEOF_PTR == 4
+# define ETHR_HAVE_NATIVE_SU_DW_ATOMIC
+# else
+# define ETHR_HAVE_NATIVE_DW_ATOMIC
+# endif
+# define ETHR_NATIVE_DW_ATOMIC_IMPL "windows-interlocked"
+
+# if defined(_M_IX86) || defined(_M_AMD64)
+/*
+ * If ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__ is defined, it will be used
+ * at runtime in order to determine if native or fallback implementation
+ * should be used.
+ */
+# define ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__ \
+ ETHR_X86_RUNTIME_CONF_HAVE_DW_CMPXCHG__
+# endif
+
+# include <intrin.h>
+# if ETHR_SIZEOF_PTR == 4
+# pragma intrinsic(_InterlockedCompareExchange64)
+# define ETHR_DW_NATMC_ALIGN_MASK__ 0x7
+# define ETHR_NATIVE_SU_DW_SINT_T ethr_sint64_t
+# else
+# pragma intrinsic(_InterlockedCompareExchange128)
+# define ETHR_DW_NATMC_ALIGN_MASK__ 0xf
+# endif
+
+typedef volatile __int64 * ethr_native_dw_ptr_t;
+
+/*
+ * We need 16 byte aligned memory in 64-bit mode, and 8 byte aligned
+ * memory in 32-bit mode. 16 byte aligned malloc in 64-bit mode is
+ * not common, and at least some glibc malloc implementations
+ * only 4 byte align in 32-bit mode.
+ *
+ * This code assumes 8 byte aligned memory in 64-bit mode, and 4 byte
+ * aligned memory in 32-bit mode. A malloc implementation that does
+ * not adhere to these alignment requirements is seriously broken,
+ * and we wont bother trying to work around it.
+ *
+ * Since memory alignment may be off by one word we need to align at
+ * runtime. We, therefore, need an extra word allocated.
+ */
+#define ETHR_DW_NATMC_MEM__(VAR) \
+ (&var->c[(int) ((ethr_uint_t) &(VAR)->c[0]) & ETHR_DW_NATMC_ALIGN_MASK__])
+typedef union {
+#ifdef ETHR_NATIVE_SU_DW_SINT_T
+ volatile ETHR_NATIVE_SU_DW_SINT_T dw_sint;
+#endif
+ volatile ethr_sint_t sint[3];
+ volatile char c[ETHR_SIZEOF_PTR*3];
+} ethr_native_dw_atomic_t;
+
+#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_ATOMIC_IMPL__)
+
+#ifdef ETHR_DEBUG
+# define ETHR_DW_DBG_ALIGNED__(PTR) \
+ ETHR_ASSERT((((ethr_uint_t) (PTR)) & ETHR_DW_NATMC_ALIGN_MASK__) == 0);
+#else
+# define ETHR_DW_DBG_ALIGNED__(PTR)
+#endif
+
+#define ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_ADDR
+
+static ETHR_INLINE ethr_sint_t *
+ethr_native_dw_atomic_addr(ethr_native_dw_atomic_t *var)
+{
+ ethr_sint_t *p = (ethr_sint_t *) ETHR_DW_NATMC_MEM__(var);
+ ETHR_DW_DBG_ALIGNED__(p);
+ return p;
+}
+
+
+#if ETHR_SIZEOF_PTR == 4
+
+#define ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_CMPXCHG_MB
+
+static ETHR_INLINE ethr_sint64_t
+ethr_native_su_dw_atomic_cmpxchg_mb(ethr_native_dw_atomic_t *var,
+ ethr_sint64_t new,
+ ethr_sint64_t exp)
+{
+ ethr_native_dw_ptr_t p = (ethr_native_dw_ptr_t) ETHR_DW_NATMC_MEM__(var);
+ ETHR_DW_DBG_ALIGNED__(p);
+ return (ethr_sint64_t) _InterlockedCompareExchange64(p, new, exp);
+}
+
+#elif ETHR_SIZEOF_PTR == 8
+
+#define ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_CMPXCHG_MB
+
+#ifdef ETHR_BIGENDIAN
+# define ETHR_WIN_LOW_WORD__ 1
+# define ETHR_WIN_HIGH_WORD__ 0
+#else
+# define ETHR_WIN_LOW_WORD__ 0
+# define ETHR_WIN_HIGH_WORD__ 1
+#endif
+
+static ETHR_INLINE int
+ethr_native_dw_atomic_cmpxchg_mb(ethr_native_dw_atomic_t *var,
+ ethr_sint_t *new,
+ ethr_sint_t *xchg)
+{
+ ethr_native_dw_ptr_t p = (ethr_native_dw_ptr_t) ETHR_DW_NATMC_MEM__(var);
+ ETHR_DW_DBG_ALIGNED__(p);
+ return (int) _InterlockedCompareExchange128(p,
+ new[ETHR_WIN_HIGH_WORD__],
+ new[ETHR_WIN_LOW_WORD__],
+ xchg);
+}
+
+#endif
+
+#endif /* ETHR_TRY_INLINE_FUNCS */
+
+#endif /* ETHR_INCLUDE_DW_ATOMIC_IMPL__ */
diff --git a/erts/include/internal/win/ethr_event.h b/erts/include/internal/win/ethr_event.h
index 598816b2c6..6363174a74 100644
--- a/erts/include/internal/win/ethr_event.h
+++ b/erts/include/internal/win/ethr_event.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2009-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2009-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -21,12 +21,12 @@
* Author: Rickard Green
*/
-#define ETHR_EVENT_OFF_WAITER__ ((long) -1)
-#define ETHR_EVENT_OFF__ ((long) 1)
-#define ETHR_EVENT_ON__ ((long) 0)
+#define ETHR_EVENT_OFF_WAITER__ ((ethr_sint32_t) -1)
+#define ETHR_EVENT_OFF__ ((ethr_sint32_t) 1)
+#define ETHR_EVENT_ON__ ((ethr_sint32_t) 0)
typedef struct {
- volatile long state;
+ ethr_atomic32_t state;
HANDLE handle;
} ethr_event;
@@ -38,7 +38,7 @@ static ETHR_INLINE void
ETHR_INLINE_FUNC_NAME_(ethr_event_set)(ethr_event *e)
{
/* _InterlockedExchange() imply a full memory barrier which is important */
- long state = _InterlockedExchange(&e->state, ETHR_EVENT_ON__);
+ ethr_sint32_t state = ethr_atomic32_xchg_wb(&e->state, ETHR_EVENT_ON__);
if (state == ETHR_EVENT_OFF_WAITER__) {
if (!SetEvent(e->handle))
ETHR_FATAL_ERROR__(ethr_win_get_errno__());
@@ -48,8 +48,8 @@ ETHR_INLINE_FUNC_NAME_(ethr_event_set)(ethr_event *e)
static ETHR_INLINE void
ETHR_INLINE_FUNC_NAME_(ethr_event_reset)(ethr_event *e)
{
- /* _InterlockedExchange() imply a full memory barrier which is important */
- InterlockedExchange(&e->state, ETHR_EVENT_OFF__);
+ ethr_atomic32_set(&e->state, ETHR_EVENT_OFF__);
+ ETHR_MEMORY_BARRIER;
}
#endif
diff --git a/erts/include/internal/win/ethr_membar.h b/erts/include/internal/win/ethr_membar.h
new file mode 100644
index 0000000000..8237660b2c
--- /dev/null
+++ b/erts/include/internal/win/ethr_membar.h
@@ -0,0 +1,145 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description: Memory barriers for Windows
+ * Author: Rickard Green
+ */
+
+#if (!defined(ETHR_WIN_MEMBAR_H__) \
+ && (defined(_MSC_VER) && _MSC_VER >= 1400) \
+ && (defined(_M_AMD64) \
+ || defined(_M_IA64) \
+ || defined(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE)))
+#define ETHR_WIN_MEMBAR_H__
+
+#define ETHR_LoadLoad (1 << 0)
+#define ETHR_LoadStore (1 << 1)
+#define ETHR_StoreLoad (1 << 2)
+#define ETHR_StoreStore (1 << 3)
+
+#include <intrin.h>
+#undef ETHR_COMPILER_BARRIER
+#define ETHR_COMPILER_BARRIER _ReadWriteBarrier()
+#pragma intrinsic(_ReadWriteBarrier)
+
+#pragma intrinsic(_InterlockedCompareExchange)
+
+#define ETHR_MB_USING_INTERLOCKED__ \
+do { \
+ volatile long x___ = 0; \
+ (void) _InterlockedCompareExchange(&x___, 2, 1); \
+} while (0)
+
+#if defined(_M_IA64)
+
+#define ETHR_MEMBAR(B) __mf()
+
+#elif defined(_M_AMD64) || defined(_M_IX86)
+
+#include <emmintrin.h>
+#include <mmintrin.h>
+
+#if ETHR_SIZEOF_PTR == 4
+# define ETHR_NO_SSE2_MB__ ETHR_MB_USING_INTERLOCKED__
+#endif
+#pragma intrinsic(_mm_mfence)
+#pragma intrinsic(_mm_sfence)
+#pragma intrinsic(_mm_lfence)
+
+static __forceinline void
+ethr_cfence__(void)
+{
+ _ReadWriteBarrier();
+}
+
+static __forceinline void
+ethr_mfence__(void)
+{
+#if ETHR_SIZEOF_PTR == 4
+ if (ETHR_X86_RUNTIME_CONF_HAVE_NO_SSE2__)
+ ETHR_NO_SSE2_MB__;
+ else
+#endif
+ _mm_mfence();
+}
+
+static __forceinline void
+ethr_sfence__(void)
+{
+#if ETHR_SIZEOF_PTR == 4
+ if (ETHR_X86_RUNTIME_CONF_HAVE_NO_SSE2__)
+ ETHR_NO_SSE2_MB__;
+ else
+#endif
+ _mm_sfence();
+}
+
+static __forceinline void
+ethr_lfence__(void)
+{
+#if ETHR_SIZEOF_PTR == 4
+ if (ETHR_X86_RUNTIME_CONF_HAVE_NO_SSE2__)
+ ETHR_NO_SSE2_MB__;
+ else
+#endif
+ _mm_lfence();
+}
+
+#define ETHR_X86_OUT_OF_ORDER_MEMBAR(B) \
+ ETHR_CHOOSE_EXPR((B) == ETHR_StoreStore, \
+ ethr_sfence__(), \
+ ETHR_CHOOSE_EXPR((B) == ETHR_LoadLoad, \
+ ethr_lfence__(), \
+ ethr_mfence__()))
+
+#ifdef ETHR_X86_OUT_OF_ORDER
+
+#define ETHR_MEMBAR(B) \
+ ETHR_X86_OUT_OF_ORDER_MEMBAR((B))
+
+#else /* !ETHR_X86_OUT_OF_ORDER (the default) */
+
+/*
+ * We assume that only stores before loads may be reordered. That is,
+ * we assume that *no* instructions like these are used:
+ * - CLFLUSH,
+ * - streaming stores executed with non-temporal move,
+ * - string operations, or
+ * - other instructions which aren't LoadLoad, LoadStore, and StoreStore
+ * ordered by themselves
+ * If such instructions are used, either insert memory barriers
+ * using ETHR_X86_OUT_OF_ORDER_MEMBAR() at appropriate places, or
+ * define ETHR_X86_OUT_OF_ORDER. For more info see Intel 64 and IA-32
+ * Architectures Software Developer's Manual; Vol 3A; Chapter 8.2.2.
+ */
+
+#define ETHR_MEMBAR(B) \
+ ETHR_CHOOSE_EXPR((B) & ETHR_StoreLoad, ethr_mfence__(), ethr_cfence__())
+
+#endif
+
+#else /* No knowledge about platform; use interlocked fallback */
+
+#define ETHR_MEMBAR(B) ETHR_MB_USING_INTERLOCKED__
+#define ETHR_READ_DEPEND_MEMORY_BARRIER ETHR_MB_USING_INTERLOCKED__
+
+#endif
+
+#endif /* ETHR_WIN_MEMBAR_H__ */
diff --git a/erts/include/internal/win/ethread.h b/erts/include/internal/win/ethread.h
index c01b17cf14..8be35e810e 100644
--- a/erts/include/internal/win/ethread.h
+++ b/erts/include/internal/win/ethread.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -25,11 +25,13 @@
#ifndef ETHREAD_WIN_H__
#define ETHREAD_WIN_H__
+#include "ethr_membar.h"
#define ETHR_ATOMIC_WANT_32BIT_IMPL__
#include "ethr_atomic.h"
#if ETHR_SIZEOF_PTR == 8
# define ETHR_ATOMIC_WANT_64BIT_IMPL__
# include "ethr_atomic.h"
#endif
+#include "ethr_dw_atomic.h"
#endif
diff --git a/erts/lib_src/Makefile.in b/erts/lib_src/Makefile.in
index 757b3b24e2..12b8732735 100644
--- a/erts/lib_src/Makefile.in
+++ b/erts/lib_src/Makefile.in
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2010. All Rights Reserved.
+# Copyright Ericsson AB 2004-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -65,7 +65,7 @@ TYPE_SUFFIX=.purecov
PRE_LD=purecov $(PURECOV_BUILD_OPTIONS)
else
ifeq ($(TYPE),gcov)
-CFLAGS=@DEBUG_CFLAGS@ -fprofile-arcs -ftest-coverage -O0
+CFLAGS=@DEBUG_CFLAGS@ -DGCOV -fprofile-arcs -ftest-coverage -O0
TYPE_SUFFIX=.gcov
PRE_LD=
else
@@ -288,6 +288,10 @@ ETHREAD_LIB_SRC=common/ethr_aux.c \
common/ethr_cbf.c \
$(ETHR_THR_LIB_BASE_DIR)/ethread.c \
$(ETHR_THR_LIB_BASE_DIR)/ethr_event.c
+ETHR_X86_SSE2_ASM=@ETHR_X86_SSE2_ASM@
+ifeq ($(ETHR_X86_SSE2_ASM),yes)
+ETHREAD_LIB_SRC += pthread/ethr_x86_sse2_asm.c
+endif
ETHREAD_LIB_NAME=ethread$(TYPE_SUFFIX)
ifeq ($(USING_VC),yes)
@@ -382,10 +386,8 @@ $(ERTS_LIB): $(ERTS_LIB_OBJS)
# Object files
#
-ifeq ($(TYPE)-@GCC@,debug-yes)
-$(r_OBJ_DIR)/ethr_aux.o: common/ethr_aux.c
- $(CC) $(THR_DEFS) $(CFLAGS) -Wno-unused-function $(INCLUDES) -c $< -o $@
-endif
+$(r_OBJ_DIR)/ethr_x86_sse2_asm.o: pthread/ethr_x86_sse2_asm.c
+ $(CC) -msse2 $(THR_DEFS) $(CFLAGS) $(INCLUDES) -c $< -o $@
$(r_OBJ_DIR)/%.o: common/%.c
$(CC) $(THR_DEFS) $(CFLAGS) $(INCLUDES) -c $< -o $@
diff --git a/erts/lib_src/common/erl_misc_utils.c b/erts/lib_src/common/erl_misc_utils.c
index 5dbf98c7d1..5e94ff19db 100644
--- a/erts/lib_src/common/erl_misc_utils.c
+++ b/erts/lib_src/common/erl_misc_utils.c
@@ -55,6 +55,12 @@
# ifdef HAVE_UNISTD_H
# include <unistd.h>
# endif
+# if defined(_SC_NPROC_CONF) && !defined(_SC_NPROCESSORS_CONF)
+# define _SC_NPROCESSORS_CONF _SC_NPROC_CONF
+# endif
+# if defined(_SC_NPROC_ONLN) && !defined(_SC_NPROCESSORS_ONLN)
+# define _SC_NPROCESSORS_ONLN _SC_NPROC_ONLN
+# endif
# if (defined(NO_SYSCONF) || !defined(_SC_NPROCESSORS_CONF))
# ifdef HAVE_SYS_SYSCTL_H
# include <sys/sysctl.h>
@@ -1511,7 +1517,7 @@ const char* parse_topology_spec_group(erts_cpu_info_t *cpuinfo, const char* xml,
}
}
- if (cacheLevel == 0) {
+ if (parentCacheLevel == 0) {
*core_p = 0;
*processor_p = (*processor_p)++;
} else {
diff --git a/erts/lib_src/common/erl_printf.c b/erts/lib_src/common/erl_printf.c
index 72d18ab6f1..108a8bb531 100644
--- a/erts/lib_src/common/erl_printf.c
+++ b/erts/lib_src/common/erl_printf.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2009. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -108,7 +108,7 @@ write_f_add_cr(void *vfp, char* buf, size_t len)
if (PUTC(buf[i], (FILE *) vfp) == EOF)
return get_error_result();
}
- return 0;
+ return len;
}
static int
@@ -126,13 +126,14 @@ write_f(void *vfp, char* buf, size_t len)
#endif
if (FWRITE((void *) buf, sizeof(char), len, (FILE *) vfp) != len)
return get_error_result();
- return 0;
+ return len;
}
static int
write_fd(void *vfdp, char* buf, size_t len)
{
ssize_t size;
+ size_t res = len;
ASSERT(vfdp);
while (len) {
@@ -149,7 +150,7 @@ write_fd(void *vfdp, char* buf, size_t len)
len -= size;
}
- return 0;
+ return res;
}
static int
@@ -160,7 +161,7 @@ write_s(void *vwbufpp, char* bufp, size_t len)
ASSERT(len > 0);
memcpy((void *) *wbufpp, (void *) bufp, len);
*wbufpp += len;
- return 0;
+ return len;
}
@@ -182,6 +183,7 @@ write_sn(void *vwsnap, char* buf, size_t len)
memcpy((void *) wsnap->buf, (void *) buf, sz);
wsnap->buf += sz;
wsnap->len -= sz;
+ return sz;
}
return 0;
}
@@ -201,7 +203,7 @@ write_ds(void *vdsbufp, char* buf, size_t len)
}
memcpy((void *) (dsbufp->str + dsbufp->str_len), (void *) buf, len);
dsbufp->str_len += len;
- return 0;
+ return len;
}
int
diff --git a/erts/lib_src/common/erl_printf_format.c b/erts/lib_src/common/erl_printf_format.c
index fba3fd723c..473791dce4 100644
--- a/erts/lib_src/common/erl_printf_format.c
+++ b/erts/lib_src/common/erl_printf_format.c
@@ -388,7 +388,7 @@ static int fmt_double(fmtfn_t fn,void*arg,double val,
max_size++;
if (precision)
max_size += precision;
- else if (fmt && FMTF_alt)
+ else if (fmt & FMTF_alt)
max_size++;
break;
case FMTC_E:
@@ -402,7 +402,7 @@ static int fmt_double(fmtfn_t fn,void*arg,double val,
max_size += 4;
if (precision)
max_size += precision;
- else if (fmt && FMTF_alt)
+ else if (fmt & FMTF_alt)
max_size++;
aexp = exp >= 0 ? exp : -exp;
if (aexp < 100)
diff --git a/erts/lib_src/common/ethr_atomics.c b/erts/lib_src/common/ethr_atomics.c
index 94557d904a..5796bdc22e 100644
--- a/erts/lib_src/common/ethr_atomics.c
+++ b/erts/lib_src/common/ethr_atomics.c
@@ -1,7 +1,16 @@
/*
+ * --------------- DO NOT EDIT THIS FILE! ---------------
+ * This file was automatically generated by the
+ * $ERL_TOP/erts/lib_src/utils/make_atomics_api script.
+ * If you need to make changes, edit the script and
+ * regenerate this file.
+ * --------------- DO NOT EDIT THIS FILE! ---------------
+ */
+
+/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010. All Rights Reserved.
+ * Copyright Ericsson AB 2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -18,385 +27,4329 @@
*/
/*
- * Description: The ethread atomic API
+ * Description: The ethread atomics API
* Author: Rickard Green
*/
+/*
+ * This file maps native atomic implementations to ethread
+ * API atomics. If no native atomic implementation
+ * is available, a less efficient fallback is used instead.
+ * The API consists of 32-bit size, word size (pointer size),
+ * and double word size atomics.
+ *
+ * The following atomic operations are implemented for
+ * 32-bit size, and word size atomics:
+ * - cmpxchg
+ * - xchg
+ * - set
+ * - init
+ * - add_read
+ * - read
+ * - inc_read
+ * - dec_read
+ * - add
+ * - inc
+ * - dec
+ * - read_band
+ * - read_bor
+ *
+ * The following atomic operations are implemented for
+ * double word size atomics:
+ * - cmpxchg
+ * - set
+ * - read
+ * - init
+ *
+ * Appart from a function implementing the atomic operation
+ * with unspecified memory barrier semantics, there are
+ * functions implementing each operation with the following
+ * memory barrier semantics:
+ * - rb (read barrier)
+ * - wb (write barrier)
+ * - acqb (acquire barrier)
+ * - relb (release barrier)
+ * - mb (full memory barrier)
+ *
+ * We implement all of these operation/barrier
+ * combinations, regardless of whether they are useful
+ * or not (some of them are useless).
+ *
+ * Double word size atomic functions are on the followning
+ * form:
+ * ethr_dw_atomic_<OP>[_<BARRIER>]
+ *
+ * Word size atomic functions are on the followning
+ * form:
+ * ethr_atomic_<OP>[_<BARRIER>]
+ *
+ * 32-bit size atomic functions are on the followning
+ * form:
+ * ethr_atomic32_<OP>[_<BARRIER>]
+ *
+ * Apart from the operation/barrier functions
+ * described above also 'addr' functions are implemented
+ * which return the actual memory address used of the
+ * atomic variable. The 'addr' functions have no barrier
+ * versions.
+ *
+ * The native atomic implementation does not need to
+ * implement all operation/barrier combinations.
+ * Functions that have no native implementation will be
+ * constructed from existing native functionality. These
+ * functions will perform the wanted operation and will
+ * produce sufficient memory barriers, but may
+ * in some cases be less efficient than pure native
+ * versions.
+ *
+ * When we create ethread API operation/barrier functions by
+ * adding barriers before and after native operations it is
+ * assumed that:
+ * - A native read operation begins, and ends with a load.
+ * - A native set operation begins, and ends with a store.
+ * - An init operation begins with either a load, or a store,
+ * and ends with either a load, or a store.
+ * - All other operations begins with a load, and ends with
+ * either a load, or a store.
+ *
+ * This is the minimum functionality that a native
+ * implementation needs to provide:
+ *
+ * - Functions that need to be implemented:
+ *
+ * - ethr_native_[dw_|su_dw_]atomic[BITS]_addr
+ * - ethr_native_[dw_|su_dw_]atomic[BITS]_cmpxchg[_<BARRIER>]
+ * (at least one cmpxchg of optional barrier)
+ *
+ * - Macros that needs to be defined:
+ *
+ * A macro informing about the presence of the native
+ * implementation:
+ *
+ * - ETHR_HAVE_NATIVE_[DW_|SU_DW_]ATOMIC[BITS]
+ *
+ * A macro naming (a string constant) the implementation:
+ *
+ * - ETHR_NATIVE_[DW_]ATOMIC[BITS]_IMPL
+ *
+ * Each implemented native atomic function has to
+ * be accompanied by a defined macro on the following
+ * form informing about its presence:
+ *
+ * - ETHR_HAVE_ETHR_NATIVE_[DW_|SU_DW_]ATOMIC[BITS]_<OP>[_<BARRIER>]
+ *
+ * A (sparc-v9 style) membar macro:
+ *
+ * - ETHR_MEMBAR(B)
+ *
+ * Which takes a combination of the following macros
+ * or:ed (using |) together:
+ *
+ * - ETHR_LoadLoad
+ * - ETHR_LoadStore
+ * - ETHR_StoreLoad
+ * - ETHR_StoreStore
+ *
+ */
+
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-#define ETHR_INLINE_FUNC_NAME_(X) X ## __
+#define ETHR_TRY_INLINE_FUNCS
+#define ETHR_INLINE_DW_ATMC_FUNC_NAME_(X) X ## __
+#define ETHR_INLINE_ATMC_FUNC_NAME_(X) X ## __
+#define ETHR_INLINE_ATMC32_FUNC_NAME_(X) X ## __
#define ETHR_ATOMIC_IMPL__
#include "ethread.h"
#include "ethr_internal.h"
-#ifndef ETHR_HAVE_NATIVE_ATOMICS
-ethr_atomic_protection_t ethr_atomic_protection__[1 << ETHR_ATOMIC_ADDR_BITS];
+#if (!defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS) \
+ || !defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS))
+/*
+ * Spinlock based fallback for atomics used in absence of a native
+ * implementation.
+ */
+
+#define ETHR_ATMC_FLLBK_ADDR_BITS 10
+#define ETHR_ATMC_FLLBK_ADDR_SHIFT 6
+
+typedef struct {
+ union {
+ ethr_spinlock_t lck;
+ char buf[ETHR_CACHE_LINE_ALIGN_SIZE(sizeof(ethr_spinlock_t))];
+ } u;
+} ethr_atomic_protection_t;
+
+extern ethr_atomic_protection_t ethr_atomic_protection__[1 << ETHR_ATMC_FLLBK_ADDR_BITS];
+
+#define ETHR_ATOMIC_PTR2LCK__(PTR) \
+(&ethr_atomic_protection__[((((ethr_uint_t) (PTR)) >> ETHR_ATMC_FLLBK_ADDR_SHIFT) \
+ & ((1 << ETHR_ATMC_FLLBK_ADDR_BITS) - 1))].u.lck)
+
+
+#define ETHR_ATOMIC_OP_FALLBACK_IMPL__(AP, EXPS) \
+do { \
+ ethr_spinlock_t *slp__ = ETHR_ATOMIC_PTR2LCK__((AP)); \
+ ethr_spin_lock(slp__); \
+ { EXPS; } \
+ ethr_spin_unlock(slp__); \
+} while (0)
+
+ethr_atomic_protection_t ethr_atomic_protection__[1 << ETHR_ATMC_FLLBK_ADDR_BITS];
+
+#endif
+
+
+#if defined(ETHR_AMC_FALLBACK__)
+
+/*
+ * Fallback for large sized (word and/or double word size) atomics using
+ * an "Atomic Modification Counter" based on smaller sized native atomics.
+ *
+ * We use a 63-bit modification counter and a one bit exclusive flag.
+ * If 32-bit native atomics are used, we need two 32-bit native atomics.
+ * The exclusive flag is the least significant bit, or if multiple atomics
+ * are used, the least significant bit of the least significant atomic.
+ *
+ * When using the AMC fallback the following is true:
+ * - Reads of the same atomic variable can be done in parallel.
+ * - Uncontended reads doesn't cause any cache line invalidations,
+ * since no modifications are done.
+ * - Assuming that the AMC atomic(s) and the integer(s) containing the
+ * value of the implemented atomic resides in the same cache line,
+ * modifications will only cause invalidations of one cache line.
+ *
+ * When using the spinlock based fallback none of the above is true,
+ * however, the spinlock based fallback consumes less memory.
+ */
+
+# if ETHR_AMC_NO_ATMCS__ != 1 && ETHR_AMC_NO_ATMCS__ != 2
+# error "Not supported"
+# endif
+# define ETHR_AMC_MAX_TRY_READ__ 10
+# ifdef ETHR_DEBUG
+# define ETHR_DBG_CHK_EXCL_STATE(ASP, S) \
+do { \
+ ETHR_AMC_SINT_T__ act = ETHR_AMC_ATMC_FUNC__(read)(&(ASP)->atomic[0]); \
+ ETHR_ASSERT(act == (S) + 1); \
+ ETHR_ASSERT(act & 1); \
+} while (0)
+# else
+# define ETHR_DBG_CHK_EXCL_STATE(ASP, S)
+# endif
+
+static ETHR_INLINE void
+amc_init(ethr_amc_t *amc, int dw, ethr_sint_t *avar, ethr_sint_t *val)
+{
+ avar[0] = val[0];
+ if (dw)
+ avar[1] = val[1];
+#if ETHR_AMC_NO_ATMCS__ == 2
+ ETHR_AMC_ATMC_FUNC__(init)(&amc->atomic[1], 0);
#endif
+ ETHR_AMC_ATMC_FUNC__(init_wb)(&amc->atomic[0], 0);
+}
+
+static ETHR_INLINE ETHR_AMC_SINT_T__
+amc_set_excl(ethr_amc_t *amc, ETHR_AMC_SINT_T__ prev_state0)
+{
+ ETHR_AMC_SINT_T__ state0 = prev_state0;
+ /* Set exclusive flag. */
+ while (1) {
+ ETHR_AMC_SINT_T__ act_state0, new_state0;
+ while (state0 & 1) { /* Wait until exclusive bit has been cleared */
+ ETHR_SPIN_BODY;
+ state0 = ETHR_AMC_ATMC_FUNC__(read)(&amc->atomic[0]);
+ }
+ /* Try to set exclusive bit */
+ new_state0 = state0 + 1;
+ act_state0 = ETHR_AMC_ATMC_FUNC__(cmpxchg_acqb)(&amc->atomic[0],
+ new_state0,
+ state0);
+ if (state0 == act_state0)
+ return state0; /* old state0 */
+ state0 = act_state0;
+ }
+}
+
+static ETHR_INLINE void
+amc_inc_mc_unset_excl(ethr_amc_t *amc, ETHR_AMC_SINT_T__ old_state0)
+{
+ ETHR_AMC_SINT_T__ state0 = old_state0;
+
+ /* Increment modification counter and reset exclusive flag. */
+
+ ETHR_DBG_CHK_EXCL_STATE(amc, state0);
+
+ state0 += 2;
+
+ ETHR_ASSERT((state0 & 1) == 0);
+
+#if ETHR_AMC_NO_ATMCS__ == 2
+ if (state0 == 0) {
+ /*
+ * state0 wrapped, so we need to increment state1. There is no need
+ * for atomic inc op, since this is always done while having exclusive
+ * flag.
+ */
+ ETHR_AMC_SINT_T__ state1 = ETHR_AMC_ATMC_FUNC__(read)(&amc->atomic[1]);
+ state1++;
+ ETHR_AMC_ATMC_FUNC__(set)(&amc->atomic[1], state1);
+ }
+#endif
+ ETHR_AMC_ATMC_FUNC__(set_relb)(&amc->atomic[0], state0);
+}
+
+static ETHR_INLINE void
+amc_unset_excl(ethr_amc_t *amc, ETHR_AMC_SINT_T__ old_state0)
+{
+ ETHR_DBG_CHK_EXCL_STATE(amc, old_state0);
+ /*
+ * Reset exclusive flag, but leave modification counter unchanged,
+ * i.e., restore state to what it was before setting exclusive
+ * flag.
+ */
+ ETHR_AMC_ATMC_FUNC__(set_relb)(&amc->atomic[0], old_state0);
+}
+
+static ETHR_INLINE void
+amc_set(ethr_amc_t *amc, int dw, ethr_sint_t *avar, ethr_sint_t *val)
+{
+ ETHR_AMC_SINT_T__ state0 = ETHR_AMC_ATMC_FUNC__(read)(&amc->atomic[0]);
+
+ state0 = amc_set_excl(amc, state0);
+
+ avar[0] = val[0];
+ if (dw)
+ avar[1] = val[1];
+
+ amc_inc_mc_unset_excl(amc, state0);
+}
+
+static ETHR_INLINE int
+amc_try_read(ethr_amc_t *amc, int dw, ethr_sint_t *avar,
+ ethr_sint_t *val, ETHR_AMC_SINT_T__ *state0p)
+{
+ /* *state0p should contain last read value if aborting */
+ ETHR_AMC_SINT_T__ old_state0;
+#if ETHR_AMC_NO_ATMCS__ == 2
+ ETHR_AMC_SINT_T__ state1;
+ int abrt;
+#endif
+
+ *state0p = ETHR_AMC_ATMC_FUNC__(read_rb)(&amc->atomic[0]);
+ if ((*state0p) & 1)
+ return 0; /* exclusive flag set; abort */
+#if ETHR_AMC_NO_ATMCS__ == 2
+ state1 = ETHR_AMC_ATMC_FUNC__(read_rb)(&amc->atomic[1]);
+#else
+ ETHR_COMPILER_BARRIER;
+#endif
+
+ val[0] = avar[0];
+ if (dw)
+ val[1] = avar[1];
+
+ ETHR_READ_MEMORY_BARRIER;
+
+ /*
+ * Abort if state has changed (i.e, either the exclusive
+ * flag is set, or modification counter changed).
+ */
+ old_state0 = *state0p;
+#if ETHR_AMC_NO_ATMCS__ == 2
+ *state0p = ETHR_AMC_ATMC_FUNC__(read_rb)(&amc->atomic[0]);
+ abrt = (old_state0 != *state0p);
+ abrt |= (state1 != ETHR_AMC_ATMC_FUNC__(read)(&amc->atomic[1]));
+ return abrt == 0;
+#else
+ *state0p = ETHR_AMC_ATMC_FUNC__(read)(&amc->atomic[0]);
+ return old_state0 == *state0p;
+#endif
+}
+
+static ETHR_INLINE void
+amc_read(ethr_amc_t *amc, int dw, ethr_sint_t *avar, ethr_sint_t *val)
+{
+ ETHR_AMC_SINT_T__ state0;
+ int i;
+
+#if ETHR_AMC_MAX_TRY_READ__ == 0
+ state0 = ETHR_AMC_ATMC_FUNC__(read)(&amc->atomic[0]);
+#else
+ for (i = 0; i < ETHR_AMC_MAX_TRY_READ__; i++) {
+ if (amc_try_read(amc, dw, avar, val, &state0))
+ return; /* read success */
+ ETHR_SPIN_BODY;
+ }
+#endif
+
+ state0 = amc_set_excl(amc, state0);
+
+ val[0] = avar[0];
+ if (dw)
+ val[1] = avar[1];
+
+ amc_unset_excl(amc, state0);
+}
+
+static ETHR_INLINE int
+amc_cmpxchg(ethr_amc_t *amc, int dw, ethr_sint_t *avar,
+ ethr_sint_t *new, ethr_sint_t *xchg)
+{
+ ethr_sint_t val[2];
+ ETHR_AMC_SINT_T__ state0;
+
+ if (amc_try_read(amc, dw, avar, val, &state0)) {
+ if (val[0] != xchg[0] || (dw && val[1] != xchg[1])) {
+ xchg[0] = val[0];
+ if (dw)
+ xchg[1] = val[1];
+ return 0; /* failed */
+ }
+ /* Operation will succeed if not interrupted */
+ }
+
+ state0 = amc_set_excl(amc, state0);
+
+ if (xchg[0] != avar[0] || (dw && xchg[1] != avar[1])) {
+ xchg[0] = avar[0];
+ if (dw)
+ xchg[1] = avar[1];
+
+ ETHR_DBG_CHK_EXCL_STATE(amc, state0);
+
+ amc_unset_excl(amc, state0);
+ return 0; /* failed */
+ }
+
+ avar[0] = new[0];
+ if (dw)
+ avar[1] = new[1];
+
+ amc_inc_mc_unset_excl(amc, state0);
+ return 1;
+}
+
+
+#define ETHR_AMC_MODIFICATION_OPS__(AMC, OPS) \
+do { \
+ ETHR_AMC_SINT_T__ state0__; \
+ state0__ = ETHR_AMC_ATMC_FUNC__(read)(&(AMC)->atomic[0]); \
+ state0__ = amc_set_excl((AMC), state0__); \
+ { OPS; } \
+ amc_inc_mc_unset_excl((AMC), state0__); \
+} while (0)
+
+#endif /* amc fallback */
+
int
ethr_init_atomics(void)
{
-#ifndef ETHR_HAVE_NATIVE_ATOMICS
- {
- int i;
- for (i = 0; i < (1 << ETHR_ATOMIC_ADDR_BITS); i++) {
- int res = ethr_spinlock_init(&ethr_atomic_protection__[i].u.lck);
- if (res != 0)
- return res;
- }
+#if (!defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS) \
+ || !defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS))
+ int i;
+ for (i = 0; i < (1 << ETHR_ATMC_FLLBK_ADDR_BITS); i++) {
+ int res = ethr_spinlock_init(&ethr_atomic_protection__[i].u.lck);
+ if (res != 0)
+ return res;
}
#endif
return 0;
}
+
+/* ---------- Double word size atomic implementation ---------- */
+
+
+
/*
- * --- Pointer size atomics ---------------------------------------------------
+ * Double word atomics need runtime test.
*/
-ethr_sint_t *
-ethr_atomic_addr(ethr_atomic_t *var)
+int ethr_have_native_dw_atomic(void)
+{
+ return ethr_have_native_dw_atomic__();
+}
+
+
+/* --- addr() --- */
+
+ethr_sint_t *ETHR_DW_ATOMIC_FUNC__(addr)(ethr_dw_atomic_t *var)
+{
+ ethr_sint_t *res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) && !defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ res = ethr_dw_atomic_addr__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ res = (ethr_sint_t *) ((&var->fallback))->sint;
+#else
+ res = (ethr_sint_t *) (&var->fallback);
+#endif
+ return res;
+}
+
+#ifdef ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__
+ethr_sint_t *ethr_dw_atomic_addr(ethr_dw_atomic_t *var)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+ return ethr_dw_atomic_addr__(var);
+}
+#endif
+
+
+/* -- cmpxchg() -- */
+
+
+int ETHR_DW_ATOMIC_FUNC__(cmpxchg)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val)
+{
+ int res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) && !defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ res = ethr_dw_atomic_cmpxchg__(var, val, old_val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ res = amc_cmpxchg(&(&var->fallback)->amc, 1, (&var->fallback)->sint, val->sint, old_val->sint);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__((&var->fallback),
+ {
+ res = ((&var->fallback)->sint[0] == old_val->sint[0] && (&var->fallback)->sint[1] == old_val->sint[1]);
+ if (res) {
+ (&var->fallback)->sint[0] = val->sint[0];
+ (&var->fallback)->sint[1] = val->sint[1];
+ }
+ else {
+ old_val->sint[0] = (&var->fallback)->sint[0];
+ old_val->sint[1] = (&var->fallback)->sint[1];
+ }
+ });
+#endif
+ return res;
+}
+
+#ifdef ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__
+int ethr_dw_atomic_cmpxchg(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+ return ethr_dw_atomic_cmpxchg__(var, val, old_val);
+}
+#endif
+
+int ETHR_DW_ATOMIC_FUNC__(cmpxchg_rb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val)
+{
+ int res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) && !defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ res = ethr_dw_atomic_cmpxchg_rb__(var, val, old_val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ res = amc_cmpxchg(&(&var->fallback)->amc, 1, (&var->fallback)->sint, val->sint, old_val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__((&var->fallback),
+ {
+ res = ((&var->fallback)->sint[0] == old_val->sint[0] && (&var->fallback)->sint[1] == old_val->sint[1]);
+ if (res) {
+ (&var->fallback)->sint[0] = val->sint[0];
+ (&var->fallback)->sint[1] = val->sint[1];
+ }
+ else {
+ old_val->sint[0] = (&var->fallback)->sint[0];
+ old_val->sint[1] = (&var->fallback)->sint[1];
+ }
+ });
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+ return res;
+}
+
+#ifdef ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__
+int ethr_dw_atomic_cmpxchg_rb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+ return ethr_dw_atomic_cmpxchg_rb__(var, val, old_val);
+}
+#endif
+
+int ETHR_DW_ATOMIC_FUNC__(cmpxchg_wb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val)
+{
+ int res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) && !defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ res = ethr_dw_atomic_cmpxchg_wb__(var, val, old_val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = amc_cmpxchg(&(&var->fallback)->amc, 1, (&var->fallback)->sint, val->sint, old_val->sint);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__((&var->fallback),
+ {
+ res = ((&var->fallback)->sint[0] == old_val->sint[0] && (&var->fallback)->sint[1] == old_val->sint[1]);
+ if (res) {
+ (&var->fallback)->sint[0] = val->sint[0];
+ (&var->fallback)->sint[1] = val->sint[1];
+ }
+ else {
+ old_val->sint[0] = (&var->fallback)->sint[0];
+ old_val->sint[1] = (&var->fallback)->sint[1];
+ }
+ });
+#endif
+ return res;
+}
+
+#ifdef ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__
+int ethr_dw_atomic_cmpxchg_wb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+ return ethr_dw_atomic_cmpxchg_wb__(var, val, old_val);
+}
+#endif
+
+int ETHR_DW_ATOMIC_FUNC__(cmpxchg_acqb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val)
+{
+ int res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) && !defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ res = ethr_dw_atomic_cmpxchg_acqb__(var, val, old_val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ res = amc_cmpxchg(&(&var->fallback)->amc, 1, (&var->fallback)->sint, val->sint, old_val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__((&var->fallback),
+ {
+ res = ((&var->fallback)->sint[0] == old_val->sint[0] && (&var->fallback)->sint[1] == old_val->sint[1]);
+ if (res) {
+ (&var->fallback)->sint[0] = val->sint[0];
+ (&var->fallback)->sint[1] = val->sint[1];
+ }
+ else {
+ old_val->sint[0] = (&var->fallback)->sint[0];
+ old_val->sint[1] = (&var->fallback)->sint[1];
+ }
+ });
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+#ifdef ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__
+int ethr_dw_atomic_cmpxchg_acqb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+ return ethr_dw_atomic_cmpxchg_acqb__(var, val, old_val);
+}
+#endif
+
+int ETHR_DW_ATOMIC_FUNC__(cmpxchg_relb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val)
+{
+ int res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) && !defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ res = ethr_dw_atomic_cmpxchg_relb__(var, val, old_val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = amc_cmpxchg(&(&var->fallback)->amc, 1, (&var->fallback)->sint, val->sint, old_val->sint);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__((&var->fallback),
+ {
+ res = ((&var->fallback)->sint[0] == old_val->sint[0] && (&var->fallback)->sint[1] == old_val->sint[1]);
+ if (res) {
+ (&var->fallback)->sint[0] = val->sint[0];
+ (&var->fallback)->sint[1] = val->sint[1];
+ }
+ else {
+ old_val->sint[0] = (&var->fallback)->sint[0];
+ old_val->sint[1] = (&var->fallback)->sint[1];
+ }
+ });
+#endif
+ return res;
+}
+
+#ifdef ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__
+int ethr_dw_atomic_cmpxchg_relb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+ return ethr_dw_atomic_cmpxchg_relb__(var, val, old_val);
+}
+#endif
+
+int ETHR_DW_ATOMIC_FUNC__(cmpxchg_mb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val)
+{
+ int res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) && !defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ res = ethr_dw_atomic_cmpxchg_mb__(var, val, old_val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = amc_cmpxchg(&(&var->fallback)->amc, 1, (&var->fallback)->sint, val->sint, old_val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__((&var->fallback),
+ {
+ res = ((&var->fallback)->sint[0] == old_val->sint[0] && (&var->fallback)->sint[1] == old_val->sint[1]);
+ if (res) {
+ (&var->fallback)->sint[0] = val->sint[0];
+ (&var->fallback)->sint[1] = val->sint[1];
+ }
+ else {
+ old_val->sint[0] = (&var->fallback)->sint[0];
+ old_val->sint[1] = (&var->fallback)->sint[1];
+ }
+ });
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+#ifdef ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__
+int ethr_dw_atomic_cmpxchg_mb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+ return ethr_dw_atomic_cmpxchg_mb__(var, val, old_val);
+}
+#endif
+
+
+/* -- set() -- */
+
+
+void ETHR_DW_ATOMIC_FUNC__(set)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) && !defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ ethr_dw_atomic_set__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ amc_set(&(&var->fallback)->amc, 1, (&var->fallback)->sint, val->sint);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__((&var->fallback), (&var->fallback)->sint[0] = val->sint[0]; (&var->fallback)->sint[1] = val->sint[1]);
+#endif
+
+}
+
+#ifdef ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__
+void ethr_dw_atomic_set(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+ ethr_dw_atomic_set__(var, val);
+}
+#endif
+
+void ETHR_DW_ATOMIC_FUNC__(set_rb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) && !defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ ethr_dw_atomic_set_rb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ amc_set(&(&var->fallback)->amc, 1, (&var->fallback)->sint, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__((&var->fallback), (&var->fallback)->sint[0] = val->sint[0]; (&var->fallback)->sint[1] = val->sint[1]);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+
+}
+
+#ifdef ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__
+void ethr_dw_atomic_set_rb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+ ethr_dw_atomic_set_rb__(var, val);
+}
+#endif
+
+void ETHR_DW_ATOMIC_FUNC__(set_wb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) && !defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ ethr_dw_atomic_set_wb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ amc_set(&(&var->fallback)->amc, 1, (&var->fallback)->sint, val->sint);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__((&var->fallback), (&var->fallback)->sint[0] = val->sint[0]; (&var->fallback)->sint[1] = val->sint[1]);
+#endif
+
+}
+
+#ifdef ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__
+void ethr_dw_atomic_set_wb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+ ethr_dw_atomic_set_wb__(var, val);
+}
+#endif
+
+void ETHR_DW_ATOMIC_FUNC__(set_acqb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) && !defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ ethr_dw_atomic_set_acqb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ amc_set(&(&var->fallback)->amc, 1, (&var->fallback)->sint, val->sint);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__((&var->fallback), (&var->fallback)->sint[0] = val->sint[0]; (&var->fallback)->sint[1] = val->sint[1]);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+
+}
+
+#ifdef ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__
+void ethr_dw_atomic_set_acqb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+ ethr_dw_atomic_set_acqb__(var, val);
+}
+#endif
+
+void ETHR_DW_ATOMIC_FUNC__(set_relb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) && !defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ ethr_dw_atomic_set_relb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ amc_set(&(&var->fallback)->amc, 1, (&var->fallback)->sint, val->sint);
+#else
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__((&var->fallback), (&var->fallback)->sint[0] = val->sint[0]; (&var->fallback)->sint[1] = val->sint[1]);
+#endif
+
+}
+
+#ifdef ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__
+void ethr_dw_atomic_set_relb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+ ethr_dw_atomic_set_relb__(var, val);
+}
+#endif
+
+void ETHR_DW_ATOMIC_FUNC__(set_mb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) && !defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ ethr_dw_atomic_set_mb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ amc_set(&(&var->fallback)->amc, 1, (&var->fallback)->sint, val->sint);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__((&var->fallback), (&var->fallback)->sint[0] = val->sint[0]; (&var->fallback)->sint[1] = val->sint[1]);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+
+}
+
+#ifdef ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__
+void ethr_dw_atomic_set_mb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+ ethr_dw_atomic_set_mb__(var, val);
+}
+#endif
+
+
+/* -- read() -- */
+
+
+void ETHR_DW_ATOMIC_FUNC__(read)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) && !defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ ethr_dw_atomic_read__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ amc_read(&(&var->fallback)->amc, 1, (&var->fallback)->sint, val->sint);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__((&var->fallback), val->sint[0] = (&var->fallback)->sint[0]; val->sint[1] = (&var->fallback)->sint[1]);
+#endif
+
+}
+
+#ifdef ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__
+void ethr_dw_atomic_read(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+ ethr_dw_atomic_read__(var, val);
+}
+#endif
+
+void ETHR_DW_ATOMIC_FUNC__(read_rb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) && !defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ ethr_dw_atomic_read_rb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ amc_read(&(&var->fallback)->amc, 1, (&var->fallback)->sint, val->sint);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__((&var->fallback), val->sint[0] = (&var->fallback)->sint[0]; val->sint[1] = (&var->fallback)->sint[1]);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+
+}
+
+#ifdef ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__
+void ethr_dw_atomic_read_rb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+ ethr_dw_atomic_read_rb__(var, val);
+}
+#endif
+
+void ETHR_DW_ATOMIC_FUNC__(read_wb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) && !defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ ethr_dw_atomic_read_wb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ amc_read(&(&var->fallback)->amc, 1, (&var->fallback)->sint, val->sint);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__((&var->fallback), val->sint[0] = (&var->fallback)->sint[0]; val->sint[1] = (&var->fallback)->sint[1]);
+#endif
+
+}
+
+#ifdef ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__
+void ethr_dw_atomic_read_wb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+ ethr_dw_atomic_read_wb__(var, val);
+}
+#endif
+
+void ETHR_DW_ATOMIC_FUNC__(read_acqb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) && !defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ ethr_dw_atomic_read_acqb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ amc_read(&(&var->fallback)->amc, 1, (&var->fallback)->sint, val->sint);
+ ETHR_MEMBAR(ETHR_LoadStore);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__((&var->fallback), val->sint[0] = (&var->fallback)->sint[0]; val->sint[1] = (&var->fallback)->sint[1]);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#endif
+
+}
+
+#ifdef ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__
+void ethr_dw_atomic_read_acqb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+ ethr_dw_atomic_read_acqb__(var, val);
+}
+#endif
+
+void ETHR_DW_ATOMIC_FUNC__(read_relb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) && !defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ ethr_dw_atomic_read_relb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ amc_read(&(&var->fallback)->amc, 1, (&var->fallback)->sint, val->sint);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__((&var->fallback), val->sint[0] = (&var->fallback)->sint[0]; val->sint[1] = (&var->fallback)->sint[1]);
+#endif
+
+}
+
+#ifdef ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__
+void ethr_dw_atomic_read_relb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+ ethr_dw_atomic_read_relb__(var, val);
+}
+#endif
+
+void ETHR_DW_ATOMIC_FUNC__(read_mb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) && !defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ ethr_dw_atomic_read_mb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ amc_read(&(&var->fallback)->amc, 1, (&var->fallback)->sint, val->sint);
+ ETHR_MEMBAR(ETHR_LoadStore);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__((&var->fallback), val->sint[0] = (&var->fallback)->sint[0]; val->sint[1] = (&var->fallback)->sint[1]);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#endif
+
+}
+
+#ifdef ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__
+void ethr_dw_atomic_read_mb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+ ethr_dw_atomic_read_mb__(var, val);
+}
+#endif
+
+
+/* -- init() -- */
+
+
+void ETHR_DW_ATOMIC_FUNC__(init)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) && !defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ ethr_dw_atomic_init__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ amc_init(&(&var->fallback)->amc, 1, (&var->fallback)->sint, val->sint);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__((&var->fallback), (&var->fallback)->sint[0] = val->sint[0]; (&var->fallback)->sint[1] = val->sint[1]);
+#endif
+
+}
+
+#ifdef ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__
+void ethr_dw_atomic_init(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(var);
+ ethr_dw_atomic_init__(var, val);
+}
+#endif
+
+void ETHR_DW_ATOMIC_FUNC__(init_rb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) && !defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ ethr_dw_atomic_init_rb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ amc_init(&(&var->fallback)->amc, 1, (&var->fallback)->sint, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__((&var->fallback), (&var->fallback)->sint[0] = val->sint[0]; (&var->fallback)->sint[1] = val->sint[1]);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+
+}
+
+#ifdef ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__
+void ethr_dw_atomic_init_rb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(var);
+ ethr_dw_atomic_init_rb__(var, val);
+}
+#endif
+
+void ETHR_DW_ATOMIC_FUNC__(init_wb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) && !defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ ethr_dw_atomic_init_wb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ amc_init(&(&var->fallback)->amc, 1, (&var->fallback)->sint, val->sint);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__((&var->fallback), (&var->fallback)->sint[0] = val->sint[0]; (&var->fallback)->sint[1] = val->sint[1]);
+#endif
+
+}
+
+#ifdef ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__
+void ethr_dw_atomic_init_wb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(var);
+ ethr_dw_atomic_init_wb__(var, val);
+}
+#endif
+
+void ETHR_DW_ATOMIC_FUNC__(init_acqb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) && !defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ ethr_dw_atomic_init_acqb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ amc_init(&(&var->fallback)->amc, 1, (&var->fallback)->sint, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__((&var->fallback), (&var->fallback)->sint[0] = val->sint[0]; (&var->fallback)->sint[1] = val->sint[1]);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+
+}
+
+#ifdef ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__
+void ethr_dw_atomic_init_acqb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(var);
+ ethr_dw_atomic_init_acqb__(var, val);
+}
+#endif
+
+void ETHR_DW_ATOMIC_FUNC__(init_relb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) && !defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ ethr_dw_atomic_init_relb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ amc_init(&(&var->fallback)->amc, 1, (&var->fallback)->sint, val->sint);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__((&var->fallback), (&var->fallback)->sint[0] = val->sint[0]; (&var->fallback)->sint[1] = val->sint[1]);
+#endif
+
+}
+
+#ifdef ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__
+void ethr_dw_atomic_init_relb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(var);
+ ethr_dw_atomic_init_relb__(var, val);
+}
+#endif
+
+void ETHR_DW_ATOMIC_FUNC__(init_mb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) && !defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ ethr_dw_atomic_init_mb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ amc_init(&(&var->fallback)->amc, 1, (&var->fallback)->sint, val->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__((&var->fallback), (&var->fallback)->sint[0] = val->sint[0]; (&var->fallback)->sint[1] = val->sint[1]);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+
+}
+
+#ifdef ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__
+void ethr_dw_atomic_init_mb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+ ETHR_ASSERT(var);
+ ethr_dw_atomic_init_mb__(var, val);
+}
+#endif
+
+
+/* ---------- Word size atomic implementation ---------- */
+
+
+
+
+/* --- addr() --- */
+
+ethr_sint_t *ethr_atomic_addr(ethr_atomic_t *var)
+{
+ ethr_sint_t *res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_addr__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ res = (ethr_sint_t *) (var)->sint;
+#else
+ res = (ethr_sint_t *) var;
+#endif
+ return res;
+}
+
+
+/* -- cmpxchg() -- */
+
+
+ethr_sint_t ethr_atomic_cmpxchg(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_cmpxchg__(var, val, old_val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ res = old_val;
+ (void) amc_cmpxchg(&var->amc, 0, &var->sint, &val, &res);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = (*var == old_val ? (*var = val, old_val) : *var));
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_cmpxchg_rb(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_cmpxchg_rb__(var, val, old_val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ res = old_val;
+ (void) amc_cmpxchg(&var->amc, 0, &var->sint, &val, &res);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = (*var == old_val ? (*var = val, old_val) : *var));
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_cmpxchg_wb(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_cmpxchg_wb__(var, val, old_val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ res = old_val;
+ (void) amc_cmpxchg(&var->amc, 0, &var->sint, &val, &res);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = (*var == old_val ? (*var = val, old_val) : *var));
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_cmpxchg_acqb(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_cmpxchg_acqb__(var, val, old_val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ res = old_val;
+ (void) amc_cmpxchg(&var->amc, 0, &var->sint, &val, &res);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = (*var == old_val ? (*var = val, old_val) : *var));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_cmpxchg_relb(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_cmpxchg_relb__(var, val, old_val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = old_val;
+ (void) amc_cmpxchg(&var->amc, 0, &var->sint, &val, &res);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = (*var == old_val ? (*var = val, old_val) : *var));
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_cmpxchg_mb(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_cmpxchg_mb__(var, val, old_val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ res = old_val;
+ (void) amc_cmpxchg(&var->amc, 0, &var->sint, &val, &res);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = (*var == old_val ? (*var = val, old_val) : *var));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+
+/* -- xchg() -- */
+
+
+ethr_sint_t ethr_atomic_xchg(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_xchg__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = var->sint; var->sint = val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var = val);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_xchg_rb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_xchg_rb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = var->sint; var->sint = val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var = val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_xchg_wb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_xchg_wb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = var->sint; var->sint = val);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var = val);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_xchg_acqb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_xchg_acqb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = var->sint; var->sint = val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var = val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_xchg_relb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_xchg_relb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = var->sint; var->sint = val);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var = val);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_xchg_mb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_xchg_mb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = var->sint; var->sint = val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var = val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+
+/* -- set() -- */
+
+
+void ethr_atomic_set(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_set__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ amc_set(&var->amc, 0, &var->sint, &val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = val);
+#endif
+
+}
+
+void ethr_atomic_set_rb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_set_rb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ amc_set(&var->amc, 0, &var->sint, &val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+
+}
+
+void ethr_atomic_set_wb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_set_wb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ amc_set(&var->amc, 0, &var->sint, &val);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = val);
+#endif
+
+}
+
+void ethr_atomic_set_acqb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_set_acqb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ amc_set(&var->amc, 0, &var->sint, &val);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = val);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+
+}
+
+void ethr_atomic_set_relb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_set_relb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ amc_set(&var->amc, 0, &var->sint, &val);
+#else
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = val);
+#endif
+
+}
+
+void ethr_atomic_set_mb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_set_mb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ amc_set(&var->amc, 0, &var->sint, &val);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = val);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+
+}
+
+
+/* -- init() -- */
+
+
+void ethr_atomic_init(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_init__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ amc_init(&var->amc, 0, &var->sint, &val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = val);
+#endif
+
+}
+
+void ethr_atomic_init_rb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_init_rb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ amc_init(&var->amc, 0, &var->sint, &val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+
+}
+
+void ethr_atomic_init_wb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_init_wb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ amc_init(&var->amc, 0, &var->sint, &val);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = val);
+#endif
+
+}
+
+void ethr_atomic_init_acqb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_init_acqb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ amc_init(&var->amc, 0, &var->sint, &val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+
+}
+
+void ethr_atomic_init_relb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_init_relb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ amc_init(&var->amc, 0, &var->sint, &val);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = val);
+#endif
+
+}
+
+void ethr_atomic_init_mb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_init_mb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ amc_init(&var->amc, 0, &var->sint, &val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+
+}
+
+
+/* -- add_read() -- */
+
+
+ethr_sint_t ethr_atomic_add_read(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_add_read__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, var->sint += val; res = var->sint);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += val; res = *var);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_add_read_rb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_add_read_rb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, var->sint += val; res = var->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += val; res = *var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_add_read_wb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_add_read_wb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, var->sint += val; res = var->sint);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += val; res = *var);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_add_read_acqb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_add_read_acqb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, var->sint += val; res = var->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += val; res = *var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_add_read_relb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_add_read_relb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, var->sint += val; res = var->sint);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += val; res = *var);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_add_read_mb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_add_read_mb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, var->sint += val; res = var->sint);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += val; res = *var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+
+/* -- read() -- */
+
+
+ethr_sint_t ethr_atomic_read(ethr_atomic_t *var)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_read__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ amc_read(&var->amc, 0, &var->sint, &res);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_read_rb(ethr_atomic_t *var)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_read_rb__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ amc_read(&var->amc, 0, &var->sint, &res);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_read_wb(ethr_atomic_t *var)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_read_wb__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ amc_read(&var->amc, 0, &var->sint, &res);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_read_acqb(ethr_atomic_t *var)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_read_acqb__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ amc_read(&var->amc, 0, &var->sint, &res);
+ ETHR_MEMBAR(ETHR_LoadStore);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_read_relb(ethr_atomic_t *var)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_read_relb__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ amc_read(&var->amc, 0, &var->sint, &res);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_read_mb(ethr_atomic_t *var)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_read_mb__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ amc_read(&var->amc, 0, &var->sint, &res);
+ ETHR_MEMBAR(ETHR_LoadStore);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#endif
+ return res;
+}
+
+
+/* -- inc_read() -- */
+
+
+ethr_sint_t ethr_atomic_inc_read(ethr_atomic_t *var)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_inc_read__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = ++(var->sint));
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = ++(*var));
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_inc_read_rb(ethr_atomic_t *var)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_inc_read_rb__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = ++(var->sint));
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = ++(*var));
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_inc_read_wb(ethr_atomic_t *var)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_inc_read_wb__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = ++(var->sint));
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = ++(*var));
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_inc_read_acqb(ethr_atomic_t *var)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_inc_read_acqb__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = ++(var->sint));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = ++(*var));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_inc_read_relb(ethr_atomic_t *var)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_inc_read_relb__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = ++(var->sint));
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = ++(*var));
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_inc_read_mb(ethr_atomic_t *var)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_inc_read_mb__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = ++(var->sint));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = ++(*var));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+
+/* -- dec_read() -- */
+
+
+ethr_sint_t ethr_atomic_dec_read(ethr_atomic_t *var)
{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic_addr__(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_dec_read__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = --(var->sint));
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = --(*var));
+#endif
+ return res;
}
-void
-ethr_atomic_init(ethr_atomic_t *var, ethr_sint_t i)
+ethr_sint_t ethr_atomic_dec_read_rb(ethr_atomic_t *var)
{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- ethr_atomic_init__(var, i);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_dec_read_rb__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = --(var->sint));
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = --(*var));
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+ return res;
}
-void
-ethr_atomic_set(ethr_atomic_t *var, ethr_sint_t i)
+ethr_sint_t ethr_atomic_dec_read_wb(ethr_atomic_t *var)
{
+ ethr_sint_t res;
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- ethr_atomic_set__(var, i);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_dec_read_wb__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = --(var->sint));
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = --(*var));
+#endif
+ return res;
}
-ethr_sint_t
-ethr_atomic_read(ethr_atomic_t *var)
+ethr_sint_t ethr_atomic_dec_read_acqb(ethr_atomic_t *var)
{
+ ethr_sint_t res;
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic_read__(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_dec_read_acqb__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = --(var->sint));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = --(*var));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
}
-ethr_sint_t
-ethr_atomic_add_read(ethr_atomic_t *var, ethr_sint_t incr)
+ethr_sint_t ethr_atomic_dec_read_relb(ethr_atomic_t *var)
{
+ ethr_sint_t res;
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic_add_read__(var, incr);
-}
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_dec_read_relb__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = --(var->sint));
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = --(*var));
+#endif
+ return res;
+}
-ethr_sint_t
-ethr_atomic_inc_read(ethr_atomic_t *var)
+ethr_sint_t ethr_atomic_dec_read_mb(ethr_atomic_t *var)
{
+ ethr_sint_t res;
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic_inc_read__(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_dec_read_mb__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = --(var->sint));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = --(*var));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
}
-ethr_sint_t
-ethr_atomic_dec_read(ethr_atomic_t *var)
+
+/* -- add() -- */
+
+
+void ethr_atomic_add(ethr_atomic_t *var, ethr_sint_t val)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic_dec_read__(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_add__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, var->sint += val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += val);
+#endif
+
+}
+
+void ethr_atomic_add_rb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_add_rb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, var->sint += val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+
}
-void
-ethr_atomic_add(ethr_atomic_t *var, ethr_sint_t incr)
+void ethr_atomic_add_wb(ethr_atomic_t *var, ethr_sint_t val)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- ethr_atomic_add__(var, incr);
-}
-
-void
-ethr_atomic_inc(ethr_atomic_t *var)
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_add_wb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, var->sint += val);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += val);
+#endif
+
+}
+
+void ethr_atomic_add_acqb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_add_acqb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, var->sint += val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+
+}
+
+void ethr_atomic_add_relb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_add_relb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, var->sint += val);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += val);
+#endif
+
+}
+
+void ethr_atomic_add_mb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_add_mb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, var->sint += val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+
+}
+
+
+/* -- inc() -- */
+
+
+void ethr_atomic_inc(ethr_atomic_t *var)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
ethr_atomic_inc__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, ++(var->sint));
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, ++(*var));
+#endif
+
}
-void
-ethr_atomic_dec(ethr_atomic_t *var)
+void ethr_atomic_inc_rb(ethr_atomic_t *var)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- ethr_atomic_dec__(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_inc_rb__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, ++(var->sint));
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, ++(*var));
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+
}
-ethr_sint_t
-ethr_atomic_read_band(ethr_atomic_t *var, ethr_sint_t mask)
+void ethr_atomic_inc_wb(ethr_atomic_t *var)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic_read_band__(var, mask);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_inc_wb__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, ++(var->sint));
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, ++(*var));
+#endif
+
}
-ethr_sint_t
-ethr_atomic_read_bor(ethr_atomic_t *var, ethr_sint_t mask)
+void ethr_atomic_inc_acqb(ethr_atomic_t *var)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic_read_bor__(var, mask);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_inc_acqb__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, ++(var->sint));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, ++(*var));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+
}
-ethr_sint_t
-ethr_atomic_xchg(ethr_atomic_t *var, ethr_sint_t new)
+void ethr_atomic_inc_relb(ethr_atomic_t *var)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic_xchg__(var, new);
-}
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_inc_relb__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, ++(var->sint));
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, ++(*var));
+#endif
+
+}
-ethr_sint_t
-ethr_atomic_cmpxchg(ethr_atomic_t *var, ethr_sint_t new, ethr_sint_t expected)
+void ethr_atomic_inc_mb(ethr_atomic_t *var)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic_cmpxchg__(var, new, expected);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_inc_mb__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, ++(var->sint));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, ++(*var));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+
}
-ethr_sint_t
-ethr_atomic_read_acqb(ethr_atomic_t *var)
+
+/* -- dec() -- */
+
+
+void ethr_atomic_dec(ethr_atomic_t *var)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic_read_acqb__(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_dec__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, --(var->sint));
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, --(*var));
+#endif
+
}
-ethr_sint_t
-ethr_atomic_inc_read_acqb(ethr_atomic_t *var)
+void ethr_atomic_dec_rb(ethr_atomic_t *var)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic_inc_read_acqb__(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_dec_rb__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, --(var->sint));
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, --(*var));
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+
}
-void
-ethr_atomic_set_relb(ethr_atomic_t *var, ethr_sint_t i)
+void ethr_atomic_dec_wb(ethr_atomic_t *var)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- ethr_atomic_set_relb__(var, i);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_dec_wb__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, --(var->sint));
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, --(*var));
+#endif
+
}
-void
-ethr_atomic_dec_relb(ethr_atomic_t *var)
+void ethr_atomic_dec_acqb(ethr_atomic_t *var)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_dec_acqb__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, --(var->sint));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, --(*var));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+
+}
+
+void ethr_atomic_dec_relb(ethr_atomic_t *var)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
ethr_atomic_dec_relb__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, --(var->sint));
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, --(*var));
+#endif
+
}
-ethr_sint_t
-ethr_atomic_dec_read_relb(ethr_atomic_t *var)
+void ethr_atomic_dec_mb(ethr_atomic_t *var)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic_dec_read_relb__(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_dec_mb__(var);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, --(var->sint));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, --(*var));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+
}
-ethr_sint_t
-ethr_atomic_cmpxchg_acqb(ethr_atomic_t *var, ethr_sint_t new, ethr_sint_t exp)
+
+/* -- read_band() -- */
+
+
+ethr_sint_t ethr_atomic_read_band(ethr_atomic_t *var, ethr_sint_t val)
{
+ ethr_sint_t res;
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic_cmpxchg_acqb__(var, new, exp);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_read_band__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = var->sint; var->sint &= val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var &= val);
+#endif
+ return res;
}
-ethr_sint_t
-ethr_atomic_cmpxchg_relb(ethr_atomic_t *var, ethr_sint_t new, ethr_sint_t exp)
+ethr_sint_t ethr_atomic_read_band_rb(ethr_atomic_t *var, ethr_sint_t val)
{
+ ethr_sint_t res;
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic_cmpxchg_relb__(var, new, exp);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_read_band_rb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = var->sint; var->sint &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+ return res;
}
+ethr_sint_t ethr_atomic_read_band_wb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_read_band_wb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = var->sint; var->sint &= val);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var &= val);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_read_band_acqb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_read_band_acqb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = var->sint; var->sint &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_read_band_relb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_read_band_relb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = var->sint; var->sint &= val);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var &= val);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_read_band_mb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_read_band_mb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = var->sint; var->sint &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+
+/* -- read_bor() -- */
+
+
+ethr_sint_t ethr_atomic_read_bor(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_read_bor__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = var->sint; var->sint |= val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var |= val);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_read_bor_rb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_read_bor_rb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = var->sint; var->sint |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_read_bor_wb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_read_bor_wb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = var->sint; var->sint |= val);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var |= val);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_read_bor_acqb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_read_bor_acqb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = var->sint; var->sint |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_read_bor_relb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_read_bor_relb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = var->sint; var->sint |= val);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var |= val);
+#endif
+ return res;
+}
+
+ethr_sint_t ethr_atomic_read_bor_mb(ethr_atomic_t *var, ethr_sint_t val)
+{
+ ethr_sint_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic_read_bor_mb__(var, val);
+#elif defined(ETHR_AMC_FALLBACK__)
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_AMC_MODIFICATION_OPS__(&var->amc, res = var->sint; var->sint |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+
+/* ---------- 32-bit atomic implementation ---------- */
+
+
+
+
+/* --- addr() --- */
+
+ethr_sint32_t *ethr_atomic32_addr(ethr_atomic32_t *var)
+{
+ ethr_sint32_t *res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_addr__(var);
+
+#else
+ res = (ethr_sint32_t *) var;
+#endif
+ return res;
+}
+
+
+/* -- cmpxchg() -- */
+
+
+ethr_sint32_t ethr_atomic32_cmpxchg(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_cmpxchg__(var, val, old_val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = (*var == old_val ? (*var = val, old_val) : *var));
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_cmpxchg_rb(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_cmpxchg_rb__(var, val, old_val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = (*var == old_val ? (*var = val, old_val) : *var));
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_cmpxchg_wb(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_cmpxchg_wb__(var, val, old_val);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = (*var == old_val ? (*var = val, old_val) : *var));
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_cmpxchg_acqb(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_cmpxchg_acqb__(var, val, old_val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = (*var == old_val ? (*var = val, old_val) : *var));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_cmpxchg_relb(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_cmpxchg_relb__(var, val, old_val);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = (*var == old_val ? (*var = val, old_val) : *var));
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_cmpxchg_mb(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_cmpxchg_mb__(var, val, old_val);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = (*var == old_val ? (*var = val, old_val) : *var));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+
+/* -- xchg() -- */
+
+
+ethr_sint32_t ethr_atomic32_xchg(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_xchg__(var, val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var = val);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_xchg_rb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_xchg_rb__(var, val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var = val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_xchg_wb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_xchg_wb__(var, val);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var = val);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_xchg_acqb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_xchg_acqb__(var, val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var = val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_xchg_relb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_xchg_relb__(var, val);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var = val);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_xchg_mb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_xchg_mb__(var, val);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var = val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+
+/* -- set() -- */
+
+
+void ethr_atomic32_set(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_set__(var, val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = val);
+#endif
+
+}
+
+void ethr_atomic32_set_rb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_set_rb__(var, val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+
+}
+
+void ethr_atomic32_set_wb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_set_wb__(var, val);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = val);
+#endif
+
+}
+
+void ethr_atomic32_set_acqb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_set_acqb__(var, val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = val);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+
+}
+
+void ethr_atomic32_set_relb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_set_relb__(var, val);
+#else
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = val);
+#endif
+
+}
+
+void ethr_atomic32_set_mb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_set_mb__(var, val);
+#else
+ ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = val);
+ ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+
+}
+
+
+/* -- init() -- */
+
+
+void ethr_atomic32_init(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_init__(var, val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = val);
+#endif
+
+}
+
+void ethr_atomic32_init_rb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_init_rb__(var, val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+
+}
+
+void ethr_atomic32_init_wb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_init_wb__(var, val);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = val);
+#endif
+
+}
+
+void ethr_atomic32_init_acqb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_init_acqb__(var, val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+
+}
+
+void ethr_atomic32_init_relb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_init_relb__(var, val);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = val);
+#endif
+
+}
+
+void ethr_atomic32_init_mb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_init_mb__(var, val);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var = val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+
+}
+
+
+/* -- add_read() -- */
+
+
+ethr_sint32_t ethr_atomic32_add_read(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_add_read__(var, val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += val; res = *var);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_add_read_rb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_add_read_rb__(var, val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += val; res = *var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_add_read_wb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_add_read_wb__(var, val);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += val; res = *var);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_add_read_acqb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_add_read_acqb__(var, val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += val; res = *var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_add_read_relb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_add_read_relb__(var, val);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += val; res = *var);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_add_read_mb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_add_read_mb__(var, val);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += val; res = *var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+
+/* -- read() -- */
+
+
+ethr_sint32_t ethr_atomic32_read(ethr_atomic32_t *var)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_read__(var);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_read_rb(ethr_atomic32_t *var)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_read_rb__(var);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_read_wb(ethr_atomic32_t *var)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_read_wb__(var);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_read_acqb(ethr_atomic32_t *var)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_read_acqb__(var);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_read_relb(ethr_atomic32_t *var)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_read_relb__(var);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_read_mb(ethr_atomic32_t *var)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_read_mb__(var);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+#endif
+ return res;
+}
+
+
+/* -- inc_read() -- */
+
+
+ethr_sint32_t ethr_atomic32_inc_read(ethr_atomic32_t *var)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_inc_read__(var);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = ++(*var));
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_inc_read_rb(ethr_atomic32_t *var)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_inc_read_rb__(var);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = ++(*var));
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_inc_read_wb(ethr_atomic32_t *var)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_inc_read_wb__(var);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = ++(*var));
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_inc_read_acqb(ethr_atomic32_t *var)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_inc_read_acqb__(var);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = ++(*var));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_inc_read_relb(ethr_atomic32_t *var)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_inc_read_relb__(var);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = ++(*var));
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_inc_read_mb(ethr_atomic32_t *var)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_inc_read_mb__(var);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = ++(*var));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+
+/* -- dec_read() -- */
-/*
- * --- 32-bit atomics ---------------------------------------------------------
- */
-ethr_sint32_t *
-ethr_atomic32_addr(ethr_atomic32_t *var)
+ethr_sint32_t ethr_atomic32_dec_read(ethr_atomic32_t *var)
{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic32_addr__(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_dec_read__(var);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = --(*var));
+#endif
+ return res;
}
-void
-ethr_atomic32_init(ethr_atomic32_t *var, ethr_sint32_t i)
+ethr_sint32_t ethr_atomic32_dec_read_rb(ethr_atomic32_t *var)
{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- ethr_atomic32_init__(var, i);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_dec_read_rb__(var);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = --(*var));
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+ return res;
}
-void
-ethr_atomic32_set(ethr_atomic32_t *var, ethr_sint32_t i)
+ethr_sint32_t ethr_atomic32_dec_read_wb(ethr_atomic32_t *var)
{
+ ethr_sint32_t res;
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- ethr_atomic32_set__(var, i);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_dec_read_wb__(var);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = --(*var));
+#endif
+ return res;
}
-ethr_sint32_t
-ethr_atomic32_read(ethr_atomic32_t *var)
+ethr_sint32_t ethr_atomic32_dec_read_acqb(ethr_atomic32_t *var)
{
+ ethr_sint32_t res;
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic32_read__(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_dec_read_acqb__(var);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = --(*var));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
}
+ethr_sint32_t ethr_atomic32_dec_read_relb(ethr_atomic32_t *var)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_dec_read_relb__(var);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = --(*var));
+#endif
+ return res;
+}
-ethr_sint32_t
-ethr_atomic32_add_read(ethr_atomic32_t *var, ethr_sint32_t incr)
+ethr_sint32_t ethr_atomic32_dec_read_mb(ethr_atomic32_t *var)
{
+ ethr_sint32_t res;
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic32_add_read__(var, incr);
-}
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_dec_read_mb__(var);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = --(*var));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+
+/* -- add() -- */
-ethr_sint32_t
-ethr_atomic32_inc_read(ethr_atomic32_t *var)
+
+void ethr_atomic32_add(ethr_atomic32_t *var, ethr_sint32_t val)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic32_inc_read__(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_add__(var, val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += val);
+#endif
+
}
-ethr_sint32_t
-ethr_atomic32_dec_read(ethr_atomic32_t *var)
+void ethr_atomic32_add_rb(ethr_atomic32_t *var, ethr_sint32_t val)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic32_dec_read__(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_add_rb__(var, val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+
+}
+
+void ethr_atomic32_add_wb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_add_wb__(var, val);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += val);
+#endif
+
+}
+
+void ethr_atomic32_add_acqb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_add_acqb__(var, val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+
+}
+
+void ethr_atomic32_add_relb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_add_relb__(var, val);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += val);
+#endif
+
}
-void
-ethr_atomic32_add(ethr_atomic32_t *var, ethr_sint32_t incr)
+void ethr_atomic32_add_mb(ethr_atomic32_t *var, ethr_sint32_t val)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- ethr_atomic32_add__(var, incr);
-}
-
-void
-ethr_atomic32_inc(ethr_atomic32_t *var)
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_add_mb__(var, val);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, *var += val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+
+}
+
+
+/* -- inc() -- */
+
+
+void ethr_atomic32_inc(ethr_atomic32_t *var)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
ethr_atomic32_inc__(var);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, ++(*var));
+#endif
+
}
-void
-ethr_atomic32_dec(ethr_atomic32_t *var)
+void ethr_atomic32_inc_rb(ethr_atomic32_t *var)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- ethr_atomic32_dec__(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_inc_rb__(var);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, ++(*var));
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+
}
-ethr_sint32_t
-ethr_atomic32_read_band(ethr_atomic32_t *var, ethr_sint32_t mask)
+void ethr_atomic32_inc_wb(ethr_atomic32_t *var)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic32_read_band__(var, mask);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_inc_wb__(var);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, ++(*var));
+#endif
+
}
-ethr_sint32_t
-ethr_atomic32_read_bor(ethr_atomic32_t *var, ethr_sint32_t mask)
+void ethr_atomic32_inc_acqb(ethr_atomic32_t *var)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic32_read_bor__(var, mask);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_inc_acqb__(var);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, ++(*var));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+
}
-ethr_sint32_t
-ethr_atomic32_xchg(ethr_atomic32_t *var, ethr_sint32_t new)
+void ethr_atomic32_inc_relb(ethr_atomic32_t *var)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic32_xchg__(var, new);
-}
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_inc_relb__(var);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, ++(*var));
+#endif
-ethr_sint32_t
-ethr_atomic32_cmpxchg(ethr_atomic32_t *var,
- ethr_sint32_t new,
- ethr_sint32_t expected)
+}
+
+void ethr_atomic32_inc_mb(ethr_atomic32_t *var)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic32_cmpxchg__(var, new, expected);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_inc_mb__(var);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, ++(*var));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+
}
-ethr_sint32_t
-ethr_atomic32_read_acqb(ethr_atomic32_t *var)
+
+/* -- dec() -- */
+
+
+void ethr_atomic32_dec(ethr_atomic32_t *var)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic32_read_acqb__(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_dec__(var);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, --(*var));
+#endif
+
+}
+
+void ethr_atomic32_dec_rb(ethr_atomic32_t *var)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_dec_rb__(var);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, --(*var));
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+
}
-ethr_sint32_t
-ethr_atomic32_inc_read_acqb(ethr_atomic32_t *var)
+void ethr_atomic32_dec_wb(ethr_atomic32_t *var)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic32_inc_read_acqb__(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_dec_wb__(var);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, --(*var));
+#endif
+
}
-void
-ethr_atomic32_set_relb(ethr_atomic32_t *var, ethr_sint32_t i)
+void ethr_atomic32_dec_acqb(ethr_atomic32_t *var)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- ethr_atomic32_set_relb__(var, i);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_dec_acqb__(var);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, --(*var));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+
}
-void
-ethr_atomic32_dec_relb(ethr_atomic32_t *var)
+void ethr_atomic32_dec_relb(ethr_atomic32_t *var)
{
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
ethr_atomic32_dec_relb__(var);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, --(*var));
+#endif
+
+}
+
+void ethr_atomic32_dec_mb(ethr_atomic32_t *var)
+{
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_dec_mb__(var);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, --(*var));
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+
+}
+
+
+/* -- read_band() -- */
+
+
+ethr_sint32_t ethr_atomic32_read_band(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_read_band__(var, val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var &= val);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_read_band_rb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_read_band_rb__(var, val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_read_band_wb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_read_band_wb__(var, val);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var &= val);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_read_band_acqb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_read_band_acqb__(var, val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_read_band_relb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_read_band_relb__(var, val);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var &= val);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_read_band_mb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_read_band_mb__(var, val);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var &= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+
+/* -- read_bor() -- */
+
+
+ethr_sint32_t ethr_atomic32_read_bor(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_read_bor__(var, val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var |= val);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_read_bor_rb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_read_bor_rb__(var, val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad);
+#endif
+ return res;
}
-ethr_sint32_t
-ethr_atomic32_dec_read_relb(ethr_atomic32_t *var)
+ethr_sint32_t ethr_atomic32_read_bor_wb(ethr_atomic32_t *var, ethr_sint32_t val)
{
+ ethr_sint32_t res;
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic32_dec_read_relb__(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_read_bor_wb__(var, val);
+#else
+ ETHR_MEMBAR(ETHR_StoreStore);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var |= val);
+#endif
+ return res;
}
-ethr_sint32_t
-ethr_atomic32_cmpxchg_acqb(ethr_atomic32_t *var,
- ethr_sint32_t new,
- ethr_sint32_t exp)
+ethr_sint32_t ethr_atomic32_read_bor_acqb(ethr_atomic32_t *var, ethr_sint32_t val)
{
+ ethr_sint32_t res;
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic32_cmpxchg_acqb__(var, new, exp);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_read_bor_acqb__(var, val);
+#else
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
}
-ethr_sint32_t
-ethr_atomic32_cmpxchg_relb(ethr_atomic32_t *var,
- ethr_sint32_t new,
- ethr_sint32_t exp)
+ethr_sint32_t ethr_atomic32_read_bor_relb(ethr_atomic32_t *var, ethr_sint32_t val)
{
+ ethr_sint32_t res;
ETHR_ASSERT(!ethr_not_inited__);
ETHR_ASSERT(var);
- return ethr_atomic32_cmpxchg_relb__(var, new, exp);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_read_bor_relb__(var, val);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var |= val);
+#endif
+ return res;
+}
+
+ethr_sint32_t ethr_atomic32_read_bor_mb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+ ethr_sint32_t res;
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(var);
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ res = ethr_atomic32_read_bor_mb__(var, val);
+#else
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);
+ ETHR_ATOMIC_OP_FALLBACK_IMPL__(var, res = *var; *var |= val);
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);
+#endif
+ return res;
+}
+
+
+
+/* --------- Info functions --------- */
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+char *zero_ops[] = {NULL};
+#endif
+
+
+static char *native_su_dw_atomic_ops[] = {
+#ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_CMPXCHG
+ "cmpxchg",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_CMPXCHG_RB
+ "cmpxchg_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_CMPXCHG_WB
+ "cmpxchg_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_CMPXCHG_ACQB
+ "cmpxchg_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_CMPXCHG_RELB
+ "cmpxchg_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_CMPXCHG_MB
+ "cmpxchg_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_SET
+ "set",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_SET_RB
+ "set_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_SET_WB
+ "set_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_SET_ACQB
+ "set_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_SET_RELB
+ "set_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_SET_MB
+ "set_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_READ
+ "read",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_READ_RB
+ "read_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_READ_WB
+ "read_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_READ_ACQB
+ "read_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_READ_RELB
+ "read_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_READ_MB
+ "read_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_INIT
+ "init",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_INIT_RB
+ "init_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_INIT_WB
+ "init_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_INIT_ACQB
+ "init_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_INIT_RELB
+ "init_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_INIT_MB
+ "init_mb",
+#endif
+ NULL
+};
+
+char **
+ethr_native_su_dw_atomic_ops(void)
+{
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (!ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ return &zero_ops[0];
+#endif
+ return &native_su_dw_atomic_ops[0];
+}
+
+
+static char *native_dw_atomic_ops[] = {
+#ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_CMPXCHG
+ "cmpxchg",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_CMPXCHG_RB
+ "cmpxchg_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_CMPXCHG_WB
+ "cmpxchg_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_CMPXCHG_ACQB
+ "cmpxchg_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_CMPXCHG_RELB
+ "cmpxchg_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_CMPXCHG_MB
+ "cmpxchg_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_SET
+ "set",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_SET_RB
+ "set_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_SET_WB
+ "set_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_SET_ACQB
+ "set_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_SET_RELB
+ "set_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_SET_MB
+ "set_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_READ
+ "read",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_READ_RB
+ "read_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_READ_WB
+ "read_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_READ_ACQB
+ "read_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_READ_RELB
+ "read_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_READ_MB
+ "read_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_INIT
+ "init",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_INIT_RB
+ "init_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_INIT_WB
+ "init_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_INIT_ACQB
+ "init_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_INIT_RELB
+ "init_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_INIT_MB
+ "init_mb",
+#endif
+ NULL
+};
+
+char **
+ethr_native_dw_atomic_ops(void)
+{
+
+#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ if (!ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
+ return &zero_ops[0];
+#endif
+ return &native_dw_atomic_ops[0];
+}
+
+
+static char *native_atomic64_ops[] = {
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG
+ "cmpxchg",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_RB
+ "cmpxchg_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_WB
+ "cmpxchg_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_ACQB
+ "cmpxchg_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_RELB
+ "cmpxchg_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_CMPXCHG_MB
+ "cmpxchg_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_XCHG
+ "xchg",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_XCHG_RB
+ "xchg_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_XCHG_WB
+ "xchg_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_XCHG_ACQB
+ "xchg_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_XCHG_RELB
+ "xchg_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_XCHG_MB
+ "xchg_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET
+ "set",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET_RB
+ "set_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET_WB
+ "set_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET_ACQB
+ "set_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET_RELB
+ "set_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_SET_MB
+ "set_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INIT
+ "init",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INIT_RB
+ "init_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INIT_WB
+ "init_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INIT_ACQB
+ "init_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INIT_RELB
+ "init_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INIT_MB
+ "init_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RETURN
+ "add_return",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RETURN_RB
+ "add_return_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RETURN_WB
+ "add_return_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RETURN_ACQB
+ "add_return_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RETURN_RELB
+ "add_return_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RETURN_MB
+ "add_return_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ
+ "read",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ_RB
+ "read_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ_WB
+ "read_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ_ACQB
+ "read_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ_RELB
+ "read_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_READ_MB
+ "read_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RETURN
+ "inc_return",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RETURN_RB
+ "inc_return_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RETURN_WB
+ "inc_return_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RETURN_ACQB
+ "inc_return_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RETURN_RELB
+ "inc_return_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RETURN_MB
+ "inc_return_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RETURN
+ "dec_return",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RETURN_RB
+ "dec_return_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RETURN_WB
+ "dec_return_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RETURN_ACQB
+ "dec_return_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RETURN_RELB
+ "dec_return_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RETURN_MB
+ "dec_return_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD
+ "add",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RB
+ "add_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_WB
+ "add_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_ACQB
+ "add_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_RELB
+ "add_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADD_MB
+ "add_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC
+ "inc",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RB
+ "inc_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_WB
+ "inc_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_ACQB
+ "inc_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_RELB
+ "inc_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_INC_MB
+ "inc_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC
+ "dec",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RB
+ "dec_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_WB
+ "dec_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_ACQB
+ "dec_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_RELB
+ "dec_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_DEC_MB
+ "dec_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_AND_RETOLD
+ "and_retold",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_AND_RETOLD_RB
+ "and_retold_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_AND_RETOLD_WB
+ "and_retold_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_AND_RETOLD_ACQB
+ "and_retold_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_AND_RETOLD_RELB
+ "and_retold_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_AND_RETOLD_MB
+ "and_retold_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_OR_RETOLD
+ "or_retold",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_OR_RETOLD_RB
+ "or_retold_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_OR_RETOLD_WB
+ "or_retold_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_OR_RETOLD_ACQB
+ "or_retold_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_OR_RETOLD_RELB
+ "or_retold_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC64_OR_RETOLD_MB
+ "or_retold_mb",
+#endif
+ NULL
+};
+
+char **
+ethr_native_atomic64_ops(void)
+{
+
+ return &native_atomic64_ops[0];
}
+
+static char *native_atomic32_ops[] = {
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG
+ "cmpxchg",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG_RB
+ "cmpxchg_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG_WB
+ "cmpxchg_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG_ACQB
+ "cmpxchg_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG_RELB
+ "cmpxchg_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_CMPXCHG_MB
+ "cmpxchg_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_XCHG
+ "xchg",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_XCHG_RB
+ "xchg_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_XCHG_WB
+ "xchg_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_XCHG_ACQB
+ "xchg_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_XCHG_RELB
+ "xchg_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_XCHG_MB
+ "xchg_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET
+ "set",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET_RB
+ "set_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET_WB
+ "set_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET_ACQB
+ "set_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET_RELB
+ "set_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_SET_MB
+ "set_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INIT
+ "init",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INIT_RB
+ "init_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INIT_WB
+ "init_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INIT_ACQB
+ "init_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INIT_RELB
+ "init_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INIT_MB
+ "init_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RETURN
+ "add_return",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RETURN_RB
+ "add_return_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RETURN_WB
+ "add_return_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RETURN_ACQB
+ "add_return_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RETURN_RELB
+ "add_return_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RETURN_MB
+ "add_return_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ
+ "read",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ_RB
+ "read_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ_WB
+ "read_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ_ACQB
+ "read_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ_RELB
+ "read_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_READ_MB
+ "read_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RETURN
+ "inc_return",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RETURN_RB
+ "inc_return_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RETURN_WB
+ "inc_return_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RETURN_ACQB
+ "inc_return_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RETURN_RELB
+ "inc_return_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RETURN_MB
+ "inc_return_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RETURN
+ "dec_return",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RETURN_RB
+ "dec_return_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RETURN_WB
+ "dec_return_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RETURN_ACQB
+ "dec_return_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RETURN_RELB
+ "dec_return_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RETURN_MB
+ "dec_return_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD
+ "add",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RB
+ "add_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_WB
+ "add_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_ACQB
+ "add_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_RELB
+ "add_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADD_MB
+ "add_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC
+ "inc",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RB
+ "inc_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_WB
+ "inc_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_ACQB
+ "inc_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_RELB
+ "inc_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_INC_MB
+ "inc_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC
+ "dec",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RB
+ "dec_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_WB
+ "dec_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_ACQB
+ "dec_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_RELB
+ "dec_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_DEC_MB
+ "dec_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_AND_RETOLD
+ "and_retold",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_AND_RETOLD_RB
+ "and_retold_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_AND_RETOLD_WB
+ "and_retold_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_AND_RETOLD_ACQB
+ "and_retold_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_AND_RETOLD_RELB
+ "and_retold_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_AND_RETOLD_MB
+ "and_retold_mb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_OR_RETOLD
+ "or_retold",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_OR_RETOLD_RB
+ "or_retold_rb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_OR_RETOLD_WB
+ "or_retold_wb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_OR_RETOLD_ACQB
+ "or_retold_acqb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_OR_RETOLD_RELB
+ "or_retold_relb",
+#endif
+#ifdef ETHR_HAVE_ETHR_NATIVE_ATOMIC32_OR_RETOLD_MB
+ "or_retold_mb",
+#endif
+ NULL
+};
+
+char **
+ethr_native_atomic32_ops(void)
+{
+
+ return &native_atomic32_ops[0];
+}
diff --git a/erts/lib_src/common/ethr_aux.c b/erts/lib_src/common/ethr_aux.c
index 2c3e25a805..521640317e 100644
--- a/erts/lib_src/common/ethr_aux.c
+++ b/erts/lib_src/common/ethr_aux.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -31,10 +31,6 @@
#define ETHR_INLINE_FUNC_NAME_(X) X ## __
#define ETHR_AUX_IMPL__
-#define ETHR_ATOMIC_IMPL__ /* Needed in order to pull in
- native atomic implementations
- for optimized fallbacks of
- spinlocks and rwspinlocks */
#include "ethread.h"
#include "ethr_internal.h"
#include <string.h>
@@ -75,10 +71,87 @@ static int main_threads;
static int init_ts_event_alloc(void);
+ethr_runtime_t ethr_runtime__
+#ifdef __GNUC__
+__attribute__ ((aligned (ETHR_CACHE_LINE_SIZE)))
+#endif
+ ;
+
+#if defined(ETHR_X86_RUNTIME_CONF__)
+
+/*
+ * x86/x86_64 specifics shared between windows and
+ * pthread implementations.
+ */
+
+#define ETHR_IS_X86_VENDOR(V, B, C, D) \
+ (sizeof(V) == 13 && is_x86_vendor((V), (B), (C), (D)))
+
+static ETHR_INLINE int
+is_x86_vendor(char *str, int ebx, int ecx, int edx)
+{
+ return (*((int *) &str[0]) == ebx
+ && *((int *) &str[sizeof(int)]) == edx
+ && *((int *) &str[sizeof(int)*2]) == ecx);
+}
+
+static void
+x86_init(void)
+{
+ int eax, ebx, ecx, edx;
+
+ eax = ebx = ecx = edx = 0;
+
+ ethr_x86_cpuid__(&eax, &ebx, &ecx, &edx);
+
+ if (eax > 0
+ && (ETHR_IS_X86_VENDOR("GenuineIntel", ebx, ecx, edx)
+ || ETHR_IS_X86_VENDOR("AuthenticAMD", ebx, ecx, edx))) {
+ eax = 1;
+ ethr_x86_cpuid__(&eax, &ebx, &ecx, &edx);
+ }
+ else {
+ /*
+ * The meaning of the feature flags for this
+ * vendor have not been verified.
+ */
+ eax = ebx = ecx = edx = 0;
+ }
+
+ /*
+ * The feature flags tested below have only been verified
+ * for vendors checked above. Also note that only these
+ * feature flags have been verified to have these specific
+ * meanings. If another feature flag test is introduced,
+ * it has to be verified to have the same meaning for all
+ * vendors above.
+ */
+
+#if ETHR_SIZEOF_PTR == 8
+ /* bit 13 of ecx is set if we have cmpxchg16b */
+ ethr_runtime__.conf.have_dw_cmpxchg = (ecx & (1 << 13));
+#elif ETHR_SIZEOF_PTR == 4
+ /* bit 8 of edx is set if we have cmpxchg8b */
+ ethr_runtime__.conf.have_dw_cmpxchg = (edx & (1 << 8));
+#else
+# error "Not supported"
+#endif
+ /* bit 26 of edx is set if we have sse2 */
+ ethr_runtime__.conf.have_sse2 = (edx & (1 << 26));
+}
+
+#endif /* ETHR_X86_RUNTIME_CONF__ */
+
+
int
ethr_init_common__(ethr_init_data *id)
{
int res;
+
+#if defined(ETHR_X86_RUNTIME_CONF__)
+ x86_init();
+#endif
+
if (id) {
ethr_thr_prepare_func__ = id->thread_create_prepare_func;
ethr_thr_parent_func__ = id->thread_create_parent_func;
diff --git a/erts/lib_src/common/ethr_mutex.c b/erts/lib_src/common/ethr_mutex.c
index 2ddef32dfc..e363279f2e 100644
--- a/erts/lib_src/common/ethr_mutex.c
+++ b/erts/lib_src/common/ethr_mutex.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -26,8 +26,9 @@
#include "config.h"
#endif
-#define ETHR_INLINE_FUNC_NAME_(X) X ## __
+#define ETHR_INLINE_MTX_FUNC_NAME_(X) X ## __
#define ETHR_MUTEX_IMPL__
+#define ETHR_TRY_INLINE_FUNCS
#include <limits.h>
#include "ethread.h"
@@ -222,9 +223,59 @@ rwmutex_try_complete_runlock(ethr_rwmutex *rwmtx,
int try_write_lock);
#endif
+/* -- Utilities used by multiple implementations -- */
+
+#if defined(ETHR_USE_OWN_RWMTX_IMPL__) || defined(ETHR_USE_OWN_MTX_IMPL__) \
+ || defined(ETHR_WIN32_THREADS)
+
+static ETHR_INLINE void
+enqueue(ethr_ts_event **queue,
+ ethr_ts_event *tse_start,
+ ethr_ts_event *tse_end)
+{
+ if (!*queue) {
+ *queue = tse_start;
+ tse_start->prev = tse_end;
+ tse_end->next = tse_start;
+ }
+ else {
+ tse_end->next = *queue;
+ tse_start->prev = (*queue)->prev;
+ (*queue)->prev->next = tse_start;
+ (*queue)->prev = tse_end;
+ }
+}
+
+
+static ETHR_INLINE void
+dequeue(ethr_ts_event **queue,
+ ethr_ts_event *tse_start,
+ ethr_ts_event *tse_end)
+{
+ if (tse_start->prev == tse_end) {
+ ETHR_ASSERT(*queue == tse_start && tse_end->next == tse_start);
+ *queue = NULL;
+ }
+ else {
+ if (*queue == tse_start)
+ *queue = tse_end->next;
+ tse_end->next->prev = tse_start->prev;
+ tse_start->prev->next = tse_end->next;
+ }
+}
+
+#endif
+
#if defined(ETHR_USE_OWN_RWMTX_IMPL__) || defined(ETHR_USE_OWN_MTX_IMPL__)
-/* -- Utilities operating both on ordinary mutexes and read write mutexes -- */
+static ETHR_INLINE void
+insert(ethr_ts_event *tse_pred, ethr_ts_event *tse)
+{
+ tse->next = tse_pred->next;
+ tse->prev = tse_pred;
+ tse_pred->next->prev = tse;
+ tse_pred->next = tse;
+}
static ETHR_INLINE void
rwmutex_freqread_wtng_rdrs_inc(ethr_rwmutex *rwmtx, ethr_ts_event *tse)
@@ -354,51 +405,6 @@ rwmutex_freqread_rdrs_read(ethr_rwmutex *rwmtx, int ix)
return res;
}
-
-static ETHR_INLINE void
-enqueue(ethr_ts_event **queue,
- ethr_ts_event *tse_start,
- ethr_ts_event *tse_end)
-{
- if (!*queue) {
- *queue = tse_start;
- tse_start->prev = tse_end;
- tse_end->next = tse_start;
- }
- else {
- tse_end->next = *queue;
- tse_start->prev = (*queue)->prev;
- (*queue)->prev->next = tse_start;
- (*queue)->prev = tse_end;
- }
-}
-
-static ETHR_INLINE void
-insert(ethr_ts_event *tse_pred, ethr_ts_event *tse)
-{
- tse->next = tse_pred->next;
- tse->prev = tse_pred;
- tse_pred->next->prev = tse;
- tse_pred->next = tse;
-}
-
-static ETHR_INLINE void
-dequeue(ethr_ts_event **queue,
- ethr_ts_event *tse_start,
- ethr_ts_event *tse_end)
-{
- if (tse_start->prev == tse_end) {
- ETHR_ASSERT(*queue == tse_start && tse_end->next == tse_start);
- *queue = NULL;
- }
- else {
- if (*queue == tse_start)
- *queue = tse_end->next;
- tse_end->next->prev = tse_start->prev;
- tse_start->prev->next = tse_end->next;
- }
-}
-
static void
event_wait(struct ethr_mutex_base_ *mtxb,
ethr_ts_event *tse,
@@ -1243,7 +1249,7 @@ ethr_cond_wait(ethr_cond *cnd, ethr_mutex *mtx)
return 0;
}
-#else
+#elif defined(ETHR_PTHREADS) && !defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS)
/* -- pthread mutex and condition variables -------------------------------- */
int
@@ -1260,6 +1266,12 @@ ethr_mutex_init(ethr_mutex *mtx)
}
int
+ethr_mutex_init_opt(ethr_mutex *mtx, ethr_mutex_opt *opt)
+{
+ return ethr_mutex_init(mtx);
+}
+
+int
ethr_mutex_destroy(ethr_mutex *mtx)
{
#if ETHR_XCHK
@@ -1292,6 +1304,12 @@ ethr_cond_init(ethr_cond *cnd)
}
int
+ethr_cond_init_opt(ethr_cond *cnd, ethr_cond_opt *opt)
+{
+ return ethr_cond_init(cnd);
+}
+
+int
ethr_cond_destroy(ethr_cond *cnd)
{
#if ETHR_XCHK
@@ -1353,7 +1371,388 @@ ethr_cond_wait(ethr_cond *cnd, ethr_mutex *mtx)
return res;
}
-#endif /* pthread_mutex */
+#elif defined(ETHR_WIN32_THREADS) || defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS)
+
+/*
+ * As of Vista/Server, 2008 Windows has condition variables that can be
+ * used with critical sections. However, we need to be able to run on
+ * older Windows versions too, so we need to implement condition variables
+ * ourselves.
+ */
+
+#ifdef ETHR_DBG_WIN_MTX_WITH_PTHREADS
+/*
+ * For debugging of this implementation on POSIX platforms...
+ */
+
+#define ethr_win_get_errno__() EINVAL
+#if defined(__GNUC__)
+#define __forceinline __inline__
+#else
+#define __forceinline
+#endif
+
+static int
+InitializeCriticalSectionAndSpinCount(CRITICAL_SECTION *cs, int sc)
+{
+ return 0 == pthread_mutex_init((pthread_mutex_t *) cs, NULL);
+}
+
+static void DeleteCriticalSection(CRITICAL_SECTION *cs)
+{
+ int res = pthread_mutex_destroy((pthread_mutex_t *) cs);
+ if (res != 0)
+ ETHR_FATAL_ERROR__(res);
+}
+
+int TryEnterCriticalSection(CRITICAL_SECTION *cs)
+{
+ int res;
+ res = pthread_mutex_trylock((pthread_mutex_t *) cs);
+ if (res != 0 && res != EBUSY)
+ ETHR_FATAL_ERROR__(res);
+ return res == 0;
+}
+
+void EnterCriticalSection(CRITICAL_SECTION *cs)
+{
+ int res = pthread_mutex_lock((pthread_mutex_t *) cs);
+ if (res != 0)
+ ETHR_FATAL_ERROR__(res);
+}
+
+void LeaveCriticalSection(CRITICAL_SECTION *cs)
+{
+ int res = pthread_mutex_unlock((pthread_mutex_t *) cs);
+ if (res != 0)
+ ETHR_FATAL_ERROR__(res);
+}
+
+#endif
+
+#define ETHR_CND_WAIT__ ((ethr_sint32_t) 0x11dead11)
+#define ETHR_CND_WAKEUP__ ((ethr_sint32_t) 0x11beef11)
+
+static __forceinline void
+cond_wakeup(ethr_ts_event *tse)
+{
+ ETHR_ASSERT(ethr_atomic32_read(&tse->uaflgs) == ETHR_CND_WAIT__);
+
+ ethr_atomic32_set_relb(&tse->uaflgs, ETHR_CND_WAKEUP__);
+ ethr_event_set(&tse->event);
+}
+
+void
+ethr_mutex_cond_wakeup__(ethr_mutex *mtx)
+{
+ /*
+ * Called by ethr_mutex_unlock() when we have
+ * cond signal/broadcast wakeups waiting to
+ * be completed.
+ */
+ ethr_ts_event *tse;
+
+ if (!mtx->posix_compliant) {
+ tse = mtx->wakeups;
+ dequeue(&mtx->wakeups, tse, tse);
+ }
+ else {
+ ethr_spin_lock(&mtx->lock);
+ tse = mtx->wakeups;
+ if (tse)
+ dequeue(&mtx->wakeups, tse, tse);
+ if (!mtx->wakeups)
+ ethr_atomic32_set_relb(&mtx->have_wakeups, 0);
+ ethr_spin_unlock(&mtx->lock);
+ }
+
+ LeaveCriticalSection(&mtx->cs);
+
+ ETHR_ASSERT(tse || mtx->posix_compliant);
+
+ /*
+ * We delay actual condition variable wakeup until
+ * this point when we have left the critical section.
+ * This in order to avoid that the other thread is
+ * woken and then right away have to go to sleep
+ * waiting for the critical section that we are in.
+ *
+ * We also only wake one thread at a time even if
+ * there are multiple threads waiting to be woken.
+ * Otherwise all but one will be woken and then right
+ * away have to go to sleep on the critical section.
+ * Since each wakeup is guaranteed to generate at
+ * least one lock/unlock sequence on this mutex, all
+ * threads will eventually be woken.
+ */
+
+ if (tse)
+ cond_wakeup(tse);
+}
+
+int
+ethr_mutex_init_opt(ethr_mutex *mtx, ethr_mutex_opt *opt)
+{
+ int spincount;
+#if ETHR_XCHK
+ if (!mtx) {
+ ETHR_ASSERT(0);
+ return EINVAL;
+ }
+ mtx->initialized = ETHR_MUTEX_INITIALIZED;
+#endif
+
+ spincount = opt ? opt->aux_spincount : 0;
+ if (spincount < 0)
+ spincount = 0;
+
+ if (!InitializeCriticalSectionAndSpinCount(&mtx->cs, spincount)) {
+#if ETHR_XCHK
+ mtx->initialized = 0;
+#endif
+ return ethr_win_get_errno__();
+ }
+
+ mtx->posix_compliant = opt ? opt->posix_compliant : 0;
+ mtx->wakeups = NULL;
+ if (mtx->posix_compliant) {
+ ethr_atomic32_init(&mtx->locked, 0);
+ ethr_atomic32_init(&mtx->have_wakeups, 0);
+ ethr_spinlock_init(&mtx->lock);
+ }
+ return 0;
+}
+
+int
+ethr_mutex_init(ethr_mutex *mtx)
+{
+ return ethr_mutex_init_opt(mtx, NULL);
+}
+
+int
+ethr_mutex_destroy(ethr_mutex *mtx)
+{
+ DeleteCriticalSection(&mtx->cs);
+ if (mtx->posix_compliant)
+ return ethr_spinlock_destroy(&mtx->lock);
+ else
+ return 0;
+}
+
+int
+ethr_cond_wait(ethr_cond *cnd, ethr_mutex *mtx)
+{
+ void *udata;
+ ethr_ts_event *tse = ethr_get_ts_event();
+ int spincount;
+
+ udata = tse->udata;
+ tse->udata = (void *) mtx;
+ ethr_atomic32_set_relb(&tse->uaflgs, ETHR_CND_WAIT__);
+
+ EnterCriticalSection(&cnd->cs);
+ enqueue(&cnd->waiters, tse, tse);
+ LeaveCriticalSection(&cnd->cs);
+
+ ethr_mutex_unlock(mtx);
+
+ spincount = cnd->spincount;
+
+ while (ethr_atomic32_read_acqb(&tse->uaflgs) != ETHR_CND_WAKEUP__) {
+ ethr_event_reset(&tse->event);
+ if (ethr_atomic32_read_acqb(&tse->uaflgs) == ETHR_CND_WAKEUP__)
+ break;
+ ethr_event_swait(&tse->event, spincount);
+ spincount = 0;
+ }
+
+ tse->udata = udata;
+ ethr_leave_ts_event(tse);
+
+ ethr_mutex_lock(mtx);
+
+ return 0;
+}
+
+static __forceinline void
+posix_compliant_mtx_enqueue(ethr_mutex *mtx,
+ ethr_ts_event *tse_start,
+ ethr_ts_event *tse_end)
+{
+ ethr_ts_event *tse_wakeup = NULL; /* Avoid erroneous compiler warning... */
+ /*
+ * The associated mutex might not be locked, so we need to
+ * check if it is. If locked, enqueue for wakeup at unlock;
+ * otherwise, wakeup the first one now and enqueue the rest.
+ */
+ if (tse_start == tse_end && !ethr_atomic32_read(&mtx->locked)) {
+ tse_wakeup = tse_start;
+ wakeup:
+ cond_wakeup(tse_wakeup);
+ }
+ else {
+ int need_wakeup;
+ ethr_spin_lock(&mtx->lock);
+ if (!mtx->wakeups)
+ ethr_atomic32_set_mb(&mtx->have_wakeups, 1);
+ need_wakeup = !ethr_atomic32_read(&mtx->locked);
+ if (need_wakeup) {
+ if (tse_start == tse_end) {
+ if (!mtx->wakeups)
+ ethr_atomic32_set_relb(&mtx->have_wakeups, 0);
+ ethr_spin_unlock(&mtx->lock);
+ tse_wakeup = tse_start;
+ goto wakeup;
+ }
+ tse_wakeup = tse_start;
+ tse_start = tse_start->next;
+ }
+ enqueue(&mtx->wakeups, tse_start, tse_end);
+ ethr_spin_unlock(&mtx->lock);
+ if (need_wakeup)
+ goto wakeup;
+ }
+}
+
+static __forceinline void
+enqueue_cond_wakeups(ethr_ts_event *queue, int posix_compliant)
+{
+ if (queue) {
+ int more;
+ ethr_ts_event *q = queue;
+
+ /*
+ * Waiters may be using different mutexes...
+ */
+
+ do {
+ ethr_mutex *mtx;
+ ethr_ts_event *tse, *tse_start, *tse_end;
+
+ more = 0;
+ tse_start = q;
+ mtx = (ethr_mutex *) tse_start->udata;
+
+ ETHR_ASSERT(posix_compliant
+ ? mtx->posix_compliant
+ : !mtx->posix_compliant);
+
+ ETHR_ASSERT(ethr_atomic32_read(&tse_start->uaflgs)
+ == ETHR_CND_WAIT__);
+ ETHR_ASSERT(mtx->initialized == ETHR_MUTEX_INITIALIZED);
+
+ tse_end = tse_start->prev;
+
+ for (tse = tse_start->next; tse != tse_start; tse = tse->next) {
+
+ ETHR_ASSERT(ethr_atomic32_read(&tse->uaflgs)
+ == ETHR_CND_WAIT__);
+
+ if (mtx != (ethr_mutex *) tse->udata) {
+ tse_end = tse->prev;
+ dequeue(&q, tse_start, tse_end);
+ more = 1;
+ break;
+ }
+ }
+
+ if (posix_compliant)
+ posix_compliant_mtx_enqueue(mtx, tse_start, tse_end);
+ else
+ enqueue(&mtx->wakeups, tse_start, tse_end);
+
+ } while (more);
+ }
+}
+
+void
+ethr_cond_broadcast(ethr_cond *cnd)
+{
+ ethr_ts_event *waiters;
+
+ EnterCriticalSection(&cnd->cs);
+ waiters = cnd->waiters;
+ cnd->waiters = NULL;
+ LeaveCriticalSection(&cnd->cs);
+
+ if (cnd->posix_compliant)
+ enqueue_cond_wakeups(waiters, 1);
+ else
+ enqueue_cond_wakeups(waiters, 0);
+}
+
+void
+ethr_cond_signal(ethr_cond *cnd)
+{
+ ethr_mutex *mtx;
+ ethr_ts_event *tse;
+
+ EnterCriticalSection(&cnd->cs);
+ tse = cnd->waiters;
+ if (tse)
+ dequeue(&cnd->waiters, tse, tse);
+ LeaveCriticalSection(&cnd->cs);
+
+ if (tse) {
+ mtx = (ethr_mutex *) tse->udata;
+
+ ETHR_ASSERT(ethr_atomic32_read(&tse->uaflgs) == ETHR_CND_WAIT__);
+ ETHR_ASSERT(mtx->initialized == ETHR_MUTEX_INITIALIZED);
+ ETHR_ASSERT(cnd->posix_compliant
+ ? mtx->posix_compliant
+ : !mtx->posix_compliant);
+
+ if (cnd->posix_compliant)
+ posix_compliant_mtx_enqueue(mtx, tse, tse);
+ else
+ enqueue(&mtx->wakeups, tse, tse);
+ }
+}
+
+int
+ethr_cond_init_opt(ethr_cond *cnd, ethr_cond_opt *opt)
+{
+ int spincount;
+
+#if ETHR_XCHK
+ if (!cnd) {
+ ETHR_ASSERT(0);
+ return EINVAL;
+ }
+ cnd->initialized = ETHR_COND_INITIALIZED;
+#endif
+
+ spincount = opt ? opt->aux_spincount : 0;
+ if (spincount < 0)
+ spincount = 0;
+
+ if (!InitializeCriticalSectionAndSpinCount(&cnd->cs, spincount)) {
+#if ETHR_XCHK
+ cnd->initialized = 0;
+#endif
+ return ethr_win_get_errno__();
+ }
+
+ cnd->posix_compliant = opt ? opt->posix_compliant : 0;
+ cnd->waiters = NULL;
+ cnd->spincount = spincount;
+ return 0;
+}
+
+int
+ethr_cond_init(ethr_cond *cnd)
+{
+ return ethr_cond_init_opt(cnd, NULL);
+}
+
+int
+ethr_cond_destroy(ethr_cond *cnd)
+{
+ DeleteCriticalSection(&cnd->cs);
+ return 0;
+}
+
+#endif
/* -- Exported symbols of inline functions --------------------------------- */
@@ -1968,7 +2367,7 @@ dbg_unlock_wake(ethr_rwmutex *rwmtx,
exp = have_w ? ETHR_RWMTX_W_FLG__ : 0;
if (rwmtx->type != ETHR_RWMUTEX_TYPE_NORMAL)
- imask = ETHR_RWMTX_R_PEND_UNLCK_MASK__;
+ imask = ETHR_RWMTX_R_PEND_UNLCK_MASK__|ETHR_RWMTX_R_ABRT_UNLCK_FLG__;
else {
#ifdef ETHR_RLOCK_WITH_INC_DEC
imask = ETHR_RWMTX_RS_MASK__;
diff --git a/erts/lib_src/pthread/ethr_x86_sse2_asm.c b/erts/lib_src/pthread/ethr_x86_sse2_asm.c
new file mode 100644
index 0000000000..6cbe73cf16
--- /dev/null
+++ b/erts/lib_src/pthread/ethr_x86_sse2_asm.c
@@ -0,0 +1,31 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description: sse2 asm:s
+ * Author: Rickard Green
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* ETHR_X86_SSE2_ASM_C__ will trigger asm:s to compile to be included */
+#define ETHR_X86_SSE2_ASM_C__
+#include "ethread.h"
diff --git a/erts/lib_src/pthread/ethread.c b/erts/lib_src/pthread/ethread.c
index f047104103..ad29249bac 100644
--- a/erts/lib_src/pthread/ethread.c
+++ b/erts/lib_src/pthread/ethread.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -121,6 +121,98 @@ ethr_ts_event *ethr_get_tse__(void)
return pthread_getspecific(ethr_ts_event_key__);
}
+#if defined(ETHR_PPC_RUNTIME_CONF__)
+
+static volatile int lwsync_caused_sigill;
+
+static void
+handle_lwsync_sigill(int signum)
+{
+ lwsync_caused_sigill = 1;
+}
+
+static int
+ppc_init__(void)
+{
+ struct sigaction act, oact;
+ lwsync_caused_sigill = 0;
+
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ act.sa_handler = handle_lwsync_sigill;
+ if (sigaction(SIGILL, &act, &oact) != 0)
+ return errno;
+
+ __asm__ __volatile__ ("lwsync\n\t" : : : "memory");
+
+ act.sa_flags = 0;
+ act.sa_handler = SIG_DFL;
+ if (sigaction(SIGILL, &act, &oact) != 0)
+ return errno;
+
+ ethr_runtime__.conf.have_lwsync = (int) !lwsync_caused_sigill;
+ return 0;
+}
+
+#endif
+
+#if defined(ETHR_X86_RUNTIME_CONF__)
+
+void
+ethr_x86_cpuid__(int *eax, int *ebx, int *ecx, int *edx)
+{
+#if ETHR_SIZEOF_PTR == 4
+ int have_cpuid;
+ /*
+ * If it is possible to toggle eflags bit 21,
+ * we have the cpuid instruction.
+ */
+ __asm__ ("pushf\n\t"
+ "popl %%eax\n\t"
+ "movl %%eax, %%ecx\n\t"
+ "xorl $0x200000, %%eax\n\t"
+ "pushl %%eax\n\t"
+ "popf\n\t"
+ "pushf\n\t"
+ "popl %%eax\n\t"
+ "movl $0x0, %0\n\t"
+ "xorl %%ecx, %%eax\n\t"
+ "jz no_cpuid\n\t"
+ "movl $0x1, %0\n\t"
+ "no_cpuid:\n\t"
+ : "=r"(have_cpuid)
+ :
+ : "%eax", "%ecx", "cc");
+ if (!have_cpuid) {
+ *eax = *ebx = *ecx = *edx = 0;
+ return;
+ }
+#endif
+#if ETHR_SIZEOF_PTR == 4 && defined(__PIC__) && __PIC__
+ /*
+ * When position independet code is used in 32-bit mode, the B register
+ * is used for storage of global offset table address, and we may not
+ * use it as input or output in an asm. We need to save and restore the
+ * B register explicitly (for some reason gcc doesn't provide this
+ * service to us).
+ */
+ __asm__ ("pushl %%ebx\n\t"
+ "cpuid\n\t"
+ "movl %%ebx, %1\n\t"
+ "popl %%ebx\n\t"
+ : "=a"(*eax), "=r"(*ebx), "=c"(*ecx), "=d"(*edx)
+ : "0"(*eax)
+ : "cc");
+#else
+ __asm__ ("cpuid\n\t"
+ : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
+ : "0"(*eax)
+ : "cc");
+#endif
+}
+
+#endif /* ETHR_X86_RUNTIME_CONF__ */
+
/*
* --------------------------------------------------------------------------
* Exported functions
@@ -137,6 +229,12 @@ ethr_init(ethr_init_data *id)
ethr_not_inited__ = 0;
+#if defined(ETHR_PPC_RUNTIME_CONF__)
+ res = ppc_init__();
+ if (res != 0)
+ goto error;
+#endif
+
res = ethr_init_common__(id);
if (res != 0)
goto error;
@@ -146,6 +244,8 @@ ethr_init(ethr_init_data *id)
child_wait_spin_count = 0;
res = pthread_key_create(&ethr_ts_event_key__, ethr_ts_event_destructor__);
+ if (res != 0)
+ goto error;
return 0;
error:
diff --git a/erts/lib_src/utils/make_atomics_api b/erts/lib_src/utils/make_atomics_api
new file mode 100755
index 0000000000..f4e71c7618
--- /dev/null
+++ b/erts/lib_src/utils/make_atomics_api
@@ -0,0 +1,2186 @@
+#!/usr/bin/env escript
+%% -*- erlang -*-
+
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-mode(compile).
+
+%%%-------------------------------------------------------------------
+%%% @author Rickard Green <[email protected]>
+%%% @copyright (C) 2011, Rickard Green
+%%% @doc
+%%% Generation of the ethread atomic API
+%%% @end
+%%% Created : 17 Jan 2011 by Rickard Green <[email protected]>
+%%%-------------------------------------------------------------------
+
+-define(H_FILE, "erts/include/internal/ethr_atomics.h").
+-define(C_FILE, "erts/lib_src/common/ethr_atomics.c").
+
+%% These order constraints are important:
+%% - 'cmpxchg' needs to appear before 'read'
+%% - 'xchg' needs to apper before 'set'
+%% - 'set' needs to apper before 'init'
+%% - 'add_read' needs to apper before 'add', 'inc_read', and 'dec_read'
+%% - 'inc_read' needs to apper before and 'inc'
+%% - 'dec_read' needs to apper before and 'dec'
+-define(ATOMIC_OPS, [cmpxchg, xchg, set, init, add_read,
+ read, inc_read, dec_read, add, inc,
+ dec, read_band, read_bor]).
+
+-define(DW_ATOMIC_OPS, [cmpxchg, set, read, init]).
+-define(DW_FUNC_MACRO, "ETHR_DW_ATOMIC_FUNC__").
+-define(DW_RTCHK_MACRO, "ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__").
+
+%% Barrier versions we implement
+-define(BARRIERS, [none, rb, wb, acqb, relb, mb]).
+
+-define(ATOMIC_SIZES, ["dword", "word", "32"]).
+
+-define(HAVE_NATIVE_ATOMIC, "ETHR_HAVE_ETHR_NATIVE_ATOMIC").
+
+-define(SU_DW_SINT_FIELD, "dw_sint").
+-define(DW_SINT_FIELD, "sint").
+
+%% Fallback
+-define(ETHR_ATMC_FLLBK_ADDR_BITS, "10").
+-define(ETHR_ATMC_FLLBK_ADDR_SHIFT, "6").
+
+-record(atomic_context, {dw,
+ amc_fallback,
+ ret_type,
+ ret_var,
+ arg1,
+ arg2,
+ arg3,
+ have_native_atomic_ops,
+ atomic,
+ atomic_t,
+ addr_aint_t,
+ aint_t,
+ naint_t,
+ 'NATMC',
+ 'ATMC',
+ unusual_val}).
+
+atomic_context("dword") ->
+ #atomic_context{dw = true,
+ amc_fallback = true,
+ ret_type = "int",
+ ret_var = "res",
+ arg1 = "var",
+ arg2 = "val",
+ arg3 = "old_val",
+ have_native_atomic_ops = "ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS",
+ atomic = "ethr_dw_atomic",
+ atomic_t = "ethr_dw_atomic_t",
+ addr_aint_t = "ethr_sint_t",
+ aint_t = "ethr_dw_sint_t",
+ naint_t = "ETHR_SU_DW_NAINT_T__",
+ 'NATMC' = "DW_NATMC",
+ 'ATMC' = "DW_ATMC",
+ unusual_val = "ETHR_UNUSUAL_SINT_VAL__"};
+atomic_context(Size) ->
+ {SizeSuffix, HaveSize, AMC} = case Size of
+ "word" -> {"", "WORD_SZ", true};
+ _ -> {Size, Size++"BIT", false}
+ end,
+ AintT = ["ethr_sint", SizeSuffix, "_t"],
+ #atomic_context{dw = false,
+ amc_fallback = AMC,
+ ret_type = AintT,
+ ret_var = "res",
+ arg1 = "var",
+ arg2 = "val",
+ arg3 = "old_val",
+ have_native_atomic_ops = ["ETHR_HAVE_", HaveSize, "_NATIVE_ATOMIC_OPS"],
+ atomic = ["ethr_atomic", SizeSuffix],
+ atomic_t = ["ethr_atomic", SizeSuffix, "_t"],
+ addr_aint_t = AintT,
+ aint_t = AintT,
+ naint_t = ["ETHR_NAINT", SizeSuffix, "_T__"],
+ 'NATMC' = ["NATMC", SizeSuffix],
+ 'ATMC' = ["ATMC", SizeSuffix],
+ unusual_val = ["ETHR_UNUSUAL_SINT", SizeSuffix, "_VAL__"]}.
+
+-record(op_context, {ret, var, val1, val2}).
+
+-define(POTENTIAL_NBITS, ["64", "32"]).
+
+is_return_op(#atomic_context{dw = false}, add) -> false;
+is_return_op(#atomic_context{dw = false}, inc) -> false;
+is_return_op(#atomic_context{dw = false}, dec) -> false;
+is_return_op(#atomic_context{dw = true}, read) -> false;
+is_return_op(_AC, init) -> false;
+is_return_op(_AC, set) -> false;
+is_return_op(_AC, _OP) -> true.
+
+native(add_read) -> add_return;
+native(inc_read) -> inc_return;
+native(dec_read) -> dec_return;
+native(read_band) -> and_retold;
+native(read_bor) -> or_retold;
+native(Op) -> Op.
+
+op(Op, #op_context{var = Var, val1 = Val1}) when Op == init; Op == set ->
+ [Var, " = ", Val1];
+op(read, #op_context{ret = Ret, var = Var}) ->
+ [Ret, " = ", Var];
+op(add_read, OpC) ->
+ [op(add, OpC), "; ", op(read, OpC)];
+op(add, #op_context{var = Var, val1 = Val1}) ->
+ [Var, " += ", Val1];
+op(inc, #op_context{var = Var}) ->
+ ["++(", Var, ")"];
+op(dec, #op_context{var = Var}) ->
+ ["--(", Var, ")"];
+op(inc_read, #op_context{ret = Ret, var = Var}) ->
+ [Ret, " = ++(", Var, ")"];
+op(dec_read, #op_context{ret = Ret, var = Var}) ->
+ [Ret, " = --(", Var, ")"];
+op(read_band, #op_context{var = Var, val1 = Val1} = OpC) ->
+ [op(read, OpC), "; ", Var, " &= ", Val1];
+op(read_bor, #op_context{var = Var, val1 = Val1} = OpC) ->
+ [op(read, OpC), "; ", Var, " |= ", Val1];
+op(xchg, OpC) ->
+ [op(read, OpC), "; ", op(set, OpC)];
+op(cmpxchg, #op_context{ret = Ret, var = Var, val1 = Val1, val2 = Val2}) ->
+ [Ret, " = (", Var, " == ", Val2, " ? (", Var, " = ", Val1, ", ", Val2, ") : ", Var, ")"].
+
+dw_op(Op, #op_context{var = Var, val1 = Val1}) when Op == init; Op == set ->
+ [Var, "[0] = ", Val1, "[0]; ", Var, "[1] = ", Val1, "[1]"];
+dw_op(read, #op_context{var = Var, val1 = Val1}) ->
+ [Val1, "[0] = ", Var, "[0]; ", Val1, "[1] = ", Var, "[1]"];
+dw_op(cmpxchg, #op_context{ret = Ret, var = Var, val1 = Val1, val2 = Val2}) ->
+ ["
+ {
+ ", Ret, " = (", Var, "[0] == ", Val2, "[0] && ", Var, "[1] == ", Val2, "[1]);
+ if (", Ret, ") {
+ ", Var, "[0] = ", Val1, "[0];
+ ", Var, "[1] = ", Val1, "[1];
+ }
+ else {
+ ", Val2, "[0] = ", Var, "[0];
+ ", Val2, "[1] = ", Var, "[1];
+ }
+ }"].
+
+op_head_tail(init) -> {undef, undef};
+op_head_tail(set) -> {store, store};
+op_head_tail(read) -> {load, load};
+op_head_tail(_) -> {load, undef}.
+
+op_barrier_ext(none) -> "";
+op_barrier_ext(Barrier) -> [$_, a2l(Barrier)].
+
+op_call(addr, _DW, Ret, Func, Arg1, _Arg2, _Arg3, _TypeCast) ->
+ [Ret, " ", Func, "(", Arg1, ");"];
+op_call(Op, false, Ret, Func, Arg1, _Arg2, _Arg3, _TypeCast) when Op == read;
+ Op == inc_read;
+ Op == inc_return;
+ Op == dec_read;
+ Op == dec_return ->
+ [Ret, " ", Func, "(", Arg1, ");"];
+op_call(Op, false, _Ret, Func, Arg1, _Arg2, _Arg3, _TypeCast) when Op == inc;
+ Op == dec ->
+ [Func, "(", Arg1, ");"];
+op_call(Op, false, Ret, Func, Arg1, Arg2, _Arg3, TypeCast) when Op == add_return;
+ Op == add_read;
+ Op == read_band;
+ Op == and_retold;
+ Op == read_bor;
+ Op == or_retold;
+ Op == xchg ->
+ [Ret, " ", Func, "(", Arg1, ",", TypeCast, " ", Arg2, ");"];
+op_call(cmpxchg, _DW, Ret, Func, Arg1, Arg2, Arg3, TypeCast) ->
+ [Ret, " ", Func, "(", Arg1, ",", TypeCast, " ", Arg2, ",", TypeCast, " ", Arg3, ");"];
+op_call(_Op, _DW, _Ret, Func, Arg1, Arg2, _Arg3, TypeCast) ->
+ [Func, "(", Arg1, ",", TypeCast, " ", Arg2, ");"]. % set, init, add (!= dw), read (== dw)
+
+native_op_call(#atomic_context{dw = DW,
+ ret_var = RetVar,
+ arg1 = Arg1,
+ arg2 = Arg2,
+ arg3 = Arg3,
+ aint_t = AintT,
+ 'NATMC' = NATMC,
+ naint_t = NAintT},
+ Op, B, TypeCasts) ->
+ op_call(Op,
+ DW,
+ [RetVar, " =",
+ case TypeCasts of
+ true -> [" (", AintT, ")"];
+ false -> ""
+ end],
+ ["ETHR_", NATMC, "_FUNC__(", opstr(native(Op)), op_barrier_ext(B), ")"],
+ Arg1,
+ Arg2,
+ Arg3,
+ case TypeCasts of
+ true -> [" (", NAintT, ")"];
+ false -> ""
+ end).
+
+simple_fallback(#atomic_context{arg1 = Arg1,
+ arg2 = Arg2,
+ 'ATMC' = ATMC},
+ init, B) -> %% Also double word
+ [" ETHR_", ATMC, "_FUNC__(set", op_barrier_ext(B),")(", Arg1, ", ", Arg2, ");\n"];
+simple_fallback(#atomic_context{dw = false,
+ arg1 = Arg1,
+ arg2 = Arg2,
+ 'ATMC' = ATMC},
+ set, B) ->
+ [" (void) ETHR_", ATMC, "_FUNC__(xchg", op_barrier_ext(B),")(", Arg1, ", ", Arg2, ");\n"];
+simple_fallback(#atomic_context{dw = false,
+ arg1 = Arg1,
+ arg2 = Arg2,
+ 'ATMC' = ATMC},
+ add, B) ->
+ [" (void) ETHR_", ATMC, "_FUNC__(add_read", op_barrier_ext(B), ")(", Arg1, ", ", Arg2, ");\n"];
+simple_fallback(#atomic_context{dw = false,
+ ret_var = RetVar,
+ arg1 = Arg1,
+ aint_t = AintT,
+ 'ATMC' = ATMC},
+ inc_read, B) ->
+ [" ", RetVar, " = ETHR_", ATMC, "_FUNC__(add_read", op_barrier_ext(B), ")(", Arg1, ", (", AintT,") 1);\n"];
+simple_fallback(#atomic_context{dw = false,
+ ret_var = RetVar,
+ arg1 = Arg1,
+ aint_t = AintT,
+ 'ATMC' = ATMC},
+ dec_read, B) ->
+ [" ", RetVar, " = ETHR_", ATMC, "_FUNC__(add_read", op_barrier_ext(B), ")(", Arg1, ", (", AintT,") -1);\n"];
+simple_fallback(#atomic_context{dw = false,
+ arg1 = Arg1,
+ 'ATMC' = ATMC},
+ inc, B) ->
+ [" (void) ETHR_", ATMC, "_FUNC__(inc_read", op_barrier_ext(B), ")(", Arg1, ");\n"];
+simple_fallback(#atomic_context{dw = false,
+ arg1 = Arg1,
+ 'ATMC' = ATMC},
+ dec, B) ->
+ [" (void) ETHR_", ATMC, "_FUNC__(dec_read", op_barrier_ext(B), ")(", Arg1, ");\n"];
+simple_fallback(#atomic_context{dw = false,
+ unusual_val = UnusualVal,
+ ret_var = RetVar,
+ arg1 = Arg1,
+ aint_t = AintT,
+ 'ATMC' = ATMC},
+ read, B) ->
+ [" ", RetVar, " = ETHR_", ATMC, "_FUNC__(cmpxchg", op_barrier_ext(B), ")(", Arg1, ", (", AintT, ") ", UnusualVal, ", (", AintT,") ", UnusualVal, ");\n"];
+simple_fallback(#atomic_context{dw = true,
+ unusual_val = UnusualVal,
+ arg1 = Arg1,
+ arg2 = Arg2,
+ aint_t = AintT,
+ 'ATMC' = ATMC},
+ read, B) ->
+ [" ", AintT, " tmp;
+ tmp.", ?DW_SINT_FIELD, "[0] = ", UnusualVal, ";
+ tmp.", ?DW_SINT_FIELD, "[1] = ", UnusualVal, ";
+ ", Arg2, "->", ?DW_SINT_FIELD, "[0] = ", UnusualVal, ";
+ ", Arg2, "->", ?DW_SINT_FIELD, "[1] = ", UnusualVal, ";
+ (void) ETHR_", ATMC, "_FUNC__(cmpxchg", op_barrier_ext(B), ")(", Arg1, ", &tmp, ", Arg2, ");
+"
+ ];
+simple_fallback(_AC, _Op, _B) ->
+ [].
+
+func_header(AC, prototype, MacroName, Op, B) ->
+ [func_header(AC, implementation, MacroName, Op, B), ";"];
+func_header(#atomic_context{'ATMC' = ATMC} = AC, inline_implementation, _MacroName, Op, B) ->
+ do_func_header(AC, Op, "static ETHR_INLINE ",
+ ["ETHR_", ATMC, "_FUNC__(", opstr(Op), op_barrier_ext(B), ")"]);
+func_header(#atomic_context{atomic = Atomic} = AC, implementation, false, Op, B) ->
+ do_func_header(AC, Op, "", [Atomic, "_", opstr(Op), op_barrier_ext(B)]);
+func_header(AC, implementation, MacroName, Op, B) ->
+ do_func_header(AC, Op, "", [MacroName, "(", opstr(Op), op_barrier_ext(B), ")"]).
+
+
+do_func_header(#atomic_context{atomic_t = AtomicT,
+ addr_aint_t = AddrAintT,
+ arg1 = Arg1},
+ addr, Inline, Func) ->
+ [Inline, AddrAintT, " *", Func, "(", AtomicT, " *", Arg1, ")"];
+do_func_header(#atomic_context{dw = false,
+ atomic_t = AtomicT,
+ aint_t = AintT,
+ arg1 = Arg1,
+ arg2 = Arg2},
+ Op, Inline, Func) when Op == init;
+ Op == set;
+ Op == add ->
+ [Inline, "void ", Func, "(", AtomicT, " *", Arg1, ", ", AintT, " ", Arg2, ")"];
+do_func_header(#atomic_context{dw = false,
+ atomic_t = AtomicT,
+ arg1 = Arg1},
+ Op, Inline, Func) when Op == inc;
+ Op == dec ->
+ [Inline, "void ", Func, "(", AtomicT, " *", Arg1, ")"];
+do_func_header(#atomic_context{dw = false,
+ atomic_t = AtomicT,
+ aint_t = AintT,
+ arg1 = Arg1},
+ Op, Inline, Func) when Op == read;
+ Op == inc_read;
+ Op == dec_read ->
+ [Inline, AintT, " ", Func, "(", AtomicT, " *", Arg1, ")"];
+do_func_header(#atomic_context{dw = false,
+ atomic_t = AtomicT,
+ aint_t = AintT,
+ arg1 = Arg1,
+ arg2 = Arg2},
+ Op, Inline, Func) when Op == add_read;
+ Op == read_band;
+ Op == read_bor;
+ Op == xchg ->
+ [Inline, AintT, " ", Func, "(", AtomicT, " *", Arg1, ", ", AintT, " ", Arg2, ")"];
+do_func_header(#atomic_context{dw = false,
+ atomic_t = AtomicT,
+ aint_t = AintT,
+ arg1 = Arg1,
+ arg2 = Arg2,
+ arg3 = Arg3},
+ cmpxchg, Inline, Func) ->
+ [Inline, AintT, " ", Func, "(", AtomicT, " *", Arg1, ", ", AintT, " ", Arg2, ", ", AintT, " ", Arg3, ")"];
+do_func_header(#atomic_context{dw = true,
+ atomic_t = AtomicT,
+ aint_t = AintT,
+ arg1 = Arg1,
+ arg2 = Arg2},
+ Op, Inline, Func) when Op == init;
+ Op == set;
+ Op == read ->
+ [Inline, "void ", Func, "(", AtomicT, " *", Arg1, ", ", AintT, " *", Arg2, ")"];
+do_func_header(#atomic_context{dw = true,
+ atomic_t = AtomicT,
+ aint_t = AintT,
+ arg1 = Arg1,
+ arg2 = Arg2,
+ arg3 = Arg3},
+ cmpxchg, Inline, Func) ->
+ [Inline, "int ", Func, "(", AtomicT, " *", Arg1, ", ", AintT, " *", Arg2, ", ", AintT, " *", Arg3, ")"].
+
+
+xbarriers(_Op, none, _NB) ->
+ {"", ""};
+
+xbarriers(_Op, acqb, NB) when NB == acqb; NB == mb ->
+ {"", ""};
+xbarriers(Op, acqb, NB) ->
+ case {op_head_tail(Op), NB} of
+ {{_, load}, rb} -> {"", "ETHR_MEMBAR(ETHR_LoadStore);"};
+ {{_, load}, _} -> {"", "ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);"};
+ {{_, store}, _} -> {"", "ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);"};
+ {_, rb} -> {"", "ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);"};
+ _ -> {"", "ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);"}
+ end;
+
+xbarriers(_Op, relb, NB) when NB == relb; NB == mb ->
+ {"", ""};
+xbarriers(Op, relb, NB) ->
+ case {op_head_tail(Op), NB} of
+ {{store, _}, wb} -> {"ETHR_MEMBAR(ETHR_LoadStore);", ""};
+ {{store, _}, _} -> {"ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);", ""};
+ {{load, _}, _} -> {"ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);", ""};
+ {_, wb} -> {"ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad);", ""};
+ _ -> {"ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);", ""}
+ end;
+
+xbarriers(_Op, wb, NB) when NB == wb; NB == mb ->
+ {"", ""};
+xbarriers(_Op, wb, _NB) ->
+ {"ETHR_MEMBAR(ETHR_StoreStore);", ""};
+
+xbarriers(_Op, rb, NB) when NB == rb; NB == mb ->
+ {"", ""};
+xbarriers(_Op, rb, _NB) ->
+ {"", "ETHR_MEMBAR(ETHR_LoadLoad);"};
+
+xbarriers(_Op, mb, mb) ->
+ {"", ""};
+xbarriers(Op, mb, NB) ->
+ MB = "ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);",
+ {Head, Tail} = op_head_tail(Op),
+ PreOp = case {Head, NB} of
+ {_, relb} -> "";
+ {store, wb} -> "ETHR_MEMBAR(ETHR_LoadStore);";
+ {store, _} -> "ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreStore);";
+ {load, _} -> "ETHR_MEMBAR(ETHR_LoadLoad|ETHR_StoreLoad);";
+ {_, wb} -> "ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad);";
+ _ -> MB
+ end,
+ PostOp = case {Tail, NB} of
+ {_, acqb} -> "";
+ {load, rb} -> "ETHR_MEMBAR(ETHR_LoadStore);";
+ {load, _} -> "ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);";
+ {store, _} -> "ETHR_MEMBAR(ETHR_StoreLoad|ETHR_StoreStore);";
+ {_, rb} -> "ETHR_MEMBAR(ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore);";
+ _ -> MB
+ end,
+ {PreOp, PostOp}.
+
+try_barrier_order_first(none) ->
+ [none, rb, wb, acqb, relb];
+try_barrier_order_first(acqb) ->
+ [acqb, rb, none, mb];
+try_barrier_order_first(relb) ->
+ [relb, wb, none, mb];
+try_barrier_order_first(rb) ->
+ [rb, none, mb];
+try_barrier_order_first(wb) ->
+ [wb, none, mb];
+try_barrier_order_first(mb) ->
+ [mb, relb, acqb, wb, rb, none].
+
+try_barrier_order(B) ->
+ First = try_barrier_order_first(B),
+ First ++ (?BARRIERS -- First).
+
+native_barrier_op(#atomic_context{'NATMC' = NATMC} = AC, If, ExtraDecl, Op, B, NB, TypeCasts) ->
+ NOpStr = opstr(native(Op)),
+ CapNOpStr = to_upper(NOpStr),
+ NBExt = op_barrier_ext(NB),
+ CapNBExt = to_upper(NBExt),
+ {PreB, PostB} = xbarriers(Op, B, NB),
+ [If, " defined(ETHR_HAVE_", NATMC, "_", CapNOpStr, CapNBExt, ")\n",
+ ExtraDecl,
+ case PreB of
+ "" -> "";
+ _ -> [" ", PreB, "\n"]
+ end,
+ " ", native_op_call(AC, Op, NB, TypeCasts), "\n",
+ case PostB of
+ "" -> "";
+ _ -> [" ", PostB, "\n"]
+ end].
+
+dw_native_barrier_op(#atomic_context{arg1 = Arg1, arg2 = Arg2, arg3 = Arg3} = AC, If, ExtraDecl, Op, B, NB) ->
+ native_barrier_op(AC#atomic_context{arg1 = ["&", Arg1, "->native"],
+ arg2 = [Arg2, "->", ?DW_SINT_FIELD],
+ arg3 = [Arg3, "->", ?DW_SINT_FIELD]},
+ If, ExtraDecl, Op, B, NB, false).
+
+su_dw_native_barrier_op(#atomic_context{dw = true,
+ naint_t = NAintT,
+ ret_var = RetVar,
+ arg1 = Arg1,
+ arg2 = Arg2,
+ arg3 = Arg3,
+ 'NATMC' = NATMC} = AC, If, cmpxchg, B, NB) ->
+ SU = ["->", ?SU_DW_SINT_FIELD],
+ TmpVar = "act",
+ SUArg1 = ["&", Arg1, "->native"],
+ SUArg2 = [Arg2, SU],
+ SUArg3 = [Arg3, SU],
+ ExtraDecl = [" ", NAintT, " ", TmpVar, ";\n"],
+ [native_barrier_op(AC#atomic_context{dw = false,
+ ret_var = TmpVar,
+ arg1 = SUArg1,
+ arg2 = SUArg2,
+ arg3 = SUArg3,
+ 'NATMC' = ["SU_", NATMC]},
+ If, ExtraDecl, cmpxchg, B, NB, false),
+ " ", RetVar, " = (", TmpVar, " == ", SUArg3, ");
+ ", SUArg3, " = ", TmpVar, ";
+"
+ ];
+su_dw_native_barrier_op(#atomic_context{dw = true,
+ arg1 = Arg1,
+ arg2 = Arg2,
+ 'NATMC' = NATMC} = AC, If, Op, B, NB) ->
+ SUArg1 = ["&", Arg1, "->native"],
+ SUArg2 = [Arg2, "->", ?SU_DW_SINT_FIELD],
+ native_barrier_op(AC#atomic_context{dw = false,
+ ret_var = SUArg2,
+ arg1 = SUArg1,
+ arg2 = SUArg2,
+ arg3 = not_used,
+ 'NATMC' = ["SU_", NATMC]}, If, "", Op, B, NB, false).
+
+cmpxchg_fallback_define(#atomic_context{dw = false, aint_t = AintT} = AC) ->
+ do_cmpxchg_fallback_define(AC, true, AintT);
+cmpxchg_fallback_define(#atomic_context{dw = true,
+ 'NATMC' = NATMC,
+ naint_t = NAintT} = AC) ->
+ ["\n\n#if defined(ETHR_HAVE_NATIVE_DW_ATOMIC)\n",
+ do_cmpxchg_fallback_define(AC, false, not_used),
+ "\n\n#elif defined(ETHR_HAVE_NATIVE_SU_DW_ATOMIC)\n",
+ do_cmpxchg_fallback_define(AC#atomic_context{'NATMC' = ["SU_", NATMC],
+ naint_t = NAintT},
+ true,
+ NAintT),
+ "
+
+#else
+# error \"?!?\"
+#endif
+"].
+
+do_cmpxchg_fallback_define(#atomic_context{'NATMC' = NATMC,
+ aint_t = AintT,
+ naint_t = NAintT},
+ SU, SUType) ->
+
+ ReadFunc = fun (IF) ->
+ fun (B) ->
+ BExt = op_barrier_ext(B),
+ CapBExt = to_upper(BExt),
+ [IF, " defined(ETHR_HAVE_", NATMC, "_READ", CapBExt, ")",
+ case SU of
+ true -> ["
+#define ETHR_", NATMC, "_CMPXCHG_FALLBACK_READ__(VAR) \\
+ ETHR_", NATMC, "_FUNC__(read", BExt, ")(VAR)
+"
+ ];
+ false -> ["
+#define ETHR_", NATMC, "_CMPXCHG_FALLBACK_READ__(VAR, VAL) \\
+ ETHR_", NATMC, "_FUNC__(read", BExt, ")(VAR, VAL)
+#elif defined(ETHR_HAVE_SU_", NATMC, "_READ", CapBExt, ")
+#define ETHR_", NATMC, "_CMPXCHG_FALLBACK_READ__(VAR, VAL) \\
+ VAL.", ?SU_DW_SINT_FIELD, " = ETHR_SU_", NATMC, "_FUNC__(read", BExt, ")(VAR)
+"
+ ]
+ end]
+ end
+ end,
+ NotDefCMPXCHG = fun (B) ->
+ CapBExt = to_upper(op_barrier_ext(B)),
+ ["!defined(ETHR_HAVE_", NATMC, "_CMPXCHG", CapBExt, ")"]
+ end,
+ NoneTryBarrierOrder = try_barrier_order(none),
+ %% First a sanity check
+ ["
+#if (", NotDefCMPXCHG(hd(?BARRIERS)) ,
+ lists:map(fun (B) ->
+ [" \\
+ && ", NotDefCMPXCHG(B)]
+ end,
+ tl(?BARRIERS)), ")
+# error \"No native cmpxchg() op available\"
+#endif
+
+
+/*
+ * Read op used together with cmpxchg() fallback when no native op present.
+ */
+",
+
+ %% Read op to use with cmpxchg fallback
+ (ReadFunc("#if"))(hd(NoneTryBarrierOrder)),
+ lists:map(ReadFunc("#elif"), tl(NoneTryBarrierOrder)),
+"#else
+/*
+ * We have no native read() op; guess zero and then use the
+ * the atomics actual value returned from cmpxchg().
+ */",
+ case SU of
+ true -> ["
+#define ETHR_", NATMC, "_CMPXCHG_FALLBACK_READ__(VAR) \\
+ ((", NAintT, ") 0)"];
+ false -> ["
+#define ETHR_", NATMC, "_CMPXCHG_FALLBACK_READ__(VAR, VAL) \\
+do { \\
+ VAL.", ?DW_SINT_FIELD, "[0] = (ethr_sint_t) 0; \\
+ VAL.", ?DW_SINT_FIELD, "[1] = (ethr_sint_t) 0; \\
+} while (0)"]
+ end, "
+#endif
+",
+
+ %% The fallback
+ "
+/*
+ * Native cmpxchg() fallback used when no native op present.
+ */
+#define ETHR_", NATMC, "_CMPXCHG_FALLBACK__(CMPXCHG, VAR, AVAL, OPS) \\
+do { \\",
+ case SU of
+ true -> ["
+ ", SUType, " AVAL; \\
+ ", NAintT, " new__, act__, exp__; \\
+ act__ = ETHR_", NATMC, "_CMPXCHG_FALLBACK_READ__(VAR); \\
+ do { \\
+ exp__ = act__; \\
+ AVAL = (", SUType, ") act__; \\
+ { OPS; } \\
+ new__ = (", NAintT, ") AVAL; \\
+ act__ = CMPXCHG(VAR, new__, exp__); \\
+ } while (__builtin_expect(act__ != exp__, 0)); \\"];
+ false -> ["
+ int res__; \\
+ ", AintT, " AVAL, exp_act__; \\
+ ETHR_", NATMC, "_CMPXCHG_FALLBACK_READ__(VAR, exp_act__); \\
+ do { \\
+ AVAL.", ?DW_SINT_FIELD, "[0] = exp_act__.", ?DW_SINT_FIELD, "[0]; \\
+ AVAL.", ?DW_SINT_FIELD, "[1] = exp_act__.", ?DW_SINT_FIELD, "[1]; \\
+ { OPS; } \\
+ res__ = CMPXCHG(VAR, AVAL.", ?DW_SINT_FIELD, ", exp_act__.", ?DW_SINT_FIELD, "); \\
+ } while (__builtin_expect(res__ == 0, 0)); \\"]
+ end, "
+} while (0)
+"
+ ].
+
+cmpxchg_fallbacks(#atomic_context{}, _SUDW, cmpxchg, _B) ->
+ ""; %% No need for a fallback
+cmpxchg_fallbacks(#atomic_context{dw = DW,
+ ret_var = RetVar,
+ arg1 = Arg1,
+ arg2 = Arg2,
+ arg3 = Arg3,
+ 'NATMC' = NATMC},
+ SUDW, Op, B) ->
+ Operation = case DW of
+ false ->
+ op(Op, #op_context{ret = RetVar,
+ var = "aval",
+ val1 = Arg2,
+ val2 = Arg3});
+ true ->
+ case SUDW of
+ true ->
+ op(Op, #op_context{ret = [Arg2, "->", ?SU_DW_SINT_FIELD],
+ var = "aval",
+ val1 = [Arg2, "->", ?SU_DW_SINT_FIELD]});
+ false ->
+ dw_op(Op, #op_context{ret = RetVar,
+ var = ["aval.", ?DW_SINT_FIELD],
+ val1 = [Arg2, "->", ?DW_SINT_FIELD]})
+ end
+ end,
+ [lists:map(fun (NB) ->
+ NativeVar = case DW of
+ true -> ["&", Arg1, "->native"];
+ false -> Arg1
+ end,
+ NBExt = op_barrier_ext(NB),
+ CapNBExt = to_upper(NBExt),
+ {PreB, PostB} = xbarriers(cmpxchg, B, NB),
+ ["#elif defined(ETHR_HAVE_", NATMC, "_CMPXCHG", CapNBExt, ")\n",
+ case PreB of
+ "" -> "";
+ _ -> [" ", PreB, "\n"]
+ end,
+ " ETHR_", NATMC, "_CMPXCHG_FALLBACK__(ETHR_", NATMC, "_FUNC__(cmpxchg", NBExt, "), ", NativeVar, ", aval, ", Operation, ");\n",
+ case PostB of
+ "" -> "";
+ _ -> [" ", PostB, "\n"]
+ end]
+ end,
+ try_barrier_order(B))].
+
+translate_have_defs(#atomic_context{dw = DW, 'NATMC' = NATMC}) ->
+ ["
+#if !defined(ETHR_", NATMC, "_BITS__)
+# error \"Missing native atomic implementation\"",
+ lists:map(fun (NBits) ->
+ {HaveInPrefix,
+ HaveOutPrefix,
+ HaveInPrefixExtra,
+ HaveOutPrefixExtra,
+ NativeTypeCheck} = case NBits of
+ "dw" ->
+ {"ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC",
+ ["ETHR_HAVE_", NATMC],
+ "ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC",
+ ["ETHR_HAVE_SU_", NATMC],
+ "\n#elif defined(ETHR_HAVE_NATIVE_DW_ATOMIC) || defined(ETHR_HAVE_NATIVE_SU_DW_ATOMIC)"};
+ _ ->
+ {[?HAVE_NATIVE_ATOMIC, NBits],
+ case DW of
+ true -> ["ETHR_HAVE_SU_", NATMC];
+ false -> ["ETHR_HAVE_", NATMC]
+ end,
+ false,
+ ["ETHR_HAVE_", NATMC],
+ ["\n#elif ETHR_", NATMC, "_BITS__ == ", NBits]}
+ end,
+ [NativeTypeCheck,
+ lists:map(fun (Op) ->
+ NOpStr = opstr(native(Op)),
+ CapNOpStr = to_upper(NOpStr),
+ lists:map(fun (B) ->
+ NBExt = op_barrier_ext(B),
+ CapNBExt = to_upper(NBExt),
+ HaveOutDef = [HaveOutPrefix, "_", CapNOpStr, CapNBExt],
+ HaveOutDefExtra = [HaveOutPrefixExtra, "_", CapNOpStr, CapNBExt],
+ [case DW of
+ true ->
+ ["\n# undef ", HaveOutDefExtra];
+ false ->
+ ""
+ end, "
+# undef ", HaveOutDef,"
+# ifdef ", HaveInPrefix, "_", CapNOpStr, CapNBExt, "
+# define ", HaveOutDef, " 1
+# endif",
+ case HaveInPrefixExtra of
+ false -> "";
+ _ -> ["
+# ifdef ", HaveInPrefixExtra, "_", CapNOpStr, CapNBExt, "
+# define ", HaveOutDefExtra, " 1
+# endif"
+ ]
+ end]
+ end,
+ ?BARRIERS)
+ end,
+ case DW of
+ true -> ?DW_ATOMIC_OPS;
+ false -> ?ATOMIC_OPS
+ end)]
+ end,
+ case DW of
+ true -> ["dw", "64"];
+ false -> ?POTENTIAL_NBITS
+ end),
+ "
+#else
+# error \"Invalid native atomic size\"
+#endif
+"].
+
+
+
+make_prototypes(#atomic_context{dw = DW, 'ATMC' = ATMC} = AC) ->
+ MkProt = fun (MacroName) ->
+ %% addr() is special
+ [func_header(AC, prototype, MacroName, addr, none), "\n",
+ lists:map(fun (Op) ->
+ lists:map(fun (B) ->
+ [func_header(AC, prototype, MacroName, Op, B), "\n"]
+ end,
+ ?BARRIERS)
+ end,
+ case DW of
+ true -> ?DW_ATOMIC_OPS;
+ false -> ?ATOMIC_OPS
+ end)]
+ end,
+ ["
+#ifdef ETHR_NEED_", ATMC, "_PROTOTYPES__
+",
+ MkProt(false),
+ case DW of
+ true -> ["#if defined(", ?DW_RTCHK_MACRO, ")\n",
+ MkProt(?DW_FUNC_MACRO),
+ "#endif\n"];
+ false -> ""
+ end,
+ "#endif /* ETHR_NEED_", ATMC, "_PROTOTYPES__ */\n"].
+
+rtchk_fallback_call(Return, #atomic_context{dw = DW,
+ ret_var = RetVar,
+ arg1 = Arg1,
+ arg2 = Arg2,
+ arg3 = Arg3},
+ Op, B) ->
+ op_call(Op, DW, case Return of
+ true -> "return";
+ false -> [RetVar, " ="]
+ end, [?DW_FUNC_MACRO, "(", opstr(Op), op_barrier_ext(B), ")"], Arg1, Arg2, Arg3, "").
+
+make_implementations(#atomic_context{dw = DW,
+ ret_type = RetType,
+ ret_var = RetVar,
+ arg1 = Arg1,
+ addr_aint_t = AddrAintT,
+ atomic = Atomic,
+ have_native_atomic_ops = HaveNativeAtomicOps,
+ 'ATMC' = ATMC,
+ 'NATMC' = NATMC} = AC) ->
+ NativeVar = case DW of
+ true -> ["(&", Arg1, "->native)"];
+ false -> Arg1
+ end,
+ RtchkBegin = ["
+#if defined(", ?DW_RTCHK_MACRO, ")
+ if (", ?DW_RTCHK_MACRO, ") {
+#endif
+"],
+ RtchkEnd = fun (Return, Operation, Barrier) ->
+ ["
+#if defined(", ?DW_RTCHK_MACRO, ")
+ } else { ", rtchk_fallback_call(Return, AC, Operation, Barrier), " }
+#endif\n"
+ ]
+ end,
+ ["
+#if (defined(", HaveNativeAtomicOps, ") \\
+ && (defined(ETHR_", ATMC, "_INLINE__) || defined(ETHR_ATOMIC_IMPL__)))
+",
+ translate_have_defs(AC),
+ cmpxchg_fallback_define(AC),
+ %% addr() is special
+ "
+
+
+/* --- addr() --- */
+
+", func_header(AC, inline_implementation, false, addr, none), "
+{", case DW of
+ true -> RtchkBegin;
+ false -> ""
+ end, "
+ return (", AddrAintT, " *) ETHR_", NATMC, "_ADDR_FUNC__(", NativeVar, ");
+",case DW of
+ true -> RtchkEnd(true, addr, none);
+ false -> ""
+ end, "
+}
+",
+ lists:map(fun (Op) ->
+ OpStr = opstr(Op),
+ ["
+
+/* --- ", OpStr, "() --- */
+
+",
+ lists:map(fun (B) ->
+ TryBarriers = try_barrier_order(B),
+ ["
+", func_header(AC, inline_implementation, false, Op, B), "
+{
+",
+ case is_return_op(AC, Op) of
+ true ->
+ [" ", RetType, " ", RetVar, ";\n"];
+ _ -> ""
+ end,
+ case DW of
+ true ->
+ [RtchkBegin,
+ "\n",
+ su_dw_native_barrier_op(AC, "#if", Op, B, hd(TryBarriers)),
+ lists:map(fun (NB) ->
+ su_dw_native_barrier_op(AC, "#elif", Op, B, NB)
+ end,
+ tl(TryBarriers)),
+ lists:map(fun (NB) ->
+ dw_native_barrier_op(AC, "#elif", "", Op, B, NB)
+ end,
+ TryBarriers),
+ case simple_fallback(AC, Op, B) of
+ "" ->
+ %% No simple fallback available;
+ %% use cmpxchg() fallbacks...
+ [cmpxchg_fallbacks(AC#atomic_context{'NATMC' = ["SU_", NATMC]}, true, Op, B),
+ cmpxchg_fallbacks(AC, false, Op, B),
+ "#else
+#error \"Missing implementation of ", Atomic, "_", opstr(Op), op_barrier_ext(B), "()!\"
+#endif
+"
+ ];
+ SimpleFallback ->
+ ["#else\n", SimpleFallback, "#endif\n"]
+ end,
+ RtchkEnd(false, Op, B), "\n"];
+ false ->
+ [native_barrier_op(AC, "#if", "", Op, B, hd(TryBarriers), true),
+ lists:map(fun (NB) ->
+ native_barrier_op(AC, "#elif", "", Op, B, NB, true)
+ end,
+ tl(TryBarriers)),
+ case simple_fallback(AC, Op, B) of
+ "" ->
+ %% No simple fallback available;
+ %% use cmpxchg() fallbacks...
+ [cmpxchg_fallbacks(AC, false, Op, B),
+ "#else
+#error \"Missing implementation of ", Atomic, "_", opstr(Op), op_barrier_ext(B), "()!\"
+#endif
+"
+ ];
+ SimpleFallback ->
+ ["#else\n", SimpleFallback, "#endif\n"]
+ end]
+ end,
+ case is_return_op(AC, Op) of
+ true ->
+ [" return ", RetVar, ";\n"];
+ false ->
+ ""
+ end,
+ "}\n"]
+ end,
+ ?BARRIERS)]
+ end,
+ case DW of
+ true -> ?DW_ATOMIC_OPS;
+ false -> ?ATOMIC_OPS
+ end),
+ "
+#endif /* ETHR_", ATMC, "_INLINE__ */
+"
+ ].
+
+atomic_implementation_comment(AtomicSize) ->
+ CSz = case AtomicSize of
+ "dword" -> "Double word size";
+ "word" -> "Word size";
+ _ -> AtomicSize ++ "-bit"
+ end,
+ ["
+
+/* ---------- ", CSz, " atomic implementation ---------- */
+
+"
+ ].
+
+write_h_file(FileName) ->
+ {ok, FD} = file:open(FileName, [write, latin1]),
+ ok = file:write(FD, comments()),
+ ok = file:write(FD, "
+#ifndef ETHR_ATOMICS_H__
+#define ETHR_ATOMICS_H__
+"
+ ),
+ ok = file:write(FD, h_top()),
+ ok = lists:foreach(fun (AtomicSize) ->
+ AC = atomic_context(AtomicSize),
+ ok = file:write(FD,
+ [atomic_implementation_comment(AtomicSize),
+ make_prototypes(AC),
+ make_implementations(AC)])
+ end,
+ ?ATOMIC_SIZES),
+ ok = file:write(FD, "
+#endif /* ETHR_ATOMICS_H__ */
+"
+ ),
+ ok = file:close(FD).
+
+
+make_native_impl_op(#atomic_context{dw = DW,
+ atomic = Atomic,
+ have_native_atomic_ops = HaveNativeAtomicOps,
+ ret_var = RetVar,
+ arg1 = Arg1,
+ arg2 = Arg2,
+ arg3 = Arg3}, Op, B) ->
+ ["#if defined(", HaveNativeAtomicOps, ")",
+ case DW of
+ true -> [" && !defined(", ?DW_RTCHK_MACRO, ")"];
+ false -> ""
+ end,
+ "\n",
+ " ", op_call(Op, DW, [RetVar, " = "], [Atomic, "_", opstr(Op), op_barrier_ext(B), "__"], Arg1, Arg2, Arg3, ""),
+ "\n"].
+
+amc_op_dw_arg(#atomic_context{dw = false}) ->
+ "0";
+amc_op_dw_arg(#atomic_context{dw = true}) ->
+ "1".
+
+amc_op_arg_prefix(#atomic_context{dw = false}) ->
+ "&";
+amc_op_arg_prefix(#atomic_context{dw = true}) ->
+ "".
+
+amc_sint_arg(#atomic_context{dw = DW, arg2 = Arg}, arg2) ->
+ amc_sint_arg(DW, Arg);
+amc_sint_arg(#atomic_context{dw = DW, arg3 = Arg}, arg3) ->
+ amc_sint_arg(DW, Arg);
+amc_sint_arg(#atomic_context{dw = DW, ret_var = Arg}, ret_var) ->
+ amc_sint_arg(DW, Arg);
+amc_sint_arg(true, Arg) ->
+ [Arg, "->" ?DW_SINT_FIELD];
+amc_sint_arg(false, Arg) ->
+ ["&", Arg].
+
+amc_op_call(#atomic_context{arg1 = Arg1} = AC, init) ->
+ [" amc_init(&", Arg1, "->amc, ", amc_op_dw_arg(AC), ", ", amc_op_arg_prefix(AC), Arg1, "->sint, ", amc_sint_arg(AC, arg2), ");\n"];
+amc_op_call(#atomic_context{arg1 = Arg1} = AC, set) ->
+ [" amc_set(&", Arg1, "->amc, ", amc_op_dw_arg(AC), ", ", amc_op_arg_prefix(AC), Arg1, "->sint, ", amc_sint_arg(AC, arg2), ");\n"];
+amc_op_call(#atomic_context{dw = false, arg1 = Arg1} = AC, read) ->
+ [" amc_read(&", Arg1, "->amc, ", amc_op_dw_arg(AC), ", ", amc_op_arg_prefix(AC), Arg1, "->sint, ", amc_sint_arg(AC, ret_var), ");\n"];
+amc_op_call(#atomic_context{dw = true, arg1 = Arg1} = AC, read) ->
+ [" amc_read(&", Arg1, "->amc, ", amc_op_dw_arg(AC), ", ", amc_op_arg_prefix(AC), Arg1, "->sint, ", amc_sint_arg(AC, arg2), ");\n"];
+amc_op_call(#atomic_context{dw = false, arg1 = Arg1, arg3 = Arg3, ret_var = RetVar} = AC, cmpxchg) ->
+ [" ", RetVar, " = ", Arg3, ";
+ (void) amc_cmpxchg(&", Arg1, "->amc, ", amc_op_dw_arg(AC), ", ", amc_op_arg_prefix(AC), Arg1, "->sint, ", amc_sint_arg(AC, arg2), ", ", amc_sint_arg(AC, ret_var), ");\n"];
+amc_op_call(#atomic_context{dw = true, arg1 = Arg1, ret_var = RetVar} = AC, cmpxchg) ->
+ [" ", RetVar, " = amc_cmpxchg(&", Arg1, "->amc, ", amc_op_dw_arg(AC), ", ", amc_op_arg_prefix(AC), Arg1, "->sint, ", amc_sint_arg(AC, arg2), ", ", amc_sint_arg(AC, arg3), ");\n"];
+amc_op_call(#atomic_context{dw = DW, arg1 = Arg1, arg2 = Arg2, arg3 = Arg3, ret_var = RetVar}, Op) ->
+ OpCtxt = #op_context{ret = RetVar, var = [Arg1,"->sint"], val1 = Arg2, val2 = Arg3},
+ OpStr = case DW of
+ true -> dw_op(Op, OpCtxt);
+ false -> op(Op, OpCtxt)
+ end,
+ [" ETHR_AMC_MODIFICATION_OPS__(&", Arg1, "->amc, ", OpStr, ");\n"].
+
+make_amc_fallback_op(#atomic_context{amc_fallback = false}, _Op, _B) ->
+ "";
+make_amc_fallback_op(#atomic_context{amc_fallback = true} = AC, Op, B) ->
+ NB = case Op of
+ read -> rb;
+ _ -> none
+ end,
+ {PreB, PostB} = xbarriers(Op, B, NB),
+ ["#elif defined(ETHR_AMC_FALLBACK__)\n",
+ case PreB of
+ "" -> "";
+ _ -> [" ", PreB, "\n"]
+ end,
+ amc_op_call(AC, Op),
+ case PostB of
+ "" -> "";
+ _ -> [" ", PostB, "\n"]
+ end].
+
+make_locked_fallback_op(#atomic_context{dw = DW,
+ ret_var = RetVar,
+ arg1 = Arg1,
+ arg2 = Arg2,
+ arg3 = Arg3}, Op, B) ->
+ OpStr = case DW of
+ true ->
+ dw_op(Op, #op_context{ret = RetVar,
+ var = [Arg1, "->" ?DW_SINT_FIELD],
+ val1 = [Arg2, "->" ?DW_SINT_FIELD],
+ val2 = [Arg3, "->" ?DW_SINT_FIELD]});
+ false ->
+ op(Op, #op_context{ret = RetVar,
+ var = ["*", Arg1],
+ val1 = Arg2,
+ val2 = Arg3})
+ end,
+ {PreB, PostB} = xbarriers(Op, B, none),
+ ["#else\n",
+ case PreB of
+ "" -> "";
+ _ -> [" ", PreB, "\n"]
+ end,
+ [" ETHR_ATOMIC_OP_FALLBACK_IMPL__(", Arg1, ", ", OpStr, ");\n"],
+ case PostB of
+ "" -> "";
+ _ -> [" ", PostB, "\n"]
+ end,
+ "#endif\n"].
+
+make_symbol_to_fallback_impl(#atomic_context{dw = true,
+ atomic = Atomic,
+ arg1 = Arg1,
+ arg2 = Arg2,
+ arg3 = Arg3} = AC,
+ Op, B) ->
+ ["
+#ifdef ", ?DW_RTCHK_MACRO, "
+", func_header(AC, implementation, false, Op, B), "
+{",
+ case Op of
+ init -> "";
+ _ -> ["\n ETHR_ASSERT(!ethr_not_inited__);"]
+ end, "
+ ETHR_ASSERT(", Arg1, ");
+ ", op_call(Op, true, "return", [Atomic, "_", opstr(Op), op_barrier_ext(B), "__"], Arg1, Arg2, Arg3, ""), "
+}
+#endif
+"
+ ];
+make_symbol_to_fallback_impl(_, _, _) ->
+ "".
+
+make_symbol_implementations(#atomic_context{dw = DW,
+ amc_fallback = AMC,
+ ret_type = RetType,
+ addr_aint_t = AddrAintT,
+ ret_var = RetVar,
+ arg1 = Arg1} = AC) ->
+ FallbackVar = case DW of
+ true -> ["(&", Arg1, "->fallback)"];
+ false -> Arg1
+ end,
+ ["
+",
+ case DW of
+ true -> ["
+/*
+ * Double word atomics need runtime test.
+ */
+
+int ethr_have_native_dw_atomic(void)
+{
+ return ethr_have_native_dw_atomic__();
+}
+ "];
+ false -> ""
+ end, "
+
+/* --- addr() --- */
+
+", func_header(AC, implementation,
+ case DW of
+ true -> ?DW_FUNC_MACRO;
+ false -> false
+ end, addr, none), "
+{
+ ", AddrAintT, " *", RetVar, ";
+ ETHR_ASSERT(!ethr_not_inited__);
+ ETHR_ASSERT(", Arg1, ");
+", make_native_impl_op(AC, addr, none),
+ case AMC of
+ true -> ["#elif defined(ETHR_AMC_FALLBACK__)
+ ", RetVar ," = (", AddrAintT, " *) (", FallbackVar, ")->sint;"];
+ false -> ""
+ end, "
+#else
+ ", RetVar, " = (", AddrAintT, " *) ", FallbackVar, ";
+#endif
+ return ", RetVar, ";
+}
+",
+ make_symbol_to_fallback_impl(AC, addr, none),
+ lists:map(fun (Op) ->
+ ["
+
+/* -- ", opstr(Op), "() -- */
+
+",
+ lists:map(fun (B) ->
+ ["\n",
+ func_header(AC, implementation,
+ case DW of
+ true -> ?DW_FUNC_MACRO;
+ false -> false
+ end, Op, B),
+ "\n{\n",
+ case is_return_op(AC, Op) of
+ true -> [" ", RetType, " ", RetVar, ";\n"];
+ false -> ""
+ end,
+ case Op of
+ init -> "";
+ _ -> [" ETHR_ASSERT(!ethr_not_inited__);\n"]
+ end,
+ [" ETHR_ASSERT(", Arg1, ");\n"],
+ make_native_impl_op(AC, Op, B),
+ make_amc_fallback_op(AC#atomic_context{arg1 = FallbackVar}, Op, B),
+ make_locked_fallback_op(AC#atomic_context{arg1 = FallbackVar}, Op, B),
+ case is_return_op(AC, Op) of
+ true -> [" return ", RetVar, ";"
+ ];
+ false ->
+ ""
+ end,
+ "\n}\n",
+ make_symbol_to_fallback_impl(AC, Op, B)]
+ end,
+ ?BARRIERS)]
+ end,
+ case DW of
+ true -> ?DW_ATOMIC_OPS;
+ false -> ?ATOMIC_OPS
+ end)].
+
+make_info_functions() ->
+ ["
+
+
+/* --------- Info functions --------- */
+
+#if defined(", ?DW_RTCHK_MACRO, ")
+char *zero_ops[] = {NULL};
+#endif
+",
+ [lists:map(fun (NBits) ->
+ {DW, Bits} = case NBits of
+ "su_dw" -> {"su_dw_", ""};
+ "dw" -> {"dw_", ""};
+ _ -> {"", NBits}
+ end,
+ ["
+
+static char *native_", DW, "atomic", Bits, "_ops[] = {",
+ lists:map(fun (Op) ->
+ NOpStr = opstr(native(Op)),
+ CapNOpStr = to_upper(NOpStr),
+ lists:map(fun (B) ->
+ HaveNative = case NBits of
+ "dw" ->
+ "ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC";
+ "su_dw" ->
+ "ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC";
+ _ ->
+ [?HAVE_NATIVE_ATOMIC, NBits]
+ end,
+ NBExt = op_barrier_ext(B),
+ CapNBExt = to_upper(NBExt),
+ ["
+#ifdef ", HaveNative, "_", CapNOpStr, CapNBExt, "
+ \"", NOpStr, NBExt, "\",
+#endif"
+ ]
+ end,
+ ?BARRIERS)
+ end,
+ case NBits of
+ "dw" -> ?DW_ATOMIC_OPS;
+ "su_dw" -> ?DW_ATOMIC_OPS;
+ _ -> ?ATOMIC_OPS
+ end), "
+ NULL
+};
+
+char **
+ethr_native_", DW, "atomic", Bits, "_ops(void)
+{
+",
+ case DW of
+ "" -> "";
+ _ -> ["
+#if defined(", ?DW_RTCHK_MACRO, ")
+ if (!", ?DW_RTCHK_MACRO, ")
+ return &zero_ops[0];
+#endif"
+ ]
+ end, "
+ return &native_", DW, "atomic", Bits, "_ops[0];
+}
+"
+ ]
+ end, ["su_dw", "dw" | ?POTENTIAL_NBITS])]].
+
+write_c_file(FileName) ->
+ {ok, FD} = file:open(FileName, [write, latin1]),
+ ok = file:write(FD, comments()),
+ ok = file:write(FD, c_top()),
+ lists:foreach(fun (AtomicSize) ->
+ ok = file:write(FD,
+ [atomic_implementation_comment(AtomicSize),
+ make_symbol_implementations(atomic_context(AtomicSize))])
+ end,
+ ?ATOMIC_SIZES),
+ ok = file:write(FD, make_info_functions()).
+
+
+main([]) ->
+ case os:getenv("ERL_TOP") of
+ false ->
+ io:format("$ERL_TOP not set!~n", []),
+ halt(1);
+ ErlTop ->
+ HFile = filename:join(ErlTop, ?H_FILE),
+ WHFile = fun () ->
+ write_h_file(HFile)
+ end,
+ CFile = filename:join(ErlTop, ?C_FILE),
+ WCFile = fun () ->
+ write_c_file(CFile)
+ end,
+ case erlang:system_info(schedulers_online) of
+ 1 ->
+ WHFile(),
+ WCFile();
+ _ ->
+ {HPid, HMon} = spawn_monitor(WHFile),
+ {CPid, CMon} = spawn_monitor(WCFile),
+ receive
+ {'DOWN', HMon, process, HPid, HReason} ->
+ normal = HReason
+ end,
+ receive
+ {'DOWN', CMon, process, CPid, CReason} ->
+ normal = CReason
+ end
+ end,
+ io:format("Wrote: ~s~n", [HFile]),
+ io:format("Wrote: ~s~n", [CFile]),
+ init:stop()
+ end.
+
+a2l(A) ->
+ atom_to_list(A).
+
+opstr(A) ->
+ a2l(A).
+
+to_upper([]) ->
+ [];
+to_upper([C|Cs]) when is_list(C) ->
+ [to_upper(C)|to_upper(Cs)];
+to_upper([C|Cs]) when is_integer(C), 97 =< C, C =< 122 ->
+ [C-32|to_upper(Cs)];
+to_upper([C|Cs]) ->
+ [C|to_upper(Cs)].
+
+
+comments() ->
+ Years = case erlang:date() of
+ {2011, _, _} -> "2011";
+ {Y, _, _} -> "2011-"++integer_to_list(Y)
+ end,
+ ["/*
+ * --------------- DO NOT EDIT THIS FILE! ---------------
+ * This file was automatically generated by the
+ * \$ERL_TOP/erts/lib_src/utils/make_atomics_api script.
+ * If you need to make changes, edit the script and
+ * regenerate this file.
+ * --------------- DO NOT EDIT THIS FILE! ---------------
+ */
+
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB ", Years, ". All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the \"License\"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an \"AS IS\"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description: The ethread atomics API
+ * Author: Rickard Green
+ */
+
+/*
+ * This file maps native atomic implementations to ethread
+ * API atomics. If no native atomic implementation
+ * is available, a less efficient fallback is used instead.
+ * The API consists of 32-bit size, word size (pointer size),
+ * and double word size atomics.
+ *
+ * The following atomic operations are implemented for
+ * 32-bit size, and word size atomics:
+",
+ lists:map(fun (Op) ->
+ [" * - ", opstr(Op), "\n"]
+ end,
+ ?ATOMIC_OPS),
+ " *
+ * The following atomic operations are implemented for
+ * double word size atomics:
+",
+ lists:map(fun (Op) ->
+ [" * - ", opstr(Op), "\n"]
+ end,
+ ?DW_ATOMIC_OPS),
+ " *
+ * Appart from a function implementing the atomic operation
+ * with unspecified memory barrier semantics, there are
+ * functions implementing each operation with the following
+ * memory barrier semantics:
+",
+ lists:map(fun (none) ->
+ "";
+ (rb) ->
+ [" * - rb (read barrier)\n"];
+ (wb) ->
+ [" * - wb (write barrier)\n"];
+ (acqb) ->
+ [" * - acqb (acquire barrier)\n"];
+ (relb) ->
+ [" * - relb (release barrier)\n"];
+ (mb) ->
+ [" * - mb (full memory barrier)\n"];
+ (B) ->
+ [" * - ", a2l(B), "\n"]
+ end,
+ ?BARRIERS),
+ " *
+ * We implement all of these operation/barrier
+ * combinations, regardless of whether they are useful
+ * or not (some of them are useless).
+ *
+ * Double word size atomic functions are on the followning
+ * form:
+ * ethr_dw_atomic_<OP>[_<BARRIER>]
+ *
+ * Word size atomic functions are on the followning
+ * form:
+ * ethr_atomic_<OP>[_<BARRIER>]
+ *
+ * 32-bit size atomic functions are on the followning
+ * form:
+ * ethr_atomic32_<OP>[_<BARRIER>]
+ *
+ * Apart from the operation/barrier functions
+ * described above also 'addr' functions are implemented
+ * which return the actual memory address used of the
+ * atomic variable. The 'addr' functions have no barrier
+ * versions.
+ *
+ * The native atomic implementation does not need to
+ * implement all operation/barrier combinations.
+ * Functions that have no native implementation will be
+ * constructed from existing native functionality. These
+ * functions will perform the wanted operation and will
+ * produce sufficient memory barriers, but may
+ * in some cases be less efficient than pure native
+ * versions.
+ *
+ * When we create ethread API operation/barrier functions by
+ * adding barriers before and after native operations it is
+ * assumed that:
+ * - A native read operation begins, and ends with a load.
+ * - A native set operation begins, and ends with a store.
+ * - An init operation begins with either a load, or a store,
+ * and ends with either a load, or a store.
+ * - All other operations begins with a load, and ends with
+ * either a load, or a store.
+ *
+ * This is the minimum functionality that a native
+ * implementation needs to provide:
+ *
+ * - Functions that need to be implemented:
+ *
+ * - ethr_native_[dw_|su_dw_]atomic[BITS]_addr
+ * - ethr_native_[dw_|su_dw_]atomic[BITS]_cmpxchg[_<BARRIER>]
+ * (at least one cmpxchg of optional barrier)
+ *
+ * - Macros that needs to be defined:
+ *
+ * A macro informing about the presence of the native
+ * implementation:
+ *
+ * - ETHR_HAVE_NATIVE_[DW_|SU_DW_]ATOMIC[BITS]
+ *
+ * A macro naming (a string constant) the implementation:
+ *
+ * - ETHR_NATIVE_[DW_]ATOMIC[BITS]_IMPL
+ *
+ * Each implemented native atomic function has to
+ * be accompanied by a defined macro on the following
+ * form informing about its presence:
+ *
+ * - ETHR_HAVE_ETHR_NATIVE_[DW_|SU_DW_]ATOMIC[BITS]_<OP>[_<BARRIER>]
+ *
+ * A (sparc-v9 style) membar macro:
+ *
+ * - ETHR_MEMBAR(B)
+ *
+ * Which takes a combination of the following macros
+ * or:ed (using |) together:
+ *
+ * - ETHR_LoadLoad
+ * - ETHR_LoadStore
+ * - ETHR_StoreLoad
+ * - ETHR_StoreStore
+ *
+ */
+"
+ ].
+
+h_top() ->
+ ["
+#undef ETHR_AMC_FALLBACK__
+#undef ETHR_AMC_NO_ATMCS__
+#undef ETHR_AMC_ATMC_T__
+#undef ETHR_AMC_ATMC_FUNC__
+
+/* -- 32-bit atomics -- */
+
+#undef ETHR_NAINT32_T__
+#undef ETHR_NATMC32_FUNC__
+#undef ETHR_NATMC32_ADDR_FUNC__
+#undef ETHR_NATMC32_BITS__
+#if defined(ETHR_HAVE_NATIVE_ATOMIC32)
+# define ETHR_NEED_NATMC32_ADDR
+# define ETHR_NATMC32_ADDR_FUNC__ ethr_native_atomic32_addr
+typedef ethr_native_atomic32_t ethr_atomic32_t;
+# define ETHR_NAINT32_T__ ethr_sint32_t
+# define ETHR_NATMC32_FUNC__(X) ethr_native_atomic32_ ## X
+# define ETHR_NATMC32_BITS__ 32
+#elif defined(ETHR_HAVE_NATIVE_ATOMIC64)
+# define ETHR_NEED_NATMC64_ADDR
+#ifdef ETHR_BIGENDIAN
+# define ETHR_NATMC32_ADDR_FUNC__(VAR) \\
+ (((ethr_sint32_t *) ethr_native_atomic64_addr((VAR))) + 1)
+#else
+# define ETHR_NATMC32_ADDR_FUNC__(VAR) \\
+ ((ethr_sint32_t *) ethr_native_atomic64_addr((VAR)))
+#endif
+typedef ethr_native_atomic64_t ethr_atomic32_t;
+# define ETHR_NAINT32_T__ ethr_sint64_t
+# define ETHR_NATMC32_FUNC__(X) ethr_native_atomic64_ ## X
+# define ETHR_NATMC32_BITS__ 64
+#else
+/*
+ * No native atomics usable for 32-bits atomics :(
+ * Use fallback...
+ */
+typedef ethr_sint32_t ethr_atomic32_t;
+#endif
+
+#undef ETHR_ATMC32_INLINE__
+#ifdef ETHR_NATMC32_BITS__
+# ifdef ETHR_TRY_INLINE_FUNCS
+# define ETHR_ATMC32_INLINE__
+# endif
+# define ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS
+#endif
+
+#if !defined(ETHR_ATMC32_INLINE__) || defined(ETHR_ATOMIC_IMPL__)
+# define ETHR_NEED_ATMC32_PROTOTYPES__
+#endif
+
+#ifndef ETHR_INLINE_ATMC32_FUNC_NAME_
+# define ETHR_INLINE_ATMC32_FUNC_NAME_(X) X
+#endif
+
+#undef ETHR_ATMC32_FUNC__
+#define ETHR_ATMC32_FUNC__(X) ETHR_INLINE_ATMC32_FUNC_NAME_(ethr_atomic32_ ## X)
+
+
+/* -- Word size atomics -- */
+
+#undef ETHR_NEED_NATMC32_ADDR
+#undef ETHR_NEED_NATMC64_ADDR
+
+#undef ETHR_NAINT_T__
+#undef ETHR_NATMC_FUNC__
+#undef ETHR_NATMC_ADDR_FUNC__
+#undef ETHR_NATMC_BITS__
+#if ETHR_SIZEOF_PTR == 8 && defined(ETHR_HAVE_NATIVE_ATOMIC64)
+# ifndef ETHR_NEED_NATMC64_ADDR
+# define ETHR_NEED_NATMC64_ADDR
+# endif
+# define ETHR_NATMC_ADDR_FUNC__ ethr_native_atomic64_addr
+typedef ethr_native_atomic64_t ethr_atomic_t;
+# define ETHR_NAINT_T__ ethr_sint64_t
+# define ETHR_NATMC_FUNC__(X) ethr_native_atomic64_ ## X
+# define ETHR_NATMC_BITS__ 64
+#elif ETHR_SIZEOF_PTR == 4 && defined(ETHR_HAVE_NATIVE_ATOMIC32)
+# ifndef ETHR_NEED_NATMC64_ADDR
+# define ETHR_NEED_NATMC32_ADDR
+# endif
+# define ETHR_NATMC_ADDR_FUNC__ ethr_native_atomic32_addr
+typedef ethr_native_atomic32_t ethr_atomic_t;
+# define ETHR_NAINT_T__ ethr_sint32_t
+# define ETHR_NATMC_FUNC__(X) ethr_native_atomic32_ ## X
+# define ETHR_NATMC_BITS__ 32
+#elif ETHR_SIZEOF_PTR == 4 && defined(ETHR_HAVE_NATIVE_ATOMIC64)
+# ifndef ETHR_NEED_NATMC64_ADDR
+# define ETHR_NEED_NATMC64_ADDR
+# endif
+#ifdef ETHR_BIGENDIAN
+# define ETHR_NATMC_ADDR_FUNC__(VAR) \\
+ (((ethr_sint32_t *) ethr_native_atomic64_addr((VAR))) + 1)
+#else
+# define ETHR_NATMC_ADDR_FUNC__(VAR) \\
+ ((ethr_sint32_t *) ethr_native_atomic64_addr((VAR)))
+#endif
+typedef ethr_native_atomic64_t ethr_atomic_t;
+# define ETHR_NATMC_T__ ethr_native_atomic64_t
+# define ETHR_NAINT_T__ ethr_sint64_t
+# define ETHR_NATMC_FUNC__(X) ethr_native_atomic64_ ## X
+# define ETHR_NATMC_BITS__ 64
+#else
+/*
+ * No native atomics usable for pointer size atomics :(
+ * Use fallback...
+ */
+
+# if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+# define ETHR_AMC_FALLBACK__
+# define ETHR_AMC_NO_ATMCS__ 2
+# define ETHR_AMC_SINT_T__ ethr_sint32_t
+# define ETHR_AMC_ATMC_T__ ethr_atomic32_t
+# define ETHR_AMC_ATMC_FUNC__(X) ETHR_INLINE_ATMC32_FUNC_NAME_(ethr_atomic32_ ## X)
+typedef struct {
+ ETHR_AMC_ATMC_T__ atomic[ETHR_AMC_NO_ATMCS__];
+} ethr_amc_t;
+typedef struct {
+ ethr_amc_t amc;
+ ethr_sint_t sint;
+} ethr_atomic_t;
+# else /* locked fallback */
+typedef ethr_sint_t ethr_atomic_t;
+# endif
+#endif
+
+#undef ETHR_ATMC_INLINE__
+#ifdef ETHR_NATMC_BITS__
+# ifdef ETHR_TRY_INLINE_FUNCS
+# define ETHR_ATMC_INLINE__
+# endif
+# define ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS
+#endif
+
+#if !defined(ETHR_ATMC_INLINE__) || defined(ETHR_ATOMIC_IMPL__)
+# define ETHR_NEED_ATMC_PROTOTYPES__
+#endif
+
+#ifndef ETHR_INLINE_ATMC_FUNC_NAME_
+# define ETHR_INLINE_ATMC_FUNC_NAME_(X) X
+#endif
+
+#undef ETHR_ATMC_FUNC__
+#define ETHR_ATMC_FUNC__(X) ETHR_INLINE_ATMC_FUNC_NAME_(ethr_atomic_ ## X)
+
+/* -- Double word atomics -- */
+
+#undef ETHR_SU_DW_NAINT_T__
+#undef ETHR_SU_DW_NATMC_FUNC__
+#undef ETHR_SU_DW_NATMC_ADDR_FUNC__
+#undef ETHR_DW_NATMC_FUNC__
+#undef ETHR_DW_NATMC_ADDR_FUNC__
+#undef ETHR_DW_NATMC_BITS__
+#if defined(ETHR_HAVE_NATIVE_DW_ATOMIC) || defined(ETHR_HAVE_NATIVE_SU_DW_ATOMIC)
+# define ETHR_NEED_DW_NATMC_ADDR
+# define ETHR_DW_NATMC_ADDR_FUNC__ ethr_native_dw_atomic_addr
+# define ETHR_NATIVE_DW_ATOMIC_T__ ethr_native_dw_atomic_t
+# define ETHR_DW_NATMC_FUNC__(X) ethr_native_dw_atomic_ ## X
+# define ETHR_SU_DW_NATMC_FUNC__(X) ethr_native_su_dw_atomic_ ## X
+# if ETHR_SIZEOF_PTR == 8
+# define ETHR_DW_NATMC_BITS__ 128
+# elif ETHR_SIZEOF_PTR == 4
+# define ETHR_DW_NATMC_BITS__ 64
+# else
+# error \"Word size not supported\"
+# endif
+# ifdef ETHR_NATIVE_SU_DW_SINT_T
+# define ETHR_SU_DW_NAINT_T__ ETHR_NATIVE_SU_DW_SINT_T
+# endif
+#elif ETHR_SIZEOF_PTR == 4 && defined(ETHR_HAVE_NATIVE_ATOMIC64)
+# define ETHR_HAVE_NATIVE_SU_DW_ATOMIC
+# ifndef ETHR_NEED_NATMC64_ADDR
+# define ETHR_NEED_NATMC64_ADDR
+# endif
+# define ETHR_DW_NATMC_ADDR_FUNC__(VAR) \\
+ ((ethr_dw_sint_t *) ethr_native_atomic64_addr((VAR)))
+# define ETHR_NATIVE_DW_ATOMIC_T__ ethr_native_atomic64_t
+# define ETHR_SU_DW_NAINT_T__ ethr_sint64_t
+# define ETHR_SU_DW_NATMC_FUNC__(X) ethr_native_atomic64_ ## X
+# define ETHR_DW_NATMC_BITS__ 64
+#endif
+
+#if defined(", ?DW_RTCHK_MACRO, ")
+#define ", ?DW_FUNC_MACRO, "(X) ethr_dw_atomic_ ## X ## _fallback__
+#else
+#define ", ?DW_FUNC_MACRO, "(X) ethr_dw_atomic_ ## X
+#endif
+
+#if !defined(ETHR_DW_NATMC_BITS__) || defined(", ?DW_RTCHK_MACRO, ")
+# define ETHR_NEED_DW_FALLBACK__
+#endif
+
+#if defined(ETHR_NEED_DW_FALLBACK__)
+/*
+ * No native atomics usable for double word atomics :(
+ * Use fallback...
+ */
+
+# ifndef ETHR_AMC_FALLBACK__
+# if ETHR_SIZEOF_PTR == 8 && defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+# define ETHR_AMC_FALLBACK__
+# define ETHR_AMC_NO_ATMCS__ 1
+# define ETHR_AMC_SINT_T__ ethr_sint_t
+# define ETHR_AMC_ATMC_T__ ethr_atomic_t
+# define ETHR_AMC_ATMC_FUNC__(X) ETHR_INLINE_ATMC_FUNC_NAME_(ethr_atomic_ ## X)
+# elif defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+# define ETHR_AMC_FALLBACK__
+# define ETHR_AMC_NO_ATMCS__ 2
+# define ETHR_AMC_SINT_T__ ethr_sint32_t
+# define ETHR_AMC_ATMC_T__ ethr_atomic32_t
+# define ETHR_AMC_ATMC_FUNC__(X) ETHR_INLINE_ATMC32_FUNC_NAME_(ethr_atomic32_ ## X)
+# endif
+# ifdef ETHR_AMC_FALLBACK__
+typedef struct {
+ ETHR_AMC_ATMC_T__ atomic[ETHR_AMC_NO_ATMCS__];
+} ethr_amc_t;
+# endif
+# endif
+
+typedef struct {
+#ifdef ETHR_AMC_FALLBACK__
+ ethr_amc_t amc;
+#endif
+ ethr_sint_t sint[2];
+} ethr_dw_atomic_fallback_t;
+
+#endif
+
+typedef union {
+#ifdef ETHR_NATIVE_DW_ATOMIC_T__
+ ETHR_NATIVE_DW_ATOMIC_T__ native;
+#endif
+#ifdef ETHR_NEED_DW_FALLBACK__
+ ethr_dw_atomic_fallback_t fallback;
+#endif
+ ethr_sint_t sint[2];
+} ethr_dw_atomic_t;
+
+typedef union {
+#ifdef ETHR_SU_DW_NAINT_T__
+ ETHR_SU_DW_NAINT_T__ ", ?SU_DW_SINT_FIELD, ";
+#endif
+ ethr_sint_t ", ?DW_SINT_FIELD, "[2];
+} ethr_dw_sint_t;
+
+#ifdef ETHR_BIGENDIAN
+# define ETHR_DW_SINT_LOW_WORD 1
+# define ETHR_DW_SINT_HIGH_WORD 0
+#else
+# define ETHR_DW_SINT_LOW_WORD 0
+# define ETHR_DW_SINT_HIGH_WORD 1
+#endif
+
+#undef ETHR_DW_ATMC_INLINE__
+#ifdef ETHR_DW_NATMC_BITS__
+# ifdef ETHR_TRY_INLINE_FUNCS
+# define ETHR_ATMC32_INLINE__
+# endif
+# define ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS
+#endif
+
+#if !defined(ETHR_DW_ATMC_INLINE__) || defined(ETHR_ATOMIC_IMPL__)
+# define ETHR_NEED_DW_ATMC_PROTOTYPES__
+#endif
+
+#ifndef ETHR_INLINE_DW_ATMC_FUNC_NAME_
+# define ETHR_INLINE_DW_ATMC_FUNC_NAME_(X) X
+#endif
+
+#undef ETHR_DW_ATMC_FUNC__
+#define ETHR_DW_ATMC_FUNC__(X) ETHR_INLINE_DW_ATMC_FUNC_NAME_(ethr_dw_atomic_ ## X)
+
+#if defined(ETHR_NEED_DW_ATMC_PROTOTYPES__)
+int ethr_have_native_dw_atomic(void);
+#endif
+#if defined(ETHR_DW_ATMC_INLINE__) || defined(ETHR_ATOMIC_IMPL__)
+static ETHR_INLINE int
+ETHR_INLINE_DW_ATMC_FUNC_NAME_(ethr_have_native_dw_atomic)(void)
+{
+#if defined(", ?DW_RTCHK_MACRO, ")
+ return ", ?DW_RTCHK_MACRO, ";
+#elif defined(ETHR_DW_NATMC_BITS__)
+ return 1;
+#else
+ return 0;
+#endif
+}
+#endif
+
+/* -- Misc -- */
+
+#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_ATOMIC_IMPL__)
+/*
+ * Unusual values are used by read() fallbacks implemented via cmpxchg().
+ * We want to use an unusual value in hope that it is more efficient
+ * not to match the value in memory.
+ *
+ * - Negative integer values are probably more unusual.
+ * - Very large absolute integer values are probably more unusual.
+ * - Odd pointers are probably more unusual (only char pointers can be odd).
+ */
+# define ETHR_UNUSUAL_SINT32_VAL__ ((ethr_sint32_t) 0x81818181)
+# if ETHR_SIZEOF_PTR == 4
+# define ETHR_UNUSUAL_SINT_VAL__ ((ethr_sint_t) ETHR_UNUSUAL_SINT32_VAL__)
+# elif ETHR_SIZEOF_PTR == 8
+# define ETHR_UNUSUAL_SINT_VAL__ ((ethr_sint_t) 0x8181818181818181L)
+# else
+# error \"Word size not supported\"
+# endif
+# if defined(ETHR_NEED_DW_NATMC_ADDR) && !defined(ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_ADDR)
+# error \"No ethr_native_dw_atomic_addr() available\"
+# endif
+# if defined(ETHR_NEED_NATMC32_ADDR) && !defined(ETHR_HAVE_ETHR_NATIVE_ATOMIC32_ADDR)
+# error \"No ethr_native_atomic32_addr() available\"
+# endif
+# if defined(ETHR_NEED_NATMC64_ADDR) && !defined(ETHR_HAVE_ETHR_NATIVE_ATOMIC64_ADDR)
+# error \"No ethr_native_atomic64_addr() available\"
+# endif
+#endif
+
+#if defined(__GNUC__)
+# ifndef ETHR_COMPILER_BARRIER
+# define ETHR_COMPILER_BARRIER __asm__ __volatile__(\"\" : : : \"memory\")
+# endif
+#elif defined(ETHR_WIN32_THREADS)
+# ifndef ETHR_COMPILER_BARRIER
+# include <intrin.h>
+# pragma intrinsic(_ReadWriteBarrier)
+# define ETHR_COMPILER_BARRIER _ReadWriteBarrier()
+# endif
+#endif
+
+void ethr_compiler_barrier_fallback(void);
+#ifndef ETHR_COMPILER_BARRIER
+# define ETHR_COMPILER_BARRIER ethr_compiler_barrier_fallback()
+#endif
+
+int ethr_init_atomics(void);
+
+/* info */
+char **ethr_native_atomic32_ops(void);
+char **ethr_native_atomic64_ops(void);
+char **ethr_native_dw_atomic_ops(void);
+char **ethr_native_su_dw_atomic_ops(void);
+
+#if !defined(ETHR_DW_NATMC_BITS__) && !defined(ETHR_NATMC_BITS__) && !defined(ETHR_NATMC32_BITS__)
+/*
+ * ETHR_*MEMORY_BARRIER orders between locked and atomic accesses only,
+ * i.e. when no native atomic implementation exist and only our lock
+ * based atomic fallback is used, a noop is sufficient.
+ */
+# undef ETHR_MEMORY_BARRIER
+# undef ETHR_WRITE_MEMORY_BARRIER
+# undef ETHR_READ_MEMORY_BARRIER
+# undef ETHR_READ_DEPEND_MEMORY_BARRIER
+# undef ETHR_MEMBAR
+# define ETHR_MEMBAR(B) do { } while (0)
+#endif
+
+#ifndef ETHR_MEMBAR
+# error \"No ETHR_MEMBAR defined\"
+#endif
+
+#define ETHR_MEMORY_BARRIER ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore|ETHR_StoreLoad|ETHR_StoreStore)
+#define ETHR_WRITE_MEMORY_BARRIER ETHR_MEMBAR(ETHR_StoreStore)
+#define ETHR_READ_MEMORY_BARRIER ETHR_MEMBAR(ETHR_LoadLoad)
+#ifdef ETHR_READ_DEPEND_MEMORY_BARRIER
+# undef ETHR_ORDERED_READ_DEPEND
+#else
+# define ETHR_READ_DEPEND_MEMORY_BARRIER ETHR_COMPILER_BARRIER
+# define ETHR_ORDERED_READ_DEPEND
+#endif
+"].
+
+c_top() ->
+ ["
+
+#ifdef HAVE_CONFIG_H
+#include \"config.h\"
+#endif
+
+#define ETHR_TRY_INLINE_FUNCS
+#define ETHR_INLINE_DW_ATMC_FUNC_NAME_(X) X ## __
+#define ETHR_INLINE_ATMC_FUNC_NAME_(X) X ## __
+#define ETHR_INLINE_ATMC32_FUNC_NAME_(X) X ## __
+#define ETHR_ATOMIC_IMPL__
+
+#include \"ethread.h\"
+#include \"ethr_internal.h\"
+
+#if (!defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS) \\
+ || !defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS))
+/*
+ * Spinlock based fallback for atomics used in absence of a native
+ * implementation.
+ */
+
+#define ETHR_ATMC_FLLBK_ADDR_BITS ", ?ETHR_ATMC_FLLBK_ADDR_BITS, "
+#define ETHR_ATMC_FLLBK_ADDR_SHIFT ", ?ETHR_ATMC_FLLBK_ADDR_SHIFT, "
+
+typedef struct {
+ union {
+ ethr_spinlock_t lck;
+ char buf[ETHR_CACHE_LINE_ALIGN_SIZE(sizeof(ethr_spinlock_t))];
+ } u;
+} ethr_atomic_protection_t;
+
+extern ethr_atomic_protection_t ethr_atomic_protection__[1 << ETHR_ATMC_FLLBK_ADDR_BITS];
+
+#define ETHR_ATOMIC_PTR2LCK__(PTR) \\
+(&ethr_atomic_protection__[((((ethr_uint_t) (PTR)) >> ETHR_ATMC_FLLBK_ADDR_SHIFT) \\
+ & ((1 << ETHR_ATMC_FLLBK_ADDR_BITS) - 1))].u.lck)
+
+
+#define ETHR_ATOMIC_OP_FALLBACK_IMPL__(AP, EXPS) \\
+do { \\
+ ethr_spinlock_t *slp__ = ETHR_ATOMIC_PTR2LCK__((AP)); \\
+ ethr_spin_lock(slp__); \\
+ { EXPS; } \\
+ ethr_spin_unlock(slp__); \\
+} while (0)
+
+ethr_atomic_protection_t ethr_atomic_protection__[1 << ETHR_ATMC_FLLBK_ADDR_BITS];
+
+#endif
+
+", make_amc_fallback(), "
+
+int
+ethr_init_atomics(void)
+{
+#if (!defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS) \\
+ || !defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS))
+ int i;
+ for (i = 0; i < (1 << ETHR_ATMC_FLLBK_ADDR_BITS); i++) {
+ int res = ethr_spinlock_init(&ethr_atomic_protection__[i].u.lck);
+ if (res != 0)
+ return res;
+ }
+#endif
+ return 0;
+}
+"].
+
+make_amc_fallback() ->
+ ["
+#if defined(ETHR_AMC_FALLBACK__)
+
+/*
+ * Fallback for large sized (word and/or double word size) atomics using
+ * an \"Atomic Modification Counter\" based on smaller sized native atomics.
+ *
+ * We use a 63-bit modification counter and a one bit exclusive flag.
+ * If 32-bit native atomics are used, we need two 32-bit native atomics.
+ * The exclusive flag is the least significant bit, or if multiple atomics
+ * are used, the least significant bit of the least significant atomic.
+ *
+ * When using the AMC fallback the following is true:
+ * - Reads of the same atomic variable can be done in parallel.
+ * - Uncontended reads doesn't cause any cache line invalidations,
+ * since no modifications are done.
+ * - Assuming that the AMC atomic(s) and the integer(s) containing the
+ * value of the implemented atomic resides in the same cache line,
+ * modifications will only cause invalidations of one cache line.
+ *
+ * When using the spinlock based fallback none of the above is true,
+ * however, the spinlock based fallback consumes less memory.
+ */
+
+# if ETHR_AMC_NO_ATMCS__ != 1 && ETHR_AMC_NO_ATMCS__ != 2
+# error \"Not supported\"
+# endif
+# define ETHR_AMC_MAX_TRY_READ__ 10
+# ifdef ETHR_DEBUG
+# define ETHR_DBG_CHK_EXCL_STATE(ASP, S) \\
+do { \\
+ ETHR_AMC_SINT_T__ act = ETHR_AMC_ATMC_FUNC__(read)(&(ASP)->atomic[0]); \\
+ ETHR_ASSERT(act == (S) + 1); \\
+ ETHR_ASSERT(act & 1); \\
+} while (0)
+# else
+# define ETHR_DBG_CHK_EXCL_STATE(ASP, S)
+# endif
+
+static ETHR_INLINE void
+amc_init(ethr_amc_t *amc, int dw, ethr_sint_t *avar, ethr_sint_t *val)
+{
+ avar[0] = val[0];
+ if (dw)
+ avar[1] = val[1];
+#if ETHR_AMC_NO_ATMCS__ == 2
+ ETHR_AMC_ATMC_FUNC__(init)(&amc->atomic[1], 0);
+#endif
+ ETHR_AMC_ATMC_FUNC__(init_wb)(&amc->atomic[0], 0);
+}
+
+static ETHR_INLINE ETHR_AMC_SINT_T__
+amc_set_excl(ethr_amc_t *amc, ETHR_AMC_SINT_T__ prev_state0)
+{
+ ETHR_AMC_SINT_T__ state0 = prev_state0;
+ /* Set exclusive flag. */
+ while (1) {
+ ETHR_AMC_SINT_T__ act_state0, new_state0;
+ while (state0 & 1) { /* Wait until exclusive bit has been cleared */
+ ETHR_SPIN_BODY;
+ state0 = ETHR_AMC_ATMC_FUNC__(read)(&amc->atomic[0]);
+ }
+ /* Try to set exclusive bit */
+ new_state0 = state0 + 1;
+ act_state0 = ETHR_AMC_ATMC_FUNC__(cmpxchg_acqb)(&amc->atomic[0],
+ new_state0,
+ state0);
+ if (state0 == act_state0)
+ return state0; /* old state0 */
+ state0 = act_state0;
+ }
+}
+
+static ETHR_INLINE void
+amc_inc_mc_unset_excl(ethr_amc_t *amc, ETHR_AMC_SINT_T__ old_state0)
+{
+ ETHR_AMC_SINT_T__ state0 = old_state0;
+
+ /* Increment modification counter and reset exclusive flag. */
+
+ ETHR_DBG_CHK_EXCL_STATE(amc, state0);
+
+ state0 += 2;
+
+ ETHR_ASSERT((state0 & 1) == 0);
+
+#if ETHR_AMC_NO_ATMCS__ == 2
+ if (state0 == 0) {
+ /*
+ * state0 wrapped, so we need to increment state1. There is no need
+ * for atomic inc op, since this is always done while having exclusive
+ * flag.
+ */
+ ETHR_AMC_SINT_T__ state1 = ETHR_AMC_ATMC_FUNC__(read)(&amc->atomic[1]);
+ state1++;
+ ETHR_AMC_ATMC_FUNC__(set)(&amc->atomic[1], state1);
+ }
+#endif
+ ETHR_AMC_ATMC_FUNC__(set_relb)(&amc->atomic[0], state0);
+}
+
+static ETHR_INLINE void
+amc_unset_excl(ethr_amc_t *amc, ETHR_AMC_SINT_T__ old_state0)
+{
+ ETHR_DBG_CHK_EXCL_STATE(amc, old_state0);
+ /*
+ * Reset exclusive flag, but leave modification counter unchanged,
+ * i.e., restore state to what it was before setting exclusive
+ * flag.
+ */
+ ETHR_AMC_ATMC_FUNC__(set_relb)(&amc->atomic[0], old_state0);
+}
+
+static ETHR_INLINE void
+amc_set(ethr_amc_t *amc, int dw, ethr_sint_t *avar, ethr_sint_t *val)
+{
+ ETHR_AMC_SINT_T__ state0 = ETHR_AMC_ATMC_FUNC__(read)(&amc->atomic[0]);
+
+ state0 = amc_set_excl(amc, state0);
+
+ avar[0] = val[0];
+ if (dw)
+ avar[1] = val[1];
+
+ amc_inc_mc_unset_excl(amc, state0);
+}
+
+static ETHR_INLINE int
+amc_try_read(ethr_amc_t *amc, int dw, ethr_sint_t *avar,
+ ethr_sint_t *val, ETHR_AMC_SINT_T__ *state0p)
+{
+ /* *state0p should contain last read value if aborting */
+ ETHR_AMC_SINT_T__ old_state0;
+#if ETHR_AMC_NO_ATMCS__ == 2
+ ETHR_AMC_SINT_T__ state1;
+ int abrt;
+#endif
+
+ *state0p = ETHR_AMC_ATMC_FUNC__(read_rb)(&amc->atomic[0]);
+ if ((*state0p) & 1)
+ return 0; /* exclusive flag set; abort */
+#if ETHR_AMC_NO_ATMCS__ == 2
+ state1 = ETHR_AMC_ATMC_FUNC__(read_rb)(&amc->atomic[1]);
+#else
+ ETHR_COMPILER_BARRIER;
+#endif
+
+ val[0] = avar[0];
+ if (dw)
+ val[1] = avar[1];
+
+ ETHR_READ_MEMORY_BARRIER;
+
+ /*
+ * Abort if state has changed (i.e, either the exclusive
+ * flag is set, or modification counter changed).
+ */
+ old_state0 = *state0p;
+#if ETHR_AMC_NO_ATMCS__ == 2
+ *state0p = ETHR_AMC_ATMC_FUNC__(read_rb)(&amc->atomic[0]);
+ abrt = (old_state0 != *state0p);
+ abrt |= (state1 != ETHR_AMC_ATMC_FUNC__(read)(&amc->atomic[1]));
+ return abrt == 0;
+#else
+ *state0p = ETHR_AMC_ATMC_FUNC__(read)(&amc->atomic[0]);
+ return old_state0 == *state0p;
+#endif
+}
+
+static ETHR_INLINE void
+amc_read(ethr_amc_t *amc, int dw, ethr_sint_t *avar, ethr_sint_t *val)
+{
+ ETHR_AMC_SINT_T__ state0;
+ int i;
+
+#if ETHR_AMC_MAX_TRY_READ__ == 0
+ state0 = ETHR_AMC_ATMC_FUNC__(read)(&amc->atomic[0]);
+#else
+ for (i = 0; i < ETHR_AMC_MAX_TRY_READ__; i++) {
+ if (amc_try_read(amc, dw, avar, val, &state0))
+ return; /* read success */
+ ETHR_SPIN_BODY;
+ }
+#endif
+
+ state0 = amc_set_excl(amc, state0);
+
+ val[0] = avar[0];
+ if (dw)
+ val[1] = avar[1];
+
+ amc_unset_excl(amc, state0);
+}
+
+static ETHR_INLINE int
+amc_cmpxchg(ethr_amc_t *amc, int dw, ethr_sint_t *avar,
+ ethr_sint_t *new, ethr_sint_t *xchg)
+{
+ ethr_sint_t val[2];
+ ETHR_AMC_SINT_T__ state0;
+
+ if (amc_try_read(amc, dw, avar, val, &state0)) {
+ if (val[0] != xchg[0] || (dw && val[1] != xchg[1])) {
+ xchg[0] = val[0];
+ if (dw)
+ xchg[1] = val[1];
+ return 0; /* failed */
+ }
+ /* Operation will succeed if not interrupted */
+ }
+
+ state0 = amc_set_excl(amc, state0);
+
+ if (xchg[0] != avar[0] || (dw && xchg[1] != avar[1])) {
+ xchg[0] = avar[0];
+ if (dw)
+ xchg[1] = avar[1];
+
+ ETHR_DBG_CHK_EXCL_STATE(amc, state0);
+
+ amc_unset_excl(amc, state0);
+ return 0; /* failed */
+ }
+
+ avar[0] = new[0];
+ if (dw)
+ avar[1] = new[1];
+
+ amc_inc_mc_unset_excl(amc, state0);
+ return 1;
+}
+
+
+#define ETHR_AMC_MODIFICATION_OPS__(AMC, OPS) \\
+do { \\
+ ETHR_AMC_SINT_T__ state0__; \\
+ state0__ = ETHR_AMC_ATMC_FUNC__(read)(&(AMC)->atomic[0]); \\
+ state0__ = amc_set_excl((AMC), state0__); \\
+ { OPS; } \\
+ amc_inc_mc_unset_excl((AMC), state0__); \\
+} while (0)
+
+#endif /* amc fallback */
+"].
+
diff --git a/erts/lib_src/win/ethr_event.c b/erts/lib_src/win/ethr_event.c
index 68f093f49c..bc2f635c26 100644
--- a/erts/lib_src/win/ethr_event.c
+++ b/erts/lib_src/win/ethr_event.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2009-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2009-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -28,13 +28,10 @@
/* --- Windows implementation of thread events ------------------------------ */
-#pragma intrinsic(_InterlockedExchangeAdd)
-#pragma intrinsic(_InterlockedCompareExchange)
-
int
ethr_event_init(ethr_event *e)
{
- e->state = ETHR_EVENT_OFF__;
+ ethr_atomic32_init(&e->state, ETHR_EVENT_OFF__);
e->handle = CreateEvent(NULL, FALSE, FALSE, NULL);
if (e->handle == INVALID_HANDLE_VALUE)
return ethr_win_get_errno__();
@@ -63,7 +60,6 @@ ethr_event_reset(ethr_event *e)
static ETHR_INLINE int
wait(ethr_event *e, int spincount)
{
- LONG state;
DWORD code;
int sc, res, until_yield = ETHR_YIELD_AFTER_BUSY_LOOPS;
@@ -73,13 +69,9 @@ wait(ethr_event *e, int spincount)
sc = spincount;
while (1) {
- long on;
+ ethr_sint32_t state;
while (1) {
-#if ETHR_READ_AND_SET_WITHOUT_INTERLOCKED_OP__
- state = e->state;
-#else
- state = _InterlockedExchangeAdd(&e->state, (LONG) 0);
-#endif
+ state = ethr_atomic32_read(&e->state);
if (state == ETHR_EVENT_ON__)
return 0;
if (sc == 0)
@@ -95,9 +87,9 @@ wait(ethr_event *e, int spincount)
}
if (state != ETHR_EVENT_OFF_WAITER__) {
- state = _InterlockedCompareExchange(&e->state,
- ETHR_EVENT_OFF_WAITER__,
- ETHR_EVENT_OFF__);
+ state = ethr_atomic32_cmpxchg(&e->state,
+ ETHR_EVENT_OFF_WAITER__,
+ ETHR_EVENT_OFF__);
if (state == ETHR_EVENT_ON__)
return 0;
ETHR_ASSERT(state == ETHR_EVENT_OFF__);
diff --git a/erts/lib_src/win/ethread.c b/erts/lib_src/win/ethread.c
index 789a360b11..3abda6de4c 100644
--- a/erts/lib_src/win/ethread.c
+++ b/erts/lib_src/win/ethread.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -35,6 +35,7 @@
#include <winerror.h>
#include <stdio.h>
#include <limits.h>
+#include <intrin.h>
#define ETHR_INLINE_FUNC_NAME_(X) X ## __
#define ETHREAD_IMPL__
@@ -158,6 +159,25 @@ ethr_abort__(void)
#endif
}
+#if defined(ETHR_X86_RUNTIME_CONF__)
+
+#pragma intrinsic(__cpuid)
+
+void
+ethr_x86_cpuid__(int *eax, int *ebx, int *ecx, int *edx)
+{
+ int CPUInfo[4];
+
+ __cpuid(CPUInfo, *eax);
+
+ *eax = CPUInfo[0];
+ *ebx = CPUInfo[1];
+ *ecx = CPUInfo[2];
+ *edx = CPUInfo[3];
+}
+
+#endif /* ETHR_X86_RUNTIME_CONF__ */
+
/*
* ----------------------------------------------------------------------------
* Exported functions
diff --git a/erts/preloaded/ebin/erl_prim_loader.beam b/erts/preloaded/ebin/erl_prim_loader.beam
index dccb92a5af..fe91a604b5 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 b537546071..dda24d4405 100644
--- a/erts/preloaded/ebin/erlang.beam
+++ b/erts/preloaded/ebin/erlang.beam
Binary files differ
diff --git a/erts/preloaded/ebin/init.beam b/erts/preloaded/ebin/init.beam
index 901def5eba..37fd8bb832 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 62ebbb9ffe..e255cc803f 100644
--- a/erts/preloaded/ebin/otp_ring0.beam
+++ b/erts/preloaded/ebin/otp_ring0.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_file.beam b/erts/preloaded/ebin/prim_file.beam
index 66fcb9e6a9..6227b562a1 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 9894050cba..d44bbbbd27 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 9ee70d59ec..7e1a5d1fdb 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 542e266f88..ebf9f8e6d6 100644
--- a/erts/preloaded/ebin/zlib.beam
+++ b/erts/preloaded/ebin/zlib.beam
Binary files differ
diff --git a/erts/preloaded/src/erl_prim_loader.erl b/erts/preloaded/src/erl_prim_loader.erl
index 024b20eadb..35defde692 100644
--- a/erts/preloaded/src/erl_prim_loader.erl
+++ b/erts/preloaded/src/erl_prim_loader.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -102,8 +102,14 @@ debug(#prim_state{debug = Deb}, Term) ->
%%% Interface Functions.
%%% --------------------------------------------------------
--spec start(term(), atom() | string(), host() | [host()]) ->
- {'ok', pid()} | {'error', term()}.
+-spec start(Id, Loader, Hosts) ->
+ {'ok', Pid} | {'error', What} when
+ Id :: term(),
+ Loader :: atom() | string(),
+ Hosts :: Host | [Host],
+ Host :: host(),
+ Pid :: pid(),
+ What :: term().
start(Id, Pgm, Hosts) when is_atom(Hosts) ->
start(Id, Pgm, [Hosts]);
start(Id, Pgm0, Hosts) ->
@@ -123,18 +129,6 @@ start(Id, Pgm0, Hosts) ->
{error,Reason}
end.
-start_it("ose_inet"=Cmd, Id, Pid, Hosts) ->
- %% Setup reserved port for ose_inet driver (only OSE)
- case catch erlang:open_port({spawn,Cmd}, [binary]) of
- {'EXIT',Why} ->
- ?dbg(ose_inet_port_open_fail, Why),
- Why;
- OseInetPort ->
- ?dbg(ose_inet_port, OseInetPort),
- OseInetPort
- end,
- start_it("inet", Id, Pid, Hosts);
-
%% Hosts must be a list on form ['1.2.3.4' ...]
start_it("inet", Id, Pid, Hosts) ->
process_flag(trap_exit, true),
@@ -174,15 +168,20 @@ init_ack(Pid) ->
Pid ! {self(),ok},
ok.
--spec set_path([string()]) -> 'ok'.
+-spec set_path(Path) -> 'ok' when
+ Path :: [Dir :: string()].
set_path(Paths) when is_list(Paths) ->
request({set_path,Paths}).
--spec get_path() -> {'ok', [string()]}.
+-spec get_path() -> {'ok', Path} when
+ Path :: [Dir :: string()].
get_path() ->
request({get_path,[]}).
--spec get_file(atom() | string()) -> {'ok', binary(), string()} | 'error'.
+-spec get_file(Filename) -> {'ok', Bin, FullName} | 'error' when
+ Filename :: atom() | string(),
+ Bin :: binary(),
+ FullName :: string().
get_file(File) when is_atom(File) ->
get_file(atom_to_list(File));
get_file(File) ->
@@ -202,13 +201,15 @@ get_files(ModFiles, Fun) ->
ok
end.
--spec list_dir(string()) -> {'ok', [string()]} | 'error'.
+-spec list_dir(Dir) -> {'ok', Filenames} | 'error' when
+ Dir :: string(),
+ Filenames :: [Filename :: string()].
list_dir(Dir) ->
check_file_result(list_dir, Dir, request({list_dir,Dir})).
-%% -> {ok,Info} | error
--spec read_file_info(string()) -> {'ok', tuple()} | 'error'.
-
+-spec read_file_info(Filename) -> {'ok', FileInfo} | 'error' when
+ Filename :: string(),
+ FileInfo :: file:file_info().
read_file_info(File) ->
check_file_result(read_file_info, File, request({read_file_info,File})).
@@ -395,7 +396,7 @@ handle_timeout(State = #state{loader = inet}, Parent) ->
inet_timeout_handler(State, Parent).
%%% --------------------------------------------------------
-%%% Functions which handles efile as prim_loader (default).
+%%% Functions which handle efile as prim_loader (default).
%%% --------------------------------------------------------
%%% Reading many files in parallel is an optimization.
@@ -469,7 +470,7 @@ efile_get_file_from_port2(#state{prim_state = PS} = State, File) ->
end.
efile_get_file_from_port3(State, File, [P | Paths]) ->
- case efile_get_file_from_port2(State, concat([P,"/",File])) of
+ case efile_get_file_from_port2(State, join(P, File)) of
{{error,Reason},State1} when Reason =/= emfile ->
case Paths of
[] -> % return last error
@@ -522,7 +523,7 @@ efile_timeout_handler(#state{n_timeouts = N} = State, _Parent) ->
end.
%%% --------------------------------------------------------
-%%% Functions which handles inet prim_loader
+%%% Functions which handle inet prim_loader
%%% --------------------------------------------------------
%%
@@ -643,7 +644,7 @@ inet_get_file_from_port(State, File, Paths) ->
end.
inet_get_file_from_port1(File, [P | Paths], State) ->
- File1 = concat([P,"/",File]),
+ File1 = join(P, File),
case inet_send_and_rcv({get,File1}, File1, State) of
{{error,Reason},State1} ->
case Paths of
@@ -728,7 +729,7 @@ udp_options() ->
%% INET version IPv4 addresses
%%
ll_tcp_connect(LocalPort, IP, RemotePort) ->
- case ll_open_set_bind(tcp, ?INET_FAMILY, tcp_options(),
+ case ll_open_set_bind(tcp, ?INET_FAMILY, stream, tcp_options(),
?INET_ADDRESS, LocalPort) of
{ok,S} ->
case prim_inet:connect(S, IP, RemotePort, tcp_timeout()) of
@@ -742,11 +743,11 @@ ll_tcp_connect(LocalPort, IP, RemotePort) ->
%% Open and initialize an udp port for broadcast
%%
ll_udp_open(P) ->
- ll_open_set_bind(udp, ?INET_FAMILY, udp_options(), ?INET_ADDRESS, P).
+ ll_open_set_bind(udp, ?INET_FAMILY, dgram, udp_options(), ?INET_ADDRESS, P).
-ll_open_set_bind(Protocol, Family, SOpts, IP, Port) ->
- case prim_inet:open(Protocol, Family) of
+ll_open_set_bind(Protocol, Family, Type, SOpts, IP, Port) ->
+ case prim_inet:open(Protocol, Family, Type) of
{ok, S} ->
case prim_inet:setopts(S, SOpts) of
ok ->
@@ -1151,14 +1152,8 @@ send_all(U, [IP | AL], Cmd) ->
send_all(U, AL, Cmd);
send_all(_U, [], _) -> ok.
-%%concat([A|T]) when is_atom(A) -> %Atom
-%% atom_to_list(A) ++ concat(T);
-concat([C|T]) when C >= 0, C =< 255 ->
- [C|concat(T)];
-concat([S|T]) -> %String
- S ++ concat(T);
-concat([]) ->
- [].
+join(P, F) ->
+ P ++ "/" ++ F.
member(X, [X|_]) -> true;
member(X, [_|Y]) -> member(X, Y);
@@ -1360,9 +1355,7 @@ pathtype(Name) when is_list(Name) ->
absolute;
_ ->
relative
- end;
- {ose,_} ->
- unix_pathtype(Name)
+ end
end.
unix_pathtype(Name) ->
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index 4679a916c7..e9a59a7aaf 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -35,14 +35,15 @@
-export([delay_trap/2]).
-export([set_cookie/2, get_cookie/0]).
-export([nodes/0]).
--export([concat_binary/1]).
+
-export([list_to_integer/2,integer_to_list/2]).
-export([flush_monitor_message/2]).
-export([set_cpu_topology/1, format_cpu_topology/1]).
-export([await_proc_exit/3]).
+-export([memory/0, memory/1]).
+-export([alloc_info/1, alloc_sizes/1]).
-deprecated([hash/2]).
--deprecated([concat_binary/1]).
% Get rid of autoimports of spawn to avoid clashes with ourselves.
-compile({no_auto_import,[spawn/1]}).
@@ -53,22 +54,31 @@
-compile({no_auto_import,[spawn_opt/4]}).
-compile({no_auto_import,[spawn_opt/5]}).
-%%--------------------------------------------------------------------------
+-export_type([timestamp/0]).
--type date() :: {pos_integer(), pos_integer(), pos_integer()}.
--type time() :: {non_neg_integer(), non_neg_integer(), non_neg_integer()}.
--type date_time() :: {date(), time()}.
+-type timestamp() :: {MegaSecs :: non_neg_integer(),
+ Secs :: non_neg_integer(),
+ MicroSecs :: non_neg_integer()}.
%%--------------------------------------------------------------------------
+-spec apply(Fun, Args) -> term() when
+ Fun :: function(),
+ Args :: [term()].
apply(Fun, Args) ->
erlang:apply(Fun, Args).
+-spec apply(Module, Function, Args) -> term() when
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()].
apply(Mod, Name, Args) ->
erlang:apply(Mod, Name, Args).
%% Spawns with a fun
+-spec spawn(Fun) -> pid() when
+ Fun :: function().
spawn(F) when is_function(F) ->
spawn(erlang, apply, [F, []]);
spawn({M,F}=MF) when is_atom(M), is_atom(F) ->
@@ -76,6 +86,9 @@ spawn({M,F}=MF) when is_atom(M), is_atom(F) ->
spawn(F) ->
erlang:error(badarg, [F]).
+-spec spawn(Node, Fun) -> pid() when
+ Node :: node(),
+ Fun :: function().
spawn(N, F) when N =:= node() ->
spawn(F);
spawn(N, F) when is_function(F) ->
@@ -85,6 +98,8 @@ spawn(N, {M,F}=MF) when is_atom(M), is_atom(F) ->
spawn(N, F) ->
erlang:error(badarg, [N, F]).
+-spec spawn_link(Fun) -> pid() when
+ Fun :: function().
spawn_link(F) when is_function(F) ->
spawn_link(erlang, apply, [F, []]);
spawn_link({M,F}=MF) when is_atom(M), is_atom(F) ->
@@ -92,6 +107,9 @@ spawn_link({M,F}=MF) when is_atom(M), is_atom(F) ->
spawn_link(F) ->
erlang:error(badarg, [F]).
+-spec spawn_link(Node, Fun) -> pid() when
+ Node :: node(),
+ Fun :: function().
spawn_link(N, F) when N =:= node() ->
spawn_link(F);
spawn_link(N, F) when is_function(F) ->
@@ -103,16 +121,30 @@ spawn_link(N, F) ->
%% Spawn and atomically set up a monitor.
+-spec spawn_monitor(Fun) -> {pid(), reference()} when
+ Fun :: function().
spawn_monitor(F) when is_function(F, 0) ->
erlang:spawn_opt({erlang,apply,[F,[]],[monitor]});
spawn_monitor(F) ->
erlang:error(badarg, [F]).
+-spec spawn_monitor(Module, Function, Args) -> {pid(), reference()} when
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()].
spawn_monitor(M, F, A) when is_atom(M), is_atom(F), is_list(A) ->
erlang:spawn_opt({M,F,A,[monitor]});
spawn_monitor(M, F, A) ->
erlang:error(badarg, [M,F,A]).
+-spec spawn_opt(Fun, Options) -> pid() | {pid(), reference()} when
+ Fun :: function(),
+ Options :: [Option],
+ Option :: link | monitor | {priority, Level}
+ | {fullsweep_after, Number :: non_neg_integer()}
+ | {min_heap_size, Size :: non_neg_integer()}
+ | {min_bin_vheap_size, VSize :: non_neg_integer()},
+ Level :: low | normal | high.
spawn_opt(F, O) when is_function(F) ->
spawn_opt(erlang, apply, [F, []], O);
spawn_opt({M,F}=MF, O) when is_atom(M), is_atom(F) ->
@@ -122,6 +154,15 @@ spawn_opt({M,F,A}, O) -> % For (undocumented) backward compatibility
spawn_opt(F, O) ->
erlang:error(badarg, [F, O]).
+-spec spawn_opt(Node, Fun, Options) -> pid() | {pid(), reference()} when
+ Node :: node(),
+ Fun :: function(),
+ Options :: [Option],
+ Option :: link | monitor | {priority, Level}
+ | {fullsweep_after, Number :: non_neg_integer()}
+ | {min_heap_size, Size :: non_neg_integer()}
+ | {min_bin_vheap_size, VSize :: non_neg_integer()},
+ Level :: low | normal | high.
spawn_opt(N, F, O) when N =:= node() ->
spawn_opt(F, O);
spawn_opt(N, F, O) when is_function(F) ->
@@ -133,6 +174,11 @@ spawn_opt(N, F, O) ->
%% Spawns with MFA
+-spec spawn(Node, Module, Function, Args) -> pid() when
+ Node :: node(),
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()].
spawn(N,M,F,A) when N =:= node(), is_atom(M), is_atom(F), is_list(A) ->
spawn(M,F,A);
spawn(N,M,F,A) when is_atom(N), is_atom(M), is_atom(F) ->
@@ -158,6 +204,11 @@ spawn(N,M,F,A) when is_atom(N), is_atom(M), is_atom(F) ->
spawn(N,M,F,A) ->
erlang:error(badarg, [N, M, F, A]).
+-spec spawn_link(Node, Module, Function, Args) -> pid() when
+ Node :: node(),
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()].
spawn_link(N,M,F,A) when N =:= node(), is_atom(M), is_atom(F), is_list(A) ->
spawn_link(M,F,A);
spawn_link(N,M,F,A) when is_atom(N), is_atom(M), is_atom(F) ->
@@ -183,6 +234,17 @@ spawn_link(N,M,F,A) when is_atom(N), is_atom(M), is_atom(F) ->
spawn_link(N,M,F,A) ->
erlang:error(badarg, [N, M, F, A]).
+-spec spawn_opt(Module, Function, Args, Options) ->
+ pid() | {pid(), reference()} when
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ Options :: [Option],
+ Option :: link | monitor | {priority, Level}
+ | {fullsweep_after, Number :: non_neg_integer()}
+ | {min_heap_size, Size :: non_neg_integer()}
+ | {min_bin_vheap_size, VSize :: non_neg_integer()},
+ Level :: low | normal | high.
spawn_opt(M, F, A, Opts) ->
case catch erlang:spawn_opt({M,F,A,Opts}) of
{'EXIT',{Reason,_}} ->
@@ -191,6 +253,18 @@ spawn_opt(M, F, A, Opts) ->
Res
end.
+-spec spawn_opt(Node, Module, Function, Args, Options) ->
+ pid() | {pid(), reference()} when
+ Node :: node(),
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ Options :: [Option],
+ Option :: link | monitor | {priority, Level}
+ | {fullsweep_after, Number :: non_neg_integer()}
+ | {min_heap_size, Size :: non_neg_integer()}
+ | {min_bin_vheap_size, VSize :: non_neg_integer()},
+ Level :: low | normal | high.
spawn_opt(N, M, F, A, O) when N =:= node(),
is_atom(M), is_atom(F), is_list(A),
is_list(O) ->
@@ -260,18 +334,25 @@ crasher(Node,Mod,Fun,Args,Opts,Reason) ->
[Mod,Fun,Args,Opts,Node]),
exit(Reason).
--spec yield() -> 'true'.
+-spec erlang:yield() -> 'true'.
yield() ->
erlang:yield().
--spec nodes() -> [node()].
+-spec nodes() -> Nodes when
+ Nodes :: [node()].
nodes() ->
erlang:nodes(visible).
--spec disconnect_node(node()) -> boolean().
+-spec disconnect_node(Node) -> boolean() | ignored when
+ Node :: node().
disconnect_node(Node) ->
net_kernel:disconnect(Node).
+-spec erlang:fun_info(Fun) -> [{Item, Info}] when
+ Fun :: function(),
+ Item :: arity | env | index | name
+ | module | new_index | new_uniq | pid | type | uniq,
+ Info :: term().
fun_info(Fun) when is_function(Fun) ->
Keys = [type,env,arity,name,uniq,index,new_uniq,new_index,module,pid],
fun_info_1(Keys, Fun, []).
@@ -283,24 +364,37 @@ fun_info_1([K|Ks], Fun, A) ->
end;
fun_info_1([], _, A) -> A.
--type dst() :: pid() | port() | atom() | {atom(), node()}.
+-type dst() :: pid()
+ | port()
+ | (RegName :: atom())
+ | {RegName :: atom(), Node :: node()}.
--spec send_nosuspend(dst(), term()) -> boolean().
+-spec erlang:send_nosuspend(Dest, Msg) -> boolean() when
+ Dest :: dst(),
+ Msg :: term().
send_nosuspend(Pid, Msg) ->
send_nosuspend(Pid, Msg, []).
--spec send_nosuspend(dst(), term(), ['noconnect' | 'nosuspend']) -> boolean().
+-spec erlang:send_nosuspend(Dest, Msg, Options) -> boolean() when
+ Dest :: dst(),
+ Msg :: term(),
+ Options :: [noconnect].
send_nosuspend(Pid, Msg, Opts) ->
case erlang:send(Pid, Msg, [nosuspend|Opts]) of
ok -> true;
_ -> false
end.
--spec localtime_to_universaltime(date_time()) -> date_time().
+-spec erlang:localtime_to_universaltime({Date1, Time1}) -> {Date2, Time2} when
+ Date1 :: calendar:date(),
+ Date2 :: calendar:date(),
+ Time1 :: calendar:time(),
+ Time2 :: calendar:time().
localtime_to_universaltime(Localtime) ->
erlang:localtime_to_universaltime(Localtime, undefined).
--spec suspend_process(pid()) -> 'true'.
+-spec erlang:suspend_process(Suspendee) -> 'true' when
+ Suspendee :: pid().
suspend_process(P) ->
case catch erlang:suspend_process(P, []) of
{'EXIT', {Reason, _}} -> erlang:error(Reason, [P]);
@@ -426,6 +520,9 @@ delay_trap(Result, Timeout) -> receive after Timeout -> Result end.
%% Messages to us use our cookie. IF we change our cookie, other nodes
%% have to reflect that, which we cannot forsee.
%%
+-spec erlang:set_cookie(Node, Cookie) -> true when
+ Node :: node(),
+ Cookie :: atom().
set_cookie(Node, C) when Node =/= nonode@nohost, is_atom(Node) ->
case is_atom(C) of
true ->
@@ -434,14 +531,14 @@ set_cookie(Node, C) when Node =/= nonode@nohost, is_atom(Node) ->
error(badarg)
end.
--spec get_cookie() -> atom().
+-spec erlang:get_cookie() -> Cookie | nocookie when
+ Cookie :: atom().
get_cookie() ->
auth:get_cookie().
-concat_binary(List) ->
- list_to_binary(List).
-
--spec integer_to_list(integer(), 1..255) -> string().
+-spec integer_to_list(Integer, Base) -> string() when
+ Integer :: integer(),
+ Base :: 2..36.
integer_to_list(I, 10) ->
erlang:integer_to_list(I);
integer_to_list(I, Base)
@@ -469,6 +566,9 @@ integer_to_list(I0, Base, R0) ->
end.
+-spec list_to_integer(String, Base) -> integer() when
+ String :: string(),
+ Base :: 2..36.
list_to_integer(L, 10) ->
erlang:list_to_integer(L);
list_to_integer(L, Base)
@@ -689,10 +789,418 @@ await_proc_exit(Proc, Op, Data) ->
end
end.
--spec min(term(), term()) -> term().
+-spec min(Term1, Term2) -> Minimum when
+ Term1 :: term(),
+ Term2 :: term(),
+ Minimum :: term().
min(A, B) when A > B -> B;
min(A, _) -> A.
--spec max(term(), term()) -> term().
+-spec max(Term1, Term2) -> Maximum when
+ Term1 :: term(),
+ Term2 :: term(),
+ Maximum :: term().
max(A, B) when A < B -> B;
max(A, _) -> A.
+
+
+%%
+%% erlang:memory/[0,1]
+%%
+%% NOTE! When updating these functions, make sure to also update
+%% erts_memory() in $ERL_TOP/erts/emulator/beam/erl_alloc.c
+%%
+
+-type memory_type() :: 'total' | 'processes' | 'processes_used' | 'system' | 'atom' | 'atom_used' | 'binary' | 'code' | 'ets' | 'low' | 'maximum'.
+
+-define(CARRIER_ALLOCS, [mseg_alloc, sbmbc_alloc, sbmbc_low_alloc]).
+-define(LOW_ALLOCS, [sbmbc_low_alloc, ll_low_alloc, std_low_alloc]).
+-define(ALL_NEEDED_ALLOCS, (erlang:system_info(alloc_util_allocators)
+ -- ?CARRIER_ALLOCS)).
+
+-record(memory, {total = 0,
+ processes = 0,
+ processes_used = 0,
+ system = 0,
+ atom = 0,
+ atom_used = 0,
+ binary = 0,
+ code = 0,
+ ets = 0,
+ low = 0,
+ maximum = 0}).
+
+-spec memory() -> [{memory_type(), non_neg_integer()}].
+memory() ->
+ case aa_mem_data(au_mem_data(?ALL_NEEDED_ALLOCS)) of
+ notsup ->
+ erlang:error(notsup);
+ Mem ->
+ InstrTail = case Mem#memory.maximum of
+ 0 -> [];
+ _ -> [{maximum, Mem#memory.maximum}]
+ end,
+ Tail = case Mem#memory.low of
+ 0 -> InstrTail;
+ _ -> [{low, Mem#memory.low} | InstrTail]
+ end,
+ [{total, Mem#memory.total},
+ {processes, Mem#memory.processes},
+ {processes_used, Mem#memory.processes_used},
+ {system, Mem#memory.system},
+ {atom, Mem#memory.atom},
+ {atom_used, Mem#memory.atom_used},
+ {binary, Mem#memory.binary},
+ {code, Mem#memory.code},
+ {ets, Mem#memory.ets} | Tail]
+ end.
+
+-spec memory(memory_type()|[memory_type()]) -> non_neg_integer() | [{memory_type(), non_neg_integer()}].
+memory(Type) when is_atom(Type) ->
+ {AA, ALCU, ChkSup, BadArgZero} = need_mem_info(Type),
+ case get_mem_data(ChkSup, ALCU, AA) of
+ notsup ->
+ erlang:error(notsup, [Type]);
+ Mem ->
+ Value = get_memval(Type, Mem),
+ case {BadArgZero, Value} of
+ {true, 0} -> erlang:error(badarg, [Type]);
+ _ -> Value
+ end
+ end;
+memory(Types) when is_list(Types) ->
+ {AA, ALCU, ChkSup, BadArgZeroList} = need_mem_info_list(Types),
+ case get_mem_data(ChkSup, ALCU, AA) of
+ notsup ->
+ erlang:error(notsup, [Types]);
+ Mem ->
+ case memory_result_list(Types, BadArgZeroList, Mem) of
+ badarg -> erlang:error(badarg, [Types]);
+ Result -> Result
+ end
+ end.
+
+memory_result_list([], [], _Mem) ->
+ [];
+memory_result_list([T|Ts], [BAZ|BAZs], Mem) ->
+ case memory_result_list(Ts, BAZs, Mem) of
+ badarg -> badarg;
+ TVs ->
+ V = get_memval(T, Mem),
+ case {BAZ, V} of
+ {true, 0} -> badarg;
+ _ -> [{T, V}| TVs]
+ end
+ end.
+
+get_mem_data(true, AlcUAllocs, NeedAllocatedAreas) ->
+ case memory_is_supported() of
+ false -> notsup;
+ true -> get_mem_data(false, AlcUAllocs, NeedAllocatedAreas)
+ end;
+get_mem_data(false, AlcUAllocs, NeedAllocatedAreas) ->
+ AlcUMem = case AlcUAllocs of
+ [] -> #memory{};
+ _ ->
+ au_mem_data(AlcUAllocs)
+ end,
+ case NeedAllocatedAreas of
+ true -> aa_mem_data(AlcUMem);
+ false -> AlcUMem
+ end.
+
+need_mem_info_list([]) ->
+ {false, [], false, []};
+need_mem_info_list([T|Ts]) ->
+ {MAA, MALCU, MChkSup, MBadArgZero} = need_mem_info_list(Ts),
+ {AA, ALCU, ChkSup, BadArgZero} = need_mem_info(T),
+ {case AA of
+ true -> true;
+ _ -> MAA
+ end,
+ ALCU ++ (MALCU -- ALCU),
+ case ChkSup of
+ true -> true;
+ _ -> MChkSup
+ end,
+ [BadArgZero|MBadArgZero]}.
+
+need_mem_info(Type) when Type == total;
+ Type == system ->
+ {true, ?ALL_NEEDED_ALLOCS, false, false};
+need_mem_info(Type) when Type == processes;
+ Type == processes_used ->
+ {true, [eheap_alloc, fix_alloc], true, false};
+need_mem_info(Type) when Type == atom;
+ Type == atom_used;
+ Type == code ->
+ {true, [], true, false};
+need_mem_info(binary) ->
+ {false, [binary_alloc], true, false};
+need_mem_info(ets) ->
+ {true, [ets_alloc], true, false};
+need_mem_info(low) ->
+ LowAllocs = ?LOW_ALLOCS -- ?CARRIER_ALLOCS,
+ {_, _, FeatureList, _} = erlang:system_info(allocator),
+ AlcUAllocs = case LowAllocs -- FeatureList of
+ [] -> LowAllocs;
+ _ -> []
+ end,
+ {false, AlcUAllocs, true, true};
+need_mem_info(maximum) ->
+ {true, [], true, true};
+need_mem_info(_) ->
+ {false, [], false, true}.
+
+get_memval(total, #memory{total = V}) -> V;
+get_memval(processes, #memory{processes = V}) -> V;
+get_memval(processes_used, #memory{processes_used = V}) -> V;
+get_memval(system, #memory{system = V}) -> V;
+get_memval(atom, #memory{atom = V}) -> V;
+get_memval(atom_used, #memory{atom_used = V}) -> V;
+get_memval(binary, #memory{binary = V}) -> V;
+get_memval(code, #memory{code = V}) -> V;
+get_memval(ets, #memory{ets = V}) -> V;
+get_memval(low, #memory{low = V}) -> V;
+get_memval(maximum, #memory{maximum = V}) -> V;
+get_memval(_, #memory{}) -> 0.
+
+memory_is_supported() ->
+ {_, _, FeatureList, _} = erlang:system_info(allocator),
+ case ((erlang:system_info(alloc_util_allocators)
+ -- ?CARRIER_ALLOCS)
+ -- FeatureList) of
+ [] -> true;
+ _ -> false
+ end.
+
+get_blocks_size([{blocks_size, Sz, _, _} | Rest], Acc) ->
+ get_blocks_size(Rest, Acc+Sz);
+get_blocks_size([{_, _, _, _} | Rest], Acc) ->
+ get_blocks_size(Rest, Acc);
+get_blocks_size([], Acc) ->
+ Acc.
+
+blocks_size([{Carriers, SizeList} | Rest], Acc) when Carriers == mbcs;
+ Carriers == sbcs;
+ Carriers == sbmbcs ->
+ blocks_size(Rest, get_blocks_size(SizeList, Acc));
+blocks_size([_ | Rest], Acc) ->
+ blocks_size(Rest, Acc);
+blocks_size([], Acc) ->
+ Acc.
+
+get_fix_proc([{ProcType, A1, U1}| Rest], {A0, U0}) when ProcType == proc;
+ ProcType == monitor_sh;
+ ProcType == nlink_sh;
+ ProcType == msg_ref ->
+ get_fix_proc(Rest, {A0+A1, U0+U1});
+get_fix_proc([_|Rest], Acc) ->
+ get_fix_proc(Rest, Acc);
+get_fix_proc([], Acc) ->
+ Acc.
+
+fix_proc([{fix_types, SizeList} | _Rest], Acc) ->
+ get_fix_proc(SizeList, Acc);
+fix_proc([_ | Rest], Acc) ->
+ fix_proc(Rest, Acc);
+fix_proc([], Acc) ->
+ Acc.
+
+is_low_alloc(_A, []) ->
+ false;
+is_low_alloc(A, [A|_As]) ->
+ true;
+is_low_alloc(A, [_A|As]) ->
+ is_low_alloc(A, As).
+
+is_low_alloc(A) ->
+ is_low_alloc(A, ?LOW_ALLOCS).
+
+au_mem_data(notsup, _) ->
+ notsup;
+au_mem_data(_, [{_, false} | _]) ->
+ notsup;
+au_mem_data(#memory{total = Tot,
+ processes = Proc,
+ processes_used = ProcU} = Mem,
+ [{eheap_alloc, _, Data} | Rest]) ->
+ Sz = blocks_size(Data, 0),
+ au_mem_data(Mem#memory{total = Tot+Sz,
+ processes = Proc+Sz,
+ processes_used = ProcU+Sz},
+ Rest);
+au_mem_data(#memory{total = Tot,
+ system = Sys,
+ ets = Ets} = Mem,
+ [{ets_alloc, _, Data} | Rest]) ->
+ Sz = blocks_size(Data, 0),
+ au_mem_data(Mem#memory{total = Tot+Sz,
+ system = Sys+Sz,
+ ets = Ets+Sz},
+ Rest);
+au_mem_data(#memory{total = Tot,
+ system = Sys,
+ binary = Bin} = Mem,
+ [{binary_alloc, _, Data} | Rest]) ->
+ Sz = blocks_size(Data, 0),
+ au_mem_data(Mem#memory{total = Tot+Sz,
+ system = Sys+Sz,
+ binary = Bin+Sz},
+ Rest);
+au_mem_data(#memory{total = Tot,
+ processes = Proc,
+ processes_used = ProcU,
+ system = Sys} = Mem,
+ [{fix_alloc, _, Data} | Rest]) ->
+ {A, U} = fix_proc(Data, {0, 0}),
+ Sz = blocks_size(Data, 0),
+ au_mem_data(Mem#memory{total = Tot+Sz,
+ processes = Proc+A,
+ processes_used = ProcU+U,
+ system = Sys+Sz-A},
+ Rest);
+au_mem_data(#memory{total = Tot,
+ system = Sys,
+ low = Low} = Mem,
+ [{A, _, Data} | Rest]) ->
+ Sz = blocks_size(Data, 0),
+ au_mem_data(Mem#memory{total = Tot+Sz,
+ system = Sys+Sz,
+ low = case is_low_alloc(A) of
+ true -> Low+Sz;
+ false -> Low
+ end},
+ Rest);
+au_mem_data(EMD, []) ->
+ EMD.
+
+au_mem_data(Allocs) ->
+ Ref = make_ref(),
+ erlang:system_info({allocator_sizes, Ref, Allocs}),
+ receive_emd(Ref).
+
+receive_emd(_Ref, EMD, 0) ->
+ EMD;
+receive_emd(Ref, EMD, N) ->
+ receive
+ {Ref, _, Data} ->
+ receive_emd(Ref, au_mem_data(EMD, Data), N-1)
+ end.
+
+receive_emd(Ref) ->
+ receive_emd(Ref, #memory{}, erlang:system_info(schedulers)).
+
+aa_mem_data(notsup, _) ->
+ notsup;
+aa_mem_data(#memory{} = Mem,
+ [{maximum, Max} | Rest]) ->
+ aa_mem_data(Mem#memory{maximum = Max},
+ Rest);
+aa_mem_data(#memory{} = Mem,
+ [{total, Tot} | Rest]) ->
+ aa_mem_data(Mem#memory{total = Tot,
+ system = 0}, % system will be adjusted later
+ Rest);
+aa_mem_data(#memory{atom = Atom,
+ atom_used = AtomU} = Mem,
+ [{atom_space, Alloced, Used} | Rest]) ->
+ aa_mem_data(Mem#memory{atom = Atom+Alloced,
+ atom_used = AtomU+Used},
+ Rest);
+aa_mem_data(#memory{atom = Atom,
+ atom_used = AtomU} = Mem,
+ [{atom_table, Sz} | Rest]) ->
+ aa_mem_data(Mem#memory{atom = Atom+Sz,
+ atom_used = AtomU+Sz},
+ Rest);
+aa_mem_data(#memory{ets = Ets} = Mem,
+ [{ets_misc, Sz} | Rest]) ->
+ aa_mem_data(Mem#memory{ets = Ets+Sz},
+ Rest);
+aa_mem_data(#memory{processes = Proc,
+ processes_used = ProcU,
+ system = Sys} = Mem,
+ [{ProcData, Sz} | Rest]) when ProcData == bif_timer;
+ ProcData == link_lh;
+ ProcData == process_table ->
+ aa_mem_data(Mem#memory{processes = Proc+Sz,
+ processes_used = ProcU+Sz,
+ system = Sys-Sz},
+ Rest);
+aa_mem_data(#memory{code = Code} = Mem,
+ [{CodeData, Sz} | Rest]) when CodeData == module_table;
+ CodeData == export_table;
+ CodeData == export_list;
+ CodeData == fun_table;
+ CodeData == module_refs;
+ CodeData == loaded_code ->
+ aa_mem_data(Mem#memory{code = Code+Sz},
+ Rest);
+aa_mem_data(EMD, [{_, _} | Rest]) ->
+ aa_mem_data(EMD, Rest);
+aa_mem_data(#memory{total = Tot,
+ processes = Proc,
+ system = Sys} = Mem,
+ []) when Sys =< 0 ->
+ %% Instrumented runtime system -> Sys = Tot - Proc
+ Mem#memory{system = Tot - Proc};
+aa_mem_data(EMD, []) ->
+ EMD.
+
+aa_mem_data(notsup) ->
+ notsup;
+aa_mem_data(EMD) ->
+ aa_mem_data(EMD, erlang:system_info(allocated_areas)).
+
+%%
+%% alloc_info/1 and alloc_sizes/1 are for internal use only (used by
+%% erlang:system_info({allocator|allocator_sizes, _})).
+%%
+
+alloc_info(Allocs) ->
+ get_alloc_info(allocator, Allocs).
+
+alloc_sizes(Allocs) ->
+ get_alloc_info(allocator_sizes, Allocs).
+
+get_alloc_info(Type, AAtom) when is_atom(AAtom) ->
+ [{AAtom, Result}] = get_alloc_info(Type, [AAtom]),
+ Result;
+get_alloc_info(Type, AList) when is_list(AList) ->
+ Ref = make_ref(),
+ erlang:system_info({Type, Ref, AList}),
+ receive_allocator(Ref,
+ erlang:system_info(schedulers),
+ mk_res_list(AList)).
+
+mk_res_list([]) ->
+ [];
+mk_res_list([Alloc | Rest]) ->
+ [{Alloc, []} | mk_res_list(Rest)].
+
+insert_instance(I, N, []) ->
+ [{instance, N, I}];
+insert_instance(I, N, [{instance, M, _}|_] = Rest) when N < M ->
+ [{instance, N, I} | Rest];
+insert_instance(I, N, [Prev|Rest]) ->
+ [Prev | insert_instance(I, N, Rest)].
+
+insert_info([], Ys) ->
+ Ys;
+insert_info([{A, false}|Xs], [{A, _IList}|Ys]) ->
+ insert_info(Xs, [{A, false}|Ys]);
+insert_info([{A, N, I}|Xs], [{A, IList}|Ys]) ->
+ insert_info(Xs, [{A, insert_instance(I, N, IList)}|Ys]);
+insert_info([{A1, _}|_] = Xs, [{A2, _} = Y | Ys]) when A1 /= A2 ->
+ [Y | insert_info(Xs, Ys)];
+insert_info([{A1, _, _}|_] = Xs, [{A2, _} = Y | Ys]) when A1 /= A2 ->
+ [Y | insert_info(Xs, Ys)].
+
+receive_allocator(_Ref, 0, Acc) ->
+ Acc;
+receive_allocator(Ref, N, Acc) ->
+ receive
+ {Ref, _, InfoList} ->
+ receive_allocator(Ref, N-1, insert_info(InfoList, Acc))
+ end.
diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl
index 24430a3d40..c9c434dea0 100644
--- a/erts/preloaded/src/init.erl
+++ b/erts/preloaded/src/init.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -28,10 +28,10 @@
%% : $Var in the boot script is expanded to
%% Value.
%% -loader LoaderMethod
-%% : efile, inet, ose_inet
+%% : efile, inet
%% (Optional - default efile)
%% -hosts [Node] : List of hosts from which we can boot.
-%% (Mandatory if -loader inet or ose_inet)
+%% (Mandatory if -loader inet)
%% -mode embedded : Load all modules at startup, no automatic loading
%% -mode interactive : Auto load modules (default system behaviour).
%% -path : Override path in bootfile.
@@ -79,19 +79,24 @@
debug(false, _) -> ok;
debug(_, T) -> erlang:display(T).
--spec get_arguments() -> [{atom(), [string()]}].
+-spec get_arguments() -> Flags when
+ Flags :: [{Flag :: atom(), Values :: [string()]}].
get_arguments() ->
request(get_arguments).
--spec get_plain_arguments() -> [string()].
+-spec get_plain_arguments() -> [Arg] when
+ Arg :: string().
get_plain_arguments() ->
bs2ss(request(get_plain_arguments)).
--spec get_argument(atom()) -> 'error' | {'ok', [[string()]]}.
+-spec get_argument(Flag) -> {'ok', Arg} | 'error' when
+ Flag :: atom(),
+ Arg :: [Values :: [string()]].
get_argument(Arg) ->
request({get_argument, Arg}).
--spec script_id() -> term().
+-spec script_id() -> Id when
+ Id :: term().
script_id() ->
request(script_id).
@@ -105,7 +110,9 @@ bs2ss(L0) when is_list(L0) ->
bs2ss(L) ->
L.
--spec get_status() -> {internal_status(), term()}.
+-spec get_status() -> {InternalStatus, ProvidedStatus} when
+ InternalStatus :: internal_status(),
+ ProvidedStatus :: term().
get_status() ->
request(get_status).
@@ -150,10 +157,12 @@ reboot() -> init ! {stop,reboot}, ok.
-spec stop() -> 'ok'.
stop() -> init ! {stop,stop}, ok.
--spec stop(non_neg_integer() | string()) -> 'ok'.
+-spec stop(Status) -> 'ok' when
+ Status :: non_neg_integer() | string().
stop(Status) -> init ! {stop,{stop,Status}}, ok.
--spec boot([binary()]) -> no_return().
+-spec boot(BootArgs) -> no_return() when
+ BootArgs :: [binary()].
boot(BootArgs) ->
register(init, self()),
process_flag(trap_exit, true),
@@ -336,7 +345,7 @@ notify(Pids) ->
lists:foreach(fun(Pid) -> Pid ! {init,started} end, Pids).
%% Garbage collect all info about initially loaded modules.
-%% This information is temporary stored until the code_server
+%% This information is temporarily stored until the code_server
%% is started.
%% We force the garbage collection as the init process holds
%% this information during the initialisation of the system and
@@ -1024,7 +1033,7 @@ start_it({eval,Bin}) ->
TsR -> reverse([{dot,1} | TsR])
end,
{ok,Expr} = erl_parse:parse_exprs(Ts1),
- erl_eval:exprs(Expr, []),
+ erl_eval:exprs(Expr, erl_eval:new_bindings()),
ok;
start_it([_|_]=MFA) ->
Ref = make_ref(),
diff --git a/erts/preloaded/src/prim_file.erl b/erts/preloaded/src/prim_file.erl
index 8e0790e74a..30b7a5246a 100644
--- a/erts/preloaded/src/prim_file.erl
+++ b/erts/preloaded/src/prim_file.erl
@@ -63,7 +63,7 @@
-include("file.hrl").
--define(DRV, efile).
+-define(DRV, "efile").
-define(FD_DRV, "efile").
-define(LARGEFILESIZE, (1 bsl 63)).
@@ -111,6 +111,7 @@
-define(FILE_RESP_EOF, 8).
-define(FILE_RESP_FNAME, 9).
-define(FILE_RESP_ALL_DATA, 10).
+-define(FILE_RESP_LFNAME, 11).
%% Open modes for the driver's open function.
-define(EFILE_MODE_READ, 1).
@@ -374,7 +375,7 @@ read(#file_descriptor{module = ?MODULE, data = {Port, _}}, Size)
{ok, Data};
{error, enomem} ->
%% Garbage collecting here might help if
- %% the current processes has some old binaries left.
+ %% the current processes have some old binaries left.
erlang:garbage_collect(),
case drv_command(Port, <<?FILE_READ, Size:64>>) of
{ok, {0, _Data}} when Size =/= 0 ->
@@ -549,7 +550,7 @@ write_file(_, _) ->
%% Returns {ok, Port}, the Port should be used as first argument in all
%% the following functions. Returns {error, Reason} upon failure.
start() ->
- try erlang:open_port({spawn, atom_to_list(?DRV)}, [binary]) of
+ try erlang:open_port({spawn, ?DRV}, [binary]) of
Port ->
{ok, Port}
catch
@@ -824,7 +825,7 @@ list_dir_int(Port, Dir) ->
%% Opens a driver port and converts any problems into {error, emfile}.
-%% Returns {ok, Port} when succesful.
+%% Returns {ok, Port} when successful.
drv_open(Driver, Portopts) ->
try erlang:open_port({spawn, Driver}, Portopts) of
@@ -914,6 +915,8 @@ drv_get_response(Port, R) when is_list(R) ->
{ok, R};
{ok, Name} ->
drv_get_response(Port, [Name|R]);
+ {append, Names} ->
+ drv_get_response(Port, append(Names, R));
Error ->
Error
end;
@@ -938,9 +941,11 @@ drv_get_response(Port) ->
%%%-----------------------------------------------------------------
%%% Utility functions.
+append([I | Is], R) when is_list(R) -> append(Is, [I | R]);
+append([], R) -> R.
-%% Converts a list of mode atoms into an mode word for the driver.
+%% Converts a list of mode atoms into a mode word for the driver.
%% Returns {Mode, Portopts, Setopts} where Portopts is a list of
%% options for erlang:open_port/2 and Setopts is a list of
%% setopt commands to send to the port, or error Reason upon failure.
@@ -1067,7 +1072,7 @@ translate_response(?FILE_RESP_N2DATA,
{ok, {Size, Offset, D}};
translate_response(?FILE_RESP_N2DATA = X, L0) when is_list(L0) ->
{Offset, L1} = get_uint64(L0),
- {ReadSize, L2} = get_uint64(L1),
+ {ReadSize, L2} = get_uint64(L1),
{Size, L3} = get_uint64(L2),
case {ReadSize, L3} of
{0, []} ->
@@ -1087,6 +1092,12 @@ translate_response(?FILE_RESP_FNAME, Data) when is_binary(Data) ->
{ok, prim_file:internal_native2name(Data)};
translate_response(?FILE_RESP_FNAME, Data) ->
{ok, Data};
+translate_response(?FILE_RESP_LFNAME, []) ->
+ ok;
+translate_response(?FILE_RESP_LFNAME, Data) when is_binary(Data) ->
+ {append, transform_lfname(Data)};
+translate_response(?FILE_RESP_LFNAME, Data) ->
+ {append, transform_lfname(Data)};
translate_response(?FILE_RESP_ALL_DATA, Data) ->
{ok, Data};
translate_response(X, Data) ->
@@ -1199,6 +1210,14 @@ transform_ldata(0, List, [Size | Sizes], R) ->
{Front, Rear} = lists_split(List, Size),
transform_ldata(0, Rear, Sizes, [Front | R]).
+transform_lfname(<<>>) -> [];
+transform_lfname(<<L:16, Name:L/binary, Names/binary>>) ->
+ [ prim_file:internal_native2name(Name) | transform_lfname(Names)];
+transform_lfname([]) -> [];
+transform_lfname([L1,L2|Names]) ->
+ L = (L1 bsl 8) bor L2,
+ {Name, Rest} = lists_split(Names, L),
+ [Name | transform_lfname(Rest)].
lists_split(List, 0) when is_list(List) ->
diff --git a/erts/preloaded/src/prim_inet.erl b/erts/preloaded/src/prim_inet.erl
index 8f2e845b4f..f144f73d68 100644
--- a/erts/preloaded/src/prim_inet.erl
+++ b/erts/preloaded/src/prim_inet.erl
@@ -25,8 +25,8 @@
%% Primitive inet_drv interface
--export([open/1, open/2, fdopen/2, fdopen/3, close/1]).
--export([bind/3, listen/1, listen/2]).
+-export([open/3, fdopen/4, close/1]).
+-export([bind/3, listen/1, listen/2, peeloff/2]).
-export([connect/3, connect/4, async_connect/4]).
-export([accept/1, accept/2, async_accept/2]).
-export([shutdown/2]).
@@ -56,58 +56,46 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
-%% OPEN(tcp | udp | sctp, inet | inet6) ->
+%% OPEN(tcp | udp | sctp, inet | inet6, stream | dgram | seqpacket) ->
%% {ok, insock()} |
%% {error, Reason}
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-open(Protocol) -> open1(Protocol, ?INET_AF_INET).
+open(Protocol, Family, Type) ->
+ open(Protocol, Family, Type, ?INET_REQ_OPEN, []).
-open(Protocol, inet) -> open1(Protocol, ?INET_AF_INET);
-open(Protocol, inet6) -> open1(Protocol, ?INET_AF_INET6);
-open(_, _) -> {error, einval}.
+fdopen(Protocol, Family, Type, Fd) when is_integer(Fd) ->
+ open(Protocol, Family, Type, ?INET_REQ_FDOPEN, ?int32(Fd)).
-fdopen(Protocol, Fd) -> fdopen1(Protocol, ?INET_AF_INET, Fd).
-
-fdopen(Protocol, Fd, inet) -> fdopen1(Protocol, ?INET_AF_INET, Fd);
-fdopen(Protocol, Fd, inet6) -> fdopen1(Protocol, ?INET_AF_INET6, Fd);
-fdopen(_, _, _) -> {error, einval}.
-
-open1(Protocol, Family) ->
- case open0(Protocol) of
- {ok, S} ->
- case ctl_cmd(S, ?INET_REQ_OPEN, [Family]) of
- {ok, _} ->
- {ok,S};
- Error ->
- close(S), Error
- end;
- Error -> Error
+open(Protocol, Family, Type, Req, Data) ->
+ Drv = protocol2drv(Protocol),
+ AF = enc_family(Family),
+ T = enc_type(Type),
+ try erlang:open_port({spawn_driver,Drv}, [binary]) of
+ S ->
+ case ctl_cmd(S, Req, [AF,T,Data]) of
+ {ok,_} -> {ok,S};
+ {error,_}=Error ->
+ close(S),
+ Error
+ end
+ catch
+ %% The only (?) way to get here is to try to open
+ %% the sctp driver when it does not exist
+ error:badarg -> {error,eprotonosupport}
end.
-fdopen1(Protocol, Family, Fd) when is_integer(Fd) ->
- case open0(Protocol) of
- {ok, S} ->
- case ctl_cmd(S,?INET_REQ_FDOPEN,[Family,?int32(Fd)]) of
- {ok, _} -> {ok,S};
- Error -> close(S), Error
- end;
- Error -> Error
- end.
+enc_family(inet) -> ?INET_AF_INET;
+enc_family(inet6) -> ?INET_AF_INET6.
-open0(Protocol) ->
- try erlang:open_port({spawn_driver,protocol2drv(Protocol)}, [binary]) of
- Port -> {ok,Port}
- catch
- error:Reason -> {error,Reason}
- end.
+enc_type(stream) -> ?INET_TYPE_STREAM;
+enc_type(dgram) -> ?INET_TYPE_DGRAM;
+enc_type(seqpacket) -> ?INET_TYPE_SEQPACKET.
protocol2drv(tcp) -> "tcp_inet";
protocol2drv(udp) -> "udp_inet";
-protocol2drv(sctp) -> "sctp_inet";
-protocol2drv(_) ->
- erlang:error(eprotonosupport).
+protocol2drv(sctp) -> "sctp_inet".
drv2protocol("tcp_inet") -> tcp;
drv2protocol("udp_inet") -> udp;
@@ -139,7 +127,7 @@ shutdown_1(S, How) ->
shutdown_2(S, How) ->
case ctl_cmd(S, ?TCP_REQ_SHUTDOWN, [How]) of
{ok, []} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
end.
shutdown_pend_loop(S, N0) ->
@@ -195,7 +183,7 @@ close_pend_loop(S, N) ->
bind(S,IP,Port) when is_port(S), is_integer(Port), Port >= 0, Port =< 65535 ->
case ctl_cmd(S,?INET_REQ_BIND,[?int16(Port),ip_to_bytes(IP)]) of
{ok, [P1,P0]} -> {ok, ?u16(P1, P0)};
- Error -> Error
+ {error,_}=Error -> Error
end;
%% Multi-homed "bind": sctp_bindx(). The Op is 'add' or 'remove'.
@@ -222,7 +210,7 @@ bindx(S, AddFlag, Addrs) ->
{IP, Port} <- Addrs]],
case ctl_cmd(S, ?SCTP_REQ_BINDX, Args) of
{ok,_} -> {ok, S};
- Error -> Error
+ {error,_}=Error -> Error
end;
_ -> {error, einval}
end.
@@ -265,7 +253,7 @@ async_connect(S, IP, Port, Time) ->
case ctl_cmd(S, ?INET_REQ_CONNECT,
[enc_time(Time),?int16(Port),ip_to_bytes(IP)]) of
{ok, [R1,R0]} -> {ok, S, ?u16(R1,R0)};
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -318,9 +306,9 @@ accept_opts(L, S) ->
end.
async_accept(L, Time) ->
- case ctl_cmd(L,?TCP_REQ_ACCEPT, [enc_time(Time)]) of
+ case ctl_cmd(L,?INET_REQ_ACCEPT, [enc_time(Time)]) of
{ok, [R1,R0]} -> {ok, ?u16(R1,R0)};
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -334,16 +322,30 @@ async_accept(L, Time) ->
%% listening) is also accepted:
listen(S) -> listen(S, ?LISTEN_BACKLOG).
-
+
+listen(S, true) -> listen(S, ?LISTEN_BACKLOG);
+listen(S, false) -> listen(S, 0);
listen(S, BackLog) when is_port(S), is_integer(BackLog) ->
- case ctl_cmd(S, ?TCP_REQ_LISTEN, [?int16(BackLog)]) of
+ case ctl_cmd(S, ?INET_REQ_LISTEN, [?int16(BackLog)]) of
{ok, _} -> ok;
- Error -> Error
- end;
-listen(S, Flag) when is_port(S), is_boolean(Flag) ->
- case ctl_cmd(S, ?SCTP_REQ_LISTEN, enc_value(set, bool8, Flag)) of
- {ok,_} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% PEELOFF(insock(), AssocId) -> {ok,outsock()} | {error, Reason}
+%%
+%% SCTP: Peel off one association into a type stream socket
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+peeloff(S, AssocId) ->
+ case ctl_cmd(S, ?SCTP_REQ_PEELOFF, [?int32(AssocId)]) of
+ inet_reply ->
+ receive
+ {inet_reply,S,Res} -> Res
+ end;
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -395,12 +397,12 @@ sendto(S, IP, Port, Data) when is_port(S), Port >= 0, Port =< 65535 ->
true ->
receive
{inet_reply,S,Reply} ->
- ?DBG_FORMAT("prim_inet:send() -> ~p~n", [Reply]),
+ ?DBG_FORMAT("prim_inet:sendto() -> ~p~n", [Reply]),
Reply
end
catch
error:_ ->
- ?DBG_FORMAT("prim_inet:send() -> {error,einval}~n", []),
+ ?DBG_FORMAT("prim_inet:sendto() -> {error,einval}~n", []),
{error,einval}
end.
@@ -455,7 +457,7 @@ recv0(S, Length, Time) when is_port(S), is_integer(Length), Length >= 0 ->
async_recv(S, Length, Time) ->
case ctl_cmd(S, ?TCP_REQ_RECV, [enc_time(Time), ?int32(Length)]) of
{ok,[R1,R0]} -> {ok, ?u16(R1,R0)};
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -501,7 +503,7 @@ recvfrom0(S, Length, Time)
{inet_async, S, Ref, Error={error, _}} ->
Error
end;
- Error ->
+ {error,_}=Error ->
Error % Front-end error
end;
recvfrom0(_, _, _) -> {error,einval}.
@@ -517,18 +519,18 @@ peername(S) when is_port(S) ->
{ok, [F, P1,P0 | Addr]} ->
{IP, _} = get_ip(F, Addr),
{ok, { IP, ?u16(P1, P0) }};
- Error -> Error
+ {error,_}=Error -> Error
end.
setpeername(S, {IP,Port}) when is_port(S) ->
case ctl_cmd(S, ?INET_REQ_SETPEER, [?int16(Port),ip_to_bytes(IP)]) of
{ok,[]} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
end;
setpeername(S, undefined) when is_port(S) ->
case ctl_cmd(S, ?INET_REQ_SETPEER, []) of
{ok,[]} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -542,18 +544,18 @@ sockname(S) when is_port(S) ->
{ok, [F, P1, P0 | Addr]} ->
{IP, _} = get_ip(F, Addr),
{ok, { IP, ?u16(P1, P0) }};
- Error -> Error
+ {error,_}=Error -> Error
end.
setsockname(S, {IP,Port}) when is_port(S) ->
case ctl_cmd(S, ?INET_REQ_SETNAME, [?int16(Port),ip_to_bytes(IP)]) of
{ok,[]} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
end;
setsockname(S, undefined) when is_port(S) ->
case ctl_cmd(S, ?INET_REQ_SETNAME, []) of
{ok,[]} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -573,7 +575,7 @@ setopts(S, Opts) when is_port(S) ->
{ok, Buf} ->
case ctl_cmd(S, ?INET_REQ_SETOPTS, Buf) of
{ok, _} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
end;
Error -> Error
end.
@@ -599,12 +601,12 @@ getopts(S, Opts) when is_port(S), is_list(Opts) ->
{ok,Rep} ->
%% Non-SCTP: "Rep" contains the encoded option vals:
decode_opt_val(Rep);
- {error,sctp_reply} ->
+ inet_reply ->
%% SCTP: Need to receive the full value:
receive
{inet_reply,S,Res} -> Res
end;
- Error -> Error
+ {error,_}=Error -> Error
end;
Error -> Error
end.
@@ -733,7 +735,7 @@ getifaddrs_ifget(S, IFs, IF, FlagsVals, Opts) ->
getiflist(S) when is_port(S) ->
case ctl_cmd(S, ?INET_REQ_GETIFLIST, []) of
{ok, Data} -> {ok, build_iflist(Data)};
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -751,7 +753,7 @@ ifget(S, Name, Opts) ->
{ok, Buf2} ->
case ctl_cmd(S, ?INET_REQ_IFGET, [Buf1,Buf2]) of
{ok, Data} -> decode_ifopts(Data,[]);
- Error -> Error
+ {error,_}=Error -> Error
end;
Error -> Error
end;
@@ -773,7 +775,7 @@ ifset(S, Name, Opts) ->
{ok, Buf2} ->
case ctl_cmd(S, ?INET_REQ_IFSET, [Buf1,Buf2]) of
{ok, _} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
end;
Error -> Error
end;
@@ -801,7 +803,7 @@ subscribe(S, Sub) when is_port(S), is_list(Sub) ->
{ok, Bytes} ->
case ctl_cmd(S, ?INET_REQ_SUBSCRIBE, Bytes) of
{ok, Data} -> decode_subs(Data);
- Error -> Error
+ {error,_}=Error -> Error
end;
Error -> Error
end.
@@ -819,7 +821,7 @@ getstat(S, Stats) when is_port(S), is_list(Stats) ->
{ok, Bytes} ->
case ctl_cmd(S, ?INET_REQ_GETSTAT, Bytes) of
{ok, Data} -> decode_stats(Data);
- Error -> Error
+ {error,_}=Error -> Error
end;
Error -> Error
end.
@@ -835,7 +837,7 @@ getstat(S, Stats) when is_port(S), is_list(Stats) ->
getfd(S) when is_port(S) ->
case ctl_cmd(S, ?INET_REQ_GETFD, []) of
{ok, [S3,S2,S1,S0]} -> {ok, ?u32(S3,S2,S1,S0)};
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -873,7 +875,7 @@ gettype(S) when is_port(S) ->
_ -> undefined
end,
{ok, {Family, Type}};
- Error -> Error
+ {error,_}=Error -> Error
end.
getprotocol(S) when is_port(S) ->
@@ -901,7 +903,7 @@ getstatus(S) when is_port(S) ->
case ctl_cmd(S, ?INET_REQ_GETSTATUS, []) of
{ok, [S3,S2,S1,S0]} ->
{ok, dec_status(?u32(S3,S2,S1,S0))};
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -943,7 +945,7 @@ getservbyname1(S,Name,Proto) ->
case ctl_cmd(S, ?INET_REQ_GETSERVBYNAME, [L1,Name,L2,Proto]) of
{ok, [P1,P0]} ->
{ok, ?u16(P1,P0)};
- Error ->
+ {error,_}=Error ->
Error
end
end.
@@ -971,7 +973,7 @@ getservbyport1(S,Port,Proto) ->
true ->
case ctl_cmd(S, ?INET_REQ_GETSERVBYPORT, [?int16(Port),L,Proto]) of
{ok, Name} -> {ok, Name};
- Error -> Error
+ {error,_}=Error -> Error
end
end.
@@ -985,7 +987,7 @@ getservbyport1(S,Port,Proto) ->
unrecv(S, Data) ->
case ctl_cmd(S, ?TCP_REQ_UNRECV, Data) of
{ok, _} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2163,7 +2165,7 @@ ctl_cmd(Port, Cmd, Args) ->
Result =
try erlang:port_control(Port, Cmd, Args) of
[?INET_REP_OK|Reply] -> {ok,Reply};
- [?INET_REP_SCTP] -> {error,sctp_reply};
+ [?INET_REP] -> inet_reply;
[?INET_REP_ERROR|Err] -> {error,list_to_atom(Err)}
catch
error:_ -> {error,einval}
diff --git a/erts/preloaded/src/prim_zip.erl b/erts/preloaded/src/prim_zip.erl
index 6a9856fdad..392a9feb45 100644
--- a/erts/preloaded/src/prim_zip.erl
+++ b/erts/preloaded/src/prim_zip.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -21,7 +21,7 @@
-module(prim_zip).
-%% unzipping piecemal
+%% unzipping piecemeal
-export([
open/1,
open/3,
diff --git a/erts/preloaded/src/zlib.erl b/erts/preloaded/src/zlib.erl
index 51d6cd0a0b..210532edac 100644
--- a/erts/preloaded/src/zlib.erl
+++ b/erts/preloaded/src/zlib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -124,7 +124,6 @@
-type zwindowbits() :: -15..-9 | 9..47.
-type zmemlevel() :: 1..9.
-type zstrategy() :: 'default' | 'filtered' | 'huffman_only'.
--type zflush() :: 'none' | 'sync' | 'full' | 'finish'.
%%------------------------------------------------------------------------
@@ -134,7 +133,8 @@ open() ->
open_port({spawn, "zlib_drv"}, [binary]).
%% close and release z_stream
--spec close(zstream()) -> 'ok'.
+-spec close(Z) -> 'ok' when
+ Z :: zstream().
close(Z) ->
try
true = port_close(Z),
@@ -145,16 +145,25 @@ close(Z) ->
catch _:_ -> erlang:error(badarg)
end.
--spec deflateInit(zstream()) -> 'ok'.
+-spec deflateInit(Z) -> 'ok' when
+ Z :: zstream().
deflateInit(Z) ->
call(Z, ?DEFLATE_INIT, <<?Z_DEFAULT_COMPRESSION:32>>).
--spec deflateInit(zstream(), zlevel()) -> 'ok'.
+-spec deflateInit(Z, Level) -> 'ok' when
+ Z :: zstream(),
+ Level :: zlevel().
deflateInit(Z, Level) ->
call(Z, ?DEFLATE_INIT, <<(arg_level(Level)):32>>).
--spec deflateInit(zstream(), zlevel(), zmethod(),
- zwindowbits(), zmemlevel(), zstrategy()) -> 'ok'.
+-spec deflateInit(Z, Level, Method,
+ WindowBits, MemLevel, Strategy) -> 'ok' when
+ Z :: zstream(),
+ Level :: zlevel(),
+ Method :: zmethod(),
+ WindowBits :: zwindowbits(),
+ MemLevel :: zmemlevel(),
+ Strategy :: zstrategy().
deflateInit(Z, Level, Method, WindowBits, MemLevel, Strategy) ->
call(Z, ?DEFLATE_INIT2, <<(arg_level(Level)):32,
(arg_method(Method)):32,
@@ -162,24 +171,38 @@ deflateInit(Z, Level, Method, WindowBits, MemLevel, Strategy) ->
(arg_mem(MemLevel)):32,
(arg_strategy(Strategy)):32>>).
--spec deflateSetDictionary(zstream(), binary()) -> integer().
+-spec deflateSetDictionary(Z, Dictionary) -> Adler32 when
+ Z :: zstream(),
+ Dictionary :: iodata(),
+ Adler32 :: integer().
deflateSetDictionary(Z, Dictionary) ->
call(Z, ?DEFLATE_SETDICT, Dictionary).
--spec deflateReset(zstream()) -> 'ok'.
+-spec deflateReset(Z) -> 'ok' when
+ Z :: zstream().
deflateReset(Z) ->
call(Z, ?DEFLATE_RESET, []).
--spec deflateParams(zstream(), zlevel(), zstrategy()) -> 'ok'.
+-spec deflateParams(Z, Level, Strategy) -> ok when
+ Z :: zstream(),
+ Level :: zlevel(),
+ Strategy :: zstrategy().
deflateParams(Z, Level, Strategy) ->
call(Z, ?DEFLATE_PARAMS, <<(arg_level(Level)):32,
(arg_strategy(Strategy)):32>>).
--spec deflate(zstream(), iodata()) -> iolist().
+-spec deflate(Z, Data) -> Compressed when
+ Z :: zstream(),
+ Data :: iodata(),
+ Compressed :: iolist().
deflate(Z, Data) ->
deflate(Z, Data, none).
--spec deflate(zstream(), iodata(), zflush()) -> iolist().
+-spec deflate(Z, Data, Flush) -> Compressed when
+ Z :: zstream(),
+ Data :: iodata(),
+ Flush :: none | sync | full | finish,
+ Compressed :: iolist().
deflate(Z, Data, Flush) ->
try port_command(Z, Data) of
true ->
@@ -191,19 +214,25 @@ deflate(Z, Data, Flush) ->
erlang:error(badarg)
end.
--spec deflateEnd(zstream()) -> 'ok'.
+-spec deflateEnd(Z) -> 'ok' when
+ Z :: zstream().
deflateEnd(Z) ->
call(Z, ?DEFLATE_END, []).
--spec inflateInit(zstream()) -> 'ok'.
+-spec inflateInit(Z) -> 'ok' when
+ Z :: zstream().
inflateInit(Z) ->
call(Z, ?INFLATE_INIT, []).
--spec inflateInit(zstream(), zwindowbits()) -> 'ok'.
+-spec inflateInit(Z, WindowBits) -> 'ok' when
+ Z :: zstream(),
+ WindowBits :: zwindowbits().
inflateInit(Z, WindowBits) ->
call(Z, ?INFLATE_INIT2, <<(arg_bitsz(WindowBits)):32>>).
--spec inflateSetDictionary(zstream(), binary()) -> 'ok'.
+-spec inflateSetDictionary(Z, Dictionary) -> 'ok' when
+ Z :: zstream(),
+ Dictionary :: iodata().
inflateSetDictionary(Z, Dictionary) ->
call(Z, ?INFLATE_SETDICT, Dictionary).
@@ -211,11 +240,15 @@ inflateSetDictionary(Z, Dictionary) ->
inflateSync(Z) ->
call(Z, ?INFLATE_SYNC, []).
--spec inflateReset(zstream()) -> 'ok'.
+-spec inflateReset(Z) -> 'ok' when
+ Z :: zstream().
inflateReset(Z) ->
call(Z, ?INFLATE_RESET, []).
--spec inflate(zstream(), iodata()) -> iolist().
+-spec inflate(Z, Data) -> Decompressed when
+ Z :: zstream(),
+ Data :: iodata(),
+ Decompressed :: iolist().
inflate(Z, Data) ->
try port_command(Z, Data) of
true ->
@@ -227,50 +260,79 @@ inflate(Z, Data) ->
erlang:error(badarg)
end.
--spec inflateEnd(zstream()) -> 'ok'.
+-spec inflateEnd(Z) -> 'ok' when
+ Z :: zstream().
inflateEnd(Z) ->
call(Z, ?INFLATE_END, []).
--spec setBufSize(zstream(), non_neg_integer()) -> 'ok'.
+-spec setBufSize(Z, Size) -> 'ok' when
+ Z :: zstream(),
+ Size :: non_neg_integer().
setBufSize(Z, Size) ->
call(Z, ?SET_BUFSZ, <<Size:32>>).
--spec getBufSize(zstream()) -> non_neg_integer().
+-spec getBufSize(Z) -> Size when
+ Z :: zstream(),
+ Size :: non_neg_integer().
getBufSize(Z) ->
call(Z, ?GET_BUFSZ, []).
--spec crc32(zstream()) -> integer().
+-spec crc32(Z) -> CRC when
+ Z :: zstream(),
+ CRC :: integer().
crc32(Z) ->
call(Z, ?CRC32_0, []).
--spec crc32(zstream(), binary()) -> integer().
-crc32(Z, Binary) ->
- call(Z, ?CRC32_1, Binary).
-
--spec crc32(zstream(), integer(), binary()) -> integer().
-crc32(Z, CRC, Binary) when is_binary(Binary), is_integer(CRC) ->
- call(Z, ?CRC32_2, <<CRC:32, Binary/binary>>);
-crc32(_Z, _CRC, _Binary) ->
- erlang:error(badarg).
-
--spec adler32(zstream(), binary()) -> integer().
-adler32(Z, Binary) ->
- call(Z, ?ADLER32_1, Binary).
-
--spec adler32(zstream(), integer(), binary()) -> integer().
-adler32(Z, Adler, Binary) when is_binary(Binary), is_integer(Adler) ->
- call(Z, ?ADLER32_2, <<Adler:32, Binary/binary>>);
-adler32(_Z, _Adler, _Binary) ->
+-spec crc32(Z, Data) -> CRC when
+ Z :: zstream(),
+ Data :: iodata(),
+ CRC :: integer().
+crc32(Z, Data) ->
+ call(Z, ?CRC32_1, Data).
+
+-spec crc32(Z, PrevCRC, Data) -> CRC when
+ Z :: zstream(),
+ PrevCRC :: integer(),
+ Data :: iodata(),
+ CRC :: integer().
+crc32(Z, CRC, Data) ->
+ call(Z, ?CRC32_2, [<<CRC:32>>, Data]).
+
+-spec adler32(Z, Data) -> CheckSum when
+ Z :: zstream(),
+ Data :: iodata(),
+ CheckSum :: integer().
+adler32(Z, Data) ->
+ call(Z, ?ADLER32_1, Data).
+
+-spec adler32(Z, PrevAdler, Data) -> CheckSum when
+ Z :: zstream(),
+ PrevAdler :: integer(),
+ Data :: iodata(),
+ CheckSum :: integer().
+adler32(Z, Adler, Data) when is_integer(Adler) ->
+ call(Z, ?ADLER32_2, [<<Adler:32>>, Data]);
+adler32(_Z, _Adler, _Data) ->
erlang:error(badarg).
--spec crc32_combine(zstream(), integer(), integer(), integer()) -> integer().
+-spec crc32_combine(Z, CRC1, CRC2, Size2) -> CRC when
+ Z :: zstream(),
+ CRC :: integer(),
+ CRC1 :: integer(),
+ CRC2 :: integer(),
+ Size2 :: integer().
crc32_combine(Z, CRC1, CRC2, Len2)
when is_integer(CRC1), is_integer(CRC2), is_integer(Len2) ->
call(Z, ?CRC32_COMBINE, <<CRC1:32, CRC2:32, Len2:32>>);
crc32_combine(_Z, _CRC1, _CRC2, _Len2) ->
erlang:error(badarg).
--spec adler32_combine(zstream(), integer(), integer(), integer()) -> integer().
+-spec adler32_combine(Z, Adler1, Adler2, Size2) -> Adler when
+ Z :: zstream(),
+ Adler :: integer(),
+ Adler1 :: integer(),
+ Adler2 :: integer(),
+ Size2 :: integer().
adler32_combine(Z, Adler1, Adler2, Len2)
when is_integer(Adler1), is_integer(Adler2), is_integer(Len2) ->
call(Z, ?ADLER32_COMBINE, <<Adler1:32, Adler2:32, Len2:32>>);
@@ -282,64 +344,83 @@ getQSize(Z) ->
call(Z, ?GET_QSIZE, []).
%% compress/uncompress zlib with header
--spec compress(binary()) -> binary().
-compress(Binary) ->
+-spec compress(Data) -> Compressed when
+ Data :: iodata(),
+ Compressed :: binary().
+compress(Data) ->
Z = open(),
deflateInit(Z, default),
- Bs = deflate(Z, Binary,finish),
+ Bs = deflate(Z, Data, finish),
deflateEnd(Z),
close(Z),
- list_to_binary(Bs).
-
--spec uncompress(binary()) -> binary().
-uncompress(Binary) when byte_size(Binary) >= 8 ->
- Z = open(),
- inflateInit(Z),
- Bs = inflate(Z, Binary),
- inflateEnd(Z),
- close(Z),
- list_to_binary(Bs);
-uncompress(Binary) when is_binary(Binary) -> erlang:error(data_error);
-uncompress(_) -> erlang:error(badarg).
+ iolist_to_binary(Bs).
+
+-spec uncompress(Data) -> Decompressed when
+ Data :: iodata(),
+ Decompressed :: binary().
+uncompress(Data) ->
+ try iolist_size(Data) of
+ Size ->
+ if
+ Size >= 8 ->
+ Z = open(),
+ inflateInit(Z),
+ Bs = inflate(Z, Data),
+ inflateEnd(Z),
+ close(Z),
+ iolist_to_binary(Bs);
+ true ->
+ erlang:error(data_error)
+ end
+ catch
+ _:_ ->
+ erlang:error(badarg)
+ end.
%% unzip/zip zlib without header (zip members)
--spec zip(binary()) -> binary().
-zip(Binary) ->
+-spec zip(Data) -> Compressed when
+ Data :: iodata(),
+ Compressed :: binary().
+zip(Data) ->
Z = open(),
deflateInit(Z, default, deflated, -?MAX_WBITS, 8, default),
- Bs = deflate(Z, Binary, finish),
+ Bs = deflate(Z, Data, finish),
deflateEnd(Z),
close(Z),
- list_to_binary(Bs).
+ iolist_to_binary(Bs).
--spec unzip(binary()) -> binary().
-unzip(Binary) ->
+-spec unzip(Data) -> Decompressed when
+ Data :: iodata(),
+ Decompressed :: binary().
+unzip(Data) ->
Z = open(),
inflateInit(Z, -?MAX_WBITS),
- Bs = inflate(Z, Binary),
+ Bs = inflate(Z, Data),
inflateEnd(Z),
close(Z),
- list_to_binary(Bs).
+ iolist_to_binary(Bs).
--spec gzip(iodata()) -> binary().
-gzip(Data) when is_binary(Data); is_list(Data) ->
+-spec gzip(Data) -> Compressed when
+ Data :: iodata(),
+ Compressed :: binary().
+gzip(Data) ->
Z = open(),
deflateInit(Z, default, deflated, 16+?MAX_WBITS, 8, default),
Bs = deflate(Z, Data, finish),
deflateEnd(Z),
close(Z),
- iolist_to_binary(Bs);
-gzip(_) -> erlang:error(badarg).
+ iolist_to_binary(Bs).
--spec gunzip(iodata()) -> binary().
-gunzip(Data) when is_binary(Data); is_list(Data) ->
+-spec gunzip(Data) -> Decompressed when
+ Data :: iodata(),
+ Decompressed :: binary().
+gunzip(Data) ->
Z = open(),
inflateInit(Z, 16+?MAX_WBITS),
Bs = inflate(Z, Data),
inflateEnd(Z),
close(Z),
- iolist_to_binary(Bs);
-gunzip(_) -> erlang:error(badarg).
+ iolist_to_binary(Bs).
-spec collect(zstream()) -> iolist().
collect(Z) ->
diff --git a/erts/test/autoimport_SUITE.erl b/erts/test/autoimport_SUITE.erl
index 0e4708e046..71ed5204b1 100644
--- a/erts/test/autoimport_SUITE.erl
+++ b/erts/test/autoimport_SUITE.erl
@@ -87,10 +87,21 @@ autoimports(Config) when is_list(Config) ->
xml(XMLFile) ->
{ok,File} = file:open(XMLFile,[read]),
+ xskip_to_funcs(file:read_line(File),File),
DocData = xloop(file:read_line(File),File),
+ true = DocData =/= [],
file:close(File),
analyze(DocData).
+%% Skip lines up to and including the <funcs> tag.
+xskip_to_funcs({ok,Line},File) ->
+ case re:run(Line,"\\<funcs\\>",[{capture,none}]) of
+ nomatch ->
+ xskip_to_funcs(file:read_line(File),File);
+ match ->
+ ok
+ end.
+
xloop({ok,Line},File) ->
case re:run(Line,"\\<name\\>",[{capture,none}]) of
nomatch ->
diff --git a/erts/test/erlc_SUITE.erl b/erts/test/erlc_SUITE.erl
index 62e0e6813d..a9e28672e3 100644
--- a/erts/test/erlc_SUITE.erl
+++ b/erts/test/erlc_SUITE.erl
@@ -79,7 +79,7 @@ compile_erl(Config) when is_list(Config) ->
?line run(Config, Cmd, FileName, "-Werror",
["compile: warnings being treated as errors\$",
- "Warning: function foo/0 is unused\$",
+ "function foo/0 is unused\$",
"_ERROR_"]),
%% Check a bad file.
@@ -213,13 +213,34 @@ deep_cwd_1(PrivDir) ->
arg_overflow(Config) when is_list(Config) ->
?line {SrcDir, _OutDir, Cmd} = get_cmd(Config),
?line FileName = filename:join(SrcDir, "erl_test_ok.erl"),
- ?line Args = lists:flatten([ ["-D", integer_to_list(N), "=1 "] ||
- N <- lists:seq(1,10000) ]),
+ %% Each -D option will be expanded to three arguments when
+ %% invoking 'erl'.
+ ?line NumDOptions = num_d_options(),
+ ?line Args = lists:flatten([ ["-D", integer_to_list(N, 36), "=1 "] ||
+ N <- lists:seq(1, NumDOptions) ]),
?line run(Config, Cmd, FileName, Args,
["Warning: function foo/0 is unused\$",
"_OK_"]),
ok.
+num_d_options() ->
+ case {os:type(),os:version()} of
+ {{win32,_},_} ->
+ %% The maximum size of a command line in the command
+ %% shell on Windows is 8191 characters.
+ %% Each -D option is expanded to "@dv NN 1", i.e.
+ %% 8 characters. (Numbers up to 1295 can be expressed
+ %% as two 36-base digits.)
+ 1000;
+ {{unix,linux},Version} when Version < {2,6,23} ->
+ %% On some older 64-bit versions of Linux, the maximum number
+ %% of arguments is 16383.
+ %% See: http://www.in-ulm.de/~mascheck/various/argmax/
+ 5440;
+ {_,_} ->
+ 12000
+ end.
+
erlc() ->
case os:find_executable("erlc") of
false ->
diff --git a/erts/test/ethread_SUITE.erl b/erts/test/ethread_SUITE.erl
index 71d8c1c679..4206bebfe7 100644
--- a/erts/test/ethread_SUITE.erl
+++ b/erts/test/ethread_SUITE.erl
@@ -47,14 +47,29 @@
spinlock/1,
rwspinlock/1,
rwmutex/1,
- atomic/1]).
+ atomic/1,
+ dw_atomic_massage/1]).
-include_lib("test_server/include/test_server.hrl").
-tests() ->
- [create_join_thread, equal_tids, mutex, try_lock_mutex,
- cond_wait, broadcast, detached_thread,
- max_threads, tsd, spinlock, rwspinlock, rwmutex, atomic].
+tests() ->
+ [create_join_thread,
+ equal_tids,
+ mutex,
+ try_lock_mutex,
+ cond_wait,
+ broadcast,
+ detached_thread,
+ max_threads,
+ tsd,
+ spinlock,
+ rwspinlock,
+ rwmutex,
+ atomic,
+ dw_atomic_massage].
+
+all(doc) -> [];
+all(suite) -> tests().
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -211,6 +226,13 @@ atomic(suite) ->
atomic(Config) ->
run_case(Config, "atomic", "").
+dw_atomic_massage(doc) ->
+ ["Massage double word atomics"];
+dw_atomic_massage(suite) ->
+ [];
+dw_atomic_massage(Config) ->
+ run_case(Config, "dw_atomic_massage", "").
+
%%
%%
%% Auxiliary functions
diff --git a/erts/test/ethread_SUITE_data/ethread_tests.c b/erts/test/ethread_SUITE_data/ethread_tests.c
index 0b59ff5aa6..7e7e133d6c 100644
--- a/erts/test/ethread_SUITE_data/ethread_tests.c
+++ b/erts/test/ethread_SUITE_data/ethread_tests.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -1310,6 +1310,9 @@ rwmutex_test(void)
* Tests atomics.
*/
+#define AT_AINT32_MAX 0x7fffffff
+#define AT_AINT32_MIN 0x80000000
+
#define AT_THREADS 4
#define AT_ITER 10000
@@ -1320,12 +1323,428 @@ static ethr_atomic_t at_go;
static ethr_atomic_t at_done;
static ethr_atomic_t at_data;
+#define AT_TEST_INIT(T, A, B) \
+do { \
+ ethr_ ## A ## _init ## B(&A, 17); \
+ ASSERT(ethr_ ## A ## _read ## B(&A) == 17); \
+} while (0)
+
+#define AT_TEST_SET(T, A, B) \
+do { \
+ ethr_ ## A ## _set ## B(&A, 4711); \
+ ASSERT(ethr_ ## A ## _read ## B(&A) == 4711); \
+} while (0)
+
+#define AT_TEST_XCHG(T, A, B) \
+do { \
+ ethr_ ## A ## _set ## B(&A, 4711); \
+ ASSERT(ethr_ ## A ## _xchg ## B(&A, 17) == 4711); \
+ ASSERT(ethr_ ## A ## _read ## B(&A) == 17); \
+} while (0)
+
+#define AT_TEST_CMPXCHG(T, A, B) \
+do { \
+ ethr_ ## A ## _set ## B(&A, 4711); \
+ ASSERT(ethr_ ## A ## _cmpxchg ## B(&A, 17, 33) == 4711); \
+ ASSERT(ethr_ ## A ## _read ## B(&A) == 4711); \
+ ASSERT(ethr_ ## A ## _cmpxchg ## B(&A, 17, 4711) == 4711); \
+ ASSERT(ethr_ ## A ## _read ## B(&A) == 17); \
+} while (0)
+
+#define AT_TEST_ADD_READ(T, A, B) \
+do { \
+ T var_ = AT_AINT32_MAX; \
+ var_ += 4711; \
+ ethr_ ## A ## _set ## B(&A, AT_AINT32_MAX); \
+ ASSERT(ethr_ ## A ## _add_read ## B(&A, 4711) == var_); \
+ ASSERT(ethr_ ## A ## _read ## B(&A) == var_); \
+ var_ = AT_AINT32_MIN; \
+ var_ -= 4711; \
+ ethr_ ## A ## _set ## B(&A, AT_AINT32_MIN); \
+ ASSERT(ethr_ ## A ## _add_read ## B(&A, -4711) == var_); \
+ ASSERT(ethr_ ## A ## _read ## B(&A) == var_); \
+ ethr_ ## A ## _set ## B(&A, 4711); \
+ ASSERT(ethr_ ## A ## _add_read ## B(&A, 10) == 4721); \
+ ASSERT(ethr_ ## A ## _read ## B(&A) == 4721); \
+} while (0)
+
+#define AT_TEST_ADD(T, A, B) \
+do { \
+ T var_ = AT_AINT32_MAX; \
+ var_ += 4711; \
+ ethr_ ## A ## _set ## B(&A, AT_AINT32_MAX); \
+ ethr_ ## A ## _add ## B(&A, 4711); \
+ ASSERT(ethr_ ## A ## _read ## B(&A) == var_); \
+ var_ = AT_AINT32_MIN; \
+ var_ -= 4711; \
+ ethr_ ## A ## _set ## B(&A, AT_AINT32_MIN); \
+ ethr_ ## A ## _add ## B(&A, -4711); \
+ ASSERT(ethr_ ## A ## _read ## B(&A) == var_); \
+ ethr_ ## A ## _set ## B(&A, 11); \
+ ethr_ ## A ## _add ## B(&A, 4700); \
+ ASSERT(ethr_ ## A ## _read ## B(&A) == 4711); \
+} while (0)
+
+#define AT_TEST_INC_READ(T, A, B) \
+do { \
+ T var_ = AT_AINT32_MAX; \
+ var_++; \
+ ethr_ ## A ## _set ## B(&A, AT_AINT32_MAX); \
+ ASSERT(ethr_ ## A ## _inc_read ## B(&A) == var_); \
+ ASSERT(ethr_ ## A ## _read ## B(&A) == var_); \
+ ethr_ ## A ## _set ## B(&A, 4710); \
+ ASSERT(ethr_ ## A ## _inc_read ## B(&A) == 4711); \
+ ASSERT(ethr_ ## A ## _read ## B(&A) == 4711); \
+} while (0)
+
+#define AT_TEST_DEC_READ(T, A, B) \
+do { \
+ T var_ = AT_AINT32_MIN; \
+ var_--; \
+ ethr_ ## A ## _set ## B(&A, AT_AINT32_MIN); \
+ ASSERT(ethr_ ## A ## _dec_read ## B(&A) == var_); \
+ ASSERT(ethr_ ## A ## _read ## B(&A) == var_); \
+ ethr_ ## A ## _set ## B(&A, 17); \
+ ASSERT(ethr_ ## A ## _dec_read ## B(&A) == 16); \
+ ASSERT(ethr_ ## A ## _read ## B(&A) == 16); \
+} while (0)
+
+
+#define AT_TEST_INC(T, A, B) \
+do { \
+ T var_ = AT_AINT32_MAX; \
+ var_++; \
+ ethr_ ## A ## _set ## B(&A, AT_AINT32_MAX); \
+ ethr_ ## A ## _inc ## B(&A); \
+ ASSERT(ethr_ ## A ## _read ## B(&A) == var_); \
+ ethr_ ## A ## _set ## B(&A, 4710); \
+ ethr_ ## A ## _inc ## B(&A); \
+ ASSERT(ethr_ ## A ## _read ## B(&A) == 4711); \
+} while (0)
+
+#define AT_TEST_DEC(T, A, B) \
+do { \
+ T var_ = AT_AINT32_MIN; \
+ var_--; \
+ ethr_ ## A ## _set ## B(&A, AT_AINT32_MIN); \
+ ethr_ ## A ## _dec ## B(&A); \
+ ASSERT(ethr_ ## A ## _read ## B(&A) == var_); \
+ ethr_ ## A ## _set ## B(&A, 17); \
+ ethr_ ## A ## _dec ## B(&A); \
+ ASSERT(ethr_ ## A ## _read ## B(&A) == 16); \
+} while (0)
+
+#define AT_TEST_READ_BAND(T, A, B) \
+do { \
+ ethr_ ## A ## _set ## B(&A, 0x13131313); \
+ ASSERT(ethr_ ## A ## _read_band ## B(&A, 0x31313131) == 0x13131313); \
+ ASSERT(ethr_ ## A ## _read ## B(&A) == 0x11111111); \
+} while (0)
+
+#define AT_TEST_READ_BOR(T, A, B) \
+do { \
+ ethr_ ## A ## _set ## B(&A, 0x11111111); \
+ ASSERT(ethr_ ## A ## _read_bor ## B(&A, 0x23232323) == 0x11111111); \
+ ASSERT(ethr_ ## A ## _read ## B(&A) == 0x33333333); \
+} while (0)
+
+
+static void
+atomic_basic_test(void)
+{
+ /*
+ * Verify that each op does what it is expected
+ * to do for at least one input.
+ */
+ ethr_atomic32_t atomic32;
+ ethr_atomic_t atomic;
+
+ print_line("AT_AINT32_MAX=%d",AT_AINT32_MAX);
+ print_line("AT_AINT32_MIN=%d",AT_AINT32_MIN);
+
+ AT_TEST_INIT(ethr_sint32_t, atomic32, );
+ AT_TEST_SET(ethr_sint32_t, atomic32, );
+ AT_TEST_XCHG(ethr_sint32_t, atomic32, );
+ AT_TEST_CMPXCHG(ethr_sint32_t, atomic32, );
+ AT_TEST_ADD_READ(ethr_sint32_t, atomic32, );
+ AT_TEST_ADD(ethr_sint32_t, atomic32, );
+ AT_TEST_INC_READ(ethr_sint32_t, atomic32, );
+ AT_TEST_DEC_READ(ethr_sint32_t, atomic32, );
+ AT_TEST_INC(ethr_sint32_t, atomic32, );
+ AT_TEST_DEC(ethr_sint32_t, atomic32, );
+ AT_TEST_READ_BAND(ethr_sint32_t, atomic32, );
+ AT_TEST_READ_BOR(ethr_sint32_t, atomic32, );
+
+ AT_TEST_INIT(ethr_sint32_t, atomic32, _acqb);
+ AT_TEST_SET(ethr_sint32_t, atomic32, _acqb);
+ AT_TEST_XCHG(ethr_sint32_t, atomic32, _acqb);
+ AT_TEST_CMPXCHG(ethr_sint32_t, atomic32, _acqb);
+ AT_TEST_ADD_READ(ethr_sint32_t, atomic32, _acqb);
+ AT_TEST_ADD(ethr_sint32_t, atomic32, _acqb);
+ AT_TEST_INC_READ(ethr_sint32_t, atomic32, _acqb);
+ AT_TEST_DEC_READ(ethr_sint32_t, atomic32, _acqb);
+ AT_TEST_INC(ethr_sint32_t, atomic32, _acqb);
+ AT_TEST_DEC(ethr_sint32_t, atomic32, _acqb);
+ AT_TEST_READ_BAND(ethr_sint32_t, atomic32, _acqb);
+ AT_TEST_READ_BOR(ethr_sint32_t, atomic32, _acqb);
+
+ AT_TEST_INIT(ethr_sint32_t, atomic32, _relb);
+ AT_TEST_SET(ethr_sint32_t, atomic32, _relb);
+ AT_TEST_XCHG(ethr_sint32_t, atomic32, _relb);
+ AT_TEST_CMPXCHG(ethr_sint32_t, atomic32, _relb);
+ AT_TEST_ADD_READ(ethr_sint32_t, atomic32, _relb);
+ AT_TEST_ADD(ethr_sint32_t, atomic32, _relb);
+ AT_TEST_INC_READ(ethr_sint32_t, atomic32, _relb);
+ AT_TEST_DEC_READ(ethr_sint32_t, atomic32, _relb);
+ AT_TEST_INC(ethr_sint32_t, atomic32, _relb);
+ AT_TEST_DEC(ethr_sint32_t, atomic32, _relb);
+ AT_TEST_READ_BAND(ethr_sint32_t, atomic32, _relb);
+ AT_TEST_READ_BOR(ethr_sint32_t, atomic32, _relb);
+
+ AT_TEST_INIT(ethr_sint32_t, atomic32, _rb);
+ AT_TEST_SET(ethr_sint32_t, atomic32, _rb);
+ AT_TEST_XCHG(ethr_sint32_t, atomic32, _rb);
+ AT_TEST_CMPXCHG(ethr_sint32_t, atomic32, _rb);
+ AT_TEST_ADD_READ(ethr_sint32_t, atomic32, _rb);
+ AT_TEST_ADD(ethr_sint32_t, atomic32, _rb);
+ AT_TEST_INC_READ(ethr_sint32_t, atomic32, _rb);
+ AT_TEST_DEC_READ(ethr_sint32_t, atomic32, _rb);
+ AT_TEST_INC(ethr_sint32_t, atomic32, _rb);
+ AT_TEST_DEC(ethr_sint32_t, atomic32, _rb);
+ AT_TEST_READ_BAND(ethr_sint32_t, atomic32, _rb);
+ AT_TEST_READ_BOR(ethr_sint32_t, atomic32, _rb);
+
+ AT_TEST_INIT(ethr_sint32_t, atomic32, _wb);
+ AT_TEST_SET(ethr_sint32_t, atomic32, _wb);
+ AT_TEST_XCHG(ethr_sint32_t, atomic32, _wb);
+ AT_TEST_CMPXCHG(ethr_sint32_t, atomic32, _wb);
+ AT_TEST_ADD_READ(ethr_sint32_t, atomic32, _wb);
+ AT_TEST_ADD(ethr_sint32_t, atomic32, _wb);
+ AT_TEST_INC_READ(ethr_sint32_t, atomic32, _wb);
+ AT_TEST_DEC_READ(ethr_sint32_t, atomic32, _wb);
+ AT_TEST_INC(ethr_sint32_t, atomic32, _wb);
+ AT_TEST_DEC(ethr_sint32_t, atomic32, _wb);
+ AT_TEST_READ_BAND(ethr_sint32_t, atomic32, _wb);
+ AT_TEST_READ_BOR(ethr_sint32_t, atomic32, _wb);
+
+ AT_TEST_INIT(ethr_sint32_t, atomic32, _mb);
+ AT_TEST_SET(ethr_sint32_t, atomic32, _mb);
+ AT_TEST_XCHG(ethr_sint32_t, atomic32, _mb);
+ AT_TEST_CMPXCHG(ethr_sint32_t, atomic32, _mb);
+ AT_TEST_ADD_READ(ethr_sint32_t, atomic32, _mb);
+ AT_TEST_ADD(ethr_sint32_t, atomic32, _mb);
+ AT_TEST_INC_READ(ethr_sint32_t, atomic32, _mb);
+ AT_TEST_DEC_READ(ethr_sint32_t, atomic32, _mb);
+ AT_TEST_INC(ethr_sint32_t, atomic32, _mb);
+ AT_TEST_DEC(ethr_sint32_t, atomic32, _mb);
+ AT_TEST_READ_BAND(ethr_sint32_t, atomic32, _mb);
+ AT_TEST_READ_BOR(ethr_sint32_t, atomic32, _mb);
+
+ AT_TEST_INIT(ethr_sint_t, atomic, );
+ AT_TEST_SET(ethr_sint_t, atomic, );
+ AT_TEST_XCHG(ethr_sint_t, atomic, );
+ AT_TEST_CMPXCHG(ethr_sint_t, atomic, );
+ AT_TEST_ADD_READ(ethr_sint_t, atomic, );
+ AT_TEST_ADD(ethr_sint_t, atomic, );
+ AT_TEST_INC_READ(ethr_sint_t, atomic, );
+ AT_TEST_DEC_READ(ethr_sint_t, atomic, );
+ AT_TEST_INC(ethr_sint_t, atomic, );
+ AT_TEST_DEC(ethr_sint_t, atomic, );
+ AT_TEST_READ_BAND(ethr_sint_t, atomic, );
+ AT_TEST_READ_BOR(ethr_sint_t, atomic, );
+
+ AT_TEST_INIT(ethr_sint_t, atomic, _acqb);
+ AT_TEST_SET(ethr_sint_t, atomic, _acqb);
+ AT_TEST_XCHG(ethr_sint_t, atomic, _acqb);
+ AT_TEST_CMPXCHG(ethr_sint_t, atomic, _acqb);
+ AT_TEST_ADD_READ(ethr_sint_t, atomic, _acqb);
+ AT_TEST_ADD(ethr_sint_t, atomic, _acqb);
+ AT_TEST_INC_READ(ethr_sint_t, atomic, _acqb);
+ AT_TEST_DEC_READ(ethr_sint_t, atomic, _acqb);
+ AT_TEST_INC(ethr_sint_t, atomic, _acqb);
+ AT_TEST_DEC(ethr_sint_t, atomic, _acqb);
+ AT_TEST_READ_BAND(ethr_sint_t, atomic, _acqb);
+ AT_TEST_READ_BOR(ethr_sint_t, atomic, _acqb);
+
+ AT_TEST_INIT(ethr_sint_t, atomic, _relb);
+ AT_TEST_SET(ethr_sint_t, atomic, _relb);
+ AT_TEST_XCHG(ethr_sint_t, atomic, _relb);
+ AT_TEST_CMPXCHG(ethr_sint_t, atomic, _relb);
+ AT_TEST_ADD_READ(ethr_sint_t, atomic, _relb);
+ AT_TEST_ADD(ethr_sint_t, atomic, _relb);
+ AT_TEST_INC_READ(ethr_sint_t, atomic, _relb);
+ AT_TEST_DEC_READ(ethr_sint_t, atomic, _relb);
+ AT_TEST_INC(ethr_sint_t, atomic, _relb);
+ AT_TEST_DEC(ethr_sint_t, atomic, _relb);
+ AT_TEST_READ_BAND(ethr_sint_t, atomic, _relb);
+ AT_TEST_READ_BOR(ethr_sint_t, atomic, _relb);
+
+ AT_TEST_INIT(ethr_sint_t, atomic, _rb);
+ AT_TEST_SET(ethr_sint_t, atomic, _rb);
+ AT_TEST_XCHG(ethr_sint_t, atomic, _rb);
+ AT_TEST_CMPXCHG(ethr_sint_t, atomic, _rb);
+ AT_TEST_ADD_READ(ethr_sint_t, atomic, _rb);
+ AT_TEST_ADD(ethr_sint_t, atomic, _rb);
+ AT_TEST_INC_READ(ethr_sint_t, atomic, _rb);
+ AT_TEST_DEC_READ(ethr_sint_t, atomic, _rb);
+ AT_TEST_INC(ethr_sint_t, atomic, _rb);
+ AT_TEST_DEC(ethr_sint_t, atomic, _rb);
+ AT_TEST_READ_BAND(ethr_sint_t, atomic, _rb);
+ AT_TEST_READ_BOR(ethr_sint_t, atomic, _rb);
+
+ AT_TEST_INIT(ethr_sint_t, atomic, _wb);
+ AT_TEST_SET(ethr_sint_t, atomic, _wb);
+ AT_TEST_XCHG(ethr_sint_t, atomic, _wb);
+ AT_TEST_CMPXCHG(ethr_sint_t, atomic, _wb);
+ AT_TEST_ADD_READ(ethr_sint_t, atomic, _wb);
+ AT_TEST_ADD(ethr_sint_t, atomic, _wb);
+ AT_TEST_INC_READ(ethr_sint_t, atomic, _wb);
+ AT_TEST_DEC_READ(ethr_sint_t, atomic, _wb);
+ AT_TEST_INC(ethr_sint_t, atomic, _wb);
+ AT_TEST_DEC(ethr_sint_t, atomic, _wb);
+ AT_TEST_READ_BAND(ethr_sint_t, atomic, _wb);
+ AT_TEST_READ_BOR(ethr_sint_t, atomic, _wb);
+
+ AT_TEST_INIT(ethr_sint_t, atomic, _mb);
+ AT_TEST_SET(ethr_sint_t, atomic, _mb);
+ AT_TEST_XCHG(ethr_sint_t, atomic, _mb);
+ AT_TEST_CMPXCHG(ethr_sint_t, atomic, _mb);
+ AT_TEST_ADD_READ(ethr_sint_t, atomic, _mb);
+ AT_TEST_ADD(ethr_sint_t, atomic, _mb);
+ AT_TEST_INC_READ(ethr_sint_t, atomic, _mb);
+ AT_TEST_DEC_READ(ethr_sint_t, atomic, _mb);
+ AT_TEST_INC(ethr_sint_t, atomic, _mb);
+ AT_TEST_DEC(ethr_sint_t, atomic, _mb);
+ AT_TEST_READ_BAND(ethr_sint_t, atomic, _mb);
+ AT_TEST_READ_BOR(ethr_sint_t, atomic, _mb);
+
+ /* Double word */
+ {
+ ethr_dw_atomic_t dw_atomic;
+ ethr_dw_sint_t dw0, dw1;
+ dw0.sint[0] = 4711;
+ dw0.sint[1] = 4712;
+
+ /* init */
+ ethr_dw_atomic_init(&dw_atomic, &dw0);
+ ethr_dw_atomic_read(&dw_atomic, &dw1);
+ ETHR_ASSERT(dw1.sint[0] == 4711);
+ ETHR_ASSERT(dw1.sint[1] == 4712);
+
+ /* set */
+ dw0.sint[0] = 42;
+ dw0.sint[1] = ~((ethr_sint_t) 0);
+ ethr_dw_atomic_set(&dw_atomic, &dw0);
+ ethr_dw_atomic_read(&dw_atomic, &dw1);
+ ASSERT(dw1.sint[0] == 42);
+ ASSERT(dw1.sint[1] == ~((ethr_sint_t) 0));
+
+ /* cmpxchg */
+ dw0.sint[0] = 17;
+ dw0.sint[1] = 18;
+ dw1.sint[0] = 19;
+ dw1.sint[1] = 20;
+ ASSERT(!ethr_dw_atomic_cmpxchg(&dw_atomic, &dw1, &dw0));
+ ethr_dw_atomic_read(&dw_atomic, &dw0);
+ ASSERT(dw0.sint[0] == 42);
+ ASSERT(dw0.sint[1] == ~((ethr_sint_t) 0));
+
+ ASSERT(ethr_dw_atomic_cmpxchg(&dw_atomic, &dw1, &dw0));
+
+ ethr_dw_atomic_read(&dw_atomic, &dw0);
+ ASSERT(dw0.sint[0] == 19);
+ ASSERT(dw0.sint[1] == 20);
+ }
+}
+
+
+#define AT_DW_MIN 12
+#define AT_DW_MAX 42
+#define AT_DW_THREADS (AT_DW_MAX - AT_DW_MIN + 1)
+
+#define AT_DW_LOOPS 200000
+#define AT_DW_R_LOOPS 10
+
+ethr_dw_atomic_t at_dw_atomic;
+
+void
+at_dw_valid(ethr_dw_sint_t *dw)
+{
+ int i;
+ char c;
+ char *cp;
+
+ ASSERT(dw->sint[0] == dw->sint[1]);
+
+ cp = (char *) &dw->sint[0];
+ c = cp[0];
+
+ ASSERT(AT_DW_MIN <= c && c <= AT_DW_MAX);
+
+ for (i = 0; i < sizeof(ethr_sint_t); i++)
+ ASSERT(c == cp[i]);
+}
+
+void *
+at_dw_thr(void *vval)
+{
+ int l, r;
+ ethr_sint_t val = (ethr_sint_t) vval;
+ ethr_dw_sint_t dw;
+ ethr_dw_sint_t my_dw;
+
+ my_dw.sint[0] = val;
+ my_dw.sint[1] = val;
+
+ ethr_dw_atomic_set(&at_dw_atomic, &my_dw);
+ for (l = 0; l < AT_DW_LOOPS; l++) {
+ for (r = 0; r < AT_DW_R_LOOPS; r++) {
+ ethr_dw_atomic_read(&at_dw_atomic, &dw);
+ at_dw_valid(&dw);
+ }
+ ethr_dw_atomic_set(&at_dw_atomic, &my_dw);
+ for (r = 0; r < AT_DW_R_LOOPS; r++) {
+ ethr_dw_atomic_read(&at_dw_atomic, &dw);
+ at_dw_valid(&dw);
+ }
+ dw.sint[0] = 0;
+ dw.sint[1] = 0;
+ while (1) {
+ if (ethr_dw_atomic_cmpxchg(&at_dw_atomic, &my_dw, &dw))
+ break;
+ }
+ }
+}
+
+static void
+dw_atomic_massage_test(void)
+{
+ int i, res;
+ ethr_tid tid[AT_DW_THREADS];
+ ethr_thr_opts thr_opts = ETHR_THR_OPTS_DEFAULT_INITER;
+ ethr_dw_sint_t dw;
+
+ dw.sint[0] = dw.sint[1] = 0;
+
+ ethr_dw_atomic_init(&at_dw_atomic, &dw);
+
+ for (i = AT_DW_MIN; i <= AT_DW_MAX; i++) {
+ ethr_sint_t val;
+ memset(&val, i, sizeof(ethr_sint_t));
+ res = ethr_thr_create(&tid[i-AT_DW_MIN], at_dw_thr, (void *) val, &thr_opts);
+ ASSERT(res == 0);
+ }
+ for (i = AT_DW_MIN; i <= AT_DW_MAX; i++) {
+ res = ethr_thr_join(tid[i-AT_DW_MIN], NULL);
+ ASSERT(res == 0);
+ }
+}
+
void *
at_thread(void *unused)
{
int i;
long val, go;
-
val = ethr_atomic_inc_read(&at_ready);
ASSERT(val > 0);
@@ -1373,7 +1792,6 @@ at_thread(void *unused)
return NULL;
}
-
static void
atomic_test(void)
{
@@ -1382,6 +1800,8 @@ atomic_test(void)
ethr_tid tid[AT_THREADS];
ethr_thr_opts thr_opts = ETHR_THR_OPTS_DEFAULT_INITER;
+ atomic_basic_test();
+
#if ETHR_SIZEOF_PTR > 4
at_rm_val = ((long) 1) << 57;
at_set_val = ((long) 1) << 60;
@@ -1493,6 +1913,8 @@ main(int argc, char *argv[])
rwmutex_test();
else if (strcmp(testcase, "atomic") == 0)
atomic_test();
+ else if (strcmp(testcase, "dw_atomic_massage") == 0)
+ dw_atomic_massage_test();
else
skip("Test case \"%s\" not implemented yet", testcase);
diff --git a/erts/test/nt_SUITE.erl b/erts/test/nt_SUITE.erl
index 7d6da28ad6..f9bd15a0ce 100644
--- a/erts/test/nt_SUITE.erl
+++ b/erts/test/nt_SUITE.erl
@@ -490,12 +490,12 @@ middleman(Waitfor) ->
match_event(_X, []) ->
nomatch;
match_event({Time,Cat,Fac,Sev,Mes},[{Pid,Ref,{Cat,Fac,Sev,MesRE}} | Tail]) ->
- case regexp:match(Mes,MesRE) of
- {match,_,_} ->
+ case re:run(Mes,MesRE,[{capture,none}]) of
+ match ->
%%io:format("Match!~n"),
{ok,{Pid,Ref,Time,Mes},Tail};
- _Z ->
- %%io:format("No match (~p)~n",[_Z]),
+ nomatch ->
+ %%io:format("No match~n"),
case match_event({Time,Cat,Fac,Sev,Mes},Tail) of
{ok,X,Rest} ->
{ok,X,[{Pid,Ref,{Cat,Fac,Sev,MesRE}} | Rest]};
diff --git a/erts/test/z_SUITE.erl b/erts/test/z_SUITE.erl
index 8fceab32a6..482ecb8fba 100644
--- a/erts/test/z_SUITE.erl
+++ b/erts/test/z_SUITE.erl
@@ -166,9 +166,12 @@ core_search_conf(RunByTS, DBTop, XDir) ->
file_inspect(#core_search_conf{file = File}, Core) ->
FRes0 = os:cmd(File ++ " " ++ Core),
- FRes = case regexp:match(FRes0, Core) of
- {match, S, E} ->
+ FRes = case string:str(FRes0, Core) of
+ 0 ->
+ FRes0;
+ S ->
L = length(FRes0),
+ E = length(Core),
case S of
1 ->
lists:sublist(FRes0, E+1, L+1);
@@ -178,19 +181,13 @@ file_inspect(#core_search_conf{file = File}, Core) ->
" "
++
lists:sublist(FRes0, E+1, L+1)
- end;
- _ -> FRes0
+ end
end,
- case regexp:match(FRes, "[Tt][Ee][Xx][Tt]") of
+ case re:run(FRes, "text|ascii", [caseless,{capture,none}]) of
+ match ->
+ not_a_core;
nomatch ->
- case regexp:match(FRes, "[Aa][Ss][Cc][Ii][Ii]") of
- nomatch ->
- probably_a_core;
- _ ->
- not_a_core
- end;
- _ ->
- not_a_core
+ probably_a_core
end.
mk_readable(F) ->
diff --git a/erts/vsn.mk b/erts/vsn.mk
index 6be703d453..d56d03146d 100644
--- a/erts/vsn.mk
+++ b/erts/vsn.mk
@@ -17,8 +17,8 @@
# %CopyrightEnd%
#
-VSN = 5.8.4.1
-SYSTEM_VSN = R14B03
+VSN = 5.9
+SYSTEM_VSN = R15A
# Port number 4365 in 4.2
# Port number 4366 in 4.3
diff --git a/lib/Makefile b/lib/Makefile
index 7f4c309da9..7e52d6e32e 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -33,20 +33,6 @@ ifeq ($(findstring vxworks,$(TARGET)),vxworks)
cosFileTransfer cosEventDomain
endif
else
- ifeq ($(findstring ose,$(TARGET)),ose)
- ERTS_SUB_DIRECTORIES = stdlib sasl kernel compiler erl_interface
- OTHER_SUB_DIRECTORIES = \
- snmp otp_mibs appmon tools
-# OTHER_SUB_DIRECTORIES = \
-# appmon os_mon tools runtime_tools
- ifdef BUILD_ALL
- OTHER_SUB_DIRECTORIES += mnesia \
- inets pman tv observer
-# OTHER_SUB_DIRECTORIES += mnesia ic asn1 debugger \
-# inets orber pman tv observer cosTransactions cosEvent \
-# cosTime cosNotification cosProperty cosFileTransfer cosEventDomain
- endif
- else
#
# unix and win32
# --------------
@@ -59,10 +45,11 @@ else
snmp otp_mibs appmon erl_interface asn1 jinterface gs wx inets ic \
mnesia crypto orber os_mon parsetools syntax_tools pman \
public_key ssl toolbar tv observer debugger reltool odbc \
- runtime_tools diameter \
+ diameter \
cosTransactions cosEvent cosTime cosNotification cosProperty \
cosFileTransfer cosEventDomain et megaco webtool \
- xmerl edoc eunit ssh inviso typer docbuilder erl_docgen common_test percept
+ xmerl edoc eunit ssh inviso typer docbuilder erl_docgen \
+ common_test percept dialyzer
# dialyzer
OTHER_SUB_DIRECTORIES += hipe
else # BUILD_ALL on unix
@@ -70,32 +57,28 @@ else
snmp otp_mibs appmon erl_interface asn1 jinterface wx debugger reltool gs inets \
ic mnesia crypto orber os_mon parsetools syntax_tools \
pman public_key ssl toolbar tv observer odbc \
- runtime_tools diameter \
+ diameter \
cosTransactions cosEvent cosTime cosNotification \
cosProperty cosFileTransfer cosEventDomain et megaco webtool \
- xmerl edoc eunit ssh inviso typer docbuilder erl_docgen common_test percept
+ xmerl edoc eunit ssh inviso typer docbuilder erl_docgen \
+ common_test percept dialyzer
# dialyzer
OTHER_SUB_DIRECTORIES += hipe $(TSP_APP)
endif
endif
- endif
endif
ifdef BOOTSTRAP
SUB_DIRECTORIES = \
- kernel stdlib compiler orber/include
+ kernel stdlib compiler
else
ifdef SECONDARY_BOOTSTRAP
SUB_DIRECTORIES = hipe parsetools asn1/src
else
ifdef TERTIARY_BOOTSTRAP
- SUB_DIRECTORIES = snmp
- else
- ifdef FOURTH_BOOTSTRAP
- SUB_DIRECTORIES = sasl jinterface ic syntax_tools
- else # Not bootstrap build
- SUB_DIRECTORIES = $(ERTS_SUB_DIRECTORIES) $(OTHER_SUB_DIRECTORIES)
- endif
+ SUB_DIRECTORIES = snmp sasl jinterface ic syntax_tools
+ else # Not bootstrap build
+ SUB_DIRECTORIES = $(ERTS_SUB_DIRECTORIES) $(OTHER_SUB_DIRECTORIES)
endif
endif
endif
diff --git a/lib/appmon/doc/src/make.dep b/lib/appmon/doc/src/make.dep
deleted file mode 100644
index ce0d7571a3..0000000000
--- a/lib/appmon/doc/src/make.dep
+++ /dev/null
@@ -1,26 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: appmon.tex appmon_chapter.tex book.tex part.tex \
- ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: app_win.ps listbox_win.ps main_win.ps pinfo_win.ps
-
diff --git a/lib/appmon/src/appmon_web.erl b/lib/appmon/src/appmon_web.erl
index fb7144246c..7c0451c3c3 100644
--- a/lib/appmon/src/appmon_web.erl
+++ b/lib/appmon/src/appmon_web.erl
@@ -578,9 +578,9 @@ htmlify_pid([],New)->
%% the HTTP protocol %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
urlify_pid(Pid) ->
- case regexp:first_match(Pid,"[<].*[>]") of
- {match,Start,Len}->
- "%3C"++string:substr(Pid,Start+1,Len-2)++"%3E";
+ case re:run(Pid,"[<](.*)[>]",[{capture,all_but_first,list}]) of
+ {match,[PidStr]}->
+ "%3C"++PidStr++"%3E";
_->
Pid
end.
diff --git a/lib/asn1/c_src/Makefile b/lib/asn1/c_src/Makefile
index 9e9cb18524..8c06be56f8 100644
--- a/lib/asn1/c_src/Makefile
+++ b/lib/asn1/c_src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2002-2010. All Rights Reserved.
+# Copyright Ericsson AB 2002-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -51,33 +51,26 @@ EI_LIBDIR = $(ERL_TOP)/lib/erl_interface/obj$(TYPEMARKER)/$(TARGET)
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
-EI_INCLUDES = -I$(ERL_TOP)/lib/erl_interface/include
CFLAGS = $(DED_INCLUDES) $(EI_INCLUDES) $(DED_CFLAGS)
LDFLAGS += $(DED_LDFLAGS)
-LD_INCL_EI = -L$(EI_LIBDIR)
-
# ----------------------------------------------------
# Target Specs
# ----------------------------------------------------
-C_FILES = asn1_erl_driver.c
+NIF_OBJ_FILES = $(OBJDIR)/asn1_erl_nif.o
ifeq ($(TARGET),win32)
-LD_EI = -lei_md
-SHARED_OBJ_FILES = $(LIBDIR)/asn1_erl_drv.dll
-OBJ_FILES = $(OBJDIR)/asn1_erl_drv.o
+NIF_SHARED_OBJ_FILE = $(LIBDIR)/asn1_erl_nif.dll
CLIB_FLAGS =
LN=cp
else
-LD_EI = -lei
-OBJ_FILES = $(OBJDIR)/asn1_erl_drv.o
ifeq ($(findstring vxworks,$(TARGET)),vxworks)
-SHARED_OBJ_FILES = $(LIBDIR)/asn1_erl_drv.eld
+NIF_SHARED_OBJ_FILE = $(LIBDIR)/asn1_erl_nif.eld
CLIB_FLAGS =
else
-SHARED_OBJ_FILES = $(LIBDIR)/asn1_erl_drv.so
+NIF_SHARED_OBJ_FILE = $(LIBDIR)/asn1_erl_nif.so
CLIB_FLAGS = -lc
endif
LN= ln -s
@@ -87,7 +80,9 @@ endif
# Targets
# ----------------------------------------------------
-opt: $(OBJDIR) $(LIBDIR) $(SHARED_OBJ_FILES)
+_create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR))
+
+opt: $(NIF_SHARED_OBJ_FILE)
debug: opt
@@ -103,20 +98,12 @@ docs:
# ----------------------------------------------------
-$(OBJ_FILES): $(C_FILES)
- $(CC) -c $(CFLAGS) -o $(OBJ_FILES) $(C_FILES)
-
-$(SHARED_OBJ_FILES): $(OBJ_FILES)
- $(LD) $(LDFLAGS) $(LD_INCL_EI) -o $(SHARED_OBJ_FILES) $(OBJ_FILES) $(LD_EI) $(CLIB_FLAGS) $(LIBS)
-
-$(LIBDIR):
- -mkdir -p $(LIBDIR)
-
-$(OBJDIR):
- -mkdir -p $(OBJDIR)
+$(OBJDIR)/%.o: %.c
+ $(CC) -c $(CFLAGS) -O3 -o $@ $<
+$(NIF_SHARED_OBJ_FILE): $(NIF_OBJ_FILES)
+ $(LD) $(LDFLAGS) -o $(NIF_SHARED_OBJ_FILE) $(NIF_OBJ_FILES) $(CLIB_FLAGS) $(LIBS)
-
# ----------------------------------------------------
# Release Target
# ----------------------------------------------------
@@ -124,9 +111,9 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)/priv/lib
- $(INSTALL_PROGRAM) $(SHARED_OBJ_FILES) $(RELSYSDIR)/priv/lib
+ $(INSTALL_PROGRAM) $(NIF_SHARED_OBJ_FILE) $(RELSYSDIR)/priv/lib
$(INSTALL_DIR) $(RELSYSDIR)/c_src
- $(INSTALL_DATA) $(C_FILES) $(RELSYSDIR)/c_src
+ $(INSTALL_DATA) *.c $(RELSYSDIR)/c_src
release_docs_spec:
diff --git a/lib/asn1/c_src/asn1_erl_driver.c b/lib/asn1/c_src/asn1_erl_driver.c
deleted file mode 100644
index 18d4157941..0000000000
--- a/lib/asn1/c_src/asn1_erl_driver.c
+++ /dev/null
@@ -1,1677 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2002-2011. All Rights Reserved.
- *
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include "erl_driver.h"
-#include "ei.h"
-
-
-/* #define ASN1_DEBUG 1 */
-
-#define ASN1_OK 0
-#define ASN1_ERROR -1
-#define ASN1_COMPL_ERROR 1
-#define ASN1_MEMORY_ERROR 0
-#define ASN1_DECODE_ERROR 2
-#define ASN1_TAG_ERROR -3
-#define ASN1_LEN_ERROR -4
-#define ASN1_INDEF_LEN_ERROR -5
-#define ASN1_VALUE_ERROR -6
-
-
-#define ASN1_CLASS 0xc0
-#define ASN1_FORM 0x20
-#define ASN1_CLASSFORM (ASN1_CLASS | ASN1_FORM)
-#define ASN1_TAG 0x1f
-#define ASN1_LONG_TAG 0x7f
-
-#define ASN1_INDEFINITE_LENGTH 0x80
-#define ASN1_SHORT_DEFINITE_LENGTH 0
-
-#define ASN1_PRIMITIVE 0
-#define ASN1_CONSTRUCTED 0x20
-
-#define ASN1_COMPLETE 1
-#define ASN1_BER_TLV_DECODE 2
-#define ASN1_BER_TLV_PARTIAL_DECODE 3
-
-#define ASN1_NOVALUE 0
-
-#define ASN1_SKIPPED 0
-#define ASN1_OPTIONAL 1
-#define ASN1_CHOOSEN 2
-
-
-#define CEIL(X,Y) ((X-1) / Y + 1)
-
-#define INVMASK(X,M) (X & (M ^ 0xff))
-#define MASK(X,M) (X & M)
-
-typedef struct {
- ErlDrvPort port;
- int buffer_size;
-} asn1_data;
-
-/* int min_alloc_bytes; */
-
-
-static ErlDrvData asn1_drv_start(ErlDrvPort, char *);
-
-static void asn1_drv_stop(ErlDrvData);
-
-int asn1_drv_control(ErlDrvData, unsigned int, char *, int, char **, int);
-
-int complete(ErlDrvBinary **,unsigned char *,unsigned char *, int);
-
-int insert_octets(int, unsigned char **, unsigned char **, int *);
-
-int insert_octets_except_unused(int, unsigned char **, unsigned char **,
- int *, int);
-
-int insert_octets_as_bits_exact_len(int, int, unsigned char **,
- unsigned char **, int *);
-
-int insert_octets_as_bits(int, unsigned char **, unsigned char **,int *);
-
-int pad_bits(int, unsigned char **, int *);
-
-int insert_least_sign_bits(int, unsigned char, unsigned char **, int *);
-
-int insert_most_sign_bits(int, unsigned char, unsigned char **, int *);
-
-int insert_bits_as_bits(int, int, unsigned char **, unsigned char **, int *);
-
-int insert_octets_unaligned(int, unsigned char **, unsigned char **, int);
-
-int realloc_decode_buf(ErlDrvBinary **,int);
-
-int realloc_memory(ErlDrvBinary **,int,unsigned char **,unsigned char **);
-
-int decode_begin(ErlDrvBinary **,unsigned char *, int, unsigned int *);
-
-int decode(ErlDrvBinary **,int *,unsigned char *,int *, int);
-
-int decode_tag(char *,int *,unsigned char *,int,int *);
-
-int decode_value(int *,unsigned char *,int *,ErlDrvBinary **,int ,int);
-
-
-/* declaration of functions used for partial decode of a BER encoded
- message */
-
-int decode_partial(ErlDrvBinary **,unsigned char *, int);
-
-int skip_tag(unsigned char *,int *,int);
-
-int skip_length_and_value(unsigned char *,int *,int);
-
-int get_tag(unsigned char *,int *,int);
-
-int get_length(unsigned char *,int *,int *,int);
-
-int get_value(char *,unsigned char *,int *,int);
-
-static ErlDrvEntry asn1_drv_entry = {
- NULL, /* init, always NULL for dynamic drivers */
- asn1_drv_start, /* start, called when port is opened */
- asn1_drv_stop, /* stop, called when port is closed */
- NULL, /* output, called when erlang has sent */
- NULL, /* ready_input, called when input descriptor ready */
- NULL, /* ready_output, called when output descriptor ready */
- "asn1_erl_drv", /* char *driver_name, the argument to open_port */
- NULL, /* finish, called when unloaded */
- NULL, /* void * that is not used (BC) */
- asn1_drv_control, /* control, port_control callback */
- NULL, /* timeout, called on timeouts */
- NULL, /* outputv, vector output interface */
-
- NULL, /* ready_async */
- NULL, /* flush */
- NULL, /* call */
- NULL, /* event */
- ERL_DRV_EXTENDED_MARKER,
- ERL_DRV_EXTENDED_MAJOR_VERSION,
- ERL_DRV_EXTENDED_MINOR_VERSION,
- ERL_DRV_FLAG_USE_PORT_LOCKING,
- NULL, /* handle2 */
- NULL /* process_exit */
-};
-
-
-
-DRIVER_INIT(asn1_erl_drv) /* must match name in driver_entry */
-{
- return &asn1_drv_entry;
-}
-
-static ErlDrvData asn1_drv_start(ErlDrvPort port, char *buff)
-{
- /* extern int min_alloc_bytes; */
- char *ptr;
- asn1_data* d;
-
- d = (asn1_data*)driver_alloc(sizeof(asn1_data));
- set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY);
- d->port = port;
-
- if ((ptr = getenv("ASN1_MIN_BUF_SIZE")) == NULL)
- d->buffer_size = 1024;
- else
- d->buffer_size = atoi(ptr);
- return (ErlDrvData)d;
-}
-
-
-static void asn1_drv_stop(ErlDrvData handle)
-{
- driver_free((char*)handle);
-}
-
-
-
-int asn1_drv_control(ErlDrvData handle,
- unsigned int command,
- char *buf,
- int buf_len,
- char **res_buf,
- int res_buf_len)
-{
- unsigned char *complete_buf;
- int complete_len, decode_len;
- ErlDrvBinary *drv_binary;
- ErlDrvBinary **drv_bin_ptr;
- asn1_data* a_data;
- int min_alloc_bytes;
- unsigned int err_pos = 0; /* in case of error, return last correct position */
- int ret_err; /* return value in case of error in TLV decode, i.e. length of list in res_buf */
-
- /* In case previous call to asn1_drv_control resulted in a change of
- return value from binary to integer list */
- a_data = (asn1_data *)handle;
- min_alloc_bytes = a_data->buffer_size;
- set_port_control_flags(a_data->port, PORT_CONTROL_FLAG_BINARY);
-
- if (command == ASN1_COMPLETE)
- {
- if (buf_len==0) {
- return 0; /* Avoid binary buffer overwrite (OTP-8451) */
- }
- /* Do the PER complete encode step */
- if ((drv_binary = driver_alloc_binary(buf_len))==NULL) {
- /* error handling */
- set_port_control_flags(a_data->port, 0);
- return ASN1_MEMORY_ERROR;
- }
- complete_buf = (unsigned char*) drv_binary->orig_bytes;
- if ((complete_len = complete(&drv_binary,complete_buf,(unsigned char*) buf,buf_len)) == ASN1_ERROR)
- {
- /* error handling due to failure in complete */
- /* printf("error when running complete\n\r"); */
- driver_free_binary(drv_binary);
- set_port_control_flags(a_data->port, 0);
- **res_buf = '1';
- return ASN1_COMPL_ERROR;
- }
- /* printf("complete_len=%dbuf_len=%d,orig_size=%d\n\r",complete_len,buf_len,drv_binary->orig_size); */
- /* now the message is complete packed, return to Erlang */
- /* if (complete_len < buf_len) {*/
- if (complete_len < drv_binary->orig_size) {
- ErlDrvBinary *tmp;
- if ((tmp=driver_realloc_binary(drv_binary,complete_len)) == NULL){
- /*error handling due to memory allocation failure */
- driver_free_binary(drv_binary);
- set_port_control_flags(a_data->port, 0);
- return ASN1_MEMORY_ERROR;
- }else
- drv_binary=tmp;
- }
- *res_buf = (char *)drv_binary;
- return complete_len;
- } else if (command == ASN1_BER_TLV_DECODE) { /* control == 2 */
- /* Do the tlv decode,
- return the resulting term encoded on the Erlang
- external format */
-/* printf("driver: buffer_len = %d, min_alloc_bytes = %d\r\n",buf_len,min_alloc_bytes); */
- if ((drv_binary = driver_alloc_binary((buf_len*5)+min_alloc_bytes))==NULL) {
- /* error handling */
- set_port_control_flags(a_data->port, 0);
- return ASN1_MEMORY_ERROR;
- }
- drv_bin_ptr = &drv_binary;
- if ((decode_len = decode_begin(drv_bin_ptr,(unsigned char*)buf,buf_len,&err_pos)) <= ASN1_ERROR)
- {
- /* error handling due to failure in decode */
- char tmp_res_buf[5];
- driver_free_binary(*drv_bin_ptr);
- set_port_control_flags(a_data->port, 0);
-
- if(decode_len==ASN1_ERROR)
- tmp_res_buf[0]='1';
- else if(decode_len==ASN1_TAG_ERROR)
- tmp_res_buf[0]='2';
- else if(decode_len==ASN1_LEN_ERROR)
- tmp_res_buf[0]='3';
- else if(decode_len==ASN1_INDEF_LEN_ERROR)
- tmp_res_buf[0]='4';
- else if(decode_len==ASN1_VALUE_ERROR)
- tmp_res_buf[0]='5';
-/* printf("err_pos=%d\r\n",err_pos); */
-/* printf("decode_len:%d\r\n",decode_len); */
- ret_err = 1;
- while(err_pos>0){
- tmp_res_buf[ret_err] =(char)err_pos;/* c;*/
- err_pos = err_pos >> 8;
- ret_err++;
- }
- strncpy(*res_buf,tmp_res_buf,ret_err);
- return ret_err;
- }
-/* printf("decode_len=%d\r\n",decode_len); */
- if (decode_len < ((buf_len * 5) + min_alloc_bytes)) {
- /* not all memory was used => we have to reallocate */
- ErlDrvBinary *tmp;
- if ((tmp=driver_realloc_binary(*drv_bin_ptr,decode_len)) == NULL){
- /*error handling due to memory allocation failure */
- driver_free_binary(*drv_bin_ptr);
- set_port_control_flags(a_data->port, 0);
- return ASN1_MEMORY_ERROR;
- }else
- *drv_bin_ptr=tmp;
- }
- *res_buf = (char *)(*drv_bin_ptr);
- return decode_len;
- } else { /*command == ASN1_BER_TLV_PARTIAL_DECODE */
- if ((drv_binary = driver_alloc_binary(buf_len))==NULL) {
- /* error handling */
- set_port_control_flags(a_data->port, 0);
- return ASN1_MEMORY_ERROR;
- }
- drv_bin_ptr = &drv_binary;
- if ((decode_len = decode_partial(drv_bin_ptr,(unsigned char*)buf,buf_len))
- <= ASN1_ERROR) {
- /* error handling due to failure in decode */
- driver_free_binary(*drv_bin_ptr);
- set_port_control_flags(a_data->port, 0);
-
-/* printf("asn1_drv_control 1: decode_len=%d\r\n",decode_len); */
-
- if(decode_len==ASN1_ERROR)
- **res_buf = '1';
- return ASN1_DECODE_ERROR;
- }
- if (decode_len < buf_len) {
- /* not all memory was used => we have to reallocate */
- ErlDrvBinary *tmp;
-/* printf("asn1_drv_control 2: decode_len=%d\r\n",decode_len); */
- if ((tmp=driver_realloc_binary(*drv_bin_ptr,decode_len)) == NULL){
- /*error handling due to memory allocation failure */
- driver_free_binary(*drv_bin_ptr);
- set_port_control_flags(a_data->port, 0);
- return ASN1_MEMORY_ERROR;
- }else
- *drv_bin_ptr=tmp;
- }
- *res_buf = (char *)(*drv_bin_ptr);
- return decode_len;
- }
-}
-
-
-
-/*
- *
- * This section defines functionality for the complete encode of a
- * PER encoded message
- *
- */
-
-int complete(ErlDrvBinary **drv_binary,unsigned char *complete_buf,
- unsigned char *in_buf, int in_buf_len)
-{
- int counter = in_buf_len;
- /* counter keeps track of number of bytes left in the
- input buffer */
-
- int buf_space = in_buf_len;
- /* This is the amount of allocated space left of the complete_buf. It
- is possible when padding is applied that more space is needed than
- was originally allocated. */
-
- int buf_size = in_buf_len;
- /* Size of the buffer. May become reallocated and thus other than
- in_buf_len */
-
- unsigned char *in_ptr, *ptr;
- /* in_ptr points at the next byte in in_buf to be moved to
- complete_buf.
- ptr points into the new completed buffer, complete_buf, at the
- position of the next byte that will be set */
- int unused = 8;
- /* unused = [1,...,8] indicates how many of the rigthmost bits of
- the byte that ptr points at that are unassigned */
-
- int no_bits,no_bytes,in_unused,desired_len,ret, saved_mem, needed, pad_bits;
-
- unsigned char val;
-
- in_ptr = in_buf;
- ptr = complete_buf;
- *ptr = 0x00;
- while(counter > 0) {
- counter--;
-/* printf("*in_ptr = %d\n\r",*in_ptr); */
- switch (*in_ptr) {
- case 0:
- /* just one zero-bit should be added to the buffer */
- if(unused == 1){
- unused = 8;
- *++ptr = 0x00;
- buf_space--;
- } else
- unused--;
- break;
-
- case 1:
- /* one one-bit should be added to the buffer */
- if(unused == 1){
- *ptr = *ptr | 1;
- unused = 8;
- *++ptr = 0x00;
- buf_space--;
- } else {
- *ptr = *ptr | (1 << (unused - 1));
- unused--;
- }
- break;
-
- case 2:
- /* align buffer to end of byte */
- if (unused != 8) {
- *++ptr = 0x00;
- buf_space--;
- unused = 8;
- }
- break;
-
- case 10:
- /* next byte in in_buf tells how many bits in the second next
- byte that will be used */
- /* The leftmost unused bits in the value byte are supposed to be
- zero bits */
- no_bits = (int)*(++in_ptr);
- val = *(++in_ptr);
- counter -= 2;
- if ((ret=insert_least_sign_bits(no_bits,val,&ptr,&unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- buf_space -= ret;
- break;
-
- case 20:
- /* in this case the next value in_ptr points at holds the number
- of following bytes that holds the value that will be inserted
- in the completed buffer */
- no_bytes = (int)*(++in_ptr);
- counter -= (no_bytes + 1);
- if ((counter<0) ||
- (ret=insert_octets(no_bytes,&in_ptr,&ptr,&unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- buf_space -= ret;
- break;
-
- case 21:
- /* in this case the next two bytes in_ptr points at holds the number
- of following bytes that holds the value that will be inserted
- in the completed buffer */
- no_bytes = (int)*(++in_ptr);
- no_bytes = no_bytes << 8;
- no_bytes = no_bytes | (int)*(++in_ptr);
- counter -= (2 + no_bytes);
- if ((counter<0) ||
- (ret=insert_octets(no_bytes,&in_ptr,&ptr,&unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- buf_space -= ret;
- break;
-
- case 30:
- /* If we call the following bytes, in the buffer in_ptr points at,
- By1,By2,Rest then Rest is the value that will be transfered to
- the completed buffer. By1 tells how many of the rightmost bits in
- Rest that should not be used. By2 is the length of Rest in bytes.*/
- in_unused = (int)*(++in_ptr);
- no_bytes = (int)*(++in_ptr);
- counter -= (2 + no_bytes);
-/* printf("%d: case 30: in_unused=%d, no_bytes=%d,counter=%d\n\r",__LINE__,in_unused,no_bytes,counter); */
- ret = -4711;
- if ((counter<0) ||
- (ret=insert_octets_except_unused(no_bytes,&in_ptr,&ptr,&unused,in_unused)) == ASN1_ERROR)
- return ASN1_ERROR;
-/* printf("%d: ret=%d\n\r",__LINE__, ret); */
- buf_space -= ret;
- break;
-
- case 31:
- /* If we call the following bytes, in the buffer in_ptr points at,
- By1,By2,By3,Rest then Rest is the value that will be transfered to
- the completed buffer. By1 tells how many of the rightmost bits in
- Rest that should not be used. By2 and By3 is the length of
- Rest in bytes.*/
- in_unused = (int)*(++in_ptr);
- no_bytes = (int)*(++in_ptr);
- no_bytes = no_bytes << 8;
- no_bytes = no_bytes | (int)*(++in_ptr);
- counter -= (3 + no_bytes);
- if ((counter<0) ||
- (ret=insert_octets_except_unused(no_bytes,&in_ptr,&ptr,&unused,in_unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- buf_space -= ret;
- break;
-
- case 40:
- /* This case implies that next byte,By1,(..,By1,By2,Bin,...)
- is the desired length of the completed value, maybe needs
- padding zero bits or removal of trailing zero bits from Bin.
- By2 is the length of Bin and Bin is the value that will be
- put into the completed buffer. Each byte in Bin has the value
- 1 or 0.*/
- desired_len = (int)*(++in_ptr);
- no_bytes=(int)*(++in_ptr);
-
- /* This is the algorithm for need of memory reallocation:
- Only when padding (cases 40 - 43,45 - 47) more memory may be
- used than allocated. Therefore one has to keep track of how
- much of the allocated memory that has been saved, i.e. the
- difference between the number of parsed bytes of the input buffer
- and the number of used bytes of the output buffer.
- If saved memory is less than needed for the padding then we
- need more memory. */
- saved_mem = buf_space - counter;
- pad_bits = desired_len - no_bytes - unused;
- needed = (pad_bits > 0) ? CEIL(pad_bits,8) : 0;
- if (saved_mem < needed) {
- /* Have to allocate more memory */
- buf_size += needed;
- buf_space += needed;
- if (realloc_memory(drv_binary,buf_size,&ptr,
- &complete_buf) == ASN1_ERROR)
- return ASN1_ERROR;
- }
-
- counter -= (2 + no_bytes);
- if ((counter<0) ||
- (ret=insert_octets_as_bits_exact_len(desired_len,no_bytes,&in_ptr,
- &ptr,&unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- buf_space -= ret;
- break;
-
- case 41:
- /* Same as case 40 apart from By2, the length of Bin, which is in
- two bytes*/
- desired_len = (int)*(++in_ptr);
- no_bytes=(int)*(++in_ptr);
- no_bytes = no_bytes << 8;
- no_bytes = no_bytes | (int)*(++in_ptr);
-
- saved_mem = buf_space - counter;
- needed = CEIL((desired_len-unused),8) - no_bytes;
- if (saved_mem < needed) {
- /* Have to allocate more memory */
- buf_size += needed;
- buf_space += needed;
- if (realloc_memory(drv_binary,buf_size,&ptr,
- &complete_buf) == ASN1_ERROR)
- return ASN1_ERROR;
- }
-
- counter -= (3 + no_bytes);
- if ((counter<0) ||
- (ret=insert_octets_as_bits_exact_len(desired_len,no_bytes,&in_ptr,
- &ptr,&unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- buf_space -= ret;
- break;
-
- case 42:
- /* Same as case 40 apart from By1, the desired length, which is in
- two bytes*/
- desired_len = (int)*(++in_ptr);
- desired_len = desired_len << 8;
- desired_len = desired_len | (int)*(++in_ptr);
- no_bytes=(int)*(++in_ptr);
-
- saved_mem = buf_space - counter;
- needed = CEIL((desired_len-unused),8) - no_bytes;
- if (saved_mem < needed) {
- /* Have to allocate more memory */
- buf_size += needed;
- buf_space += needed;
- if (realloc_memory(drv_binary,buf_size,&ptr,
- &complete_buf) == ASN1_ERROR)
- return ASN1_ERROR;
- }
-
- counter -= (3 + no_bytes);
- if ((counter<0) ||
- (ret=insert_octets_as_bits_exact_len(desired_len,no_bytes,&in_ptr,
- &ptr,&unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- buf_space -= ret;
- break;
-
- case 43:
- /* Same as case 40 apart from By1 and By2, the desired length and
- the length of Bin, which are in two bytes each. */
- desired_len = (int)*(++in_ptr);
- desired_len = desired_len << 8;
- desired_len = desired_len | (int)*(++in_ptr);
- no_bytes=(int)*(++in_ptr);
- no_bytes = no_bytes << 8;
- no_bytes = no_bytes | (int)*(++in_ptr);
-
- saved_mem = buf_space - counter;
- needed = CEIL((desired_len-unused),8) - no_bytes;
- if (saved_mem < needed) {
- /* Have to allocate more memory */
- buf_size += needed;
- buf_space += needed;
- if (realloc_memory(drv_binary,buf_size,&ptr,
- &complete_buf) == ASN1_ERROR)
- return ASN1_ERROR;
- }
-
- counter -= (4 + no_bytes);
- if ((counter<0) ||
- (ret=insert_octets_as_bits_exact_len(desired_len,no_bytes,&in_ptr,
- &ptr,&unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- buf_space -= ret;
- break;
-
- case 45:
- /* This case assumes that the following bytes in the incoming buffer
- (called By1,By2,Bin) is By1, which is the number of bits (n) that
- will be inserted in the completed buffer. By2 is the number of
- bytes in Bin. Each bit in the buffer Bin should be inserted from
- the leftmost until the nth.*/
- desired_len = (int)*(++in_ptr);
- no_bytes=(int)*(++in_ptr);
-
- saved_mem = buf_space - counter;
- needed = CEIL((desired_len-unused),8) - no_bytes;
-/* printf("buf_space=%d, counter=%d, needed=%d",buf_space,counter,needed); */
- if (saved_mem < needed) {
- /* Have to allocate more memory */
- buf_size += needed;
- buf_space += needed;
- if (realloc_memory(drv_binary,buf_size,&ptr,
- &complete_buf) == ASN1_ERROR)
- return ASN1_ERROR;
- }
-
- counter -= (2 + no_bytes);
-/* printf("calling insert_bits_as_bits: desired_len=%d, no_bytes=%d\n\r",desired_len,no_bytes); */
-/* printf("1in_ptr=%d\n\r",in_ptr); */
-
- if((counter<0) ||
- (ret=insert_bits_as_bits(desired_len,no_bytes,&in_ptr,
- &ptr,&unused)) == ASN1_ERROR)
- return ASN1_ERROR;
-/* printf("2in_ptr=%d, ptr=%d, complete_buf=%d\n\r",in_ptr,ptr,complete_buf); */
-/* printf("buf_space=%d, ret=%d, counter=%d\n\r",buf_space,ret,counter); */
- buf_space -= ret;
- break;
-
- case 46:
- /* Same as case 45 apart from By1, the desired length, which is
- in two bytes. */
- desired_len = (int)*(++in_ptr);
- desired_len = desired_len << 8;
- desired_len = desired_len | (int)*(++in_ptr);
- no_bytes=(int)*(++in_ptr);
-
- saved_mem = buf_space - counter;
- needed = CEIL((desired_len-unused),8) - no_bytes;
- if (saved_mem < needed) {
- /* Have to allocate more memory */
- buf_size += needed;
- buf_space += needed;
- if (realloc_memory(drv_binary,buf_size,&ptr,
- &complete_buf) == ASN1_ERROR)
- return ASN1_ERROR;
- }
-
- counter -= (3 + no_bytes);
- if((counter<0) ||
- (ret=insert_bits_as_bits(desired_len,no_bytes,&in_ptr,
- &ptr,&unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- buf_space -= ret;
- break;
-
- case 47:
- /* Same as case 45 apart from By1 and By2, the desired length
- and the length of Bin, which are in two bytes each. */
- desired_len = (int)*(++in_ptr);
- desired_len = desired_len << 8;
- desired_len = desired_len | (int)*(++in_ptr);
- no_bytes=(int)*(++in_ptr);
- no_bytes = no_bytes << 8;
- no_bytes = no_bytes | (int)*(++in_ptr);
-
- saved_mem = buf_space - counter;
- needed = CEIL((desired_len-unused),8) - no_bytes;
- if (saved_mem < needed) {
- /* Have to allocate more memory */
- buf_size += needed;
- buf_space += needed;
- if (realloc_memory(drv_binary,buf_size,&ptr,
- &complete_buf) == ASN1_ERROR)
- return ASN1_ERROR;
- }
-
- counter -= (4 + no_bytes);
- if((counter<0) ||
- (ret=insert_bits_as_bits(desired_len,no_bytes,&in_ptr,
- &ptr,&unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- buf_space -= ret;
- break;
-
- default:
- return ASN1_ERROR;
- }
- in_ptr++;
- }
- /* The returned buffer must be at least one byte and
- it must be octet aligned */
- if ((unused == 8) && (ptr != complete_buf))
- return (ptr - complete_buf);
- else {
- ptr++; /* octet align buffer */
- return (ptr - complete_buf);
- }
-}
-
-
-int realloc_memory(ErlDrvBinary **drv_binary,
- int amount,
- unsigned char **ptr,
- unsigned char **complete_buf) {
-
- ErlDrvBinary *tmp_bin;
- int i;
-
-/* printf("realloc_momory: amount = %d\n",amount); */
- if ((tmp_bin=driver_realloc_binary(*drv_binary,amount)) == NULL) {
- /*error handling due to memory allocation failure */
-/* printf("error when allocating memory\n"); */
- return ASN1_ERROR;
- }else {
- i = *ptr - *complete_buf;
- *drv_binary=tmp_bin;
- *complete_buf = (unsigned char*)(*drv_binary)->orig_bytes;
- *ptr = *complete_buf + i;
- }
- return ASN1_OK;
-}
-
-
-int insert_most_sign_bits(int no_bits,
- unsigned char val,
- unsigned char **output_ptr,
- int *unused) {
- unsigned char *ptr = *output_ptr;
-
- if (no_bits < *unused){
- *ptr = *ptr | (val >> (8 - *unused));
- *unused -= no_bits;
- } else if (no_bits == *unused) {
- *ptr = *ptr | (val >> (8 - *unused));
- *unused = 8;
- *++ptr = 0x00;
- } else {
- *ptr = *ptr | (val >> (8 - *unused));
- *++ptr = 0x00;
- *ptr = *ptr | (val << *unused);
- *unused = 8 - (no_bits - *unused);
- }
- *output_ptr = ptr;
- return ASN1_OK;
-}
-
-
-int insert_least_sign_bits(int no_bits,
- unsigned char val,
- unsigned char **output_ptr,
- int *unused) {
- unsigned char *ptr = *output_ptr;
- int ret = 0;
-
- if (no_bits < *unused){
- *ptr = *ptr | (val << (*unused - no_bits));
- *unused -= no_bits;
- } else if (no_bits == *unused){
- *ptr = *ptr | val;
- *unused = 8;
- *++ptr = 0x00;
- ret++;
- } else {
- /* first in the begun byte in the completed buffer insert
- so many bits that fit, then insert the rest in next byte.*/
- *ptr = *ptr | (val >> (no_bits - *unused));
- *++ptr = 0x00;
- ret++;
- *ptr = *ptr | (val << (8 - (no_bits - *unused)));
- *unused = 8 - (no_bits - *unused);
- }
- *output_ptr = ptr;
- return ret;
-}
-
-/* pad_bits adds no_bits bits in the buffer that output_ptr
- points at.
- */
-int pad_bits(int no_bits, unsigned char **output_ptr, int *unused)
- {
- unsigned char *ptr = *output_ptr;
- int ret = 0;
-
- while (no_bits > 0) {
- if(*unused == 1){
- *unused = 8;
- *++ptr = 0x00;
- ret++;
- } else
- (*unused)--;
- no_bits--;
- }
- *output_ptr = ptr;
- return ret;
- }
-
-
-/* insert_bits_as_bits removes no_bytes bytes from the buffer that in_ptr
- points at and takes the desired_no leftmost bits from those removed
- bytes and inserts them in the buffer(output buffer) that ptr points at.
- The unused parameter tells how many bits that are not set in the
- actual byte in the output buffer. If desired_no is more bits than the
- input buffer has in no_bytes bytes, then zero bits is padded.*/
-int insert_bits_as_bits(int desired_no,
- int no_bytes,
- unsigned char **input_ptr,
- unsigned char **output_ptr,
- int *unused)
-{
- unsigned char *in_ptr = *input_ptr;
- unsigned char val;
- int no_bits, ret, ret2;
-
- if (desired_no == (no_bytes * 8)) {
- if(insert_octets_unaligned(no_bytes,&in_ptr,output_ptr,*unused)
- == ASN1_ERROR)
- return ASN1_ERROR;
- ret = no_bytes;
- }
- else if (desired_no < (no_bytes * 8)) {
-/* printf("insert_bits_as_bits 1\n\r"); */
- if(insert_octets_unaligned(desired_no/8,&in_ptr,output_ptr,*unused)
- == ASN1_ERROR)
- return ASN1_ERROR;
-/* printf("insert_bits_as_bits 2\n\r"); */
- val = *++in_ptr;
-/* printf("val = %d\n\r",(int)val); */
- no_bits = desired_no % 8;
-/* printf("no_bits = %d\n\r",no_bits); */
- insert_most_sign_bits(no_bits,val,output_ptr,unused);
- ret = CEIL(desired_no,8);
- }
- else {
- if(insert_octets_unaligned(no_bytes,&in_ptr,output_ptr,*unused)
- == ASN1_ERROR)
- return ASN1_ERROR;
- ret2 = pad_bits(desired_no - (no_bytes * 8),output_ptr,unused);
-/* printf("ret2 = %d\n\r",ret2); */
- ret = CEIL(desired_no,8);
-/* printf("ret = %d\n\r",ret); */
- }
-/* printf("*unused = %d\n\r",*unused); */
- *input_ptr = in_ptr;
- return ret;
-}
-
-
-/* insert_octets_as_bits_exact_len */
-int
-insert_octets_as_bits_exact_len(int desired_len,
- int in_buff_len,
- unsigned char **in_ptr,
- unsigned char **ptr,
- int *unused)
-{
- int ret = 0;
- int ret2 = 0;
-
- if (desired_len == in_buff_len) {
- if ((ret = insert_octets_as_bits(in_buff_len,in_ptr,ptr,unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- }
- else if(desired_len > in_buff_len) {
- if((ret = insert_octets_as_bits(in_buff_len,in_ptr,ptr,unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- /* now pad with zero bits */
-/* printf("~npad_bits: called with %d bits padding~n~n~r",desired_len - in_buff_len); */
- if ((ret2=pad_bits(desired_len - in_buff_len,ptr,unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- }
- else {/* desired_len < no_bits */
- if ((ret=insert_octets_as_bits(desired_len,in_ptr,ptr,unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- /* now remove no_bits - desired_len bytes from in buffer */
- *in_ptr += (in_buff_len - desired_len);
- }
- return (ret+ret2);
-}
-
-
-
-/* insert_octets_as_bits takes no_bytes bytes from the buffer that input_ptr
- points at and inserts the least significant bit of it in the buffer that
- output_ptr points at. Each byte in the input buffer must be 1 or 0
- otherwise the function returns ASN1_ERROR. The output buffer is concatenated
- without alignment.
- */
-int insert_octets_as_bits(int no_bytes,
- unsigned char **input_ptr,
- unsigned char **output_ptr,
- int *unused)
-{
- unsigned char *in_ptr = *input_ptr;
- unsigned char *ptr = *output_ptr;
- int used_bits = 8 - *unused;
-
- while (no_bytes > 0) {
- switch (*++in_ptr) {
- case 0:
- if(*unused == 1){
- *unused = 8;
- *++ptr = 0x00;
- } else
- (*unused)--;
- break;
- case 1:
- if(*unused == 1){
- *ptr = *ptr | 1;
- *unused = 8;
- *++ptr = 0x00;
- } else {
- *ptr = *ptr | (1 << (*unused - 1));
- (*unused)--;
- }
- break;
- default:
- return ASN1_ERROR;
- }
- no_bytes--;
- }
- *input_ptr = in_ptr;
- *output_ptr = ptr;
- return ((used_bits+no_bytes) / 8); /*return number of new bytes
- in completed buffer */
-}
-
-/* insert_octets inserts bytes from the input buffer, *input_ptr,
- into the output buffer, *output_ptr. Before the first byte is
- inserted the input buffer is aligned.
- */
-int insert_octets(int no_bytes,
- unsigned char **input_ptr,
- unsigned char **output_ptr,
- int *unused)
-{
- unsigned char *in_ptr = *input_ptr;
- unsigned char *ptr = *output_ptr;
- int ret = 0;
-
- if (*unused != 8) {/* must align before octets are added */
- *++ptr = 0x00;
- ret++;
- *unused = 8;
- }
- while(no_bytes > 0) {
- *ptr = *(++in_ptr);
- *++ptr = 0x00;
- /* *unused = *unused - 1; */
- no_bytes--;
- }
- *input_ptr = in_ptr;
- *output_ptr = ptr;
- return (ret + no_bytes);
-}
-
-/* insert_octets_unaligned inserts bytes from the input buffer, *input_ptr,
- into the output buffer, *output_ptr.No alignment is done.
- */
-int insert_octets_unaligned(int no_bytes,
- unsigned char **input_ptr,
- unsigned char **output_ptr,
- int unused)
-{
- unsigned char *in_ptr = *input_ptr;
- unsigned char *ptr = *output_ptr;
- int n = no_bytes;
- unsigned char val;
-
- while (n > 0) {
- if (unused == 8) {
- *ptr = *++in_ptr;
- *++ptr = 0x00;
- }else {
- val = *++in_ptr;
- *ptr = *ptr | val >> (8 - unused);
- *++ptr = 0x00;
- *ptr = val << unused;
- }
- n--;
- }
- *input_ptr = in_ptr;
- *output_ptr = ptr;
- return no_bytes;
-}
-
-
-int insert_octets_except_unused(int no_bytes,
- unsigned char **input_ptr,
- unsigned char **output_ptr,
- int *unused,
- int in_unused)
-{
- unsigned char *in_ptr = *input_ptr;
- unsigned char *ptr = *output_ptr;
- int val, no_bits;
- int ret = 0;
-
- if (in_unused == 0){
-/* printf("%d: insert_octets_except_unused: if\n\r",__LINE__); */
- if ((ret = insert_octets_unaligned(no_bytes,&in_ptr,&ptr,
- *unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- }
- else {
-/* printf("%d: insert_octets_except_unused: else\n\r",__LINE__); */
- if ((ret=insert_octets_unaligned(no_bytes - 1,&in_ptr,&ptr,*unused)) != ASN1_ERROR) {
- val = (int) *(++in_ptr);
- no_bits = 8 - in_unused;
- /* no_bits is always less than *unused since the buffer is
- octet aligned after insert:octets call, so the following
- if clasuse is obsolete I think */
- if(no_bits < *unused){
- *ptr = *ptr | (val >> (8 - *unused));
- *unused = *unused - no_bits;
- } else if (no_bits == *unused) {
- *ptr = *ptr | (val >> (8 - *unused));
- *++ptr = 0x00;
- ret++;
- *unused = 8;
- } else {
- *ptr = *ptr | (val >> (8 - *unused));
- *++ptr = 0x00;
- ret++;
- *ptr = *ptr | (val << *unused);
- *unused = 8 - (no_bits - *unused);
- }
- } else
- return ASN1_ERROR;
- }
- *input_ptr = in_ptr;
- *output_ptr = ptr;
-/* printf("%d: insert_octets_except_unused: ret=%d\n\r",__LINE__,ret); */
- return ret;
-}
-
-
-
-/*
- *
- * This section defines functionality for the partial decode of a
- * BER encoded message
- *
- */
-
-/*
- * int decode(ErlDrvBinary **drv_binary,unsigned char *decode_buf,
- * unsigned char *in_buf, int in_buf_len)
- * drv_binary is a pointer to a pointer to an allocated driver binary.
- * in_buf is a pointer into the buffer of incoming bytes.
- * in_buf_len is the length of the incoming buffer.
- * The function reads the bytes in the incoming buffer and structures
- * it in a nested way as Erlang terms. The buffer contains data in the
- * order tag - length - value. Tag, length and value has the following
- * format:
- * A tag is normally one byte but may be of any length, if the tag number
- * is greater than 30. +----------+
- * |CL|C|NNNNN|
- * +----------+
- * If NNNNN is 31 then will the 7 l.s.b of each of the following tag number
- * bytes contain the tag number. Each tag number byte that is not the last one
- * has the m.s.b. set to 1.
- * The length can be short definite length (sdl), long definite length (ldl)
- * or indefinite length (il).
- * sdl: +---------+ the L bits is the length
- * |0|LLLLLLL|
- * +---------+
- * ldl: +---------+ +---------+ +---------+ +-----------+
- * |1|lllllll| |first len| | | |the Nth len|
- * +---------+ +---------+ +---------+ ... +-----------+
- * The first byte tells how many len octets will follow, max 127
- * il: +---------+ +----------------------+ +--------+ +--------+
- * |1|0000000| |content octets (Value)| |00000000| |00000000|
- * +---------+ +----------------------+ +--------+ +--------+
- * The value octets are preceded by one octet and followed by two
- * exactly as above. The value must be some tag-length-value encoding.
- *
- * The function returns a value in Erlnag term format:
- * {{TagNo,Value},Rest}
- * TagNo is an integer ((CL bsl 16) + tag number) which limits the tag number
- * to 65535.
- * Value is a binary if the C bit in tag was unset, otherwise (if tag was
- * constructed) Value is a list, List.
- * List is like: [{TagNo,Value},{TagNo,Value},...]
- * Rest is a binary, i.e. the undecoded part of the buffer. Most often Rest
- * is the empty binary.
- * If some error occured during the decoding of the in_buf an error is returned.
- */
-int decode_begin(ErlDrvBinary **drv_binary,unsigned char *in_buf, int in_buf_len, unsigned int *err_pos)
-{
- int maybe_ret;
- char *decode_buf = (*drv_binary)->orig_bytes;
- int ei_index = 0;
- int ib_index = 0;
- /* ei_index is the index used by the ei functions to encode an
- Erlang term into the buffer decode_buf */
- /* ib_index is the index were to read the next byte from in_buf */
-
-
-#ifdef ASN1_DEBUG
- printf("decode_begin1: ei_index=%d, ib_index=%d\n\r",ei_index,ib_index);
-#endif
- /* the first byte must be a "version magic" */
- if(ei_encode_version(decode_buf,&ei_index) == ASN1_ERROR)
- return ASN1_ERROR; /* 1 byte */
-#ifdef ASN1_DEBUG
- printf("decode_begin2: ei_index=%d, ib_index=%d\n\r",ei_index,ib_index);
-#endif
- if (ei_encode_tuple_header(decode_buf,&ei_index,2) == ASN1_ERROR)
- return ASN1_ERROR; /* 2 bytes */
-#ifdef ASN1_DEBUG
- printf("decode_begin3: ei_index=%d, ib_index=%d\n\r",ei_index,ib_index);
-#endif
- if((maybe_ret=decode(drv_binary,&ei_index,in_buf,&ib_index,in_buf_len)) <= ASN1_ERROR)
- {
- *err_pos = ib_index;
-#ifdef ASN1_DEBUG
- printf("err_pos=%d,ib_index=%d\r\n",*err_pos,ib_index);
-#endif
- return maybe_ret;
- };
-
- decode_buf = (*drv_binary)->orig_bytes; /* maybe a realloc during decode_value */
-#ifdef ASN1_DEBUG
- printf("decode_begin4: in_buf_len=%d, ei_index=%d, ib_index=%d\n\r",
- in_buf_len,ei_index,ib_index);
-#endif
- /* "{{TagNo,Value},Rest}" */
- if (ei_encode_binary(decode_buf,&ei_index,&(in_buf[ib_index]),in_buf_len-ib_index)
- == ASN1_ERROR) /* at least 5 bytes */
- return ASN1_ERROR;
-#ifdef ASN1_DEBUG
- printf("decode_begin5: ei_index=%d, ib_index=%d\n\r",ei_index,ib_index);
-#endif
- return ei_index;
-}
-
-int decode(ErlDrvBinary **drv_binary,int *ei_index,unsigned char *in_buf,
- int *ib_index, int in_buf_len)
-{
- int maybe_ret;
- char *decode_buf = (*drv_binary)->orig_bytes;
- int form;
-#ifdef ASN1_DEBUG
- printf("decode 1\n\r");
-#endif
- if (((*drv_binary)->orig_size - *ei_index) < 19) {/* minimum amount of bytes */
- /* allocate more memory */
- if (realloc_decode_buf(drv_binary,(*drv_binary)->orig_size * 2) ==
- ASN1_ERROR)
- return ASN1_ERROR;
- decode_buf = (*drv_binary)->orig_bytes;
- }
-/* printf("decode 2\n\r"); */
- /* "{" */
- if (ei_encode_tuple_header(decode_buf,ei_index,2) == ASN1_ERROR)
- return ASN1_ERROR; /* 2 bytes */
-#ifdef ASN1_DEBUG
- printf("decode 3:orig_size=%ld, ei_index=%d, ib_index=%d\n\r",(*drv_binary)->orig_size,*ei_index,*ib_index);
-#endif
-
- /*buffer must hold at least two bytes*/
- if ((*ib_index +2) > in_buf_len)
- return ASN1_VALUE_ERROR;
- /* "{{TagNo," */
- if ((form = decode_tag(decode_buf,ei_index,in_buf,in_buf_len,ib_index)) <= ASN1_ERROR)
- return form; /* 5 bytes */
-#ifdef ASN1_DEBUG
- printf("i_i=%d,in_buf_len=%d\r\n",*ei_index,in_buf_len);
-#endif
- if (*ib_index >= in_buf_len){
- return ASN1_TAG_ERROR;
- }
-#ifdef ASN1_DEBUG
- printf("decode 5 ib_index=%d\n\r",*ib_index);
-#endif
- /* buffer must hold at least one byte (0 as length and nothing as
- value) */
- /* "{{TagNo,Value}," */
- if ((maybe_ret=decode_value(ei_index,in_buf,ib_index,drv_binary,form,
- in_buf_len)) <= ASN1_ERROR)
- return maybe_ret; /* at least 5 bytes */
-#ifdef ASN1_DEBUG
- printf("decode 7\n\r");
-#endif
- return *ei_index;
-}
-
-/*
- * decode_tag decodes the BER encoded tag in in_buf and puts it in the
- * decode_buf encoded by the Erlang extern format as an Erlang term.
- */
-int decode_tag(char *decode_buf,int *db_index,unsigned char *in_buf,
- int in_buf_len, int *ib_index)
-{
- int tag_no, tmp_tag, form;
-
-
- /* first get the class of tag and bit shift left 16*/
- tag_no = ((MASK(in_buf[*ib_index],ASN1_CLASS)) << 10);
-
- form = (MASK(in_buf[*ib_index],ASN1_FORM));
-#ifdef ASN1_DEBUG
- printf("decode_tag0:ii=%d, tag_no=%d, form=%d.\r\n",
- *ib_index,tag_no,form);
-#endif
-
- /* then get the tag number */
- if((tmp_tag = (int) INVMASK(in_buf[*ib_index],ASN1_CLASSFORM)) < 31) {
- ei_encode_ulong(decode_buf,db_index,tag_no+tmp_tag); /* usual case */
- (*ib_index)++;
-#ifdef ASN1_DEBUG
- printf("decode_tag1:ii=%d.\r\n",*ib_index);
-#endif
- }
- else
- {
- int n = 0; /* n is used to check that the 64K limit is not
- exceeded*/
-#ifdef ASN1_DEBUG
- printf("decode_tag1:ii=%d, in_buf_len=%d.\r\n",*ib_index,in_buf_len);
-#endif
-
- /* should check that at least three bytes are left in
- in-buffer,at least two tag byte and at least one length byte */
- if ((*ib_index +3) > in_buf_len)
- return ASN1_VALUE_ERROR;
- (*ib_index)++;
-#ifdef ASN1_DEBUG
- printf("decode_tag2:ii=%d.\r\n",*ib_index);
-#endif
- /* The tag is in the following bytes in in_buf as
- 1ttttttt 1ttttttt ... 0ttttttt, where the t-bits
- is the tag number*/
- /* In practice is the tag size limited to 64K, i.e. 16 bits. If
- the tag is greater then 64K return an error */
- while (((tmp_tag = (int)in_buf[*ib_index]) >= 128) && n < 2){
- /* m.s.b. = 1 */
- tag_no = tag_no + (MASK(tmp_tag,ASN1_LONG_TAG) << 7);
- (*ib_index)++;
-#ifdef ASN1_DEBUG
- printf("decode_tag3:ii=%d.\r\n",*ib_index);
-#endif
- n++;
- };
- if ((n==2) && in_buf[*ib_index] > 3)
- return ASN1_TAG_ERROR; /* tag number > 64K */
- tag_no = tag_no + in_buf[*ib_index];
- (*ib_index)++;
-#ifdef ASN1_DEBUG
- printf("decode_tag4:ii=%d.\r\n",*ib_index);
-#endif
- ei_encode_ulong(decode_buf,db_index,tag_no);
- }
- return form;
-}
-
-
-/*
- * decode_value decodes the BER encoded length and value fields in the
- * in_buf and puts the value part in the decode_buf as an Erlang term
- * encoded by the Erlang extern format
- */
-int decode_value(int *ei_index,unsigned char *in_buf,
- int *ib_index,ErlDrvBinary **drv_binary,int form,
- int in_buf_len)
-{
- int maybe_ret;
- char *decode_buf = (*drv_binary)->orig_bytes;
- unsigned int len = 0;
- unsigned int lenoflen = 0;
- int indef = 0;
-
-#ifdef ASN1_DEBUG
- printf("decode_value1:ib_index=%d\n\r",*ib_index);
-#endif
- if (((in_buf[*ib_index]) & 0x80) == ASN1_SHORT_DEFINITE_LENGTH) {
- len = in_buf[*ib_index];
- }
- else if (in_buf[*ib_index] == ASN1_INDEFINITE_LENGTH)
- indef = 1;
- else /* long definite length */ {
- lenoflen = (in_buf[*ib_index] & 0x7f); /*length of length */
-#ifdef ASN1_DEBUG
- printf("decode_value,lenoflen:%d\r\n",lenoflen);
-#endif
- if (lenoflen > (in_buf_len - (*ib_index+1)))
- return ASN1_LEN_ERROR;
- len = 0;
- while (lenoflen-- ) {
- (*ib_index)++;
-#ifdef ASN1_DEBUG
- printf("decode_value1:*ib_index=%d, byte = %d.\r\n",*ib_index,in_buf[*ib_index]);
-#endif
- if (!(len < (1 << (sizeof(len)-1)*8)))
- return ASN1_LEN_ERROR; /* length does not fit in 32 bits */
- len = (len << 8) + in_buf[*ib_index];
- }
- }
- if (len > (in_buf_len - (*ib_index + 1)))
- return ASN1_VALUE_ERROR;
- (*ib_index)++;
-#ifdef ASN1_DEBUG
- printf("decode_value2:ii=%d.\r\n",*ib_index);
-#endif
- if (indef == 1)
- { /* in this case it is desireably to check that indefinite length
- end bytes exist in inbuffer */
- while (!(in_buf[*ib_index]==0 && in_buf[*ib_index + 1]==0)) {
-#ifdef ASN1_DEBUG
- printf("decode_value while:ib_index=%d in_buf_len=%d\n\r",
- *ib_index,in_buf_len);
-#endif
- if(*ib_index >= in_buf_len)
- return ASN1_INDEF_LEN_ERROR;
- ei_encode_list_header(decode_buf,ei_index,1); /* 5 bytes */
- if((maybe_ret=decode(drv_binary,ei_index,in_buf,
- ib_index,in_buf_len)) <= ASN1_ERROR)
- return maybe_ret;
- decode_buf = (*drv_binary)->orig_bytes;
- }
- (*ib_index) += 2; /* skip the indefinite length end bytes */
-#ifdef ASN1_DEBUG
- printf("decode_value3:ii=%d.\r\n",*ib_index);
-#endif
- ei_encode_empty_list(decode_buf,ei_index); /* 1 byte */
- }
- else if (form == ASN1_CONSTRUCTED)
- {
- int end_index = *ib_index + len;
- if(end_index > in_buf_len)
- return ASN1_LEN_ERROR;
- while (*ib_index < end_index) {
-
-#ifdef ASN1_DEBUG
- printf("decode_value3:*ib_index=%d, end_index=%d\n\r",*ib_index,end_index);
-#endif
- ei_encode_list_header(decode_buf,ei_index,1); /* 5 bytes */
- if((maybe_ret=decode(drv_binary,ei_index,in_buf,
- ib_index,in_buf_len))<=ASN1_ERROR)
- return maybe_ret;
- decode_buf = (*drv_binary)->orig_bytes;
- }
- ei_encode_empty_list(decode_buf,ei_index); /* 1 byte */
- }
- else
- {
- if (((*drv_binary)->orig_size - *ei_index) < 10+len) { /* 5+len for the binary*/
- if (realloc_decode_buf(drv_binary,(*drv_binary)->orig_size * 2) ==
- ASN1_ERROR)
- return ASN1_ERROR;
- decode_buf = (*drv_binary)->orig_bytes;
- }
- if((*ib_index + len) > in_buf_len)
- return ASN1_LEN_ERROR;
- ei_encode_binary(decode_buf,ei_index,&in_buf[*ib_index],len);
- *ib_index = *ib_index + len;
-#ifdef ASN1_DEBUG
- printf("decode_value4:ii=%d.\r\n",*ib_index);
-#endif
- }
- return ASN1_OK;
-}
-
-int realloc_decode_buf(ErlDrvBinary **drv_binary,int amount) {
- ErlDrvBinary *tmp_bin;
-
- if ((tmp_bin=driver_realloc_binary(*drv_binary,amount)) == NULL)
- return ASN1_ERROR;
- *drv_binary = tmp_bin;
- return ASN1_OK;
-}
-
-
-
-/*
- * int decode_partial(drv_binary,in_buf,in_buf_len)
- */
-/*
- * The in_buf contains two parts: first information about which value
- * will be decoded, as a sequence of tags and tag codes, then the
- * encoded BER value. First of all comes a length field that tells how
- * many following bytes contains the sequence of tags. Then starts the
- * BER encoded message. The tag sequence length field is a single
- * byte. The sequence of tags/tag codes may be one of the codes
- * ASN1_SKIPPED, ASN1_CHOOSEN and a tag or ASN1_OPTIONAL and a
- * tag. ASN1_SKIPPED means that the following tag is mandatory and is
- * skipped. ASN1_CHOOSEN means that the value of this tag shall, if
- * this was the last tag in tag sequence, be returned or be searched
- * in for the next tag. ASN1_OPTIONAL means that this tag shall be
- * skipped but it may be missing. Each tag in the tag sequence
- * correspond to a tag in the BER encoded message. If the decode
- * arives to a position where there is no matching tag, an error is
- * returned (if it wasn't the last tag and it was OPTIONAL). After the
- * right value has been detected it is returned in the out_buf.
- *
- */
-int decode_partial(ErlDrvBinary **drv_binary,unsigned char *in_buf, int in_buf_len)
-{
- char *out_buf = (*drv_binary)->orig_bytes;
- int tag_index_val = 1;
- int msg_index_val;
- int *msg_index, *tag_index, tmp_index;
- int tag_seq_length;
- int wanted_tag, next_tag;
- int buf_end_index = in_buf_len;
- int ret = 0, length, old_index;
-
- tag_index = &tag_index_val;
- tag_seq_length = in_buf[0];
- msg_index = &msg_index_val;
- *msg_index = tag_seq_length + 1;
-
-
-/* printf("decode_partial 1: in_buf_len=%d, tag_index=%d, msg_index=%d\r\n,tag_seq_length=%d\r\n",in_buf_len,*tag_index,*msg_index,tag_seq_length); */
- while(*tag_index < tag_seq_length) {
- switch(in_buf[*tag_index]) {
- case ASN1_SKIPPED:
-/* printf("decode_partial ASN1_SKIPPED: in_buf[*msg_index]=%d\r\n",in_buf[*msg_index]); */
- (*tag_index)++;
-/* printf("decode_partial ASN1_SKIPPED 2: *msg_index=%d\r\n",*msg_index); */
- skip_tag(in_buf,msg_index,buf_end_index);
-/* printf("decode_partial ASN1_SKIPPED 3: *msg_index=%d\r\n",*msg_index); */
- skip_length_and_value(in_buf,msg_index,buf_end_index);
-/* printf("decode_partial ASN1_SKIPPED 4: *msg_index=%d\r\n",*msg_index); */
- break;
- case ASN1_OPTIONAL:
- (*tag_index)++;
-/* printf("decode_partial ASN1_OPTIONAL: in_buf[*tag_index]=%d\r\n",in_buf[*tag_index]); */
- wanted_tag = in_buf[*tag_index];
- (*tag_index)++;
- tmp_index = *msg_index;
- next_tag = get_tag(in_buf,msg_index,buf_end_index);
- if (wanted_tag != next_tag) {
- *msg_index = tmp_index;
- } else
- skip_length_and_value(in_buf,msg_index,buf_end_index);
- break;
- case ASN1_CHOOSEN:
-/* printf("decode_partial ASN1_CHOOSEN: in_buf[*msg_index]=%d, *msg_index=%d\r\n",in_buf[*msg_index],*msg_index); */
- (*tag_index)++;
- wanted_tag = in_buf[*tag_index];
- (*tag_index)++;
- old_index = *msg_index;
-/* printf("decode_partial ASN1_CHOOSEN 2: *msg_index=%d\r\n",*msg_index); */
- next_tag = get_tag(in_buf,msg_index,buf_end_index);
-/* printf("decode_partial ASN1_CHOOSEN 3: *msg_index=%d\r\n,wanted_tag=%d, next_tag=%d\r\n",*msg_index,wanted_tag,next_tag); */
- if (wanted_tag != next_tag)
- return ASN1_NOVALUE; /* an empty binary will be returned to Erlang */
- if (*tag_index == (tag_seq_length + 1)) {
- /* get the value and return*/
- if((ret = get_value(out_buf,in_buf,msg_index,buf_end_index)) <= ASN1_ERROR)
- return ASN1_ERROR;
- return ret;
- }
- else {
- /* calculate the length of the sub buffer and let *msg_index
- be at the value part of this BER encoded type*/
- int indef;
- indef = 0;
- length = get_length(in_buf,msg_index,&indef,buf_end_index);
-/* printf("decode_partial ASN1_CHOOSEN 4: length=%d, *msg_index=%d\r\n",length,*msg_index); */
- if ((length == 0) && (indef == 1)) {
- /* indefinite length of value */
- old_index = *msg_index;
- length = skip_length_and_value(in_buf,msg_index,buf_end_index);
- *msg_index = old_index;
- buf_end_index = *msg_index + length - 2;
- /* remove two bytes due to indefinete length end zeros */
- } else
- buf_end_index = (*msg_index + length);
- }
- break;
- default:
- return ASN1_ERROR;
- }
- }
- return ASN1_ERROR;
-}
-
-
-/*
- * int skip_tag(unsigned char *in_buf,int *index,int buf_len)
- * steps past the BER encoded tag in in_buf and updates *index.
- * Returns the number of skipped bytes.
- */
-int skip_tag(unsigned char *in_buf,int *index,int buf_len)
-{
- int start_index = *index;
- if ((MASK(in_buf[*index],ASN1_TAG)) == 31){
- do {
- (*index)++;
- if (*index >= buf_len)
- return ASN1_ERROR;
- }
- while(in_buf[*index] >=128);
- }
- (*index)++;
- return (*index - start_index);
-}
-
-
-/*
- * int skip_length_and_value(unsigned char *in_buf,int *index,int buf_len)
- * steps past the BER encoded length and value in in_buf and updates *index.
- * returns the length if the skipped "length value".
- * Returns the number of skipped bytes.
- */
-int skip_length_and_value(unsigned char *in_buf,int *index,int buf_len)
-{
- long len;
- int indef = 0, lenoflen;
- int start_index = *index;
-
- if ((MASK(in_buf[*index],0x80)) == ASN1_SHORT_DEFINITE_LENGTH){
- len = in_buf[*index];
- if (len > (buf_len - (*index + 1)))
- return ASN1_LEN_ERROR;
- } else if (in_buf[*index] == ASN1_INDEFINITE_LENGTH)
- indef = 1;
- else /* long definite length */ {
- lenoflen = (in_buf[*index] & 0x7f); /*length of length */
- len = 0;
- while (lenoflen--) {
- (*index)++;
- len = (len << 8) + in_buf[*index];
- }
- if (len > (buf_len - (*index + 1)))
- return ASN1_LEN_ERROR;
- }
- (*index)++;
- if (indef == 1)
- {
- while(!(in_buf[*index]==0 && in_buf[*index + 1]==0)) {
- skip_tag(in_buf,index,buf_len);
- skip_length_and_value(in_buf,index,buf_len);
- }
- (*index) += 2;
- }
- else
- (*index) += len;
- return (*index - start_index);
-}
-
-/* int get_tag(unsigned char *in_buf,int *index)
- *
- * assumes next byte/bytes in in_buf is an encoded BER tag. A tag
- * number has theoretically no upper limit in size. Here the tag
- * number is assumed to be less than 64K. Returns an integer value
- * on the format:
- * xxxxxxxx xxxxxxcc tttttttt tttttttt
- * the x-bits are 0 (insignificant)
- * the c-bits are the class of the tag
- * the t-bits are the tag number. This implies that the tag number
- * is limited to 64K-1
- *
- */
-int get_tag(unsigned char *in_buf,int *index,int buf_len)
-{
- int tag_no = 0,tmp_tag = 0;
-
- tag_no = (MASK(in_buf[*index],ASN1_CLASSFORM));
- if ((MASK(in_buf[*index],ASN1_TAG)) == ASN1_TAG) {
- /* long form of tag */
- do {
- (*index)++;
- if (*index >= buf_len)
- return ASN1_TAG_ERROR;
- tmp_tag = tmp_tag << 7;
- tmp_tag += (MASK(in_buf[*index],ASN1_LONG_TAG));
- } while (in_buf[*index] >= 128);
- (*index)++;
- tag_no = tag_no + tmp_tag;
- } else {
- tag_no += (MASK(in_buf[*index],ASN1_TAG));
- (*index)++;
- }
- if (*index >= buf_len)
- return ASN1_TAG_ERROR;
- return tag_no;
-}
-
-
-/*
- * int get_value(char *out_buf,unsigned char *in_buf,
- * int *msg_index,int in_buf_len)
- */
-/* assumes next byte/bytes in in_buf is an encoded BER value preceeded by a BER encoded length. Puts value in out_buf.
- */
-int get_value(char *out_buf,
- unsigned char *in_buf,
- int *msg_index,
- int in_buf_len)
-{
- int len, lenoflen, indef=0, skip_len;
- int ret=0;
- int start_index;
-
-/* printf("get_value 1\n\r"); */
- if (in_buf[*msg_index] < 0x80){ /* short definite length */
- len = in_buf[*msg_index];
-/* printf("short definite length\r\n"); */
- } else if (in_buf[*msg_index] > 0x80) { /* long definite length */
- lenoflen = (in_buf[*msg_index] & 0x7f); /*length of length */
- len = 0;
- while (lenoflen--) {
- (*msg_index)++;
- len = (len << 8) + in_buf[*msg_index];
- }
- if (len > (in_buf_len - (*msg_index + 1)))
- return ASN1_LEN_ERROR;
- } else
- indef = 1;
- (*msg_index)++;
-/* printf("get_value 2: len = %d, *msg_index = %d\r\n",len,*msg_index); */
- if (indef == 1) {
- while(!(in_buf[*msg_index]==0 && in_buf[*msg_index + 1]==0)) {
- start_index = *msg_index;
- skip_len = skip_tag(in_buf,msg_index,in_buf_len);
-/* printf("get_value 3: skip_len=%d,start_index=%d,*msg_index=%d\n\r", */
-/* skip_len,start_index,*msg_index); */
- memcpy(&out_buf[ret],&in_buf[start_index],skip_len);
- ret += skip_len;
- start_index = *msg_index;
- skip_len = skip_length_and_value(in_buf,msg_index,in_buf_len);
-/* printf("get_value 4: skip_len=%d,start_index=%d,*msg_index=%d\n\r", */
-/* skip_len,start_index,*msg_index); */
- memcpy(&out_buf[ret],&in_buf[start_index],skip_len);
- ret += skip_len;
- }
- return ret;
- }
- else
- memcpy(&out_buf[ret],&in_buf[*msg_index],len);
- return len;
-}
-
-
-/*
- * int get_length(unsigned char *in_buf,int *msg_index)
- * assumes next byte/bytes contain a BER encoded length field,
- * which is decoded. The value of the length is returned. If it
- * is an indefinite length the *indef is set to one.
- */
-int get_length(unsigned char *in_buf,int *msg_index,
- int *indef,int in_buf_len)
-{
- int len=0, lenoflen;
-
- if (in_buf[*msg_index] < 0x80) /* short definite length */
- len = in_buf[*msg_index];
- else if (in_buf[*msg_index] > 0x80) { /* long definite length */
- lenoflen = (in_buf[*msg_index] & 0x7f); /*length of length */
- len = 0;
- while (lenoflen--) {
- (*msg_index)++;
- len = (len << 8) + in_buf[*msg_index];
- }
- if (len > (in_buf_len - (*msg_index + 1)))
- return ASN1_LEN_ERROR;
- } else
- *indef = 1;
- (*msg_index)++;
- return len;
-}
diff --git a/lib/asn1/c_src/asn1_erl_nif.c b/lib/asn1/c_src/asn1_erl_nif.c
new file mode 100644
index 0000000000..9c9f83bc2a
--- /dev/null
+++ b/lib/asn1/c_src/asn1_erl_nif.c
@@ -0,0 +1,1305 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2002-2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "erl_nif.h"
+
+/* #define ASN1_DEBUG 1 */
+
+#define ASN1_OK 0
+#define ASN1_ERROR -1
+#define ASN1_COMPL_ERROR 1
+#define ASN1_MEMORY_ERROR 0
+#define ASN1_DECODE_ERROR 2
+#define ASN1_TAG_ERROR -3
+#define ASN1_LEN_ERROR -4
+#define ASN1_INDEF_LEN_ERROR -5
+#define ASN1_VALUE_ERROR -6
+
+#define ASN1_CLASS 0xc0
+#define ASN1_FORM 0x20
+#define ASN1_CLASSFORM (ASN1_CLASS | ASN1_FORM)
+#define ASN1_TAG 0x1f
+#define ASN1_LONG_TAG 0x7f
+
+#define ASN1_INDEFINITE_LENGTH 0x80
+#define ASN1_SHORT_DEFINITE_LENGTH 0
+
+#define ASN1_PRIMITIVE 0
+#define ASN1_CONSTRUCTED 0x20
+
+#define ASN1_NOVALUE 0
+
+#define ASN1_SKIPPED 0
+#define ASN1_OPTIONAL 1
+#define ASN1_CHOOSEN 2
+
+#define CEIL(X,Y) ((X-1) / Y + 1)
+
+#define INVMASK(X,M) (X & (M ^ 0xff))
+#define MASK(X,M) (X & M)
+
+/* PER COMPLETE */
+int per_complete(ErlNifBinary *, unsigned char *, int);
+
+int per_insert_octets(int, unsigned char **, unsigned char **, int *);
+
+int per_insert_octets_except_unused(int, unsigned char **, unsigned char **,
+ int *, int);
+
+int per_insert_octets_as_bits_exact_len(int, int, unsigned char **,
+ unsigned char **, int *);
+
+int per_insert_octets_as_bits(int, unsigned char **, unsigned char **, int *);
+
+int per_pad_bits(int, unsigned char **, int *);
+
+int per_insert_least_sign_bits(int, unsigned char, unsigned char **, int *);
+
+int per_insert_most_sign_bits(int, unsigned char, unsigned char **, int *);
+
+int per_insert_bits_as_bits(int, int, unsigned char **, unsigned char **, int *);
+
+int per_insert_octets_unaligned(int, unsigned char **, unsigned char **, int);
+
+int per_realloc_memory(ErlNifBinary *, int, unsigned char **);
+
+/* BER DECODE */
+int ber_decode_begin(ErlNifEnv *, ERL_NIF_TERM *, unsigned char *, int,
+ unsigned int *);
+
+int ber_decode(ErlNifEnv *, ERL_NIF_TERM *, unsigned char *, int *, int);
+
+int ber_decode_tag(ErlNifEnv *, ERL_NIF_TERM *, unsigned char *, int, int *);
+
+int ber_decode_value(ErlNifEnv*, ERL_NIF_TERM *, unsigned char *, int *, int,
+ int);
+
+/* BER ENCODE */
+typedef struct ber_encode_mem_chunk mem_chunk_t;
+
+int ber_encode(ErlNifEnv *, ERL_NIF_TERM , mem_chunk_t **, unsigned int *);
+
+void ber_free_chunks(mem_chunk_t *chunk);
+mem_chunk_t *ber_new_chunk(unsigned int length);
+int ber_check_memory(mem_chunk_t **curr, unsigned int needed);
+
+int ber_encode_tag(ErlNifEnv *, ERL_NIF_TERM , unsigned int ,
+ mem_chunk_t **, unsigned int *);
+
+int ber_encode_length(size_t , mem_chunk_t **, unsigned int *);
+
+/*
+ *
+ * This section defines functionality for the complete encode of a
+ * PER encoded message
+ *
+ */
+
+int per_complete(ErlNifBinary *out_binary, unsigned char *in_buf,
+ int in_buf_len) {
+ int counter = in_buf_len;
+ /* counter keeps track of number of bytes left in the
+ input buffer */
+
+ int buf_space = in_buf_len;
+ /* This is the amount of allocated space left of the out_binary. It
+ is possible when padding is applied that more space is needed than
+ was originally allocated. */
+
+ int buf_size = in_buf_len;
+ /* Size of the buffer. May become reallocated and thus other than
+ in_buf_len */
+
+ unsigned char *in_ptr, *ptr;
+ /* in_ptr points at the next byte in in_buf to be moved to
+ complete_buf.
+ ptr points into the new completed buffer, complete_buf, at the
+ position of the next byte that will be set */
+ int unused = 8;
+ /* unused = [1,...,8] indicates how many of the rigthmost bits of
+ the byte that ptr points at that are unassigned */
+
+ int no_bits, no_bytes, in_unused, desired_len, ret, saved_mem, needed,
+ pad_bits;
+
+ unsigned char val;
+
+ in_ptr = in_buf;
+ ptr = out_binary->data;
+ *ptr = 0x00;
+ while (counter > 0) {
+ counter--;
+ switch (*in_ptr) {
+ case 0:
+ /* just one zero-bit should be added to the buffer */
+ if (unused == 1) {
+ unused = 8;
+ *++ptr = 0x00;
+ buf_space--;
+ } else
+ unused--;
+ break;
+
+ case 1:
+ /* one one-bit should be added to the buffer */
+ if (unused == 1) {
+ *ptr = *ptr | 1;
+ unused = 8;
+ *++ptr = 0x00;
+ buf_space--;
+ } else {
+ *ptr = *ptr | (1 << (unused - 1));
+ unused--;
+ }
+ break;
+
+ case 2:
+ /* align buffer to end of byte */
+ if (unused != 8) {
+ *++ptr = 0x00;
+ buf_space--;
+ unused = 8;
+ }
+ break;
+
+ case 10:
+ /* next byte in in_buf tells how many bits in the second next
+ byte that will be used */
+ /* The leftmost unused bits in the value byte are supposed to be
+ zero bits */
+ no_bits = (int) *(++in_ptr);
+ val = *(++in_ptr);
+ counter -= 2;
+ if ((ret = per_insert_least_sign_bits(no_bits, val, &ptr, &unused))
+ == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ buf_space -= ret;
+ break;
+
+ case 20:
+ /* in this case the next value in_ptr points at holds the number
+ of following bytes that holds the value that will be inserted
+ in the completed buffer */
+ no_bytes = (int) *(++in_ptr);
+ counter -= (no_bytes + 1);
+ if ((counter < 0)
+ || (ret = per_insert_octets(no_bytes, &in_ptr, &ptr,
+ &unused)) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ buf_space -= ret;
+ break;
+
+ case 21:
+ /* in this case the next two bytes in_ptr points at holds the number
+ of following bytes that holds the value that will be inserted
+ in the completed buffer */
+ no_bytes = (int) *(++in_ptr);
+ no_bytes = no_bytes << 8;
+ no_bytes = no_bytes | (int) *(++in_ptr);
+ counter -= (2 + no_bytes);
+ if ((counter < 0)
+ || (ret = per_insert_octets(no_bytes, &in_ptr, &ptr,
+ &unused)) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ buf_space -= ret;
+ break;
+
+ case 30:
+ /* If we call the following bytes, in the buffer in_ptr points at,
+ By1,By2,Rest then Rest is the value that will be transfered to
+ the completed buffer. By1 tells how many of the rightmost bits in
+ Rest that should not be used. By2 is the length of Rest in bytes.*/
+ in_unused = (int) *(++in_ptr);
+ no_bytes = (int) *(++in_ptr);
+ counter -= (2 + no_bytes);
+ ret = -4711;
+ if ((counter < 0)
+ || (ret = per_insert_octets_except_unused(no_bytes, &in_ptr,
+ &ptr, &unused, in_unused)) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ buf_space -= ret;
+ break;
+
+ case 31:
+ /* If we call the following bytes, in the buffer in_ptr points at,
+ By1,By2,By3,Rest then Rest is the value that will be transfered to
+ the completed buffer. By1 tells how many of the rightmost bits in
+ Rest that should not be used. By2 and By3 is the length of
+ Rest in bytes.*/
+ in_unused = (int) *(++in_ptr);
+ no_bytes = (int) *(++in_ptr);
+ no_bytes = no_bytes << 8;
+ no_bytes = no_bytes | (int) *(++in_ptr);
+ counter -= (3 + no_bytes);
+ if ((counter < 0)
+ || (ret = per_insert_octets_except_unused(no_bytes, &in_ptr,
+ &ptr, &unused, in_unused)) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ buf_space -= ret;
+ break;
+
+ case 40:
+ /* This case implies that next byte,By1,(..,By1,By2,Bin,...)
+ is the desired length of the completed value, maybe needs
+ padding zero bits or removal of trailing zero bits from Bin.
+ By2 is the length of Bin and Bin is the value that will be
+ put into the completed buffer. Each byte in Bin has the value
+ 1 or 0.*/
+ desired_len = (int) *(++in_ptr);
+ no_bytes = (int) *(++in_ptr);
+
+ /* This is the algorithm for need of memory reallocation:
+ Only when padding (cases 40 - 43,45 - 47) more memory may be
+ used than allocated. Therefore one has to keep track of how
+ much of the allocated memory that has been saved, i.e. the
+ difference between the number of parsed bytes of the input buffer
+ and the number of used bytes of the output buffer.
+ If saved memory is less than needed for the padding then we
+ need more memory. */
+ saved_mem = buf_space - counter;
+ pad_bits = desired_len - no_bytes - unused;
+ needed = (pad_bits > 0) ? CEIL(pad_bits,8) : 0;
+ if (saved_mem < needed) {
+ /* Have to allocate more memory */
+ buf_size += needed;
+ buf_space += needed;
+ if (per_realloc_memory(out_binary, buf_size, &ptr) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ }
+
+ counter -= (2 + no_bytes);
+ if ((counter < 0)
+ || (ret = per_insert_octets_as_bits_exact_len(desired_len,
+ no_bytes, &in_ptr, &ptr, &unused)) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ buf_space -= ret;
+ break;
+
+ case 41:
+ /* Same as case 40 apart from By2, the length of Bin, which is in
+ two bytes*/
+ desired_len = (int) *(++in_ptr);
+ no_bytes = (int) *(++in_ptr);
+ no_bytes = no_bytes << 8;
+ no_bytes = no_bytes | (int) *(++in_ptr);
+
+ saved_mem = buf_space - counter;
+ needed = CEIL((desired_len-unused),8) - no_bytes;
+ if (saved_mem < needed) {
+ /* Have to allocate more memory */
+ buf_size += needed;
+ buf_space += needed;
+ if (per_realloc_memory(out_binary, buf_size, &ptr) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ }
+
+ counter -= (3 + no_bytes);
+ if ((counter < 0)
+ || (ret = per_insert_octets_as_bits_exact_len(desired_len,
+ no_bytes, &in_ptr, &ptr, &unused)) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ buf_space -= ret;
+ break;
+
+ case 42:
+ /* Same as case 40 apart from By1, the desired length, which is in
+ two bytes*/
+ desired_len = (int) *(++in_ptr);
+ desired_len = desired_len << 8;
+ desired_len = desired_len | (int) *(++in_ptr);
+ no_bytes = (int) *(++in_ptr);
+
+ saved_mem = buf_space - counter;
+ needed = CEIL((desired_len-unused),8) - no_bytes;
+ if (saved_mem < needed) {
+ /* Have to allocate more memory */
+ buf_size += needed;
+ buf_space += needed;
+ if (per_realloc_memory(out_binary, buf_size, &ptr) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ }
+
+ counter -= (3 + no_bytes);
+ if ((counter < 0)
+ || (ret = per_insert_octets_as_bits_exact_len(desired_len,
+ no_bytes, &in_ptr, &ptr, &unused)) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ buf_space -= ret;
+ break;
+
+ case 43:
+ /* Same as case 40 apart from By1 and By2, the desired length and
+ the length of Bin, which are in two bytes each. */
+ desired_len = (int) *(++in_ptr);
+ desired_len = desired_len << 8;
+ desired_len = desired_len | (int) *(++in_ptr);
+ no_bytes = (int) *(++in_ptr);
+ no_bytes = no_bytes << 8;
+ no_bytes = no_bytes | (int) *(++in_ptr);
+
+ saved_mem = buf_space - counter;
+ needed = CEIL((desired_len-unused),8) - no_bytes;
+ if (saved_mem < needed) {
+ /* Have to allocate more memory */
+ buf_size += needed;
+ buf_space += needed;
+ if (per_realloc_memory(out_binary, buf_size, &ptr) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ }
+
+ counter -= (4 + no_bytes);
+ if ((counter < 0)
+ || (ret = per_insert_octets_as_bits_exact_len(desired_len,
+ no_bytes, &in_ptr, &ptr, &unused)) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ buf_space -= ret;
+ break;
+
+ case 45:
+ /* This case assumes that the following bytes in the incoming buffer
+ (called By1,By2,Bin) is By1, which is the number of bits (n) that
+ will be inserted in the completed buffer. By2 is the number of
+ bytes in Bin. Each bit in the buffer Bin should be inserted from
+ the leftmost until the nth.*/
+ desired_len = (int) *(++in_ptr);
+ no_bytes = (int) *(++in_ptr);
+
+ saved_mem = buf_space - counter;
+ needed = CEIL((desired_len-unused),8) - no_bytes;
+ if (saved_mem < needed) {
+ /* Have to allocate more memory */
+ buf_size += needed;
+ buf_space += needed;
+ if (per_realloc_memory(out_binary, buf_size, &ptr) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ }
+
+ counter -= (2 + no_bytes);
+
+ if ((counter < 0)
+ || (ret = per_insert_bits_as_bits(desired_len, no_bytes,
+ &in_ptr, &ptr, &unused)) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ buf_space -= ret;
+ break;
+
+ case 46:
+ /* Same as case 45 apart from By1, the desired length, which is
+ in two bytes. */
+ desired_len = (int) *(++in_ptr);
+ desired_len = desired_len << 8;
+ desired_len = desired_len | (int) *(++in_ptr);
+ no_bytes = (int) *(++in_ptr);
+
+ saved_mem = buf_space - counter;
+ needed = CEIL((desired_len-unused),8) - no_bytes;
+ if (saved_mem < needed) {
+ /* Have to allocate more memory */
+ buf_size += needed;
+ buf_space += needed;
+ if (per_realloc_memory(out_binary, buf_size, &ptr) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ }
+
+ counter -= (3 + no_bytes);
+ if ((counter < 0)
+ || (ret = per_insert_bits_as_bits(desired_len, no_bytes,
+ &in_ptr, &ptr, &unused)) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ buf_space -= ret;
+ break;
+
+ case 47:
+ /* Same as case 45 apart from By1 and By2, the desired length
+ and the length of Bin, which are in two bytes each. */
+ desired_len = (int) *(++in_ptr);
+ desired_len = desired_len << 8;
+ desired_len = desired_len | (int) *(++in_ptr);
+ no_bytes = (int) *(++in_ptr);
+ no_bytes = no_bytes << 8;
+ no_bytes = no_bytes | (int) *(++in_ptr);
+
+ saved_mem = buf_space - counter;
+ needed = CEIL((desired_len-unused),8) - no_bytes;
+ if (saved_mem < needed) {
+ /* Have to allocate more memory */
+ buf_size += needed;
+ buf_space += needed;
+ if (per_realloc_memory(out_binary, buf_size, &ptr) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ }
+
+ counter -= (4 + no_bytes);
+ if ((counter < 0)
+ || (ret = per_insert_bits_as_bits(desired_len, no_bytes,
+ &in_ptr, &ptr, &unused)) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ buf_space -= ret;
+ break;
+
+ default:
+ return ASN1_ERROR;
+ }
+ in_ptr++;
+ }
+ /* The returned buffer must be at least one byte and
+ it must be octet aligned */
+ if ((unused == 8) && (ptr != out_binary->data))
+ return (ptr - out_binary->data);
+ else {
+ ptr++; /* octet align buffer */
+ return (ptr - out_binary->data);
+ }
+}
+
+int per_realloc_memory(ErlNifBinary *binary, int amount, unsigned char **ptr) {
+
+ int i = *ptr - binary->data;
+
+ if (!enif_realloc_binary(binary, amount)) {
+ /*error handling due to memory allocation failure */
+ return ASN1_ERROR;
+ } else {
+ *ptr = binary->data + i;
+ }
+ return ASN1_OK;
+}
+
+int per_insert_most_sign_bits(int no_bits, unsigned char val,
+ unsigned char **output_ptr, int *unused) {
+ unsigned char *ptr = *output_ptr;
+
+ if (no_bits < *unused) {
+ *ptr = *ptr | (val >> (8 - *unused));
+ *unused -= no_bits;
+ } else if (no_bits == *unused) {
+ *ptr = *ptr | (val >> (8 - *unused));
+ *unused = 8;
+ *++ptr = 0x00;
+ } else {
+ *ptr = *ptr | (val >> (8 - *unused));
+ *++ptr = 0x00;
+ *ptr = *ptr | (val << *unused);
+ *unused = 8 - (no_bits - *unused);
+ }
+ *output_ptr = ptr;
+ return ASN1_OK;
+}
+
+int per_insert_least_sign_bits(int no_bits, unsigned char val,
+ unsigned char **output_ptr, int *unused) {
+ unsigned char *ptr = *output_ptr;
+ int ret = 0;
+
+ if (no_bits < *unused) {
+ *ptr = *ptr | (val << (*unused - no_bits));
+ *unused -= no_bits;
+ } else if (no_bits == *unused) {
+ *ptr = *ptr | val;
+ *unused = 8;
+ *++ptr = 0x00;
+ ret++;
+ } else {
+ /* first in the begun byte in the completed buffer insert
+ so many bits that fit, then insert the rest in next byte.*/
+ *ptr = *ptr | (val >> (no_bits - *unused));
+ *++ptr = 0x00;
+ ret++;
+ *ptr = *ptr | (val << (8 - (no_bits - *unused)));
+ *unused = 8 - (no_bits - *unused);
+ }
+ *output_ptr = ptr;
+ return ret;
+}
+
+/* per_pad_bits adds no_bits bits in the buffer that output_ptr
+ points at.
+ */
+int per_pad_bits(int no_bits, unsigned char **output_ptr, int *unused) {
+ unsigned char *ptr = *output_ptr;
+ int ret = 0;
+
+ while (no_bits > 0) {
+ if (*unused == 1) {
+ *unused = 8;
+ *++ptr = 0x00;
+ ret++;
+ } else
+ (*unused)--;
+ no_bits--;
+ }
+ *output_ptr = ptr;
+ return ret;
+}
+
+/* insert_bits_as_bits removes no_bytes bytes from the buffer that in_ptr
+ points at and takes the desired_no leftmost bits from those removed
+ bytes and inserts them in the buffer(output buffer) that ptr points at.
+ The unused parameter tells how many bits that are not set in the
+ actual byte in the output buffer. If desired_no is more bits than the
+ input buffer has in no_bytes bytes, then zero bits is padded.*/
+int per_insert_bits_as_bits(int desired_no, int no_bytes,
+ unsigned char **input_ptr, unsigned char **output_ptr, int *unused) {
+ unsigned char *in_ptr = *input_ptr;
+ unsigned char val;
+ int no_bits, ret, ret2;
+
+ if (desired_no == (no_bytes * 8)) {
+ if (per_insert_octets_unaligned(no_bytes, &in_ptr, output_ptr, *unused)
+ == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ ret = no_bytes;
+ } else if (desired_no < (no_bytes * 8)) {
+ /* printf("per_insert_bits_as_bits 1\n\r"); */
+ if (per_insert_octets_unaligned(desired_no / 8, &in_ptr, output_ptr,
+ *unused) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ /* printf("per_insert_bits_as_bits 2\n\r"); */
+ val = *++in_ptr;
+ /* printf("val = %d\n\r",(int)val); */
+ no_bits = desired_no % 8;
+ /* printf("no_bits = %d\n\r",no_bits); */
+ per_insert_most_sign_bits(no_bits, val, output_ptr, unused);
+ ret = CEIL(desired_no,8);
+ } else {
+ if (per_insert_octets_unaligned(no_bytes, &in_ptr, output_ptr, *unused)
+ == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ ret2 = per_pad_bits(desired_no - (no_bytes * 8), output_ptr, unused);
+ /* printf("ret2 = %d\n\r",ret2); */
+ ret = CEIL(desired_no,8);
+ /* printf("ret = %d\n\r",ret); */
+ }
+ /* printf("*unused = %d\n\r",*unused); */
+ *input_ptr = in_ptr;
+ return ret;
+}
+
+/* per_insert_octets_as_bits_exact_len */
+int per_insert_octets_as_bits_exact_len(int desired_len, int in_buff_len,
+ unsigned char **in_ptr, unsigned char **ptr, int *unused) {
+ int ret = 0;
+ int ret2 = 0;
+
+ if (desired_len == in_buff_len) {
+ if ((ret = per_insert_octets_as_bits(in_buff_len, in_ptr, ptr, unused))
+ == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ } else if (desired_len > in_buff_len) {
+ if ((ret = per_insert_octets_as_bits(in_buff_len, in_ptr, ptr, unused))
+ == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ /* now pad with zero bits */
+ /* printf("~npad_bits: called with %d bits padding~n~n~r",desired_len - in_buff_len); */
+ if ((ret2 = per_pad_bits(desired_len - in_buff_len, ptr, unused))
+ == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ } else {/* desired_len < no_bits */
+ if ((ret = per_insert_octets_as_bits(desired_len, in_ptr, ptr, unused))
+ == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ /* now remove no_bits - desired_len bytes from in buffer */
+ *in_ptr += (in_buff_len - desired_len);
+ }
+ return (ret + ret2);
+}
+
+/* insert_octets_as_bits takes no_bytes bytes from the buffer that input_ptr
+ points at and inserts the least significant bit of it in the buffer that
+ output_ptr points at. Each byte in the input buffer must be 1 or 0
+ otherwise the function returns ASN1_ERROR. The output buffer is concatenated
+ without alignment.
+ */
+int per_insert_octets_as_bits(int no_bytes, unsigned char **input_ptr,
+ unsigned char **output_ptr, int *unused) {
+ unsigned char *in_ptr = *input_ptr;
+ unsigned char *ptr = *output_ptr;
+ int used_bits = 8 - *unused;
+
+ while (no_bytes > 0) {
+ switch (*++in_ptr) {
+ case 0:
+ if (*unused == 1) {
+ *unused = 8;
+ *++ptr = 0x00;
+ } else
+ (*unused)--;
+ break;
+ case 1:
+ if (*unused == 1) {
+ *ptr = *ptr | 1;
+ *unused = 8;
+ *++ptr = 0x00;
+ } else {
+ *ptr = *ptr | (1 << (*unused - 1));
+ (*unused)--;
+ }
+ break;
+ default:
+ return ASN1_ERROR;
+ }
+ no_bytes--;
+ }
+ *input_ptr = in_ptr;
+ *output_ptr = ptr;
+ return ((used_bits + no_bytes) / 8); /*return number of new bytes
+ in completed buffer */
+}
+
+/* insert_octets inserts bytes from the input buffer, *input_ptr,
+ into the output buffer, *output_ptr. Before the first byte is
+ inserted the input buffer is aligned.
+ */
+int per_insert_octets(int no_bytes, unsigned char **input_ptr,
+ unsigned char **output_ptr, int *unused) {
+ unsigned char *in_ptr = *input_ptr;
+ unsigned char *ptr = *output_ptr;
+ int ret = 0;
+
+ if (*unused != 8) {/* must align before octets are added */
+ *++ptr = 0x00;
+ ret++;
+ *unused = 8;
+ }
+ while (no_bytes > 0) {
+ *ptr = *(++in_ptr);
+ *++ptr = 0x00;
+ /* *unused = *unused - 1; */
+ no_bytes--;
+ }
+ *input_ptr = in_ptr;
+ *output_ptr = ptr;
+ return (ret + no_bytes);
+}
+
+/* per_insert_octets_unaligned inserts bytes from the input buffer, *input_ptr,
+ into the output buffer, *output_ptr.No alignment is done.
+ */
+int per_insert_octets_unaligned(int no_bytes, unsigned char **input_ptr,
+ unsigned char **output_ptr, int unused) {
+ unsigned char *in_ptr = *input_ptr;
+ unsigned char *ptr = *output_ptr;
+ int n = no_bytes;
+ unsigned char val;
+
+ while (n > 0) {
+ if (unused == 8) {
+ *ptr = *++in_ptr;
+ *++ptr = 0x00;
+ } else {
+ val = *++in_ptr;
+ *ptr = *ptr | val >> (8 - unused);
+ *++ptr = 0x00;
+ *ptr = val << unused;
+ }
+ n--;
+ }
+ *input_ptr = in_ptr;
+ *output_ptr = ptr;
+ return no_bytes;
+}
+
+int per_insert_octets_except_unused(int no_bytes, unsigned char **input_ptr,
+ unsigned char **output_ptr, int *unused, int in_unused) {
+ unsigned char *in_ptr = *input_ptr;
+ unsigned char *ptr = *output_ptr;
+ int val, no_bits;
+ int ret = 0;
+
+ if (in_unused == 0) {
+ if ((ret = per_insert_octets_unaligned(no_bytes, &in_ptr, &ptr, *unused))
+ == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ } else {
+ if ((ret = per_insert_octets_unaligned(no_bytes - 1, &in_ptr, &ptr, *unused))
+ != ASN1_ERROR) {
+ val = (int) *(++in_ptr);
+ no_bits = 8 - in_unused;
+ /* no_bits is always less than *unused since the buffer is
+ octet aligned after insert:octets call, so the following
+ if clasuse is obsolete I think */
+ if (no_bits < *unused) {
+ *ptr = *ptr | (val >> (8 - *unused));
+ *unused = *unused - no_bits;
+ } else if (no_bits == *unused) {
+ *ptr = *ptr | (val >> (8 - *unused));
+ *++ptr = 0x00;
+ ret++;
+ *unused = 8;
+ } else {
+ *ptr = *ptr | (val >> (8 - *unused));
+ *++ptr = 0x00;
+ ret++;
+ *ptr = *ptr | (val << *unused);
+ *unused = 8 - (no_bits - *unused);
+ }
+ } else
+ return ASN1_ERROR;
+ }
+ *input_ptr = in_ptr;
+ *output_ptr = ptr;
+ return ret;
+}
+
+/*
+ *
+ * This section defines functionality for the partial decode of a
+ * BER encoded message
+ *
+ */
+
+/*
+ * int decode(ErlNifEnv* env, ERL_NIF_TERM *term, unsigned char *in_buf,
+ int in_buf_len, unsigned int *err_pos)
+ * term is a pointer to the term which is to be returned to erlang
+ * in_buf is a pointer into the buffer of incoming bytes.
+ * in_buf_len is the length of the incoming buffer.
+ * The function reads the bytes in the incoming buffer and structures
+ * it in a nested way as Erlang terms. The buffer contains data in the
+ * order tag - length - value. Tag, length and value has the following
+ * format:
+ * A tag is normally one byte but may be of any length, if the tag number
+ * is greater than 30. +----------+
+ * |CL|C|NNNNN|
+ * +----------+
+ * If NNNNN is 31 then will the 7 l.s.b of each of the following tag number
+ * bytes contain the tag number. Each tag number byte that is not the last one
+ * has the m.s.b. set to 1.
+ * The length can be short definite length (sdl), long definite length (ldl)
+ * or indefinite length (il).
+ * sdl: +---------+ the L bits is the length
+ * |0|LLLLLLL|
+ * +---------+
+ * ldl: +---------+ +---------+ +---------+ +-----------+
+ * |1|lllllll| |first len| | | |the Nth len|
+ * +---------+ +---------+ +---------+ ... +-----------+
+ * The first byte tells how many len octets will follow, max 127
+ * il: +---------+ +----------------------+ +--------+ +--------+
+ * |1|0000000| |content octets (Value)| |00000000| |00000000|
+ * +---------+ +----------------------+ +--------+ +--------+
+ * The value octets are preceded by one octet and followed by two
+ * exactly as above. The value must be some tag-length-value encoding.
+ *
+ * The function returns a value in Erlang nif term format:
+ * {{TagNo,Value},Rest}
+ * TagNo is an integer ((CL bsl 16) + tag number) which limits the tag number
+ * to 65535.
+ * Value is a binary if the C bit in tag was unset, otherwise (if tag was
+ * constructed) Value is a list, List.
+ * List is like: [{TagNo,Value},{TagNo,Value},...]
+ * Rest is a binary, i.e. the undecoded part of the buffer. Most often Rest
+ * is the empty binary.
+ * If some error occured during the decoding of the in_buf an error is returned.
+ */
+int ber_decode_begin(ErlNifEnv* env, ERL_NIF_TERM *term, unsigned char *in_buf,
+ int in_buf_len, unsigned int *err_pos) {
+ int maybe_ret;
+ int ib_index = 0;
+ unsigned char *rest_data;
+ ERL_NIF_TERM decoded_term, rest;
+
+ if ((maybe_ret = ber_decode(env, &decoded_term, in_buf, &ib_index,
+ in_buf_len)) <= ASN1_ERROR)
+ {
+ *err_pos = ib_index;
+ return maybe_ret;
+ };
+
+ // The remaining binary after one ASN1 segment has been decoded
+ if ((rest_data = enif_make_new_binary(env, in_buf_len - ib_index, &rest))
+ == NULL) {
+ *term = enif_make_atom(env, "could_not_alloc_binary");
+ return ASN1_ERROR;
+ }
+
+ *term = enif_make_tuple2(env, decoded_term, rest);
+ return ASN1_OK;
+}
+
+int ber_decode(ErlNifEnv* env, ERL_NIF_TERM *term, unsigned char *in_buf,
+ int *ib_index, int in_buf_len) {
+ int maybe_ret;
+ int form;
+ ERL_NIF_TERM tag, value;
+
+ /*buffer must hold at least two bytes*/
+ if ((*ib_index + 2) > in_buf_len)
+ return ASN1_VALUE_ERROR;
+ /* "{{TagNo," */
+ if ((form = ber_decode_tag(env, &tag, in_buf, in_buf_len, ib_index))
+ <= ASN1_ERROR
+ )
+ return form; /* 5 bytes */
+ if (*ib_index >= in_buf_len) {
+ return ASN1_TAG_ERROR;
+ }
+ /* buffer must hold at least one byte (0 as length and nothing as
+ value) */
+ /* "{{TagNo,Value}," */
+ if ((maybe_ret = ber_decode_value(env, &value, in_buf, ib_index, form,
+ in_buf_len)) <= ASN1_ERROR
+ )
+ return maybe_ret; /* at least 5 bytes */
+ *term = enif_make_tuple2(env, tag, value);
+ return ASN1_OK;
+}
+
+/*
+ * decode_tag decodes the BER encoded tag in in_buf and creates an
+ * nif term tag
+ */
+int ber_decode_tag(ErlNifEnv* env, ERL_NIF_TERM *tag, unsigned char *in_buf,
+ int in_buf_len, int *ib_index) {
+ int tag_no, tmp_tag, form;
+
+ /* first get the class of tag and bit shift left 16*/
+ tag_no = ((MASK(in_buf[*ib_index],ASN1_CLASS)) << 10);
+
+ form = (MASK(in_buf[*ib_index],ASN1_FORM));
+
+ /* then get the tag number */
+ if ((tmp_tag = (int) INVMASK(in_buf[*ib_index],ASN1_CLASSFORM)) < 31) {
+ *tag = enif_make_uint(env, tag_no + tmp_tag);
+ (*ib_index)++;
+ } else {
+ int n = 0; /* n is used to check that the 64K limit is not
+ exceeded*/
+
+ /* should check that at least three bytes are left in
+ in-buffer,at least two tag byte and at least one length byte */
+ if ((*ib_index + 3) > in_buf_len)
+ return ASN1_VALUE_ERROR;
+ (*ib_index)++;
+ /* The tag is in the following bytes in in_buf as
+ 1ttttttt 1ttttttt ... 0ttttttt, where the t-bits
+ is the tag number*/
+ /* In practice is the tag size limited to 64K, i.e. 16 bits. If
+ the tag is greater then 64K return an error */
+ while (((tmp_tag = (int) in_buf[*ib_index]) >= 128) && n < 2) {
+ /* m.s.b. = 1 */
+ tag_no = tag_no + (MASK(tmp_tag,ASN1_LONG_TAG) << 7);
+ (*ib_index)++;
+ n++;
+ };
+ if ((n == 2) && in_buf[*ib_index] > 3)
+ return ASN1_TAG_ERROR; /* tag number > 64K */
+ tag_no = tag_no + in_buf[*ib_index];
+ (*ib_index)++;
+ *tag = enif_make_uint(env, tag_no);
+ }
+ return form;
+}
+
+/*
+ * ber_decode_value decodes the BER encoded length and value fields in the
+ * in_buf and puts the value part in the decode_buf as an Erlang
+ * nif term into value
+ */
+int ber_decode_value(ErlNifEnv* env, ERL_NIF_TERM *value, unsigned char *in_buf,
+ int *ib_index, int form, int in_buf_len) {
+ int maybe_ret;
+ unsigned int len = 0;
+ unsigned int lenoflen = 0;
+ int indef = 0;
+ unsigned char *tmp_out_buff;
+ ERL_NIF_TERM term = 0, curr_head = 0;
+
+ if (((in_buf[*ib_index]) & 0x80) == ASN1_SHORT_DEFINITE_LENGTH) {
+ len = in_buf[*ib_index];
+ } else if (in_buf[*ib_index] == ASN1_INDEFINITE_LENGTH
+ )
+ indef = 1;
+ else /* long definite length */{
+ lenoflen = (in_buf[*ib_index] & 0x7f); /*length of length */
+ if (lenoflen > (in_buf_len - (*ib_index + 1)))
+ return ASN1_LEN_ERROR;
+ len = 0;
+ while (lenoflen--) {
+ (*ib_index)++;
+ if (!(len < (1 << (sizeof(len) - 1) * 8)))
+ return ASN1_LEN_ERROR; /* length does not fit in 32 bits */
+ len = (len << 8) + in_buf[*ib_index];
+ }
+ }
+ if (len > (in_buf_len - (*ib_index + 1)))
+ return ASN1_VALUE_ERROR;
+ (*ib_index)++;
+ if (indef == 1) { /* in this case it is desireably to check that indefinite length
+ end bytes exist in inbuffer */
+ curr_head = enif_make_list(env, 0);
+ while (!(in_buf[*ib_index] == 0 && in_buf[*ib_index + 1] == 0)) {
+ if (*ib_index >= in_buf_len)
+ return ASN1_INDEF_LEN_ERROR;
+
+ if ((maybe_ret = ber_decode(env, &term, in_buf, ib_index, in_buf_len))
+ <= ASN1_ERROR
+ )
+ return maybe_ret;
+ curr_head = enif_make_list_cell(env, term, curr_head);
+ }
+ enif_make_reverse_list(env, curr_head, value);
+ (*ib_index) += 2; /* skip the indefinite length end bytes */
+ } else if (form == ASN1_CONSTRUCTED)
+ {
+ int end_index = *ib_index + len;
+ if (end_index > in_buf_len)
+ return ASN1_LEN_ERROR;
+ curr_head = enif_make_list(env, 0);
+ while (*ib_index < end_index) {
+
+ if ((maybe_ret = ber_decode(env, &term, in_buf, ib_index,
+ in_buf_len)) <= ASN1_ERROR
+ )
+ return maybe_ret;
+ curr_head = enif_make_list_cell(env, term, curr_head);
+ }
+ enif_make_reverse_list(env, curr_head, value);
+ } else {
+ if ((*ib_index + len) > in_buf_len)
+ return ASN1_LEN_ERROR;
+ tmp_out_buff = enif_make_new_binary(env, len, value);
+ memcpy(tmp_out_buff, in_buf + *ib_index, len);
+ *ib_index = *ib_index + len;
+ }
+ return ASN1_OK;
+}
+
+struct ber_encode_mem_chunk {
+ mem_chunk_t *next;
+ int length;
+ char *top;
+ char *curr;
+};
+
+int ber_encode(ErlNifEnv *env, ERL_NIF_TERM term, mem_chunk_t **curr, unsigned int *count) {
+
+ const ERL_NIF_TERM *tv;
+ unsigned int form;
+ int arity;
+
+ if (!enif_get_tuple(env, term, &arity, &tv))
+ return ASN1_ERROR;
+
+ form = enif_is_list(env, tv[1]) ? ASN1_CONSTRUCTED : ASN1_PRIMITIVE;
+
+ switch (form) {
+ case ASN1_PRIMITIVE: {
+ ErlNifBinary value;
+ if (!enif_inspect_binary(env, tv[1], &value))
+ return ASN1_ERROR;
+
+ if (ber_check_memory(curr, value.size))
+ return ASN1_ERROR;
+ memcpy((*curr)->curr - value.size + 1, value.data, value.size);
+ (*curr)->curr -= value.size;
+ *count += value.size;
+
+ if (ber_encode_length(value.size, curr, count))
+ return ASN1_ERROR;
+
+ break;
+ }
+ case ASN1_CONSTRUCTED: {
+ ERL_NIF_TERM head, tail;
+ unsigned int tmp_cnt;
+
+ if(!enif_make_reverse_list(env, tv[1], &head))
+ return ASN1_ERROR;
+
+ if (!enif_get_list_cell(env, head, &head, &tail)) {
+ if (enif_is_empty_list(env, tv[1])) {
+ *((*curr)->curr) = 0;
+ (*curr)->curr -= 1;
+ (*count)++;
+ break;
+ } else
+ return ASN1_ERROR;
+ }
+
+ do {
+ tmp_cnt = 0;
+ if (ber_encode(env, head, curr, &tmp_cnt)) {
+ return ASN1_ERROR;
+ }
+ *count += tmp_cnt;
+ } while (enif_get_list_cell(env, tail, &head, &tail));
+
+ if (ber_check_memory(curr, *count)) {
+ return ASN1_ERROR;
+ }
+
+ if (ber_encode_length(*count, curr, count)) {
+ return ASN1_ERROR;
+ }
+
+ break;
+ }
+ }
+
+ // We need atleast 5 bytes to encode the next tlv
+ if (ber_check_memory(curr, 3))
+ return ASN1_ERROR;
+
+ if (ber_encode_tag(env, tv[0], form, curr, count))
+ return ASN1_ERROR;
+
+ return ASN1_OK;
+}
+
+int ber_encode_tag(ErlNifEnv *env, ERL_NIF_TERM tag, unsigned int form,
+ mem_chunk_t **curr, unsigned int *count) {
+ unsigned int class_tag_no, head_tag;
+ if (!enif_get_uint(env, tag, &class_tag_no))
+ return ASN1_ERROR;
+
+ head_tag = form | ((class_tag_no & 0x30000) >> 10);
+ class_tag_no = class_tag_no & 0xFFFF;
+
+ if (class_tag_no <= 30) {
+ *(*curr)->curr = head_tag | class_tag_no;
+ (*curr)->curr -= 1;
+ (*count)++;
+ return ASN1_OK;
+ } else {
+ *(*curr)->curr = class_tag_no & 127;
+ class_tag_no = class_tag_no >> 7;
+ (*curr)->curr -= 1;
+ (*count)++;
+
+ while (class_tag_no > 0) {
+ *(*curr)->curr = (class_tag_no & 127) | 0x80;
+ class_tag_no >>= 7;
+ (*curr)->curr -= 1;
+ (*count)++;
+ }
+
+ *(*curr)->curr = head_tag | 0x1F;
+ (*curr)->curr -= 1;
+ (*count)++;
+
+ return ASN1_OK;
+ }
+}
+
+int ber_encode_length(size_t size, mem_chunk_t **curr, unsigned int *count) {
+ if (size < 128) {
+ if (ber_check_memory(curr, 1u))
+ return ASN1_ERROR;
+ *(*curr)->curr = size;
+ (*curr)->curr -= 1;
+ (*count)++;
+ } else {
+ int chunks = size / 256 + 1;
+ if (ber_check_memory(curr, chunks + 1))
+ return ASN1_ERROR;
+
+ while (size > 0)
+ {
+ *(*curr)->curr = size & 0xFF;
+ size >>= 8;
+ (*curr)->curr -= 1;
+ (*count)++;
+ }
+
+ *(*curr)->curr = chunks | 0x80;
+ (*curr)->curr -= 1;
+ (*count)++;
+ }
+ return ASN1_OK;
+}
+
+mem_chunk_t *ber_new_chunk(unsigned int length) {
+ mem_chunk_t *new = enif_alloc(sizeof(mem_chunk_t));
+ if (new == NULL)
+ return NULL;
+ new->next = NULL;
+ new->top = enif_alloc(sizeof(char) * length);
+ if (new->top == NULL) {
+ free(new);
+ return NULL;
+ }
+ new->curr = new->top + length - 1;
+ new->length = length;
+ return new;
+}
+
+void ber_free_chunks(mem_chunk_t *chunk) {
+ mem_chunk_t *curr, *next = chunk;
+ while (next != NULL) {
+ curr = next;
+ next = curr->next;
+ enif_free(curr->top);
+ enif_free(curr);
+ }
+}
+
+int ber_check_memory(mem_chunk_t **curr, unsigned int needed) {
+ mem_chunk_t *new;
+ if ((*curr)->curr-needed >= (*curr)->top)
+ return ASN1_OK;
+
+ if ((new = ber_new_chunk((*curr)->length > needed ? (*curr)->length * 2 : (*curr)->length + needed)) == NULL)
+ return ASN1_ERROR;
+ new->next = *curr;
+ *curr = new;
+ return ASN1_OK;
+}
+
+static ERL_NIF_TERM encode_per_complete(ErlNifEnv* env, int argc,
+ const ERL_NIF_TERM argv[]) {
+ ERL_NIF_TERM err_code;
+ ErlNifBinary in_binary;
+ ErlNifBinary out_binary;
+ int complete_len;
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &in_binary))
+ return enif_make_atom(env, "badarg");
+
+ if (!enif_alloc_binary(in_binary.size, &out_binary))
+ return enif_make_atom(env, "alloc_binary_failed");
+
+ if (in_binary.size == 0)
+ return enif_make_binary(env, &out_binary);
+
+ if ((complete_len = per_complete(&out_binary, in_binary.data,
+ in_binary.size)) <= ASN1_ERROR) {
+ enif_release_binary(&out_binary);
+ if (complete_len == ASN1_ERROR
+ )
+ err_code = enif_make_uint(env, '1');
+ else
+ err_code = enif_make_uint(env, 0);
+ return enif_make_tuple2(env, enif_make_atom(env, "error"), err_code);
+ }
+ if (complete_len < out_binary.size)
+ enif_realloc_binary(&out_binary, complete_len);
+
+ return enif_make_binary(env, &out_binary);
+}
+
+static ERL_NIF_TERM decode_ber_tlv(ErlNifEnv* env, int argc,
+ const ERL_NIF_TERM argv[]) {
+ ErlNifBinary in_binary;
+ ERL_NIF_TERM return_term;
+ unsigned int err_pos = 0, return_code;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &in_binary))
+ return enif_make_badarg(env);
+
+ if ((return_code = ber_decode_begin(env, &return_term, in_binary.data,
+ in_binary.size, &err_pos)) != ASN1_OK
+ )
+ return enif_make_tuple2(env, enif_make_atom(env,"error"), enif_make_tuple2(env,
+ enif_make_int(env, return_code),enif_make_int(env, err_pos)));
+ return return_term;
+}
+
+static ERL_NIF_TERM encode_ber_tlv(ErlNifEnv* env, int argc,
+ const ERL_NIF_TERM argv[]) {
+ ErlNifBinary out_binary;
+ unsigned int length = 0, pos = 0;
+ int encode_err;
+ mem_chunk_t *curr, *top;
+ ERL_NIF_TERM err_code;
+
+ curr = ber_new_chunk(40);
+
+ if ((encode_err = ber_encode(env, argv[0], &curr, &length))
+ <= ASN1_ERROR) {
+ ber_free_chunks(curr);
+ err_code = enif_make_int(env, encode_err);
+ return enif_make_tuple2(env, enif_make_atom(env, "error"), err_code);
+ }
+
+ if (!enif_alloc_binary(length, &out_binary)) {
+ ber_free_chunks(curr);
+ return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_atom(env,"oom"));
+ }
+
+ top = curr;
+
+ while (curr != NULL) {
+ length = curr->length - (curr->curr-curr->top) -1;
+ if (length > 0)
+ memcpy(out_binary.data + pos, curr->curr+1, length);
+ pos += length;
+ curr = curr->next;
+ }
+
+ ber_free_chunks(top);
+
+ return enif_make_binary(env, &out_binary);
+}
+
+static int is_ok_load_info(ErlNifEnv* env, ERL_NIF_TERM load_info) {
+ int i;
+ return enif_get_int(env, load_info, &i) && i == 1;
+}
+
+static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) {
+ if (!is_ok_load_info(env, load_info))
+ return -1;
+ return 0;
+}
+
+static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data,
+ ERL_NIF_TERM load_info) {
+ if (!is_ok_load_info(env, load_info))
+ return -1;
+ return 0;
+}
+
+static void unload(ErlNifEnv* env, void* priv_data) {
+
+}
+
+static ErlNifFunc nif_funcs[] = { { "encode_per_complete", 1,
+ encode_per_complete }, { "decode_ber_tlv", 1, decode_ber_tlv }, {
+ "encode_ber_tlv", 1, encode_ber_tlv } };
+
+ERL_NIF_INIT(asn1rt_nif, nif_funcs, load, NULL, upgrade, unload)
diff --git a/lib/asn1/doc/src/Makefile b/lib/asn1/doc/src/Makefile
index d29225f6c9..566173837c 100644
--- a/lib/asn1/doc/src/Makefile
+++ b/lib/asn1/doc/src/Makefile
@@ -27,15 +27,6 @@ include ../../vsn.mk
VSN=$(ASN1_VSN)
APPLICATION=asn1
-
-# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
@@ -86,34 +77,10 @@ EXTRA_FILES = \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex) \
- $(BOOK_FILES:%.xml=%.sgml) part.tex
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -126,8 +93,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -142,32 +107,6 @@ clean clean_docs:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f $(GEN_XML) errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES)
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ $(LATEX_CLEAN)
-
-endif
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -179,8 +118,6 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
$(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
$(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
@@ -191,31 +128,4 @@ release_docs_spec: docs
$(INSTALL_DIR) $(RELEASE_PATH)/man/man3
$(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(HTML_APPHISTORY) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-endif
-endif
-
-endif
-
release_spec:
-
-
-
diff --git a/lib/asn1/doc/src/asn1_spec.xmlsrc b/lib/asn1/doc/src/asn1_spec.xmlsrc
index 8d61834da8..07cba17816 100644
--- a/lib/asn1/doc/src/asn1_spec.xmlsrc
+++ b/lib/asn1/doc/src/asn1_spec.xmlsrc
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2009</year>
+ <year>2003</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -43,7 +43,7 @@
<p>So far this functionality is only provided when using the
optimized BER_BIN version, that is when compiling with the
options <c>ber_bin</c> and <c>optimize</c>. It does also work
- using the <c>driver</c> option. We have no intent to make this
+ using the <c>nif</c> option. We have no intent to make this
available on the default BER version, but maybe in the PER_BIN
version (<c>per_bin</c>).
</p>
@@ -661,7 +661,9 @@ ValAction = {'Action',17,{'Button',4711,false}}.
<p>The ASN.1 specs in the test are compiled with the options
<c>ber_bin, optimize, driver</c> and <c>asn1config</c>. If the
<c>driver</c> option had been omitted there should have been
- higher values for <c>decode</c> and <c>decode_part</c>.
+ higher values for <c>decode</c> and <c>decode_part</c>. These tests have
+ not been re-run using nifs, but are expected to perform about 5% better
+ than the linked-in driver.
</p>
<p>The test program runs 10000 decodes on the value, resulting
in a printout with the elapsed time in microseconds for the
diff --git a/lib/asn1/doc/src/asn1_ug.xml b/lib/asn1/doc/src/asn1_ug.xml
index 12d986308f..1b399fb641 100644
--- a/lib/asn1/doc/src/asn1_ug.xml
+++ b/lib/asn1/doc/src/asn1_ug.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2010</year>
+ <year>1997</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -347,7 +347,7 @@ erlc -o ../asnfiles -I ../asnfiles -I /usr/local/standards/asn1 Person.asn
<p>This flag has effect only when used together with one of
<c>per_bin</c> or <c>ber_bin</c> flags. It gives time optimized
code in the generated modules and it uses another runtime module.
- In the <c>per_bin</c> case a linked-in driver is used. The
+ In the <c>per_bin</c> case a nif is used. The
result from an encode is a binary.</p>
<p><em>When this flag is used you cannot use the old format</em><c>{TypeName,Value}</c> when you encode values. Since it is
an unnecessary construct it has been removed in favor of
@@ -362,9 +362,14 @@ erlc -o ../asnfiles -I ../asnfiles -I /usr/local/standards/asn1 Person.asn
</item>
<tag><c>+driver</c></tag>
<item>
- <p>Together with the flags <c>ber_bin</c> and <c>optimize</c>
- you choose to use a linked in driver for considerable faster
- decode.</p>
+ <p>As of R15B this means the same as the <c>nif</c> option. Kept for
+ backwards compatability reasons.</p>
+ </item>
+ <tag><c>+nif</c></tag>
+ <item>
+ <p>Together with the flags <c>ber_bin</c>
+ and <c>optimize</c> you choose to use a nif for considerable
+ faster encode and decode. </p>
</item>
<tag><c>+asn1config</c></tag>
<item>
@@ -492,7 +497,7 @@ asn1ct:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre>
</row>
<row>
<cell align="left" valign="middle">BER</cell>
- <cell align="left" valign="middle"><em>[ber_bin, optimize, driver]</em></cell>
+ <cell align="left" valign="middle"><em>[ber_bin, optimize, nif]</em></cell>
<cell align="left" valign="middle">EAVF</cell>
<cell align="left" valign="middle">iolist</cell>
<cell align="left" valign="middle">iolist / binary</cell>
@@ -557,7 +562,7 @@ asn1ct:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre>
</row>
<row>
<cell align="left" valign="middle">DER</cell>
- <cell align="left" valign="middle"><em>[ber_bin, optimize, driver, der]</em></cell>
+ <cell align="left" valign="middle"><em>[ber_bin, optimize, nif, der]</em></cell>
<cell align="left" valign="middle">EAVF</cell>
<cell align="left" valign="middle">iolist</cell>
<cell align="left" valign="middle">binary</cell>
@@ -626,23 +631,24 @@ asn1ct:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre>
</table>
<p>
- The sole compile options <c>ber</c>, <c>ber_bin</c> and <c>per</c>
- are kept for backwards compatibility and should not be used in
- new code.
+ The compile options <c>ber</c>, <c>per</c> and
+ <c>driver</c> are kept for backwards compatibility and should not be
+ used in new code. The nif implementation which replaces the linked-in
+ driver has been shown to be about 5-15% faster.
</p>
<p>
You are strongly recommended to use the appropriate alternative
of the bold typed options. The <c>optimize</c> and
- <c>driver</c> options does not affect the encode or decode
+ <c>nif</c> options does not affect the encode or decode
result, just the time spent in run-time. When <c>ber_bin</c> and
- <c>driver</c> or <c>per_bin, optimize</c> and <c>driver</c> is
- combined the C-code driver is used in chosen parts of encode /
+ <c>nif</c> or <c>per_bin</c> and <c>optimize</c> is
+ combined the C-code nif is used in chosen parts of encode /
decode procedure.
</p>
<table>
<row>
<cell align="left" valign="middle"><em>Compile options, allowed combinations</em></cell>
- <cell align="left" valign="middle"><em>use of linked-in driver</em></cell>
+ <cell align="left" valign="middle"><em>use of nif</em></cell>
</row>
<row>
<cell align="left" valign="middle">[ber]</cell>
@@ -657,7 +663,7 @@ asn1ct:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre>
<cell align="left" valign="middle">no</cell>
</row>
<row>
- <cell align="left" valign="middle"><em>[ber_bin, optimize, driver]</em></cell>
+ <cell align="left" valign="middle"><em>[ber_bin, optimize, nif]</em></cell>
<cell align="left" valign="middle">yes</cell>
</row>
<row>
@@ -690,12 +696,12 @@ asn1ct:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre>
<cell align="left" valign="middle">no</cell>
</row>
<row>
- <cell align="left" valign="middle"><em>[ber_bin, optimize, driver, der]</em></cell>
+ <cell align="left" valign="middle"><em>[ber_bin, optimize, nif, der]</em></cell>
<cell align="left" valign="middle">yes</cell>
</row>
- <tcaption>When the ASN1 linked-in driver is used.</tcaption>
+ <tcaption>When the ASN1 nif is used.</tcaption>
</table>
</section>
@@ -712,14 +718,14 @@ asn1rt:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre>
<pre>
'H323-MESSAGES':encode('SomeChoiceType',{call,"octetstring"}).
'H323-MESSAGES':decode('SomeChoiceType',Bytes). </pre>
- <p>The asn1 linked-in driver is enabled in two occasions: encoding of
+ <p>The asn1 nif is enabled in two occasions: encoding of
asn1 values when the asn1 spec is compiled with <c>per_bin</c> and
<c>optimize</c> or decode of encoded asn1 values when the asn1 spec is
- compiled with <c>ber_bin</c>, <c>optimize</c> and <c>driver</c>. In
- those cases the driver will be loaded automatically at the first call
+ compiled with <c>ber_bin</c>, <c>optimize</c> and <c>nif</c>. In
+ those cases the nif will be loaded automatically at the first call
to <c>encode</c>/<c>decode</c>. If one doesn't want the performance
- overhead of the driver being loaded at the first call it is possible
- to load the driver separately by <c>asn1rt:load_driver()</c>. </p>
+ overhead of the nif being loaded at the first call it is possible
+ to load the nif separately by loading the <c>asn1rt_nif</c> module.</p>
<p>By invoking the function <c>info/0</c> in a generated module, one
gets information about which compiler options were used.</p>
</section>
diff --git a/lib/asn1/doc/src/asn1ct.xml b/lib/asn1/doc/src/asn1ct.xml
index 265f8735c2..0b9ec3df7f 100644
--- a/lib/asn1/doc/src/asn1ct.xml
+++ b/lib/asn1/doc/src/asn1ct.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2010</year>
+ <year>1997</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -52,8 +52,8 @@
<v>Options = [Option| OldOption]</v>
<v>Option = ber_bin | per_bin | uper_bin | der | compact_bit_string |
noobj | {n2n,EnumTypeName} |{outdir,Dir} | {i,IncludeDir} | optimize |
- driver | asn1config | undec_rest | {inline,OutputName} | inline |
- {macro_name_prefix, Prefix} | {record_name_prefix, Prefix} | verbose</v>
+ nif | asn1config | undec_rest | {inline,OutputName} | inline |
+ {macro_name_prefix, Prefix} | {record_name_prefix, Prefix} | verbose | warnings_as_errors</v>
<v>OldOption = ber | per</v>
<v>Reason = term()</v>
<v>Prefix = string()</v>
@@ -212,16 +212,21 @@ Binary = binary()
<c>per_bin</c>
or <c>ber_bin</c> option. It gives time optimized code
generated and it uses another runtime module and
- in the <c>per_bin</c> case a linked-in driver. The result
+ in the <c>per_bin</c> case a nif. The result
in the <c>per_bin</c> case from an encode when compiled
with this option will be a binary.</p>
</item>
<tag><c>driver</c></tag>
<item>
+ <p>As of R15B this means the same as the <c>nif</c> option. Kept for
+ backwards compatability reasons.</p>
+ </item>
+ <tag><c>nif</c></tag>
+ <item>
<p>Option valid together with <c>ber_bin</c> and <c>optimize</c>
- options. It enables the use of a linked-in driver that gives
- considerable faster decode. In <c>ber_bin</c> the driver is
- enabled only by explicit use of the option <c>driver</c>.</p>
+ options. It enables the use of several nifs that gives faster
+ encode and decode. Nifs are only enabled by the explicit use of
+ the option <c>nif</c></p>
</item>
<tag><c>asn1config</c></tag>
<item>
@@ -264,7 +269,11 @@ Binary = binary()
<c>.set.asn</c> are exported, unless a
<c>{export,[atom()]}</c> or <c>{export_all,true}</c> option
are provided. The list of atoms are names of chosen asn1
- specs from the <c>.set.asn</c> file.</p>
+ specs from the <c>.set.asn</c> file. </p>
+ <p>When used together with <c>nif</c> for <c>ber_bin</c>, the
+ asn1 nifs will be used if the <c>asn1rt_nif</c> module is
+ available. If it is not available, a slower erlang fallback
+ will be used.</p>
</item>
<tag><c>inline</c></tag>
<item>
@@ -289,6 +298,10 @@ Binary = binary()
<p>Causes more verbose information from the compiler
describing what it is doing.</p>
</item>
+ <tag><c>warnings_as_errors</c></tag>
+ <item>
+ <p>Causes warnings to be treated as errors.</p>
+ </item>
</taglist>
<p>Any additional option that is applied will be passed to
the final step when the generated .erl file is compiled.
@@ -343,18 +356,6 @@ Binary = binary()
</desc>
</func>
<func>
- <name>validate(Module,Type,Value) -> ok | {error,Reason}</name>
- <fsummary>Validate an ASN.1 value.</fsummary>
- <type>
- <v>Module = Type = atom()</v>
- <v>Value = term()</v>
- </type>
- <desc>
- <p>Validates that <c>Value</c> conforms to <c>Type</c>
- from <c>Module</c>. <em>Not implemented in this version of the ASN.1 application.</em></p>
- </desc>
- </func>
- <func>
<name>value(Module ,Type) -> {ok,Value} | {error,Reason}</name>
<fsummary>Create an ASN.1 value for test purposes.</fsummary>
<type>
diff --git a/lib/asn1/doc/src/asn1rt.xml b/lib/asn1/doc/src/asn1rt.xml
index 1217a07e9b..0c3c257189 100644
--- a/lib/asn1/doc/src/asn1rt.xml
+++ b/lib/asn1/doc/src/asn1rt.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2009</year>
+ <year>1997</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -42,36 +42,6 @@
<funcs>
<func>
- <name>start() -> ok |{error,Reason}</name>
- <fsummary>Starts the asn1 server.</fsummary>
- <type>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Starts the asn1 server that loads the drivers.</p>
- <p>The server schedules a driver that is not blocked by
- another caller. The driver is used by the asn1 application if
- specs are compiled with options <c>[per_bin, optimize]</c> or
- <c>[ber_bin, optimize, driver]</c>. The server will be started
- automatically at encode/decode if it isn't done explicitly. If
- encode/decode with driver is used in test or industrial code
- it is a performance gain to start it explicitly to avoid the
- one time load in run-time.</p>
- </desc>
- </func>
-
- <func>
- <name>stop() -> ok |{error,Reason}</name>
- <fsummary>Stops the asn1 server.</fsummary>
- <type>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Stops the asn1 server and unloads the drivers.</p>
- </desc>
- </func>
-
- <func>
<name>decode(Module,Type,Bytes) -> {ok,Value}|{error,Reason}</name>
<fsummary>Decode from bytes into an ASN.1 value.</fsummary>
<type>
@@ -126,35 +96,23 @@
<func>
<name>load_driver() -> ok | {error,Reason}</name>
- <fsummary>Loads the linked-in driver.</fsummary>
+ <fsummary>Loads the linked-in driver. (deprecated)</fsummary>
<type>
<v>Reason = term()</v>
</type>
<desc>
- <p>This function loads the linked-in driver before the first call
- to encode. If this function is not called the driver will be loaded
- automatically at the first call to encode. If one doesn't want the
- performance cost of a driver load when the application is running,
- this function makes it possible to load the driver in an
- initialization.</p>
- <p>The driver is only used when encoding/decoding ASN.1 files that
- were compiled with the options <c>per_bin</c> and <c>optimize</c>.</p>
+ <p>This function is obsolete and will be removed in R16A</p>
</desc>
</func>
<func>
<name>unload_driver() -> ok | {error,Reason}</name>
- <fsummary>Unloads the linked-in driver.</fsummary>
+ <fsummary>Unloads the linked-in driver. (deprecated)</fsummary>
<type>
<v>Reason = term()</v>
</type>
<desc>
- <p>This function unloads the linked-in driver.
- When the driver has been loaded it remains in the environment until
- it is unloaded. Normally the driver should remain loaded, it is
- crucial for the performance of ASN.1 encoding. </p>
- <p>The driver is only used when ASN.1 modules have been compiled
- with the flags <c>per_bin</c> and <c>optimize</c>.</p>
+ <p>This function is obsolete and will be removed in R16A</p>
</desc>
</func>
@@ -188,19 +146,6 @@
value, to a UTF8 encoded binary.</p>
</desc>
</func>
-
- <func>
- <name>validate(Module,Type,Value) -> ok | {error,Reason}</name>
- <fsummary>Validate an ASN.1 value.</fsummary>
- <type>
- <v>Module = Type = atom()</v>
- <v>Value = term()</v>
- </type>
- <desc>
- <p>Validates that <c>Value</c> conforms to <c>Type</c>
- from <c>Module</c>. <em>Not implemented in this version of the ASN.1 application.</em></p>
- </desc>
- </func>
</funcs>
diff --git a/lib/asn1/doc/src/make.dep b/lib/asn1/doc/src/make.dep
deleted file mode 100644
index eb2c0e9a98..0000000000
--- a/lib/asn1/doc/src/make.dep
+++ /dev/null
@@ -1,31 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/gandalf/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: asn1_spec.tex asn1_ug.tex asn1ct.tex asn1rt.tex \
- book.tex part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-asn1_spec.tex: Seq.asn Seq.asn1config
-
-book.tex: part.xml ref_man.xml
-
-asn1_ug.tex: ../../../../system/doc/definitions/cite.defs
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: exclusive_Win_But.ps selective_TypeList.ps \
- selective_Window2.ps
-
diff --git a/lib/asn1/doc/src/notes.xml b/lib/asn1/doc/src/notes.xml
index 5e221c03e9..52d770c9f6 100644
--- a/lib/asn1/doc/src/notes.xml
+++ b/lib/asn1/doc/src/notes.xml
@@ -31,6 +31,25 @@
<p>This document describes the changes made to the asn1 application.</p>
+<section><title>Asn1 1.6.18</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Implement or fix -Werror option</p>
+ <p>
+ If -Werror is enabled and there are warnings no output
+ file is written. Also make sure that error/warning
+ reporting is consistent. (Thanks to Tuncer Ayaz)</p>
+ <p>
+ Own Id: OTP-9536</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Asn1 1.6.17</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/asn1/src/Makefile b/lib/asn1/src/Makefile
index 2733cde3f8..3a59773d93 100644
--- a/lib/asn1/src/Makefile
+++ b/lib/asn1/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2009. All Rights Reserved.
+# Copyright Ericsson AB 1997-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -68,7 +68,7 @@ RT_MODULES= \
asn1rt_per_bin_rt2ct \
asn1rt_uper_bin \
asn1rt_check \
- asn1rt_driver_handler
+ asn1rt_nif
# asn1_sup \
# asn1_app \
# asn1_server
diff --git a/lib/asn1/src/asn1.app.src b/lib/asn1/src/asn1.app.src
index abacb0a1e9..09144ba2f7 100644
--- a/lib/asn1/src/asn1.app.src
+++ b/lib/asn1/src/asn1.app.src
@@ -9,12 +9,11 @@
asn1rt_ber_bin,
asn1rt_ber_bin_v2,
asn1rt_check,
- asn1rt_driver_handler
+ asn1rt_nif
]},
{registered, [
asn1_ns,
- asn1db,
- asn1_driver_owner
+ asn1db
]},
{env, []},
{applications, [kernel, stdlib]}
diff --git a/lib/asn1/src/asn1_app.erl b/lib/asn1/src/asn1_app.erl
index 2d3eed1743..9fff96e0bf 100644
--- a/lib/asn1/src/asn1_app.erl
+++ b/lib/asn1/src/asn1_app.erl
@@ -28,7 +28,7 @@
%% {error, Reason}
%%
start(_Type, _StartArgs) ->
- asn1_sup:start_link().
+ {ok, self()}.
%% stop(State)
%%
diff --git a/lib/asn1/src/asn1_server.erl b/lib/asn1/src/asn1_server.erl
deleted file mode 100644
index aeb59d8b0c..0000000000
--- a/lib/asn1/src/asn1_server.erl
+++ /dev/null
@@ -1,107 +0,0 @@
-%% ``The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved via the world wide web at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
-%% AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
-
-%% Purpose: Provide complete encode/and pre-decode of asn1.
--module(asn1_server).
-
-
-
--behaviour(gen_server).
-
--export([start_link/0,client_port/0]).
-
-%% Internal exports, call-back functions.
--export([init/1,handle_call/3,handle_cast/2,handle_info/2,code_change/3,
- terminate/2]).
-
-
-%% Macros
--define(port_names,
- { asn1_drv01, asn1_drv02, asn1_drv03, asn1_drv04,
- asn1_drv05, asn1_drv06, asn1_drv07, asn1_drv08,
- asn1_drv09, asn1_drv10, asn1_drv11, asn1_drv12,
- asn1_drv13, asn1_drv14, asn1_drv15, asn1_drv16 }).
-%%% --------------------------------------------------------
-%%% Interface Functions.
-%%% --------------------------------------------------------
-
-start_link() ->
- gen_server:start_link({local, asn1_server}, asn1_server, [], []).
-
-init([]) ->
- process_flag(trap_exit, true),
- erl_ddll:start(),
- PrivDir = code:priv_dir(asn1),
- LibDir1 = filename:join([PrivDir, "lib"]),
- case erl_ddll:load_driver(LibDir1, asn1_erl_drv) of
- ok -> ok;
- {error,_} ->
- LibDir2 =
- filename:join(LibDir1,
- erlang:system_info(system_architecture)),
- erl_ddll:load_driver(LibDir2, asn1_erl_drv)
- end,
- open_ports("asn1_erl_drv",size(?port_names)).
-
-open_ports(_,0) ->
- {ok, []};
-open_ports(Cmd,N) ->
- Port = open_port({spawn, Cmd}, []),
- %% check that driver is loaded, linked and working
- case catch port_control(Port, 0, []) of
- {'EXIT', _} ->
- {stop, nodriver};
- _ ->
- register(element(N,?port_names), Port),
- open_ports(Cmd,N-1)
- end.
-
-client_port() ->
- element(erlang:system_info(scheduler_id) rem size(?port_names) + 1,
- ?port_names).
-
-
-%%% --------------------------------------------------------
-%%% The call-back functions.
-%%% --------------------------------------------------------
-
-handle_call(_, _, State) ->
- {noreply, State}.
-
-handle_cast(_, State) ->
- {noreply, State}.
-
-handle_info({'EXIT', Pid, _Reason}, State) when is_pid(Pid) ->
- {noreply, State};
-
-handle_info({'EXIT', Port, Reason}, State) when is_port(Port) ->
- {stop, {port_died, Reason}, State};
-handle_info(_, State) ->
- {noreply, State}.
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-terminate(_Reason, _State) ->
- close_ports(size(?port_names)).
-
-close_ports(0) ->
- ok;
-close_ports(N) ->
- element(N,?port_names) ! {self(), close}, %% almost same as port_close(Name)
- close_ports(N-1).
diff --git a/lib/asn1/src/asn1ct.erl b/lib/asn1/src/asn1ct.erl
index a167d27f82..85bb5b2f28 100644
--- a/lib/asn1/src/asn1ct.erl
+++ b/lib/asn1/src/asn1ct.erl
@@ -39,7 +39,7 @@
add_tobe_refed_func/1,add_generated_refed_func/1,
maybe_rename_function/3,latest_sindex/0,current_sindex/0,
set_current_sindex/1,next_sindex/0,maybe_saved_sindex/2,
- parse_and_save/2,verbose/3,warning/3,error/3]).
+ parse_and_save/2,verbose/3,warning/3,warning/4,error/3]).
-include("asn1_records.hrl").
-include_lib("stdlib/include/erl_compile.hrl").
@@ -47,6 +47,10 @@
-import(asn1ct_gen_ber_bin_v2,[encode_tag_val/3,decode_class/1]).
+-ifndef(vsn).
+-define(vsn,"0.0.1").
+-endif.
+
-define(unique_names,0).
-define(dupl_uniquedefs,1).
-define(dupl_equaldefs,2).
@@ -81,6 +85,12 @@ compile(File) ->
compile(File,[]).
compile(File,Options) when is_list(Options) ->
+ case lists:member(driver, Options) of %% remove me in R16A!
+ true ->
+ io:format("Warning: driver option is obsolete and will be removed in R16A, use nif instead!");
+ false ->
+ ok
+ end,
Options1 = optimize_ber_bin(Options),
Options2 = includes(File,Options1),
Includes=[I||{i,I}<-Options2],
@@ -825,10 +835,13 @@ generate({true,{M,_Module,GenTOrV}},OutFile,EncodingRule,Options) ->
case catch specialized_decode_prepare(EncodingRule,M,GenTOrV,Options) of
{error, enoent} -> ok;
{error, Reason} -> warning("Error in configuration "
- "file: ~n~p~n",[Reason],Options);
+ "file: ~n~p~n",[Reason],Options,
+ "Error in configuration file");
{'EXIT',Reason} -> warning("Internal error when "
"analyzing configuration "
- "file: ~n~p~n",[Reason],Options);
+ "file: ~n~p~n",[Reason],Options,
+ "Internal error when "
+ "analyzing configuration");
_ -> ok
end,
@@ -1082,7 +1095,7 @@ get_runtime_mod(Options) ->
ber_bin_v2 -> ["asn1rt_ber_bin_v2.erl"];
uper_bin -> ["asn1rt_uper_bin.erl"]
end,
- RtMod1++["asn1rt_check.erl","asn1rt_driver_handler.erl","asn1rt.erl"].
+ RtMod1++["asn1rt_check.erl","asn1rt.erl"].
erl_compile(OutFile,Options) ->
@@ -2524,14 +2537,14 @@ type_check(#'Externaltypereference'{}) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Report functions.
%%
-%% Errors messages are controlled with the 'errors' compiler option
+%% Error messages are controlled with the 'errors' compiler option
%% Warning messages are controlled with the 'warnings' compiler option
%% Verbose messages are controlled with the 'verbose' compiler option
error(Format, Args, S) ->
case is_error(S) of
true ->
- io:format("Error: " ++ Format, Args);
+ io:format(Format, Args);
false ->
ok
end.
@@ -2544,6 +2557,17 @@ warning(Format, Args, S) ->
ok
end.
+warning(Format, Args, S, Reason) ->
+ case {is_werr(S), is_error(S), is_warning(S)} of
+ {true, true, _} ->
+ io:format(Format, Args),
+ throw({error, Reason});
+ {false, _, true} ->
+ io:format(Format, Args);
+ _ ->
+ ok
+ end.
+
verbose(Format, Args, S) ->
case is_verbose(S) of
true ->
@@ -2566,3 +2590,8 @@ is_verbose(S) when is_record(S, state) ->
is_verbose(S#state.options);
is_verbose(O) ->
lists:member(verbose, O).
+
+is_werr(S) when is_record(S, state) ->
+ is_werr(S#state.options);
+is_werr(O) ->
+ lists:member(warnings_as_errors, O).
diff --git a/lib/asn1/src/asn1ct_check.erl b/lib/asn1/src/asn1ct_check.erl
index efd731f052..e318477234 100644
--- a/lib/asn1/src/asn1ct_check.erl
+++ b/lib/asn1/src/asn1ct_check.erl
@@ -2031,7 +2031,7 @@ get_objectset_def2(_S,T = #typedef{typespec=#'ObjectSet'{}},_CField) ->
T;
get_objectset_def2(S,T,_CField) ->
asn1ct:warning("get_objectset_def2: uncontrolled object set structure:~n~p~n",
- [T],S).
+ [T],S,"get_objectset_def2: uncontrolled object set structure").
type_name(S,#type{def=Def}) ->
CurrMod = S#state.mname,
@@ -2705,7 +2705,7 @@ normalize_value(S,Type,{'DEFAULT',Value},NameList) ->
normalize_objectclassfieldvalue(S,Value,NL);
Err ->
asn1ct:warning("could not check default value ~p~nType:~n~p~nNameList:~n~p~n",
- [Value,Type,Err],S),
+ [Value,Type,Err],S,"could not check default value"),
Value
end;
normalize_value(S,Type,Val,NameList) ->
@@ -2791,22 +2791,27 @@ normalize_bitstring(S,Value,Type)->
case catch lists:map(F,RecList) of
{error,Reason} ->
asn1ct:warning("default value not "
- "compatible with type definition ~p~n",
- [Reason],S),
+ "compatible with type definition ~p~n",
+ [Reason],S,
+ "default value not "
+ "compatible with type definition"),
Value;
NewList ->
NewList
end;
_ ->
asn1ct:warning("default value not "
- "compatible with type definition ~p~n",
- [RecList],S),
+ "compatible with type definition ~p~n",
+ [RecList],S,
+ "default value not "
+ "compatible with type definition"),
Value
end;
{Name,String} when is_atom(Name) ->
normalize_bitstring(S,String,Type);
Other ->
- asn1ct:warning("illegal default value ~p~n",[Other],S),
+ asn1ct:warning("illegal default value ~p~n",[Other],S,
+ "illegal default value"),
Value
end.
@@ -2846,12 +2851,14 @@ normalize_octetstring(S,Value,CType) ->
lists:map(fun([])-> ok;
(H)when H > 255->
asn1ct:warning("not legal octet value ~p in OCTET STRING, ~p~n",
- [H,List],S);
+ [H,List],S,
+ "not legal octet value ~p in OCTET STRING");
(_)-> ok
end, List),
List;
Other ->
- asn1ct:warning("unknown default value ~p~n",[Other],S),
+ asn1ct:warning("unknown default value ~p~n",[Other],S,
+ "unknown default value"),
Value
end.
@@ -2908,13 +2915,15 @@ normalize_enumerated(S,{Name,EnumV},CType) when is_atom(Name) ->
normalize_enumerated(S,Value,{CType1,CType2}) when is_list(CType1), is_list(CType2)->
normalize_enumerated(S,Value,CType1++CType2);
normalize_enumerated(S,V,CType) ->
- asn1ct:warning("Enumerated unknown type ~p~n",[CType],S),
+ asn1ct:warning("Enumerated unknown type ~p~n",[CType],S,
+ "Enumerated unknown type"),
V.
normalize_enumerated2(S,V,Enum) ->
case lists:keysearch(V,1,Enum) of
{value,{Val,_}} -> Val;
_ ->
- asn1ct:warning("Enumerated value is not correct ~p~n",[V],S),
+ asn1ct:warning("enumerated value is not correct ~p~n",[V],S,
+ "enumerated value is not correct"),
V
end.
@@ -2925,7 +2934,8 @@ normalize_choice(S,{'CHOICE',{C,V}},CType,NameList) when is_atom(C) ->
{C,normalize_value(S,CT,{'DEFAULT',V},
[Name|NameList])};
Other ->
- asn1ct:warning("Wrong format of type/value ~p/~p~n",[Other,V],S),
+ asn1ct:warning("Wrong format of type/value ~p/~p~n",[Other,V],S,
+ "Wrong format of type/value"),
{C,V}
end;
normalize_choice(S,{'DEFAULT',ValueList},CType,NameList) when is_list(ValueList) ->
@@ -3101,7 +3111,8 @@ normalize_s_of(SorS,S,Value,Type,NameList) when is_list(Value) ->
List when is_list(List) ->
List;
_ ->
- asn1ct:warning("~p could not handle value ~p~n",[SorS,Value],S),
+ asn1ct:warning("~p could not handle value ~p~n",[SorS,Value],S,
+ "could not handle value"),
Value
end;
normalize_s_of(SorS,S,Value,Type,NameList)
@@ -3159,7 +3170,8 @@ get_normalized_value(S,Val,Type,Func,AddArg) ->
V2 = sort_val_if_set(AddArg,NewVal,Type),
call_Func(update_state(S,ExtM),V2,Type,Func,AddArg);
_ ->
- asn1ct:warning("default value not comparable ~p~n",[Val],S),
+ asn1ct:warning("default value not comparable ~p~n",[Val],S,
+ "default value not comparable"),
Val
end.
@@ -5756,7 +5768,8 @@ ascending_order_check1(S,TypeName,
[C1 = #'ComponentType'{tags=[{_,T}|_]},
C2 = #'ComponentType'{tags=[{_,T}|_]}|Rest]) ->
asn1ct:warning("Indistinct tag ~p in SET ~p, components ~p and ~p~n",
- [T,TypeName,C1#'ComponentType'.name,C2#'ComponentType'.name],S),
+ [T,TypeName,C1#'ComponentType'.name,C2#'ComponentType'.name],S,
+ "Indistinct tag in SET"),
ascending_order_check1(S,TypeName,[C2|Rest]);
ascending_order_check1(S,TypeName,
[C1 = #'ComponentType'{tags=[{'UNIVERSAL',T1}|_]},
@@ -5764,9 +5777,10 @@ ascending_order_check1(S,TypeName,
case (decode_type(T1) == decode_type(T2)) of
true ->
asn1ct:warning("Indistinct tags ~p and ~p in"
- " SET ~p, components ~p and ~p~n",
- [T1,T2,TypeName,C1#'ComponentType'.name,
- C2#'ComponentType'.name],S),
+ " SET ~p, components ~p and ~p~n",
+ [T1,T2,TypeName,C1#'ComponentType'.name,
+ C2#'ComponentType'.name],S,
+ "Indistinct tags and in SET"),
ascending_order_check1(S,TypeName,[C2|Rest]);
_ ->
ascending_order_check1(S,TypeName,[C2|Rest])
diff --git a/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl b/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl
index e3be914af4..243ff234a7 100644
--- a/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl
+++ b/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl
@@ -877,13 +877,13 @@ gen_dec_choice(Erules,TopType, _ChTag, CompList, Ext) ->
emit([indent(9),"exit({error,{asn1,{invalid_choice_tag,",
{curr,else},"}}})",nl]);
_ ->
- emit([indent(9),"{asn1_ExtAlt, ?RT_BER:encode(",{curr,else},")}",nl])
+ emit([indent(9),"{asn1_ExtAlt, ?RT_BER:encode(",{curr,else},
+ asn1ct_gen:nif_parameter(),")}",nl])
end,
emit([indent(3),"end",nl]),
asn1ct_name:new(tag),
asn1ct_name:new(else).
-
gen_dec_choice_cases(_Erules,_TopType, []) ->
ok;
gen_dec_choice_cases(Erules,TopType, [H|T]) ->
@@ -1227,7 +1227,7 @@ gen_dec_call({typefield,_},_,_,_Cname,Type,BytesVar,Tag,_,_,false,_) ->
emit([nl,indent(6),"begin",nl]),
% emit([indent(9),{curr,opendec}," = ?RT_BER:decode_open_type(",
emit([indent(9),{curr,tmptlv}," = ?RT_BER:decode_open_type(",
- BytesVar,",",{asis,Tag},"),",nl]),
+ BytesVar,",",{asis,Tag},asn1ct_gen:nif_parameter(),"),",nl]),
% emit([indent(9),"{",{curr,tmptlv},",_} = ?RT_BER:decode(",
% {curr,opendec},"),",nl]),
@@ -1242,7 +1242,8 @@ gen_dec_call({typefield,_},_,_,_Cname,Type,BytesVar,Tag,_,_,false,_) ->
emit([indent(9),"end",nl,indent(6),"end",nl]),
[];
gen_dec_call({typefield,_},_,_,Cname,Type,BytesVar,Tag,_,_,_DecObjInf,OptOrMandComp) ->
- emit(["?RT_BER:decode_open_type(",BytesVar,",",{asis,Tag},")"]),
+ emit(["?RT_BER:decode_open_type(",BytesVar,",",{asis,Tag},
+ asn1ct_gen:nif_parameter(),")"]),
RefedFieldName =
% asn1ct_gen:get_constraint(Type#type.constraint,
% tableconstraint_info),
@@ -1250,7 +1251,8 @@ gen_dec_call({typefield,_},_,_,Cname,Type,BytesVar,Tag,_,_,_DecObjInf,OptOrMandC
[{Cname,RefedFieldName,asn1ct_gen:mk_var(asn1ct_name:curr(term)),
asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),Tag,OptOrMandComp}];
gen_dec_call({objectfield,PrimFieldName,PFNList},_,_,Cname,_,BytesVar,Tag,_,_,_,OptOrMandComp) ->
- emit(["?RT_BER:decode_open_type(",BytesVar,",",{asis,Tag},")"]),
+ emit(["?RT_BER:decode_open_type(",BytesVar,",",{asis,Tag},
+ asn1ct_gen:nif_parameter(),")"]),
[{Cname,{PrimFieldName,PFNList},asn1ct_gen:mk_var(asn1ct_name:curr(term)),
asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),Tag,OptOrMandComp}];
gen_dec_call(InnerType,Erules,TopType,Cname,Type,BytesVar,Tag,PrimOptOrMand,
diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl
index c1b6aa5713..e07680f10b 100644
--- a/lib/asn1/src/asn1ct_constructed_per.erl
+++ b/lib/asn1/src/asn1ct_constructed_per.erl
@@ -73,16 +73,23 @@ gen_encode_constructed(Erule,Typename,D) when is_record(D,type) ->
_ ->
ok
end,
- case {Optionals = optionals(to_textual_order(CompList)),CompList} of
- {[],EmptyCL} when EmptyCL == {[],[],[]};EmptyCL == {[],[]};EmptyCL == [] ->
+ case {Optionals = optionals(to_textual_order(CompList)),CompList,
+ is_optimized(Erule)} of
+ {[],EmptyCL,_} when EmptyCL == {[],[],[]};EmptyCL == {[],[]};EmptyCL == [] ->
emit(["%%Variable setting just to eliminate ",
"compiler warning for unused vars!",nl,
"_Val = ",{curr,val},",",nl]);
- {[],_} ->
+ {[],_,_} ->
emit([{next,val}," = ?RT_PER:list_to_record("]),
emit(["'",asn1ct_gen:list2rname(Typename),"'"]),
emit([", ",{curr,val},"),",nl]);
- _ ->
+ {_,_,true} ->
+ gen_fixoptionals(Optionals),
+ FixOpts = param_map(fun(Var) ->
+ {var,Var}
+ end,asn1ct_name:all(fixopt)),
+ emit({"{",{next,val},",Opt} = {",{curr,val},",[",FixOpts,"]},",nl});
+ {_,_,false} ->
Fixoptcall = ",Opt} = ?RT_PER:fixoptionals(",
emit({"{",{next,val},Fixoptcall,
{asis,Optionals},",",length(Optionals),
@@ -439,9 +446,7 @@ gen_encode_sof(Erule,Typename,SeqOrSetOf,D) when is_record(D,type) ->
_->
""
end,
- emit({nl,indent(3),"?RT_PER:encode_length(",
- {asis,SizeConstraint},
- ",length(Val)),",nl}),
+ gen_encode_length(SizeConstraint, is_optimized(Erule)),
emit({indent(3),"'enc_",asn1ct_gen:list2name(Typename),
"_components'(Val",ObjFun,", [])"}),
emit({nl,"].",nl}),
@@ -453,6 +458,42 @@ gen_encode_sof(Erule,Typename,SeqOrSetOf,D) when is_record(D,type) ->
end,
gen_encode_sof_components(Erule,Typename,SeqOrSetOf,NewComponentType).
+
+%% Logic copied from asn1_per_bin_rt2ct:encode_constrained_number
+gen_encode_length({Lb,Ub},true) when Ub =< 65535, Lb >= 0 ->
+ Range = Ub - Lb + 1,
+ V2 = ["(length(Val) - ",Lb,")"],
+ Encode = if
+ Range == 1 ->
+ "[]";
+ Range == 2 ->
+ {"[",V2,"]"};
+ Range =< 4 ->
+ {"[10,2,",V2,"]"};
+ Range =< 8 ->
+ {"[10,3,",V2,"]"};
+ Range =< 16 ->
+ {"[10,4,",V2,"]"};
+ Range =< 32 ->
+ {"[10,5,",V2,"]"};
+ Range =< 64 ->
+ {"[10,6,",V2,"]"};
+ Range =< 128 ->
+ {"[10,7,",V2,"]"};
+ Range =< 255 ->
+ {"[10,8,",V2,"]"};
+ Range =< 256 ->
+ {"[20,1,",V2,"]"};
+ Range =< 65536 ->
+ {"[20,2,<<",V2,":16>>]"};
+ true ->
+ {"?RT_PER:encode_length(",{asis,{Lb,Ub}},",length(Val))"}
+ end,
+ emit({nl,Encode,",",nl});
+gen_encode_length(SizeConstraint,_) ->
+ emit({nl,indent(3),"?RT_PER:encode_length(",
+ {asis,SizeConstraint},",length(Val)),",nl}).
+
gen_decode_sof(Erules,Typename,SeqOrSetOf,D) when is_record(D,type) ->
asn1ct_name:start(),
{_SeqOrSetOf,ComponentType} = D#type.def,
@@ -469,7 +510,8 @@ gen_decode_sof(Erules,Typename,SeqOrSetOf,D) when is_record(D,type) ->
_ ->
""
end,
- emit({nl,"{Num,Bytes1} = ?RT_PER:decode_length(Bytes,",{asis,SizeConstraint},"),",nl}),
+ gen_decode_length(SizeConstraint,
+ is_optimized(Erules)),
emit({"'dec_",asn1ct_gen:list2name(Typename),
"_components'(Num, Bytes1, telltype",ObjFun,", []).",nl}),
NewComponentType =
@@ -480,6 +522,41 @@ gen_decode_sof(Erules,Typename,SeqOrSetOf,D) when is_record(D,type) ->
end,
gen_decode_sof_components(Erules,Typename,SeqOrSetOf,NewComponentType).
+%% Logic copied from asn1_per_bin_rt2ct:decode_constrained_number
+gen_decode_length({Lb,Ub},true) when Ub =< 65535, Lb >= 0 ->
+ Range = Ub - Lb + 1,
+ Call = if
+ Range == 1 ->
+ "{0,Bytes}";
+ Range == 2 ->
+ "?RT_PER:getbits(Bytes,1)";
+ Range =< 4 ->
+ "?RT_PER:getbits(Bytes,2)";
+ Range =< 8 ->
+ "?RT_PER:getbits(Bytes,3)";
+ Range =< 16 ->
+ "?RT_PER:getbits(Bytes,4)";
+ Range =< 32 ->
+ "?RT_PER:getbits(Bytes,5)";
+ Range =< 64 ->
+ "?RT_PER:getbits(Bytes,6)";
+ Range =< 128 ->
+ "?RT_PER:getbits(Bytes,7)";
+ Range =< 255 ->
+ "?RT_PER:getbits(Bytes,8)";
+ Range =< 256 ->
+ "?RT_PER:getoctets(Bytes,1)";
+ Range =< 65536 ->
+ "?RT_PER:getoctets(Bytes,2)";
+ true ->
+ ["exit({not_supported,{integer_range,",Range,"}}"]
+ end,
+ emit({nl,"{Val,Remain} = ",Call,",",nl}),
+ emit({nl,"{Num,Bytes1} = {Val+",Lb,",Remain},",nl});
+gen_decode_length(SizeConstraint,_) ->
+ emit({nl,"{Num,Bytes1} = ?RT_PER:decode_length(Bytes,",
+ {asis,SizeConstraint},"),",nl}).
+
gen_encode_sof_components(Erule,Typename,SeqOrSetOf,Cont) ->
{ObjFun,ObjFun_Var} =
case Cont#type.tablecinf of
@@ -636,6 +713,27 @@ gen_dec_extension_value(_) ->
emit({"{Ext,",{next,bytes},"} = ?RT_PER:getext(",{curr,bytes},")"}),
asn1ct_name:new(bytes).
+gen_fixoptionals([{Pos,Def}|R]) ->
+ asn1ct_name:new(fixopt),
+ emit({{curr,fixopt}," = case element(",{asis,Pos},",",{curr,val},") of",nl,
+ "asn1_DEFAULT -> 0;",nl,
+ {asis,Def}," -> 0;",nl,
+ "_ -> 1",nl,
+ "end,",nl}),
+ gen_fixoptionals(R);
+gen_fixoptionals([Pos|R]) ->
+ gen_fixoptionals([{Pos,asn1_NOVALUE}|R]);
+gen_fixoptionals([]) ->
+ ok.
+
+
+param_map(Fun, [H]) ->
+ [Fun(H)];
+param_map(Fun, [H|T]) ->
+ [Fun(H),","|param_map(Fun,T)].
+
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Produce a list with positions (in the Value record) where
%% there are optional components, start with 2 because first element
@@ -922,7 +1020,7 @@ gen_enc_line(Erule,TopType,Cname,Type,Element, _Pos,DynamicEnc,Ext) ->
end,
case Ext of
{ext,_Ep2,_} ->
- emit(["))"]);
+ emit("))");
_ -> true
end.
gen_dec_components_call(Erule,TopType,{Root1,ExtList,Root2},MaybeComma,DecInfObj,Ext,NumberOfOptionals) ->
diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl
index e49829d82f..0f8833f716 100644
--- a/lib/asn1/src/asn1ct_gen.erl
+++ b/lib/asn1/src/asn1ct_gen.erl
@@ -47,6 +47,7 @@
un_hyphen_var/1]).
-export([gen_encode_constructed/4,
gen_decode_constructed/4]).
+-export([nif_parameter/0]).
%% pgen(Outfile, Erules, Module, TypeOrVal, Options)
%% Generate Erlang module (.erl) and (.hrl) file corresponding to an ASN.1 module
@@ -938,13 +939,13 @@ pgen_dispatcher(Erules,_Module,{Types,_Values,_,_,_Objects,_ObjectSets}) ->
NoFinalPadding = lists:member(no_final_padding,get(encoding_options)),
Call = case Erules of
per -> "?RT_PER:complete(encode_disp(Type,Data))";
- per_bin -> "?RT_PER:complete(encode_disp(Type,Data))";
+ per_bin -> ["?RT_PER:complete(encode_disp(Type,Data))"];
ber -> "encode_disp(Type,Data)";
ber_bin -> "encode_disp(Type,Data)";
ber_bin_v2 -> "encode_disp(Type,Data)";
uper_bin when NoFinalPadding == true ->
"?RT_PER:complete_NFP(encode_disp(Type,Data))";
- uper_bin -> "?RT_PER:complete(encode_disp(Type,Data))"
+ uper_bin -> ["?RT_PER:complete(encode_disp(Type,Data))"]
end,
EncWrap = case Erules of
ber -> "wrap_encode(Bytes)";
@@ -974,7 +975,7 @@ pgen_dispatcher(Erules,_Module,{Types,_Values,_,_,_Objects,_ObjectSets}) ->
% case Erules of
% ber_bin_v2 ->
% emit(["decode(Type,Data0) ->",nl]),
-% emit(["{Data,_RestBin} = ?RT_BER:decode(Data0",driver_parameter(),"),",nl]);
+% emit(["{Data,_RestBin} = ?RT_BER:decode(Data0",nif_parameter(),"),",nl]);
% _ ->
% emit(["decode(Type,Data) ->",nl])
% end,
@@ -991,10 +992,10 @@ pgen_dispatcher(Erules,_Module,{Types,_Values,_,_,_Objects,_ObjectSets}) ->
{ber_bin_v2,false} ->
io_lib:format("~s~s~s~n",
["element(1,?RT_BER:decode(Data",
- driver_parameter(),"))"]);
+ nif_parameter(),"))"]);
{ber_bin_v2,true} ->
emit(["{Data,Rest} = ?RT_BER:decode(Data0",
- driver_parameter(),"),",nl]),
+ nif_parameter(),"),",nl]),
"Data";
_ ->
"Data"
@@ -1130,13 +1131,8 @@ gen_decode_partial_incomplete(Erule) when Erule == ber;Erule==ber_bin;
"Data) of",nl]),
EmitCaseClauses(),
emit(["decode_part(Type,Data0) ->",nl]),
- Driver =
- case lists:member(driver,get(encoding_options)) of
- true ->
- ",driver";
- _ -> ""
- end,
- emit([" case catch decode_inc_disp(Type,element(1,?RT_BER:decode(Data0",Driver,"))) of",nl]),
+ emit([" case catch decode_inc_disp(Type,element(1,"
+ "?RT_BER:decode(Data0",nif_parameter(),"))) of",nl]),
% " {Data,_RestBin} = ?RT_BER:decode(Data0),",nl,
% " case catch decode_inc_disp(Type,Data) of",nl]),
EmitCaseClauses();
@@ -1179,12 +1175,12 @@ gen_partial_inc_dispatcher([],_) ->
emit(["decode_partial_inc_disp(Type,_Data) ->",nl,
" exit({error,{asn1,{undefined_type,Type}}}).",nl]).
-driver_parameter() ->
+nif_parameter() ->
Options = get(encoding_options),
- case lists:member(driver,Options) of
- true ->
- ",driver";
- _ -> ""
+ case {lists:member(driver,Options),lists:member(nif,Options)} of
+ {true,_} -> ",nif";
+ {_,true} -> ",nif";
+ _ -> ""
end.
gen_wrapper() ->
@@ -1525,8 +1521,9 @@ gen_head(Erules,Mod,Hrl) ->
emit({"-module('",Mod,"').",nl}),
put(currmod,Mod),
%emit({"-compile(export_all).",nl}),
- case Hrl of
- 0 -> true;
+ case {Hrl,lists:member(inline,get(encoding_options))} of
+ {0,_} -> true;
+ {_,true} -> true;
_ ->
emit({"-include(\"",Mod,".hrl\").",nl})
end,
diff --git a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
index 9ec458e351..781271bae7 100644
--- a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
+++ b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
@@ -416,7 +416,7 @@ gen_decode_selected(Erules,Type,FuncName) ->
end,
emit([" case ?RT_BER:decode_selective(",{asis,Pattern},",Bin) of",nl,
" {ok,Bin2} when is_binary(Bin2) ->",nl,
- " {Tlv,_} = ?RT_BER:decode(Bin2),",nl]),
+ " {Tlv,_} = ?RT_BER:decode(Bin2",asn1ct_gen:nif_parameter(),"),",nl]),
emit("{ok,"),
gen_decode_selected_type(Erules,Type),
emit(["};",nl," Err -> exit({error,{selctive_decode,Err}})",nl,
@@ -708,7 +708,7 @@ gen_dec_prim(Erules,Att,BytesVar,DoTag,TagIn,Form,OptOrMand) ->
'ASN1_OPEN_TYPE' ->
emit(["?RT_BER:decode_open_type_as_binary(",
BytesVar,","]),
- add_func({decode_open_type_as_binary,2});
+ add_func({decode_open_type_as_binary,3});
#'ObjectClassFieldType'{} ->
case asn1ct_gen:get_inner(Att#type.def) of
{fixedtypevaluefield,_,InnerType} ->
@@ -716,7 +716,7 @@ gen_dec_prim(Erules,Att,BytesVar,DoTag,TagIn,Form,OptOrMand) ->
'ASN1_OPEN_TYPE' ->
emit(["?RT_BER:decode_open_type_as_binary(",
BytesVar,","]),
- add_func({decode_open_type_as_binary,2});
+ add_func({decode_open_type_as_binary,3});
Other ->
exit({'can not decode' ,Other})
end;
@@ -728,13 +728,13 @@ gen_dec_prim(Erules,Att,BytesVar,DoTag,TagIn,Form,OptOrMand) ->
{_,#'ObjectClassFieldType'{}} ->
case asn1ct_gen:get_inner(Att#type.def) of
'ASN1_OPEN_TYPE' ->
- emit([{asis,DoTag},")"]);
+ emit([{asis,DoTag},asn1ct_gen:nif_parameter(),")"]);
_ -> ok
end;
{{string,TagStr},'ASN1_OPEN_TYPE'} ->
- emit([TagStr,")"]);
+ emit([TagStr,asn1ct_gen:nif_parameter(),")"]);
{_,'ASN1_OPEN_TYPE'} ->
- emit([{asis,DoTag},")"]);
+ emit([{asis,DoTag},asn1ct_gen:nif_parameter(),")"]);
{{string,TagStr},_} ->
emit([TagStr,")"]);
_ when is_list(DoTag) ->
@@ -1064,7 +1064,7 @@ emit_tlv_format_function() ->
end.
emit_tlv_format_function1() ->
emit(["tlv_format(Bytes) when is_binary(Bytes) ->",nl,
- " {Tlv,_}=?RT_BER:decode(Bytes),",nl,
+ " {Tlv,_}=?RT_BER:decode(Bytes",asn1ct_gen:nif_parameter(),"),",nl,
" Tlv;",nl,
"tlv_format(Bytes) ->",nl,
" Bytes.",nl]).
@@ -1502,13 +1502,14 @@ gen_objset_dec(Erules,ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,
_ClFields,_NthObj) ->
emit(["'getdec_",ObjSetName,"'(_, _) ->",nl]),
emit([indent(2),"fun(_,Bytes, _RestPrimFieldName) ->",nl]),
+
case Erules of
ber_bin_v2 ->
emit([indent(4),"case Bytes of",nl,
indent(6),"Bin when is_binary(Bin) -> ",nl,
indent(8),"Bin;",nl,
indent(6),"_ ->",nl,
- indent(8),"?RT_BER:encode(Bytes)",nl,
+ indent(8),"?RT_BER:encode(Bytes",driver_parameter(),")",nl,
indent(4),"end",nl]);
_ ->
emit([indent(6),"Len = case Bytes of",nl,indent(9),
@@ -1521,6 +1522,14 @@ gen_objset_dec(Erules,ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,
gen_objset_dec(_,_,_,[],_,_,_) ->
ok.
+driver_parameter() ->
+ Options = get(encoding_options),
+ case {lists:member(driver,Options),lists:member(nif,Options)} of
+ {true,_} -> ",nif";
+ {_,true} -> ",nif";
+ _ -> ",erlang"
+ end.
+
emit_default_getdec(ObjSetName,UniqueName) ->
emit(["'getdec_",ObjSetName,"'(",{asis,UniqueName},", ErrV) ->",nl]),
emit([indent(2), "fun(C,V,_) -> exit({{component,C},{value,V},{unique_name_and_value,",{asis,UniqueName},", ErrV}}) end"]).
diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl
index 8313cf1b60..b90a0adf81 100644
--- a/lib/asn1/src/asn1ct_gen_per.erl
+++ b/lib/asn1/src/asn1ct_gen_per.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -238,7 +238,8 @@ gen_encode_prim(Erules,D,DoTag,Value) when is_record(D,type) ->
"?RT_PER:complete(enc_~s(~s))",[Tname,Value]);
[#type{def=#'Externaltypereference'{type=Tname}}] ->
io_lib:format(
- "?RT_PER:complete(enc_~s(~s))",[Tname,Value]);
+ "?RT_PER:complete(enc_~s(~s))",
+ [Tname,Value]);
_ -> Value
end,
emit(["?RT_PER:encode_open_type(", {asis,Constraint}, ",",
diff --git a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
index 4f4fcfafc3..1a0a0e211d 100644
--- a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
+++ b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -230,7 +230,8 @@ gen_encode_prim(Erules,D,DoTag,Value) when is_record(D,type) ->
"?RT_PER:complete(enc_~s(~s))",[Tname,Value]);
[#type{def=#'Externaltypereference'{type=Tname}}] ->
io_lib:format(
- "?RT_PER:complete(enc_~s(~s))",[Tname,Value]);
+ "?RT_PER:complete(enc_~s(~s))",
+ [Tname,Value]);
_ -> Value
end,
emit(["?RT_PER:encode_open_type(", {asis,Constraint}, ",",
diff --git a/lib/asn1/src/asn1ct_value.erl b/lib/asn1/src/asn1ct_value.erl
index 693e039a13..d099376b1b 100644
--- a/lib/asn1/src/asn1ct_value.erl
+++ b/lib/asn1/src/asn1ct_value.erl
@@ -435,11 +435,11 @@ get_encoding_rule(M) ->
open_type_value(ber) ->
[4,9,111,112,101,110,95,116,121,112,101];
open_type_value(ber_bin) ->
- [4,9,111,112,101,110,95,116,121,112,101];
-% <<4,9,111,112,101,110,95,116,121,112,101>>;
+% [4,9,111,112,101,110,95,116,121,112,101];
+ <<4,9,111,112,101,110,95,116,121,112,101>>;
open_type_value(ber_bin_v2) ->
- [4,9,111,112,101,110,95,116,121,112,101];
-% <<4,9,111,112,101,110,95,116,121,112,101>>;
+% [4,9,111,112,101,110,95,116,121,112,101];
+ <<4,9,111,112,101,110,95,116,121,112,101>>;
open_type_value(per) ->
"\n\topen_type"; %octet string value "open_type"
open_type_value(per_bin) ->
diff --git a/lib/asn1/src/asn1rt.erl b/lib/asn1/src/asn1rt.erl
index 9ef68efab5..d18f81346a 100644
--- a/lib/asn1/src/asn1rt.erl
+++ b/lib/asn1/src/asn1rt.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -21,12 +21,12 @@
%% Runtime functions for ASN.1 (i.e encode, decode)
--include("asn1_records.hrl").
-
-export([encode/2,encode/3,decode/3,load_driver/0,unload_driver/0,info/1]).
-export([utf8_binary_to_list/1,utf8_list_to_binary/1]).
+-deprecated([load_driver/0,unload_driver/0]).
+
encode(Module,{Type,Term}) ->
encode(Module,Type,Term).
@@ -46,38 +46,12 @@ decode(Module,Type,Bytes) ->
Result
end.
-%% asn1-1.6.8.1
-%% load_driver() ->
-%% asn1rt_driver_handler:load_driver(),
-%% receive
-%% driver_ready ->
-%% ok;
-%% Err={error,_Reason} ->
-%% Err;
-%% Error ->
-%% {error,Error}
-%% end.
-
-%% asn1-1.6.9
- load_driver() ->
- case catch asn1rt_driver_handler:load_driver() of
- ok ->
- ok;
- {error,{already_started,asn1}} ->
- ok;
- Err ->
- {error,Err}
- end.
-
+%% Remove in R16A
+load_driver() ->
+ ok.
unload_driver() ->
- case catch asn1rt_driver_handler:unload_driver() of
- ok ->
- ok;
- Error ->
- {error,Error}
- end.
-
+ ok.
info(Module) ->
case catch apply(Module,info,[]) of
diff --git a/lib/asn1/src/asn1rt_ber_bin_v2.erl b/lib/asn1/src/asn1rt_ber_bin_v2.erl
index a3bb570282..17e66f77c9 100644
--- a/lib/asn1/src/asn1rt_ber_bin_v2.erl
+++ b/lib/asn1/src/asn1rt_ber_bin_v2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -21,7 +21,7 @@
%% encoding / decoding of BER
--export([decode/1, decode/2, match_tags/2, encode/1]).
+-export([decode/1, decode/2, match_tags/2, encode/1, encode/2]).
-export([fixoptionals/2, cindex/3,
list_to_record/2,
encode_tag_val/1,
@@ -49,11 +49,13 @@
decode_tag_and_length/1]).
-export([encode_open_type/1,encode_open_type/2,
- decode_open_type/2,decode_open_type_as_binary/2]).
+ decode_open_type/2,decode_open_type/3,
+ decode_open_type_as_binary/2,
+ decode_open_type_as_binary/3]).
-export([decode_primitive_incomplete/2,decode_selective/2]).
-
--include("asn1_records.hrl").
+
+-export([is_nif_loadable/0]).
% the encoding of class of tag bits 8 and 7
-define(UNIVERSAL, 0).
@@ -125,15 +127,28 @@
% encode(Tlv) ->
% encode_constructed(Tlv).
-encode([Tlv]) ->
- encode(Tlv);
-encode({TlvTag,TlvVal}) when is_list(TlvVal) ->
+encode(Tlv) ->
+ encode(Tlv,erlang).
+
+encode(Tlv,_) when is_binary(Tlv) ->
+ Tlv;
+encode([Tlv],Method) ->
+ encode(Tlv,Method);
+encode(Tlv, nif) ->
+ case is_nif_loadable() of
+ true ->
+ asn1rt_nif:encode_ber_tlv(Tlv);
+ false ->
+ encode_erl(Tlv)
+ end;
+encode(Tlv, _) ->
+ encode_erl(Tlv).
+
+encode_erl({TlvTag,TlvVal}) when is_list(TlvVal) ->
%% constructed form of value
encode_tlv(TlvTag,TlvVal,?CONSTRUCTED);
-encode({TlvTag,TlvVal}) ->
- encode_tlv(TlvTag,TlvVal,?PRIMITIVE);
-encode(Bin) when is_binary(Bin) ->
- Bin.
+encode_erl({TlvTag,TlvVal}) ->
+ encode_tlv(TlvTag,TlvVal,?PRIMITIVE).
encode_tlv(TlvTag,TlvVal,Form) ->
Tag = encode_tlv_tag(TlvTag,Form),
@@ -152,70 +167,61 @@ encode_tlv_val(Bin) ->
{Bin,size(Bin)}.
encode_tlv_list([Tlv|Tlvs],Acc) ->
- EncTlv = encode(Tlv),
+ EncTlv = encode_erl(Tlv),
encode_tlv_list(Tlvs,[EncTlv|Acc]);
encode_tlv_list([],Acc) ->
Bin=list_to_binary(lists:reverse(Acc)),
{Bin,size(Bin)}.
-%% asn1-1.6.8.1
-%% decode(B,driver) ->
-%% case catch port_control(asn1_driver_port,2,B) of
-%% Bin when is_binary(Bin) ->
-%% binary_to_term(Bin);
-%% List when is_list(List) -> handle_error(List,B);
-%% {'EXIT',{badarg,Reason}} ->
-%% asn1rt_driver_handler:load_driver(),
-%% receive
-%% driver_ready ->
-%% case catch port_control(asn1_driver_port,2,B) of
-%% Bin2 when is_binary(Bin2) -> binary_to_term(Bin2);
-%% List when is_list(List) -> handle_error(List,B);
-%% Error -> exit(Error)
-%% end;
-%% {error,Error} -> % error when loading driver
-%% %% the driver could not be loaded
-%% exit(Error);
-%% Error={port_error,Reason} ->
-%% exit(Error)
-%% end;
-%% {'EXIT',Reason} ->
-%% exit(Reason)
-%% end.
-
-%% asn1-1.6.9
-decode(B,driver) ->
- case catch control(?TLV_DECODE,B) of
- Bin when is_binary(Bin) ->
- binary_to_term(Bin);
- List when is_list(List) -> handle_error(List,B);
- {'EXIT',{badarg,_Reason}} ->
- case asn1rt:load_driver() of
- ok ->
- case control(?TLV_DECODE,B) of
- Bin when is_binary(Bin) -> binary_to_term(Bin);
- List when is_list(List) -> handle_error(List,B)
- end;
- Err ->
- Err
- end
- end.
+decode(B) ->
+ decode(B, erlang).
+%% asn1-1.7
+decode(B, nif) ->
+ case is_nif_loadable() of
+ true ->
+ case asn1rt_nif:decode_ber_tlv(B) of
+ {error, Reason} -> handle_error(Reason, B);
+ Else -> Else
+ end;
+ false ->
+ decode(B)
+ end;
+decode(B,erlang) when is_binary(B) ->
+ decode_primitive(B);
+decode(Tlv,erlang) ->
+ {Tlv,<<>>}.
+
+%% Have to check this since asn1 is not guaranteed to be available
+is_nif_loadable() ->
+ case application:get_env(asn1, nif_loadable) of
+ {ok,R} ->
+ R;
+ undefined ->
+ case catch code:load_file(asn1rt_nif) of
+ {module, asn1rt_nif} ->
+ application:set_env(asn1, nif_loadable, true),
+ true;
+ _Else ->
+ application:set_env(asn1, nif_loadable, false),
+ false
+ end
+ end.
handle_error([],_)->
exit({error,{asn1,{"memory allocation problem"}}});
-handle_error([$1|_],L) -> % error in driver
+handle_error({$1,_},L) -> % error in nif
exit({error,{asn1,L}});
-handle_error([$2|T],L) -> % error in driver due to wrong tag
+handle_error({$2,T},L) -> % error in nif due to wrong tag
exit({error,{asn1,{"bad tag after byte:",error_pos(T),L}}});
-handle_error([$3|T],L) -> % error in driver due to length error
+handle_error({$3,T},L) -> % error in driver due to length error
exit({error,{asn1,{"bad length field after byte:",
error_pos(T),L}}});
-handle_error([$4|T],L) -> % error in driver due to indefinite length error
+handle_error({$4,T},L) -> % error in driver due to indefinite length error
exit({error,{asn1,
{"indefinite length without end bytes after byte:",
error_pos(T),L}}});
-handle_error([$5|T],L) -> % error in driver due to indefinite length error
+handle_error({$5,T},L) -> % error in driver due to indefinite length error
exit({error,{asn1,{"bad encoded value after byte:",
error_pos(T),L}}});
handle_error(ErrL,L) ->
@@ -228,16 +234,6 @@ error_pos([B])->
error_pos([B|Bs]) ->
BS = 8 * length(Bs),
B bsl BS + error_pos(Bs).
-%% asn1-1.6.9
-control(Cmd, Data) ->
- Port = asn1rt_driver_handler:client_port(),
- erlang:port_control(Port, Cmd, Data).
-
-decode(Bin) when is_binary(Bin) ->
- decode_primitive(Bin);
-decode(Tlv) -> % assume it is a tlv
- {Tlv,<<>>}.
-
decode_primitive(Bin) ->
{Form,TagNo,V,Rest} = decode_tag_and_length(Bin),
@@ -796,20 +792,24 @@ encode_open_type(Val,Tag) ->
%% Value = binary with decoded data (which must be decoded again as some type)
%%
decode_open_type(Tlv, TagIn) ->
+ decode_open_type(Tlv, TagIn, erlang).
+decode_open_type(Tlv, TagIn, Method) ->
case match_tags(Tlv,TagIn) of
Bin when is_binary(Bin) ->
- {InnerTlv,_} = decode(Bin),
+ {InnerTlv,_} = decode(Bin,Method),
InnerTlv;
TlvBytes -> TlvBytes
end.
-decode_open_type_as_binary(Tlv,TagIn)->
+decode_open_type_as_binary(Tlv, TagIn) ->
+ decode_open_type_as_binary(Tlv, TagIn, erlang).
+decode_open_type_as_binary(Tlv,TagIn, Method)->
case match_tags(Tlv,TagIn) of
V when is_binary(V) ->
V;
- [Tlv2] -> encode(Tlv2);
- Tlv2 -> encode(Tlv2)
+ [Tlv2] -> encode(Tlv2, Method);
+ Tlv2 -> encode(Tlv2, Method)
end.
%%===============================================================================
@@ -1056,7 +1056,7 @@ encode_real(C,Val, TagIn) when is_tuple(Val); is_list(Val) ->
encode_real(C,Val) ->
- ?RT_COMMON:encode_real(C,Val).
+ asn1rt_ber_bin:encode_real(C,Val).
%%============================================================================
@@ -1081,7 +1081,7 @@ decode_real_notag(Buffer) ->
{_T,_V} ->
exit({error,{asn1,{real_not_in_primitive_form,Buffer}}})
end,
- {Val,_Rest,Len} = ?RT_COMMON:decode_real(Buffer,Len),
+ {Val,_Rest,Len} = asn1rt_ber_bin:decode_real(Buffer,Len),
Val.
%% exit({error,{asn1, {unimplemented,real}}}).
%% decode_real2(Buffer, Form, size(Buffer)).
@@ -1577,14 +1577,12 @@ e_object_identifier(V) when is_tuple(V) ->
e_object_identifier([E1, E2 | Tail]) ->
Head = 40*E1 + E2, % wow!
{H,Lh} = mk_object_val(Head),
- {R,Lr} = enc_obj_id_tail(Tail, [], 0),
+ {R,Lr} = lists:mapfoldl(fun enc_obj_id_tail/2,0,Tail),
{[H|R], Lh+Lr}.
-enc_obj_id_tail([], Ack, Len) ->
- {lists:reverse(Ack), Len};
-enc_obj_id_tail([H|T], Ack, Len) ->
+enc_obj_id_tail(H, Len) ->
{B, L} = mk_object_val(H),
- enc_obj_id_tail(T, [B|Ack], Len+L).
+ {B,Len+L}.
%%%%%%%%%%%
diff --git a/lib/asn1/src/asn1rt_check.erl b/lib/asn1/src/asn1rt_check.erl
index 24a2a3802d..d9856901b8 100644
--- a/lib/asn1/src/asn1rt_check.erl
+++ b/lib/asn1/src/asn1rt_check.erl
@@ -19,8 +19,6 @@
%%
-module(asn1rt_check).
--include("asn1_records.hrl").
-
-export([check_bool/2,
check_int/3,
check_bitstring/3,
diff --git a/lib/asn1/src/asn1rt_driver_handler.erl b/lib/asn1/src/asn1rt_driver_handler.erl
deleted file mode 100644
index 146d0043f9..0000000000
--- a/lib/asn1/src/asn1rt_driver_handler.erl
+++ /dev/null
@@ -1,144 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(asn1rt_driver_handler).
-
--include("asn1_records.hrl").
-
--export([load_driver/0,unload_driver/0,client_port/0]).
-
-%% Internal exports
--export([init/2]).
-
-%% Macros
--define(port_names,
- { asn1_drv01, asn1_drv02, asn1_drv03, asn1_drv04,
- asn1_drv05, asn1_drv06, asn1_drv07, asn1_drv08,
- asn1_drv09, asn1_drv10, asn1_drv11, asn1_drv12,
- asn1_drv13, asn1_drv14, asn1_drv15, asn1_drv16 }).
-
-%%% --------------------------------------------------------
-%%% Interface Functions.
-%%% --------------------------------------------------------
-load_driver() ->
- load_driver(noreason).
-
-load_driver(Reason) ->
- Ref = make_ref(),
- case whereis(asn1_driver_owner) of % to prevent unnecessary spawn
- Pid when is_pid(Pid) ->
- asn1_driver_owner ! {self(),Ref,are_you_ready},
- receive
- {Ref,driver_ready} ->
- ok
- after 10000 ->
- {error,{timeout,waiting_for_drivers}}
- end;
- _ ->
- {_,Mref} = spawn_monitor(asn1rt_driver_handler, init, [self(),Ref]),
- receive
- {'DOWN', Mref, _, _, NewReason} ->
- case NewReason of
- Reason -> {error,Reason};
- _ -> load_driver(NewReason)
- end;
- {Ref,driver_ready} ->
- erlang:demonitor(Mref),
- ok;
- {Ref,Error = {error,_Reason}} ->
- erlang:demonitor(Mref),
- Error
- after 10000 -> %% 10 seconds
- {error,{timeout,waiting_for_drivers}}
- end
- end.
-
-init(FromPid,FromRef) ->
- case catch register(asn1_driver_owner,self()) of
- true -> true;
- _Other -> exit(normal)
- end,
- Dir = filename:join([code:priv_dir(asn1),"lib"]),
- case catch erl_ddll:load_driver(Dir,asn1_erl_drv) of
- ok ->
- Result = open_named_ports(),
- catch (FromPid ! {FromRef,Result}),
- loop(Result);
- {error,Err} -> % if erl_ddll:load_driver fails
- ForErr = erl_ddll:format_error(Err),
- OSDir = filename:join(Dir,erlang:system_info(system_architecture)),
- case catch erl_ddll:load_driver(OSDir,asn1_erl_drv) of
- ok ->
- Result = open_named_ports(),
- catch (FromPid ! {FromRef,Result}),
- loop(Result);
- {error,Err2} ->
-% catch (FromPid ! {FromRef,Error})
- ForErr2 = erl_ddll:format_error(Err2),
- catch (FromPid ! {FromRef,{error,{{Dir,ForErr},{OSDir,ForErr2}}}})
- end
- end.
-
-
-open_named_ports() ->
- open_named_ports(size(?port_names)).
-
-open_named_ports(0) ->
- driver_ready;
-open_named_ports(N) ->
- case catch open_port({spawn,"asn1_erl_drv"},[]) of
- {'EXIT',Reason} ->
- {error,{port_error,Reason}};
- Port ->
- register(element(N,?port_names),Port),
- open_named_ports(N-1)
- end.
-
-loop(Result) ->
- receive
- {_FromPid,_FromRef,unload} ->
- close_ports(size(?port_names)),
- erl_ddll:unload_driver(asn1_erl_drv),
- ok;
- {FromPid,FromRef,are_you_ready} ->
- catch (FromPid ! {FromRef,driver_ready}),
- loop(Result);
- _ ->
- loop(Result)
- end.
-
-unload_driver() ->
- case whereis(asn1_driver_owner) of
- Pid when is_pid(Pid) ->
- Pid ! {self(),make_ref(),unload},
- ok;
- _ ->
- ok
- end.
-
-close_ports(0) ->
- ok;
-close_ports(N) ->
- element(N,?port_names) ! {self(), close}, %% almost same as port_close(Name)
- close_ports(N-1).
-
-client_port() ->
- element(erlang:system_info(scheduler_id) rem size(?port_names) + 1,
- ?port_names).
diff --git a/lib/asn1/src/asn1rt_nif.erl b/lib/asn1/src/asn1rt_nif.erl
new file mode 100644
index 0000000000..de1fb94816
--- /dev/null
+++ b/lib/asn1/src/asn1rt_nif.erl
@@ -0,0 +1,87 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+-module(asn1rt_nif).
+
+%% Nif interface for asn1
+
+-export([encode_per_complete/1,
+ decode_ber_tlv/1,
+ encode_ber_tlv/1]).
+
+-on_load(load_nif/0).
+
+-define(ASN1_NIF_VSN,1).
+
+load_nif() ->
+ LibBaseName = "asn1_erl_nif",
+ PrivDir = code:priv_dir(asn1),
+ LibName = case erlang:system_info(build_type) of
+ opt ->
+ LibBaseName;
+ Type ->
+ LibTypeName = LibBaseName ++ "." ++ atom_to_list(Type),
+ case (filelib:wildcard(
+ filename:join(
+ [PrivDir,
+ "lib",
+ LibTypeName ++ "*"])) /= []) orelse
+ (filelib:wildcard(
+ filename:join(
+ [PrivDir,
+ "lib",
+ erlang:system_info(system_architecture),
+ LibTypeName ++ "*"])) /= []) of
+ true -> LibTypeName;
+ false -> LibBaseName
+ end
+ end,
+ Lib = filename:join([PrivDir, "lib", LibName]),
+ Status = case erlang:load_nif(Lib, ?ASN1_NIF_VSN) of
+ ok -> ok;
+ {error, {load_failed, _}}=Error1 ->
+ ArchLibDir =
+ filename:join([PrivDir, "lib",
+ erlang:system_info(system_architecture)]),
+ Candidate =
+ filelib:wildcard(filename:join([ArchLibDir,LibName ++ "*" ])),
+ case Candidate of
+ [] -> Error1;
+ _ ->
+ ArchLib = filename:join([ArchLibDir, LibName]),
+ erlang:load_nif(ArchLib, ?ASN1_NIF_VSN)
+ end;
+ Error1 -> Error1
+ end,
+ case Status of
+ ok -> ok;
+ {error, {E, Str}} ->
+ error_logger:error_msg("Unable to load asn1 nif library. "
+ "Failed with error:~n\"~p, ~s\"~n",[E,Str]),
+ Status
+ end.
+
+encode_per_complete(_TagValueList) ->
+ erlang:nif_error({nif_not_loaded,module,?MODULE,line,?LINE}).
+
+decode_ber_tlv(_Binary) ->
+ erlang:nif_error({nif_not_loaded,module,?MODULE,line,?LINE}).
+
+encode_ber_tlv(_TagValueList) ->
+ erlang:nif_error({nif_not_loaded,module,?MODULE,line,?LINE}).
diff --git a/lib/asn1/src/asn1rt_per_bin.erl b/lib/asn1/src/asn1rt_per_bin.erl
index 6bbca26209..a124c7553d 100644
--- a/lib/asn1/src/asn1rt_per_bin.erl
+++ b/lib/asn1/src/asn1rt_per_bin.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -57,7 +57,7 @@
encode_NumericString/2, decode_NumericString/2,
encode_ObjectDescriptor/2, decode_ObjectDescriptor/1
]).
--export([complete_bytes/1]).
+-export([complete_bytes/1, getbits/2, getoctets/2]).
-define('16K',16384).
-define('32K',32768).
diff --git a/lib/asn1/src/asn1rt_per_bin_rt2ct.erl b/lib/asn1/src/asn1rt_per_bin_rt2ct.erl
index f4aecf9322..c7ead680ce 100644
--- a/lib/asn1/src/asn1rt_per_bin_rt2ct.erl
+++ b/lib/asn1/src/asn1rt_per_bin_rt2ct.erl
@@ -1734,143 +1734,24 @@ get_constraint(C,Key) ->
-ifdef(nodriver).
complete(L) ->
- case complete1(L) of
- {[],[]} ->
- <<0>>;
- {Acc,[]} ->
- Acc;
- {Acc,Bacc} ->
- [Acc|complete_bytes(Bacc)]
- end.
-
-
-% this function builds the ugly form of lists [E1|E2] to avoid having to reverse it at the end.
-% this is done because it is efficient and that the result always will be sent on a port or
-% converted by means of list_to_binary/1
- complete1(InList) when is_list(InList) ->
- complete1(InList,[],[]);
- complete1(InList) ->
- complete1([InList],[],[]).
-
- complete1([],Acc,Bacc) ->
- {Acc,Bacc};
- complete1([H|T],Acc,Bacc) when is_list(H) ->
- {NewH,NewBacc} = complete1(H,Acc,Bacc),
- complete1(T,NewH,NewBacc);
-
- complete1([{octets,Bin}|T],Acc,[]) ->
- complete1(T,[Acc|Bin],[]);
-
- complete1([{octets,Bin}|T],Acc,Bacc) ->
- complete1(T,[Acc|[complete_bytes(Bacc),Bin]],[]);
-
- complete1([{debug,_}|T], Acc,Bacc) ->
- complete1(T,Acc,Bacc);
-
- complete1([{bits,N,Val}|T],Acc,Bacc) ->
- complete1(T,Acc,complete_update_byte(Bacc,Val,N));
-
- complete1([{bit,Val}|T],Acc,Bacc) ->
- complete1(T,Acc,complete_update_byte(Bacc,Val,1));
-
- complete1([align|T],Acc,[]) ->
- complete1(T,Acc,[]);
- complete1([align|T],Acc,Bacc) ->
- complete1(T,[Acc|complete_bytes(Bacc)],[]);
- complete1([{0,Bin}|T],Acc,[]) when is_binary(Bin) ->
- complete1(T,[Acc|Bin],[]);
- complete1([{Unused,Bin}|T],Acc,[]) when is_integer(Unused),is_binary(Bin) ->
- Size = size(Bin)-1,
- <<Bs:Size/binary,B>> = Bin,
- NumBits = 8-Unused,
- complete1(T,[Acc|Bs],[[B bsr Unused]|NumBits]);
- complete1([{Unused,Bin}|T],Acc,Bacc) when is_integer(Unused),is_binary(Bin) ->
- Size = size(Bin)-1,
- <<Bs:Size/binary,B>> = Bin,
- NumBits = 8 - Unused,
- Bf = complete_bytes(Bacc),
- complete1(T,[Acc|[Bf,Bs]],[[B bsr Unused]|NumBits]).
-
-
- complete_update_byte([],Val,Len) ->
- complete_update_byte([[0]|0],Val,Len);
- complete_update_byte([[Byte|Bacc]|NumBits],Val,Len) when NumBits + Len == 8 ->
- [[0,((Byte bsl Len) + Val) band 255|Bacc]|0];
- complete_update_byte([[Byte|Bacc]|NumBits],Val,Len) when NumBits + Len > 8 ->
- Rem = 8 - NumBits,
- Rest = Len - Rem,
- complete_update_byte([[0,((Byte bsl Rem) + (Val bsr Rest)) band 255 |Bacc]|0],Val,Rest);
- complete_update_byte([[Byte|Bacc]|NumBits],Val,Len) ->
- [[((Byte bsl Len) + Val) band 255|Bacc]|NumBits+Len].
-
-
- complete_bytes([[Byte|Bacc]|0]) ->
- lists:reverse(Bacc);
- complete_bytes([[Byte|Bacc]|NumBytes]) ->
- lists:reverse([(Byte bsl (8-NumBytes)) band 255|Bacc]);
- complete_bytes([]) ->
- [].
+ erlang_complete(L).
-else.
-%% asn1-1.6.8.1_dev
-%% complete(L) ->
-%% case catch port_control(asn1_driver_port,1,L) of
-%% Bin when is_binary(Bin) ->
-%% Bin;
-%% List when is_list(List) -> handle_error(List,L);
-%% {'EXIT',{badarg,Reason}} ->
-%% asn1rt_driver_handler:load_driver(),
-%% receive
-%% driver_ready ->
-%% case catch port_control(asn1_driver_port,1,L) of
-%% Bin2 when is_binary(Bin2) -> Bin2;
-%% List when is_list(List) -> handle_error(List,L);
-%% {'EXIT',Reason2={badarg,_R}} ->
-%% exit({"failed to call driver probably due to bad asn1 value",Reason2});
-%% Reason2 -> exit(Reason2)
-%% end;
-%% {error,Error} -> % error when loading driver
-%% %% the driver could not be loaded
-%% exit(Error);
-%% Error={port_error,Reason} ->
-%% exit(Error)
-%% end;
-%% {'EXIT',Reason} ->
-%% exit(Reason)
-%% end.
-
-%% asn1-1.6.9
+%% asn1-1.7
complete(L) ->
- case catch control(?COMPLETE_ENCODE,L) of
- Bin when is_binary(Bin) ->
- Bin;
- List when is_list(List) -> handle_error(List,L);
- {'EXIT',{badarg,_Reason}} ->
- case asn1rt:load_driver() of
- ok ->
- case control(?COMPLETE_ENCODE,L) of
- Bin when is_binary(Bin) ->Bin;
- List when is_list(List) -> handle_error(List,L)
- end;
- Err ->
- Err
- end
+ case asn1rt_nif:encode_per_complete(L) of
+ {error, Reason} -> handle_error(Reason, L);
+ Else when is_binary(Else) -> Else
end.
-
handle_error([],_)->
exit({error,{asn1,{"memory allocation problem in driver"}}});
-handle_error("1",L) -> % error in complete in driver
+handle_error($1,L) -> % error in complete in driver
exit({error,{asn1,L}});
handle_error(ErrL,L) ->
exit({error,{asn1,ErrL,L}}).
-%% asn1-1.6.9
-control(Cmd, Data) ->
- Port = asn1rt_driver_handler:client_port(),
- erlang:port_control(Port, Cmd, Data).
-
-endif.
diff --git a/lib/asn1/test/asn1.cover b/lib/asn1/test/asn1.cover
index 589a8b7e3d..ad3a0f3db9 100644
--- a/lib/asn1/test/asn1.cover
+++ b/lib/asn1/test/asn1.cover
@@ -1,2 +1,3 @@
{incl_app,asn1,details}.
+{excl_mods, asn1, [asn1rt_nif]}. \ No newline at end of file
diff --git a/lib/asn1/test/asn1_SUITE.erl.src b/lib/asn1/test/asn1_SUITE.erl.src
index 582ccd877c..124ee2d2bb 100644
--- a/lib/asn1/test/asn1_SUITE.erl.src
+++ b/lib/asn1/test/asn1_SUITE.erl.src
@@ -2036,11 +2036,7 @@ rtUI(Config) ->
?line {ok,_} = asn1rt:info('Prim'),
?line ok = asn1ct:compile(filename:join(DataDir,"Prim"),[?PER]),
- ?line {ok,_} = asn1rt:info('Prim'),
-
- ?line ok = asn1rt:load_driver(),
- ?line ok = asn1rt:load_driver(),
- ?line ok = asn1rt:unload_driver().
+ ?line {ok,_} = asn1rt:info('Prim').
testROSE(suite) -> [];
testROSE(Config) ->
@@ -2236,8 +2232,10 @@ test_compile_options(Config) ->
?line ok = test_compile_options:path(Config),
?line ok = test_compile_options:noobj(Config),
?line ok = test_compile_options:record_name_prefix(Config),
- ?line ok = test_compile_options:verbose(Config)
+ ?line ok = test_compile_options:verbose(Config),
+ ?line ok = test_compile_options:warnings_as_errors(Config)
end.
+
testDoubleEllipses(suite) -> [];
testDoubleEllipses(Config) ->
?line testDoubleEllipses:compile(Config,?BER,[]),
diff --git a/lib/asn1/test/asn1_SUITE_data/DirectoryAbstractService.asn b/lib/asn1/test/asn1_SUITE_data/DirectoryAbstractService.asn
index 5a5d310729..5a5d310729 100755..100644
--- a/lib/asn1/test/asn1_SUITE_data/DirectoryAbstractService.asn
+++ b/lib/asn1/test/asn1_SUITE_data/DirectoryAbstractService.asn
diff --git a/lib/asn1/test/asn1_SUITE_data/InformationFramework.asn b/lib/asn1/test/asn1_SUITE_data/InformationFramework.asn
index ef236e98a9..ef236e98a9 100755..100644
--- a/lib/asn1/test/asn1_SUITE_data/InformationFramework.asn
+++ b/lib/asn1/test/asn1_SUITE_data/InformationFramework.asn
diff --git a/lib/asn1/test/asn1_SUITE_data/LDAP.asn1 b/lib/asn1/test/asn1_SUITE_data/LDAP.asn1
index 4d845942e1..4d845942e1 100755..100644
--- a/lib/asn1/test/asn1_SUITE_data/LDAP.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/LDAP.asn1
diff --git a/lib/asn1/test/asn1_SUITE_data/Nortel.asn b/lib/asn1/test/asn1_SUITE_data/Nortel.asn
index a27c78a0b5..a27c78a0b5 100755..100644
--- a/lib/asn1/test/asn1_SUITE_data/Nortel.asn
+++ b/lib/asn1/test/asn1_SUITE_data/Nortel.asn
diff --git a/lib/asn1/test/asn1_SUITE_data/UpperBounds.asn b/lib/asn1/test/asn1_SUITE_data/UpperBounds.asn
index 247260495b..247260495b 100755..100644
--- a/lib/asn1/test/asn1_SUITE_data/UpperBounds.asn
+++ b/lib/asn1/test/asn1_SUITE_data/UpperBounds.asn
diff --git a/lib/asn1/test/asn1_SUITE_data/UsefulDefinitions.asn b/lib/asn1/test/asn1_SUITE_data/UsefulDefinitions.asn
index d9601bb7d0..d9601bb7d0 100755..100644
--- a/lib/asn1/test/asn1_SUITE_data/UsefulDefinitions.asn
+++ b/lib/asn1/test/asn1_SUITE_data/UsefulDefinitions.asn
diff --git a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-CommonDataTypes.asn b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-CommonDataTypes.asn
index e3f6e83d6b..e3f6e83d6b 100755..100644
--- a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-CommonDataTypes.asn
+++ b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-CommonDataTypes.asn
diff --git a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-Constants.asn b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-Constants.asn
index 1411d455b7..1411d455b7 100755..100644
--- a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-Constants.asn
+++ b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-Constants.asn
diff --git a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-Containers.asn b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-Containers.asn
index fb08451103..fb08451103 100755..100644
--- a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-Containers.asn
+++ b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-Containers.asn
diff --git a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-IEs.asn b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-IEs.asn
index 848d8f6099..848d8f6099 100755..100644
--- a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-IEs.asn
+++ b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-IEs.asn
diff --git a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Contents.asn b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Contents.asn
index 9ecfa688a2..9ecfa688a2 100755..100644
--- a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Contents.asn
+++ b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Contents.asn
diff --git a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Discriptions.asn b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Discriptions.asn
index b9be9934e4..b9be9934e4 100755..100644
--- a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Discriptions.asn
+++ b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Discriptions.asn
diff --git a/lib/asn1/test/asn1_bin_v2_particular_SUITE.erl.src b/lib/asn1/test/asn1_bin_v2_particular_SUITE.erl.src
index abd21b0d78..4c3c8c7808 100644
--- a/lib/asn1/test/asn1_bin_v2_particular_SUITE.erl.src
+++ b/lib/asn1/test/asn1_bin_v2_particular_SUITE.erl.src
@@ -11,37 +11,219 @@ smp(Config) ->
?line Msg = {initiatingMessage, testNBAPsystem:cell_setup_req_msg()},
?line ok = testNBAPsystem:compile(Config,per_bin,[optimize]),
-
- Parent = self(),
- ?line ok = asn1rt:load_driver(),
-
- smp2(Parent,NumOfProcs,Msg,2),
+ enc_dec(NumOfProcs,Msg,2),
N = 10000,
- ?line {Time1,ok} = timer:tc(?MODULE,smp2,[Parent,NumOfProcs,Msg, N]),
- ?line {Time1S,ok} = timer:tc(?MODULE,sequential,[NumOfProcs * N,Msg]),
+ ?line {Time1,ok} = timer:tc(?MODULE,enc_dec,[NumOfProcs,Msg, N]),
+ ?line {Time1S,ok} = timer:tc(?MODULE,enc_dec,[1, Msg, NumOfProcs * N]),
- ?line ok = testNBAPsystem:compile(Config,ber_bin,[optimize,driver]),
- ?line {Time2,ok} = timer:tc(?MODULE,smp2,[Parent,NumOfProcs,Msg, N]),
+ ?line ok = testNBAPsystem:compile(Config,ber_bin,[optimize,nif]),
+ ?line {Time3,ok} = timer:tc(?MODULE,enc_dec,[NumOfProcs,Msg, N]),
- ?line {Time2S,ok} = timer:tc(?MODULE,sequential,[NumOfProcs * N,Msg]),
+ ?line {Time3S,ok} = timer:tc(?MODULE,enc_dec,[1, Msg, NumOfProcs * N]),
- {comment,lists:flatten(io_lib:format("Encode/decode time parallell with ~p cores: ~p [microsecs]~nEncode/decode time sequential: ~p [microsecs]",[NumOfProcs,Time1+Time2,Time1S+Time2S]))};
+ {comment,lists:flatten(
+ io_lib:format(
+ "Encode/decode time parallell with ~p cores: ~p [microsecs]~n"
+ "Encode/decode time sequential: ~p [microsecs]",
+ [NumOfProcs,Time1+Time3,Time1S+Time3S]))};
false ->
{skipped,"No smp support"}
end.
-smp2(Parent,NumOfProcs,Msg, N) ->
- Pids = [spawn_link(fun() -> worker(Msg,Parent, N) end)
- || _ <- lists:seq(1,NumOfProcs)],
- ?line ok = wait_pids(Pids).
+per_performance(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ NifDir = filename:join(PrivDir,"nif"),
+ ErlDir = filename:join(PrivDir,"erl"),
+ file:make_dir(NifDir),file:make_dir(ErlDir),
+
+ ?line Msg = {initiatingMessage, testNBAPsystem:cell_setup_req_msg()},
+ ?line ok = testNBAPsystem:compile([{priv_dir,NifDir}|Config],per_bin,
+ [optimize]),
+ ?line ok = testNBAPsystem:compile([{priv_dir,ErlDir}|Config],per_bin,
+ []),
+
+ Modules = ['NBAP-CommonDataTypes',
+ 'NBAP-Constants',
+ 'NBAP-Containers',
+ 'NBAP-IEs',
+ 'NBAP-PDU-Contents',
+ 'NBAP-PDU-Discriptions'],
+
+
+ PreNif = fun() ->
+ code:add_patha(NifDir),
+ lists:foreach(fun(M) ->
+ code:purge(M),
+ code:load_file(M)
+ end,Modules)
+ end,
+
+ PreErl = fun() ->
+ code:add_patha(ErlDir),
+ lists:foreach(fun(M) ->
+ code:purge(M),
+ code:load_file(M)
+ end,Modules)
+ end,
+
+ Func = fun() ->
+ element(1,timer:tc(
+ asn1_wrapper,encode,['NBAP-PDU-Discriptions',
+ 'NBAP-PDU',
+ Msg]))
+ end,
+
+ nif_vs_erlang_performance({{{PreNif,Func},{PreErl,Func}},100000,32}).
+
+ber_performance(Config) ->
+
+ ?line Msg = {initiatingMessage, testNBAPsystem:cell_setup_req_msg()},
+ ?line ok = testNBAPsystem:compile(Config,ber_bin,[optimize,nif]),
+
+
+ BerFun = fun() ->
+ {ok,B} = asn1_wrapper:encode('NBAP-PDU-Discriptions',
+ 'NBAP-PDU', Msg),
+ asn1_wrapper:decode(
+ 'NBAP-PDU-Discriptions',
+ 'NBAP-PDU',
+ B)
+ end,
+ nif_vs_erlang_performance({BerFun,100000,32}).
+
+cert_pem_performance(Config) when is_list(Config) ->
+ cert_pem_performance({100000, 32});
+cert_pem_performance({N,S}) ->
+ nif_vs_erlang_performance({fun cert_pem/0,N,S}).
+
+dsa_pem_performance(Config) when is_list(Config) ->
+ cert_pem_performance({100000, 32});
+dsa_pem_performance({N,S}) ->
+ nif_vs_erlang_performance({fun dsa_pem/0,N,S}).
+
+
+nif_vs_erlang_performance({{TC1,TC2},N,Sched}) ->
+ random:seed({123,456,789}),
+ io:format("Running a ~p sample with ~p max procs...~n~n",[N,Sched]),
+
+ {True,False} = exec(TC1,TC2,Sched,N+1),
+
+ io:format("~ndone!~n"),
+
+ io:format("~n"),TStats = print_stats(strip(True,N div 20)),
+ io:format("~n"),FStats = print_stats(strip(False,N div 20)),
+ Str = io_lib:format("~nNifs are ~.3f% faster than erlang!~n",
+ [(element(2,FStats) - element(2,TStats)) /
+ element(2,FStats) * 100]),
+ io:format(Str),
+ {comment, lists:flatten(Str)};
+nif_vs_erlang_performance({T,N,Sched}) ->
+ PTC1 = fun() ->
+ application:set_env(asn1, nif_loadable, true)
+ end,
+ PTC2 = fun() ->
+ application:set_env(asn1, nif_loadable, false)
+ end,
+ TC = fun() ->
+ element(1,timer:tc(T))
+ end,
+ nif_vs_erlang_performance({{{PTC1,TC},{PTC2,TC}},N,Sched}).
+
+
+print_stats(Data) ->
+ Length = length(Data),
+ Mean = lists:sum(Data) / Length,
+ Variance = lists:foldl(fun(N,Acc) -> math:pow(N - Mean, 2)+Acc end, 0, Data),
+ StdDev = math:sqrt(Variance / Length),
+ Median = lists:nth(round(Length/2),Data),
+ Min = lists:min(Data),
+ Max = lists:max(Data),
+ if Length < 20 ->
+ io:format("Data: ~w~n",[Data]);
+ true ->
+ ok
+ end,
+ io:format("Length: ~p~nMean: ~p~nStdDev: ~p~nMedian: ~p~nMin: ~p~nMax: ~p~n",
+ [Length,Mean,StdDev,Median,Min,Max]),
+ {Length,Mean,StdDev,Median,Min,Max}.
+
+collect(Acc) ->
+ receive
+ {Tag,Val} ->
+ Prev = proplists:get_value(Tag,Acc,[]),
+ collect(lists:keystore(Tag,1,Acc,{Tag,[Val|Prev]}))
+ after 100 ->
+ Acc
+ end.
+
+exec(One,Two,Max,N) ->
+ exec(One,Two,Max,N,{[],[]}).
+exec(_,_,_,1,{D1,D2}) ->
+ {lists:flatten(D1),lists:flatten(D2)};
+exec({PreOne,One} = O,{PreTwo,Two} = T,MaxProcs, N, {D1,D2}) ->
+ Num = random:uniform(round(N/2)),
+ if Num rem 3 == 0 ->
+ timer:sleep(Num rem 1000);
+ true ->
+ ok
+ end,
+ Procs = random:uniform(MaxProcs),
+ io:format("\tBatch: ~p items in ~p processes, ~p left~n",[Num,Procs,N-Num]),
+ if Num rem 2 == 1 ->
+ erlang:garbage_collect(),
+ PreOne(),
+ MoreOne = pexec(One, Num, Procs, []),
+ erlang:garbage_collect(),
+ PreTwo(),
+ MoreTwo = pexec(Two, Num, Procs, []);
+ true ->
+ erlang:garbage_collect(),
+ PreTwo(),
+ MoreTwo = pexec(Two, Num, Procs, []),
+ erlang:garbage_collect(),
+ PreOne(),
+ MoreOne = pexec(One, Num, Procs, [])
+ end,
+ exec(O,T,MaxProcs,N-Num,{[MoreOne|D1],
+ [MoreTwo|D2]}).
+
+pexec(_Fun, _, 0, []) ->
+ [];
+pexec(Fun, _, 0, [{Ref,Pid}|Rest]) ->
+ receive
+ {data,D} ->
+ [D|pexec(Fun,0,0,[{Ref,Pid}|Rest])];
+ {'DOWN', Ref, process, Pid, normal} ->
+ pexec(Fun, 0,0,Rest)
+ end;
+pexec(Fun, 0, 1, AccProcs) ->
+ pexec(Fun, 0, 0, AccProcs);
+pexec(Fun, N, 1, AccProcs) ->
+ [Fun()|pexec(Fun, N - 1, 1, AccProcs)];
+pexec(Fun, N, Procs, AccProcs) ->
+ S = self(),
+ Pid = spawn(fun() ->
+ S ! {data,pexec(Fun,N,1,[])}
+ end),
+ Ref = erlang:monitor(process, Pid),
+ pexec(Fun, N, Procs - 1, [{Ref,Pid}|AccProcs]).
-worker(Msg, Parent, N) ->
- %% io:format("smp worker ~p with ~p worker loops.~n",[self(), N]),
- worker_loop(N, Msg),
- Parent ! self().
+strip(Data,Num) ->
+ {_,R} = lists:split(Num,lists:sort(Data)),
+ element(2,lists:split(Num,lists:reverse(R))).
+
+faster(A,B) ->
+ (B - A)/B * 100.
+
+enc_dec(1, Msg, N) ->
+ worker_loop(N, Msg);
+enc_dec(NumOfProcs,Msg, N) ->
+ pforeach(fun(_) ->
+ worker_loop(N, Msg)
+ end, [I || I <- lists:seq(1,NumOfProcs)]).
worker_loop(0, _Msg) ->
ok;
@@ -50,28 +232,24 @@ worker_loop(N, Msg) ->
'NBAP-PDU',
Msg),
?line {ok,_Msg}=asn1_wrapper:decode('NBAP-PDU-Discriptions',
- 'NBAP-PDU',
- B),
+ 'NBAP-PDU',
+ B),
worker_loop(N - 1, Msg).
-wait_pids([]) ->
- ok;
-wait_pids(Pids) ->
+pforeach(Fun, List) ->
+ pforeach(Fun, List, []).
+pforeach(Fun, [], [{Pid,Ref}|Pids]) ->
receive
- Pid when is_pid(Pid) ->
- ?line true = lists:member(Pid,Pids),
- Others = lists:delete(Pid,Pids),
- io:format("wait_pid got ~p, still waiting for ~p\n",[Pid,Others]),
- wait_pids(Others);
- Err ->
- io:format("Err: ~p~n",[Err]),
- ?line exit(Err)
- end.
-
-sequential(N,Msg) ->
- %%io:format("sequential encode/decode with N = ~p~n",[N]),
- worker_loop(N,Msg).
+ {'DOWN', Ref, process, Pid, normal} ->
+ pforeach(Fun, [], Pids)
+ end;
+pforeach(Fun, [H|T], Pids) ->
+ Pid = spawn(fun() -> Fun(H) end),
+ Ref = erlang:monitor(process, Pid),
+ pforeach(Fun, T, [{Pid, Ref}|Pids]);
+pforeach(_Fun,[],[]) ->
+ ok.
-record('InitiatingMessage',{procedureCode,criticality,value}).
-record('Iu-ReleaseCommand',{first,second}).
@@ -93,3 +271,21 @@ ticket7904(Config) ->
?line {ok,_} = 'RANAPextract1':encode('InitiatingMessage', Val1),
asn1rt:unload_driver(),
?line {ok,_} = 'RANAPextract1':encode('InitiatingMessage', Val1).
+
+cert_pem() ->
+ 'OTP-PUB-KEY':decode('Certificate',<<48,130,3,184,48,130,3,33,160,3,2,1,2,2,1,1,48,13,6,9,42,134,72,134,247,13,1,1,5,5,0,48,129,131,49,14,48,12,6,3,85,4,3,19,5,111,116,112,67,65,49,19,48,17,6,3,85,4,11,19,10,69,114,108,97,110,103,32,79,84,80,49,20,48,18,6,3,85,4,10,19,11,69,114,105,99,115,115,111,110,32,65,66,49,11,48,9,6,3,85,4,6,19,2,83,69,49,18,48,16,6,3,85,4,7,19,9,83,116,111,99,107,104,111,108,109,49,37,48,35,6,9,42,134,72,134,247,13,1,9,1,22,22,112,101,116,101,114,64,101,114,105,120,46,101,114,105,99,115,115,111,110,46,115,101,48,30,23,13,48,56,48,49,48,57,48,56,50,57,51,48,90,23,13,49,55,49,49,49,55,48,56,50,57,51,48,90,48,129,132,49,15,48,13,6,3,85,4,3,19,6,99,108,105,101,110,116,49,19,48,17,6,3,85,4,11,19,10,69,114,108,97,110,103,32,79,84,80,49,20,48,18,6,3,85,4,10,19,11,69,114,105,99,115,115,111,110,32,65,66,49,11,48,9,6,3,85,4,6,19,2,83,69,49,18,48,16,6,3,85,4,7,19,9,83,116,111,99,107,104,111,108,109,49,37,48,35,6,9,42,134,72,134,247,13,1,9,1,22,22,112,101,116,101,114,64,101,114,105,120,46,101,114,105,99,115,115,111,110,46,115,101,48,129,159,48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,3,129,141,0,48,129,137,2,129,129,0,245,56,68,254,220,239,193,190,63,221,182,60,67,77,121,163,214,136,137,183,139,8,166,30,100,27,45,17,126,58,15,173,151,218,75,224,148,14,22,164,10,100,186,183,104,175,197,97,96,182,146,150,106,129,140,100,194,106,90,62,133,233,155,46,155,33,101,220,83,193,182,232,240,99,253,249,114,8,159,172,143,77,179,132,229,205,29,110,185,233,224,52,25,149,249,100,80,229,199,125,23,106,146,233,159,26,13,8,161,206,221,43,240,149,42,45,194,190,85,6,235,152,220,219,160,32,144,67,2,3,1,0,1,163,130,1,55,48,130,1,51,48,9,6,3,85,29,19,4,2,48,0,48,11,6,3,85,29,15,4,4,3,2,5,224,48,29,6,3,85,29,14,4,22,4,20,26,59,44,5,72,211,158,214,23,34,30,241,125,27,123,115,93,163,231,120,48,129,179,6,3,85,29,35,4,129,171,48,129,168,128,20,6,171,128,52,58,164,184,118,178,189,157,46,40,229,109,145,222,125,1,155,161,129,140,164,129,137,48,129,134,49,17,48,15,6,3,85,4,3,19,8,101,114,108,97,110,103,67,65,49,19,48,17,6,3,85,4,11,19,10,69,114,108,97,110,103,32,79,84,80,49,20,48,18,6,3,85,4,10,19,11,69,114,105,99,115,115,111,110,32,65,66,49,18,48,16,6,3,85,4,7,19,9,83,116,111,99,107,104,111,108,109,49,11,48,9,6,3,85,4,6,19,2,83,69,49,37,48,35,6,9,42,134,72,134,247,13,1,9,1,22,22,112,101,116,101,114,64,101,114,105,120,46,101,114,105,99,115,115,111,110,46,115,101,130,1,1,48,33,6,3,85,29,17,4,26,48,24,129,22,112,101,116,101,114,64,101,114,105,120,46,101,114,105,99,115,115,111,110,46,115,101,48,33,6,3,85,29,18,4,26,48,24,129,22,112,101,116,101,114,64,101,114,105,120,46,101,114,105,99,115,115,111,110,46,115,101,48,13,6,9,42,134,72,134,247,13,1,1,5,5,0,3,129,129,0,93,11,112,227,121,15,121,179,247,135,110,216,17,197,84,18,149,166,147,142,190,178,0,209,190,0,142,233,144,100,194,205,220,182,73,204,108,42,95,23,48,63,4,120,239,42,194,25,184,35,117,107,96,229,18,45,76,122,125,40,171,210,132,50,146,178,160,55,17,35,255,208,114,30,47,55,185,154,155,165,204,180,14,143,20,234,6,234,201,225,72,235,5,87,61,255,250,23,217,1,144,246,98,221,223,102,49,168,177,13,70,241,26,27,254,251,217,14,244,18,242,197,151,50,186,214,15,42>>).
+
+dsa_pem() ->
+ 'OTP-PUB-KEY':decode('DSAPrivateKey',<<48,130,1,187,2,1,0,2,129,129,0,183,179,230,217,37,99,144,157,21,228,204,162,207,61,246,144,58,139,139,184,184,43,108,206,0,115,173,208,100,233,201,121,21,90,179,119,53,140,25,52,34,202,121,211,164,107,43,56,68,162,159,51,244,232,138,126,164,109,121,89,237,142,57,28,32,188,44,67,253,111,121,104,40,141,211,255,140,118,37,234,150,201,155,160,16,17,51,59,26,249,41,129,16,211,119,128,95,254,182,235,132,0,92,206,93,77,106,217,201,132,203,4,75,201,246,204,216,162,1,84,79,211,10,21,152,195,103,145,2,21,0,213,30,184,86,247,16,247,69,192,241,35,138,84,57,140,3,71,65,206,233,2,129,129,0,148,179,24,63,74,91,128,25,96,29,5,78,223,246,175,0,121,86,54,178,42,231,98,241,147,180,157,60,149,160,50,243,227,76,175,89,234,203,252,242,76,108,9,204,157,182,59,206,227,127,99,215,42,156,194,78,116,25,7,62,243,169,45,5,101,179,247,127,199,144,135,103,23,42,154,125,231,248,154,101,175,155,101,42,232,41,80,41,47,128,208,11,31,106,63,12,202,207,135,80,200,136,250,171,31,118,52,91,200,138,112,111,179,23,214,123,21,118,194,179,0,185,217,52,197,182,236,13,2,129,128,124,66,0,111,121,139,142,209,95,136,95,237,177,150,248,252,49,135,117,100,155,232,138,244,132,89,40,5,70,125,202,96,78,239,76,37,125,149,82,64,107,54,227,73,25,180,227,41,0,234,73,47,80,242,242,129,250,61,68,62,39,38,156,193,146,40,241,247,106,215,223,202,194,110,130,62,186,90,18,28,196,174,99,47,193,61,130,100,150,25,248,115,164,231,153,99,46,69,66,139,33,187,51,49,35,219,234,29,44,172,166,247,42,16,177,187,9,162,81,243,33,26,100,46,78,57,203,135,2,20,89,128,159,14,187,249,182,172,15,88,162,110,211,71,179,209,29,125,217,38>>),
+ 'OTP-PUB-KEY':decode('SubjectPublicKeyInfo',<<48,130,1,183,48,130,1,44,6,7,42,134,72,206,56,4,1,48,130,1,31,2,129,129,0,183,179,230,217,37,99,144,157,21,228,204,162,207,61,246,144,58,139,139,184,184,43,108,206,0,115,173,208,100,233,201,121,21,90,179,119,53,140,25,52,34,202,121,211,164,107,43,56,68,162,159,51,244,232,138,126,164,109,121,89,237,142,57,28,32,188,44,67,253,111,121,104,40,141,211,255,140,118,37,234,150,201,155,160,16,17,51,59,26,249,41,129,16,211,119,128,95,254,182,235,132,0,92,206,93,77,106,217,201,132,203,4,75,201,246,204,216,162,1,84,79,211,10,21,152,195,103,145,2,21,0,213,30,184,86,247,16,247,69,192,241,35,138,84,57,140,3,71,65,206,233,2,129,129,0,148,179,24,63,74,91,128,25,96,29,5,78,223,246,175,0,121,86,54,178,42,231,98,241,147,180,157,60,149,160,50,243,227,76,175,89,234,203,252,242,76,108,9,204,157,182,59,206,227,127,99,215,42,156,194,78,116,25,7,62,243,169,45,5,101,179,247,127,199,144,135,103,23,42,154,125,231,248,154,101,175,155,101,42,232,41,80,41,47,128,208,11,31,106,63,12,202,207,135,80,200,136,250,171,31,118,52,91,200,138,112,111,179,23,214,123,21,118,194,179,0,185,217,52,197,182,236,13,3,129,132,0,2,129,128,124,66,0,111,121,139,142,209,95,136,95,237,177,150,248,252,49,135,117,100,155,232,138,244,132,89,40,5,70,125,202,96,78,239,76,37,125,149,82,64,107,54,227,73,25,180,227,41,0,234,73,47,80,242,242,129,250,61,68,62,39,38,156,193,146,40,241,247,106,215,223,202,194,110,130,62,186,90,18,28,196,174,99,47,193,61,130,100,150,25,248,115,164,231,153,99,46,69,66,139,33,187,51,49,35,219,234,29,44,172,166,247,42,16,177,187,9,162,81,243,33,26,100,46,78,57,203,135>>),
+ 'OTP-PUB-KEY':decode('DSAParams',<<48,130,1,31,2,129,129,0,183,179,230,217,37,99,144,157,21,228,204,162,207,61,246,144,58,139,139,184,184,43,108,206,0,115,173,208,100,233,201,121,21,90,179,119,53,140,25,52,34,202,121,211,164,107,43,56,68,162,159,51,244,232,138,126,164,109,121,89,237,142,57,28,32,188,44,67,253,111,121,104,40,141,211,255,140,118,37,234,150,201,155,160,16,17,51,59,26,249,41,129,16,211,119,128,95,254,182,235,132,0,92,206,93,77,106,217,201,132,203,4,75,201,246,204,216,162,1,84,79,211,10,21,152,195,103,145,2,21,0,213,30,184,86,247,16,247,69,192,241,35,138,84,57,140,3,71,65,206,233,2,129,129,0,148,179,24,63,74,91,128,25,96,29,5,78,223,246,175,0,121,86,54,178,42,231,98,241,147,180,157,60,149,160,50,243,227,76,175,89,234,203,252,242,76,108,9,204,157,182,59,206,227,127,99,215,42,156,194,78,116,25,7,62,243,169,45,5,101,179,247,127,199,144,135,103,23,42,154,125,231,248,154,101,175,155,101,42,232,41,80,41,47,128,208,11,31,106,63,12,202,207,135,80,200,136,250,171,31,118,52,91,200,138,112,111,179,23,214,123,21,118,194,179,0,185,217,52,197,182,236,13>>),
+ 'OTP-PUB-KEY':decode('DSAPublicKey',<<2,129,128,124,66,0,111,121,139,142,209,95,136,95,237,177,150,248,252,49,135,117,100,155,232,138,244,132,89,40,5,70,125,202,96,78,239,76,37,125,149,82,64,107,54,227,73,25,180,227,41,0,234,73,47,80,242,242,129,250,61,68,62,39,38,156,193,146,40,241,247,106,215,223,202,194,110,130,62,186,90,18,28,196,174,99,47,193,61,130,100,150,25,248,115,164,231,153,99,46,69,66,139,33,187,51,49,35,219,234,29,44,172,166,247,42,16,177,187,9,162,81,243,33,26,100,46,78,57,203,135>>),
+ 'OTP-PUB-KEY':encode('DSAParams',{params,{'Dss-Parms',129000451850199666185842362389296595317127259539517666765336291347244303954511451744518587442120964433734460998523119938005801396466878889993179871123036311260456172022864663021425348874648247531097042575063545128239655736096045972718934778583429973433661785691086624069991876932064334822608460064613803976593,1216700114794736143432235288305776850295620488937,104420402274523493329542694749036577763086597934731674202966304958550599470165597750883637440049774107540742087494301536297571301945349213110548764383811017178451900599240379681904765817950545426764751538502808499880604633364255316249231153053427235538288687666086821781456733226598288985591031656134573747213}}),
+ 'OTP-PUB-KEY':encode(
+ 'SubjectPublicKeyInfo',
+ {'SubjectPublicKeyInfo',
+ {'AlgorithmIdentifier',
+ {1,2,840,10040,4,1},
+ <<48,130,1,31,2,129,129,0,183,179,230,217,37,99,144,157,21,228,204,162,207,61,246,144,58,139,139,184,184,43,108,206,0,115,173,208,100,233,201,121,21,90,179,119,53,140,25,52,34,202,121,211,164,107,43,56,68,162,159,51,244,232,138,126,164,109,121,89,237,142,57,28,32,188,44,67,253,111,121,104,40,141,211,255,140,118,37,234,150,201,155,160,16,17,51,59,26,249,41,129,16,211,119,128,95,254,182,235,132,0,92,206,93,77,106,217,201,132,203,4,75,201,246,204,216,162,1,84,79,211,10,21,152,195,103,145,2,21,0,213,30,184,86,247,16,247,69,192,241,35,138,84,57,140,3,71,65,206,233,2,129,129,0,148,179,24,63,74,91,128,25,96,29,5,78,223,246,175,0,121,86,54,178,42,231,98,241,147,180,157,60,149,160,50,243,227,76,175,89,234,203,252,242,76,108,9,204,157,182,59,206,227,127,99,215,42,156,194,78,116,25,7,62,243,169,45,5,101,179,247,127,199,144,135,103,23,42,154,125,231,248,154,101,175,155,101,42,232,41,80,41,47,128,208,11,31,106,63,12,202,207,135,80,200,136,250,171,31,118,52,91,200,138,112,111,179,23,214,123,21,118,194,179,0,185,217,52,197,182,236,13>>},
+ {0,
+ <<2,129,128,124,66,0,111,121,139,142,209,95,136,95,237,177,150,248,252,49,135,117,100,155,232,138,244,132,89,40,5,70,125,202,96,78,239,76,37,125,149,82,64,107,54,227,73,25,180,227,41,0,234,73,47,80,242,242,129,250,61,68,62,39,38,156,193,146,40,241,247,106,215,223,202,194,110,130,62,186,90,18,28,196,174,99,47,193,61,130,100,150,25,248,115,164,231,153,99,46,69,66,139,33,187,51,49,35,219,234,29,44,172,166,247,42,16,177,187,9,162,81,243,33,26,100,46,78,57,203,135>>}}).
diff --git a/lib/asn1/test/ber_decode_error.erl b/lib/asn1/test/ber_decode_error.erl
index 96d6545636..a566e0b07f 100644
--- a/lib/asn1/test/ber_decode_error.erl
+++ b/lib/asn1/test/ber_decode_error.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -45,6 +45,10 @@ run([]) ->
run([driver]) ->
%% test of OTP-4797, bad indata to driver does not cause an EXIT
?line {error,_Reason} = asn1rt:decode('Constructed','S3',[3,5]),
+ ok;
+run([nif]) ->
+ %% test of OTP-4797, bad indata to driver does not cause an EXIT
+ ?line {error,_Reason} = asn1rt:decode('Constructed','S3',[3,5]),
ok.
diff --git a/lib/asn1/test/testPrim.erl b/lib/asn1/test/testPrim.erl
index 97f99e7b1c..39c1e4d1d8 100644
--- a/lib/asn1/test/testPrim.erl
+++ b/lib/asn1/test/testPrim.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -37,21 +37,10 @@ compile(Config,Rules,Opt) ->
?line DataDir = ?config(data_dir,Config),
?line OutDir = ?config(priv_dir,Config),
?line true = code:add_patha(?config(priv_dir,Config)),
- case Opt of
- [optimize] ->
- ?line ok = asn1ct:compile(DataDir ++ "Prim",
- [Rules,optimize,{outdir,OutDir}]),
- ?line ok = asn1ct:compile(DataDir ++ "Real",
- [Rules,optimize,{outdir,OutDir}]);
- __ ->
- ?line ok = asn1ct:compile(DataDir ++ "Prim",
- [Rules,{outdir,OutDir}]),
- ?line ok = asn1ct:compile(DataDir ++ "Real",
- [Rules,{outdir,OutDir}])
- end.
-
-
-
+ ?line ok = asn1ct:compile(DataDir ++ "Prim",
+ [Rules,{outdir,OutDir}] ++ Opt),
+ ?line ok = asn1ct:compile(DataDir ++ "Real",
+ [Rules,{outdir,OutDir}] ++ Opt).
bool(Rules) ->
diff --git a/lib/asn1/test/test_compile_options.erl b/lib/asn1/test/test_compile_options.erl
index 5e027cdedb..a622d5bfd2 100644
--- a/lib/asn1/test/test_compile_options.erl
+++ b/lib/asn1/test/test_compile_options.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -24,7 +24,7 @@
-export([wrong_path/1,comp/2,path/1,ticket_6143/1,noobj/1,
- record_name_prefix/1,verbose/1]).
+ record_name_prefix/1,verbose/1,warnings_as_errors/1]).
%% OTP-5689
wrong_path(Config) ->
@@ -141,6 +141,43 @@ verbose(Config) when is_list(Config) ->
?line [] = test_server:capture_get(),
ok.
+warnings_as_errors(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir,Config),
+ Asn1File = filename:join([PrivDir,"WERROR.asn1"]),
+ OutFile = filename:join([PrivDir,"WERROR.erl"]),
+ Opts = [{outdir,PrivDir},noobj,verbose],
+
+ %% Generate WERR.asn to emit warning
+ %% Warning: Wrong format of type/value
+ %% false/{'Externalvaluereference',_,'WERR',noInvokeId}
+ Warn = <<"WERROR DEFINITIONS IMPLICIT TAGS ::=\n"
+ "\n"
+ "BEGIN\n"
+ "\n"
+ "InvokeId ::= CHOICE\n"
+ "{\n"
+ " present INTEGER,\n"
+ " absent NULL\n"
+ "}\n"
+ "\n"
+ "noInvokeId InvokeId ::= absent:NULL\n"
+ "\n"
+ "NoInvokeId InvokeId ::= {noInvokeId}\n"
+ "\n"
+ "END -- end of useful definitions.\n">>,
+ ?line ok = file:write_file(Asn1File, Warn),
+
+ %% Test warnings_as_errors compile
+ ?line false = filelib:is_regular(OutFile),
+ ?line {error, _} = asn1ct:compile(Asn1File, [warnings_as_errors|Opts]),
+ ?line false = filelib:is_regular(OutFile),
+
+ %% Test normal compile
+ ?line ok = asn1ct:compile(Asn1File, Opts),
+ ?line true = filelib:is_regular(OutFile),
+ ?line ok = file:delete(OutFile),
+ ok.
+
outfiles_check(OutDir) ->
outfiles_check(OutDir,outfiles1()).
diff --git a/lib/asn1/vsn.mk b/lib/asn1/vsn.mk
index 36e082c8ba..b1132155e6 100644
--- a/lib/asn1/vsn.mk
+++ b/lib/asn1/vsn.mk
@@ -1,2 +1,2 @@
#next version number to use is 1.6.15 | 1.7 | 2.0
-ASN1_VSN = 1.6.17
+ASN1_VSN = 1.6.18
diff --git a/lib/common_test/doc/src/Makefile b/lib/common_test/doc/src/Makefile
index 3ea6ae65d5..964f7c76c1 100644
--- a/lib/common_test/doc/src/Makefile
+++ b/lib/common_test/doc/src/Makefile
@@ -138,12 +138,6 @@ man: $(MAN6_FILES) $(MAN3_FILES) $(MAN1_FILES)
debug opt:
-#
-# checkout make.dep before generating new dependecies
-#
-#make_doc_depend: xml
-# docdepend > make.dep
-
clean clean_docs:
rm -f $(CT_XML_FILES)
rm -rf $(HTMLDIR)/*
@@ -176,12 +170,3 @@ release_docs_spec: docs
release_spec:
release_tests_spec:
-
-# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-include make.dep
-# DO NOT DELETE
-
-
diff --git a/lib/common_test/doc/src/common_test_app.xml b/lib/common_test/doc/src/common_test_app.xml
index c92566de37..f58b2ab0a9 100644
--- a/lib/common_test/doc/src/common_test_app.xml
+++ b/lib/common_test/doc/src/common_test_app.xml
@@ -133,9 +133,15 @@
{require,Name,Required} | {userdata,UserData} |
{silent_connections,Conns} | {stylesheet,CSSFile} |
{ct_hooks, CTHs}</v>
- <v> Time = MilliSec | {seconds,integer()} | {minutes,integer()}
- | {hours,integer()}</v>
+ <v> Time = TimeVal | TimeFunc</v>
+ <v> TimeVal = MilliSec | {seconds,integer()} | {minutes,integer()} |
+ {hours,integer()}</v>
+ <v> TimeFunc = {Mod,Func,Args} | Fun</v>
<v> MilliSec = integer()</v>
+ <v> Mod = atom()</v>
+ <v> Func = atom()</v>
+ <v> Args = list()</v>
+ <v> Fun = fun()</v>
<v> Required = Key | {Key,SubKeys}</v>
<v> Key = atom()</v>
<v> SubKeys = SubKey | [SubKey]</v>
@@ -144,7 +150,7 @@
<v> UserData = term()</v>
<v> Conns = [atom()]</v>
<v> CSSFile = string()</v>
- <v> CTHs = [CTHModule | {CTHModule, CTHInitArgs}]</v>
+ <v> CTHs = [CTHModule | {CTHModule, CTHInitArgs} | {CTHModule, CTHInitArgs, CTHPriority}]</v>
<v> CTHModule = atom()</v>
<v> CTHInitArgs = term()</v>
</type>
@@ -161,7 +167,9 @@
test case is allowed to take (including <c>init_per_testcase/2</c>
and <c>end_per_testcase/2</c>). If the timetrap time is
exceeded, the test case fails with reason
- <c>timetrap_timeout</c>.</p>
+ <c>timetrap_timeout</c>. If a <c>TimeFunc</c> function is specified,
+ it will be called initially and must return a value on
+ <c>TimeVal</c> format.</p>
<p>The <c>require</c> tag specifies configuration variables
that are required by test cases in the suite. If the required
@@ -248,7 +256,7 @@
</type>
<desc>
- <p> MANDATORY (only if one or more groups are defined) </p>
+ <p> OPTIONAL </p>
<p>This function is called before execution of a test case group.
It typically contains initialization which is common for
@@ -279,7 +287,7 @@
</type>
<desc>
- <p> MANDATORY (only if one or more groups are defined) </p>
+ <p> OPTIONAL </p>
<p>This function is called after the execution of a test case group is finished.
It is meant to be used for cleaning up after <c>init_per_group/2</c>.
@@ -353,9 +361,15 @@
<v> Info = {timetrap,Time} | {require,Required} |
{require,Name,Required} | {userdata,UserData} |
{silent_connections,Conns}</v>
- <v> Time = MilliSec | {seconds,integer()} | {minutes,integer()}
- | {hours,integer()}</v>
+ <v> Time = TimeVal | TimeFunc</v>
+ <v> TimeVal = MilliSec | {seconds,integer()} | {minutes,integer()} |
+ {hours,integer()}</v>
+ <v> TimeFunc = {Mod,Func,Args} | Fun</v>
<v> MilliSec = integer()</v>
+ <v> Mod = atom()</v>
+ <v> Func = atom()</v>
+ <v> Args = list()</v>
+ <v> Fun = fun()</v>
<v> Required = Key | {Key,SubKeys}</v>
<v> Key = atom()</v>
<v> SubKeys = SubKey | [SubKey]</v>
@@ -378,7 +392,9 @@
exceeded, the test case fails with reason
<c>timetrap_timeout</c>. <c>init_per_testcase/2</c>
and <c>end_per_testcase/2</c> are included in the
- timetrap time.</p>
+ timetrap time. If a <c>TimeFunc</c> function is specified,
+ it will be called before the test case (or <c>init_per_testcase/2</c>)
+ and must return a value on <c>TimeVal</c> format.</p>
<p>The <c>require</c> tag specifies configuration variables
that are required by the test case. If the required
diff --git a/lib/common_test/doc/src/config_file_chapter.xml b/lib/common_test/doc/src/config_file_chapter.xml
index 59151a73ec..6fc6638bf7 100644
--- a/lib/common_test/doc/src/config_file_chapter.xml
+++ b/lib/common_test/doc/src/config_file_chapter.xml
@@ -285,7 +285,7 @@
<c>{ok, Config}</c> - if the configuration variables are read successfully,
</item>
<item>
- <c>{error, Error, ErrorDetails}</c> - if the callback module fails to
+ <c>{error, {Error, ErrorDetails}}</c> - if the callback module fails to
proceed with the given configuration parameters.
</item>
</list>
@@ -422,14 +422,14 @@ stop()->
call(Client, Request)->
case whereis(?REGISTERED_NAME) of
undefined->
- {error, not_started, Request};
+ {error, {not_started, Request}};
Pid->
Pid ! {Client, Request},
receive
Reply->
{ok, Reply}
after 4000->
- {error, timeout, Request}
+ {error, {timeout, Request}}
end
end.
diff --git a/lib/common_test/doc/src/ct_hooks.xml b/lib/common_test/doc/src/ct_hooks.xml
index 7d5c9f4750..f9fc1858d0 100644
--- a/lib/common_test/doc/src/ct_hooks.xml
+++ b/lib/common_test/doc/src/ct_hooks.xml
@@ -81,12 +81,14 @@
<funcs>
<func>
- <name>Module:init(Id, Opts) -&gt; State</name>
+ <name>Module:init(Id, Opts) -&gt; {ok, State} |
+ {ok, State, Priority}</name>
<fsummary>Initiates the Common Test Hook</fsummary>
<type>
<v>Id = reference() | term()</v>
<v>Opts = term()</v>
<v>State = term()</v>
+ <v>Priority = integer()</v>
</type>
<desc>
@@ -103,6 +105,10 @@
if <seealso marker="#Module:id-1">id/1</seealso> is not implemented.
</p>
+ <p><c>Priority</c> is the relative priority of this hook. Hooks with a
+ lower priority will be executed first. If no priority is given,
+ it will be set to 0. </p>
+
<p>For details about when init is called see
<seealso marker="ct_hooks_chapter#scope">scope</seealso>
in the User's Guide.</p>
@@ -296,7 +302,7 @@
<p>Note that it is not possible to add CTH's here right now,
that feature might be added later,
- but it would right now break backwards compatability.</p>
+ but it would right now break backwards compatibility.</p>
</desc>
</func>
diff --git a/lib/common_test/doc/src/ct_hooks_chapter.xml b/lib/common_test/doc/src/ct_hooks_chapter.xml
index fc5ab48e1b..3b9620d0f2 100644
--- a/lib/common_test/doc/src/ct_hooks_chapter.xml
+++ b/lib/common_test/doc/src/ct_hooks_chapter.xml
@@ -94,9 +94,11 @@
<seealso marker="common_test#Module:init_per_group-2">
init_per_group/2</seealso>. <c>CTH</c> in this case can be either
only the module name of the CTH or a tuple with the module name and the
- initial arguments to the CTH. Eg:
+ initial arguments and optionally the hook priority of the CTH. Eg:
<c>{ct_hooks,[my_cth_module]}</c> or
- <c>{ct_hooks,[{my_cth_module,[{debug,true}]}]}</c></p>
+ <c>{ct_hooks,[{my_cth_module,[{debug,true}]}]}</c> or
+ <c>{ct_hooks,[{my_cth_module,[{debug,true}],500}]}</c>
+ </p>
<section>
<title>Overriding CTHs</title>
@@ -109,7 +111,16 @@
<c>id</c> in both places, Common Test knows that this CTH
has already been installed and will not try to install it again.</p>
</section>
-
+
+ <section>
+ <title>CTH Priority</title>
+ <p>By default each CTH installed will be executed in the order which
+ they are installed. This is not always wanted so common_test allows
+ the user to specify a priority for each hook. The priority can either
+ be specified in the CTH <seealso marker="ct_hooks#Module:init-2">init/2
+ </seealso> function or when installing the hook. The priority given at
+ installation will override the priority returned by the CTH. </p>
+ </section>
</section>
<marker id="scope"/>
@@ -331,7 +342,7 @@ id(Opts) ->
%% any common state.
init(Id, Opts) ->
{ok,D} = file:open(Id,[write]),
- #state{ file_handle = D, total = 0, data = [] }.
+ {ok, #state{ file_handle = D, total = 0, data = [] }}.
%% @doc Called before init_per_suite is called.
pre_init_per_suite(Suite,Config,State) ->
@@ -394,6 +405,38 @@ terminate(State) ->
ok.</code>
</section>
+ <marker id="builtin_cths"/>
+ <section>
+ <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.
+ Some of these are enabled by default when starting running common_test,
+ they can be disabled by setting <c>enable_builtin_hooks</c> to
+ <c>false</c> on the command line or in the test specification. In the
+ table below there is a list of all current CTHs which are delivered with
+ Common Test.</p>
+
+ <table>
+ <row>
+ <cell><em>CTH Name</em></cell>
+ <cell><em>Is Built-in</em></cell>
+ <cell><em>Description</em></cell>
+ </row>
+ <row>
+ <cell>cth_log_redirect</cell>
+ <cell>yes</cell>
+ <cell>Captures all error_logger and SASL logging events and prints them
+ to the current test case log. If an event can not be associated with a
+ testcase it will be printed in the common test framework log. This will
+ happen for testcases which are run in parallel and events which occur
+ inbetween testcases. You can configure the level of
+ <seealso marker="sasl:sasl_app">SASL</seealso> events report
+ using the normal SASL mechanisms. </cell>
+ </row>
+ </table>
+
+ </section>
+
</chapter>
diff --git a/lib/common_test/doc/src/ct_run.xml b/lib/common_test/doc/src/ct_run.xml
index 1ab563d74f..9045646733 100644
--- a/lib/common_test/doc/src/ct_run.xml
+++ b/lib/common_test/doc/src/ct_run.xml
@@ -83,7 +83,7 @@
<title>Run tests from command line</title>
<pre>
ct_run [-dir TestDir1 TestDir2 .. TestDirN] |
- [-suite Suite1 Suite2 .. SuiteN
+ [[-dir TestDir] -suite Suite1 Suite2 .. SuiteN
[[-group Group1 Group2 .. GroupN] [-case Case1 Case2 .. CaseN]]]
[-step [config | keep_inactive]]
[-config ConfigFile1 ConfigFile2 .. ConfigFileN]
@@ -92,6 +92,7 @@
[-decrypt_key Key] | [-decrypt_file KeyFile]
[-label Label]
[-logdir LogDir]
+ [-logopts LogOpts]
[-silent_connections [ConnType1 ConnType2 .. ConnTypeN]]
[-stylesheet CSSFile]
[-cover CoverCfgFile]
@@ -117,6 +118,7 @@
[-decrypt_key Key] | [-decrypt_file KeyFile]
[-label Label]
[-logdir LogDir]
+ [-logopts LogOpts]
[-allow_user_terms]
[-silent_connections [ConnType1 ConnType2 .. ConnTypeN]]
[-stylesheet CSSFile]
@@ -138,10 +140,11 @@
<pre>
ct_run -vts [-browser Browser]
[-dir TestDir1 TestDir2 .. TestDirN] |
- [-suite Suite [[-group Group] [-case Case]]]
+ [[dir TestDir] -suite Suite [[-group Group] [-case Case]]]
[-config ConfigFile1 ConfigFile2 .. ConfigFileN]
[-userconfig CallbackModule1 ConfigString1 and CallbackModule2
ConfigString2 and .. and CallbackModuleN ConfigStringN]
+ [-logopts LogOpts]
[-decrypt_key Key] | [-decrypt_file KeyFile]
[-include InclDir1 InclDir2 .. InclDirN]
[-no_auto_compile]
diff --git a/lib/common_test/doc/src/filestruct.gif b/lib/common_test/doc/src/filestruct.gif
index 2b06833d0b..2b06833d0b 100755..100644
--- a/lib/common_test/doc/src/filestruct.gif
+++ b/lib/common_test/doc/src/filestruct.gif
Binary files differ
diff --git a/lib/common_test/doc/src/make.dep b/lib/common_test/doc/src/make.dep
deleted file mode 100644
index e34075888d..0000000000
--- a/lib/common_test/doc/src/make.dep
+++ /dev/null
@@ -1,27 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: basics_chapter.tex book.tex common_test_app.tex \
- config_file_chapter.tex cover_chapter.tex \
- ct.tex ct_cover.tex ct_ftp.tex ct_master.tex \
- ct_master_chapter.tex ct_rpc.tex ct_snmp.tex \
- ct_ssh.tex ct_telnet.tex dependencies_chapter.tex \
- event_handler_chapter.tex example_chapter.tex \
- install_chapter.tex part.tex ref_man.tex run_test.tex \
- run_test_chapter.tex test_structure_chapter.tex \
- unix_telnet.tex why_test_chapter.tex write_test_chapter.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/common_test/doc/src/notes.xml b/lib/common_test/doc/src/notes.xml
index 826b3c598d..af96ef621f 100644
--- a/lib/common_test/doc/src/notes.xml
+++ b/lib/common_test/doc/src/notes.xml
@@ -32,6 +32,229 @@
<file>notes.xml</file>
</header>
+<section><title>Common_Test 1.5.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ An error in how comments are colored in the test suite
+ overview html log file has been corrected. As result, a
+ new framework callback function, format_comment/1, has
+ been introduced.</p>
+ <p>
+ Own Id: OTP-9237</p>
+ </item>
+ <item>
+ <p>
+ Automatically generated init- and end-configuration
+ functions for test case groups caused incorrect execution
+ order of test cases. This has been corrected.</p>
+ <p>
+ Own Id: OTP-9369</p>
+ </item>
+ <item>
+ <p>
+ If multiple directories were specified with the 'logdir'
+ flag/option, Common Test would crash. This has been fixed
+ so that an error is properly reported instead.</p>
+ <p>
+ Own Id: OTP-9370</p>
+ </item>
+ <item>
+ <p>
+ If ct:log/2 was called with bad arguments, this could
+ cause the Common Test IO handling process to crash. This
+ fault has been corrected.</p>
+ <p>
+ Own Id: OTP-9371 Aux Id: OTP-8933 </p>
+ </item>
+ <item>
+ <p>
+ A bug has been fixed that made Test Server call the
+ end_tc/3 framework function with an incorrect module name
+ as first argument.</p>
+ <p>
+ Own Id: OTP-9379 Aux Id: seq11863 </p>
+ </item>
+ <item>
+ <p>
+ If a timetrap timeout occured during execution of of a
+ function in a lib module (i.e. a function called directly
+ or indirectly from a test case), the Suite argument in
+ the end_tc/3 framework callback function would not
+ correctly contain the name of the test suite, but the lib
+ module. (This would only happen if the lib module was
+ compiled with ct.hrl included). This error has been
+ solved.</p>
+ <p>
+ Own Id: OTP-9398</p>
+ </item>
+ <item>
+ <p>
+ Corrections of the vts mode. It will now report errors
+ (about e.g. incorrect config files) instead of crashing
+ or hanging. Furthermore, the requirement that the test
+ directory name must have a "_test" suffix has been
+ removed. Also, a workaround has been implemented for the
+ limitation that the file browser (in many web browsers)
+ will only return the basic file name, not the full
+ directory path (which made it impossible to have config
+ files in other directories than the main test directory).</p>
+ <p>
+ Own Id: OTP-9429</p>
+ </item>
+ <item>
+ <p>
+ Add a proplist() type</p>
+ <p>
+ Recently I was adding specs to an API and found that
+ there is no canonical proplist() type defined. (Thanks to
+ Ryan Zezeski)</p>
+ <p>
+ Own Id: OTP-9499</p>
+ </item>
+ <item>
+ <p>
+ It is now possible to use the 'step' flag/option to run
+ the debugger for test suites that contain test case
+ groups. This previously caused Common Test to crash. If
+ 'step config' is specified, breakpoints are now also
+ automatically set on init_per_group and end_per_group.
+ Note that breakpoints are always set automatically on
+ test case functions and this is true also for grouped
+ cases.</p>
+ <p>
+ Own Id: OTP-9518 Aux Id: OTP-8933 </p>
+ </item>
+ <item>
+ <p>
+ The test index page was not refreshed at the start of
+ each test suite which made it impossible to follow test
+ execution by means of refreshing the browser window (no
+ links to follow). This has been fixed.</p>
+ <p>
+ Own Id: OTP-9520 Aux Id: OTP-8933 </p>
+ </item>
+ <item>
+ <p>
+ If a test suite would start with a test case group
+ defined without the init_per_group/2 and end_per_group/2
+ function, init_per_suite/1 would not execute initially
+ and logging of the test run would fail. This error has
+ been fixed.</p>
+ <p>
+ Own Id: OTP-9584</p>
+ </item>
+ <item>
+ <p>
+ The "Missing Suites" link from the top level index page
+ was incorrect and has been fixed.</p>
+ <p>
+ Own Id: OTP-9592</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Various corrections and updates to improve the handling
+ and reporting of errors.</p>
+ <p>
+ Own Id: OTP-8933</p>
+ </item>
+ <item>
+ <p>
+ The dir and suite start option can now be used in
+ combination. E.g. executing my_SUITE in directory
+ my_tests can either be specified as "ct_run -suite
+ my_tests/my_SUITE" or as "ct_run -dir my_tests -suite
+ my_SUITE". Furthermore, the specification:
+ ct:run_test([{suite,["./my_SUITE"]},{testcase,t1}]) is
+ now interpreted as
+ ct:run_test([{suite,"./my_SUITE"},{testcase,t1}]), i.e.
+ only testcase t1 in test suite my_SUITE - not all cases -
+ will be executed.</p>
+ <p>
+ Own Id: OTP-9155</p>
+ </item>
+ <item>
+ <p>
+ A new option, 'logopts', has been introduced, to make it
+ possible to modify some aspects of the logging behaviour
+ in Common Test (or Test Server). For example, whenever an
+ io printout is made, test_server adds newline (\n) to the
+ end of the output string. This may not always be a
+ preferred action and can therefore be disabled by means
+ of "ct_run ... -logopts no_nl" (or ct:run_test([...,
+ {logopts,[no_nl]}])). A new framework callback function,
+ get_logopts/0, has been introduced (see the ct_framework
+ module for details).</p>
+ <p>
+ Own Id: OTP-9372 Aux Id: OTP-9396 </p>
+ </item>
+ <item>
+ <p>
+ A new option, 'logopts', has been introduced, to make it
+ possible to modify some aspects of the logging behaviour
+ in Common Test (or Test Server). For example, if the html
+ version of the test suite source code should not be
+ generated during the test run (and consequently be
+ unavailable in the log file system), the feature may be
+ disabled by means of "ct_run ... -logopts no_src" (or
+ ct:run_test([..., {logopts,[no_src]}])). A new framework
+ callback function, get_logopts/0, has been introduced
+ (see the ct_framework module for details).</p>
+ <p>
+ Own Id: OTP-9396 Aux Id: seq11869, OTP-9372 </p>
+ </item>
+ <item>
+ <p>
+ CT Hooks can now be assigned a priority. The priority of
+ a CTH determines when it should execute in relation to
+ other CTHs. The CTH with the lowest priority will be
+ executed first, CTHs with equal priority will be executed
+ in the order which they were installed.</p>
+ <p>
+ Own Id: OTP-9445</p>
+ </item>
+ <item>
+ <p>
+ It is now possible to use a tuple {M,F,A}, or a fun, as
+ timetrap specification in the suite info function or test
+ case info functions. The function must return a valid
+ timeout value, as documented in the common_test man page
+ and in the User's Guide.</p>
+ <p>
+ Own Id: OTP-9501 Aux Id: seq11894 </p>
+ </item>
+ <item>
+ <p>
+ A new built-in common test hook has been added which
+ captures error_logger and SASL event and prints them in
+ the testcase log. To disable this (and any other built-in
+ hooks) pass 'enable_builtin_hooks false' to common test.</p>
+ <p>
+ Own Id: OTP-9543</p>
+ </item>
+ <item>
+ <p>
+ Common Test now has the possibility to have built-in
+ hooks which are started by default when any test is run.
+ To disable built-in hooks pass 'enable_builtin_hooks
+ false' to common test. See the common test hooks
+ documentation for more details.</p>
+ <p>
+ Own Id: OTP-9564</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Common_Test 1.5.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/common_test/doc/src/run_test_chapter.xml b/lib/common_test/doc/src/run_test_chapter.xml
index e6fb85634f..57059f0ba2 100644
--- a/lib/common_test/doc/src/run_test_chapter.xml
+++ b/lib/common_test/doc/src/run_test_chapter.xml
@@ -128,6 +128,15 @@
<p><c>$ ct_run -suite $SYS1_TEST/setup_SUITE -case start stop</c></p>
<p><c>$ ct_run -suite $SYS1_TEST/setup_SUITE -group installation -case start stop</c></p>
+ <p>It is also possible to combine the <c>dir</c>, <c>suite</c> and <c>group/case</c> flags. E.g, to run
+ <c>x_SUITE</c> and <c>y_SUITE</c> in directory <c>testdir</c>:</p>
+
+ <p><c>$ ct_run -dir ./testdir -suite x_SUITE y_SUITE</c></p>
+
+ <p>This has the same effect as calling:</p>
+
+ <p><c>$ ct_run -suite ./testdir/x_SUITE ./testdir/y_SUITE</c></p>
+
<p>Other flags that may be used with <c>ct_run</c>:</p>
<list>
<item><c><![CDATA[-logdir <dir>]]></c>, specifies where the HTML log files are to be written.</item>
@@ -150,6 +159,8 @@
<seealso marker="event_handler_chapter#event_handling">event handlers</seealso> including start arguments.</item>
<item><c><![CDATA[-ct_hooks <ct_hooks>]]></c>, to install
<seealso marker="ct_hooks_chapter#installing">Common Test Hooks</seealso> including start arguments.</item>
+ <item><c><![CDATA[-enable_builtin_hooks <bool>]]></c>, to enable/disable
+ <seealso marker="ct_hooks_chapter#builtin_cths">Built-in Common Test Hooks</seealso>. Default is <c>true</c>.</item>
<item><c><![CDATA[-include]]></c>, specifies include directories (see above).</item>
<item><c><![CDATA[-no_auto_compile]]></c>, disables the automatic test suite compilation feature (see above).</item>
<item><c><![CDATA[-multiply_timetraps <n>]]></c>, extends <seealso marker="write_test_chapter#timetraps">timetrap
@@ -165,6 +176,8 @@
<item><c><![CDATA[-decrypt_file <key_file>]]></c>, points out a file containing a decryption key for
<seealso marker="config_file_chapter#encrypted_config_files">encrypted configuration files</seealso>.</item>
<item><c><![CDATA[-basic_html]]></c>, switches off html enhancements that might not be compatible with older browsers.</item>
+ <item><c><![CDATA[-logopts <opts>]]></c>, makes it possible to modify aspects of the logging behaviour, see
+ <seealso marker="run_test_chapter#logopts">Log options</seealso> below.</item>
</list>
<note><p>Directories passed to Common Test may have either relative or absolute paths.</p></note>
@@ -322,8 +335,9 @@
are to be executed by Common Test, and those functions only. If
the step option <c>config</c> is specified, breakpoints will
also be initially set on the configuration functions in the suite, i.e.
- <c>init_per_suite/1</c>, <c>end_per_suite/1</c>, <c>init_per_testcase/2</c>
- and <c>end_per_testcase/2</c>.</p>
+ <c>init_per_suite/1</c>, <c>end_per_suite/1</c>,
+ <c>init_per_group/2</c>, <c>end_per_group/2</c>,
+ <c>init_per_testcase/2</c> and <c>end_per_testcase/2</c>.</p>
<p>Common Test enables the Debugger auto attach feature, which means
that for every new interpreted test case function that starts to execute,
a new trace window will automatically pop up. (This is because each test
@@ -450,6 +464,8 @@
{ct_hooks, CTHModules}.
{ct_hooks, NodeRefs, CTHModules}.
+
+ {enable_builtin_hooks, Bool}.
</pre>
<p>Test terms:</p>
<pre>
@@ -488,7 +504,7 @@
LogDir = string()
EventHandlers = atom() | [atom()]
InitArgs = [term()]
- CTHModules = [CTHModule | {CTHModule, CTHInitArgs}]
+ CTHModules = [CTHModule | {CTHModule, CTHInitArgs} | {CTHModule, CTHInitArgs, CTHPriority}]
CTHModule = atom()
CTHInitArgs = term()
DirRef = DirAlias | Dir
@@ -631,7 +647,11 @@
<p>The minor log file contain full details of every single test
case, each one in a separate file. This way the files should
be easy to compare with previous test runs, even if the set of
- test cases change.</p>
+ test cases change. If SASL is running those logs will also be
+ printed there by the
+ <seealso marker="common_test:ct_hooks_chapter#builtin_cths">
+ cth_log_redirect built-in hook</seealso>.
+ </p>
<p>Which information goes where is user configurable via the
test server controller. Three threshold values determine what
@@ -644,6 +664,30 @@
to follow test progress simply by refreshing pages in the HTML browser.
Statistics totals are not presented until a test is complete however.</p>
+ <section>
+ <marker id="logopts"></marker>
+ <title>Log options</title>
+ <p>With the <c>logopts</c> start flag, it's possible to specify
+ options that modify some aspects of the logging behaviour.
+ Currently, the following options are available:</p>
+ <list>
+ <item><c>no_src</c></item>
+ <item><c>no_nl</c></item>
+ </list>
+ <p>With <c>no_src</c>, the html version of the test suite source
+ code will not be generated during the test run (and consequently
+ not be available in the log file system).</p>
+ <p>With <c>no_nl</c>, Common Test will not add a newline character
+ (\n) to the end of an output string that it receives from a call to e.g.
+ <c>io:format/2</c>, and which it prints to the test case log.</p>
+ <p>For example, if a test is started with:</p>
+ <p><c>$ ct_run -suite my_SUITE -logopts no_src</c></p>
+ <p>then printouts during the test made by successive calls to <c>io:format("x")</c>,
+ will appear in the test case log as:</p>
+ <p><c>xxx</c></p>
+ <p>instead of each <c>x</c> printed on a new line, which is the default behaviour.</p>
+ </section>
+
</section>
<section>
diff --git a/lib/common_test/doc/src/write_test_chapter.xml b/lib/common_test/doc/src/write_test_chapter.xml
index 3f9fdb7121..e35888e68f 100644
--- a/lib/common_test/doc/src/write_test_chapter.xml
+++ b/lib/common_test/doc/src/write_test_chapter.xml
@@ -280,6 +280,8 @@
the timetrap time is exceeded, the test case fails with
reason <c>timetrap_timeout</c>. Note that <c>init_per_testcase</c>
and <c>end_per_testcase</c> are included in the timetrap time.
+ Please see the <seealso marker="write_test_chapter#timetraps">Timetrap</seealso>
+ section for more details.
</p>
</item>
<tag><em><c>userdata</c></em></tag>
@@ -699,8 +701,8 @@
</section>
<section>
- <title>Timetrap timeouts</title>
<marker id="timetraps"></marker>
+ <title>Timetrap timeouts</title>
<p>The default time limit for a test case is 30 minutes, unless a
<c>timetrap</c> is specified either by the suite info function
or a test case info function. The timetrap timeout value defined
@@ -723,6 +725,13 @@
multipled by <c>multiply_timetraps</c>, and possibly scaled up if
<c>scale_timetraps</c> is enabled, the function <c>ct:sleep/1</c>
may be called.</p>
+ <p>A function (<c>fun</c> or <c>MFA</c>) may be specified as timetrap value
+ in the suite- and test case info function, e.g:</p>
+ <p><c>{timetrap,{test_utils,get_timetrap_value,[?MODULE,system_start]}}</c></p>
+ <p>The function will be called initially by Common Test (before execution
+ of the suite or the test case) and must return a time value such as an
+ integer (millisec), or a <c>{SecMinOrHourTag,Time}</c> tuple. More
+ information can be found in the <c>common_test</c> reference manual.</p>
</section>
<section>
@@ -818,6 +827,3 @@
</list>
</section>
</chapter>
-
-
-
diff --git a/lib/common_test/include/ct.hrl b/lib/common_test/include/ct.hrl
index aa1cc832cf..5a77108e1a 100644
--- a/lib/common_test/include/ct.hrl
+++ b/lib/common_test/include/ct.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -18,5 +18,4 @@
%%
-include_lib("test_server/include/test_server.hrl").
--compile({parse_transform,ct_line}).
diff --git a/lib/common_test/src/Makefile b/lib/common_test/src/Makefile
index 84b122b5e4..125aa828fb 100644
--- a/lib/common_test/src/Makefile
+++ b/lib/common_test/src/Makefile
@@ -40,7 +40,6 @@ RELSYSDIR = $(RELEASE_PATH)/lib/common_test-$(VSN)
# ----------------------------------------------------
MODULES= \
- ct_line \
ct \
ct_logs \
ct_framework \
@@ -69,9 +68,11 @@ MODULES= \
ct_config_xml \
ct_slave \
ct_hooks\
- ct_hooks_lock
+ ct_hooks_lock\
+ cth_log_redirect
TARGET_MODULES= $(MODULES:%=$(EBIN)/%)
+BEAM_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
ERL_FILES= $(MODULES:=.erl)
HRL_FILES = \
@@ -97,7 +98,7 @@ ERL_COMPILE_FLAGS += -pa ../ebin -I../include -I $(ERL_TOP)/lib/snmp/include/ \
# ----------------------------------------------------
TARGET_FILES = \
$(GEN_ERL_FILES:%.erl=$(EBIN)/%.$(EMULATOR)) \
- $(MODULES:%=$(EBIN)/%.$(EMULATOR)) \
+ $(BEAM_FILES) \
$(APP_TARGET) $(APPUP_TARGET)
APP_FILE= common_test.app
diff --git a/lib/common_test/src/common_test.app.src b/lib/common_test/src/common_test.app.src
index b42173f412..57606c01db 100644
--- a/lib/common_test/src/common_test.app.src
+++ b/lib/common_test/src/common_test.app.src
@@ -25,7 +25,6 @@
ct_framework,
ct_ftp,
ct_gen_conn,
- ct_line,
ct_logs,
ct_make,
ct_master,
diff --git a/lib/common_test/src/ct.erl b/lib/common_test/src/ct.erl
index 66da3ef742..69e15fa246 100644
--- a/lib/common_test/src/ct.erl
+++ b/lib/common_test/src/ct.erl
@@ -148,10 +148,10 @@ run(TestDirs) ->
%%% {auto_compile,Bool} | {multiply_timetraps,M} | {scale_timetraps,Bool} |
%%% {repeat,N} | {duration,DurTime} | {until,StopTime} |
%%% {force_stop,Bool} | {decrypt,DecryptKeyOrFile} |
-%%% {refresh_logs,LogDir} | {basic_html,Bool} |
-%%% {ct_hooks, CTHs}
+%%% {refresh_logs,LogDir} | {logopts,LogOpts} | {basic_html,Bool} |
+%%% {ct_hooks, CTHs} | {enable_builtin_hooks,Bool}
%%% TestDirs = [string()] | string()
-%%% Suites = [string()] | string()
+%%% Suites = [string()] | [atom()] | string() | atom()
%%% Cases = [atom()] | atom()
%%% Groups = [atom()] | atom()
%%% TestSpecs = [string()] | string()
@@ -177,6 +177,8 @@ run(TestDirs) ->
%%% DecryptKeyOrFile = {key,DecryptKey} | {file,DecryptFile}
%%% DecryptKey = string()
%%% DecryptFile = string()
+%%% LogOpts = [LogOpt]
+%%% LogOpt = no_nl | no_src
%%% CTHs = [CTHModule | {CTHModule, CTHInitArgs}]
%%% CTHModule = atom()
%%% CTHInitArgs = term()
diff --git a/lib/common_test/src/ct_config.erl b/lib/common_test/src/ct_config.erl
index 6b75937668..fc51aea7f3 100644
--- a/lib/common_test/src/ct_config.erl
+++ b/lib/common_test/src/ct_config.erl
@@ -204,9 +204,9 @@ get_config_file_list(Opts) ->
DefaultConfigs = process_default_configs(Opts),
CfgFiles =
if
- DefaultConfigs == []->
+ DefaultConfigs == [] ->
[];
- true->
+ true ->
[{?ct_config_txt, DefaultConfigs}]
end ++
process_user_configs(Opts, []),
@@ -240,12 +240,12 @@ read_config_files(Opts) ->
end,
ConfigFiles = case lists:keyfind(config, 1, Opts) of
- {config,ConfigLists}->
+ {config,ConfigLists} ->
lists:foldr(fun({Callback,Files}, Acc) ->
AddCallback(Callback,Files)
++ Acc
end,[],ConfigLists);
- false->
+ false ->
[]
end,
read_config_files_int(ConfigFiles, fun store_config/3).
@@ -255,7 +255,9 @@ read_config_files_int([{Callback, File}|Files], FunToSave) ->
{ok, Config} ->
FunToSave(Config, Callback, File),
read_config_files_int(Files, FunToSave);
- {error, ErrorName, ErrorDetail}->
+ {error, {ErrorName, ErrorDetail}} ->
+ {user_error, {ErrorName, File, ErrorDetail}};
+ {error, ErrorName, ErrorDetail} ->
{user_error, {ErrorName, File, ErrorDetail}}
end;
read_config_files_int([], _FunToSave) ->
@@ -283,7 +285,7 @@ rewrite_config(Config, Callback, File) ->
config=File,_='_'}),
Updater = fun({Key, Value}) ->
case keyfindall(Key, #ct_conf.key, OldRows) of
- []->
+ [] ->
ets:insert(?attr_table,
#ct_conf{key=Key,
value=Value,
@@ -453,9 +455,9 @@ update_conf(Name, NewConfig) ->
reload_conf(KeyOrName) ->
case lookup_handler_for_config(KeyOrName) of
- []->
+ [] ->
undefined;
- HandlerList->
+ HandlerList ->
HandlerList2 = lists:usort(HandlerList),
read_config_files_int(HandlerList2, fun rewrite_config/3),
get_config(KeyOrName)
@@ -711,13 +713,13 @@ random_bytes_1(N, Acc) -> random_bytes_1(N-1, [random:uniform(255)|Acc]).
check_callback_load(Callback) ->
case code:is_loaded(Callback) of
- {file, _Filename}->
+ {file, _Filename} ->
check_exports(Callback);
- false->
+ false ->
case code:load_file(Callback) of
- {module, Callback}->
+ {module, Callback} ->
check_exports(Callback);
- {error, Error}->
+ {error, Error} ->
{error, Error}
end
end.
@@ -745,14 +747,14 @@ check_config_files(Configs) ->
end,
Files)
end;
- {error, Why}->
+ {error, Why} ->
{error, {callback, {Callback,Why}}}
end;
({Callback, []}) ->
case check_callback_load(Callback) of
- {ok, Callback}->
+ {ok, Callback} ->
Callback:check_parameter([]);
- {error, Why}->
+ {error, Why} ->
{error, {callback, {Callback,Why}}}
end
end,
@@ -773,15 +775,15 @@ prepare_user_configs([], Acc, _) ->
prepare_config_list(Args) ->
ConfigFiles = case lists:keysearch(ct_config, 1, Args) of
- {value,{ct_config,Files}}->
+ {value,{ct_config,Files}} ->
[{?ct_config_txt,[filename:absname(F) || F <- Files]}];
- false->
+ false ->
[]
end,
UserConfigs = case lists:keysearch(userconfig, 1, Args) of
- {value,{userconfig,UserConfigFiles}}->
+ {value,{userconfig,UserConfigFiles}} ->
prepare_user_configs(UserConfigFiles, [], new);
- false->
+ false ->
[]
end,
ConfigFiles ++ UserConfigs.
diff --git a/lib/common_test/src/ct_config_plain.erl b/lib/common_test/src/ct_config_plain.erl
index 3fbc8af9fb..6698332379 100644
--- a/lib/common_test/src/ct_config_plain.erl
+++ b/lib/common_test/src/ct_config_plain.erl
@@ -29,7 +29,7 @@ read_config(ConfigFile) ->
{ok,Config} ->
{ok, Config};
{error,enoent} ->
- {error, config_file_error, enoent};
+ {error,{config_file_error,file:format_error(enoent)}};
{error,Reason} ->
Key =
case application:get_env(common_test, decrypt) of
@@ -45,23 +45,27 @@ read_config(ConfigFile) ->
end,
case Key of
{error,no_crypt_file} ->
- {error, config_file_error, Reason};
+ {error,{config_file_error,
+ lists:flatten(
+ io_lib:format("~s",[file:format_error(Reason)]))}};
{error,CryptError} ->
- {error, decrypt_file_error, CryptError};
+ {error,{decrypt_file_error,CryptError}};
_ when is_list(Key) ->
- case ct_config:decrypt_config_file(ConfigFile, undefined, {key,Key}) of
+ case ct_config:decrypt_config_file(ConfigFile,
+ undefined,
+ {key,Key}) of
{ok,CfgBin} ->
case read_config_terms(CfgBin) of
{error,ReadFail} ->
- {error, config_file_error, ReadFail};
+ {error,{config_file_error,ReadFail}};
Config ->
- {ok, Config}
+ {ok,Config}
end;
{error,DecryptFail} ->
- {error, decrypt_config_error, DecryptFail}
+ {error,{decrypt_config_error,DecryptFail}}
end;
_ ->
- {error, bad_decrypt_key, Key}
+ {error,{bad_decrypt_key,Key}}
end
end.
@@ -69,9 +73,9 @@ read_config(ConfigFile) ->
check_parameter(File)->
case filelib:is_file(File) of
true->
- {ok, {file, File}};
+ {ok,{file,File}};
false->
- {error, {nofile, File}}
+ {error,{nofile,File}}
end.
read_config_terms(Bin) when is_binary(Bin) ->
diff --git a/lib/common_test/src/ct_config_xml.erl b/lib/common_test/src/ct_config_xml.erl
index 8a6e75e635..794174e663 100644
--- a/lib/common_test/src/ct_config_xml.erl
+++ b/lib/common_test/src/ct_config_xml.erl
@@ -27,30 +27,30 @@
% read config file
read_config(ConfigFile) ->
case catch do_read_xml_config(ConfigFile) of
- {ok, Config}->
- {ok, Config};
- {error, Error, ErroneousString}->
- {error, Error, ErroneousString}
+ {ok,Config} ->
+ {ok,Config};
+ Error = {error,_} ->
+ Error
end.
% check file exists
-check_parameter(File)->
+check_parameter(File) ->
case filelib:is_file(File) of
- true->
- {ok, {file, File}};
- false->
- {error, {nofile, File}}
+ true ->
+ {ok,{file,File}};
+ false ->
+ {error,{nofile,File}}
end.
% actual reading of the config
-do_read_xml_config(ConfigFile)->
+do_read_xml_config(ConfigFile) ->
case catch xmerl_sax_parser:file(ConfigFile,
- [{event_fun, fun event/3},
- {event_state, []}]) of
- {ok, EntityList, _}->
- {ok, lists:reverse(transform_entity_list(EntityList))};
- Oops->
- {error, parsing_failed, Oops}
+ [{event_fun,fun event/3},
+ {event_state,[]}]) of
+ {ok,EntityList,_} ->
+ {ok,lists:reverse(transform_entity_list(EntityList))};
+ Oops ->
+ {error,{parsing_failed,Oops}}
end.
% event callback for xmerl_sax_parser
@@ -92,18 +92,18 @@ tag(_El, State) ->
State.
% transform of the ugly deeply nested entity list to the key-value "tree"
-transform_entity_list(EntityList)->
+transform_entity_list(EntityList) ->
lists:map(fun transform_entity/1, EntityList).
% transform entity from {list(), list()} to {atom(), term()}
transform_entity({Tag, [Value|Rest]}) when
- is_tuple(Value)->
+ is_tuple(Value) ->
{list_to_atom(Tag), transform_entity_list(lists:reverse([Value|Rest]))};
-transform_entity({Tag, String})->
+transform_entity({Tag, String}) ->
case list_to_term(String) of
- {ok, Value}->
+ {ok, Value} ->
{list_to_atom(Tag), Value};
- Error->
+ Error ->
throw(Error)
end.
@@ -111,8 +111,8 @@ transform_entity({Tag, String})->
list_to_term(String) ->
{ok, T, _} = erl_scan:string(String++"."),
case catch erl_parse:parse_term(T) of
- {ok, Term} ->
- {ok, Term};
+ {ok,Term} ->
+ {ok,Term};
Error ->
- {error, Error, String}
+ {error,{Error,String}}
end.
diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl
index 809616d8e3..482c5242ce 100644
--- a/lib/common_test/src/ct_framework.erl
+++ b/lib/common_test/src/ct_framework.erl
@@ -24,10 +24,10 @@
-module(ct_framework).
--export([init_tc/3, end_tc/3, end_tc/4, get_suite/2, report/2, warn/1]).
--export([error_notification/4]).
+-export([init_tc/3, end_tc/3, end_tc/4, get_suite/2, get_all_cases/1]).
+-export([report/2, warn/1, error_notification/4]).
--export([overview_html_header/1]).
+-export([get_logopts/0, format_comment/1, overview_html_header/1]).
-export([error_in_suite/1, ct_init_per_group/2, ct_end_per_group/2]).
@@ -116,7 +116,7 @@ init_tc1(Mod,Func,[Config0],DoInit) when is_list(Config0) ->
Config = lists:keydelete(watchdog,1,Config1),
if Func /= init_per_suite, DoInit /= true ->
ok;
- true ->
+ true ->
%% delete all default values used in previous suite
ct_config:delete_default_config(suite),
%% release all name -> key bindings (once per suite)
@@ -133,7 +133,7 @@ init_tc1(Mod,Func,[Config0],DoInit) when is_list(Config0) ->
ct_config:delete_default_config(testcase),
case add_defaults(Mod,Func,TestCaseInfo,DoInit) of
Error = {suite0_failed,_} ->
- ct_logs:init_tc(),
+ ct_logs:init_tc(false),
FuncSpec = group_or_func(Func,Config0),
ct_event:notify(#event{name=tc_start,
node=node(),
@@ -143,7 +143,7 @@ init_tc1(Mod,Func,[Config0],DoInit) when is_list(Config0) ->
{SuiteInfo,MergeResult} ->
case MergeResult of
{error,Reason} when DoInit == false ->
- ct_logs:init_tc(),
+ ct_logs:init_tc(false),
FuncSpec = group_or_func(Func,Config0),
ct_event:notify(#event{name=tc_start,
node=node(),
@@ -194,19 +194,24 @@ init_tc2(Mod,Func,SuiteInfo,MergeResult,Config,DoInit) ->
Conns ->
ct_util:silence_connections(Conns)
end,
-
- ct_logs:init_tc(),
+ if Func /= init_per_suite, DoInit /= true ->
+ ct_logs:init_tc(false);
+ true ->
+ ct_logs:init_tc(true)
+ end,
FuncSpec = group_or_func(Func,Config),
ct_event:notify(#event{name=tc_start,
node=node(),
data={Mod,FuncSpec}}),
- case configure(MergedInfo1,MergedInfo1,SuiteInfo,{Func,DoInit},Config) of
+ case catch configure(MergedInfo1,MergedInfo1,SuiteInfo,{Func,DoInit},Config) of
{suite0_failed,Reason} ->
ct_util:set_testdata({curr_tc,{Mod,{suite0_failed,{require,Reason}}}}),
{skip,{require_failed_in_suite0,Reason}};
{error,Reason} ->
{auto_skip,{require_failed,Reason}};
+ {'EXIT',Reason} ->
+ {auto_skip,Reason};
{ok, FinalConfig} ->
case MergeResult of
{error,Reason} ->
@@ -240,28 +245,45 @@ add_defaults(Mod,Func,FuncInfo,DoInit) ->
case (catch Mod:suite()) of
{'EXIT',{undef,_}} ->
SuiteInfo = merge_with_suite_defaults(Mod,[]),
- case add_defaults1(Mod,Func,FuncInfo,SuiteInfo,DoInit) of
+ SuiteInfoNoCTH = [I || I <- SuiteInfo, element(1,I) =/= ct_hooks],
+ case add_defaults1(Mod,Func,FuncInfo,SuiteInfoNoCTH,DoInit) of
Error = {error,_} -> {SuiteInfo,Error};
MergedInfo -> {SuiteInfo,MergedInfo}
end;
- {'EXIT',Reason} ->
+ {'EXIT',Reason} ->
+ ErrStr = io_lib:format("~n*** ERROR *** "
+ "~w:suite/0 failed: ~p~n",
+ [Mod,Reason]),
+ io:format(ErrStr, []),
+ io:format(user, ErrStr, []),
{suite0_failed,{exited,Reason}};
SuiteInfo when is_list(SuiteInfo) ->
case lists:all(fun(E) when is_tuple(E) -> true;
(_) -> false
end, SuiteInfo) of
true ->
- SuiteInfoNoCTH =
- lists:keydelete(ct_hooks,1,SuiteInfo),
- SuiteInfo1 = merge_with_suite_defaults(Mod,SuiteInfoNoCTH),
- case add_defaults1(Mod,Func,FuncInfo,SuiteInfo1,DoInit) of
+ SuiteInfo1 = merge_with_suite_defaults(Mod,SuiteInfo),
+ SuiteInfoNoCTH = [I || I <- SuiteInfo1,
+ element(1,I) =/= ct_hooks],
+ case add_defaults1(Mod,Func,FuncInfo,
+ SuiteInfoNoCTH,DoInit) of
Error = {error,_} -> {SuiteInfo1,Error};
MergedInfo -> {SuiteInfo1,MergedInfo}
end;
false ->
+ ErrStr = io_lib:format("~n*** ERROR *** "
+ "Invalid return value from "
+ "~w:suite/0: ~p~n", [Mod,SuiteInfo]),
+ io:format(ErrStr, []),
+ io:format(user, ErrStr, []),
{suite0_failed,bad_return_value}
end;
- _ ->
+ SuiteInfo ->
+ ErrStr = io_lib:format("~n*** ERROR *** "
+ "Invalid return value from "
+ "~w:suite/0: ~p~n", [Mod,SuiteInfo]),
+ io:format(ErrStr, []),
+ io:format(user, ErrStr, []),
{suite0_failed,bad_return_value}
end.
@@ -435,7 +457,7 @@ try_set_default(Name,Key,Info,Where) ->
%%% @doc Test server framework callback, called by the test_server
%%% when a test case is finished.
end_tc(Mod, Fun, Args) ->
- %% Have to keep end_tc/3 for backwards compatabilty issues
+ %% Have to keep end_tc/3 for backwards compatibility issues
end_tc(Mod, Fun, Args, '$end_tc_dummy').
end_tc(?MODULE,error_in_suite,_, _) -> % bad start!
ok;
@@ -449,7 +471,6 @@ end_tc(Mod,Func,TCPid,Result,Args,Return) ->
{value,{watchdog,Dog}} -> test_server:timetrap_cancel(Dog);
false -> ok
end,
-
%% save the testcase process pid so that it can be used
%% to look up the attached trace window later
case ct_util:get_testdata(interpret) of
@@ -459,7 +480,6 @@ end_tc(Mod,Func,TCPid,Result,Args,Return) ->
_ ->
ok
end,
-
ct_util:delete_testdata(comment),
ct_util:delete_suite_data(last_saved_config),
FuncSpec =
@@ -765,6 +785,37 @@ get_suite(Mod, Name) ->
%%%-----------------------------------------------------------------
+get_all_cases(Suite) ->
+ case get_suite(Suite, all) of
+ [{?MODULE,error_in_suite,[[{error,_}=Error]]}] ->
+ Error;
+ [{?MODULE,error_in_suite,[[Error]]}] ->
+ {error,Error};
+ Tests ->
+ Cases = get_all_cases1(Suite, Tests),
+ lists:reverse(
+ lists:foldl(fun(TC, TCs) ->
+ case lists:member(TC, TCs) of
+ true -> TCs;
+ false -> [TC | TCs]
+ end
+ end, [], Cases))
+ end.
+
+get_all_cases1(Suite, [{conf,_Props,_Init,GrTests,_End} | Tests]) ->
+ get_all_cases1(Suite, GrTests) ++ get_all_cases1(Suite, Tests);
+
+get_all_cases1(Suite, [Test | Tests]) when is_atom(Test) ->
+ [{Suite,Test} | get_all_cases1(Suite, Tests)];
+
+get_all_cases1(Suite, [Test | Tests]) ->
+ [Test | get_all_cases1(Suite, Tests)];
+
+get_all_cases1(_, []) ->
+ [].
+
+%%%-----------------------------------------------------------------
+
find_groups(Mod, Name, TCs, GroupDefs) ->
Found = find(Mod, Name, TCs, GroupDefs, [], GroupDefs, false),
trim(Found).
@@ -976,15 +1027,20 @@ make_conf(Mod, Name, Props, TestSpec) ->
_ ->
ok
end,
- {InitConf,EndConf} =
+ {InitConf,EndConf,ExtraProps} =
case erlang:function_exported(Mod,init_per_group,2) of
true ->
- {{Mod,init_per_group},{Mod,end_per_group}};
+ {{Mod,init_per_group},{Mod,end_per_group},[]};
false ->
+ ct_logs:log("TEST INFO", "init_per_group/2 and "
+ "end_per_group/2 missing for group "
+ "~p in ~p, using default.",
+ [Name,Mod]),
{{?MODULE,ct_init_per_group},
- {?MODULE,ct_end_per_group}}
+ {?MODULE,ct_end_per_group},
+ [{suite,Mod}]}
end,
- {conf,[{name,Name}|Props],InitConf,TestSpec,EndConf}.
+ {conf,[{name,Name}|Props++ExtraProps],InitConf,TestSpec,EndConf}.
%%%-----------------------------------------------------------------
@@ -1157,13 +1213,15 @@ error_in_suite(Config) ->
%% if the group config functions are missing in the suite,
%% use these instead
ct_init_per_group(GroupName, Config) ->
- ct_logs:log("WARNING", "init_per_group/2 for ~w missing "
+ ct:comment(io_lib:format("start of ~p", [GroupName])),
+ ct_logs:log("TEST INFO", "init_per_group/2 for ~w missing "
"in suite, using default.",
[GroupName]),
Config.
ct_end_per_group(GroupName, _) ->
- ct_logs:log("WARNING", "end_per_group/2 for ~w missing "
+ ct:comment(io_lib:format("end of ~p", [GroupName])),
+ ct_logs:log("TEST INFO", "end_per_group/2 for ~w missing "
"in suite, using default.",
[GroupName]),
ok.
@@ -1240,12 +1298,20 @@ report(What,Data) ->
ok;
{end_per_group,_} ->
ok;
+ {ct_init_per_group,_} ->
+ ok;
+ {ct_end_per_group,_} ->
+ ok;
{_,ok} ->
add_to_stats(ok);
{_,{skipped,{failed,{_,init_per_testcase,_}}}} ->
add_to_stats(auto_skipped);
{_,{skipped,{require_failed,_}}} ->
add_to_stats(auto_skipped);
+ {_,{skipped,{timetrap_error,_}}} ->
+ add_to_stats(auto_skipped);
+ {_,{skipped,{invalid_time_format,_}}} ->
+ add_to_stats(auto_skipped);
{_,{skipped,_}} ->
add_to_stats(user_skipped);
{_,{SkipOrFail,_Reason}} ->
@@ -1330,6 +1396,21 @@ add_data_dir(File,Config) when is_list(File) ->
end.
%%%-----------------------------------------------------------------
+%%% @spec get_logopts() -> [LogOpt]
+get_logopts() ->
+ case ct_util:get_testdata(logopts) of
+ undefined ->
+ [];
+ LogOpts ->
+ LogOpts
+ end.
+
+%%%-----------------------------------------------------------------
+%%% @spec format_comment(Comment) -> HtmlComment
+format_comment(Comment) ->
+ "<font color=\"green\">" ++ Comment ++ "</font>".
+
+%%%-----------------------------------------------------------------
%%% @spec overview_html_header(TestName) -> Header
overview_html_header(TestName) ->
TestName1 = lists:flatten(io_lib:format("~p", [TestName])),
diff --git a/lib/common_test/src/ct_hooks.erl b/lib/common_test/src/ct_hooks.erl
index 984e04b90f..ffafc582cf 100644
--- a/lib/common_test/src/ct_hooks.erl
+++ b/lib/common_test/src/ct_hooks.erl
@@ -31,11 +31,17 @@
-export([on_tc_skip/2]).
-export([on_tc_fail/2]).
--type proplist() :: [{atom(),term()}].
-
%% If you change this, remember to update ct_util:look -> stop clause as well.
-define(config_name, ct_hooks).
+%% All of the hooks which are to be started by default. Remove by issuing
+%% -enable_builtin_hooks false to when starting common test.
+-define(BUILTIN_HOOKS,[#ct_hook_config{ module = cth_log_redirect,
+ opts = [],
+ prio = ctfirst }]).
+
+-record(ct_hook_config, {id, module, prio, scope, opts = [], state = []}).
+
%% -------------------------------------------------------------------------
%% API Functions
%% -------------------------------------------------------------------------
@@ -44,7 +50,7 @@
-spec init(State :: term()) -> ok |
{error, Reason :: term()}.
init(Opts) ->
- call([{Hook, call_id, undefined} || Hook <- get_new_hooks(Opts)],
+ call(get_new_hooks(Opts, undefined) ++ get_builtin_hooks(Opts),
ok, init, []).
@@ -52,14 +58,15 @@ init(Opts) ->
-spec terminate(Hooks :: term()) ->
ok.
terminate(Hooks) ->
- call([{HookId, fun call_terminate/3} || {HookId,_,_} <- Hooks],
+ call([{HookId, fun call_terminate/3}
+ || #ct_hook_config{id = HookId} <- Hooks],
ct_hooks_terminate_dummy, terminate, Hooks),
ok.
%% @doc Called as each test case is started. This includes all configuration
%% tests.
-spec init_tc(Mod :: atom(), Func :: atom(), Args :: list()) ->
- NewConfig :: proplist() |
+ NewConfig :: proplists:proplist() |
{skip, Reason :: term()} |
{auto_skip, Reason :: term()} |
{fail, Reason :: term()}.
@@ -68,11 +75,11 @@ init_tc(ct_framework, _Func, Args) ->
init_tc(Mod, init_per_suite, Config) ->
Info = try proplists:get_value(ct_hooks, Mod:suite(),[]) of
List when is_list(List) ->
- [{ct_hooks,List}];
+ [{?config_name,List}];
CTHook when is_atom(CTHook) ->
- [{ct_hooks,[CTHook]}]
+ [{?config_name,[CTHook]}]
catch error:undef ->
- [{ct_hooks,[]}]
+ [{?config_name,[]}]
end,
call(fun call_generic/3, Config ++ Info, [pre_init_per_suite, Mod]);
init_tc(Mod, end_per_suite, Config) ->
@@ -92,7 +99,7 @@ init_tc(_Mod, TC, Config) ->
Args :: list(),
Result :: term(),
Resturn :: term()) ->
- NewConfig :: proplist() |
+ NewConfig :: proplists:proplist() |
{skip, Reason :: term()} |
{auto_skip, Reason :: term()} |
{fail, Reason :: term()} |
@@ -131,36 +138,48 @@ on_tc_fail(_How, {Suite, Case, Reason}) ->
%% -------------------------------------------------------------------------
%% Internal Functions
%% -------------------------------------------------------------------------
-call_id(Mod, Config, Meta) when is_atom(Mod) ->
- call_id({Mod, []}, Config, Meta);
-call_id({Mod, Opts}, Config, Scope) ->
+call_id(#ct_hook_config{ module = Mod, opts = Opts} = Hook, Config, Scope) ->
Id = catch_apply(Mod,id,[Opts], make_ref()),
- {Config, {Id, scope(Scope), {Mod, {Id,Opts}}}}.
+ {Config, Hook#ct_hook_config{ id = Id, scope = scope(Scope)}}.
-call_init({Mod,{Id,Opts}},Config,_Meta) ->
- NewState = Mod:init(Id, Opts),
- {Config, {Mod, NewState}}.
-
-call_terminate({Mod, State}, _, _) ->
+call_init(#ct_hook_config{ module = Mod, opts = Opts, id = Id, prio = P} = Hook,
+ Config,_Meta) ->
+ case Mod:init(Id, Opts) of
+ {ok, NewState} when P =:= undefined ->
+ {Config, Hook#ct_hook_config{ state = NewState, prio = 0 } };
+ {ok, NewState} ->
+ {Config, Hook#ct_hook_config{ state = NewState } };
+ {ok, NewState, Prio} when P =:= undefined ->
+ %% Only set prio if not already set when installing hook
+ {Config, Hook#ct_hook_config{ state = NewState, prio = Prio } };
+ {ok, NewState, _} ->
+ {Config, Hook#ct_hook_config{ state = NewState } };
+ NewState -> %% Keep for backward compatability reasons
+ {Config, Hook#ct_hook_config{ state = NewState } }
+ end.
+
+call_terminate(#ct_hook_config{ module = Mod, state = State} = Hook, _, _) ->
catch_apply(Mod,terminate,[State], ok),
- {[],{Mod,State}}.
+ {[],Hook}.
-call_cleanup({Mod, State}, Reason, [Function, _Suite | Args]) ->
+call_cleanup(#ct_hook_config{ module = Mod, state = State} = Hook,
+ Reason, [Function, _Suite | Args]) ->
NewState = catch_apply(Mod,Function, Args ++ [Reason, State],
State),
- {Reason, {Mod, NewState}}.
+ {Reason, Hook#ct_hook_config{ state = NewState } }.
-call_generic({Mod, State}, Value, [Function | Args]) ->
+call_generic(#ct_hook_config{ module = Mod, state = State} = Hook,
+ Value, [Function | Args]) ->
{NewValue, NewState} = catch_apply(Mod, Function, Args ++ [Value, State],
{Value,State}),
- {NewValue, {Mod, NewState}}.
+ {NewValue, Hook#ct_hook_config{ state = NewState } }.
%% Generic call function
call(Fun, Config, Meta) ->
maybe_lock(),
Hooks = get_hooks(),
- Res = call([{HookId,Fun} || {HookId,_, _} <- Hooks] ++
- get_new_hooks(Config, Fun),
+ Res = call(get_new_hooks(Config, Fun) ++
+ [{HookId,Fun} || #ct_hook_config{id = HookId} <- Hooks],
remove(?config_name,Config), Meta, Hooks),
maybe_unlock(),
Res.
@@ -173,19 +192,20 @@ call(Fun, Config, Meta, NoChangeRet) when is_function(Fun) ->
call([{Hook, call_id, NextFun} | Rest], Config, Meta, Hooks) ->
try
- {Config, {NewId, _, _} = NewHook} = call_id(Hook, Config, Meta),
+ {Config, #ct_hook_config{ id = NewId } = NewHook} =
+ call_id(Hook, Config, Meta),
{NewHooks, NewRest} =
- case lists:keyfind(NewId, 1, Hooks) of
+ case lists:keyfind(NewId, #ct_hook_config.id, Hooks) of
false when NextFun =:= undefined ->
{Hooks ++ [NewHook],
- [{NewId, fun call_init/3} | Rest]};
+ [{NewId, call_init} | Rest]};
ExistingHook when is_tuple(ExistingHook) ->
{Hooks, Rest};
_ ->
{Hooks ++ [NewHook],
- [{NewId, fun call_init/3},{NewId,NextFun} | Rest]}
+ [{NewId, call_init}, {NewId,NextFun} | Rest]}
end,
- call(NewRest, Config, Meta, NewHooks)
+ call(resort(NewRest,NewHooks), Config, Meta, NewHooks)
catch Error:Reason ->
Trace = erlang:get_stacktrace(),
ct_logs:log("Suite Hook","Failed to start a CTH: ~p:~p",
@@ -193,13 +213,16 @@ call([{Hook, call_id, NextFun} | Rest], Config, Meta, Hooks) ->
call([], {fail,"Failed to start CTH"
", see the CT Log for details"}, Meta, Hooks)
end;
+call([{HookId, call_init} | Rest], Config, Meta, Hooks) ->
+ call([{HookId, fun call_init/3} | Rest], Config, Meta, Hooks);
call([{HookId, Fun} | Rest], Config, Meta, Hooks) ->
try
- {_,Scope,ModState} = lists:keyfind(HookId, 1, Hooks),
- {NewConf, NewHookInfo} = Fun(ModState, Config, Meta),
+ Hook = lists:keyfind(HookId, #ct_hook_config.id, Hooks),
+ {NewConf, NewHook} = Fun(Hook, Config, Meta),
NewCalls = get_new_hooks(NewConf, Fun),
- NewHooks = lists:keyreplace(HookId, 1, Hooks, {HookId, Scope, NewHookInfo}),
- call(NewCalls ++ Rest, remove(?config_name, NewConf), Meta,
+ NewHooks = lists:keyreplace(HookId, #ct_hook_config.id, Hooks, NewHook),
+ call(resort(NewCalls ++ Rest,NewHooks), %% Resort if call_init changed prio
+ remove(?config_name, NewConf), Meta,
terminate_if_scope_ends(HookId, Meta, NewHooks))
catch throw:{error_in_cth_call,Reason} ->
call(Rest, {fail, Reason}, Meta,
@@ -237,19 +260,26 @@ terminate_if_scope_ends(HookId, [on_tc_skip,Suite,end_per_suite], Hooks) ->
terminate_if_scope_ends(HookId, [Function,Tag|T], Hooks) when T =/= [] ->
terminate_if_scope_ends(HookId,[Function,Tag],Hooks);
terminate_if_scope_ends(HookId, Function, Hooks) ->
- case lists:keyfind(HookId, 1, Hooks) of
- {HookId, Function, _ModState} = Hook ->
+ case lists:keyfind(HookId, #ct_hook_config.id, Hooks) of
+ #ct_hook_config{ id = HookId, scope = Function} = Hook ->
terminate([Hook]),
- lists:keydelete(HookId, 1, Hooks);
+ lists:keydelete(HookId, #ct_hook_config.id, Hooks);
_ ->
Hooks
end.
%% Fetch hook functions
get_new_hooks(Config, Fun) ->
- lists:foldl(fun(NewHook, Acc) ->
- [{NewHook, call_id, Fun} | Acc]
- end, [], get_new_hooks(Config)).
+ lists:map(fun(NewHook) when is_atom(NewHook) ->
+ {#ct_hook_config{ module = NewHook }, call_id, Fun};
+ ({NewHook,Opts}) ->
+ {#ct_hook_config{ module = NewHook,
+ opts = Opts}, call_id, Fun};
+ ({NewHook,Opts,Prio}) ->
+ {#ct_hook_config{ module = NewHook,
+ opts = Opts,
+ prio = Prio }, call_id, Fun}
+ end, get_new_hooks(Config)).
get_new_hooks(Config) when is_list(Config) ->
lists:flatmap(fun({?config_name, HookConfigs}) ->
@@ -260,11 +290,63 @@ get_new_hooks(Config) when is_list(Config) ->
get_new_hooks(_Config) ->
[].
+get_builtin_hooks(Opts) ->
+ case proplists:get_value(enable_builtin_hooks,Opts) of
+ false ->
+ [];
+ _Else ->
+ [{HookConf, call_id, undefined} || HookConf <- ?BUILTIN_HOOKS]
+ end.
+
save_suite_data_async(Hooks) ->
ct_util:save_suite_data_async(?config_name, Hooks).
get_hooks() ->
- ct_util:read_suite_data(?config_name).
+ lists:keysort(#ct_hook_config.prio,ct_util:read_suite_data(?config_name)).
+
+%% Sort all calls in this order:
+%% call_id < call_init < ctfirst < Priority 1 < .. < Priority N < ctlast
+%% If Hook Priority is equal, check when it has been installed and
+%% sort on that instead.
+resort(Calls, Hooks) ->
+ lists:sort(
+ fun({_,_,_},_) ->
+ true;
+ (_,{_,_,_}) ->
+ false;
+ ({_,call_init},_) ->
+ true;
+ (_,{_,call_init}) ->
+ false;
+ ({Id1,_},{Id2,_}) ->
+ P1 = (lists:keyfind(Id1, #ct_hook_config.id, Hooks))#ct_hook_config.prio,
+ P2 = (lists:keyfind(Id2, #ct_hook_config.id, Hooks))#ct_hook_config.prio,
+ if
+ P1 == P2 ->
+ %% If priorities are equal, we check the position in the
+ %% hooks list
+ pos(Id1,Hooks) < pos(Id2,Hooks);
+ P1 == ctfirst ->
+ true;
+ P2 == ctfirst ->
+ false;
+ P1 == ctlast ->
+ false;
+ P2 == ctlast ->
+ true;
+ true ->
+ P1 < P2
+ end
+ end,Calls).
+
+pos(Id,Hooks) ->
+ pos(Id,Hooks,0).
+pos(Id,[#ct_hook_config{ id = Id}|_],Num) ->
+ Num;
+pos(Id,[_|Rest],Num) ->
+ pos(Id,Rest,Num+1).
+
+
catch_apply(M,F,A, Default) ->
try
@@ -272,7 +354,7 @@ catch_apply(M,F,A, Default) ->
catch error:Reason ->
case erlang:get_stacktrace() of
%% Return the default if it was the CTH module which did not have the function.
- [{M,F,A}|_] when Reason == undef ->
+ [{M,F,A,_}|_] when Reason == undef ->
Default;
Trace ->
ct_logs:log("Suite Hook","Call to CTH failed: ~p:~p",
diff --git a/lib/common_test/src/ct_line.erl b/lib/common_test/src/ct_line.erl
deleted file mode 100644
index 4af9da5463..0000000000
--- a/lib/common_test/src/ct_line.erl
+++ /dev/null
@@ -1,266 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%% @doc Parse transform for inserting line numbers
-
--module(ct_line).
-
--record(vars, {module, % atom() Module name
- vsn, % atom()
-
- init_info=[], % [{M,F,A,C,L}]
-
- function, % atom()
- arity, % int()
- clause, % int()
- lines, % [int()]
- depth, % int()
- is_guard=false % boolean
- }).
-
--export([parse_transform/2,
- line/1]).
-
-line(LOC={{Mod,Func},_Line}) ->
- Lines = case get(test_server_loc) of
- [{{Mod,Func},_}|Ls] ->
- Ls;
- Ls when is_list(Ls) ->
- case length(Ls) of
- 10 ->
- [_|T]=lists:reverse(Ls),
- lists:reverse(T);
- _ ->
- Ls
- end;
- _ ->
- []
- end,
- put(test_server_loc,[LOC|Lines]).
-
-parse_transform(Forms, _Options) ->
- transform(Forms, _Options).
-
-%% forms(Fs) -> lists:map(fun (F) -> form(F) end, Fs).
-
-transform(Forms, _Options)->
- Vars0 = #vars{},
- {ok, MungedForms, _Vars} = transform(Forms, [], Vars0),
- MungedForms.
-
-
-transform([Form|Forms], MungedForms, Vars) ->
- case munge(Form, Vars) of
- ignore ->
- transform(Forms, MungedForms, Vars);
- {MungedForm, Vars2} ->
- transform(Forms, [MungedForm|MungedForms], Vars2)
- end;
-transform([], MungedForms, Vars) ->
- {ok, lists:reverse(MungedForms), Vars}.
-
-%% This code traverses the abstract code, stored as the abstract_code
-%% chunk in the BEAM file, as described in absform(3) for Erlang/OTP R8B
-%% (Vsn=abstract_v2).
-%% The abstract format after preprocessing differs slightly from the abstract
-%% format given eg using epp:parse_form, this has been noted in comments.
-munge(Form={attribute,_,module,Module}, Vars) ->
- Vars2 = Vars#vars{module=Module},
- {Form, Vars2};
-
-munge({function,0,module_info,_Arity,_Clauses}, _Vars) ->
- ignore; % module_info will be added again when the forms are recompiled
-munge({function,Line,Function,Arity,Clauses}, Vars) ->
- Vars2 = Vars#vars{function=Function,
- arity=Arity,
- clause=1,
- lines=[],
- depth=1},
- {MungedClauses, Vars3} = munge_clauses(Clauses, Vars2, []),
- {{function,Line,Function,Arity,MungedClauses}, Vars3};
-munge(Form, Vars) -> % attributes
- {Form, Vars}.
-
-munge_clauses([{clause,Line,Pattern,Guards,Body}|Clauses], Vars, MClauses) ->
- {MungedGuards, _Vars} = munge_exprs(Guards, Vars#vars{is_guard=true},[]),
-
- case Vars#vars.depth of
- 1 -> % function clause
- {MungedBody, Vars2} = munge_body(Body, Vars#vars{depth=2}, []),
- ClauseInfo = {Vars2#vars.module,
- Vars2#vars.function,
- Vars2#vars.arity,
- Vars2#vars.clause,
- length(Vars2#vars.lines)},
- InitInfo = [ClauseInfo | Vars2#vars.init_info],
- Vars3 = Vars2#vars{init_info=InitInfo,
- clause=(Vars2#vars.clause)+1,
- lines=[],
- depth=1},
- munge_clauses(Clauses, Vars3,
- [{clause,Line,Pattern,MungedGuards,MungedBody}|
- MClauses]);
-
- 2 -> % receive-, case- or if clause
- {MungedBody, Vars2} = munge_body(Body, Vars, []),
- munge_clauses(Clauses, Vars2,
- [{clause,Line,Pattern,MungedGuards,MungedBody}|
- MClauses])
- end;
-munge_clauses([], Vars, MungedClauses) ->
- {lists:reverse(MungedClauses), Vars}.
-
-munge_body([Expr|Body], Vars, MungedBody) ->
- %% Here is the place to add a call to cover:bump/6!
- Line = element(2, Expr),
- Lines = Vars#vars.lines,
- case lists:member(Line,Lines) of
- true -> % already a bump at this line!
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- munge_body(Body, Vars2, [MungedExpr|MungedBody]);
- false ->
- Bump = {call, 0, {remote,0,{atom,0,?MODULE},{atom,0,line}},
- [{tuple,0,[{tuple,0,[{atom,0,Vars#vars.module},
- {atom, 0, Vars#vars.function}]},
- {integer, 0, Line}]}]},
- Lines2 = [Line|Lines],
-
- {MungedExpr, Vars2} = munge_expr(Expr, Vars#vars{lines=Lines2}),
- munge_body(Body, Vars2, [MungedExpr,Bump|MungedBody])
- end;
-munge_body([], Vars, MungedBody) ->
- {lists:reverse(MungedBody), Vars}.
-
-munge_expr({match,Line,ExprL,ExprR}, Vars) ->
- {MungedExprL, Vars2} = munge_expr(ExprL, Vars),
- {MungedExprR, Vars3} = munge_expr(ExprR, Vars2),
- {{match,Line,MungedExprL,MungedExprR}, Vars3};
-munge_expr({tuple,Line,Exprs}, Vars) ->
- {MungedExprs, Vars2} = munge_exprs(Exprs, Vars, []),
- {{tuple,Line,MungedExprs}, Vars2};
-munge_expr({record,Line,Expr,Exprs}, Vars) ->
- %% Only for Vsn=raw_abstract_v1
- {MungedExprName, Vars2} = munge_expr(Expr, Vars),
- {MungedExprFields, Vars3} = munge_exprs(Exprs, Vars2, []),
- {{record,Line,MungedExprName,MungedExprFields}, Vars3};
-munge_expr({record_field,Line,ExprL,ExprR}, Vars) ->
- %% Only for Vsn=raw_abstract_v1
- {MungedExprL, Vars2} = munge_expr(ExprL, Vars),
- {MungedExprR, Vars3} = munge_expr(ExprR, Vars2),
- {{record_field,Line,MungedExprL,MungedExprR}, Vars3};
-munge_expr({cons,Line,ExprH,ExprT}, Vars) ->
- {MungedExprH, Vars2} = munge_expr(ExprH, Vars),
- {MungedExprT, Vars3} = munge_expr(ExprT, Vars2),
- {{cons,Line,MungedExprH,MungedExprT}, Vars3};
-munge_expr({op,Line,Op,ExprL,ExprR}, Vars) ->
- {MungedExprL, Vars2} = munge_expr(ExprL, Vars),
- {MungedExprR, Vars3} = munge_expr(ExprR, Vars2),
- {{op,Line,Op,MungedExprL,MungedExprR}, Vars3};
-munge_expr({op,Line,Op,Expr}, Vars) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- {{op,Line,Op,MungedExpr}, Vars2};
-munge_expr({'catch',Line,Expr}, Vars) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- {{'catch',Line,MungedExpr}, Vars2};
-munge_expr({call,Line1,{remote,Line2,ExprM,ExprF},Exprs},
- Vars) when Vars#vars.is_guard==false->
- {MungedExprM, Vars2} = munge_expr(ExprM, Vars),
- {MungedExprF, Vars3} = munge_expr(ExprF, Vars2),
- {MungedExprs, Vars4} = munge_exprs(Exprs, Vars3, []),
- {{call,Line1,{remote,Line2,MungedExprM,MungedExprF},MungedExprs}, Vars4};
-munge_expr({call,Line1,{remote,_Line2,_ExprM,ExprF},Exprs},
- Vars) when Vars#vars.is_guard==true ->
- %% Difference in abstract format after preprocessing: BIF calls in guards
- %% are translated to {remote,...} (which is not allowed as source form)
- %% NOT NECESSARY FOR Vsn=raw_abstract_v1
- munge_expr({call,Line1,ExprF,Exprs}, Vars);
-munge_expr({call,Line,Expr,Exprs}, Vars) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- {MungedExprs, Vars3} = munge_exprs(Exprs, Vars2, []),
- {{call,Line,MungedExpr,MungedExprs}, Vars3};
-munge_expr({lc,Line,Expr,LC}, Vars) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- {MungedLC, Vars3} = munge_lc(LC, Vars2, []),
- {{lc,Line,MungedExpr,MungedLC}, Vars3};
-munge_expr({block,Line,Body}, Vars) ->
- {MungedBody, Vars2} = munge_body(Body, Vars, []),
- {{block,Line,MungedBody}, Vars2};
-munge_expr({'if',Line,Clauses}, Vars) ->
- {MungedClauses,Vars2} = munge_clauses(Clauses, Vars, []),
- {{'if',Line,MungedClauses}, Vars2};
-munge_expr({'case',Line,Expr,Clauses}, Vars) ->
- {MungedExpr,Vars2} = munge_expr(Expr,Vars),
- {MungedClauses,Vars3} = munge_clauses(Clauses, Vars2, []),
- {{'case',Line,MungedExpr,MungedClauses}, Vars3};
-munge_expr({'receive',Line,Clauses}, Vars) ->
- {MungedClauses,Vars2} = munge_clauses(Clauses, Vars, []),
- {{'receive',Line,MungedClauses}, Vars2};
-munge_expr({'receive',Line,Clauses,Expr,Body}, Vars) ->
- {MungedClauses,Vars2} = munge_clauses(Clauses, Vars, []),
- {MungedExpr, Vars3} = munge_expr(Expr, Vars2),
- {MungedBody, Vars4} = munge_body(Body, Vars3, []),
- {{'receive',Line,MungedClauses,MungedExpr,MungedBody}, Vars4};
-munge_expr({'try',Line,Exprs,Clauses,CatchClauses}, Vars) ->
- {MungedExprs, Vars1} = munge_exprs(Exprs, Vars, []),
- {MungedClauses, Vars2} = munge_clauses(Clauses, Vars1, []),
- {MungedCatchClauses, Vars3} = munge_clauses(CatchClauses, Vars2, []),
- {{'try',Line,MungedExprs,MungedClauses,MungedCatchClauses}, Vars3};
-%% Difference in abstract format after preprocessing: Funs get an extra
-%% element Extra.
-%% NOT NECESSARY FOR Vsn=raw_abstract_v1
-munge_expr({'fun',Line,{function,Name,Arity},_Extra}, Vars) ->
- {{'fun',Line,{function,Name,Arity}}, Vars};
-munge_expr({'fun',Line,{clauses,Clauses},_Extra}, Vars) ->
- {MungedClauses,Vars2}=munge_clauses(Clauses, Vars, []),
- {{'fun',Line,{clauses,MungedClauses}}, Vars2};
-munge_expr({'fun',Line,{clauses,Clauses}}, Vars) ->
- %% Only for Vsn=raw_abstract_v1
- {MungedClauses,Vars2}=munge_clauses(Clauses, Vars, []),
- {{'fun',Line,{clauses,MungedClauses}}, Vars2};
-munge_expr(Form, Vars) -> % var|char|integer|float|string|atom|nil|bin|eof
- {Form, Vars}.
-
-munge_exprs([Expr|Exprs], Vars, MungedExprs) when Vars#vars.is_guard==true,
- is_list(Expr) ->
- {MungedExpr, _Vars} = munge_exprs(Expr, Vars, []),
- munge_exprs(Exprs, Vars, [MungedExpr|MungedExprs]);
-munge_exprs([Expr|Exprs], Vars, MungedExprs) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- munge_exprs(Exprs, Vars2, [MungedExpr|MungedExprs]);
-munge_exprs([], Vars, MungedExprs) ->
- {lists:reverse(MungedExprs), Vars}.
-
-munge_lc([{generate,Line,Pattern,Expr}|LC], Vars, MungedLC) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- munge_lc(LC, Vars2, [{generate,Line,Pattern,MungedExpr}|MungedLC]);
-munge_lc([Expr|LC], Vars, MungedLC) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- munge_lc(LC, Vars2, [MungedExpr|MungedLC]);
-munge_lc([], Vars, MungedLC) ->
- {lists:reverse(MungedLC), Vars}.
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl
index b839521e24..c1523509a5 100644
--- a/lib/common_test/src/ct_logs.erl
+++ b/lib/common_test/src/ct_logs.erl
@@ -28,7 +28,7 @@
-module(ct_logs).
--export([init/1,close/1,init_tc/0,end_tc/1]).
+-export([init/1,close/2,init_tc/1,end_tc/1]).
-export([get_log_dir/0,log/3,start_log/1,cont_log/2,end_log/0]).
-export([set_stylesheet/2,clear_stylesheet/1]).
-export([add_external_logs/1,add_link/3]).
@@ -36,7 +36,7 @@
-export([make_all_suites_index/1,make_all_runs_index/1]).
%% Logging stuff directly from testcase
--export([tc_log/3,tc_print/3,tc_pal/3,
+-export([tc_log/3,tc_print/3,tc_pal/3,ct_log/3,
basic_html/0]).
%% Simulate logger process for use without ct environment running
@@ -97,11 +97,11 @@ logdir_node_prefix() ->
logdir_prefix()++"."++atom_to_list(node()).
%%%-----------------------------------------------------------------
-%%% @spec close(Info) -> ok
+%%% @spec close(Info, StartDir) -> ok
%%%
%%% @doc Create index pages with test results and close the CT Log
%%% (tool-internal use only).
-close(Info) ->
+close(Info, StartDir) ->
make_last_run_index(),
ct_event:notify(#event{name=stop_logging,node=node(),data=[]}),
@@ -124,14 +124,29 @@ close(Info) ->
ok;
Error ->
io:format("Warning! Cleanup failed: ~p~n", [Error])
- end;
+ end,
+ make_all_suites_index(stop),
+ make_all_runs_index(stop);
true ->
- file:set_cwd("..")
- end,
-
- make_all_suites_index(stop),
- make_all_runs_index(stop),
-
+ file:set_cwd(".."),
+ make_all_suites_index(stop),
+ make_all_runs_index(stop),
+ case ct_util:get_profile_data(browser, StartDir) of
+ undefined ->
+ ok;
+ BrowserData ->
+ case {proplists:get_value(prog, BrowserData),
+ proplists:get_value(args, BrowserData),
+ proplists:get_value(page, BrowserData)} of
+ {Prog,Args,Page} when is_list(Args),
+ is_list(Page) ->
+ URL = "\"file://" ++ ?abs(Page) ++ "\"",
+ ct_util:open_url(Prog, Args, URL);
+ _ ->
+ ok
+ end
+ end
+ end,
ok.
%%%-----------------------------------------------------------------
@@ -182,15 +197,14 @@ cast(Msg) ->
?MODULE ! Msg
end.
-
%%%-----------------------------------------------------------------
-%%% @spec init_tc() -> ok
+%%% @spec init_tc(RefreshLog) -> ok
%%%
%%% @doc Test case initiation (tool-internal use only).
%%%
%%% <p>This function is called by ct_framework:init_tc/3</p>
-init_tc() ->
- call({init_tc,self(),group_leader()}),
+init_tc(RefreshLog) ->
+ call({init_tc,self(),group_leader(),RefreshLog}),
ok.
%%%-----------------------------------------------------------------
@@ -360,6 +374,23 @@ tc_pal(Category,Format,Args) ->
ok.
+%%%-----------------------------------------------------------------
+%%% @spec tc_pal(Category,Format,Args) -> ok
+%%% Category = atom()
+%%% Format = string()
+%%% Args = list()
+%%%
+%%% @doc Print and log to the ct framework log
+%%%
+%%% <p>This function is called by internal ct functions to
+%%% force logging to the ct framework log</p>
+ct_log(Category,Format,Args) ->
+ cast({ct_log,[{div_header(Category),[]},
+ {Format,Args},
+ {div_footer(),[]}]}),
+ ok.
+
+
%%%=================================================================
%%% Internal functions
int_header() ->
@@ -469,8 +500,8 @@ logger_loop(State) ->
[Str,Args]),
%% stop the testcase, we need
%% to see the fault
- exit(Pid,logging_failed),
- ok;
+ exit(Pid,{log_printout_error,Str,Args}),
+ [];
IoStr when IoList == [] ->
[IoStr];
IoStr ->
@@ -490,10 +521,15 @@ logger_loop(State) ->
[begin io:format(Fd,Str,Args),io:nl(Fd) end || {Str,Args} <- List],
logger_loop(State#logger_state{tc_groupleaders=TCGLs})
end;
- {{init_tc,TCPid,GL},From} ->
+ {{init_tc,TCPid,GL,RefreshLog},From} ->
print_style(GL, State#logger_state.stylesheet),
set_evmgr_gl(GL),
TCGLs = add_tc_gl(TCPid,GL,State),
+ if not RefreshLog ->
+ ok;
+ true ->
+ make_last_run_index(State#logger_state.start_time)
+ end,
return(From,ok),
logger_loop(State#logger_state{tc_groupleaders=TCGLs});
{{end_tc,TCPid},From} ->
@@ -516,7 +552,12 @@ logger_loop(State) ->
{clear_stylesheet,_} when State#logger_state.stylesheet == undefined ->
logger_loop(State);
{clear_stylesheet,_} ->
- logger_loop(State#logger_state{stylesheet=undefined});
+ logger_loop(State#logger_state{stylesheet=undefined});
+ {ct_log, List} ->
+ Fd = State#logger_state.ct_log_fd,
+ [begin io:format(Fd,Str,Args),io:nl(Fd) end ||
+ {Str,Args} <- List],
+ logger_loop(State);
stop ->
io:format(State#logger_state.ct_log_fd,
int_header()++int_footer(),
@@ -819,6 +860,7 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip,
""
end
end,
+ CtRunDir = filename:dirname(filename:dirname(Link)),
{Lbl,Timestamp,Node,AllInfo} =
case All of
{true,OldRuns} ->
@@ -828,7 +870,6 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip,
_ -> NodeOrDate
end,
N = ["<TD ALIGN=right><FONT SIZE=-1>",Node1,"</FONT></TD>\n"],
- CtRunDir = filename:dirname(filename:dirname(Link)),
L = ["<TD ALIGN=center><FONT SIZE=-1><B>",Label,"</FONT></B></TD>\n"],
T = ["<TD><FONT SIZE=-1>",timestamp(CtRunDir),"</FONT></TD>\n"],
CtLogFile = filename:join(CtRunDir,?ct_log_name),
@@ -847,7 +888,7 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip,
if NotBuilt == 0 ->
["<TD ALIGN=right>",integer_to_list(NotBuilt),"</TD>\n"];
true ->
- ["<TD ALIGN=right><A HREF=\"",?ct_log_name,"\">",
+ ["<TD ALIGN=right><A HREF=\"",filename:join(CtRunDir,?ct_log_name),"\">",
integer_to_list(NotBuilt),"</A></TD>\n"]
end,
FailStr =
diff --git a/lib/common_test/src/ct_make.erl b/lib/common_test/src/ct_make.erl
index 233e45248e..40e9e99f37 100644
--- a/lib/common_test/src/ct_make.erl
+++ b/lib/common_test/src/ct_make.erl
@@ -177,7 +177,7 @@ members([],_MakefileMods,I,Rest) ->
{I,Rest}.
-%% Any flags that are not recognixed as make flags are passed directly
+%% Any flags that are not recognised as make flags are passed directly
%% to the compiler.
%% So for example make:all([load,debug_info]) will make everything
%% with the debug_info flag and load it.
diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl
index c01e97b358..0a9bb5af67 100644
--- a/lib/common_test/src/ct_run.erl
+++ b/lib/common_test/src/ct_run.erl
@@ -33,7 +33,7 @@
%% Exported for VTS
--export([run_make/3,do_run/3,tests/1,tests/2,tests/3]).
+-export([run_make/3,do_run/4,tests/1,tests/2,tests/3]).
%% Misc internal functions
@@ -46,15 +46,18 @@
-define(testdir(Name, Suite), ct_util:get_testdir(Name, Suite)).
-record(opts, {label,
+ profile,
vts,
shell,
cover,
coverspec,
step,
logdir,
+ logopts = [],
config = [],
event_handlers = [],
ct_hooks = [],
+ enable_builtin_hooks = true,
include = [],
silent_connections,
stylesheet,
@@ -156,15 +159,19 @@ script_start(Args) ->
end,
stop_trace(Tracing),
timer:sleep(1000),
+ io:nl(),
Res.
script_start1(Parent, Args) ->
%% read general start flags
Label = get_start_opt(label, fun([Lbl]) -> Lbl end, Args),
+ Profile = get_start_opt(profile, fun([Prof]) -> Prof end, Args),
Vts = get_start_opt(vts, true, Args),
Shell = get_start_opt(shell, true, Args),
Cover = get_start_opt(cover, fun([CoverFile]) -> ?abs(CoverFile) end, Args),
LogDir = get_start_opt(logdir, fun([LogD]) -> LogD end, Args),
+ LogOpts = get_start_opt(logopts, fun(Os) -> [list_to_atom(O) || O <- Os] end,
+ [], Args),
MultTT = get_start_opt(multiply_timetraps,
fun([MT]) -> list_to_integer(MT) end, 1, Args),
ScaleTT = get_start_opt(scale_timetraps,
@@ -173,6 +180,10 @@ script_start1(Parent, Args) ->
end, false, Args),
EvHandlers = event_handler_args2opts(Args),
CTHooks = ct_hooks_args2opts(Args),
+ EnableBuiltinHooks = get_start_opt(enable_builtin_hooks,
+ fun([CT]) -> list_to_atom(CT);
+ ([]) -> true
+ end, true, Args),
%% check flags and set corresponding application env variables
@@ -234,9 +245,12 @@ script_start1(Parent, Args) ->
application:set_env(common_test, basic_html, true)
end,
- StartOpts = #opts{label = Label, vts = Vts, shell = Shell, cover = Cover,
- logdir = LogDir, event_handlers = EvHandlers,
+ StartOpts = #opts{label = Label, profile = Profile,
+ vts = Vts, shell = Shell, cover = Cover,
+ logdir = LogDir, logopts = LogOpts,
+ event_handlers = EvHandlers,
ct_hooks = CTHooks,
+ enable_builtin_hooks = EnableBuiltinHooks,
include = IncludeDirs,
silent_connections = SilentConns,
stylesheet = Stylesheet,
@@ -297,9 +311,15 @@ script_start2(StartOpts = #opts{vts = undefined,
Label = choose_val(StartOpts#opts.label,
SpecStartOpts#opts.label),
+ Profile = choose_val(StartOpts#opts.profile,
+ SpecStartOpts#opts.profile),
+
LogDir = choose_val(StartOpts#opts.logdir,
SpecStartOpts#opts.logdir),
+ AllLogOpts = merge_vals([StartOpts#opts.logopts,
+ SpecStartOpts#opts.logopts]),
+
Cover = choose_val(StartOpts#opts.cover,
SpecStartOpts#opts.cover),
MultTT = choose_val(StartOpts#opts.multiply_timetraps,
@@ -311,18 +331,27 @@ script_start2(StartOpts = #opts{vts = undefined,
AllCTHooks = merge_vals(
[StartOpts#opts.ct_hooks,
SpecStartOpts#opts.ct_hooks]),
+
+ EnableBuiltinHooks =
+ choose_val(
+ StartOpts#opts.enable_builtin_hooks,
+ SpecStartOpts#opts.enable_builtin_hooks),
AllInclude = merge_vals([StartOpts#opts.include,
SpecStartOpts#opts.include]),
application:set_env(common_test, include, AllInclude),
{TS,StartOpts#opts{label = Label,
+ profile = Profile,
testspecs = Specs,
cover = Cover,
logdir = LogDir,
+ logopts = AllLogOpts,
config = SpecStartOpts#opts.config,
event_handlers = AllEvHs,
ct_hooks = AllCTHooks,
+ enable_builtin_hooks =
+ EnableBuiltinHooks,
include = AllInclude,
multiply_timetraps = MultTT,
scale_timetraps = ScaleTT}}
@@ -339,9 +368,7 @@ script_start2(StartOpts = #opts{vts = undefined,
{[],_} ->
{error,no_testspec_specified};
{undefined,_} -> % no testspec used
- case check_and_install_configfiles(InitConfig, TheLogDir,
- Opts#opts.event_handlers,
- Opts#opts.ct_hooks) of
+ case check_and_install_configfiles(InitConfig, TheLogDir, Opts) of
ok -> % go on read tests from start flags
script_start3(Opts#opts{config=InitConfig,
logdir=TheLogDir}, Args);
@@ -351,9 +378,7 @@ script_start2(StartOpts = #opts{vts = undefined,
{_,_} -> % testspec used
%% merge config from start flags with config from testspec
AllConfig = merge_vals([InitConfig, Opts#opts.config]),
- case check_and_install_configfiles(AllConfig, TheLogDir,
- Opts#opts.event_handlers,
- Opts#opts.ct_hooks) of
+ case check_and_install_configfiles(AllConfig, TheLogDir, Opts) of
ok -> % read tests from spec
{Run,Skip} = ct_testspec:prepare_tests(Terms, node()),
do_run(Run, Skip, Opts#opts{config=AllConfig,
@@ -367,9 +392,7 @@ script_start2(StartOpts, Args) ->
%% read config/userconfig from start flags
InitConfig = ct_config:prepare_config_list(Args),
LogDir = which(logdir, StartOpts#opts.logdir),
- case check_and_install_configfiles(InitConfig, LogDir,
- StartOpts#opts.event_handlers,
- StartOpts#opts.ct_hooks) of
+ case check_and_install_configfiles(InitConfig, LogDir, StartOpts) of
ok -> % go on read tests from start flags
script_start3(StartOpts#opts{config=InitConfig,
logdir=LogDir}, Args);
@@ -377,12 +400,17 @@ script_start2(StartOpts, Args) ->
Error
end.
-check_and_install_configfiles(Configs, LogDir, EvHandlers, CTHooks) ->
+check_and_install_configfiles(
+ Configs, LogDir, #opts{
+ event_handlers = EvHandlers,
+ ct_hooks = CTHooks,
+ enable_builtin_hooks = EnableBuiltinHooks} ) ->
case ct_config:check_config_files(Configs) of
false ->
install([{config,Configs},
{event_handler,EvHandlers},
- {ct_hooks,CTHooks}], LogDir);
+ {ct_hooks,CTHooks},
+ {enable_builtin_hooks,EnableBuiltinHooks}], LogDir);
{value,{error,{nofile,File}}} ->
{error,{cant_read_config_file,File}};
{value,{error,{wrong_config,Message}}}->
@@ -392,50 +420,72 @@ check_and_install_configfiles(Configs, LogDir, EvHandlers, CTHooks) ->
end.
script_start3(StartOpts, Args) ->
- case proplists:get_value(dir, Args) of
- [] ->
+ StartOpts1 = get_start_opt(step,
+ fun(Step) ->
+ StartOpts#opts{step = Step,
+ cover = undefined}
+ end, StartOpts, Args),
+ case {proplists:get_value(dir, Args),
+ proplists:get_value(suite, Args),
+ groups_and_cases(proplists:get_value(group, Args),
+ proplists:get_value(testcase, Args))} of
+ %% flag specified without data
+ {_,_,Error={error,_}} ->
+ Error;
+ {_,[],_} ->
+ {error,no_suite_specified};
+ {[],_,_} ->
{error,no_dir_specified};
- Dirs when is_list(Dirs) ->
+
+ {Dirs,undefined,[]} when is_list(Dirs) ->
script_start4(StartOpts#opts{tests = tests(Dirs)}, Args);
- undefined ->
- case proplists:get_value(suite, Args) of
- [] ->
- {error,no_suite_specified};
- Suites when is_list(Suites) ->
- StartOpts1 =
- get_start_opt(step,
- fun(Step) ->
- StartOpts#opts{step = Step,
- cover = undefined}
- end, StartOpts, Args),
- DirMods = [suite_to_test(S) || S <- Suites],
- case groups_and_cases(proplists:get_value(group, Args),
- proplists:get_value(testcase, Args)) of
- Error = {error,_} ->
- Error;
- [] when DirMods =/= [] ->
- Ts = tests(DirMods),
- script_start4(StartOpts1#opts{tests = Ts}, Args);
- GroupsAndCases when length(DirMods) == 1 ->
- Ts = tests(DirMods, GroupsAndCases),
- script_start4(StartOpts1#opts{tests = Ts}, Args);
- [_,_|_] when length(DirMods) > 1 ->
- {error,multiple_suites_and_cases};
- _ ->
- {error,incorrect_suite_option}
- end;
- undefined ->
- if StartOpts#opts.vts ; StartOpts#opts.shell ->
- script_start4(StartOpts#opts{tests = []}, Args);
- true ->
- script_usage(),
- {error,incorrect_usage}
- end
+
+ {undefined,Suites,[]} when is_list(Suites) ->
+ Ts = tests([suite_to_test(S) || S <- Suites]),
+ script_start4(StartOpts1#opts{tests = Ts}, Args);
+
+ {undefined,Suite,GsAndCs} when is_list(Suite) ->
+ case [suite_to_test(S) || S <- Suite] of
+ DirMods = [_] ->
+ Ts = tests(DirMods, GsAndCs),
+ script_start4(StartOpts1#opts{tests = Ts}, Args);
+ [_,_|_] ->
+ {error,multiple_suites_and_cases};
+ _ ->
+ {error,incorrect_start_options}
+ end;
+
+ {[_,_|_],Suite,[]} when is_list(Suite) ->
+ {error,multiple_dirs_and_suites};
+
+ {[Dir],Suite,GsAndCs} when is_list(Dir), is_list(Suite) ->
+ case [suite_to_test(Dir,S) || S <- Suite] of
+ DirMods when GsAndCs == [] ->
+ Ts = tests(DirMods),
+ script_start4(StartOpts1#opts{tests = Ts}, Args);
+ DirMods = [_] when GsAndCs /= [] ->
+ Ts = tests(DirMods, GsAndCs),
+ script_start4(StartOpts1#opts{tests = Ts}, Args);
+ [_,_|_] when GsAndCs /= [] ->
+ {error,multiple_suites_and_cases};
+ _ ->
+ {error,incorrect_start_options}
+ end;
+
+ {undefined,undefined,GsAndCs} when GsAndCs /= [] ->
+ {error,incorrect_start_options};
+
+ {undefined,undefined,_} ->
+ if StartOpts#opts.vts ; StartOpts#opts.shell ->
+ script_start4(StartOpts#opts{tests = []}, Args);
+ true ->
+ script_usage(),
+ {error,missing_start_options}
end
end.
script_start4(#opts{vts = true, config = Config, event_handlers = EvHandlers,
- tests = Tests, logdir = LogDir}, _Args) ->
+ tests = Tests, logdir = LogDir, logopts = LogOpts}, _Args) ->
ConfigFiles =
lists:foldl(fun({ct_config_plain,CfgFiles}, AllFiles) when
is_list(hd(CfgFiles)) ->
@@ -446,25 +496,32 @@ script_start4(#opts{vts = true, config = Config, event_handlers = EvHandlers,
(_, AllFiles) ->
AllFiles
end, [], Config),
- vts:init_data(ConfigFiles, EvHandlers, ?abs(LogDir), Tests);
+ vts:init_data(ConfigFiles, EvHandlers, ?abs(LogDir), LogOpts, Tests);
-script_start4(#opts{label = Label, shell = true, config = Config,
+script_start4(#opts{label = Label, profile = Profile,
+ shell = true, config = Config,
event_handlers = EvHandlers,
ct_hooks = CTHooks,
+ logopts = LogOpts,
+ enable_builtin_hooks = EnableBuiltinHooks,
logdir = LogDir, testspecs = Specs}, _Args) ->
%% label - used by ct_logs
application:set_env(common_test, test_label, Label),
- InstallOpts = [{config,Config},{event_handler,EvHandlers},
- {ct_hooks, CTHooks}],
+ %% profile - used in ct_util
+ application:set_env(common_test, profile, Profile),
+
if Config == [] ->
ok;
true ->
io:format("\nInstalling: ~p\n\n", [Config])
end,
- case install(InstallOpts) of
+ case install([{config,Config},{event_handler,EvHandlers},
+ {ct_hooks, CTHooks},
+ {enable_builtin_hooks,EnableBuiltinHooks}]) of
ok ->
ct_util:start(interactive, LogDir),
+ ct_util:set_testdata({logopts, LogOpts}),
log_ts_names(Specs),
io:nl(),
ok;
@@ -505,6 +562,7 @@ script_usage() ->
"\n\t[-decrypt_key Key] | [-decrypt_file KeyFile]"
"\n\t[-dir TestDir1 TestDir2 .. TestDirN] |"
"\n\t[-suite Suite [-case Case]]"
+ "\n\t[-logopts LogOpt1 LogOpt2 .. LogOptN]"
"\n\t[-include InclDir1 InclDir2 .. InclDirN]"
"\n\t[-no_auto_compile]"
"\n\t[-multiply_timetraps N]"
@@ -522,6 +580,7 @@ script_usage() ->
"\n\t[-stylesheet CSSFile]"
"\n\t[-cover CoverCfgFile]"
"\n\t[-event_handler EvHandler1 EvHandler2 .. EvHandlerN]"
+ "\n\t[-logopts LogOpt1 LogOpt2 .. LogOptN]"
"\n\t[-ct_hooks CTHook1 CTHook2 .. CTHookN]"
"\n\t[-include InclDir1 InclDir2 .. InclDirN]"
"\n\t[-no_auto_compile]"
@@ -541,6 +600,7 @@ script_usage() ->
"\n\t[-stylesheet CSSFile]"
"\n\t[-cover CoverCfgFile]"
"\n\t[-event_handler EvHandler1 EvHandler2 .. EvHandlerN]"
+ "\n\t[-logopts LogOpt1 LogOpt2 .. LogOptN]"
"\n\t[-ct_hooks CTHook1 CTHook2 .. CTHookN]"
"\n\t[-include InclDir1 InclDir2 .. InclDirN]"
"\n\t[-no_auto_compile]"
@@ -619,6 +679,16 @@ run_test(StartOpt) when is_tuple(StartOpt) ->
run_test([StartOpt]);
run_test(StartOpts) when is_list(StartOpts) ->
+ CTPid = spawn(fun() -> run_test1(StartOpts) end),
+ Ref = monitor(process, CTPid),
+ receive
+ {'DOWN',Ref,process,CTPid,{user_error,Error}} ->
+ Error;
+ {'DOWN',Ref,process,CTPid,Other} ->
+ Other
+ end.
+
+run_test1(StartOpts) when is_list(StartOpts) ->
case proplists:get_value(refresh_logs, StartOpts) of
undefined ->
Tracing = start_trace(StartOpts),
@@ -627,7 +697,7 @@ run_test(StartOpts) when is_list(StartOpts) ->
Res =
case ct_repeat:loop_test(func, StartOpts) of
false ->
- case catch run_test1(StartOpts) of
+ case catch run_test2(StartOpts) of
{'EXIT',Reason} ->
file:set_cwd(Cwd),
{error,Reason};
@@ -638,20 +708,27 @@ run_test(StartOpts) when is_list(StartOpts) ->
Result
end,
stop_trace(Tracing),
- Res;
+ exit(Res);
RefreshDir ->
refresh_logs(?abs(RefreshDir)),
- ok
+ exit(done)
end.
-run_test1(StartOpts) ->
+run_test2(StartOpts) ->
%% label
Label = get_start_opt(label, fun(Lbl) when is_list(Lbl) -> Lbl;
(Lbl) when is_atom(Lbl) -> atom_to_list(Lbl)
end, StartOpts),
+ %% profile
+ Profile = get_start_opt(profile, fun(Prof) when is_list(Prof) -> Prof;
+ (Prof) when is_atom(Prof) -> atom_to_list(Prof)
+ end, StartOpts),
%% logdir
LogDir = get_start_opt(logdir, fun(LD) when is_list(LD) -> LD end,
StartOpts),
+ %% logopts
+ LogOpts = get_start_opt(logopts, value, [], StartOpts),
+
%% config & userconfig
CfgFiles = ct_config:get_config_file_list(StartOpts),
@@ -682,6 +759,11 @@ run_test1(StartOpts) ->
%% CT Hooks
CTHooks = get_start_opt(ct_hooks, value, [], StartOpts),
+ EnableBuiltinHooks = get_start_opt(enable_builtin_hooks,
+ fun(EBH) when EBH == true;
+ EBH == false ->
+ EBH
+ end, true, StartOpts),
%% silent connections
SilentConns = get_start_opt(silent_connections,
@@ -750,10 +832,12 @@ run_test1(StartOpts) ->
%% stepped execution
Step = get_start_opt(step, value, StartOpts),
- Opts = #opts{label = Label,
- cover = Cover, step = Step, logdir = LogDir, config = CfgFiles,
+ Opts = #opts{label = Label, profile = Profile,
+ cover = Cover, step = Step, logdir = LogDir,
+ logopts = LogOpts, config = CfgFiles,
event_handlers = EvHandlers,
ct_hooks = CTHooks,
+ enable_builtin_hooks = EnableBuiltinHooks,
include = Include,
silent_connections = SilentConns,
stylesheet = Stylesheet,
@@ -792,8 +876,12 @@ run_spec_file(Relaxed,
SpecOpts = get_data_for_node(TS, node()),
Label = choose_val(Opts#opts.label,
SpecOpts#opts.label),
+ Profile = choose_val(Opts#opts.profile,
+ SpecOpts#opts.profile),
LogDir = choose_val(Opts#opts.logdir,
SpecOpts#opts.logdir),
+ AllLogOpts = merge_vals([Opts#opts.logopts,
+ SpecOpts#opts.logopts]),
AllConfig = merge_vals([CfgFiles, SpecOpts#opts.config]),
Cover = choose_val(Opts#opts.cover,
SpecOpts#opts.cover),
@@ -808,24 +896,29 @@ run_spec_file(Relaxed,
AllCTHooks = merge_vals([Opts#opts.ct_hooks,
SpecOpts#opts.ct_hooks]),
+ EnableBuiltinHooks = choose_val(Opts#opts.enable_builtin_hooks,
+ SpecOpts#opts.enable_builtin_hooks),
application:set_env(common_test, include, AllInclude),
- case check_and_install_configfiles(AllConfig,
- which(logdir,LogDir),
- AllEvHs,
- AllCTHooks) of
+ Opts1 = Opts#opts{label = Label,
+ profile = Profile,
+ cover = Cover,
+ logdir = which(logdir, LogDir),
+ logopts = AllLogOpts,
+ config = AllConfig,
+ event_handlers = AllEvHs,
+ include = AllInclude,
+ testspecs = AbsSpecs,
+ multiply_timetraps = MultTT,
+ scale_timetraps = ScaleTT,
+ ct_hooks = AllCTHooks,
+ enable_builtin_hooks = EnableBuiltinHooks
+ },
+
+ case check_and_install_configfiles(AllConfig,Opts1#opts.logdir,
+ Opts1) of
ok ->
- Opts1 = Opts#opts{label = Label,
- cover = Cover,
- logdir = which(logdir, LogDir),
- config = AllConfig,
- event_handlers = AllEvHs,
- include = AllInclude,
- testspecs = AbsSpecs,
- multiply_timetraps = MultTT,
- scale_timetraps = ScaleTT,
- ct_hooks = AllCTHooks},
{Run,Skip} = ct_testspec:prepare_tests(TS, node()),
reformat_result(catch do_run(Run, Skip, Opts1, StartOpts));
{error,GCFReason} ->
@@ -834,13 +927,10 @@ run_spec_file(Relaxed,
end.
run_prepared(Run, Skip, Opts = #opts{logdir = LogDir,
- config = CfgFiles,
- event_handlers = EvHandlers,
- ct_hooks = CTHooks},
+ config = CfgFiles },
StartOpts) ->
LogDir1 = which(logdir, LogDir),
- case check_and_install_configfiles(CfgFiles, LogDir1,
- EvHandlers, CTHooks) of
+ case check_and_install_configfiles(CfgFiles, LogDir1, Opts) of
ok ->
reformat_result(catch do_run(Run, Skip, Opts#opts{logdir = LogDir1},
StartOpts));
@@ -872,7 +962,8 @@ check_config_file(Callback, File)->
run_dir(Opts = #opts{logdir = LogDir,
config = CfgFiles,
event_handlers = EvHandlers,
- ct_hooks = CTHook }, StartOpts) ->
+ ct_hooks = CTHook,
+ enable_builtin_hooks = EnableBuiltinHooks }, StartOpts) ->
LogDir1 = which(logdir, LogDir),
Opts1 = Opts#opts{logdir = LogDir1},
AbsCfgFiles =
@@ -895,71 +986,107 @@ run_dir(Opts = #opts{logdir = LogDir,
end, CfgFiles),
case install([{config,AbsCfgFiles},
{event_handler,EvHandlers},
- {ct_hooks, CTHook}], LogDir1) of
+ {ct_hooks, CTHook},
+ {enable_builtin_hooks,EnableBuiltinHooks}], LogDir1) of
ok -> ok;
{error,IReason} -> exit(IReason)
end,
- case lists:keysearch(dir, 1, StartOpts) of
- {value,{_,Dirs=[Dir|_]}} when not is_integer(Dir),
- length(Dirs)>1 ->
- %% multiple dirs (no suite)
- reformat_result(catch do_run(tests(Dirs), [], Opts1, StartOpts));
- false -> % no dir
- %% fun for converting suite name to {Dir,Mod} tuple
- S2M = fun(S) when is_list(S) ->
- {filename:dirname(S),
- list_to_atom(filename:rootname(filename:basename(S)))};
- (A) ->
- {".",A}
- end,
- case lists:keysearch(suite, 1, StartOpts) of
- {value,{_,Suite}} when is_integer(hd(Suite)) ; is_atom(Suite) ->
- {Dir,Mod} = S2M(Suite),
- case groups_and_cases(proplists:get_value(group, StartOpts),
- proplists:get_value(testcase, StartOpts)) of
- Error = {error,_} ->
- exit(Error);
+ case {proplists:get_value(dir, StartOpts),
+ proplists:get_value(suite, StartOpts),
+ groups_and_cases(proplists:get_value(group, StartOpts),
+ proplists:get_value(testcase, StartOpts))} of
+ %% flag specified without data
+ {_,_,Error={error,_}} ->
+ Error;
+ {_,[],_} ->
+ {error,no_suite_specified};
+ {[],_,_} ->
+ {error,no_dir_specified};
+
+ {Dirs=[Hd|_],undefined,[]} when is_list(Dirs), not is_integer(Hd) ->
+ Dirs1 = [if is_atom(D) -> atom_to_list(D);
+ true -> D end || D <- Dirs],
+ reformat_result(catch do_run(tests(Dirs1), [], Opts1, StartOpts));
+
+ {Dir=[Hd|_],undefined,[]} when is_list(Dir) and is_integer(Hd) ->
+ reformat_result(catch do_run(tests(Dir), [], Opts1, StartOpts));
+
+ {Dir,undefined,[]} when is_atom(Dir) and (Dir /= undefined) ->
+ reformat_result(catch do_run(tests(atom_to_list(Dir)),
+ [], Opts1, StartOpts));
+
+ {undefined,Suites=[Hd|_],[]} when not is_integer(Hd) ->
+ Suites1 = [suite_to_test(S) || S <- Suites],
+ reformat_result(catch do_run(tests(Suites1), [], Opts1, StartOpts));
+
+ {undefined,Suite,[]} when is_atom(Suite) and
+ (Suite /= undefined) ->
+ {Dir,Mod} = suite_to_test(Suite),
+ reformat_result(catch do_run(tests(Dir, Mod), [], Opts1, StartOpts));
+
+ {undefined,Suite,GsAndCs} when is_atom(Suite) and
+ (Suite /= undefined) ->
+ {Dir,Mod} = suite_to_test(Suite),
+ reformat_result(catch do_run(tests(Dir, Mod, GsAndCs),
+ [], Opts1, StartOpts));
+
+ {undefined,[Hd,_|_],_GsAndCs} when not is_integer(Hd) ->
+ exit(multiple_suites_and_cases);
+
+ {undefined,Suite=[Hd|Tl],GsAndCs} when is_integer(Hd) ;
+ (is_list(Hd) and (Tl == [])) ;
+ (is_atom(Hd) and (Tl == [])) ->
+ {Dir,Mod} = suite_to_test(Suite),
+ reformat_result(catch do_run(tests(Dir, Mod, GsAndCs),
+ [], Opts1, StartOpts));
+
+ {[Hd,_|_],_Suites,[]} when is_list(Hd) ; not is_integer(Hd) ->
+ exit(multiple_dirs_and_suites);
+
+ {undefined,undefined,GsAndCs} when GsAndCs /= [] ->
+ exit(incorrect_start_options);
+
+ {Dir,Suite,GsAndCs} when is_integer(hd(Dir)) ;
+ (is_atom(Dir) and (Dir /= undefined)) ;
+ ((length(Dir) == 1) and is_atom(hd(Dir))) ;
+ ((length(Dir) == 1) and is_list(hd(Dir))) ->
+ Dir1 = if is_atom(Dir) -> atom_to_list(Dir);
+ true -> Dir end,
+ if Suite == undefined ->
+ exit(incorrect_start_options);
+
+ is_integer(hd(Suite)) ;
+ (is_atom(Suite) and (Suite /= undefined)) ;
+ ((length(Suite) == 1) and is_atom(hd(Suite))) ;
+ ((length(Suite) == 1) and is_list(hd(Suite))) ->
+ {Dir2,Mod} = suite_to_test(Dir1, Suite),
+ case GsAndCs of
[] ->
- reformat_result(catch do_run(tests(Dir, listify(Mod)),
+ reformat_result(catch do_run(tests(Dir2, Mod),
[], Opts1, StartOpts));
- GsAndCs ->
- reformat_result(catch do_run(tests(Dir, Mod, GsAndCs),
+ _ ->
+ reformat_result(catch do_run(tests(Dir2, Mod, GsAndCs),
[], Opts1, StartOpts))
end;
- {value,{_,Suites}} ->
- reformat_result(catch do_run(tests(lists:map(S2M, Suites)),
- [], Opts1, StartOpts));
- _ ->
- exit(no_tests_specified)
- end;
- {value,{_,Dir}} ->
- case lists:keysearch(suite, 1, StartOpts) of
- {value,{_,Suite}} when is_integer(hd(Suite)) ; is_atom(Suite) ->
- Mod = if is_atom(Suite) -> Suite;
- true -> list_to_atom(Suite)
- end,
- case groups_and_cases(proplists:get_value(group, StartOpts),
- proplists:get_value(testcase, StartOpts)) of
- Error = {error,_} ->
- exit(Error);
- [] ->
- reformat_result(catch do_run(tests(Dir, listify(Mod)),
+
+ is_list(Suite) -> % multiple suites
+ case [suite_to_test(Dir1, S) || S <- Suite] of
+ [_,_|_] when GsAndCs /= [] ->
+ exit(multiple_suites_and_cases);
+ [{Dir2,Mod}] when GsAndCs /= [] ->
+ reformat_result(catch do_run(tests(Dir2, Mod, GsAndCs),
[], Opts1, StartOpts));
- GsAndCs ->
- reformat_result(catch do_run(tests(Dir, Mod, GsAndCs),
+ DirMods ->
+ reformat_result(catch do_run(tests(DirMods),
[], Opts1, StartOpts))
- end;
- {value,{_,Suites=[Suite|_]}} when is_list(Suite) ->
- Mods = lists:map(fun(Str) -> list_to_atom(Str) end, Suites),
- reformat_result(catch do_run(tests(delistify(Dir), Mods),
- [], Opts1, StartOpts));
- {value,{_,Suites}} ->
- reformat_result(catch do_run(tests(delistify(Dir), Suites),
- [], Opts1, StartOpts));
- false -> % no suite, only dir
- reformat_result(catch do_run(tests(listify(Dir)),
- [], Opts1, StartOpts))
- end
+ end
+ end;
+
+ {undefined,undefined,[]} ->
+ exit(no_test_specified);
+
+ {Dir,Suite,GsAndCs} ->
+ exit({incorrect_start_options,{Dir,Suite,GsAndCs}})
end.
%%%-----------------------------------------------------------------
@@ -970,19 +1097,38 @@ run_dir(Opts = #opts{logdir = LogDir,
%%% the same as those used in test specification files.
%%% @equiv ct:run_testspec/1
%%%-----------------------------------------------------------------
-
run_testspec(TestSpec) ->
+ CTPid = spawn(fun() -> run_testspec1(TestSpec) end),
+ Ref = monitor(process, CTPid),
+ receive
+ {'DOWN',Ref,process,CTPid,{user_error,Error}} ->
+ Error;
+ {'DOWN',Ref,process,CTPid,Other} ->
+ Other
+ end.
+
+run_testspec1(TestSpec) ->
{ok,Cwd} = file:get_cwd(),
io:format("~nCommon Test starting (cwd is ~s)~n~n", [Cwd]),
- case catch run_testspec1(TestSpec) of
+ case catch run_testspec2(TestSpec) of
{'EXIT',Reason} ->
file:set_cwd(Cwd),
- {error,Reason};
+ exit({error,Reason});
Result ->
- Result
+ exit(Result)
end.
-run_testspec1(TestSpec) ->
+run_testspec2(File) when is_list(File), is_integer(hd(File)) ->
+ case file:read_file_info(File) of
+ {ok,_} ->
+ exit("Bad argument, "
+ "use ct:run_test([{spec," ++ File ++ "}])");
+ _ ->
+ exit("Bad argument, list of tuples expected, "
+ "use ct:run_test/1 for test specification files")
+ end;
+
+run_testspec2(TestSpec) ->
case catch ct_testspec:collect_tests_from_list(TestSpec, false) of
{E,CTReason} when E == error ; E == 'EXIT' ->
exit(CTReason);
@@ -999,9 +1145,8 @@ run_testspec1(TestSpec) ->
end,
application:set_env(common_test, include, AllInclude),
LogDir1 = which(logdir,Opts#opts.logdir),
- case check_and_install_configfiles(Opts#opts.config, LogDir1,
- Opts#opts.event_handlers,
- Opts#opts.ct_hooks) of
+ case check_and_install_configfiles(
+ Opts#opts.config, LogDir1, Opts) of
ok ->
Opts1 = Opts#opts{testspecs = [],
logdir = LogDir1,
@@ -1014,20 +1159,28 @@ run_testspec1(TestSpec) ->
end.
get_data_for_node(#testspec{label = Labels,
+ profile = Profiles,
logdir = LogDirs,
+ logopts = LogOptsList,
cover = CoverFs,
config = Cfgs,
userconfig = UsrCfgs,
event_handler = EvHs,
ct_hooks = CTHooks,
+ enable_builtin_hooks = EnableBuiltinHooks,
include = Incl,
multiply_timetraps = MTs,
scale_timetraps = STs}, Node) ->
Label = proplists:get_value(Node, Labels),
+ Profile = proplists:get_value(Node, Profiles),
LogDir = case proplists:get_value(Node, LogDirs) of
undefined -> ".";
Dir -> Dir
end,
+ LogOpts = case proplists:get_value(Node, LogOptsList) of
+ undefined -> [];
+ LOs -> LOs
+ end,
Cover = proplists:get_value(Node, CoverFs),
MT = proplists:get_value(Node, MTs),
ST = proplists:get_value(Node, STs),
@@ -1037,11 +1190,14 @@ get_data_for_node(#testspec{label = Labels,
FiltCTHooks = [Hook || {N,Hook} <- CTHooks, N==Node],
Include = [I || {N,I} <- Incl, N==Node],
#opts{label = Label,
+ profile = Profile,
logdir = LogDir,
+ logopts = LogOpts,
cover = Cover,
config = ConfigFiles,
event_handlers = EvHandlers,
ct_hooks = FiltCTHooks,
+ enable_builtin_hooks = EnableBuiltinHooks,
include = Include,
multiply_timetraps = MT,
scale_timetraps = ST}.
@@ -1118,8 +1274,24 @@ reformat_result({user_error,Reason}) ->
reformat_result(Result) ->
Result.
-suite_to_test(Suite) ->
- {filename:dirname(Suite),list_to_atom(filename:rootname(filename:basename(Suite)))}.
+suite_to_test(Suite) when is_atom(Suite) ->
+ suite_to_test(atom_to_list(Suite));
+
+suite_to_test(Suite) when is_list(Suite) ->
+ {filename:dirname(Suite),
+ list_to_atom(filename:rootname(filename:basename(Suite)))}.
+
+suite_to_test(Dir, Suite) when is_atom(Suite) ->
+ suite_to_test(Dir, atom_to_list(Suite));
+
+suite_to_test(Dir, Suite) when is_list(Suite) ->
+ case filename:dirname(Suite) of
+ "." ->
+ {Dir,list_to_atom(filename:rootname(Suite))};
+ DirName -> % ignore Dir
+ File = filename:basename(Suite),
+ {DirName,list_to_atom(filename:rootname(File))}
+ end.
groups_and_cases(Gs, Cs) when ((Gs == undefined) or (Gs == [])) and
((Cs == undefined) or (Cs == [])) ->
@@ -1153,9 +1325,11 @@ tests(TestDirs) when is_list(TestDirs), is_list(hd(TestDirs)) ->
[{?testdir(TestDir,all),all,all} || TestDir <- TestDirs].
do_run(Tests, Misc) when is_list(Misc) ->
- do_run(Tests, Misc, ".").
+ do_run(Tests, Misc, ".", []).
-do_run(Tests, Misc, LogDir) when is_list(Misc) ->
+do_run(Tests, Misc, LogDir, LogOpts) when is_list(Misc),
+ is_list(LogDir),
+ is_list(LogOpts) ->
Opts =
case proplists:get_value(step, Misc) of
undefined ->
@@ -1170,11 +1344,10 @@ do_run(Tests, Misc, LogDir) when is_list(Misc) ->
CoverFile ->
Opts#opts{cover = CoverFile}
end,
- do_run(Tests, [], Opts1#opts{logdir = LogDir}, []).
-
-do_run(Tests, Skip, Opts, Args) ->
- #opts{label = Label, cover = Cover} = Opts,
+ do_run(Tests, [], Opts1#opts{logdir = LogDir}, []);
+do_run(Tests, Skip, Opts, Args) when is_record(Opts, opts) ->
+ #opts{label = Label, profile = Profile, cover = Cover} = Opts,
%% label - used by ct_logs
TestLabel =
if Label == undefined -> undefined;
@@ -1184,6 +1357,15 @@ do_run(Tests, Skip, Opts, Args) ->
end,
application:set_env(common_test, test_label, TestLabel),
+ %% profile - used in ct_util
+ TestProfile =
+ if Profile == undefined -> undefined;
+ is_atom(Profile) -> atom_to_list(Profile);
+ is_list(Profile) -> Profile;
+ true -> undefined
+ end,
+ application:set_env(common_test, profile, TestProfile),
+
case code:which(test_server) of
non_existing ->
exit({error,no_path_to_test_server});
@@ -1218,6 +1400,8 @@ do_run(Tests, Skip, Opts, Args) ->
_Pid ->
%% save stylesheet info
ct_util:set_testdata({stylesheet,Opts#opts.stylesheet}),
+ %% save logopts
+ ct_util:set_testdata({logopts,Opts#opts.logopts}),
%% enable silent connections
case Opts#opts.silent_connections of
[] ->
@@ -1985,7 +2169,14 @@ maybe_interpret1(Suite, Cases, StepOpts) when is_list(Cases) ->
maybe_interpret2(Suite, Cases, StepOpts) ->
set_break_on_config(Suite, StepOpts),
- [i:ib(Suite, Case, 1) || Case <- Cases],
+ [begin try i:ib(Suite, Case, 1) of
+ _ -> ok
+ catch
+ _:_Error ->
+ io:format(user, "Invalid breakpoint: ~w:~w/1~n",
+ [Suite,Case])
+ end
+ end || Case <- Cases, is_atom(Case)],
test_server_ctrl:multiply_timetraps(infinity),
WinOp = case lists:member(keep_inactive, ensure_atom(StepOpts)) of
true -> no_kill;
@@ -1998,10 +2189,18 @@ maybe_interpret2(Suite, Cases, StepOpts) ->
set_break_on_config(Suite, StepOpts) ->
case lists:member(config, ensure_atom(StepOpts)) of
true ->
- i:ib(Suite, init_per_suite, 1),
- i:ib(Suite, init_per_testcase, 2),
- i:ib(Suite, end_per_testcase, 2),
- i:ib(Suite, end_per_suite, 1);
+ SetBPIfExists = fun(F,A) ->
+ case erlang:function_exported(Suite, F, A) of
+ true -> i:ib(Suite, F, A);
+ false -> ok
+ end
+ end,
+ SetBPIfExists(init_per_suite, 1),
+ SetBPIfExists(init_per_group, 2),
+ SetBPIfExists(init_per_testcase, 2),
+ SetBPIfExists(end_per_testcase, 2),
+ SetBPIfExists(end_per_group, 2),
+ SetBPIfExists(end_per_suite, 1);
false ->
ok
end.
@@ -2055,6 +2254,15 @@ get_start_opt(Key, IfExists, Args) ->
get_start_opt(Key, IfExists, undefined, Args).
get_start_opt(Key, IfExists, IfNotExists, Args) ->
+ try try_get_start_opt(Key, IfExists, IfNotExists, Args) of
+ Result ->
+ Result
+ catch
+ error:_ ->
+ exit({user_error,{bad_argument,Key}})
+ end.
+
+try_get_start_opt(Key, IfExists, IfNotExists, Args) ->
case lists:keysearch(Key, 1, Args) of
{value,{Key,Val}} when is_function(IfExists) ->
IfExists(Val);
@@ -2067,18 +2275,27 @@ get_start_opt(Key, IfExists, IfNotExists, Args) ->
end.
ct_hooks_args2opts(Args) ->
- ct_hooks_args2opts(
- proplists:get_value(ct_hooks, Args, []),[]).
+ lists:foldl(fun({ct_hooks,Hooks}, Acc) ->
+ ct_hooks_args2opts(Hooks,Acc);
+ (_,Acc) ->
+ Acc
+ end,[],Args).
+ct_hooks_args2opts([CTH,Arg,Prio,"and"| Rest],Acc) ->
+ ct_hooks_args2opts(Rest,[{list_to_atom(CTH),
+ parse_cth_args(Arg),
+ parse_cth_args(Prio)}|Acc]);
ct_hooks_args2opts([CTH,Arg,"and"| Rest],Acc) ->
ct_hooks_args2opts(Rest,[{list_to_atom(CTH),
- parse_cth_args(Arg)}|Acc]);
+ parse_cth_args(Arg)}|Acc]);
ct_hooks_args2opts([CTH], Acc) ->
ct_hooks_args2opts([CTH,"and"],Acc);
ct_hooks_args2opts([CTH, "and" | Rest], Acc) ->
ct_hooks_args2opts(Rest,[list_to_atom(CTH)|Acc]);
ct_hooks_args2opts([CTH, Args], Acc) ->
ct_hooks_args2opts([CTH, Args, "and"],Acc);
+ct_hooks_args2opts([CTH, Args, Prio], Acc) ->
+ ct_hooks_args2opts([CTH, Args, Prio, "and"],Acc);
ct_hooks_args2opts([],Acc) ->
lists:reverse(Acc).
@@ -2220,12 +2437,21 @@ opts2args(EnvStartOpts) ->
end, EHs),
[_LastAnd|StrsR] = lists:reverse(lists:flatten(Strs)),
[{event_handler_init,lists:reverse(StrsR)}];
+ ({logopts,LOs}) when is_list(LOs) ->
+ [{logopts,[atom_to_list(LO) || LO <- LOs]}];
({ct_hooks,[]}) ->
[];
({ct_hooks,CTHs}) when is_list(CTHs) ->
io:format(user,"ct_hooks: ~p",[CTHs]),
Strs = lists:flatmap(
- fun({CTH,Arg}) ->
+ fun({CTH,Arg,Prio}) ->
+ [atom_to_list(CTH),
+ lists:flatten(
+ io_lib:format("~p",[Arg])),
+ lists:flatten(
+ io_lib:format("~p",[Prio])),
+ "and"];
+ ({CTH,Arg}) ->
[atom_to_list(CTH),
lists:flatten(
io_lib:format("~p",[Arg])),
@@ -2276,32 +2502,31 @@ is_suite(ModOrFile) when is_list(ModOrFile) ->
end.
get_all_testcases(Suite) ->
- %%! this needs to be updated to handle testcase groups later!!
- case catch Suite:all() of
- {'EXIT',Why} ->
- {error,Why};
- {skip,_} ->
- [];
- Cases ->
- AllCases =
- lists:foldl(fun({sequence,SeqName}, All) ->
- case catch Suite:sequences() of
- {'EXIT',_} ->
- All;
- Seqs ->
- case proplists:get_value(SeqName, Seqs) of
- undefined ->
- All;
- SeqCases ->
- lists:reverse(SeqCases) ++ All
- end
- end;
- (Case,All) ->
- [Case|All]
- end, [], Cases),
- lists:reverse(AllCases)
+ try ct_framework:get_all_cases(Suite) of
+ {error,_Reason} = Error ->
+ Error;
+ SuiteCases ->
+ Cases = [C || {_S,C} <- SuiteCases],
+ try Suite:sequences() of
+ [] ->
+ Cases;
+ Seqs ->
+ TCs1 = lists:flatten([TCs || {_,TCs} <- Seqs]),
+ lists:reverse(
+ lists:foldl(fun(TC, Acc) ->
+ case lists:member(TC, Acc) of
+ true -> Acc;
+ false -> [TC | Acc]
+ end
+ end, [], Cases ++ TCs1))
+ catch
+ _:_ ->
+ Cases
+ end
+ catch
+ _:Error ->
+ {error,Error}
end.
-
%% Internal tracing support. If {ct_trace,TraceSpec} is present, the
%% TraceSpec file will be consulted and dbg used to trace function
@@ -2322,8 +2547,8 @@ start_trace(Args) ->
false
end;
{_,Error} ->
- io:format("Warning! Tracing not started. Reason: ~p~n~n",
- [Error]),
+ io:format("Warning! Tracing not started. Reason: ~s~n~n",
+ [file:format_error(Error)]),
false
end;
false ->
diff --git a/lib/common_test/src/ct_telnet.erl b/lib/common_test/src/ct_telnet.erl
index c6f5fd7df4..71a784870c 100644
--- a/lib/common_test/src/ct_telnet.erl
+++ b/lib/common_test/src/ct_telnet.erl
@@ -245,7 +245,6 @@ cmdf(Connection,CmdFormat,Args) ->
%%% Data = [string()]
%%% @doc Send a telnet command and wait for prompt
%%% (uses a format string and list of arguments to build the command).
-%%%-----------------------------------------------------------------
cmdf(Connection,CmdFormat,Args,Timeout) when is_list(Args) ->
Cmd = lists:flatten(io_lib:format(CmdFormat,Args)),
cmd(Connection,Cmd,Timeout).
@@ -360,15 +359,15 @@ expect(Connection,Patterns) ->
%%% will also be a <code>HaltReason</code> returned.</p>
%%%
%%% <p><underline>Examples:</underline><br/>
-%%% <code>expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}],
-%%% [sequence,{halt,[{nnn,"NNN"}]}]).</code><br/> will try to match
+%%% <code>expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}],</code>
+%%% <code>[sequence,{halt,[{nnn,"NNN"}]}]).</code><br/> will try to match
%%% "ABC" first and then "XYZ", but if "NNN" appears the function will
%%% return <code>{error,{nnn,["NNN"]}}</code>. If both "ABC" and "XYZ"
%%% are matched, the function will return
%%% <code>{ok,[AbcMatch,XyzMatch]}</code>.</p>
%%%
-%%% <p><code>expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}],
-%%% [{repeat,2},{halt,[{nnn,"NNN"}]}]).</code><br/> will try to match
+%%% <p><code>expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}],</code>
+%%% <code>[{repeat,2},{halt,[{nnn,"NNN"}]}]).</code><br/> will try to match
%%% "ABC" or "XYZ" twice. If "NNN" appears the function will return
%%% with <code>HaltReason = {nnn,["NNN"]}</code>.</p>
%%%
diff --git a/lib/common_test/src/ct_testspec.erl b/lib/common_test/src/ct_testspec.erl
index d845358bb2..317910d5c8 100644
--- a/lib/common_test/src/ct_testspec.erl
+++ b/lib/common_test/src/ct_testspec.erl
@@ -249,11 +249,15 @@ collect_tests_from_file1([Spec|Specs],TestSpec,Relaxed) ->
SpecDir = filename:dirname(filename:absname(Spec)),
case file:consult(Spec) of
{ok,Terms} ->
- TestSpec1 = collect_tests(Terms,TestSpec#testspec{spec_dir=SpecDir},
+ TestSpec1 = collect_tests(Terms,
+ TestSpec#testspec{spec_dir=SpecDir},
Relaxed),
collect_tests_from_file1(Specs,TestSpec1,Relaxed);
{error,Reason} ->
- throw({error,{Spec,Reason}})
+ ReasonStr =
+ lists:flatten(io_lib:format("~s",
+ [file:format_error(Reason)])),
+ throw({error,{Spec,ReasonStr}})
end;
collect_tests_from_file1([],TS=#testspec{config=Cfgs,event_handler=EvHs,
include=Incl,tests=Tests},_) ->
@@ -481,6 +485,26 @@ add_tests([{logdir,Node,Dir}|Ts],Spec) ->
add_tests([{logdir,Dir}|Ts],Spec) ->
add_tests([{logdir,all_nodes,Dir}|Ts],Spec);
+%% --- logopts ---
+add_tests([{logopts,all_nodes,Opts}|Ts],Spec) ->
+ LogOpts = Spec#testspec.logopts,
+ Tests = [{logopts,N,Opts} ||
+ N <- list_nodes(Spec),
+ lists:keymember(ref2node(N,Spec#testspec.nodes),1,
+ LogOpts) == false],
+ add_tests(Tests++Ts,Spec);
+add_tests([{logopts,Nodes,Opts}|Ts],Spec) when is_list(Nodes) ->
+ Ts1 = separate(Nodes,logopts,[Opts],Ts,Spec#testspec.nodes),
+ add_tests(Ts1,Spec);
+add_tests([{logopts,Node,Opts}|Ts],Spec) ->
+ LogOpts = Spec#testspec.logopts,
+ LogOpts1 = [{ref2node(Node,Spec#testspec.nodes),Opts} |
+ lists:keydelete(ref2node(Node,Spec#testspec.nodes),
+ 1,LogOpts)],
+ add_tests(Ts,Spec#testspec{logopts=LogOpts1});
+add_tests([{logopts,Opts}|Ts],Spec) ->
+ add_tests([{logopts,all_nodes,Opts}|Ts],Spec);
+
%% --- label ---
add_tests([{label,all_nodes,Lbl}|Ts],Spec) ->
Labels = Spec#testspec.label,
@@ -646,6 +670,10 @@ add_tests([{ct_hooks, _Node, []}|Ts], Spec) ->
add_tests([{ct_hooks, Hooks}|Ts], Spec) ->
add_tests([{ct_hooks, all_nodes, Hooks}|Ts], Spec);
+%% -- enable_builtin_hooks --
+add_tests([{enable_builtin_hooks,Bool}|Ts],Spec) ->
+ add_tests(Ts, Spec#testspec{ enable_builtin_hooks = Bool });
+
%% --- include ---
add_tests([{include,all_nodes,InclDirs}|Ts],Spec) ->
Tests = lists:map(fun(N) -> {include,N,InclDirs} end, list_nodes(Spec)),
@@ -1097,6 +1125,8 @@ valid_terms() ->
{merge_tests,1},
{logdir,2},
{logdir,3},
+ {logopts,2},
+ {logopts,3},
{label,2},
{label,3},
{event_handler,2},
@@ -1104,6 +1134,7 @@ valid_terms() ->
{event_handler,4},
{ct_hooks,2},
{ct_hooks,3},
+ {enable_builtin_hooks,1},
{multiply_timetraps,2},
{multiply_timetraps,3},
{scale_timetraps,2},
diff --git a/lib/common_test/src/ct_util.erl b/lib/common_test/src/ct_util.erl
index b3e345b4e5..3b6ad6f98d 100644
--- a/lib/common_test/src/ct_util.erl
+++ b/lib/common_test/src/ct_util.erl
@@ -47,7 +47,7 @@
-export([get_mode/0, create_table/3, read_opts/0]).
--export([set_cwd/1, reset_cwd/0]).
+-export([set_cwd/1, reset_cwd/0, get_start_dir/0]).
-export([parse_table/1]).
@@ -61,6 +61,9 @@
-export([warn_duplicates/1]).
+-export([get_profile_data/0, get_profile_data/1,
+ get_profile_data/2, open_url/3]).
+
-include("ct_event.hrl").
-include("ct_util.hrl").
@@ -121,13 +124,15 @@ do_start(Parent,Mode,LogDir) ->
ok -> ok;
E -> exit(E)
end,
+ DoExit = fun(Reason) -> file:set_cwd(StartDir), exit(Reason) end,
Opts = case read_opts() of
{ok,Opts1} ->
Opts1;
Error ->
Parent ! {self(),Error},
- exit(Error)
+ DoExit(Error)
end,
+
%% start an event manager (if not already started by master)
case ct_event:start_link() of
{error,{already_started,_}} ->
@@ -140,16 +145,23 @@ do_start(Parent,Mode,LogDir) ->
ct_event:add_handler([{vts,VtsPid}])
end
end,
+
%% start ct_config server
- ct_config:start(Mode),
+ try ct_config:start(Mode) of
+ _ -> ok
+ catch
+ _Class:CfgError ->
+ DoExit(CfgError)
+ end,
+
%% add user event handlers
case lists:keysearch(event_handler,1,Opts) of
{value,{_,Handlers}} ->
Add = fun({H,Args}) ->
case catch gen_event:add_handler(?CT_EVMGR_REF,H,Args) of
ok -> ok;
- {'EXIT',Why} -> exit(Why);
- Other -> exit({event_handler,Other})
+ {'EXIT',Why} -> DoExit(Why);
+ Other -> DoExit({event_handler,Other})
end
end,
case catch lists:foreach(Add,Handlers) of
@@ -168,10 +180,15 @@ do_start(Parent,Mode,LogDir) ->
data={StartTime,
lists:flatten(TestLogDir)}}),
%% Initialize ct_hooks
- case catch ct_hooks:init(Opts) of
+ try ct_hooks:init(Opts) of
ok ->
Parent ! {self(),started};
- {_,CTHReason} ->
+ {fail,CTHReason} ->
+ ct_logs:tc_print('Suite Callback',CTHReason,[]),
+ self() ! {{stop,{self(),{user_error,CTHReason}}},
+ {Parent,make_ref()}}
+ catch
+ _:CTHReason ->
ct_logs:tc_print('Suite Callback',CTHReason,[]),
self() ! {{stop,{self(),{user_error,CTHReason}}},
{Parent,make_ref()}}
@@ -243,6 +260,9 @@ set_cwd(Dir) ->
reset_cwd() ->
call(reset_cwd).
+get_start_dir() ->
+ call(get_start_dir).
+
loop(Mode,TestData,StartDir) ->
receive
{update_last_run_index,From} ->
@@ -319,6 +339,9 @@ loop(Mode,TestData,StartDir) ->
{reset_cwd,From} ->
return(From,file:set_cwd(StartDir)),
loop(From,TestData,StartDir);
+ {get_start_dir,From} ->
+ return(From,StartDir),
+ loop(From,TestData,StartDir);
{{stop,Info},From} ->
Time = calendar:local_time(),
ct_event:sync_notify(#event{name=test_done,
@@ -332,7 +355,7 @@ loop(Mode,TestData,StartDir) ->
ets:delete(?conn_table),
ets:delete(?board_table),
ets:delete(?suite_table),
- ct_logs:close(Info),
+ ct_logs:close(Info, StartDir),
ct_event:stop(),
ct_config:stop(),
file:set_cwd(StartDir),
@@ -727,6 +750,79 @@ warn_duplicates(Suites) ->
lists:foreach(Warn, Suites),
ok.
+%%%-----------------------------------------------------------------
+%%% @spec
+%%%
+%%% @doc
+get_profile_data() ->
+ get_profile_data(all).
+
+get_profile_data(KeyOrStartDir) ->
+ if is_atom(KeyOrStartDir) ->
+ get_profile_data(KeyOrStartDir, get_start_dir());
+ is_list(KeyOrStartDir) ->
+ get_profile_data(all, KeyOrStartDir)
+ end.
+
+get_profile_data(Key, StartDir) ->
+ Profile = case application:get_env(common_test, profile) of
+ {ok,undefined} -> default;
+ {ok,Prof} -> Prof;
+ _ -> default
+ end,
+ get_profile_data(Profile, Key, StartDir).
+
+get_profile_data(Profile, Key, StartDir) ->
+ File = case Profile of
+ default ->
+ ?ct_profile_file;
+ _ when is_list(Profile) ->
+ ?ct_profile_file ++ "." ++ Profile;
+ _ when is_atom(Profile) ->
+ ?ct_profile_file ++ "." ++ atom_to_list(Profile)
+ end,
+ FullNameWD = filename:join(StartDir, File),
+ {WhichFile,Result} =
+ case file:consult(FullNameWD) of
+ {error,enoent} ->
+ case init:get_argument(home) of
+ {ok,[[HomeDir]]} ->
+ FullNameHome = filename:join(HomeDir, File),
+ {FullNameHome,file:consult(FullNameHome)};
+ _ ->
+ {File,{error,enoent}}
+ end;
+ Consulted ->
+ {FullNameWD,Consulted}
+ end,
+ case Result of
+ {error,enoent} when Profile /= default ->
+ io:format(user, "~nERROR! Missing profile file ~p~n", [File]),
+ undefined;
+ {error,enoent} when Profile == default ->
+ undefined;
+ {error,Reason} ->
+ io:format(user,"~nERROR! Error in profile file ~p: ~p~n",
+ [WhichFile,Reason]),
+ undefined;
+ {ok,Data} ->
+ Data1 = case Data of
+ [List] when is_list(List) ->
+ List;
+ _ when is_list(Data) ->
+ Data;
+ _ ->
+ io:format(user,
+ "~nERROR! Invalid profile data in ~p~n",
+ [WhichFile]),
+ []
+ end,
+ if Key == all ->
+ Data1;
+ true ->
+ proplists:get_value(Key, Data)
+ end
+ end.
%%%-----------------------------------------------------------------
%%% Internal functions
@@ -799,3 +895,28 @@ abs_name2([H|T],Acc) ->
abs_name2(T,[H|Acc]);
abs_name2([],Acc) ->
filename:join(lists:reverse(Acc)).
+
+open_url(iexplore, Args, URL) ->
+ {ok,R} = win32reg:open([read]),
+ ok = win32reg:change_key(R,"applications\\iexplore.exe\\shell\\open\\command"),
+ case win32reg:values(R) of
+ {ok, Paths} ->
+ Path = proplists:get_value(default, Paths),
+ [Cmd | _] = string:tokens(Path, "%"),
+ Cmd1 = Cmd ++ " " ++ Args ++ " " ++ URL,
+ io:format(user, "~nOpening ~s with command:~n ~s~n", [URL,Cmd1]),
+ open_port({spawn,Cmd1}, []);
+ _ ->
+ io:format("~nNo path to iexplore.exe~n",[])
+ end,
+ win32reg:close(R),
+ ok;
+
+open_url(Prog, Args, URL) ->
+ ProgStr = if is_atom(Prog) -> atom_to_list(Prog);
+ is_list(Prog) -> Prog
+ end,
+ Cmd = ProgStr ++ " " ++ Args ++ " " ++ URL,
+ io:format(user, "~nOpening ~s with command:~n ~s~n", [URL,Cmd]),
+ open_port({spawn,Cmd},[]),
+ ok.
diff --git a/lib/common_test/src/ct_util.hrl b/lib/common_test/src/ct_util.hrl
index 556f88c84d..bde832811a 100644
--- a/lib/common_test/src/ct_util.hrl
+++ b/lib/common_test/src/ct_util.hrl
@@ -31,12 +31,15 @@
nodes=[],
init=[],
label=[],
+ profile=[],
logdir=["."],
+ logopts=[],
cover=[],
config=[],
userconfig=[],
event_handler=[],
ct_hooks=[],
+ enable_builtin_hooks=true,
include=[],
multiply_timetraps=[],
scale_timetraps=[],
@@ -58,3 +61,5 @@
-define(missing_suites_info, "missing_suites.info").
-define(ct_config_txt, ct_config_plain).
+
+-define(ct_profile_file, ".common_test").
diff --git a/lib/common_test/src/cth_log_redirect.erl b/lib/common_test/src/cth_log_redirect.erl
new file mode 100644
index 0000000000..14663b7738
--- /dev/null
+++ b/lib/common_test/src/cth_log_redirect.erl
@@ -0,0 +1,111 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(cth_log_redirect).
+
+%%% @doc Common Test Framework functions handling test specifications.
+%%%
+%%% <p>This module redirects sasl and error logger info to common test log.</p>
+%%% @end
+
+
+%% CTH Callbacks
+-export([id/1, init/2, post_init_per_group/4, pre_end_per_group/3,
+ post_end_per_testcase/4]).
+
+%% Event handler Callbacks
+-export([init/1,
+ handle_event/2, handle_call/2, handle_info/2,
+ terminate/2]).
+
+id(_Opts) ->
+ ?MODULE.
+
+init(?MODULE, _Opts) ->
+ error_logger:add_report_handler(?MODULE),
+ tc_log.
+
+post_init_per_group(Group, Config, Result, tc_log) ->
+ case lists:member(parallel,proplists:get_value(
+ tc_group_properties,Config,[])) of
+ true ->
+ {Result, {set_log_func(ct_log),Group}};
+ false ->
+ {Result, tc_log}
+ end;
+post_init_per_group(_Group, _Config, Result, State) ->
+ {Result, State}.
+
+post_end_per_testcase(_TC, _Config, Result, State) ->
+ %% Make sure that the event queue is flushed
+ %% before ending this test case.
+ gen_event:call(error_logger, ?MODULE, flush),
+ {Result, State}.
+
+pre_end_per_group(Group, Config, {ct_log, Group}) ->
+ {Config, set_log_func(tc_log)};
+pre_end_per_group(_Group, Config, State) ->
+ {Config, State}.
+
+
+%% Copied and modified from sasl_report_tty_h.erl
+init(_Type) ->
+ {ok, tc_log}.
+
+handle_event({_Type, GL, _Msg}, State) when node(GL) /= node() ->
+ {ok, State};
+handle_event(Event, LogFunc) ->
+ case lists:keyfind(sasl, 1, application:which_applications()) of
+ false ->
+ sasl_not_started;
+ _Else ->
+ {ok, ErrLogType} = application:get_env(sasl, errlog_type),
+ SReport = sasl_report:format_report(group_leader(), ErrLogType,
+ tag_event(Event)),
+ if is_list(SReport) ->
+ ct_logs:LogFunc(sasl, SReport, []);
+ true -> %% Report is an atom if no logging is to be done
+ ignore
+ end
+ end,
+ EReport = error_logger_tty_h:write_event(
+ tag_event(Event),io_lib),
+ if is_list(EReport) ->
+ ct_logs:LogFunc(error_logger, EReport, []);
+ true -> %% Report is an atom if no logging is to be done
+ ignore
+ end,
+ {ok, LogFunc}.
+
+
+handle_info(_,State) -> {ok, State}.
+
+handle_call(flush,State) ->
+ {ok, ok, State};
+handle_call({set_logfunc,NewLogFunc},_) ->
+ {ok, NewLogFunc, NewLogFunc};
+handle_call(_Query, _State) -> {error, bad_query}.
+
+terminate(_Reason, _Type) ->
+ [].
+
+tag_event(Event) ->
+ {calendar:local_time(), Event}.
+
+set_log_func(Func) ->
+ gen_event:call(error_logger, ?MODULE, {set_logfunc, Func}).
diff --git a/lib/common_test/src/vts.erl b/lib/common_test/src/vts.erl
index f0bf090804..cc8a932887 100644
--- a/lib/common_test/src/vts.erl
+++ b/lib/common_test/src/vts.erl
@@ -20,7 +20,7 @@
-module(vts).
-export([start/0,
- init_data/4,
+ init_data/5,
stop/0,
report/2]).
@@ -32,6 +32,7 @@
menu_frame/2,
welcome_frame/2,
config_frame/2,
+ browse_config_file/2,
add_config_file/2,
remove_config_file/2,
run_frame/2,
@@ -56,7 +57,7 @@
-record(state,{tests=[],config=[],event_handler=[],test_runner,
running=0,reload_results=false,start_dir,current_log_dir,
- total=0,ok=0,fail=0,skip=0,testruns=[]}).
+ logopts=[],total=0,ok=0,fail=0,skip=0,testruns=[]}).
%%%-----------------------------------------------------------------
@@ -65,8 +66,8 @@ start() ->
webtool:start(),
webtool:start_tools([],"app=vts").
-init_data(ConfigFiles,EvHandlers,LogDir,Tests) ->
- call({init_data,ConfigFiles,EvHandlers,LogDir,Tests}).
+init_data(ConfigFiles,EvHandlers,LogDir,LogOpts,Tests) ->
+ call({init_data,ConfigFiles,EvHandlers,LogDir,LogOpts,Tests}).
stop() ->
webtool:stop_tools([],"app=vts"),
@@ -119,6 +120,8 @@ menu_frame(_Env,_Input) ->
call(menu_frame).
config_frame(_Env,_Input) ->
call(config_frame).
+browse_config_file(_Env,Input) ->
+ call({browse_config_file,Input}).
add_config_file(_Env,Input) ->
call({add_config_file,Input}).
remove_config_file(_Env,Input) ->
@@ -160,10 +163,11 @@ init(Parent) ->
loop(State) ->
receive
- {{init_data,Config,EvHandlers,LogDir,Tests},From} ->
+ {{init_data,Config,EvHandlers,LogDir,LogOpts,Tests},From} ->
%% ct:pal("State#state.current_log_dir=~p", [State#state.current_log_dir]),
NewState = State#state{config=Config,event_handler=EvHandlers,
- current_log_dir=LogDir,tests=Tests},
+ current_log_dir=LogDir,
+ logopts=LogOpts,tests=Tests},
ct_install(NewState),
return(From,ok),
loop(NewState);
@@ -182,6 +186,9 @@ loop(State) ->
{config_frame,From} ->
return(From,config_frame1(State)),
loop(State);
+ {{browse_config_file,_Input},From} ->
+ return(From,ok),
+ loop(State);
{{add_config_file,Input},From} ->
{Return,State1} = add_config_file1(Input,State),
ct_install(State1),
@@ -241,10 +248,12 @@ loop(State) ->
return(From,ok);
{'EXIT',Pid,Reason} ->
case State#state.test_runner of
- Pid -> io:format("ERROR: test runner crashed: ~p\n",[Reason]);
- _ -> ignore
- end,
- loop(State);
+ Pid ->
+ io:format("Test run error: ~p\n",[Reason]),
+ loop(State);
+ _ ->
+ loop(State)
+ end;
{{test_info,_Type,_Data},From} ->
return(From,ok),
loop(State)
@@ -270,10 +279,11 @@ return({To,Ref},Result) ->
To ! {Ref, Result}.
-run_test1(State=#state{tests=Tests,current_log_dir=LogDir}) ->
+run_test1(State=#state{tests=Tests,current_log_dir=LogDir,
+ logopts=LogOpts}) ->
Self=self(),
RunTest = fun() ->
- case ct_run:do_run(Tests,[],LogDir) of
+ case ct_run:do_run(Tests,[],LogDir,LogOpts) of
{error,_Reason} ->
aborted();
_ ->
@@ -282,17 +292,18 @@ run_test1(State=#state{tests=Tests,current_log_dir=LogDir}) ->
unlink(Self)
end,
Pid = spawn_link(RunTest),
- Total =
+ {Total,Tests1} =
receive
{{test_info,start_info,{_,_,Cases}},From} ->
return(From,ok),
- Cases;
+ {Cases,Tests};
EXIT = {'EXIT',_,_} ->
- self() ! EXIT
+ self() ! EXIT,
+ {0,[]}
after 30000 ->
- 0
+ {0,[]}
end,
- State#state{test_runner=Pid,running=length(Tests),
+ State#state{test_runner=Pid,running=length(Tests1),
total=Total,ok=0,fail=0,skip=0,testruns=[]}.
@@ -356,22 +367,32 @@ config_frame1(State) ->
config_body(State) ->
Entry = [input("TYPE=file NAME=browse SIZE=40"),
input("TYPE=hidden NAME=file")],
+ BrowseForm =
+ form(
+ "NAME=read_file_form METHOD=post ACTION=\"./browse_config_file\"",
+ table(
+ "BORDER=0",
+ [tr(td("1. Locate config file")),
+ tr(td(Entry))])),
AddForm =
form(
- "NAME=read_file_form METHOD=post ACTION=\"./add_config_file\"",
+ "NAME=add_file_form METHOD=post ACTION=\"./add_config_file\"",
table(
"BORDER=0",
- [tr(
- [td(Entry),
+ [tr(td("2. Paste full config file name here")),
+ tr(
+ [td(input("TYPE=text NAME=file SIZE=40")),
td("ALIGN=center",
input("TYPE=submit onClick=\"file.value=browse.value;\""
" VALUE=\"Add\""))])])),
+
{Text,RemoveForm} =
case State#state.config of
[] ->
- T = "To be able to run any tests, one or more configuration "
- "files must be added. Enter the name of the configuration "
- "file below and click the \"Add\" button.",
+ T = "Before running the tests, one or more configuration "
+ "files may be added. Locate the config file, copy its "
+ "full name, paste this into the text field below, then "
+ "click the \"Add\" button.",
R = "",
{T,R};
Files ->
@@ -394,20 +415,24 @@ config_body(State) ->
input("TYPE=submit VALUE=\"Remove\"")))])),
{T,R}
end,
-
+
[h1("ALIGN=center","Config"),
table(
- "WIDTH=600 ALIGN=center CELLPADDING=5",
+ "WIDTH=450 ALIGN=center CELLPADDING=5",
[tr(td(["BGCOLOR=",?INFO_BG_COLOR],Text)),
- tr(td("ALIGN=center",AddForm)),
- tr(td("ALIGN=center",RemoveForm))])].
-
+ tr(td("")),
+ tr(td("")),
+ tr(td("ALIGN=left",BrowseForm)),
+ tr(td("ALIGN=left",AddForm)),
+ tr(td("ALIGN=left",RemoveForm))])].
add_config_file1(Input,State) ->
State1 =
case get_input_data(Input,"file") of
- "" -> State;
- File -> State#state{config=[File|State#state.config]}
+ "" ->
+ State;
+ File ->
+ State#state{config=[File|State#state.config]}
end,
Return = config_frame1(State1),
{Return,State1}.
@@ -427,10 +452,17 @@ run_body(#state{running=Running}) when Running>0 ->
[h1("ALIGN=center","Run Test"),
p(["Test are ongoing: ",href("./result_frameset","Results")])];
run_body(State) ->
- ConfigList = ul([li(File) || File <- State#state.config]),
+ ConfigList =
+ case State#state.config of
+ [] ->
+ ul(["none"]);
+ CfgFiles ->
+ ul([li(File) || File <- CfgFiles])
+ end,
ConfigFiles = [h3("Config Files"),
ConfigList],
-
+ {ok,CWD} = file:get_cwd(),
+ CurrWD = [h3("Current Working Directory"), ul(CWD)],
AddDirForm =
form(
"NAME=add_dir_form METHOD=post ACTION=\"./add_test_dir\"",
@@ -442,7 +474,6 @@ run_body(State) ->
td("ALIGN=center",
input("TYPE=submit onClick=\"dir.value=browse.value;\""
" VALUE=\"Add Test Dir\""))])])),
-
{LoadedTestsTable,Submit} =
case create_testdir_entries(State#state.tests,1) of
[] -> {"",""};
@@ -454,22 +485,20 @@ run_body(State) ->
{table("CELLPADDING=5",[Heading,TestDirs]),
submit_button()}
end,
-
- %% It should be ok to have no config-file!
Body =
- %% case State#state.config of %% [] -> %% p("ALIGN=center",
- %% href("./config_frame","Please select one or
- %% more config files")); %% _ ->
table(
- "WIDTH=100%",
- [tr(td(ConfigFiles)),
+ "WIDTH=450 ALIGN=center",
+ [tr(td("")),
+ tr(td("")),
+ tr(td(ConfigFiles)),
+ tr(td("")),
+ tr(td(CurrWD)),
tr(td("")),
tr(td(AddDirForm)),
tr(td("")),
tr(td(LoadedTestsTable)),
- tr(td(Submit))]),
- %% end,
-
+ tr(td(Submit))
+ ]),
[h1("ALIGN=center","Run Test"), Body].
create_testdir_entries([{Dir,Suite,Case}|Tests],N) ->
@@ -556,18 +585,17 @@ options([Element|Elements],Selected,N,Func) ->
options([],_Selected,_N,_Func) ->
[].
-add_test_dir1(Input,State) ->
+add_test_dir1(Input, State) ->
State1 =
case get_input_data(Input,"dir") of
"" -> State;
Dir0 ->
Dir = case ct_util:is_test_dir(Dir0) of
- true ->
- Dir0;
- false -> filename:join(Dir0,"test")
+ true -> Dir0;
+ false -> ct_util:get_testdir(Dir0, all)
end,
case filelib:is_dir(Dir) of
- true ->
+ true ->
Test = ct_run:tests(Dir),
State#state{tests=State#state.tests++Test};
false ->
@@ -577,8 +605,6 @@ add_test_dir1(Input,State) ->
Return = run_frame1(State1),
{Return,State1}.
-
-
remove_test_dir1(Input,State) ->
N = list_to_integer(get_input_data(Input,"dir")),
State1 = State#state{tests=delete_test(N,State#state.tests)},
@@ -641,6 +667,9 @@ result_frameset2(State) ->
"./redirect_to_result_log_frame";
{_Dir,0} ->
filename:join(["/log_dir","index.html"]);
+ {_Dir,_} when State#state.testruns == [] ->
+ %% crash before first test
+ "./no_result_log_frame";
{_Dir,_} ->
{_,CurrentLog} = hd(State#state.testruns),
CurrentLog
@@ -749,6 +778,8 @@ report1(tc_done,{_Suite,_Case,{skipped,_Reason}},State) ->
State#state{skip=State#state.skip+1};
report1(tc_user_skip,{_Suite,_Case,_Reason},State) ->
State#state{skip=State#state.skip+1};
+report1(tc_auto_skip,{_Suite,_Case,_Reason},State) ->
+ State#state{skip=State#state.skip+1};
report1(loginfo,_,State) ->
State.
@@ -850,6 +881,8 @@ h2(Text) ->
["<H2>",Text,"</H2>\n"].
h3(Text) ->
["<H3>",Text,"</H3>\n"].
+%%h4(Text) ->
+%% ["<H4>",Text,"</H4>\n"].
font(Args,Text) ->
["<FONT ",Args,">\n",Text,"\n</FONT>\n"].
p(Text) ->
diff --git a/lib/common_test/test/ct_error_SUITE.erl b/lib/common_test/test/ct_error_SUITE.erl
index 6867e59b60..c1a455c6d8 100644
--- a/lib/common_test/test/ct_error_SUITE.erl
+++ b/lib/common_test/test/ct_error_SUITE.erl
@@ -60,7 +60,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[cfg_error, lib_error, no_compile, timetrap_end_conf,
- timetrap_normal, timetrap_extended].
+ timetrap_normal, timetrap_extended, timetrap_parallel,
+ timetrap_fun].
groups() ->
[].
@@ -228,6 +229,28 @@ timetrap_parallel(Config) when is_list(Config) ->
ok = ct_test_support:verify_events(TestEvents, Events, Config).
%%%-----------------------------------------------------------------
+%%%
+timetrap_fun(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Join = fun(D, S) -> filename:join(D, "error/test/"++S) end,
+ Suites = [Join(DataDir, "timetrap_4_SUITE"),
+ Join(DataDir, "timetrap_5_SUITE"),
+ Join(DataDir, "timetrap_6_SUITE"),
+ Join(DataDir, "timetrap_7_SUITE")],
+ {Opts,ERPid} = setup([{suite,Suites}], Config),
+ ok = ct_test_support:run(Opts, Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(timetrap_fun,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
+
+ TestEvents = events_to_check(timetrap_fun),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+
+%%%-----------------------------------------------------------------
%%% HELP FUNCTIONS
%%%-----------------------------------------------------------------
@@ -260,7 +283,7 @@ test_events(cfg_error) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
- {?eh,start_info,{14,14,43}},
+ {?eh,start_info,{14,14,45}},
{?eh,tc_start,{cfg_error_1_SUITE,init_per_suite}},
{?eh,tc_done,
@@ -280,41 +303,21 @@ test_events(cfg_error) ->
{?eh,tc_start,{cfg_error_2_SUITE,init_per_suite}},
{?eh,tc_done,
{cfg_error_2_SUITE,init_per_suite,
- {failed,{error,{{badmatch,[1,2]},
- [{cfg_error_2_SUITE,init_per_suite,1},
- {test_server,my_apply,3},
- {test_server,ts_tc,3},
- {test_server,run_test_case_eval1,6},
- {test_server,run_test_case_eval,8}]}}}}},
+ {failed,{error,{{badmatch,[1,2]},'_'}}}}},
{?eh,tc_auto_skip,
{cfg_error_2_SUITE,tc1,
{failed,{cfg_error_2_SUITE,init_per_suite,
- {'EXIT',{{badmatch,[1,2]},
- [{cfg_error_2_SUITE,init_per_suite,1},
- {test_server,my_apply,3},
- {test_server,ts_tc,3},
- {test_server,run_test_case_eval1,6},
- {test_server,run_test_case_eval,8}]}}}}}},
+ {'EXIT',{{badmatch,[1,2]},'_'}}}}}},
{?eh,test_stats,{0,0,{0,3}}},
{?eh,tc_auto_skip,
{cfg_error_2_SUITE,tc2,
{failed,{cfg_error_2_SUITE,init_per_suite,
- {'EXIT',{{badmatch,[1,2]},
- [{cfg_error_2_SUITE,init_per_suite,1},
- {test_server,my_apply,3},
- {test_server,ts_tc,3},
- {test_server,run_test_case_eval1,6},
- {test_server,run_test_case_eval,8}]}}}}}},
+ {'EXIT',{{badmatch,[1,2]},'_'}}}}}},
{?eh,test_stats,{0,0,{0,4}}},
{?eh,tc_auto_skip,
{cfg_error_2_SUITE,end_per_suite,
{failed,{cfg_error_2_SUITE,init_per_suite,
- {'EXIT',{{badmatch,[1,2]},
- [{cfg_error_2_SUITE,init_per_suite,1},
- {test_server,my_apply,3},
- {test_server,ts_tc,3},
- {test_server,run_test_case_eval1,6},
- {test_server,run_test_case_eval,8}]}}}}}},
+ {'EXIT',{{badmatch,[1,2]},'_'}}}}}},
{?eh,tc_start,{cfg_error_3_SUITE,init_per_suite}},
{?eh,tc_done,
@@ -373,12 +376,7 @@ test_events(cfg_error) ->
{?eh,tc_done,{cfg_error_6_SUITE,{end_per_group,g1,[]},ok}}],
{?eh,tc_start,{cfg_error_6_SUITE,end_per_suite}},
{?eh,tc_done,{cfg_error_6_SUITE,end_per_suite,
- {failed,{error,{{badmatch,[1,2]},
- [{cfg_error_6_SUITE,end_per_suite,1},
- {test_server,my_apply,3},
- {test_server,ts_tc,3},
- {test_server,run_test_case_eval1,6},
- {test_server,run_test_case_eval,8}]}}}}},
+ {failed,{error,{{badmatch,[1,2]},'_'}}}}},
{?eh,tc_start,{cfg_error_7_SUITE,init_per_suite}},
{?eh,tc_done,{cfg_error_7_SUITE,init_per_suite,ok}},
@@ -427,31 +425,16 @@ test_events(cfg_error) ->
[{?eh,tc_start,{cfg_error_8_SUITE,{init_per_group,g3,[]}}},
{?eh,tc_done,
{cfg_error_8_SUITE,{init_per_group,g3,[]},
- {failed,{error,{{badmatch,42},
- [{cfg_error_8_SUITE,init_per_group,2},
- {test_server,my_apply,3},
- {test_server,ts_tc,3},
- {test_server,run_test_case_eval1,6},
- {test_server,run_test_case_eval,8}]}}}}},
+ {failed,{error,{{badmatch,42},'_'}}}}},
{?eh,tc_auto_skip,
{cfg_error_8_SUITE,tc1,
{failed,{cfg_error_8_SUITE,init_per_group,
- {'EXIT',{{badmatch,42},
- [{cfg_error_8_SUITE,init_per_group,2},
- {test_server,my_apply,3},
- {test_server,ts_tc,3},
- {test_server,run_test_case_eval1,6},
- {test_server,run_test_case_eval,8}]}}}}}},
+ {'EXIT',{{badmatch,42},'_'}}}}}},
{?eh,test_stats,{4,0,{0,13}}},
{?eh,tc_auto_skip,
{cfg_error_8_SUITE,end_per_group,
{failed,{cfg_error_8_SUITE,init_per_group,
- {'EXIT',{{badmatch,42},
- [{cfg_error_8_SUITE,init_per_group,2},
- {test_server,my_apply,3},
- {test_server,ts_tc,3},
- {test_server,run_test_case_eval1,6},
- {test_server,run_test_case_eval,8}]}}}}}}],
+ {'EXIT',{{badmatch,42},'_'}}}}}}],
[{?eh,tc_start,{cfg_error_8_SUITE,{init_per_group,g4,[]}}},
{?eh,tc_done,{cfg_error_8_SUITE,{init_per_group,g4,[]},ok}},
@@ -520,12 +503,7 @@ test_events(cfg_error) ->
{?eh,tc_start,{cfg_error_9_SUITE,tc3}},
{?eh,tc_done,{cfg_error_9_SUITE,tc3,
{skipped,{failed,{cfg_error_9_SUITE,init_per_testcase,
- {{badmatch,undefined},
- [{cfg_error_9_SUITE,init_per_testcase,2},
- {test_server,my_apply,3},
- {test_server,init_per_testcase,3},
- {test_server,run_test_case_eval1,6},
- {test_server,run_test_case_eval,8}]}}}}}},
+ {{badmatch,undefined},'_'}}}}}},
{?eh,test_stats,{9,0,{0,17}}},
{?eh,tc_start,{cfg_error_9_SUITE,tc4}},
{?eh,tc_done,
@@ -562,13 +540,18 @@ test_events(cfg_error) ->
{test_server,my_apply,3},
{test_server,do_end_per_testcase,4},
{test_server,run_test_case_eval1,6},
- {test_server,run_test_case_eval,8}]}}}}}},
+ {test_server,run_test_case_eval,9}]}}}}}},
{?eh,test_stats,{12,3,{0,18}}},
{?eh,tc_start,{cfg_error_9_SUITE,tc14}},
{?eh,tc_done,
{cfg_error_9_SUITE,tc14,{failed,{error,tc14_should_be_failed}}}},
- {?eh,test_stats,{12,4,{0,18}}},
-
+ {?eh,tc_start,{cfg_error_9_SUITE,tc15}},
+ {?eh,tc_done,
+ {cfg_error_9_SUITE,tc15,{failed,{error,this_error_must_show}}}},
+ {?eh,tc_start,{cfg_error_9_SUITE,tc16}},
+ {?eh,tc_done,
+ {cfg_error_9_SUITE,tc16,{failed,{error,this_error_must_show}}}},
+ {?eh,test_stats,{12,6,{0,18}}},
{?eh,tc_start,{cfg_error_9_SUITE,end_per_suite}},
{?eh,tc_done,{cfg_error_9_SUITE,end_per_suite,ok}},
@@ -578,7 +561,7 @@ test_events(cfg_error) ->
{?eh,tc_auto_skip,{cfg_error_10_SUITE,tc1,
{failed,{cfg_error_10_SUITE,init_per_suite,
{failed,fail_init_per_suite}}}}},
- {?eh,test_stats,{12,4,{0,19}}},
+ {?eh,test_stats,{12,6,{0,19}}},
{?eh,tc_auto_skip,{cfg_error_10_SUITE,end_per_suite,
{failed,{cfg_error_10_SUITE,init_per_suite,
{failed,fail_init_per_suite}}}}},
@@ -587,40 +570,40 @@ test_events(cfg_error) ->
{?eh,tc_start,{cfg_error_11_SUITE,tc1}},
{?eh,tc_done,{cfg_error_11_SUITE,tc1,
{skipped,{config_name_already_in_use,[dummy0]}}}},
- {?eh,test_stats,{12,4,{1,19}}},
+ {?eh,test_stats,{12,6,{1,19}}},
{?eh,tc_start,{cfg_error_11_SUITE,tc2}},
{?eh,tc_done,{cfg_error_11_SUITE,tc2,ok}},
- {?eh,test_stats,{13,4,{1,19}}},
+ {?eh,test_stats,{13,6,{1,19}}},
{?eh,tc_start,{cfg_error_11_SUITE,end_per_suite}},
{?eh,tc_done,{cfg_error_11_SUITE,end_per_suite,ok}},
{?eh,tc_start,{cfg_error_12_SUITE,tc1}},
{?eh,tc_done,{cfg_error_12_SUITE,tc1,{failed,{timetrap_timeout,500}}}},
- {?eh,test_stats,{13,5,{1,19}}},
+ {?eh,test_stats,{13,7,{1,19}}},
{?eh,tc_start,{cfg_error_12_SUITE,tc2}},
{?eh,tc_done,{cfg_error_12_SUITE,tc2,{failed,
{cfg_error_12_SUITE,end_per_testcase,
{timetrap_timeout,500}}}}},
- {?eh,test_stats,{14,5,{1,19}}},
+ {?eh,test_stats,{14,7,{1,19}}},
{?eh,tc_start,{cfg_error_12_SUITE,tc3}},
{?eh,tc_done,{cfg_error_12_SUITE,tc3,ok}},
- {?eh,test_stats,{15,5,{1,19}}},
+ {?eh,test_stats,{15,7,{1,19}}},
{?eh,tc_start,{cfg_error_12_SUITE,tc4}},
{?eh,tc_done,{cfg_error_12_SUITE,tc4,{failed,
{cfg_error_12_SUITE,end_per_testcase,
{timetrap_timeout,500}}}}},
- {?eh,test_stats,{16,5,{1,19}}},
+ {?eh,test_stats,{16,7,{1,19}}},
{?eh,tc_start,{cfg_error_13_SUITE,init_per_suite}},
{?eh,tc_done,{cfg_error_13_SUITE,init_per_suite,ok}},
{?eh,tc_start,{cfg_error_13_SUITE,tc1}},
{?eh,tc_done,{cfg_error_13_SUITE,tc1,ok}},
- {?eh,test_stats,{17,5,{1,19}}},
+ {?eh,test_stats,{17,7,{1,19}}},
{?eh,tc_start,{cfg_error_13_SUITE,end_per_suite}},
{?eh,tc_done,{cfg_error_13_SUITE,end_per_suite,ok}},
{?eh,tc_start,{cfg_error_14_SUITE,init_per_suite}},
{?eh,tc_done,{cfg_error_14_SUITE,init_per_suite,ok}},
{?eh,tc_start,{cfg_error_14_SUITE,tc1}},
{?eh,tc_done,{cfg_error_14_SUITE,tc1,ok}},
- {?eh,test_stats,{18,5,{1,19}}},
+ {?eh,test_stats,{18,7,{1,19}}},
{?eh,tc_start,{cfg_error_14_SUITE,end_per_suite}},
{?eh,tc_done,{cfg_error_14_SUITE,end_per_suite,
{comment,
@@ -640,13 +623,7 @@ test_events(lib_error) ->
{?eh,tc_done,
{lib_error_1_SUITE,lines_error,{failed,
{error,
- {{badmatch,[1,2]},
- [{lib_lines,do_error,0},
- {lib_error_1_SUITE,lines_error,1},
- {test_server,my_apply,3},
- {test_server,ts_tc,3},
- {test_server,run_test_case_eval1,6},
- {test_server,run_test_case_eval,8}]}}}}},
+ {{badmatch,[1,2]},'_'}}}}},
{?eh,test_stats,{0,1,{0,0}}},
{?eh,tc_start,{lib_error_1_SUITE,lines_exit}},
{?eh,tc_done,
@@ -654,7 +631,7 @@ test_events(lib_error) ->
{?eh,test_stats,{0,2,{0,0}}},
{?eh,tc_start,{lib_error_1_SUITE,lines_hang}},
{?eh,tc_done,
- {lib_lines,do_hang,{failed,{timetrap_timeout,3000}}}},
+ {lib_error_1_SUITE,lines_hang,{failed,{timetrap_timeout,3000}}}},
{?eh,test_stats,{0,3,{0,0}}},
{?eh,tc_start,{lib_error_1_SUITE,lines_throw}},
{?eh,tc_done,
@@ -665,13 +642,7 @@ test_events(lib_error) ->
{?eh,tc_done,
{lib_error_1_SUITE,no_lines_error,{failed,
{error,
- {{badmatch,[1,2]},
- [{lib_no_lines,do_error,0},
- {lib_error_1_SUITE,no_lines_error,1},
- {test_server,my_apply,3},
- {test_server,ts_tc,3},
- {test_server,run_test_case_eval1,6},
- {test_server,run_test_case_eval,8}]}}}}},
+ {{badmatch,[1,2]},'_'}}}}},
{?eh,test_stats,{0,5,{0,0}}},
{?eh,tc_start,{lib_error_1_SUITE,no_lines_exit}},
{?eh,tc_done,
@@ -809,7 +780,7 @@ test_events(timetrap_parallel) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
- {?eh,start_info,{1,1,7}},
+ {?eh,start_info,{1,1,8}},
{?eh,tc_done,{timetrap_3_SUITE,init_per_suite,ok}},
{parallel,
[{?eh,tc_start,
@@ -821,9 +792,12 @@ test_events(timetrap_parallel) ->
{?eh,tc_start,{timetrap_3_SUITE,tc2}},
{?eh,tc_start,{timetrap_3_SUITE,tc3}},
{?eh,tc_start,{timetrap_3_SUITE,tc4}},
+ {?eh,tc_start,{timetrap_3_SUITE,tc5}},
{?eh,tc_start,{timetrap_3_SUITE,tc6}},
{?eh,tc_start,{timetrap_3_SUITE,tc7}},
{?eh,tc_done,
+ {timetrap_3_SUITE,tc5,ok}},
+ {?eh,tc_done,
{timetrap_3_SUITE,tc1,{failed,{timetrap_timeout,500}}}},
{?eh,tc_done,
{timetrap_3_SUITE,tc2,{failed,{timetrap_timeout,1000}}}},
@@ -837,11 +811,90 @@ test_events(timetrap_parallel) ->
{timetrap_3_SUITE,tc4,{failed,{timetrap_timeout,2000}}}},
{?eh,tc_done,
{timetrap_3_SUITE,tc3,{failed,{timetrap_timeout,3000}}}},
- {?eh,test_stats,{0,7,{0,0}}},
+ {?eh,test_stats,{1,7,{0,0}}},
{?eh,tc_start,
{timetrap_3_SUITE,{end_per_group,g1,[parallel]}}},
{?eh,tc_done,
{timetrap_3_SUITE,{end_per_group,g1,[parallel]},ok}}]},
{?eh,tc_done,{timetrap_3_SUITE,end_per_suite,ok}},
{?eh,test_done,{'DEF','STOP_TIME'}},
- {?eh,stop_logging,[]}].
+ {?eh,stop_logging,[]}];
+
+test_events(timetrap_fun) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,start_info,{4,4,17}},
+ {?eh,tc_done,{timetrap_4_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{timetrap_4_SUITE,tc0}},
+ {?eh,tc_done,
+ {timetrap_4_SUITE,tc0,{failed,{timetrap_timeout,1000}}}},
+ {?eh,tc_start,{timetrap_4_SUITE,tc1}},
+ {?eh,tc_done,
+ {timetrap_4_SUITE,tc1,{failed,{timetrap_timeout,2000}}}},
+ {?eh,tc_start,{timetrap_4_SUITE,tc2}},
+ {?eh,tc_done,
+ {timetrap_4_SUITE,tc2,{failed,{timetrap_timeout,500}}}},
+ {?eh,tc_start,{timetrap_4_SUITE,tc3}},
+ {?eh,tc_done,
+ {timetrap_4_SUITE,tc3,{failed,{timetrap_timeout,1000}}}},
+ {?eh,test_stats,{0,4,{0,0}}},
+ {?eh,tc_done,{timetrap_4_SUITE,end_per_suite,ok}},
+
+ {?eh,tc_done,{timetrap_5_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{timetrap_5_SUITE,tc0}},
+ {?eh,tc_done,
+ {timetrap_5_SUITE,tc0,{failed,{timetrap_timeout,1000}}}},
+ {?eh,test_stats,{0,5,{0,0}}},
+ {?eh,tc_start,{timetrap_5_SUITE,tc1}},
+ {?eh,tc_done,
+ {timetrap_5_SUITE,tc1,{skipped,{timetrap_error,kaboom}}}},
+ {?eh,tc_start,{timetrap_5_SUITE,tc2}},
+ {?eh,tc_done,
+ {timetrap_5_SUITE,tc2,{skipped,{timetrap_error,kaboom}}}},
+ {?eh,tc_start,{timetrap_5_SUITE,tc3}},
+ {?eh,tc_done,
+ {timetrap_5_SUITE,tc3,
+ {skipped,{invalid_time_format,{timetrap_utils,timetrap_val,[5000]}}}}},
+ {?eh,tc_start,{timetrap_5_SUITE,tc4}},
+ {?eh,tc_done,
+ {timetrap_5_SUITE,tc4,{skipped,{invalid_time_format,'_'}}}},
+ {?eh,test_stats,{0,5,{0,4}}},
+ {?eh,tc_start,{timetrap_5_SUITE,tc5}},
+ {?eh,tc_done,
+ {timetrap_5_SUITE,tc5,{failed,{timetrap_timeout,1000}}}},
+ {?eh,tc_start,{timetrap_5_SUITE,tc6}},
+ {?eh,tc_done,
+ {timetrap_5_SUITE,tc6,{failed,{timetrap_timeout,1000}}}},
+ {?eh,tc_start,{timetrap_5_SUITE,tc7}},
+ {?eh,tc_done,
+ {timetrap_5_SUITE,tc7,{failed,{timetrap_timeout,1000}}}},
+ {?eh,test_stats,{0,8,{0,4}}},
+ {?eh,tc_done,{timetrap_5_SUITE,end_per_suite,ok}},
+
+ {?eh,tc_start,{timetrap_6_SUITE,init_per_suite}},
+ {?eh,tc_done,
+ {timetrap_6_SUITE,init_per_suite,{skipped,{timetrap_error,kaboom}}}},
+ {?eh,tc_auto_skip,
+ {timetrap_6_SUITE,tc0,{fw_auto_skip,{timetrap_error,kaboom}}}},
+ {?eh,test_stats,{0,8,{0,5}}},
+ {?eh,tc_auto_skip,
+ {timetrap_6_SUITE,end_per_suite,{fw_auto_skip,{timetrap_error,kaboom}}}},
+
+ {?eh,tc_done,{timetrap_7_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{timetrap_7_SUITE,tc0}},
+ {?eh,tc_done,
+ {timetrap_7_SUITE,tc0,{failed,{timetrap_timeout,1000}}}},
+ {?eh,tc_start,{timetrap_7_SUITE,tc1}},
+ {?eh,tc_done,
+ {timetrap_7_SUITE,tc1,{failed,{timetrap_timeout,2000}}}},
+ {?eh,tc_start,{timetrap_7_SUITE,tc2}},
+ {?eh,tc_done,
+ {timetrap_7_SUITE,tc2,{failed,{timetrap_timeout,500}}}},
+ {?eh,tc_start,{timetrap_7_SUITE,tc3}},
+ {?eh,tc_done,
+ {timetrap_7_SUITE,tc3,{failed,{timetrap_timeout,1000}}}},
+ {?eh,test_stats,{0,12,{0,5}}},
+ {?eh,tc_done,{timetrap_7_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ].
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_9_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_9_SUITE.erl
index c4e0d72948..f292985c0c 100644
--- a/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_9_SUITE.erl
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_9_SUITE.erl
@@ -76,7 +76,7 @@ init_per_testcase(tc1, Config) ->
Config;
init_per_testcase(tc2, Config) ->
ct:comment("init_per_testcase(tc2) timeout"),
- timer:sleep(5000),
+ ct:sleep(5000),
Config;
init_per_testcase(tc3, Config) ->
badmatch = ?config(void, Config),
@@ -96,22 +96,20 @@ init_per_testcase(_, Config) ->
%%--------------------------------------------------------------------
end_per_testcase(tc11, _Config) ->
ct:comment("A warning should be printed"),
- exit(warning_should_be_printed),
- done;
+ exit(warning_should_be_printed);
end_per_testcase(tc12, _Config) ->
ct:comment("A warning should be printed"),
- timer:sleep(5000),
- done;
+ ct:sleep(5000);
end_per_testcase(tc13, Config) ->
ct:comment("A warning should be printed"),
- badmatch = ?config(void, Config),
- done;
+ badmatch = ?config(void, Config);
end_per_testcase(tc14, Config) ->
ok = ?config(tc_status, Config),
{fail,tc14_should_be_failed};
end_per_testcase(tc15, Config) ->
- {failed,byebye} = ?config(tc_status, Config),
- ok;
+ exit(kaboom);
+end_per_testcase(tc16, Config) ->
+ ct:sleep(5000);
end_per_testcase(_TestCase, _Config) ->
done.
@@ -139,7 +137,7 @@ groups() ->
%%--------------------------------------------------------------------
all() ->
[tc1,tc2,tc3,tc4,tc5,tc6,tc7,
- tc11,tc12,tc13,tc14].
+ tc11,tc12,tc13,tc14,tc15,tc16].
tc1(_) ->
fini.
@@ -189,4 +187,6 @@ tc14(_) ->
ct:comment("This one should be failed by eptc"),
yes.
tc15(_) ->
- exit(byebye).
+ exit(this_error_must_show).
+tc16(_) ->
+ exit(this_error_must_show).
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_3_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_3_SUITE.erl
new file mode 100644
index 0000000000..8271b23afe
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_3_SUITE.erl
@@ -0,0 +1,146 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(timetrap_3_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+-define(TO, 3).
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,?TO}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [{g1,[parallel],[tc0,tc1,tc2,tc3,tc4,tc5,tc6,tc7]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [{group,g1}].
+
+tc0() ->
+ [{timetrap,2000}].
+tc0(_) ->
+ ct:comment("TO after 2 sec"),
+ ct:sleep({seconds,5}),
+ ok.
+
+tc1() ->
+ [{timetrap,500}].
+tc1(_) ->
+ ct:comment("TO after 1/2 sec"),
+ ct:sleep({seconds,5}),
+ ok.
+
+tc2() ->
+ [{timetrap,1000}].
+tc2(_) ->
+ ct:comment("TO after 1 sec"),
+ ct:sleep({seconds,5}),
+ ok.
+
+tc3(_) ->
+ ct:comment(io_lib:format("TO after ~w sec", [?TO])),
+ ct:sleep({seconds,5}),
+ ok.
+
+tc4() ->
+ [{timetrap,2000}].
+tc4(_) ->
+ ct:comment(io_lib:format("TO after 2 sec", [])),
+ ct:sleep({seconds,5}),
+ ok.
+
+tc5() ->
+ [{timetrap,2000}].
+tc5(_) ->
+ ct:comment("No timeout"),
+ ct:sleep({seconds,1}),
+ ok.
+
+tc6() ->
+ [{timetrap,1000}].
+tc6(_) ->
+ ct:comment("TO after 1 sec"),
+ ct:sleep({seconds,5}),
+ ok.
+
+tc7() ->
+ [{timetrap,1500}].
+tc7(_) ->
+ ct:comment("TO after 1 1/2 sec"),
+ ct:sleep({seconds,5}),
+ ok.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_4_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_4_SUITE.erl
new file mode 100644
index 0000000000..d902454f09
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_4_SUITE.erl
@@ -0,0 +1,135 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(timetrap_4_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+-define(TO, 1).
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{timetrap_utils,timetrap_val,[{seconds,?TO}]}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc0,tc1,tc2,tc3].
+
+tc0(_) ->
+ ct:comment(io_lib:format("TO after ~w sec", [?TO])),
+ ct:sleep({seconds,5}),
+ ok.
+
+tc1() ->
+ [{timetrap,{timetrap_utils,timetrap_val,[2000]}}].
+tc1(_) ->
+ ct:comment("TO after 2 sec"),
+ ct:sleep({seconds,5}),
+ ok.
+
+tc2() ->
+ [{timetrap,fun() -> timetrap_utils:timetrap_val(500) end}].
+tc2(_) ->
+ ct:comment("TO after 0.5 sec"),
+ ct:sleep(1000),
+ ok.
+
+tc3(_) ->
+ ct:comment(io_lib:format("TO after ~w sec", [?TO])),
+ ct:sleep({seconds,5}),
+ ok.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_5_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_5_SUITE.erl
new file mode 100644
index 0000000000..c5d4b5062e
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_5_SUITE.erl
@@ -0,0 +1,155 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(timetrap_5_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+-define(TO, 1).
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap, fun() -> timetrap_utils:timetrap_val({seconds,?TO}) end}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc0,tc1,tc2,tc3,tc4,tc5,tc6,tc7].
+
+tc0(_) ->
+ ct:comment(io_lib:format("TO after ~w sec", [?TO])),
+ ct:sleep({seconds,5}),
+ ok.
+
+tc1() ->
+ [{timetrap,{timetrap_utils,timetrap_exit,[kaboom]}}].
+tc1(_) ->
+ exit(this_should_not_execute).
+
+tc2() ->
+ [{timetrap,fun() -> exit(kaboom) end}].
+tc2(_) ->
+ exit(this_should_not_execute).
+
+tc3() ->
+ [{timetrap,{timetrap_utils,timetrap_err_mfa,[]}}].
+tc3(_) ->
+ exit(this_should_not_execute).
+
+tc4() ->
+ [{timetrap,fun() -> timetrap_utils:timetrap_err_fun() end}].
+tc4(_) ->
+ exit(this_should_not_execute).
+
+tc5() ->
+ [{timetrap,{timetrap_utils,timetrap_timeout,[{seconds,40},
+ {seconds,1}]}}].
+tc5(_) ->
+ ct:comment("TO after 40+1 sec"),
+ ct:sleep({seconds,42}),
+ ok.
+
+tc6() ->
+ [{timetrap,fun() -> ct:sleep(6000), 1000 end}].
+tc6(_) ->
+ ct:comment("TO after 6+1 sec"),
+ ct:sleep({seconds,10}).
+
+tc7(_) ->
+ ct:comment(io_lib:format("TO after ~w sec", [?TO])),
+ ct:sleep({seconds,5}),
+ ok.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_6_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_6_SUITE.erl
new file mode 100644
index 0000000000..90467ff752
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_6_SUITE.erl
@@ -0,0 +1,114 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(timetrap_6_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+-define(TO, 1).
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap, fun() -> exit(kaboom) end}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc0].
+
+tc0(_) ->
+ ok.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_7_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_7_SUITE.erl
new file mode 100644
index 0000000000..b25b7770a7
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_7_SUITE.erl
@@ -0,0 +1,137 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(timetrap_7_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+-define(TO, 1).
+-define(HANG, 6).
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{timetrap_utils,timetrap_timeout,[{seconds,?HANG},
+ {seconds,?TO}]}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc0,tc1,tc2,tc3].
+
+tc0(_) ->
+ ct:comment(io_lib:format("TO after ~w+~w sec", [?HANG,?TO])),
+ ct:sleep({seconds,5}),
+ ok.
+
+tc1() ->
+ [{timetrap,{timetrap_utils,timetrap_val,[2000]}}].
+tc1(_) ->
+ ct:comment("TO after 2 sec"),
+ ct:sleep({seconds,5}),
+ ok.
+
+tc2() ->
+ [{timetrap,fun() -> timetrap_utils:timetrap_val(500) end}].
+tc2(_) ->
+ ct:comment("TO after 0.5 sec"),
+ ct:sleep(1000),
+ ok.
+
+tc3(_) ->
+ ct:comment(io_lib:format("TO after ~w+~w sec", [?HANG,?TO])),
+ ct:sleep({seconds,5}),
+ ok.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_utils.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_utils.erl
new file mode 100644
index 0000000000..fcde6cd701
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_utils.erl
@@ -0,0 +1,43 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(timetrap_utils).
+
+-export([timetrap_val/1,
+ timetrap_err_fun/0,
+ timetrap_err_mfa/0,
+ timetrap_exit/1,
+ timetrap_timeout/2]).
+
+timetrap_val(Val) ->
+ Val.
+
+timetrap_err_fun() ->
+ fun() -> 5000 end.
+
+timetrap_err_mfa() ->
+ {?MODULE,timetrap_val,[5000]}.
+
+timetrap_exit(Reason) ->
+ exit(Reason).
+
+timetrap_timeout(Sleep, Val) ->
+ ct:sleep(Sleep),
+ Val.
+
diff --git a/lib/common_test/test/ct_groups_test_2_SUITE.erl b/lib/common_test/test/ct_groups_test_2_SUITE.erl
index f33be8a9d4..940d791b15 100644
--- a/lib/common_test/test/ct_groups_test_2_SUITE.erl
+++ b/lib/common_test/test/ct_groups_test_2_SUITE.erl
@@ -173,16 +173,14 @@ test_events(missing_conf) ->
{?eh,start_info,{1,1,2}},
{?eh,tc_start,{ct_framework,ct_init_per_group}},
{?eh,tc_done,{ct_framework,ct_init_per_group,ok}},
- {?eh,test_stats,{1,0,{0,0}}},
{?eh,tc_start,{missing_conf_SUITE,tc1}},
{?eh,tc_done,{missing_conf_SUITE,tc1,ok}},
- {?eh,test_stats,{2,0,{0,0}}},
+ {?eh,test_stats,{1,0,{0,0}}},
{?eh,tc_start,{missing_conf_SUITE,tc2}},
{?eh,tc_done,{missing_conf_SUITE,tc2,ok}},
- {?eh,test_stats,{3,0,{0,0}}},
+ {?eh,test_stats,{2,0,{0,0}}},
{?eh,tc_start,{ct_framework,ct_end_per_group}},
{?eh,tc_done,{ct_framework,ct_end_per_group,ok}},
- {?eh,test_stats,{4,0,{0,0}}},
{?eh,test_done,{'DEF','STOP_TIME'}},
{?eh,stop_logging,[]}
];
diff --git a/lib/common_test/test/ct_hooks_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE.erl
index 8574d7aabc..5c99f0f9f7 100644
--- a/lib/common_test/test/ct_hooks_SUITE.erl
+++ b/lib/common_test/test/ct_hooks_SUITE.erl
@@ -83,7 +83,7 @@ all(suite) ->
fail_post_suite_cth, skip_pre_suite_cth,
skip_post_suite_cth, recover_post_suite_cth, update_config_cth,
state_update_cth, options_cth, same_id_cth,
- fail_n_skip_with_minimal_cth
+ fail_n_skip_with_minimal_cth, prio_cth
]
)
.
@@ -209,6 +209,11 @@ fail_n_skip_with_minimal_cth(Config) when is_list(Config) ->
do_test(fail_n_skip_with_minimal_cth, "ct_cth_fail_one_skip_one_SUITE.erl",
[minimal_terminate_cth],Config).
+prio_cth(Config) when is_list(Config) ->
+ do_test(prio_cth, "ct_cth_prio_SUITE.erl",
+ [{empty_cth,[1000],1000},{empty_cth,[900],900},
+ {prio_cth,[1100,100],100},{prio_cth,[1100]}],Config).
+
%%%-----------------------------------------------------------------
%%% HELP FUNCTIONS
%%%-----------------------------------------------------------------
@@ -296,9 +301,9 @@ test_events(two_empty_cth) ->
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
{?eh,cth,{'_',id,[[]]}},
- {?eh,cth,{'_',init,['_',[]]}},
{?eh,cth,{'_',id,[[]]}},
{?eh,cth,{'_',init,['_',[]]}},
+ {?eh,cth,{'_',init,['_',[]]}},
{?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}},
{?eh,cth,{'_',pre_init_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}},
{?eh,cth,{'_',pre_init_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}},
@@ -365,9 +370,9 @@ test_events(minimal_and_maximal_cth) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{'_',id,[[]]}},
{negative,{?eh,cth,{'_',id,['_',[]]}},
{?eh,cth,{'_',init,['_',[]]}}},
- {?eh,cth,{'_',id,[[]]}},
{?eh,cth,{'_',init,['_',[]]}},
{?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}},
{?eh,cth,{'_',pre_init_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}},
@@ -954,8 +959,8 @@ test_events(same_id_cth) ->
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
{?eh,cth,{'_',id,[[]]}},
- {?eh,cth,{'_',init,[same_id_cth,[]]}},
{?eh,cth,{'_',id,[[]]}},
+ {?eh,cth,{'_',init,[same_id_cth,[]]}},
{?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}},
{?eh,cth,{'_',pre_init_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}},
{negative,
@@ -1001,6 +1006,73 @@ test_events(fail_n_skip_with_minimal_cth) ->
{?eh,stop_logging,[]}
];
+test_events(prio_cth) ->
+
+ GenPre = fun(Func,States) ->
+ [{?eh,cth,{'_',Func,['_','_',State]}} ||
+ State <- States]
+ end,
+
+ GenPost = fun(Func,States) ->
+ [{?eh,cth,{'_',Func,['_','_','_',State]}} ||
+ State <- States]
+ end,
+
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}] ++
+
+ [{?eh,tc_start,{ct_cth_prio_SUITE,init_per_suite}}] ++
+ GenPre(pre_init_per_suite,
+ [[1100,100],[800],[900],[1000],[1200,1050],[1100],[1200]]) ++
+ GenPost(post_init_per_suite,
+ [[1100,100],[600,200],[600,600],[700],[800],[900],[1000],
+ [1200,1050],[1100],[1200]]) ++
+ [{?eh,tc_done,{ct_cth_prio_SUITE,init_per_suite,ok}},
+
+
+ [{?eh,tc_start,{ct_cth_prio_SUITE,{init_per_group,'_',[]}}}] ++
+ GenPre(pre_init_per_group,
+ [[1100,100],[600,200],[600,600],[700],[800],
+ [900],[1000],[1200,1050],[1100],[1200]]) ++
+ GenPost(post_init_per_group,
+ [[1100,100],[600,200],[600,600],[600],[700],[800],
+ [900],[900,900],[500,900],[1000],[1200,1050],
+ [1100],[1200]]) ++
+ [{?eh,tc_done,{ct_cth_prio_SUITE,{init_per_group,'_',[]},ok}}] ++
+
+ [{?eh,tc_start,{ct_cth_prio_SUITE,test_case}}] ++
+ GenPre(pre_init_per_testcase,
+ [[1100,100],[600,200],[600,600],[600],[700],[800],
+ [900],[900,900],[500,900],[1000],[1200,1050],
+ [1100],[1200]]) ++
+ GenPost(post_end_per_testcase,
+ [[1100,100],[600,200],[600,600],[600],[700],[800],
+ [900],[900,900],[500,900],[1000],[1200,1050],
+ [1100],[1200]]) ++
+ [{?eh,tc_done,{ct_cth_prio_SUITE,test_case,ok}},
+
+ {?eh,tc_start,{ct_cth_prio_SUITE,{end_per_group,'_',[]}}}] ++
+ GenPre(pre_end_per_group,
+ [[1100,100],[600,200],[600,600],[600],[700],[800],
+ [900],[900,900],[500,900],[1000],[1200,1050],
+ [1100],[1200]]) ++
+ GenPost(post_end_per_group,
+ [[1100,100],[600,200],[600,600],[600],[700],[800],
+ [900],[900,900],[500,900],[1000],[1200,1050],
+ [1100],[1200]]) ++
+ [{?eh,tc_done,{ct_cth_prio_SUITE,{end_per_group,'_',[]},ok}}],
+
+ {?eh,tc_start,{ct_cth_prio_SUITE,end_per_suite}}] ++
+ GenPre(pre_end_per_suite,
+ [[1100,100],[600,200],[600,600],[700],[800],[900],[1000],
+ [1200,1050],[1100],[1200]]) ++
+ GenPost(post_end_per_suite,
+ [[1100,100],[600,200],[600,600],[700],[800],[900],[1000],
+ [1200,1050],[1100],[1200]]) ++
+ [{?eh,tc_done,{ct_cth_prio_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
test_events(ok) ->
ok.
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_prio_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_prio_SUITE.erl
new file mode 100644
index 0000000000..d564398cd0
--- /dev/null
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_prio_SUITE.erl
@@ -0,0 +1,62 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(ct_cth_prio_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include("ct.hrl").
+
+suite() ->
+ ([{timetrap, {minutes, 10}},
+ {ct_hooks, [{empty_cth,[800],800},
+ {prio_cth,[1200]},{prio_cth,[1200,1050],1050}]}]).
+
+%% Test server callback functions
+init_per_suite(Config) ->
+ [{ct_hooks, [{empty_cth,[700],700},
+ {prio_cth,[600,600]},
+ {prio_cth,[600,200],200}]}|Config].
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_G, Config) ->
+ [{ct_hooks, [{empty_cth,[600],600},
+ {prio_cth,[900,900]},{prio_cth,[500,900],900}]}|Config].
+
+end_per_group(_G, _Config) ->
+ ok.
+
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+all() ->
+ [{group,test_group}].
+
+groups() ->
+ [{test_group,[],[test_case]}].
+
+%% Test cases starts here.
+test_case(Config) when is_list(Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl
index ebebfd18a9..7befcfa57c 100644
--- a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl
@@ -59,8 +59,7 @@
-include_lib("common_test/src/ct_util.hrl").
-include_lib("common_test/include/ct_event.hrl").
--type proplist() :: list({atom(),term()}).
--type config() :: proplist().
+-type config() :: proplists:proplist().
-type reason() :: term().
-type skip_or_fail() :: {skip, reason()} |
{auto_skip, reason()} |
@@ -71,17 +70,17 @@
%% @doc Always called before any other callback function. Use this to initiate
%% any common state. It should return an state for this CTH.
--spec init(Id :: term(), Opts :: proplist()) ->
- State :: #state{}.
+-spec init(Id :: term(), Opts :: proplists:proplist()) ->
+ {ok, State :: #state{}}.
init(Id, Opts) ->
gen_event:notify(?CT_EVMGR_REF, #event{ name = cth, node = node(),
data = {?MODULE, init, [Id, Opts]}}),
- Opts.
+ {ok,Opts}.
%% @doc The ID is used to uniquly identify an CTH instance, if two CTH's
%% return the same ID the seconds CTH is ignored. This function should NOT
%% have any side effects as it might be called multiple times by common test.
--spec id(Opts :: proplist()) ->
+-spec id(Opts :: proplists:proplist()) ->
Id :: term().
id(Opts) ->
gen_event:notify(?CT_EVMGR_REF, #event{ name = cth, node = node(),
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/prio_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/prio_cth.erl
new file mode 100644
index 0000000000..82511ab0d3
--- /dev/null
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/prio_cth.erl
@@ -0,0 +1,74 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+
+-module(prio_cth).
+
+
+-include_lib("common_test/src/ct_util.hrl").
+
+
+%% CT Hooks
+-compile(export_all).
+
+id(Opts) ->
+ empty_cth:id(Opts).
+
+init(Id, Opts) ->
+ {ok, [Prio|_] = State} = empty_cth:init(Id, Opts),
+ {ok, State, Prio}.
+
+pre_init_per_suite(Suite, Config, State) ->
+ empty_cth:pre_init_per_suite(Suite,Config,State).
+
+post_init_per_suite(Suite,Config,Return,State) ->
+ empty_cth:post_init_per_suite(Suite,Config,Return,State).
+
+pre_end_per_suite(Suite,Config,State) ->
+ empty_cth:pre_end_per_suite(Suite,Config,State).
+
+post_end_per_suite(Suite,Config,Return,State) ->
+ empty_cth:post_end_per_suite(Suite,Config,Return,State).
+
+pre_init_per_group(Group,Config,State) ->
+ empty_cth:pre_init_per_group(Group,Config,State).
+
+post_init_per_group(Group,Config,Return,State) ->
+ empty_cth:post_init_per_group(Group,Config,Return,State).
+
+pre_end_per_group(Group,Config,State) ->
+ empty_cth:pre_end_per_group(Group,Config,State).
+
+post_end_per_group(Group,Config,Return,State) ->
+ empty_cth:post_end_per_group(Group,Config,Return,State).
+
+pre_init_per_testcase(TC,Config,State) ->
+ empty_cth:pre_init_per_testcase(TC,Config,State).
+
+post_end_per_testcase(TC,Config,Return,State) ->
+ empty_cth:post_end_per_testcase(TC,Config,Return,State).
+
+on_tc_fail(TC, Reason, State) ->
+ empty_cth:on_tc_fail(TC,Reason,State).
+
+on_tc_skip(TC, Reason, State) ->
+ empty_cth:on_tc_skip(TC,Reason,State).
+
+terminate(State) ->
+ empty_cth:terminate(State).
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/state_update_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/state_update_cth.erl
index 35c990c0be..9da48d3a4c 100644
--- a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/state_update_cth.erl
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/state_update_cth.erl
@@ -29,7 +29,7 @@
init(Id, Opts) ->
State = empty_cth:init(Id, Opts),
- [init|State].
+ {ok, [init|State]}.
pre_init_per_suite(Suite, Config, State) ->
empty_cth:pre_init_per_suite(Suite,Config,State),
diff --git a/lib/common_test/test/ct_repeat_1_SUITE.erl b/lib/common_test/test/ct_repeat_1_SUITE.erl
index 4e842bd6d6..090002d0c2 100644
--- a/lib/common_test/test/ct_repeat_1_SUITE.erl
+++ b/lib/common_test/test/ct_repeat_1_SUITE.erl
@@ -560,12 +560,7 @@ test_events(repeat_cs_until_any_fail) ->
{repeat_1_SUITE,tc_fail_1,
{failed,
{error,
- {{badmatch,2},
- [{repeat_1_SUITE,tc_fail_1,1},
- {test_server,my_apply,3},
- {test_server,ts_tc,3},
- {test_server,run_test_case_eval1,6},
- {test_server,run_test_case_eval,8}]}}}}},
+ {{badmatch,2},'_'}}}}},
{?eh,test_stats,{5,2,{0,0}}},
{?eh,tc_start,{repeat_1_SUITE,tc_fail_2}},
{?eh,tc_done,
diff --git a/lib/common_test/test/ct_skip_SUITE.erl b/lib/common_test/test/ct_skip_SUITE.erl
index 4ba4479208..b8be55f43a 100644
--- a/lib/common_test/test/ct_skip_SUITE.erl
+++ b/lib/common_test/test/ct_skip_SUITE.erl
@@ -197,7 +197,7 @@ test_events(auto_skip) ->
{?eh,tc_done,
{auto_skip_3_SUITE,tc1,
{skipped,{failed,{auto_skip_3_SUITE,init_per_testcase,
- {init_per_testcase,tc1,failed}}}}}},
+ {{init_per_testcase,tc1,failed},'_'}}}}}},
{?eh,test_stats,{0,0,{0,4}}},
{?eh,tc_start,{auto_skip_3_SUITE,tc2}},
{?eh,tc_done,{auto_skip_3_SUITE,tc2,ok}},
@@ -364,12 +364,7 @@ test_events(auto_skip) ->
{?eh,tc_done,
{auto_skip_9_SUITE,tc8,
{skipped,{failed,{auto_skip_9_SUITE,init_per_testcase,
- {{badmatch,undefined},
- [{auto_skip_9_SUITE,init_per_testcase,2},
- {test_server,my_apply,3},
- {test_server,init_per_testcase,3},
- {test_server,run_test_case_eval1,6},
- {test_server,run_test_case_eval,8}]}}}}}},
+ {{badmatch,undefined},'_'}}}}}},
{?eh,tc_start,
{auto_skip_9_SUITE,{end_per_group,g5,[parallel]}}},
{?eh,tc_done,
diff --git a/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl
index 47cea190dd..bda7d91161 100644
--- a/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl
+++ b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl
@@ -143,7 +143,7 @@ tc1(_) ->
exit(should_have_been_skipped).
tc2(_) ->
- exit(should_have_been_skipped).
+ timeout_in_end_per_testcase.
tc3(_) ->
timer:sleep(5000).
diff --git a/lib/common_test/test/ct_test_support.erl b/lib/common_test/test/ct_test_support.erl
index 31381abc40..6df02d12b7 100644
--- a/lib/common_test/test/ct_test_support.erl
+++ b/lib/common_test/test/ct_test_support.erl
@@ -23,8 +23,8 @@
%%%
-module(ct_test_support).
--include_lib("test_server/include/test_server.hrl").
-include_lib("common_test/include/ct_event.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([init_per_suite/1, init_per_suite/2, end_per_suite/1,
init_per_testcase/2, end_per_testcase/2,
@@ -46,9 +46,10 @@ init_per_suite(Config) ->
init_per_suite(Config, Level) ->
case os:type() of
{win32, _} ->
- %% Extend timeout for windows as starting node
+ %% Extend timeout to 1 hour for windows as starting node
%% can take a long time there
- test_server:timetrap( 120000 * test_server:timetrap_scale_factor());
+ test_server:timetrap( 60*60*1000 *
+ test_server:timetrap_scale_factor());
_ ->
ok
end,
diff --git a/lib/common_test/vsn.mk b/lib/common_test/vsn.mk
index f77629b4d1..4782a32933 100644
--- a/lib/common_test/vsn.mk
+++ b/lib/common_test/vsn.mk
@@ -1,3 +1,3 @@
-COMMON_TEST_VSN = 1.5.4
+COMMON_TEST_VSN = 1.5.5
diff --git a/lib/compiler/doc/src/compile.xml b/lib/compiler/doc/src/compile.xml
index 830c89ae84..522c1dc411 100644
--- a/lib/compiler/doc/src/compile.xml
+++ b/lib/compiler/doc/src/compile.xml
@@ -395,6 +395,14 @@ module.beam: module.erl \
<code>-compile({no_auto_import,[error/1]}).</code>
</item>
+ <tag><c>no_line_info</c></tag>
+
+ <item>
+ <p>Omit line number information in order to produce a slightly
+ smaller output file.
+ </p>
+ </item>
+
</taglist>
<p>If warnings are turned on (the <c>report_warnings</c> option
diff --git a/lib/compiler/doc/src/make.dep b/lib/compiler/doc/src/make.dep
deleted file mode 100644
index f5c097afad..0000000000
--- a/lib/compiler/doc/src/make.dep
+++ /dev/null
@@ -1,19 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex compile.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml
index dd29323787..740cbcf8eb 100644
--- a/lib/compiler/doc/src/notes.xml
+++ b/lib/compiler/doc/src/notes.xml
@@ -31,6 +31,34 @@
<p>This document describes the changes made to the Compiler
application.</p>
+<section><title>Compiler 4.7.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Compiler options given in the source code using a
+ <c>-compile()</c> attribute used to be included twice in
+ <c>Mod:module_info(compile)</c>. They are now only
+ included once at the beginning of the list of options.</p>
+ <p>
+ Own Id: OTP-9534</p>
+ </item>
+ <item>
+ <p>
+ beam_disasm: Handle stripped BEAM files</p>
+ <p>
+ beam_disasm:file/1 would crash if asked to disassemble a
+ stripped BEAM file without an "Attr" chunk. (Thanks to
+ Haitao Li)</p>
+ <p>
+ Own Id: OTP-9571</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Compiler 4.7.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/compiler/src/beam_asm.erl b/lib/compiler/src/beam_asm.erl
index 89d64834cf..4a9c12dfea 100644
--- a/lib/compiler/src/beam_asm.erl
+++ b/lib/compiler/src/beam_asm.erl
@@ -23,7 +23,7 @@
-export([module/4]).
-export([encode/2]).
--import(lists, [map/2,member/2,keymember/3,duplicate/2]).
+-import(lists, [map/2,member/2,keymember/3,duplicate/2,splitwith/2]).
-include("beam_opcodes.hrl").
module(Code, Abst, SourceFile, Opts) ->
@@ -31,22 +31,20 @@ module(Code, Abst, SourceFile, Opts) ->
assemble({Mod,Exp,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),
- {Code,Dict1} = assemble_1(Asm, Exp, Dict0, []),
- build_file(Code, Attr, Dict1, NumLabels, NumFuncs, Abst, SourceFile, Opts).
+ {Code,Dict2} = assemble_1(Asm, Exp, Dict1, []),
+ build_file(Code, Attr, Dict2, NumLabels, NumFuncs, Abst, SourceFile, Opts).
on_load(Fs0, Attr0) ->
case proplists:get_value(on_load, Attr0) of
undefined ->
{Fs0,Attr0};
[{Name,0}] ->
- Fs = map(fun({function,N,0,Entry,Asm0}) when N =:= Name ->
- [{label,_}=L,
- {func_info,_,_,_}=Fi,
- {label,_}=E|Asm1] = Asm0,
- Asm = [L,Fi,E,on_load|Asm1],
- {function,N,0,Entry,Asm};
+ Fs = map(fun({function,N,0,Entry,Is0}) when N =:= Name ->
+ Is = insert_on_load_instruction(Is0, Entry),
+ {function,N,0,Entry,Is};
(F) ->
F
end, Fs0),
@@ -54,6 +52,13 @@ on_load(Fs0, Attr0) ->
{Fs,Attr}
end.
+insert_on_load_instruction(Is0, Entry) ->
+ {Bef,[{label,Entry}=El|Is]} =
+ splitwith(fun({label,L}) when L =:= Entry -> false;
+ (_) -> true
+ end, Is0),
+ Bef ++ [El,on_load|Is].
+
assemble_1([{function,Name,Arity,Entry,Asm}|T], Exp, Dict0, Acc) ->
Dict1 = case member({Name,Arity}, Exp) of
true ->
@@ -132,14 +137,19 @@ build_file(Code, Attr, Dict, NumLabels, NumFuncs, Abst, SourceFile, Opts) ->
LitTab = iolist_to_binary(zlib:compress(LitTab2)),
chunk(<<"LitT">>, <<(byte_size(LitTab2)):32>>, LitTab)
end,
+
+ %% Create the line chunk.
+ LineChunk = chunk(<<"Line">>, build_line_table(Dict)),
%% Create the attributes and compile info chunks.
Essentials0 = [AtomChunk,CodeChunk,StringChunk,ImportChunk,
ExpChunk,LambdaChunk,LiteralChunk],
- Essentials = [iolist_to_binary(C) || C <- Essentials0],
- {Attributes,Compile} = build_attributes(Opts, SourceFile, Attr, Essentials),
+ Essentials1 = [iolist_to_binary(C) || C <- Essentials0],
+ MD5 = module_md5(Essentials1),
+ Essentials = finalize_fun_table(Essentials1, MD5),
+ {Attributes,Compile} = build_attributes(Opts, SourceFile, Attr, MD5),
AttrChunk = chunk(<<"Attr">>, Attributes),
CompileChunk = chunk(<<"CInf">>, Compile),
@@ -150,11 +160,32 @@ build_file(Code, Attr, Dict, NumLabels, NumFuncs, Abst, SourceFile, Opts) ->
%% Create IFF chunk.
Chunks = case member(slim, Opts) of
- true -> [Essentials,AttrChunk,AbstChunk];
- false -> [Essentials,LocChunk,AttrChunk,CompileChunk,AbstChunk]
+ true ->
+ [Essentials,AttrChunk,AbstChunk];
+ false ->
+ [Essentials,LocChunk,AttrChunk,
+ CompileChunk,AbstChunk,LineChunk]
end,
build_form(<<"BEAM">>, Chunks).
+%% finalize_fun_table(Essentials, MD5) -> FinalizedEssentials
+%% Update the 'old_uniq' field in the entry for each fun in the
+%% 'FunT' chunk. We'll use part of the MD5 for the module as a
+%% unique value.
+
+finalize_fun_table(Essentials, MD5) ->
+ [finalize_fun_table_1(E, MD5) || E <- Essentials].
+
+finalize_fun_table_1(<<"FunT",Keep:8/binary,Table0/binary>>, MD5) ->
+ <<Uniq:27,_:101/bits>> = MD5,
+ Table = finalize_fun_table_2(Table0, Uniq, <<>>),
+ <<"FunT",Keep/binary,Table/binary>>;
+finalize_fun_table_1(Chunk, _) -> Chunk.
+
+finalize_fun_table_2(<<Keep:20/binary,0:32,T/binary>>, Uniq, Acc) ->
+ finalize_fun_table_2(T, Uniq, <<Acc/binary,Keep/binary,Uniq:32>>);
+finalize_fun_table_2(<<>>, _, Acc) -> Acc.
+
%% Build an IFF form.
build_form(Id, Chunks0) when byte_size(Id) =:= 4, is_list(Chunks0) ->
@@ -191,7 +222,7 @@ flatten_exports(Exps) ->
flatten_imports(Imps) ->
list_to_binary(map(fun({M,F,A}) -> <<M:32,F:32,A:32>> end, Imps)).
-build_attributes(Opts, SourceFile, Attr, Essentials) ->
+build_attributes(Opts, SourceFile, Attr, MD5) ->
Misc = case member(slim, Opts) of
false ->
{{Y,Mo,D},{H,Mi,S}} = erlang:universaltime(),
@@ -199,7 +230,32 @@ build_attributes(Opts, SourceFile, Attr, Essentials) ->
true -> []
end,
Compile = [{options,Opts},{version,?COMPILER_VSN}|Misc],
- {term_to_binary(calc_vsn(Attr, Essentials)),term_to_binary(Compile)}.
+ {term_to_binary(set_vsn_attribute(Attr, MD5)),term_to_binary(Compile)}.
+
+build_line_table(Dict) ->
+ {NumLineInstrs,NumFnames0,Fnames0,NumLines,Lines0} =
+ beam_dict:line_table(Dict),
+ NumFnames = NumFnames0 - 1,
+ [_|Fnames1] = Fnames0,
+ Fnames2 = [unicode:characters_to_binary(F) || F <- Fnames1],
+ Fnames = << <<(byte_size(F)):16,F/binary>> || F <- Fnames2 >>,
+ Lines1 = encode_line_items(Lines0, 0),
+ Lines = iolist_to_binary(Lines1),
+ Ver = 0,
+ Bits = 0,
+ <<Ver:32,Bits:32,NumLineInstrs:32,NumLines:32,NumFnames:32,
+ Lines/binary,Fnames/binary>>.
+
+%% encode_line_items([{FnameIndex,Line}], PrevFnameIndex)
+%% Encode the line items compactly. Tag the FnameIndex with
+%% an 'a' tag (atom) and only include it when it has changed.
+%% Tag the line numbers with an 'i' (integer) tag.
+
+encode_line_items([{F,L}|T], F) ->
+ [encode(?tag_i, L)|encode_line_items(T, F)];
+encode_line_items([{F,L}|T], _) ->
+ [encode(?tag_a, F),encode(?tag_i, L)|encode_line_items(T, F)];
+encode_line_items([], _) -> [].
%%
%% If the attributes contains no 'vsn' attribute, we'll insert one
@@ -207,32 +263,30 @@ build_attributes(Opts, SourceFile, Attr, Essentials) ->
%% We'll not change an existing 'vsn' attribute.
%%
-calc_vsn(Attr, Essentials0) ->
+set_vsn_attribute(Attr, MD5) ->
case keymember(vsn, 1, Attr) of
true -> Attr;
false ->
- Essentials = filter_essentials(Essentials0),
- <<Number:128>> = erlang:md5(Essentials),
+ <<Number:128>> = MD5,
[{vsn,[Number]}|Attr]
end.
+module_md5(Essentials0) ->
+ Essentials = filter_essentials(Essentials0),
+ erlang:md5(Essentials).
+
%% filter_essentials([Chunk]) -> [Chunk']
%% Filter essentials so that we obtain the same MD5 as code:module_md5/1 and
-%% beam_lib:md5/1 would calculate for this module.
+%% beam_lib:md5/1 would calculate for this module. Note that at this
+%% point, the 'old_uniq' entry for each fun in the 'FunT' chunk is zeroed,
+%% so there is no need to go through the 'FunT' chunk.
-filter_essentials([<<"FunT",_Sz:4/binary,Entries:4/binary,Table0/binary>>|T]) ->
- Table = filter_funtab(Table0, <<0:32>>),
- [Entries,Table|filter_essentials(T)];
filter_essentials([<<_Tag:4/binary,Sz:32,Data:Sz/binary,_Padding/binary>>|T]) ->
[Data|filter_essentials(T)];
filter_essentials([<<>>|T]) ->
filter_essentials(T);
filter_essentials([]) -> [].
-filter_funtab(<<Important:20/binary,_OldUniq:4/binary,T/binary>>, Zero) ->
- [Important,Zero|filter_funtab(T, Zero)];
-filter_funtab(<<>>, _) -> [].
-
bif_type(fnegate, 1) -> {op,fnegate};
bif_type(fadd, 2) -> {op,fadd};
bif_type(fsub, 2) -> {op,fsub};
@@ -243,6 +297,9 @@ bif_type(_, 2) -> bif2.
make_op({'%',_}, Dict) ->
{[],Dict};
+make_op({line,Location}, Dict0) ->
+ {Index,Dict} = beam_dict:line(Location, Dict0),
+ encode_op(line, [Index], Dict);
make_op({bif, Bif, {f,_}, [], Dest}, Dict) ->
%% BIFs without arguments cannot fail.
encode_op(bif0, [{extfunc, erlang, Bif, 0}, Dest], Dict);
@@ -271,8 +328,8 @@ make_op({test,Cond,Fail,Ops}, Dict) when is_list(Ops) ->
encode_op(Cond, [Fail|Ops], Dict);
make_op({test,Cond,Fail,Live,[Op|Ops],Dst}, Dict) when is_list(Ops) ->
encode_op(Cond, [Fail,Op,Live|Ops++[Dst]], Dict);
-make_op({make_fun2,{f,Lbl},Index,OldUniq,NumFree}, Dict0) ->
- {Fun,Dict} = beam_dict:lambda(Lbl, Index, OldUniq, NumFree, Dict0),
+make_op({make_fun2,{f,Lbl},_Index,_OldUniq,NumFree}, Dict0) ->
+ {Fun,Dict} = beam_dict:lambda(Lbl, NumFree, Dict0),
make_op({make_fun2,Fun}, Dict);
make_op({kill,Y}, Dict) ->
make_op({init,Y}, Dict);
diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl
index c45874597a..432d1e7eea 100644
--- a/lib/compiler/src/beam_block.erl
+++ b/lib/compiler/src/beam_block.erl
@@ -36,13 +36,14 @@ function({function,Name,Arity,CLabel,Is0}, Lc0) ->
%% Collect basic blocks and optimize them.
Is2 = blockify(Is1),
- Is3 = move_allocates(Is2),
- Is4 = beam_utils:live_opt(Is3),
- Is5 = opt_blocks(Is4),
- Is6 = beam_utils:delete_live_annos(Is5),
+ Is3 = embed_lines(Is2),
+ Is4 = move_allocates(Is3),
+ Is5 = beam_utils:live_opt(Is4),
+ Is6 = opt_blocks(Is5),
+ Is7 = beam_utils:delete_live_annos(Is6),
%% Optimize bit syntax.
- {Is,Lc} = bsm_opt(Is6, Lc0),
+ {Is,Lc} = bsm_opt(Is7, Lc0),
%% Done.
{{function,Name,Arity,CLabel,Is},Lc}
@@ -148,6 +149,24 @@ collect(remove_message) -> {set,[],[],remove_message};
collect({'catch',R,L}) -> {set,[R],[],{'catch',L}};
collect(_) -> error.
+%% embed_lines([Instruction]) -> [Instruction]
+%% Combine blocks that would be split by line/1 instructions.
+%% Also move a line instruction before a block into the block,
+%% but leave the line/1 instruction after a block outside.
+
+embed_lines(Is) ->
+ embed_lines(reverse(Is), []).
+
+embed_lines([{block,B2},{line,_}=Line,{block,B1}|T], Acc) ->
+ B = {block,B1++[{set,[],[],Line}]++B2},
+ embed_lines([B|T], Acc);
+embed_lines([{block,B1},{line,_}=Line|T], Acc) ->
+ B = {block,[{set,[],[],Line}|B1]},
+ embed_lines([B|T], Acc);
+embed_lines([I|Is], Acc) ->
+ embed_lines(Is, [I|Acc]);
+embed_lines([], Acc) -> Acc.
+
opt_blocks([{block,Bl0}|Is]) ->
%% The live annotation at the beginning is not useful.
[{'%live',_}|Bl] = Bl0,
@@ -225,10 +244,12 @@ opt([{set,[Dst],As,{bif,Bif,Fail}}=I1,
RevBif -> [{set,[Dst],As,{bif,RevBif,Fail}}|opt(Is)]
end;
opt([{set,[X],[X],move}|Is]) -> opt(Is);
-opt([{set,[D1],[{integer,Idx1},Reg],{bif,element,{f,0}}}=I1,
+opt([{set,_,_,{line,_}}=Line1,
+ {set,[D1],[{integer,Idx1},Reg],{bif,element,{f,0}}}=I1,
+ {set,_,_,{line,_}}=Line2,
{set,[D2],[{integer,Idx2},Reg],{bif,element,{f,0}}}=I2|Is])
when Idx1 < Idx2, D1 =/= D2, D1 =/= Reg, D2 =/= Reg ->
- opt([I2,I1|Is]);
+ opt([Line2,I2,Line1,I1|Is]);
opt([{set,Ds0,Ss,Op}|Is0]) ->
{Ds,Is} = opt_moves(Ds0, Is0),
[{set,Ds,Ss,Op}|opt(Is)];
diff --git a/lib/compiler/src/beam_bsm.erl b/lib/compiler/src/beam_bsm.erl
index 415864b8e9..1217f7f777 100644
--- a/lib/compiler/src/beam_bsm.erl
+++ b/lib/compiler/src/beam_bsm.erl
@@ -20,7 +20,7 @@
-module(beam_bsm).
-export([module/2,format_error/1]).
--import(lists, [member/2,foldl/3,reverse/1,sort/1,all/2]).
+-import(lists, [member/2,foldl/3,reverse/1,sort/1,all/2,dropwhile/2]).
%%%
%%% We optimize bit syntax matching where the tail end of a binary is
@@ -376,6 +376,8 @@ btb_reaches_match_2([{func_info,_,_,Arity}=I|_], Regs0, D) ->
[] -> D;
_ -> {binary_used_in,I}
end;
+btb_reaches_match_2([{line,_}|Is], Regs, D) ->
+ btb_reaches_match_1(Is, Regs, D);
btb_reaches_match_2([I|_], Regs, _) ->
btb_error({btb_context_regs(Regs),I,not_handled}).
@@ -580,7 +582,10 @@ btb_index(Fs) ->
btb_index_1(Fs, []).
btb_index_1([{function,_,_,Entry,Is0}|Fs], Acc0) ->
- [{label,_},{func_info,_,_,_},{label,Entry}|Is] = Is0,
+ [{label,Entry}|Is] =
+ dropwhile(fun({label,L}) when L =:= Entry -> false;
+ (_) -> true
+ end, Is0),
Acc = btb_index_2(Is, Entry, false, Acc0),
btb_index_1(Fs, Acc);
btb_index_1([], Acc) -> gb_trees:from_orddict(sort(Acc)).
diff --git a/lib/compiler/src/beam_clean.erl b/lib/compiler/src/beam_clean.erl
index 64c93e11f7..a7994ab3b3 100644
--- a/lib/compiler/src/beam_clean.erl
+++ b/lib/compiler/src/beam_clean.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -23,9 +23,9 @@
-export([module/2]).
-export([bs_clean_saves/1]).
-export([clean_labels/1]).
--import(lists, [map/2,foldl/3,reverse/1]).
+-import(lists, [map/2,foldl/3,reverse/1,filter/2]).
-module({Mod,Exp,Attr,Fs0,_}, _Opt) ->
+module({Mod,Exp,Attr,Fs0,_}, Opts) ->
Order = [Lbl || {function,_,_,Lbl,_} <- Fs0],
All = foldl(fun({function,_,_,Lbl,_}=Func,D) -> dict:store(Lbl, Func, D) end,
dict:new(), Fs0),
@@ -33,7 +33,8 @@ module({Mod,Exp,Attr,Fs0,_}, _Opt) ->
Used = find_all_used(WorkList, All, sets:from_list(WorkList)),
Fs1 = remove_unused(Order, Used, All),
{Fs2,Lc} = clean_labels(Fs1),
- Fs = bs_fix(Fs2),
+ Fs3 = bs_fix(Fs2),
+ Fs = maybe_remove_lines(Fs3, Opts),
{ok,{Mod,Exp,Attr,Fs,Lc}}.
%% Remove all bs_save2/2 instructions not referenced by a bs_restore2/2.
@@ -375,3 +376,20 @@ bs_clean_saves_1([{bs_save2,_,{_,_}=SavePoint}=I|Is], Needed, Acc) ->
bs_clean_saves_1([I|Is], Needed, Acc) ->
bs_clean_saves_1(Is, Needed, [I|Acc]);
bs_clean_saves_1([], _, Acc) -> reverse(Acc).
+
+%%%
+%%% Remove line instructions if requested.
+%%%
+
+maybe_remove_lines(Fs, Opts) ->
+ case proplists:get_bool(no_line_info, Opts) of
+ false -> Fs;
+ true -> remove_lines(Fs)
+ end.
+
+remove_lines([{function,N,A,Lbl,Is0}|T]) ->
+ Is = filter(fun({line,_}) -> false;
+ (_) -> true
+ end, Is0),
+ [{function,N,A,Lbl,Is}|remove_lines(T)];
+remove_lines([]) -> [].
diff --git a/lib/compiler/src/beam_dead.erl b/lib/compiler/src/beam_dead.erl
index 1365f3d20a..9f81a6ab43 100644
--- a/lib/compiler/src/beam_dead.erl
+++ b/lib/compiler/src/beam_dead.erl
@@ -144,9 +144,9 @@ function({function,Name,Arity,CLabel,Is0}, Lc0) ->
%% Initialize label information with the code
%% for the func_info label. Without it, a register
%% may seem to be live when it is not.
- [{label,L},{func_info,_,_,_}=FI|_] = Is1,
+ [{label,L}|FiIs] = Is1,
D0 = beam_utils:empty_label_index(),
- D = beam_utils:index_label(L, [FI], D0),
+ D = beam_utils:index_label(L, FiIs, D0),
%% Optimize away dead code.
{Is2,Lc} = forward(Is1, Lc0),
@@ -185,6 +185,8 @@ split_block([{set,[R],As,{alloc,Live,{gc_bif,N,{f,Lbl}=Fail}}}|Is], Bl, Acc)
split_block(Is, [], [{gc_bif,N,Fail,Live,As,R}|make_block(Bl, Acc)]);
split_block([{set,[R],[],{'catch',L}}|Is], Bl, Acc) ->
split_block(Is, [], [{'catch',R,L}|make_block(Bl, Acc)]);
+split_block([{set,[],[],{line,_}=Line}|Is], Bl, Acc) ->
+ split_block(Is, [], [Line|make_block(Bl, Acc)]);
split_block([I|Is], Bl, Acc) ->
split_block(Is, [I|Bl], Acc);
split_block([], Bl, Acc) -> make_block(Bl, Acc).
@@ -406,7 +408,7 @@ backward([{test,Op,{f,To0},Live,Ops0,Dst}|Is], D, Acc) ->
end,
I = {test,Op,{f,To},Live,Ops0,Dst},
backward(Is, D, [I|Acc]);
-backward([{kill,_}=I|Is], D, [Exit|_]=Acc) ->
+backward([{kill,_}=I|Is], D, [{line,_},Exit|_]=Acc) ->
case beam_jump:is_exit_instruction(Exit) of
false -> backward(Is, D, [I|Acc]);
true -> backward(Is, D, Acc)
@@ -471,7 +473,7 @@ shortcut_fail_label(To0, Reg, Val, D) ->
shortcut_boolean_label(To0, Reg, Bool0, D) when is_boolean(Bool0) ->
case beam_utils:code_at(To0, D) of
- [{bif,'not',_,[Reg],Reg},{jump,{f,To}}|_] ->
+ [{line,_},{bif,'not',_,[Reg],Reg},{jump,{f,To}}|_] ->
Bool = not Bool0,
{shortcut_select_label(To, Reg, Bool, D),Bool};
_ ->
diff --git a/lib/compiler/src/beam_dict.erl b/lib/compiler/src/beam_dict.erl
index c50ed28aa9..531968b3c8 100644
--- a/lib/compiler/src/beam_dict.erl
+++ b/lib/compiler/src/beam_dict.erl
@@ -22,9 +22,10 @@
-export([new/0,opcode/2,highest_opcode/1,
atom/2,local/4,export/4,import/4,
- string/2,lambda/5,literal/2,
+ string/2,lambda/3,literal/2,line/2,fname/2,
atom_table/1,local_table/1,export_table/1,import_table/1,
- string_table/1,lambda_table/1,literal_table/1]).
+ string_table/1,lambda_table/1,literal_table/1,
+ line_table/1]).
-type label() :: non_neg_integer().
@@ -36,6 +37,9 @@
strings = <<>> :: binary(), %String pool
lambdas = [], %[{...}]
literals = dict:new() :: dict(), %Format: {Literal,Number}
+ fnames = gb_trees:empty() :: gb_tree(), %{Name,Index}
+ lines = gb_trees:empty() :: gb_tree(), %{{Fname,Line},Index}
+ num_lines = 0 :: non_neg_integer(), %Number of line instructions
next_import = 0 :: non_neg_integer(),
string_offset = 0 :: non_neg_integer(),
next_literal = 0 :: non_neg_integer(),
@@ -129,13 +133,18 @@ string(Str, Dict) when is_list(Str) ->
{NextOffset-Offset,Dict}
end.
-%% Returns the index for a funentry (adding it to the table if necessary).
-%% lambda(Lbl, Index, Uniq, NumFree, Dict) -> {Index,Dict'}
--spec lambda(label(), non_neg_integer(), integer(), non_neg_integer(), bdict()) ->
+%% Returns the index for a fun entry.
+%% lambda(Lbl, NumFree, Dict) -> {Index,Dict'}
+-spec lambda(label(), non_neg_integer(), bdict()) ->
{non_neg_integer(), bdict()}.
-lambda(Lbl, Index, OldUniq, NumFree, #asm{lambdas=Lambdas0}=Dict) ->
+lambda(Lbl, NumFree, #asm{lambdas=Lambdas0}=Dict) ->
OldIndex = length(Lambdas0),
+ %% Set Index the same as OldIndex.
+ Index = OldIndex,
+ %% Initialize OldUniq to 0. It will be set to an unique value
+ %% based on the MD5 checksum of the BEAM code for the module.
+ OldUniq = 0,
Lambdas = [{Lbl,{OldIndex,Lbl,Index,NumFree,OldUniq}}|Lambdas0],
{OldIndex,Dict#asm{lambdas=Lambdas}}.
@@ -152,6 +161,36 @@ literal(Lit, #asm{literals=Tab0,next_literal=NextIndex}=Dict) ->
{NextIndex,Dict#asm{literals=Tab,next_literal=NextIndex+1}}
end.
+%% Returns the index for a line instruction (adding information
+%% to the location information table).
+-spec line(list(), bdict()) -> {non_neg_integer(), bdict()}.
+
+line([], #asm{num_lines=N}=Dict) ->
+ %% No location available. Return the special pre-defined
+ %% index 0.
+ {0,Dict#asm{num_lines=N+1}};
+line([{location,Name,Line}], #asm{lines=Lines0,num_lines=N}=Dict0) ->
+ {FnameIndex,Dict1} = fname(Name, Dict0),
+ case gb_trees:lookup({FnameIndex,Line}, Lines0) of
+ {value,Index} ->
+ {Index,Dict1#asm{num_lines=N+1}};
+ none ->
+ Index = gb_trees:size(Lines0) + 1,
+ Lines = gb_trees:insert({FnameIndex,Line}, Index, Lines0),
+ Dict = Dict1#asm{lines=Lines,num_lines=N+1},
+ {Index,Dict}
+ end.
+
+fname(Name, #asm{fnames=Fnames0}=Dict) ->
+ case gb_trees:lookup(Name, Fnames0) of
+ {value,Index} ->
+ {Index,Dict};
+ none ->
+ Index = gb_trees:size(Fnames0),
+ Fnames = gb_trees:insert(Name, Index, Fnames0),
+ {Index,Dict#asm{fnames=Fnames}}
+ end.
+
%% Returns the atom table.
%% atom_table(Dict) -> {LastIndex,[Length,AtomString...]}
-spec atom_table(bdict()) -> {non_neg_integer(), [[non_neg_integer(),...]]}.
@@ -219,6 +258,21 @@ literal_table(#asm{literals=Tab,next_literal=NumLiterals}) ->
my_term_to_binary(Term) ->
term_to_binary(Term, [{minor_version,1}]).
+%% Return the line table.
+-spec line_table(bdict()) ->
+ {non_neg_integer(), %Number of line instructions.
+ non_neg_integer(),[string()],
+ non_neg_integer(),[{non_neg_integer(),non_neg_integer()}]}.
+
+line_table(#asm{fnames=Fnames0,lines=Lines0,num_lines=NumLineInstrs}) ->
+ NumFnames = gb_trees:size(Fnames0),
+ Fnames1 = lists:keysort(2, gb_trees:to_list(Fnames0)),
+ Fnames = [Name || {Name,_} <- Fnames1],
+ NumLines = gb_trees:size(Lines0),
+ Lines1 = lists:keysort(2, gb_trees:to_list(Lines0)),
+ Lines = [L || {L,_} <- Lines1],
+ {NumLineInstrs,NumFnames,Fnames,NumLines,Lines}.
+
%% Search for binary string Str in the binary string pool Pool.
%% old_string(Str, Pool) -> none | Index
-spec old_string(binary(), binary()) -> 'none' | pos_integer().
diff --git a/lib/compiler/src/beam_disasm.erl b/lib/compiler/src/beam_disasm.erl
index 017ca129b0..7103d2390f 100644
--- a/lib/compiler/src/beam_disasm.erl
+++ b/lib/compiler/src/beam_disasm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -204,7 +204,7 @@ process_chunks(F) ->
optional_chunk(F, ChunkTag) ->
case beam_lib:chunks(F, [ChunkTag]) of
{ok,{_Module,[{ChunkTag,Chunk}]}} -> Chunk;
- {error,beam_lib,{missing_chunk,_,ChunkTag}} -> none
+ {error,beam_lib,{missing_chunk,_,_}} -> none
end.
%%-----------------------------------------------------------------------
@@ -296,6 +296,8 @@ get_function_chunks(Code) ->
labels_r([], R) -> {R, []};
labels_r([{label,_}=I|Is], R) ->
labels_r(Is, [I|R]);
+labels_r([{line,_}=I|Is], R) ->
+ labels_r(Is, [I|R]);
labels_r(Is, R) -> {R, Is}.
get_funs({[],[]}) -> [];
@@ -335,20 +337,17 @@ local_labels(Funs) ->
local_labels_1(function__code(F), R)
end, [], Funs)).
-%% The first clause below attempts to provide some (limited form of)
-%% backwards compatibility; it is not needed for .beam files generated
-%% by the R8 compiler. The clause should one fine day be taken out.
-local_labels_1([{label,_}|[{label,_}|_]=Code], R) ->
- local_labels_1(Code, R);
-local_labels_1([{label,_},{func_info,{atom,M},{atom,F},A}|Code], R)
- when is_atom(M), is_atom(F) ->
- local_labels_2(Code, R, M, F, A);
-local_labels_1(Code, _) ->
- ?exit({'local_labels: no label in code',Code}).
+local_labels_1(Code0, R) ->
+ Code1 = lists:dropwhile(fun({label,_}) -> true;
+ ({line,_}) -> true;
+ ({func_info,_,_,_}) -> false
+ end, Code0),
+ [{func_info,{atom,M},{atom,F},A}|Code] = Code1,
+ local_labels_2(Code, R, {M,F,A}).
-local_labels_2([{label,[{u,L}]}|Code], R, M, F, A) ->
- local_labels_2(Code, [{L,{M,F,A}}|R], M, F, A);
-local_labels_2(_, R, _, _, _) -> R.
+local_labels_2([{label,[{u,L}]}|Code], R, MFA) ->
+ local_labels_2(Code, [{L,MFA}|R], MFA);
+local_labels_2(_, R, _) -> R.
%%-----------------------------------------------------------------------
%% Disassembles a single BEAM instruction; most instructions are handled
@@ -1105,6 +1104,12 @@ resolve_inst({recv_set,[Lbl]},_,_,_) ->
{recv_set,Lbl};
%%
+%% R15A.
+%%
+resolve_inst({line,[Index]},_,_,_) ->
+ {line,resolve_arg(Index)};
+
+%%
%% Catches instructions that are not yet handled.
%%
resolve_inst(X,_,_,_) -> ?exit({resolve_inst,X}).
diff --git a/lib/compiler/src/beam_jump.erl b/lib/compiler/src/beam_jump.erl
index 3cab55c4cb..537f8ca81b 100644
--- a/lib/compiler/src/beam_jump.erl
+++ b/lib/compiler/src/beam_jump.erl
@@ -169,7 +169,7 @@ share_1([{label,L}=Lbl|Is], Dict0, Seq, Acc) ->
share_1(Is, Dict0, [], [Lbl,{jump,{f,Label}}|Acc])
end;
share_1([{func_info,_,_,_}=I|Is], _, [], Acc) ->
- Is++[I|Acc];
+ reverse(Is, [I|Acc]);
share_1([I|Is], Dict, Seq, Acc) ->
case is_unreachable_after(I) of
false ->
@@ -206,25 +206,35 @@ is_label(_) -> false.
move(Is) ->
move_1(Is, [], []).
-move_1([I|Is], End, Acc) ->
+move_1([I|Is], End0, Acc0) ->
case is_exit_instruction(I) of
- false -> move_1(Is, End, [I|Acc]);
- true -> move_2(I, Is, End, Acc)
+ false ->
+ move_1(Is, End0, [I|Acc0]);
+ true ->
+ case extract_seq(Acc0, [I|End0]) of
+ no ->
+ move_1(Is, End0, [I|Acc0]);
+ {yes,End,Acc} ->
+ move_1(Is, End, Acc)
+ end
end;
-move_1([], End, Acc) ->
- reverse(Acc, reverse(End)).
-
-move_2(Exit, Is, End, [{block,_},{label,_},{func_info,_,_,_}|_]=Acc) ->
- move_1(Is, End, [Exit|Acc]);
-move_2(Exit, Is, End, [{block,_}=Blk,{label,_}=Lbl,Unreachable|More]) ->
- move_1([Unreachable|Is], [Exit,Blk,Lbl|End], More);
-move_2(Exit, Is, End, [{bs_context_to_binary,_}=Bs,{label,_}=Lbl,
- Unreachable|More]) ->
- move_1([Unreachable|Is], [Exit,Bs,Lbl|End], More);
-move_2(Exit, Is, End, [{label,_}=Lbl,Unreachable|More]) ->
- move_1([Unreachable|Is], [Exit,Lbl|End], More);
-move_2(Exit, Is, End, Acc) ->
- move_1(Is, End, [Exit|Acc]).
+move_1([], End, Acc) -> reverse(Acc, End).
+
+extract_seq([{line,_}=Line|Is], Acc) ->
+ extract_seq(Is, [Line|Acc]);
+extract_seq([{block,_}=Bl|Is], Acc) ->
+ extract_seq_1(Is, [Bl|Acc]);
+extract_seq([{label,_}|_]=Is, Acc) ->
+ extract_seq_1(Is, Acc);
+extract_seq(_, _) -> no.
+
+extract_seq_1([{line,_}=Line|Is], Acc) ->
+ extract_seq_1(Is, [Line|Acc]);
+extract_seq_1([{label,_},{func_info,_,_,_}|_], _) ->
+ no;
+extract_seq_1([{label,_}=Lbl|Is], Acc) ->
+ {yes,[Lbl|Acc],Is};
+extract_seq_1(_, _) -> no.
%%%
%%% (3) (4) (5) (6) Jump and unreachable code optimizations.
@@ -454,6 +464,7 @@ is_label_used_in_2({set,_,_,Info}, Lbl) ->
{put_tuple,_} -> false;
{get_tuple_element,_} -> false;
{set_tuple_element,_} -> false;
+ {line,_} -> false;
_ when is_atom(Info) -> false
end.
@@ -487,6 +498,8 @@ rem_unused([], _, Acc) -> reverse(Acc).
initial_labels(Is) ->
initial_labels(Is, []).
+initial_labels([{line,_}|Is], Acc) ->
+ initial_labels(Is, Acc);
initial_labels([{label,Lbl}|Is], Acc) ->
initial_labels(Is, [Lbl|Acc]);
initial_labels([{func_info,_,_,_},{label,Lbl}|_], Acc) ->
diff --git a/lib/compiler/src/beam_listing.erl b/lib/compiler/src/beam_listing.erl
index be7b14c3dd..2941f6135c 100644
--- a/lib/compiler/src/beam_listing.erl
+++ b/lib/compiler/src/beam_listing.erl
@@ -61,7 +61,7 @@ print_op(Stream, Label) when element(1, Label) == label ->
print_op(Stream, Op) ->
io:format(Stream, " ~p.\n", [Op]).
-function(File, {function,Name,Arity,Args,Body,Vdb}) ->
+function(File, {function,Name,Arity,Args,Body,Vdb,_Anno}) ->
io:nl(File),
io:format(File, "function ~p/~p.\n", [Name,Arity]),
io:format(File, " ~p.\n", [Args]),
diff --git a/lib/compiler/src/beam_receive.erl b/lib/compiler/src/beam_receive.erl
index 9ed44ad5d7..c483d85a97 100644
--- a/lib/compiler/src/beam_receive.erl
+++ b/lib/compiler/src/beam_receive.erl
@@ -175,6 +175,8 @@ opt_update_regs({label,Lbl}, R, L) ->
end;
opt_update_regs({try_end,_}, R, L) ->
{R,L};
+opt_update_regs({line,_}, R, L) ->
+ {R,L};
opt_update_regs(_I, _R, L) ->
%% Unrecognized instruction. Abort the search.
{regs_init(),L}.
diff --git a/lib/compiler/src/beam_trim.erl b/lib/compiler/src/beam_trim.erl
index 790aba0a9a..25e6ffbb73 100644
--- a/lib/compiler/src/beam_trim.erl
+++ b/lib/compiler/src/beam_trim.erl
@@ -222,7 +222,9 @@ remap([{call_last,Ar,Name,N}|Is], Map, Acc) ->
reverse(Acc, [I|Is]);
remap([{call_ext_last,Ar,Name,N}|Is], Map, Acc) ->
I = {call_ext_last,Ar,Name,Map({frame_size,N})},
- reverse(Acc, [I|Is]).
+ reverse(Acc, [I|Is]);
+remap([{line,_}=I|Is], Map, Acc) ->
+ remap(Is, Map, [I|Acc]).
remap_block([{set,Ds0,Ss0,Info}|Is], Map, Acc) ->
Ds = [Map(D) || D <- Ds0],
@@ -230,14 +232,15 @@ remap_block([{set,Ds0,Ss0,Info}|Is], Map, Acc) ->
remap_block(Is, Map, [{set,Ds,Ss,Info}|Acc]);
remap_block([], _, Acc) -> reverse(Acc).
-safe_labels([{label,L},{badmatch,{Tag,_}}|Is], Acc) when Tag =/= y ->
+safe_labels([{label,L},{line,_},{badmatch,{Tag,_}}|Is], Acc) when Tag =/= y ->
safe_labels(Is, [L|Acc]);
-safe_labels([{label,L},{case_end,{Tag,_}}|Is], Acc) when Tag =/= y ->
+safe_labels([{label,L},{line,_},{case_end,{Tag,_}}|Is], Acc) when Tag =/= y ->
safe_labels(Is, [L|Acc]);
-safe_labels([{label,L},if_end|Is], Acc) ->
+safe_labels([{label,L},{line,_},if_end|Is], Acc) ->
safe_labels(Is, [L|Acc]);
safe_labels([{label,L},
{block,[{set,[{x,0}],[{Tag,_}],move}]},
+ {line,_},
{call_ext,1,{extfunc,erlang,error,1}}|Is], Acc) when Tag =/= y ->
safe_labels(Is, [L|Acc]);
safe_labels([_|Is], Acc) ->
@@ -321,6 +324,8 @@ frame_size([{make_fun2,_,_,_,_}|Is], Safe) ->
frame_size([{deallocate,N}|_], _) -> N;
frame_size([{call_last,_,_,N}|_], _) -> N;
frame_size([{call_ext_last,_,_,N}|_], _) -> N;
+frame_size([{line,_}|Is], Safe) ->
+ frame_size(Is, Safe);
frame_size([_|_], _) -> throw(not_possible).
frame_size_branch(0, Is, Safe) ->
diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl
index f83f73b224..0c51251f1b 100644
--- a/lib/compiler/src/beam_type.erl
+++ b/lib/compiler/src/beam_type.erl
@@ -168,6 +168,8 @@ simplify_float_1([{set,[D0],[A,B],{alloc,_,{gc_bif,Op0,{f,0}}}}=I|Is]=Is0, Ts0,
simplify_float_1([{set,_,_,{'catch',_}}=I|Is]=Is0, _Ts, Rs0, Acc0) ->
Acc = flush_all(Rs0, Is0, Acc0),
simplify_float_1(Is, tdb_new(), Rs0, [I|Acc]);
+simplify_float_1([{set,_,_,{line,_}}=I|Is], Ts, Rs, Acc) ->
+ simplify_float_1(Is, Ts, Rs, [I|Acc]);
simplify_float_1([I|Is]=Is0, Ts0, Rs0, Acc0) ->
Ts = update(I, Ts0),
{Rs,Acc} = flush(Rs0, Is0, Acc0),
@@ -400,6 +402,7 @@ update({call_ext,3,{extfunc,erlang,setelement,3}}, Ts0) ->
update({call,_Arity,_Func}, Ts) -> tdb_kill_xregs(Ts);
update({call_ext,_Arity,_Func}, Ts) -> tdb_kill_xregs(Ts);
update({make_fun2,_,_,_,_}, Ts) -> tdb_kill_xregs(Ts);
+update({line,_}, Ts) -> Ts;
%% The instruction is unknown. Kill all information.
update(_I, _Ts) -> tdb_new().
diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl
index 45cdf8a659..f281ad5eac 100644
--- a/lib/compiler/src/beam_utils.erl
+++ b/lib/compiler/src/beam_utils.erl
@@ -26,7 +26,7 @@
code_at/2,bif_to_test/3,is_pure_test/1,
live_opt/1,delete_live_annos/1,combine_heap_needs/2]).
--import(lists, [member/2,sort/1,reverse/1]).
+-import(lists, [member/2,sort/1,reverse/1,splitwith/2]).
-record(live,
{bl, %Block check fun.
@@ -195,10 +195,14 @@ is_pure_test({test,Op,_,Ops}) ->
%% Also insert {'%live',Live} annotations at the beginning
%% and end of each block.
%%
-live_opt([{label,Fail}=I1,
- {func_info,_,_,Live}=I2|Is]) ->
+live_opt(Is0) ->
+ {[{label,Fail}|_]=Bef,[Fi|Is]} =
+ splitwith(fun({func_info,_,_,_}) -> false;
+ (_) -> true
+ end, Is0),
+ {func_info,_,_,Live} = Fi,
D = gb_trees:insert(Fail, live_call(Live), gb_trees:empty()),
- [I1,I2|live_opt(reverse(Is), 0, D, [])].
+ Bef ++ [Fi|live_opt(reverse(Is), 0, D, [])].
%% delete_live_annos([Instruction]) -> [Instruction].
@@ -499,6 +503,8 @@ check_liveness(R, [{loop_rec,{f,_},{x,0}}|_], St) ->
end;
check_liveness(R, [{loop_rec_end,{f,Fail}}|_], St) ->
check_liveness_at(R, Fail, St);
+check_liveness(R, [{line,_}|Is], St) ->
+ check_liveness(R, Is, St);
check_liveness(_R, Is, St) when is_list(Is) ->
%% case Is of
%% [I|_] ->
@@ -799,6 +805,8 @@ live_opt([{wait,_}=I|Is], Regs, D, Acc) ->
live_opt(Is, Regs, D, [I|Acc]);
live_opt([{wait_timeout,_,{Tag,_}}=I|Is], Regs, D, Acc) when Tag =/= x ->
live_opt(Is, Regs, D, [I|Acc]);
+live_opt([{line,_}=I|Is], Regs, D, Acc) ->
+ live_opt(Is, Regs, D, [I|Acc]);
%% The following instructions can occur if the "compilation" has been
%% started from a .S file using the 'asm' option.
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl
index fb267b35b6..fe3b1680d9 100644
--- a/lib/compiler/src/beam_validator.erl
+++ b/lib/compiler/src/beam_validator.erl
@@ -166,12 +166,17 @@ validate(Module, Fs) ->
Ft = index_bs_start_match(Fs, []),
validate_0(Module, Fs, Ft).
-index_bs_start_match([{function,_,_,Entry,Code}|Fs], Acc0) ->
+index_bs_start_match([{function,_,_,Entry,Code0}|Fs], Acc0) ->
+ Code = dropwhile(fun({label,L}) when L =:= Entry -> false;
+ (_) -> true
+ end, Code0),
case Code of
- [_,_,{label,Entry}|Is] ->
+ [{label,Entry}|Is] ->
Acc = index_bs_start_match_1(Is, Entry, Acc0),
index_bs_start_match(Fs, Acc);
_ ->
+ %% Something serious is wrong. Ignore it for now.
+ %% It will be detected and diagnosed later.
index_bs_start_match(Fs, Acc0)
end;
index_bs_start_match([], Acc) ->
@@ -292,6 +297,8 @@ labels(Is) ->
labels_1([{label,L}|Is], R) ->
labels_1(Is, [L|R]);
+labels_1([{line,_}|Is], R) ->
+ labels_1(Is, R);
labels_1(Is, R) ->
{lists:reverse(R),Is}.
@@ -433,6 +440,8 @@ valfun_1(remove_message, Vst) ->
Vst;
valfun_1({'%',_}, Vst) ->
Vst;
+valfun_1({line,_}, Vst) ->
+ Vst;
%% Exception generating calls
valfun_1({call_ext,Live,Func}=I, Vst) ->
case return_type(Func, Vst) of
@@ -870,6 +879,8 @@ val_dsetel({set_tuple_element,_,_,_}, #vst{current=#st{setelem=false}}) ->
error(illegal_context_for_set_tuple_element);
val_dsetel({set_tuple_element,_,_,_}, #vst{current=#st{setelem=true}}=Vst) ->
Vst;
+val_dsetel({line,_}, Vst) ->
+ Vst;
val_dsetel(_, #vst{current=#st{setelem=true}=St}=Vst) ->
Vst#vst{current=St#st{setelem=false}};
val_dsetel(_, Vst) -> Vst.
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index ce8a5bf864..bfa7c6cedd 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -113,7 +113,7 @@ noenv_forms(Forms, Opt) when is_atom(Opt) ->
noenv_output_generated(Opts) ->
{_,Passes} = passes(file, expand_opts(Opts)),
- any(fun ({save_binary,_F}) -> true;
+ any(fun ({save_binary,_T,_F}) -> true;
(_Other) -> false
end, Passes).
@@ -122,6 +122,7 @@ noenv_output_generated(Opts) ->
%%
-define(pass(P), {P,fun P/1}).
+-define(pass(P,T), {P,fun T/1,fun P/1}).
env_default_opts() ->
Key = "ERL_COMPILER_OPTIONS",
@@ -171,9 +172,9 @@ expand_opt(report, Os) ->
expand_opt(return, Os) ->
[return_errors,return_warnings|Os];
expand_opt(r12, Os) ->
- [no_recv_opt|Os];
+ [no_recv_opt,no_line_info|Os];
expand_opt(r13, Os) ->
- [no_recv_opt|Os];
+ [no_recv_opt,no_line_info|Os];
expand_opt({debug_info_key,_}=O, Os) ->
[encrypt_debug_info,O|Os];
expand_opt(no_float_opt, Os) ->
@@ -304,7 +305,7 @@ run_tc({Name,Fun}, St) ->
Val.
comp_ret_ok(#compile{code=Code,warnings=Warn0,module=Mod,options=Opts}=St) ->
- case member(warnings_as_errors, Opts) andalso length(Warn0) > 0 of
+ case werror(St) of
true ->
case member(report_warnings, Opts) of
true ->
@@ -339,6 +340,11 @@ comp_ret_err(#compile{warnings=Warn0,errors=Err0,options=Opts}=St) ->
false -> error
end.
+not_werror(St) -> not werror(St).
+
+werror(#compile{options=Opts,warnings=Ws}) ->
+ Ws =/= [] andalso member(warnings_as_errors, Opts).
+
%% messages_per_file([{File,[Message]}]) -> [{File,[Message]}]
messages_per_file(Ms) ->
T = lists:sort([{File,M} || {File,Messages} <- Ms, M <- Messages]),
@@ -373,7 +379,7 @@ passes(Type, Opts) ->
%% insert a first pass to remove the file (unless the
%% source file is a BEAM file).
{Ext,case last(Passes) of
- {save_binary,_Fun} ->
+ {save_binary,_TestFun,_Fun} ->
case Passes of
[{read_beam_file,_}|_] ->
%% The BEAM is both input and output.
@@ -655,7 +661,7 @@ asm_passes() ->
binary_passes() ->
[{native_compile,fun test_native/1,fun native_compile/1},
- {unless,binary,?pass(save_binary)}].
+ {unless,binary,?pass(save_binary,not_werror)}].
%%%
%%% Compiler passes.
@@ -1379,28 +1385,34 @@ report_errors(#compile{options=Opts,errors=Errors}) ->
end.
report_warnings(#compile{options=Opts,warnings=Ws0}) ->
- case member(report_warnings, Opts) of
+ Werror = member(warnings_as_errors, Opts),
+ P = case Werror of
+ true -> "";
+ false -> "Warning: "
+ end,
+ ReportWerror = Werror andalso member(report_errors, Opts),
+ case member(report_warnings, Opts) orelse ReportWerror of
true ->
- Ws1 = flatmap(fun({{F,_L},Eds}) -> format_message(F, Eds);
- ({F,Eds}) -> format_message(F, Eds) end,
+ Ws1 = flatmap(fun({{F,_L},Eds}) -> format_message(F, P, Eds);
+ ({F,Eds}) -> format_message(F, P, Eds) end,
Ws0),
Ws = lists:sort(Ws1),
foreach(fun({_,Str}) -> io:put_chars(Str) end, Ws);
false -> ok
end.
-format_message(F, [{{Line,Column}=Loc,Mod,E}|Es]) ->
- M = {{F,Loc},io_lib:format("~s:~w:~w Warning: ~s\n",
- [F,Line,Column,Mod:format_error(E)])},
- [M|format_message(F, Es)];
-format_message(F, [{Line,Mod,E}|Es]) ->
- M = {{F,{Line,0}},io_lib:format("~s:~w: Warning: ~s\n",
- [F,Line,Mod:format_error(E)])},
- [M|format_message(F, Es)];
-format_message(F, [{Mod,E}|Es]) ->
- M = {none,io_lib:format("~s: Warning: ~s\n", [F,Mod:format_error(E)])},
- [M|format_message(F, Es)];
-format_message(_, []) -> [].
+format_message(F, P, [{{Line,Column}=Loc,Mod,E}|Es]) ->
+ M = {{F,Loc},io_lib:format("~s:~w:~w ~s~s\n",
+ [F,Line,Column,P,Mod:format_error(E)])},
+ [M|format_message(F, P, Es)];
+format_message(F, P, [{Line,Mod,E}|Es]) ->
+ M = {{F,{Line,0}},io_lib:format("~s:~w: ~s~s\n",
+ [F,Line,P,Mod:format_error(E)])},
+ [M|format_message(F, P, Es)];
+format_message(F, P, [{Mod,E}|Es]) ->
+ M = {none,io_lib:format("~s: ~s~s\n", [F,P,Mod:format_error(E)])},
+ [M|format_message(F, P, Es)];
+format_message(_, _, []) -> [].
%% list_errors(File, ErrorDescriptors) -> ok
@@ -1426,6 +1438,8 @@ iofile(File) when is_atom(File) ->
iofile(File) ->
{filename:dirname(File), filename:basename(File, ".erl")}.
+erlfile(".", Base, Suffix) ->
+ Base ++ Suffix;
erlfile(Dir, Base, Suffix) ->
filename:join(Dir, Base ++ Suffix).
@@ -1498,6 +1512,8 @@ restore_expand_module([{attribute,Line,opaque,[Type]}|Fs]) ->
[{attribute,Line,opaque,Type}|restore_expand_module(Fs)];
restore_expand_module([{attribute,Line,spec,[Arg]}|Fs]) ->
[{attribute,Line,spec,Arg}|restore_expand_module(Fs)];
+restore_expand_module([{attribute,Line,callback,[Arg]}|Fs]) ->
+ [{attribute,Line,callback,Arg}|restore_expand_module(Fs)];
restore_expand_module([F|Fs]) ->
[F|restore_expand_module(Fs)];
restore_expand_module([]) -> [].
diff --git a/lib/compiler/src/erl_bifs.erl b/lib/compiler/src/erl_bifs.erl
index f8128702dd..2514c06360 100644
--- a/lib/compiler/src/erl_bifs.erl
+++ b/lib/compiler/src/erl_bifs.erl
@@ -72,7 +72,6 @@ is_pure(erlang, binary_to_list, 1) -> true;
is_pure(erlang, binary_to_list, 3) -> true;
is_pure(erlang, bit_size, 1) -> true;
is_pure(erlang, byte_size, 1) -> true;
-is_pure(erlang, concat_binary, 1) -> true;
is_pure(erlang, element, 2) -> true;
is_pure(erlang, float, 1) -> true;
is_pure(erlang, float_to_list, 1) -> true;
diff --git a/lib/compiler/src/genop.tab b/lib/compiler/src/genop.tab
index 63527bda8f..39c1e8297f 100644
--- a/lib/compiler/src/genop.tab
+++ b/lib/compiler/src/genop.tab
@@ -280,3 +280,7 @@ BEAM_FORMAT_NUMBER=0
150: recv_mark/1
151: recv_set/1
152: gc_bif3/7
+
+# R15A
+
+153: line/1
diff --git a/lib/compiler/src/sys_pre_expand.erl b/lib/compiler/src/sys_pre_expand.erl
index 480954adac..ba9cde1de0 100644
--- a/lib/compiler/src/sys_pre_expand.erl
+++ b/lib/compiler/src/sys_pre_expand.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -31,8 +31,6 @@
-import(ordsets, [from_list/1,add_element/2,union/2]).
-import(lists, [member/2,foldl/3,foldr/3]).
--compile({nowarn_deprecated_function, {erlang,hash,2}}).
-
-include("../include/erl_bits.hrl").
-record(expand, {module=[], %Module name
@@ -43,12 +41,12 @@
mod_imports, %Module Imports
compile=[], %Compile flags
attributes=[], %Attributes
+ callbacks=[], %Callbacks
defined=[], %Defined functions
vcount=0, %Variable counter
func=[], %Current function
arity=[], %Arity for current function
fcount=0, %Local fun count
- fun_index=0, %Global index for funs
bitdefault,
bittypes
}).
@@ -172,10 +170,41 @@ define_functions(Forms, #expand{defined=Predef}=St) ->
end, Predef, Forms),
St#expand{defined=ordsets:from_list(Fs)}.
-module_attrs(St) ->
- {[{attribute,Line,Name,Val} || {Name,Line,Val} <- St#expand.attributes],St}.
+module_attrs(#expand{attributes=Attributes}=St) ->
+ Attrs = [{attribute,Line,Name,Val} || {Name,Line,Val} <- Attributes],
+ Callbacks = [Callback || {_,_,callback,_}=Callback <- Attrs],
+ {Attrs,St#expand{callbacks=Callbacks}}.
module_predef_funcs(St) ->
+ {Mpf1,St1}=module_predef_func_beh_info(St),
+ {Mpf2,St2}=module_predef_funcs_mod_info(St1),
+ {Mpf1++Mpf2,St2}.
+
+module_predef_func_beh_info(#expand{callbacks=[]}=St) ->
+ {[], St};
+module_predef_func_beh_info(#expand{callbacks=Callbacks,defined=Defined,
+ exports=Exports}=St) ->
+ PreDef=[{behaviour_info,1}],
+ PreExp=PreDef,
+ {[gen_beh_info(Callbacks)],
+ St#expand{defined=union(from_list(PreDef), Defined),
+ exports=union(from_list(PreExp), Exports)}}.
+
+gen_beh_info(Callbacks) ->
+ List = make_list(Callbacks),
+ {function,0,behaviour_info,1,
+ [{clause,0,[{atom,0,callbacks}],[],
+ [List]}]}.
+
+make_list([]) -> {nil,0};
+make_list([{_,_,_,[{{Name,Arity},_}]}|Rest]) ->
+ {cons,0,
+ {tuple,0,
+ [{atom,0,Name},
+ {integer,0,Arity}]},
+ make_list(Rest)}.
+
+module_predef_funcs_mod_info(St) ->
PreDef = [{module_info,0},{module_info,1}],
PreExp = PreDef,
{[{function,0,module_info,0,
@@ -223,10 +252,8 @@ attribute(export, Es, _L, St) ->
St#expand{exports=union(from_list(Es), St#expand.exports)};
attribute(import, Is, _L, St) ->
import(Is, St);
-attribute(compile, C, _L, St) when is_list(C) ->
- St#expand{compile=St#expand.compile ++ C};
-attribute(compile, C, _L, St) ->
- St#expand{compile=St#expand.compile ++ [C]};
+attribute(compile, _C, _L, St) ->
+ St;
attribute(Name, Val, Line, St) when is_list(Val) ->
St#expand{attributes=St#expand.attributes ++ [{Name,Line,Val}]};
attribute(Name, Val, Line, St) ->
@@ -508,32 +535,34 @@ lc_tq(_Line, [], St0) ->
%% Transform an "explicit" fun {'fun', Line, {clauses, Cs}} into an
%% extended form {'fun', Line, {clauses, Cs}, Info}, unless it is the
%% name of a BIF (erl_lint has checked that it is not an import).
-%% Process the body sequence directly to get the new and used variables.
%% "Implicit" funs {'fun', Line, {function, F, A}} are not changed.
fun_tq(Lf, {function,F,A}=Function, St0) ->
- {As,St1} = new_vars(A, Lf, St0),
- Cs = [{clause,Lf,As,[],[{call,Lf,{atom,Lf,F},As}]}],
case erl_internal:bif(F, A) of
true ->
+ {As,St1} = new_vars(A, Lf, St0),
+ Cs = [{clause,Lf,As,[],[{call,Lf,{atom,Lf,F},As}]}],
fun_tq(Lf, {clauses,Cs}, St1);
false ->
- Index = St0#expand.fun_index,
- Uniq = erlang:hash(Cs, (1 bsl 27)-1),
- {Fname,St2} = new_fun_name(St1),
- {{'fun',Lf,Function,{Index,Uniq,Fname}},
- St2#expand{fun_index=Index+1}}
+ {Fname,St1} = new_fun_name(St0),
+ Index = Uniq = 0,
+ {{'fun',Lf,Function,{Index,Uniq,Fname}},St1}
end;
-fun_tq(L, {function,M,F,A}, St) ->
- {{call,L,{remote,L,{atom,L,erlang},{atom,L,make_fun}},
- [{atom,L,M},{atom,L,F},{integer,L,A}]},St};
+fun_tq(L, {function,M,F,A}, St) when is_atom(M), is_atom(F), is_integer(A) ->
+ %% This is the old format for external funs, generated by a pre-R15
+ %% compiler. That means that a tool, such as the debugger or xref,
+ %% directly invoked this module with the abstract code from a
+ %% pre-R15 BEAM file. Be helpful, and translate it to the new format.
+ fun_tq(L, {function,{atom,L,M},{atom,L,F},{integer,L,A}}, St);
+fun_tq(Lf, {function,_,_,_}=ExtFun, St) ->
+ {{'fun',Lf,ExtFun},St};
fun_tq(Lf, {clauses,Cs0}, St0) ->
- Uniq = erlang:hash(Cs0, (1 bsl 27)-1),
{Cs1,St1} = fun_clauses(Cs0, St0),
- Index = St1#expand.fun_index,
{Fname,St2} = new_fun_name(St1),
- {{'fun',Lf,{clauses,Cs1},{Index,Uniq,Fname}},
- St2#expand{fun_index=Index+1}}.
+ %% Set dummy values for Index and Uniq -- the real values will
+ %% be assigned by beam_asm.
+ Index = Uniq = 0,
+ {{'fun',Lf,{clauses,Cs1},{Index,Uniq,Fname}},St2}.
fun_clauses([{clause,L,H0,G0,B0}|Cs0], St0) ->
{H,St1} = head(H0, St0),
diff --git a/lib/compiler/src/v3_codegen.erl b/lib/compiler/src/v3_codegen.erl
index 55e3c58d2a..e7dae67085 100644
--- a/lib/compiler/src/v3_codegen.erl
+++ b/lib/compiler/src/v3_codegen.erl
@@ -79,9 +79,10 @@ module({Mod,Exp,Attr,Forms}, Options) ->
functions(Forms, AtomMod) ->
mapfoldl(fun (F, St) -> function(F, AtomMod, St) end, #cg{lcount=1}, Forms).
-function({function,Name,Arity,Asm0,Vb,Vdb}, AtomMod, St0) ->
+function({function,Name,Arity,Asm0,Vb,Vdb,Anno}, AtomMod, St0) ->
try
- {Asm,EntryLabel,St} = cg_fun(Vb, Asm0, Vdb, AtomMod, {Name,Arity}, St0),
+ {Asm,EntryLabel,St} = cg_fun(Vb, Asm0, Vdb, AtomMod,
+ {Name,Arity}, Anno, St0),
Func = {function,Name,Arity,EntryLabel,Asm},
{Func,St}
catch
@@ -93,7 +94,7 @@ function({function,Name,Arity,Asm0,Vb,Vdb}, AtomMod, St0) ->
%% cg_fun([Lkexpr], [HeadVar], Vdb, State) -> {[Ainstr],State}
-cg_fun(Les, Hvs, Vdb, AtomMod, NameArity, St0) ->
+cg_fun(Les, Hvs, Vdb, AtomMod, NameArity, Anno, St0) ->
{Fi,St1} = new_label(St0), %FuncInfo label
{Fl,St2} = local_func_label(NameArity, St1),
@@ -129,7 +130,7 @@ cg_fun(Les, Hvs, Vdb, AtomMod, NameArity, St0) ->
ultimate_failure=UltimateMatchFail,
is_top_block=true}),
{Name,Arity} = NameArity,
- Asm = [{label,Fi},{func_info,AtomMod,{atom,Name},Arity},
+ Asm = [{label,Fi},line(Anno),{func_info,AtomMod,{atom,Name},Arity},
{label,Fl}|B++[{label,UltimateMatchFail},if_end]],
{Asm,Fl,St}.
@@ -307,23 +308,23 @@ match_fail_cg({badmatch,Term}, Le, Vdb, Bef, St) ->
R = cg_reg_arg(Term, Bef),
Int0 = clear_dead(Bef, Le#l.i, Vdb),
{Sis,Int} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb),
- {Sis ++ [{badmatch,R}],
+ {Sis ++ [line(Le),{badmatch,R}],
Int#sr{reg=clear_regs(Int0#sr.reg)},St};
match_fail_cg({case_clause,Reason}, Le, Vdb, Bef, St) ->
R = cg_reg_arg(Reason, Bef),
Int0 = clear_dead(Bef, Le#l.i, Vdb),
{Sis,Int} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb),
- {Sis++[{case_end,R}],
+ {Sis++[line(Le),{case_end,R}],
Int#sr{reg=clear_regs(Bef#sr.reg)},St};
match_fail_cg(if_clause, Le, Vdb, Bef, St) ->
Int0 = clear_dead(Bef, Le#l.i, Vdb),
{Sis,Int1} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb),
- {Sis++[if_end],Int1#sr{reg=clear_regs(Int1#sr.reg)},St};
+ {Sis++[line(Le),if_end],Int1#sr{reg=clear_regs(Int1#sr.reg)},St};
match_fail_cg({try_clause,Reason}, Le, Vdb, Bef, St) ->
R = cg_reg_arg(Reason, Bef),
Int0 = clear_dead(Bef, Le#l.i, Vdb),
{Sis,Int} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb),
- {Sis ++ [{try_case_end,R}],
+ {Sis ++ [line(Le),{try_case_end,R}],
Int#sr{reg=clear_regs(Int0#sr.reg)},St}.
%% bsm_rename_ctx([Clause], Var) -> [Clause]
@@ -1047,7 +1048,7 @@ call_cg({var,_V} = Var, As, Rs, Le, Vdb, Bef, St0) ->
%% Build complete code and final stack/register state.
Arity = length(As),
{Frees,Aft} = free_dead(clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb)),
- {Sis ++ Frees ++ [{call_fun,Arity}],Aft,
+ {Sis ++ Frees ++ [line(Le),{call_fun,Arity}],Aft,
need_stack_frame(St0)};
call_cg({remote,Mod,Name}, As, Rs, Le, Vdb, Bef, St0)
when element(1, Mod) =:= var;
@@ -1057,11 +1058,10 @@ call_cg({remote,Mod,Name}, As, Rs, Le, Vdb, Bef, St0)
Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
%% Build complete code and final stack/register state.
Arity = length(As),
- Call = {apply,Arity},
St = need_stack_frame(St0),
%%{Call,St1} = build_call(Func, Arity, St0),
{Frees,Aft} = free_dead(clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb)),
- {Sis ++ Frees ++ [Call],Aft,St};
+ {Sis ++ Frees ++ [line(Le),{apply,Arity}],Aft,St};
call_cg(Func, As, Rs, Le, Vdb, Bef, St0) ->
case St0 of
#cg{bfail=Fail} when Fail =/= 0 ->
@@ -1091,7 +1091,7 @@ call_cg(Func, As, Rs, Le, Vdb, Bef, St0) ->
Arity = length(As),
{Call,St1} = build_call(Func, Arity, St0),
{Frees,Aft} = free_dead(clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb)),
- {Sis ++ Frees ++ Call,Aft,St1}
+ {Sis ++ Frees ++ [line(Le)|Call],Aft,St1}
end.
build_call({remote,{atom,erlang},{atom,'!'}}, 2, St0) ->
@@ -1118,7 +1118,7 @@ enter_cg({var,_V} = Var, As, Le, Vdb, Bef, St0) ->
{Sis,Int} = cg_setup_call(As++[Var], Bef, Le#l.i, Vdb),
%% Build complete code and final stack/register state.
Arity = length(As),
- {Sis ++ [{call_fun,Arity},return],
+ {Sis ++ [line(Le),{call_fun,Arity},return],
clear_dead(Int#sr{reg=clear_regs(Int#sr.reg)}, Le#l.i, Vdb),
need_stack_frame(St0)};
enter_cg({remote,Mod,Name}, As, Le, Vdb, Bef, St0)
@@ -1127,9 +1127,8 @@ enter_cg({remote,Mod,Name}, As, Le, Vdb, Bef, St0)
{Sis,Int} = cg_setup_call(As++[Mod,Name], Bef, Le#l.i, Vdb),
%% Build complete code and final stack/register state.
Arity = length(As),
- Call = {apply_only,Arity},
St = need_stack_frame(St0),
- {Sis ++ [Call],
+ {Sis ++ [line(Le),{apply_only,Arity}],
clear_dead(Int#sr{reg=clear_regs(Int#sr.reg)}, Le#l.i, Vdb),
St};
enter_cg(Func, As, Le, Vdb, Bef, St0) ->
@@ -1137,7 +1136,8 @@ enter_cg(Func, As, Le, Vdb, Bef, St0) ->
%% Build complete code and final stack/register state.
Arity = length(As),
{Call,St1} = build_enter(Func, Arity, St0),
- {Sis ++ Call,
+ Line = enter_line(Func, Arity, Le),
+ {Sis ++ Line ++ Call,
clear_dead(Int#sr{reg=clear_regs(Int#sr.reg)}, Le#l.i, Vdb),
St1}.
@@ -1153,6 +1153,23 @@ build_enter(Name, Arity, St0) when is_atom(Name) ->
{Lbl,St1} = local_func_label(Name, Arity, St0),
{[{call_only,Arity,{f,Lbl}}],St1}.
+enter_line({remote,{atom,Mod},{atom,Name}}, Arity, Le) ->
+ case erl_bifs:is_safe(Mod, Name, Arity) of
+ false ->
+ %% Tail-recursive call, possibly to a BIF.
+ %% We'll need a line instruction in case the
+ %% BIF call fails.
+ [line(Le)];
+ true ->
+ %% Call to a safe BIF. Since it cannot fail,
+ %% we don't need any line instruction here.
+ []
+ end;
+enter_line(_, _, _) ->
+ %% Tail-recursive call to a local function. A line
+ %% instruction will not be useful.
+ [].
+
%% local_func_label(Name, Arity, State) -> {Label,State'}
%% local_func_label({Name,Arity}, State) -> {Label,State'}
%% Get the function entry label for a local function.
@@ -1226,9 +1243,10 @@ bif_cg(Bif, As, [{var,V}], Le, Vdb, Bef, St0) ->
%% Currently, we are somewhat pessimistic in
%% that we save any variable that will be live after this BIF call.
+ MayFail = not erl_bifs:is_safe(erlang, Bif, length(As)),
{Sis,Int0} = case St0#cg.in_catch andalso
St0#cg.bfail =:= 0 andalso
- not erl_bifs:is_safe(erlang, Bif, length(As)) of
+ MayFail of
true -> adjust_stack(Bef, Le#l.i, Le#l.i+1, Vdb);
false -> {[],Bef}
end,
@@ -1237,7 +1255,14 @@ bif_cg(Bif, As, [{var,V}], Le, Vdb, Bef, St0) ->
Int = Int1#sr{reg=Reg},
Dst = fetch_reg(V, Reg),
BifFail = {f,St0#cg.bfail},
- {Sis++[{bif,Bif,BifFail,Ars,Dst}],
+ %% We need a line instructions for BIFs that may fail in a body.
+ Line = case BifFail of
+ {f,0} when MayFail ->
+ [line(Le)];
+ _ ->
+ []
+ end,
+ {Sis++Line++[{bif,Bif,BifFail,Ars,Dst}],
clear_dead(Int, Le#l.i, Vdb), St0}.
@@ -1266,7 +1291,11 @@ gc_bif_cg(Bif, As, [{var,V}], Le, Vdb, Bef, St0) ->
Int = Int1#sr{reg=Reg},
Dst = fetch_reg(V, Reg),
BifFail = {f,St0#cg.bfail},
- {Sis++[{gc_bif,Bif,BifFail,max_reg(Bef#sr.reg),Ars,Dst}],
+ Line = case BifFail of
+ {f,0} -> [line(Le)];
+ {f,_} -> []
+ end,
+ {Sis++Line++[{gc_bif,Bif,BifFail,max_reg(Bef#sr.reg),Ars,Dst}],
clear_dead(Int, Le#l.i, Vdb), St0}.
%% recv_loop_cg(TimeOut, ReceiveVar, ReceiveMatch, TimeOutExprs,
@@ -1284,7 +1313,7 @@ recv_loop_cg(Te, Rvar, Rm, Tes, Rs, Le, Vdb, Bef, St0) ->
{Wis,Taft,St6} = cg_recv_wait(Te, Tes, Le#l.i, Int1, St5),
Int2 = sr_merge(Raft, Taft), %Merge stack/registers
Reg = load_vars(Rs, Int2#sr.reg),
- {Sis ++ Ris ++ [{label,Tl}] ++ Wis ++ [{label,Bl}],
+ {Sis ++ [line(Le)] ++ Ris ++ [{label,Tl}] ++ Wis ++ [{label,Bl}],
clear_dead(Int2#sr{reg=Reg}, Le#l.i, Vdb),
St6#cg{break=St0#cg.break,recv=St0#cg.recv}}.
@@ -1463,12 +1492,13 @@ cg_binary([{bs_put_binary,Fail,{atom,all},U,_Flags,Src}|PutCode],
{bs_append,Fail,Target,0,MaxRegs,U,Src,BinFlags,Target}
end] ++ PutCode,
cg_bin_opt(Code);
-cg_binary(PutCode, Target, Temp, Fail, MaxRegs, _Anno) ->
+cg_binary(PutCode, Target, Temp, Fail, MaxRegs, Anno) ->
+ Line = line(Anno),
Live = cg_live(Target, MaxRegs),
{InitOp,SzCode} = cg_binary_size(PutCode, Target, Temp, Fail, Live),
- Code = SzCode ++ [{InitOp,Fail,Target,0,MaxRegs,
- {field_flags,[]},Target}|PutCode],
+ Code = [Line|SzCode] ++ [{InitOp,Fail,Target,0,MaxRegs,
+ {field_flags,[]},Target}|PutCode],
cg_bin_opt(Code).
cg_live({x,X}, MaxRegs) when X =:= MaxRegs -> MaxRegs+1;
@@ -2052,6 +2082,38 @@ drop_catch(Tag, [Other|Stk]) -> [Other|drop_catch(Tag, Stk)].
new_label(#cg{lcount=Next}=St) ->
{Next,St#cg{lcount=Next+1}}.
+%% line(Le) -> {line,[] | {location,File,Line}}
+%% Create a line instruction, containing information about
+%% the current filename and line number. A line information
+%% instruction should be placed before any operation that could
+%% cause an exception.
+
+line(#l{a=Anno}) ->
+ line(Anno);
+line([Line,{file,Name}]) when is_integer(Line) ->
+ line_1(Name, Line);
+line([_|_]=A) ->
+ {Name,Line} = find_loc(A, no_file, 0),
+ line_1(Name, Line);
+line([]) ->
+ {line,[]}.
+
+line_1(no_file, _) ->
+ {line,[]};
+line_1(_, 0) ->
+ %% Missing line number or line number 0.
+ {line,[]};
+line_1(Name, Line) ->
+ {line,[{location,Name,abs(Line)}]}.
+
+find_loc([Line|T], File, _) when is_integer(Line) ->
+ find_loc(T, File, Line);
+find_loc([{file,File}|T], _, Line) ->
+ find_loc(T, File, Line);
+find_loc([_|T], File, Line) ->
+ find_loc(T, File, Line);
+find_loc([], File, Line) -> {File,Line}.
+
flatmapfoldl(F, Accu0, [Hd|Tail]) ->
{R,Accu1} = F(Hd, Accu0),
{Rs,Accu2} = flatmapfoldl(F, Accu1, Tail),
diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl
index 87bb5bec25..6885405ae0 100644
--- a/lib/compiler/src/v3_core.erl
+++ b/lib/compiler/src/v3_core.erl
@@ -180,7 +180,7 @@ body(Cs0, Name, Arity, St0) ->
{Args,St1} = new_vars(Anno, Arity, St0),
{Cs1,St2} = clauses(Cs0, St1),
{Ps,St3} = new_vars(Arity, St2), %Need new variables here
- Fc = function_clause(Ps, {Name,Arity}),
+ Fc = function_clause(Ps, Anno, {Name,Arity}),
{#ifun{anno=#a{anno=Anno},id=[],vars=Args,clauses=Cs1,fc=Fc},St3}.
%% clause(Clause, State) -> {Cclause,State} | noclause.
@@ -507,15 +507,15 @@ expr({block,_,Es0}, St0) ->
{E1,Es1 ++ Eps,St2};
expr({'if',L,Cs0}, St0) ->
{Cs1,St1} = clauses(Cs0, St0),
- Fc = fail_clause([], #c_literal{val=if_clause}),
Lanno = lineno_anno(L, St1),
+ Fc = fail_clause([], Lanno, #c_literal{val=if_clause}),
{#icase{anno=#a{anno=Lanno},args=[],clauses=Cs1,fc=Fc},[],St1};
expr({'case',L,E0,Cs0}, St0) ->
{E1,Eps,St1} = novars(E0, St0),
{Cs1,St2} = clauses(Cs0, St1),
{Fpat,St3} = new_var(St2),
- Fc = fail_clause([Fpat], c_tuple([#c_literal{val=case_clause},Fpat])),
- Lanno = lineno_anno(L, St3),
+ Lanno = lineno_anno(L, St2),
+ Fc = fail_clause([Fpat], Lanno, c_tuple([#c_literal{val=case_clause},Fpat])),
{#icase{anno=#a{anno=Lanno},args=[E1],clauses=Cs1,fc=Fc},Eps,St3};
expr({'receive',L,Cs0}, St0) ->
{Cs1,St1} = clauses(Cs0, St0),
@@ -541,9 +541,10 @@ expr({'try',L,Es0,Cs0,Ecs,[]}, St0) ->
{V,St2} = new_var(St1), %This name should be arbitrary
{Cs1,St3} = clauses(Cs0, St2),
{Fpat,St4} = new_var(St3),
- Fc = fail_clause([Fpat], c_tuple([#c_literal{val=try_clause},Fpat])),
+ Lanno = lineno_anno(L, St4),
+ Fc = fail_clause([Fpat], Lanno,
+ c_tuple([#c_literal{val=try_clause},Fpat])),
{Evs,Hs,St5} = try_exception(Ecs, St4),
- Lanno = lineno_anno(L, St1),
{#itry{anno=#a{anno=lineno_anno(L, St5)},args=Es1,
vars=[V],body=[#icase{anno=#a{anno=Lanno},args=[V],clauses=Cs1,fc=Fc}],
evars=Evs,handler=Hs},
@@ -572,6 +573,13 @@ expr({'catch',L,E0}, St0) ->
expr({'fun',L,{function,F,A},{_,_,_}=Id}, St) ->
Lanno = lineno_anno(L, St),
{#c_var{anno=Lanno++[{id,Id}],name={F,A}},[],St};
+expr({'fun',L,{function,M,F,A}}, St0) ->
+ {As,Aps,St1} = safe_list([M,F,A], St0),
+ Lanno = lineno_anno(L, St1),
+ {#icall{anno=#a{anno=Lanno},
+ module=#c_literal{val=erlang},
+ name=#c_literal{val=make_fun},
+ args=As},Aps,St1};
expr({'fun',L,{clauses,Cs},Id}, St) ->
fun_tq(Id, Cs, L, St);
expr({call,L,{remote,_,M,F},As0}, #core{wanted=Wanted}=St0) ->
@@ -607,8 +615,8 @@ expr({match,L,P0,E0}, St0) ->
Thrown
end,
{Fpat,St4} = new_var(St3),
- Fc = fail_clause([Fpat], c_tuple([#c_literal{val=badmatch},Fpat])),
Lanno = lineno_anno(L, St4),
+ Fc = fail_clause([Fpat], Lanno, c_tuple([#c_literal{val=badmatch},Fpat])),
case P2 of
nomatch ->
St = add_warning(L, nomatch, St4),
@@ -828,8 +836,9 @@ fun_tq({_,_,Name}=Id, Cs0, L, St0) ->
{Cs1,St1} = clauses(Cs0, St0),
{Args,St2} = new_vars(Arity, St1),
{Ps,St3} = new_vars(Arity, St2), %Need new variables here
- Fc = function_clause(Ps, {Name,Arity}),
- Fun = #ifun{anno=#a{anno=lineno_anno(L, St3)},
+ Anno = lineno_anno(L, St3),
+ Fc = function_clause(Ps, Anno, {Name,Arity}),
+ Fun = #ifun{anno=#a{anno=Anno},
id=[{id,Id}], %We KNOW!
vars=Args,clauses=Cs1,fc=Fc},
{Fun,[],St3}.
@@ -929,7 +938,7 @@ lc_tq(Line, E, [{b_generate,Lg,P,G}|Qs0], Mc, St0) ->
[],St};
lc_tq(Line, E, [Fil0|Qs0], Mc, St0) ->
%% Special case sequences guard tests.
- LA = lineno_anno(Line, St0),
+ LA = lineno_anno(element(2, Fil0), St0),
LAnno = #a{anno=LA},
case is_guard_test(Fil0) of
true ->
@@ -945,7 +954,8 @@ lc_tq(Line, E, [Fil0|Qs0], Mc, St0) ->
false ->
{Lc,Lps,St1} = lc_tq(Line, E, Qs0, Mc, St0),
{Fpat,St2} = new_var(St1),
- Fc = fail_clause([Fpat], c_tuple([#c_literal{val=case_clause},Fpat])),
+ Fc = fail_clause([Fpat], LA,
+ c_tuple([#c_literal{val=case_clause},Fpat])),
%% Do a novars little optimisation here.
{Filc,Fps,St3} = novars(Fil0, St2),
{#icase{anno=LAnno,
@@ -1072,7 +1082,7 @@ bc_tq1(Line, E, [{b_generate,Lg,P,G}|Qs0], AccExpr, St0) ->
[],St};
bc_tq1(Line, E, [Fil0|Qs0], AccVar, St0) ->
%% Special case sequences guard tests.
- LA = lineno_anno(Line, St0),
+ LA = lineno_anno(element(2, Fil0), St0),
LAnno = #a{anno=LA},
case is_guard_test(Fil0) of
true ->
@@ -1089,7 +1099,8 @@ bc_tq1(Line, E, [Fil0|Qs0], AccVar, St0) ->
false ->
{Bc,Bps,St1} = bc_tq1(Line, E, Qs0, AccVar, St0),
{Fpat,St2} = new_var(St1),
- Fc = fail_clause([Fpat], c_tuple([#c_literal{val=case_clause},Fpat])),
+ Fc = fail_clause([Fpat], LA,
+ c_tuple([#c_literal{val=case_clause},Fpat])),
%% Do a novars little optimisation here.
{Filc,Fps,St} = novars(Fil0, St2),
{#icase{anno=LAnno,
@@ -1562,17 +1573,11 @@ new_vars_1(N, Anno, St0, Vs) when N > 0 ->
new_vars_1(N-1, Anno, St1, [V|Vs]);
new_vars_1(0, _, St, Vs) -> {Vs,St}.
-function_clause(Ps, Name) ->
- function_clause(Ps, [], Name).
-
function_clause(Ps, LineAnno, Name) ->
- FcAnno = [{function_name,Name}],
+ FcAnno = [{function_name,Name}|LineAnno],
fail_clause(Ps, FcAnno,
ann_c_tuple(LineAnno, [#c_literal{val=function_clause}|Ps])).
-fail_clause(Pats, Arg) ->
- fail_clause(Pats, [], Arg).
-
fail_clause(Pats, Anno, Arg) ->
#iclause{anno=#a{anno=[compiler_generated]},
pats=Pats,guard=[],
diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl
index 3b33a08cf7..47e5e49a76 100644
--- a/lib/compiler/src/v3_kernel.erl
+++ b/lib/compiler/src/v3_kernel.erl
@@ -84,8 +84,6 @@
keymember/3,keyfind/3]).
-import(ordsets, [add_element/2,del_element/2,union/2,union/1,subtract/2]).
--compile({nowarn_deprecated_function, {erlang,hash,2}}).
-
-include("core_parse.hrl").
-include("v3_kernel.hrl").
@@ -247,7 +245,7 @@ expr(#c_var{anno=A,name={_Name,Arity}}=Fname, Sub, St) ->
%% instead of one for each occurrence as done now.
Vs = [#c_var{name=list_to_atom("V" ++ integer_to_list(V))} ||
V <- integers(1, Arity)],
- Fun = #c_fun{anno=A,vars=Vs,body=#c_apply{op=Fname,args=Vs}},
+ Fun = #c_fun{anno=A,vars=Vs,body=#c_apply{anno=A,op=Fname,args=Vs}},
expr(Fun, Sub, St);
expr(#c_var{anno=A,name=V}, Sub, St) ->
{#k_var{anno=A,name=get_vsub(V, Sub)},[],St};
@@ -291,7 +289,7 @@ expr(#c_binary{anno=A,segments=Cv}, Sub, St0) ->
Erl = #c_literal{val=erlang},
Name = #c_literal{val=error},
Args = [#c_literal{val=badarg}],
- Error = #c_call{module=Erl,name=Name,args=Args},
+ Error = #c_call{anno=A,module=Erl,name=Name,args=Args},
expr(Error, Sub, St0)
end;
expr(#c_fun{anno=A,vars=Cvs,body=Cb}, Sub0, #kern{ff=OldFF,func=Func}=St0) ->
@@ -1167,9 +1165,7 @@ select_bin_int_1(_, _, _, _) -> throw(not_possible).
select_assert_match_possible(Sz, Val, Fs) ->
EmptyBindings = erl_eval:new_bindings(),
- MatchFun = fun({integer,_,_}, NewV, Bs) when NewV =:= Val ->
- {match,Bs}
- end,
+ MatchFun = match_fun(Val),
EvalFun = fun({integer,_,S}, B) -> {value,S,B} end,
Expr = [{bin_element,0,{integer,0,Val},{integer,0,Sz},[{unit,1}|Fs]}],
{value,Bin,EmptyBindings} = eval_bits:expr_grp(Expr, EmptyBindings, EvalFun),
@@ -1184,6 +1180,11 @@ select_assert_match_possible(Sz, Val, Fs) ->
throw(not_possible)
end.
+match_fun(Val) ->
+ fun(match, {{integer,_,_},NewV,Bs}) when NewV =:= Val ->
+ {match,Bs}
+ end.
+
select_utf8(Val0) ->
try
Bin = <<Val0/utf8>>,
@@ -1655,31 +1656,31 @@ uexpr(#k_catch{anno=A,body=B0}, {break,Rs0}, St0) ->
{Ns,St3} = new_vars(1 - length(Rs0), St2),
Rs1 = Rs0 ++ Ns,
{#k_catch{anno=#k{us=Bu,ns=lit_list_vars(Rs1),a=A},body=B1,ret=Rs1},Bu,St3};
-uexpr(#ifun{anno=A,vars=Vs,body=B0}=IFun, {break,Rs}, St0) ->
+uexpr(#ifun{anno=A,vars=Vs,body=B0}, {break,Rs}, St0) ->
{B1,Bu,St1} = ubody(B0, return, St0), %Return out of new function
Ns = lit_list_vars(Vs),
Free = subtract(Bu, Ns), %Free variables in fun
Fvs = make_vars(Free),
Arity = length(Vs) + length(Free),
- {{Index,Uniq,Fname}, St3} =
+ {Fname,St} =
case lists:keyfind(id, 1, A) of
- {id,Id} ->
- {Id, St1};
+ {id,{_,_,Fname0}} ->
+ {Fname0,St1};
false ->
- %% No id annotation. Must invent one.
- I = St1#kern.fcount,
- U = erlang:hash(IFun, (1 bsl 27)-1),
- {N, St2} = new_fun_name(St1),
- {{I,U,N}, St2}
+ %% No id annotation. Must invent a fun name.
+ new_fun_name(St1)
end,
Fun = #k_fdef{anno=#k{us=[],ns=[],a=A},func=Fname,arity=Arity,
vars=Vs ++ Fvs,body=B1},
+ %% Set dummy values for Index and Uniq -- the real values will
+ %% be assigned by beam_asm.
+ Index = Uniq = 0,
{#k_bif{anno=#k{us=Free,ns=lit_list_vars(Rs),a=A},
op=#k_internal{name=make_fun,arity=length(Free)+3},
args=[#k_atom{val=Fname},#k_int{val=Arity},
#k_int{val=Index},#k_int{val=Uniq}|Fvs],
ret=Rs},
- Free,add_local_function(Fun, St3)};
+ Free,add_local_function(Fun, St)};
uexpr(Lit, {break,Rs}, St) ->
%% Transform literals to puts here.
%%ok = io:fwrite("uexpr ~w:~p~n", [?LINE,Lit]),
diff --git a/lib/compiler/src/v3_life.erl b/lib/compiler/src/v3_life.erl
index a7a4d4dc91..a1d92af9f8 100644
--- a/lib/compiler/src/v3_life.erl
+++ b/lib/compiler/src/v3_life.erl
@@ -65,7 +65,7 @@ functions([], Acc) -> reverse(Acc).
%% function(Kfunc) -> Func.
-function(#k_fdef{func=F,arity=Ar,vars=Vs,body=Kb}) ->
+function(#k_fdef{anno=#k{a=Anno},func=F,arity=Ar,vars=Vs,body=Kb}) ->
try
As = var_list(Vs),
Vdb0 = foldl(fun ({var,N}, Vdb) -> new_var(N, 0, Vdb) end, [], As),
@@ -80,7 +80,7 @@ function(#k_fdef{func=F,arity=Ar,vars=Vs,body=Kb}) ->
put(guard_refc, 0),
{B1,_,Vdb1} = body(B0, 1, Vdb0),
erase(guard_refc),
- {function,F,Ar,As,B1,Vdb1}
+ {function,F,Ar,As,B1,Vdb1,Anno}
catch
Class:Error ->
Stack = erlang:get_stacktrace(),
diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile
index fe713fd019..b90adaf917 100644
--- a/lib/compiler/test/Makefile
+++ b/lib/compiler/test/Makefile
@@ -9,6 +9,7 @@ MODULES= \
andor_SUITE \
apply_SUITE \
beam_validator_SUITE \
+ beam_disasm_SUITE \
bs_bincomp_SUITE \
bs_bit_binaries_SUITE \
bs_construct_SUITE \
diff --git a/lib/compiler/test/beam_disasm_SUITE.erl b/lib/compiler/test/beam_disasm_SUITE.erl
new file mode 100644
index 0000000000..44574ae64a
--- /dev/null
+++ b/lib/compiler/test/beam_disasm_SUITE.erl
@@ -0,0 +1,65 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(beam_disasm_SUITE).
+
+-include_lib("test_server/include/test_server.hrl").
+
+-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_group/2,end_per_group/2]).
+
+-export([stripped/1]).
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [stripped].
+
+groups() ->
+ [].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+stripped(doc) ->
+ ["Check that stripped beam files can be disassembled"];
+stripped(Config) when is_list(Config) ->
+ ?line PrivDir = ?config(priv_dir, Config),
+ ?line SrcName = filename:join(PrivDir, "tmp.erl"),
+ ?line BeamName = filename:join(PrivDir, "tmp.beam"),
+ Prog = <<"-module(tmp).\n-export([tmp/0]).\ntmp()->ok.\n">>,
+ ?line ok = file:write_file(SrcName, Prog),
+ ?line {ok, tmp} =
+ compile:file(SrcName, [{outdir, PrivDir}]),
+ ?line {beam_file, tmp, _, Attr, CompileInfo, [_|_]} =
+ beam_disasm:file(BeamName),
+ ?line true = is_list(Attr),
+ ?line true = is_list(CompileInfo),
+ ?line {ok, {tmp, _}} = beam_lib:strip(BeamName),
+ ?line {beam_file, tmp, _, none, none, [_|_]} =
+ beam_disasm:file(BeamName),
+ ok.
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index 6a795f6634..f8c71a0257 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -1028,8 +1028,8 @@ haystack_2(Haystack) ->
fc({'EXIT',{function_clause,_}}) -> ok;
fc({'EXIT',{{case_clause,_},_}}) when ?MODULE =:= bs_match_inline_SUITE -> ok.
-fc(Name, Args, {'EXIT',{function_clause,[{?MODULE,Name,Args}|_]}}) -> ok;
-fc(Name, Args, {'EXIT',{function_clause,[{?MODULE,Name,Arity}|_]}})
+fc(Name, Args, {'EXIT',{function_clause,[{?MODULE,Name,Args,_}|_]}}) -> ok;
+fc(Name, Args, {'EXIT',{function_clause,[{?MODULE,Name,Arity,_}|_]}})
when length(Args) =:= Arity ->
true = test_server:is_native(?MODULE);
fc(_, Args, {'EXIT',{{case_clause,ActualArgs},_}})
diff --git a/lib/compiler/test/bs_utf_SUITE.erl b/lib/compiler/test/bs_utf_SUITE.erl
index f30a4d3fef..94549ad0d3 100644
--- a/lib/compiler/test/bs_utf_SUITE.erl
+++ b/lib/compiler/test/bs_utf_SUITE.erl
@@ -264,18 +264,10 @@ literals(Config) when is_list(Config) ->
?line {'EXIT',{badarg,_}} = (catch <<(-1)/utf32,I/utf8>>),
?line {'EXIT',{badarg,_}} = (catch <<(-1)/little-utf32,I/utf8>>),
?line {'EXIT',{badarg,_}} = (catch <<16#D800/utf8,I/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<16#FFFE/utf8,I/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<16#FFFF/utf8,I/utf8>>),
?line {'EXIT',{badarg,_}} = (catch <<16#D800/utf16,I/utf8>>),
?line {'EXIT',{badarg,_}} = (catch <<16#D800/little-utf16,I/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<16#FFFE/utf16,I/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<16#FFFE/little-utf16,I/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<16#FFFF/utf16,I/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<16#FFFF/little-utf16,I/utf8>>),
?line {'EXIT',{badarg,_}} = (catch <<16#D800/utf32,I/utf8>>),
?line {'EXIT',{badarg,_}} = (catch <<16#D800/little-utf32,I/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<16#FFFE/utf32,I/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<16#FFFF/little-utf32,I/utf8>>),
B = 16#10FFFF+1,
?line {'EXIT',{badarg,_}} = (catch <<B/utf8>>),
@@ -286,20 +278,11 @@ literals(Config) when is_list(Config) ->
%% Matching of bad literals.
?line error = bad_literal_match(<<237,160,128>>), %16#D800 in UTF-8
- ?line error = bad_literal_match(<<239,191,190>>), %16#FFFE in UTF-8
- ?line error = bad_literal_match(<<239,191,191>>), %16#FFFF in UTF-8
?line error = bad_literal_match(<<244,144,128,128>>), %16#110000 in UTF-8
- ?line error = bad_literal_match(<<255,254>>), %16#FFFE in UTF-16
- ?line error = bad_literal_match(<<255,255>>), %16#FFFF in UTF-16
-
?line error = bad_literal_match(<<16#D800:32>>),
- ?line error = bad_literal_match(<<16#FFFE:32>>),
- ?line error = bad_literal_match(<<16#FFFF:32>>),
?line error = bad_literal_match(<<16#110000:32>>),
?line error = bad_literal_match(<<16#D800:32/little>>),
- ?line error = bad_literal_match(<<16#FFFE:32/little>>),
- ?line error = bad_literal_match(<<16#FFFF:32/little>>),
?line error = bad_literal_match(<<16#110000:32/little>>),
ok.
@@ -314,11 +297,7 @@ match_literal(<<"bj\366rn"/big-utf16>>) -> bjorn_utf16be;
match_literal(<<"bj\366rn"/little-utf16>>) -> bjorn_utf16le.
bad_literal_match(<<16#D800/utf8>>) -> ok;
-bad_literal_match(<<16#FFFE/utf8>>) -> ok;
-bad_literal_match(<<16#FFFF/utf8>>) -> ok;
bad_literal_match(<<16#110000/utf8>>) -> ok;
-bad_literal_match(<<16#FFFE/utf16>>) -> ok;
-bad_literal_match(<<16#FFFF/utf16>>) -> ok;
bad_literal_match(<<16#D800/utf32>>) -> ok;
bad_literal_match(<<16#110000/utf32>>) -> ok;
bad_literal_match(<<16#D800/little-utf32>>) -> ok;
diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl
index b3e5376ffd..8c6a623dfb 100644
--- a/lib/compiler/test/compile_SUITE.erl
+++ b/lib/compiler/test/compile_SUITE.erl
@@ -82,6 +82,7 @@ file_1(Config) when is_list(Config) ->
?line {ok,simple} = compile:file(Simple, [native,report]), %Smoke test.
?line {ok,simple} = compile:file(Target, [native,from_beam]), %Smoke test.
?line {ok,simple} = compile:file(Simple, [debug_info]),
+ ?line {ok,simple} = compile:file(Simple, [no_line_info]), %Coverage
?line ok = file:set_cwd(Cwd),
?line true = exists(Target),
?line passed = run(Target, test, []),
diff --git a/lib/compiler/test/error_SUITE.erl b/lib/compiler/test/error_SUITE.erl
index 6e0aadf007..eb5e50818e 100644
--- a/lib/compiler/test/error_SUITE.erl
+++ b/lib/compiler/test/error_SUITE.erl
@@ -183,23 +183,47 @@ get_compilation_errors(Config, Filename) ->
E.
warnings_as_errors(Config) when is_list(Config) ->
- Ts = [{warnings_as_errors,
+ ?line TestFile = test_filename(Config),
+ ?line BeamFile = filename:rootname(TestFile, ".erl") ++ ".beam",
+ ?line OutDir = ?config(priv_dir, Config),
+
+ Ts1 = [{warnings_as_errors,
<<"
t() ->
A = unused,
ok.
">>,
- [export_all,warnings_as_errors],
- {error,
- [],
- [{3,erl_lint,{unused_var,'A'}}]} }],
- ?line [] = run(Config, Ts),
+ [warnings_as_errors, export_all, {outdir, OutDir}],
+ {error,
+ [],
+ [{3,erl_lint,{unused_var,'A'}}]} }],
+ ?line [] = run(Ts1, TestFile, write_beam),
+ ?line false = filelib:is_regular(BeamFile),
+
+ Ts2 = [{warning_unused_var,
+ <<"
+ t() ->
+ A = unused,
+ ok.
+ ">>,
+ [return_warnings, export_all, {outdir, OutDir}],
+ {warning,
+ [{3,erl_lint,{unused_var,'A'}}]} }],
+
+ ?line [] = run(Ts2, TestFile, write_beam),
+ ?line true = filelib:is_regular(BeamFile),
+ ?line ok = file:delete(BeamFile),
+
ok.
run(Config, Tests) ->
+ ?line File = test_filename(Config),
+ run(Tests, File, dont_write_beam).
+
+run(Tests, File, WriteBeam) ->
F = fun({N,P,Ws,E}, BadL) ->
- case catch run_test(Config, P, Ws) of
+ case catch run_test(P, File, Ws, WriteBeam) of
E ->
BadL;
Bad ->
@@ -211,8 +235,12 @@ run(Config, Tests) ->
lists:foldl(F, [], Tests).
run2(Config, Tests) ->
+ ?line File = test_filename(Config),
+ run2(Tests, File, dont_write_beam).
+
+run2(Tests, File, WriteBeam) ->
F = fun({N,P,Ws,E}, BadL) ->
- case catch filter(run_test(Config, P, Ws)) of
+ case catch filter(run_test(P, File, Ws, WriteBeam)) of
E ->
BadL;
Bad ->
@@ -231,12 +259,19 @@ filter(X) ->
%% Compiles a test module and returns the list of errors and warnings.
-run_test(Conf, Test0, Warnings) ->
- Filename = 'errors_test.erl',
- ?line DataDir = ?config(priv_dir, Conf),
+test_filename(Conf) ->
+ Filename = "errors_test.erl",
+ DataDir = ?config(priv_dir, Conf),
+ filename:join(DataDir, Filename).
+
+run_test(Test0, File, Warnings, WriteBeam) ->
?line Test = ["-module(errors_test). ", Test0],
- ?line File = filename:join(DataDir, Filename),
- ?line Opts = [binary,return_errors|Warnings],
+ ?line Opts = case WriteBeam of
+ dont_write_beam ->
+ [binary,return_errors|Warnings];
+ write_beam ->
+ [return_errors|Warnings]
+ end,
?line ok = file:write_file(File, Test),
%% Compile once just to print all errors and warnings.
@@ -252,6 +287,10 @@ run_test(Conf, Test0, Warnings) ->
%io:format("compile:file(~s,~p) ->~n~p~n",
% [File,Opts,Ws]),
[];
+ {ok,errors_test,[{_File,Ws}]} ->
+ {warning,Ws};
+ {ok,errors_test,[]} ->
+ [];
{error,[{XFile,Es}],Ws} = _ZZ when is_list(XFile) ->
%io:format("compile:file(~s,~p) ->~n~p~n",
% [File,Opts,_ZZ]),
diff --git a/lib/compiler/test/fun_SUITE.erl b/lib/compiler/test/fun_SUITE.erl
index 368a5815bf..6067ee8e06 100644
--- a/lib/compiler/test/fun_SUITE.erl
+++ b/lib/compiler/test/fun_SUITE.erl
@@ -20,7 +20,11 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
- test1/1,overwritten_fun/1,otp_7202/1,bif_fun/1]).
+ test1/1,overwritten_fun/1,otp_7202/1,bif_fun/1,
+ external/1]).
+
+%% Internal export.
+-export([call_me/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -28,7 +32,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
test_lib:recompile(?MODULE),
- [test1, overwritten_fun, otp_7202, bif_fun].
+ [test1,overwritten_fun,otp_7202,bif_fun,external].
groups() ->
[].
@@ -45,7 +49,6 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-
%%% The help functions below are copied from emulator:bs_construct_SUITE.
-define(T(B, L), {B, ??B, L}).
@@ -152,4 +155,47 @@ bif_fun(Config) when is_list(Config) ->
?line F = fun abs/1,
?line 5 = F(-5),
ok.
+
+-define(APPLY(M, F, A), (fun(Fun) -> {ok,{a,b}} = Fun({a,b}) end)(fun M:F/A)).
+-define(APPLY2(M, F, A),
+ (fun(Map) ->
+ Id = fun(I) -> I end,
+ List = [x,y],
+ List = Map(Id, List),
+ {type,external} = erlang:fun_info(Map, type)
+ end)(fun M:F/A)).
+external(Config) when is_list(Config) ->
+ Mod = id(?MODULE),
+ Func = id(call_me),
+ Arity = id(1),
+
+ ?APPLY(?MODULE, call_me, 1),
+ ?APPLY(?MODULE, call_me, Arity),
+ ?APPLY(?MODULE, Func, 1),
+ ?APPLY(?MODULE, Func, Arity),
+ ?APPLY(Mod, call_me, 1),
+ ?APPLY(Mod, call_me, Arity),
+ ?APPLY(Mod, Func, 1),
+ ?APPLY(Mod, Func, Arity),
+
+ ListsMod = id(lists),
+ ListsMap = id(map),
+ ListsArity = id(2),
+
+ ?APPLY2(lists, map, 2),
+ ?APPLY2(lists, map, ListsArity),
+ ?APPLY2(lists, ListsMap, 2),
+ ?APPLY2(lists, ListsMap, ListsArity),
+ ?APPLY2(ListsMod, map, 2),
+ ?APPLY2(ListsMod, map, ListsArity),
+ ?APPLY2(ListsMod, ListsMap, 2),
+ ?APPLY2(ListsMod, ListsMap, ListsArity),
+
+ ok.
+
+call_me(I) ->
+ {ok,I}.
+
+id(I) ->
+ I.
diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl
index 0e69efba6b..40711783ed 100644
--- a/lib/compiler/test/guard_SUITE.erl
+++ b/lib/compiler/test/guard_SUITE.erl
@@ -32,7 +32,8 @@
t_is_boolean/1,is_function_2/1,
tricky/1,rel_ops/1,literal_type_tests/1,
basic_andalso_orelse/1,traverse_dcd/1,
- check_qlc_hrl/1,andalso_semi/1,t_tuple_size/1,binary_part/1]).
+ check_qlc_hrl/1,andalso_semi/1,t_tuple_size/1,binary_part/1,
+ bad_constants/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -44,7 +45,8 @@ all() ->
more_xor_guards, build_in_guard, old_guard_tests, gbif,
t_is_boolean, is_function_2, tricky, rel_ops,
literal_type_tests, basic_andalso_orelse, traverse_dcd,
- check_qlc_hrl, andalso_semi, t_tuple_size, binary_part].
+ check_qlc_hrl, andalso_semi, t_tuple_size, binary_part,
+ bad_constants].
groups() ->
[].
@@ -1517,8 +1519,27 @@ bptest(B,A,C) when erlang:binary_part(B,{A,C}) =:= <<3,3>> ->
bptest(_,_,_) ->
error.
-
-
+-define(FAILING(C),
+ if
+ C -> ?t:fail(should_fail);
+ true -> ok
+ end,
+ if
+ true, C -> ?t:fail(should_fail);
+ true -> ok
+ end).
+
+bad_constants(Config) when is_list(Config) ->
+ ?line ?FAILING(false),
+ ?line ?FAILING([]),
+ ?line ?FAILING([a]),
+ ?line ?FAILING([Config]),
+ ?line ?FAILING({a,b}),
+ ?line ?FAILING({a,Config}),
+ ?line ?FAILING(<<1>>),
+ ?line ?FAILING(42),
+ ?line ?FAILING(3.14),
+ ok.
%% Call this function to turn off constant propagation.
id(I) -> I.
diff --git a/lib/compiler/test/inline_SUITE.erl b/lib/compiler/test/inline_SUITE.erl
index af2b8ec92a..086fba2649 100644
--- a/lib/compiler/test/inline_SUITE.erl
+++ b/lib/compiler/test/inline_SUITE.erl
@@ -263,7 +263,8 @@ my_apply(M, F, A, Init) ->
really_inlined(Config) when is_list(Config) ->
%% Make sure that badarg/2 really gets inlined.
- {'EXIT',{badarg,[{?MODULE,fail_me_now,[]}|_]}} = (catch fail_me_now()),
+ {'EXIT',{badarg,[{?MODULE,fail_me_now,[],_}|_]}} =
+ (catch fail_me_now()),
ok.
fail_me_now() ->
diff --git a/lib/compiler/test/lc_SUITE.erl b/lib/compiler/test/lc_SUITE.erl
index c8908858ba..f5948504b3 100644
--- a/lib/compiler/test/lc_SUITE.erl
+++ b/lib/compiler/test/lc_SUITE.erl
@@ -179,8 +179,8 @@ empty_generator(Config) when is_list(Config) ->
id(I) -> I.
-fc(Args, {'EXIT',{function_clause,[{?MODULE,_,Args}|_]}}) -> ok;
-fc(Args, {'EXIT',{function_clause,[{?MODULE,_,Arity}|_]}})
+fc(Args, {'EXIT',{function_clause,[{?MODULE,_,Args,_}|_]}}) -> ok;
+fc(Args, {'EXIT',{function_clause,[{?MODULE,_,Arity,_}|_]}})
when length(Args) =:= Arity ->
true = test_server:is_native(?MODULE);
fc(Args, {'EXIT',{{case_clause,ActualArgs},_}})
diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl
index c941a80e61..9b414cade6 100644
--- a/lib/compiler/test/misc_SUITE.erl
+++ b/lib/compiler/test/misc_SUITE.erl
@@ -179,7 +179,7 @@ silly_coverage(Config) when is_list(Config) ->
?line expect_error(fun() -> v3_life:module(BadKernel, []) end),
%% v3_codegen
- CodegenInput = {?MODULE,[{foo,0}],[],[{function,foo,0,[a|b],a,b}]},
+ CodegenInput = {?MODULE,[{foo,0}],[],[{function,foo,0,[a|b],a,b,[]}]},
?line expect_error(fun() -> v3_codegen:module(CodegenInput, []) end),
%% beam_block
@@ -187,7 +187,7 @@ silly_coverage(Config) when is_list(Config) ->
[{function,foo,0,2,
[{label,1},
{func_info,{atom,?MODULE},{atom,foo},0},
- {label,2}|non_proper_list],99}]},
+ {label,2}|non_proper_list]}],99},
?line expect_error(fun() -> beam_block:module(BlockInput, []) end),
%% beam_bool
diff --git a/lib/compiler/test/pmod_SUITE.erl b/lib/compiler/test/pmod_SUITE.erl
index 9a317b5762..3d02adaf52 100644
--- a/lib/compiler/test/pmod_SUITE.erl
+++ b/lib/compiler/test/pmod_SUITE.erl
@@ -96,6 +96,10 @@ basic_1(Config, Opts) ->
?line error = Prop4:bar_bar({s,a,b}),
?line error = Prop4:bar_bar([]),
+ %% Call from a fun.
+ Fun = fun(Arg) -> Prop4:bar(Arg) end,
+ ?line ok = Fun({s,0}),
+
ok.
otp_8447(Config) when is_list(Config) ->
diff --git a/lib/compiler/test/trycatch_SUITE.erl b/lib/compiler/test/trycatch_SUITE.erl
index c6e0f8d85d..760cf17225 100644
--- a/lib/compiler/test/trycatch_SUITE.erl
+++ b/lib/compiler/test/trycatch_SUITE.erl
@@ -314,19 +314,19 @@ eclectic(Conf) when is_list(Conf) ->
V = {make_ref(),3.1415926535,[[]|{}]},
?line {{value,{value,V},V},V} =
eclectic_1({foo,{value,{value,V}}}, undefined, {value,V}),
- ?line {{'EXIT',{V,[{?MODULE,foo,1}|_]}},V} =
+ ?line {{'EXIT',{V,[{?MODULE,foo,1,_}|_]}},V} =
eclectic_1({catch_foo,{error,V}}, undefined, {value,V}),
?line {{error,{exit,V},{'EXIT',V}},V} =
eclectic_1({foo,{error,{exit,V}}}, error, {value,V}),
?line {{value,{value,V},V},
- {'EXIT',{badarith,[{?MODULE,my_add,2}|_]}}} =
+ {'EXIT',{badarith,[{?MODULE,my_add,2,_}|_]}}} =
eclectic_1({foo,{value,{value,V}}}, undefined, {'add',{0,a}}),
?line {{'EXIT',V},V} =
eclectic_1({catch_foo,{exit,V}}, undefined, {throw,V}),
- ?line {{error,{'div',{1,0}},{'EXIT',{badarith,[{?MODULE,my_div,2}|_]}}},
+ ?line {{error,{'div',{1,0}},{'EXIT',{badarith,[{?MODULE,my_div,2,_}|_]}}},
{'EXIT',V}} =
eclectic_1({foo,{error,{'div',{1,0}}}}, error, {exit,V}),
- ?line {{{error,V},{'EXIT',{V,[{?MODULE,foo,1}|_]}}},
+ ?line {{{error,V},{'EXIT',{V,[{?MODULE,foo,1,_}|_]}}},
{'EXIT',V}} =
eclectic_1({catch_foo,{throw,{error,V}}}, undefined, {exit,V}),
%%
@@ -336,15 +336,15 @@ eclectic(Conf) when is_list(Conf) ->
eclectic_2({throw,{value,V}}, throw, {value,V}),
?line {{caught,{'EXIT',V}},undefined} =
eclectic_2({value,{value,V}}, undefined, {exit,V}),
- ?line {{caught,{'EXIT',{V,[{?MODULE,foo,1}|_]}}},undefined} =
+ ?line {{caught,{'EXIT',{V,[{?MODULE,foo,1,_}|_]}}},undefined} =
eclectic_2({error,{value,V}}, throw, {error,V}),
- ?line {{caught,{'EXIT',{badarg,[{erlang,abs,[V]}|_]}}},V} =
+ ?line {{caught,{'EXIT',{badarg,[{erlang,abs,[V],_}|_]}}},V} =
eclectic_2({value,{'abs',V}}, undefined, {value,V}),
- ?line {{caught,{'EXIT',{badarith,[{?MODULE,my_add,2}|_]}}},V} =
+ ?line {{caught,{'EXIT',{badarith,[{?MODULE,my_add,2,_}|_]}}},V} =
eclectic_2({exit,{'add',{0,a}}}, exit, {value,V}),
?line {{caught,{'EXIT',V}},undefined} =
eclectic_2({value,{error,V}}, undefined, {exit,V}),
- ?line {{caught,{'EXIT',{V,[{?MODULE,foo,1}|_]}}},undefined} =
+ ?line {{caught,{'EXIT',{V,[{?MODULE,foo,1,_}|_]}}},undefined} =
eclectic_2({throw,{'div',{1,0}}}, throw, {error,V}),
ok.
diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk
index 5863842f5b..04290c0a7f 100644
--- a/lib/compiler/vsn.mk
+++ b/lib/compiler/vsn.mk
@@ -1 +1 @@
-COMPILER_VSN = 4.7.4
+COMPILER_VSN = 4.7.5
diff --git a/lib/cosEvent/doc/src/Makefile b/lib/cosEvent/doc/src/Makefile
index 4b76a64b7d..db2f7e6da5 100644
--- a/lib/cosEvent/doc/src/Makefile
+++ b/lib/cosEvent/doc/src/Makefile
@@ -26,13 +26,6 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
include ../../vsn.mk
VSN=$(COSEVENT_VSN)
APPLICATION=cosEvent
-# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
# ----------------------------------------------------
# Release directory specification
@@ -98,32 +91,10 @@ EXTRA_FILES = summary.html.src \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -136,8 +107,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -153,31 +122,6 @@ clean clean_docs:
rm -f errs core *~
rm -f $(JD_HTML) $(JD_PACK)
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES) $(INTERNAL_HTML_FILES)
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ *xmls_output *xmls_errs $(LATEX_CLEAN)
-endif
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -192,8 +136,6 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
$(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
$(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
@@ -204,30 +146,4 @@ release_docs_spec: docs
$(INSTALL_DIR) $(RELEASE_PATH)/man/man3
$(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-
-endif
-endif
-
-endif
-
release_spec:
-
diff --git a/lib/cosEvent/doc/src/make.dep b/lib/cosEvent/doc/src/make.dep
deleted file mode 100644
index b8a95c2d58..0000000000
--- a/lib/cosEvent/doc/src/make.dep
+++ /dev/null
@@ -1,34 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: CosEventChannelAdmin.tex CosEventChannelAdmin_ConsumerAdmin.tex \
- CosEventChannelAdmin_EventChannel.tex CosEventChannelAdmin_ProxyPullConsumer.tex \
- CosEventChannelAdmin_ProxyPullSupplier.tex \
- CosEventChannelAdmin_ProxyPushConsumer.tex \
- CosEventChannelAdmin_ProxyPushSupplier.tex \
- CosEventChannelAdmin_SupplierAdmin.tex book.tex \
- ch_contents.tex ch_event_service.tex ch_introduction.tex \
- cosEventApp.tex part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-CosEventChannelAdmin.tex: ../../src/CosEventChannelAdmin.idl
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: e_s_components.ps e_s_models.ps
-
diff --git a/lib/cosEvent/src/Makefile b/lib/cosEvent/src/Makefile
index a62d47ce74..736b95538a 100644
--- a/lib/cosEvent/src/Makefile
+++ b/lib/cosEvent/src/Makefile
@@ -164,7 +164,7 @@ debug:
@${MAKE} TYPE=debug opt
clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET)
+ rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET) IDL-GENERATED
rm -f errs core *~
$(APP_TARGET): $(APP_SRC)
@@ -177,16 +177,18 @@ docs:
# ----------------------------------------------------
# Special Build Targets
# ----------------------------------------------------
-$(GEN_ERL_FILES1) $(EXTERNAL_GEN_HRL_FILES1): CosEventChannelAdmin.idl
+
+IDL-GENERATED: CosEventChannelAdmin.idl cosEventApp.idl CosEventComm.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosEventChannelAdmin.cfg"}' CosEventChannelAdmin.idl
mv $(GEN_HRL_FILES1) $(EXTERNAL_INC_PATH)
-
-$(GEN_ERL_FILES2) $(GEN_HRL_FILES2): cosEventApp.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"cosEventApp.cfg"}' cosEventApp.idl
-
-$(GEN_ERL_FILES3) $(EXTERNAL_GEN_HRL_FILES3): CosEventComm.idl
erlc $(ERL_IDL_FLAGS) CosEventComm.idl
mv $(GEN_HRL_FILES3) $(EXTERNAL_INC_PATH)
+ >IDL-GENERATED
+
+$(GEN_FILES): IDL-GENERATED
+
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Target
diff --git a/lib/cosEvent/test/Makefile b/lib/cosEvent/test/Makefile
index c59c7ee315..c3f07c156f 100644
--- a/lib/cosEvent/test/Makefile
+++ b/lib/cosEvent/test/Makefile
@@ -121,17 +121,13 @@ docs:
# Special Targets
# ----------------------------------------------------
-#
-# Each IDL file produces many target files so no pattern
-# rule can be used.
-#
-TGT_COS = \
- $(GEN_HRL_COS:%=$(IDLOUTDIR)/%) \
- $(GEN_MOD_COS:%=$(IDLOUTDIR)/%.erl)
+IDL-GENERATED: event_test_server.idl
+ erlc $(ERL_IDL_FLAGS) -o$(IDLOUTDIR) event_test_server.idl
+ >IDL-GENERATED
+$(GEN_FILES): IDL-GENERATED
-$(TGT_COS): event_test_server.idl
- erlc $(ERL_IDL_FLAGS) -o$(IDLOUTDIR) event_test_server.idl
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Targets
diff --git a/lib/cosEventDomain/doc/src/Makefile b/lib/cosEventDomain/doc/src/Makefile
index 6a0d3c353a..b2cdef278a 100644
--- a/lib/cosEventDomain/doc/src/Makefile
+++ b/lib/cosEventDomain/doc/src/Makefile
@@ -28,14 +28,6 @@ VSN=$(COSEVENTDOMAIN_VSN)
APPLICATION=cosEventDomain
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -93,33 +85,10 @@ EXTRA_FILES = summary.html.src \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -132,8 +101,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -149,32 +116,6 @@ clean clean_docs:
rm -f errs core *~
rm -f $(JD_HTML) $(JD_PACK)
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES) $(INTERNAL_HTML_FILES)
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ *xmls_output *xmls_errs $(LATEX_CLEAN)
-
-endif
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -189,9 +130,6 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-
-ifdef DOCSUPPORT
-
release_docs_spec: docs
$(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
$(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
@@ -201,30 +139,5 @@ release_docs_spec: docs
$(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
$(INSTALL_DIR) $(RELEASE_PATH)/man/man3
$(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-
-endif
-endif
-
-endif
release_spec:
-
diff --git a/lib/cosEventDomain/doc/src/make.dep b/lib/cosEventDomain/doc/src/make.dep
deleted file mode 100644
index 2f3f1ae53d..0000000000
--- a/lib/cosEventDomain/doc/src/make.dep
+++ /dev/null
@@ -1,23 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: CosEventDomainAdmin.tex CosEventDomainAdmin_EventDomain.tex \
- CosEventDomainAdmin_EventDomainFactory.tex \
- book.tex ch_QoS.tex ch_contents.tex ch_event_domain_service.tex \
- ch_introduction.tex cosEventDomainApp.tex \
- part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/cosEventDomain/src/Makefile b/lib/cosEventDomain/src/Makefile
index 56a67cd225..5af790c760 100644
--- a/lib/cosEventDomain/src/Makefile
+++ b/lib/cosEventDomain/src/Makefile
@@ -137,7 +137,7 @@ debug:
@${MAKE} TYPE=debug opt
clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET)
+ rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET) IDL-GENERATED
rm -f errs core *~
$(APP_TARGET): $(APP_SRC)
@@ -150,9 +150,14 @@ docs:
# ----------------------------------------------------
# Special Build Targets
# ----------------------------------------------------
-$(GEN_ERL_FILES) $(EXTERNAL_GEN_HRL_FILES): CosEventDomainAdmin.idl
+IDL-GENERATED: CosEventDomainAdmin.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosEventDomainAdmin.cfg"}' CosEventDomainAdmin.idl
mv $(GEN_HRL_FILES) $(EXTERNAL_INC_PATH)
+ >IDL-GENERATED
+
+$(GEN_FILES): IDL-GENERATED
+
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Target
diff --git a/lib/cosFileTransfer/doc/src/CosFileTransfer_FileTransferSession.xml b/lib/cosFileTransfer/doc/src/CosFileTransfer_FileTransferSession.xml
index 5ac2c61c92..918f0bf9f7 100644
--- a/lib/cosFileTransfer/doc/src/CosFileTransfer_FileTransferSession.xml
+++ b/lib/cosFileTransfer/doc/src/CosFileTransfer_FileTransferSession.xml
@@ -159,7 +159,7 @@
</func>
<func>
<name>insert(FTS, SourceFile, DestinationFile, Offset) -> Return</name>
- <fsummary>Insert the <c>SourceFile</c>into the <c>DestinationFile</c><c>Offset</c>bytes from the start of the file</fsummary>
+ <fsummary>Insert the <c>SourceFile</c>into the <c>DestinationFile</c> <c>Offset</c>bytes from the start of the file</fsummary>
<type>
<v>FTS = SourceFile = DestinationFile = #objref</v>
<v>Offset = long()</v>
@@ -168,7 +168,7 @@
<desc>
<p>This operation behaves almost like the <c>append/3</c> operation. The
difference is that the <c>SourceFile</c> will be inserted into the
- <c>DestinationFile</c><c>Offset</c> bytes from the start of the file.</p>
+ <c>DestinationFile</c> <c>Offset</c> bytes from the start of the file.</p>
<p>Currently, it is not possible to use this operation when the target
object represents FTP.</p>
</desc>
diff --git a/lib/cosFileTransfer/doc/src/Makefile b/lib/cosFileTransfer/doc/src/Makefile
index 2286db43ff..e62738daba 100644
--- a/lib/cosFileTransfer/doc/src/Makefile
+++ b/lib/cosFileTransfer/doc/src/Makefile
@@ -26,14 +26,6 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
include ../../vsn.mk
VSN=$(COSFILETRANSFER_VSN)
APPLICATION=cosFileTransfer
-# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
# ----------------------------------------------------
# Release directory specification
@@ -97,33 +89,10 @@ EXTRA_FILES = summary.html.src \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-
-TOP_PS_FILE = $(APPLICATION)-$-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -136,8 +105,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -152,32 +119,6 @@ clean clean_docs:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES) $(INTERNAL_HTML_FILES)
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ *xmls_output *xmls_errs $(LATEX_CLEAN)
-
-endif
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -192,9 +133,6 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-
-ifdef DOCSUPPORT
-
release_docs_spec: docs
$(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
$(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
@@ -204,30 +142,5 @@ release_docs_spec: docs
$(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
$(INSTALL_DIR) $(RELEASE_PATH)/man/man3
$(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-
-endif
-endif
-
-endif
release_spec:
-
diff --git a/lib/cosFileTransfer/doc/src/make.dep b/lib/cosFileTransfer/doc/src/make.dep
deleted file mode 100644
index 3be0c185c3..0000000000
--- a/lib/cosFileTransfer/doc/src/make.dep
+++ /dev/null
@@ -1,30 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: CosFileTransfer_Directory.tex CosFileTransfer_File.tex \
- CosFileTransfer_FileIterator.tex CosFileTransfer_FileTransferSession.tex \
- CosFileTransfer_VirtualFileSystem.tex book.tex \
- ch_contents.tex ch_example.tex ch_install.tex \
- ch_introduction.tex ch_system.tex cosFileTransferApp.tex \
- part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: CosFileTransfer.ps
-
diff --git a/lib/cosFileTransfer/doc/src/notes.xml b/lib/cosFileTransfer/doc/src/notes.xml
index 53c207db2f..c7a4fd4504 100644
--- a/lib/cosFileTransfer/doc/src/notes.xml
+++ b/lib/cosFileTransfer/doc/src/notes.xml
@@ -30,7 +30,21 @@
<file>notes.xml</file>
</header>
- <section>
+ <section><title>cosFileTransfer 1.1.12</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> XML files have been corrected. </p>
+ <p>
+ Own Id: OTP-9550 Aux Id: OTP-9541 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section>
<title>cosFileTransfer 1.1.11</title>
<section>
diff --git a/lib/cosFileTransfer/src/CosFileTransfer_FileTransferSession_impl.erl b/lib/cosFileTransfer/src/CosFileTransfer_FileTransferSession_impl.erl
index e222c5b92b..b7643fb30d 100644
--- a/lib/cosFileTransfer/src/CosFileTransfer_FileTransferSession_impl.erl
+++ b/lib/cosFileTransfer/src/CosFileTransfer_FileTransferSession_impl.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -792,7 +792,7 @@ target_FTS_operation(State, _SrcFile, DestFile, Op, Offset) ->
%% Delete the temporary local copy.
delete_tmp_file(TempName,
"Transfer completed but failed to remove temporary local copy."),
- %% Completed the transfer succesfully.
+ %% Completed the transfer successfully.
{reply, ok, State};
{error, epath} ->
delete_tmp_file(TempName,
diff --git a/lib/cosFileTransfer/src/Makefile b/lib/cosFileTransfer/src/Makefile
index 773ed7f6b7..b811ef1106 100644
--- a/lib/cosFileTransfer/src/Makefile
+++ b/lib/cosFileTransfer/src/Makefile
@@ -147,7 +147,7 @@ cleanb:
rm -f errs core *~
clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET)
+ rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET) IDL-GENERATED
rm -f errs core *~
$(APP_TARGET): $(APP_SRC)
@@ -161,9 +161,14 @@ docs:
# ----------------------------------------------------
# Special Build Targets
# ----------------------------------------------------
-$(GEN_ERL_FILES) $(GEN_HRL_FILES): CosFileTransfer.idl
+IDL-GENERATED: CosFileTransfer.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosFileTransfer.cfg"}' CosFileTransfer.idl
mv $(LOCAL_HRL_FILES) $(EXTERNAL_INC_PATH)
+ >IDL-GENERATED
+
+$(GEN_FILES): IDL-GENERATED
+
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Target
diff --git a/lib/cosFileTransfer/vsn.mk b/lib/cosFileTransfer/vsn.mk
index 9d68ab2720..fe0226e3b3 100644
--- a/lib/cosFileTransfer/vsn.mk
+++ b/lib/cosFileTransfer/vsn.mk
@@ -1 +1 @@
-COSFILETRANSFER_VSN = 1.1.11
+COSFILETRANSFER_VSN = 1.1.12
diff --git a/lib/cosNotification/doc/src/Makefile b/lib/cosNotification/doc/src/Makefile
index bfdd2f1f8c..2ead9aba7b 100644
--- a/lib/cosNotification/doc/src/Makefile
+++ b/lib/cosNotification/doc/src/Makefile
@@ -28,14 +28,6 @@ VSN=$(COSNOTIFICATION_VSN)
APPLICATION=cosNotification
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -122,33 +114,10 @@ EXTRA_FILES = summary.html.src \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -161,8 +130,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -177,32 +144,6 @@ clean clean_docs:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES) $(INTERNAL_HTML_FILES)
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ *xmls_output *xmls_errs $(LATEX_CLEAN)
-
-endif
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -217,8 +158,6 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
$(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
$(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
@@ -228,30 +167,5 @@ release_docs_spec: docs
$(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
$(INSTALL_DIR) $(RELEASE_PATH)/man/man3
$(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-
-endif
-endif
-
-endif
release_spec:
-
diff --git a/lib/cosNotification/doc/src/make.dep b/lib/cosNotification/doc/src/make.dep
deleted file mode 100644
index 031a2b3e98..0000000000
--- a/lib/cosNotification/doc/src/make.dep
+++ /dev/null
@@ -1,48 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: CosNotification.tex CosNotification_AdminPropertiesAdmin.tex \
- CosNotification_QoSAdmin.tex CosNotifyChannelAdmin_ConsumerAdmin.tex \
- CosNotifyChannelAdmin_EventChannel.tex CosNotifyChannelAdmin_EventChannelFactory.tex \
- CosNotifyChannelAdmin_ProxyConsumer.tex CosNotifyChannelAdmin_ProxyPullConsumer.tex \
- CosNotifyChannelAdmin_ProxyPullSupplier.tex \
- CosNotifyChannelAdmin_ProxyPushConsumer.tex \
- CosNotifyChannelAdmin_ProxyPushSupplier.tex \
- CosNotifyChannelAdmin_ProxySupplier.tex CosNotifyChannelAdmin_SequenceProxyPullConsumer.tex \
- CosNotifyChannelAdmin_SequenceProxyPullSupplier.tex \
- CosNotifyChannelAdmin_SequenceProxyPushConsumer.tex \
- CosNotifyChannelAdmin_SequenceProxyPushSupplier.tex \
- CosNotifyChannelAdmin_StructuredProxyPullConsumer.tex \
- CosNotifyChannelAdmin_StructuredProxyPullSupplier.tex \
- CosNotifyChannelAdmin_StructuredProxyPushConsumer.tex \
- CosNotifyChannelAdmin_StructuredProxyPushSupplier.tex \
- CosNotifyChannelAdmin_SupplierAdmin.tex CosNotifyComm_NotifyPublish.tex \
- CosNotifyComm_NotifySubscribe.tex CosNotifyFilter_Filter.tex \
- CosNotifyFilter_FilterAdmin.tex CosNotifyFilter_FilterFactory.tex \
- CosNotifyFilter_MappingFilter.tex book.tex \
- ch_BNF.tex ch_QoS.tex ch_contents.tex ch_example.tex \
- ch_install.tex ch_introduction.tex ch_system.tex \
- cosNotificationApp.tex part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: eventstructure.ps
-
-book.dvi: notificationFlow.ps
-
diff --git a/lib/cosNotification/src/Makefile b/lib/cosNotification/src/Makefile
index 637c633e52..be52d1a06f 100644
--- a/lib/cosNotification/src/Makefile
+++ b/lib/cosNotification/src/Makefile
@@ -242,20 +242,26 @@ GEN_OE_EVENTCOMM_HRL_FILES = \
oe_CosNotificationComm.hrl \
oe_CosNotificationComm_Event.hrl
-GEN_ERL_FILES = \
+IDL_GEN_ERL_FILES = \
$(GEN_NOTIFICATION_ERL_FILES) \
$(GEN_OE_EVENTCOMM_ERL_FILES) \
$(GEN_NOTIFYCOMM_ERL_FILES) \
$(GEN_NOTIFYFILTER_ERL_FILES) \
- $(GEN_CHANNELADMIN_ERL_FILES) \
- $(GEN_YECC_ERL_FILES)
+ $(GEN_CHANNELADMIN_ERL_FILES)
-GEN_HRL_FILES = \
+IDL_GEN_HRL_FILES = \
$(EXTERNAL_GEN_NOTIFICATION_HRL_FILES) \
$(GEN_OE_EVENTCOMM_HRL_FILES) \
$(EXTERNAL_GEN_NOTIFYCOMM_HRL_FILES) \
$(EXTERNAL_GEN_NOTIFYFILTER_HRL_FILES) \
- $(EXTERNAL_GEN_CHANNELADMIN_HRL_FILES) \
+ $(EXTERNAL_GEN_CHANNELADMIN_HRL_FILES)
+
+GEN_ERL_FILES = \
+ $(IDL_GEN_ERL_FILES) \
+ $(GEN_YECC_ERL_FILES)
+
+GEN_HRL_FILES = \
+ $(IDL_GEN_HRL_FILES) \
$(GEN_YECC_HRL_FILES)
@@ -322,7 +328,7 @@ cleanb:
rm -f errs core *~
clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET)
+ rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET) IDL-GENERATED
rm -f errs core *~
$(APP_TARGET): $(APP_SRC)
@@ -336,20 +342,23 @@ docs:
# ----------------------------------------------------
# Special Build Targets
# ----------------------------------------------------
-$(GEN_NOTIFICATION_ERL_FILES) $(EXTERNAL_GEN_NOTIFICATION_HRL_FILES): CosNotification.idl
+IDL-GENERATED: CosNotification.idl CosNotifyChannelAdmin.idl \
+ CosNotifyFilter.idl cosNotificationAppComm.idl CosNotifyComm.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosNotification.cfg"}' CosNotification.idl
mv $(GEN_NOTIFICATION_HRL_FILES) $(EXTERNAL_INC_PATH)
-$(GEN_CHANNELADMIN_ERL_FILES) $(EXTERNAL_GEN_CHANNELADMIN_HRL_FILES): CosNotifyChannelAdmin.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosNotifyChannelAdmin.cfg"}' CosNotifyChannelAdmin.idl
mv $(GEN_CHANNELADMIN_HRL_FILES) $(EXTERNAL_INC_PATH)
-$(GEN_NOTIFYFILTER_ERL_FILES) $(EXTERNAL_GEN_NOTIFYFILTER_HRL_FILES): CosNotifyFilter.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosNotifyFilter.cfg"}' CosNotifyFilter.idl
mv $(GEN_NOTIFYFILTER_HRL_FILES) $(EXTERNAL_INC_PATH)
-$(GEN_OE_EVENTCOMM_ERL_FILES) $(GEN_OE_EVENTCOMM_HRL_FILES): cosNotificationAppComm.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"cosNotificationComm.cfg"}' cosNotificationAppComm.idl
-$(GEN_NOTIFYCOMM_ERL_FILES) $(EXTERNAL_GEN_NOTIFYCOMM_HRL_FILES): CosNotifyComm.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosNotifyComm.cfg"}' CosNotifyComm.idl
mv $(GEN_NOTIFYCOMM_HRL_FILES) $(EXTERNAL_INC_PATH)
+ >IDL-GENERATED
+
+$(IDL_GEN_ERL_FILES) $(IDL_GEN_HRL_FILES): IDL-GENERATED
+
+$(TARGET_FILES): IDL-GENERATED
+
$(GEN_YECC_ERL_FILES) $(GEN_YECC_HRL_FILES): cosNotification_Grammar.yrl
# ----------------------------------------------------
diff --git a/lib/cosNotification/test/Makefile b/lib/cosNotification/test/Makefile
index 43f73addae..f509370430 100644
--- a/lib/cosNotification/test/Makefile
+++ b/lib/cosNotification/test/Makefile
@@ -161,13 +161,14 @@ docs:
# Special Targets
# ----------------------------------------------------
-TGT_TEST = \
- $(GEN_HRL_FILES:%=$(IDLOUTDIR)/%) \
- $(GEN_MODULES:%=$(IDLOUTDIR)/%.erl)
-
-$(TGT_TEST): notify_test_server.idl
+IDL-GENERATED: notify_test_server.idl
erlc $(ERL_COMPILE_FLAGS) -o$(IDLOUTDIR) \
+'{cfgfile,"notify_test_server.cfg"}' notify_test_server.idl
+ >IDL-GENERATED
+
+$(GEN_FILES): IDL-GENERATED
+
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Targets
diff --git a/lib/cosProperty/doc/src/Makefile b/lib/cosProperty/doc/src/Makefile
index baf995d35e..d4c89ff44f 100644
--- a/lib/cosProperty/doc/src/Makefile
+++ b/lib/cosProperty/doc/src/Makefile
@@ -28,14 +28,6 @@ VSN=$(COSPROPERTY_VSN)
APPLICATION=cosProperty
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -99,35 +91,10 @@ EXTRA_FILES = summary.html.src \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
MAN6_FILES = $(XML_REF6_FILES:%.xml=$(MAN6DIR)/%.6)
-
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_REF6_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -140,8 +107,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -156,42 +121,6 @@ clean clean_docs:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES) $(INTERNAL_HTML_FILES)
-
-tex_users_guide: $(TEX_FILES_USERS_GUIDE)
-tex_ref_man: $(TEX_FILES_REF_MAN)
-tex: tex_users_guide tex_ref_man $(TEX_FILES_BOOK)
-
-$(DOCDIR)/latexlog: $(BOOK_FILES:%.xml=%.dvi)
- -fgrep -i "latex warning" $(BOOK_FILES:%.xml=%.log) >$(DOCDIR)/latexlog
-
-clean_tex:
- -rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
-
-clean:
- rm -f ../html/* $(MAN3_FILES) $(MAN6_FILES) $(TEX_FILES_USERS_GUIDE)
- rm -f *xmls_output *xmls_errs
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ $(LATEX_CLEAN)
-
-endif
-
man: $(MAN3_FILES) $(MAN6_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -206,8 +135,6 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
$(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
$(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
@@ -217,30 +144,5 @@ release_docs_spec: docs
$(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
$(INSTALL_DIR) $(RELEASE_PATH)/man/man3
$(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-
-endif
-endif
-
-endif
release_spec:
-
diff --git a/lib/cosProperty/doc/src/make.dep b/lib/cosProperty/doc/src/make.dep
deleted file mode 100644
index 383af54244..0000000000
--- a/lib/cosProperty/doc/src/make.dep
+++ /dev/null
@@ -1,26 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: CosPropertyService_PropertiesIterator.tex \
- CosPropertyService_PropertyNamesIterator.tex \
- CosPropertyService_PropertySet.tex CosPropertyService_PropertySetDef.tex \
- CosPropertyService_PropertySetDefFactory.tex \
- CosPropertyService_PropertySetFactory.tex \
- book.tex ch_contents.tex ch_example.tex ch_install.tex \
- ch_introduction.tex cosProperty.tex part.tex \
- ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/cosProperty/src/Makefile b/lib/cosProperty/src/Makefile
index 1d2119dfb3..b72019f37d 100644
--- a/lib/cosProperty/src/Makefile
+++ b/lib/cosProperty/src/Makefile
@@ -147,7 +147,7 @@ cleanb:
rm -f errs core *~
clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET)
+ rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET) IDL-GENERATED
rm -f errs core *~
$(APP_TARGET): $(APP_SRC)
@@ -161,10 +161,14 @@ docs:
# ----------------------------------------------------
# Special Build Targets
# ----------------------------------------------------
-$(GEN_ERL_FILES) $(GEN_HRL_FILES): CosProperty.idl
+IDL-GENERATED: CosProperty.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosProperty.cfg"}' CosProperty.idl
mv $(LOCAL_HRL_FILES) $(EXTERNAL_INC_PATH)
+ >IDL-GENERATED
+$(GEN_FILES): IDL-GENERATED
+
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Target
diff --git a/lib/cosTime/doc/src/Makefile b/lib/cosTime/doc/src/Makefile
index 83abc5e7c2..af418896aa 100644
--- a/lib/cosTime/doc/src/Makefile
+++ b/lib/cosTime/doc/src/Makefile
@@ -28,14 +28,6 @@ VSN=$(COSTIME_VSN)
APPLICATION=cosTime
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -93,33 +85,10 @@ EXTRA_FILES = summary.html.src \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -132,8 +101,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -148,32 +115,6 @@ clean clean_docs:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES) $(INTERNAL_HTML_FILES)
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ *xmls_output *xmls_errs $(LATEX_CLEAN)
-
-endif
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -188,8 +129,6 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
$(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
$(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
@@ -199,30 +138,5 @@ release_docs_spec: docs
$(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
$(INSTALL_DIR) $(RELEASE_PATH)/man/man3
$(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-
-endif
-endif
-
-endif
release_spec:
-
diff --git a/lib/cosTime/doc/src/make.dep b/lib/cosTime/doc/src/make.dep
deleted file mode 100644
index 69a584ab95..0000000000
--- a/lib/cosTime/doc/src/make.dep
+++ /dev/null
@@ -1,22 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: CosTime_TIO.tex CosTime_TimeService.tex CosTime_UTO.tex \
- CosTimerEvent_TimerEventHandler.tex CosTimerEvent_TimerEventService.tex \
- book.tex ch_contents.tex ch_example.tex ch_install.tex \
- ch_introduction.tex cosTime.tex part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/cosTime/src/Makefile b/lib/cosTime/src/Makefile
index 3b6f7bae2e..fa456249bd 100644
--- a/lib/cosTime/src/Makefile
+++ b/lib/cosTime/src/Makefile
@@ -162,7 +162,7 @@ cleanb:
rm -f errs core *~
clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET)
+ rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET) IDL-GENERATED
rm -f errs core *~
$(APP_TARGET): $(APP_SRC)
@@ -176,17 +176,18 @@ docs:
# ----------------------------------------------------
# Special Build Targets
# ----------------------------------------------------
-$(GEN_TIMEBASE_ERL_FILES) $(EXTERNAL_TIMEBASE_HRL_FILES): TimeBase.idl
+IDL-GENERATED: TimeBase.idl CosTime.idl CosTimerEvent.idl
erlc $(ERL_IDL_FLAGS) TimeBase.idl
mv $(GEN_TIMEBASE_HRL_FILES) $(EXTERNAL_INC_PATH)
-
-$(GEN_COSTIME_ERL_FILES) $(EXTERNAL_COSTIME_HRL_FILES): CosTime.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosTime.cfg"}' CosTime.idl
mv $(GEN_COSTIME_HRL_FILES) $(EXTERNAL_INC_PATH)
-
-$(GEN_COSTIMEREVENT_ERL_FILES) $(EXTERNAL_COSTIMEREVENT_HRL_FILES): CosTimerEvent.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosTimerEvent.cfg"}' CosTimerEvent.idl
mv $(GEN_COSTIMEREVENT_HRL_FILES) $(EXTERNAL_INC_PATH)
+ >IDL-GENERATED
+
+$(GEN_FILES): IDL-GENERATED
+
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Target
diff --git a/lib/cosTransactions/doc/src/Makefile b/lib/cosTransactions/doc/src/Makefile
index 1af9ed24b7..7d959cbc8f 100644
--- a/lib/cosTransactions/doc/src/Makefile
+++ b/lib/cosTransactions/doc/src/Makefile
@@ -28,14 +28,6 @@ VSN=$(COSTRANSACTIONS_VSN)
APPLICATION=cosTransactions
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -97,33 +89,10 @@ EXTRA_FILES = summary.html.src \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -136,8 +105,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -152,32 +119,6 @@ clean clean_docs:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES) $(INTERNAL_HTML_FILES)
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ *xmls_output *xmls_errs $(LATEX_CLEAN)
-
-endif
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -192,8 +133,6 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
$(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
$(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
@@ -203,30 +142,5 @@ release_docs_spec: docs
$(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
$(INSTALL_DIR) $(RELEASE_PATH)/man/man3
$(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-
-endif
-endif
-
-endif
release_spec:
-
diff --git a/lib/cosTransactions/doc/src/make.dep b/lib/cosTransactions/doc/src/make.dep
deleted file mode 100644
index bd45aea286..0000000000
--- a/lib/cosTransactions/doc/src/make.dep
+++ /dev/null
@@ -1,27 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: CosTransactions_Control.tex CosTransactions_Coordinator.tex \
- CosTransactions_RecoveryCoordinator.tex CosTransactions_Resource.tex \
- CosTransactions_SubtransactionAwareResource.tex \
- CosTransactions_Terminator.tex CosTransactions_TransactionFactory.tex \
- book.tex ch_contents.tex ch_example.tex ch_install.tex \
- ch_introduction.tex ch_skeletons.tex cosTransactions.tex \
- part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-ch_example.tex: ../../../../system/doc/definitions/term.defs
-
diff --git a/lib/cosTransactions/src/Makefile b/lib/cosTransactions/src/Makefile
index 7e10ec175b..e7d4b0b080 100644
--- a/lib/cosTransactions/src/Makefile
+++ b/lib/cosTransactions/src/Makefile
@@ -141,7 +141,7 @@ debug:
@${MAKE} TYPE=debug
clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET)
+ rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET) IDL-GENERATED
rm -f errs core *~
$(APP_TARGET): $(APP_SRC)
@@ -155,9 +155,14 @@ docs:
# ----------------------------------------------------
# Special Build Targets
# ----------------------------------------------------
-$(GEN_ERL_FILES) $(EXTERNAL_GEN_HRL_FILES): CosTransactions.idl
+IDL-GENERATED: CosTransactions.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosTransactions.cfg"}' CosTransactions.idl
mv $(GEN_HRL_FILES) $(EXTERNAL_INC_PATH)
+ >IDL-GENERATED
+
+$(GEN_FILES): IDL-GENERATED
+
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Target
diff --git a/lib/cosTransactions/test/Makefile b/lib/cosTransactions/test/Makefile
index 44c90e8f84..0bc8c007da 100644
--- a/lib/cosTransactions/test/Makefile
+++ b/lib/cosTransactions/test/Makefile
@@ -121,13 +121,14 @@ docs:
# Special Targets
# ----------------------------------------------------
-TGT_TEST = \
- $(GEN_HRL_FILES:%=$(IDLOUTDIR)/%) \
- $(GEN_MODULES:%=$(IDLOUTDIR)/%.erl)
-
-$(TGT_TEST): etrap_test.idl
+IDL-GENERATED: etrap_test.idl
erlc $(ERL_IDL_FLAGS) -o$(IDLOUTDIR) \
+'{cfgfile,"etrap_test.cfg"}' etrap_test.idl
+ >IDL-GENERATED
+
+$(GEN_FILES): IDL-GENERATED
+
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Targets
diff --git a/lib/crypto/c_src/Makefile.in b/lib/crypto/c_src/Makefile.in
index 276c84d601..285537643e 100644
--- a/lib/crypto/c_src/Makefile.in
+++ b/lib/crypto/c_src/Makefile.in
@@ -41,6 +41,7 @@ CFLAGS = $(DED_CFLAGS)
SSL_LIBDIR = @SSL_LIBDIR@
SSL_INCLUDE = @SSL_INCLUDE@
SSL_CRYPTO_LIBNAME = @SSL_CRYPTO_LIBNAME@
+SSL_SSL_LIBNAME = @SSL_SSL_LIBNAME@
INCLUDES = $(SSL_INCLUDE) $(DED_INCLUDES)
@@ -84,7 +85,7 @@ DYNAMIC_CRYPTO_LIB=@SSL_DYNAMIC_ONLY@
ifeq ($(DYNAMIC_CRYPTO_LIB),yes)
SSL_DED_LD_RUNTIME_LIBRARY_PATH = @SSL_DED_LD_RUNTIME_LIBRARY_PATH@
-CRYPTO_LINK_LIB=$(SSL_DED_LD_RUNTIME_LIBRARY_PATH) -L$(SSL_LIBDIR) -l$(SSL_CRYPTO_LIBNAME)
+CRYPTO_LINK_LIB=$(SSL_DED_LD_RUNTIME_LIBRARY_PATH) -L$(SSL_LIBDIR) -l$(SSL_CRYPTO_LIBNAME) -l$(SSL_SSL_LIBNAME)
else
SSL_DED_LD_RUNTIME_LIBRARY_PATH=
CRYPTO_LINK_LIB=$(SSL_LIBDIR)/lib$(SSL_CRYPTO_LIBNAME).a
@@ -94,13 +95,9 @@ endif
# Targets
# ----------------------------------------------------
-debug opt valgrind: $(OBJDIR) $(LIBDIR) $(NIF_LIB)
+_create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR))
-$(OBJDIR):
- -@mkdir -p $(OBJDIR)
-
-$(LIBDIR):
- -@mkdir -p $(LIBDIR)
+debug opt valgrind: $(NIF_LIB)
$(OBJDIR)/%$(TYPEMARKER).o: %.c
$(INSTALL_DIR) $(OBJDIR)
@@ -112,7 +109,7 @@ $(LIBDIR)/crypto$(TYPEMARKER).so: $(OBJS)
$(LIBDIR)/crypto$(TYPEMARKER).dll: $(OBJS)
$(INSTALL_DIR) $(LIBDIR)
- $(LD) $(LDFLAGS) -o $@ $(SSL_DED_LD_RUNTIME_LIBRARY_PATH) -L$(SSL_LIBDIR) $(OBJS) -l$(SSL_CRYPTO_LIBNAME)
+ $(LD) $(LDFLAGS) -o $@ $(SSL_DED_LD_RUNTIME_LIBRARY_PATH) -L$(SSL_LIBDIR) $(OBJS) -l$(SSL_CRYPTO_LIBNAME) -l$(SSL_SSL_LIBNAME)
clean:
ifeq ($(findstring win32,$(TARGET)), win32)
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index c781ccb302..802c1991de 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -134,8 +134,10 @@ static ERL_NIF_TERM hmac_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
static ERL_NIF_TERM hmac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM des_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM des_cfb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM des_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM des_ede3_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM des_ede3_cfb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM aes_cfb_128_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -152,7 +154,7 @@ static ERL_NIF_TERM exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_set_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM rc2_40_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM rc2_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -210,8 +212,10 @@ static ErlNifFunc nif_funcs[] = {
{"hmac_final", 1, hmac_final},
{"hmac_final_n", 2, hmac_final},
{"des_cbc_crypt", 4, des_cbc_crypt},
+ {"des_cfb_crypt", 4, des_cfb_crypt},
{"des_ecb_crypt", 3, des_ecb_crypt},
{"des_ede3_cbc_crypt", 6, des_ede3_cbc_crypt},
+ {"des_ede3_cfb_crypt", 6, des_ede3_cfb_crypt},
{"aes_cfb_128_crypt", 4, aes_cfb_128_crypt},
{"aes_ctr_encrypt", 3, aes_ctr_encrypt},
{"aes_ctr_decrypt", 3, aes_ctr_encrypt},
@@ -230,7 +234,7 @@ static ErlNifFunc nif_funcs[] = {
{"rc4_encrypt", 2, rc4_encrypt},
{"rc4_set_key", 1, rc4_set_key},
{"rc4_encrypt_with_state", 2, rc4_encrypt_with_state},
- {"rc2_40_cbc_crypt", 4, rc2_40_cbc_crypt},
+ {"rc2_cbc_crypt", 4, rc2_cbc_crypt},
{"rsa_sign_nif", 3, rsa_sign_nif},
{"dss_sign_nif", 3, dss_sign_nif},
{"rsa_public_crypt", 4, rsa_public_crypt},
@@ -693,6 +697,25 @@ static ERL_NIF_TERM des_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
return ret;
}
+static ERL_NIF_TERM des_cfb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, Ivec, Text, IsEncrypt) */
+ ErlNifBinary key, ivec, text;
+ DES_key_schedule schedule;
+ DES_cblock ivec_clone; /* writable copy */
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8
+ || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 8
+ || !enif_inspect_iolist_as_binary(env, argv[2], &text)) {
+ return enif_make_badarg(env);
+ }
+ memcpy(&ivec_clone, ivec.data, 8);
+ DES_set_key((const_DES_cblock*)key.data, &schedule);
+ DES_cfb_encrypt(text.data, enif_make_new_binary(env, text.size, &ret),
+ 8, text.size, &schedule, &ivec_clone, (argv[3] == atom_true));
+ return ret;
+}
+
static ERL_NIF_TERM des_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key, Text/Cipher, IsEncrypt) */
ErlNifBinary key, text;
@@ -735,6 +758,31 @@ static ERL_NIF_TERM des_ede3_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_T
return ret;
}
+static ERL_NIF_TERM des_ede3_cfb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key1, Key2, Key3, IVec, Text/Cipher, IsEncrypt) */
+ ErlNifBinary key1, key2, key3, ivec, text;
+ DES_key_schedule schedule1, schedule2, schedule3;
+ DES_cblock ivec_clone; /* writable copy */
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key1) || key1.size != 8
+ || !enif_inspect_iolist_as_binary(env, argv[1], &key2) || key2.size != 8
+ || !enif_inspect_iolist_as_binary(env, argv[2], &key3) || key3.size != 8
+ || !enif_inspect_binary(env, argv[3], &ivec) || ivec.size != 8
+ || !enif_inspect_iolist_as_binary(env, argv[4], &text)) {
+ return enif_make_badarg(env);
+ }
+
+ memcpy(&ivec_clone, ivec.data, 8);
+ DES_set_key((const_DES_cblock*)key1.data, &schedule1);
+ DES_set_key((const_DES_cblock*)key2.data, &schedule2);
+ DES_set_key((const_DES_cblock*)key3.data, &schedule3);
+ DES_ede3_cfb_encrypt(text.data, enif_make_new_binary(env,text.size,&ret),
+ 8, text.size, &schedule1, &schedule2, &schedule3,
+ &ivec_clone, (argv[5] == atom_true));
+ return ret;
+}
+
static ERL_NIF_TERM aes_cfb_128_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key, IVec, Data, IsEncrypt) */
ErlNifBinary key, ivec, text;
@@ -1189,30 +1237,31 @@ static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_N
return enif_make_tuple2(env,new_state,new_data);
}
-static ERL_NIF_TERM rc2_40_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static ERL_NIF_TERM rc2_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key,IVec,Data,IsEncrypt) */
ErlNifBinary key_bin, ivec_bin, data_bin;
RC2_KEY rc2_key;
ERL_NIF_TERM ret;
-
+ unsigned char iv_copy[8];
+
if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || key_bin.size != 5
+ || (key_bin.size != 5 && key_bin.size != 8 && key_bin.size != 16)
|| !enif_inspect_binary(env, argv[1], &ivec_bin)
|| ivec_bin.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)) {
-
+ || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)
+ || data_bin.size % 8 != 0) {
return enif_make_badarg(env);
}
-
- RC2_set_key(&rc2_key, 5, key_bin.data, 40);
+
+ RC2_set_key(&rc2_key, key_bin.size, key_bin.data, key_bin.size*8);
+ memcpy(iv_copy, ivec_bin.data, 8);
RC2_cbc_encrypt(data_bin.data,
- enif_make_new_binary(env, data_bin.size, &ret),
+ enif_make_new_binary(env, data_bin.size, &ret),
data_bin.size, &rc2_key,
- ivec_bin.data,
+ iv_copy,
(argv[3] == atom_true));
-
return ret;
-}
+}
static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Type,Data,Key=[E,N,D]) */
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 179ba4498c..48243fd693 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd">
<erlref>
@@ -334,20 +334,22 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
</func>
<func>
<name>sha_mac(Key, Data) -> Mac</name>
+ <name>sha_mac(Key, Data, MacLength) -> Mac</name>
<fsummary>Compute an <c>MD5 MAC</c>message authentification code</fsummary>
<type>
<v>Key = Data = iolist() | binary()</v>
<v>Mac = binary()</v>
+ <v>MacLenength = integer() =&lt; 20 </v>
</type>
<desc>
<p>Computes an <c>SHA MAC</c> message authentification code
- from <c>Key</c> and <c>Data</c>, where the length of the Mac
+ from <c>Key</c> and <c>Data</c>, where the default length of the Mac
is 160 bits (20 bytes).</p>
</desc>
</func>
<func>
<name>sha_mac_96(Key, Data) -> Mac</name>
- <fsummary>Compute an <c>MD5 MAC</c>message authentification code</fsummary>
+ <fsummary>Compute an <c>SHA MAC</c>message authentification code</fsummary>
<type>
<v>Key = Data = iolist() | binary()</v>
<v>Mac = binary()</v>
@@ -404,6 +406,51 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
</desc>
</func>
<func>
+ <name>des_cfb_encrypt(Key, IVec, Text) -> Cipher</name>
+ <fsummary>Encrypt <c>Text</c>according to DES in CFB mode</fsummary>
+ <type>
+ <v>Key = Text = iolist() | binary()</v>
+ <v>IVec = Cipher = binary()</v>
+ </type>
+ <desc>
+ <p>Encrypts <c>Text</c> according to DES in 8-bit CFB
+ mode. <c>Key</c> is the DES key, and <c>IVec</c> is an
+ arbitrary initializing vector. The lengths of <c>Key</c> and
+ <c>IVec</c> must be 64 bits (8 bytes).</p>
+ </desc>
+ </func>
+ <func>
+ <name>des_cfb_decrypt(Key, IVec, Cipher) -> Text</name>
+ <fsummary>Decrypt <c>Cipher</c>according to DES in CFB mode</fsummary>
+ <type>
+ <v>Key = Cipher = iolist() | binary()</v>
+ <v>IVec = Text = binary()</v>
+ </type>
+ <desc>
+ <p>Decrypts <c>Cipher</c> according to DES in 8-bit CFB mode.
+ <c>Key</c> is the DES key, and <c>IVec</c> is an arbitrary
+ initializing vector. <c>Key</c> and <c>IVec</c> must have
+ the same values as those used when encrypting. The lengths of
+ <c>Key</c> and <c>IVec</c> must be 64 bits (8 bytes).</p>
+ </desc>
+ </func>
+ <func>
+ <name>des_cfb_ivec(IVec, Data) -> NextIVec</name>
+ <fsummary>Get <c>IVec</c> to be used in next iteration of
+ <c>des_cfb_[ecrypt|decrypt]</c></fsummary>
+ <type>
+ <v>IVec = iolist() | binary()</v>
+ <v>Data = iolist() | binary()</v>
+ <v>NextIVec = binary()</v>
+ </type>
+ <desc>
+ <p>Returns the <c>IVec</c> to be used in a next iteration of
+ <c>des_cfb_[encrypt|decrypt]</c>. <c>IVec</c> is the vector
+ used in the previous iteration step. <c>Data</c> is the encrypted
+ data from the previous iteration step.</p>
+ </desc>
+ </func>
+ <func>
<name>des3_cbc_encrypt(Key1, Key2, Key3, IVec, Text) -> Cipher</name>
<fsummary>Encrypt <c>Text</c>according to DES3 in CBC mode</fsummary>
<type>
@@ -421,7 +468,7 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
</func>
<func>
<name>des3_cbc_decrypt(Key1, Key2, Key3, IVec, Cipher) -> Text</name>
- <fsummary>Decrypt <c>Cipher</c>according to DES in CBC mode</fsummary>
+ <fsummary>Decrypt <c>Cipher</c>according to DES3 in CBC mode</fsummary>
<type>
<v>Key1 = Key2 = Key3 = Cipher = iolist() | binary()</v>
<v>IVec = Text = binary()</v>
@@ -437,6 +484,38 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
<c>Key3</c>, and <c>IVec</c> must be 64 bits (8 bytes).</p>
</desc>
</func>
+ <func>
+ <name>des3_cfb_encrypt(Key1, Key2, Key3, IVec, Text) -> Cipher</name>
+ <fsummary>Encrypt <c>Text</c>according to DES3 in CFB mode</fsummary>
+ <type>
+ <v>Key1 =Key2 = Key3 Text = iolist() | binary()</v>
+ <v>IVec = Cipher = binary()</v>
+ </type>
+ <desc>
+ <p>Encrypts <c>Text</c> according to DES3 in 8-bit CFB
+ mode. <c>Key1</c>, <c>Key2</c>, <c>Key3</c>, are the DES
+ keys, and <c>IVec</c> is an arbitrary initializing
+ vector. The lengths of each of <c>Key1</c>, <c>Key2</c>,
+ <c>Key3</c> and <c>IVec</c> must be 64 bits (8 bytes).</p>
+ </desc>
+ </func>
+ <func>
+ <name>des3_cfb_decrypt(Key1, Key2, Key3, IVec, Cipher) -> Text</name>
+ <fsummary>Decrypt <c>Cipher</c>according to DES3 in CFB mode</fsummary>
+ <type>
+ <v>Key1 = Key2 = Key3 = Cipher = iolist() | binary()</v>
+ <v>IVec = Text = binary()</v>
+ </type>
+ <desc>
+ <p>Decrypts <c>Cipher</c> according to DES3 in 8-bit CFB mode.
+ <c>Key1</c>, <c>Key2</c>, <c>Key3</c> are the DES key, and
+ <c>IVec</c> is an arbitrary initializing vector.
+ <c>Key1</c>, <c>Key2</c>, <c>Key3</c> and <c>IVec</c> must
+ and <c>IVec</c> must have the same values as those used when
+ encrypting. The lengths of <c>Key1</c>, <c>Key2</c>,
+ <c>Key3</c>, and <c>IVec</c> must be 64 bits (8 bytes).</p>
+ </desc>
+ </func>
<func>
<name>des_ecb_encrypt(Key, Text) -> Cipher</name>
@@ -744,7 +823,7 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
<p>Generate a random number <c><![CDATA[N, Lo =< N < Hi.]]></c> Uses the
<c>crypto</c> library pseudo-random number generator. The
arguments (and result) can be either erlang integers or binary
- multi-precision integers.</p>
+ multi-precision integers. <c>Hi</c> must be larger than <c>Lo</c>.</p>
</desc>
</func>
<func>
@@ -969,6 +1048,30 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
</func>
<func>
+ <name>rc2_cbc_encrypt(Key, IVec, Text) -> Cipher</name>
+ <fsummary>Encrypt <c>Text</c>according to RC2 in CBC mode</fsummary>
+ <type>
+ <v>Key = Text = iolist() | binary()</v>
+ <v>Ivec = Cipher = binary()</v>
+ </type>
+ <desc>
+ <p>Encrypts <c>Text</c> according to RC2 in CBC mode.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>rc2_cbc_decrypt(Key, IVec, Cipher) -> Text</name>
+ <fsummary>Decrypts <c>Cipher</c>according to RC2 in CBC mode</fsummary>
+ <type>
+ <v>Key = Text = iolist() | binary()</v>
+ <v>Ivec = Cipher = binary()</v>
+ </type>
+ <desc>
+ <p>Decrypts <c>Cipher</c> according to RC2 in CBC mode.</p>
+ </desc>
+ </func>
+
+ <func>
<name>rc4_encrypt(Key, Data) -> Result</name>
<fsummary>Encrypt data using RC4</fsummary>
<type>
diff --git a/lib/crypto/doc/src/make.dep b/lib/crypto/doc/src/make.dep
deleted file mode 100644
index 73b090bbb6..0000000000
--- a/lib/crypto/doc/src/make.dep
+++ /dev/null
@@ -1,20 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex crypto.tex crypto_app.tex licenses.tex \
- ref_man.tex usersguide.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml
index a5434ebd68..763f79e02d 100644
--- a/lib/crypto/doc/src/notes.xml
+++ b/lib/crypto/doc/src/notes.xml
@@ -30,6 +30,31 @@
</header>
<p>This document describes the changes made to the Crypto application.</p>
+<section><title>Crypto 2.0.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ <c>crypto:rand_uniform</c> works correctly for negative
+ integers. Fails with <c>badarg</c> exception for invalid
+ ranges (when <c>Hi =&lt; Lo</c>) instead of returning
+ incorrect output.</p>
+ <p>
+ Own Id: OTP-9526</p>
+ </item>
+ <item>
+ <p>
+ Fix win32 OpenSSL static linking (Thanks to Dave
+ Cottlehuber)</p>
+ <p>
+ Own Id: OTP-9532</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Crypto 2.0.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index c35dfcebab..0714cb686d 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -27,11 +27,13 @@
-export([sha/1, sha_init/0, sha_update/2, sha_final/1]).
%-export([sha256/1, sha256_init/0, sha256_update/2, sha256_final/1]).
%-export([sha512/1, sha512_init/0, sha512_update/2, sha512_final/1]).
--export([md5_mac/2, md5_mac_96/2, sha_mac/2, sha_mac_96/2]).
+-export([md5_mac/2, md5_mac_96/2, sha_mac/2, sha_mac/3, sha_mac_96/2]).
-export([hmac_init/2, hmac_update/2, hmac_final/1, hmac_final_n/2]).
-export([des_cbc_encrypt/3, des_cbc_decrypt/3, des_cbc_ivec/1]).
-export([des_ecb_encrypt/2, des_ecb_decrypt/2]).
+-export([des_cfb_encrypt/3, des_cfb_decrypt/3, des_cfb_ivec/2]).
-export([des3_cbc_encrypt/5, des3_cbc_decrypt/5]).
+-export([des3_cfb_encrypt/5, des3_cfb_decrypt/5]).
-export([blowfish_ecb_encrypt/2, blowfish_ecb_decrypt/2]).
-export([blowfish_cbc_encrypt/3, blowfish_cbc_decrypt/3]).
-export([blowfish_cfb64_encrypt/3, blowfish_cfb64_decrypt/3]).
@@ -40,7 +42,7 @@
-export([aes_cfb_128_encrypt/3, aes_cfb_128_decrypt/3]).
-export([exor/2]).
-export([rc4_encrypt/2, rc4_set_key/1, rc4_encrypt_with_state/2]).
--export([rc2_40_cbc_encrypt/3, rc2_40_cbc_decrypt/3]).
+-export([rc2_cbc_encrypt/3, rc2_cbc_decrypt/3, rc2_40_cbc_encrypt/3, rc2_40_cbc_decrypt/3]).
-export([dss_verify/3, dss_verify/4, rsa_verify/3, rsa_verify/4]).
-export([dss_sign/2, dss_sign/3, rsa_sign/2, rsa_sign/3]).
-export([rsa_public_encrypt/3, rsa_private_decrypt/3]).
@@ -68,8 +70,10 @@
sha_mac, sha_mac_96,
sha_mac_init, sha_mac_update, sha_mac_final,
des_cbc_encrypt, des_cbc_decrypt,
+ des_cfb_encrypt, des_cfb_decrypt,
des_ecb_encrypt, des_ecb_decrypt,
des_ede3_cbc_encrypt, des_ede3_cbc_decrypt,
+ des_ede3_cfb_encrypt, des_ede3_cfb_decrypt,
aes_cfb_128_encrypt, aes_cfb_128_decrypt,
rand_bytes,
strong_rand_bytes,
@@ -79,7 +83,7 @@
dss_verify,dss_sign,
rsa_verify,rsa_sign,
rsa_public_encrypt,rsa_private_decrypt,
- rsa_private_encrypt,rsa_public_decrypt,
+ rsa_private_encrypt,rsa_public_decrypt,
dh_generate_key, dh_compute_key,
aes_cbc_128_encrypt, aes_cbc_128_decrypt,
exor,
@@ -87,7 +91,7 @@
rc2_40_cbc_encrypt, rc2_40_cbc_decrypt,
%% idea_cbc_encrypt, idea_cbc_decrypt,
aes_cbc_256_encrypt, aes_cbc_256_decrypt,
- aes_ctr_encrypt, aes_ctr_decrypt,
+ aes_ctr_encrypt, aes_ctr_decrypt,
aes_ctr_stream_init, aes_ctr_stream_encrypt, aes_ctr_stream_decrypt,
info_lib]).
@@ -256,6 +260,9 @@ md5_mac_n(_Key,_Data,_MacSz) -> ?nif_stub.
sha_mac(Key, Data) ->
sha_mac_n(Key,Data,20).
+sha_mac(Key, Data, Size) ->
+ sha_mac_n(Key, Data, Size).
+
sha_mac_96(Key, Data) ->
sha_mac_n(Key,Data,12).
@@ -294,6 +301,33 @@ des_cbc_ivec(Data) when is_list(Data) ->
des_cbc_ivec(list_to_binary(Data)).
%%
+%% DES - in 8-bits cipher feedback mode (CFB)
+%%
+-spec des_cfb_encrypt(iodata(), binary(), iodata()) -> binary().
+-spec des_cfb_decrypt(iodata(), binary(), iodata()) -> binary().
+
+des_cfb_encrypt(Key, IVec, Data) ->
+ des_cfb_crypt(Key, IVec, Data, true).
+
+des_cfb_decrypt(Key, IVec, Data) ->
+ des_cfb_crypt(Key, IVec, Data, false).
+
+des_cfb_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+
+%%
+%% dec_cfb_ivec(IVec, Data) -> binary()
+%%
+%% Returns the IVec to be used in the next iteration of
+%% des_cfb_[encrypt|decrypt].
+%%
+-spec des_cfb_ivec(iodata(), iodata()) -> binary().
+
+des_cfb_ivec(IVec, Data) ->
+ IVecAndData = list_to_binary([IVec, Data]),
+ {_, NewIVec} = split_binary(IVecAndData, byte_size(IVecAndData) - 8),
+ NewIVec.
+
+%%
%% DES - in electronic codebook mode (ECB)
%%
-spec des_ecb_encrypt(iodata(), iodata()) -> binary().
@@ -326,6 +360,26 @@ des_ede3_cbc_decrypt(Key1, Key2, Key3, IVec, Data) ->
des_ede3_cbc_crypt(_Key1, _Key2, _Key3, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
%%
+%% DES3 - in 8-bits cipher feedback mode (CFB)
+%%
+-spec des3_cfb_encrypt(iodata(), iodata(), iodata(), binary(), iodata()) ->
+ binary().
+-spec des3_cfb_decrypt(iodata(), iodata(), iodata(), binary(), iodata()) ->
+ binary().
+
+des3_cfb_encrypt(Key1, Key2, Key3, IVec, Data) ->
+ des_ede3_cfb_encrypt(Key1, Key2, Key3, IVec, Data).
+des_ede3_cfb_encrypt(Key1, Key2, Key3, IVec, Data) ->
+ des_ede3_cfb_crypt(Key1, Key2, Key3, IVec, Data, true).
+
+des3_cfb_decrypt(Key1, Key2, Key3, IVec, Data) ->
+ des_ede3_cfb_decrypt(Key1, Key2, Key3, IVec, Data).
+des_ede3_cfb_decrypt(Key1, Key2, Key3, IVec, Data) ->
+ des_ede3_cfb_crypt(Key1, Key2, Key3, IVec, Data, false).
+
+des_ede3_cfb_crypt(_Key1, _Key2, _Key3, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+
+%%
%% Blowfish
%%
-spec blowfish_ecb_encrypt(iodata(), iodata()) -> binary().
@@ -415,6 +469,13 @@ rand_uniform(From,To) when is_binary(From), is_binary(To) ->
Whatever
end;
rand_uniform(From,To) when is_integer(From),is_integer(To) ->
+ if From < 0 ->
+ rand_uniform_pos(0, To - From) + From;
+ true ->
+ rand_uniform_pos(From, To)
+ end.
+
+rand_uniform_pos(From,To) when From < To ->
BinFrom = mpint(From),
BinTo = mpint(To),
case rand_uniform(BinFrom, BinTo) of
@@ -422,7 +483,9 @@ rand_uniform(From,To) when is_integer(From),is_integer(To) ->
erlint(Result);
Other ->
Other
- end.
+ end;
+rand_uniform_pos(_,_) ->
+ error(badarg).
rand_uniform_nif(_From,_To) -> ?nif_stub.
@@ -629,16 +692,25 @@ rc4_encrypt(_Key, _Data) -> ?nif_stub.
rc4_set_key(_Key) -> ?nif_stub.
rc4_encrypt_with_state(_State, _Data) -> ?nif_stub.
+
+%% RC2 block cipher
+
+rc2_cbc_encrypt(Key, IVec, Data) ->
+ rc2_cbc_crypt(Key,IVec,Data,true).
+
+rc2_cbc_decrypt(Key, IVec, Data) ->
+ rc2_cbc_crypt(Key,IVec,Data,false).
+
+rc2_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+
%%
-%% RC2 - 40 bits block cipher
+%% RC2 - 40 bits block cipher - Backwards compatibility not documented.
%%
-rc2_40_cbc_encrypt(Key, IVec, Data) ->
- rc2_40_cbc_crypt(Key,IVec,Data,true).
-
-rc2_40_cbc_decrypt(Key, IVec, Data) ->
- rc2_40_cbc_crypt(Key,IVec,Data,false).
+rc2_40_cbc_encrypt(Key, IVec, Data) when erlang:byte_size(Key) == 5 ->
+ rc2_cbc_crypt(Key,IVec,Data,true).
-rc2_40_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+rc2_40_cbc_decrypt(Key, IVec, Data) when erlang:byte_size(Key) == 5 ->
+ rc2_cbc_crypt(Key,IVec,Data,false).
%%
%% DH Diffie-Hellman functions
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index 283aadb6ea..86acdc27df 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -44,7 +44,12 @@
md5_mac_io/1,
des_cbc/1,
des_cbc_iter/1,
+ des_cfb/1,
+ des_cfb_iter/1,
des_ecb/1,
+ des3_cbc/1,
+ des3_cfb/1,
+ rc2_cbc/1,
aes_cfb/1,
aes_cbc/1,
aes_cbc_iter/1,
@@ -75,7 +80,9 @@ all() ->
md5_mac_io, sha, sha_update,
hmac_update_sha, hmac_update_sha_n, hmac_update_md5_n, hmac_update_md5_io, hmac_update_md5,
%% sha256, sha256_update, sha512,sha512_update,
- des_cbc, aes_cfb, aes_cbc,
+ des_cbc, des_cfb, des3_cbc, des3_cfb, rc2_cbc, aes_cfb, aes_cbc,
+ aes_cbc_iter, aes_ctr, aes_ctr_stream, des_cbc_iter, des_cfb_iter, des_ecb,
+ des_cbc, rc2_cbc, aes_cfb, aes_cbc,
aes_cbc_iter, aes_ctr, aes_ctr_stream, des_cbc_iter, des_ecb,
rand_uniform_test, strong_rand_test,
rsa_verify_test, dsa_verify_test, rsa_sign_test,
@@ -138,14 +145,15 @@ link_test_2(Drv) ->
Libs = os:cmd(Cmd),
io:format("~p\n", [Libs]),
case string:str(Libs, "libcrypto") of
- 0 -> ok;
- _ ->
+ 0 ->
case ?t:is_commercial() of
true ->
- ?t:fail({libcrypto,not_statically_linked});
+ ?t:fail({libcrypto,statically_linked});
false ->
- {comment,"Not statically linked (OK for open-source platform)"}
- end
+ {comment,"Statically linked (OK for open-source platform)"}
+ end;
+ _ ->
+ ok
end
end.
@@ -291,7 +299,7 @@ sha(Config) when is_list(Config) ->
hexstr2bin("84983E441C3BD26EBAAE4AA1F95129E5E54670F1")).
-%%
+%%
hmac_update_sha_n(doc) ->
["Request a larger-than-allowed SHA1 HMAC using hmac_init, hmac_update, and hmac_final_n. "
"Expected values for examples are generated using crypto:sha_mac." ];
@@ -342,7 +350,7 @@ hmac_update_md5(Config) when is_list(Config) ->
Key2 = "A fine speach by a fine man!",
?line Long1 = "Four score and seven years ago our fathers brought forth on this continent a new nation, conceived in liberty, and dedicated to the proposition that all men are created equal.",
?line Long2 = "Now we are engaged in a great civil war, testing whether that nation, or any nation, so conceived and so dedicated, can long endure. We are met on a great battle-field of that war. We have come to dedicate a portion of that field, as a final resting place for those who here gave their lives that that nation might live. It is altogether fitting and proper that we should do this.",
- ?line Long3 = "But, in a larger sense, we can not dedicate, we can not consecrate, we can not hallow this ground. The brave men, living and dead, who struggled here, have consecrated it, far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us-that from these honored dead we take increased devotion to that cause for which they gave the last full measure of devotion—that we here highly resolve that these dead shall not have died in vain-that this nation, under God, shall have a new birth of freedom-and that government of the people, by the people, for the people, shall not perish from the earth.",
+ ?line Long3 = "But, in a larger sense, we can not dedicate, we can not consecrate, we can not hallow this ground. The brave men, living and dead, who struggled here, have consecrated it, far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us-that from these honored dead we take increased devotion to that cause for which they gave the last full measure of devotion that we here highly resolve that these dead shall not have died in vain-that this nation, under God, shall have a new birth of freedom-and that government of the people, by the people, for the people, shall not perish from the earth.",
?line CtxA = crypto:hmac_init(md5, Key2),
?line CtxB = crypto:hmac_update(CtxA, Long1),
?line CtxC = crypto:hmac_update(CtxB, Long2),
@@ -546,6 +554,40 @@ des_cbc_iter(Config) when is_list(Config) ->
%%
%%
+des_cfb(doc) ->
+ "Encrypt and decrypt according to CFB DES. and check the result. "
+ "Example is from FIPS-81.";
+des_cfb(suite) ->
+ [];
+des_cfb(Config) when is_list(Config) ->
+ ?line Key = hexstr2bin("0123456789abcdef"),
+ ?line IVec = hexstr2bin("1234567890abcdef"),
+ ?line Plain = "Now is the",
+ ?line Cipher = crypto:des_cfb_encrypt(Key, IVec, Plain),
+ ?line m(Cipher, hexstr2bin("f31fda07011462ee187f")),
+ ?line m(list_to_binary(Plain),
+ crypto:des_cfb_decrypt(Key, IVec, Cipher)).
+
+%%
+%%
+des_cfb_iter(doc) ->
+ "Encrypt and decrypt according to CFB DES in two steps, and "
+ "check the result. Example is from FIPS-81.";
+des_cfb_iter(suite) ->
+ [];
+des_cfb_iter(Config) when is_list(Config) ->
+ ?line Key = hexstr2bin("0123456789abcdef"),
+ ?line IVec = hexstr2bin("1234567890abcdef"),
+ ?line Plain1 = "Now i",
+ ?line Plain2 = "s the",
+ ?line Cipher1 = crypto:des_cfb_encrypt(Key, IVec, Plain1),
+ ?line IVec2 = crypto:des_cfb_ivec(IVec, Cipher1),
+ ?line Cipher2 = crypto:des_cfb_encrypt(Key, IVec2, Plain2),
+ ?line Cipher = list_to_binary([Cipher1, Cipher2]),
+ ?line m(Cipher, hexstr2bin("f31fda07011462ee187f")).
+
+%%
+%%
des_ecb(doc) ->
"Encrypt and decrypt according to ECB DES and check the result. "
"Example are from FIPS-81.";
@@ -565,6 +607,81 @@ des_ecb(Config) when is_list(Config) ->
?line m(Cipher5, <<"he time ">>),
?line Cipher6 = crypto:des_ecb_decrypt(Key, hexstr2bin("893d51ec4b563b53")),
?line m(Cipher6, <<"for all ">>).
+%%
+%%
+rc2_cbc(doc) ->
+ "Encrypt and decrypt according to RC2 CBC and check the result. "
+ "Example stripped out from public_key application test";
+rc2_cbc(Config) when is_list(Config) ->
+
+ Key = <<146,210,160,124,215,227,153,239,227,17,222,140,3,93,27,191>>,
+ IV = <<72,91,135,182,25,42,35,210>>,
+
+ Cipher = <<36,245,206,158,168,230,58,69,148,137,32,192,250,41,237,181,181,251, 192,2,175,135,177,171,57,30,111,117,159,149,15,28,88,158,28,81,28,115, 85,219,241,82,117,222,91,85,73,117,164,25,182,52,191,64,123,57,26,19, 211,27,253,31,194,219,231,104,247,240,172,130,119,21,225,154,101,247, 32,216,42,216,133,169,78,22,97,27,227,26,196,224,172,168,17,9,148,55, 203,91,252,40,61,226,236,221,215,160,78,63,13,181,68,57,196,241,185, 207, 116,129,152,237,60,139,247,153,27,146,161,246,222,98,185,222,152, 187,135, 236,86,34,7,110,91,230,173,34,160,242,202,222,121,127,181,140, 101,203,195, 190,88,250,86,147,127,87,72,126,171,16,71,47,110,248,88, 14,29,143,161,152, 129,236,148,22,152,186,208,119,70,8,174,193,203,100, 193,203,200,117,102,242, 134,142,96,125,135,200,217,190,76,117,50,70, 209,186,101,241,200,91,40,193,54, 90,195,38,47,59,197,38,234,86,223,16, 51,253,204,129,20,171,66,21,241,26,135,216, 196,114,110,91,15,53,40, 164,201,136,113,95,247,51,181,208,241,68,168,98,151,36, 155,72,24,57, 42,191,14,125,204,10,167,214,233,138,115,125,234,121,134,227,26,247, 77,200,117,110,117,111,168,156,206,67,159,149,189,173,150,193,91,199, 216,153,22, 189,137,185,89,160,13,131,132,58,109,28,110,246,252,251,14, 232,91,38,52,29,101,188,69,123,50,0,130,178,93,73,239,118,7,77,35,59, 253,10,159,45,86,142,37,78,232,48>>,
+ Text = <<48,130,1,85,2,1,0,48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,4,130,1,63,48,130, 1,59,2,1,0,2,65,0,222,187,252,44,9,214,27,173,162,169,70,47,36,34,78,84,204, 107,60,192,117,95,21,206,49,142,245,126,121,223,23,2,107,106,133,204,161,36, 40,2,114,69,4,93,242,5,42,50,154,47,154,211,209,123,120,161,5,114,173,155,34, 191,52,59,2,3,1,0,1,2,64,45,144,169,106,220,236,71,39,67,82,123,192,35,21,61, 143,13,110,150,180,12,142,210,40,39,109,70,125,132,51,6,66,159,134,112,85, 155,243,118,221,65,133,127,99,151,194,252,141,149,224,229,62,214,45,228,32, 184,85,67,14,228,161,184,161,2,33,0,255,202,240,131,130,57,49,224,115,255,83, 79,6,165,212,21,179,212,20,188,97,74,69,68,163,223,247,237,39,24,23,235,2,33, 0,222,234,48,36,33,23,219,45,59,136,55,245,143,29,165,48,255,131,207,146,131, 104,13,163,54,131,236,78,88,54,16,241,2,33,0,230,2,99,129,173,176,166,131, 241,106,143,76,9,107,70,41,121,185,228,39,124,200,159,62,216,169,5,180,111, 169,255,159,2,33,0,151,193,70,212,209,210,179,219,175,83,165,4,255,81,103,76, 92,39,24,0,222,132,208,3,244,241,10,198,171,54,227,129,2,32,43,250,20,31,16, 189,168,116,225,1,125,132,94,130,118,124,28,56,232,39,69,218,244,33,240,200, 205,9,215,101,35,135,7,7,7,7,7,7,7>>,
+
+ Text = crypto:rc2_cbc_decrypt(Key, IV, Cipher),
+ Cipher = crypto:rc2_cbc_encrypt(Key, IV, Text).
+
+%%
+%%
+des3_cbc(doc) ->
+ "Encrypt and decrypt according to CBC 3DES, and check the result.";
+des3_cbc(suite) ->
+ [];
+des3_cbc(Config) when is_list(Config) ->
+ ?line Key1 = hexstr2bin("0123456789abcdef"),
+ ?line Key2 = hexstr2bin("fedcba9876543210"),
+ ?line Key3 = hexstr2bin("0f2d4b6987a5c3e1"),
+ ?line IVec = hexstr2bin("1234567890abcdef"),
+ ?line Plain = "Now is the time for all ",
+ ?line Cipher = crypto:des3_cbc_encrypt(Key1, Key2, Key3, IVec, Plain),
+ ?line m(Cipher, hexstr2bin("8a2667ee5577267cd9b1af2c5a0480"
+ "0bac1ae66970fb2b89")),
+ ?line m(list_to_binary(Plain),
+ crypto:des3_cbc_decrypt(Key1, Key2, Key3, IVec, Cipher)),
+ ?line Plain2 = "7654321 Now is the time for " ++ [0, 0, 0, 0],
+ ?line Cipher2 = crypto:des3_cbc_encrypt(Key1, Key2, Key3, IVec, Plain2),
+ ?line m(Cipher2, hexstr2bin("eb33ec6ede2c8e90f6877e77b95d5"
+ "4c83cee22907f7f0041ca1b7abe202bfafe")),
+ ?line m(list_to_binary(Plain2),
+ crypto:des3_cbc_decrypt(Key1, Key2, Key3, IVec, Cipher2)),
+
+ ?line Key = hexstr2bin("0123456789abcdef"),
+ ?line DESCipher = crypto:des3_cbc_encrypt(Key, Key, Key, IVec, Plain),
+ ?line m(DESCipher, hexstr2bin("e5c7cdde872bf27c43e934008c389c"
+ "0f683788499a7c05f6")),
+ ?line m(list_to_binary(Plain),
+ crypto:des3_cbc_decrypt(Key, Key, Key, IVec, DESCipher)),
+ ?line DESCipher2 = crypto:des3_cbc_encrypt(Key, Key, Key, IVec, Plain2),
+ ?line m(DESCipher2, hexstr2bin("b9916b8ee4c3da64b4f44e3cbefb9"
+ "9484521388fa59ae67d58d2e77e86062733")),
+ ?line m(list_to_binary(Plain2),
+ crypto:des3_cbc_decrypt(Key, Key, Key, IVec, DESCipher2)).
+
+%%
+%%
+des3_cfb(doc) ->
+ "Encrypt and decrypt according to CFB 3DES, and check the result.";
+des3_cfb(suite) ->
+ [];
+des3_cfb(Config) when is_list(Config) ->
+ ?line Key1 = hexstr2bin("0123456789abcdef"),
+ ?line Key2 = hexstr2bin("fedcba9876543210"),
+ ?line Key3 = hexstr2bin("0f2d4b6987a5c3e1"),
+ ?line IVec = hexstr2bin("1234567890abcdef"),
+ ?line Plain = "Now is the time for all ",
+ ?line Cipher = crypto:des3_cfb_encrypt(Key1, Key2, Key3, IVec, Plain),
+ ?line m(Cipher, hexstr2bin("fc0ba7a20646ba53cc8bff263f0937"
+ "1deab42a00666db02c")),
+ ?line m(list_to_binary(Plain),
+ crypto:des3_cfb_decrypt(Key1, Key2, Key3, IVec, Cipher)),
+ ?line Plain2 = "7654321 Now is the time for " ++ [0, 0, 0, 0],
+ ?line Cipher2 = crypto:des3_cfb_encrypt(Key1, Key2, Key3, IVec, Plain2),
+ ?line m(Cipher2, hexstr2bin("8582c59ac01897422632c0accb66c"
+ "e413f5efab838fce7e41e2ba67705bad5bc")),
+ ?line m(list_to_binary(Plain2),
+ crypto:des3_cfb_decrypt(Key1, Key2, Key3, IVec, Cipher2)).
%%
%%
@@ -878,10 +995,17 @@ rand_uniform_aux_test(0) ->
rand_uniform_aux_test(N) ->
?line L = N*1000,
?line H = N*100000+1,
+ ?line crypto_rand_uniform(L, H),
+ ?line crypto_rand_uniform(-L, L),
+ ?line crypto_rand_uniform(-H, -L),
+ ?line crypto_rand_uniform(-H, L),
+ ?line rand_uniform_aux_test(N-1).
+
+crypto_rand_uniform(L,H) ->
?line R1 = crypto:rand_uniform(L, H),
?line t(R1 >= L),
- ?line t(R1 < H),
- ?line rand_uniform_aux_test(N-1).
+ ?line t(R1 < H).
+
%%
%%
@@ -1225,8 +1349,8 @@ rc4_test(doc) ->
rc4_test(suite) ->
[];
rc4_test(Config) when is_list(Config) ->
- CT1 = <<"hej p� dig">>,
- R1 = <<71,112,14,44,140,33,212,144,155,47>>,
+ CT1 = <<"Yo baby yo">>,
+ R1 = <<118,122,68,110,157,166,141,212,139,39>>,
K = "apaapa",
R1 = crypto:rc4_encrypt(K, CT1),
CT1 = crypto:rc4_encrypt(K, R1),
@@ -1240,14 +1364,14 @@ rc4_stream_test(doc) ->
rc4_stream_test(suite) ->
[];
rc4_stream_test(Config) when is_list(Config) ->
- CT1 = <<"hej">>,
- CT2 = <<" p� dig">>,
+ CT1 = <<"Yo ">>,
+ CT2 = <<"baby yo">>,
K = "apaapa",
State0 = crypto:rc4_set_key(K),
{State1, R1} = crypto:rc4_encrypt_with_state(State0, CT1),
{_State2, R2} = crypto:rc4_encrypt_with_state(State1, CT2),
R = list_to_binary([R1, R2]),
- <<71,112,14,44,140,33,212,144,155,47>> = R,
+ <<118,122,68,110,157,166,141,212,139,39>> = R,
ok.
blowfish_cfb64(doc) -> ["Test Blowfish encrypt/decrypt."];
diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk
index e754aabc44..33fa9b1ec3 100644
--- a/lib/crypto/vsn.mk
+++ b/lib/crypto/vsn.mk
@@ -1 +1 @@
-CRYPTO_VSN = 2.0.3
+CRYPTO_VSN = 2.0.4
diff --git a/lib/debugger/doc/src/debugger_chapter.xml b/lib/debugger/doc/src/debugger_chapter.xml
index 1f5d4dd5ff..2d812b0236 100644
--- a/lib/debugger/doc/src/debugger_chapter.xml
+++ b/lib/debugger/doc/src/debugger_chapter.xml
@@ -254,19 +254,17 @@ c_break(Bindings) ->
used, for example, if an error occurs:</p>
<pre>
1> <input>catch a+1.</input>
-{'EXIT',{badarith,[{erlang,'+',[a,1]},
- {erl_eval,do_apply,5},
- {erl_eval,expr,5},
- {shell,exprs,6},
- {shell,eval_exprs,6},
- {shell,eval_loop,3}]}}</pre>
-
- <p>In the case above, the stack trace shows that the function called
- last was <c>erl_eval:eval_op/3</c>. See <em>Erlang Reference
- Manual, Errors and Error handling</em>, for more information
- about stack trace.</p>
-
- <p>Debugger emulates the stack trace by keeping track of recently
+{'EXIT',{badarith,[{erlang,'+',[a,1],[]},
+ {erl_eval,do_apply,5,[{file,"erl_eval.erl"},{line,562}]},
+ {erl_eval,expr,5,[{file,"erl_eval.erl"},{line,359}]},
+ {shell,exprs,7,[{file,"shell.erl"},{line,668}]},
+ {shell,eval_exprs,7,[{file,"shell.erl"},{line,623}]},
+ {shell,eval_loop,3,[{file,"shell.erl"},{line,608}]}]}}</pre>
+
+ <p>See the <em>Erlang Reference Manual, Errors and Error handling</em>,
+ for more information about the stack trace.</p>
+
+ <p>The Debugger emulates the stack trace by keeping track of recently
called interpreted functions. (The real stack trace cannot be
used, as it shows which functions of the Debugger have been
called, rather than which interpreted functions).</p>
@@ -276,17 +274,15 @@ c_break(Bindings) ->
<seealso marker="#attach">the Attach Process window</seealso>.
</p>
- <p>By default, the Debugger saves information about all current
+ <p>By default, the Debugger only saves information about recursive
function calls, that is, function calls that have not yet returned
- a value (option 'Stack On, Tail').</p>
-
- <p>This means, however, that information is saved also for tail
- recursive calls. For example, repeated calls to the <c>loop</c>
- function of an Erlang process. This may consume unnecessary
- amounts of memory for debugged processes with long lifetimes and
- many tail recursive calls. It is therefore possible to set
- the option 'Stack On, no tail', in which case information about
- previous calls are discarded when a tail recursive call is made.
+ a value (option 'Stack On, No Tail').</p>
+
+ <p>Sometimes, however, it can be useful to save all calls, even
+ tail-recursive calls. That can be done with the 'Stack On, Tail'
+ option. Note that this option will consume more memory and slow
+ down execution of interpreted functions when there are many
+ tail-recursive calls.
</p>
<p>It is also possible to turn off the Debugger stack trace
diff --git a/lib/debugger/doc/src/int.xml b/lib/debugger/doc/src/int.xml
index 8b55461a44..c9d815755d 100644
--- a/lib/debugger/doc/src/int.xml
+++ b/lib/debugger/doc/src/int.xml
@@ -284,12 +284,12 @@ spawn(Module, Name, [Pid | Args])
<list>
<item><c>all</c> - save information about all current calls,
that is, function calls that have not yet returned a value.
- This is the default.</item>
+ </item>
<item><c>no_tail</c> - save information about current calls,
but discard previous information when a tail recursive call
is made. This option consumes less memory and may be
necessary to use for processes with long lifetimes and many
- tail recursive calls.</item>
+ tail recursive calls. This is the default.</item>
<item><c>false</c> - do not save any information about current
calls.</item>
</list>
diff --git a/lib/debugger/doc/src/make.dep b/lib/debugger/doc/src/make.dep
deleted file mode 100644
index c11fd3c21c..0000000000
--- a/lib/debugger/doc/src/make.dep
+++ /dev/null
@@ -1,29 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex debugger.tex debugger_chapter.tex \
- i.tex int.tex part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: part.xml ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: images/attach.ps images/cond_break_dialog.ps \
- images/function_break_dialog.ps images/interpret.ps \
- images/line_break_dialog.ps images/monitor.ps \
- images/view.ps
-
diff --git a/lib/debugger/src/Makefile b/lib/debugger/src/Makefile
index 8551fe887d..6dc7d0d783 100644
--- a/lib/debugger/src/Makefile
+++ b/lib/debugger/src/Makefile
@@ -44,6 +44,7 @@ MODULES= \
dbg_ieval \
dbg_iload \
dbg_iserver \
+ dbg_istk \
dbg_ui_break \
dbg_ui_break_win \
dbg_ui_edit \
diff --git a/lib/debugger/src/dbg_debugged.erl b/lib/debugger/src/dbg_debugged.erl
index 3732c40c73..18dcd92ff3 100644
--- a/lib/debugger/src/dbg_debugged.erl
+++ b/lib/debugger/src/dbg_debugged.erl
@@ -76,8 +76,8 @@ msg_loop(Meta, Mref, SaveStacktrace) ->
msg_loop(Meta, Mref, SaveStacktrace);
%% Meta needs something evaluated within context of real process
- {sys, Meta, {command, Command, Stacktrace}} ->
- Reply = handle_command(Command, Stacktrace),
+ {sys, Meta, {command,Command}} ->
+ Reply = handle_command(Command),
Meta ! {sys, self(), Reply},
msg_loop(Meta, Mref, SaveStacktrace);
@@ -93,11 +93,12 @@ msg_loop(Meta, Mref, SaveStacktrace) ->
end
end.
-handle_command(Command, Stacktrace) ->
- try reply(Command)
+handle_command(Command) ->
+ try
+ reply(Command)
catch Class:Reason ->
- Stacktrace2 = stacktrace_f(erlang:get_stacktrace()),
- {exception, {Class,Reason,Stacktrace2++Stacktrace}}
+ Stacktrace = stacktrace_f(erlang:get_stacktrace()),
+ {exception,{Class,Reason,Stacktrace}}
end.
reply({apply,M,F,As}) ->
@@ -116,5 +117,5 @@ demonitor(Mref) ->
%% Fix stacktrace - keep all above call to this module.
%%
stacktrace_f([]) -> [];
-stacktrace_f([{?MODULE,_,_}|_]) -> [];
+stacktrace_f([{?MODULE,_,_,_}|_]) -> [];
stacktrace_f([F|S]) -> [F|stacktrace_f(S)].
diff --git a/lib/debugger/src/dbg_icmd.erl b/lib/debugger/src/dbg_icmd.erl
index e9502eaa2b..b230efaa7a 100644
--- a/lib/debugger/src/dbg_icmd.erl
+++ b/lib/debugger/src/dbg_icmd.erl
@@ -273,7 +273,7 @@ handle_int_msg({old_code,Mod}, Status, Bs,
erase([Mod|db]),
put(cache, []);
true ->
- case dbg_ieval:in_use_p(Mod, M) of
+ case dbg_istk:in_use_p(Mod, M) of
true ->
%% A call to Mod is on the stack (or might be),
%% so we must terminate.
@@ -342,11 +342,11 @@ handle_user_msg({set,stack_trace,Flag}, _Status, _Bs, _Ieval) ->
handle_user_msg({get,bindings,From,SP}, _Status, Bs, _Ieval) ->
reply(From, bindings, bindings(Bs, SP));
handle_user_msg({get,stack_frame,From,{Dir,SP}}, _Status, _Bs,_Ieval) ->
- reply(From, stack_frame, dbg_ieval:stack_frame(Dir, SP));
+ reply(From, stack_frame, dbg_istk:stack_frame(Dir, SP));
handle_user_msg({get,messages,From,_}, _Status, _Bs, _Ieval) ->
reply(From, messages, messages());
-handle_user_msg({get,backtrace,From,N}, _Status, _Bs, _Ieval) ->
- reply(From, backtrace, dbg_ieval:backtrace(N)).
+handle_user_msg({get,backtrace,From,N}, _Status, _Bs, Ieval) ->
+ reply(From, backtrace, dbg_istk:backtrace(N, Ieval)).
set_stack_trace(true) ->
set_stack_trace(all);
@@ -366,11 +366,11 @@ reply(From, Tag, Reply) ->
bindings(Bs, nostack) ->
Bs;
bindings(Bs, SP) ->
- case dbg_ieval:stack_level() of
+ case dbg_istk:stack_level() of
Le when SP > Le ->
Bs;
_ ->
- dbg_ieval:bindings(SP)
+ dbg_istk:bindings(SP)
end.
messages() ->
@@ -422,7 +422,7 @@ eval_nonrestricted({From, _Mod, Cmd, _SP}, Bs,
eval_nonrestricted_1({match,_,{var,_,Var},Expr}, Bs, Ieval) ->
{value,Res,Bs2} =
- dbg_ieval:eval_expr(Expr, Bs, Ieval#ieval{last_call=false}),
+ dbg_ieval:eval_expr(Expr, Bs, Ieval#ieval{top=false}),
Bs3 = case lists:keyfind(Var, 1, Bs) of
{Var,_Value} ->
lists:keyreplace(Var, 1, Bs2, {Var,Res});
@@ -437,7 +437,7 @@ eval_nonrestricted_1({var,_,Var}, Bs, _Ieval) ->
{Res,Bs};
eval_nonrestricted_1(Expr, Bs, Ieval) ->
{value,Res,Bs2} =
- dbg_ieval:eval_expr(Expr, Bs, Ieval#ieval{last_call=false}),
+ dbg_ieval:eval_expr(Expr, Bs, Ieval#ieval{top=false}),
{Res,Bs2}.
mark_running(LineNo, Le) ->
diff --git a/lib/debugger/src/dbg_ieval.erl b/lib/debugger/src/dbg_ieval.erl
index 306323f8ea..2e88c35741 100644
--- a/lib/debugger/src/dbg_ieval.erl
+++ b/lib/debugger/src/dbg_ieval.erl
@@ -20,8 +20,7 @@
-export([eval/3,exit_info/5]).
-export([eval_expr/3]).
--export([check_exit_msg/3,exception/4,in_use_p/2]).
--export([stack_level/0, bindings/1, stack_frame/2, backtrace/1]).
+-export([check_exit_msg/3,exception/4]).
-include("dbg_ieval.hrl").
@@ -71,13 +70,12 @@ exit_info(Int, AttPid, OrigPid, Reason, ExitInfo) ->
case ExitInfo of
{{Mod,Line},Bs,S} ->
- Stack = binary_to_term(S),
- put(stack, Stack),
- Le = stack_level(Stack),
+ dbg_istk:from_external(S),
+ Le = dbg_istk:stack_level(),
dbg_icmd:tell_attached({exit_at, {Mod, Line}, Reason, Le}),
exit_loop(OrigPid, Reason, Bs,#ieval{module=Mod,line=Line});
{} ->
- put(stack, []),
+ dbg_istk:init(),
dbg_icmd:tell_attached({exit_at, null, Reason, 1}),
exit_loop(OrigPid, Reason, erl_eval:new_bindings(),#ieval{})
end.
@@ -142,12 +140,12 @@ check_exit_msg({'DOWN',_,_,_,Reason}, Bs,
undefined when Le =:= 1 -> % died outside interpreted code
{};
undefined when Le > 1 ->
- StackBin = term_to_binary(get(stack)),
- {{Mod, Li}, Bs, StackBin};
+ StackExternal = (dbg_istk:delayed_to_external())(),
+ {{Mod, Li}, Bs, StackExternal};
%% Debugged has terminated due to an exception
- ExitInfo0 ->
- ExitInfo0
+ ExitInfo0 when is_function(ExitInfo0, 0) ->
+ ExitInfo0()
end,
dbg_iserver:cast(get(int), {set_exit_info,self(),ExitInfo}),
@@ -170,30 +168,26 @@ check_exit_msg(_Msg, _Bs, _Ieval) ->
%% and then raise the exception.
%%--------------------------------------------------------------------
exception(Class, Reason, Bs, Ieval) ->
- exception(Class, Reason, fix_stacktrace(1), Bs, Ieval).
-
-exception(Class, Reason, Stacktrace, Bs, #ieval{module=M, line=Line}) ->
- ExitInfo = {{M,Line}, Bs, term_to_binary(get(stack))},
+ exception(Class, Reason, Bs, Ieval, false).
+
+exception(Class, Reason, Bs, Ieval, false) ->
+ do_exception(Class, Reason,
+ dbg_istk:delayed_stacktrace(no_args, Ieval),
+ Bs, Ieval);
+exception(Class, Reason, Bs, Ieval, true) ->
+ do_exception(Class, Reason,
+ dbg_istk:delayed_stacktrace(include_args, Ieval),
+ Bs, Ieval).
+
+do_exception(Class, Reason, Stacktrace, Bs, #ieval{module=M, line=Line}) ->
+ StackFun = dbg_istk:delayed_to_external(),
+ ExitInfo = fun() ->
+ {{M,Line},Bs,StackFun()}
+ end,
put(exit_info, ExitInfo),
put(stacktrace, Stacktrace),
erlang:Class(Reason).
-%%--------------------------------------------------------------------
-%% in_use_p(Mod, Cm) -> boolean()
-%% Mod = Cm = atom()
-%% Returns true if Mod is found on the stack, otherwise false.
-%%--------------------------------------------------------------------
-in_use_p(Mod, Mod) -> true;
-in_use_p(Mod, _Cm) ->
- case get(trace_stack) of
- false -> true;
- _ -> % all | no_tail
- lists:any(fun({_,{M,_,_,_}}) when M =:= Mod -> true;
- (_) -> false
- end,
- get(stack))
- end.
-
%%====================================================================
%% Internal functions
%%====================================================================
@@ -225,7 +219,7 @@ meta(Int, Debugged, M, F, As) ->
put(cache, []),
put(next_break, Status), % break | running (other values later)
put(self, Debugged), % pid() interpreted process
- put(stack, []),
+ dbg_istk:init(),
put(stacktrace, []),
put(trace_stack, dbg_iserver:call(Int, get_stack_trace)),
put(trace, false), % bool() Trace on/off
@@ -243,8 +237,7 @@ meta(Int, Debugged, M, F, As) ->
debugged_cmd(Cmd, Bs, Ieval) ->
Debugged = get(self),
- Stacktrace = fix_stacktrace(2),
- Debugged ! {sys, self(), {command,Cmd,Stacktrace}},
+ Debugged ! {sys, self(), {command,Cmd}},
meta_loop(Debugged, Bs, Ieval).
meta_loop(Debugged, Bs, #ieval{level=Le} = Ieval) ->
@@ -257,12 +250,17 @@ meta_loop(Debugged, Bs, #ieval{level=Le} = Ieval) ->
{value, Val, Bs};
{sys, Debugged, {value,Val,Bs2}} ->
{value, Val, Bs2};
- {sys, Debugged, {exception,{Class,Reason,Stacktrace}}} ->
+ {sys, Debugged, {exception,{Class,Reason,Stk}}} ->
case get(exit_info) of
- %% Error occured outside interpreted code
+ %% Error occurred outside of interpreted code.
undefined ->
- exception(Class,Reason,Stacktrace,Bs,Ieval);
+ MakeStk0 = dbg_istk:delayed_stacktrace(),
+ MakeStk = fun(Depth0) ->
+ Depth = max(0, Depth0 - length(Stk)),
+ Stk ++ MakeStk0(Depth)
+ end,
+ do_exception(Class, Reason, MakeStk, Bs, Ieval);
%% Error must have occured within a re-entry to
%% interpreted code, simply raise the exception
@@ -275,7 +273,7 @@ meta_loop(Debugged, Bs, #ieval{level=Le} = Ieval) ->
%% Reset process dictionary
%% This is really only necessary if the process left
%% interpreted code at a call level > 1
- put(stack, []),
+ dbg_istk:init(),
put(stacktrace, []),
put(exit_info, undefined),
@@ -313,177 +311,6 @@ exit_loop(OrigPid, Reason, Bs, Ieval) ->
exit_loop(OrigPid, Reason, Bs, Ieval)
end.
-%%--Stack emulation---------------------------------------------------
-
-%% We keep track of a call stack that is used for
-%% 1) saving stack frames that can be inspected from an Attached
-%% Process GUI (using dbg_icmd:get(Meta, stack_frame, {Dir, SP})
-%% 2) generate an approximation of regular stacktrace -- sent to
-%% Debugged when it should raise an exception or evaluate a
-%% function (since it might possible raise an exception)
-%%
-%% Stack = [Entry]
-%% Entry = {Le, {MFA, Where, Bs}}
-%% Le = int() % current call level
-%% MFA = {M,F,Args} % called function (or fun)
-%% | {Fun,Args} %
-%% Where = {M,Li} % from where (module+line) function is called
-%% Bs = bindings() % current variable bindings
-%%
-%% How to push depends on the "Stack Trace" option (value saved in
-%% process dictionary item 'trace_stack').
-%% all - everything is pushed
-%% no_tail - tail recursive push
-%% false - nothing is pushed
-%% Whenever a function returns, the corresponding call frame is popped.
-
-push(MFA, Bs, #ieval{level=Le,module=Cm,line=Li,last_call=Lc}) ->
- Entry = {Le, {MFA, {Cm,Li}, Bs}},
- case get(trace_stack) of
- false -> ignore;
- no_tail when Lc ->
- case get(stack) of
- [] -> put(stack, [Entry]);
- [_Entry|Entries] -> put(stack, [Entry|Entries])
- end;
- _ -> % all | no_tail when Lc =:= false
- put(stack, [Entry|get(stack)])
- end.
-
-pop() ->
- case get(trace_stack) of
- false -> ignore;
- _ -> % all � no_tail
- case get(stack) of
- [_Entry|Entries] ->
- put(stack, Entries);
- [] ->
- ignore
- end
- end.
-
-pop(Le) ->
- case get(trace_stack) of
- false -> ignore;
- _ -> % all | no_tail
- put(stack, pop(Le, get(stack)))
- end.
-
-pop(Level, [{Le, _}|Stack]) when Level=<Le ->
- pop(Level, Stack);
-pop(_Level, Stack) ->
- Stack.
-
-
-%% stack_level() -> Le
-%% stack_level(Stack) -> Le
-%% Top call level
-stack_level() ->
- stack_level(get(stack)).
-
-stack_level([]) -> 1;
-stack_level([{Le,_}|_]) -> Le.
-
-%% fix_stacktrace(Start) -> Stacktrace
-%% Start = 1|2
-%% Stacktrace = [{M,F,Args|Arity} | {Fun,Args}]
-%% Convert internal stack format to imitation of regular stacktrace.
-%% Max three elements, no repeated (recursive) calls to the same
-%% function and convert argument lists to arity for all but topmost
-%% entry (and funs).
-%% 'Start' indicates where at get(stack) to start. This somewhat ugly
-%% solution is because fix_stacktrace has two uses: 1) to imitate
-%% the stacktrace in the case of an exception in the interpreted code,
-%% in which case the current call (top of the stack = first of the list)
-%% should be included, and 2) to send a current stacktrace to Debugged
-%% when evaluation passes into non-interpreted code, in which case
-%% the current call should NOT be included (as it is Debugged which
-%% will make the actual function call).
-fix_stacktrace(Start) ->
- case fix_stacktrace2(sublist(get(stack), Start, 3)) of
- [] ->
- [];
- [H|T] ->
- [H|args2arity(T)]
- end.
-
-sublist([], _Start, _Length) ->
- []; % workaround, lists:sublist([],2,3) fails
-sublist(L, Start, Length) ->
- lists:sublist(L, Start, Length).
-
-fix_stacktrace2([{_,{{M,F,As1},_,_}}, {_,{{M,F,As2},_,_}}|_])
- when length(As1) =:= length(As2) ->
- [{M,F,As1}];
-fix_stacktrace2([{_,{{Fun,As1},_,_}}, {_,{{Fun,As2},_,_}}|_])
- when length(As1) =:= length(As2) ->
- [{Fun,As1}];
-fix_stacktrace2([{_,{MFA,_,_}}|Entries]) ->
- [MFA|fix_stacktrace2(Entries)];
-fix_stacktrace2([]) ->
- [].
-
-args2arity([{M,F,As}|Entries]) when is_list(As) ->
- [{M,F,length(As)}|args2arity(Entries)];
-args2arity([Entry|Entries]) ->
- [Entry|args2arity(Entries)];
-args2arity([]) ->
- [].
-
-%% bindings(SP) -> Bs
-%% SP = Le % stack pointer
-%% Return the bindings for the specified call level
-bindings(SP) ->
- bindings(SP, get(stack)).
-
-bindings(SP, [{SP,{_MFA,_Wh,Bs}}|_]) ->
- Bs;
-bindings(SP, [_Entry|Entries]) ->
- bindings(SP, Entries);
-bindings(_SP, []) ->
- erl_eval:new_bindings().
-
-%% stack_frame(Dir, SP) -> {Le, Where, Bs} | top | bottom
-%% Dir = up | down
-%% Where = {Cm, Li}
-%% Cm = Module | undefined % module
-%% Li = int() | -1 % line number
-%% Bs = bindings()
-%% Return stack frame info one step up/down from given stack pointer
-%% up = to lower call levels
-%% down = to higher call levels
-stack_frame(up, SP) ->
- stack_frame(SP, up, get(stack));
-stack_frame(down, SP) ->
- stack_frame(SP, down, lists:reverse(get(stack))).
-
-stack_frame(SP, up, [{Le, {_MFA,Where,Bs}}|_]) when Le<SP ->
- {Le, Where, Bs};
-stack_frame(SP, down, [{Le, {_MFA,Where,Bs}}|_]) when Le>SP ->
- {Le, Where, Bs};
-stack_frame(SP, Dir, [{SP, _}|Stack]) ->
- case Stack of
- [{Le, {_MFA,Where,Bs}}|_] ->
- {Le, Where, Bs};
- [] when Dir =:= up ->
- top;
- [] when Dir =:= down ->
- bottom
- end;
-stack_frame(SP, Dir, [_Entry|Stack]) ->
- stack_frame(SP, Dir, Stack).
-
-%% backtrace(HowMany) -> Backtrace
-%% HowMany = all | int()
-%% Backtrace = {Le, MFA}
-%% Return all/the last N called functions, in reversed call order
-backtrace(HowMany) ->
- Stack = case HowMany of
- all -> get(stack);
- N -> lists:sublist(get(stack), N)
- end,
- [{Le, MFA} || {Le,{MFA,_Wh,_Bs}} <- Stack].
-
%%--Trace function----------------------------------------------------
%%--------------------------------------------------------------------
@@ -558,7 +385,7 @@ format_args1([]) ->
%% Mimic catch behaviour
catch_value(error, Reason) ->
- {'EXIT',{Reason,get(stacktrace)}};
+ {'EXIT',{Reason,get_stacktrace()}};
catch_value(exit, Reason) ->
{'EXIT',Reason};
catch_value(throw, Reason) ->
@@ -570,11 +397,13 @@ catch_value(throw, Reason) ->
%% Top level function of meta evaluator.
%% Return message to be replied to the target process.
%%--------------------------------------------------------------------
-eval_mfa(Debugged, M, F, As, Ieval) ->
+eval_mfa(Debugged, M, F, As, #ieval{level=Le}=Ieval0) ->
Int = get(int),
Bs = erl_eval:new_bindings(),
- try eval_function(M,F,As,Bs,extern,Ieval#ieval{last_call=true}) of
+ Ieval = Ieval0#ieval{level=Le+1,top=true},
+ try do_eval_function(M, F, As, Bs, extern, Ieval) of
{value, Val, _Bs} ->
+ trace(return, {Le,Val}),
{ready, Val}
catch
exit:{Debugged, Reason} ->
@@ -582,76 +411,68 @@ eval_mfa(Debugged, M, F, As, Ieval) ->
exit:{Int, Reason} ->
exit(Reason);
Class:Reason ->
- {exception, {Class, Reason, get(stacktrace)}}
+ {exception, {Class, Reason, get_stacktrace()}}
end.
-eval_function(Mod, Fun, As0, Bs0, _Called, Ieval) when is_function(Fun);
- Mod =:= ?MODULE,
- Fun =:= eval_fun ->
- #ieval{level=Le, line=Li, last_call=Lc} = Ieval,
+eval_function(Mod, Name, As, Bs, Called, Ieval0, Lc) ->
+ Tail = Lc andalso get(trace_stack) =:= no_tail,
+ case Tail of
+ false ->
+ Ieval = dbg_istk:push(Bs, Ieval0, Lc),
+ {value,Val,_} = do_eval_function(Mod, Name, As, Bs, Called, Ieval),
+ dbg_istk:pop(),
+ trace(return, {Ieval#ieval.level,Val}),
+ {value,Val,Bs};
+ true ->
+ do_eval_function(Mod, Name, As, Bs, Called, Ieval0)
+ end.
+
+do_eval_function(Mod, Fun, As0, Bs0, _, Ieval0) when is_function(Fun);
+ Mod =:= ?MODULE,
+ Fun =:= eval_fun ->
+ #ieval{level=Le,line=Li,top=Top} = Ieval0,
case lambda(Fun, As0) of
- {Cs,Module,Name,As,Bs} ->
- push({Module,Name,As}, Bs0, Ieval),
+ {[{clause,Fc,_,_,_}|_]=Cs,Module,Name,As,Bs} ->
+ Ieval = Ieval0#ieval{module=Module,function=Name,
+ arguments=As0,line=Fc},
trace(call_fun, {Le,Li,Name,As}),
- {value, Val, _Bs} =
- fnk_clauses(Cs, Module, Name, As, Bs,
- Ieval#ieval{level=Le+1}),
- pop(),
- trace(return, {Le,Val}),
- {value, Val, Bs0};
+ fnk_clauses(Cs, As, Bs, Ieval);
- not_interpreted when Lc -> % We are leaving interpreted code
+ not_interpreted when Top -> % We are leaving interpreted code
trace(call_fun, {Le,Li,Fun,As0}),
{value, {dbg_apply,erlang,apply,[Fun,As0]}, Bs0};
not_interpreted ->
- push({Fun,As0}, Bs0, Ieval),
trace(call_fun, {Le,Li,Fun,As0}),
- {value, Val, _Bs} =
- debugged_cmd({apply,erlang,apply,[Fun,As0]},Bs0,
- Ieval#ieval{level=Le+1}),
- pop(),
- trace(return, {Le,Val}),
- {value, Val, Bs0};
+ debugged_cmd({apply,erlang,apply,[Fun,As0]}, Bs0, Ieval0);
{error,Reason} ->
%% It's ok not to push anything in this case, the error
%% reason contains information about the culprit
%% ({badarity,{{Mod,Name},As}})
- exception(error, Reason, Bs0, Ieval)
+ exception(error, Reason, Bs0, Ieval0)
end;
%% Common Test adaptation
-eval_function(ct_line, line, As, Bs, extern, #ieval{level=Le}=Ieval) ->
+do_eval_function(ct_line, line, As, Bs, extern, #ieval{level=Le}=Ieval) ->
debugged_cmd({apply,ct_line,line,As}, Bs, Ieval#ieval{level=Le+1}),
{value, ignore, Bs};
-eval_function(Mod, Name, As0, Bs0, Called, Ieval) ->
- #ieval{level=Le, line=Li, last_call=Lc} = Ieval,
-
- push({Mod,Name,As0}, Bs0, Ieval),
+do_eval_function(Mod, Name, As0, Bs0, Called, Ieval0) ->
+ #ieval{level=Le,line=Li,top=Top} = Ieval0,
trace(call, {Called, {Le,Li,Mod,Name,As0}}),
-
+ Ieval = Ieval0#ieval{module=Mod,function=Name,arguments=As0},
case get_function(Mod, Name, As0, Called) of
- Cs when is_list(Cs) ->
- {value, Val, _Bs} =
- fnk_clauses(Cs, Mod, Name, As0, erl_eval:new_bindings(),
- Ieval#ieval{level=Le+1}),
- pop(),
- trace(return, {Le,Val}),
- {value, Val, Bs0};
+ [{clause,FcLine,_,_,_}|_]=Cs ->
+ fnk_clauses(Cs, As0, erl_eval:new_bindings(),
+ Ieval#ieval{line=FcLine});
- not_interpreted when Lc -> % We are leaving interpreted code
+ not_interpreted when Top -> % We are leaving interpreted code
{value, {dbg_apply,Mod,Name,As0}, Bs0};
not_interpreted ->
- {value, Val, _Bs} =
- debugged_cmd({apply,Mod,Name,As0}, Bs0,
- Ieval#ieval{level=Le+1}),
- pop(),
- trace(return, {Le,Val}),
- {value, Val, Bs0};
+ debugged_cmd({apply,Mod,Name,As0}, Bs0, Ieval);
undef ->
- exception(error, undef, Bs0, Ieval)
+ exception(error, undef, Bs0, Ieval, true)
end.
lambda(eval_fun, [Cs,As,Bs,{Mod,Name}=F]) ->
@@ -752,23 +573,21 @@ cached(Key) ->
%% Try to find a matching function clause
%% #ieval.level is set, the other fields must be set in this function
-fnk_clauses([{clause,Line,Pars,Gs,Body}|Cs], M, F, As, Bs0, Ieval) ->
+fnk_clauses([{clause,Line,Pars,Gs,Body}|Cs], As, Bs0, Ieval) ->
case head_match(Pars, As, [], Bs0) of
{match,Bs1} ->
Bs = add_bindings(Bs1, Bs0),
case guard(Gs, Bs) of
true ->
- seq(Body, Bs,
- Ieval#ieval{line=Line,
- module=M,function=F,arguments=As});
+ seq(Body, Bs, Ieval#ieval{line=Line});
false ->
- fnk_clauses(Cs, M, F, As, Bs0, Ieval)
+ fnk_clauses(Cs, As, Bs0, Ieval)
end;
nomatch ->
- fnk_clauses(Cs, M, F, As, Bs0, Ieval)
+ fnk_clauses(Cs, As, Bs0, Ieval)
end;
-fnk_clauses([], _M, _F, _As, Bs, Ieval) ->
- exception(error, function_clause, Bs, Ieval).
+fnk_clauses([], _As, Bs, Ieval) ->
+ exception(error, function_clause, Bs, Ieval, true).
seq([E], Bs0, Ieval) ->
case dbg_icmd:cmd(E, Bs0, Ieval) of
@@ -782,7 +601,7 @@ seq([E|Es], Bs0, Ieval) ->
{skip,Bs} ->
seq(Es, Bs, Ieval);
Bs1 ->
- {value,_,Bs} = expr(E, Bs1, Ieval#ieval{last_call=false}),
+ {value,_,Bs} = expr(E, Bs1, Ieval#ieval{top=false}),
seq(Es, Bs, Ieval)
end;
seq([], Bs, _) ->
@@ -804,10 +623,9 @@ expr({value,Val}, Bs, _Ieval) -> % Special case straight values
%% List
expr({cons,Line,H0,T0}, Bs0, Ieval0) ->
- Ieval = Ieval0#ieval{line=Line},
- Ieval1 = Ieval#ieval{last_call=false},
- {value,H,Bs1} = expr(H0,Bs0,Ieval1),
- {value,T,Bs2} = expr(T0,Bs0,Ieval1),
+ Ieval = Ieval0#ieval{line=Line,top=false},
+ {value,H,Bs1} = expr(H0, Bs0, Ieval),
+ {value,T,Bs2} = expr(T0, Bs0, Ieval),
{value,[H|T],merge_bindings(Bs2, Bs1, Ieval)};
%% Tuple
@@ -821,12 +639,12 @@ expr({block,Line,Es},Bs,Ieval) ->
%% Catch statement
expr({'catch',Line,Expr}, Bs0, Ieval) ->
- try expr(Expr, Bs0, Ieval#ieval{line=Line, last_call=false})
+ try expr(Expr, Bs0, Ieval#ieval{line=Line, top=false})
catch
Class:Reason ->
%% Exception caught, reset exit info
put(exit_info, undefined),
- pop(Ieval#ieval.level),
+ dbg_istk:pop(Ieval#ieval.level),
Value = catch_value(Class, Reason),
trace(return, {Ieval#ieval.level,Value}),
{value, Value, Bs0}
@@ -835,7 +653,7 @@ expr({'catch',Line,Expr}, Bs0, Ieval) ->
%% Try-catch statement
expr({'try',Line,Es,CaseCs,CatchCs,[]}, Bs0, Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
- try seq(Es, Bs0, Ieval#ieval{last_call=false}) of
+ try seq(Es, Bs0, Ieval#ieval{top=false}) of
{value,Val,Bs} = Value ->
case CaseCs of
[] -> Value;
@@ -848,7 +666,7 @@ expr({'try',Line,Es,CaseCs,CatchCs,[]}, Bs0, Ieval0) ->
end;
expr({'try',Line,Es,CaseCs,CatchCs,As}, Bs0, Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
- try seq(Es, Bs0, Ieval#ieval{last_call=false}) of
+ try seq(Es, Bs0, Ieval#ieval{top=false}) of
{value,Val,Bs} = Value ->
case CaseCs of
[] -> Value;
@@ -859,13 +677,13 @@ expr({'try',Line,Es,CaseCs,CatchCs,As}, Bs0, Ieval0) ->
Class:Reason when CatchCs =/= [] ->
catch_clauses({Class,Reason,[]}, CatchCs, Bs0, Ieval)
after
- seq(As, Bs0, Ieval#ieval{last_call=false})
+ seq(As, Bs0, Ieval#ieval{top=false})
end;
%% Case statement
expr({'case',Line,E,Cs}, Bs0, Ieval) ->
{value,Val,Bs} =
- expr(E, Bs0, Ieval#ieval{line=Line, last_call=false}),
+ expr(E, Bs0, Ieval#ieval{line=Line, top=false}),
case_clauses(Val, Cs, Bs, case_clause, Ieval#ieval{line=Line});
%% If statement
@@ -874,20 +692,20 @@ expr({'if',Line,Cs}, Bs, Ieval) ->
%% Andalso/orelse
expr({'andalso',Line,E1,E2}, Bs, Ieval) ->
- case expr(E1, Bs, Ieval#ieval{line=Line, last_call=false}) of
+ case expr(E1, Bs, Ieval#ieval{line=Line, top=false}) of
{value,false,_}=Res ->
Res;
{value,true,_} ->
- expr(E2, Bs, Ieval#ieval{line=Line, last_call=false});
+ expr(E2, Bs, Ieval#ieval{line=Line, top=false});
{value,Val,Bs} ->
exception(error, {badarg,Val}, Bs, Ieval)
end;
expr({'orelse',Line,E1,E2}, Bs, Ieval) ->
- case expr(E1, Bs, Ieval#ieval{line=Line, last_call=false}) of
+ case expr(E1, Bs, Ieval#ieval{line=Line, top=false}) of
{value,true,_}=Res ->
Res;
{value,false,_} ->
- expr(E2, Bs, Ieval#ieval{line=Line, last_call=false});
+ expr(E2, Bs, Ieval#ieval{line=Line, top=false});
{value,Val,_} ->
exception(error, {badarg,Val}, Bs, Ieval)
end;
@@ -895,7 +713,7 @@ expr({'orelse',Line,E1,E2}, Bs, Ieval) ->
%% Matching expression
expr({match,Line,Lhs,Rhs0}, Bs0, Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
- {value,Rhs,Bs1} = expr(Rhs0, Bs0, Ieval#ieval{last_call=false}),
+ {value,Rhs,Bs1} = expr(Rhs0, Bs0, Ieval#ieval{top=false}),
case match(Lhs, Rhs, Bs1) of
{match,Bs} ->
{value,Rhs,Bs};
@@ -950,22 +768,37 @@ expr({make_fun,Line,Name,Cs}, Bs, #ieval{module=Module}=Ieval) ->
end,
{value,Fun,Bs};
+%% Construct an external fun.
+expr({make_ext_fun,Line,MFA0}, Bs0, Ieval0) ->
+ {[M,F,A],Bs} = eval_list(MFA0, Bs0, Ieval0),
+ try erlang:make_fun(M, F, A) of
+ Value ->
+ {value,Value,Bs}
+ catch
+ error:badarg ->
+ Ieval1 = Ieval0#ieval{line=Line},
+ Ieval2 = dbg_istk:push(Bs0, Ieval1, false),
+ Ieval = Ieval2#ieval{module=erlang,function=make_fun,
+ arguments=[M,F,A],line=-1},
+ exception(error, badarg, Bs, Ieval, true)
+ end;
+
%% Common test adaptation
-expr({call_remote,0,ct_line,line,As0}, Bs0, Ieval0) ->
+expr({call_remote,0,ct_line,line,As0,Lc}, Bs0, Ieval0) ->
{As,_Bs} = eval_list(As0, Bs0, Ieval0),
- eval_function(ct_line, line, As, Bs0, extern, Ieval0);
+ eval_function(ct_line, line, As, Bs0, extern, Ieval0, Lc);
%% Local function call
-expr({local_call,Line,F,As0}, Bs0, #ieval{module=M} = Ieval0) ->
+expr({local_call,Line,F,As0,Lc}, Bs0, #ieval{module=M} = Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
{As,Bs} = eval_list(As0, Bs0, Ieval),
- eval_function(M, F, As, Bs, local, Ieval);
+ eval_function(M, F, As, Bs, local, Ieval, Lc);
%% Remote function call
-expr({call_remote,Line,M,F,As0}, Bs0, Ieval0) ->
+expr({call_remote,Line,M,F,As0,Lc}, Bs0, Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
{As,Bs} = eval_list(As0, Bs0, Ieval),
- eval_function(M, F, As, Bs, extern, Ieval);
+ eval_function(M, F, As, Bs, extern, Ieval, Lc);
%% Emulated semantics of some BIFs
expr({dbg,Line,self,[]}, Bs, #ieval{level=Le}) ->
@@ -975,9 +808,28 @@ expr({dbg,Line,self,[]}, Bs, #ieval{level=Le}) ->
{value,Self,Bs};
expr({dbg,Line,get_stacktrace,[]}, Bs, #ieval{level=Le}) ->
trace(bif, {Le,Line,erlang,get_stacktrace,[]}),
- Stacktrace = get(stacktrace),
+ Stacktrace = get_stacktrace(),
trace(return, {Le,Stacktrace}),
{value,Stacktrace,Bs};
+expr({dbg,Line,raise,As0}, Bs0, #ieval{level=Le}=Ieval0) ->
+ %% Since erlang:get_stacktrace/0 is emulated, we will
+ %% need to emulate erlang:raise/3 too so that we can
+ %% capture the stacktrace.
+ Ieval = Ieval0#ieval{line=Line},
+ {[Class,Reason,Stk0]=As,Bs} = eval_list(As0, Bs0, Ieval),
+ trace(bif, {Le,Line,erlang,raise,As}),
+ try
+ %% Evaluate raise/3 for error checking and
+ %% truncating of the stacktrace to the correct depth.
+ Error = erlang:raise(Class, Reason, Stk0),
+ trace(return, {Le,Error}),
+ {value,Error,Bs}
+ catch
+ _:_ ->
+ Stk = erlang:get_stacktrace(), %Possibly truncated.
+ StkFun = fun(_) -> Stk end,
+ do_exception(Class, Reason, StkFun, Bs, Ieval)
+ end;
expr({dbg,Line,throw,As0}, Bs0, #ieval{level=Le}=Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
{[Term],Bs} = eval_list(As0, Bs0, Ieval),
@@ -988,11 +840,6 @@ expr({dbg,Line,error,As0}, Bs0, #ieval{level=Le}=Ieval0) ->
{[Term],Bs} = eval_list(As0, Bs0, Ieval),
trace(bif, {Le,Line,erlang,error,[Term]}),
exception(error, Term, Bs, Ieval);
-expr({dbg,Line,fault,As0}, Bs0, #ieval{level=Le}=Ieval0) ->
- Ieval = Ieval0#ieval{line=Line},
- {[Term],Bs} = eval_list(As0, Bs0, Ieval),
- trace(bif, {Le,Line,erlang,fault,[Term]}),
- exception(fault, Term, Bs, Ieval);
expr({dbg,Line,exit,As0}, Bs0, #ieval{level=Le}=Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
{[Term],Bs} = eval_list(As0, Bs0, Ieval),
@@ -1001,36 +848,26 @@ expr({dbg,Line,exit,As0}, Bs0, #ieval{level=Le}=Ieval0) ->
%% Call to "safe" BIF, ie a BIF that can be executed in Meta process
expr({safe_bif,Line,M,F,As0}, Bs0, #ieval{level=Le}=Ieval0) ->
- Ieval = Ieval0#ieval{line=Line},
- {As,Bs} = eval_list(As0, Bs0, Ieval),
+ Ieval1 = Ieval0#ieval{line=Line},
+ {As,Bs} = eval_list(As0, Bs0, Ieval1),
trace(bif, {Le,Line,M,F,As}),
- push({M,F,As}, Bs0, Ieval),
+ Ieval2 = dbg_istk:push(Bs0, Ieval1, false),
+ Ieval = Ieval2#ieval{module=M,function=F,arguments=As,line=-1},
{_,Value,_} = Res = safe_bif(M, F, As, Bs, Ieval),
trace(return, {Le,Value}),
- pop(),
+ dbg_istk:pop(),
Res;
%% Call to a BIF that must be evaluated in the correct process
expr({bif,Line,M,F,As0}, Bs0, #ieval{level=Le}=Ieval0) ->
- Ieval = Ieval0#ieval{line=Line},
- {As,Bs} = eval_list(As0, Bs0, Ieval),
+ Ieval1 = Ieval0#ieval{line=Line},
+ {As,Bs} = eval_list(As0, Bs0, Ieval1),
trace(bif, {Le,Line,M,F,As}),
- push({M,F,As}, Bs0, Ieval),
- {_,Value,_} =
- Res = debugged_cmd({apply,M,F,As}, Bs, Ieval#ieval{level=Le+1}),
+ Ieval2 = dbg_istk:push(Bs0, Ieval1, false),
+ Ieval = Ieval2#ieval{module=M,function=F,arguments=As,line=-1},
+ {_,Value,_} = Res = debugged_cmd({apply,M,F,As}, Bs, Ieval),
trace(return, {Le,Value}),
- pop(),
- Res;
-
-%% Call to a BIF that spawns a new process
-expr({spawn_bif,Line,M,F,As0}, Bs0, #ieval{level=Le}=Ieval0) ->
- Ieval = Ieval0#ieval{line=Line},
- {As,Bs} = eval_list(As0, Bs0, Ieval),
- trace(bif, {Le,Line,M,F,As}),
- push({M,F,As}, Bs0, Ieval),
- Res = debugged_cmd({apply,M,F,As}, Bs,Ieval#ieval{level=Le+1}),
- trace(return, {Le,Res}),
- pop(),
+ dbg_istk:pop(),
Res;
%% Call to an operation
@@ -1046,7 +883,7 @@ expr({op,Line,Op,As0}, Bs0, Ieval0) ->
end;
%% apply/2 (fun)
-expr({apply_fun,Line,Fun0,As0}, Bs0, #ieval{level=Le}=Ieval0) ->
+expr({apply_fun,Line,Fun0,As0,Lc}, Bs0, #ieval{level=Le}=Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
FunValue = case expr(Fun0, Bs0, Ieval) of
{value,{dbg_apply,Mx,Fx,Asx},Bsx} ->
@@ -1058,31 +895,20 @@ expr({apply_fun,Line,Fun0,As0}, Bs0, #ieval{level=Le}=Ieval0) ->
case FunValue of
{value,Fun,Bs1} when is_function(Fun) ->
{As,Bs} = eval_list(As0, Bs1, Ieval),
- eval_function(undefined, Fun, As, Bs, extern, Ieval);
+ eval_function(undefined, Fun, As, Bs, extern, Ieval, Lc);
{value,{M,F},Bs1} when is_atom(M), is_atom(F) ->
{As,Bs} = eval_list(As0, Bs1, Ieval),
- eval_function(M, F, As, Bs, extern, Ieval);
+ eval_function(M, F, As, Bs, extern, Ieval, Lc);
{value,BadFun,Bs1} ->
exception(error, {badfun,BadFun}, Bs1, Ieval)
end;
%% apply/3
-expr({apply,Line,As0}, Bs0, Ieval0) ->
+expr({apply,Line,As0,Lc}, Bs0, Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
{[M,F,As],Bs} = eval_list(As0, Bs0, Ieval),
- eval_function(M, F, As, Bs, extern, Ieval);
+ eval_function(M, F, As, Bs, extern, Ieval, Lc);
-%% Mod:module_info/0,1
-expr({module_info_0,_,Mod}, Bs, _Ieval) ->
- {value,[{compile,module_info(Mod,compile)},
- {attributes,module_info(Mod,attributes)},
- {imports,module_info(Mod,imports)},
- {exports,module_info(Mod,exports)}],Bs};
-expr({module_info_1,Line,Mod,[As0]}, Bs0, Ieval0) ->
- Ieval = Ieval0#ieval{line=Line},
- {value,What,Bs} = expr(As0, Bs0, Ieval),
- {value,module_info(Mod, What),Bs};
-
%% Receive statement
expr({'receive',Line,Cs}, Bs0, #ieval{level=Le}=Ieval) ->
trace(receivex, {Le,false}),
@@ -1091,7 +917,7 @@ expr({'receive',Line,Cs}, Bs0, #ieval{level=Le}=Ieval) ->
%% Receive..after statement
expr({'receive',Line,Cs,To,ToExprs}, Bs0, #ieval{level=Le}=Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
- {value,ToVal,ToBs} = expr(To, Bs0, Ieval#ieval{last_call=false}),
+ {value,ToVal,ToBs} = expr(To, Bs0, Ieval#ieval{top=false}),
trace(receivex, {Le,true}),
check_timeoutvalue(ToVal, ToBs, To, Ieval),
{Stamp,_} = statistics(wall_clock),
@@ -1101,7 +927,7 @@ expr({'receive',Line,Cs,To,ToExprs}, Bs0, #ieval{level=Le}=Ieval0) ->
%% Send (!)
expr({send,Line,To0,Msg0}, Bs0, Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
- Ieval1 = Ieval#ieval{last_call=false},
+ Ieval1 = Ieval#ieval{top=false},
{value,To,Bs1} = expr(To0, Bs0, Ieval1),
{value,Msg,Bs2} = expr(Msg0, Bs0, Ieval1),
Bs = merge_bindings(Bs2, Bs1, Ieval),
@@ -1110,10 +936,15 @@ expr({send,Line,To0,Msg0}, Bs0, Ieval0) ->
%% Binary
expr({bin,Line,Fs}, Bs0, Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
- eval_bits:expr_grp(Fs, Bs0,
- fun (E, B) -> expr(E, B, Ieval) end,
- [],
- false);
+ try
+ eval_bits:expr_grp(Fs, Bs0,
+ fun (E, B) -> expr(E, B, Ieval) end,
+ [],
+ false)
+ catch
+ Class:Reason ->
+ exception(Class, Reason, Bs0, Ieval)
+ end;
%% List comprehension
expr({lc,_Line,E,Qs}, Bs, Ieval) ->
@@ -1138,12 +969,12 @@ eval_lc(E, Qs, Bs, Ieval) ->
eval_lc1(E, [{generate,Line,P,L0}|Qs], Bs0, Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
- {value,L1,Bs1} = expr(L0, Bs0, Ieval#ieval{last_call=false}),
+ {value,L1,Bs1} = expr(L0, Bs0, Ieval#ieval{top=false}),
CompFun = fun(NewBs) -> eval_lc1(E, Qs, NewBs, Ieval) end,
eval_generate(L1, P, Bs1, CompFun, Ieval);
eval_lc1(E, [{b_generate,Line,P,L0}|Qs], Bs0, Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
- {value,Bin,_} = expr(L0, Bs0, Ieval#ieval{last_call=false}),
+ {value,Bin,_} = expr(L0, Bs0, Ieval#ieval{top=false}),
CompFun = fun(NewBs) -> eval_lc1(E, Qs, NewBs, Ieval) end,
eval_b_generate(Bin, P, Bs0, CompFun, Ieval);
eval_lc1(E, [{guard,Q}|Qs], Bs0, Ieval) ->
@@ -1152,13 +983,13 @@ eval_lc1(E, [{guard,Q}|Qs], Bs0, Ieval) ->
false -> []
end;
eval_lc1(E, [Q|Qs], Bs0, Ieval) ->
- case expr(Q, Bs0, Ieval#ieval{last_call=false}) of
+ case expr(Q, Bs0, Ieval#ieval{top=false}) of
{value,true,Bs} -> eval_lc1(E, Qs, Bs, Ieval);
{value,false,_Bs} -> [];
{value,V,Bs} -> exception(error, {bad_filter,V}, Bs, Ieval)
end;
eval_lc1(E, [], Bs, Ieval) ->
- {value,V,_} = expr(E, Bs, Ieval#ieval{last_call=false}),
+ {value,V,_} = expr(E, Bs, Ieval#ieval{top=false}),
[V].
%% eval_bc(Expr,[Qualifier],Bindings,IevalState) ->
@@ -1171,12 +1002,12 @@ eval_bc(E, Qs, Bs, Ieval) ->
eval_bc1(E, [{generate,Line,P,L0}|Qs], Bs0, Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
- {value,L1,Bs1} = expr(L0, Bs0, Ieval#ieval{last_call=false}),
+ {value,L1,Bs1} = expr(L0, Bs0, Ieval#ieval{top=false}),
CompFun = fun(NewBs) -> eval_bc1(E, Qs, NewBs, Ieval) end,
eval_generate(L1, P, Bs1, CompFun, Ieval);
eval_bc1(E, [{b_generate,Line,P,L0}|Qs], Bs0, Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
- {value,Bin,_} = expr(L0, Bs0, Ieval#ieval{last_call=false}),
+ {value,Bin,_} = expr(L0, Bs0, Ieval#ieval{top=false}),
CompFun = fun(NewBs) -> eval_bc1(E, Qs, NewBs, Ieval) end,
eval_b_generate(Bin, P, Bs0, CompFun, Ieval);
eval_bc1(E, [{guard,Q}|Qs], Bs0, Ieval) ->
@@ -1185,13 +1016,13 @@ eval_bc1(E, [{guard,Q}|Qs], Bs0, Ieval) ->
false -> []
end;
eval_bc1(E, [Q|Qs], Bs0, Ieval) ->
- case expr(Q, Bs0, Ieval#ieval{last_call=false}) of
+ case expr(Q, Bs0, Ieval#ieval{top=false}) of
{value,true,Bs} -> eval_bc1(E, Qs, Bs, Ieval);
{value,false,_Bs} -> [];
{value,V,Bs} -> exception(error, {bad_filter,V}, Bs, Ieval)
end;
eval_bc1(E, [], Bs, Ieval) ->
- {value,V,_} = expr(E, Bs, Ieval#ieval{last_call=false}),
+ {value,V,_} = expr(E, Bs, Ieval#ieval{top=false}),
[V].
eval_generate([V|Rest], P, Bs0, CompFun, Ieval) ->
@@ -1208,7 +1039,7 @@ eval_generate(Term, _P, Bs, _CompFun, Ieval) ->
exception(error, {bad_generator,Term}, Bs, Ieval).
eval_b_generate(<<_/bitstring>>=Bin, P, Bs0, CompFun, Ieval) ->
- Mfun = fun(L, R, Bs) -> match1(L, R, Bs, Bs0) end,
+ Mfun = match_fun(Bs0),
Efun = fun(Exp, Bs) -> expr(Exp, Bs, #ieval{}) end,
case eval_bits:bin_gen(P, Bin, erl_eval:new_bindings(), Bs0, Mfun, Efun) of
{match,Rest,Bs1} ->
@@ -1222,24 +1053,13 @@ eval_b_generate(<<_/bitstring>>=Bin, P, Bs0, CompFun, Ieval) ->
eval_b_generate(Term, _P, Bs, _CompFun, Ieval) ->
exception(error, {bad_generator,Term}, Bs, Ieval).
-module_info(Mod, module) -> Mod;
-module_info(_Mod, compile) -> [];
-module_info(Mod, attributes) ->
- {ok, Attr} = dbg_iserver:call(get(int), {lookup, Mod, attributes}),
- Attr;
-module_info(_Mod, imports) -> [];
-module_info(Mod, exports) ->
- {ok, Exp} = dbg_iserver:call(get(int), {lookup, Mod, exports}),
- Exp;
-module_info(_Mod, functions) -> [].
-
safe_bif(M, F, As, Bs, Ieval) ->
try apply(M, F, As) of
Value ->
{value,Value,Bs}
catch
Class:Reason ->
- exception(Class, Reason, Bs, Ieval)
+ exception(Class, Reason, Bs, Ieval, true)
end.
eval_send(To, Msg, Bs, Ieval) ->
@@ -1408,12 +1228,12 @@ flush_traces(Debugged) ->
%% eval_list(ExpressionList, Bindings, Ieval)
%% Evaluate a list of expressions "in parallel" at the same level.
eval_list(Es, Bs, Ieval) ->
- eval_list(Es, [], Bs, Bs, Ieval).
+ eval_list_1(Es, [], Bs, Bs, Ieval#ieval{top=false}).
-eval_list([E|Es], Vs, BsOrig, Bs0, Ieval) ->
- {value,V,Bs1} = expr(E, BsOrig, Ieval#ieval{last_call=false}),
- eval_list(Es, [V|Vs], BsOrig, merge_bindings(Bs1,Bs0,Ieval), Ieval);
-eval_list([], Vs, _, Bs, _Ieval) ->
+eval_list_1([E|Es], Vs, BsOrig, Bs0, Ieval) ->
+ {value,V,Bs1} = expr(E, BsOrig, Ieval),
+ eval_list_1(Es, [V|Vs], BsOrig, merge_bindings(Bs1, Bs0, Ieval), Ieval);
+eval_list_1([], Vs, _, Bs, _Ieval) ->
{lists:reverse(Vs,[]),Bs}.
%% if_clauses(Clauses, Bindings, Ieval)
@@ -1453,7 +1273,7 @@ catch_clauses(Exception, [{clause,_,[P],G,B}|CatchCs], Bs0, Ieval) ->
true ->
%% Exception caught, reset exit info
put(exit_info, undefined),
- pop(Ieval#ieval.level),
+ dbg_istk:pop(Ieval#ieval.level),
seq(B, Bs, Ieval);
false ->
catch_clauses(Exception, CatchCs, Bs0, Ieval)
@@ -1588,11 +1408,9 @@ match1({cons,_,H,T}, [H1|T1], Bs0, BBs) ->
match1({tuple,_,Elts}, Tuple, Bs, BBs)
when length(Elts) =:= tuple_size(Tuple) ->
match_tuple(Elts, Tuple, 1, Bs, BBs);
-match1({bin,_,Fs}, B, Bs0, BBs0) when is_bitstring(B) ->
- Bs1 = lists:sort(Bs0), %Kludge.
- BBs = lists:sort(BBs0),
- try eval_bits:match_bits(Fs, B, Bs1, BBs,
- fun(L, R, Bs) -> match1(L, R, Bs, BBs) end,
+match1({bin,_,Fs}, B, Bs0, BBs) when is_bitstring(B) ->
+ try eval_bits:match_bits(Fs, B, Bs0, BBs,
+ match_fun(BBs),
fun(E, Bs) -> expr(E, Bs, #ieval{}) end,
false)
catch
@@ -1601,6 +1419,12 @@ match1({bin,_,Fs}, B, Bs0, BBs0) when is_bitstring(B) ->
match1(_,_,_,_) ->
throw(nomatch).
+match_fun(BBs) ->
+ fun(match, {L,R,Bs}) -> match1(L, R, Bs, BBs);
+ (binding, {Name,Bs}) -> binding(Name, Bs);
+ (add_binding, {Name,Val,Bs}) -> add_binding(Name, Val, Bs)
+ end.
+
match_tuple([E|Es], Tuple, I, Bs0, BBs) ->
{match,Bs} = match1(E, element(I, Tuple), Bs0, BBs),
match_tuple(Es, Tuple, I+1, Bs, BBs);
@@ -1731,3 +1555,19 @@ add_binding(N,Val,[B1|Bs]) ->
[B1|add_binding(N,Val,Bs)];
add_binding(N,Val,[]) ->
[{N,Val}].
+
+%% get_stacktrace() -> Stacktrace
+%% Return the latest stacktrace for the process.
+get_stacktrace() ->
+ case get(stacktrace) of
+ MakeStk when is_function(MakeStk, 1) ->
+ %% The stacktrace has not been constructed before.
+ %% Construct it and remember the result.
+ Depth = erlang:system_flag(backtrace_depth, 8),
+ erlang:system_flag(backtrace_depth, Depth),
+ Stk = MakeStk(Depth),
+ put(stacktrace, Stk),
+ Stk;
+ Stk when is_list(Stk) ->
+ Stk
+ end.
diff --git a/lib/debugger/src/dbg_ieval.hrl b/lib/debugger/src/dbg_ieval.hrl
index a344748f48..ea6189ad02 100644
--- a/lib/debugger/src/dbg_ieval.hrl
+++ b/lib/debugger/src/dbg_ieval.hrl
@@ -21,6 +21,8 @@
module, % MFA which called the currently
function, % interpreted function
arguments, %
- last_call = false % True if current expression is
- }). % the VERY last to be evaluated
- % (ie at all, not only in a clause)
+
+ %% True if the current expression is at the top level
+ %% (i.e. the next call will leave interpreted code).
+ top = false
+ }).
diff --git a/lib/debugger/src/dbg_iload.erl b/lib/debugger/src/dbg_iload.erl
index 2ae0c333da..3c95ef8068 100644
--- a/lib/debugger/src/dbg_iload.erl
+++ b/lib/debugger/src/dbg_iload.erl
@@ -62,22 +62,23 @@ load_mod1(Mod, File, Binary, Db) ->
store_module(Mod, File, Binary, Db) ->
{interpreter_module, Exp, Abst, Src, MD5} = binary_to_term(Binary),
Forms = case abstr(Abst) of
- {abstract_v1,Forms0} -> Forms0;
- {abstract_v2,Forms0} -> Forms0;
+ {abstract_v1,_} ->
+ exit({Mod,too_old_beam_file});
+ {abstract_v2,_} ->
+ exit({Mod,too_old_beam_file});
{raw_abstract_v1,Code0} ->
Code = interpret_file_attribute(Code0),
{_,_,Forms0,_} = sys_pre_expand:module(Code, []),
Forms0
end,
dbg_idb:insert(Db, mod_file, File),
- dbg_idb:insert(Db, exports, Exp),
dbg_idb:insert(Db, defs, []),
put(vcount, 0),
put(fun_count, 0),
put(funs, []),
put(mod_md5, MD5),
- Attr = store_forms(Forms, Mod, Db, Exp, []),
+ store_forms(Forms, Mod, Db, Exp),
erase(mod_md5),
erase(current_function),
%% store_funs(Db, Mod),
@@ -85,11 +86,10 @@ store_module(Mod, File, Binary, Db) ->
erase(funs),
erase(fun_count),
- dbg_idb:insert(Db, attributes, Attr),
NewBinary = store_mod_line_no(Mod, Db, binary_to_list(Src)),
dbg_idb:insert(Db, mod_bin, NewBinary),
- dbg_idb:insert(Db, mod_raw, <<Src/binary,0:8>>), %% Add eos
- dbg_idb:insert(Db, module, Mod).
+ dbg_idb:insert(Db, mod_raw, <<Src/binary,0:8>>). %% Add eos
+
%% Adjust line numbers using the file/2 attribute.
%% Also take the absolute value of line numbers.
%% This simple fix will make the marker point at the correct line
@@ -111,27 +111,19 @@ abstr(Term) -> Term.
% store_funs_1(Fs, Db, Mod);
% store_funs_1([], _, _) -> ok.
-store_forms([{function,_,module_info,0,_}|Fs], Mod, Db, Exp, Attr) ->
- Cs = [{clause,0,[],[], [{module_info_0,0,Mod}]}],
- dbg_idb:insert(Db, {Mod,module_info,0,true}, Cs),
- store_forms(Fs, Mod, Db, Exp, Attr);
-store_forms([{function,_,module_info,1,_}|Fs], Mod, Db, Exp, Attr) ->
- Cs = [{clause,0,[{var,0,'What'}],[], [{module_info_1,0,Mod,[{var,0,'What'}]}]}],
- dbg_idb:insert(Db, {Mod,module_info,1,true}, Cs),
- store_forms(Fs, Mod, Db, Exp, Attr);
-store_forms([{function,_,Name,Arity,Cs0}|Fs], Mod, Db, Exp, Attr) ->
+store_forms([{function,_,Name,Arity,Cs0}|Fs], Mod, Db, Exp) ->
FA = {Name,Arity},
put(current_function, FA),
Cs = clauses(Cs0),
Exported = lists:member(FA, Exp),
dbg_idb:insert(Db, {Mod,Name,Arity,Exported}, Cs),
- store_forms(Fs, Mod, Db, Exp, Attr);
-store_forms([{attribute,_,Name,Val}|Fs], Mod, Db, Exp, Attr) ->
- store_forms(Fs, Mod, Db, Exp, [{Name,Val}|Attr]);
-store_forms([F|_], _Mod, _Db, _Exp, _Attr) ->
+ store_forms(Fs, Mod, Db, Exp);
+store_forms([{attribute,_,_Name,_Val}|Fs], Mod, Db, Exp) ->
+ store_forms(Fs, Mod, Db, Exp);
+store_forms([F|_], _Mod, _Db, _Exp) ->
exit({unknown_form,F});
-store_forms([], _, _, _, Attr) ->
- lists:reverse(Attr).
+store_forms([], _, _, _) ->
+ ok.
store_mod_line_no(Mod, Db, Contents) ->
store_mod_line_no(Mod, Db, Contents, 1, 0, []).
@@ -164,14 +156,14 @@ get_nl([],Pos,Head) -> {lists:reverse(Head),[],Pos}.
%%% to interpret.
clauses([C0|Cs]) ->
- C1 = clause(C0),
+ C1 = clause(C0, true),
[C1|clauses(Cs)];
clauses([]) -> [].
-clause({clause,Line,H0,G0,B0}) ->
+clause({clause,Line,H0,G0,B0}, Lc) ->
H1 = head(H0),
G1 = guard(G0),
- B1 = exprs(B0),
+ B1 = exprs(B0, Lc),
{clause,Line,H1,G1,B1}.
head(Ps) -> patterns(Ps).
@@ -219,7 +211,7 @@ pattern({bin,Line,Grp}) ->
{bin,Line,Grp1};
pattern({bin_element,Line,Expr,Size,Type}) ->
Expr1 = pattern(Expr),
- Size1 = expr(Size),
+ Size1 = expr(Size, false),
{bin_element,Line,Expr1,Size1,Type}.
%% These patterns are processed "in parallel" for purposes of variable
@@ -235,8 +227,6 @@ guard([G0|Gs]) ->
[G1|guard(Gs)];
guard([]) -> [].
-and_guard([{atom,_,true}|Gs]) ->
- and_guard(Gs);
and_guard([G0|Gs]) ->
G1 = guard_test(G0),
[G1|and_guard(Gs)];
@@ -244,12 +234,7 @@ and_guard([]) -> [].
guard_test({call,Line,{remote,_,{atom,_,erlang},{atom,_,F}},As0}) ->
As = gexpr_list(As0),
- case map_guard_bif(F, length(As0)) of
- {ok,Name} ->
- {safe_bif,Line,erlang,Name,As};
- error ->
- {safe_bif,Line,erlang,F,As}
- end;
+ {safe_bif,Line,erlang,F,As};
guard_test({op,Line,Op,L0}) ->
true = erl_internal:arith_op(Op, 1) orelse %Assertion.
erl_internal:bool_op(Op, 1),
@@ -266,25 +251,18 @@ guard_test({op,Line,Op,L0,R0}) ->
L1 = gexpr(L0),
R1 = gexpr(R0), %They see the same variables
{safe_bif,Line,erlang,Op,[L1,R1]};
-guard_test({integer,_,_}=I) -> I;
-guard_test({char,_,_}=C) -> C;
-guard_test({float,_,_}=F) -> F;
-guard_test({atom,_,_}=A) -> A;
-guard_test({nil,_}=N) -> N;
-guard_test({var,_,_}=V) ->V. % Boolean var
-
-map_guard_bif(integer, 1) -> {ok,is_integer};
-map_guard_bif(float, 1) -> {ok,is_float};
-map_guard_bif(number, 1) -> {ok,is_number};
-map_guard_bif(atom, 1) -> {ok,is_atom};
-map_guard_bif(list, 1) -> {ok,is_list};
-map_guard_bif(tuple, 1) -> {ok,is_tuple};
-map_guard_bif(pid, 1) -> {ok,is_pid};
-map_guard_bif(reference, 1) -> {ok,is_reference};
-map_guard_bif(port, 1) -> {ok,is_port};
-map_guard_bif(binary, 1) -> {ok,is_binary};
-map_guard_bif(function, 1) -> {ok,is_function};
-map_guard_bif(_, _) -> error.
+guard_test({var,_,_}=V) ->V; % Boolean var
+guard_test({atom,Line,true}) -> {value,Line,true};
+%% All other constants at this level means false.
+guard_test({atom,Line,_}) -> {value,Line,false};
+guard_test({integer,Line,_}) -> {value,Line,false};
+guard_test({char,Line,_}) -> {value,Line,false};
+guard_test({float,Line,_}) -> {value,Line,false};
+guard_test({string,Line,_}) -> {value,Line,false};
+guard_test({nil,Line}) -> {value,Line,false};
+guard_test({cons,Line,_,_}) -> {value,Line,false};
+guard_test({tuple,Line,_}) -> {value,Line,false};
+guard_test({bin,Line,_}) -> {value,Line,false}.
gexpr({var,Line,V}) -> {var,Line,V};
gexpr({integer,Line,I}) -> {value,Line,I};
@@ -341,186 +319,187 @@ gexpr_list([]) -> [].
%% These expressions are processed "sequentially" for purposes of variable
%% definition etc.
-exprs([E0|Es]) ->
- E1 = expr(E0),
- [E1|exprs(Es)];
-exprs([]) -> [].
-
-expr({var,Line,V}) -> {var,Line,V};
-expr({integer,Line,I}) -> {value,Line,I};
-expr({char,Line,I}) -> {value,Line,I};
-expr({float,Line,F}) -> {value,Line,F};
-expr({atom,Line,A}) -> {value,Line,A};
-expr({string,Line,S}) -> {value,Line,S};
-expr({nil,Line}) -> {value,Line,[]};
-expr({cons,Line,H0,T0}) ->
- case {expr(H0),expr(T0)} of
+exprs([E], Lc) ->
+ [expr(E, Lc)];
+exprs([E0|Es], Lc) ->
+ E1 = expr(E0, false),
+ [E1|exprs(Es, Lc)];
+exprs([], _Lc) -> [].
+
+expr({var,Line,V}, _Lc) -> {var,Line,V};
+expr({integer,Line,I}, _Lc) -> {value,Line,I};
+expr({char,Line,I}, _Lc) -> {value,Line,I};
+expr({float,Line,F}, _Lc) -> {value,Line,F};
+expr({atom,Line,A}, _Lc) -> {value,Line,A};
+expr({string,Line,S}, _Lc) -> {value,Line,S};
+expr({nil,Line}, _Lc) -> {value,Line,[]};
+expr({cons,Line,H0,T0}, _Lc) ->
+ case {expr(H0, false),expr(T0, false)} of
{{value,Line,H1},{value,Line,T1}} -> {value,Line,[H1|T1]};
{H1,T1} -> {cons,Line,H1,T1}
end;
-expr({tuple,Line,Es0}) ->
+expr({tuple,Line,Es0}, _Lc) ->
Es1 = expr_list(Es0),
{tuple,Line,Es1};
-expr({block,Line,Es0}) ->
+expr({block,Line,Es0}, Lc) ->
%% Unfold block into a sequence.
- Es1 = exprs(Es0),
+ Es1 = exprs(Es0, Lc),
{block,Line,Es1};
-expr({'if',Line,Cs0}) ->
- Cs1 = icr_clauses(Cs0),
+expr({'if',Line,Cs0}, Lc) ->
+ Cs1 = icr_clauses(Cs0, Lc),
{'if',Line,Cs1};
-expr({'case',Line,E0,Cs0}) ->
- E1 = expr(E0),
- Cs1 = icr_clauses(Cs0),
+expr({'case',Line,E0,Cs0}, Lc) ->
+ E1 = expr(E0, false),
+ Cs1 = icr_clauses(Cs0, Lc),
{'case',Line,E1,Cs1};
-expr({'receive',Line,Cs0}) ->
- Cs1 = icr_clauses(Cs0),
+expr({'receive',Line,Cs0}, Lc) ->
+ Cs1 = icr_clauses(Cs0, Lc),
{'receive',Line,Cs1};
-expr({'receive',Line,Cs0,To0,ToEs0}) ->
- To1 = expr(To0),
- ToEs1 = exprs(ToEs0),
- Cs1 = icr_clauses(Cs0),
+expr({'receive',Line,Cs0,To0,ToEs0}, Lc) ->
+ To1 = expr(To0, false),
+ ToEs1 = exprs(ToEs0, Lc),
+ Cs1 = icr_clauses(Cs0, Lc),
{'receive',Line,Cs1,To1,ToEs1};
-expr({'fun',Line,{clauses,Cs0},{_,_,Name}}) when is_atom(Name) ->
+expr({'fun',Line,{clauses,Cs0},{_,_,Name}}, _Lc) when is_atom(Name) ->
%% New R10B-2 format (abstract_v2).
Cs = fun_clauses(Cs0),
{make_fun,Line,Name,Cs};
-expr({'fun',Line,{clauses,Cs0},{_,_,_,_,Name}}) when is_atom(Name) ->
- %% New R8 format (abstract_v2).
- Cs = fun_clauses(Cs0),
- {make_fun,Line,Name,Cs};
-expr({'fun',Line,{function,F,A},{_Index,_OldUniq,Name}}) ->
+expr({'fun',Line,{function,F,A},{_Index,_OldUniq,Name}}, _Lc) ->
%% New R8 format (abstract_v2).
As = new_vars(A, Line),
- Cs = [{clause,Line,As,[],[{local_call,Line,F,As}]}],
+ Cs = [{clause,Line,As,[],[{local_call,Line,F,As,true}]}],
{make_fun,Line,Name,Cs};
-expr({'fun',_,{clauses,_},{_OldUniq,_Hvss,_Free}}) ->
- %% Old format (abstract_v1).
- exit({?MODULE,old_funs});
-expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,self}},[]}) ->
+expr({'fun',Line,{function,{atom,_,M},{atom,_,F},{integer,_,A}}}, _Lc)
+ when 0 =< A, A =< 255 ->
+ %% New format in R15 for fun M:F/A (literal values).
+ {value,Line,erlang:make_fun(M, F, A)};
+expr({'fun',Line,{function,M,F,A}}, _Lc) ->
+ %% New format in R15 for fun M:F/A (one or more variables).
+ MFA = expr_list([M,F,A]),
+ {make_ext_fun,Line,MFA};
+expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,self}},[]}, _Lc) ->
{dbg,Line,self,[]};
-expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,get_stacktrace}},[]}) ->
+expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,get_stacktrace}},[]}, _Lc) ->
{dbg,Line,get_stacktrace,[]};
-expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,throw}},[_]=As}) ->
+expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,throw}},[_]=As}, _Lc) ->
{dbg,Line,throw,expr_list(As)};
-expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,error}},[_]=As}) ->
+expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,error}},[_]=As}, _Lc) ->
{dbg,Line,error,expr_list(As)};
-expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,fault}},[_]=As}) ->
- {dbg,Line,fault,expr_list(As)};
-expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,exit}},[_]=As}) ->
+expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,exit}},[_]=As}, _Lc) ->
{dbg,Line,exit,expr_list(As)};
-expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,apply}},[_,_,_]=As0}) ->
+expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,raise}},[_,_,_]=As}, _Lc) ->
+ {dbg,Line,raise,expr_list(As)};
+expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,apply}},[_,_,_]=As0}, Lc) ->
As = expr_list(As0),
- {apply,Line,As};
-expr({call,Line,{remote,_,{atom,_,Mod},{atom,_,Func}},As0}) ->
+ {apply,Line,As,Lc};
+expr({call,Line,{remote,_,{atom,_,Mod},{atom,_,Func}},As0}, Lc) ->
As = expr_list(As0),
case erlang:is_builtin(Mod, Func, length(As)) of
false ->
- {call_remote,Line,Mod,Func,As};
+ {call_remote,Line,Mod,Func,As,Lc};
true ->
- case bif_type(Mod, Func) of
+ case bif_type(Mod, Func, length(As0)) of
safe -> {safe_bif,Line,Mod,Func,As};
- spawn -> {spawn_bif,Line,Mod,Func,As};
unsafe ->{bif,Line,Mod,Func,As}
end
end;
-expr({call,Line,{remote,_,Mod0,Func0},As0}) ->
+expr({call,Line,{remote,_,Mod0,Func0},As0}, Lc) ->
%% New R8 format (abstract_v2).
- Mod = expr(Mod0),
- Func = expr(Func0),
+ Mod = expr(Mod0, false),
+ Func = expr(Func0, false),
As = consify(expr_list(As0)),
- {apply,Line,[Mod,Func,As]};
-expr({call,Line,{atom,_,Func},As0}) ->
+ {apply,Line,[Mod,Func,As],Lc};
+expr({call,Line,{atom,_,Func},As0}, Lc) ->
As = expr_list(As0),
- {local_call,Line,Func,As};
-expr({call,Line,Fun0,As0}) ->
- Fun = expr(Fun0),
+ {local_call,Line,Func,As,Lc};
+expr({call,Line,Fun0,As0}, Lc) ->
+ Fun = expr(Fun0, false),
As = expr_list(As0),
- {apply_fun,Line,Fun,As};
-expr({'catch',Line,E0}) ->
+ {apply_fun,Line,Fun,As,Lc};
+expr({'catch',Line,E0}, _Lc) ->
%% No new variables added.
- E1 = expr(E0),
+ E1 = expr(E0, false),
{'catch',Line,E1};
-expr({'try',Line,Es0,CaseCs0,CatchCs0,As0}) ->
+expr({'try',Line,Es0,CaseCs0,CatchCs0,As0}, Lc) ->
%% No new variables added.
Es = expr_list(Es0),
- CaseCs = icr_clauses(CaseCs0),
- CatchCs = icr_clauses(CatchCs0),
+ CaseCs = icr_clauses(CaseCs0, Lc),
+ CatchCs = icr_clauses(CatchCs0, Lc),
As = expr_list(As0),
{'try',Line,Es,CaseCs,CatchCs,As};
-expr({'query', Line, E0}) ->
- E = expr(E0),
- {'query', Line, E};
-expr({lc,Line,E0,Gs0}) -> %R8.
+expr({lc,Line,E0,Gs0}, _Lc) -> %R8.
Gs = lists:map(fun ({generate,L,P0,Qs}) ->
- {generate,L,expr(P0),expr(Qs)};
+ {generate,L,expr(P0, false),expr(Qs, false)};
({b_generate,L,P0,Qs}) -> %R12.
- {b_generate,L,expr(P0),expr(Qs)};
+ {b_generate,L,expr(P0, false),expr(Qs, false)};
(Expr) ->
- case is_guard_test(Expr) of
- true -> {guard,[[guard_test(Expr)]]};
- false -> expr(Expr)
+ case is_guard(Expr) of
+ true -> {guard,guard([[Expr]])};
+ false -> expr(Expr, false)
end
end, Gs0),
- {lc,Line,expr(E0),Gs};
-expr({bc,Line,E0,Gs0}) -> %R12.
+ {lc,Line,expr(E0, false),Gs};
+expr({bc,Line,E0,Gs0}, _Lc) -> %R12.
Gs = lists:map(fun ({generate,L,P0,Qs}) ->
- {generate,L,expr(P0),expr(Qs)};
+ {generate,L,expr(P0, false),expr(Qs, false)};
({b_generate,L,P0,Qs}) -> %R12.
- {b_generate,L,expr(P0),expr(Qs)};
+ {b_generate,L,expr(P0, false),expr(Qs, false)};
(Expr) ->
- case is_guard_test(Expr) of
- true -> {guard,[[guard_test(Expr)]]};
- false -> expr(Expr)
+ case is_guard(Expr) of
+ true -> {guard,guard([[Expr]])};
+ false -> expr(Expr, false)
end
end, Gs0),
- {bc,Line,expr(E0),Gs};
-expr({match,Line,P0,E0}) ->
- E1 = expr(E0),
+ {bc,Line,expr(E0, false),Gs};
+expr({match,Line,P0,E0}, _Lc) ->
+ E1 = expr(E0, false),
P1 = pattern(P0),
{match,Line,P1,E1};
-expr({op,Line,Op,A0}) ->
- A1 = expr(A0),
+expr({op,Line,Op,A0}, _Lc) ->
+ A1 = expr(A0, false),
{op,Line,Op,[A1]};
-expr({op,Line,'++',L0,R0}) ->
- L1 = expr(L0),
- R1 = expr(R0), %They see the same variables
+expr({op,Line,'++',L0,R0}, _Lc) ->
+ L1 = expr(L0, false),
+ R1 = expr(R0, false), %They see the same variables
{op,Line,append,[L1,R1]};
-expr({op,Line,'--',L0,R0}) ->
- L1 = expr(L0),
- R1 = expr(R0), %They see the same variables
+expr({op,Line,'--',L0,R0}, _Lc) ->
+ L1 = expr(L0, false),
+ R1 = expr(R0, false), %They see the same variables
{op,Line,subtract,[L1,R1]};
-expr({op,Line,'!',L0,R0}) ->
- L1 = expr(L0),
- R1 = expr(R0), %They see the same variables
+expr({op,Line,'!',L0,R0}, _Lc) ->
+ L1 = expr(L0, false),
+ R1 = expr(R0, false), %They see the same variables
{send,Line,L1,R1};
-expr({op,Line,Op,L0,R0}) when Op =:= 'andalso'; Op =:= 'orelse' ->
- L1 = expr(L0),
- R1 = expr(R0), %They see the same variables
+expr({op,Line,Op,L0,R0}, _Lc) when Op =:= 'andalso'; Op =:= 'orelse' ->
+ L1 = expr(L0, false),
+ R1 = expr(R0, false), %They see the same variables
{Op,Line,L1,R1};
-expr({op,Line,Op,L0,R0}) ->
- L1 = expr(L0),
- R1 = expr(R0), %They see the same variables
+expr({op,Line,Op,L0,R0}, _Lc) ->
+ L1 = expr(L0, false),
+ R1 = expr(R0, false), %They see the same variables
{op,Line,Op,[L1,R1]};
-expr({bin,Line,Grp}) ->
+expr({bin,Line,Grp}, _Lc) ->
Grp1 = expr_list(Grp),
{bin,Line,Grp1};
-expr({bin_element,Line,Expr,Size,Type}) ->
- Expr1 = expr(Expr),
- Size1 = expr(Size),
+expr({bin_element,Line,Expr,Size,Type}, _Lc) ->
+ Expr1 = expr(Expr, false),
+ Size1 = expr(Size, false),
{bin_element,Line,Expr1,Size1,Type};
-expr(Other) ->
+expr(Other, _Lc) ->
exit({?MODULE,{unknown_expr,Other}}).
-%% is_guard_test(Expression) -> true | false.
-%% Test if a general expression is a guard test. Cannot use erl_lint
-%% here as sys_pre_expand has transformed source.
+%% is_guard(Expression) -> true | false.
+%% Test if a general expression is a guard test or guard BIF.
+%% Cannot use erl_lint here as sys_pre_expand has transformed source.
-is_guard_test({op,_,Op,L,R}) ->
+is_guard({op,_,Op,L,R}) ->
erl_internal:comp_op(Op, 2) andalso is_gexpr_list([L,R]);
-is_guard_test({call,_,{remote,_,{atom,_,erlang},{atom,_,Test}},As}) ->
- erl_internal:type_test(Test, length(As)) andalso is_gexpr_list(As);
-is_guard_test({atom,_,true}) -> true;
-is_guard_test(_) -> false.
+is_guard({call,_,{remote,_,{atom,_,erlang},{atom,_,Test}},As}) ->
+ Arity = length(As),
+ (erl_internal:guard_bif(Test, Arity) orelse
+ erl_internal:old_type_test(Test, Arity)) andalso is_gexpr_list(As);
+is_guard({atom,_,true}) -> true;
+is_guard(_) -> false.
is_gexpr({var,_,_}) -> true;
is_gexpr({atom,_,_}) -> true;
@@ -555,17 +534,17 @@ consify([]) -> {value,0,[]}.
%% definition etc.
expr_list([E0|Es]) ->
- E1 = expr(E0),
+ E1 = expr(E0, false),
[E1|expr_list(Es)];
expr_list([]) -> [].
-icr_clauses([C0|Cs]) ->
- C1 = clause(C0),
- [C1|icr_clauses(Cs)];
-icr_clauses([]) -> [].
+icr_clauses([C0|Cs], Lc) ->
+ C1 = clause(C0, Lc),
+ [C1|icr_clauses(Cs, Lc)];
+icr_clauses([], _) -> [].
fun_clauses([{clause,L,H,G,B}|Cs]) ->
- [{clause,L,head(H),guard(G),exprs(B)}|fun_clauses(Cs)];
+ [{clause,L,head(H),guard(G),exprs(B, true)}|fun_clauses(Cs)];
fun_clauses([]) -> [].
%% new_var_name() -> VarName.
@@ -585,24 +564,21 @@ new_vars(N, L, Vs) when N > 0 ->
new_vars(N-1, L, [V|Vs]);
new_vars(0, _, Vs) -> Vs.
-bif_type(erlang, Name) -> bif_type(Name);
-bif_type(_, _) -> unsafe.
+bif_type(erlang, Name, Arity) ->
+ case erl_internal:guard_bif(Name, Arity) of
+ true ->
+ %% Guard BIFs are safe (except for self/0, but it is
+ %% handled with a special instruction anyway).
+ safe;
+ false ->
+ bif_type(Name)
+ end;
+bif_type(_, _, _) -> unsafe.
bif_type(register) -> safe;
bif_type(unregister) -> safe;
bif_type(whereis) -> safe;
bif_type(registered) -> safe;
-bif_type(abs) -> safe;
-bif_type(float) -> safe;
-bif_type(trunc) -> safe;
-bif_type(round) -> safe;
-bif_type(math) -> safe;
-bif_type(node) -> safe;
-bif_type(length) -> safe;
-bif_type(hd) -> safe;
-bif_type(tl) -> safe;
-bif_type(size) -> safe;
-bif_type(element) -> safe;
bif_type(setelement) -> safe;
bif_type(atom_to_list) -> safe;
bif_type(list_to_atom) -> safe;
@@ -627,22 +603,14 @@ bif_type(list_to_pid) -> safe;
bif_type(module_loaded) -> safe;
bif_type(binary_to_term) -> safe;
bif_type(term_to_binary) -> safe;
-bif_type(alive) -> safe;
-bif_type(notalive) -> safe;
bif_type(nodes) -> safe;
bif_type(is_alive) -> safe;
bif_type(disconnect_node) -> safe;
bif_type(binary_to_list) -> safe;
bif_type(list_to_binary) -> safe;
bif_type(split_binary) -> safe;
-bif_type(concat_binary) -> safe;
-bif_type(term_to_atom) -> safe;
bif_type(hash) -> safe;
bif_type(pre_loaded) -> safe;
-bif_type(info) -> safe;
bif_type(set_cookie) -> safe;
bif_type(get_cookie) -> safe;
-bif_type(spawn) -> spawn;
-bif_type(spawn_link) -> spawn;
-bif_type(spawn_opt) -> spawn;
bif_type(_) -> unsafe.
diff --git a/lib/debugger/src/dbg_iserver.erl b/lib/debugger/src/dbg_iserver.erl
index 212bc2b8ab..1bb73a43b9 100644
--- a/lib/debugger/src/dbg_iserver.erl
+++ b/lib/debugger/src/dbg_iserver.erl
@@ -97,13 +97,10 @@ ensure_started() ->
%%
%% Key Value
%% --- -----
-%% attributes Attr
-%% exports Exp
%% defs []
%% mod_bin Binary
%% mod_raw Raw Binary
%% mod_file File
-%% module Mod
%% {Mod,Name,Arity,Exported} Cs
%% {'fun',Mod,Index,Uniq} {Name,Arity,Cs}
%% Line {Pos,PosNL}
@@ -117,7 +114,7 @@ init([]) ->
process_flag(trap_exit, true),
global:register_name(?MODULE, self()),
Db = ets:new(?MODULE, [ordered_set, protected]),
- {ok, #state{db=Db, auto=false, stack=all}}.
+ {ok, #state{db=Db, auto=false, stack=no_tail}}.
%% Attaching to a process
handle_call({attached, AttPid, Pid}, _From, State) ->
diff --git a/lib/debugger/src/dbg_istk.erl b/lib/debugger/src/dbg_istk.erl
new file mode 100644
index 0000000000..c6922a80e4
--- /dev/null
+++ b/lib/debugger/src/dbg_istk.erl
@@ -0,0 +1,245 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(dbg_istk).
+-export([init/0,delayed_to_external/0,from_external/1,
+ push/3,pop/0,pop/1,stack_level/0,
+ delayed_stacktrace/0,delayed_stacktrace/2,
+ bindings/1,stack_frame/2,backtrace/2,
+ in_use_p/2]).
+
+-include("dbg_ieval.hrl").
+
+-define(STACK, ?MODULE).
+
+-record(e,
+ {level, %Level
+ mfa, %{Mod,Func,Args|Arity}|{Fun,Args}
+ line, %Line called from
+ bindings,
+ lc %Last call (true|false)
+ }).
+
+init() ->
+ init([]).
+
+delayed_to_external() ->
+ Stack = get(?STACK),
+ fun() -> {stack,term_to_binary(Stack)} end.
+
+from_external({stack,Stk}) ->
+ put(?STACK, binary_to_term(Stk)).
+
+init(Stack) ->
+ put(?STACK, Stack).
+
+%% We keep track of a call stack that is used for
+%% 1) saving stack frames that can be inspected from an Attached
+%% Process GUI (using dbg_icmd:get(Meta, stack_frame, {Dir, SP})
+%% 2) generate an approximation of regular stacktrace -- sent to
+%% Debugged when it should raise an exception or evaluate a
+%% function (since it might possible raise an exception)
+%%
+%% How to push depends on the "Stack Trace" option (value saved in
+%% process dictionary item 'trace_stack').
+%% all - everything is pushed
+%% no_tail - tail recursive push
+%% false - nothing is pushed
+%% Whenever a function returns, the corresponding call frame is popped.
+
+push(Bs, #ieval{level=Le,module=Mod,function=Name,
+ arguments=As,line=Li}=Ieval, Lc) ->
+ Entry = #e{level=Le,mfa={Mod,Name,As},line=Li,bindings=Bs,lc=Lc},
+ case get(trace_stack) of
+ false ->
+ Ieval#ieval{level=Le+1};
+ no_tail when Lc ->
+ Ieval;
+ _ -> % all | no_tail when Lc =:= false
+ put(?STACK, [Entry|get(?STACK)]),
+ Ieval#ieval{level=Le+1}
+ end.
+
+pop() ->
+ case get(trace_stack) of
+ false -> ignore;
+ _ -> % all ¦ no_tail
+ case get(?STACK) of
+ [_Entry|Entries] ->
+ put(?STACK, Entries);
+ [] ->
+ ignore
+ end
+ end.
+
+pop(Le) ->
+ case get(trace_stack) of
+ false -> ignore;
+ _ -> % all | no_tail
+ put(?STACK, pop(Le, get(?STACK)))
+ end.
+
+pop(Level, [#e{level=Le}|Stack]) when Level =< Le ->
+ pop(Level, Stack);
+pop(_Level, Stack) ->
+ Stack.
+
+%% stack_level() -> Le
+%% stack_level(Stack) -> Le
+%% Top call level
+stack_level() ->
+ stack_level(get(?STACK)).
+
+stack_level([]) -> 1;
+stack_level([#e{level=Le}|_]) -> Le.
+
+%% delayed_stacktrace() -> CreateStacktraceFun
+%% delayed_stacktrace(ArgFlag, #ieval{}) -> CreateStacktraceFun
+%% ArgFlag = no_args | include_args
+%% CreateStacktraceFun = fun(NumberOfEntries)
+%%
+%% Return a fun that can convert the internal stack format to
+%% an imitation of the regular stacktrace.
+
+delayed_stacktrace() ->
+ Stack0 = get(?STACK),
+ fun(NumEntries) ->
+ Stack = stacktrace(NumEntries, Stack0, []),
+ [finalize(ArityOnly) || {ArityOnly,_} <- Stack]
+ end.
+
+delayed_stacktrace(include_args, Ieval) ->
+ #ieval{module=Mod,function=Name,arguments=As,line=Li} = Ieval,
+ Stack0 = [#e{mfa={Mod,Name,As},line=Li}|get(?STACK)],
+ fun(NumEntries) ->
+ case stacktrace(NumEntries, Stack0, []) of
+ [] ->
+ [];
+ [{_,WithArgs}|Stack] ->
+ [finalize(WithArgs) |
+ [finalize(ArityOnly) || {ArityOnly,_} <- Stack]]
+ end
+ end;
+delayed_stacktrace(no_args, Ieval) ->
+ #ieval{module=Mod,function=Name,arguments=As,line=Li} = Ieval,
+ Stack0 = [#e{mfa={Mod,Name,As},line=Li}|get(?STACK)],
+ fun(NumEntries) ->
+ Stack = stacktrace(NumEntries, Stack0, []),
+ [finalize(ArityOnly) || {ArityOnly,_} <- Stack]
+ end.
+
+stacktrace(N, [#e{lc=true}|T], Acc) ->
+ stacktrace(N, T, Acc);
+stacktrace(N, [E|T], []) ->
+ stacktrace(N-1, T, [normalize(E)]);
+stacktrace(N, [E|T], [{P,_}|_]=Acc) when N > 0 ->
+ case normalize(E) of
+ {P,_} ->
+ stacktrace(N, T, Acc);
+ New ->
+ stacktrace(N-1, T, [New|Acc])
+ end;
+stacktrace(_, _, Acc) ->
+ lists:reverse(Acc).
+
+normalize(#e{mfa={M,Fun,As},line=Li}) when is_function(Fun) ->
+ Loc = {M,Li},
+ {{Fun,length(As),Loc},{Fun,As,Loc}};
+normalize(#e{mfa={M,F,As},line=Li}) ->
+ Loc = {M,Li},
+ {{M,F,length(As),Loc},{M,F,As,Loc}}.
+
+finalize({M,F,A,Loc}) -> {M,F,A,line(Loc)};
+finalize({Fun,A,Loc}) -> {Fun,A,line(Loc)}.
+
+line({Mod,Line}) when Line > 0 ->
+ [{file,atom_to_list(Mod)++".erl"},{line,Line}];
+line(_) -> [].
+
+%% bindings(SP) -> Bs
+%% SP = Le % stack pointer
+%% Return the bindings for the specified call level
+bindings(SP) ->
+ bindings(SP, get(?STACK)).
+
+bindings(SP, [#e{level=SP,bindings=Bs}|_]) ->
+ Bs;
+bindings(SP, [_Entry|Entries]) ->
+ bindings(SP, Entries);
+bindings(_SP, []) ->
+ erl_eval:new_bindings().
+
+%% stack_frame(Dir, SP) -> {Le, Where, Bs} | top | bottom
+%% Dir = up | down
+%% Where = {Cm, Li}
+%% Cm = Module | undefined % module
+%% Li = int() | -1 % line number
+%% Bs = bindings()
+%% Return stack frame info one step up/down from given stack pointer
+%% up = to lower call levels
+%% down = to higher call levels
+stack_frame(up, SP) ->
+ stack_frame(SP, up, get(?STACK));
+stack_frame(down, SP) ->
+ stack_frame(SP, down, lists:reverse(get(?STACK))).
+
+stack_frame(SP, up, [#e{level=Le,mfa={Cm,_,_},line=Li,bindings=Bs}|_])
+ when Le < SP ->
+ {Le,{Cm,Li},Bs};
+stack_frame(SP, down, [#e{level=Le,mfa={Cm,_,_},line=Li,bindings=Bs}|_])
+ when Le > SP ->
+ {Le,{Cm,Li},Bs};
+stack_frame(SP, Dir, [#e{level=SP}|Stack]) ->
+ case Stack of
+ [#e{level=Le,mfa={Cm,_,_},line=Li,bindings=Bs}|_] ->
+ {Le,{Cm,Li},Bs};
+ [] when Dir =:= up ->
+ top;
+ [] when Dir =:= down ->
+ bottom
+ end;
+stack_frame(SP, Dir, [_Entry|Stack]) ->
+ stack_frame(SP, Dir, Stack).
+
+%% backtrace(HowMany) -> Backtrace
+%% HowMany = all | int()
+%% Backtrace = {Le, MFA}
+%% Return all/the last N called functions, in reversed call order
+backtrace(HowMany, Ieval) ->
+ #ieval{level=Level,module=Mod,function=Name,arguments=As} = Ieval,
+ Stack0 = [#e{level=Level,mfa={Mod,Name,As}}|get(?STACK)],
+ Stack = case HowMany of
+ all -> Stack0;
+ N -> lists:sublist(Stack0, N)
+ end,
+ [{Le,MFA} || #e{level=Le,mfa=MFA} <- Stack].
+
+%%--------------------------------------------------------------------
+%% in_use_p(Mod, Cm) -> boolean()
+%% Mod = Cm = atom()
+%% Returns true if Mod is found on the stack, otherwise false.
+%%--------------------------------------------------------------------
+in_use_p(Mod, Mod) -> true;
+in_use_p(Mod, _Cm) ->
+ case get(trace_stack) of
+ false -> true;
+ _ -> % all | no_tail
+ lists:any(fun(#e{mfa={M,_,_}}) when M =:= Mod -> true;
+ (_) -> false
+ end, get(?STACK))
+ end.
diff --git a/lib/debugger/src/dbg_ui_break_win.erl b/lib/debugger/src/dbg_ui_break_win.erl
index 4039bf785f..abbec158b0 100644
--- a/lib/debugger/src/dbg_ui_break_win.erl
+++ b/lib/debugger/src/dbg_ui_break_win.erl
@@ -81,12 +81,12 @@ create_win(GS, {X, Y}, function, Mod, _Line) ->
{pack_x, 2}, {pack_y, 3},
{selectmode, multiple}]),
- %% Add Ok and Cancel buttons
- {Wbtn, Hbtn} = dbg_ui_win:min_size(["Ok","Cancel"], 70, 30),
+ %% Add OK and Cancel buttons
+ {Wbtn, Hbtn} = dbg_ui_win:min_size(["OK","Cancel"], 70, 30),
Bot = gs:frame(Frm, [{pack_x, {1, 3}}, {pack_y, 4}]),
- Ok = gs:button(Bot, [{x, Pad}, {y, Pad},
+ OK = gs:button(Bot, [{x, Pad}, {y, Pad},
{width, Wbtn}, {height, Hbtn},
- {label, {text,"Ok"}}, {font, Font}]),
+ {label, {text,"OK"}}, {font, Font}]),
Cancel = gs:button(Bot, [{x, W-Pad-Wbtn}, {y, Pad},
{width, Wbtn}, {height, Hbtn},
{label, {text,"Cancel"}}, {font, Font}]),
@@ -95,7 +95,7 @@ create_win(GS, {X, Y}, function, Mod, _Line) ->
gs:config(Win, [{width, Wfrm}, {height, Hfrm}, {map, true}]),
#winInfo{type=function, win=Win,
packer=Frm, entries=Entries, trigger=enable,
- ok=Ok, cancel=Cancel, listbox=Lb, funcs=[]};
+ ok=OK, cancel=Cancel, listbox=Lb, funcs=[]};
create_win(GS, {X, Y}, Type, Mod, Line) ->
Pad = 8,
W = 230,
@@ -161,12 +161,12 @@ create_win(GS, {X, Y}, Type, Mod, Line) ->
{align, w}, {group, Grp},
{data, {trigger, delete}}]),
- %% Add Ok and Cancel buttons
- {Wbtn, Hbtn} = dbg_ui_win:min_size(["Ok","Cancel"], 70, 30),
+ %% Add OK and Cancel buttons
+ {Wbtn, Hbtn} = dbg_ui_win:min_size(["OK","Cancel"], 70, 30),
Ybtn = Yacc + Pad + Hfrm + Pad,
- Ok = gs:button(Win, [{x, Pad}, {y, Ybtn},
+ OK = gs:button(Win, [{x, Pad}, {y, Ybtn},
{width, Wbtn}, {height, Hbtn},
- {label, {text,"Ok"}}, {font, Font}]),
+ {label, {text,"OK"}}, {font, Font}]),
gs:button(Win, [{x, W-Pad-Wbtn}, {y, Ybtn},
{width, Wbtn}, {height, Hbtn},
{label, {text,"Cancel"}}, {font, Font}]),
@@ -175,7 +175,7 @@ create_win(GS, {X, Y}, Type, Mod, Line) ->
gs:config(Win, [{width, W}, {height, Hwin}, {map, true}]),
#winInfo{type=Type, win=Win,
- entries=Entries, trigger=enable, ok=Ok}.
+ entries=Entries, trigger=enable, ok=OK}.
%%--------------------------------------------------------------------
%% update_functions(WinInfo, Funcs) -> WinInfo
@@ -229,7 +229,7 @@ handle_event({gs, LB, keypress, window, [Key|_]}, WinInfo) ->
Key/='Tab', Key/='Return' ->
ignore;
true ->
- handle_event({gs, LB, click, listbox, ["Ok"]}, WinInfo)
+ handle_event({gs, LB, click, listbox, ["OK"]}, WinInfo)
end;
handle_event({gs, Ent, keypress, Data, [Key|_]}, WinInfo) ->
case WinInfo#winInfo.type of
@@ -249,14 +249,14 @@ handle_event({gs, Ent, keypress, Data, [Key|_]}, WinInfo) ->
case next_entry(Ent, WinInfo#winInfo.entries) of
last ->
gs:config(WinInfo#winInfo.ok, flash),
- handle_event({gs, Ent, click, Data, ["Ok"]}, WinInfo);
+ handle_event({gs, Ent, click, Data, ["OK"]}, WinInfo);
Next ->
gs:config(Next, {setfocus, true}),
ignore
end;
_Type -> ignore
end;
-handle_event({gs, _Id, click, _Data, ["Ok"|_]}, WinInfo) ->
+handle_event({gs, _Id, click, _Data, ["OK"|_]}, WinInfo) ->
case check_input(WinInfo#winInfo.entries) of
error -> ignore;
Data when WinInfo#winInfo.type/=function ->
diff --git a/lib/debugger/src/dbg_ui_edit_win.erl b/lib/debugger/src/dbg_ui_edit_win.erl
index badaf4bef4..82f784aa83 100644
--- a/lib/debugger/src/dbg_ui_edit_win.erl
+++ b/lib/debugger/src/dbg_ui_edit_win.erl
@@ -64,13 +64,13 @@ create_win(GS, {X, Y}, Title, Prompt, {Type, Value}) ->
{text, Value},
{keypress, true}]),
- %% Ok and Cancel buttons
+ %% OK and Cancel buttons
W = Pad + Wlbl + Went + Pad,
{Wbtn, Hbtn} = dbg_ui_win:min_size(["Cancel"], 70, 30),
Ybtn = Pad + Hlbl + Pad,
Btn = gs:button(Win, [{x, Pad}, {y, Ybtn},
{width, Wbtn}, {height, Hbtn},
- {label, {text,"Ok"}}, {font, Font}]),
+ {label, {text,"OK"}}, {font, Font}]),
gs:button(Win, [{x, W-Pad-Wbtn}, {y, Ybtn},
{width, Wbtn}, {height, Hbtn},
{label, {text,"Cancel"}}, {font, Font}]),
@@ -100,8 +100,8 @@ handle_event({gs, _Id, destroy, _Data, _Arg}, _WinInfo) ->
stopped;
handle_event({gs, Id, keypress, Data, ['Return'|_]}, WinInfo) ->
gs:config(WinInfo#winInfo.button, flash),
- handle_event({gs, Id, click, Data, ["Ok"]}, WinInfo);
-handle_event({gs, _Id, click, _Data, ["Ok"|_]}, WinInfo) ->
+ handle_event({gs, Id, click, Data, ["OK"]}, WinInfo);
+handle_event({gs, _Id, click, _Data, ["OK"|_]}, WinInfo) ->
Ent = WinInfo#winInfo.entry,
Str = gs:read(Ent, text),
Type = WinInfo#winInfo.type,
diff --git a/lib/debugger/src/dbg_ui_filedialog_win.erl b/lib/debugger/src/dbg_ui_filedialog_win.erl
index 3203991c1f..1eced1104d 100644
--- a/lib/debugger/src/dbg_ui_filedialog_win.erl
+++ b/lib/debugger/src/dbg_ui_filedialog_win.erl
@@ -100,7 +100,7 @@ create_win(GS, Title, {X,Y}, Mode, Filter, Extra, FileName) ->
Opts = [{y, Y4}, {width, Wbtn}, {height, Hbtn}, {font, Font}],
case Mode of
normal ->
- gs:button(Win, [{label, {text,"Ok"}}, {x, Pad},
+ gs:button(Win, [{label, {text,"OK"}}, {x, Pad},
{data, select} | Opts]),
gs:button(Win, [{label, {text,"Filter"}}, {x, Wlb/2-Wbtn/2},
{data, filter} | Opts]),
diff --git a/lib/debugger/src/dbg_ui_interpret.erl b/lib/debugger/src/dbg_ui_interpret.erl
index 952e73b537..079eaeb634 100644
--- a/lib/debugger/src/dbg_ui_interpret.erl
+++ b/lib/debugger/src/dbg_ui_interpret.erl
@@ -145,7 +145,7 @@ interpret_all(State, Dir, [File0|Files]) ->
Window = dbg_ui_filedialog_win:get_window(State#state.win),
Error = format_error(int:interpretable(File)),
Msg = ["Error when interpreting:", File, Error,
- "Ok to continue?"],
+ "OK to continue?"],
case tool_utils:confirm(Window, Msg) of
ok -> interpret_all(State, Dir, Files);
cancel -> true
diff --git a/lib/debugger/src/dbg_ui_settings.erl b/lib/debugger/src/dbg_ui_settings.erl
index 146aa7e239..38b2ec424f 100644
--- a/lib/debugger/src/dbg_ui_settings.erl
+++ b/lib/debugger/src/dbg_ui_settings.erl
@@ -136,8 +136,8 @@ default_settings_dir(GS) ->
{ok, CWD} = file:get_cwd(),
Msg = ["Default directory", DefDir, "does not exist.",
- "Click Ok to create it or",
- "Cancel to use other directory!"],
+ "Click OK to create it or",
+ "Cancel to use other directory."],
case tool_utils:confirm(GS, Msg) of
ok ->
ToolsDir = filename:dirname(DefDir),
diff --git a/lib/debugger/src/dbg_wx_break_win.erl b/lib/debugger/src/dbg_wx_break_win.erl
index 7ac82c8fb4..062da3937a 100644
--- a/lib/debugger/src/dbg_wx_break_win.erl
+++ b/lib/debugger/src/dbg_wx_break_win.erl
@@ -82,8 +82,8 @@ create_win(Parent, Pos, function, Mod, _Line) ->
wxComboBox:connect(Text, command_text_updated),
wxListBox:connect(LB, command_listbox_selected),
wxListBox:connect(LB, command_listbox_doubleclicked),
- OkId = wxDialog:getAffirmativeId(Win),
- OKButt = wxWindow:findWindowById(OkId, [{parent, Win}]),
+ OKId = wxDialog:getAffirmativeId(Win),
+ OKButt = wxWindow:findWindowById(OKId, [{parent, Win}]),
wxWindow:disable(OKButt),
wxDialog:centreOnParent(Win),
wxDialog:show(Win),
@@ -141,8 +141,8 @@ create_win(Parent, Pos, Type, Mod, Line) ->
wxComboBox:setFocus(ModT),
wxDialog:connect(Win, command_button_clicked),
wxDialog:connect(Win, command_text_updated),
- OkId = wxDialog:getAffirmativeId(Win),
- OKButt = wxWindow:findWindowById(OkId),
+ OKId = wxDialog:getAffirmativeId(Win),
+ OKButt = wxWindow:findWindowById(OKId),
wxWindow:disable(OKButt),
wxDialog:centreOnParent(Win),
wxDialog:show(Win),
@@ -180,30 +180,30 @@ handle_event(#wx{id=?wxID_CANCEL}, #winInfo{win=Win}) ->
wxDialog:destroy(Win),
stopped;
handle_event(#wx{event=#wxCommand{type=command_text_updated}},
- #winInfo{type=function, text=Text, ok=Ok}) ->
+ #winInfo{type=function, text=Text, ok=OK}) ->
Module = wxComboBox:getValue(Text),
- wxWindow:disable(Ok),
+ wxWindow:disable(OK),
{module, list_to_atom(Module)};
handle_event(#wx{event=#wxCommand{type=command_text_updated}},
- #winInfo{text=Text, ok=Ok, entries=Es}) ->
+ #winInfo{text=Text, ok=OK, entries=Es}) ->
Module = wxComboBox:getValue(Text),
case check_input(Es) of
- error -> wxWindow:disable(Ok);
- _Data when Module =/= "" -> wxWindow:enable(Ok);
- _ -> wxWindow:disable(Ok)
+ error -> wxWindow:disable(OK);
+ _Data when Module =/= "" -> wxWindow:enable(OK);
+ _ -> wxWindow:disable(OK)
end,
ignore;
handle_event(#wx{event=#wxCommand{type=command_listbox_selected}},
- #winInfo{type=function, listbox=LB, ok=Ok}) ->
+ #winInfo{type=function, listbox=LB, ok=OK}) ->
case wxListBox:getSelections(LB) of
- {N,_} when N > 0 -> wxWindow:enable(Ok);
- _ -> wxWindow:disable(Ok)
+ {N,_} when N > 0 -> wxWindow:enable(OK);
+ _ -> wxWindow:disable(OK)
end,
ignore;
-handle_event(#wx{id=OKorListBox, event=#wxCommand{type=OkorDoubleClick}},
+handle_event(#wx{id=OKorListBox, event=#wxCommand{type=OKorDoubleClick}},
#winInfo{type=function,win=Win,listbox=LB,funcs=Funcs,text=Text})
when OKorListBox =:= ?wxID_OK;
- OkorDoubleClick =:= command_listbox_doubleclicked ->
+ OKorDoubleClick =:= command_listbox_doubleclicked ->
Mod = wxComboBox:getValue(Text),
{_, IndexL} = wxListBox:getSelections(LB),
Breaks = [[list_to_atom(Mod)|lists:nth(Index+1, Funcs)] || Index <- IndexL],
diff --git a/lib/debugger/src/dbg_wx_filedialog_win.erl b/lib/debugger/src/dbg_wx_filedialog_win.erl
index 9687efa981..9f45ad0c47 100644
--- a/lib/debugger/src/dbg_wx_filedialog_win.erl
+++ b/lib/debugger/src/dbg_wx_filedialog_win.erl
@@ -151,7 +151,7 @@ init([Parent, Id, Options0]) ->
Bott = wxDialog:createButtonSizer(Dlg, ?wxCANCEL bor ?wxOK),
wxDialog:connect(Dlg, command_button_clicked),
- %% Ok done
+ %% OK done
Box = wxBoxSizer:new(?wxVERTICAL),
wxSizer:add(Box, Top, [{border, 2}, {flag,?wxALL bor ?wxEXPAND}]),
wxSizer:add(Box, Dir, [{border, 2}, {flag,?wxALL bor ?wxEXPAND}]),
diff --git a/lib/debugger/src/dbg_wx_settings.erl b/lib/debugger/src/dbg_wx_settings.erl
index 8f87815949..bc88bdf7da 100644
--- a/lib/debugger/src/dbg_wx_settings.erl
+++ b/lib/debugger/src/dbg_wx_settings.erl
@@ -83,9 +83,9 @@ default_settings_dir(Win) ->
false ->
{ok, CWD} = file:get_cwd(),
- Msg = ["Default directory", DefDir, "does not exist.",
- "Click Ok to create it or",
- "Cancel to use other directory!"],
+ Msg = ["Default directory ", DefDir, " does not exist. ",
+ "Click OK to create it or ",
+ "Cancel to use other directory."],
case dbg_wx_win:confirm(Win, Msg) of
ok ->
ToolsDir = filename:dirname(DefDir),
diff --git a/lib/debugger/src/dbg_wx_trace_win.erl b/lib/debugger/src/dbg_wx_trace_win.erl
index 720b913024..720b913024 100755..100644
--- a/lib/debugger/src/dbg_wx_trace_win.erl
+++ b/lib/debugger/src/dbg_wx_trace_win.erl
diff --git a/lib/debugger/src/dbg_wx_winman.erl b/lib/debugger/src/dbg_wx_winman.erl
index 79dcc47f6f..79dcc47f6f 100755..100644
--- a/lib/debugger/src/dbg_wx_winman.erl
+++ b/lib/debugger/src/dbg_wx_winman.erl
diff --git a/lib/debugger/src/debugger.app.src b/lib/debugger/src/debugger.app.src
index 21cf59a2e1..5538f66260 100644
--- a/lib/debugger/src/debugger.app.src
+++ b/lib/debugger/src/debugger.app.src
@@ -26,6 +26,7 @@
dbg_ieval,
dbg_iload,
dbg_iserver,
+ dbg_istk,
dbg_ui_break,
dbg_ui_break_win,
dbg_ui_edit,
diff --git a/lib/debugger/test/Makefile b/lib/debugger/test/Makefile
index 2296bd0ae6..3dfbed31ff 100644
--- a/lib/debugger/test/Makefile
+++ b/lib/debugger/test/Makefile
@@ -43,6 +43,7 @@ MODULES= \
exception_SUITE \
fun_SUITE \
lc_SUITE \
+ line_number_SUITE \
record_SUITE \
trycatch_SUITE \
test_lib \
diff --git a/lib/debugger/test/bs_construct_SUITE.erl b/lib/debugger/test/bs_construct_SUITE.erl
index 5c7d49e951..187c9f53b0 100644
--- a/lib/debugger/test/bs_construct_SUITE.erl
+++ b/lib/debugger/test/bs_construct_SUITE.erl
@@ -19,18 +19,31 @@
-module(bs_construct_SUITE).
+%% Copied from bs_construct_SUITE in the emulator test suite.
+%% The following test cases have been omitted since they don't
+%% make much sense for the debugger:
+%% bs_add
+%% kostis
+
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
init_per_suite/1,end_per_suite/1,
- test1/1, test2/1, test3/1, test4/1, test5/1, testf/1, not_used/1, in_guard/1,
- coerce_to_float/1]).
+ test1/1, test2/1, test3/1, test4/1, test5/1, testf/1,
+ not_used/1, in_guard/1,
+ mem_leak/1, coerce_to_float/1, bjorn/1,
+ huge_float_field/1, huge_binary/1, system_limit/1, badarg/1,
+ copy_writable_binary/1, dynamic/1,
+ otp_7422/1, zero_width/1]).
-include_lib("test_server/include/test_server.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- cases().
+ [test1, test2, test3, test4, test5, testf, not_used,
+ in_guard, mem_leak, coerce_to_float, bjorn,
+ huge_float_field, huge_binary, system_limit, badarg,
+ copy_writable_binary, dynamic, otp_7422, zero_width].
groups() ->
[].
@@ -41,11 +54,6 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-
-cases() ->
- [test1, test2, test3, test4, test5, testf, not_used,
- in_guard, coerce_to_float].
-
init_per_testcase(_Case, Config) ->
test_lib:interpret(?MODULE),
Dog = test_server:timetrap(?t:minutes(1)),
@@ -75,7 +83,9 @@ r(L) ->
-define(T(B, L), {B, ??B, L}).
-define(N(B), {B, ??B, unknown}).
--define(FAIL(Expr), ?line {'EXIT',{badarg,_}} = (catch Expr)).
+-define(FAIL(Expr), ?line fail_check(catch Expr, ??Expr, [])).
+
+-define(FAIL_VARS(Expr, Vars), ?line fail_check(catch Expr, ??Expr, Vars)).
l(I_13, I_big1) ->
[
@@ -143,7 +153,13 @@ l(I_13, I_big1) ->
native_3798()),
?T(<<32978297842987249827298387697777669766334937:128/native-integer>>,
- native_bignum())
+ native_bignum()),
+
+ %% Unit tests.
+ ?T(<<<<5:3>>/bitstring>>, <<5:3>>),
+ ?T(<<42,<<7:4>>/binary-unit:4>>, <<42,7:4>>),
+ ?T(<<<<344:17>>/binary-unit:17>>, <<344:17>>),
+ ?T(<<<<42,3,7656:16>>/binary-unit:16>>, <<42,3,7656:16>>)
].
@@ -179,7 +195,7 @@ eval_list([{C_bin, Str, Bytes} | Rest], Vars) ->
[{C_bin, E_bin, Str, Bytes} | eval_list(Rest, Vars)]
end.
-one_test({C_bin, E_bin, Str, Bytes}) when list(Bytes) ->
+one_test({C_bin, E_bin, Str, Bytes}) when is_list(Bytes) ->
io:format(" ~s, ~p~n", [Str, Bytes]),
Bin = list_to_binary(Bytes),
if
@@ -222,7 +238,7 @@ one_test({C_bin, E_bin, Str, Result}) ->
ok;
%% For situations where the final bits may not matter, like
%% for floats:
- N when integer(N) ->
+ N when is_integer(N) ->
io:format("Info: compiled and interpreted differ in the"
" last bytes:~n ~p, ~p.~n",
[binary_to_list(C_bin), binary_to_list(E_bin)]),
@@ -248,9 +264,22 @@ equal_lists(A, B, R) ->
false
end.
+fail_check({'EXIT',{badarg,_}}, Str, Vars) ->
+ try evaluate(Str, Vars) of
+ Res ->
+ io:format("Interpreted result: ~p", [Res]),
+ ?t:fail(did_not_fail_in_intepreted_code)
+ catch
+ error:badarg ->
+ ok
+ end;
+fail_check(Res, _, _) ->
+ io:format("Compiled result: ~p", [Res]),
+ ?t:fail(did_not_fail_in_compiled_code).
+
%%% Simple working cases
test1(suite) -> [];
-test1(Config) when list(Config) ->
+test1(Config) when is_list(Config) ->
?line I_13 = i(13),
?line I_big1 = big(1),
?line Vars = [{'I_13', I_13},
@@ -272,7 +301,7 @@ gen_l(N, S, A) ->
[?T(<<A:S/little, A:(N-S)/little>>, comp(N, A, S))].
test2(suite) -> [];
-test2(Config) when list(Config) ->
+test2(Config) when is_list(Config) ->
?line test2(0, 8, 2#10101010101010101),
?line test2(0, 8, 2#1111111111).
@@ -300,7 +329,7 @@ t3() ->
].
test3(suite) -> [];
-test3(Config) when list(Config) ->
+test3(Config) when is_list(Config) ->
?line Vars = [],
?line lists:foreach(fun one_test/1, eval_list(t3(), Vars)).
@@ -311,7 +340,7 @@ gen_u_l(N, S, A) ->
[?N(<<A:S/little, A:(N-S)/little>>)].
test4(suite) -> [];
-test4(Config) when list(Config) ->
+test4(Config) when is_list(Config) ->
?line test4(0, 16, 2#10101010101010101),
?line test4(0, 16, 2#1111111111).
@@ -333,7 +362,7 @@ gen_b(N, S, A) ->
test5(suite) -> [];
test5(doc) -> ["OTP-3995"];
-test5(Config) when list(Config) ->
+test5(Config) when is_list(Config) ->
?line test5(0, 8, <<73>>),
?line test5(0, 8, <<68>>).
@@ -350,40 +379,63 @@ test5(S, A) ->
%%% Failure cases
testf(suite) -> [];
-testf(Config) when list(Config) ->
- ?FAIL(<<3.14>>),
- ?FAIL(<<<<1,2>>>>),
-
- ?FAIL(<<2.71/binary>>),
- ?FAIL(<<24334/binary>>),
- ?FAIL(<<24334344294788947129487129487219847/binary>>),
-
- ?FAIL(<<<<1,2,3>>/float>>),
+testf(Config) when is_list(Config) ->
+ ?line ?FAIL(<<3.14>>),
+ ?line ?FAIL(<<<<1,2>>>>),
+
+ ?line ?FAIL(<<2.71/binary>>),
+ ?line ?FAIL(<<24334/binary>>),
+ ?line ?FAIL(<<24334344294788947129487129487219847/binary>>),
+ BigInt = id(24334344294788947129487129487219847),
+ ?line ?FAIL_VARS(<<BigInt/binary>>, [{'BigInt',BigInt}]),
+ ?line ?FAIL_VARS(<<42,BigInt/binary>>, [{'BigInt',BigInt}]),
+ ?line ?FAIL_VARS(<<BigInt:2/binary>>, [{'BigInt',BigInt}]),
+
+ %% One negative field size, but the sum of field sizes will be 1 byte.
+ %% Make sure that we reject that properly.
+ I_minus_777 = id(-777),
+ I_minus_2047 = id(-2047),
+ ?line ?FAIL_VARS(<<I_minus_777:2048/unit:8,57:I_minus_2047/unit:8>>,
+ ordsets:from_list([{'I_minus_777',I_minus_777},
+ {'I_minus_2047',I_minus_2047}])),
+ ?line ?FAIL(<<<<1,2,3>>/float>>),
%% Negative field widths.
- testf_1(-8, <<1,2,3,4,5>>),
-
- ?FAIL(<<42:(-16)>>),
- ?FAIL(<<3.14:(-8)/float>>),
- ?FAIL(<<<<23,56,0,2>>:(-16)/binary>>),
- ?FAIL(<<<<23,56,0,2>>:(2.5)/binary>>),
- ?FAIL(<<<<23,56,0,2>>:(anka)>>),
+ ?line testf_1(-8, <<1,2,3,4,5>>),
+ ?line ?FAIL(<<0:(-(1 bsl 100))>>),
+
+ ?line ?FAIL(<<42:(-16)>>),
+ ?line ?FAIL(<<3.14:(-8)/float>>),
+ ?line ?FAIL(<<<<23,56,0,2>>:(-16)/binary>>),
+ ?line ?FAIL(<<<<23,56,0,2>>:(2.5)/binary>>),
+ ?line ?FAIL(<<<<23,56,0,2>>:(anka)>>),
+ ?line ?FAIL(<<<<23,56,0,2>>:(anka)>>),
+
+ %% Unit failures.
+ ?line ?FAIL(<<<<1:1>>/binary>>),
+ Sz = id(1),
+ ?line ?FAIL_VARS(<<<<1:Sz>>/binary>>, [{'Sz',Sz}]),
+ ?line {'EXIT',{badarg,_}} = (catch <<<<1:(id(1))>>/binary>>),
+ ?line ?FAIL(<<<<7,8,9>>/binary-unit:16>>),
+ ?line ?FAIL(<<<<7,8,9,3:7>>/binary-unit:16>>),
+ ?line ?FAIL(<<<<7,8,9,3:7>>/binary-unit:17>>),
ok.
testf_1(W, B) ->
- ?FAIL(<<42:W>>),
- ?FAIL(<<3.14:W/float>>),
- ?FAIL(<<B:W/binary>>).
+ Vars = [{'W',W}],
+ ?FAIL_VARS(<<42:W>>, Vars),
+ ?FAIL_VARS(<<3.14:W/float>>, Vars),
+ ?FAIL_VARS(<<B:W/binary>>, [{'B',B}|Vars]).
not_used(doc) ->
"Test that constructed binaries that are not used will still give an exception.";
not_used(Config) when is_list(Config) ->
?line ok = not_used1(3, <<"dum">>),
- ?line ?FAIL(not_used1(3, "dum")),
- ?line ?FAIL(not_used2(444, -2)),
- ?line ?FAIL(not_used2(444, anka)),
- ?line ?FAIL(not_used3(444)),
+ ?line {'EXIT',{badarg,_}} = (catch not_used1(3, "dum")),
+ ?line {'EXIT',{badarg,_}} = (catch not_used2(444, -2)),
+ ?line {'EXIT',{badarg,_}} = (catch not_used2(444, anka)),
+ ?line {'EXIT',{badarg,_}} = (catch not_used3(444)),
ok.
not_used1(I, BinString) ->
@@ -398,7 +450,7 @@ not_used3(I) ->
<<I:(-8)>>,
ok.
-in_guard(Config) when list(Config) ->
+in_guard(Config) when is_list(Config) ->
?line 1 = in_guard(<<16#74ad:16>>, 16#e95, 5),
?line 2 = in_guard(<<16#3A,16#F7,"hello">>, 16#3AF7, <<"hello">>),
?line 3 = in_guard(<<16#FBCD:14,3.1415/float,3:2>>, 16#FBCD, 3.1415),
@@ -415,6 +467,36 @@ in_guard(Bin, A, B) when <<A:14,B/float,3:2>> == Bin -> 3;
in_guard(Bin, A, B) when {a,b,<<A:14,B/float,3:2>>} == Bin -> cant_happen;
in_guard(_, _, _) -> nope.
+mem_leak(doc) -> "Make sure that construction has no memory leak";
+mem_leak(Config) when is_list(Config) ->
+ ?line B = make_bin(16, <<0>>),
+ ?line mem_leak(1024, B),
+ ok.
+
+mem_leak(0, _) -> ok;
+mem_leak(N, B) ->
+ ?line big_bin(B, <<23>>),
+ ?line {'EXIT',{badarg,_}} = (catch big_bin(B, bad)),
+ maybe_gc(),
+ mem_leak(N-1, B).
+
+big_bin(B1, B2) ->
+ <<B1/binary,B1/binary,B1/binary,B1/binary,
+ B1/binary,B1/binary,B1/binary,B1/binary,
+ B1/binary,B1/binary,B1/binary,B1/binary,
+ B1/binary,B1/binary,B1/binary,B1/binary,
+ B2/binary>>.
+
+make_bin(0, Acc) -> Acc;
+make_bin(N, Acc) -> make_bin(N-1, <<Acc/binary,Acc/binary>>).
+
+maybe_gc() ->
+ case erlang:system_info(heap_type) of
+ shared -> erlang:garbage_collect();
+ hybrid -> erlang:garbage_collect();
+ private -> ok
+ end.
+
-define(COF(Int0),
?line (fun(Int) ->
true = <<Int:32/float>> =:= <<(float(Int)):32/float>>,
@@ -431,7 +513,7 @@ in_guard(_, _, _) -> nope.
nonliteral(X) -> X.
-coerce_to_float(Config) when list(Config) ->
+coerce_to_float(Config) when is_list(Config) ->
?COF(0),
?COF(-1),
?COF(1),
@@ -444,3 +526,232 @@ coerce_to_float(Config) when list(Config) ->
?COF64(298748888888888888888888888883478264866528467367364766666666666666663),
?COF64(-367546729879999999999947826486652846736736476555566666663),
ok.
+
+bjorn(Config) when is_list(Config) ->
+ ?line error = bjorn_1(),
+ ok.
+
+bjorn_1() ->
+ Bitstr = <<7:13>>,
+ try
+ do_something()
+ catch
+ throw:blurf ->
+ ignore
+ end,
+ do_more(Bitstr, 13).
+
+do_more(Bin, Sz) ->
+ %% Previous bug in the bs_bits_to_bytes instruction: The exeption code
+ %% was not set - the previous exception (throw:blurf) would be used,
+ %% causing the catch to slip.
+ try <<Bin:Sz/binary>> of
+ _V -> ok
+ catch
+ error:_ ->
+ error
+ end.
+
+do_something() ->
+ throw(blurf).
+
+huge_float_field(Config) when is_list(Config) ->
+ ?line {'EXIT',{badarg,_}} = (catch <<0.0:9/float-unit:8>>),
+ ?line huge_float_check(catch <<0.0:67108865/float-unit:64>>),
+ ?line huge_float_check(catch <<0.0:((1 bsl 26)+1)/float-unit:64>>),
+ ?line huge_float_check(catch <<0.0:(id(67108865))/float-unit:64>>),
+%% ?line huge_float_check(catch <<0.0:((1 bsl 60)+1)/float-unit:64>>),
+ ?line huge_float_check(catch <<3839739387439387383739387987347983:((1 bsl 26)+1)/float-unit:64>>),
+%% ?line huge_float_check(catch <<3839739387439387383739387987347983:((1 bsl 60)+1)/float-unit:64>>),
+ ok.
+
+huge_float_check({'EXIT',{system_limit,_}}) -> ok;
+huge_float_check({'EXIT',{badarg,_}}) -> ok.
+
+huge_binary(Config) when is_list(Config) ->
+ ?line 16777216 = size(<<0:(id(1 bsl 26)),(-1):(id(1 bsl 26))>>),
+ ok.
+
+system_limit(Config) when is_list(Config) ->
+ WordSize = erlang:system_info(wordsize),
+ BitsPerWord = WordSize * 8,
+ ?line {'EXIT',{system_limit,_}} =
+ (catch <<0:(id(0)),42:(id(1 bsl BitsPerWord))>>),
+ ?line {'EXIT',{system_limit,_}} =
+ (catch <<42:(id(1 bsl BitsPerWord)),0:(id(0))>>),
+ ?line {'EXIT',{system_limit,_}} =
+ (catch <<(id(<<>>))/binary,0:(id(1 bsl 100))>>),
+
+ case WordSize of
+ 4 ->
+ system_limit_32();
+ 8 ->
+ ok
+ end.
+
+system_limit_32() ->
+ ?line {'EXIT',{badarg,_}} = (catch <<42:(-1)>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<42:(id(-1))>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<42:(id(-389739873536870912))/unit:8>>),
+ ?line {'EXIT',{system_limit,_}} = (catch <<42:536870912/unit:8>>),
+ ?line {'EXIT',{system_limit,_}} = (catch <<42:(id(536870912))/unit:8>>),
+ ?line {'EXIT',{system_limit,_}} = (catch <<0:(id(8)),42:536870912/unit:8>>),
+ ?line {'EXIT',{system_limit,_}} =
+ (catch <<0:(id(8)),42:(id(536870912))/unit:8>>),
+ ok.
+
+badarg(Config) when is_list(Config) ->
+ %% BEAM will generate a badarg exception for:
+ %% <<0:(id(1 bsl 100)),0:(id(-1))>>
+ %% but the debugger will generate a system_limit exception.
+ %% It does not seems worthwhile to fix the debugger.
+
+ ?line {'EXIT',{badarg,_}} =
+ (catch <<(id(<<>>))/binary,0:(id(-(1 bsl 100)))>>),
+
+ ok.
+
+copy_writable_binary(Config) when is_list(Config) ->
+ ?line [copy_writable_binary_1(I) || I <- lists:seq(0, 256)],
+ ok.
+
+copy_writable_binary_1(_) ->
+ ?line Bin0 = <<(id(<<>>))/binary,0,1,2,3,4,5,6,7>>,
+ ?line SubBin = make_sub_bin(Bin0),
+ ?line id(<<42,34,55,Bin0/binary>>), %Make reallocation likelier.
+ ?line Pid = spawn(fun() ->
+ copy_writable_binary_holder(Bin0, SubBin)
+ end),
+ ?line Tab = ets:new(holder, []),
+ ?line ets:insert(Tab, {17,Bin0}),
+ ?line ets:insert(Tab, {42,SubBin}),
+ ?line id(<<Bin0/binary,0:(64*1024*8)>>),
+ ?line Pid ! self(),
+ ?line [{17,Bin0}] = ets:lookup(Tab, 17),
+ ?line [{42,Bin0}] = ets:lookup(Tab, 42),
+ receive
+ {Pid,Bin0,Bin0} -> ok;
+ Other ->
+ io:format("Unexpected message: ~p", [Other]),
+ ?line ?t:fail()
+ end,
+ ok.
+
+copy_writable_binary_holder(Bin, SubBin) ->
+ receive
+ Pid ->
+ Pid ! {self(),Bin,SubBin}
+ end.
+
+make_sub_bin(Bin0) ->
+ N = bit_size(Bin0),
+ <<_:17,Bin:N/bitstring,_:5>> = <<(-1):17,Bin0/bitstring,(-1):5>>,
+ Bin = Bin0, %Assertion.
+ Bin.
+
+%% Test that different ways of using bit syntax instructions
+%% give the same result.
+
+dynamic(Config) when is_list(Config) ->
+ ?line dynamic_1(fun dynamic_big/5),
+ ?line dynamic_1(fun dynamic_little/5),
+ ok.
+
+dynamic_1(Dynamic) ->
+ <<Lpad:128>> = erlang:md5([0]),
+ <<Rpad:128>> = erlang:md5([1]),
+ <<Int:128>> = erlang:md5([2]),
+ 8385 = dynamic_2(0, {Int,Lpad,Rpad,Dynamic}, 0).
+
+dynamic_2(129, _, Count) -> Count;
+dynamic_2(Bef, Data, Count0) ->
+ Count = dynamic_3(Bef, 128-Bef, Data, Count0),
+ dynamic_2(Bef+1, Data, Count).
+
+dynamic_3(_, -1, _, Count) -> Count;
+dynamic_3(Bef, N, {Int0,Lpad,Rpad,Dynamic}=Data, Count) ->
+ Int1 = Int0 band ((1 bsl (N+3))-1),
+ Dynamic(Bef, N, Int1, Lpad, Rpad),
+ Dynamic(Bef, N, -Int1, Lpad, Rpad),
+
+ %% OTP-7085: Test a small number in a wide field.
+ Int2 = Int0 band 16#FFFFFF,
+ Dynamic(Bef, N, Int2, Lpad, Rpad),
+ Dynamic(Bef, N, -Int2, Lpad, Rpad),
+ dynamic_3(Bef, N-1, Data, Count+1).
+
+dynamic_big(Bef, N, Int, Lpad, Rpad) ->
+ NumBin = id(<<Int:N>>),
+ MaskedInt = Int band ((1 bsl N) - 1),
+ <<MaskedInt:N>> = NumBin,
+
+ %% Construct the binary in two different ways.
+ Bin = id(<<Lpad:Bef,NumBin/bitstring,Rpad:(128-Bef-N)>>),
+ Bin = <<Lpad:Bef,Int:N,Rpad:(128-Bef-N)>>,
+
+ %% Further verify the result by matching.
+ LpadMasked = Lpad band ((1 bsl Bef) - 1),
+ RpadMasked = Rpad band ((1 bsl (128-Bef-N)) - 1),
+ Rbits = (128-Bef-N),
+ <<LpadMasked:Bef,MaskedInt:N,RpadMasked:Rbits>> = id(Bin),
+ ok.
+
+dynamic_little(Bef, N, Int, Lpad, Rpad) ->
+ NumBin = id(<<Int:N/little>>),
+ MaskedInt = Int band ((1 bsl N) - 1),
+ <<MaskedInt:N/little>> = NumBin,
+
+ %% Construct the binary in two different ways.
+ Bin = id(<<Lpad:Bef/little,NumBin/bitstring,Rpad:(128-Bef-N)/little>>),
+ Bin = <<Lpad:Bef/little,Int:N/little,Rpad:(128-Bef-N)/little>>,
+
+ %% Further verify the result by matching.
+ LpadMasked = Lpad band ((1 bsl Bef) - 1),
+ RpadMasked = Rpad band ((1 bsl (128-Bef-N)) - 1),
+ Rbits = (128-Bef-N),
+ <<LpadMasked:Bef/little,MaskedInt:N/little,RpadMasked:Rbits/little>> = id(Bin),
+ ok.
+
+otp_7422(Config) when is_list(Config) ->
+ otp_7422_int(0),
+ otp_7422_bin(0).
+
+otp_7422_int(N) when N < 512 ->
+ T = erlang:make_tuple(N, []),
+ spawn_link(fun() ->
+ id(T),
+ %% A size of field 0 would write one byte beyond
+ %% the current position in the binary. It could
+ %% overwrite the continuation pointer stored on
+ %% the stack if HTOP was equal to E (the stack pointer).
+ id(<<0:(id(0))>>)
+ end),
+ otp_7422_int(N+1);
+otp_7422_int(_) -> ok.
+
+otp_7422_bin(N) when N < 512 ->
+ T = erlang:make_tuple(N, []),
+ Z = id(<<>>),
+ spawn_link(fun() ->
+ id(T),
+ id(<<Z:(id(0))/bits>>)
+ end),
+ otp_7422_bin(N+1);
+otp_7422_bin(_) -> ok.
+
+zero_width(Config) when is_list(Config) ->
+ ?line Z = id(0),
+ Small = id(42),
+ Big = id(1 bsl 128),
+ ?line <<>> = <<Small:Z>>,
+ ?line <<>> = <<Small:0>>,
+ ?line <<>> = <<Big:Z>>,
+ ?line <<>> = <<Big:0>>,
+
+ ?line {'EXIT',{badarg,_}} = (catch <<not_a_number:0>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<(id(not_a_number)):Z>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<(id(not_a_number)):0>>),
+
+ ok.
+
+id(I) -> I.
diff --git a/lib/debugger/test/bs_match_bin_SUITE.erl b/lib/debugger/test/bs_match_bin_SUITE.erl
index b42b84aef2..5a7c30f16b 100644
--- a/lib/debugger/test/bs_match_bin_SUITE.erl
+++ b/lib/debugger/test/bs_match_bin_SUITE.erl
@@ -24,14 +24,14 @@
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
init_per_suite/1,end_per_suite/1,
- byte_split_binary/1,bit_split_binary/1]).
+ byte_split_binary/1,bit_split_binary/1,match_huge_bin/1]).
-include_lib("test_server/include/test_server.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- cases().
+ [byte_split_binary, bit_split_binary, match_huge_bin].
groups() ->
[].
@@ -42,10 +42,6 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-
-cases() ->
- [byte_split_binary, bit_split_binary].
-
init_per_testcase(_Case, Config) ->
test_lib:interpret(?MODULE),
Dog = test_server:timetrap(?t:minutes(1)),
@@ -65,11 +61,12 @@ end_per_suite(Config) when is_list(Config) ->
ok.
byte_split_binary(doc) -> "Tries to split a binary at all byte-aligned positions.";
-byte_split_binary(suite) -> [];
-byte_split_binary(Config) when list(Config) ->
+byte_split_binary(Config) when is_list(Config) ->
?line L = lists:seq(0, 57),
?line B = mkbin(L),
- ?line byte_split(L, B, size(B)).
+ ?line byte_split(L, B, size(B)),
+ ?line Unaligned = make_unaligned_sub_binary(B),
+ ?line byte_split(L, Unaligned, size(Unaligned)).
byte_split(L, B, Pos) when Pos >= 0 ->
?line Sz1 = Pos,
@@ -78,18 +75,19 @@ byte_split(L, B, Pos) when Pos >= 0 ->
?line B1 = list_to_binary(lists:sublist(L, 1, Pos)),
?line B2 = list_to_binary(lists:nthtail(Pos, L)),
?line byte_split(L, B, Pos-1);
-byte_split(_L, _B, _) -> ok.
+byte_split(_, _, _) -> ok.
bit_split_binary(doc) -> "Tries to split a binary at all positions.";
-bit_split_binary(suite) -> [];
-bit_split_binary(Config) when list(Config) ->
+bit_split_binary(Config) when is_list(Config) ->
Fun = fun(Bin, List, SkipBef, N) ->
?line SkipAft = 8*size(Bin) - N - SkipBef,
- io:format("~p, ~p, ~p", [SkipBef,N,SkipAft]),
- ?line <<_I1:SkipBef,OutBin:N/binary-unit:1,_I2:SkipAft>> = Bin,
+ %%io:format("~p, ~p, ~p", [SkipBef,N,SkipAft]),
+ ?line <<_:SkipBef,OutBin:N/binary-unit:1,_:SkipAft>> = Bin,
?line OutBin = make_bin_from_list(List, N)
end,
?line bit_split_binary1(Fun, erlang:md5(<<1,2,3>>)),
+ ?line bit_split_binary1(Fun,
+ make_unaligned_sub_binary(erlang:md5(<<1,2,3>>))),
ok.
bit_split_binary1(Action, Bin) ->
@@ -99,24 +97,23 @@ bit_split_binary1(Action, Bin) ->
bit_split_binary2(Action, Bin, [_|T]=List, Bef) ->
bit_split_binary3(Action, Bin, List, Bef, size(Bin)*8),
bit_split_binary2(Action, Bin, T, Bef+1);
-bit_split_binary2(_Action, _Bin, [], _Bef) -> ok.
+bit_split_binary2(_, _, [], _) -> ok.
bit_split_binary3(Action, Bin, List, Bef, Aft) when Bef =< Aft ->
Action(Bin, List, Bef, (Aft-Bef) div 8 * 8),
bit_split_binary3(Action, Bin, List, Bef, Aft-8);
bit_split_binary3(_, _, _, _, _) -> ok.
-make_bin_from_list(_List, 0) ->
- mkbin([]);
+make_bin_from_list(_, 0) -> mkbin([]);
make_bin_from_list(List, N) ->
list_to_binary([make_int(List, 8, 0),
make_bin_from_list(lists:nthtail(8, List), N-8)]).
-make_int(_List, 0, Acc) -> Acc;
+make_int(_, 0, Acc) -> Acc;
make_int([H|T], N, Acc) -> make_int(T, N-1, Acc bsl 1 bor H).
-bits_to_list([_H|T], 0) -> bits_to_list(T, 16#80);
+bits_to_list([_|T], 0) -> bits_to_list(T, 16#80);
bits_to_list([H|_]=List, Mask) ->
[case H band Mask of
0 -> 0;
@@ -124,5 +121,109 @@ bits_to_list([H|_]=List, Mask) ->
end|bits_to_list(List, Mask bsr 1)];
bits_to_list([], _) -> [].
+mkbin(L) when is_list(L) -> list_to_binary(L).
+
+make_unaligned_sub_binary(Bin0) ->
+ Bin1 = <<0:3,Bin0/binary,31:5>>,
+ Sz = size(Bin0),
+ <<0:3,Bin:Sz/binary,31:5>> = id(Bin1),
+ Bin.
+
+id(I) -> I.
+
+match_huge_bin(Config) when is_list(Config) ->
+ ?line Bin = <<0:(1 bsl 27),13:8>>,
+ ?line skip_huge_bin_1(1 bsl 27, Bin),
+ ?line 16777216 = match_huge_bin_1(1 bsl 27, Bin),
+
+ %% Test overflowing the size of a binary field.
+ ?line nomatch = overflow_huge_bin_skip_32(Bin),
+ ?line nomatch = overflow_huge_bin_32(Bin),
+ ?line nomatch = overflow_huge_bin_skip_64(Bin),
+ ?line nomatch = overflow_huge_bin_64(Bin),
+
+ %% Size in variable
+ ?line ok = overflow_huge_bin(Bin, lists:seq(25, 32)++lists:seq(50, 64)),
+ ?line 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.
-mkbin(L) when list(L) -> list_to_binary(L).
+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.
diff --git a/lib/debugger/test/bs_match_int_SUITE.erl b/lib/debugger/test/bs_match_int_SUITE.erl
index 745368fdfc..bff5f8ff65 100644
--- a/lib/debugger/test/bs_match_int_SUITE.erl
+++ b/lib/debugger/test/bs_match_int_SUITE.erl
@@ -19,11 +19,11 @@
-module(bs_match_int_SUITE).
--author('[email protected]').
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
init_per_suite/1,end_per_suite/1,
- integer/1,signed_integer/1,dynamic/1,more_dynamic/1,mml/1]).
+ integer/1,signed_integer/1,dynamic/1,more_dynamic/1,mml/1,
+ match_huge_int/1,bignum/1,unaligned_32_bit/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -32,7 +32,8 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [cases()].
+ [integer, signed_integer, dynamic, more_dynamic, mml,
+ match_huge_int, bignum, unaligned_32_bit].
groups() ->
[].
@@ -43,10 +44,6 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-
-cases() ->
- [integer, signed_integer, dynamic, more_dynamic, mml].
-
init_per_testcase(_Case, Config) ->
test_lib:interpret(?MODULE),
Dog = test_server:timetrap(?t:minutes(4)),
@@ -65,8 +62,7 @@ init_per_suite(Config) when is_list(Config) ->
end_per_suite(Config) when is_list(Config) ->
ok.
-integer(suite) -> [];
-integer(Config) when list(Config) ->
+integer(Config) when is_list(Config) ->
?line 0 = get_int(mkbin([])),
?line 0 = get_int(mkbin([0])),
?line 42 = get_int(mkbin([42])),
@@ -78,22 +74,33 @@ integer(Config) when list(Config) ->
?line 65534 = get_int(mkbin([255,254])),
?line 16776455 = get_int(mkbin([255,253,7])),
?line 4245492555 = get_int(mkbin([253,13,19,75])),
+ ?line 4294967294 = get_int(mkbin([255,255,255,254])),
+ ?line 4294967295 = get_int(mkbin([255,255,255,255])),
?line Eight = [200,1,19,128,222,42,97,111],
?line cmp128(Eight, uint(Eight)),
?line fun_clause(catch get_int(mkbin(seq(1,5)))),
ok.
-get_int(<<I:0>>) -> I;
-get_int(<<I:8>>) -> I;
-get_int(<<I:16>>) -> I;
-get_int(<<I:24>>) -> I;
-get_int(<<I:32>>) -> I.
+get_int(Bin) ->
+ I = get_int1(Bin),
+ get_int(Bin, I).
+
+get_int(Bin0, I) when size(Bin0) < 4 ->
+ Bin = <<0,Bin0/binary>>,
+ I = get_int1(Bin),
+ get_int(Bin, I);
+get_int(_, I) -> I.
+
+get_int1(<<I:0>>) -> I;
+get_int1(<<I:8>>) -> I;
+get_int1(<<I:16>>) -> I;
+get_int1(<<I:24>>) -> I;
+get_int1(<<I:32>>) -> I.
cmp128(<<I:128>>, I) -> equal;
-cmp128(_B, _I) -> not_equal.
+cmp128(_, _) -> not_equal.
-signed_integer(suite) -> [];
-signed_integer(Config) when list(Config) ->
+signed_integer(Config) when is_list(Config) ->
?line {no_match,_} = sint(mkbin([])),
?line {no_match,_} = sint(mkbin([1,2,3])),
?line 127 = sint(mkbin([127])),
@@ -113,7 +120,7 @@ uint(L) -> uint(L, 0).
uint([H|T], Acc) -> uint(T, Acc bsl 8 bor H);
uint([], Acc) -> Acc.
-dynamic(Config) when list(Config) ->
+dynamic(Config) when is_list(Config) ->
dynamic(mkbin([255]), 8),
dynamic(mkbin([255,255]), 16),
dynamic(mkbin([255,255,255]), 24),
@@ -124,7 +131,7 @@ dynamic(Bin, S1) when S1 >= 0 ->
S2 = size(Bin) * 8 - S1,
dynamic(Bin, S1, S2, (1 bsl S1) - 1, (1 bsl S2) - 1),
dynamic(Bin, S1-1);
-dynamic(_Bin, _) -> ok.
+dynamic(_, _) -> ok.
dynamic(Bin, S1, S2, A, B) ->
% io:format("~p ~p ~p ~p\n", [S1,S2,A,B]),
@@ -132,25 +139,24 @@ dynamic(Bin, S1, S2, A, B) ->
<<A:S1,B:S2>> ->
io:format("~p ~p ~p ~p\n", [S1,S2,A,B]),
ok;
- _Other ->
- erlang:error(badmatch, [Bin,S1,S2,A,B])
+ _Other -> erlang:error(badmatch, [Bin,S1,S2,A,B])
end.
more_dynamic(doc) -> "Extract integers at different alignments and of different sizes.";
-more_dynamic(Config) when list(Config) ->
+more_dynamic(Config) when is_list(Config) ->
% Unsigned big-endian numbers.
Unsigned = fun(Bin, List, SkipBef, N) ->
SkipAft = 8*size(Bin) - N - SkipBef,
- <<_I1:SkipBef,Int:N,_I2:SkipAft>> = Bin,
+ <<_:SkipBef,Int:N,_:SkipAft>> = Bin,
Int = make_int(List, N, 0)
end,
?line more_dynamic1(Unsigned, funny_binary(42)),
- % Signed big-endian numbers.
+ %% Signed big-endian numbers.
Signed = fun(Bin, List, SkipBef, N) ->
SkipAft = 8*size(Bin) - N - SkipBef,
- <<_I1:SkipBef,Int:N/signed,_I2:SkipAft>> = Bin,
+ <<_:SkipBef,Int:N/signed,_:SkipAft>> = Bin,
case make_signed_int(List, N) of
Int -> ok;
Other ->
@@ -162,18 +168,18 @@ more_dynamic(Config) when list(Config) ->
end,
?line more_dynamic1(Signed, funny_binary(43)),
- % Unsigned little-endian numbers.
+ %% Unsigned little-endian numbers.
UnsLittle = fun(Bin, List, SkipBef, N) ->
SkipAft = 8*size(Bin) - N - SkipBef,
- <<_I1:SkipBef,Int:N/little,_I2:SkipAft>> = Bin,
+ <<_:SkipBef,Int:N/little,_:SkipAft>> = Bin,
Int = make_int(big_to_little(List, N), N, 0)
end,
?line more_dynamic1(UnsLittle, funny_binary(44)),
- % Signed little-endian numbers.
+ %% Signed little-endian numbers.
SignLittle = fun(Bin, List, SkipBef, N) ->
SkipAft = 8*size(Bin) - N - SkipBef,
- <<_I1:SkipBef,Int:N/signed-little,_I2:SkipAft>> = Bin,
+ <<_:SkipBef,Int:N/signed-little,_:SkipAft>> = Bin,
Little = big_to_little(List, N),
Int = make_signed_int(Little, N)
end,
@@ -181,11 +187,6 @@ more_dynamic(Config) when list(Config) ->
ok.
-funny_binary(N) ->
- B0 = erlang:md5([N]),
- {B1,_B2} = split_binary(B0, size(B0) div 2),
- B1.
-
more_dynamic1(Action, Bin) ->
BitList = bits_to_list(binary_to_list(Bin), 16#80),
more_dynamic2(Action, Bin, BitList, 0).
@@ -193,7 +194,7 @@ more_dynamic1(Action, Bin) ->
more_dynamic2(Action, Bin, [_|T]=List, Bef) ->
more_dynamic3(Action, Bin, List, Bef, size(Bin)*8),
more_dynamic2(Action, Bin, T, Bef+1);
-more_dynamic2(_Action, _Bin, [], _Bef) -> ok.
+more_dynamic2(_, _, [], _) -> ok.
more_dynamic3(Action, Bin, List, Bef, Aft) when Bef =< Aft ->
%% io:format("~p, ~p", [Bef,Aft-Bef]),
@@ -208,8 +209,8 @@ big_to_little([B0,B1,B2,B3,B4,B5,B6,B7|T], N, Acc) when N >= 8 ->
big_to_little(List, N, Acc) -> lists:sublist(List, 1, N) ++ Acc.
make_signed_int(_List, 0) -> 0;
-make_signed_int([0|_T]=List, N) -> make_int(List, N, 0);
-make_signed_int([1|_T]=List0, N) ->
+make_signed_int([0|_]=List, N) -> make_int(List, N, 0);
+make_signed_int([1|_]=List0, N) ->
List1 = reversed_sublist(List0, N, []),
List2 = two_complement_and_reverse(List1, 1, []),
-make_int(List2, length(List2), 0).
@@ -225,7 +226,7 @@ two_complement_and_reverse([], Carry, Acc) -> [Carry|Acc].
make_int(_List, 0, Acc) -> Acc;
make_int([H|T], N, Acc) -> make_int(T, N-1, Acc bsl 1 bor H).
-bits_to_list([_H|T], 0) -> bits_to_list(T, 16#80);
+bits_to_list([_|T], 0) -> bits_to_list(T, 16#80);
bits_to_list([H|_]=List, Mask) ->
[case H band Mask of
0 -> 0;
@@ -234,11 +235,134 @@ bits_to_list([H|_]=List, Mask) ->
bits_to_list([], _) -> [].
fun_clause({'EXIT',{function_clause,_}}) -> ok.
-mkbin(L) when list(L) -> list_to_binary(L).
+mkbin(L) when is_list(L) -> list_to_binary(L).
+
+funny_binary(N) ->
+ B0 = erlang:md5([N]),
+ {B1,_B2} = split_binary(B0, byte_size(B0) div 3),
+ B1.
-mml(Config) when list(Config) ->
+mml(Config) when is_list(Config) ->
?line single_byte_binary = mml_choose(<<42>>),
?line multi_byte_binary = mml_choose(<<42,43>>).
mml_choose(<<_A:8>>) -> single_byte_binary;
-mml_choose(<<_A:8, _T/binary>>) -> multi_byte_binary.
+mml_choose(<<_A:8,_T/binary>>) -> multi_byte_binary.
+
+match_huge_int(Config) when is_list(Config) ->
+ Sz = 1 bsl 27,
+ ?line Bin = <<0:Sz,13:8>>,
+ ?line skip_huge_int_1(Sz, Bin),
+ ?line 0 = match_huge_int_1(Sz, Bin),
+
+ %% Test overflowing the size of an integer field.
+ ?line nomatch = overflow_huge_int_skip_32(Bin),
+ case erlang:system_info(wordsize) of
+ 4 ->
+ ?line nomatch = overflow_huge_int_32(Bin);
+ 8 ->
+ %% An attempt will be made to allocate heap space for
+ %% the bignum (which will probably fail); only if the
+ %% allocation succeds will the matching fail because
+ %% the binary is too small.
+ ok
+ end,
+ ?line nomatch = overflow_huge_int_skip_64(Bin),
+ ?line nomatch = overflow_huge_int_64(Bin),
+
+ %% Test overflowing the size of an integer field using variables as sizes.
+ ?line Sizes = case erlang:system_info(wordsize) of
+ 4 -> lists:seq(25, 32);
+ 8 -> []
+ end ++ lists:seq(50, 64),
+ ?line ok = overflow_huge_int_unit128(Bin, Sizes),
+
+ ok.
+
+overflow_huge_int_unit128(Bin, [Sz0|Sizes]) ->
+ Sz = id(1 bsl Sz0),
+ case Bin of
+ <<_:Sz/unit:128,0,_/binary>> ->
+ {error,Sz};
+ _ ->
+ case Bin of
+ <<Var:Sz/unit:128,0,_/binary>> ->
+ {error,Sz,Var};
+ _ ->
+ overflow_huge_int_unit128(Bin, Sizes)
+ end
+ end;
+overflow_huge_int_unit128(_, []) -> ok.
+
+match_huge_int_1(I, Bin) ->
+ <<Int:I,13>> = Bin,
+ Int.
+
+skip_huge_int_1(I, Bin) ->
+ <<_:I,13>> = Bin.
+
+overflow_huge_int_skip_32(<<_:4294967296,0,_/binary>>) -> 1; % 1 bsl 32
+overflow_huge_int_skip_32(<<_:33554432/unit:128,0,_/binary>>) -> 2; % 1 bsl 25
+overflow_huge_int_skip_32(<<_:67108864/unit:64,0,_/binary>>) -> 3; % 1 bsl 26
+overflow_huge_int_skip_32(<<_:134217728/unit:32,0,_/binary>>) -> 4; % 1 bsl 27
+overflow_huge_int_skip_32(<<_:268435456/unit:16,0,_/binary>>) -> 5; % 1 bsl 28
+overflow_huge_int_skip_32(<<_:536870912/unit:8,0,_/binary>>) -> 6; % 1 bsl 29
+overflow_huge_int_skip_32(<<_:1073741824/unit:8,0,_/binary>>) -> 7; % 1 bsl 30
+overflow_huge_int_skip_32(<<_:2147483648/unit:8,0,_/binary>>) -> 8; % 1 bsl 31
+overflow_huge_int_skip_32(_) -> nomatch.
+
+overflow_huge_int_32(<<Int:4294967296,_/binary>>) -> {1,Int}; % 1 bsl 32
+overflow_huge_int_32(<<Int:33554432/unit:128,0,_/binary>>) -> {2,Int}; % 1 bsl 25
+overflow_huge_int_32(<<Int:67108864/unit:128,0,_/binary>>) -> {3,Int}; % 1 bsl 26
+overflow_huge_int_32(<<Int:134217728/unit:128,0,_/binary>>) -> {4,Int}; % 1 bsl 27
+overflow_huge_int_32(<<Int:268435456/unit:128,0,_/binary>>) -> {5,Int}; % 1 bsl 28
+overflow_huge_int_32(<<Int:536870912/unit:128,0,_/binary>>) -> {6,Int}; % 1 bsl 29
+overflow_huge_int_32(<<Int:1073741824/unit:128,0,_/binary>>) -> {7,Int}; % 1 bsl 30
+overflow_huge_int_32(<<Int:2147483648/unit:128,0,_/binary>>) -> {8,Int}; % 1 bsl 31
+overflow_huge_int_32(_) -> nomatch.
+
+overflow_huge_int_skip_64(<<_:18446744073709551616,_/binary>>) -> 1; % 1 bsl 64
+overflow_huge_int_skip_64(<<_:144115188075855872/unit:128,0,_/binary>>) -> 2; % 1 bsl 57
+overflow_huge_int_skip_64(<<_:288230376151711744/unit:64,0,_/binary>>) -> 3; % 1 bsl 58
+overflow_huge_int_skip_64(<<_:576460752303423488/unit:32,0,_/binary>>) -> 4; % 1 bsl 59
+overflow_huge_int_skip_64(<<_:1152921504606846976/unit:16,0,_/binary>>) -> 5; % 1 bsl 60
+overflow_huge_int_skip_64(<<_:2305843009213693952/unit:8,0,_/binary>>) -> 6; % 1 bsl 61
+overflow_huge_int_skip_64(<<_:4611686018427387904/unit:8,0,_/binary>>) -> 7; % 1 bsl 62
+overflow_huge_int_skip_64(<<_:9223372036854775808/unit:8,0,_/binary>>) -> 8; % 1 bsl 63
+overflow_huge_int_skip_64(_) -> nomatch.
+
+overflow_huge_int_64(<<Int:18446744073709551616,_/binary>>) -> {1,Int}; % 1 bsl 64
+overflow_huge_int_64(<<Int:144115188075855872/unit:128,0,_/binary>>) -> {2,Int}; % 1 bsl 57
+overflow_huge_int_64(<<Int:288230376151711744/unit:128,0,_/binary>>) -> {3,Int}; % 1 bsl 58
+overflow_huge_int_64(<<Int:576460752303423488/unit:128,0,_/binary>>) -> {4,Int}; % 1 bsl 59
+overflow_huge_int_64(<<Int:1152921504606846976/unit:128,0,_/binary>>) -> {5,Int}; % 1 bsl 60
+overflow_huge_int_64(<<Int:2305843009213693952/unit:128,0,_/binary>>) -> {6,Int}; % 1 bsl 61
+overflow_huge_int_64(<<Int:4611686018427387904/unit:128,0,_/binary>>) -> {7,Int}; % 1 bsl 62
+overflow_huge_int_64(<<Int:9223372036854775808/unit:128,0,_/binary>>) -> {8,Int}; % 1 bsl 63
+overflow_huge_int_64(_) -> nomatch.
+
+bignum(Config) when is_list(Config) ->
+ ?line Bin = id(<<42,0:1024/unit:8,43>>),
+ ?line <<42:1025/little-integer-unit:8,_:8>> = Bin,
+ ?line <<_:8,43:1025/integer-unit:8>> = Bin,
+
+ ?line BignumBin = id(<<0:512/unit:8,258254417031933722623:9/unit:8>>),
+ ?line <<258254417031933722623:(512+9)/unit:8>> = BignumBin,
+ erlang:garbage_collect(), %Search for holes in debug-build.
+ ok.
+
+unaligned_32_bit(Config) when is_list(Config) ->
+ %% There used to be a risk for heap overflow (fixed in R11B-5).
+ ?line L = unaligned_32_bit_1(<<-1:(64*1024)>>),
+ ?line unaligned_32_bit_verify(L, 1638).
+
+unaligned_32_bit_1(<<1:1,U:32,_:7,T/binary>>) ->
+ [U|unaligned_32_bit_1(T)];
+unaligned_32_bit_1(_) ->
+ [].
+
+unaligned_32_bit_verify([], 0) -> ok;
+unaligned_32_bit_verify([4294967295|T], N) when N > 0 ->
+ unaligned_32_bit_verify(T, N-1).
+
+id(I) -> I.
diff --git a/lib/debugger/test/bs_match_misc_SUITE.erl b/lib/debugger/test/bs_match_misc_SUITE.erl
index 53d11ba179..89fce263f5 100644
--- a/lib/debugger/test/bs_match_misc_SUITE.erl
+++ b/lib/debugger/test/bs_match_misc_SUITE.erl
@@ -19,18 +19,24 @@
-module(bs_match_misc_SUITE).
--author('[email protected]').
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
init_per_suite/1,end_per_suite/1,
- bound_var/1,bound_tail/1,t_float/1,little_float/1,sean/1]).
+ bound_var/1,bound_tail/1,t_float/1,little_float/1,sean/1,
+ kenneth/1,encode_binary/1,native/1,happi/1,
+ size_var/1,wiger/1,x0_context/1,huge_float_field/1,
+ writable_binary_matched/1,otp_7198/1,
+ unordered_bindings/1]).
-include_lib("test_server/include/test_server.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- cases().
+ [bound_var, bound_tail, t_float, little_float, sean,
+ kenneth, encode_binary, native, happi, size_var, wiger,
+ x0_context, huge_float_field, writable_binary_matched,
+ otp_7198, unordered_bindings].
groups() ->
[].
@@ -41,9 +47,13 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
+init_per_suite(Config) when is_list(Config) ->
+ ?line test_lib:interpret(?MODULE),
+ ?line true = lists:member(?MODULE, int:interpreted()),
+ Config.
-cases() ->
- [bound_var, bound_tail, t_float, little_float, sean].
+end_per_suite(Config) when is_list(Config) ->
+ ok.
init_per_testcase(_Case, Config) ->
test_lib:interpret(?MODULE),
@@ -55,16 +65,8 @@ end_per_testcase(_Case, Config) ->
?t:timetrap_cancel(Dog),
ok.
-init_per_suite(Config) when is_list(Config) ->
- ?line test_lib:interpret(?MODULE),
- ?line true = lists:member(?MODULE, int:interpreted()),
- Config.
-
-end_per_suite(Config) when is_list(Config) ->
- ok.
-
bound_var(doc) -> "Test matching of bound variables.";
-bound_var(Config) when list(Config) ->
+bound_var(Config) when is_list(Config) ->
?line ok = bound_var(42, 13, <<42,13>>),
?line nope = bound_var(42, 13, <<42,255>>),
?line nope = bound_var(42, 13, <<154,255>>),
@@ -74,7 +76,7 @@ bound_var(A, B, <<A:8,B:8>>) -> ok;
bound_var(_, _, _) -> nope.
bound_tail(doc) -> "Test matching of a bound tail.";
-bound_tail(Config) when list(Config) ->
+bound_tail(Config) when is_list(Config) ->
?line ok = bound_tail(<<>>, <<13,14>>),
?line ok = bound_tail(<<2,3>>, <<1,1,2,3>>),
?line nope = bound_tail(<<2,3>>, <<1,1,2,7>>),
@@ -85,7 +87,7 @@ bound_tail(Config) when list(Config) ->
bound_tail(T, <<_:16,T/binary>>) -> ok;
bound_tail(_, _) -> nope.
-t_float(Config) when list(Config) ->
+t_float(Config) when is_list(Config) ->
F = f1(),
G = f_one(),
@@ -98,6 +100,10 @@ t_float(Config) when list(Config) ->
?line fcmp(F, match_float(<<1:1,F:64/float,127:7>>, 64, 1)),
?line fcmp(F, match_float(<<1:13,F:32/float,127:3>>, 32, 13)),
?line fcmp(F, match_float(<<1:13,F:64/float,127:3>>, 64, 13)),
+
+ ?line {'EXIT',{{badmatch,_},_}} = (catch match_float(<<0,0>>, 16, 0)),
+ ?line {'EXIT',{{badmatch,_},_}} = (catch match_float(<<0,0>>, 16#7fffffff, 0)),
+
ok.
@@ -110,7 +116,7 @@ match_float(Bin0, Fsz, I) ->
<<_:I,F:Fsz/float,_:Tsz>> = Bin,
F.
-little_float(Config) when list(Config) ->
+little_float(Config) when is_list(Config) ->
F = f2(),
G = f_one(),
@@ -149,7 +155,7 @@ f2() ->
f_one() ->
1.0.
-sean(Config) when list(Config) ->
+sean(Config) when is_list(Config) ->
?line small = sean1(<<>>),
?line small = sean1(<<1>>),
?line small = sean1(<<1,2>>),
@@ -162,5 +168,414 @@ sean(Config) when list(Config) ->
?line {'EXIT',{function_clause,_}} = (catch sean1(<<4,5,6,7>>)),
ok.
-sean1(<<B/binary>>) when size(B) < 4 -> small;
+sean1(<<B/binary>>) when byte_size(B) < 4 -> small;
sean1(<<1, _B/binary>>) -> large.
+
+kenneth(Config) when is_list(Config) ->
+ {ok,[145,148,113,129,0,0,0,0]} =
+ msisdn_internal_storage(<<145,148,113,129,0,0,0,0>>, []).
+
+msisdn_internal_storage(<<>>,MSISDN) ->
+ {ok,lists:reverse(MSISDN)};
+msisdn_internal_storage(<<2#11111111:8,_Rest/binary>>,MSISDN) ->
+ {ok,lists:reverse(MSISDN)};
+msisdn_internal_storage(<<2#1111:4,DigitN:4,_Rest/binary>>,MSISDN) when
+ DigitN < 10 ->
+ {ok,lists:reverse([(DigitN bor 2#11110000)|MSISDN])};
+msisdn_internal_storage(<<DigitNplus1:4,DigitN:4,Rest/binary>>,MSISDN) when
+ DigitNplus1 < 10,
+ DigitN < 10 ->
+ NewMSISDN=[((DigitNplus1 bsl 4) bor DigitN)|MSISDN],
+ msisdn_internal_storage(Rest,NewMSISDN);
+msisdn_internal_storage(_Rest,_MSISDN) ->
+ {fault}. %% Mandatory IE incorrect
+
+encode_binary(Config) when is_list(Config) ->
+ "C2J2QiSc" = encodeBinary(<<11,98,118,66,36,156>>, []),
+ ok.
+
+encodeBinary(<<>>, Output) ->
+ lists:reverse(Output);
+encodeBinary(<<Data:1/binary>>, Output) ->
+ <<DChar1:6, DChar2:2>> = Data,
+ Char1 = getBase64Char(DChar1),
+ Char2 = getBase64Char(DChar2),
+ Char3 = "=",
+ Char4 = "=",
+ NewOutput = Char4 ++ Char3 ++ Char2 ++ Char1 ++ Output,
+ encodeBinary(<<>>, NewOutput);
+encodeBinary(<<Data:2/binary>>, Output) ->
+ <<DChar1:6, DChar2:6, DChar3:4>> = Data,
+ Char1 = getBase64Char(DChar1),
+ Char2 = getBase64Char(DChar2),
+ Char3 = getBase64Char(DChar3),
+ Char4 = "=",
+ NewOutput = Char4 ++ Char3 ++ Char2 ++ Char1 ++ Output,
+ encodeBinary(<<>>, NewOutput);
+encodeBinary(<<Data:3/binary, Rest/binary>>, Output) ->
+ <<DChar1:6, DChar2:6, DChar3:6, DChar4:6>> = Data,
+ Char1 = getBase64Char(DChar1),
+ Char2 = getBase64Char(DChar2),
+ Char3 = getBase64Char(DChar3),
+ Char4 = getBase64Char(DChar4),
+ NewOutput = Char4 ++ Char3 ++ Char2 ++ Char1 ++ Output,
+ encodeBinary(Rest, NewOutput);
+encodeBinary(_Data, _) ->
+ error.
+
+getBase64Char(0) -> "A";
+getBase64Char(1) -> "B";
+getBase64Char(2) -> "C";
+getBase64Char(3) -> "D";
+getBase64Char(4) -> "E";
+getBase64Char(5) -> "F";
+getBase64Char(6) -> "G";
+getBase64Char(7) -> "H";
+getBase64Char(8) -> "I";
+getBase64Char(9) -> "J";
+getBase64Char(10) -> "K";
+getBase64Char(11) -> "L";
+getBase64Char(12) -> "M";
+getBase64Char(13) -> "N";
+getBase64Char(14) -> "O";
+getBase64Char(15) -> "P";
+getBase64Char(16) -> "Q";
+getBase64Char(17) -> "R";
+getBase64Char(18) -> "S";
+getBase64Char(19) -> "T";
+getBase64Char(20) -> "U";
+getBase64Char(21) -> "V";
+getBase64Char(22) -> "W";
+getBase64Char(23) -> "X";
+getBase64Char(24) -> "Y";
+getBase64Char(25) -> "Z";
+getBase64Char(26) -> "a";
+getBase64Char(27) -> "b";
+getBase64Char(28) -> "c";
+getBase64Char(29) -> "d";
+getBase64Char(30) -> "e";
+getBase64Char(31) -> "f";
+getBase64Char(32) -> "g";
+getBase64Char(33) -> "h";
+getBase64Char(34) -> "i";
+getBase64Char(35) -> "j";
+getBase64Char(36) -> "k";
+getBase64Char(37) -> "l";
+getBase64Char(38) -> "m";
+getBase64Char(39) -> "n";
+getBase64Char(40) -> "o";
+getBase64Char(41) -> "p";
+getBase64Char(42) -> "q";
+getBase64Char(43) -> "r";
+getBase64Char(44) -> "s";
+getBase64Char(45) -> "t";
+getBase64Char(46) -> "u";
+getBase64Char(47) -> "v";
+getBase64Char(48) -> "w";
+getBase64Char(49) -> "x";
+getBase64Char(50) -> "y";
+getBase64Char(51) -> "z";
+getBase64Char(52) -> "0";
+getBase64Char(53) -> "1";
+getBase64Char(54) -> "2";
+getBase64Char(55) -> "3";
+getBase64Char(56) -> "4";
+getBase64Char(57) -> "5";
+getBase64Char(58) -> "6";
+getBase64Char(59) -> "7";
+getBase64Char(60) -> "8";
+getBase64Char(61) -> "9";
+getBase64Char(62) -> "+";
+getBase64Char(63) -> "/";
+getBase64Char(_Else) ->
+ %% This is an illegal input.
+% cgLogEM:log(error, ?MODULE, getBase64Char, [Else],
+% "illegal input",
+% ?LINE, version()),
+ "**".
+
+-define(M(F), <<F>> = <<F>>).
+
+native(Config) when is_list(Config) ->
+ ?line ?M(3.14:64/native-float),
+ ?line ?M(333:16/native),
+ ?line ?M(38658345:32/native),
+ case <<1:16/native>> of
+ <<0,1>> -> native_big();
+ <<1,0>> -> native_little()
+ end.
+
+native_big() ->
+ ?line <<37.33:64/native-float>> = <<37.33:64/big-float>>,
+ ?line <<3974:16/native-integer>> = <<3974:16/big-integer>>,
+ {comment,"Big endian"}.
+
+native_little() ->
+ ?line <<37869.32343:64/native-float>> = <<37869.32343:64/little-float>>,
+ ?line <<7974:16/native-integer>> = <<7974:16/little-integer>>,
+ {comment,"Little endian"}.
+
+happi(Config) when is_list(Config) ->
+ Bin = <<".123">>,
+ ?line <<"123">> = lex_digits1(Bin, 1, []),
+ ?line <<"123">> = lex_digits2(Bin, 1, []),
+ ok.
+
+lex_digits1(<<$., Rest/binary>>,_Val,_Acc) ->
+ Rest;
+lex_digits1(<<N, Rest/binary>>,Val, Acc) when N >= $0 , N =< $9 ->
+ lex_digits1(Rest,Val*10+dec(N),Acc);
+lex_digits1(_Other,_Val,_Acc) ->
+ not_ok.
+
+lex_digits2(<<N, Rest/binary>>,Val, Acc) when N >= $0 , N =< $9 ->
+ lex_digits2(Rest,Val*10+dec(N),Acc);
+lex_digits2(<<$., Rest/binary>>,_Val,_Acc) ->
+ Rest;
+lex_digits2(_Other,_Val,_Acc) ->
+ not_ok.
+
+dec(A) ->
+ A-$0.
+
+size_var(Config) when is_list(Config) ->
+ ?line {<<45>>,<<>>} = split(<<1:16,45>>),
+ ?line {<<45>>,<<46,47>>} = split(<<1:16,45,46,47>>),
+ ?line {<<45,46>>,<<47>>} = split(<<2:16,45,46,47>>),
+
+ ?line {<<45,46,47>>,<<48>>} = split_2(<<16:8,3:16,45,46,47,48>>),
+
+ ?line {<<45,46>>,<<47>>} = split(2, <<2:16,45,46,47>>),
+ ?line {'EXIT',{function_clause,_}} = (catch split(42, <<2:16,45,46,47>>)),
+
+ ?line <<"cdef">> = skip(<<2:8,"abcdef">>),
+
+ ok.
+
+split(<<N:16,B:N/binary,T/binary>>) ->
+ {B,T}.
+
+split(N, <<N:16,B:N/binary,T/binary>>) ->
+ {B,T}.
+
+split_2(<<N0:8,N:N0,B:N/binary,T/binary>>) ->
+ {B,T}.
+
+skip(<<N:8,_:N/binary,T/binary>>) -> T.
+
+wiger(Config) when is_list(Config) ->
+ ?line ok1 = wcheck(<<3>>),
+ ?line ok2 = wcheck(<<1,2,3>>),
+ ?line ok3 = wcheck(<<4>>),
+ ?line {error,<<1,2,3,4>>} = wcheck(<<1,2,3,4>>),
+ ?line {error,<<>>} = wcheck(<<>>),
+ ok.
+
+wcheck(<<A>>) when A==3->
+ ok1;
+wcheck(<<_,_:2/binary>>) ->
+ ok2;
+wcheck(<<_>>) ->
+ ok3;
+wcheck(Other) ->
+ {error,Other}.
+
+%% Test that having the match context in x(0) works.
+
+x0_context(Config) when is_list(Config) ->
+ x0_0([], <<3.0:64/float,42:16,123456:32>>).
+
+x0_0(_, Bin) ->
+ <<3.0:64/float,42:16,_/binary>> = Bin,
+ x0_1([], Bin, 64, 16, 2).
+
+x0_1(_, Bin, FloatSz, IntSz, BinSz) ->
+ <<_:FloatSz/float,42:IntSz,B:BinSz/binary,C:1/binary,D/binary>> = Bin,
+ id({B,C,D}),
+ <<_:FloatSz/float,42:IntSz,B:BinSz/binary,_/binary>> = Bin,
+ x0_2([], Bin).
+
+x0_2(_, Bin) ->
+ <<_:64,0:7,42:9,_/binary>> = Bin,
+ x0_3([], Bin).
+
+x0_3(_, Bin) ->
+ case Bin of
+ <<_:72,7:8,_/binary>> ->
+ ?line ?t:fail();
+ <<_:64,0:16,_/binary>> ->
+ ?line ?t:fail();
+ <<_:64,42:16,123456:32,_/binary>> ->
+ ok
+ end.
+
+
+huge_float_field(Config) when is_list(Config) ->
+ Sz = 1 bsl 27,
+ ?line Bin = <<0:Sz>>,
+
+ ?line nomatch = overflow_huge_float_skip_32(Bin),
+ ?line nomatch = overflow_huge_float_32(Bin),
+
+ ?line ok = overflow_huge_float(Bin, lists:seq(25, 32)++lists:seq(50, 64)),
+ ?line ok = overflow_huge_float_unit128(Bin, lists:seq(25, 32)++lists:seq(50, 64)),
+ ok.
+
+overflow_huge_float_skip_32(<<_:4294967296/float,0,_/binary>>) -> 1; % 1 bsl 32
+overflow_huge_float_skip_32(<<_:33554432/float-unit:128,0,_/binary>>) -> 2; % 1 bsl 25
+overflow_huge_float_skip_32(<<_:67108864/float-unit:64,0,_/binary>>) -> 3; % 1 bsl 26
+overflow_huge_float_skip_32(<<_:134217728/float-unit:32,0,_/binary>>) -> 4; % 1 bsl 27
+overflow_huge_float_skip_32(<<_:268435456/float-unit:16,0,_/binary>>) -> 5; % 1 bsl 28
+overflow_huge_float_skip_32(<<_:536870912/float-unit:8,0,_/binary>>) -> 6; % 1 bsl 29
+overflow_huge_float_skip_32(<<_:1073741824/float-unit:8,0,_/binary>>) -> 7; % 1 bsl 30
+overflow_huge_float_skip_32(<<_:2147483648/float-unit:8,0,_/binary>>) -> 8; % 1 bsl 31
+overflow_huge_float_skip_32(_) -> nomatch.
+
+overflow_huge_float_32(<<F:4294967296/float,_/binary>>) -> {1,F}; % 1 bsl 32
+overflow_huge_float_32(<<F:33554432/float-unit:128,0,_/binary>>) -> {2,F}; % 1 bsl 25
+overflow_huge_float_32(<<F:67108864/float-unit:128,0,_/binary>>) -> {3,F}; % 1 bsl 26
+overflow_huge_float_32(<<F:134217728/float-unit:128,0,_/binary>>) -> {4,F}; % 1 bsl 27
+overflow_huge_float_32(<<F:268435456/float-unit:128,0,_/binary>>) -> {5,F}; % 1 bsl 28
+overflow_huge_float_32(<<F:536870912/float-unit:128,0,_/binary>>) -> {6,F}; % 1 bsl 29
+overflow_huge_float_32(<<F:1073741824/float-unit:128,0,_/binary>>) -> {7,F}; % 1 bsl 30
+overflow_huge_float_32(<<F:2147483648/float-unit:128,0,_/binary>>) -> {8,F}; % 1 bsl 31
+overflow_huge_float_32(_) -> nomatch.
+
+
+overflow_huge_float(Bin, [Sz0|Sizes]) ->
+ Sz = id(1 bsl Sz0),
+ case Bin of
+ <<_:Sz/float-unit:8,0,_/binary>> ->
+ {error,Sz};
+ _ ->
+ case Bin of
+ <<Var:Sz/float-unit:8,0,_/binary>> ->
+ {error,Sz,Var};
+ _ ->
+ overflow_huge_float(Bin, Sizes)
+ end
+ end;
+overflow_huge_float(_, []) -> ok.
+
+overflow_huge_float_unit128(Bin, [Sz0|Sizes]) ->
+ Sz = id(1 bsl Sz0),
+ case Bin of
+ <<_:Sz/float-unit:128,0,_/binary>> ->
+ {error,Sz};
+ _ ->
+ case Bin of
+ <<Var:Sz/float-unit:128,0,_/binary>> ->
+ {error,Sz,Var};
+ _ ->
+ overflow_huge_float_unit128(Bin, Sizes)
+ end
+ end;
+overflow_huge_float_unit128(_, []) -> ok.
+
+
+%%
+%% Test that a writable binary can be safely matched.
+%%
+
+writable_binary_matched(Config) when is_list(Config) ->
+ ?line WritableBin = create_writeable_binary(),
+ ?line writable_binary_matched(WritableBin, WritableBin, 500).
+
+writable_binary_matched(<<0>>, _, N) ->
+ if
+ N =:= 0 -> ok;
+ true ->
+ put(grow_heap, [N|get(grow_heap)]),
+ ?line WritableBin = create_writeable_binary(),
+ ?line writable_binary_matched(WritableBin, WritableBin, N-1)
+ end;
+writable_binary_matched(<<B:8,T/binary>>, WritableBin0, N) ->
+ ?line WritableBin = writable_binary(WritableBin0, B),
+ writable_binary_matched(T, WritableBin, N).
+
+writable_binary(WritableBin0, B) when is_binary(WritableBin0) ->
+ %% Heavy append to force the binary to move.
+ ?line WritableBin = <<WritableBin0/binary,0:(size(WritableBin0))/unit:8,B>>,
+ ?line id(<<(id(0)):128/unit:8>>),
+ WritableBin.
+
+create_writeable_binary() ->
+ <<(id(<<>>))/binary,1,2,3,4,5,6,0>>.
+
+otp_7198(Config) when is_list(Config) ->
+ %% When a match context was reused, and grown at the same time to
+ %% increase the number of saved positions, the thing word was not updated
+ %% to account for the new size. Therefore, if there was a garbage collection,
+ %% the new slots would be included in the garbage collection.
+ ?line [do_otp_7198(FillerSize) || FillerSize <- lists:seq(0, 256)],
+ ok.
+
+do_otp_7198(FillerSize) ->
+ Filler = erlang:make_tuple(FillerSize, 42),
+ {Pid,Ref} = spawn_monitor(fun() -> do_otp_7198_test(Filler) end),
+ receive
+ {'DOWN',Ref,process,Pid,normal} ->
+ ok;
+ {'DOWN',Ref,process,Pid,Reason} ->
+ io:format("unexpected: ~p", [Reason]),
+ ?line ?t:fail()
+ end.
+
+do_otp_7198_test(_) ->
+ [{'KEYWORD',114},
+ {'KEYWORD',101},
+ {'KEYWORD',103},
+ {'KEYWORD',105},
+ {'KEYWORD',111},
+ {'FIELD',110},
+ {'KEYWORD',119},
+ {'KEYWORD',104},
+ {'KEYWORD',97},
+ {'KEYWORD',116},
+ {'KEYWORD',101},
+ {'KEYWORD',118},
+ {'KEYWORD',101},
+ {'KEYWORD',114},
+ '$thats_all_folks$'] = otp_7198_scan(<<"region:whatever">>, []).
+
+
+otp_7198_scan(<<>>, TokAcc) ->
+ lists:reverse(['$thats_all_folks$' | TokAcc]);
+
+otp_7198_scan(<<D, Z, Rest/binary>>, TokAcc) when
+ (D =:= $D orelse D =:= $d) and
+ ((Z =:= $\s) or (Z =:= $() or (Z =:= $))) ->
+ otp_7198_scan(<<Z, Rest/binary>>, ['AND' | TokAcc]);
+
+otp_7198_scan(<<D>>, TokAcc) when
+ (D =:= $D) or (D =:= $d) ->
+ otp_7198_scan(<<>>, ['AND' | TokAcc]);
+
+otp_7198_scan(<<N, Z, Rest/binary>>, TokAcc) when
+ (N =:= $N orelse N =:= $n) and
+ ((Z =:= $\s) or (Z =:= $() or (Z =:= $))) ->
+ otp_7198_scan(<<Z, Rest/binary>>, ['NOT' | TokAcc]);
+
+otp_7198_scan(<<C, Rest/binary>>, TokAcc) when
+ (C >= $A) and (C =< $Z);
+ (C >= $a) and (C =< $z);
+ (C >= $0) and (C =< $9) ->
+ case Rest of
+ <<$:, R/binary>> ->
+ otp_7198_scan(R, [{'FIELD', C} | TokAcc]);
+ _ ->
+ otp_7198_scan(Rest, [{'KEYWORD', C} | TokAcc])
+ end.
+
+unordered_bindings(Config) when is_list(Config) ->
+ {<<1,2,3,4>>,<<42,42>>,<<3,3,3>>} =
+ unordered_bindings(4, 2, 3, <<1,2,3,4, 42,42, 3,3,3, 3>>),
+ ok.
+
+unordered_bindings(CompressedLength, HashSize, PadLength, T) ->
+ <<Content:CompressedLength/binary,Mac:HashSize/binary,
+ Padding:PadLength/binary,PadLength>> = T,
+ {Content,Mac,Padding}.
+
+
+id(I) -> I.
diff --git a/lib/debugger/test/bs_match_tail_SUITE.erl b/lib/debugger/test/bs_match_tail_SUITE.erl
index 961ccbb599..9f7519cf3a 100644
--- a/lib/debugger/test/bs_match_tail_SUITE.erl
+++ b/lib/debugger/test/bs_match_tail_SUITE.erl
@@ -64,7 +64,7 @@ end_per_suite(Config) when is_list(Config) ->
ok.
aligned(doc) -> "Test aligned tails.";
-aligned(Config) when list(Config) ->
+aligned(Config) when is_list(Config) ->
?line Tail1 = mkbin([]),
?line {258,Tail1} = al_get_tail_used(mkbin([1,2])),
?line Tail2 = mkbin(lists:seq(1, 127)),
@@ -84,10 +84,10 @@ aligned(Config) when list(Config) ->
ok.
al_get_tail_used(<<A:16,T/binary>>) -> {A,T}.
-al_get_tail_unused(<<A:16,_T/binary>>) -> A.
+al_get_tail_unused(<<A:16,_/binary>>) -> A.
unaligned(doc) -> "Test that an non-aligned tail cannot be matched out.";
-unaligned(Config) when list(Config) ->
+unaligned(Config) when is_list(Config) ->
?line {'EXIT',{function_clause,_}} = (catch get_tail_used(mkbin([42]))),
?line {'EXIT',{{badmatch,_},_}} = (catch get_dyn_tail_used(mkbin([137]), 3)),
?line {'EXIT',{function_clause,_}} = (catch get_tail_unused(mkbin([42,33]))),
@@ -103,11 +103,11 @@ get_dyn_tail_used(Bin, Sz) ->
{A,T}.
get_dyn_tail_unused(Bin, Sz) ->
- <<A:Sz,_T/binary>> = Bin,
+ <<A:Sz,_/binary>> = Bin,
A.
zero_tail(doc) -> "Test that zero tails are tested correctly.";
-zero_tail(Config) when list(Config) ->
+zero_tail(Config) when is_list(Config) ->
?line 7 = (catch test_zero_tail(mkbin([7]))),
?line {'EXIT',{function_clause,_}} = (catch test_zero_tail(mkbin([1,2]))),
?line {'EXIT',{function_clause,_}} = (catch test_zero_tail2(mkbin([1,2,3]))),
@@ -117,4 +117,4 @@ test_zero_tail(<<A:8>>) -> A.
test_zero_tail2(<<_A:4,_B:4>>) -> ok.
-mkbin(L) when list(L) -> list_to_binary(L).
+mkbin(L) when is_list(L) -> list_to_binary(L).
diff --git a/lib/debugger/test/bug_SUITE.erl b/lib/debugger/test/bug_SUITE.erl
index a831897dfb..1a7e876329 100644
--- a/lib/debugger/test/bug_SUITE.erl
+++ b/lib/debugger/test/bug_SUITE.erl
@@ -51,7 +51,7 @@ end_per_group(_GroupName, Config) ->
otp2163(doc) -> ["BIF exit reason"];
otp2163(suite) -> [];
-otp2163(Config) when list(Config) ->
+otp2163(Config) when is_list(Config) ->
?line DataDir = ?config(data_dir, Config),
%% First compile and get the expected results:
@@ -74,7 +74,7 @@ otp2163(Config) when list(Config) ->
otp4845(doc) -> ["BIF not loading and not bug compatible, OTP-4845 OTP-4859"];
otp4845(suite) -> [];
-otp4845(Config) when list(Config) ->
+otp4845(Config) when is_list(Config) ->
?line DataDir = ?config(data_dir, Config),
%% First compile and get the expected results:
diff --git a/lib/debugger/test/exception_SUITE.erl b/lib/debugger/test/exception_SUITE.erl
index 8c864e4b5f..86554ab2d4 100644
--- a/lib/debugger/test/exception_SUITE.erl
+++ b/lib/debugger/test/exception_SUITE.erl
@@ -23,7 +23,8 @@
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
init_per_suite/1,end_per_suite/1,
- badmatch/1,pending_errors/1,nil_arith/1]).
+ badmatch/1,pending_errors/1,nil_arith/1,
+ stacktrace/1,nested_stacktrace/1,raise/1,gunilla/1,per/1]).
-export([bad_guy/2]).
@@ -31,6 +32,19 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
+%% Filler.
+%%
+%%
+%%
+%%
+%% This is line 40.
+even(N) when is_integer(N), N > 1, (N rem 2) == 0 ->
+ odd(N-1)++[N].
+
+odd(N) when is_integer(N), N > 1, (N rem 2) == 1 ->
+ even(N-1)++[N].
+
+
all() ->
cases().
@@ -45,7 +59,8 @@ end_per_group(_GroupName, Config) ->
cases() ->
- [badmatch, pending_errors, nil_arith].
+ [badmatch, pending_errors, nil_arith, stacktrace,
+ nested_stacktrace, raise, gunilla, per].
-define(try_match(E),
catch ?MODULE:bar(),
@@ -69,9 +84,9 @@ init_per_suite(Config) when is_list(Config) ->
end_per_suite(Config) when is_list(Config) ->
ok.
-badmatch(doc) -> "Test that deliberately bad matches are reported correctly.";
-badmatch(suite) -> [];
-badmatch(Config) when list(Config) ->
+%% Test that deliberately bad matches are reported correctly.
+
+badmatch(Config) when is_list(Config) ->
?line ?try_match(a),
?line ?try_match(42),
?line ?try_match({a, b, c}),
@@ -79,11 +94,9 @@ badmatch(Config) when list(Config) ->
?line ?try_match(1.0),
ok.
-pending_errors(doc) ->
- ["Test various exceptions, in the presence of a previous error suppressed ",
- "in a guard."];
-pending_errors(suite) -> [];
-pending_errors(Config) when list(Config) ->
+%% Test various exceptions, in the presence of a previous error suppressed
+%% in a guard.
+pending_errors(Config) when is_list(Config) ->
?line pending(e_badmatch, {badmatch, b}),
?line pending(x, function_clause),
?line pending(e_case, {case_clause, xxx}),
@@ -100,7 +113,7 @@ bad_guy(pe_badarith, Other) when Other+1 == 0 -> % badarith (suppressed)
bad_guy(pe_badarg, Other) when length(Other) > 0 -> % badarg (suppressed)
ok;
bad_guy(_, e_case) ->
- case xxx of
+ case id(xxx) of
ok -> ok
end; % case_clause
bad_guy(_, e_if) ->
@@ -121,7 +134,7 @@ bad_guy(_, e_badarg) ->
bad_guy(_, e_badarg_spawn) ->
spawn({}, {}, {}); % badarg
bad_guy(_, e_badmatch) ->
- a = b. % badmatch
+ a = id(b). % badmatch
pending(Arg, Expected) ->
pending(pe_badarith, Arg, Expected),
@@ -155,28 +168,23 @@ pending_exit_message(Args, Expected) ->
end,
process_flag(trap_exit, false).
-pending({badarg,[{erlang,Bif,BifArgs},{?MODULE,Func,Arity}|_]}, Func, Args, _Code)
- when atom(Bif), list(BifArgs), length(Args) == Arity -> %Threaded code.
- ok;
-pending({badarg,[{erlang,Bif,BifArgs},{?MODULE,Func,Args}|_]}, Func, Args, _Code)
- when atom(Bif), list(BifArgs) -> %From interpreted code.
+pending({badarg, [{erlang,Bif,BifArgs,_},{?MODULE,Func,Arity,_}|_]},
+ Func, Args, _Code)
+ when is_atom(Bif), is_list(BifArgs), length(Args) == Arity ->
ok;
-pending({undef,[{non_existing_module,foo,[]}|_]}, _, _, _) ->
+pending({undef,[{non_existing_module,foo,[],_}|_]}, _, _, _) ->
ok;
-pending({function_clause,[{?MODULE,Func,Args}|_]}, Func, Args, _Code) ->
+pending({function_clause,[{?MODULE,Func,Args,_}|_]}, Func, Args, _Code) ->
ok;
-pending({Code,[{?MODULE,Func,Arity}|_]}, Func, Args, Code) when length(Args) == Arity -> %Threaded code
+pending({Code,[{?MODULE,Func,Arity,_}|_]}, Func, Args, Code)
+ when length(Args) == Arity ->
ok;
-pending({Code,[{?MODULE,Func,Args}|_]}, Func, Args, Code) -> %From interpreted code.
- ok;
-pending(Reason, Func, Args, Code) ->
- test_server:fail({bad_exit_reason,Reason,{Func,Args,Code}}).
-
-nil_arith(doc) ->
- "Test that doing arithmetics on [] gives a badarith EXIT and not a crash.";
-nil_arith(suite) ->
- [];
-nil_arith(Config) when list(Config) ->
+pending(Reason, _Function, _Args, _Code) ->
+ test_server:fail({bad_exit_reason,Reason}).
+
+%% Test that doing arithmetics on [] gives a badarith EXIT and not a crash.
+
+nil_arith(Config) when is_list(Config) ->
?line ba_plus_minus_times([], []),
?line ba_plus_minus_times([], 0),
@@ -268,3 +276,199 @@ ba_shift(A, B) ->
ba_bnot(A) ->
io:format("bnot ~p", [A]),
{'EXIT', {badarith, _}} = (catch bnot A).
+
+stacktrace(Conf) when is_list(Conf) ->
+ Tag = make_ref(),
+ ?line {_,Mref} = spawn_monitor(fun() -> exit({Tag,erlang:get_stacktrace()}) end),
+ ?line {Tag,[]} = receive {'DOWN',Mref,_,_,Info} -> Info end,
+ V = [make_ref()|self()],
+ ?line {value2,{caught1,badarg,[{erlang,abs,[V],_}|_]=St1}} =
+ stacktrace_1({'abs',V}, error, {value,V}),
+ ?line St1 = erase(stacktrace1),
+ ?line St1 = erase(stacktrace2),
+ ?line St1 = erlang:get_stacktrace(),
+ ?line {caught2,{error,badarith},[{?MODULE,my_add,2,_}|_]=St2} =
+ stacktrace_1({'div',{1,0}}, error, {'add',{0,a}}),
+ ?line [{?MODULE,my_div,2,_}|_] = erase(stacktrace1),
+ ?line St2 = erase(stacktrace2),
+ ?line St2 = erlang:get_stacktrace(),
+ ?line {caught2,{error,{try_clause,V}},[{?MODULE,stacktrace_1,3,_}|_]=St3} =
+ stacktrace_1({value,V}, error, {value,V}),
+ ?line St3 = erase(stacktrace1),
+ ?line St3 = erase(stacktrace2),
+ ?line St3 = erlang:get_stacktrace(),
+ ?line {caught2,{throw,V},[{?MODULE,foo,1,_}|_]=St4} =
+ stacktrace_1({value,V}, error, {throw,V}),
+ ?line [{?MODULE,stacktrace_1,3,_}|_] = erase(stacktrace1),
+ ?line St4 = erase(stacktrace2),
+ ?line St4 = erlang:get_stacktrace(),
+ ok.
+
+stacktrace_1(X, C1, Y) ->
+ erase(stacktrace1),
+ erase(stacktrace2),
+ try try foo(X) of
+ C1 -> value1
+ catch
+ C1:D1 -> {caught1,D1,erlang:get_stacktrace()}
+ after
+ put(stacktrace1, erlang:get_stacktrace()),
+ foo(Y)
+ end of
+ V2 -> {value2,V2}
+ catch
+ C2:D2 -> {caught2,{C2,D2},erlang:get_stacktrace()}
+ after
+ put(stacktrace2, erlang:get_stacktrace())
+ end.
+
+
+
+nested_stacktrace(Conf) when is_list(Conf) ->
+ V = [{make_ref()}|[self()]],
+ ?line value1 =
+ nested_stacktrace_1({{value,{V,x1}},void,{V,x1}},
+ {void,void,void}),
+ ?line {caught1,
+ [{?MODULE,my_add,2,_}|_],
+ value2,
+ [{?MODULE,my_add,2,_}|_]} =
+ nested_stacktrace_1({{'add',{V,x1}},error,badarith},
+ {{value,{V,x2}},void,{V,x2}}),
+ ?line {caught1,
+ [{?MODULE,my_add,2,_}|_],
+ {caught2,[{erlang,abs,[V],_}|_]},
+ [{erlang,abs,[V],_}|_]} =
+ nested_stacktrace_1({{'add',{V,x1}},error,badarith},
+ {{'abs',V},error,badarg}),
+ ok.
+
+nested_stacktrace_1({X1,C1,V1}, {X2,C2,V2}) ->
+ try foo(X1) of
+ V1 -> value1
+ catch
+ C1:V1 ->
+ S1 = erlang:get_stacktrace(),
+ T2 =
+ try foo(X2) of
+ V2 -> value2
+ catch
+ C2:V2 -> {caught2,erlang:get_stacktrace()}
+ end,
+ {caught1,S1,T2,erlang:get_stacktrace()}
+ end.
+
+
+
+raise(Conf) when is_list(Conf) ->
+ ?line erase(raise),
+ ?line A =
+ try
+ ?line try foo({'div',{1,0}})
+ catch
+ error:badarith ->
+ put(raise, A0 = erlang:get_stacktrace()),
+ ?line erlang:raise(error, badarith, A0)
+ end
+ catch
+ error:badarith ->
+ ?line A1 = erlang:get_stacktrace(),
+ ?line A1 = get(raise)
+ end,
+ ?line A = erlang:get_stacktrace(),
+ ?line A = get(raise),
+ ?line [{?MODULE,my_div,2,_}|_] = A,
+ %%
+ N = 8, % Must be even
+ ?line N = erlang:system_flag(backtrace_depth, N),
+ ?line try even(N)
+ catch error:function_clause -> ok
+ end,
+ ?line B = odd_even(N, []),
+ ?line B = erlang:get_stacktrace(),
+ %%
+ ?line C0 = odd_even(N+1, []),
+ ?line C = lists:sublist(C0, N),
+ ?line try odd(N+1)
+ catch error:function_clause -> ok
+ end,
+ ?line C = erlang:get_stacktrace(),
+ ?line try erlang:raise(error, function_clause, C0)
+ catch error:function_clause -> ok
+ end,
+ ?line C = erlang:get_stacktrace(),
+ ok.
+
+odd_even(N, R) when is_integer(N), N > 1 ->
+ odd_even(N-1,
+ [if (N rem 2) == 0 ->
+ {?MODULE,even,1,[{file,?MODULE_STRING++".erl"},
+ {line,42}]};
+ true ->
+ {?MODULE,odd,1,[{file,?MODULE_STRING++".erl"},
+ {line,45}]}
+ end|R]);
+odd_even(1, R) ->
+ [{?MODULE,odd,[1],[{file,?MODULE_STRING++".erl"},
+ {line,44}]}|R].
+
+foo({value,Value}) -> Value;
+foo({'div',{A,B}}) ->
+ my_div(A, B);
+foo({'add',{A,B}}) ->
+ my_add(A, B);
+foo({'abs',X}) ->
+ my_abs(X);
+foo({error,Error}) ->
+ erlang:error(Error);
+foo({throw,Throw}) ->
+ erlang:throw(Throw);
+foo({exit,Exit}) ->
+ erlang:exit(Exit);
+foo({raise,{Class,Reason,Stacktrace}}) ->
+ erlang:raise(Class, Reason, Stacktrace).
+%%foo(function_clause) -> % must not be defined!
+
+my_div(A, B) ->
+ A div B.
+
+my_add(A, B) ->
+ A + B.
+
+my_abs(X) -> abs(X).
+
+gunilla(Config) when is_list(Config) ->
+ ?line {throw,kalle} = gunilla_1(),
+ ?line [] = erlang:get_stacktrace(),
+ ok.
+
+gunilla_1() ->
+ try try arne()
+ after
+ pelle
+ end
+ catch
+ C:R ->
+ {C,R}
+ end.
+
+arne() ->
+ %% Empty stack trace used to cause change the error class to 'error'.
+ erlang:raise(throw, kalle, []).
+
+per(Config) when is_list(Config) ->
+ try
+ t1(0,pad,0),
+ t2(0,pad,0)
+ catch
+ error:badarith ->
+ ok
+ end.
+
+t1(_,X,_) ->
+ (1 bsl X) + 1.
+
+t2(_,X,_) ->
+ (X bsl 1) + 1.
+
+id(I) -> I.
diff --git a/lib/debugger/test/fun_SUITE.erl b/lib/debugger/test/fun_SUITE.erl
index 8103d9c692..a06cdc7165 100644
--- a/lib/debugger/test/fun_SUITE.erl
+++ b/lib/debugger/test/fun_SUITE.erl
@@ -24,8 +24,10 @@
init_per_testcase/2,end_per_testcase/2,
init_per_suite/1,end_per_suite/1,
good_call/1,bad_apply/1,bad_fun_call/1,badarity/1,
- ext_badarity/1,otp_6061/1]).
--export([nothing/0]).
+ ext_badarity/1,otp_6061/1,external/1]).
+
+%% Internal exports.
+-export([nothing/0,call_me/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -46,7 +48,7 @@ end_per_group(_GroupName, Config) ->
cases() ->
[good_call, bad_apply, bad_fun_call, badarity,
- ext_badarity, otp_6061].
+ ext_badarity, otp_6061, external].
init_per_testcase(_Case, Config) ->
test_lib:interpret(?MODULE),
@@ -244,3 +246,47 @@ test_otp_6061(Starter) ->
fun() -> Starter ! working end,
fun() -> Starter ! not_working end],
lists:foreach(fun(P)->(lists:nth(P,PassesF))() end,Passes).
+
+-define(APPLY(M, F, A), (fun(Fun) -> {ok,{a,b}} = Fun({a,b}) end)(fun M:F/A)).
+-define(APPLY2(M, F, A),
+ (fun(Map) ->
+ Id = fun(I) -> I end,
+ List = [x,y],
+ List = Map(Id, List),
+ {type,external} = erlang:fun_info(Map, type)
+ end)(fun M:F/A)).
+
+external(Config) when is_list(Config) ->
+ Mod = id(?MODULE),
+ Func = id(call_me),
+ Arity = id(1),
+
+ ?APPLY(?MODULE, call_me, 1),
+ ?APPLY(?MODULE, call_me, Arity),
+ ?APPLY(?MODULE, Func, 1),
+ ?APPLY(?MODULE, Func, Arity),
+ ?APPLY(Mod, call_me, 1),
+ ?APPLY(Mod, call_me, Arity),
+ ?APPLY(Mod, Func, 1),
+ ?APPLY(Mod, Func, Arity),
+
+ ListsMod = id(lists),
+ ListsMap = id(map),
+ ListsArity = id(2),
+
+ ?APPLY2(lists, map, 2),
+ ?APPLY2(lists, map, ListsArity),
+ ?APPLY2(lists, ListsMap, 2),
+ ?APPLY2(lists, ListsMap, ListsArity),
+ ?APPLY2(ListsMod, map, 2),
+ ?APPLY2(ListsMod, map, ListsArity),
+ ?APPLY2(ListsMod, ListsMap, 2),
+ ?APPLY2(ListsMod, ListsMap, ListsArity),
+
+ ok.
+
+call_me(I) ->
+ {ok,I}.
+
+id(I) ->
+ I.
diff --git a/lib/debugger/test/guard_SUITE.erl b/lib/debugger/test/guard_SUITE.erl
index 611dcb4dff..bf5fa82749 100644
--- a/lib/debugger/test/guard_SUITE.erl
+++ b/lib/debugger/test/guard_SUITE.erl
@@ -35,7 +35,8 @@
t_is_boolean/1,is_function_2/1,
tricky/1,rel_ops/1,
basic_andalso_orelse/1,traverse_dcd/1,
- check_qlc_hrl/1]).
+ check_qlc_hrl/1,andalso_semi/1,t_tuple_size/1,binary_part/1,
+ bad_constants/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -65,7 +66,8 @@ cases() ->
xor_guard, more_xor_guards, build_in_guard,
old_guard_tests, gbif, t_is_boolean, is_function_2,
tricky, rel_ops, basic_andalso_orelse, traverse_dcd,
- check_qlc_hrl].
+ check_qlc_hrl, andalso_semi, t_tuple_size, binary_part,
+ bad_constants].
init_per_testcase(_Case, Config) ->
test_lib:interpret(?MODULE),
@@ -294,9 +296,7 @@ try_gbif(Id, X, Y) ->
try_fail_gbif(Id, X, Y) ->
case catch guard_bif(Id, X, Y) of
- {'EXIT', {function_clause,{?MODULE,guard_bif,[Id,X,Y]}}} -> %Jam
- io:format("guard_bif(~p, ~p, ~p) -- ok", [Id,X,Y]);
- {'EXIT', {function_clause,[{?MODULE,guard_bif,[Id,X,Y]}|_]}} -> %Beam
+ {'EXIT', {function_clause,[{?MODULE,guard_bif,[Id,X,Y],_}|_]}} ->
io:format("guard_bif(~p, ~p, ~p) -- ok", [Id,X,Y]);
Other ->
?line ok = io:format("guard_bif(~p, ~p, ~p) -- bad result: ~p\n",
@@ -367,9 +367,8 @@ type_tests(Test, [Type|T], Allowed) ->
end;
false ->
case catch type_test(Test, Value) of
- {'EXIT', {function_clause, {?MODULE, type_test, [Test, Value]}}} ->
- ok;
- {'EXIT', {function_clause,[{?MODULE,type_test,[Test,Value]}|_]}} ->
+ {'EXIT',{function_clause,
+ [{?MODULE,type_test,[Test,Value],_}|_]}} ->
ok;
{'EXIT',Other} ->
?line test_server:fail({unexpected_error_reason,Other});
@@ -1477,7 +1476,207 @@ cqlc(M, F, As, St) ->
St
end.
+%% OTP-7679: Thanks to Hunter Morris.
+andalso_semi(Config) when is_list(Config) ->
+ ?line ok = andalso_semi_foo(0),
+ ?line ok = andalso_semi_foo(1),
+ ?line fc(catch andalso_semi_foo(2)),
+
+ ?line ok = andalso_semi_bar([a,b,c]),
+ ?line ok = andalso_semi_bar(1),
+ ?line fc(catch andalso_semi_bar([a,b])),
+ ok.
+
+andalso_semi_foo(Bar) when is_integer(Bar) andalso Bar =:= 0; Bar =:= 1 ->
+ ok.
+
+andalso_semi_bar(Bar) when is_list(Bar) andalso length(Bar) =:= 3; Bar =:= 1 ->
+ ok.
+
+
+t_tuple_size(Config) when is_list(Config) ->
+ ?line 10 = do_tuple_size({1,2,3,4}),
+ ?line fc(catch do_tuple_size({1,2,3})),
+ ?line fc(catch do_tuple_size(42)),
+ ?line error = ludicrous_tuple_size({a,b,c}),
+ ?line error = ludicrous_tuple_size([a,b,c]),
+
+ ok.
+
+do_tuple_size(T) when tuple_size(T) =:= 4 ->
+ {A,B,C,D} = T,
+ A+B+C+D.
+
+ludicrous_tuple_size(T)
+ when tuple_size(T) =:= 16#7777777777777777777777777777777777 -> ok;
+ludicrous_tuple_size(T)
+ when tuple_size(T) =:= 16#10000000000000000 -> ok;
+ludicrous_tuple_size(T)
+ when tuple_size(T) =:= (1 bsl 64) - 1 -> ok;
+ludicrous_tuple_size(T)
+ when tuple_size(T) =:= 16#FFFFFFFFFFFFFFFF -> ok;
+ludicrous_tuple_size(_) -> error.
+
+%%
+%% The binary_part/2,3 guard BIFs
+%%
+-define(MASK_ERROR(EXPR),mask_error((catch (EXPR)))).
+mask_error({'EXIT',{Err,_}}) ->
+ Err;
+mask_error(Else) ->
+ Else.
+
+binary_part(doc) ->
+ ["Tests the binary_part/2,3 guard (GC) bif's"];
+binary_part(Config) when is_list(Config) ->
+ %% This is more or less a copy of what the guard_SUITE in emulator
+ %% does to cover the guard bif's
+ ?line 1 = bptest(<<1,2,3>>),
+ ?line 2 = bptest(<<2,1,3>>),
+ ?line error = bptest(<<1>>),
+ ?line error = bptest(<<>>),
+ ?line error = bptest(apa),
+ ?line 3 = bptest(<<2,3,3>>),
+ % With one variable (pos)
+ ?line 1 = bptest(<<1,2,3>>,1),
+ ?line 2 = bptest(<<2,1,3>>,1),
+ ?line error = bptest(<<1>>,1),
+ ?line error = bptest(<<>>,1),
+ ?line error = bptest(apa,1),
+ ?line 3 = bptest(<<2,3,3>>,1),
+ % With one variable (length)
+ ?line 1 = bptesty(<<1,2,3>>,1),
+ ?line 2 = bptesty(<<2,1,3>>,1),
+ ?line error = bptesty(<<1>>,1),
+ ?line error = bptesty(<<>>,1),
+ ?line error = bptesty(apa,1),
+ ?line 3 = bptesty(<<2,3,3>>,2),
+ % With one variable (whole tuple)
+ ?line 1 = bptestx(<<1,2,3>>,{1,1}),
+ ?line 2 = bptestx(<<2,1,3>>,{1,1}),
+ ?line error = bptestx(<<1>>,{1,1}),
+ ?line error = bptestx(<<>>,{1,1}),
+ ?line error = bptestx(apa,{1,1}),
+ ?line 3 = bptestx(<<2,3,3>>,{1,2}),
+ % With two variables
+ ?line 1 = bptest(<<1,2,3>>,1,1),
+ ?line 2 = bptest(<<2,1,3>>,1,1),
+ ?line error = bptest(<<1>>,1,1),
+ ?line error = bptest(<<>>,1,1),
+ ?line error = bptest(apa,1,1),
+ ?line 3 = bptest(<<2,3,3>>,1,2),
+ % Direct (autoimported) call, these will be evaluated by the compiler...
+ ?line <<2>> = binary_part(<<1,2,3>>,1,1),
+ ?line <<1>> = binary_part(<<2,1,3>>,1,1),
+ % Compiler warnings due to constant evaluation expected (3)
+ ?line badarg = ?MASK_ERROR(binary_part(<<1>>,1,1)),
+ ?line badarg = ?MASK_ERROR(binary_part(<<>>,1,1)),
+ ?line badarg = ?MASK_ERROR(binary_part(apa,1,1)),
+ ?line <<3,3>> = binary_part(<<2,3,3>>,1,2),
+ % Direct call through apply
+ ?line <<2>> = apply(erlang,binary_part,[<<1,2,3>>,1,1]),
+ ?line <<1>> = apply(erlang,binary_part,[<<2,1,3>>,1,1]),
+ % Compiler warnings due to constant evaluation expected (3)
+ ?line badarg = ?MASK_ERROR(apply(erlang,binary_part,[<<1>>,1,1])),
+ ?line badarg = ?MASK_ERROR(apply(erlang,binary_part,[<<>>,1,1])),
+ ?line badarg = ?MASK_ERROR(apply(erlang,binary_part,[apa,1,1])),
+ ?line <<3,3>> = apply(erlang,binary_part,[<<2,3,3>>,1,2]),
+ % Constant propagation
+ ?line Bin = <<1,2,3>>,
+ ?line ok = if
+ binary_part(Bin,1,1) =:= <<2>> ->
+ ok;
+ %% Compiler warning, clause cannot match (expected)
+ true ->
+ error
+ end,
+ ?line ok = if
+ binary_part(Bin,{1,1}) =:= <<2>> ->
+ ok;
+ %% Compiler warning, clause cannot match (expected)
+ true ->
+ error
+ end,
+ ok.
+
+
+bptest(B) when length(B) =:= 1337 ->
+ 1;
+bptest(B) when binary_part(B,{1,1}) =:= <<2>> ->
+ 1;
+bptest(B) when erlang:binary_part(B,1,1) =:= <<1>> ->
+ 2;
+bptest(B) when erlang:binary_part(B,{1,2}) =:= <<3,3>> ->
+ 3;
+bptest(_) ->
+ error.
+
+bptest(B,A) when length(B) =:= A ->
+ 1;
+bptest(B,A) when binary_part(B,{A,1}) =:= <<2>> ->
+ 1;
+bptest(B,A) when erlang:binary_part(B,A,1) =:= <<1>> ->
+ 2;
+bptest(B,A) when erlang:binary_part(B,{A,2}) =:= <<3,3>> ->
+ 3;
+bptest(_,_) ->
+ error.
+
+bptestx(B,A) when length(B) =:= A ->
+ 1;
+bptestx(B,A) when binary_part(B,A) =:= <<2>> ->
+ 1;
+bptestx(B,A) when erlang:binary_part(B,A) =:= <<1>> ->
+ 2;
+bptestx(B,A) when erlang:binary_part(B,A) =:= <<3,3>> ->
+ 3;
+bptestx(_,_) ->
+ error.
+
+bptesty(B,A) when length(B) =:= A ->
+ 1;
+bptesty(B,A) when binary_part(B,{1,A}) =:= <<2>> ->
+ 1;
+bptesty(B,A) when erlang:binary_part(B,1,A) =:= <<1>> ->
+ 2;
+bptesty(B,A) when erlang:binary_part(B,{1,A}) =:= <<3,3>> ->
+ 3;
+bptesty(_,_) ->
+ error.
+
+bptest(B,A,_C) when length(B) =:= A ->
+ 1;
+bptest(B,A,C) when binary_part(B,{A,C}) =:= <<2>> ->
+ 1;
+bptest(B,A,C) when erlang:binary_part(B,A,C) =:= <<1>> ->
+ 2;
+bptest(B,A,C) when erlang:binary_part(B,{A,C}) =:= <<3,3>> ->
+ 3;
+bptest(_,_,_) ->
+ error.
+
+-define(FAILING(C),
+ if
+ C -> ?t:fail(should_fail);
+ true -> ok
+ end,
+ if
+ true, C -> ?t:fail(should_fail);
+ true -> ok
+ end).
+
+bad_constants(Config) when is_list(Config) ->
+ ?line ?FAILING(false),
+ ?line ?FAILING([]),
+ ?line ?FAILING([a]),
+ ?line ?FAILING([Config]),
+ ?line ?FAILING({a,b}),
+ ?line ?FAILING({a,Config}),
+ ?line ?FAILING(<<1>>),
+ ?line ?FAILING(42),
+ ?line ?FAILING(3.14),
+ ok.
%% Call this function to turn off constant propagation.
id(I) -> I.
@@ -1490,3 +1689,5 @@ check(F, Result) ->
io:format(" Got: ~p\n", [Other]),
test_server:fail()
end.
+
+fc({'EXIT',{function_clause,_}}) -> ok.
diff --git a/lib/debugger/test/int_eval_SUITE.erl b/lib/debugger/test/int_eval_SUITE.erl
index f36ed213d1..4ffcf7888e 100644
--- a/lib/debugger/test/int_eval_SUITE.erl
+++ b/lib/debugger/test/int_eval_SUITE.erl
@@ -28,7 +28,7 @@
bifs_outside_erlang/1, spawning/1, applying/1,
catch_and_throw/1, external_call/1, test_module_info/1,
apply_interpreted_fun/1, apply_uninterpreted_fun/1,
- interpreted_exit/1, otp_8310/1]).
+ interpreted_exit/1, otp_8310/1, stacktrace/1]).
%% Helpers.
-export([applier/3]).
@@ -44,7 +44,7 @@ all() ->
[bifs_outside_erlang, spawning, applying,
catch_and_throw, external_call, test_module_info,
apply_interpreted_fun, apply_uninterpreted_fun,
- interpreted_exit, otp_8310].
+ interpreted_exit, otp_8310, stacktrace].
groups() ->
[].
@@ -191,23 +191,23 @@ apply_interpreted_fun(Config) when is_list(Config) ->
?line {ok,ATerm} = spawn_eval(fun() -> F2() end),
%% Called from uninterpreted code, badarity
- ?line {'EXIT',{{badarity,{F1,[snape]}},[{?MODULE,_,_}|_]}} =
+ ?line {'EXIT',{{badarity,{F1,[snape]}},[{?MODULE,_,_,_}|_]}} =
spawn_eval(fun() -> F1(snape) end),
%% Called from uninterpreted code, error in fun
?line F3 = spawn_eval(fun() -> ?IM:give_me_a_bad_fun() end),
- ?line {'EXIT',{snape,[{?IM,_FunName,_}|_]}} =
+ ?line {'EXIT',{snape,[{?IM,_FunName,_,_}|_]}} =
spawn_eval(fun() -> F3(snape) end),
%% Called from within interpreted code
?line perfectly_alright = spawn_eval(fun() -> ?IM:do_apply(F1) end),
%% Called from within interpreted code, badarity
- ?line {'EXIT',{{badarity,{F1,[snape]}},[{?IM,do_apply,_}|_]}} =
+ ?line {'EXIT',{{badarity,{F1,[snape]}},[{?IM,do_apply,_,_}|_]}} =
spawn_eval(fun() -> ?IM:do_apply(F1, snape) end),
%% Called from within interpreted code, error in fun
- ?line {'EXIT',{snape,[{?IM,_FunName,_}|_]}} =
+ ?line {'EXIT',{snape,[{?IM,_FunName,_,_}|_]}} =
spawn_eval(fun() -> ?IM:do_apply(F3, snape) end),
%% Try some more complex funs.
@@ -239,11 +239,11 @@ apply_uninterpreted_fun(Config) when is_list(Config) ->
spawn_eval(fun() -> ?IM:do_apply(F1, any_arg) end),
%% Badarity (evaluated in dbg_debugged, which calls erlang:apply/2)
- ?line {'EXIT',{{badarity,{F1,[]}},[{erlang,apply,_}|_]}} =
+ ?line {'EXIT',{{badarity,{F1,[]}},[{erlang,apply,_,_}|_]}} =
spawn_eval(fun() -> ?IM:do_apply(F1) end),
%% Error in fun
- ?line {'EXIT',{snape,[{?MODULE,_FunName,_}|_]}} =
+ ?line {'EXIT',{snape,[{?MODULE,_FunName,_,_}|_]}} =
spawn_eval(fun() -> ?IM:do_apply(F1, snape) end),
ok.
@@ -277,6 +277,37 @@ applier(M, F, A) ->
io:format("~p:~p(~p) => ~p\n", [M,F,A,Res]),
Res.
+stacktrace(Config) when is_list(Config) ->
+ ?line {done,Stk} = do_eval(Config, stacktrace),
+ ?line 13 = length(Stk),
+ ?line OldStackTraceFlag = int:stack_trace(),
+ ?line int:stack_trace(no_tail),
+ try
+ ?line Res = spawn_eval(fun() -> stacktrace:stacktrace() end),
+ ?line io:format("\nInterpreted (no_tail):\n~p", [Res]),
+ ?line {done,Stk} = Res
+ after
+ ?line int:stack_trace(OldStackTraceFlag)
+ end,
+ ok.
+
+
+do_eval(Config, Mod) ->
+ ?line DataDir = ?config(data_dir, Config),
+ ?line ok = file:set_cwd(DataDir),
+
+ ?line {ok,Mod} = compile:file(Mod, [report,debug_info]),
+ ?line {module,Mod} = code:load_file(Mod),
+ ?line CompiledRes = Mod:Mod(),
+ ?line ok = io:format("Compiled:\n~p", [CompiledRes]),
+ io:nl(),
+
+ ?line {module,Mod} = int:i(Mod),
+ ?line IntRes = Mod:Mod(),
+ ?line ok = io:format("Interpreted:\n~p", [IntRes]),
+
+ ?line CompiledRes = IntRes.
+
%%
%% Evaluate in another process, to prevent the test_case process to become
%% interpreted.
diff --git a/lib/debugger/test/int_eval_SUITE_data/my_int_eval_module.erl b/lib/debugger/test/int_eval_SUITE_data/my_int_eval_module.erl
index 997ee6e17d..90f83e80e8 100644
--- a/lib/debugger/test/int_eval_SUITE_data/my_int_eval_module.erl
+++ b/lib/debugger/test/int_eval_SUITE_data/my_int_eval_module.erl
@@ -117,7 +117,7 @@ more_nocatch(Fun) ->
%% External calls.
external_call_test(Data) ->
- {'EXIT',{undef,[{?MODULE,not_exported,[42,Data]}|_]}} =
+ {'EXIT',{undef,[{?MODULE,not_exported,[42,Data],_}|_]}} =
(catch ?MODULE:not_exported(42, Data)),
{yes,Data} = i_am_exported(Data),
{yes,Data} = ?MODULE:i_am_exported(Data),
@@ -127,7 +127,7 @@ external_call_test(Data) ->
{ok,Data,[a,b]} = not_exported(Data, [a,b]),
{yes,Data} = i_am_exported(Data),
{ok,Data,[a,b]} = not_exported(Data, [a,b]),
- {'EXIT',{undef,[{?MODULE,not_exported,[7,Data]}|_]}} =
+ {'EXIT',{undef,[{?MODULE,not_exported,[7,Data],_}|_]}} =
(catch ?MODULE:not_exported(7, Data)),
{yes,Data} = ?MODULE:i_am_exported(Data),
ok.
diff --git a/lib/debugger/test/int_eval_SUITE_data/stacktrace.erl b/lib/debugger/test/int_eval_SUITE_data/stacktrace.erl
new file mode 100644
index 0000000000..3380178fdc
--- /dev/null
+++ b/lib/debugger/test/int_eval_SUITE_data/stacktrace.erl
@@ -0,0 +1,130 @@
+-module(stacktrace).
+-export([?MODULE/0]).
+
+?MODULE() ->
+ OldDepth = erlang:system_flag(backtrace_depth, 32),
+ done = (catch do_try()),
+ Stk = trim(erlang:get_stacktrace()),
+ erlang:system_flag(backtrace_depth, OldDepth),
+ {done,Stk}.
+
+trim([{int_eval_SUITE,_,_,_}|_]) ->
+ [];
+trim([H|T]) ->
+ [H|trim(T)];
+trim([]) -> [].
+
+do_try() ->
+ try
+ 0 = id(42)
+ catch
+ error:{badmatch,42} ->
+ do_try2() %Tail-recursive
+ end.
+
+do_try2() ->
+ try
+ 0 = id(42)
+ catch
+ error:{badmatch,42} ->
+ do_try3() %Not tail-recursive
+ end,
+ ?LINE.
+
+do_try3() ->
+ try id(42) of
+ 42 -> do_try4() %Tail-recursive
+ catch
+ error:ignore -> %Should never catch
+ ?LINE
+ end.
+
+do_try4() ->
+ try
+ do_recv() %Not tail-recursive
+ catch
+ error:ignore -> %Should never catch
+ ?LINE
+ end.
+
+do_recv() ->
+ self() ! x,
+ receive
+ x -> do_recv2() %Not tail-recursive
+ end,
+ ?LINE.
+
+do_recv2() ->
+ self() ! y,
+ receive
+ y -> do_recv3() %Tail-recursive
+ end.
+
+do_recv3() ->
+ receive
+ after 0 -> do_recv4() %Tail-recursive
+ end.
+
+do_recv4() ->
+ receive
+ after 0 -> do_if(true) %Not tail-recursive
+ end,
+ ?LINE.
+
+do_if(Bool) ->
+ if
+ Bool -> do_if2(Bool) %Tail-recursive
+ end.
+
+do_if2(Bool) ->
+ if
+ Bool -> do_case(Bool) %Not tail-recursive
+ end,
+ ?LINE.
+
+
+do_case(Bool) ->
+ case Bool of
+ true -> do_case2(Bool) %Tail-recursive
+ end.
+
+do_case2(Bool) ->
+ case Bool of
+ true -> do_fun(Bool) %Not tail-recursive
+ end,
+ ?LINE.
+
+do_fun(Bool) ->
+ F = fun(true) ->
+ do_fun2(Bool) %Tail-recursive
+ end,
+ F(Bool). %Tail-recursive
+
+do_fun2(Bool) ->
+ F = fun(true) ->
+ cons(Bool) %Tail-recursive
+ end,
+ F(Bool), %Not tail-recursive
+ ?LINE.
+
+cons(Bool) ->
+ [Bool|tuple()].
+
+tuple() ->
+ {ok,op()}.
+
+op() ->
+ 1 + lc().
+
+lc() ->
+ [done() || true].
+
+done() ->
+ tail(100),
+ throw(done).
+
+tail(0) -> ok;
+tail(N) -> tail(N-1).
+
+id(I) ->
+ I.
diff --git a/lib/debugger/test/lc_SUITE.erl b/lib/debugger/test/lc_SUITE.erl
index 92a03ef58e..2f05eb7fca 100644
--- a/lib/debugger/test/lc_SUITE.erl
+++ b/lib/debugger/test/lc_SUITE.erl
@@ -17,21 +17,22 @@
%% %CopyrightEnd%
%%
-%%
-module(lc_SUITE).
--author('[email protected]').
+%% Copied from lc_SUITE in the compiler application.
+
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
init_per_suite/1,end_per_suite/1,
- basic/1]).
+ basic/1,deeply_nested/1,no_generator/1,
+ empty_generator/1]).
-include_lib("test_server/include/test_server.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- cases().
+ [basic, deeply_nested, no_generator, empty_generator].
groups() ->
[].
@@ -42,10 +43,6 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-
-cases() ->
- [basic].
-
init_per_testcase(_Case, Config) ->
test_lib:interpret(?MODULE),
Dog = test_server:timetrap(?t:minutes(1)),
@@ -64,7 +61,7 @@ init_per_suite(Config) when is_list(Config) ->
end_per_suite(Config) when is_list(Config) ->
ok.
-basic(Config) when list(Config) ->
+basic(Config) when is_list(Config) ->
?line L0 = lists:seq(1, 10),
?line L1 = my_map(fun(X) -> {x,X} end, L0),
?line L1 = [{x,X} || X <- L0],
@@ -73,16 +70,116 @@ basic(Config) when list(Config) ->
?line [4,5,6] = [X || X <- L0, X > 3, X < 7],
?line [] = [X || X <- L0, X > 32, X < 7],
?line [1,3,5,7,9] = [X || X <- L0, odd(X)],
+ ?line [2,4,6,8,10] = [X || X <- L0, not odd(X)],
+ ?line [1,3,5,9] = [X || X <- L0, odd(X), X =/= 7],
+ ?line [2,4,8,10] = [X || X <- L0, not odd(X), X =/= 6],
+
+ %% Append is specially handled.
+ ?line [1,3,5,9,2,4,8,10] = [X || X <- L0, odd(X), X =/= 7] ++
+ [X || X <- L0, not odd(X), X =/= 6],
+
+ %% Guards BIFs are evaluated in guard context. Weird, but true.
+ ?line [{a,b,true},{x,y,true,true}] = [X || X <- tuple_list(), element(3, X)],
+
+ %% Filter expressions with andalso/orelse.
+ ?line "abc123" = alphanum("?abc123.;"),
%% Error cases.
- ?line [] = [X || X <- L1, X+1 < 2],
?line [] = [{xx,X} || X <- L0, element(2, X) == no_no_no],
- ?line {'EXIT',_} = (catch [X || X <- L1, odd(X)]),
+ ?line {'EXIT',_} = (catch [X || X <- L1, list_to_atom(X) == dum]),
+ ?line [] = [X || X <- L1, X+1 < 2],
+ ?line {'EXIT',_} = (catch [X || X <- L1, odd(X)]),
+ %% A bad generator has a different exception compared to BEAM.
+ ?line {'EXIT',{{bad_generator,x},_}} = (catch [E || E <- id(x)]),
ok.
+tuple_list() ->
+ [{a,b,true},[a,b,c],glurf,{a,b,false,xx},{a,b},{x,y,true,true},{a,b,d,ddd}].
+
my_map(F, L) ->
[F(X) || X <- L].
odd(X) ->
X rem 2 == 1.
+
+alphanum(Str) ->
+ [C || C <- Str, ((C >= $0) andalso (C =< $9))
+ orelse ((C >= $a) andalso (C =< $z))
+ orelse ((C >= $A) andalso (C =< $Z))].
+
+deeply_nested(Config) when is_list(Config) ->
+ [[99,98,97,96,42,17,1764,12,11,10,9,8,7,6,5,4,3,7,2,1]] = deeply_nested_1(),
+ ok.
+
+deeply_nested_1() ->
+ %% This used to compile really, really SLOW before R11B-1...
+ [[X1,X2,X3,X4,X5,X6,X7(),X8,X9,X10,X11,X12,X13,X14,X15,X16,X17,X18(),X19,X20] ||
+ X1 <- [99],X2 <- [98],X3 <- [97],X4 <- [96],X5 <- [42],X6 <- [17],
+ X7 <- [fun() -> X5*X5 end],X8 <- [12],X9 <- [11],X10 <- [10],
+ X11 <- [9],X12 <- [8],X13 <- [7],X14 <- [6],X15 <- [5],
+ X16 <- [4],X17 <- [3],X18 <- [fun() -> X16+X17 end],X19 <- [2],X20 <- [1]].
+
+no_generator(Config) when is_list(Config) ->
+ ?line Seq = lists:seq(-10, 17),
+ ?line [no_gen_verify(no_gen(A, B), A, B) || A <- Seq, B <- Seq],
+
+ %% Literal expression, for coverage.
+ ?line [a] = [a || true],
+ ?line [a,b,c] = [a || true] ++ [b,c],
+ ok.
+
+no_gen(A, B) ->
+ [{A,B} || A+B =:= 0] ++
+ [{A,B} || A*B =:= 0] ++
+ [{A,B} || A rem B =:= 3] ++
+ [{A,B} || A =:= B] ++
+ [{one_more,A,B} || no_gen_one_more(A, B)] ++
+ [A || A =:= 1] ++
+ [A || A =:= 2] ++
+ [A || A =:= 3] ++
+ [A || A =:= 4] ++
+ [A || A =:= 5] ++
+ [A || A =:= 6] ++
+ [A || A =:= 7] ++
+ [A || A =:= 8] ++
+ [A || A =:= 9] ++
+ [B || B =:= 1] ++
+ [B || B =:= 2] ++
+ [B || B =:= 3] ++
+ [B || B =:= 4] ++
+ [B || B =:= 5] ++
+ [B || B =:= 6] ++
+ [B || B =:= 7] ++
+ [B || B =:= 8] ++
+ [B || B =:= 9].
+
+no_gen_verify(Res, A, B) ->
+ Pair = {A,B},
+ ShouldBe = no_gen_eval(fun() -> A+B =:= 0 end, Pair) ++
+ no_gen_eval(fun() -> A*B =:= 0 end, Pair) ++
+ no_gen_eval(fun() -> B =/= 0 andalso A rem B =:= 3 end, Pair) ++
+ no_gen_eval(fun() -> A =:= B end, Pair) ++
+ no_gen_eval(fun() -> A + 1 =:= B end, {one_more,A,B}) ++
+ no_gen_eval(fun() -> 1 =< A andalso A =< 9 end, A) ++
+ no_gen_eval(fun() -> 1 =< B andalso B =< 9 end, B),
+ case Res of
+ ShouldBe -> ok;
+ _ ->
+ io:format("A = ~p; B = ~p; Expected = ~p, actual = ~p", [A,B,ShouldBe,Res]),
+ ?t:fail()
+ end.
+
+no_gen_eval(Fun, Res) ->
+ case Fun() of
+ true -> [Res];
+ false -> []
+ end.
+
+no_gen_one_more(A, B) -> A + 1 =:= B.
+
+empty_generator(Config) when is_list(Config) ->
+ ?line [] = [X || {X} <- [], (false or (X/0 > 3))],
+ ok.
+
+id(I) -> I.
diff --git a/lib/debugger/test/line_number_SUITE.erl b/lib/debugger/test/line_number_SUITE.erl
new file mode 100644
index 0000000000..d1f56d3493
--- /dev/null
+++ b/lib/debugger/test/line_number_SUITE.erl
@@ -0,0 +1,220 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(line_number_SUITE).
+
+-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
+ init_per_testcase/2,end_per_testcase/2,
+ init_per_suite/1,end_per_suite/1,
+ line_numbers/1]).
+-export([crash/1]).
+
+-include_lib("test_server/include/test_server.hrl").
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ cases().
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+cases() ->
+ [line_numbers].
+
+init_per_testcase(_Case, Config) ->
+ test_lib:interpret(?MODULE),
+ Dog = test_server:timetrap(?t:minutes(1)),
+ [{watchdog,Dog}|Config].
+
+end_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+init_per_suite(Config) when is_list(Config) ->
+ ?line test_lib:interpret(?MODULE),
+ ?line true = lists:member(?MODULE, int:interpreted()),
+ Config.
+
+end_per_suite(Config) when is_list(Config) ->
+ ok.
+
+
+
+
+
+%%
+%% === Make sure that this is always line 70 ===
+%%
+line1(Tag, X) -> %Line 72
+ case Tag of %Line 73
+ a ->
+ Y = X + 1, %Line 75
+ Res = id({ok,Y}), %Line 76
+ ?MODULE:crash({ok,42} = Res); %Line 77
+ b ->
+ x = id(x), %Line 79
+ ok %Line 80
+ end. %Line 81
+
+crash(_) -> %Line 83
+ erlang:error(crash). %Line 84
+
+close_calls(Where) -> %Line 86
+ put(where_to_crash, Where), %Line 87
+ try
+ call1(), %Line 89
+ call2(), %Line 90
+ call3(), %Line 91
+ no_crash %Line 92
+ catch error:crash ->
+ erlang:get_stacktrace() %Line 94
+ end. %Line 95
+
+call1() -> %Line 97
+ maybe_crash(call1), %Line 98
+ ok. %Line 99
+
+call2() -> %Line 101
+ maybe_crash(call2), %Line 102
+ ok. %Line 103
+
+call3() -> %Line 105
+ maybe_crash(call3), %Line 106
+ ok. %Line 107
+
+maybe_crash(Name) -> %Line 109
+ case get(where_to_crash) of %Line 110
+ Name ->
+ erlang:error(crash); %Line 112
+ _ ->
+ ok %Line 114
+ end. %Line 115
+
+build_binary1(Size) -> %Line 117
+ id(42), %Line 118
+ <<0:Size>>. %Line 119
+
+build_binary2(Size, Bin) -> %Line 121
+ id(0), %Line 122
+ <<7:Size,Bin/binary>>. %Line 123
+
+do_call_abs(x, Arg) -> %Line 125
+ abs(Arg). %Line 126
+
+do_call_unsafe_bif(x, Arg) -> %Line 128
+ link(Arg). %Line 129
+
+
+line_numbers(Config) when is_list(Config) ->
+ File = ?MODULE_STRING ++ ".erl",
+ {'EXIT',{{case_clause,bad_tag},
+ [{?MODULE,line1,2,
+ [{file,File},{line,73}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch line1(bad_tag, 0)),
+ {'EXIT',{badarith,
+ [{?MODULE,line1,2,
+ [{file,File},{line,75}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch line1(a, not_an_integer)),
+ {'EXIT',{{badmatch,{ok,1}},
+ [{?MODULE,line1,2,
+ [{file,File},{line,77}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch line1(a, 0)),
+ {'EXIT',{crash,
+ [{?MODULE,crash,1,
+ [{file,File},{line,84}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch line1(a, 41)),
+
+ [{?MODULE,maybe_crash,1,[{file,File},{line,112}]},
+ {?MODULE,call1,0,[{file,File},{line,98}]},
+ {?MODULE,close_calls,1,[{file,File},{line,89}]},
+ {?MODULE,line_numbers,1,[{file,File},{line,_}]}|_] =
+ close_calls(call1),
+ [{?MODULE,maybe_crash,1,[{file,File},{line,112}]},
+ {?MODULE,call2,0,[{file,File},{line,102}]},
+ {?MODULE,close_calls,1,[{file,File},{line,90}]},
+ {?MODULE,line_numbers,1,[{file,File},{line,_}]}|_] =
+ close_calls(call2),
+ [{?MODULE,maybe_crash,1,[{file,File},{line,112}]},
+ {?MODULE,call3,0,[{file,File},{line,106}]},
+ {?MODULE,close_calls,1,[{file,File},{line,91}]},
+ {?MODULE,line_numbers,1,[{file,File},{line,_}]}|_] =
+ close_calls(call3),
+ no_crash = close_calls(other),
+
+ <<0,0>> = build_binary1(16),
+ {'EXIT',{badarg,
+ [{?MODULE,build_binary1,1,
+ [{file,File},{line,119}]},
+ {?MODULE,line_numbers,1,
+ [{file,ModFile},{line,_}]}|_]}} =
+ (catch build_binary1(bad_size)),
+
+ <<7,1,2,3>> = build_binary2(8, <<1,2,3>>),
+ {'EXIT',{badarg,
+ [{?MODULE,build_binary2,2,
+ [{file,File},{line,123}]},
+ {?MODULE,line_numbers,1,
+ [{file,ModFile},{line,_}]}|_]}} =
+ (catch build_binary2(bad_size, <<>>)),
+ {'EXIT',{badarg,
+ [%% Beam has an extra here:
+ %% {erlang,bit_size,[bad_binary],[]}
+ %% Since this is an artifact of the implementation,
+ %% we don't attempt to mimic it in the debugger.
+ {?MODULE,build_binary2,2,
+ [{file,File},{line,123}]},
+ {?MODULE,line_numbers,1,
+ [{file,ModFile},{line,_}]}|_]}} =
+ (catch build_binary2(8, bad_binary)),
+
+ {'EXIT',{function_clause,
+ [{?MODULE,do_call_abs,[y,y],
+ [{file,File},{line,125}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch do_call_abs(y, y)),
+ {'EXIT',{badarg,
+ [{erlang,abs,[[]],[]},
+ {?MODULE,do_call_abs,2,
+ [{file,File},{line,126}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch do_call_abs(x, [])),
+
+ {'EXIT',{badarg,
+ [{erlang,link,[[]],[]},
+ {?MODULE,do_call_unsafe_bif,2,
+ [{file,File},{line,129}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch do_call_unsafe_bif(x, [])),
+
+ ok.
+
+id(I) ->
+ I.
diff --git a/lib/debugger/test/test_lib.erl b/lib/debugger/test/test_lib.erl
index 541375e64a..5e4ac7f164 100644
--- a/lib/debugger/test/test_lib.erl
+++ b/lib/debugger/test/test_lib.erl
@@ -22,7 +22,7 @@
-export([interpret/1]).
-interpret(Mod) when atom(Mod) ->
+interpret(Mod) when is_atom(Mod) ->
case lists:member(Mod, int:interpreted()) of
true -> ok;
false -> {module,Mod} = i:ii(Mod)
diff --git a/lib/debugger/test/trycatch_SUITE.erl b/lib/debugger/test/trycatch_SUITE.erl
index a87c5db138..470d46d915 100644
--- a/lib/debugger/test/trycatch_SUITE.erl
+++ b/lib/debugger/test/trycatch_SUITE.erl
@@ -318,17 +318,18 @@ eclectic(Conf) when is_list(Conf) ->
V = {make_ref(),3.1415926535,[[]|{}]},
?line {{value,{value,V},V},V} =
eclectic_1({foo,{value,{value,V}}}, undefined, {value,V}),
- ?line {{'EXIT',{V,[{?MODULE,foo,_}|_]}},V} =
+ ?line {{'EXIT',{V,[{?MODULE,foo,_,_}|_]}},V} =
eclectic_1({catch_foo,{error,V}}, undefined, {value,V}),
?line {{error,{exit,V},{'EXIT',V}},V} =
eclectic_1({foo,{error,{exit,V}}}, error, {value,V}),
- ?line {{value,{value,V},V},{'EXIT',{badarith,[{?MODULE,my_add,_}|_]}}} =
+ ?line {{value,{value,V},V},{'EXIT',{badarith,[{?MODULE,my_add,_,_}|_]}}} =
eclectic_1({foo,{value,{value,V}}}, undefined, {'add',{0,a}}),
?line {{'EXIT',V},V} =
eclectic_1({catch_foo,{exit,V}}, undefined, {throw,V}),
- ?line {{error,{'div',{1,0}},{'EXIT',{badarith,[{?MODULE,my_div,_}|_]}}}, {'EXIT',V}} =
+ ?line {{error,{'div',{1,0}},{'EXIT',{badarith,[{?MODULE,my_div,_,_}|_]}}},
+ {'EXIT',V}} =
eclectic_1({foo,{error,{'div',{1,0}}}}, error, {exit,V}),
- ?line {{{error,V},{'EXIT',{V,[{?MODULE,foo,_}|_]}}},{'EXIT',V}} =
+ ?line {{{error,V},{'EXIT',{V,[{?MODULE,foo,_,_}|_]}}},{'EXIT',V}} =
eclectic_1({catch_foo,{throw,{error,V}}}, undefined, {exit,V}),
%%
?line {{value,{value,{value,V},V}},V} =
@@ -337,15 +338,15 @@ eclectic(Conf) when is_list(Conf) ->
eclectic_2({throw,{value,V}}, throw, {value,V}),
?line {{caught,{'EXIT',V}},undefined} =
eclectic_2({value,{value,V}}, undefined, {exit,V}),
- ?line {{caught,{'EXIT',{V,[{?MODULE,foo,_}|_]}}},undefined} =
+ ?line {{caught,{'EXIT',{V,[{?MODULE,foo,_,_}|_]}}},undefined} =
eclectic_2({error,{value,V}}, throw, {error,V}),
- ?line {{caught,{'EXIT',{badarg,[{erlang,abs,[V]}|_]}}},V} =
+ ?line {{caught,{'EXIT',{badarg,[{erlang,abs,[V],_}|_]}}},V} =
eclectic_2({value,{'abs',V}}, undefined, {value,V}),
- ?line {{caught,{'EXIT',{badarith,[{?MODULE,my_add,_}|_]}}},V} =
+ ?line {{caught,{'EXIT',{badarith,[{?MODULE,my_add,_,_}|_]}}},V} =
eclectic_2({exit,{'add',{0,a}}}, exit, {value,V}),
?line {{caught,{'EXIT',V}},undefined} =
eclectic_2({value,{error,V}}, undefined, {exit,V}),
- ?line {{caught,{'EXIT',{V,[{?MODULE,foo,_}|_]}}},undefined} =
+ ?line {{caught,{'EXIT',{V,[{?MODULE,foo,_,_}|_]}}},undefined} =
eclectic_2({throw,{'div',{1,0}}}, throw, {error,V}),
ok.
diff --git a/lib/dialyzer/doc/src/Makefile b/lib/dialyzer/doc/src/Makefile
index 45b0ffa5ff..45b0ffa5ff 100755..100644
--- a/lib/dialyzer/doc/src/Makefile
+++ b/lib/dialyzer/doc/src/Makefile
diff --git a/lib/dialyzer/doc/src/book.xml b/lib/dialyzer/doc/src/book.xml
index 0b4e1cb617..0b4e1cb617 100755..100644
--- a/lib/dialyzer/doc/src/book.xml
+++ b/lib/dialyzer/doc/src/book.xml
diff --git a/lib/dialyzer/doc/src/fascicules.xml b/lib/dialyzer/doc/src/fascicules.xml
index 0678195e07..0678195e07 100755..100644
--- a/lib/dialyzer/doc/src/fascicules.xml
+++ b/lib/dialyzer/doc/src/fascicules.xml
diff --git a/lib/dialyzer/doc/src/make.dep b/lib/dialyzer/doc/src/make.dep
deleted file mode 100755
index f8177cd419..0000000000
--- a/lib/dialyzer/doc/src/make.dep
+++ /dev/null
@@ -1,20 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex dialyzer.tex dialyzer_chapter.tex \
- part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml
index 81622a3854..17291b24f7 100755..100644
--- a/lib/dialyzer/doc/src/notes.xml
+++ b/lib/dialyzer/doc/src/notes.xml
@@ -31,6 +31,115 @@
<p>This document describes the changes made to the Dialyzer
application.</p>
+<section><title>Dialyzer 2.4.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Update results of race_SUITE/extract_translations Update
+ results of small_SUITE/flatten Add codec_can and
+ list_to_bitstring tests Fix bug when reporting unused
+ functions Update Dialyzer r9c_suite results Fix dialyzer
+ warning on default clause for binary comprehension
+ (Thanks to Ivan Dubrov)</p>
+ <p>
+ Own Id: OTP-9483</p>
+ </item>
+ <item>
+ <p>
+ Fix server loop detection</p>
+ <p>
+ Dialyzer does not normally emit warnings for functions
+ that implement non-terminating server loops. This
+ detection failed when some of the elements in an SCC
+ terminated normally (being for example list
+ comprehensions or other generic anonymous functions that
+ were included in the SCC). This patch fixes that.</p>
+ <p>
+ Own Id: OTP-9489</p>
+ </item>
+ <item>
+ <p>
+ Add a proplist() type</p>
+ <p>
+ Recently I was adding specs to an API and found that
+ there is no canonical proplist() type defined. (Thanks to
+ Ryan Zezeski)</p>
+ <p>
+ Own Id: OTP-9499</p>
+ </item>
+ <item>
+ <p>
+ Suppress some warnings about generation of non-returning
+ funs</p>
+ <p>
+ No warnings are emitted for funs that are non-returning
+ when the function that generates them has a contract that
+ specifies that it will return such a non-returning fun.</p>
+ <p>
+ Enhance Dialyzer's inference on comparisons</p>
+ <p>
+ This patch makes Dialyzer aware of Erlang's total
+ ordering of terms, enabling discrepancy detection in
+ cases where e.g. integer() &lt; tuple() is treated as a
+ comparison that might also return false (when it is
+ certain to always return true).</p>
+ <p>
+ Minor fix in dead code</p>
+ <p>
+ Fix infinite loop in dataflow</p>
+ <p>
+ Update r9c/{inets,mnesia} results in dialyzer's test
+ suite</p>
+ <p>
+ Add origin information to #fun_var closures</p>
+ <p>
+ (Thanks to Tuncer Ayaz and Maria Christakis)</p>
+ <p>
+ Own Id: OTP-9529</p>
+ </item>
+ <item>
+ <p>
+ Quote atoms if necessary in types</p>
+ <p>
+ Atoms in some occurrences were not correctly quoted when
+ formatted to strings, for instance by the typer program
+ (Thanks to Tomas Abrahamsson)</p>
+ <p>
+ Update Dialyzer's reference results</p>
+ <p>
+ Own Id: OTP-9560</p>
+ </item>
+ <item>
+ <p>
+ Fix typer's crash for nonexisting files Remove unused
+ macro Fix bug in dataflow Decrease tuple arity limit This
+ fixes a memory related crash.</p>
+ <p>
+ Own Id: OTP-9597</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Types for several BIFs have been extended/corrected. Also
+ the types for types for <c>lists:keyfind/3</c>,
+ <c>lists:keysearch/3</c>, and <c>lists:keyemember/3</c>
+ have been corrected. The incorrect/incomplete types could
+ cause false dialyzer warnings.</p>
+ <p>
+ Own Id: OTP-9496</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Dialyzer 2.4.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/dialyzer/doc/src/part.xml b/lib/dialyzer/doc/src/part.xml
index 4410840660..4410840660 100755..100644
--- a/lib/dialyzer/doc/src/part.xml
+++ b/lib/dialyzer/doc/src/part.xml
diff --git a/lib/dialyzer/doc/src/part_notes.xml b/lib/dialyzer/doc/src/part_notes.xml
index cb048d55dd..cb048d55dd 100755..100644
--- a/lib/dialyzer/doc/src/part_notes.xml
+++ b/lib/dialyzer/doc/src/part_notes.xml
diff --git a/lib/dialyzer/doc/src/ref_man.xml b/lib/dialyzer/doc/src/ref_man.xml
index ca5410f6b8..ca5410f6b8 100755..100644
--- a/lib/dialyzer/doc/src/ref_man.xml
+++ b/lib/dialyzer/doc/src/ref_man.xml
diff --git a/lib/dialyzer/info b/lib/dialyzer/info
index 9fba4b54ad..9fba4b54ad 100755..100644
--- a/lib/dialyzer/info
+++ b/lib/dialyzer/info
diff --git a/lib/dialyzer/src/dialyzer_contracts.erl b/lib/dialyzer/src/dialyzer_contracts.erl
index bcdcf2685d..84b926a17a 100644
--- a/lib/dialyzer/src/dialyzer_contracts.erl
+++ b/lib/dialyzer/src/dialyzer_contracts.erl
@@ -480,7 +480,7 @@ invalid_contract_warning({M, F, A}, FileLine, SuccType, RecDict) ->
extra_range_warning({M, F, A}, FileLine, ExtraRanges, STRange) ->
ERangesStr = erl_types:t_to_string(ExtraRanges),
STRangeStr = erl_types:t_to_string(STRange),
- {?WARN_CONTRACT_TYPES, FileLine,
+ {?WARN_CONTRACT_SUPERTYPE, FileLine,
{extra_range, [M, F, A, ERangesStr, STRangeStr]}}.
picky_contract_check(CSig0, Sig0, MFA, FileLine, Contract, RecDict, Acc) ->
diff --git a/lib/dialyzer/src/dialyzer_dataflow.erl b/lib/dialyzer/src/dialyzer_dataflow.erl
index 7137dbc036..d74c04385b 100644
--- a/lib/dialyzer/src/dialyzer_dataflow.erl
+++ b/lib/dialyzer/src/dialyzer_dataflow.erl
@@ -528,7 +528,7 @@ handle_apply(Tree, Map, State) ->
{CallSitesKnown, FunList} =
case state__lookup_call_site(Tree, State2) of
error -> {false, []};
- {ok, [external]} -> {false, {}};
+ {ok, [external]} -> {false, []};
{ok, List} -> {true, List}
end,
case CallSitesKnown of
@@ -554,7 +554,13 @@ handle_apply(Tree, Map, State) ->
{State3, enter_type(Op, OpType1, Map2), t_none()};
false ->
Map3 = enter_type_lists(Args, NewArgs, Map2),
- {State2, enter_type(Op, OpType1, Map3), t_fun_range(OpType1)}
+ Range0 = t_fun_range(OpType1),
+ Range =
+ case t_is_unit(Range0) of
+ true -> t_none();
+ false -> Range0
+ end,
+ {State2, enter_type(Op, OpType1, Map3), Range}
end
end;
true ->
@@ -1393,10 +1399,14 @@ do_clause(C, Arg, ArgType0, OrigArgType, Map,
true -> Any = t_any(), [Any || _ <- Pats];
false -> t_to_tlist(OrigArgType)
end,
- case bind_pat_vars(Pats, OrigArgTypes, [], Map1, State1) of
- {error, bind, _, _, _} -> {{pattern_match, PatTypes}, false};
- {_, _} -> {{pattern_match_cov, PatTypes}, false}
- end;
+ Tag =
+ case bind_pat_vars(Pats, OrigArgTypes, [], Map1, State1) of
+ {error, bind, _, _, _} -> pattern_match;
+ {error, record, _, _, _} -> record_match;
+ {error, opaque, _, _, _} -> opaque_match;
+ {_, _} -> pattern_match_cov
+ end,
+ {{Tag, PatTypes}, false};
false ->
%% Try to find out if this is a default clause in a list
%% comprehension and supress this. A real Hack(tm)
@@ -1414,6 +1424,17 @@ do_clause(C, Arg, ArgType0, OrigArgType, Map,
false ->
true
end;
+ [Pat0, Pat1] -> % binary comprehension
+ case cerl:is_c_cons(Pat0) of
+ true ->
+ not (cerl:is_c_var(cerl:cons_hd(Pat0)) andalso
+ cerl:is_c_var(cerl:cons_tl(Pat0)) andalso
+ cerl:is_c_var(Pat1) andalso
+ cerl:is_literal(Guard) andalso
+ (cerl:concrete(Guard) =:= true));
+ false ->
+ true
+ end;
_ -> true
end;
false ->
@@ -1425,12 +1446,12 @@ do_clause(C, Arg, ArgType0, OrigArgType, Map,
opaque -> [PatString, format_type(Type, State1),
format_type(OpaqueTerm, State1)]
end,
- FailedMsg = case ErrorType of
- bind -> {pattern_match, PatTypes};
- record -> {record_match, PatTypes};
- opaque -> {opaque_match, PatTypes}
+ FailedTag = case ErrorType of
+ bind -> pattern_match;
+ record -> record_match;
+ opaque -> opaque_match
end,
- {FailedMsg, Force0}
+ {{FailedTag, PatTypes}, Force0}
end,
WarnType = case Msg of
{opaque_match, _} -> ?WARN_OPAQUE;
@@ -2915,7 +2936,7 @@ state__get_warnings(#state{tree_map = TreeMap, fun_tab = FunTab,
{Warn, Msg} =
case dialyzer_callgraph:lookup_name(FunLbl, Callgraph) of
error -> {true, {unused_fun, []}};
- {ok, {_M, F, A}} = MFA ->
+ {ok, {_M, F, A} = MFA} ->
{not sets:is_element(MFA, NoWarnUnused),
{unused_fun, [F, A]}}
end,
@@ -2935,7 +2956,7 @@ state__get_warnings(#state{tree_map = TreeMap, fun_tab = FunTab,
%% Check if the function has a contract that allows this.
Warn =
case Contract of
- none -> true;
+ none -> not parent_allows_this(FunLbl, State);
{value, C} ->
GenRet = dialyzer_contracts:get_contract_return(C),
not t_is_unit(GenRet)
@@ -3423,6 +3444,33 @@ map_pats(Pats) ->
end,
cerl_trees:map(Fun, Pats).
+parent_allows_this(FunLbl, #state{callgraph = Callgraph, plt = Plt} =State) ->
+ case state__is_escaping(FunLbl, State) of
+ false -> false; % if it isn't escaping it can't be a return value
+ true ->
+ case state__lookup_name(FunLbl, State) of
+ {_M, _F, _A} -> false; % if it has a name it is not a fun
+ _ ->
+ case dialyzer_callgraph:in_neighbours(FunLbl, Callgraph) of
+ [Parent] ->
+ case state__lookup_name(Parent, State) of
+ {_M, _F, _A} = PMFA ->
+ case dialyzer_plt:lookup_contract(Plt, PMFA) of
+ none -> false;
+ {value, C} ->
+ GenRet = dialyzer_contracts:get_contract_return(C),
+ case erl_types:t_is_fun(GenRet) of
+ false -> false; % element of structure? far-fetched...
+ true -> t_is_unit(t_fun_range(GenRet))
+ end
+ end;
+ _ -> false % parent should have a name to have a contract
+ end;
+ _ -> false % called in other funs? far-fetched...
+ end
+ end
+ end.
+
classify_returns(Tree) ->
case find_terminals(cerl:fun_body(Tree)) of
{false, false} -> no_match;
diff --git a/lib/dialyzer/src/dialyzer_typesig.erl b/lib/dialyzer/src/dialyzer_typesig.erl
index c45615d670..92868b6878 100644
--- a/lib/dialyzer/src/dialyzer_typesig.erl
+++ b/lib/dialyzer/src/dialyzer_typesig.erl
@@ -2,7 +2,7 @@
%%-----------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -62,7 +62,8 @@
-type dep() :: integer(). %% type variable names used as constraint ids
-type type_var() :: erl_types:erl_type(). %% actually: {'c','var',_,_}
--record(fun_var, {'fun' :: fun((_) -> erl_types:erl_type()), deps :: [dep()]}).
+-record(fun_var, {'fun' :: fun((_) -> erl_types:erl_type()), deps :: [dep()],
+ origin :: integer()}).
-type constr_op() :: 'eq' | 'sub'.
-type fvar_or_type() :: #fun_var{} | erl_types:erl_type().
@@ -121,8 +122,10 @@
-ifdef(DEBUG).
-define(debug(__String, __Args), io:format(__String, __Args)).
+-define(mk_fun_var(Fun, Vars), mk_fun_var(?LINE, Fun, Vars)).
-else.
-define(debug(__String, __Args), ok).
+-define(mk_fun_var(Fun, Vars), mk_fun_var(Fun, Vars)).
-endif.
%% ============================================================================
@@ -218,10 +221,10 @@ traverse(Tree, DefinedVars, State) ->
binary ->
{State1, SegTypes} = traverse_list(cerl:binary_segments(Tree),
DefinedVars, State),
- Type = mk_fun_var(fun(Map) ->
- TmpSegTypes = lookup_type_list(SegTypes, Map),
- t_bitstr_concat(TmpSegTypes)
- end, SegTypes),
+ Type = ?mk_fun_var(fun(Map) ->
+ TmpSegTypes = lookup_type_list(SegTypes, Map),
+ t_bitstr_concat(TmpSegTypes)
+ end, SegTypes),
{state__store_conj(mk_var(Tree), sub, Type, State1), mk_var(Tree)};
bitstr ->
Size = cerl:bitstr_size(Tree),
@@ -236,7 +239,7 @@ traverse(Tree, DefinedVars, State) ->
N when is_integer(N) -> {State1, t_bitstr(0, N)};
any -> % Size is not a literal
{state__store_conj(SizeType, sub, t_non_neg_integer(), State1),
- mk_fun_var(bitstr_constr(SizeType, UnitVal), [SizeType])}
+ ?mk_fun_var(bitstr_constr(SizeType, UnitVal), [SizeType])}
end,
ValTypeConstr =
case cerl:concrete(cerl:bitstr_type(Tree)) of
@@ -250,8 +253,8 @@ traverse(Tree, DefinedVars, State) ->
case state__is_in_match(State1) of
true ->
Flags = cerl:concrete(cerl:bitstr_flags(Tree)),
- mk_fun_var(bitstr_val_constr(SizeType, UnitVal, Flags),
- [SizeType]);
+ ?mk_fun_var(bitstr_val_constr(SizeType, UnitVal, Flags),
+ [SizeType]);
false -> t_integer()
end;
utf8 -> t_integer();
@@ -281,24 +284,24 @@ traverse(Tree, DefinedVars, State) ->
{State, t_cons(HdVar, TlVar)};
false ->
ConsVar = mk_var(Tree),
- ConsType = mk_fun_var(fun(Map) ->
- t_cons(lookup_type(HdVar, Map),
- lookup_type(TlVar, Map))
- end, [HdVar, TlVar]),
- HdType = mk_fun_var(fun(Map) ->
- Cons = lookup_type(ConsVar, Map),
- case t_is_cons(Cons) of
- false -> t_any();
- true -> t_cons_hd(Cons)
- end
- end, [ConsVar]),
- TlType = mk_fun_var(fun(Map) ->
- Cons = lookup_type(ConsVar, Map),
- case t_is_cons(Cons) of
- false -> t_any();
- true -> t_cons_tl(Cons)
- end
- end, [ConsVar]),
+ ConsType = ?mk_fun_var(fun(Map) ->
+ t_cons(lookup_type(HdVar, Map),
+ lookup_type(TlVar, Map))
+ end, [HdVar, TlVar]),
+ HdType = ?mk_fun_var(fun(Map) ->
+ Cons = lookup_type(ConsVar, Map),
+ case t_is_cons(Cons) of
+ false -> t_any();
+ true -> t_cons_hd(Cons)
+ end
+ end, [ConsVar]),
+ TlType = ?mk_fun_var(fun(Map) ->
+ Cons = lookup_type(ConsVar, Map),
+ case t_is_cons(Cons) of
+ false -> t_any();
+ true -> t_cons_tl(Cons)
+ end
+ end, [ConsVar]),
State2 = state__store_conj_lists([HdVar, TlVar, ConsVar], sub,
[HdType, TlType, ConsType],
State1),
@@ -656,25 +659,25 @@ get_plt_constr(MFA, Dst, ArgVars, State) ->
{RetType, ArgCs} =
case PltRes of
none ->
- {mk_fun_var(fun(Map) ->
- ArgTypes = lookup_type_list(ArgVars, Map),
- dialyzer_contracts:get_contract_return(C, ArgTypes)
- end, ArgVars), GenArgs};
+ {?mk_fun_var(fun(Map) ->
+ ArgTypes = lookup_type_list(ArgVars, Map),
+ dialyzer_contracts:get_contract_return(C, ArgTypes)
+ end, ArgVars), GenArgs};
{value, {PltRetType, PltArgTypes}} ->
%% Need to combine the contract with the success typing.
- {mk_fun_var(
- fun(Map) ->
- ArgTypes0 = lookup_type_list(ArgVars, Map),
- ArgTypes = case FunModule =:= Module of
- false ->
- List = lists:zip(PltArgTypes, ArgTypes0),
- [erl_types:t_unopaque_on_mismatch(T1, T2, Opaques)
- || {T1, T2} <- List];
- true -> ArgTypes0
- end,
- CRet = dialyzer_contracts:get_contract_return(C, ArgTypes),
- t_inf(CRet, PltRetType, opaque)
- end, ArgVars),
+ {?mk_fun_var(
+ fun(Map) ->
+ ArgTypes0 = lookup_type_list(ArgVars, Map),
+ ArgTypes = case FunModule =:= Module of
+ false ->
+ List = lists:zip(PltArgTypes, ArgTypes0),
+ [erl_types:t_unopaque_on_mismatch(T1, T2, Opaques)
+ || {T1, T2} <- List];
+ true -> ArgTypes0
+ end,
+ CRet = dialyzer_contracts:get_contract_return(C, ArgTypes),
+ t_inf(CRet, PltRetType, opaque)
+ end, ArgVars),
[t_inf(X, Y, opaque) || {X, Y} <- lists:zip(GenArgs, PltArgTypes)]}
end,
state__store_conj_lists([Dst|ArgVars], sub, [RetType|ArgCs], State)
@@ -766,10 +769,10 @@ handle_clauses_1([Clause|Tail], TopVar, Arg, DefinedVars,
case SubtrTypes =:= overflow of
true -> S;
false ->
- SubtrPatVar = mk_fun_var(fun(Map) ->
- TmpType = lookup_type(Arg, Map),
- t_subtract_list(TmpType, SubtrTypes)
- end, [Arg]),
+ SubtrPatVar = ?mk_fun_var(fun(Map) ->
+ TmpType = lookup_type(Arg, Map),
+ t_subtract_list(TmpType, SubtrTypes)
+ end, [Arg]),
state__store_conj(Arg, sub, SubtrPatVar, S)
end
end,
@@ -1043,10 +1046,10 @@ handle_guard(Guard, DefinedVars, State) ->
get_bif_constr({erlang, Op, 2}, Dst, Args = [Arg1, Arg2], _State)
when Op =:= '+'; Op =:= '-'; Op =:= '*' ->
- ReturnType = mk_fun_var(fun(Map) ->
- TmpArgTypes = lookup_type_list(Args, Map),
- erl_bif_types:type(erlang, Op, 2, TmpArgTypes)
- end, Args),
+ ReturnType = ?mk_fun_var(fun(Map) ->
+ TmpArgTypes = lookup_type_list(Args, Map),
+ erl_bif_types:type(erlang, Op, 2, TmpArgTypes)
+ end, Args),
ArgFun =
fun(A, Pos) ->
F =
@@ -1074,7 +1077,7 @@ get_bif_constr({erlang, Op, 2}, Dst, Args = [Arg1, Arg2], _State)
end
end
end,
- mk_fun_var(F, [Dst, A])
+ ?mk_fun_var(F, [Dst, A])
end,
Arg1FunVar = ArgFun(Arg2, 2),
Arg2FunVar = ArgFun(Arg1, 1),
@@ -1131,12 +1134,12 @@ get_bif_constr({erlang, Op, 2}, Dst, [Arg1, Arg2] = Args, _State)
'>=' -> {ArgFun(Arg1, Arg2, '>='), ArgFun(Arg2, Arg1, '=<')}
end,
DstArgs = [Dst, Arg1, Arg2],
- Arg1Var = mk_fun_var(Arg1Fun, DstArgs),
- Arg2Var = mk_fun_var(Arg2Fun, DstArgs),
- DstVar = mk_fun_var(fun(Map) ->
- TmpArgTypes = lookup_type_list(Args, Map),
- erl_bif_types:type(erlang, Op, 2, TmpArgTypes)
- end, Args),
+ Arg1Var = ?mk_fun_var(Arg1Fun, DstArgs),
+ Arg2Var = ?mk_fun_var(Arg2Fun, DstArgs),
+ DstVar = ?mk_fun_var(fun(Map) ->
+ TmpArgTypes = lookup_type_list(Args, Map),
+ erl_bif_types:type(erlang, Op, 2, TmpArgTypes)
+ end, Args),
mk_conj_constraint_list([mk_constraint(Dst, sub, DstVar),
mk_constraint(Arg1, sub, Arg1Var),
mk_constraint(Arg2, sub, Arg2Var)]);
@@ -1172,13 +1175,13 @@ get_bif_constr({erlang, '++', 2}, Dst, [Hd, Tl] = Args, _State) ->
end
end,
DstL = [Dst],
- HdVar = mk_fun_var(HdFun, DstL),
- TlVar = mk_fun_var(TlFun, DstL),
+ HdVar = ?mk_fun_var(HdFun, DstL),
+ TlVar = ?mk_fun_var(TlFun, DstL),
ArgTypes = erl_bif_types:arg_types(erlang, '++', 2),
- ReturnType = mk_fun_var(fun(Map) ->
- TmpArgTypes = lookup_type_list(Args, Map),
- erl_bif_types:type(erlang, '++', 2, TmpArgTypes)
- end, Args),
+ ReturnType = ?mk_fun_var(fun(Map) ->
+ TmpArgTypes = lookup_type_list(Args, Map),
+ erl_bif_types:type(erlang, '++', 2, TmpArgTypes)
+ end, Args),
Cs = mk_constraints(Args, sub, ArgTypes),
mk_conj_constraint_list([mk_constraint(Dst, sub, ReturnType),
mk_constraint(Hd, sub, HdVar),
@@ -1209,7 +1212,7 @@ get_bif_constr({erlang, is_function, 2}, Dst, [Fun, Arity], _State) ->
false -> t_any()
end
end,
- ArgV = mk_fun_var(ArgFun, [Dst, Arity]),
+ ArgV = ?mk_fun_var(ArgFun, [Dst, Arity]),
mk_conj_constraint_list([mk_constraint(Dst, sub, t_boolean()),
mk_constraint(Arity, sub, t_integer()),
mk_constraint(Fun, sub, ArgV)]);
@@ -1232,12 +1235,12 @@ get_bif_constr({erlang, is_record, 2}, Dst, [Var, Tag] = Args, _State) ->
false -> t_any()
end
end,
- ArgV = mk_fun_var(ArgFun, [Dst]),
+ ArgV = ?mk_fun_var(ArgFun, [Dst]),
DstFun = fun(Map) ->
TmpArgTypes = lookup_type_list(Args, Map),
erl_bif_types:type(erlang, is_record, 2, TmpArgTypes)
end,
- DstV = mk_fun_var(DstFun, Args),
+ DstV = ?mk_fun_var(DstFun, Args),
mk_conj_constraint_list([mk_constraint(Dst, sub, DstV),
mk_constraint(Tag, sub, t_atom()),
mk_constraint(Var, sub, ArgV)]);
@@ -1280,7 +1283,7 @@ get_bif_constr({erlang, is_record, 3}, Dst, [Var, Tag, Arity] = Args, State) ->
false -> t_any()
end
end,
- ArgV = mk_fun_var(ArgFun, [Tag, Arity, Dst]),
+ ArgV = ?mk_fun_var(ArgFun, [Tag, Arity, Dst]),
DstFun = fun(Map) ->
[TmpVar, TmpTag, TmpArity] = TmpArgTypes = lookup_type_list(Args, Map),
TmpArgTypes2 =
@@ -1314,7 +1317,7 @@ get_bif_constr({erlang, is_record, 3}, Dst, [Var, Tag, Arity] = Args, State) ->
end,
erl_bif_types:type(erlang, is_record, 3, TmpArgTypes2)
end,
- DstV = mk_fun_var(DstFun, Args),
+ DstV = ?mk_fun_var(DstFun, Args),
mk_conj_constraint_list([mk_constraint(Dst, sub, DstV),
mk_constraint(Arity, sub, t_integer()),
mk_constraint(Tag, sub, t_atom()),
@@ -1359,9 +1362,9 @@ get_bif_constr({erlang, 'and', 2}, Dst, [Arg1, Arg2] = Args, _State) ->
end
end
end,
- ArgV1 = mk_fun_var(ArgFun(Arg2), [Arg2, Dst]),
- ArgV2 = mk_fun_var(ArgFun(Arg1), [Arg1, Dst]),
- DstV = mk_fun_var(DstFun, Args),
+ ArgV1 = ?mk_fun_var(ArgFun(Arg2), [Arg2, Dst]),
+ ArgV2 = ?mk_fun_var(ArgFun(Arg1), [Arg1, Dst]),
+ DstV = ?mk_fun_var(DstFun, Args),
mk_conj_constraint_list([mk_constraint(Dst, sub, DstV),
mk_constraint(Arg1, sub, ArgV1),
mk_constraint(Arg2, sub, ArgV2)]);
@@ -1403,9 +1406,9 @@ get_bif_constr({erlang, 'or', 2}, Dst, [Arg1, Arg2] = Args, _State) ->
end
end
end,
- ArgV1 = mk_fun_var(ArgFun(Arg2), [Arg2, Dst]),
- ArgV2 = mk_fun_var(ArgFun(Arg1), [Arg1, Dst]),
- DstV = mk_fun_var(DstFun, Args),
+ ArgV1 = ?mk_fun_var(ArgFun(Arg2), [Arg2, Dst]),
+ ArgV2 = ?mk_fun_var(ArgFun(Arg1), [Arg1, Dst]),
+ DstV = ?mk_fun_var(DstFun, Args),
F = fun(A) ->
try [mk_constraint(A, sub, True)]
catch throw:error -> []
@@ -1433,8 +1436,8 @@ get_bif_constr({erlang, 'not', 1}, Dst, [Arg] = Args, _State) ->
end
end
end,
- ArgV = mk_fun_var(Fun(Dst), [Dst]),
- DstV = mk_fun_var(Fun(Arg), Args),
+ ArgV = ?mk_fun_var(Fun(Dst), [Dst]),
+ DstV = ?mk_fun_var(Fun(Arg), Args),
mk_conj_constraint_list([mk_constraint(Arg, sub, ArgV),
mk_constraint(Dst, sub, DstV)]);
get_bif_constr({erlang, '=:=', 2}, Dst, [Arg1, Arg2] = Args, _State) ->
@@ -1467,9 +1470,9 @@ get_bif_constr({erlang, '=:=', 2}, Dst, [Arg1, Arg2] = Args, _State) ->
end
end,
DstArgs = [Dst, Arg1, Arg2],
- ArgV1 = mk_fun_var(ArgFun(Arg1, Arg2), DstArgs),
- ArgV2 = mk_fun_var(ArgFun(Arg2, Arg1), DstArgs),
- DstV = mk_fun_var(DstFun, Args),
+ ArgV1 = ?mk_fun_var(ArgFun(Arg1, Arg2), DstArgs),
+ ArgV2 = ?mk_fun_var(ArgFun(Arg2, Arg1), DstArgs),
+ DstV = ?mk_fun_var(DstFun, Args),
mk_conj_constraint_list([mk_constraint(Dst, sub, DstV),
mk_constraint(Arg1, sub, ArgV1),
mk_constraint(Arg2, sub, ArgV2)]);
@@ -1510,10 +1513,10 @@ get_bif_constr({erlang, '==', 2}, Dst, [Arg1, Arg2] = Args, _State) ->
end
end
end,
- DstV = mk_fun_var(DstFun, Args),
+ DstV = ?mk_fun_var(DstFun, Args),
ArgL = [Arg1, Arg2, Dst],
- ArgV1 = mk_fun_var(ArgFun(Arg2, Arg1), ArgL),
- ArgV2 = mk_fun_var(ArgFun(Arg1, Arg2), ArgL),
+ ArgV1 = ?mk_fun_var(ArgFun(Arg2, Arg1), ArgL),
+ ArgV2 = ?mk_fun_var(ArgFun(Arg1, Arg2), ArgL),
mk_conj_constraint_list([mk_constraint(Dst, sub, DstV),
mk_constraint(Arg1, sub, ArgV1),
mk_constraint(Arg2, sub, ArgV2)]);
@@ -1531,7 +1534,7 @@ get_bif_constr({erlang, element, 2} = _BIF, Dst, Args,
end,
erl_bif_types:type(erlang, element, 2, ATs2)
end,
- ReturnType = mk_fun_var(Fun, Args),
+ ReturnType = ?mk_fun_var(Fun, Args),
ArgTypes = erl_bif_types:arg_types(erlang, element, 2),
Cs = mk_constraints(Args, sub, ArgTypes),
NewCs =
@@ -1553,7 +1556,7 @@ get_bif_constr({M, F, A} = _BIF, Dst, Args, State) ->
false -> T
end
end,
- ReturnType = mk_fun_var(fun(Map) ->
+ ReturnType = ?mk_fun_var(fun(Map) ->
TmpArgTypes0 = lookup_type_list(Args, Map),
TmpArgTypes = [UnopaqueFun(T) || T<- TmpArgTypes0],
erl_bif_types:type(M, F, A, TmpArgTypes)
@@ -1608,7 +1611,7 @@ get_bif_test_constr(Dst, Arg, Type, State) ->
false -> t_any()
end
end,
- ArgV = mk_fun_var(ArgFun, [Dst]),
+ ArgV = ?mk_fun_var(ArgFun, [Dst]),
DstFun = fun(Map) ->
ArgType = lookup_type(Arg, Map),
case t_is_none(t_inf(ArgType, Type)) of
@@ -1633,7 +1636,7 @@ get_bif_test_constr(Dst, Arg, Type, State) ->
end
end
end,
- DstV = mk_fun_var(DstFun, [Arg]),
+ DstV = ?mk_fun_var(DstFun, [Arg]),
mk_conj_constraint_list([mk_constraint(Dst, sub, DstV),
mk_constraint(Arg, sub, ArgV)]).
@@ -1684,11 +1687,14 @@ solve_scc(SCC, Map, State, TryingUnit) ->
true ->
?debug("SCC ~w reached fixpoint\n", [SCC]),
NewTypes = unsafe_lookup_type_list(Funs, Map2),
- case lists:all(fun(T) -> t_is_none(t_fun_range(T)) end, NewTypes)
+ case erl_types:any_none([t_fun_range(T) || T <- NewTypes])
andalso TryingUnit =:= false of
true ->
- UnitTypes = [t_fun(state__fun_arity(F, State), t_unit())
- || F <- Funs],
+ UnitTypes =
+ [case t_is_none(t_fun_range(T)) of
+ false -> T;
+ true -> t_fun(t_fun_args(T), t_unit())
+ end || T <- NewTypes],
Map3 = enter_type_lists(Funs, UnitTypes, Map2),
solve_scc(SCC, Map3, State, true);
false ->
@@ -2155,13 +2161,21 @@ get_apply_constr(FunLabels, Dst, ArgTypes, #state{callgraph = CG} = State) ->
case lists:member(error, MFAs) of
true -> error;
false ->
- Constrs = [begin
- State1 = state__new_constraint_context(State),
- State2 = get_plt_constr(MFA, Dst, ArgTypes, State1),
- state__cs(State2)
- end || {ok, MFA} <- MFAs],
- ApplyConstr = mk_disj_constraint_list(Constrs),
- {ok, state__store_conj(ApplyConstr, State)}
+ Constrs0 =
+ [begin
+ State1 = state__new_constraint_context(State),
+ try get_plt_constr(MFA, Dst, ArgTypes, State1) of
+ State2 -> state__cs(State2)
+ catch
+ throw:error -> error
+ end
+ end || {ok, MFA} <- MFAs],
+ case [C || C <- Constrs0, C =/= error] of
+ [] -> throw(error);
+ Constrs ->
+ ApplyConstr = mk_disj_constraint_list(Constrs),
+ {ok, state__store_conj(ApplyConstr, State)}
+ end
end.
state__scc(#state{scc = SCC}) ->
@@ -2320,12 +2334,25 @@ mk_constraint(Lhs, Op, Rhs) ->
constraint_opnd_is_any(#fun_var{}) -> false;
constraint_opnd_is_any(Type) -> t_is_any(Type).
+-ifdef(DEBUG).
+
+-spec mk_fun_var(fun((_) -> erl_types:erl_type()), [erl_types:erl_type()],
+ integer()) -> #fun_var{}.
+
+mk_fun_var(Line, Fun, Types) ->
+ Deps = [t_var_name(Var) || Var <- t_collect_vars(t_product(Types))],
+ #fun_var{'fun' = Fun, deps = ordsets:from_list(Deps), origin = Line}.
+
+-else.
+
-spec mk_fun_var(fun((_) -> erl_types:erl_type()), [erl_types:erl_type()]) -> #fun_var{}.
mk_fun_var(Fun, Types) ->
Deps = [t_var_name(Var) || Var <- t_collect_vars(t_product(Types))],
#fun_var{'fun' = Fun, deps = ordsets:from_list(Deps)}.
+-endif.
+
-spec get_deps(constr()) -> [dep()].
get_deps(#constraint{deps = D}) -> D;
@@ -2676,8 +2703,9 @@ find_constraint(Tuple, [_|Cs]) ->
-endif.
-ifdef(DEBUG).
-format_type(#fun_var{deps = Deps}) ->
- io_lib:format("Fun(~s)", [lists:flatten([format_type(t_var(X))||X<-Deps])]);
+format_type(#fun_var{deps = Deps, origin = Origin}) ->
+ io_lib:format("Fun@L~p(~s)",
+ [Origin, lists:flatten([format_type(t_var(X))||X<-Deps])]);
format_type(Type) ->
case cerl:is_literal(Type) of
true -> io_lib:format("~w", [cerl:concrete(Type)]);
diff --git a/lib/dialyzer/test/Makefile b/lib/dialyzer/test/Makefile
index 69a8fd742e..47deb17f1d 100644
--- a/lib/dialyzer/test/Makefile
+++ b/lib/dialyzer/test/Makefile
@@ -26,7 +26,7 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_tests_spec:
$(INSTALL_DIR) $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
$(INSTALL_DATA) $(AUXILIARY_FILES) $(RELSYSDIR)
@tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
cd $(RELSYSDIR);\
diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/crash b/lib/dialyzer/test/opaque_SUITE_data/results/crash
index 6bdd934169..1ddae5149f 100644
--- a/lib/dialyzer/test/opaque_SUITE_data/results/crash
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/crash
@@ -1,5 +1,4 @@
-crash_1.erl:42: The specification for crash_1:empty/0 states that the function might also return crash_1:targetlist() but the inferred return is none()
crash_1.erl:45: Record construction #targetlist{list::[]} violates the declared type of field list::'undefined' | crash_1:target()
crash_1.erl:48: The call crash_1:get_using_branch2(Branch::maybe_improper_list(),L::'undefined' | crash_1:target()) contains an opaque term as 2nd argument when terms of different types are expected in these positions
crash_1.erl:50: The pattern <_Branch, []> can never match the type <maybe_improper_list(),'undefined' | crash_1:target()>
diff --git a/lib/dialyzer/test/r9c_SUITE_data/results/asn1 b/lib/dialyzer/test/r9c_SUITE_data/results/asn1
index ac83366bc8..292275dd6e 100644
--- a/lib/dialyzer/test/r9c_SUITE_data/results/asn1
+++ b/lib/dialyzer/test/r9c_SUITE_data/results/asn1
@@ -2,11 +2,11 @@
asn1ct.erl:1500: The variable Err can never match since previous clauses completely covered the type #type{}
asn1ct.erl:1596: The variable _ can never match since previous clauses completely covered the type 'ber_bin_v2'
asn1ct.erl:1673: The pattern 'all' can never match the type 'asn1_module' | 'exclusive_decode' | 'partial_decode'
-asn1ct.erl:672: The pattern <{'false', Result}, _, _> can never match the type <{'true','true'},atom() | binary() | [atom() | binary() | [atom() | binary() | [any()] | char()] | char()],[any()]>
+asn1ct.erl:672: The pattern <{'false', Result}, _, _> can never match the type <{'true','true'},atom() | binary() | [atom() | [any()] | char()],[any()]>
asn1ct.erl:909: Guard test is_atom(Ext::[49 | 97 | 98 | 100 | 110 | 115]) can never succeed
asn1ct_check.erl:1698: The pattern {'error', _} can never match the type [any()]
asn1ct_check.erl:2733: The pattern {'type', Tag, _, _, _, _} can never match the type 'ASN1_OPEN_TYPE' | {_,_} | {'fixedtypevaluefield',_,_}
-asn1ct_check.erl:2738: The pattern <_S, _> can never match since previous clauses completely covered the type <#state{},#ObjectClassFieldType{class::#objectclass{fields::maybe_improper_list() | {_,_,_,_}},fieldname::{_,maybe_improper_list()},type::'ASN1_OPEN_TYPE' | {_,_} | {'fixedtypevaluefield',_,_}}>
+asn1ct_check.erl:2738: The pattern <_S, _> can never match since previous clauses completely covered the type <#state{},#'ObjectClassFieldType'{class::#objectclass{fields::maybe_improper_list() | {_,_,_,_}},fieldname::{_,maybe_improper_list()},type::'ASN1_OPEN_TYPE' | {_,_} | {'fixedtypevaluefield',_,_}}>
asn1ct_check.erl:2887: The variable Other can never match since previous clauses completely covered the type any()
asn1ct_check.erl:3188: The pattern <_S, [], B> can never match the type <#state{},{'SingleValue',_},{'ValueRange',_}>
asn1ct_check.erl:3190: The pattern <_S, A, []> can never match the type <#state{},{'SingleValue',_},{'ValueRange',_}>
@@ -29,8 +29,8 @@ asn1ct_check.erl:5128: Guard test is_record(Type::{_,_} | {'fixedtypevaluefield'
asn1ct_check.erl:540: The pattern <_S, {'poc', _ObjSet, _Params}> can never match since previous clauses completely covered the type <#state{},_>
asn1ct_check.erl:5517: The pattern <_, []> can never match the type <_,[{'ABSTRACT-SYNTAX',{_,_,_}} | {'TYPE-IDENTIFIER',{_,_,_}},...]>
asn1ct_constructed_ber.erl:1075: The pattern {{{'ObjectClassFieldType', _, _, _, {'objectfield', PrimFieldName1, PFNList}}, _}, {'componentrelation', _, _}} can never match the type {#type{},_}
-asn1ct_constructed_ber.erl:695: The pattern {'EXTENSIONMARK', _, _} can never match the type #ComponentType{}
-asn1ct_constructed_ber.erl:748: The pattern <Erules, TopType, {CompList, _ExtList}> can never match the type <_,maybe_improper_list(),[#ComponentType{typespec::{_,_,_,_,_,_}}]>
+asn1ct_constructed_ber.erl:695: The pattern {'EXTENSIONMARK', _, _} can never match the type #'ComponentType'{}
+asn1ct_constructed_ber.erl:748: The pattern <Erules, TopType, {CompList, _ExtList}> can never match the type <_,maybe_improper_list(),[#'ComponentType'{typespec::{_,_,_,_,_,_}}]>
asn1ct_constructed_ber_bin_v2.erl:914: The pattern {{{'ObjectClassFieldType', _, _, _, {'objectfield', PrimFieldName1, PFNList}}, _}, {'componentrelation', _, _}} can never match the type {#type{},_}
asn1ct_gen.erl:740: The pattern [] can never match the type [any(),...]
asn1ct_gen_ber.erl:974: The pattern <Erules, [{Name, Def} | Rest]> can never match the type <_,[#typedef{name::atom(),typespec::{_,_,_,_,_,_}}]>
diff --git a/lib/dialyzer/test/r9c_SUITE_data/results/inets b/lib/dialyzer/test/r9c_SUITE_data/results/inets
index fd5e36a3cd..0177dcc88c 100644
--- a/lib/dialyzer/test/r9c_SUITE_data/results/inets
+++ b/lib/dialyzer/test/r9c_SUITE_data/results/inets
@@ -3,13 +3,15 @@ ftp.erl:1243: The pattern {'ok', {N, Bytes}} can never match the type 'eof' | {'
ftp.erl:640: The pattern {'closed', _Why} can never match the type 'perm_fname_not_allowed' | 'perm_neg_compl' | 'perm_no_space' | 'pos_compl' | 'pos_interm' | 'pos_interm_acct' | 'trans_neg_compl' | 'trans_no_space' | {'error' | 'perm_fname_not_allowed' | 'perm_neg_compl' | 'perm_no_space' | 'pos_compl' | 'pos_interm' | 'pos_interm_acct' | 'pos_prel' | 'trans_neg_compl' | 'trans_no_space',atom() | [any()] | {'invalid_server_response',[any(),...]}}
http.erl:117: The pattern {'error', Reason} can never match the type #req_headers{connection::[45 | 97 | 101 | 105 | 107 | 108 | 112 | 118,...],content_length::[48,...],other::[{_,_}]}
http.erl:138: Function close_session/2 will never be called
-http_lib.erl:286: The call http_lib:close('ip_comm' | {'ssl',_},any()) will never return since it differs in the 1st argument from the success typing arguments: ('http' | 'https',any())
-http_lib.erl:424: The variable _ can never match since previous clauses completely covered the type any()
-http_lib.erl:438: The variable _ can never match since previous clauses completely covered the type any()
+http_lib.erl:286: The call http_lib:close('ip_comm' | {'ssl',_},port() | {'sslsocket',_,_}) will never return since it differs in the 1st argument from the success typing arguments: ('http' | 'https',port() | {'sslsocket',_,pid() | {_,{'config',_,_,_,_,{_,_,_,_}}} | {'sslsocket',_,pid() | {'sslsocket',_,pid() | {_,_,_}}}})
+http_lib.erl:415: The pattern 61 can never match the type 'http_eoh' | binary() | maybe_improper_list(any(),binary() | []) | {'http_error',binary() | string()} | #http_request{method::'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'POST' | 'PUT' | 'TRACE' | binary() | string(),path::'*' | binary() | string() | {'abs_path',binary() | string()} | {'scheme',binary() | string(),binary() | string()} | {'absoluteURI','http' | 'https',binary() | string(),'undefined' | non_neg_integer(),binary() | string()},version::{non_neg_integer(),non_neg_integer()}} | #http_response{version::{non_neg_integer(),non_neg_integer()},status::integer(),phrase::binary() | string()} | {'http_header',integer(),atom() | binary() | string(),_,binary() | string()}
+http_lib.erl:417: The pattern 59 can never match the type 'http_eoh' | binary() | maybe_improper_list(any(),binary() | []) | {'http_error',binary() | string()} | #http_request{method::'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'POST' | 'PUT' | 'TRACE' | binary() | string(),path::'*' | binary() | string() | {'abs_path',binary() | string()} | {'scheme',binary() | string(),binary() | string()} | {'absoluteURI','http' | 'https',binary() | string(),'undefined' | non_neg_integer(),binary() | string()},version::{non_neg_integer(),non_neg_integer()}} | #http_response{version::{non_neg_integer(),non_neg_integer()},status::integer(),phrase::binary() | string()} | {'http_header',integer(),atom() | binary() | string(),_,binary() | string()}
+http_lib.erl:420: The pattern 13 can never match the type 'http_eoh' | binary() | maybe_improper_list(any(),binary() | []) | {'http_error',binary() | string()} | #http_request{method::'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'POST' | 'PUT' | 'TRACE' | binary() | string(),path::'*' | binary() | string() | {'abs_path',binary() | string()} | {'scheme',binary() | string(),binary() | string()} | {'absoluteURI','http' | 'https',binary() | string(),'undefined' | non_neg_integer(),binary() | string()},version::{non_neg_integer(),non_neg_integer()}} | #http_response{version::{non_neg_integer(),non_neg_integer()},status::integer(),phrase::binary() | string()} | {'http_header',integer(),atom() | binary() | string(),_,binary() | string()}
+http_lib.erl:424: The variable _ can never match since previous clauses completely covered the type 'http_eoh' | binary() | maybe_improper_list(any(),binary() | []) | {'http_error',binary() | string()} | #http_request{method::'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'POST' | 'PUT' | 'TRACE' | binary() | string(),path::'*' | binary() | string() | {'abs_path',binary() | string()} | {'scheme',binary() | string(),binary() | string()} | {'absoluteURI','http' | 'https',binary() | string(),'undefined' | non_neg_integer(),binary() | string()},version::{non_neg_integer(),non_neg_integer()}} | #http_response{version::{non_neg_integer(),non_neg_integer()},status::integer(),phrase::binary() | string()} | {'http_header',integer(),atom() | binary() | string(),_,binary() | string()}
+http_lib.erl:428: Function read_chunk_ext_val/6 will never be called
+http_lib.erl:444: The pattern 10 can never match the type 'http_eoh' | binary() | maybe_improper_list(any(),binary() | []) | {'http_error',binary() | string()} | #http_request{method::'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'POST' | 'PUT' | 'TRACE' | binary() | string(),path::'*' | binary() | string() | {'abs_path',binary() | string()} | {'scheme',binary() | string(),binary() | string()} | {'absoluteURI','http' | 'https',binary() | string(),'undefined' | non_neg_integer(),binary() | string()},version::{non_neg_integer(),non_neg_integer()}} | #http_response{version::{non_neg_integer(),non_neg_integer()},status::integer(),phrase::binary() | string()} | {'http_header',integer(),atom() | binary() | string(),_,binary() | string()}
+http_lib.erl:552: Call to missing or unexported function ssl:accept/2
http_lib.erl:99: Function getHeaderValue/2 will never be called
-httpc_handler.erl:322: Function status_continue/2 has no local return
-httpc_handler.erl:37: Function init_connection/2 has no local return
-httpc_handler.erl:65: Function next_response_with_request/2 has no local return
httpc_handler.erl:660: Function exit_session_ok/2 has no local return
httpc_manager.erl:145: The pattern {ErrorReply, State2} can never match the type {{'ok',number()},number(),#state{reqid::number()}}
httpc_manager.erl:160: The pattern {ErrorReply, State2} can never match the type {{'ok',number()},number(),#state{reqid::number()}}
@@ -24,11 +26,14 @@ httpd_manager.erl:885: The pattern {'EXIT', Reason} can never match since previo
httpd_manager.erl:919: Function auth_status/1 will never be called
httpd_manager.erl:926: Function sec_status/1 will never be called
httpd_manager.erl:933: Function acceptor_status/1 will never be called
-httpd_request_handler.erl:374: The call httpd_response:send_status(Info::#mod{parsed_header::maybe_improper_list()},417,[32 | 66 | 98 | 100 | 103 | 105 | 111 | 116 | 121,...]) will never return since it differs in the 2nd argument from the success typing arguments: (#mod{socket_type::'ip_comm' | {'ssl',_}},100 | 301 | 304 | 400 | 401 | 403 | 404 | 412 | 414 | 416 | 500 | 501 | 503,any())
-httpd_request_handler.erl:378: The call httpd_response:send_status(Info::#mod{parsed_header::maybe_improper_list()},417,[32 | 77 | 97 | 100 | 101 | 104 | 108 | 110 | 111 | 116 | 119,...]) will never return since it differs in the 2nd argument from the success typing arguments: (#mod{socket_type::'ip_comm' | {'ssl',_}},100 | 301 | 304 | 400 | 401 | 403 | 404 | 412 | 414 | 416 | 500 | 501 | 503,any())
-httpd_request_handler.erl:401: The call httpd_response:send_status(Info::#mod{parsed_header::maybe_improper_list()},417,[32 | 77 | 97 | 100 | 101 | 104 | 108 | 110 | 111 | 116 | 119,...]) will never return since it differs in the 2nd argument from the success typing arguments: (#mod{socket_type::'ip_comm' | {'ssl',_}},100 | 301 | 304 | 400 | 401 | 403 | 404 | 412 | 414 | 416 | 500 | 501 | 503,any())
-httpd_request_handler.erl:644: The call lists:reverse(Fields0::{'error',_} | {'ok',[[any()]]}) will never return since it differs in the 1st argument from the success typing arguments: ([any()])
+httpd_request_handler.erl:374: The call httpd_response:send_status(Info::#mod{parsed_header::maybe_improper_list()},417,[32 | 66 | 98 | 100 | 103 | 105 | 111 | 116 | 121,...]) will never return since it differs in the 2nd argument from the success typing arguments: (#mod{socket_type::'ip_comm' | {'ssl',_},socket::port() | {'sslsocket',_,_}},100 | 301 | 304 | 400 | 401 | 403 | 404 | 412 | 414 | 416 | 500 | 501 | 503,any())
+httpd_request_handler.erl:378: The call httpd_response:send_status(Info::#mod{parsed_header::maybe_improper_list()},417,[32 | 77 | 97 | 100 | 101 | 104 | 108 | 110 | 111 | 116 | 119,...]) will never return since it differs in the 2nd argument from the success typing arguments: (#mod{socket_type::'ip_comm' | {'ssl',_},socket::port() | {'sslsocket',_,_}},100 | 301 | 304 | 400 | 401 | 403 | 404 | 412 | 414 | 416 | 500 | 501 | 503,any())
+httpd_request_handler.erl:401: The call httpd_response:send_status(Info::#mod{parsed_header::maybe_improper_list()},417,[32 | 77 | 97 | 100 | 101 | 104 | 108 | 110 | 111 | 116 | 119,...]) will never return since it differs in the 2nd argument from the success typing arguments: (#mod{socket_type::'ip_comm' | {'ssl',_},socket::port() | {'sslsocket',_,_}},100 | 301 | 304 | 400 | 401 | 403 | 404 | 412 | 414 | 416 | 500 | 501 | 503,any())
+httpd_request_handler.erl:489: The variable Other can never match since previous clauses completely covered the type {'error',_} | {'ok','http_eoh' | binary() | maybe_improper_list(any(),binary() | []) | {'http_error',binary() | string()} | {'http_request','DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'POST' | 'PUT' | 'TRACE' | binary() | string(),'*' | binary() | string() | {'abs_path',binary() | [any()]} | {'scheme',binary() | [any()],binary() | [any()]} | {'absoluteURI','http' | 'https',binary() | [any()],'undefined' | non_neg_integer(),binary() | [any()]},{non_neg_integer(),non_neg_integer()}} | {'http_response',{non_neg_integer(),non_neg_integer()},integer(),binary() | string()} | {'http_header',integer(),atom() | binary() | string(),_,binary() | string()}}
+httpd_request_handler.erl:644: The call lists:reverse(Fields0::{'error',_} | {'ok',_}) will never return since it differs in the 1st argument from the success typing arguments: ([any()])
httpd_request_handler.erl:645: Function will never be called
+httpd_socket.erl:129: Call to missing or unexported function ssl:accept/2
+httpd_socket.erl:49: The pattern {'ok', _} can never match the type {'error',_}
httpd_sup.erl:63: The variable Else can never match since previous clauses completely covered the type {'error',_} | {'ok',[any()],_,_}
httpd_sup.erl:88: The pattern {'error', Reason} can never match the type {'ok',_,_}
httpd_sup.erl:92: The variable Else can never match since previous clauses completely covered the type {'ok',_,_}
@@ -38,17 +43,17 @@ mod_auth_plain.erl:100: The variable _ can never match since previous clauses co
mod_auth_plain.erl:159: The variable _ can never match since previous clauses completely covered the type [any()]
mod_auth_plain.erl:83: The variable O can never match since previous clauses completely covered the type [any()]
mod_cgi.erl:372: The pattern {'http_response', NewAccResponse} can never match the type 'ok'
-mod_dir.erl:101: The call lists:flatten(nonempty_improper_list(atom() | binary() | [any()] | char(),atom())) will never return since it differs in the 1st argument from the success typing arguments: ([any()])
+mod_dir.erl:101: The call lists:flatten(nonempty_improper_list(atom() | [any()] | char(),atom())) will never return since it differs in the 1st argument from the success typing arguments: ([any()])
mod_dir.erl:72: The pattern {'error', Reason} can never match the type {'ok',[[[any()] | char()],...]}
-mod_get.erl:135: The pattern <{'enfile', _}, _Info, Path> can never match the type <atom(),#mod{},atom() | binary() | [atom() | binary() | [any()] | char()]>
-mod_head.erl:80: The pattern <{'enfile', _}, _Info, Path> can never match the type <atom(),#mod{},atom() | binary() | [atom() | binary() | [atom() | binary() | [any()] | char()] | char()]>
+mod_get.erl:135: The pattern <{'enfile', _}, _Info, Path> can never match the type <atom(),#mod{},atom() | binary() | [atom() | [any()] | char()]>
+mod_head.erl:80: The pattern <{'enfile', _}, _Info, Path> can never match the type <atom(),#mod{},atom() | binary() | [atom() | [any()] | char()]>
mod_htaccess.erl:460: The pattern {'error', BadData} can never match the type {'ok',_}
-mod_include.erl:193: The pattern {_, Name, {[], []}} can never match the type {[any()],[any()],maybe_improper_list()}
-mod_include.erl:195: The pattern {_, Name, {PathInfo, []}} can never match the type {[any()],[any()],maybe_improper_list()}
-mod_include.erl:197: The pattern {_, Name, {PathInfo, QueryString}} can never match the type {[any()],[any()],maybe_improper_list()}
-mod_include.erl:201: The variable Gurka can never match since previous clauses completely covered the type {[any()],[any()],maybe_improper_list()}
-mod_include.erl:692: The pattern <{'read', Reason}, Info, Path> can never match the type <{'open',atom()},#mod{},atom() | binary() | [atom() | binary() | [atom() | binary() | [any()] | char()] | char()]>
-mod_include.erl:706: The pattern <{'enfile', _}, _Info, Path> can never match the type <atom(),#mod{},atom() | binary() | [atom() | binary() | [atom() | binary() | [any()] | char()] | char()]>
+mod_include.erl:193: The pattern {_, Name, {[], []}} can never match the type {[any()],[any()],string()}
+mod_include.erl:195: The pattern {_, Name, {PathInfo, []}} can never match the type {[any()],[any()],string()}
+mod_include.erl:197: The pattern {_, Name, {PathInfo, QueryString}} can never match the type {[any()],[any()],string()}
+mod_include.erl:201: The variable Gurka can never match since previous clauses completely covered the type {[any()],[any()],string()}
+mod_include.erl:692: The pattern <{'read', Reason}, Info, Path> can never match the type <{'open',atom()},#mod{},atom() | binary() | [atom() | [any()] | char()]>
+mod_include.erl:706: The pattern <{'enfile', _}, _Info, Path> can never match the type <atom(),#mod{},atom() | binary() | [atom() | [any()] | char()]>
mod_include.erl:716: Function read_error/3 will never be called
mod_include.erl:719: Function read_error/4 will never be called
mod_security_server.erl:386: The variable O can never match since previous clauses completely covered the type [any()]
diff --git a/lib/dialyzer/test/r9c_SUITE_data/results/mnesia b/lib/dialyzer/test/r9c_SUITE_data/results/mnesia
index e199581a0e..2be71ac7d7 100644
--- a/lib/dialyzer/test/r9c_SUITE_data/results/mnesia
+++ b/lib/dialyzer/test/r9c_SUITE_data/results/mnesia
@@ -6,6 +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) -> Void 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()), is_subtype(Void,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',_,_}
@@ -15,6 +16,7 @@ mnesia_frag.erl:294: The call mnesia_frag:remote_collect(Ref::reference(),{'erro
mnesia_frag.erl:304: The call mnesia_frag:remote_collect(Ref::reference(),{'error',{'node_not_running',_}},[],OldSelectFun::fun(() -> [any()])) will never return since it differs in the 2nd argument from the success typing arguments: (reference(),'ok',[any()],fun(() -> [any()]))
mnesia_frag.erl:312: The call mnesia_frag:remote_collect(Ref::reference(),LocalRes::{'error',_},[],OldSelectFun::fun(() -> [any()])) will never return since it differs in the 2nd argument from the success typing arguments: (reference(),'ok',[any()],fun(() -> [any()]))
mnesia_index.erl:52: The call mnesia_lib:other_val(Var::{_,'commit_work' | 'index' | 'setorbag' | 'storage_type' | {'index',_}},_ReASoN_::any()) will never return since it differs in the 1st argument from the success typing arguments: ({_,'active_replicas' | 'where_to_read' | 'where_to_write'},any())
+mnesia_lib.erl:1028: The pattern {'EXIT', Reason} can never match the type [any()] | {'error',_}
mnesia_lib.erl:957: The pattern {'ok', {0, _}} can never match the type 'eof' | {'error',atom()} | {'ok',binary() | string()}
mnesia_lib.erl:959: The pattern {'ok', {_, Bin}} can never match the type 'eof' | {'error',atom()} | {'ok',binary() | string()}
mnesia_loader.erl:36: The call mnesia_lib:other_val(Var::{_,'access_mode' | 'cstruct' | 'db_nodes' | 'setorbag' | 'snmp' | 'storage_type'},Reason::any()) will never return since it differs in the 1st argument from the success typing arguments: ({_,'active_replicas' | 'where_to_read' | 'where_to_write'},any())
@@ -30,5 +32,6 @@ mnesia_schema.erl:1258: Guard test FromS::'disc_copies' | 'disc_only_copies' | '
mnesia_schema.erl:1639: The pattern {'false', 'mandatory'} can never match the type {'false','optional'}
mnesia_schema.erl:2434: The variable Reason can never match since previous clauses completely covered the type {'error',_} | {'ok',_}
mnesia_schema.erl:451: Guard test UseDirAnyway::'false' == 'true' can never succeed
+mnesia_text.erl:180: The variable T can never match since previous clauses completely covered the type {'error',{integer(),atom() | tuple(),_}} | {'ok',_}
mnesia_tm.erl:1522: Function commit_participant/5 has no local return
mnesia_tm.erl:2169: Function system_terminate/4 has no local return
diff --git a/lib/dialyzer/test/race_SUITE_data/results/extract_translations b/lib/dialyzer/test/race_SUITE_data/results/extract_translations
index f7d5abc6f5..62aa1aa511 100644
--- a/lib/dialyzer/test/race_SUITE_data/results/extract_translations
+++ b/lib/dialyzer/test/race_SUITE_data/results/extract_translations
@@ -1,5 +1,5 @@
-extract_translations.erl:140: The call ets:insert('files',{atom() | binary() | [atom() | binary() | [atom() | binary() | [any()] | char()] | char()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('files',File::atom() | binary() | [atom() | binary() | [atom() | binary() | [any()] | char()] | char()]) call in extract_translations.erl on line 135
+extract_translations.erl:140: The call ets:insert('files',{atom() | binary() | [atom() | [any()] | char()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('files',File::atom() | binary() | [atom() | [any()] | char()]) call in extract_translations.erl on line 135
extract_translations.erl:146: The call ets:insert('translations',{_,[]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('translations',Str::any()) call in extract_translations.erl on line 126
-extract_translations.erl:152: The call ets:insert('files',{atom() | binary() | [atom() | binary() | [atom() | binary() | [any()] | char()] | char()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('files',File::atom() | binary() | [atom() | binary() | [atom() | binary() | [any()] | char()] | char()]) call in extract_translations.erl on line 148
+extract_translations.erl:152: The call ets:insert('files',{atom() | binary() | [atom() | [any()] | char()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('files',File::atom() | binary() | [atom() | [any()] | char()]) call in extract_translations.erl on line 148
extract_translations.erl:154: The call ets:insert('translations',{_,[]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('translations',Str::any()) call in extract_translations.erl on line 126
diff --git a/lib/dialyzer/test/small_SUITE_data/results/common_eunit b/lib/dialyzer/test/small_SUITE_data/results/common_eunit
new file mode 100644
index 0000000000..bb5fd1c9ac
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/common_eunit
@@ -0,0 +1,2 @@
+
+common_eunit.erl:57: The created fun has no local return
diff --git a/lib/dialyzer/test/small_SUITE_data/results/comparisons b/lib/dialyzer/test/small_SUITE_data/results/comparisons
new file mode 100644
index 0000000000..642585d25e
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/comparisons
@@ -0,0 +1,153 @@
+
+comparisons.erl:100: The pattern 'true' can never match the type 'false'
+comparisons.erl:101: The pattern 'true' can never match the type 'false'
+comparisons.erl:102: The pattern 'false' can never match the type 'true'
+comparisons.erl:103: The pattern 'false' can never match the type 'true'
+comparisons.erl:104: The pattern 'true' can never match the type 'false'
+comparisons.erl:105: The pattern 'true' can never match the type 'false'
+comparisons.erl:107: The pattern 'true' can never match the type 'false'
+comparisons.erl:108: The pattern 'true' can never match the type 'false'
+comparisons.erl:109: The pattern 'false' can never match the type 'true'
+comparisons.erl:110: The pattern 'false' can never match the type 'true'
+comparisons.erl:111: The pattern 'true' can never match the type 'false'
+comparisons.erl:112: The pattern 'true' can never match the type 'false'
+comparisons.erl:113: The pattern 'false' can never match the type 'true'
+comparisons.erl:114: The pattern 'false' can never match the type 'true'
+comparisons.erl:115: The pattern 'true' can never match the type 'false'
+comparisons.erl:116: The pattern 'true' can never match the type 'false'
+comparisons.erl:117: The pattern 'false' can never match the type 'true'
+comparisons.erl:118: The pattern 'false' can never match the type 'true'
+comparisons.erl:123: The pattern 'false' can never match the type 'true'
+comparisons.erl:124: The pattern 'false' can never match the type 'true'
+comparisons.erl:125: The pattern 'true' can never match the type 'false'
+comparisons.erl:126: The pattern 'true' can never match the type 'false'
+comparisons.erl:127: The pattern 'false' can never match the type 'true'
+comparisons.erl:128: The pattern 'false' can never match the type 'true'
+comparisons.erl:129: The pattern 'true' can never match the type 'false'
+comparisons.erl:130: The pattern 'true' can never match the type 'false'
+comparisons.erl:132: The pattern 'true' can never match the type 'false'
+comparisons.erl:133: The pattern 'true' can never match the type 'false'
+comparisons.erl:134: The pattern 'false' can never match the type 'true'
+comparisons.erl:135: The pattern 'false' can never match the type 'true'
+comparisons.erl:136: The pattern 'true' can never match the type 'false'
+comparisons.erl:137: The pattern 'true' can never match the type 'false'
+comparisons.erl:138: The pattern 'false' can never match the type 'true'
+comparisons.erl:139: The pattern 'false' can never match the type 'true'
+comparisons.erl:140: The pattern 'true' can never match the type 'false'
+comparisons.erl:141: The pattern 'true' can never match the type 'false'
+comparisons.erl:142: The pattern 'false' can never match the type 'true'
+comparisons.erl:143: The pattern 'false' can never match the type 'true'
+comparisons.erl:144: The pattern 'true' can never match the type 'false'
+comparisons.erl:145: The pattern 'true' can never match the type 'false'
+comparisons.erl:146: The pattern 'false' can never match the type 'true'
+comparisons.erl:147: The pattern 'false' can never match the type 'true'
+comparisons.erl:152: The pattern 'false' can never match the type 'true'
+comparisons.erl:153: The pattern 'false' can never match the type 'true'
+comparisons.erl:154: The pattern 'true' can never match the type 'false'
+comparisons.erl:155: The pattern 'true' can never match the type 'false'
+comparisons.erl:157: The pattern 'true' can never match the type 'false'
+comparisons.erl:158: The pattern 'true' can never match the type 'false'
+comparisons.erl:159: The pattern 'false' can never match the type 'true'
+comparisons.erl:160: The pattern 'false' can never match the type 'true'
+comparisons.erl:161: The pattern 'true' can never match the type 'false'
+comparisons.erl:162: The pattern 'true' can never match the type 'false'
+comparisons.erl:163: The pattern 'false' can never match the type 'true'
+comparisons.erl:164: The pattern 'false' can never match the type 'true'
+comparisons.erl:165: The pattern 'true' can never match the type 'false'
+comparisons.erl:166: The pattern 'true' can never match the type 'false'
+comparisons.erl:167: The pattern 'false' can never match the type 'true'
+comparisons.erl:168: The pattern 'false' can never match the type 'true'
+comparisons.erl:169: The pattern 'true' can never match the type 'false'
+comparisons.erl:170: The pattern 'true' can never match the type 'false'
+comparisons.erl:171: The pattern 'false' can never match the type 'true'
+comparisons.erl:172: The pattern 'false' can never match the type 'true'
+comparisons.erl:173: The pattern 'true' can never match the type 'false'
+comparisons.erl:174: The pattern 'true' can never match the type 'false'
+comparisons.erl:175: The pattern 'false' can never match the type 'true'
+comparisons.erl:176: The pattern 'false' can never match the type 'true'
+comparisons.erl:186: The pattern 'false' can never match the type 'true'
+comparisons.erl:187: The pattern 'false' can never match the type 'true'
+comparisons.erl:188: The pattern 'true' can never match the type 'false'
+comparisons.erl:189: The pattern 'true' can never match the type 'false'
+comparisons.erl:190: The pattern 'false' can never match the type 'true'
+comparisons.erl:191: The pattern 'false' can never match the type 'true'
+comparisons.erl:192: The pattern 'true' can never match the type 'false'
+comparisons.erl:193: The pattern 'true' can never match the type 'false'
+comparisons.erl:203: The pattern 'false' can never match the type 'true'
+comparisons.erl:204: The pattern 'false' can never match the type 'true'
+comparisons.erl:205: The pattern 'true' can never match the type 'false'
+comparisons.erl:206: The pattern 'true' can never match the type 'false'
+comparisons.erl:208: The pattern 'true' can never match the type 'false'
+comparisons.erl:209: The pattern 'true' can never match the type 'false'
+comparisons.erl:210: The pattern 'false' can never match the type 'true'
+comparisons.erl:211: The pattern 'false' can never match the type 'true'
+comparisons.erl:221: The pattern 'true' can never match the type 'false'
+comparisons.erl:222: The pattern 'true' can never match the type 'false'
+comparisons.erl:223: The pattern 'false' can never match the type 'true'
+comparisons.erl:224: The pattern 'false' can never match the type 'true'
+comparisons.erl:225: The pattern 'true' can never match the type 'false'
+comparisons.erl:226: The pattern 'true' can never match the type 'false'
+comparisons.erl:227: The pattern 'false' can never match the type 'true'
+comparisons.erl:228: The pattern 'false' can never match the type 'true'
+comparisons.erl:242: The pattern 'false' can never match the type 'true'
+comparisons.erl:243: The pattern 'false' can never match the type 'true'
+comparisons.erl:244: The pattern 'true' can never match the type 'false'
+comparisons.erl:245: The pattern 'true' can never match the type 'false'
+comparisons.erl:246: The pattern 'false' can never match the type 'true'
+comparisons.erl:247: The pattern 'false' can never match the type 'true'
+comparisons.erl:248: The pattern 'true' can never match the type 'false'
+comparisons.erl:249: The pattern 'true' can never match the type 'false'
+comparisons.erl:251: The pattern 'true' can never match the type 'false'
+comparisons.erl:252: The pattern 'true' can never match the type 'false'
+comparisons.erl:253: The pattern 'false' can never match the type 'true'
+comparisons.erl:254: The pattern 'false' can never match the type 'true'
+comparisons.erl:263: The pattern 'false' can never match the type 'true'
+comparisons.erl:264: The pattern 'false' can never match the type 'true'
+comparisons.erl:265: The pattern 'true' can never match the type 'false'
+comparisons.erl:266: The pattern 'true' can never match the type 'false'
+comparisons.erl:268: The pattern 'true' can never match the type 'false'
+comparisons.erl:269: The pattern 'true' can never match the type 'false'
+comparisons.erl:270: The pattern 'false' can never match the type 'true'
+comparisons.erl:271: The pattern 'false' can never match the type 'true'
+comparisons.erl:272: The pattern 'true' can never match the type 'false'
+comparisons.erl:273: The pattern 'true' can never match the type 'false'
+comparisons.erl:274: The pattern 'false' can never match the type 'true'
+comparisons.erl:275: The pattern 'false' can never match the type 'true'
+comparisons.erl:293: The pattern 'false' can never match the type 'true'
+comparisons.erl:294: The pattern 'false' can never match the type 'true'
+comparisons.erl:295: The pattern 'true' can never match the type 'false'
+comparisons.erl:296: The pattern 'true' can never match the type 'false'
+comparisons.erl:311: The pattern 'true' can never match the type 'false'
+comparisons.erl:312: The pattern 'true' can never match the type 'false'
+comparisons.erl:313: The pattern 'false' can never match the type 'true'
+comparisons.erl:314: The pattern 'false' can never match the type 'true'
+comparisons.erl:44: The pattern 'false' can never match the type 'true'
+comparisons.erl:45: The pattern 'false' can never match the type 'true'
+comparisons.erl:46: The pattern 'true' can never match the type 'false'
+comparisons.erl:47: The pattern 'true' can never match the type 'false'
+comparisons.erl:48: The pattern 'false' can never match the type 'true'
+comparisons.erl:49: The pattern 'false' can never match the type 'true'
+comparisons.erl:50: The pattern 'true' can never match the type 'false'
+comparisons.erl:51: The pattern 'true' can never match the type 'false'
+comparisons.erl:52: The pattern 'false' can never match the type 'true'
+comparisons.erl:53: The pattern 'false' can never match the type 'true'
+comparisons.erl:54: The pattern 'true' can never match the type 'false'
+comparisons.erl:55: The pattern 'true' can never match the type 'false'
+comparisons.erl:69: The pattern 'false' can never match the type 'true'
+comparisons.erl:70: The pattern 'false' can never match the type 'true'
+comparisons.erl:71: The pattern 'true' can never match the type 'false'
+comparisons.erl:72: The pattern 'true' can never match the type 'false'
+comparisons.erl:73: The pattern 'false' can never match the type 'true'
+comparisons.erl:74: The pattern 'false' can never match the type 'true'
+comparisons.erl:75: The pattern 'true' can never match the type 'false'
+comparisons.erl:76: The pattern 'true' can never match the type 'false'
+comparisons.erl:77: The pattern 'false' can never match the type 'true'
+comparisons.erl:78: The pattern 'false' can never match the type 'true'
+comparisons.erl:79: The pattern 'true' can never match the type 'false'
+comparisons.erl:80: The pattern 'true' can never match the type 'false'
+comparisons.erl:94: The pattern 'false' can never match the type 'true'
+comparisons.erl:95: The pattern 'false' can never match the type 'true'
+comparisons.erl:96: The pattern 'true' can never match the type 'false'
+comparisons.erl:97: The pattern 'true' can never match the type 'false'
+comparisons.erl:98: The pattern 'false' can never match the type 'true'
+comparisons.erl:99: The pattern 'false' can never match the type 'true'
diff --git a/lib/dialyzer/test/small_SUITE_data/results/failing_funs b/lib/dialyzer/test/small_SUITE_data/results/failing_funs
new file mode 100644
index 0000000000..a1fb22cbc6
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/failing_funs
@@ -0,0 +1,20 @@
+
+failing_funs.erl:101: The created fun has no local return
+failing_funs.erl:104: The created fun has no local return
+failing_funs.erl:127: The created fun has no local return
+failing_funs.erl:135: The created fun has no local return
+failing_funs.erl:138: The created fun has no local return
+failing_funs.erl:13: Function foo3/0 has no local return
+failing_funs.erl:13: The pattern 'b' can never match the type 'a'
+failing_funs.erl:161: The created fun has no local return
+failing_funs.erl:169: The created fun has no local return
+failing_funs.erl:172: The created fun has no local return
+failing_funs.erl:17: The pattern 'b' can never match the type 'a'
+failing_funs.erl:195: The created fun has no local return
+failing_funs.erl:203: The created fun has no local return
+failing_funs.erl:206: The created fun has no local return
+failing_funs.erl:229: The created fun has no local return
+failing_funs.erl:55: The created fun has no local return
+failing_funs.erl:62: The created fun has no local return
+failing_funs.erl:69: The created fun has no local return
+failing_funs.erl:76: The created fun has no local return
diff --git a/lib/dialyzer/test/small_SUITE_data/results/flatten b/lib/dialyzer/test/small_SUITE_data/results/flatten
index 4571214e49..8aa44dd002 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/flatten
+++ b/lib/dialyzer/test/small_SUITE_data/results/flatten
@@ -1,2 +1,2 @@
-flatten.erl:17: The call lists:flatten(nonempty_improper_list(atom() | binary() | [any()] | char(),atom())) will never return since it differs in the 1st argument from the success typing arguments: ([any()])
+flatten.erl:17: The call lists:flatten(nonempty_improper_list(atom() | [any()] | char(),atom())) will never return since it differs in the 1st argument from the success typing arguments: ([any()])
diff --git a/lib/dialyzer/test/small_SUITE_data/results/higher_order_discrepancy b/lib/dialyzer/test/small_SUITE_data/results/higher_order_discrepancy
new file mode 100644
index 0000000000..7ce440a60d
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/higher_order_discrepancy
@@ -0,0 +1,4 @@
+
+higher_order_discrepancy.erl:11: The call higher_order_discrepancy:g('foo') will never return since it differs in the 1st argument from the success typing arguments: ('bar')
+higher_order_discrepancy.erl:14: Function g/1 has no local return
+higher_order_discrepancy.erl:14: The pattern 'bar' can never match the type 'foo'
diff --git a/lib/dialyzer/test/small_SUITE_data/results/higher_order_discrepancy_2 b/lib/dialyzer/test/small_SUITE_data/results/higher_order_discrepancy_2
new file mode 100644
index 0000000000..c1c7dbbfcc
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/higher_order_discrepancy_2
@@ -0,0 +1,8 @@
+
+higher_order_discrepancy_2.erl:11: The call higher_order_discrepancy_2:f('foo') will never return since it differs in the 1st argument from the success typing arguments: ('bar')
+higher_order_discrepancy_2.erl:11: The call higher_order_discrepancy_2:g('foo') will never return since it differs in the 1st argument from the success typing arguments: ('baz')
+higher_order_discrepancy_2.erl:13: Function f/1 has no local return
+higher_order_discrepancy_2.erl:13: The pattern 'bar' can never match the type 'foo'
+higher_order_discrepancy_2.erl:14: Function g/1 has no local return
+higher_order_discrepancy_2.erl:14: The pattern 'baz' can never match the type 'foo'
+higher_order_discrepancy_2.erl:5: Function test/1 has no local return
diff --git a/lib/dialyzer/test/small_SUITE_data/results/my_sofs b/lib/dialyzer/test/small_SUITE_data/results/my_sofs
index bfee0bce0d..bc97c08d62 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/my_sofs
+++ b/lib/dialyzer/test/small_SUITE_data/results/my_sofs
@@ -1,3 +1,3 @@
-my_sofs.erl:34: The pattern {'Set', _, _} can never match the type #OrdSet{}
-my_sofs.erl:54: The pattern {'Set', _, _} can never match the type #OrdSet{}
+my_sofs.erl:34: The pattern {'Set', _, _} can never match the type #'OrdSet'{}
+my_sofs.erl:54: The pattern {'Set', _, _} can never match the type #'OrdSet'{}
diff --git a/lib/dialyzer/test/small_SUITE_data/results/tuple_set_crash b/lib/dialyzer/test/small_SUITE_data/results/tuple_set_crash
index 191d3d4173..8c9df56a4b 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/tuple_set_crash
+++ b/lib/dialyzer/test/small_SUITE_data/results/tuple_set_crash
@@ -12,4 +12,3 @@ tuple_set_crash.erl:179: The pattern <<AudioVolume:16/integer-little-unit:1,Rest
tuple_set_crash.erl:182: The pattern <<Delay:16/integer-little-unit:1,_Padding/binary-unit:8>> can never match the type <<_:8>>
tuple_set_crash.erl:62: The pattern {'play_list', _Playlist} can never match the type 'ok' | {'device_properties',[{atom(),_}]} | {'error',[{atom(),_}]}
tuple_set_crash.erl:64: The pattern {'error', 17} can never match the type 'ok' | {'device_properties',[{atom(),_}]} | {'error',[{atom(),_}]}
-tuple_set_crash.erl:83: The specification for tuple_set_crash:parse_message/1 states that the function might also return {'media_item_url_reply',integer(),binary()} but the inferred return is 'ok' | {'audio_device_info' | 'audio_output_info' | 'audio_target_info' | 'device_properties' | 'error' | 'video_device_info' | 'video_output_info' | 'video_target_info',[{'address' | 'audio_volume' | 'controller_description' | 'controller_name' | 'controller_status' | 'device_id' | 'display_type' | 'fw_version' | 'master_volume' | 'model' | 'output_id' | 'status' | 'target_id',binary() | non_neg_integer()}] | 1..255}
diff --git a/lib/dialyzer/test/small_SUITE_data/src/binary_lc_bug.erl b/lib/dialyzer/test/small_SUITE_data/src/binary_lc_bug.erl
new file mode 100644
index 0000000000..c1e82bfa59
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/binary_lc_bug.erl
@@ -0,0 +1,8 @@
+-module(test).
+
+-export([bin_compr/0]).
+
+bin_compr() ->
+% [ 0 || {N, V} <- [{a, b}] ]. % Works ok
+ << <<>> || {A, B} <- [{a, b}] >>. % Complains
+% << <<>> || X <- [{a, b}] >>. % Works ok
diff --git a/lib/dialyzer/test/small_SUITE_data/src/codec_can.erl b/lib/dialyzer/test/small_SUITE_data/src/codec_can.erl
new file mode 100644
index 0000000000..8abf872b37
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/codec_can.erl
@@ -0,0 +1,35 @@
+%%---------------------------------------------------------------------
+%% From: Peer Stritzinger
+%% Date: 1 May 2011
+%% Subject: Dialyzer v2.2.0 crash
+%%
+%% Binaries of the form <<_:N,_:_*M>> in specs resulted in a crash:
+%% dialyzer: Analysis failed with error: {{case_clause,8},
+%% [{erl_types,t_form_to_string,1},
+%% {erl_types,t_form_to_string,1},
+%% {dialyzer_contracts,contract_to_string_1,1},
+%% {dialyzer_contracts,extra_contract_warning,6},
+%% {dialyzer_contracts,picky_contract_check,7},
+%% because function erl_types:t_form_to_string/1 was not the inverse
+%% of erl_types:t_to_string/2.
+%%
+%% Fixed on the same date and send to OTP for inclusion.
+%%---------------------------------------------------------------------
+-module(codec_can).
+
+-export([recv/3, decode/1]).
+
+-record(can_pkt, {id, data :: binary(), timestamp}).
+
+-type can_pkt() :: #can_pkt{}.
+-type channel() :: atom() | pid() | {atom(),_}.
+
+-spec recv(<<_:64,_:_*8>>, fun((can_pkt()) -> R), channel()) -> R.
+recv(Packet, Fun, Chan) ->
+ #can_pkt{id = Can_id, data = Can_data} = P = decode(Packet),
+ Fun(P).
+
+-spec decode(<<_:64,_:_*8>>) -> #can_pkt{id::<<_:11>>,timestamp::char()}.
+decode(<<_:12, Len:4, Timestamp:16, 0:3, Id:11/bitstring, 0:18,
+ Data:Len/binary, _/binary>>) ->
+ #can_pkt{id = Id, data = Data, timestamp = Timestamp}.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/common_eunit.erl b/lib/dialyzer/test/small_SUITE_data/src/common_eunit.erl
new file mode 100644
index 0000000000..bca390068e
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/common_eunit.erl
@@ -0,0 +1,121 @@
+%%=====================================================================
+%% Program with an erroneous type declaration that caused dialyzer to
+%% go into an infinite loop. There are some comments that explain the
+%% symptoms and the culprit: the return of test_fun() is erroneous and
+%% its type should read
+%% fun((config()) -> test_rep() | [test_rep()])
+%% instead. But this should not throw dialyzer into an infinite loop.
+%% This concerned dialyzer in R14B02 (and probably prior).
+%%=====================================================================
+-module(common_eunit).
+
+-export([expand_cases/2]).
+
+-type test_name() :: atom() | {'group', atom()}.
+
+-type test_rep() :: {{atom(), atom(), arity()}, fun()}
+ | {'setup', fun(), fun()}
+ | {'setup', fun(), fun(), fun()}
+ | {atom(), test_rep()}
+ | {atom(), term(), test_rep()}.
+
+-type config() :: [proplists:property()].
+
+-type control() :: tuple() | atom().
+
+%% The combination of the following type and the (erroneous) spec for
+%% expand_cases/2 is the reason for the infinite loop in dialyzer.
+-type test_fun() :: fun((config()) -> test_rep()).
+
+%% If one comments out this spec the infinite loop disappears.
+-spec expand_cases(atom(), test_name() | [test_name()]) -> test_fun().
+expand_cases(Module, Cases) ->
+ if is_list(Cases) ->
+ TestFuns = [expand_case(Module, Case) || Case <- Cases],
+ fun(Config) -> [F(Config) || F <- TestFuns] end;
+ is_atom(Cases); is_tuple(Cases) ->
+ expand_cases(Module, [Cases])
+ end.
+
+-spec expand_case(atom(), test_name()) -> test_fun().
+expand_case(Module, CaseName) when is_atom(CaseName) ->
+ TestFun = fun(Config) ->
+ {{Module, CaseName, 1},
+ fun() -> apply(Module, CaseName, [Config]) end}
+ end,
+ setup_wrapper(Module, TestFun, {init_per_testcase, [CaseName]},
+ {end_per_testcase, [CaseName]});
+expand_case(Module, {group, GroupName}) ->
+ {Control, Cases} = group_specification(Module, GroupName),
+ TestFun = control_wrapper(Control, expand_cases(Module, Cases)),
+ setup_wrapper(Module, TestFun, {init_per_group, [GroupName]},
+ {end_per_group, [GroupName]}).
+
+-spec control_wrapper([control()], test_fun()) -> test_fun().
+control_wrapper([Control|T], TestFun0) ->
+ TestFun1 = control_wrapper(T, TestFun0),
+ fun(Config) ->
+ case Control of
+ parallel ->
+ {inparallel, TestFun1(Config)};
+ sequence ->
+ {inorder, TestFun1(Config)};
+ {timetrap, Time} ->
+ Seconds = case Time of
+ {hours, Hs} -> Hs * 60 * 60;
+ {minutes, Ms} -> Ms * 60;
+ {seconds, Ss} -> Ss;
+ MSs -> MSs / 1000
+ end,
+ {timeout, Seconds, TestFun1(Config)};
+ C when is_atom(C) ->
+ {C, TestFun1(Config)};
+ {C, Arg} ->
+ {C, Arg, TestFun1(Config)}
+ end
+ end;
+control_wrapper([], TestFun) ->
+ TestFun.
+
+-spec setup_wrapper(atom(), test_fun(), Callback, Callback) -> test_fun()
+ when Callback :: {atom(), list()}.
+setup_wrapper(Module, TestFun, {Setup, SA}, {Cleanup, CA}) ->
+ case erlang:function_exported(Module, Setup, length(SA) + 1) of
+ true ->
+ case erlang:function_exported(Module, Cleanup, length(CA) + 1) of
+ true ->
+ fun(Config0) ->
+ {setup,
+ fun() ->
+ apply(Module, Setup, SA ++ [Config0])
+ end,
+ fun(Config1) ->
+ apply(Module, Cleanup, CA ++ [Config1])
+ end,
+ TestFun}
+ end;
+ false ->
+ fun(Config) ->
+ {setup,
+ fun() ->
+ apply(Module, Setup, SA ++ [Config])
+ end,
+ TestFun}
+ end
+ end;
+ false ->
+ TestFun
+ end.
+
+-spec group_specification(atom(), atom()) -> {[control()], [test_name()]}.
+group_specification(Module, GroupName) ->
+ case lists:keyfind(GroupName, 1, Module:groups()) of
+ {_, Control, Cases} when is_list(Control), is_list(Cases) ->
+ {Control, Cases};
+ {_, Cases} when is_list(Cases) ->
+ {[], Cases};
+ false ->
+ exit({missing_group, GroupName});
+ _ ->
+ exit({bad_group_spec, GroupName})
+ end.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/comparisons.erl b/lib/dialyzer/test/small_SUITE_data/src/comparisons.erl
new file mode 100644
index 0000000000..70e3cb6af4
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/comparisons.erl
@@ -0,0 +1,322 @@
+-module(comparisons).
+
+-compile(export_all).
+
+-define(r, get(r)).
+
+integer() -> integer(?r).
+integer(X) when is_integer(X) -> X.
+
+mfloat() -> float(?r).
+mfloat(X) when is_float(X) -> X.
+
+atom() -> atom(?r).
+atom(X) when is_atom(X) -> X.
+
+tuple() -> tuple(?r).
+tuple(X) when is_tuple(X) -> X.
+
+list() -> list(?r).
+list(X) when is_list(X) -> X.
+
+i() -> integer().
+f() -> mfloat().
+n() -> case ?r of 1 -> i(); 2 -> f() end.
+a() -> atom().
+t() -> tuple().
+l() -> list().
+na() -> case ?r of 1 -> n(); 2 -> a() end.
+at() -> case ?r of 1 -> t(); 2 -> a() end.
+tl() -> case ?r of 1 -> t(); 2 -> l() end.
+
+test_i_ll_i() -> case i() < i() of true -> maybe; false -> maybe_too end.
+test_i_le_i() -> case i() =< i() of true -> maybe; false -> maybe_too end.
+test_i_gg_i() -> case i() > i() of true -> maybe; false -> maybe_too end.
+test_i_ge_i() -> case i() >= i() of true -> maybe; false -> maybe_too end.
+test_i_ll_f() -> case i() < f() of true -> maybe; false -> maybe_too end.
+test_i_le_f() -> case i() =< f() of true -> maybe; false -> maybe_too end.
+test_i_gg_f() -> case i() > f() of true -> maybe; false -> maybe_too end.
+test_i_ge_f() -> case i() >= f() of true -> maybe; false -> maybe_too end.
+test_i_ll_n() -> case i() < n() of true -> maybe; false -> maybe_too end.
+test_i_le_n() -> case i() =< n() of true -> maybe; false -> maybe_too end.
+test_i_gg_n() -> case i() > n() of true -> maybe; false -> maybe_too end.
+test_i_ge_n() -> case i() >= n() of true -> maybe; false -> maybe_too end.
+test_i_ll_a() -> case i() < a() of true -> always; false -> never end.
+test_i_le_a() -> case i() =< a() of true -> always; false -> never end.
+test_i_gg_a() -> case i() > a() of true -> never; false -> always end.
+test_i_ge_a() -> case i() >= a() of true -> never; false -> always end.
+test_i_ll_t() -> case i() < t() of true -> always; false -> never end.
+test_i_le_t() -> case i() =< t() of true -> always; false -> never end.
+test_i_gg_t() -> case i() > t() of true -> never; false -> always end.
+test_i_ge_t() -> case i() >= t() of true -> never; false -> always end.
+test_i_ll_l() -> case i() < l() of true -> always; false -> never end.
+test_i_le_l() -> case i() =< l() of true -> always; false -> never end.
+test_i_gg_l() -> case i() > l() of true -> never; false -> always end.
+test_i_ge_l() -> case i() >= l() of true -> never; false -> always end.
+
+test_f_ll_i() -> case f() < i() of true -> maybe; false -> maybe_too end.
+test_f_le_i() -> case f() =< i() of true -> maybe; false -> maybe_too end.
+test_f_gg_i() -> case f() > i() of true -> maybe; false -> maybe_too end.
+test_f_ge_i() -> case f() >= i() of true -> maybe; false -> maybe_too end.
+test_f_ll_f() -> case f() < f() of true -> maybe; false -> maybe_too end.
+test_f_le_f() -> case f() =< f() of true -> maybe; false -> maybe_too end.
+test_f_gg_f() -> case f() > f() of true -> maybe; false -> maybe_too end.
+test_f_ge_f() -> case f() >= f() of true -> maybe; false -> maybe_too end.
+test_f_ll_n() -> case f() < n() of true -> maybe; false -> maybe_too end.
+test_f_le_n() -> case f() =< n() of true -> maybe; false -> maybe_too end.
+test_f_gg_n() -> case f() > n() of true -> maybe; false -> maybe_too end.
+test_f_ge_n() -> case f() >= n() of true -> maybe; false -> maybe_too end.
+test_f_ll_a() -> case f() < a() of true -> always; false -> never end.
+test_f_le_a() -> case f() =< a() of true -> always; false -> never end.
+test_f_gg_a() -> case f() > a() of true -> never; false -> always end.
+test_f_ge_a() -> case f() >= a() of true -> never; false -> always end.
+test_f_ll_t() -> case f() < t() of true -> always; false -> never end.
+test_f_le_t() -> case f() =< t() of true -> always; false -> never end.
+test_f_gg_t() -> case f() > t() of true -> never; false -> always end.
+test_f_ge_t() -> case f() >= t() of true -> never; false -> always end.
+test_f_ll_l() -> case f() < l() of true -> always; false -> never end.
+test_f_le_l() -> case f() =< l() of true -> always; false -> never end.
+test_f_gg_l() -> case f() > l() of true -> never; false -> always end.
+test_f_ge_l() -> case f() >= l() of true -> never; false -> always end.
+
+test_n_ll_i() -> case n() < i() of true -> maybe; false -> maybe_too end.
+test_n_le_i() -> case n() =< i() of true -> maybe; false -> maybe_too end.
+test_n_gg_i() -> case n() > i() of true -> maybe; false -> maybe_too end.
+test_n_ge_i() -> case n() >= i() of true -> maybe; false -> maybe_too end.
+test_n_ll_f() -> case n() < f() of true -> maybe; false -> maybe_too end.
+test_n_le_f() -> case n() =< f() of true -> maybe; false -> maybe_too end.
+test_n_gg_f() -> case n() > f() of true -> maybe; false -> maybe_too end.
+test_n_ge_f() -> case n() >= f() of true -> maybe; false -> maybe_too end.
+test_n_ll_n() -> case n() < n() of true -> maybe; false -> maybe_too end.
+test_n_le_n() -> case n() =< n() of true -> maybe; false -> maybe_too end.
+test_n_gg_n() -> case n() > n() of true -> maybe; false -> maybe_too end.
+test_n_ge_n() -> case n() >= n() of true -> maybe; false -> maybe_too end.
+test_n_ll_a() -> case n() < a() of true -> always; false -> never end.
+test_n_le_a() -> case n() =< a() of true -> always; false -> never end.
+test_n_gg_a() -> case n() > a() of true -> never; false -> always end.
+test_n_ge_a() -> case n() >= a() of true -> never; false -> always end.
+test_n_ll_t() -> case n() < t() of true -> always; false -> never end.
+test_n_le_t() -> case n() =< t() of true -> always; false -> never end.
+test_n_gg_t() -> case n() > t() of true -> never; false -> always end.
+test_n_ge_t() -> case n() >= t() of true -> never; false -> always end.
+test_n_ll_l() -> case n() < l() of true -> always; false -> never end.
+test_n_le_l() -> case n() =< l() of true -> always; false -> never end.
+test_n_gg_l() -> case n() > l() of true -> never; false -> always end.
+test_n_ge_l() -> case n() >= l() of true -> never; false -> always end.
+
+test_a_ll_i() -> case a() < i() of true -> never; false -> always end.
+test_a_le_i() -> case a() =< i() of true -> never; false -> always end.
+test_a_gg_i() -> case a() > i() of true -> always; false -> never end.
+test_a_ge_i() -> case a() >= i() of true -> always; false -> never end.
+test_a_ll_f() -> case a() < f() of true -> never; false -> always end.
+test_a_le_f() -> case a() =< f() of true -> never; false -> always end.
+test_a_gg_f() -> case a() > f() of true -> always; false -> never end.
+test_a_ge_f() -> case a() >= f() of true -> always; false -> never end.
+test_a_ll_n() -> case a() < n() of true -> never; false -> always end.
+test_a_le_n() -> case a() =< n() of true -> never; false -> always end.
+test_a_gg_n() -> case a() > n() of true -> always; false -> never end.
+test_a_ge_n() -> case a() >= n() of true -> always; false -> never end.
+test_a_ll_a() -> case a() < a() of true -> maybe; false -> maybe_too end.
+test_a_le_a() -> case a() =< a() of true -> maybe; false -> maybe_too end.
+test_a_gg_a() -> case a() > a() of true -> maybe; false -> maybe_too end.
+test_a_ge_a() -> case a() >= a() of true -> maybe; false -> maybe_too end.
+test_a_ll_t() -> case a() < t() of true -> always; false -> never end.
+test_a_le_t() -> case a() =< t() of true -> always; false -> never end.
+test_a_gg_t() -> case a() > t() of true -> never; false -> always end.
+test_a_ge_t() -> case a() >= t() of true -> never; false -> always end.
+test_a_ll_l() -> case a() < l() of true -> always; false -> never end.
+test_a_le_l() -> case a() =< l() of true -> always; false -> never end.
+test_a_gg_l() -> case a() > l() of true -> never; false -> always end.
+test_a_ge_l() -> case a() >= l() of true -> never; false -> always end.
+
+test_t_ll_i() -> case t() < i() of true -> never; false -> always end.
+test_t_le_i() -> case t() =< i() of true -> never; false -> always end.
+test_t_gg_i() -> case t() > i() of true -> always; false -> never end.
+test_t_ge_i() -> case t() >= i() of true -> always; false -> never end.
+test_t_ll_f() -> case t() < f() of true -> never; false -> always end.
+test_t_le_f() -> case t() =< f() of true -> never; false -> always end.
+test_t_gg_f() -> case t() > f() of true -> always; false -> never end.
+test_t_ge_f() -> case t() >= f() of true -> always; false -> never end.
+test_t_ll_n() -> case t() < n() of true -> never; false -> always end.
+test_t_le_n() -> case t() =< n() of true -> never; false -> always end.
+test_t_gg_n() -> case t() > n() of true -> always; false -> never end.
+test_t_ge_n() -> case t() >= n() of true -> always; false -> never end.
+test_t_ll_a() -> case t() < a() of true -> never; false -> always end.
+test_t_le_a() -> case t() =< a() of true -> never; false -> always end.
+test_t_gg_a() -> case t() > a() of true -> always; false -> never end.
+test_t_ge_a() -> case t() >= a() of true -> always; false -> never end.
+test_t_ll_t() -> case t() < t() of true -> maybe; false -> maybe_too end.
+test_t_le_t() -> case t() =< t() of true -> maybe; false -> maybe_too end.
+test_t_gg_t() -> case t() > t() of true -> maybe; false -> maybe_too end.
+test_t_ge_t() -> case t() >= t() of true -> maybe; false -> maybe_too end.
+test_t_ll_l() -> case t() < l() of true -> always; false -> never end.
+test_t_le_l() -> case t() =< l() of true -> always; false -> never end.
+test_t_gg_l() -> case t() > l() of true -> never; false -> always end.
+test_t_ge_l() -> case t() >= l() of true -> never; false -> always end.
+
+test_l_ll_i() -> case l() < i() of true -> never; false -> always end.
+test_l_le_i() -> case l() =< i() of true -> never; false -> always end.
+test_l_gg_i() -> case l() > i() of true -> always; false -> never end.
+test_l_ge_i() -> case l() >= i() of true -> always; false -> never end.
+test_l_ll_f() -> case l() < f() of true -> never; false -> always end.
+test_l_le_f() -> case l() =< f() of true -> never; false -> always end.
+test_l_gg_f() -> case l() > f() of true -> always; false -> never end.
+test_l_ge_f() -> case l() >= f() of true -> always; false -> never end.
+test_l_ll_n() -> case l() < n() of true -> never; false -> always end.
+test_l_le_n() -> case l() =< n() of true -> never; false -> always end.
+test_l_gg_n() -> case l() > n() of true -> always; false -> never end.
+test_l_ge_n() -> case l() >= n() of true -> always; false -> never end.
+test_l_ll_a() -> case l() < a() of true -> never; false -> always end.
+test_l_le_a() -> case l() =< a() of true -> never; false -> always end.
+test_l_gg_a() -> case l() > a() of true -> always; false -> never end.
+test_l_ge_a() -> case l() >= a() of true -> always; false -> never end.
+test_l_ll_t() -> case l() < t() of true -> never; false -> always end.
+test_l_le_t() -> case l() =< t() of true -> never; false -> always end.
+test_l_gg_t() -> case l() > t() of true -> always; false -> never end.
+test_l_ge_t() -> case l() >= t() of true -> always; false -> never end.
+test_l_ll_l() -> case l() < l() of true -> maybe; false -> maybe_too end.
+test_l_le_l() -> case l() =< l() of true -> maybe; false -> maybe_too end.
+test_l_gg_l() -> case l() > l() of true -> maybe; false -> maybe_too end.
+test_l_ge_l() -> case l() >= l() of true -> maybe; false -> maybe_too end.
+
+test_n_ll_na() -> case n() < na() of true -> maybe; false -> maybe_too end.
+test_n_le_na() -> case n() =< na() of true -> maybe; false -> maybe_too end.
+test_n_gg_na() -> case n() > na() of true -> maybe; false -> maybe_too end.
+test_n_ge_na() -> case n() >= na() of true -> maybe; false -> maybe_too end.
+test_n_ll_at() -> case n() < at() of true -> always; false -> never end.
+test_n_le_at() -> case n() =< at() of true -> always; false -> never end.
+test_n_gg_at() -> case n() > at() of true -> never; false -> always end.
+test_n_ge_at() -> case n() >= at() of true -> never; false -> always end.
+test_n_ll_tl() -> case n() < tl() of true -> always; false -> never end.
+test_n_le_tl() -> case n() =< tl() of true -> always; false -> never end.
+test_n_gg_tl() -> case n() > tl() of true -> never; false -> always end.
+test_n_ge_tl() -> case n() >= tl() of true -> never; false -> always end.
+
+test_a_ll_na() -> case a() < na() of true -> maybe; false -> maybe_too end.
+test_a_le_na() -> case a() =< na() of true -> maybe; false -> maybe_too end.
+test_a_gg_na() -> case a() > na() of true -> maybe; false -> maybe_too end.
+test_a_ge_na() -> case a() >= na() of true -> maybe; false -> maybe_too end.
+test_a_ll_at() -> case a() < at() of true -> maybe; false -> maybe_too end.
+test_a_le_at() -> case a() =< at() of true -> maybe; false -> maybe_too end.
+test_a_gg_at() -> case a() > at() of true -> maybe; false -> maybe_too end.
+test_a_ge_at() -> case a() >= at() of true -> maybe; false -> maybe_too end.
+test_a_ll_tl() -> case a() < tl() of true -> always; false -> never end.
+test_a_le_tl() -> case a() =< tl() of true -> always; false -> never end.
+test_a_gg_tl() -> case a() > tl() of true -> never; false -> always end.
+test_a_ge_tl() -> case a() >= tl() of true -> never; false -> always end.
+
+test_t_ll_na() -> case t() < na() of true -> never; false -> always end.
+test_t_le_na() -> case t() =< na() of true -> never; false -> always end.
+test_t_gg_na() -> case t() > na() of true -> always; false -> never end.
+test_t_ge_na() -> case t() >= na() of true -> always; false -> never end.
+test_t_ll_at() -> case t() < at() of true -> maybe; false -> maybe_too end.
+test_t_le_at() -> case t() =< at() of true -> maybe; false -> maybe_too end.
+test_t_gg_at() -> case t() > at() of true -> maybe; false -> maybe_too end.
+test_t_ge_at() -> case t() >= at() of true -> maybe; false -> maybe_too end.
+test_t_ll_tl() -> case t() < tl() of true -> maybe; false -> maybe_too end.
+test_t_le_tl() -> case t() =< tl() of true -> maybe; false -> maybe_too end.
+test_t_gg_tl() -> case t() > tl() of true -> maybe; false -> maybe_too end.
+test_t_ge_tl() -> case t() >= tl() of true -> maybe; false -> maybe_too end.
+
+test_l_ll_na() -> case l() < na() of true -> never; false -> always end.
+test_l_le_na() -> case l() =< na() of true -> never; false -> always end.
+test_l_gg_na() -> case l() > na() of true -> always; false -> never end.
+test_l_ge_na() -> case l() >= na() of true -> always; false -> never end.
+test_l_ll_at() -> case l() < at() of true -> never; false -> always end.
+test_l_le_at() -> case l() =< at() of true -> never; false -> always end.
+test_l_gg_at() -> case l() > at() of true -> always; false -> never end.
+test_l_ge_at() -> case l() >= at() of true -> always; false -> never end.
+test_l_ll_tl() -> case l() < tl() of true -> maybe; false -> maybe_too end.
+test_l_le_tl() -> case l() =< tl() of true -> maybe; false -> maybe_too end.
+test_l_gg_tl() -> case l() > tl() of true -> maybe; false -> maybe_too end.
+test_l_ge_tl() -> case l() >= tl() of true -> maybe; false -> maybe_too end.
+
+test_na_ll_n() -> case na() < n() of true -> maybe; false -> maybe_too end.
+test_na_le_n() -> case na() =< n() of true -> maybe; false -> maybe_too end.
+test_na_gg_n() -> case na() > n() of true -> maybe; false -> maybe_too end.
+test_na_ge_n() -> case na() >= n() of true -> maybe; false -> maybe_too end.
+test_na_ll_a() -> case na() < a() of true -> maybe; false -> maybe_too end.
+test_na_le_a() -> case na() =< a() of true -> maybe; false -> maybe_too end.
+test_na_gg_a() -> case na() > a() of true -> maybe; false -> maybe_too end.
+test_na_ge_a() -> case na() >= a() of true -> maybe; false -> maybe_too end.
+test_na_ll_t() -> case na() < t() of true -> always; false -> never end.
+test_na_le_t() -> case na() =< t() of true -> always; false -> never end.
+test_na_gg_t() -> case na() > t() of true -> never; false -> always end.
+test_na_ge_t() -> case na() >= t() of true -> never; false -> always end.
+test_na_ll_l() -> case na() < l() of true -> always; false -> never end.
+test_na_le_l() -> case na() =< l() of true -> always; false -> never end.
+test_na_gg_l() -> case na() > l() of true -> never; false -> always end.
+test_na_ge_l() -> case na() >= l() of true -> never; false -> always end.
+
+test_at_ll_n() -> case at() < n() of true -> never; false -> always end.
+test_at_le_n() -> case at() =< n() of true -> never; false -> always end.
+test_at_gg_n() -> case at() > n() of true -> always; false -> never end.
+test_at_ge_n() -> case at() >= n() of true -> always; false -> never end.
+test_at_ll_a() -> case at() < a() of true -> maybe; false -> maybe_too end.
+test_at_le_a() -> case at() =< a() of true -> maybe; false -> maybe_too end.
+test_at_gg_a() -> case at() > a() of true -> maybe; false -> maybe_too end.
+test_at_ge_a() -> case at() >= a() of true -> maybe; false -> maybe_too end.
+test_at_ll_t() -> case at() < t() of true -> maybe; false -> maybe_too end.
+test_at_le_t() -> case at() =< t() of true -> maybe; false -> maybe_too end.
+test_at_gg_t() -> case at() > t() of true -> maybe; false -> maybe_too end.
+test_at_ge_t() -> case at() >= t() of true -> maybe; false -> maybe_too end.
+test_at_ll_l() -> case at() < l() of true -> always; false -> never end.
+test_at_le_l() -> case at() =< l() of true -> always; false -> never end.
+test_at_gg_l() -> case at() > l() of true -> never; false -> always end.
+test_at_ge_l() -> case at() >= l() of true -> never; false -> always end.
+
+test_tl_ll_n() -> case tl() < n() of true -> never; false -> always end.
+test_tl_le_n() -> case tl() =< n() of true -> never; false -> always end.
+test_tl_gg_n() -> case tl() > n() of true -> always; false -> never end.
+test_tl_ge_n() -> case tl() >= n() of true -> always; false -> never end.
+test_tl_ll_a() -> case tl() < a() of true -> never; false -> always end.
+test_tl_le_a() -> case tl() =< a() of true -> never; false -> always end.
+test_tl_gg_a() -> case tl() > a() of true -> always; false -> never end.
+test_tl_ge_a() -> case tl() >= a() of true -> always; false -> never end.
+test_tl_ll_t() -> case tl() < t() of true -> maybe; false -> maybe_too end.
+test_tl_le_t() -> case tl() =< t() of true -> maybe; false -> maybe_too end.
+test_tl_gg_t() -> case tl() > t() of true -> maybe; false -> maybe_too end.
+test_tl_ge_t() -> case tl() >= t() of true -> maybe; false -> maybe_too end.
+test_tl_ll_l() -> case tl() < l() of true -> maybe; false -> maybe_too end.
+test_tl_le_l() -> case tl() =< l() of true -> maybe; false -> maybe_too end.
+test_tl_gg_l() -> case tl() > l() of true -> maybe; false -> maybe_too end.
+test_tl_ge_l() -> case tl() >= l() of true -> maybe; false -> maybe_too end.
+
+test_na_ll_na() -> case na() < na() of true -> maybe; false -> maybe_too end.
+test_na_le_na() -> case na() =< na() of true -> maybe; false -> maybe_too end.
+test_na_gg_na() -> case na() > na() of true -> maybe; false -> maybe_too end.
+test_na_ge_na() -> case na() >= na() of true -> maybe; false -> maybe_too end.
+test_na_ll_at() -> case na() < at() of true -> maybe; false -> maybe_too end.
+test_na_le_at() -> case na() =< at() of true -> maybe; false -> maybe_too end.
+test_na_gg_at() -> case na() > at() of true -> maybe; false -> maybe_too end.
+test_na_ge_at() -> case na() >= at() of true -> maybe; false -> maybe_too end.
+test_na_ll_tl() -> case na() < tl() of true -> always; false -> never end.
+test_na_le_tl() -> case na() =< tl() of true -> always; false -> never end.
+test_na_gg_tl() -> case na() > tl() of true -> never; false -> always end.
+test_na_ge_tl() -> case na() >= tl() of true -> never; false -> always end.
+
+test_at_ll_na() -> case at() < na() of true -> maybe; false -> maybe_too end.
+test_at_le_na() -> case at() =< na() of true -> maybe; false -> maybe_too end.
+test_at_gg_na() -> case at() > na() of true -> maybe; false -> maybe_too end.
+test_at_ge_na() -> case at() >= na() of true -> maybe; false -> maybe_too end.
+test_at_ll_at() -> case at() < at() of true -> maybe; false -> maybe_too end.
+test_at_le_at() -> case at() =< at() of true -> maybe; false -> maybe_too end.
+test_at_gg_at() -> case at() > at() of true -> maybe; false -> maybe_too end.
+test_at_ge_at() -> case at() >= at() of true -> maybe; false -> maybe_too end.
+test_at_ll_tl() -> case at() < tl() of true -> maybe; false -> maybe_too end.
+test_at_le_tl() -> case at() =< tl() of true -> maybe; false -> maybe_too end.
+test_at_gg_tl() -> case at() > tl() of true -> maybe; false -> maybe_too end.
+test_at_ge_tl() -> case at() >= tl() of true -> maybe; false -> maybe_too end.
+
+test_tl_ll_na() -> case tl() < na() of true -> never; false -> always end.
+test_tl_le_na() -> case tl() =< na() of true -> never; false -> always end.
+test_tl_gg_na() -> case tl() > na() of true -> always; false -> never end.
+test_tl_ge_na() -> case tl() >= na() of true -> always; false -> never end.
+test_tl_ll_at() -> case tl() < at() of true -> maybe; false -> maybe_too end.
+test_tl_le_at() -> case tl() =< at() of true -> maybe; false -> maybe_too end.
+test_tl_gg_at() -> case tl() > at() of true -> maybe; false -> maybe_too end.
+test_tl_ge_at() -> case tl() >= at() of true -> maybe; false -> maybe_too end.
+test_tl_ll_tl() -> case tl() < tl() of true -> maybe; false -> maybe_too end.
+test_tl_le_tl() -> case tl() =< tl() of true -> maybe; false -> maybe_too end.
+test_tl_gg_tl() -> case tl() > tl() of true -> maybe; false -> maybe_too end.
+test_tl_ge_tl() -> case tl() >= tl() of true -> maybe; false -> maybe_too end.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/failing_funs.erl b/lib/dialyzer/test/small_SUITE_data/src/failing_funs.erl
new file mode 100644
index 0000000000..1784c4a494
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/failing_funs.erl
@@ -0,0 +1,250 @@
+-module(failing_funs).
+
+-compile(export_all).
+
+% Crashes with system call. No spec.
+foo1() -> halt().
+
+% Crashes with system call. With spec.
+-spec foo2() -> no_return().
+foo2() -> halt().
+
+% Crashes on its own. No spec.
+foo3() -> case a of b -> ok end.
+
+% Crashes on its own. With spec.
+-spec foo4() -> no_return().
+foo4() -> case a of b -> ok end.
+
+% Creates fun that crashes with system call. No spec.
+foo5() -> fun() -> halt() end.
+
+% Creates fun that crashes with system call. With spec.
+-spec foo6() -> fun(() -> no_return()).
+foo6() -> fun() -> halt() end.
+
+% Creates fun from named fun that will crash. Neither have spec.
+foo7() -> fun foo1/0.
+
+% Creates fun from named fun that will crash. Has spec.
+-spec foo8() -> fun(() -> no_return()).
+foo8() -> fun foo1/0.
+
+% Creates fun from named fun that will crash. Named has spec.
+foo9() -> fun foo2/0.
+
+% Creates fun from named fun that will crash. Both have specs.
+-spec foo10() -> fun(() -> no_return()).
+foo10() -> fun foo2/0.
+
+% Creates fun from named fun that will crash. Neither have spec.
+foo11() -> fun foo3/0.
+
+% Creates fun from named fun that will crash. Has spec.
+-spec foo12() -> fun(() -> no_return()).
+foo12() -> fun foo3/0.
+
+% Creates fun from named fun that will crash. Named has spec.
+foo13() -> fun foo4/0.
+
+% Creates fun from named fun that will crash. Both have specs.
+-spec foo14() -> fun(() -> no_return()).
+foo14() -> fun foo4/0.
+
+% Creates fun calling a named fun that will crash. Neither have spec.
+foo15() -> fun() -> foo1() end.
+
+% Creates fun calling a named fun that will crash. Has spec.
+-spec foo16() -> fun(() -> no_return()).
+foo16() -> fun() -> foo1() end.
+
+% Creates fun calling a named fun that will crash. Named has spec.
+foo17() -> fun() -> foo2() end.
+
+% Creates fun calling a named fun that will crash. Both have specs.
+-spec foo18() -> fun(() -> no_return()).
+foo18() -> fun() -> foo2() end.
+
+% Creates fun calling a named fun that will crash. Neither have spec.
+foo19() -> fun() -> foo3() end.
+
+% Creates fun calling a named fun that will crash. Has spec.
+-spec foo20() -> fun(() -> no_return()).
+foo20() -> fun() -> foo3() end.
+
+% Creates fun calling a named fun that will crash. Named has spec.
+foo21() -> fun() -> foo4() end.
+
+% Creates fun calling a named fun that will crash. Both have specs.
+-spec foo22() -> fun(() -> no_return()).
+foo22() -> fun() -> foo4() end.
+
+% Creates two funs with no local return and will return one or die. No spec.
+foo23() ->
+ Bomb = fun() -> halt() end,
+ case get(42) of
+ a -> Bomb();
+ b -> fun() -> halt() end
+ end.
+
+% Creates two funs with no local return and will return one or die. With spec.
+-spec foo24() -> fun(() -> no_return()).
+foo24() ->
+ Bomb = fun() -> halt() end,
+ case get(42) of
+ a -> Bomb();
+ b -> fun() -> halt() end
+ end.
+
+% Creates two funs with no local return and will return one or die. No spec.
+foo25() ->
+ Bomb = fun() -> foo1() end,
+ case get(42) of
+ a -> Bomb();
+ b -> fun() -> foo1() end
+ end.
+
+% Creates two funs with no local return and will return one or die. With spec.
+-spec foo26() -> fun(() -> no_return()).
+foo26() ->
+ Bomb = fun foo1/0,
+ case get(42) of
+ a -> Bomb();
+ b -> fun foo1/0
+ end.
+
+% Creates two funs with no local return and will return one or die. No spec.
+foo27() ->
+ Bomb = fun foo1/0,
+ case get(42) of
+ a -> Bomb();
+ b -> fun foo1/0
+ end.
+
+% Creates two funs with no local return and will return one or die. With spec.
+-spec foo28() -> fun(() -> no_return()).
+foo28() ->
+ Bomb = fun() -> foo1() end,
+ case get(42) of
+ a -> Bomb();
+ b -> fun() -> foo1() end
+ end.
+
+% Creates two funs with no local return and will return one or die. No spec.
+foo29() ->
+ Bomb = fun() -> foo2() end,
+ case get(42) of
+ a -> Bomb();
+ b -> fun() -> foo2() end
+ end.
+
+% Creates two funs with no local return and will return one or die. With spec.
+-spec foo30() -> fun(() -> no_return()).
+foo30() ->
+ Bomb = fun foo2/0,
+ case get(42) of
+ a -> Bomb();
+ b -> fun foo2/0
+ end.
+
+% Creates two funs with no local return and will return one or die. No spec.
+foo31() ->
+ Bomb = fun foo2/0,
+ case get(42) of
+ a -> Bomb();
+ b -> fun foo2/0
+ end.
+
+% Creates two funs with no local return and will return one or die. With spec.
+-spec foo32() -> fun(() -> no_return()).
+foo32() ->
+ Bomb = fun() -> foo2() end,
+ case get(42) of
+ a -> Bomb();
+ b -> fun() -> foo2() end
+ end.
+
+% Creates two funs with no local return and will return one or die. No spec.
+foo33() ->
+ Bomb = fun() -> foo3() end,
+ case get(42) of
+ a -> Bomb();
+ b -> fun() -> foo3() end
+ end.
+
+% Creates two funs with no local return and will return one or die. With spec.
+-spec foo34() -> fun(() -> no_return()).
+foo34() ->
+ Bomb = fun foo3/0,
+ case get(42) of
+ a -> Bomb();
+ b -> fun foo3/0
+ end.
+
+% Creates two funs with no local return and will return one or die. No spec.
+foo35() ->
+ Bomb = fun foo3/0,
+ case get(42) of
+ a -> Bomb();
+ b -> fun foo3/0
+ end.
+
+% Creates two funs with no local return and will return one or die. With spec.
+-spec foo36() -> fun(() -> no_return()).
+foo36() ->
+ Bomb = fun() -> foo3() end,
+ case get(42) of
+ a -> Bomb();
+ b -> fun() -> foo3() end
+ end.
+
+% Creates two funs with no local return and will return one or die. No spec.
+foo37() ->
+ Bomb = fun() -> foo4() end,
+ case get(42) of
+ a -> Bomb();
+ b -> fun() -> foo4() end
+ end.
+
+% Creates two funs with no local return and will return one or die. With spec.
+-spec foo38() -> fun(() -> no_return()).
+foo38() ->
+ Bomb = fun foo4/0,
+ case get(42) of
+ a -> Bomb();
+ b -> fun foo4/0
+ end.
+
+% Creates two funs with no local return and will return one or die. No spec.
+foo39() ->
+ Bomb = fun foo4/0,
+ case get(42) of
+ a -> Bomb();
+ b -> fun foo4/0
+ end.
+
+% Creates two funs with no local return and will return one or die. With spec.
+-spec foo40() -> fun(() -> no_return()).
+foo40() ->
+ Bomb = fun() -> foo4() end,
+ case get(42) of
+ a -> Bomb();
+ b -> fun() -> foo4() end
+ end.
+
+% Obtains two funs with no local return and will return one or die. No spec.
+foo41() ->
+ Bomb = foo5(),
+ case get(42) of
+ a -> Bomb();
+ b -> foo5()
+ end.
+
+% Obtains two funs with no local return and will return one or die. With spec.
+-spec foo42() -> fun(() -> no_return()).
+foo42() ->
+ Bomb = foo5(),
+ case get(42) of
+ a -> Bomb();
+ b -> foo5()
+ end.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/file_open_encoding.erl b/lib/dialyzer/test/small_SUITE_data/src/file_open_encoding.erl
index 4f1268eba8..086df3464b 100644
--- a/lib/dialyzer/test/small_SUITE_data/src/file_open_encoding.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/file_open_encoding.erl
@@ -6,9 +6,7 @@
-export([parse/1]).
--type proplist() :: [{atom(), any()}].
-
--spec parse(string()) -> proplist().
+-spec parse(string()) -> proplists:proplist().
parse(FileName) ->
{ok, IoDevice} = file:open(FileName, [read, binary, {encoding, utf8}]),
do_parse(IoDevice, []).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/higher_order_discrepancy.erl b/lib/dialyzer/test/small_SUITE_data/src/higher_order_discrepancy.erl
new file mode 100644
index 0000000000..ff5ee6bac4
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/higher_order_discrepancy.erl
@@ -0,0 +1,14 @@
+-module(higher_order_discrepancy).
+
+-export([test/1]).
+
+test(X) ->
+ F =
+ case X of
+ 1 -> fun f/1;
+ 2 -> fun g/1
+ end,
+ F(foo).
+
+f(foo) -> ok.
+g(bar) -> ok.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/higher_order_discrepancy_2.erl b/lib/dialyzer/test/small_SUITE_data/src/higher_order_discrepancy_2.erl
new file mode 100644
index 0000000000..4b0d4f6b45
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/higher_order_discrepancy_2.erl
@@ -0,0 +1,14 @@
+-module(higher_order_discrepancy_2).
+
+-export([test/1]).
+
+test(X) ->
+ F =
+ case X of
+ 1 -> fun f/1;
+ 2 -> fun g/1
+ end,
+ F(foo).
+
+f(bar) -> ok.
+g(baz) -> ok.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/list_to_bitstring.erl b/lib/dialyzer/test/small_SUITE_data/src/list_to_bitstring.erl
new file mode 100644
index 0000000000..109aa88f16
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/list_to_bitstring.erl
@@ -0,0 +1,21 @@
+%%=====================================================================
+%% From: Ken Robinson
+%% Date: 28/04/2011, 17:26
+%%
+%% Program that produced bogus "Function has no local return" warnings
+%% due to erlang:list_to_bitstring/1 having erroneous hard coded type
+%% information, namely accepting iolist() instead of bitstrlist().
+%% Fixed 29/04/2011.
+%%=====================================================================
+
+-module(list_to_bitstring).
+
+-export([l2bs/0, l2bs_ok/0]).
+
+%% This function was producing a warning
+l2bs() ->
+ erlang:list_to_bitstring([<<42>>, <<42:13>>]).
+
+%% while this one was ok.
+l2bs_ok() ->
+ erlang:list_to_bitstring([<<42>>, <<42,42>>]).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/no_return_bug.erl b/lib/dialyzer/test/small_SUITE_data/src/no_return_bug.erl
new file mode 100644
index 0000000000..5c24902590
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/no_return_bug.erl
@@ -0,0 +1,42 @@
+%% Dialyzer couldn't infer that monitor_diskspace would go in an infinite loop
+%% instead of crashing due to the existence of list comprehensions that have a
+%% normal success typing. These were added to the monitor_diskspace's SCC and
+%% dialyzer_typesig didn't try to assign unit() to monitor_diskspace, as it
+%% required all the members of the SCC to return none().
+%%
+%% Testcase was submitted in erlang-questions mailing list by Prashanth Mundkur
+%% (http://erlang.org/pipermail/erlang-questions/2011-May/058063.html)
+
+-module(no_return_bug).
+-export([diskspace/1, monitor_diskspace/2, refresh_tags/1, monitor_launch/0]).
+
+-type diskinfo() :: {non_neg_integer(), non_neg_integer()}.
+
+-spec diskspace(nonempty_string()) -> {'ok', diskinfo()} | {'error', term()}.
+diskspace(Path) ->
+ case Path of
+ "a" -> {ok, {0,0}};
+ _ -> {error, error}
+ end.
+
+-spec monitor_diskspace(nonempty_string(),
+ [{diskinfo(), nonempty_string()}]) ->
+ no_return().
+monitor_diskspace(Root, Vols) ->
+ Df = fun(VolName) ->
+ diskspace(filename:join([Root, VolName]))
+ end,
+ NewVols = [{Space, VolName}
+ || {VolName, {ok, Space}}
+ <- [{VolName, Df(VolName)}
+ || {_OldSpace, VolName} <- Vols]],
+ monitor_diskspace(Root, NewVols).
+
+-spec refresh_tags(nonempty_string()) -> no_return().
+refresh_tags(Root) ->
+ {ok, _} = diskspace(Root),
+ refresh_tags(Root).
+
+monitor_launch() ->
+ spawn_link(fun() -> refresh_tags("abc") end),
+ spawn_link(fun() -> monitor_diskspace("root", [{{0,0}, "a"}]) end).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/nowarnunused.erl b/lib/dialyzer/test/small_SUITE_data/src/nowarnunused.erl
new file mode 100644
index 0000000000..63daeee9e3
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/nowarnunused.erl
@@ -0,0 +1,7 @@
+-module(nowarnunused).
+
+-compile({nowarn_unused_function, return_error/2}).
+
+-spec return_error(integer(), any()) -> no_return().
+return_error(Line, Message) ->
+ throw({error, {Line, ?MODULE, Message}}).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/rebar_no_return.erl b/lib/dialyzer/test/small_SUITE_data/src/rebar_no_return.erl
new file mode 100644
index 0000000000..d3b504ae04
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/rebar_no_return.erl
@@ -0,0 +1,19 @@
+-module(rebar_no_return).
+
+-export([t/0]).
+
+-spec t() -> no_return().
+t() ->
+ F = log_and_halt("baz"),
+ F("foo", 123).
+
+-spec log_and_halt(string()) -> fun((string(),integer()) -> no_return()).
+log_and_halt(Msg) ->
+ fun(_, _) ->
+ abort(Msg)
+ end.
+
+-spec abort(string()) -> no_return().
+abort(Msg) ->
+ io:format("~s~n", [Msg]),
+ halt(1).
diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk
index 10de07dfbb..a7e82b54ce 100644
--- a/lib/dialyzer/vsn.mk
+++ b/lib/dialyzer/vsn.mk
@@ -1 +1 @@
-DIALYZER_VSN = 2.4.3
+DIALYZER_VSN = 2.4.4
diff --git a/lib/diameter/bin/diameterc b/lib/diameter/bin/diameterc
index f5cf3ebc10..c0e83ea1a4 100755
--- a/lib/diameter/bin/diameterc
+++ b/lib/diameter/bin/diameterc
@@ -33,19 +33,24 @@
usage() ->
io:format(
- "~w [options] file~n"
+ "~w [options] dict~n"
"~n"
" Compile a diameter dictionary file (.dia) to Erlang source (.erl)~n"
" and/or header (.hrl) files.~n"
"~n"
" options:~n"
- " -h = print this message~n"
- " -v = verbose output~n"
- " -o dir = set the output directory (default .)~n"
- " -i dir = set an include directory for inherited beams~n"
- " -E = no .erl output~n"
- " -H = no .hrl output~n"
- " -d = write intermediate files (.spec and .forms)~n",
+ "~n"
+ " --name name = set @name~n"
+ " --prefix prefix = set @prefix~n"
+ " --inherits dict|- = set/clear @inherits~n"
+ "~n"
+ " -h = print this message~n"
+ " -v = verbose output~n"
+ " -o dir = set the output directory (default .)~n"
+ " -i dir = set an include directory for inherited beams~n"
+ " -E = no .erl output~n"
+ " -H = no .hrl output~n"
+ " -d = write intermediate files (.spec and .forms)~n",
[?MODULE]).
main(Args) ->
@@ -109,9 +114,17 @@ arg(["-o", Dir | Args], #argv{options = Opts} = A) ->
arg(Args, A#argv{options = [{outdir, Dir} | Opts]});
arg(["-i", Dir | Args], #argv{options = Opts} = A) ->
- true = dir_exists(Dir),
arg(Args, A#argv{options = Opts ++ [{include, Dir}]});
+arg(["--name", Name | Args], #argv{options = Opts} = A) ->
+ arg(Args, A#argv{options = [{name, Name} | Opts]});
+
+arg(["--prefix", Name | Args], #argv{options = Opts} = A) ->
+ arg(Args, A#argv{options = [{prefix, Name} | Opts]});
+
+arg(["--inherits", Dict | Args], #argv{options = Opts} = A) ->
+ arg(Args, A#argv{options = Opts ++ [{inherits, Dict}]});
+
arg(["-E" | Args], #argv{output = Output} = A) ->
arg(Args, A#argv{output = lists:delete(erl, Output)});
@@ -120,10 +133,10 @@ arg(["-H" | Args], #argv{output = Output} = A) ->
arg(["-d" | Args], #argv{options = Opts, output = Output} = A) ->
arg(Args, A#argv{options = [debug | Opts],
- output = [spec | Output]});
+ output = [spec | Output]});
arg([[$- = M, C, H | T] | Args], A) %% clustered options
- when C /= $i, C /= $o ->
+ when C /= $i, C /= $o, C /= $- ->
arg([[M,C], [M,H|T] | Args], A);
arg([File], A) ->
diff --git a/lib/diameter/configure.in b/lib/diameter/configure.in
index 9aca3859c5..8acfb28fed 100644
--- a/lib/diameter/configure.in
+++ b/lib/diameter/configure.in
@@ -132,7 +132,6 @@ dnl </STANDALONE DIAMETER>
AC_OUTPUT(
Makefile:Makefile.in
- src/app/diameter.mk:src/app/diameter.mk.in
make/$host/rules.mk:make/rules.mk.in
)
diff --git a/lib/diameter/doc/src/Makefile b/lib/diameter/doc/src/Makefile
index 1453138cb6..bc3e649e6b 100644
--- a/lib/diameter/doc/src/Makefile
+++ b/lib/diameter/doc/src/Makefile
@@ -126,8 +126,6 @@ debug opt:
info:
@echo "->Makefile<-"
@echo ""
- @echo "DOCSUPPORT = $(DOCSUPPORT)"
- @echo ""
@echo "INDEX_FILE = $(INDEX_FILE)"
@echo "INDEX_SRC = $(INDEX_SRC)"
@echo "INDEX_TARGET = $(INDEX_TARGET)"
@@ -141,10 +139,6 @@ info:
@echo ""
@echo "GIF_FILES = $(GIF_FILES)"
@echo ""
- @echo "TEX_FILES_USERS_GUIDE = $(TEX_FILES_USERS_GUIDE)"
- @echo "TEX_FILES_REF_MAN = $(TEX_FILES_REF_MAN)"
- @echo "TEX_FILES_BOOK = $(TEX_FILES_BOOK)"
- @echo ""
@echo "MAN1_FILES = $(MAN1_FILES)"
@echo "MAN3_FILES = $(MAN3_FILES)"
@echo "MAN4_FILES = $(MAN4_FILES)"
diff --git a/lib/diameter/doc/src/depend.sed b/lib/diameter/doc/src/depend.sed
index 5973c4586e..42de597f15 100644
--- a/lib/diameter/doc/src/depend.sed
+++ b/lib/diameter/doc/src/depend.sed
@@ -21,14 +21,18 @@
# massaged in Makefile.
#
-/^<com>\([^<]*\)<\/com>/b rf
-/^<module>\([^<]*\)<\/module>/b rf
+/^<com>/b c
+/^<module>/b c
/^<chapter>/!d
+# Chapter: html basename is same as xml.
s@@$(HTMLDIR)/%FILE%.html: %FILE%.xml@
q
-:rf
-s@@$(HTMLDIR)/\1.html: %FILE%.xml@
+# Reference: html basename is from contents of com/module element.
+:c
+s@^[^>]*>@@
+s@<.*@@
+s@.*@$(HTMLDIR)/&.html: %FILE%.xml@
q
diff --git a/lib/diameter/doc/src/diameter.xml b/lib/diameter/doc/src/diameter.xml
index 36b6cbf0cf..2d8edb1301 100644
--- a/lib/diameter/doc/src/diameter.xml
+++ b/lib/diameter/doc/src/diameter.xml
@@ -277,6 +277,10 @@ callback.</p>
</taglist>
+<p>
+An invalid option will cause <seealso marker="#call">call/4</seealso>
+to fail.</p>
+
<marker id="capability"/>
</item>
@@ -363,6 +367,19 @@ capabilities exchange message.
Optional, defaults to the empty list.</p>
</item>
+<tag><c>{'Inband-Security-Id', [Unsigned32()]}</c></tag>
+<item>
+<p>
+Values of Inband-Security-Id AVPs sent in an outgoing
+capabilities exchange message.
+Optional, defaults to the empty list, which is equivalent to a
+list containing only 0 (= NO_INBAND_SECURITY).</p>
+
+<p>
+If 1 (= TLS) is specified then TLS is selected if the CER/CEA received
+from the peer offers it.</p>
+</item>
+
<tag><c>{'Acct-Application-Id', [Unsigned32()]}</c></tag>
<item>
<p>
@@ -405,6 +422,8 @@ sense.</p>
<code>
eval([{M,F,A} | T]) ->
apply(M, F, T ++ A);
+eval([[F|A] | T]) ->
+ eval([F | T ++ A]);
eval([F|A]) ->
apply(F, A);
eval(F) ->
@@ -412,7 +431,7 @@ eval(F) ->
</code>
<p>
-Evaluating an evaluable() <c>E</c> on an argument list <c>A</c>
+Applying an evaluable() <c>E</c> to an argument list <c>A</c>
is meant in the sense of <c>eval([E|A])</c>.</p>
<p>
@@ -461,14 +480,14 @@ or any peer if the request does not contain
a <c>Destination-Realm</c> AVP.</p>
</item>
-<tag><c>{host, any|UTF8String()}</c></tag>
+<tag><c>{host, any|DiameterIdentity()}</c></tag>
<item>
<p>
Matches only those peers whose <c>Origin-Host</c> has the
specified value, or all peers if the atom <c>any</c>.</p>
</item>
-<tag><c>{realm, any|UTF8String()</c></tag>
+<tag><c>{realm, any|DiameterIdentity()</c></tag>
<item>
<p>
Matches only those peers whose <c>Origin-Realm</c> has the
@@ -478,8 +497,9 @@ value, or all peers if the atom <c>any</c>.</p>
<tag><c>{eval, evaluable()}</c></tag>
<item>
<p>
-Matches only those peers for which the specified evaluable() evaluates
-to true on the peer's <c>diameter_caps</c> record.</p>
+Matches only those peers for which the specified evaluable() returns
+<c>true</c> on the connection's <c>diameter_caps</c> record.
+Any other return value or exception is equivalent to <c>false</c>.</p>
</item>
<tag><c>{neg, peer_filter()}</c></tag>
@@ -503,6 +523,21 @@ specified list.</p>
</taglist>
+<p>
+Note that the <c>host</c> and <c>realm</c> filters examine the
+outgoing request as passed to <seealso marker="#call">call/4</seealso>,
+assuming that this is a record- or list-valued message() as documented
+in <seealso marker="diameter_app">diameter_app(3)</seealso>, and that
+the message contains at most one of each AVP.
+If this is not the case then the <c>{host|realm, DiameterIdentity()}</c>
+filters must be used to achieve the desired result.
+Note also that an empty host/realm (which should not be typical)
+is equivalent to an unspecified one for the purposes of filtering.</p>
+
+<p>
+An invalid filter is equivalent to <c>{any, []}</c>, a filter
+that matches no peer.</p>
+
<marker id="service_event"/>
</item>
@@ -530,7 +565,7 @@ Pkt = #diameter_packet{}
</code>
<p>
-Reports that the RFC 3539 watchdog state machine has
+The RFC 3539 watchdog state machine has
transitioned into (<c>up</c>) or out of (<c>down</c>) the open
state.
If a <c>diameter_packet</c> record is present in an <c>up</c> tuple
@@ -541,9 +576,9 @@ connectivity.</p>
<p>
Note that a single up/down event for a given peer corresponds to
-as many peer_up/down callbacks as there are Diameter
-applications shared by the peer, as determined during capablilities
-exchange.
+as many <seealso marker="diameter_app#peer_up">peer_up/peer_down</seealso>
+callbacks as there are Diameter applications shared by the peer,
+as determined during capablilities exchange.
That is, the event communicates connectivity with the
peer as a whole while the callbacks communicate connectivity with
respect to individual Diameter applications.</p>
@@ -562,12 +597,96 @@ transport connection with a peer following <c>reconnect_timer</c> or
<c>watchdog_timer</c> expiry.</p>
</item>
+<tag><c>{closed, Ref, Reason, Config}</c></tag>
+<item>
+<code>
+Ref = transport_ref()
+Config = {connect|listen, [transport_opt()]}
+</code>
+
+<p>
+Capabilities exchange has failed. <c>Reason</c> can be one of
+the following.</p>
+
+<taglist>
+
+<tag><c>{'CER', Result, Caps, Pkt}</c></tag>
+<item>
+<code>
+Result = ResultCode | {capabilities_cb, CB, ResultCode|discard}
+Caps = #diameter_caps{}
+Pkt = #diameter_packet{}
+ResultCode = integer()
+CB = evaluable()
+</code>
+
+<p>
+An incoming CER has been answered with the indicated result code or
+discarded.
+The capabilities record contains pairs of values for the the local
+node and remote peer.
+The packet record contains the CER in question.
+In the case of rejection by a capabilities callback, the tuple
+indicates the rejecting callback.</p>
+</item>
+
+<tag><c>{'CER', Caps, {ResultCode, Pkt}}</c></tag>
+<item>
+<code>
+ResultCode = integer()
+Caps = #diameter_caps{}
+Pkt = #diameter_packet{}
+</code>
+
+<p>
+An incoming CER contained errors and has been answered with the
+indicated result code.
+The capabilities record contains only values for the the local
+node.
+The packet record contains the CER in question.</p>
+</item>
+
+<tag><c>{'CEA', Result, Caps, Pkt}</c></tag>
+<item>
+<code>
+Result = integer() | atom() | {capabilities_cb, CB, ResultCode|discard}
+Caps = #diameter_caps{}
+Pkt = #diameter_packet{}
+ResultCode = integer()
+</code>
+
+<p>
+An incoming CEA has been rejected for the indicated reason.
+An integer-valued <c>Result</c> indicates the result code sent
+by the peer.
+The capabilities record contains pairs of values for the the local
+node and remote peer.
+The packet record contains the CEA in question.
+In the case of rejection by a capabilities callback, the tuple
+indicates the rejecting callback.</p>
+</item>
+
+<tag><c>{'CEA', Caps, Pkt}</c></tag>
+<item>
+<code>
+Caps = #diameter_caps{}
+Pkt = #diameter_packet{}
+</code>
+
+<p>
+An incoming CER contained errors and has been rejected.
+The capabilities record contains only values for the the local node.
+The packet record contains the CEA in question.</p>
+</item>
+
+</taglist>
+</item>
+
</taglist>
<p>
For forward compatibility, a subscriber should be prepared to receive
-<c>diameter_event.info</c> of forms other than those documented
-above.</p>
+info fields of forms other than the above.</p>
<marker id="service_name"/>
</item>
@@ -661,6 +780,39 @@ in question.</p>
AVP's used to construct outgoing CER/CEA messages.
Any AVP specified takes precedence over a corresponding value specified
for the service in question.</p>
+
+<p>
+Specifying a capability as a transport option
+may be particularly appropriate for Inband-Security-Id in case
+TLS is desired over TCP as implemented by
+<seealso marker="diameter_tcp">diameter_tcp(3)</seealso> but
+not over SCTP as implemented by
+<seealso marker="diameter_sctp">diameter_sctp(3)</seealso>.</p>
+</item>
+
+<tag><c>{capabilities_cb, evaluable()}</c></tag>
+<item>
+<p>
+A callback invoked upon reception of CER/CEA during capabilities
+exchange in order to ask whether or not the connection should
+be accepted.
+Applied to the transport reference (as returned by <seealso
+marker="#add_transport">add_transport/2</seealso>) and
+<c>diameter_caps</c> record of the connection.
+Returning <c>ok</c> accepts the connection.
+Returning <c>integer()</c> causes an incoming
+CER to be answered with the specified Result-Code.
+Returning <c>discard</c> causes an incoming CER to
+be discarded.
+Returning <c>unknown</c> is equivalent to returning <c>3010</c>,
+DIAMETER_UNKNOWN_PEER.
+Returning anything but <c>ok</c> or a 2xxx series result
+code causes the transport connection to be broken.</p>
+
+<p>
+Multiple <c>capabilities_cb</c> options can be specified, in which
+case the corresponding callbacks are applied until either all return
+<c>ok</c> or one does not.</p>
</item>
<tag><c>{watchdog_timer, TwInit}</c></tag>
@@ -787,7 +939,7 @@ transports.</p>
<type>
<v>SvcName = service_name()</v>
<v>App = application_alias()</v>
-<v>Request = diameter_app:message()</v>
+<v>Request = diameter_app:message() | term()</v>
<v>Answer = term()</v>
<v>Options = [call_opt()]</v>
</type>
@@ -819,9 +971,8 @@ If there are no suitable peers, or if
<seealso marker="diameter_app#pick_peer">pick_peer/4</seealso>
rejects them by returning 'false', then <c>{error, no_connection}</c>
is returned.
-If <seealso marker="diameter_app#pick_peer">pick_peer/4</seealso>
-selects a candidate peer then a request process is spawned for the
-outgoing request, in which there is a
+Otherwise <seealso marker="diameter_app#pick_peer">pick_peer/4</seealso>
+is followed by a
<seealso
marker="diameter_app#prepare_request">prepare_request/3</seealso>
callback, the message is encoded and sent.</p>
diff --git a/lib/diameter/doc/src/diameter_app.xml b/lib/diameter/doc/src/diameter_app.xml
index fc359b9d1d..a9ae0ebbec 100644
--- a/lib/diameter/doc/src/diameter_app.xml
+++ b/lib/diameter/doc/src/diameter_app.xml
@@ -269,7 +269,12 @@ The candidate peers list will only include those
which are selected by any <c>filter</c> option specified in the call to
<seealso marker="diameter#call">diameter:call/4</seealso>, and only
those which have indicated support for the Diameter application in
-question.</p>
+question.
+The order of the elements is unspecified except that any
+peers whose Origin-Host and Origin-Realm matches that of the
+outgoing request (in the sense of a <c>{filter, {all, [host, realm]}}</c>
+option to <seealso marker="diameter#call">diameter:call/4</seealso>)
+will be placed at the head of the list.</p>
<p>
The return values <c>false</c> and <c>{false, State}</c> are
@@ -467,11 +472,11 @@ callback returned false.</p>
<v>Packet = packet()</v>
<v>SvcName = term()</v>
<v>Peer = peer()</v>
-<v>Action = Reply | {relay, Opts} | discard | {eval, Action, ContF}</v>
+<v>Action = Reply | {relay, Opts} | discard | {eval, Action, PostF}</v>
<v>Reply = {reply, message()}
| {protocol_error, 3000..3999}</v>
<v>Opts = diameter:call_opts()</v>
-<v>ContF = diameter:evaluable()</v>
+<v>PostF = diameter:evaluable()</v>
</type>
<desc>
<p>
@@ -559,26 +564,28 @@ will cause the request process in question to fail.</p>
<tag><c>{relay, Opts}</c></tag>
<item>
<p>
-Relay a request to another peer.
-The appropriate Route-Record AVP will be added to the relayed request
-by diameter and <seealso marker="#pick_peer">pick_peer/4</seealso>
-and <seealso marker="#prepare_request">prepare_request/3</seealso>
-callback will take place just as if <seealso
+Relay a request to another peer in the role of a Diameter relay agent.
+If a routing loop is detected then the request is answered with
+3005 (DIAMETER_LOOP_DETECTED).
+Otherwise a Route-Record AVP (containing the sending peer's Origin-Host) is
+added to the request and <seealso marker="#pick_peer">pick_peer/4</seealso>
+and subsequent callbacks take place just as if <seealso
marker="diameter#call">diameter:call/4</seealso> had been called
explicitly.
-However, returning a <c>relay</c> tuple also causes the End-to-End
-Identifier to be preserved in the header of the relayed request as
-required by RFC 3588.</p>
+The End-to-End Identifier of the incoming request is preserved in the
+header of the relayed request.</p>
<p>
-The returned <c>Opts</c> should not specify <c>detach</c> and
-the <seealso marker="#handle_answer">handle_answer/4</seealso>
-callback following from a relayed request must return its first
+The returned <c>Opts</c> should not specify <c>detach</c>.
+A subsequent <seealso marker="#handle_answer">handle_answer/4</seealso>
+callback for the relayed request must return its first
argument, the <c>diameter_packet</c> record containing the answer
message.
Note that the <c>extra</c> option can be specified to supply arguments
-that can distinguish the relay case from others if so desired,
-although the form of the request message may be sufficient.</p>
+that can distinguish the relay case from others if so desired.
+Any other return value (for example, from a
+<seealso marker="#handle_error">handle_error/4</seealso> callback)
+causes the request to be answered with 3002 (DIAMETER_UNABLE_TO_DELIVER).</p>
</item>
<tag><c>discard</c></tag>
@@ -587,18 +594,18 @@ although the form of the request message may be sufficient.</p>
Discard the request.</p>
</item>
-<tag><c>{eval, Action, ContF}</c></tag>
+<tag><c>{eval, Action, PostF}</c></tag>
<item>
<p>
Handle the request as if <c>Action</c> has been returned and then
-evaluate <c>ContF</c> in the request process.</p>
+evaluate <c>PostF</c> in the request process.</p>
</item>
</taglist>
<p>
-Note that diameter will respond to protocol errors in an incoming
-request without invoking <c>handle_request/3</c>.</p>
+Note that protocol errors detected by diameter will result in an
+answer message without <c>handle_request/3</c> being invoked.</p>
</desc>
</func>
diff --git a/lib/diameter/doc/src/diameter_compile.xml b/lib/diameter/doc/src/diameter_compile.xml
index 72bac30709..60e08d41da 100644
--- a/lib/diameter/doc/src/diameter_compile.xml
+++ b/lib/diameter/doc/src/diameter_compile.xml
@@ -64,9 +64,10 @@ Defaults to the current working directory.</p>
<item>
<p>
Specifies a directory to add to the code path.
-Typically used to point at beam files corresponding to dictionaries
-included by the one being compiled (using the <c>@includes</c> directive):
-inclusion is a beam dependency, not an erl/hrl dependency.</p>
+Use to point at beam files corresponding to dictionaries
+inherited by the one being compiled using <c>@inherits</c> or
+<c>--inherits</c>.
+Inheritance is a beam dependency, not an erl/hrl dependency.</p>
<p>
Multiple <c>-i</c> options can be specified.</p>
@@ -84,6 +85,31 @@ Supresses erl generation.</p>
Supresses hrl generation.</p>
</item>
+<tag><![CDATA[--name <name>]]></tag>
+<item>
+<p>
+Set <c>@name</c> in the dictionary file.
+Overrides any setting in the file itself.</p>
+</item>
+
+<tag><![CDATA[--prefix <prefix>]]></tag>
+<item>
+<p>
+Set <c>@prefix</c> in the dictionary file.
+Overrides any setting in the file itself.</p>
+</item>
+
+<tag><![CDATA[--inherits <dict>]]></tag>
+<item>
+<p>
+Append an <c>@inherits</c> to the dictionary file.
+Specifying <c>'-'</c> as the dictionary has the effect of clearing
+any previous inherits, effectively ignoring previous inherits.</p>
+
+<p>
+Multiple <c>--inherits</c> options can be specified.</p>
+</item>
+
</taglist>
</item>
diff --git a/lib/diameter/doc/src/diameter_dict.xml b/lib/diameter/doc/src/diameter_dict.xml
index a87f59bad5..e7c530f1b8 100644
--- a/lib/diameter/doc/src/diameter_dict.xml
+++ b/lib/diameter/doc/src/diameter_dict.xml
@@ -105,7 +105,7 @@ quantity is insignificant.</p>
<p>
The tags, their arguments and the contents of each corresponding
section are as follows.
-Each section can occur only once unless otherwise specified.
+Each section can occur at most once unless otherwise specified.
The order in which sections are specified is unimportant.</p>
<taglist>
@@ -115,6 +115,7 @@ The order in which sections are specified is unimportant.</p>
<p>
Defines the integer Number as the Diameter Application Id of the
application in question.
+Required if the dictionary defines <c>@messages</c>.
The section has empty content.</p>
<p>
@@ -370,7 +371,11 @@ Integer values can be prefixed with 0x to be interpreted as
hexidecimal.</p>
<p>
-Can occur 0 or more times (with different values of Name).</p>
+Can occur 0 or more times (with different values of Name).
+The AVP in question can be defined in an inherited dictionary in order
+to introduce additional values.
+An AVP so extended must be referenced by in a <c>@messages</c> or
+<c>@grouped</c> section.</p>
<p>
Example:</p>
diff --git a/lib/diameter/doc/src/diameter_sctp.xml b/lib/diameter/doc/src/diameter_sctp.xml
index d0377f4b38..c1e839b8e1 100644
--- a/lib/diameter/doc/src/diameter_sctp.xml
+++ b/lib/diameter/doc/src/diameter_sctp.xml
@@ -74,11 +74,12 @@ marker="diameter_transport#start">diameter_transport(3)</seealso>.</p>
<p>
The only diameter_sctp-specific argument is the options list.
Options <c>raddr</c> and <c>rport</c> specify the remote address
-and port for a connector and not valid for a listener.
+and port for a connecting transport and not valid for a listening
+transport.
The former is required while latter defaults to 3868 if unspecified.
More than one <c>raddr</c> option can be specified, in which case the
-connector in question attempts each in sequence until an association
-is established.
+connecting transport in question attempts each in sequence until
+an association is established.
Remaining options are any accepted by gen_sctp:open/1, with the exception
of options <c>mode</c>, <c>binary</c>, <c>list</c>, <c>active</c>
and <c>sctp_events</c>.
@@ -89,7 +90,8 @@ and port respectively.</p>
Multiple <c>ip</c> options can be specified for a multihomed peer.
If none are specified then the values of Host-IP-Address
on the service are used. (In particular, one of these must be specified.)
-Option <c>port</c> defaults to 3868 for a listener and 0 for a connector.</p>
+Option <c>port</c> defaults to 3868 for a listening transport and 0 for a
+connecting transport.</p>
<p>
diameter_sctp uses the <c>transport_data</c> field of
diff --git a/lib/diameter/doc/src/diameter_soc.xml b/lib/diameter/doc/src/diameter_soc.xml
index 4f8581a904..6b9ef9f756 100644
--- a/lib/diameter/doc/src/diameter_soc.xml
+++ b/lib/diameter/doc/src/diameter_soc.xml
@@ -57,9 +57,13 @@ including the P Flag in the AVP header.</p>
<item>
<p>
-There is no TLS support.
-It's unclear (aka uninvestigated) how TLS would impact
-diameter but IPsec can be used without it needing to know.</p>
+There is no TLS support over SCTP.
+RFC 3588 requires that a Diameter server support TLS but in
+practise this seems to mean TLS over SCTP since there are limitations
+with running over SCTP: see RFC 6083 (DTLS over SCTP), which is a
+response to RFC 3436 (TLS over SCTP).
+The current RFC 3588 draft acknowledges this by equating
+TLS with TLS/TCP and DTLS/SCTP but we do not yet support DTLS.</p>
</item>
<item>
diff --git a/lib/diameter/doc/src/diameter_tcp.xml b/lib/diameter/doc/src/diameter_tcp.xml
index 5d6e07b1b8..e6b53383c0 100644
--- a/lib/diameter/doc/src/diameter_tcp.xml
+++ b/lib/diameter/doc/src/diameter_tcp.xml
@@ -43,7 +43,14 @@ It can be specified as the value of a transport_module option to
<seealso
marker="diameter#add_transport">diameter:add_transport/2</seealso>
and implements the behaviour documented in
-<seealso marker="diameter_transport">diameter_transport(3)</seealso>.</p>
+<seealso marker="diameter_transport">diameter_transport(3)</seealso>.
+TLS security is supported, both as an upgrade following
+capabilities exchange as specified by RFC 3588 and
+at connection establishment as in the current draft standard.</p>
+
+<p>
+Note that the ssl application is required for TLS and must be started
+before configuring TLS capability on diameter transports.</p>
<marker id="start"/>
</description>
@@ -60,10 +67,15 @@ and implements the behaviour documented in
<v>Type = connect | accept</v>
<v>Ref = reference()</v>
<v>Svc = #diameter_service{}</v>
-<v>Opt = {raddr, ip_address()} | {rport, integer()} | term()</v>
+<v>Opt = OwnOpt | SslOpt | OtherOpt</v>
<v>Pid = pid()</v>
<v>LAddr = ip_address()</v>
<v>Reason = term()</v>
+<v>OwnOpt = {raddr, ip_address()}
+ | {rport, integer()}
+ | {port, integer()}</v>
+<v>SslOpt = {ssl_options, true | list()}</v>
+<v>OtherOpt = term()</v>
</type>
<desc>
@@ -74,16 +86,42 @@ marker="diameter_transport#start">diameter_transport(3)</seealso>.</p>
<p>
The only diameter_tcp-specific argument is the options list.
Options <c>raddr</c> and <c>rport</c> specify the remote address
-and port for a connector and not valid for a listener.
-Remaining options are any accepted by gen_tcp:connect/3 for
-a connector, or gen_tcp:listen/2 for a listener, with the exception
-of <c>binary</c>, <c>packet</c> and <c>active</c>.
-Also, option <c>port</c> can be specified for a listener to specify the
-local listening port, the default being the standardized 3868 if
-unspecified.
+and port for a connecting transport and are not valid for a listening
+transport.
+Option <c>ssl_options</c> must be specified for a transport
+that must be able to support TLS: a value of <c>true</c> results in a
+TLS handshake immediately upon connection establishment while
+list() specifies options to be passed to ssl:connect/2 of ssl:ssl_accept/2
+after capabilities exchange if TLS is negotiated.
+Remaining options are any accepted by ssl:connect/3 or gen_tcp:connect/3 for
+a connecting transport, or ssl:listen/3 or gen_tcp:listen/2 for
+a listening transport, depending on whether or not <c>{ssl_options, true}</c>
+has been specified.
+Options <c>binary</c>, <c>packet</c> and <c>active</c> cannot be specified.
+Also, option <c>port</c> can be specified for a listening transport
+to specify the local listening port, the default being the standardized
+3868 if unspecified.
Note that option <c>ip</c> specifies the local address.</p>
<p>
+An <c>ssl_options</c> list must be specified if and only if
+the transport in question has specified an Inband-Security-Id
+AVP with value TLS on the relevant call to
+<seealso
+marker="diameter#start_service">start_service/2</seealso> or
+<seealso
+marker="diameter#add_transport">add_transport/2</seealso>,
+so that the transport process will receive notification of
+whether or not to commence with a TLS handshake following capabilities
+exchange.
+Failing to specify an options list on a TLS-capable transport
+for which TLS is negotiated will cause TLS handshake to fail.
+Failing to specify TLS capability when <c>ssl_options</c> has been
+specified will cause the transport process to wait for a notification
+that will not be forthcoming, which will eventually cause the RFC 3539
+watchdog to take down the connection.</p>
+
+<p>
If the service specifies more than one Host-IP-Address and
option <c>ip</c> is unspecified then then the
first of the service's addresses is used as the local address.</p>
@@ -103,6 +141,7 @@ The returned local address list has length one.</p>
<title>SEE ALSO</title>
<p>
+<seealso marker="diameter">diameter(3)</seealso>,
<seealso marker="diameter_transport">diameter_transport(3)</seealso></p>
</section>
diff --git a/lib/diameter/doc/src/diameter_transport.xml b/lib/diameter/doc/src/diameter_transport.xml
index 37cc871e75..087a90b099 100644
--- a/lib/diameter/doc/src/diameter_transport.xml
+++ b/lib/diameter/doc/src/diameter_transport.xml
@@ -143,6 +143,34 @@ connection.
Pid is the pid() of the parent process.</p>
</item>
+<tag><c>{diameter, {tls, Ref, Type, Bool}}</c></tag>
+<item>
+<p>
+Indication of whether or not capabilities exchange has selected
+inband security using TLS.
+Ref is a reference() that must be included in the
+<c>{diameter, {tls, Ref}}</c> reply message to the transport's
+parent process (see below).
+Type is either <c>connect</c> or <c>accept</c> depending on
+whether the process has been started for a connecting or listening
+transport respectively.
+Bool is a boolean() indicating whether or not the transport connection
+should be upgraded to TLS.</p>
+
+<p>
+If TLS is requested (Bool = true) then a connecting process should
+initiate a TLS handshake with the peer and an accepting process should
+prepare to accept a handshake.
+A successful handshake should be followed by a <c>{diameter, {tls, Ref}}</c>
+message to the parent process.
+A failed handshake should cause the process to exit.</p>
+
+<p>
+This message is only sent to a transport process over whose
+<c>Inband-Security-Id</c> configuration has indicated support for
+TLS.</p>
+</item>
+
</taglist>
<p>
@@ -184,6 +212,16 @@ How the <c>transport_data</c> is used/interpreted is up to the
transport module.</p>
</item>
+<tag><c>{diameter, {tls, Ref}}</c></tag>
+<item>
+<p>
+Acknowledgment of a successful TLS handshake.
+Ref is the reference() received in the
+<c>{diameter, {tls, Ref, Type, Bool}}</c> message in response
+to which the reply is sent.
+A transport must exit if a handshake is not successful.</p>
+</item>
+
</taglist>
</section>
diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml
index eafddd7d1e..e2723f3e99 100644
--- a/lib/diameter/doc/src/notes.xml
+++ b/lib/diameter/doc/src/notes.xml
@@ -36,6 +36,135 @@ first.</p>
<!-- ===================================================================== -->
+<section><title>Diameter 0.10</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Handle #sctp_paddr_change and #sctp_pdapi_event from
+ gen_sctp.</p>
+ <p>
+ The events are enabled by default but diameter_sctp
+ neither disabled nor dealt with them. Reception of such
+ an event caused a transport process to crash.</p>
+ <p>
+ Own Id: OTP-9538</p>
+ </item>
+ <item>
+ <p>
+ Fix header folding bug.</p>
+ <p>
+ A prepare_request callback from diameter can return a
+ diameter_header record in order to set values in the
+ header of an outgoing request. A fault in
+ diameter_lib:fold_tuple/3 caused the subsequent encode of
+ the outgoing request to fail.</p>
+ <p>
+ Own Id: OTP-9577</p>
+ </item>
+ <item>
+ <p>
+ Fix bugs in sending of answer-message replies.</p>
+ <p>
+ 3001 (DIAMETER_COMMAND_UNSUPPORTED) was not sent since
+ the decode placed the AVP list in the wrong field of the
+ diameter_packet, causing the subsequent encode to fail.
+ Session-Id was also set improperly, causing encode to
+ fail even in this case.</p>
+ <p>
+ Own Id: OTP-9578</p>
+ </item>
+ <item>
+ <p>
+ Fix improper use of error_logger:info_report/2.</p>
+ <p>
+ Function doesn't take a format string and arguments as it
+ was called. Instead use error_logger:info_report/1 and
+ use the same report format as used for warning and error
+ reports.</p>
+ <p>
+ Own Id: OTP-9579</p>
+ </item>
+ <item>
+ <p>
+ Fix and clarify semantics of peer filters.</p>
+ <p>
+ An eval filter returning a non-true value caused the call
+ process to fail and the doc was vague on how an exception
+ was treated. Clarify that the non-tuple host/realm
+ filters assume messages of a certain form.</p>
+ <p>
+ Own Id: OTP-9580</p>
+ </item>
+ <item>
+ <p>
+ Fix and clarify relay behaviour.</p>
+ <p>
+ Implicit filtering of the sending peer in relaying a
+ request could cause loop detection to be preempted in a
+ manner not specified by RFC3588. Reply with 3002
+ (DIAMETER_UNABLE_TO_DELIVER) on anything but an answer to
+ a relayed request.</p>
+ <p>
+ Own Id: OTP-9583</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ @id required in dictionary files only when @messages is
+ specified.</p>
+ <p>
+ @id defines an application identifier and this is used
+ only when sending or receiving messages. A dictionary can
+ define only AVP's however, to be included by other
+ dictionaries using @inherits, in which case it makes no
+ sense to require @id.</p>
+ <p>
+ Note that message definitions are not inherited with
+ @inherits, only AVP's</p>
+ <p>
+ Own Id: OTP-9467</p>
+ </item>
+ <item>
+ <p>
+ Allow @enum when AVP is defined in an inherited
+ dictionary.</p>
+ <p>
+ 3GPP standards (for one) extend the values allowed for
+ RFC 3588 AVP's of type Enumerated. Previously, extending
+ an AVP was only possible by completely redefining the
+ AVP.</p>
+ <p>
+ Own Id: OTP-9469</p>
+ </item>
+ <item>
+ <p>
+ Migrate testsuites to pure common test and add both
+ suites and testcases.</p>
+ <p>
+ Own Id: OTP-9553</p>
+ </item>
+ <item>
+ <p>
+ Requests of arbitrary form.</p>
+ <p>
+ diameter:call/4 can be passed anything, as long as the
+ subsequent prepare_request callback returns a term that
+ can be encoded.</p>
+ <p>
+ Own Id: OTP-9581</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section>
<title>diameter 0.9</title>
diff --git a/lib/diameter/include/diameter_gen.hrl b/lib/diameter/include/diameter_gen.hrl
index 4c91954a21..13a6c462af 100644
--- a/lib/diameter/include/diameter_gen.hrl
+++ b/lib/diameter/include/diameter_gen.hrl
@@ -40,18 +40,18 @@ encode_avps(Name, Rec) ->
list_to_binary(encode(Name, Rec))
catch
throw: {?MODULE, Reason} ->
- diameter_dbg:log({encode, error},
+ diameter_lib:log({encode, error},
?MODULE,
?LINE,
{Reason, Name, Rec}),
- erlang:error(list_to_tuple(Reason ++ [Name, Rec, ?MODULE]));
+ erlang:error(list_to_tuple(Reason ++ [Name]));
error: Reason ->
Stack = erlang:get_stacktrace(),
- diameter_dbg:log({encode, failure},
+ diameter_lib:log({encode, failure},
?MODULE,
?LINE,
{Reason, Name, Rec, Stack}),
- erlang:error({encode_failure, Reason, Name, Rec, ?MODULE, Stack})
+ erlang:error({encode_failure, Reason, Name, Stack})
end.
%% encode/2
@@ -159,7 +159,7 @@ d_rc(Name, {Avps, {Rec, [] = Failed}}) ->
{Rec, Avps, Failed}
catch
throw: {?MODULE, {AvpName, Reason}} ->
- diameter_dbg:log({decode, error},
+ diameter_lib:log({decode, error},
?MODULE,
?LINE,
{AvpName, Reason, Rec}),
@@ -260,7 +260,7 @@ d(Name, Avp, {Avps, Acc}) ->
%% respond sensibly to. Log the occurence for traceability,
%% but the peer will also receive info in the resulting
%% answer-message.
- diameter_dbg:log({decode, failure},
+ diameter_lib:log({decode, failure},
?MODULE,
?LINE,
{Reason, Avp, erlang:get_stacktrace()}),
diff --git a/lib/diameter/make/rules.mk.in b/lib/diameter/make/rules.mk.in
index 4a1a55b8d3..cd3c297d75 100644
--- a/lib/diameter/make/rules.mk.in
+++ b/lib/diameter/make/rules.mk.in
@@ -112,8 +112,6 @@ $(EBIN)/%.beam: $(ESRC)/%.erl
# ----------------------------------------------------
# export VSN
-# DOCSUPPORT = 1
-
# TOPDOCDIR=../../../../doc
DOCDIR = ..
@@ -164,7 +162,7 @@ $(MAN3DIR)/%.3:: %.xml
date=`date +"%B %e %Y"`; \
xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude -path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_man_entities $(DOCGEN)/priv/xsl/db_man.xsl $<
-# left for compatability
+# left for compatibility
$(MAN4DIR)/%.4:: %.xml
date=`date +"%B %e %Y"`; \
xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude -path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_man_entities $(DOCGEN)/priv/xsl/db_man.xsl $<
@@ -173,7 +171,7 @@ $(MAN4DIR)/%.5:: %.xml
date=`date +"%B %e %Y"`; \
xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude -path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_man_entities $(DOCGEN)/priv/xsl/db_man.xsl $<
-# left for compatability
+# left for compatibility
$(MAN6DIR)/%.6:: %_app.xml
date=`date +"%B %e %Y"`; \
xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude -path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_man_entities $(DOCGEN)/priv/xsl/db_man.xsl $<
diff --git a/lib/diameter/src/compiler/.gitignore b/lib/diameter/src/.gitignore
index d9f072e262..feeb378fd8 100644
--- a/lib/diameter/src/compiler/.gitignore
+++ b/lib/diameter/src/.gitignore
@@ -1,3 +1,2 @@
/depend.mk
-
diff --git a/lib/diameter/src/Makefile b/lib/diameter/src/Makefile
index 6935eb053e..eea2aa894d 100644
--- a/lib/diameter/src/Makefile
+++ b/lib/diameter/src/Makefile
@@ -16,28 +16,225 @@
#
# %CopyrightEnd%
-ifneq ($(ERL_TOP),)
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-else
+ifeq ($(ERL_TOP),)
include $(DIAMETER_TOP)/make/target.mk
include $(DIAMETER_TOP)/make/$(TARGET)/rules.mk
+else
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
endif
# ----------------------------------------------------
-# Common Macros
+# Application version
# ----------------------------------------------------
-include subdirs.mk
+include ../vsn.mk
-SPECIAL_TARGETS =
+VSN = $(DIAMETER_VSN)
# ----------------------------------------------------
-# Default Subdir Targets
+# Release directory specification
# ----------------------------------------------------
-ifneq ($(ERL_TOP),)
-include $(ERL_TOP)/make/otp_subdir.mk
+
+RELSYSDIR = $(RELEASE_PATH)/lib/diameter-$(VSN)
+
+# Where to put/find things.
+EBIN = ../ebin
+INCDIR = ../include
+
+# Dumbed down to make 3.80. In 3.81 and later it's just $(realpath $(EBIN)).
+ABS_EBIN := $(shell cd $(EBIN) && pwd)
+
+# Where make should look for dependencies.
+VPATH = .:base:compiler:transport:gen
+
+# ----------------------------------------------------
+# Target specs
+# ----------------------------------------------------
+
+include modules.mk
+
+DICT_MODULES = $(DICTS:%=gen/diameter_gen_%)
+DICT_ERLS = $(DICT_MODULES:%=%.erl)
+DICT_HRLS = $(DICT_MODULES:%=%.hrl)
+
+# Modules to build before compiling dictionaries.
+COMPILER_MODULES = $(filter compiler/%, $(CT_MODULES))
+
+# All handwritten modules.
+MODULES = \
+ $(RT_MODULES) \
+ $(CT_MODULES)
+
+# Modules whose names are inserted into the app file.
+APP_MODULES = \
+ $(RT_MODULES) \
+ $(DICT_MODULES)
+
+# Modules for which to build beams.
+TARGET_MODULES = \
+ $(APP_MODULES) \
+ $(CT_MODULES)
+
+# What to build for the 'opt' target.
+TARGET_FILES = \
+ $(patsubst %,$(EBIN)/%.$(EMULATOR),$(notdir $(TARGET_MODULES))) \
+ $(APP_TARGET) \
+ $(APPUP_TARGET)
+
+# Subdirectories of src to release modules into.
+TARGET_DIRS = $(sort $(dir $(TARGET_MODULES)))
+
+APP_FILE = diameter.app
+APP_SRC = $(APP_FILE).src
+APP_TARGET = $(EBIN)/$(APP_FILE)
+
+APPUP_FILE = diameter.appup
+APPUP_SRC = $(APPUP_FILE).src
+APPUP_TARGET = $(EBIN)/$(APPUP_FILE)
+
+# ----------------------------------------------------
+# Flags
+# ----------------------------------------------------
+
+ifeq ($(TYPE),debug)
+ERL_COMPILE_FLAGS += -Ddebug
+endif
+
+ERL_COMPILE_FLAGS += \
+ +'{parse_transform,sys_pre_attributes}' \
+ +'{attribute,insert,app_vsn,$(APP_VSN)}' \
+ +warn_export_vars \
+ +warn_unused_vars \
+ -pa $(ABS_EBIN) \
+ -I $(INCDIR) \
+ -I gen
+# -pa is to be able to include_lib from the include directory: the
+# path must contain the application name.
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+# erl/hrl from dictionary file.
+gen/diameter_gen_%.erl gen/diameter_gen_%.hrl: dict/%.dia
+ ../bin/diameterc -o gen -i $(EBIN) $<
+
+opt: $(TARGET_FILES)
+
+debug:
+ @$(MAKE) TYPE=debug opt
+
+# Generate the app file.
+$(APP_TARGET): $(APP_SRC) ../vsn.mk modules.mk
+ M=`echo $(notdir $(APP_MODULES)) | tr ' ' ,`; \
+ sed -e 's;%VSN%;$(VSN);' \
+ -e "s;%MODULES%;$$M;" \
+ $< > $@
+
+$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
+ sed -e 's;%VSN%;$(VSN);' $< > $@
+
+app: $(APP_TARGET) $(APPUP_TARGET)
+dict: $(DICT_ERLS)
+
+docs:
+
+list = echo $(1):; echo $($(1)) | tr ' ' '\n' | sort | sed 's@^@ @'
+
+info:
+ @echo ========================================
+ @$(call list,DICTS)
+ @echo
+ @$(call list,RT_MODULES)
+ @echo
+ @$(call list,CT_MODULES)
+ @echo
+ @$(call list,TARGET_MODULES)
+ @echo
+ @$(call list,TARGET_DIRS)
+ @echo
+ @$(call list,EXTERNAL_HRLS)
+ @echo
+ @$(call list,INTERNAL_HRLS)
+ @echo
+ @$(call list,EXAMPLES)
+ @echo
+ @$(call list,BINS)
+ @echo ========================================
+
+clean:
+ rm -f $(TARGET_FILES) $(DICT_ERLS) $(DICT_HRLS)
+ rm -f depend.mk
+
+# ----------------------------------------------------
+# Release targets
+# ----------------------------------------------------
+
+ifeq ($(ERL_TOP),)
+include $(DIAMETER_TOP)/make/release_targets.mk
else
-include $(DIAMETER_TOP)/make/subdir.mk
+include $(ERL_TOP)/make/otp_release_targets.mk
endif
-#include ../make/subdir.mk
+
+# Can't $(INSTALL_DIR) more than one directory at a time on Solaris.
+
+release_spec: opt
+ for d in bin ebin examples include src/dict $(TARGET_DIRS:%/=src/%); do \
+ $(INSTALL_DIR) $(RELSYSDIR)/$$d; \
+ done
+ $(INSTALL_SCRIPT) $(BINS:%=../bin/%) $(RELSYSDIR)/bin
+ $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DATA) $(EXAMPLES:%=../examples/%) $(RELSYSDIR)/examples
+ $(INSTALL_DATA) $(EXTERNAL_HRLS:%=../include/%) $(DICT_HRLS) \
+ $(RELSYSDIR)/include
+ $(INSTALL_DATA) $(DICTS:%=dict/%.dia) $(RELSYSDIR)/src/dict
+ $(MAKE) $(TARGET_DIRS:%/=release_src_%)
+
+$(TARGET_DIRS:%/=release_src_%): release_src_%:
+ $(INSTALL_DATA) $(filter $*/%,$(TARGET_MODULES:%=%.erl) \
+ $(INTERNAL_HRLS)) \
+ $(RELSYSDIR)/src/$*
+
+release_docs_spec:
+
+# ----------------------------------------------------
+# Dependencies
+# ----------------------------------------------------
+
+gen/diameter_gen_base_accounting.erl gen/diameter_gen_relay.erl \
+gen/diameter_gen_base_accounting.hrl gen/diameter_gen_relay.hrl: \
+ $(EBIN)/diameter_gen_base_rfc3588.$(EMULATOR)
+
+gen/diameter_gen_base_rfc3588.erl gen/diameter_gen_base_rfc3588.hrl: \
+ $(COMPILER_MODULES:compiler/%=$(EBIN)/%.$(EMULATOR))
+
+$(DICT_MODULES:gen/%=$(EBIN)/%.$(EMULATOR)): \
+ $(INCDIR)/diameter.hrl \
+ $(INCDIR)/diameter_gen.hrl
+
+depend: depend.mk
+
+# Generate dependencies makefile.
+depend.mk: depend.sed $(MODULES:%=%.erl) Makefile
+ (for f in $(MODULES); do \
+ (echo $$f; cat $$f.erl) | sed -f $<; \
+ done) \
+ > $@
+
+-include depend.mk
+
+.PRECIOUS: $(DICT_ERLS) $(DICT_HRLS)
+.PHONY: app clean depend dict info release_subdir
+.PHONY: debug opt release_docs_spec release_spec
+.PHONY: $(TARGET_DIRS:%/=%) $(TARGET_DIRS:%/=release_src_%)
+
+# ----------------------------------------------------
+# Targets using secondary expansion (make >= 3.81)
+# ----------------------------------------------------
+
+.SECONDEXPANSION:
+
+# Make beams from a subdirectory.
+$(TARGET_DIRS:%/=%): \
+ $$(patsubst $$@/%,$(EBIN)/%.$(EMULATOR),$$(filter $$@/%,$(TARGET_MODULES)))
diff --git a/lib/diameter/src/app/.gitignore b/lib/diameter/src/app/.gitignore
deleted file mode 100644
index d388e61877..0000000000
--- a/lib/diameter/src/app/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
-
-/diameter_gen_*.erl
-/diameter_gen_*.hrl
-/depend.mk
-/diameter.mk
-
diff --git a/lib/diameter/src/app/Makefile b/lib/diameter/src/app/Makefile
deleted file mode 100644
index 6de220d282..0000000000
--- a/lib/diameter/src/app/Makefile
+++ /dev/null
@@ -1,199 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2010-2011. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-#
-
-ifneq ($(ERL_TOP),)
-include $(ERL_TOP)/make/target.mk
-EBIN = ../../ebin
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-else
-include $(DIAMETER_TOP)/make/target.mk
-EBIN = ../../ebin
-include $(DIAMETER_TOP)/make/$(TARGET)/rules.mk
-endif
-
-
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-
-include ../../vsn.mk
-
-VSN=$(DIAMETER_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-
-RELSYSDIR = $(RELEASE_PATH)/lib/diameter-$(VSN)
-
-INCDIR = ../../include
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-include modules.mk
-
-SPEC_ERL_FILES = \
- $(SPEC_FILES:%.dia=%.erl)
-
-SPEC_HRL_FILES = \
- $(SPEC_FILES:%.dia=%.hrl)
-
-APP_MODULES = \
- $(MODULES) \
- $(SPEC_FILES:%.dia=%)
-
-TARGET_FILES = \
- $(APP_MODULES:%=$(EBIN)/%.$(EMULATOR)) \
- $(APP_TARGET) \
- $(APPUP_TARGET)
-
-ESCRIPT_FILES = \
- ../../bin/diameterc
-
-APP_FILE = diameter.app
-APP_SRC = $(APP_FILE).src
-APP_TARGET = $(EBIN)/$(APP_FILE)
-
-APPUP_FILE = diameter.appup
-APPUP_SRC = $(APPUP_FILE).src
-APPUP_TARGET = $(EBIN)/$(APPUP_FILE)
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-
-ifeq ($(TYPE),debug)
-ERL_COMPILE_FLAGS += -Ddebug
-endif
-
-include diameter.mk
-
-ERL_COMPILE_FLAGS += \
- $(DIAMETER_ERL_COMPILE_FLAGS) \
- -I$(INCDIR)
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-debug:
- @$(MAKE) TYPE=debug opt
-
-opt: $(TARGET_FILES)
-
-clean:
- rm -f $(TARGET_FILES) $(SPEC_ERL_FILES) $(SPEC_HRL_FILES)
- rm -f $(APP_TARGET) $(APPUP_TARGET)
- rm -f errs core *~ diameter_gen_*.forms diameter_gen_*.spec
- rm -f depend.mk
-
-docs:
-
-info:
- @echo ""
- @echo "SPEC_FILES = $(FILES)"
- @echo "MODULES = $(MODULES)"
- @echo ""
- @echo "EXTERNAL_HRL_FILES = $(EXTERNAL_HRL_FILES)"
- @echo "INTERNAL_HRL_FILES = $(INTERNAL_HRL_FILES)"
- @echo ""
- @echo "EXAMPLE_FILES = $(EXAMPLE_FILES)"
- @echo ""
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-
-# Generate the app file and then modules into in. This shouldn't know
-# about ../{compiler,transport} but good enough for now.
-$(APP_TARGET): $(APP_SRC) \
- ../../vsn.mk \
- modules.mk \
- ../compiler/modules.mk \
- ../transport/modules.mk
- sed -e 's;%VSN%;$(VSN);' $< > $@
- M=`echo $(APP_MODULES) | sed -e 's/^ *//' -e 's/ *$$//' -e 'y/ /,/'`; \
- echo "/%APP_MODULES%/s//$$M/;w;q" | tr ';' '\n' \
- | ed -s $@
- $(MAKE) -C ../compiler $(APP_TARGET) APP_TARGET=$(APP_TARGET)
- $(MAKE) -C ../transport $(APP_TARGET) APP_TARGET=$(APP_TARGET)
-
-$(APPUP_TARGET): $(APPUP_SRC) ../../vsn.mk
- sed -e 's;%VSN%;$(VSN);' $< > $@
-
-compiler:
- $(MAKE) -C ../$@
-
-app: $(APP_TARGET) $(APPUP_TARGET)
-
-# erl/hrl from application spec
-diameter_gen_%.erl diameter_gen_%.hrl: diameter_gen_%.dia
- ../../bin/diameterc -i $(EBIN) -o $(@D) $<
-
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-
-ifneq ($(ERL_TOP),)
-include $(ERL_TOP)/make/otp_release_targets.mk
-else
-include $(DIAMETER_TOP)/make/release_targets.mk
-endif
-
-release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/bin
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/src/app
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DIR) $(RELSYSDIR)/examples
- $(INSTALL_SCRIPT) $(ESCRIPT_FILES) $(RELSYSDIR)/bin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(MODULES:%=%.erl) $(SPEC_ERL_FILES) $(RELSYSDIR)/src/app
- $(INSTALL_DATA) $(SPEC_FILES) $(RELSYSDIR)/src/app
- $(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src/app
- $(INSTALL_DATA) $(EXTERNAL_HRL_FILES) $(SPEC_HRL_FILES) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(EXAMPLE_FILES) $(RELSYSDIR)/examples
-
-release_docs_spec:
-
-# ----------------------------------------------------
-# Dependencies
-# ----------------------------------------------------
-
-depend: depend.mk
-
-# Generate dependencies makefile. It's assumed that the compile target
-# has already been made since it's currently not smart enough to not
-# force a rebuild of those beams dependent on generated hrls, and this
-# is a no-no at make release.
-depend.mk: depend.sed $(MODULES:%=%.erl) Makefile
- (for f in $(MODULES); do \
- sed -f $< $$f.erl | sed "s@/@/$$f@"; \
- done) \
- > $@
-
--include depend.mk
-
-.PRECIOUS: $(SPEC_ERL_FILES) $(SPEC_HRL_FILES)
-.PHONY: app clean debug depend info opt compiler release_spec release_docs_spec
diff --git a/lib/diameter/src/app/diameter.mk.in b/lib/diameter/src/app/diameter.mk.in
deleted file mode 100644
index c161064303..0000000000
--- a/lib/diameter/src/app/diameter.mk.in
+++ /dev/null
@@ -1,47 +0,0 @@
-#-*-makefile-*- ; force emacs to enter makefile-mode
-
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2010-2011. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-
-DIAMETER_TOP = @DIAMETER_TOP@
-
-# ifneq ($(PREFIX),)
-# ifeq ($(TESTROOT),)
-# TESTROOT = $(PREFIX)
-# endif
-# endif
-
-ifeq ($(USE_DIAMETER_TEST_CODE), true)
-ERL_COMPILE_FLAGS += -DDIAMETER_TEST_CODE=mona_lisa_spelar_doom
-endif
-
-ifeq ($(USE_DIAMETER_HIPE), true)
-ERL_COMPILE_FLAGS += +native
-endif
-
-ifeq ($(WARN_UNUSED_WARS), true)
-ERL_COMPILE_FLAGS += +warn_unused_vars
-endif
-
-DIAMETER_APP_VSN_COMPILE_FLAGS = \
- +'{parse_transform,sys_pre_attributes}' \
- +'{attribute,insert,app_vsn,$(APP_VSN)}'
-
-DIAMETER_ERL_COMPILE_FLAGS += \
- -pa $(DIAMETER_TOP)/ebin \
- $(DIAMETER_APP_VSN_COMPILE_FLAGS)
-
diff --git a/lib/diameter/src/app/diameter_gen_base_accounting.dia b/lib/diameter/src/app/diameter_gen_base_accounting.dia
deleted file mode 100644
index 64e95dddb5..0000000000
--- a/lib/diameter/src/app/diameter_gen_base_accounting.dia
+++ /dev/null
@@ -1,68 +0,0 @@
-;;
-;; %CopyrightBegin%
-;;
-;; Copyright Ericsson AB 2010-2011. All Rights Reserved.
-;;
-;; The contents of this file are subject to the Erlang Public License,
-;; Version 1.1, (the "License"); you may not use this file except in
-;; compliance with the License. You should have received a copy of the
-;; Erlang Public License along with this software. If not, it can be
-;; retrieved online at http://www.erlang.org/.
-;;
-;; Software distributed under the License is distributed on an "AS IS"
-;; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-;; the License for the specific language governing rights and limitations
-;; under the License.
-;;
-;; %CopyrightEnd%
-;;
-
-@id 3
-@prefix diameter_base_accounting
-@vendor 0 IETF
-
-@inherits diameter_gen_base_rfc3588
-
-@messages
-
- ACR ::= < Diameter Header: 271, REQ, PXY >
- < Session-Id >
- { Origin-Host }
- { Origin-Realm }
- { Destination-Realm }
- { Accounting-Record-Type }
- { Accounting-Record-Number }
- [ Acct-Application-Id ]
- [ Vendor-Specific-Application-Id ]
- [ User-Name ]
- [ Accounting-Sub-Session-Id ]
- [ Acct-Session-Id ]
- [ Acct-Multi-Session-Id ]
- [ Acct-Interim-Interval ]
- [ Accounting-Realtime-Required ]
- [ Origin-State-Id ]
- [ Event-Timestamp ]
- * [ Proxy-Info ]
- * [ Route-Record ]
- * [ AVP ]
-
- ACA ::= < Diameter Header: 271, PXY >
- < Session-Id >
- { Result-Code }
- { Origin-Host }
- { Origin-Realm }
- { Accounting-Record-Type }
- { Accounting-Record-Number }
- [ Acct-Application-Id ]
- [ Vendor-Specific-Application-Id ]
- [ User-Name ]
- [ Accounting-Sub-Session-Id ]
- [ Acct-Session-Id ]
- [ Acct-Multi-Session-Id ]
- [ Error-Reporting-Host ]
- [ Acct-Interim-Interval ]
- [ Accounting-Realtime-Required ]
- [ Origin-State-Id ]
- [ Event-Timestamp ]
- * [ Proxy-Info ]
- * [ AVP ]
diff --git a/lib/diameter/src/app/diameter_gen_base_rfc3588.dia b/lib/diameter/src/app/diameter_gen_base_rfc3588.dia
deleted file mode 100644
index 4a12e21acd..0000000000
--- a/lib/diameter/src/app/diameter_gen_base_rfc3588.dia
+++ /dev/null
@@ -1,413 +0,0 @@
-;;
-;; %CopyrightBegin%
-;;
-;; Copyright Ericsson AB 2010-2011. All Rights Reserved.
-;;
-;; The contents of this file are subject to the Erlang Public License,
-;; Version 1.1, (the "License"); you may not use this file except in
-;; compliance with the License. You should have received a copy of the
-;; Erlang Public License along with this software. If not, it can be
-;; retrieved online at http://www.erlang.org/.
-;;
-;; Software distributed under the License is distributed on an "AS IS"
-;; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-;; the License for the specific language governing rights and limitations
-;; under the License.
-;;
-;; %CopyrightEnd%
-;;
-
-@id 0
-@prefix diameter_base
-@vendor 0 IETF
-
-@avp_types
-
- Acct-Interim-Interval 85 Unsigned32 M
- Accounting-Realtime-Required 483 Enumerated M
- Acct-Multi-Session-Id 50 UTF8String M
- Accounting-Record-Number 485 Unsigned32 M
- Accounting-Record-Type 480 Enumerated M
- Acct-Session-Id 44 OctetString M
- Accounting-Sub-Session-Id 287 Unsigned64 M
- Acct-Application-Id 259 Unsigned32 M
- Auth-Application-Id 258 Unsigned32 M
- Auth-Request-Type 274 Enumerated M
- Authorization-Lifetime 291 Unsigned32 M
- Auth-Grace-Period 276 Unsigned32 M
- Auth-Session-State 277 Enumerated M
- Re-Auth-Request-Type 285 Enumerated M
- Class 25 OctetString M
- Destination-Host 293 DiamIdent M
- Destination-Realm 283 DiamIdent M
- Disconnect-Cause 273 Enumerated M
- E2E-Sequence 300 Grouped M
- Error-Message 281 UTF8String -
- Error-Reporting-Host 294 DiamIdent -
- Event-Timestamp 55 Time M
- Experimental-Result 297 Grouped M
- Experimental-Result-Code 298 Unsigned32 M
- Failed-AVP 279 Grouped M
- Firmware-Revision 267 Unsigned32 -
- Host-IP-Address 257 Address M
- Inband-Security-Id 299 Unsigned32 M
- Multi-Round-Time-Out 272 Unsigned32 M
- Origin-Host 264 DiamIdent M
- Origin-Realm 296 DiamIdent M
- Origin-State-Id 278 Unsigned32 M
- Product-Name 269 UTF8String -
- Proxy-Host 280 DiamIdent M
- Proxy-Info 284 Grouped M
- Proxy-State 33 OctetString M
- Redirect-Host 292 DiamURI M
- Redirect-Host-Usage 261 Enumerated M
- Redirect-Max-Cache-Time 262 Unsigned32 M
- Result-Code 268 Unsigned32 M
- Route-Record 282 DiamIdent M
- Session-Id 263 UTF8String M
- Session-Timeout 27 Unsigned32 M
- Session-Binding 270 Unsigned32 M
- Session-Server-Failover 271 Enumerated M
- Supported-Vendor-Id 265 Unsigned32 M
- Termination-Cause 295 Enumerated M
- User-Name 1 UTF8String M
- Vendor-Id 266 Unsigned32 M
- Vendor-Specific-Application-Id 260 Grouped M
-
-@messages
-
- CER ::= < Diameter Header: 257, REQ >
- { Origin-Host }
- { Origin-Realm }
- 1* { Host-IP-Address }
- { Vendor-Id }
- { Product-Name }
- [ Origin-State-Id ]
- * [ Supported-Vendor-Id ]
- * [ Auth-Application-Id ]
- * [ Inband-Security-Id ]
- * [ Acct-Application-Id ]
- * [ Vendor-Specific-Application-Id ]
- [ Firmware-Revision ]
- * [ AVP ]
-
- CEA ::= < Diameter Header: 257 >
- { Result-Code }
- { Origin-Host }
- { Origin-Realm }
- 1* { Host-IP-Address }
- { Vendor-Id }
- { Product-Name }
- [ Origin-State-Id ]
- [ Error-Message ]
- * [ Failed-AVP ]
- * [ Supported-Vendor-Id ]
- * [ Auth-Application-Id ]
- * [ Inband-Security-Id ]
- * [ Acct-Application-Id ]
- * [ Vendor-Specific-Application-Id ]
- [ Firmware-Revision ]
- * [ AVP ]
-
- DPR ::= < Diameter Header: 282, REQ >
- { Origin-Host }
- { Origin-Realm }
- { Disconnect-Cause }
-
- DPA ::= < Diameter Header: 282 >
- { Result-Code }
- { Origin-Host }
- { Origin-Realm }
- [ Error-Message ]
- * [ Failed-AVP ]
-
- DWR ::= < Diameter Header: 280, REQ >
- { Origin-Host }
- { Origin-Realm }
- [ Origin-State-Id ]
-
- DWA ::= < Diameter Header: 280 >
- { Result-Code }
- { Origin-Host }
- { Origin-Realm }
- [ Error-Message ]
- * [ Failed-AVP ]
- [ Origin-State-Id ]
-
- answer-message ::= < Diameter Header: code, ERR [PXY] >
- 0*1< Session-Id >
- { Origin-Host }
- { Origin-Realm }
- { Result-Code }
- [ Origin-State-Id ]
- [ Error-Reporting-Host ]
- [ Proxy-Info ]
- * [ AVP ]
-
- RAR ::= < Diameter Header: 258, REQ, PXY >
- < Session-Id >
- { Origin-Host }
- { Origin-Realm }
- { Destination-Realm }
- { Destination-Host }
- { Auth-Application-Id }
- { Re-Auth-Request-Type }
- [ User-Name ]
- [ Origin-State-Id ]
- * [ Proxy-Info ]
- * [ Route-Record ]
- * [ AVP ]
-
- RAA ::= < Diameter Header: 258, PXY >
- < Session-Id >
- { Result-Code }
- { Origin-Host }
- { Origin-Realm }
- [ User-Name ]
- [ Origin-State-Id ]
- [ Error-Message ]
- [ Error-Reporting-Host ]
- * [ Failed-AVP ]
- * [ Redirect-Host ]
- [ Redirect-Host-Usage ]
- [ Redirect-Max-Cache-Time ]
- * [ Proxy-Info ]
- * [ AVP ]
-
- STR ::= < Diameter Header: 275, REQ, PXY >
- < Session-Id >
- { Origin-Host }
- { Origin-Realm }
- { Destination-Realm }
- { Auth-Application-Id }
- { Termination-Cause }
- [ User-Name ]
- [ Destination-Host ]
- * [ Class ]
- [ Origin-State-Id ]
- * [ Proxy-Info ]
- * [ Route-Record ]
- * [ AVP ]
-
- STA ::= < Diameter Header: 275, PXY >
- < Session-Id >
- { Result-Code }
- { Origin-Host }
- { Origin-Realm }
- [ User-Name ]
- * [ Class ]
- [ Error-Message ]
- [ Error-Reporting-Host ]
- * [ Failed-AVP ]
- [ Origin-State-Id ]
- * [ Redirect-Host ]
- [ Redirect-Host-Usage ]
- [ Redirect-Max-Cache-Time ]
- * [ Proxy-Info ]
- * [ AVP ]
-
- ASR ::= < Diameter Header: 274, REQ, PXY >
- < Session-Id >
- { Origin-Host }
- { Origin-Realm }
- { Destination-Realm }
- { Destination-Host }
- { Auth-Application-Id }
- [ User-Name ]
- [ Origin-State-Id ]
- * [ Proxy-Info ]
- * [ Route-Record ]
- * [ AVP ]
-
- ASA ::= < Diameter Header: 274, PXY >
- < Session-Id >
- { Result-Code }
- { Origin-Host }
- { Origin-Realm }
- [ User-Name ]
- [ Origin-State-Id ]
- [ Error-Message ]
- [ Error-Reporting-Host ]
- * [ Failed-AVP ]
- * [ Redirect-Host ]
- [ Redirect-Host-Usage ]
- [ Redirect-Max-Cache-Time ]
- * [ Proxy-Info ]
- * [ AVP ]
-
- ACR ::= < Diameter Header: 271, REQ, PXY >
- < Session-Id >
- { Origin-Host }
- { Origin-Realm }
- { Destination-Realm }
- { Accounting-Record-Type }
- { Accounting-Record-Number }
- [ Acct-Application-Id ]
- [ Vendor-Specific-Application-Id ]
- [ User-Name ]
- [ Accounting-Sub-Session-Id ]
- [ Acct-Session-Id ]
- [ Acct-Multi-Session-Id ]
- [ Acct-Interim-Interval ]
- [ Accounting-Realtime-Required ]
- [ Origin-State-Id ]
- [ Event-Timestamp ]
- * [ Proxy-Info ]
- * [ Route-Record ]
- * [ AVP ]
-
- ACA ::= < Diameter Header: 271, PXY >
- < Session-Id >
- { Result-Code }
- { Origin-Host }
- { Origin-Realm }
- { Accounting-Record-Type }
- { Accounting-Record-Number }
- [ Acct-Application-Id ]
- [ Vendor-Specific-Application-Id ]
- [ User-Name ]
- [ Accounting-Sub-Session-Id ]
- [ Acct-Session-Id ]
- [ Acct-Multi-Session-Id ]
- [ Error-Reporting-Host ]
- [ Acct-Interim-Interval ]
- [ Accounting-Realtime-Required ]
- [ Origin-State-Id ]
- [ Event-Timestamp ]
- * [ Proxy-Info ]
- * [ AVP ]
-
-@enum Disconnect-Cause
-
- REBOOTING 0
- BUSY 1
- DO_NOT_WANT_TO_TALK_TO_YOU 2
-
-@enum Redirect-Host-Usage
-
- DONT_CACHE 0
- ALL_SESSION 1
- ALL_REALM 2
- REALM_AND_APPLICATION 3
- ALL_APPLICATION 4
- ALL_HOST 5
- ALL_USER 6
-
-@enum Auth-Request-Type
-
- AUTHENTICATE_ONLY 1
- AUTHORIZE_ONLY 2
- AUTHORIZE_AUTHENTICATE 3
-
-@enum Auth-Session-State
-
- STATE_MAINTAINED 0
- NO_STATE_MAINTAINED 1
-
-@enum Re-Auth-Request-Type
-
- AUTHORIZE_ONLY 0
- AUTHORIZE_AUTHENTICATE 1
-
-@enum Termination-Cause
-
- DIAMETER_LOGOUT 1
- DIAMETER_SERVICE_NOT_PROVIDED 2
- DIAMETER_BAD_ANSWER 3
- DIAMETER_ADMINISTRATIVE 4
- DIAMETER_LINK_BROKEN 5
- DIAMETER_AUTH_EXPIRED 6
- DIAMETER_USER_MOVED 7
- DIAMETER_SESSION_TIMEOUT 8
-
-@enum Session-Server-Failover
-
- REFUSE_SERVICE 0
- TRY_AGAIN 1
- ALLOW_SERVICE 2
- TRY_AGAIN_ALLOW_SERVICE 3
-
-@enum Accounting-Record-Type
-
- EVENT_RECORD 1
- START_RECORD 2
- INTERIM_RECORD 3
- STOP_RECORD 4
-
-@enum Accounting-Realtime-Required
-
- DELIVER_AND_GRANT 1
- GRANT_AND_STORE 2
- GRANT_AND_LOSE 3
-
-@result_code Result-Code
-
-;; 7.1.1. Informational
- DIAMETER_MULTI_ROUND_AUTH 1001
-
-;; 7.1.2. Success
- DIAMETER_SUCCESS 2001
- DIAMETER_LIMITED_SUCCESS 2002
-
-;; 7.1.3. Protocol Errors
- DIAMETER_COMMAND_UNSUPPORTED 3001
- DIAMETER_UNABLE_TO_DELIVER 3002
- DIAMETER_REALM_NOT_SERVED 3003
- DIAMETER_TOO_BUSY 3004
- DIAMETER_LOOP_DETECTED 3005
- DIAMETER_REDIRECT_INDICATION 3006
- DIAMETER_APPLICATION_UNSUPPORTED 3007
- DIAMETER_INVALID_HDR_BITS 3008
- DIAMETER_INVALID_AVP_BITS 3009
- DIAMETER_UNKNOWN_PEER 3010
-
-;; 7.1.4. Transient Failures
- DIAMETER_AUTHENTICATION_REJECTED 4001
- DIAMETER_OUT_OF_SPACE 4002
- ELECTION_LOST 4003
-
-;; 7.1.5. Permanent Failures
- DIAMETER_AVP_UNSUPPORTED 5001
- DIAMETER_UNKNOWN_SESSION_ID 5002
- DIAMETER_AUTHORIZATION_REJECTED 5003
- DIAMETER_INVALID_AVP_VALUE 5004
- DIAMETER_MISSING_AVP 5005
- DIAMETER_RESOURCES_EXCEEDED 5006
- DIAMETER_CONTRADICTING_AVPS 5007
- DIAMETER_AVP_NOT_ALLOWED 5008
- DIAMETER_AVP_OCCURS_TOO_MANY_TIMES 5009
- DIAMETER_NO_COMMON_APPLICATION 5010
- DIAMETER_UNSUPPORTED_VERSION 5011
- DIAMETER_UNABLE_TO_COMPLY 5012
- DIAMETER_INVALID_BIT_IN_HEADER 5013
- DIAMETER_INVALID_AVP_LENGTH 5014
- DIAMETER_INVALID_MESSAGE_LENGTH 5015
- DIAMETER_INVALID_AVP_BIT_COMBO 5016
- DIAMETER_NO_COMMON_SECURITY 5017
-
-@grouped
-
- Proxy-Info ::= < AVP Header: 284 >
- { Proxy-Host }
- { Proxy-State }
- * [ AVP ]
-
- Failed-AVP ::= < AVP Header: 279 >
- 1* {AVP}
-
- Experimental-Result ::= < AVP Header: 297 >
- { Vendor-Id }
- { Experimental-Result-Code }
-
- Vendor-Specific-Application-Id ::= < AVP Header: 260 >
- 1* { Vendor-Id }
- [ Auth-Application-Id ]
- [ Acct-Application-Id ]
-
-;; The E2E-Sequence AVP is defined in RFC 3588 as Grouped, but
-;; there is no definition of the group - only an informal text stating
-;; that there should be a nonce (an OctetString) and a counter
-;; (integer)
-;;
- E2E-Sequence ::= <AVP Header: 300 >
- 2* { AVP }
diff --git a/lib/diameter/src/app/modules.mk b/lib/diameter/src/app/modules.mk
deleted file mode 100644
index a7a78b1a9d..0000000000
--- a/lib/diameter/src/app/modules.mk
+++ /dev/null
@@ -1,68 +0,0 @@
-#-*-makefile-*- ; force emacs to enter makefile-mode
-
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2010-2011. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-
-SPEC_FILES = \
- diameter_gen_base_rfc3588.dia \
- diameter_gen_base_accounting.dia \
- diameter_gen_relay.dia
-
-MODULES = \
- diameter \
- diameter_app \
- diameter_callback \
- diameter_capx \
- diameter_config \
- diameter_dbg \
- diameter_codec \
- diameter_dict \
- diameter_exprecs \
- diameter_info \
- diameter_lib \
- diameter_misc_sup \
- diameter_peer \
- diameter_peer_fsm \
- diameter_peer_fsm_sup \
- diameter_reg \
- diameter_service \
- diameter_service_sup \
- diameter_session \
- diameter_stats \
- diameter_sup \
- diameter_sync \
- diameter_types \
- diameter_watchdog \
- diameter_watchdog_sup
-
-INTERNAL_HRL_FILES = \
- diameter_internal.hrl \
- diameter_types.hrl
-
-EXTERNAL_HRL_FILES = \
- ../../include/diameter.hrl \
- ../../include/diameter_gen.hrl
-
-EXAMPLE_FILES = \
- ../../examples/GNUmakefile \
- ../../examples/peer.erl \
- ../../examples/client.erl \
- ../../examples/client_cb.erl \
- ../../examples/server.erl \
- ../../examples/server_cb.erl \
- ../../examples/relay.erl \
- ../../examples/relay_cb.erl
diff --git a/lib/diameter/src/app/diameter.app.src b/lib/diameter/src/base/diameter.app.src
index 119997953e..c092fdb022 100644
--- a/lib/diameter/src/app/diameter.app.src
+++ b/lib/diameter/src/base/diameter.app.src
@@ -20,7 +20,7 @@
{application, diameter,
[{description, "Diameter protocol"},
{vsn, "%VSN%"},
- {modules, [%APP_MODULES%,%COMPILER_MODULES%,%TRANSPORT_MODULES%]},
+ {modules, [%MODULES%]},
{registered, []},
{applications, [stdlib, kernel]},
{env, []},
diff --git a/lib/diameter/src/base/diameter.appup.src b/lib/diameter/src/base/diameter.appup.src
new file mode 100644
index 0000000000..b1c94d4cc8
--- /dev/null
+++ b/lib/diameter/src/base/diameter.appup.src
@@ -0,0 +1,30 @@
+%% This is an -*- erlang -*- file.
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+{"%VSN%",
+ [
+ {"0.9", [{restart_application, diameter}]},
+ {"0.10", [{restart_application, diameter}]}
+ ],
+ [
+ {"0.9", [{restart_application, diameter}]},
+ {"0.10", [{restart_application, diameter}]}
+ ]
+}.
diff --git a/lib/diameter/src/app/diameter.erl b/lib/diameter/src/base/diameter.erl
index 2f721421d8..2f721421d8 100644
--- a/lib/diameter/src/app/diameter.erl
+++ b/lib/diameter/src/base/diameter.erl
diff --git a/lib/diameter/src/app/diameter_app.erl b/lib/diameter/src/base/diameter_app.erl
index 600f7ff04d..600f7ff04d 100644
--- a/lib/diameter/src/app/diameter_app.erl
+++ b/lib/diameter/src/base/diameter_app.erl
diff --git a/lib/diameter/src/app/diameter_callback.erl b/lib/diameter/src/base/diameter_callback.erl
index fcf9a8fc1e..6d5c8cdca1 100644
--- a/lib/diameter/src/app/diameter_callback.erl
+++ b/lib/diameter/src/base/diameter_callback.erl
@@ -60,28 +60,28 @@ pick_peer([Peer|_], _, _SvcName, _State) ->
%%% ----------------------------------------------------------
prepare_request(Pkt, _SvcName, _Peer) ->
- Pkt.
+ {send, Pkt}.
%%% ----------------------------------------------------------
%%% # prepare_retransmit/3
%%% ----------------------------------------------------------
prepare_retransmit(Pkt, _SvcName, _Peer) ->
- Pkt.
+ {send, Pkt}.
%%% ----------------------------------------------------------
%%% # handle_request/3
%%% ----------------------------------------------------------
handle_request(_Pkt, _SvcName, _Peer) ->
- discard.
+ {protocol_error, 3001}. %% DIAMETER_COMMAND_UNSUPPORTED
%%% ----------------------------------------------------------
%%% # handle_answer/4
%%% ----------------------------------------------------------
handle_answer(#diameter_packet{msg = Ans}, _Req, _SvcName, _Peer) ->
- {ok, Ans}.
+ Ans.
%%% ---------------------------------------------------------------------------
%%% # handle_error/4
diff --git a/lib/diameter/src/app/diameter_capx.erl b/lib/diameter/src/base/diameter_capx.erl
index aa5318e79d..842a9e6103 100644
--- a/lib/diameter/src/app/diameter_capx.erl
+++ b/lib/diameter/src/base/diameter_capx.erl
@@ -57,11 +57,12 @@
-include("diameter_types.hrl").
-include("diameter_gen_base_rfc3588.hrl").
--define(SUCCESS, ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_SUCCESS').
--define(NOAPP, ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_NO_COMMON_APPLICATION').
--define(NOSECURITY, ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_NO_COMMON_SECURITY').
+-define(SUCCESS, 2001). %% DIAMETER_SUCCESS
+-define(NOAPP, 5010). %% DIAMETER_NO_COMMON_APPLICATION
+-define(NOSECURITY, 5017). %% DIAMETER_NO_COMMON_SECURITY
-define(NO_INBAND_SECURITY, 0).
+-define(TLS, 1).
%% ===========================================================================
@@ -80,7 +81,7 @@ recv_CER(CER, Svc) ->
try_it([fun rCER/2, CER, Svc]).
-spec recv_CEA(#diameter_base_CEA{}, #diameter_service{})
- -> tried({['Unsigned32'()], #diameter_caps{}}).
+ -> tried({['Unsigned32'()], ['Unsigned32'()], #diameter_caps{}}).
recv_CEA(CEA, Svc) ->
try_it([fun rCEA/2, CEA, Svc]).
@@ -95,7 +96,7 @@ try_it([Fun | Args]) ->
try apply(Fun, Args) of
T -> {ok, T}
catch
- throw: ?FAILURE(Reason) -> {error, {Reason, Args}}
+ throw: ?FAILURE(Reason) -> {error, Reason}
end.
%% mk_caps/2
@@ -126,10 +127,11 @@ mk_caps(Caps0, Opts) ->
set_cap({Key, _}, _) ->
?THROW({duplicate, Key}).
-cap(K, V) when K == 'Origin-Host';
- K == 'Origin-Realm';
- K == 'Vendor-Id';
- K == 'Product-Name' ->
+cap(K, V)
+ when K == 'Origin-Host';
+ K == 'Origin-Realm';
+ K == 'Vendor-Id';
+ K == 'Product-Name' ->
V;
cap('Host-IP-Address', Vs)
@@ -139,11 +141,8 @@ cap('Host-IP-Address', Vs)
cap('Firmware-Revision', V) ->
[V];
-%% Not documented but accept it as long as it's what we support.
-cap('Inband-Security-Id', [0] = Vs) -> %% NO_INBAND_SECURITY
- Vs;
-
-cap(K, Vs) when K /= 'Inband-Security-Id', is_list(Vs) ->
+cap(_, Vs)
+ when is_list(Vs) ->
Vs;
cap(K, V) ->
@@ -161,28 +160,10 @@ ipaddr(A) ->
%%
%% Build a CER record to send to a remote peer.
-bCER(#diameter_caps{origin_host = Host,
- origin_realm = Realm,
- host_ip_address = Addrs,
- vendor_id = Vid,
- product_name = Name,
- origin_state_id = OSI,
- supported_vendor_id = SVid,
- auth_application_id = AuId,
- acct_application_id = AcId,
- vendor_specific_application_id = VSA,
- firmware_revision = Rev}) ->
- #diameter_base_CER{'Origin-Host' = Host,
- 'Origin-Realm' = Realm,
- 'Host-IP-Address' = Addrs,
- 'Vendor-Id' = Vid,
- 'Product-Name' = Name,
- 'Origin-State-Id' = OSI,
- 'Supported-Vendor-Id' = SVid,
- 'Auth-Application-Id' = AuId,
- 'Acct-Application-Id' = AcId,
- 'Vendor-Specific-Application-Id' = VSA,
- 'Firmware-Revision' = Rev}.
+%% Use the fact that diameter_caps has the same field names as CER.
+bCER(#diameter_caps{} = Rec) ->
+ #diameter_base_CER{}
+ = list_to_tuple([diameter_base_CER | tl(tuple_to_list(Rec))]).
%% rCER/2
%%
@@ -219,19 +200,16 @@ bCER(#diameter_caps{origin_host = Host,
%% That is, each side sends all of its capabilities and is responsible for
%% not sending commands that the peer doesn't support.
-%% TODO: Make it an option to send only common applications in CEA to
-%% allow backwards compatibility, and also because there are likely
-%% servers that expect this. Or maybe a callback.
-
%% 6.10. Inband-Security-Id AVP
%%
%% NO_INBAND_SECURITY 0
%% This peer does not support TLS. This is the default value, if the
%% AVP is omitted.
+%%
+%% TLS 1
+%% This node supports TLS security, as defined by [TLS].
rCER(CER, #diameter_service{capabilities = LCaps} = Svc) ->
- #diameter_base_CER{'Inband-Security-Id' = RIS}
- = CER,
#diameter_base_CEA{}
= CEA
= cea_from_cer(bCER(LCaps)),
@@ -241,59 +219,81 @@ rCER(CER, #diameter_service{capabilities = LCaps} = Svc) ->
{SApps,
RCaps,
- build_CEA([] == SApps,
- RIS,
- lists:member(?NO_INBAND_SECURITY, RIS),
- CEA#diameter_base_CEA{'Result-Code' = ?SUCCESS,
- 'Inband-Security-Id' = []})}.
-
-%% TODO: 5.3 of RFC3588 says we MUST return DIAMETER_NO_COMMON_APPLICATION
-%% in the CEA and SHOULD disconnect the transport. However, we have
-%% no way to guarantee the send before disconnecting.
+ build_CEA(SApps,
+ LCaps,
+ RCaps,
+ CEA#diameter_base_CEA{'Result-Code' = ?SUCCESS})}.
-build_CEA(true, _, _, CEA) ->
+build_CEA([], _, _, CEA) ->
CEA#diameter_base_CEA{'Result-Code' = ?NOAPP};
-build_CEA(false, [_|_], false, CEA) ->
- CEA#diameter_base_CEA{'Result-Code' = ?NOSECURITY};
-build_CEA(false, [_|_], true, CEA) ->
- CEA#diameter_base_CEA{'Inband-Security-Id' = [?NO_INBAND_SECURITY]};
-build_CEA(false, [], false, CEA) ->
- CEA.
+
+build_CEA(_, LCaps, RCaps, CEA) ->
+ case common_security(LCaps, RCaps) of
+ [] ->
+ CEA#diameter_base_CEA{'Result-Code' = ?NOSECURITY};
+ [_] = IS ->
+ CEA#diameter_base_CEA{'Inband-Security-Id' = IS}
+ end.
+
+%% common_security/2
+
+common_security(#diameter_caps{inband_security_id = LS},
+ #diameter_caps{inband_security_id = RS}) ->
+ cs(LS, RS).
+
+%% Unspecified is equivalent to NO_INBAND_SECURITY.
+cs([], RS) ->
+ cs([?NO_INBAND_SECURITY], RS);
+cs(LS, []) ->
+ cs(LS, [?NO_INBAND_SECURITY]);
+
+%% Agree on TLS if both parties support it. When sending CEA, this is
+%% to ensure the peer is clear that we will be expecting a TLS
+%% handshake since there is no ssl:maybe_accept that would allow the
+%% peer to choose between TLS or not upon reception of our CEA. When
+%% receiving CEA it deals with a server that isn't explicit about its choice.
+%% TODO: Make the choice configurable.
+cs(LS, RS) ->
+ Is = ordsets:to_list(ordsets:intersection(ordsets:from_list(LS),
+ ordsets:from_list(RS))),
+ case lists:member(?TLS, Is) of
+ true ->
+ [?TLS];
+ false when [] == Is ->
+ Is;
+ false ->
+ [hd(Is)] %% probably NO_INBAND_SECURITY
+ end.
+%% The only two values defined by RFC 3588 are NO_INBAND_SECURITY and
+%% TLS but don't enforce this. In theory this allows some other
+%% security mechanism we don't have to know about, although in
+%% practice something there may be a need for more synchronization
+%% than notification by way of an event subscription offers.
%% cea_from_cer/1
+%% CER is a subset of CEA, the latter adding Result-Code and a few
+%% more AVP's.
cea_from_cer(#diameter_base_CER{} = CER) ->
lists:foldl(fun(F,A) -> to_cea(CER, F, A) end,
#diameter_base_CEA{},
record_info(fields, diameter_base_CER)).
to_cea(CER, Field, CEA) ->
- try ?BASE:'#info-'(diameter_base_CEA, {index, Field}) of
- N ->
- setelement(N, CEA, ?BASE:'#get-'(Field, CER))
+ try ?BASE:'#get-'(Field, CER) of
+ V -> ?BASE:'#set-'({Field, V}, CEA)
catch
- error: _ ->
- CEA
+ error: _ -> CEA
end.
-
+
%% rCEA/2
-rCEA(CEA, #diameter_service{capabilities = LCaps} = Svc)
- when is_record(CEA, diameter_base_CEA) ->
- #diameter_base_CEA{'Result-Code' = RC}
- = CEA,
-
- RC == ?SUCCESS orelse ?THROW({'Result-Code', RC}),
-
+rCEA(CEA, #diameter_service{capabilities = LCaps} = Svc) ->
RCaps = capx_to_caps(CEA),
SApps = common_applications(LCaps, RCaps, Svc),
+ IS = common_security(LCaps, RCaps),
- [] == SApps andalso ?THROW({no_common_apps, LCaps, RCaps}),
-
- {SApps, RCaps};
-
-rCEA(CEA, _Svc) ->
- ?THROW({invalid, CEA}).
+ {SApps, IS, RCaps}.
%% capx_to_caps/1
diff --git a/lib/diameter/src/app/diameter_codec.erl b/lib/diameter/src/base/diameter_codec.erl
index f6cbde5446..fe1212b7e0 100644
--- a/lib/diameter/src/app/diameter_codec.erl
+++ b/lib/diameter/src/base/diameter_codec.erl
@@ -140,10 +140,10 @@ make_flags(Flags0, #diameter_header{is_request = R,
mf(undefined, F, _) ->
F;
mf(B, F, N) -> %% reset the affected bit
- (F bxor (F band (1 bsl N))) bor (bit(B) bsl N).
+ (F bxor (F band (1 bsl N))) bor bit(B, N).
-bit(true) -> 1;
-bit(false) -> 0.
+bit(true, N) -> 1 bsl N;
+bit(false, _) -> 0.
%% values/1
@@ -190,35 +190,13 @@ encode_avps(Avps) ->
%% msg_header/3
-msg_header(Mod, MsgName, Header) ->
- {Code, Flags, ApplId} = h(Mod, MsgName, Header),
- {Code, p(Flags, Header), ApplId}.
-
-%% 6.2 of 3588 requires the same 'P' bit on an answer as on the
-%% request.
-
-p(Flags, #diameter_header{is_request = true,
- is_proxiable = P}) ->
- Flags bor choose(P, 2#01000000, 0);
-p(Flags, _) ->
- Flags.
-
-%% The header below is that of the incoming request being answered,
-%% not of the answer (which hasn't been encoded yet).
-
-h(Mod, 'answer-message' = MsgName, Header) ->
+msg_header(Mod, 'answer-message' = MsgName, Header) ->
?BASE = Mod,
- #diameter_header{is_request = true,
- cmd_code = Code}
- = Header,
+ #diameter_header{cmd_code = Code} = Header,
{_, Flags, ApplId} = ?BASE:msg_header(MsgName),
{Code, Flags, ApplId};
-h(Mod, MsgName, #diameter_header{is_request = true,
- cmd_code = Code}) ->
- {Code, _, _} = Mod:msg_header(MsgName); %% ensure Code
-
-h(Mod, MsgName, _) ->
+msg_header(Mod, MsgName, _) ->
Mod:msg_header(MsgName).
%% rec2msg/2
@@ -290,7 +268,8 @@ decode_avps(MsgName, Mod, Pkt, {Bs, Avps}) -> %% invalid avp bits ...
decode_avps('', Mod, Pkt, Avps) -> %% unknown message ...
?LOG(unknown, {Mod, Pkt#diameter_packet.header}),
- Pkt#diameter_packet{errors = lists:reverse(Avps)};
+ Pkt#diameter_packet{avps = lists:reverse(Avps),
+ errors = [3001]}; %% DIAMETER_COMMAND_UNSUPPORTED
%% msg = undefined identifies this case.
decode_avps(MsgName, Mod, Pkt, Avps) -> %% ... or not
@@ -562,8 +541,3 @@ pack_avp(Code, Flags, Vid, Sz, Bin) ->
pack_avp(Code, Flags, Sz, Bin) ->
Length = Sz + 8,
<<Code:32, Flags:8, Length:24, Bin/binary>>.
-
-%% ===========================================================================
-
-choose(true, X, _) -> X;
-choose(false, _, X) -> X.
diff --git a/lib/diameter/src/app/diameter_config.erl b/lib/diameter/src/base/diameter_config.erl
index 42c70890b3..a6b48fe65b 100644
--- a/lib/diameter/src/app/diameter_config.erl
+++ b/lib/diameter/src/base/diameter_config.erl
@@ -267,7 +267,7 @@ handle_call(uptime, _, #state{id = Time} = State) ->
{reply, diameter_lib:now_diff(Time), State};
handle_call(Req, From, State) ->
- warning_msg("received unexpected request from ~p:~n~w", [From, Req]),
+ ?UNEXPECTED([Req, From]),
Reply = {error, {bad_request, Req}},
{reply, Reply, State}.
@@ -276,7 +276,7 @@ handle_call(Req, From, State) ->
%%% ----------------------------------------------------------
handle_cast(Msg, State) ->
- warning_msg("received unexpected message:~n~w", [Msg]),
+ ?UNEXPECTED([Msg]),
{noreply, State}.
%%% ----------------------------------------------------------
@@ -309,7 +309,7 @@ handle_info(restart, State) ->
{noreply, State};
handle_info(Info, State) ->
- warning_msg("received unknown info:~n~w", [Info]),
+ ?UNEXPECTED([Info]),
{noreply, State}.
%%--------------------------------------------------------------------
@@ -674,8 +674,3 @@ cb(M,F) ->
call(Request) ->
gen_server:call(?SERVER, Request, infinity).
-
-%% warning_msg/2
-
-warning_msg(F, A) ->
- ?diameter_warning("~p: " ++ F, [?MODULE | A]).
diff --git a/lib/diameter/src/app/diameter_dbg.erl b/lib/diameter/src/base/diameter_dbg.erl
index b18f34e13d..5b0ac3a3b6 100644
--- a/lib/diameter/src/app/diameter_dbg.erl
+++ b/lib/diameter/src/base/diameter_dbg.erl
@@ -68,12 +68,6 @@
-define(VALUES(Rec), tl(tuple_to_list(Rec))).
-%%% ----------------------------------------------------------
-%%% # log/4
-%%%
-%%% Called to have something to trace on for happenings of interest.
-%%% ----------------------------------------------------------
-
log(_Slogan, _Mod, _Line, _Details) ->
ok.
@@ -82,9 +76,6 @@ log(_Slogan, _Mod, _Line, _Details) ->
%%% ----------------------------------------------------------
help() ->
- ?INFO:usage(usage()).
-
-usage() ->
not_yet_implemented.
%%% ----------------------------------------------------------
@@ -99,30 +90,23 @@ table(T)
when (T == diameter_peer) orelse (T == diameter_reg) ->
?INFO:format(collect(T), fields(T), fun ?INFO:split/2);
-table(diameter_service = T) ->
- Fs = [name, started] ++ fields(T) ++ [peerT,
- connT,
- share_peers,
- use_shared_peers,
- shared_peers,
- local_peers,
- monitor],
- ?INFO:format(T,
- fun(R) ->
- [I,N,S|Vs] = ?VALUES(R),
- {Fs, [N,I] ++ ?VALUES(S) ++ Vs}
- end,
- fun ?INFO:split/2);
-
table(Table)
when is_atom(Table) ->
case fields(Table) of
undefined = No ->
No;
Fields ->
- ?INFO:format(Table, Fields, fun ?INFO:split/2)
+ ?INFO:format(Table, Fields, fun split/2)
end.
+split([started, name | Fs], [S, N | Vs]) ->
+ {name, [started | Fs], N, [S | Vs]};
+split([[F|FT]|Fs], [Rec|Vs]) ->
+ [_, V | VT] = tuple_to_list(Rec),
+ {F, FT ++ Fs, V, VT ++ Vs};
+split([F|Fs], [V|Vs]) ->
+ {F, Fs, V, Vs}.
+
%%% ----------------------------------------------------------
%%% # TableName()
%%% ----------------------------------------------------------
@@ -146,14 +130,14 @@ table(Table)
%%% ----------------------------------------------------------
tables() ->
- format_all(fun ?INFO:split/3).
-
-format_all(SplitFun) ->
- ?INFO:format(field(?LOCAL), SplitFun, fun collect/1).
+ ?INFO:format(field(?LOCAL), fun split/3, fun collect/1).
field(Tables) ->
lists:map(fun(T) -> {T, fields(T)} end, lists:sort(Tables)).
+split(_, Fs, Vs) ->
+ split(Fs, Vs).
+
%%% ----------------------------------------------------------
%%% # modules()
%%% ----------------------------------------------------------
@@ -396,76 +380,24 @@ stop() ->
%% tp/1
tpl(T) ->
- dbg(tpl, dbg(T)).
+ dbg(tpl, T).
tp(T) ->
- dbg(tp, dbg(T)).
-
-%% dbg/1
-
-dbg(x) ->
- [{M, x, []} || M <- [diameter_tcp,
- diameter_etcp,
- diameter_sctp,
- diameter_peer_fsm,
- diameter_watchdog]];
-
-dbg(log) ->
- {?MODULE, log, 4};
-
-dbg({log = F, Mods})
- when is_list(Mods) ->
- {?MODULE, F, [{['_','$1','_','_'],
- [?ORCOND([{'==', '$1', M} || M <- Mods])],
- []}]};
-
-dbg({log = F, Mod}) ->
- dbg({F, [Mod]});
-
-dbg(send) ->
- {diameter_peer, send, 2};
-
-dbg(recv) ->
- {diameter_peer, recv, 2};
-
-dbg(sendrecv) ->
- [{diameter_peer, send, 2},
- {diameter_peer, recv, 2}];
-
-dbg(decode) ->
- [{diameter_codec,decode,2}];
-
-dbg(encode) ->
- [{diameter_codec,encode,2,[]},
- {diameter_codec,encode,3,[]},
- {diameter_codec,encode,4}];
-
-dbg(transition = T) ->
- [{?MODULE, log, [{[T,M,'_','_'],[],[]}]}
- || M <- [diameter_watchdog, diameter_peer_fsm]];
-
-dbg(T) ->
- T.
+ dbg(tp, T).
%% dbg/2
-dbg(TF, L)
+dbg(F, L)
when is_list(L) ->
- {ok, lists:foldl(fun(T,A) -> {ok, X} = dbg(TF, T), [X|A] end, [], L)};
+ [dbg(F, X) || X <- L];
dbg(F, M)
when is_atom(M) ->
- dbg(F, {M});
+ apply(dbg, F, [M, x]);
dbg(F, T)
when is_tuple(T) ->
- [_|_] = A = tuple_to_list(T),
- {ok,_} = apply(dbg, F, case is_list(lists:last(A)) of
- false ->
- A ++ [[{'_',[],[{exception_trace}]}]];
- true ->
- A
- end).
+ apply(dbg, F, tuple_to_list(T)).
%% ===========================================================================
%% ===========================================================================
@@ -493,15 +425,19 @@ peers(Name) ->
peers(_, undefined) ->
[];
-peers(Name, {Cs,As}) ->
- mk_peer(Name, connector, Cs) ++ mk_peer(Name, acceptor, As).
-
-mk_peer(Name, T, Ts) ->
- [[Name | mk_peer(T,Vs)] || Vs <- Ts].
-
-mk_peer(Type, Vs) ->
- [Ref, State, Opts, WPid, TPid, SApps, Caps]
- = get_values(Vs, [ref, state, options, watchdog, peer, apps, caps]),
+peers(Name, Ts) ->
+ lists:flatmap(fun(T) -> mk_peers(Name, T) end, Ts).
+
+mk_peers(Name, [_, {type, connect} | _] = Ts) ->
+ [[Name | mk_peer(Ts)]];
+mk_peers(Name, [R, {type, listen}, O, {accept = A, As}]) ->
+ [[Name | mk_peer([R, {type, A}, O | Ts])] || Ts <- As].
+%% This is a bit lame: service_info works to build this list and out
+%% of something like what we want here and then we take it apart.
+
+mk_peer(Vs) ->
+ [Type, Ref, State, Opts, WPid, TPid, SApps, Caps]
+ = get_values(Vs, [type,ref,state,options,watchdog,peer,apps,caps]),
[Ref, State, [{type, Type} | Opts], s(WPid), s(TPid), SApps, Caps].
get_values(Vs, Ks) ->
@@ -509,9 +445,13 @@ get_values(Vs, Ks) ->
s(undefined = T) ->
T;
+s({Pid, _Started, _State}) ->
+ state(Pid);
+s({Pid, _Started}) ->
+ state(Pid).
%% Collect states from watchdog/transport pids.
-s(Pid) ->
+state(Pid) ->
MRef = erlang:monitor(process, Pid),
Pid ! {state, self()},
receive
@@ -541,7 +481,18 @@ fields(diameter_stats) ->
[]
end;
-?FIELDS(diameter_service);
+fields(diameter_service) ->
+ [started,
+ name,
+ record_info(fields, diameter_service),
+ peerT,
+ connT,
+ share_peers,
+ use_shared_peers,
+ shared_peers,
+ local_peers,
+ monitor];
+
?FIELDS(diameter_event);
?FIELDS(diameter_uri);
?FIELDS(diameter_avp);
diff --git a/lib/diameter/src/app/diameter_dict.erl b/lib/diameter/src/base/diameter_dict.erl
index 3b9ba00a3f..3b9ba00a3f 100644
--- a/lib/diameter/src/app/diameter_dict.erl
+++ b/lib/diameter/src/base/diameter_dict.erl
diff --git a/lib/diameter/src/app/diameter_info.erl b/lib/diameter/src/base/diameter_info.erl
index 39d32d07cd..39d32d07cd 100644
--- a/lib/diameter/src/app/diameter_info.erl
+++ b/lib/diameter/src/base/diameter_info.erl
diff --git a/lib/diameter/src/app/diameter_internal.hrl b/lib/diameter/src/base/diameter_internal.hrl
index 9de3914830..63b35550a8 100644
--- a/lib/diameter/src/app/diameter_internal.hrl
+++ b/lib/diameter/src/base/diameter_internal.hrl
@@ -37,13 +37,14 @@
%% Failure reports always get a stack trace.
-define(STACK, erlang:get_stacktrace()).
-%% Info report for anything unexpected.
--define(REPORT(Reason, Func, Args),
- diameter_lib:report(Reason, {?MODULE, Func, Args})).
+%% Warning report for unexpected messages in various processes.
+-define(UNEXPECTED(F,A),
+ diameter_lib:warning_report(unexpected, {?MODULE, F, A})).
+-define(UNEXPECTED(A), ?UNEXPECTED(?FUNC, A)).
%% Something to trace on.
-define(LOG(Slogan, Details),
- diameter_dbg:log(Slogan, ?MODULE, ?LINE, Details)).
+ diameter_lib:log(Slogan, ?MODULE, ?LINE, Details)).
-define(LOGC(Bool, Slogan, Details), ((Bool) andalso ?LOG(Slogan, Details))).
%% Compensate for no builtin ?FUNC for use in log reports.
@@ -77,19 +78,3 @@
server_id,
is_dynamic,
expiration}).
-
-%%%----------------------------------------------------------------------
-%%% Error/warning/info message macro(s)
-%%%----------------------------------------------------------------------
-
--define(diameter_info(F, A),
- (catch error_logger:info_msg("[ ~w : ~w : ~p ] ~n" ++ F ++ "~n",
- [?APPLICATION, ?MODULE, self()|A]))).
-
--define(diameter_warning(F, A),
- (catch error_logger:warning_msg("[ ~w : ~w : ~p ] ~n" ++ F ++ "~n",
- [?APPLICATION, ?MODULE, self()|A]))).
-
--define(diameter_error(F, A),
- (catch error_logger:error_msg("[ ~w : ~w : ~p ] ~n" ++ F ++ "~n",
- [?APPLICATION, ?MODULE, self()|A]))).
diff --git a/lib/diameter/src/app/diameter_lib.erl b/lib/diameter/src/base/diameter_lib.erl
index b5c0e1bf6a..362d593b24 100644
--- a/lib/diameter/src/app/diameter_lib.erl
+++ b/lib/diameter/src/base/diameter_lib.erl
@@ -30,7 +30,8 @@
ipaddr/1,
spawn_opts/2,
wait/1,
- fold_tuple/3]).
+ fold_tuple/3,
+ log/4]).
-include("diameter_internal.hrl").
@@ -46,14 +47,9 @@
report(Reason, MFA) ->
info_report(Reason, MFA).
-info_report(Reason, {M,F,A}) ->
- error_logger:info_report(" Reason: ~p~n"
- " Pid: ~p~n"
- " Node: ~p~n"
- " Module: ~p~n"
- " Function: ~p~n"
- "Arguments: ~p~n",
- [Reason, self(), node(), M, F, A]).
+info_report(Reason, MFA) ->
+ report(fun error_logger:info_report/1, Reason, MFA),
+ true.
%%% ---------------------------------------------------------------------------
%%% # error_report(Reason, MFA)
@@ -69,7 +65,7 @@ warning_report(Reason, MFA) ->
report(fun error_logger:warning_report/1, Reason, MFA).
report(Fun, Reason, MFA) ->
- Fun([{reason, Reason}, {who, self()}, {where, node()}, {what, MFA}]),
+ Fun([{why, Reason}, {who, self()}, {what, MFA}]),
false.
%%% ---------------------------------------------------------------------------
@@ -255,12 +251,22 @@ w(L) ->
fold_tuple(_, T, undefined) ->
T;
-fold_tuple(N, T0, T) ->
- element(2, lists:foldl(fun(X, {M,_} = A) -> {M+1, ft(X, A)} end,
- {N, T0},
- lists:nthtail(N-1, tuple_to_list(T)))).
+fold_tuple(N, T0, T1) ->
+ {_, T} = lists:foldl(fun(V, {I,_} = IT) -> {I+1, ft(V, IT)} end,
+ {N, T0},
+ lists:nthtail(N-1, tuple_to_list(T1))),
+ T.
-ft(undefined, T) ->
+ft(undefined, {_, T}) ->
T;
-ft(X, {N, T}) ->
- setelement(N, T, X).
+ft(Value, {Idx, T}) ->
+ setelement(Idx, T, Value).
+
+%%% ----------------------------------------------------------
+%%% # log(Slogan, Mod, Line, Details)
+%%%
+%%% Called to have something to trace on for happenings of interest.
+%%% ----------------------------------------------------------
+
+log(_, _, _, _) ->
+ ok.
diff --git a/lib/diameter/src/app/diameter_misc_sup.erl b/lib/diameter/src/base/diameter_misc_sup.erl
index 4e40476f14..4e40476f14 100644
--- a/lib/diameter/src/app/diameter_misc_sup.erl
+++ b/lib/diameter/src/base/diameter_misc_sup.erl
diff --git a/lib/diameter/src/app/diameter_peer.erl b/lib/diameter/src/base/diameter_peer.erl
index 6b8971b8ea..3e78c4caef 100644
--- a/lib/diameter/src/app/diameter_peer.erl
+++ b/lib/diameter/src/base/diameter_peer.erl
@@ -148,7 +148,7 @@ handle_call(uptime, _, #state{id = Time} = State) ->
{reply, diameter_lib:now_diff(Time), State};
handle_call(Req, From, State) ->
- warning_msg("received unexpected request from ~p:~n~w", [From, Req]),
+ ?UNEXPECTED([Req, From]),
{reply, nok, State}.
%%% ----------------------------------------------------------
@@ -156,7 +156,7 @@ handle_call(Req, From, State) ->
%%% ----------------------------------------------------------
handle_cast(Msg, State) ->
- warning_msg("received unexpected message:~n~w", [Msg]),
+ ?UNEXPECTED([Msg]),
{noreply, State}.
%%% ----------------------------------------------------------
@@ -169,7 +169,7 @@ handle_info({notify, SvcName, T}, S) ->
{noreply, S};
handle_info(Info, State) ->
- warning_msg("received unexpected info:~n~w", [Info]),
+ ?UNEXPECTED([Info]),
{noreply, State}.
%% ----------------------------------------------------------
@@ -223,8 +223,3 @@ value([], V) ->
call(Request) ->
gen_server:call(?SERVER, Request, infinity).
-
-%% warning_msg/2
-
-warning_msg(F, A) ->
- ?diameter_warning("~p: " ++ F, [?MODULE | A]).
diff --git a/lib/diameter/src/app/diameter_peer_fsm.erl b/lib/diameter/src/base/diameter_peer_fsm.erl
index 0252fb3809..fae5d763dc 100644
--- a/lib/diameter/src/app/diameter_peer_fsm.erl
+++ b/lib/diameter/src/base/diameter_peer_fsm.erl
@@ -52,7 +52,11 @@
-define(GOAWAY, ?'DIAMETER_BASE_DISCONNECT-CAUSE_DO_NOT_WANT_TO_TALK_TO_YOU').
-define(REBOOT, ?'DIAMETER_BASE_DISCONNECT-CAUSE_REBOOTING').
--define(LOOP_TIMEOUT, 2000).
+-define(NO_INBAND_SECURITY, 0).
+-define(TLS, 1).
+
+%% A 2xxx series Result-Code. Not necessarily 2001.
+-define(IS_SUCCESS(N), 2 == (N) div 1000).
%% RFC 3588:
%%
@@ -139,9 +143,12 @@ init(T) ->
proc_lib:init_ack({ok, self()}),
gen_server:enter_loop(?MODULE, [], i(T)).
-i({WPid, {M, _} = T, Opts, #diameter_service{capabilities = Caps} = Svc0}) ->
+i({WPid, T, Opts, #diameter_service{capabilities = Caps} = Svc0}) ->
putr(dwa, dwa(Caps)),
- {ok, TPid, Svc} = start_transport(T, Opts, Svc0),
+ {M, Ref} = T,
+ {[Ts], Rest} = proplists:split(Opts, [capabilities_cb]),
+ putr(capabilities_cb, {Ref, [F || {_,F} <- Ts]}),
+ {ok, TPid, Svc} = start_transport(T, Rest, Svc0),
erlang:monitor(process, TPid),
erlang:monitor(process, WPid),
#state{parent = WPid,
@@ -195,12 +202,13 @@ handle_info(T, #state{} = State) ->
?LOG(stop, T),
x(T, State)
catch
- throw: {?MODULE, close = C, Reason} ->
- ?LOG(C, {Reason, T}),
- x(Reason, State);
- throw: {?MODULE, abort, Reason} ->
+ {?MODULE, Tag, Reason} ->
+ ?LOG(Tag, {Reason, T}),
{stop, {shutdown, Reason}, State}
end.
+%% The form of the exception caught here is historical. It's
+%% significant that it's not a 2-tuple, as in ?FAILURE(Reason),
+%% since these are caught elsewhere.
x(Reason, #state{} = S) ->
close_wd(Reason, S),
@@ -225,6 +233,9 @@ putr(Key, Val) ->
getr(Key) ->
get({?MODULE, Key}).
+eraser(Key) ->
+ erase({?MODULE, Key}).
+
%% transition/2
%% Connection to peer.
@@ -281,10 +292,9 @@ transition(shutdown, _) -> %% DPR already send: ensure expected timeout
%% Request to close the transport connection.
transition({close = T, Pid}, #state{parent = Pid,
- transport = TPid}
- = S) ->
+ transport = TPid}) ->
diameter_peer:close(TPid),
- close(T,S);
+ {stop, T};
%% DPA reception has timed out.
transition(dpa_timeout, _) ->
@@ -316,9 +326,10 @@ send_CER(#state{mode = {connect, Remote},
service = #diameter_service{capabilities = Caps},
transport = TPid}
= S) ->
- req_send_CER(Caps#diameter_caps.origin_host, Remote)
+ OH = Caps#diameter_caps.origin_host,
+ req_send_CER(OH, Remote)
orelse
- close(connected, S),
+ close({already_connected, Remote, Caps}, S),
CER = build_CER(S),
?LOG(send, 'CER'),
send(TPid, encode(CER)),
@@ -418,11 +429,11 @@ rcv('CER' = N, Pkt, #state{state = recv_CER} = S) ->
%% Anything but CER/CEA in a non-Open state is an error, as is
%% CER/CEA in anything but recv_CER/Wait-CEA.
-rcv(Name, _, #state{state = PS} = S)
+rcv(Name, _, #state{state = PS})
when PS /= 'Open';
Name == 'CER';
Name == 'CEA' ->
- close({Name, PS}, S);
+ {stop, {Name, PS}};
rcv(N, Pkt, S)
when N == 'DWR';
@@ -460,20 +471,20 @@ handle_request(Type, #diameter_packet{} = Pkt, S) ->
%% send_answer/3
send_answer(Type, ReqPkt, #state{transport = TPid} = S) ->
- #diameter_packet{header = #diameter_header{version = V,
- end_to_end_id = Eid,
- hop_by_hop_id = Hid,
- is_proxiable = P},
+ #diameter_packet{header = H,
transport_data = TD}
= ReqPkt,
- {Answer, PostF} = build_answer(Type, V, ReqPkt, S),
+ {Msg, PostF} = build_answer(Type, ReqPkt, S),
- Pkt = #diameter_packet{header = #diameter_header{version = V,
- end_to_end_id = Eid,
- hop_by_hop_id = Hid,
- is_proxiable = P},
- msg = Answer,
+ %% An answer message clears the R and T flags and retains the P
+ %% flag. The E flag is set at encode.
+ Pkt = #diameter_packet{header
+ = H#diameter_header{version = ?DIAMETER_VERSION,
+ is_request = false,
+ is_error = undefined,
+ is_retransmitted = false},
+ msg = Msg,
transport_data = TD},
send(TPid, diameter_codec:encode(?BASE, Pkt)),
@@ -484,51 +495,104 @@ eval([F|A], S) ->
eval(ok, S) ->
S.
-%% build_answer/4
+%% build_answer/3
build_answer('CER',
- ?DIAMETER_VERSION,
#diameter_packet{msg = CER,
- header = #diameter_header{is_error = false},
+ header = #diameter_header{version
+ = ?DIAMETER_VERSION,
+ is_error = false},
errors = []}
= Pkt,
- #state{service = Svc}
- = S) ->
- #diameter_service{capabilities = #diameter_caps{origin_host = OH}}
- = Svc,
-
- {SupportedApps, #diameter_caps{origin_host = DH} = RCaps, CEA}
+ S) ->
+ {SupportedApps, RCaps, #diameter_base_CEA{'Result-Code' = RC,
+ 'Inband-Security-Id' = IS}
+ = CEA}
= recv_CER(CER, S),
+ #diameter_caps{origin_host = {OH, DH}}
+ = Caps
+ = capz(caps(S), RCaps),
+
try
- [] == SupportedApps
- andalso ?THROW({no_common_application, 5010}),
+ 2001 == RC %% DIAMETER_SUCCESS
+ orelse ?THROW(RC),
register_everywhere({?MODULE, connection, OH, DH})
- orelse ?THROW({election_lost, 4003}),
- {CEA, [fun open/4, Pkt, SupportedApps, RCaps]}
+ orelse ?THROW(4003), %% DIAMETER_ELECTION_LOST
+ caps_cb(Caps)
+ of
+ N -> {cea(CEA, N), [fun open/5, Pkt,
+ SupportedApps,
+ Caps,
+ {accept, hd([_] = IS)}]}
catch
- ?FAILURE({Reason, RC}) ->
- {answer('CER', S) ++ [{'Result-Code', RC}],
- [fun close/2, {'CER', Reason, DH}]}
+ ?FAILURE(Reason) ->
+ rejected(Reason, {'CER', Reason, Caps, Pkt}, S)
end;
%% The error checks below are similar to those in diameter_service for
%% other messages. Should factor out the commonality.
-build_answer(Type, V, #diameter_packet{header = H, errors = Es} = Pkt, S) ->
- FailedAvp = failed_avp([A || {_,A} <- Es]),
- Ans = answer(answer(Type, S), V, H, Es),
- {set(Ans, FailedAvp), if 'CER' == Type ->
- [fun close/2, {Type, V, Pkt}];
- true ->
- ok
- end}.
+build_answer(Type,
+ #diameter_packet{header = H,
+ errors = Es}
+ = Pkt,
+ S) ->
+ RC = rc(H, Es),
+ {answer(Type, RC, Es, S), post(Type, RC, Pkt, S)}.
+
+cea(CEA, ok) ->
+ CEA;
+cea(CEA, 2001) ->
+ CEA;
+cea(CEA, RC) ->
+ CEA#diameter_base_CEA{'Result-Code' = RC}.
+
+post('CER' = T, RC, Pkt, S) ->
+ [fun close/2, {T, caps(S), {RC, Pkt}}];
+post(_, _, _, _) ->
+ ok.
+
+rejected({capabilities_cb, _F, Reason}, T, S) ->
+ rejected(Reason, T, S);
+
+rejected(discard, T, S) ->
+ close(T, S);
+rejected({N, Es}, T, S) ->
+ {answer('CER', N, Es, S), [fun close/2, T]};
+rejected(N, T, S) ->
+ rejected({N, []}, T, S).
+
+answer(Type, RC, Es, S) ->
+ set(answer(Type, RC, S), failed_avp([A || {_,A} <- Es])).
+
+answer(Type, RC, S) ->
+ answer_message(answer(Type, S), RC).
+%% answer_message/2
+
+answer_message([_ | Avps], RC)
+ when 3000 =< RC, RC < 4000 ->
+ ['answer-message', {'Result-Code', RC}
+ | lists:filter(fun is_origin/1, Avps)];
+
+answer_message(Msg, RC) ->
+ Msg ++ [{'Result-Code', RC}].
+
+is_origin({N, _}) ->
+ N == 'Origin-Host'
+ orelse N == 'Origin-Realm'
+ orelse N == 'Origin-State-Id'.
+
+%% failed_avp/1
+
failed_avp([] = No) ->
No;
failed_avp(Avps) ->
[{'Failed-AVP', [[{'AVP', Avps}]]}].
+%% set/2
+
set(Ans, []) ->
Ans;
set(['answer-message' | _] = Ans, FailedAvp) ->
@@ -536,18 +600,22 @@ set(['answer-message' | _] = Ans, FailedAvp) ->
set([_|_] = Ans, FailedAvp) ->
Ans ++ FailedAvp.
-answer([_, OH, OR | _], _, #diameter_header{is_error = true}, _) ->
- ['answer-message', OH, OR, {'Result-Code', 3008}];
+%% rc/2
+
+rc(#diameter_header{is_error = true}, _) ->
+ 3008; %% DIAMETER_INVALID_HDR_BITS
-answer([_, OH, OR | _], _, _, [Bs|_])
+rc(_, [Bs|_])
when is_bitstring(Bs) ->
- ['answer-message', OH, OR, {'Result-Code', 3009}];
+ 3009; %% DIAMETER_INVALID_HDR_BITS
-answer(Ans, ?DIAMETER_VERSION, _, Es) ->
- Ans ++ [{'Result-Code', rc(Es)}];
+rc(#diameter_header{version = ?DIAMETER_VERSION}, Es) ->
+ rc(Es);
-answer(Ans, _, _, _) ->
- Ans ++ [{'Result-Code', 5011}]. %% DIAMETER_UNSUPPORTED_VERSION
+rc(_, _) ->
+ 5011. %% DIAMETER_UNSUPPORTED_VERSION
+
+%% rc/1
rc([]) ->
2001; %% DIAMETER_SUCCESS
@@ -590,12 +658,14 @@ a('CER', #diameter_caps{vendor_id = Vid,
origin_host = Host,
origin_realm = Realm,
host_ip_address = Addrs,
- product_name = Name}) ->
+ product_name = Name,
+ origin_state_id = OSI}) ->
['CEA', {'Origin-Host', Host},
{'Origin-Realm', Realm},
{'Host-IP-Address', Addrs},
{'Vendor-Id', Vid},
- {'Product-Name', Name}];
+ {'Product-Name', Name},
+ {'Origin-State-Id', OSI}];
a('DPR', #diameter_caps{origin_host = Host,
origin_realm = Realm}) ->
@@ -610,23 +680,25 @@ recv_CER(CER, #state{service = Svc}) ->
%% handle_CEA/1
-handle_CEA(#diameter_packet{header = #diameter_header{version = V},
- bin = Bin}
+handle_CEA(#diameter_packet{bin = Bin}
= Pkt,
- #state{service = Svc}
+ #state{service = #diameter_service{capabilities = LCaps}}
= S)
when is_binary(Bin) ->
?LOG(recv, 'CEA'),
- ?DIAMETER_VERSION == V orelse close({version, V}, S),
-
- #diameter_packet{msg = CEA, errors = Errors}
+ #diameter_packet{msg = CEA}
= DPkt
= diameter_codec:decode(?BASE, Pkt),
- [] == Errors orelse close({errors, Errors}, S),
+ {SApps, IS, RCaps} = recv_CEA(DPkt, S),
+
+ #diameter_caps{origin_host = {OH, DH}}
+ = Caps
+ = capz(LCaps, RCaps),
- {SApps, #diameter_caps{origin_host = DH} = RCaps} = recv_CEA(CEA, S),
+ #diameter_base_CEA{'Result-Code' = RC}
+ = CEA,
%% Ensure that we don't already have a connection to the peer in
%% question. This isn't the peer election of 3588 except in the
@@ -634,40 +706,103 @@ handle_CEA(#diameter_packet{header = #diameter_header{version = V},
%% receive a CER/CEA, the first that arrives wins the right to a
%% connection with the peer.
- #diameter_service{capabilities = #diameter_caps{origin_host = OH}}
- = Svc,
+ try
+ ?IS_SUCCESS(RC)
+ orelse ?THROW(RC),
+ [] == SApps
+ andalso ?THROW(no_common_application),
+ [] == IS
+ andalso ?THROW(no_common_security),
+ register_everywhere({?MODULE, connection, OH, DH})
+ orelse ?THROW(election_lost),
+ caps_cb(Caps)
+ of
+ _ -> open(DPkt, SApps, Caps, {connect, hd([_] = IS)}, S)
+ catch
+ ?FAILURE(Reason) -> close({'CEA', Reason, Caps, DPkt}, S)
+ end.
+%% Check more than the result code since the peer could send success
+%% regardless. If not 2001 then a peer_up callback could do anything
+%% required. It's not unimaginable that a peer agreeing to TLS after
+%% capabilities exchange could send DIAMETER_LIMITED_SUCCESS = 2002,
+%% even if this isn't required by RFC 3588.
- register_everywhere({?MODULE, connection, OH, DH})
- orelse
- close({'CEA', DH}, S),
+%% recv_CEA/2
- open(DPkt, SApps, RCaps, S).
+recv_CEA(#diameter_packet{header = #diameter_header{version
+ = ?DIAMETER_VERSION,
+ is_error = false},
+ msg = CEA,
+ errors = []},
+ #state{service = Svc}) ->
+ {ok, T} = diameter_capx:recv_CEA(CEA, Svc),
+ T;
-%% recv_CEA/2
+recv_CEA(Pkt, S) ->
+ close({'CEA', caps(S), Pkt}, S).
-recv_CEA(CEA, #state{service = Svc} = S) ->
- case diameter_capx:recv_CEA(CEA, Svc) of
- {ok, {[], _}} ->
- close({'CEA', no_common_application}, S);
- {ok, T} ->
- T;
- {error, Reason} ->
- close({'CEA', Reason}, S)
+caps(#diameter_service{capabilities = Caps}) ->
+ Caps;
+caps(#state{service = Svc}) ->
+ caps(Svc).
+
+%% caps_cb/1
+
+caps_cb(Caps) ->
+ {Ref, Ts} = eraser(capabilities_cb),
+ ccb(Ts, [Ref, Caps]).
+
+ccb([], _) ->
+ ok;
+ccb([F | Rest], T) ->
+ case diameter_lib:eval([F|T]) of
+ ok ->
+ ccb(Rest, T);
+ N when ?IS_SUCCESS(N) -> %% 2xxx result code: accept immediately
+ N;
+ Res ->
+ ?THROW({capabilities_cb, F, rejected(Res)})
end.
+%% Note that returning 2xxx causes the capabilities exchange to be
+%% accepted directly, without further callbacks.
+
+rejected(discard = T) ->
+ T;
+rejected(unknown) ->
+ 3010; %% DIAMETER_UNKNOWN_PEER
+rejected(N)
+ when is_integer(N) ->
+ N.
+
+%% open/5
+
+open(Pkt, SupportedApps, Caps, {Type, IS}, #state{parent = Pid} = S) ->
+ #diameter_caps{origin_host = {_,_} = H,
+ inband_security_id = {LS,_}}
+ = Caps,
+
+ tls_ack(lists:member(?TLS, LS), Caps, Type, IS, S),
+ Pid ! {open, self(), H, {Caps, SupportedApps, Pkt}},
-%% open/4
-
-open(Pkt, SupportedApps, RCaps, #state{parent = Pid,
- service = Svc}
- = S) ->
- #diameter_service{capabilities = #diameter_caps{origin_host = OH}
- = LCaps}
- = Svc,
- #diameter_caps{origin_host = DH}
- = RCaps,
- Pid ! {open, self(), {OH,DH}, {capz(LCaps, RCaps), SupportedApps, Pkt}},
S#state{state = 'Open'}.
+%% We've advertised TLS support: tell the transport the result
+%% and expect a reply when the handshake is complete.
+tls_ack(true, Caps, Type, IS, #state{transport = TPid} = S) ->
+ Ref = make_ref(),
+ TPid ! {diameter, {tls, Ref, Type, IS == ?TLS}},
+ receive
+ {diameter, {tls, Ref}} ->
+ ok;
+ {'DOWN', _, process, TPid, Reason} ->
+ close({tls_ack, Reason, Caps}, S)
+ end;
+
+%% Or not. Don't send anything to the transport so that transports
+%% not supporting TLS work as before without modification.
+tls_ack(false, _, _, _, _) ->
+ ok.
+
capz(#diameter_caps{} = L, #diameter_caps{} = R) ->
#diameter_caps{}
= list_to_tuple([diameter_caps | lists:zip(tl(tuple_to_list(L)),
diff --git a/lib/diameter/src/app/diameter_peer_fsm_sup.erl b/lib/diameter/src/base/diameter_peer_fsm_sup.erl
index 995eaf74d0..995eaf74d0 100644
--- a/lib/diameter/src/app/diameter_peer_fsm_sup.erl
+++ b/lib/diameter/src/base/diameter_peer_fsm_sup.erl
diff --git a/lib/diameter/src/app/diameter_reg.erl b/lib/diameter/src/base/diameter_reg.erl
index 8e5f34c2c3..882b9da238 100644
--- a/lib/diameter/src/app/diameter_reg.erl
+++ b/lib/diameter/src/base/diameter_reg.erl
@@ -243,7 +243,8 @@ handle_call(state, _, State) ->
handle_call(uptime, _, #state{id = Time} = State) ->
{reply, diameter_lib:now_diff(Time), State};
-handle_call(_Req, _From, State) ->
+handle_call(Req, From, State) ->
+ ?UNEXPECTED([Req, From]),
{reply, nok, State}.
%%% ----------------------------------------------------------
@@ -251,7 +252,7 @@ handle_call(_Req, _From, State) ->
%%% ----------------------------------------------------------
handle_cast(Msg, State)->
- warning_msg("received unexpected message:~n~w", [Msg]),
+ ?UNEXPECTED([Msg]),
{noreply, State}.
%%% ----------------------------------------------------------
@@ -264,7 +265,7 @@ handle_info({'DOWN', MRef, process, Pid, _}, State) ->
{noreply, State};
handle_info(Info, State) ->
- warning_msg("received unknown info:~n~w", [Info]),
+ ?UNEXPECTED([Info]),
{noreply, State}.
%%% ----------------------------------------------------------
@@ -324,8 +325,3 @@ repl([], _, _) ->
call(Request) ->
gen_server:call(?SERVER, Request, infinity).
-
-%% warning_msg/2
-
-warning_msg(F, A) ->
- ?diameter_warning("~p: " ++ F, [?MODULE | A]).
diff --git a/lib/diameter/src/app/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl
index 63b0649dc4..7adcf1c265 100644
--- a/lib/diameter/src/app/diameter_service.erl
+++ b/lib/diameter/src/base/diameter_service.erl
@@ -463,7 +463,7 @@ handle_call(stop, _From, S) ->
%% stating a monitor that waits for DOWN before returning.
handle_call(Req, From, S) ->
- ?REPORT(unknown_request, ?FUNC, [Req, From]),
+ unexpected(handle_call, [Req, From], S),
{reply, nok, S}.
%%% ---------------------------------------------------------------------------
@@ -471,7 +471,7 @@ handle_call(Req, From, S) ->
%%% ---------------------------------------------------------------------------
handle_cast(Req, S) ->
- ?REPORT(unknown_request, ?FUNC, [Req]),
+ unexpected(handle_cast, [Req], S),
{noreply, S}.
%%% ---------------------------------------------------------------------------
@@ -553,8 +553,8 @@ transition({failover, TRef, Seqs}, S) ->
failover(TRef, Seqs, S),
ok;
-transition(Req, _) ->
- ?REPORT(unknown_request, ?FUNC, [Req]),
+transition(Req, S) ->
+ unexpected(handle_info, [Req], S),
ok.
%%% ---------------------------------------------------------------------------
@@ -591,6 +591,9 @@ code_change(FromVsn, SvcName, Extra, #diameter_app{alias = Alias} = A) ->
%% ===========================================================================
%% ===========================================================================
+unexpected(F, A, #state{service_name = Name}) ->
+ ?UNEXPECTED(F, A ++ [Name]).
+
cb([_|_] = M, F, A) ->
eval(M, F, A);
cb(Rec, F, A) ->
@@ -980,7 +983,8 @@ peer_cb(MFA, Alias) ->
connection_down(Pid, #state{peerT = PeerT,
connT = ConnT}
= S) ->
- #peer{conn = TPid}
+ #peer{op_state = ?STATE_UP, %% assert
+ conn = TPid}
= P
= fetch(PeerT, Pid),
@@ -990,6 +994,9 @@ connection_down(Pid, #state{peerT = PeerT,
%% connection_down/3
+connection_down(#peer{op_state = ?STATE_DOWN}, _, S) ->
+ S;
+
connection_down(#peer{conn = TPid,
op_state = ?STATE_UP}
= P,
@@ -1031,13 +1038,23 @@ down_conn(Id, Alias, TC, {SvcName, Apps}) ->
%% Peer process has died.
-peer_down(Pid, _Reason, #state{peerT = PeerT} = S) ->
+peer_down(Pid, Reason, #state{peerT = PeerT} = S) ->
P = fetch(PeerT, Pid),
ets:delete_object(PeerT, P),
+ closed(Reason, P, S),
restart(P,S),
peer_down(P,S).
-%% peer_down/2
+%% Send an event at connection establishment failure.
+closed({shutdown, {close, _TPid, Reason}},
+ #peer{op_state = ?STATE_DOWN,
+ ref = Ref,
+ type = Type,
+ options = Opts},
+ #state{service_name = SvcName}) ->
+ send_event(SvcName, {closed, Ref, Reason, {type(Type), Opts}});
+closed(_, _, _) ->
+ ok.
%% The peer has never come up ...
peer_down(#peer{conn = B}, S)
@@ -1045,27 +1062,9 @@ peer_down(#peer{conn = B}, S)
S;
%% ... or it has.
-peer_down(#peer{ref = Ref,
- conn = TPid,
- type = Type,
- options = Opts}
- = P,
- #state{service_name = SvcName,
- connT = ConnT}
- = S) ->
- #conn{caps = Caps}
- = C
- = fetch(ConnT, TPid),
+peer_down(#peer{conn = TPid} = P, #state{connT = ConnT} = S) ->
+ #conn{} = C = fetch(ConnT, TPid),
ets:delete_object(ConnT, C),
- try
- pd(P,C,S)
- after
- send_event(SvcName, {closed, Ref, {TPid, Caps}, {type(Type), Opts}})
- end.
-
-pd(#peer{op_state = ?STATE_DOWN}, _, S) ->
- S;
-pd(#peer{op_state = ?STATE_UP} = P, C, S) ->
connection_down(P,C,S).
%% restart/2
@@ -1256,11 +1255,11 @@ send_request({TPid, Caps, App}, Msg, Opts, Caller, SvcName) ->
#diameter_app{module = ModX}
= App,
- Pkt = make_packet(Msg),
+ Pkt = make_request_packet(Msg),
case cb(ModX, prepare_request, [Pkt, SvcName, {TPid, Caps}]) of
{send, P} ->
- send_request(make_packet(P, Pkt),
+ send_request(make_request_packet(P, Pkt),
TPid,
Caps,
App,
@@ -1275,70 +1274,73 @@ send_request({TPid, Caps, App}, Msg, Opts, Caller, SvcName) ->
?ERROR({invalid_return, prepare_request, App, T})
end.
-%% make_packet/1
+%% make_request_packet/1
%%
%% Turn an outgoing request as passed to call/4 into a diameter_packet
%% record in preparation for a prepare_request callback.
-make_packet(Bin)
+make_request_packet(Bin)
when is_binary(Bin) ->
#diameter_packet{header = diameter_codec:decode_header(Bin),
bin = Bin};
-make_packet(#diameter_packet{msg = [#diameter_header{} = Hdr | Avps]} = Pkt) ->
- Pkt#diameter_packet{msg = [make_header(Hdr) | Avps]};
+make_request_packet(#diameter_packet{msg = [#diameter_header{} = Hdr | Avps]}
+ = Pkt) ->
+ Pkt#diameter_packet{msg = [make_request_header(Hdr) | Avps]};
-make_packet(#diameter_packet{header = Hdr} = Pkt) ->
- Pkt#diameter_packet{header = make_header(Hdr)};
+make_request_packet(#diameter_packet{header = Hdr} = Pkt) ->
+ Pkt#diameter_packet{header = make_request_header(Hdr)};
-make_packet(Msg) ->
- make_packet(#diameter_packet{msg = Msg}).
+make_request_packet(Msg) ->
+ make_request_packet(#diameter_packet{msg = Msg}).
-%% make_header/1
+%% make_request_header/1
-make_header(undefined) ->
+make_request_header(undefined) ->
Seq = diameter_session:sequence(),
- make_header(#diameter_header{end_to_end_id = Seq,
- hop_by_hop_id = Seq});
+ make_request_header(#diameter_header{end_to_end_id = Seq,
+ hop_by_hop_id = Seq});
-make_header(#diameter_header{version = undefined} = Hdr) ->
- make_header(Hdr#diameter_header{version = ?DIAMETER_VERSION});
+make_request_header(#diameter_header{version = undefined} = Hdr) ->
+ make_request_header(Hdr#diameter_header{version = ?DIAMETER_VERSION});
-make_header(#diameter_header{end_to_end_id = undefined} = H) ->
+make_request_header(#diameter_header{end_to_end_id = undefined} = H) ->
Seq = diameter_session:sequence(),
- make_header(H#diameter_header{end_to_end_id = Seq});
+ make_request_header(H#diameter_header{end_to_end_id = Seq});
-make_header(#diameter_header{hop_by_hop_id = undefined} = H) ->
+make_request_header(#diameter_header{hop_by_hop_id = undefined} = H) ->
Seq = diameter_session:sequence(),
- make_header(H#diameter_header{hop_by_hop_id = Seq});
+ make_request_header(H#diameter_header{hop_by_hop_id = Seq});
-make_header(#diameter_header{} = Hdr) ->
+make_request_header(#diameter_header{} = Hdr) ->
Hdr;
-make_header(T) ->
+make_request_header(T) ->
?ERROR({invalid_header, T}).
-%% make_packet/2
+%% make_request_packet/2
%%
%% Reconstruct a diameter_packet from the return value of
%% prepare_request or prepare_retransmit callback.
-make_packet(Bin, _)
+make_request_packet(Bin, _)
when is_binary(Bin) ->
- make_packet(Bin);
+ make_request_packet(Bin);
-make_packet(#diameter_packet{msg = [#diameter_header{} | _]} = Pkt, _) ->
+make_request_packet(#diameter_packet{msg = [#diameter_header{} | _]}
+ = Pkt,
+ _) ->
Pkt;
%% Returning a diameter_packet with no header from a prepare_request
%% or prepare_retransmit callback retains the header passed into it.
%% This is primarily so that the end to end and hop by hop identifiers
%% are retained.
-make_packet(#diameter_packet{header = Hdr} = Pkt,
+make_request_packet(#diameter_packet{header = Hdr} = Pkt,
#diameter_packet{header = Hdr0}) ->
Pkt#diameter_packet{header = fold_record(Hdr0, Hdr)};
-make_packet(Msg, Pkt) ->
+make_request_packet(Msg, Pkt) ->
Pkt#diameter_packet{msg = Msg}.
%% fold_record/2
@@ -1398,15 +1400,15 @@ recv_answer(Timeout,
%% is, from the last peer to which we've transmitted.
receive
- {answer = A, Ref, Rq, Pkt} -> %% Answer from peer.
+ {answer = A, Ref, Rq, Pkt} -> %% Answer from peer
{A, Rq, Pkt};
- {timeout = Reason, TRef, _} -> %% No timely reply
+ {timeout = Reason, TRef, _} -> %% No timely reply
{error, Req, Reason};
- {failover = Reason, TRef, false} -> %% No alternative peer.
+ {failover = Reason, TRef, false} -> %% No alternate peer
{error, Req, Reason};
- {failover, TRef, Transport} -> %% Resend to alternate peer.
+ {failover, TRef, Transport} -> %% Resend to alternate peer
try_retransmit(Timeout, SvcName, Req, Transport);
- {failover, TRef} -> %% May have missed failover notification.
+ {failover, TRef} -> %% May have missed failover notification
Seqs = diameter_codec:sequence_numbers(RPkt),
Pid = whois(SvcName),
is_pid(Pid) andalso (Pid ! {failover, TRef, Seqs}),
@@ -1530,7 +1532,7 @@ retransmit({TPid, Caps, #diameter_app{alias = Alias} = App},
case cb(App, prepare_retransmit, [Pkt, SvcName, {TPid, Caps}]) of
{send, P} ->
- retransmit(make_packet(P, Pkt), TPid, Caps, Req, Timeout);
+ retransmit(make_request_packet(P, Pkt), TPid, Caps, Req, Timeout);
{discard, Reason} ->
?THROW(Reason);
discard ->
@@ -1685,9 +1687,9 @@ recv_request({Id, Alias}, T, TPid, Apps, Caps, Pkt) ->
%% DIAMETER_APPLICATION_UNSUPPORTED 3007
%% A request was sent for an application that is not supported.
-recv_request(false, {_, OH, OR}, TPid, _, _, Pkt) ->
- ?LOG({error, application}, Pkt),
- reply(answer_message({OH, OR, 3007}, collect_avps(Pkt)), ?BASE, TPid, Pkt).
+recv_request(false, T, TPid, _, _, Pkt) ->
+ As = collect_avps(Pkt),
+ protocol_error(3007, T, TPid, Pkt#diameter_packet{avps = As}).
collect_avps(Pkt) ->
case diameter_codec:collect_avps(Pkt) of
@@ -1706,13 +1708,9 @@ collect_avps(Pkt) ->
%% set to an unrecognized value, or that is inconsistent with the
%% AVP's definition.
%%
-recv_request({_, OH, OR}, {TPid, _}, _, #diameter_packet{errors = [Bs | _],
- bin = Bin,
- avps = Avps}
- = Pkt)
+recv_request(T, {TPid, _}, _, #diameter_packet{errors = [Bs | _]} = Pkt)
when is_bitstring(Bs) ->
- ?LOG({error, invalid_avp_bits}, Bin),
- reply(answer_message({OH, OR, 3009}, Avps), ?BASE, TPid, Pkt);
+ protocol_error(3009, T, TPid, Pkt);
%% Either we support this application but don't recognize the command
%% or we're a relay and the command isn't proxiable.
@@ -1722,18 +1720,15 @@ recv_request({_, OH, OR}, {TPid, _}, _, #diameter_packet{errors = [Bs | _],
%% recognize or support. This MUST be used when a Diameter node
%% receives an experimental command that it does not understand.
%%
-recv_request({_, OH, OR},
+recv_request(T,
{TPid, _},
#diameter_app{id = Id},
#diameter_packet{header = #diameter_header{is_proxiable = P},
- msg = M,
- avps = Avps,
- bin = Bin}
+ msg = M}
= Pkt)
when ?APP_ID_RELAY /= Id, undefined == M;
?APP_ID_RELAY == Id, not P ->
- ?LOG({error, command_unsupported}, Bin),
- reply(answer_message({OH, OR, 3001}, Avps), ?BASE, TPid, Pkt);
+ protocol_error(3001, T, TPid, Pkt);
%% Error bit was set on a request.
%%
@@ -1742,15 +1737,12 @@ recv_request({_, OH, OR},
%% either set to an invalid combination, or to a value that is
%% inconsistent with the command code's definition.
%%
-recv_request({_, OH, OR},
+recv_request(T,
{TPid, _},
_,
- #diameter_packet{header = #diameter_header{is_error = true},
- avps = Avps,
- bin = Bin}
+ #diameter_packet{header = #diameter_header{is_error = true}}
= Pkt) ->
- ?LOG({error, error_bit}, Bin),
- reply(answer_message({OH, OR, 3008}, Avps), ?BASE, TPid, Pkt);
+ protocol_error(3008, T, TPid, Pkt);
%% A message in a locally supported application or a proxiable message
%% in the relay application. Don't distinguish between the two since
@@ -1878,7 +1870,7 @@ resend(true, _, _, T, {TPid, _}, Pkt) -> %% Route-Record loop
resend(false,
Opts,
App,
- {SvcName, _, _},
+ {SvcName, _, _} = T,
{TPid, #diameter_caps{origin_host = {_, OH}}},
#diameter_packet{header = Hdr0,
avps = Avps}
@@ -1887,46 +1879,41 @@ resend(false,
Seq = diameter_session:sequence(),
Hdr = Hdr0#diameter_header{hop_by_hop_id = Seq},
Msg = [Hdr, Route | Avps],
- %% Filter sender as ineligible receiver.
- reply(call(SvcName, App, Msg, [{filter, {neg, {host, OH}}} | Opts]),
- TPid,
- Pkt).
+ resend(call(SvcName, App, Msg, Opts), T, TPid, Pkt).
%% The incoming request is relayed with the addition of a
-%% Route-Record. Note the requirement on the return from call/4.
-%% This places a requirement on the values returned by the
-%% handle_answer and handle_error callbacks of the application module
-%% in question.
+%% Route-Record. Note the requirement on the return from call/4 below,
+%% which places a requirement on the value returned by the
+%% handle_answer callback of the application module in question.
+%%
+%% Note that there's nothing stopping the request from being relayed
+%% back to the sender. A pick_peer callback may want to avoid this but
+%% a smart peer might recognize the potential loop and choose another
+%% route. A less smart one will probably just relay the request back
+%% again and force us to detect the loop. A pick_peer that wants to
+%% avoid this can specify filter to avoid the possibility.
+%% Eg. {neg, {host, OH} where #diameter_caps{origin_host = {OH, _}}.
%%
%% RFC 6.3 says that a relay agent does not modify Origin-Host but
%% says nothing about a proxy. Assume it should behave the same way.
-%% reply/3
+%% resend/4
%%
%% Relay a reply to a relayed request.
%% Answer from the peer: reset the hop by hop identifier and send.
-reply(#diameter_packet{bin = B}
- = Pkt,
- TPid,
- #diameter_packet{header = #diameter_header{hop_by_hop_id = Id},
- transport_data = TD}) ->
+resend(#diameter_packet{bin = B}
+ = Pkt,
+ _,
+ TPid,
+ #diameter_packet{header = #diameter_header{hop_by_hop_id = Id},
+ transport_data = TD}) ->
send(TPid, Pkt#diameter_packet{bin = diameter_codec:hop_by_hop_id(Id, B),
transport_data = TD});
%% TODO: counters
-%% Not. Ignoring the error feels harsh but there is no appropriate
-%% Result-Code for a protocol error (which this isn't really anyway)
-%% and the RFC doesn't provide any guidance how to act. A weakness
-%% here is that we don't deal well with a decode error: the request
-%% will simply timeout on the peer's end. Better would be to just send
-%% the answer (with modified hop by hop identifier) on regardless, at
-%% least in the relay case in which there's no examination of the
-%% answer. In the proxy case it's not clear that the callback won't
-%% examine the answer. Just be quiet here since a decode error causes
-%% the request process to crash (or not depending on the error and
-%% config and/or handle_answer callback).
-reply(_, _, _) ->
- ok.
+%% Or not: DIAMETER_UNABLE_TO_DELIVER.
+resend(_, T, TPid, Pkt) ->
+ protocol_error(3002, T, TPid, Pkt).
%% is_loop/4
%%
@@ -1958,7 +1945,7 @@ reply(Msg, Dict, TPid, #diameter_packet{errors = Es,
= ReqPkt)
when [] == Es;
is_record(hd(Msg), diameter_header) ->
- Pkt = diameter_codec:encode(Dict, make_reply_packet(Msg, ReqPkt)),
+ Pkt = diameter_codec:encode(Dict, make_answer_packet(Msg, ReqPkt)),
incr(send, Pkt, Dict, TPid), %% count result codes in sent answers
send(TPid, Pkt#diameter_packet{transport_data = TD});
@@ -1969,26 +1956,23 @@ reply(Msg, Dict, TPid, #diameter_packet{errors = [H|_] = Es} = Pkt) ->
TPid,
Pkt#diameter_packet{errors = []}).
-%% make_reply_packet/2
+%% make_answer_packet/2
-make_reply_packet(Bin, _)
+%% Binaries and header/avp lists are sent as-is.
+make_answer_packet(Bin, _)
when is_binary(Bin) ->
#diameter_packet{bin = Bin};
-
-make_reply_packet([#diameter_header{} | _] = Msg, _) ->
+make_answer_packet([#diameter_header{} | _] = Msg, _) ->
#diameter_packet{msg = Msg};
-make_reply_packet(Msg, #diameter_packet{header = ReqHdr}) ->
- #diameter_header{end_to_end_id = EId,
- hop_by_hop_id = Hid,
- is_proxiable = P}
- = ReqHdr,
-
- Hdr = #diameter_header{version = ?DIAMETER_VERSION,
- end_to_end_id = EId,
- hop_by_hop_id = Hid,
- is_proxiable = P,
- is_retransmitted = false},
+%% Otherwise a reply message clears the R and T flags and retains the
+%% P flag. The E flag will be set at encode. 6.2 of 3588 requires the
+%% same P flag on an answer as on the request.
+make_answer_packet(Msg, #diameter_packet{header = ReqHdr}) ->
+ Hdr = ReqHdr#diameter_header{version = ?DIAMETER_VERSION,
+ is_request = false,
+ is_error = undefined,
+ is_retransmitted = false},
#diameter_packet{header = Hdr,
msg = Msg}.
@@ -2126,16 +2110,6 @@ answer_message({OH, OR, RC}, Avps) ->
session_id(Code, Vid, Avps)
when is_list(Avps) ->
try
- {value, #diameter_avp{} = Avp} = find_avp(Code, Vid, Avps),
- Avp
- catch
- error: _ ->
- []
- end;
-
-session_id(Code, Vid, Avps)
- when is_list(Avps) ->
- try
{value, #diameter_avp{data = D}} = find_avp(Code, Vid, Avps),
[{'Session-Id', [?BASE:avp(decode, D, 'Session-Id')]}]
catch
@@ -2482,6 +2456,7 @@ rpd(Pid, Alias, PDict) ->
%%%
%%% Output: {TransportPid, #diameter_caps{}, #diameter_app{}}
%%% | false
+%%% | {error, Reason}
%%% ---------------------------------------------------------------------------
%% Initial call, from an arbitrary process.
@@ -2540,28 +2515,18 @@ get_destination(Msg, Dict) ->
[str(get_avp_value(Dict, 'Destination-Realm', Msg)),
str(get_avp_value(Dict, 'Destination-Host', Msg))].
-%% TODO:
-%%
-%% Should add some way of specifying destination directly so that the
-%% only requirement is that the prepare_request callback returns
-%% something specific. (eg. {host, DH}; that is, let the caller specify.)
-%%
-%% Also, there is no longer any need to call get_destination at all in
-%% the default case.
-
-str(T)
- when T == undefined;
- T == [] ->
+%% This is not entirely correct. The avp could have an arity 1, in
+%% which case an empty list is a DiameterIdentity of length 0 rather
+%% than the list of no values we treat it as by mapping to undefined.
+%% This behaviour is documented.
+str([]) ->
undefined;
-str([X])
- when is_list(X) ->
- X;
str(T) ->
T.
%% get_avp_value/3
%%
-%% Support outgoing messages in one of three forms:
+%% Find an AVP in a message of one of three forms:
%%
%% - a message record (as generated from a .dia spec) or
%% - a list of an atom message name followed by 2-tuple, avp name/value pairs.
@@ -2593,8 +2558,9 @@ get_avp_value(_, Name, [_MsgName | Avps]) ->
undefined
end;
-get_avp_value(Dict, Name, Rec)
- when is_tuple(Rec) ->
+%% Message is typically a record but not necessarily: diameter:call/4
+%% can be passed an arbitrary term.
+get_avp_value(Dict, Name, Rec) ->
try
Dict:'#get-'(Name, Rec)
catch
@@ -2690,7 +2656,8 @@ peers(Alias, RH, Filter, Peers) ->
end.
%% Place a peer whose Destination-Host/Realm matches those of the
-%% request at the front of the result list.
+%% request at the front of the result list. Could add some sort of
+%% 'sort' option to allow more control.
ps([], _, _, {Ys, Ns}) ->
lists:reverse(Ys, Ns);
@@ -2700,11 +2667,11 @@ ps([{_TPid, #diameter_caps{} = Caps} = TC | Rest], RH, Filter, Acc) ->
TC,
Acc)).
-pacc(true, true, TC, {Ts, Fs}) ->
- {[TC|Ts], Fs};
-pacc(true, false, TC, {Ts, Fs}) ->
- {Ts, [TC|Fs]};
-pacc(false, _, _, Acc) ->
+pacc(true, true, Peer, {Ts, Fs}) ->
+ {[Peer|Ts], Fs};
+pacc(true, false, Peer, {Ts, Fs}) ->
+ {Ts, [Peer|Fs]};
+pacc(_, _, _, Acc) ->
Acc.
%% caps_filter/3
@@ -2712,17 +2679,19 @@ pacc(false, _, _, Acc) ->
caps_filter(C, RH, {neg, F}) ->
not caps_filter(C, RH, F);
-caps_filter(C, RH, {all, L}) ->
+caps_filter(C, RH, {all, L})
+ when is_list(L) ->
lists:all(fun(F) -> caps_filter(C, RH, F) end, L);
-caps_filter(C, RH, {any, L}) ->
+caps_filter(C, RH, {any, L})
+ when is_list(L) ->
lists:any(fun(F) -> caps_filter(C, RH, F) end, L);
-caps_filter(#diameter_caps{origin_host = {_,H}}, [_,DH], host) ->
- eq(undefined, DH, H);
+caps_filter(#diameter_caps{origin_host = {_,OH}}, [_,DH], host) ->
+ eq(undefined, DH, OH);
-caps_filter(#diameter_caps{origin_realm = {_,R}}, [DR,_], realm) ->
- eq(undefined, DR, R);
+caps_filter(#diameter_caps{origin_realm = {_,OR}}, [DR,_], realm) ->
+ eq(undefined, DR, OR);
caps_filter(C, _, Filter) ->
caps_filter(C, Filter).
@@ -2738,6 +2707,9 @@ caps_filter(#diameter_caps{origin_host = {_,OH}}, {host, H}) ->
caps_filter(#diameter_caps{origin_realm = {_,OR}}, {realm, R}) ->
eq(any, R, OR);
+%% Anything else is expected to be an eval filter. Filter failure is
+%% documented as being equivalent to a non-matching filter.
+
caps_filter(C, T) ->
try
{eval, F} = T,
@@ -2746,8 +2718,14 @@ caps_filter(C, T) ->
_:_ -> false
end.
-eq(X, A, B) ->
- X == A orelse A == B.
+eq(Any, Id, PeerId) ->
+ Any == Id orelse try
+ iolist_to_binary(Id) == iolist_to_binary(PeerId)
+ catch
+ _:_ -> false
+ end.
+%% OctetString() can be specified as an iolist() so test for string
+%% rather then term equality.
%% transports/1
diff --git a/lib/diameter/src/app/diameter_service_sup.erl b/lib/diameter/src/base/diameter_service_sup.erl
index 153fff902f..153fff902f 100644
--- a/lib/diameter/src/app/diameter_service_sup.erl
+++ b/lib/diameter/src/base/diameter_service_sup.erl
diff --git a/lib/diameter/src/app/diameter_session.erl b/lib/diameter/src/base/diameter_session.erl
index bb91e97f39..bb91e97f39 100644
--- a/lib/diameter/src/app/diameter_session.erl
+++ b/lib/diameter/src/base/diameter_session.erl
diff --git a/lib/diameter/src/app/diameter_stats.erl b/lib/diameter/src/base/diameter_stats.erl
index b52d4cdcfb..71479afa95 100644
--- a/lib/diameter/src/app/diameter_stats.erl
+++ b/lib/diameter/src/base/diameter_stats.erl
@@ -207,7 +207,7 @@ handle_call({flush, Contrib}, _From, State) ->
{reply, fetch(Contrib), State};
handle_call(Req, From, State) ->
- warning_msg("received unexpected request from ~p:~n~w", [From, Req]),
+ ?UNEXPECTED([Req, From]),
{reply, nok, State}.
%% ----------------------------------------------------------
@@ -219,7 +219,7 @@ handle_cast({incr, Rec}, State) ->
{noreply, State};
handle_cast(Msg, State) ->
- warning_msg("received unexpected message:~n~w", [Msg]),
+ ?UNEXPECTED([Msg]),
{noreply, State}.
%% ----------------------------------------------------------
@@ -231,7 +231,7 @@ handle_info({'DOWN', _MRef, process, Pid, _}, State) ->
{noreply, State};
handle_info(Info, State) ->
- warning_msg("received unknown info:~n~w", [Info]),
+ ?UNEXPECTED([Info]),
{noreply, State}.
%% ----------------------------------------------------------
@@ -340,8 +340,3 @@ cast(Msg) ->
call(Request) ->
gen_server:call(?SERVER, Request, infinity).
-
-%% warning_msg/2
-
-warning_msg(F, A) ->
- ?diameter_warning("~p: " ++ F, [?MODULE | A]).
diff --git a/lib/diameter/src/app/diameter_sup.erl b/lib/diameter/src/base/diameter_sup.erl
index e5afd23dcd..e5afd23dcd 100644
--- a/lib/diameter/src/app/diameter_sup.erl
+++ b/lib/diameter/src/base/diameter_sup.erl
diff --git a/lib/diameter/src/app/diameter_sync.erl b/lib/diameter/src/base/diameter_sync.erl
index f7777ae809..ce2db4b3a2 100644
--- a/lib/diameter/src/app/diameter_sync.erl
+++ b/lib/diameter/src/base/diameter_sync.erl
@@ -204,37 +204,37 @@ handle_call(?REQUEST(Type, Name, Req, Max, Timeout),
T = find(Name, QD),
nq(queued(T) =< Max, T, {Type, From}, Name, Req, Timeout, State);
-handle_call(Request, _From, State) ->
- {reply, call(Request, State), State}.
+handle_call(Request, From, State) ->
+ {reply, call(Request, From, State), State}.
-%% call/2
+%% call/3
-call(?CARP(Name), #state{queue = QD}) ->
+call(?CARP(Name), _, #state{queue = QD}) ->
pcar(find(Name, QD));
-call(state, State) ->
+call(state, _, State) ->
State;
-call(uptime, #state{time = T}) ->
+call(uptime, _, #state{time = T}) ->
diameter_lib:now_diff(T);
-call({flush, Name}, #state{queue = QD}) ->
+call({flush, Name}, _, #state{queue = QD}) ->
cancel(find(Name, QD));
-call(pending, #state{pending = N}) ->
+call(pending, _, #state{pending = N}) ->
N;
-call({pending, Name}, #state{queue = QD}) ->
+call({pending, Name}, _, #state{queue = QD}) ->
queued(find(Name, QD));
-call(queues, #state{queue = QD}) ->
+call(queues, _, #state{queue = QD}) ->
fetch_keys(QD);
-call({pids, Name}, #state{queue = QD}) ->
+call({pids, Name}, _, #state{queue = QD}) ->
plist(find(Name, QD));
-call(Req, _State) -> %% ignore
- warning_msg("received unexpected request:~n~w", [Req]),
+call(Req, From, _State) -> %% ignore
+ ?UNEXPECTED(handle_call, [Req, From]),
nok.
%%% ----------------------------------------------------------
@@ -242,7 +242,7 @@ call(Req, _State) -> %% ignore
%%% ----------------------------------------------------------
handle_cast(Msg, State) ->
- warning_msg("received unexpected message:~n~w", [Msg]),
+ ?UNEXPECTED([Msg]),
{noreply, State}.
%%% ----------------------------------------------------------
@@ -267,7 +267,7 @@ info({'DOWN', MRef, process, Pid, Info},
queue = dq(fetch(Name, QD), Pid, Info, Name, QD)};
info(Info, State) ->
- warning_msg("received unknown info:~n~w", [Info]),
+ ?UNEXPECTED(handle_info, [Info]),
State.
reply({call, From}, T) ->
@@ -548,8 +548,3 @@ gen_call(Server, Req, Timeout) ->
exit: _ ->
timeout
end.
-
-%% warning_msg/2
-
-warning_msg(F, A) ->
- ?diameter_warning("~p: " ++ F, [?MODULE | A]).
diff --git a/lib/diameter/src/app/diameter_types.erl b/lib/diameter/src/base/diameter_types.erl
index 6b1b1b8d39..6b1b1b8d39 100644
--- a/lib/diameter/src/app/diameter_types.erl
+++ b/lib/diameter/src/base/diameter_types.erl
diff --git a/lib/diameter/src/app/diameter_types.hrl b/lib/diameter/src/base/diameter_types.hrl
index 02bf8a74dd..02bf8a74dd 100644
--- a/lib/diameter/src/app/diameter_types.hrl
+++ b/lib/diameter/src/base/diameter_types.hrl
diff --git a/lib/diameter/src/app/diameter_watchdog.erl b/lib/diameter/src/base/diameter_watchdog.erl
index b7c1491f4b..6dc53d9f31 100644
--- a/lib/diameter/src/app/diameter_watchdog.erl
+++ b/lib/diameter/src/base/diameter_watchdog.erl
@@ -179,11 +179,11 @@ transition({close, TPid, _Reason}, #watchdog{transport = TPid}) ->
%% state okay as the result of the Peer State Machine reaching the
%% Open state.
%%
-%% If we're an acceptor then we may be resuming a connection that went
-%% down in another acceptor process, in which case this is the
-%% transition below, from down into reopen. That is, it's not until
-%% we know the identity of the peer (ie. now) that we know that we're
-%% in state down rather than initial.
+%% If we're accepting then we may be resuming a connection that went
+%% down in another watchdog process, in which case this is the
+%% transition below, from down to reopen. That is, it's not until we
+%% know the identity of the peer (ie. now) that we know that we're in
+%% state down rather than initial.
transition({open, TPid, Hosts, T} = Open,
#watchdog{transport = TPid,
diff --git a/lib/diameter/src/app/diameter_watchdog_sup.erl b/lib/diameter/src/base/diameter_watchdog_sup.erl
index fc837fe4ef..fc837fe4ef 100644
--- a/lib/diameter/src/app/diameter_watchdog_sup.erl
+++ b/lib/diameter/src/base/diameter_watchdog_sup.erl
diff --git a/lib/diameter/src/compiler/Makefile b/lib/diameter/src/compiler/Makefile
deleted file mode 100644
index 3ab76064ac..0000000000
--- a/lib/diameter/src/compiler/Makefile
+++ /dev/null
@@ -1,141 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2010-2011. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-#
-
-ifneq ($(ERL_TOP),)
-include $(ERL_TOP)/make/target.mk
-EBIN = ../../ebin
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-else
-include $(DIAMETER_TOP)/make/target.mk
-EBIN = ../../ebin
-include $(DIAMETER_TOP)/make/$(TARGET)/rules.mk
-endif
-
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(DIAMETER_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-
-RELSYSDIR = $(RELEASE_PATH)/lib/diameter-$(VSN)
-
-INCDIR = ../../include
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-include modules.mk
-
-ERL_FILES = \
- $(MODULES:%=%.erl)
-
-TARGET_FILES = \
- $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-
-ifeq ($(TYPE),debug)
-ERL_COMPILE_FLAGS += -Ddebug
-endif
-
-include ../app/diameter.mk
-
-ERL_COMPILE_FLAGS += \
- $(DIAMETER_ERL_COMPILE_FLAGS) \
- -I$(INCDIR)
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-debug:
- @${MAKE} TYPE=debug opt
-
-opt: $(TARGET_FILES)
-
-clean:
- rm -f $(TARGET_FILES)
- rm -f errs core *~
- rm -f depend.mk
-
-docs:
-
-info:
- @echo ""
- @echo "ERL_FILES = $(ERL_FILES)"
- @echo "HRL_FILES = $(HRL_FILES)"
- @echo ""
- @echo "TARGET_FILES = $(TARGET_FILES)"
- @echo ""
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-
-# Invoked from ../app to add modules to the app file.
-$(APP_TARGET): force
- M=`echo $(MODULES) | sed -e 's/^ *//' -e 's/ *$$//' -e 'y/ /,/'`; \
- echo "/%COMPILER_MODULES%/s//$$M/;w;q" | tr ';' '\n' \
- | ed -s $@
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-ifneq ($(ERL_TOP),)
-include $(ERL_TOP)/make/otp_release_targets.mk
-else
-include $(DIAMETER_TOP)/make/release_targets.mk
-endif
-
-release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/src/compiler
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)/src/compiler
-
-release_docs_spec:
-
-force:
-
-# ----------------------------------------------------
-# Dependencies
-# ----------------------------------------------------
-
-depend: depend.mk
-
-# Generate dependencies makefile.
-depend.mk: ../app/depend.sed $(ERL_FILES) Makefile
- for f in $(MODULES); do \
- sed -f $< $$f.erl | sed "s@/@/$$f@"; \
- done \
- > $@
-
--include depend.mk
-
-.PHONY: clean debug depend docs force info opt release_docs_spec release_spec
diff --git a/lib/diameter/src/compiler/diameter_codegen.erl b/lib/diameter/src/compiler/diameter_codegen.erl
index 213ba0d22c..0fd4a0b301 100644
--- a/lib/diameter/src/compiler/diameter_codegen.erl
+++ b/lib/diameter/src/compiler/diameter_codegen.erl
@@ -37,7 +37,6 @@
file/2,
file/3]).
--include_lib("diameter/src/app/diameter_internal.hrl").
-include("diameter_forms.hrl").
%% Generated functions that could have no generated clauses will have
@@ -250,9 +249,14 @@ f_name(Name) ->
%%% ------------------------------------------------------------------------
f_id(Spec) ->
- Id = orddict:fetch(id, Spec),
{?function, id, 0,
- [{?clause, [], [], [?INTEGER(Id)]}]}.
+ [c_id(orddict:find(id, Spec))]}.
+
+c_id({ok, Id}) ->
+ {?clause, [], [], [?INTEGER(Id)]};
+
+c_id(error) ->
+ ?UNEXPECTED(0).
%%% ------------------------------------------------------------------------
%%% # vendor_id/0
@@ -454,9 +458,10 @@ avp(Spec) ->
Native = get_value(avp_types, Spec),
Custom = get_value(custom_types, Spec),
Imported = get_value(import_avps, Spec),
- avp([{N,T} || {N,_,T,_,_} <- Native], Imported, Custom).
+ Enums = get_value(enums, Spec),
+ avp([{N,T} || {N,_,T,_,_} <- Native], Imported, Custom, Enums).
-avp(Native, Imported, Custom) ->
+avp(Native, Imported, Custom, Enums) ->
Dict = orddict:from_list(Native),
report(native, Dict),
@@ -470,8 +475,8 @@ avp(Native, Imported, Custom) ->
false == lists:member(N, CustomNames)
end,
Native))
- ++ lists:flatmap(fun c_imported_avp/1, Imported)
- ++ lists:flatmap(fun(C) -> c_custom_avp(C, Dict) end, Custom).
+ ++ lists:flatmap(fun(I) -> cs_imported_avp(I, Enums) end, Imported)
+ ++ lists:flatmap(fun(C) -> cs_custom_avp(C, Dict) end, Custom).
c_base_avp({AvpName, T}) ->
{?clause, [?VAR('T'), ?VAR('Data'), ?ATOM(AvpName)],
@@ -487,23 +492,35 @@ base_avp(AvpName, 'Grouped') ->
base_avp(_, Type) ->
?APPLY(diameter_types, Type, [?VAR('T'), ?VAR('Data')]).
-c_imported_avp({Mod, Avps}) ->
- lists:map(fun(A) -> imported_avp(Mod, A) end, Avps).
+cs_imported_avp({Mod, Avps}, Enums) ->
+ lists:map(fun(A) -> imported_avp(Mod, A, Enums) end, Avps).
-imported_avp(_Mod, {AvpName, _, 'Grouped' = T, _, _}) ->
+imported_avp(_Mod, {AvpName, _, 'Grouped' = T, _, _}, _) ->
c_base_avp({AvpName, T});
-imported_avp(Mod, {AvpName, _, _, _, _}) ->
+imported_avp(Mod, {AvpName, _, 'Enumerated' = T, _, _}, Enums) ->
+ case lists:keymember(AvpName, 1, Enums) of
+ true ->
+ c_base_avp({AvpName, T});
+ false ->
+ c_imported_avp(Mod, AvpName)
+ end;
+
+imported_avp(Mod, {AvpName, _, _, _, _}, _) ->
+ c_imported_avp(Mod, AvpName).
+
+c_imported_avp(Mod, AvpName) ->
{?clause, [?VAR('T'), ?VAR('Data'), ?ATOM(AvpName)],
[],
[?APPLY(Mod, avp, [?VAR('T'),
?VAR('Data'),
?ATOM(AvpName)])]}.
-c_custom_avp({Mod, Avps}, Dict) ->
- lists:map(fun(N) -> custom_avp(Mod, N, orddict:fetch(N, Dict)) end, Avps).
+cs_custom_avp({Mod, Avps}, Dict) ->
+ lists:map(fun(N) -> c_custom_avp(Mod, N, orddict:fetch(N, Dict)) end,
+ Avps).
-custom_avp(Mod, AvpName, Type) ->
+c_custom_avp(Mod, AvpName, Type) ->
{?clause, [?VAR('T'), ?VAR('Data'), ?ATOM(AvpName)],
[],
[?APPLY(Mod, AvpName, [?VAR('T'), ?ATOM(Type), ?VAR('Data')])]}.
@@ -516,9 +533,25 @@ f_enumerated_avp(Spec) ->
{?function, enumerated_avp, 3, enumerated_avp(Spec) ++ [?UNEXPECTED(3)]}.
enumerated_avp(Spec) ->
- lists:flatmap(fun c_enumerated_avp/1, get_value(enums, Spec)).
+ Enums = get_value(enums, Spec),
+ lists:flatmap(fun cs_enumerated_avp/1, Enums)
+ ++ lists:flatmap(fun({M,Es}) -> enumerated_avp(M, Es, Enums) end,
+ get_value(import_enums, Spec)).
+
+enumerated_avp(Mod, Es, Enums) ->
+ lists:flatmap(fun({N,_}) ->
+ cs_enumerated_avp(lists:keymember(N, 1, Enums),
+ Mod,
+ N)
+ end,
+ Es).
-c_enumerated_avp({AvpName, Values}) ->
+cs_enumerated_avp(true, Mod, Name) ->
+ [c_imported_avp(Mod, Name)];
+cs_enumerated_avp(false, _, _) ->
+ [].
+
+cs_enumerated_avp({AvpName, Values}) ->
lists:flatmap(fun(V) -> c_enumerated_avp(AvpName, V) end, Values).
c_enumerated_avp(AvpName, {I,_}) ->
@@ -537,10 +570,14 @@ f_msg_header(Spec) ->
{?function, msg_header, 1, msg_header(Spec) ++ [?UNEXPECTED(1)]}.
msg_header(Spec) ->
+ msg_header(get_value(messages, Spec), Spec).
+
+msg_header([], _) ->
+ [];
+msg_header(Msgs, Spec) ->
ApplId = orddict:fetch(id, Spec),
- lists:map(fun({M,C,F,_,_}) -> c_msg_header(M, C, F, ApplId) end,
- get_value(messages, Spec)).
+ lists:map(fun({M,C,F,_,_}) -> c_msg_header(M, C, F, ApplId) end, Msgs).
%% Note that any application id in the message header spec is ignored.
@@ -616,10 +653,12 @@ f_empty_value(Spec) ->
{?function, empty_value, 1, empty_value(Spec)}.
empty_value(Spec) ->
+ Imported = lists:flatmap(fun avps/1, get_value(import_enums, Spec)),
Groups = get_value(grouped, Spec)
++ lists:flatmap(fun avps/1, get_value(import_groups, Spec)),
- Enums = get_value(enums, Spec)
- ++ lists:flatmap(fun avps/1, get_value(import_enums, Spec)),
+ Enums = [T || {N,_} = T <- get_value(enums, Spec),
+ not lists:keymember(N, 1, Imported)]
+ ++ Imported,
lists:map(fun c_empty_value/1, Groups ++ Enums)
++ [{?clause, [?VAR('Name')], [], [?CALL(empty, [?VAR('Name')])]}].
@@ -668,9 +707,9 @@ gen_hrl(Path, Mod, Spec) ->
write("ENUM Macros",
Fd,
m_enums(PREFIX, false, get_value(enums, Spec))),
- write("RESULT CODE Macros",
+ write("DEFINE Macros",
Fd,
- m_enums(PREFIX, false, get_value(result_codes, Spec))),
+ m_enums(PREFIX, false, get_value(defines, Spec))),
lists:foreach(fun({M,Es}) ->
write("ENUM Macros from " ++ atom_to_list(M),
diff --git a/lib/diameter/src/app/diameter_exprecs.erl b/lib/diameter/src/compiler/diameter_exprecs.erl
index 5e120d6f44..5e120d6f44 100644
--- a/lib/diameter/src/app/diameter_exprecs.erl
+++ b/lib/diameter/src/compiler/diameter_exprecs.erl
diff --git a/lib/diameter/src/compiler/diameter_make.erl b/lib/diameter/src/compiler/diameter_make.erl
index 4431b88c4d..5380ee56ca 100644
--- a/lib/diameter/src/compiler/diameter_make.erl
+++ b/lib/diameter/src/compiler/diameter_make.erl
@@ -18,103 +18,61 @@
%%
%%
-%% Driver for the encoder generator utility.
+%% Module alternative to diameterc for dictionary compilation.
+%%
+%% Eg. 1> diameter_make:dict("mydict.dia").
+%%
+%% $ erl -noshell \
+%% -boot start_clean \
+%% -s diameter_make dict mydict.dia \
+%% -s init stop
%%
-module(diameter_make).
--export([spec/0,
- hrl/0,
- erl/0]).
+-export([dict/1,
+ dict/2,
+ spec/1,
+ spec/2]).
--spec spec() -> no_return().
--spec hrl() -> no_return().
--spec erl() -> no_return().
+-type opt() :: {outdir|include|name|prefix|inherits, string()}
+ | verbose
+ | debug.
-spec() ->
- make(spec).
+%% dict/1-2
-hrl() ->
- make(hrl).
+-spec dict(string(), [opt()])
+ -> ok.
-erl() ->
- make(erl).
+dict(File, Opts) ->
+ make(File,
+ Opts,
+ spec(File, Opts),
+ [spec || _ <- [1], lists:member(debug, Opts)] ++ [erl, hrl]).
-%% make/1
+dict(File) ->
+ dict(File, []).
-make(Mode) ->
- Args = init:get_plain_arguments(),
- Opts = try options(Args) catch throw: help -> help(Mode) end,
- Files = proplists:get_value(files, Opts, []),
- lists:foreach(fun(F) -> from_file(F, Mode, Opts) end, Files),
- halt(0).
+%% spec/2
-%% from_file/3
-
-from_file(F, Mode, Opts) ->
- try to_spec(F, Mode, Opts) of
- Spec ->
- from_spec(F, Spec, Mode, Opts)
- catch
- error: Reason ->
- io:format("==> ~p parse failure:~n~p~n",
- [F, {Reason, erlang:get_stacktrace()}]),
- halt(1)
- end.
+-spec spec(string(), [opt()])
+ -> orddict:orddict().
-%% to_spec/2
+spec(File, Opts) ->
+ diameter_spec_util:parse(File, Opts).
-%% Try to read the input as an already parsed file or else parse it.
-to_spec(F, spec, Opts) ->
- diameter_spec_util:parse(F, Opts);
-to_spec(F, _, _) ->
- {ok, [Spec]} = file:consult(F),
- Spec.
+spec(File) ->
+ spec(File, []).
-%% from_spec/4
+%% ===========================================================================
-from_spec(File, Spec, Mode, Opts) ->
- try
- diameter_codegen:from_spec(File, Spec, Opts, Mode)
+make(_, _, _, []) ->
+ ok;
+make(File, Opts, Spec, [Mode | Rest]) ->
+ try diameter_codegen:from_spec(File, Spec, Opts, Mode) of
+ ok ->
+ make(File, Opts, Spec, Rest)
catch
error: Reason ->
- io:format("==> ~p codegen failure:~n~p~n~p~n",
- [Mode, File, {Reason, erlang:get_stacktrace()}]),
- halt(1)
+ {error, {Reason, Mode, erlang:get_stacktrace()}}
end.
-
-%% options/1
-
-options(["-v" | Rest]) ->
- [verbose | options(Rest)];
-
-options(["-o", Outdir | Rest]) ->
- [{outdir, Outdir} | options(Rest)];
-
-options(["-i", Incdir | Rest]) ->
- [{include, Incdir} | options(Rest)];
-
-options(["-h" | _]) ->
- throw(help);
-
-options(["--" | Fs]) ->
- [{files, Fs}];
-
-options(["-" ++ _ = Opt | _]) ->
- io:fwrite("==> unknown option: ~s~n", [Opt]),
- throw(help);
-
-options(Fs) -> %% trailing arguments
- options(["--" | Fs]).
-
-%% help/1
-
-help(M) ->
- io:fwrite("Usage: ~p ~p [Options] [--] File ...~n"
- "Options:~n"
- " -v verbose output~n"
- " -h shows this help message~n"
- " -o OutDir where to put the output files~n"
- " -i IncludeDir where to search for beams to import~n",
- [?MODULE, M]),
- halt(1).
diff --git a/lib/diameter/src/compiler/diameter_spec_util.erl b/lib/diameter/src/compiler/diameter_spec_util.erl
index 322d53a199..62536bf06d 100644
--- a/lib/diameter/src/compiler/diameter_spec_util.erl
+++ b/lib/diameter/src/compiler/diameter_spec_util.erl
@@ -34,19 +34,38 @@
%%
%% Output: orddict()
-parse(Path, Options) ->
- put({?MODULE, verbose}, lists:member(verbose, Options)),
+parse(Path, Opts) ->
+ put({?MODULE, verbose}, lists:member(verbose, Opts)),
{ok, B} = file:read_file(Path),
Chunks = chunk(B),
- Spec = make_spec(Chunks),
- true = enums_defined(Spec), %% sanity checks
- true = groups_defined(Spec), %%
+ Spec = reset(make_spec(Chunks), Opts, [name, prefix, inherits]),
+ true = groups_defined(Spec), %% sanity checks
true = customs_defined(Spec), %%
- Full = import_enums(import_groups(import_avps(insert_codes(Spec),
- Options))),
+ Full = import_enums(import_groups(import_avps(insert_codes(Spec), Opts))),
+ true = enums_defined(Full), %% sanity checks
true = v_flags_set(Spec),
Full.
+reset(Spec, Opts, Keys) ->
+ lists:foldl(fun(K,S) ->
+ reset([{A,?ATOM(V)} || {A,V} <- Opts, A == K], S)
+ end,
+ Spec,
+ Keys).
+
+reset(L, Spec)
+ when is_list(L) ->
+ lists:foldl(fun reset/2, Spec, L);
+
+reset({inherits = Key, '-'}, Spec) ->
+ orddict:erase(Key, Spec);
+reset({inherits = Key, Dict}, Spec) ->
+ orddict:append(Key, Dict, Spec);
+reset({Key, Atom}, Spec) ->
+ orddict:store(Key, Atom, Spec);
+reset(_, Spec) ->
+ Spec.
+
%% Optional reports when running verbosely.
report(What, Data) ->
report(get({?MODULE, verbose}), What, Data).
@@ -204,9 +223,11 @@ chunk({avp_vendor_id = T, [{number, I}], Body}, Dict) ->
chunk({enum, [N], Str}, Dict) ->
append(enums, {atomize(N), parse_enums(Str)}, Dict);
-%% result_codes -> [{ResultName, [{Value, Name}, ...]}, ...]
-chunk({result_code, [N], Str}, Dict) ->
- append(result_codes, {atomize(N), parse_enums(Str)}, Dict);
+%% defines -> [{DefineName, [{Value, Name}, ...]}, ...]
+chunk({define, [N], Str}, Dict) ->
+ append(defines, {atomize(N), parse_enums(Str)}, Dict);
+chunk({result_code, [_] = N, Str}, Dict) -> %% backwards compatibility
+ chunk({define, N, Str}, Dict);
%% commands -> [{Name, Abbrev}, ...]
chunk({commands = T, [], Body}, Dict) ->
@@ -243,35 +264,48 @@ get_value(Key, Spec) ->
%% with an appropriate type.
enums_defined(Spec) ->
- is_defined(Spec, 'Enumerated', enums).
+ Avps = get_value(avp_types, Spec),
+ Import = get_value(import_enums, Spec),
+ lists:all(fun({N,_}) ->
+ true = enum_defined(N, Avps, Import)
+ end,
+ get_value(enums, Spec)).
-groups_defined(Spec) ->
- is_defined(Spec, 'Grouped', grouped).
+enum_defined(Name, Avps, Import) ->
+ case lists:keyfind(Name, 1, Avps) of
+ {Name, _, 'Enumerated', _, _} ->
+ true;
+ {Name, _, T, _, _} ->
+ ?ERROR({avp_has_wrong_type, Name, 'Enumerated', T});
+ false ->
+ lists:any(fun({_,Is}) -> lists:keymember(Name, 1, Is) end, Import)
+ orelse ?ERROR({avp_not_defined, Name, 'Enumerated'})
+ end.
+%% Note that an AVP is imported only if referenced by a message or
+%% grouped AVP, so the final branch will fail if an enum definition is
+%% extended without this being the case.
-is_defined(Spec, Type, Key) ->
+groups_defined(Spec) ->
Avps = get_value(avp_types, Spec),
- lists:all(fun(T) -> true = is_local(name(Key, T), Type, Avps) end,
- get_value(Key, Spec)).
+ lists:all(fun({N,_,_,_}) -> true = group_defined(N, Avps) end,
+ get_value(grouped, Spec)).
-name(enums, {N,_}) -> N;
-name(grouped, {N,_,_,_}) -> N.
-
-is_local(Name, Type, Avps) ->
+group_defined(Name, Avps) ->
case lists:keyfind(Name, 1, Avps) of
- {Name, _, Type, _, _} ->
+ {Name, _, 'Grouped', _, _} ->
true;
{Name, _, T, _, _} ->
- ?ERROR({avp_has_wrong_type, Name, Type, T});
+ ?ERROR({avp_has_wrong_type, Name, 'Grouped', T});
false ->
- ?ERROR({avp_not_defined, Name, Type})
+ ?ERROR({avp_not_defined, Name, 'Grouped'})
end.
customs_defined(Spec) ->
Avps = get_value(avp_types, Spec),
- lists:all(fun(A) -> true = is_local(A, Avps) end,
+ lists:all(fun(A) -> true = custom_defined(A, Avps) end,
lists:flatmap(fun last/1, get_value(custom_types, Spec))).
-is_local(Name, Avps) ->
+custom_defined(Name, Avps) ->
case lists:keyfind(Name, 1, Avps) of
{Name, _, T, _, _} when T == 'Grouped';
T == 'Enumerated' ->
@@ -510,6 +544,9 @@ choose(false, _, X) -> X.
%% ------------------------------------------------------------------------
%% import_groups/1
%% import_enums/1
+%%
+%% For each inherited module, store the content of imported AVP's of
+%% type grouped/enumerated in a new key.
import_groups(Spec) ->
orddict:store(import_groups, import(grouped, Spec), Spec).
diff --git a/lib/diameter/src/compiler/modules.mk b/lib/diameter/src/compiler/modules.mk
deleted file mode 100644
index 17a311dacf..0000000000
--- a/lib/diameter/src/compiler/modules.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-#-*-makefile-*- ; force emacs to enter makefile-mode
-
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2010-2011. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-
-MODULES = \
- diameter_codegen \
- diameter_spec_scan \
- diameter_spec_util
-
-HRL_FILES = \
- diameter_forms.hrl
-
diff --git a/lib/diameter/src/depend.sed b/lib/diameter/src/depend.sed
new file mode 100644
index 0000000000..8f999f646f
--- /dev/null
+++ b/lib/diameter/src/depend.sed
@@ -0,0 +1,51 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2010-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+
+#
+# Extract include dependencies from .erl files. First line of input
+# is the path to the module in question (minus the .erl extension),
+# the rest is the contents of the module.
+#
+
+1{
+ s@^[^/]*/@@
+ h
+ d
+}
+
+# Only interested in includes of diameter hrls.
+/^-include/!d
+/"diameter/!d
+
+# Extract the name of the included files in one of two forms:
+#
+# $(INCDIR)/diameter.hrl
+# diameter_internal.hrl
+
+s@^-include_lib(".*/@$(INCDIR)/@
+s@^-include("@@
+s@".*@@
+
+# Retrieve the path to our module from the hold space, morph it
+# into a beam path and turn it into a dependency like this:
+#
+# $(EBIN)/diameter_service.$(EMULATOR): $(INCDIR)/diameter.hrl
+
+G
+s@^\(.*\)\n\(.*\)@$(EBIN)/\2.$(EMULATOR): \1@
diff --git a/lib/diameter/src/dict/base_accounting.dia b/lib/diameter/src/dict/base_accounting.dia
new file mode 100644
index 0000000000..ced324078c
--- /dev/null
+++ b/lib/diameter/src/dict/base_accounting.dia
@@ -0,0 +1,69 @@
+;;
+;; %CopyrightBegin%
+;;
+;; Copyright Ericsson AB 2010-2011. All Rights Reserved.
+;;
+;; The contents of this file are subject to the Erlang Public License,
+;; Version 1.1, (the "License"); you may not use this file except in
+;; compliance with the License. You should have received a copy of the
+;; Erlang Public License along with this software. If not, it can be
+;; retrieved online at http://www.erlang.org/.
+;;
+;; Software distributed under the License is distributed on an "AS IS"
+;; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+;; the License for the specific language governing rights and limitations
+;; under the License.
+;;
+;; %CopyrightEnd%
+;;
+
+@id 3
+@name diameter_gen_base_accounting
+@prefix diameter_base_accounting
+@vendor 0 IETF
+
+@inherits diameter_gen_base_rfc3588
+
+@messages
+
+ ACR ::= < Diameter Header: 271, REQ, PXY >
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Accounting-Record-Type }
+ { Accounting-Record-Number }
+ [ Acct-Application-Id ]
+ [ Vendor-Specific-Application-Id ]
+ [ User-Name ]
+ [ Accounting-Sub-Session-Id ]
+ [ Acct-Session-Id ]
+ [ Acct-Multi-Session-Id ]
+ [ Acct-Interim-Interval ]
+ [ Accounting-Realtime-Required ]
+ [ Origin-State-Id ]
+ [ Event-Timestamp ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ ACA ::= < Diameter Header: 271, PXY >
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ { Accounting-Record-Type }
+ { Accounting-Record-Number }
+ [ Acct-Application-Id ]
+ [ Vendor-Specific-Application-Id ]
+ [ User-Name ]
+ [ Accounting-Sub-Session-Id ]
+ [ Acct-Session-Id ]
+ [ Acct-Multi-Session-Id ]
+ [ Error-Reporting-Host ]
+ [ Acct-Interim-Interval ]
+ [ Accounting-Realtime-Required ]
+ [ Origin-State-Id ]
+ [ Event-Timestamp ]
+ * [ Proxy-Info ]
+ * [ AVP ]
diff --git a/lib/diameter/src/dict/base_rfc3588.dia b/lib/diameter/src/dict/base_rfc3588.dia
new file mode 100644
index 0000000000..f7a0b717cd
--- /dev/null
+++ b/lib/diameter/src/dict/base_rfc3588.dia
@@ -0,0 +1,414 @@
+;;
+;; %CopyrightBegin%
+;;
+;; Copyright Ericsson AB 2010-2011. All Rights Reserved.
+;;
+;; The contents of this file are subject to the Erlang Public License,
+;; Version 1.1, (the "License"); you may not use this file except in
+;; compliance with the License. You should have received a copy of the
+;; Erlang Public License along with this software. If not, it can be
+;; retrieved online at http://www.erlang.org/.
+;;
+;; Software distributed under the License is distributed on an "AS IS"
+;; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+;; the License for the specific language governing rights and limitations
+;; under the License.
+;;
+;; %CopyrightEnd%
+;;
+
+@id 0
+@name diameter_gen_base_rfc3588
+@prefix diameter_base
+@vendor 0 IETF
+
+@avp_types
+
+ Acct-Interim-Interval 85 Unsigned32 M
+ Accounting-Realtime-Required 483 Enumerated M
+ Acct-Multi-Session-Id 50 UTF8String M
+ Accounting-Record-Number 485 Unsigned32 M
+ Accounting-Record-Type 480 Enumerated M
+ Acct-Session-Id 44 OctetString M
+ Accounting-Sub-Session-Id 287 Unsigned64 M
+ Acct-Application-Id 259 Unsigned32 M
+ Auth-Application-Id 258 Unsigned32 M
+ Auth-Request-Type 274 Enumerated M
+ Authorization-Lifetime 291 Unsigned32 M
+ Auth-Grace-Period 276 Unsigned32 M
+ Auth-Session-State 277 Enumerated M
+ Re-Auth-Request-Type 285 Enumerated M
+ Class 25 OctetString M
+ Destination-Host 293 DiamIdent M
+ Destination-Realm 283 DiamIdent M
+ Disconnect-Cause 273 Enumerated M
+ E2E-Sequence 300 Grouped M
+ Error-Message 281 UTF8String -
+ Error-Reporting-Host 294 DiamIdent -
+ Event-Timestamp 55 Time M
+ Experimental-Result 297 Grouped M
+ Experimental-Result-Code 298 Unsigned32 M
+ Failed-AVP 279 Grouped M
+ Firmware-Revision 267 Unsigned32 -
+ Host-IP-Address 257 Address M
+ Inband-Security-Id 299 Unsigned32 M
+ Multi-Round-Time-Out 272 Unsigned32 M
+ Origin-Host 264 DiamIdent M
+ Origin-Realm 296 DiamIdent M
+ Origin-State-Id 278 Unsigned32 M
+ Product-Name 269 UTF8String -
+ Proxy-Host 280 DiamIdent M
+ Proxy-Info 284 Grouped M
+ Proxy-State 33 OctetString M
+ Redirect-Host 292 DiamURI M
+ Redirect-Host-Usage 261 Enumerated M
+ Redirect-Max-Cache-Time 262 Unsigned32 M
+ Result-Code 268 Unsigned32 M
+ Route-Record 282 DiamIdent M
+ Session-Id 263 UTF8String M
+ Session-Timeout 27 Unsigned32 M
+ Session-Binding 270 Unsigned32 M
+ Session-Server-Failover 271 Enumerated M
+ Supported-Vendor-Id 265 Unsigned32 M
+ Termination-Cause 295 Enumerated M
+ User-Name 1 UTF8String M
+ Vendor-Id 266 Unsigned32 M
+ Vendor-Specific-Application-Id 260 Grouped M
+
+@messages
+
+ CER ::= < Diameter Header: 257, REQ >
+ { Origin-Host }
+ { Origin-Realm }
+ 1* { Host-IP-Address }
+ { Vendor-Id }
+ { Product-Name }
+ [ Origin-State-Id ]
+ * [ Supported-Vendor-Id ]
+ * [ Auth-Application-Id ]
+ * [ Inband-Security-Id ]
+ * [ Acct-Application-Id ]
+ * [ Vendor-Specific-Application-Id ]
+ [ Firmware-Revision ]
+ * [ AVP ]
+
+ CEA ::= < Diameter Header: 257 >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ 1* { Host-IP-Address }
+ { Vendor-Id }
+ { Product-Name }
+ [ Origin-State-Id ]
+ [ Error-Message ]
+ * [ Failed-AVP ]
+ * [ Supported-Vendor-Id ]
+ * [ Auth-Application-Id ]
+ * [ Inband-Security-Id ]
+ * [ Acct-Application-Id ]
+ * [ Vendor-Specific-Application-Id ]
+ [ Firmware-Revision ]
+ * [ AVP ]
+
+ DPR ::= < Diameter Header: 282, REQ >
+ { Origin-Host }
+ { Origin-Realm }
+ { Disconnect-Cause }
+
+ DPA ::= < Diameter Header: 282 >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ Error-Message ]
+ * [ Failed-AVP ]
+
+ DWR ::= < Diameter Header: 280, REQ >
+ { Origin-Host }
+ { Origin-Realm }
+ [ Origin-State-Id ]
+
+ DWA ::= < Diameter Header: 280 >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ Error-Message ]
+ * [ Failed-AVP ]
+ [ Origin-State-Id ]
+
+ answer-message ::= < Diameter Header: code, ERR [PXY] >
+ 0*1 < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Result-Code }
+ [ Origin-State-Id ]
+ [ Error-Reporting-Host ]
+ [ Proxy-Info ]
+ * [ AVP ]
+
+ RAR ::= < Diameter Header: 258, REQ, PXY >
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Destination-Host }
+ { Auth-Application-Id }
+ { Re-Auth-Request-Type }
+ [ User-Name ]
+ [ Origin-State-Id ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ RAA ::= < Diameter Header: 258, PXY >
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ User-Name ]
+ [ Origin-State-Id ]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ * [ Failed-AVP ]
+ * [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+ STR ::= < Diameter Header: 275, REQ, PXY >
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Auth-Application-Id }
+ { Termination-Cause }
+ [ User-Name ]
+ [ Destination-Host ]
+ * [ Class ]
+ [ Origin-State-Id ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ STA ::= < Diameter Header: 275, PXY >
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ User-Name ]
+ * [ Class ]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ * [ Failed-AVP ]
+ [ Origin-State-Id ]
+ * [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+ ASR ::= < Diameter Header: 274, REQ, PXY >
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Destination-Host }
+ { Auth-Application-Id }
+ [ User-Name ]
+ [ Origin-State-Id ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ ASA ::= < Diameter Header: 274, PXY >
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ User-Name ]
+ [ Origin-State-Id ]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ * [ Failed-AVP ]
+ * [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+ ACR ::= < Diameter Header: 271, REQ, PXY >
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Accounting-Record-Type }
+ { Accounting-Record-Number }
+ [ Acct-Application-Id ]
+ [ Vendor-Specific-Application-Id ]
+ [ User-Name ]
+ [ Accounting-Sub-Session-Id ]
+ [ Acct-Session-Id ]
+ [ Acct-Multi-Session-Id ]
+ [ Acct-Interim-Interval ]
+ [ Accounting-Realtime-Required ]
+ [ Origin-State-Id ]
+ [ Event-Timestamp ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ ACA ::= < Diameter Header: 271, PXY >
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ { Accounting-Record-Type }
+ { Accounting-Record-Number }
+ [ Acct-Application-Id ]
+ [ Vendor-Specific-Application-Id ]
+ [ User-Name ]
+ [ Accounting-Sub-Session-Id ]
+ [ Acct-Session-Id ]
+ [ Acct-Multi-Session-Id ]
+ [ Error-Reporting-Host ]
+ [ Acct-Interim-Interval ]
+ [ Accounting-Realtime-Required ]
+ [ Origin-State-Id ]
+ [ Event-Timestamp ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+@enum Disconnect-Cause
+
+ REBOOTING 0
+ BUSY 1
+ DO_NOT_WANT_TO_TALK_TO_YOU 2
+
+@enum Redirect-Host-Usage
+
+ DONT_CACHE 0
+ ALL_SESSION 1
+ ALL_REALM 2
+ REALM_AND_APPLICATION 3
+ ALL_APPLICATION 4
+ ALL_HOST 5
+ ALL_USER 6
+
+@enum Auth-Request-Type
+
+ AUTHENTICATE_ONLY 1
+ AUTHORIZE_ONLY 2
+ AUTHORIZE_AUTHENTICATE 3
+
+@enum Auth-Session-State
+
+ STATE_MAINTAINED 0
+ NO_STATE_MAINTAINED 1
+
+@enum Re-Auth-Request-Type
+
+ AUTHORIZE_ONLY 0
+ AUTHORIZE_AUTHENTICATE 1
+
+@enum Termination-Cause
+
+ DIAMETER_LOGOUT 1
+ DIAMETER_SERVICE_NOT_PROVIDED 2
+ DIAMETER_BAD_ANSWER 3
+ DIAMETER_ADMINISTRATIVE 4
+ DIAMETER_LINK_BROKEN 5
+ DIAMETER_AUTH_EXPIRED 6
+ DIAMETER_USER_MOVED 7
+ DIAMETER_SESSION_TIMEOUT 8
+
+@enum Session-Server-Failover
+
+ REFUSE_SERVICE 0
+ TRY_AGAIN 1
+ ALLOW_SERVICE 2
+ TRY_AGAIN_ALLOW_SERVICE 3
+
+@enum Accounting-Record-Type
+
+ EVENT_RECORD 1
+ START_RECORD 2
+ INTERIM_RECORD 3
+ STOP_RECORD 4
+
+@enum Accounting-Realtime-Required
+
+ DELIVER_AND_GRANT 1
+ GRANT_AND_STORE 2
+ GRANT_AND_LOSE 3
+
+@define Result-Code
+
+;; 7.1.1. Informational
+ DIAMETER_MULTI_ROUND_AUTH 1001
+
+;; 7.1.2. Success
+ DIAMETER_SUCCESS 2001
+ DIAMETER_LIMITED_SUCCESS 2002
+
+;; 7.1.3. Protocol Errors
+ DIAMETER_COMMAND_UNSUPPORTED 3001
+ DIAMETER_UNABLE_TO_DELIVER 3002
+ DIAMETER_REALM_NOT_SERVED 3003
+ DIAMETER_TOO_BUSY 3004
+ DIAMETER_LOOP_DETECTED 3005
+ DIAMETER_REDIRECT_INDICATION 3006
+ DIAMETER_APPLICATION_UNSUPPORTED 3007
+ DIAMETER_INVALID_HDR_BITS 3008
+ DIAMETER_INVALID_AVP_BITS 3009
+ DIAMETER_UNKNOWN_PEER 3010
+
+;; 7.1.4. Transient Failures
+ DIAMETER_AUTHENTICATION_REJECTED 4001
+ DIAMETER_OUT_OF_SPACE 4002
+ ELECTION_LOST 4003
+
+;; 7.1.5. Permanent Failures
+ DIAMETER_AVP_UNSUPPORTED 5001
+ DIAMETER_UNKNOWN_SESSION_ID 5002
+ DIAMETER_AUTHORIZATION_REJECTED 5003
+ DIAMETER_INVALID_AVP_VALUE 5004
+ DIAMETER_MISSING_AVP 5005
+ DIAMETER_RESOURCES_EXCEEDED 5006
+ DIAMETER_CONTRADICTING_AVPS 5007
+ DIAMETER_AVP_NOT_ALLOWED 5008
+ DIAMETER_AVP_OCCURS_TOO_MANY_TIMES 5009
+ DIAMETER_NO_COMMON_APPLICATION 5010
+ DIAMETER_UNSUPPORTED_VERSION 5011
+ DIAMETER_UNABLE_TO_COMPLY 5012
+ DIAMETER_INVALID_BIT_IN_HEADER 5013
+ DIAMETER_INVALID_AVP_LENGTH 5014
+ DIAMETER_INVALID_MESSAGE_LENGTH 5015
+ DIAMETER_INVALID_AVP_BIT_COMBO 5016
+ DIAMETER_NO_COMMON_SECURITY 5017
+
+@grouped
+
+ Proxy-Info ::= < AVP Header: 284 >
+ { Proxy-Host }
+ { Proxy-State }
+ * [ AVP ]
+
+ Failed-AVP ::= < AVP Header: 279 >
+ 1* {AVP}
+
+ Experimental-Result ::= < AVP Header: 297 >
+ { Vendor-Id }
+ { Experimental-Result-Code }
+
+ Vendor-Specific-Application-Id ::= < AVP Header: 260 >
+ 1* { Vendor-Id }
+ [ Auth-Application-Id ]
+ [ Acct-Application-Id ]
+
+;; The E2E-Sequence AVP is defined in RFC 3588 as Grouped, but
+;; there is no definition of the group - only an informal text stating
+;; that there should be a nonce (an OctetString) and a counter
+;; (integer)
+;;
+ E2E-Sequence ::= <AVP Header: 300 >
+ 2* { AVP }
diff --git a/lib/diameter/src/app/diameter_gen_relay.dia b/lib/diameter/src/dict/relay.dia
index d86446e368..c22293209b 100644
--- a/lib/diameter/src/app/diameter_gen_relay.dia
+++ b/lib/diameter/src/dict/relay.dia
@@ -18,6 +18,7 @@
;;
@id 0xFFFFFFFF
+@name diameter_gen_relay
@prefix diameter_relay
@vendor 0 IETF
diff --git a/lib/diameter/src/gen/.gitignore b/lib/diameter/src/gen/.gitignore
new file mode 100644
index 0000000000..d490642eb7
--- /dev/null
+++ b/lib/diameter/src/gen/.gitignore
@@ -0,0 +1,2 @@
+
+/diameter_gen*rl
diff --git a/lib/diameter/src/modules.mk b/lib/diameter/src/modules.mk
new file mode 100644
index 0000000000..c7cbe598af
--- /dev/null
+++ b/lib/diameter/src/modules.mk
@@ -0,0 +1,93 @@
+#-*-makefile-*- ; force emacs to enter makefile-mode
+
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2010-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+
+# Runtime dictionary files in ./dict. Modules will be generated from
+# these are included in the app file.
+DICTS = \
+ base_rfc3588 \
+ base_accounting \
+ relay
+
+# Handwritten (runtime) modules included in the app file.
+RT_MODULES = \
+ base/diameter \
+ base/diameter_app \
+ base/diameter_capx \
+ base/diameter_config \
+ base/diameter_codec \
+ base/diameter_dict \
+ base/diameter_lib \
+ base/diameter_misc_sup \
+ base/diameter_peer \
+ base/diameter_peer_fsm \
+ base/diameter_peer_fsm_sup \
+ base/diameter_reg \
+ base/diameter_service \
+ base/diameter_service_sup \
+ base/diameter_session \
+ base/diameter_stats \
+ base/diameter_sup \
+ base/diameter_sync \
+ base/diameter_types \
+ base/diameter_watchdog \
+ base/diameter_watchdog_sup \
+ transport/diameter_etcp \
+ transport/diameter_etcp_sup \
+ transport/diameter_tcp \
+ transport/diameter_tcp_sup \
+ transport/diameter_sctp \
+ transport/diameter_sctp_sup \
+ transport/diameter_transport_sup
+
+# Handwritten (compile time) modules not included in the app file.
+CT_MODULES = \
+ base/diameter_callback \
+ base/diameter_dbg \
+ base/diameter_info \
+ compiler/diameter_codegen \
+ compiler/diameter_exprecs \
+ compiler/diameter_spec_scan \
+ compiler/diameter_spec_util \
+ compiler/diameter_make
+
+# Released hrl files in ../include intended for public consumption.
+EXTERNAL_HRLS = \
+ diameter.hrl \
+ diameter_gen.hrl
+
+# Released hrl files intended for private use.
+INTERNAL_HRLS = \
+ base/diameter_internal.hrl \
+ base/diameter_types.hrl \
+ compiler/diameter_forms.hrl
+
+# Released files relative to ../bin.
+BINS = \
+ diameterc
+
+# Released files relative to ../examples.
+EXAMPLES = \
+ GNUmakefile \
+ peer.erl \
+ client.erl \
+ client_cb.erl \
+ server.erl \
+ server_cb.erl \
+ relay.erl \
+ relay_cb.erl
diff --git a/lib/diameter/src/transport/Makefile b/lib/diameter/src/transport/Makefile
deleted file mode 100644
index 4b53100fd2..0000000000
--- a/lib/diameter/src/transport/Makefile
+++ /dev/null
@@ -1,141 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2010-2011. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-#
-
-ifneq ($(ERL_TOP),)
-include $(ERL_TOP)/make/target.mk
-EBIN = ../../ebin
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-else
-include $(DIAMETER_TOP)/make/target.mk
-EBIN = ../../ebin
-include $(DIAMETER_TOP)/make/$(TARGET)/rules.mk
-endif
-
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-
-include ../../vsn.mk
-VSN=$(DIAMETER_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-
-RELSYSDIR = $(RELEASE_PATH)/lib/diameter-$(VSN)
-
-INCDIR = ../../include
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-include modules.mk
-
-ERL_FILES = \
- $(MODULES:%=%.erl)
-
-TARGET_FILES = \
- $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-
-ifeq ($(TYPE),debug)
-ERL_COMPILE_FLAGS += -Ddebug
-endif
-
-include ../app/diameter.mk
-
-ERL_COMPILE_FLAGS += \
- $(DIAMETER_ERL_COMPILE_FLAGS) \
- -I$(INCDIR)
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-debug:
- @${MAKE} TYPE=debug opt
-
-opt: $(TARGET_FILES)
-
-clean:
- rm -f $(TARGET_FILES)
- rm -f errs core *~
- rm -f depend.mk
-
-docs:
-
-info:
- @echo ""
- @echo "ERL_FILES = $(ERL_FILES)"
- @echo "HRL_FILES = $(HRL_FILES)"
- @echo ""
- @echo "TARGET_FILES = $(TARGET_FILES)"
- @echo ""
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-
-# Invoked from ../app to add modules to the app file.
-$(APP_TARGET): force
- M=`echo $(MODULES) | sed -e 's/^ *//' -e 's/ *$$//' -e 'y/ /,/'`; \
- echo "/%TRANSPORT_MODULES%/s//$$M/;w;q" | tr ';' '\n' \
- | ed -s $@
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-ifneq ($(ERL_TOP),)
-include $(ERL_TOP)/make/otp_release_targets.mk
-else
-include $(DIAMETER_TOP)/make/release_targets.mk
-endif
-
-release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/src/transport
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)/src/transport
-
-release_docs_spec:
-
-force:
-
-# ----------------------------------------------------
-# Dependencies
-# ----------------------------------------------------
-
-depend: depend.mk
-
-# Generate dependencies makefile.
-depend.mk: ../app/depend.sed $(ERL_FILES) Makefile
- for f in $(MODULES); do \
- sed -f $< $$f.erl | sed "s@/@/$$f@"; \
- done \
- > $@
-
--include depend.mk
-
-.PHONY: clean debug depend docs force info opt release_docs_spec release_spec
diff --git a/lib/diameter/src/transport/diameter_sctp.erl b/lib/diameter/src/transport/diameter_sctp.erl
index 92aa8488a0..209f8c01c1 100644
--- a/lib/diameter/src/transport/diameter_sctp.erl
+++ b/lib/diameter/src/transport/diameter_sctp.erl
@@ -37,6 +37,9 @@
code_change/3,
terminate/2]).
+-export([ports/0,
+ ports/1]).
+
-include_lib("kernel/include/inet_sctp.hrl").
-include_lib("diameter/include/diameter.hrl").
@@ -118,8 +121,8 @@ s({accept, Ref} = A, Addrs, Opts) ->
%% gen_sctp in order to be able to accept a new association only
%% *after* an accepting transport has been spawned.
-s({connect = C, _}, Addrs, Opts) ->
- diameter_sctp_sup:start_child({C, self(), Opts, Addrs}).
+s({connect = C, Ref}, Addrs, Opts) ->
+ diameter_sctp_sup:start_child({C, self(), Opts, Addrs, Ref}).
%% start_link/1
@@ -149,28 +152,36 @@ i({listen, Ref, {Opts, Addrs}}) ->
socket = Sock});
%% A connecting transport.
-i({connect, Pid, Opts, Addrs}) ->
+i({connect, Pid, Opts, Addrs, Ref}) ->
{[As, Ps], Rest} = proplists:split(Opts, [raddr, rport]),
RAs = [diameter_lib:ipaddr(A) || {raddr, A} <- As],
[RP] = [P || {rport, P} <- Ps] ++ [P || P <- [?DEFAULT_PORT], [] == Ps],
{LAs, Sock} = open(Addrs, Rest, 0),
+ putr(ref, Ref),
proc_lib:init_ack({ok, self(), LAs}),
erlang:monitor(process, Pid),
#transport{parent = Pid,
mode = {connect, connect(Sock, RAs, RP, [])},
socket = Sock};
+i({connect, _, _, _} = T) -> %% from old code
+ x(T);
%% An accepting transport spawned by diameter.
-i({accept, Pid, LPid, Sock}) ->
+i({accept, Pid, LPid, Sock, Ref})
+ when is_pid(Pid) ->
+ putr(ref, Ref),
proc_lib:init_ack({ok, self()}),
erlang:monitor(process, Pid),
erlang:monitor(process, LPid),
#transport{parent = Pid,
mode = {accept, LPid},
socket = Sock};
+i({accept, _, _, _} = T) -> %% from old code
+ x(T);
%% An accepting transport spawned at association establishment.
i({accept, Ref, LPid, Sock, Id}) ->
+ putr(ref, Ref),
proc_lib:init_ack({ok, self()}),
MRef = erlang:monitor(process, LPid),
%% Wait for a signal that the transport has been started before
@@ -250,13 +261,33 @@ gen_opts(Opts) ->
[binary, {active, once} | Opts].
%% ---------------------------------------------------------------------------
+%% # ports/0-1
+%% ---------------------------------------------------------------------------
+
+ports() ->
+ Ts = diameter_reg:match({?MODULE, '_', '_'}),
+ [{type(T), N, Pid} || {{?MODULE, T, {_, {_, S}}}, Pid} <- Ts,
+ {ok, N} <- [inet:port(S)]].
+
+ports(Ref) ->
+ Ts = diameter_reg:match({?MODULE, '_', {Ref, '_'}}),
+ [{type(T), N, Pid} || {{?MODULE, T, {R, {_, S}}}, Pid} <- Ts,
+ R == Ref,
+ {ok, N} <- [inet:port(S)]].
+
+type(listener) ->
+ listen;
+type(T) ->
+ T.
+
+%% ---------------------------------------------------------------------------
%% # handle_call/3
%% ---------------------------------------------------------------------------
handle_call({{accept, Ref}, Pid}, _, #listener{ref = Ref,
count = N}
= S) ->
- {TPid, NewS} = accept(Pid, S),
+ {TPid, NewS} = accept(Ref, Pid, S),
{reply, {ok, TPid}, NewS#listener{count = N+1}};
handle_call(_, _, State) ->
@@ -306,6 +337,12 @@ terminate(_, #listener{socket = Sock}) ->
%% ---------------------------------------------------------------------------
+putr(Key, Val) ->
+ put({?MODULE, Key}, Val).
+
+getr(Key) ->
+ get({?MODULE, Key}).
+
%% start_timer/1
start_timer(#listener{count = 0} = S) ->
@@ -411,27 +448,41 @@ transition({diameter, {send, Msg}}, S) ->
transition({diameter, {close, Pid}}, #transport{parent = Pid}) ->
stop;
+%% TLS over SCTP is described in RFC 3436 but has limitations as
+%% described in RFC 6083. The latter describes DTLS over SCTP, which
+%% addresses these limitations, DTLS itself being described in RFC
+%% 4347. TLS is primarily used over TCP, which the current RFC 3588
+%% draft acknowledges by equating TLS with TLS/TCP and DTLS/SCTP.
+transition({diameter, {tls, _Ref, _Type, _Bool}}, _) ->
+ stop;
+
%% Listener process has died.
transition({'DOWN', _, process, Pid, _}, #transport{mode = {accept, Pid}}) ->
stop;
%% Parent process has died.
transition({'DOWN', _, process, Pid, _}, #transport{parent = Pid}) ->
- stop.
+ stop;
+
+%% Request for the local port number.
+transition({resolve_port, Pid}, #transport{socket = Sock})
+ when is_pid(Pid) ->
+ Pid ! inet:port(Sock),
+ ok.
%% Crash on anything unexpected.
-%% accept/2
+%% accept/3
%%
%% Start a new transport process or use one that's already been
%% started as a consequence of association establishment.
%% No pending associations: spawn a new transport.
-accept(Pid, #listener{socket = Sock,
- tmap = T,
- pending = {0,_} = Q}
- = S) ->
- Arg = {accept, Pid, self(), Sock},
+accept(Ref, Pid, #listener{socket = Sock,
+ tmap = T,
+ pending = {0,_} = Q}
+ = S) ->
+ Arg = {accept, Pid, self(), Sock, Ref},
{ok, TPid} = diameter_sctp_sup:start_child(Arg),
MRef = erlang:monitor(process, TPid),
ets:insert(T, [{MRef, TPid}, {TPid, MRef}]),
@@ -442,12 +493,12 @@ accept(Pid, #listener{socket = Sock,
%% Accepting transport has died. This can happen if a new transport is
%% started before the DOWN has arrived.
-accept(Pid, #listener{pending = [TPid | {0,_} = Q]} = S) ->
+accept(Ref, Pid, #listener{pending = [TPid | {0,_} = Q]} = S) ->
false = is_process_alive(TPid), %% assert
- accept(Pid, S#listener{pending = Q});
+ accept(Ref, Pid, S#listener{pending = Q});
%% Pending associations: attach to the first in the queue.
-accept(Pid, #listener{ref = Ref, pending = {N,Q}} = S) ->
+accept(_, Pid, #listener{ref = Ref, pending = {N,Q}} = S) ->
TPid = ets:first(Q),
TPid ! {Ref, Pid},
ets:delete(Q, TPid),
@@ -499,8 +550,14 @@ recv({[], #sctp_assoc_change{state = comm_up,
outbound_streams = OS,
inbound_streams = IS,
assoc_id = Id}},
- #transport{assoc_id = undefined}
+ #transport{assoc_id = undefined,
+ mode = {T, _},
+ socket = Sock}
= S) ->
+ Ref = getr(ref),
+ is_reference(Ref) %% started in new code
+ andalso
+ (true = diameter_reg:add_new({?MODULE, T, {Ref, {Id, Sock}}})),
up(S#transport{assoc_id = Id,
streams = {IS, OS}});
@@ -525,7 +582,22 @@ recv({[#sctp_sndrcvinfo{stream = Id}], Bin}, #transport{parent = Pid})
recv({[], #sctp_shutdown_event{assoc_id = Id}},
#transport{assoc_id = Id}) ->
- stop.
+ stop;
+
+%% Note that diameter_sctp(3) documents that sctp_events cannot be
+%% specified in the list of options passed to gen_sctp and that
+%% gen_opts/1 guards against this. This is to ensure that we know what
+%% events to expect and also to ensure that we receive
+%% #sctp_sndrcvinfo{} with each incoming message (data_io_event =
+%% true). Adaptation layer events (ie. #sctp_adaptation_event{}) are
+%% disabled by default so don't handle it. We could simply disable
+%% events we don't react to but don't.
+
+recv({[], #sctp_paddr_change{}}, _) ->
+ ok;
+
+recv({[], #sctp_pdapi_event{}}, _) ->
+ ok.
%% up/1
@@ -591,7 +663,7 @@ f([], _, _) ->
%% assoc_id/1
-assoc_id(#sctp_shutdown_event{assoc_id = Id}) -> %% undocumented
+assoc_id(#sctp_shutdown_event{assoc_id = Id}) ->
Id;
assoc_id(#sctp_assoc_change{assoc_id = Id}) ->
Id;
diff --git a/lib/diameter/src/transport/diameter_tcp.erl b/lib/diameter/src/transport/diameter_tcp.erl
index 653c114471..78dbda6888 100644
--- a/lib/diameter/src/transport/diameter_tcp.erl
+++ b/lib/diameter/src/transport/diameter_tcp.erl
@@ -37,6 +37,9 @@
code_change/3,
terminate/2]).
+-export([ports/0,
+ ports/1]).
+
-include_lib("diameter/include/diameter.hrl").
-define(ERROR(T), erlang:error({T, ?MODULE, ?LINE})).
@@ -45,6 +48,9 @@
-define(LISTENER_TIMEOUT, 30000).
-define(FRAGMENT_TIMEOUT, 1000).
+%% cb_info passed to ssl.
+-define(TCP_CB(Mod), {Mod, tcp, tcp_closed, tcp_error}).
+
%% The same gen_server implementation supports three different kinds
%% of processes: an actual transport process, one that will club it to
%% death should the parent die before a connection is established, and
@@ -71,8 +77,8 @@
{socket :: inet:socket(), %% accept or connect socket
parent :: pid(), %% of process that started us
module :: module(), %% gen_tcp-like module
- frag = <<>> :: binary() | {tref(), frag()}}). %% message fragment
-
+ frag = <<>> :: binary() | {tref(), frag()}, %% message fragment
+ ssl :: boolean() | [term()]}). %% ssl options
%% The usual transport using gen_tcp can be replaced by anything
%% sufficiently gen_tcp-like by passing a 'module' option as the first
%% (for simplicity) transport option. The transport_module diameter_etcp
@@ -122,12 +128,18 @@ i({T, Ref, Mod, Pid, Opts, Addrs})
%% that does nothing but kill us with the parent until call
%% returns.
{ok, MPid} = diameter_tcp_sup:start_child(#monitor{parent = Pid}),
- Sock = i(T, Ref, Mod, Pid, Opts, Addrs),
+ {SslOpts, Rest} = ssl(Opts),
+ Sock = i(T, Ref, Mod, Pid, SslOpts, Rest, Addrs),
MPid ! {stop, self()}, %% tell the monitor to die
- setopts(Mod, Sock),
+ M = if SslOpts -> ssl; true -> Mod end,
+ setopts(M, Sock),
+ putr(ref, Ref),
#transport{parent = Pid,
- module = Mod,
- socket = Sock};
+ module = M,
+ socket = Sock,
+ ssl = SslOpts};
+%% Put the reference in the process dictionary since we now use it
+%% advertise the ssl socket after TLS upgrade.
%% A monitor process to kill the transport if the parent dies.
i(#monitor{parent = Pid, transport = TPid} = S) ->
@@ -146,27 +158,51 @@ i({listen, LRef, APid, {Mod, Opts, Addrs}}) ->
LAddr = get_addr(LA, Addrs),
LPort = get_port(LP),
{ok, LSock} = Mod:listen(LPort, gen_opts(LAddr, Rest)),
+ true = diameter_reg:add_new({?MODULE, listener, {LRef, {LAddr, LSock}}}),
proc_lib:init_ack({ok, self(), {LAddr, LSock}}),
erlang:monitor(process, APid),
- true = diameter_reg:add_new({?MODULE, listener, {LRef, {LAddr, LSock}}}),
start_timer(#listener{socket = LSock}).
-%% i/6
+ssl(Opts) ->
+ {[SslOpts], Rest} = proplists:split(Opts, [ssl_options]),
+ {ssl_opts(SslOpts), Rest}.
+
+ssl_opts([]) ->
+ false;
+ssl_opts([{ssl_options, true}]) ->
+ true;
+ssl_opts([{ssl_options, Opts}])
+ when is_list(Opts) ->
+ Opts;
+ssl_opts(L) ->
+ ?ERROR({ssl_options, L}).
+
+%% i/7
+
+%% Establish a TLS connection before capabilities exchange ...
+i(Type, Ref, Mod, Pid, true, Opts, Addrs) ->
+ i(Type, Ref, ssl, Pid, [{cb_info, ?TCP_CB(Mod)} | Opts], Addrs);
+
+%% ... or not.
+i(Type, Ref, Mod, Pid, _, Opts, Addrs) ->
+ i(Type, Ref, Mod, Pid, Opts, Addrs).
-i(accept, Ref, Mod, Pid, Opts, Addrs) ->
+i(accept = T, Ref, Mod, Pid, Opts, Addrs) ->
{LAddr, LSock} = listener(Ref, {Mod, Opts, Addrs}),
proc_lib:init_ack({ok, self(), [LAddr]}),
Sock = ok(accept(Mod, LSock)),
+ true = diameter_reg:add_new({?MODULE, T, {Ref, Sock}}),
diameter_peer:up(Pid),
Sock;
-i(connect, _, Mod, Pid, Opts, Addrs) ->
+i(connect = T, Ref, Mod, Pid, Opts, Addrs) ->
{[LA, RA, RP], Rest} = proplists:split(Opts, [ip, raddr, rport]),
LAddr = get_addr(LA, Addrs),
RAddr = get_addr(RA, []),
RPort = get_port(RP),
proc_lib:init_ack({ok, self(), [LAddr]}),
Sock = ok(connect(Mod, RAddr, RPort, gen_opts(LAddr, Rest))),
+ true = diameter_reg:add_new({?MODULE, T, {Ref, Sock}}),
diameter_peer:up(Pid, {RAddr, RPort}),
Sock.
@@ -227,6 +263,43 @@ gen_opts(LAddr, Opts) ->
| Opts].
%% ---------------------------------------------------------------------------
+%% # ports/1
+%% ---------------------------------------------------------------------------
+
+ports() ->
+ Ts = diameter_reg:match({?MODULE, '_', '_'}),
+ [{type(T), resolve(T,S), Pid} || {{?MODULE, T, {_,S}}, Pid} <- Ts].
+
+ports(Ref) ->
+ Ts = diameter_reg:match({?MODULE, '_', {Ref, '_'}}),
+ [{type(T), resolve(T,S), Pid} || {{?MODULE, T, {R,S}}, Pid} <- Ts,
+ R == Ref].
+
+type(listener) ->
+ listen;
+type(T) ->
+ T.
+
+sock(listener, {_LAddr, Sock}) ->
+ Sock;
+sock(_, Sock) ->
+ Sock.
+
+resolve(Type, S) ->
+ Sock = sock(Type, S),
+ try
+ ok(portnr(Sock))
+ catch
+ _:_ -> Sock
+ end.
+
+portnr(Sock)
+ when is_port(Sock) ->
+ portnr(gen_tcp, Sock);
+portnr(Sock) ->
+ portnr(ssl, Sock).
+
+%% ---------------------------------------------------------------------------
%% # handle_call/3
%% ---------------------------------------------------------------------------
@@ -258,6 +331,8 @@ handle_info(T, #monitor{} = S) ->
%% # code_change/3
%% ---------------------------------------------------------------------------
+code_change(_, {transport, _, _, _, _} = S, _) ->
+ {ok, #transport{} = list_to_tuple(tuple_to_list(S) ++ [false])};
code_change(_, State, _) ->
{ok, State}.
@@ -270,6 +345,12 @@ terminate(_, _) ->
%% ---------------------------------------------------------------------------
+putr(Key, Val) ->
+ put({?MODULE, Key}, Val).
+
+getr(Key) ->
+ get({?MODULE, Key}).
+
%% start_timer/1
start_timer(#listener{count = 0} = S) ->
@@ -332,17 +413,56 @@ t(T,S) ->
%% transition/2
+%% Initial incoming message when we might need to upgrade to TLS:
+%% don't request another message until we know.
+transition({tcp, Sock, Bin}, #transport{socket = Sock,
+ parent = Pid,
+ frag = Head,
+ module = M,
+ ssl = Opts}
+ = S)
+ when is_list(Opts) ->
+ case recv1(Head, Bin) of
+ {Msg, B} when is_binary(Msg) ->
+ diameter_peer:recv(Pid, Msg),
+ S#transport{frag = B};
+ Frag ->
+ setopts(M, Sock),
+ S#transport{frag = Frag}
+ end;
+
%% Incoming message.
-transition({tcp, Sock, Data}, #transport{socket = Sock,
- module = M}
- = S) ->
+transition({P, Sock, Bin}, #transport{socket = Sock,
+ module = M,
+ ssl = B}
+ = S)
+ when P == tcp, not B;
+ P == ssl, B ->
+ setopts(M, Sock),
+ recv(Bin, S);
+
+%% Capabilties exchange has decided on whether or not to run over TLS.
+transition({diameter, {tls, Ref, Type, B}}, #transport{parent = Pid}
+ = S) ->
+ #transport{socket = Sock,
+ module = M}
+ = NS
+ = tls_handshake(Type, B, S),
+ Pid ! {diameter, {tls, Ref}},
setopts(M, Sock),
- recv(Data, S);
+ NS#transport{ssl = B};
-transition({tcp_closed, Sock}, #transport{socket = Sock}) ->
+transition({C, Sock}, #transport{socket = Sock,
+ ssl = B})
+ when C == tcp_closed, not B;
+ C == ssl_closed, B ->
stop;
-transition({tcp_error, Sock, _Reason} = T, #transport{socket = Sock} = S) ->
+transition({E, Sock, _Reason} = T, #transport{socket = Sock,
+ ssl = B}
+ = S)
+ when E == tcp_error, not B;
+ E == ssl_error, B ->
?ERROR({T,S});
%% Outgoing message.
@@ -367,10 +487,10 @@ transition({timeout, TRef, flush}, S) ->
flush(TRef, S);
%% Request for the local port number.
-transition({resolve_port, RPid}, #transport{socket = Sock,
- module = M})
- when is_pid(RPid) ->
- RPid ! lport(M, Sock),
+transition({resolve_port, Pid}, #transport{socket = Sock,
+ module = M})
+ when is_pid(Pid) ->
+ Pid ! portnr(M, Sock),
ok;
%% Parent process has died.
@@ -379,80 +499,122 @@ transition({'DOWN', _, process, Pid, _}, #transport{parent = Pid}) ->
%% Crash on anything unexpected.
+%% tls_handshake/3
+%%
+%% In the case that no tls message is received (eg. the service hasn't
+%% been configured to advertise TLS support) we will simply never ask
+%% for another TCP message, which will force the watchdog to
+%% eventually take us down.
+
+%% TLS has already been established with the connection.
+tls_handshake(_, _, #transport{ssl = true} = S) ->
+ S;
+
+%% Capabilities exchange negotiated TLS but transport was not
+%% configured with an options list.
+tls_handshake(_, true, #transport{ssl = false}) ->
+ ?ERROR(no_ssl_options);
+
+%% Capabilities exchange negotiated TLS: upgrade the connection.
+tls_handshake(Type, true, #transport{socket = Sock,
+ module = M,
+ ssl = Opts}
+ = S) ->
+ {ok, SSock} = tls(Type, Sock, [{cb_info, ?TCP_CB(M)} | Opts]),
+ Ref = getr(ref),
+ is_reference(Ref) %% started in new code
+ andalso
+ (true = diameter_reg:add_new({?MODULE, Type, {Ref, SSock}})),
+ S#transport{socket = SSock,
+ module = ssl};
+
+%% Capabilities exchange has not negotiated TLS.
+tls_handshake(_, false, S) ->
+ S.
+
+tls(connect, Sock, Opts) ->
+ ssl:connect(Sock, Opts);
+tls(accept, Sock, Opts) ->
+ ssl:ssl_accept(Sock, Opts).
+
%% recv/2
%%
%% Reassemble fragmented messages and extract multple message sent
%% using Nagle.
recv(Bin, #transport{parent = Pid, frag = Head} = S) ->
- S#transport{frag = recv(Pid, Head, Bin)}.
+ case recv1(Head, Bin) of
+ {Msg, B} when is_binary(Msg) ->
+ diameter_peer:recv(Pid, Msg),
+ recv(B, S#transport{frag = <<>>});
+ Frag ->
+ S#transport{frag = Frag}
+ end.
-%% recv/3
+%% recv1/2
%% No previous fragment.
-recv(Pid, <<>>, Bin) ->
- rcv(Pid, Bin);
+recv1(<<>>, Bin) ->
+ rcv(Bin);
-recv(Pid, {TRef, Head}, Bin) ->
+recv1({TRef, Head}, Bin) ->
erlang:cancel_timer(TRef),
- rcv(Pid, Head, Bin).
+ rcv(Head, Bin).
-%% rcv/3
+%% rcv/2
%% Not even the first four bytes of the header.
-rcv(Pid, Head, Bin)
+rcv(Head, Bin)
when is_binary(Head) ->
- rcv(Pid, <<Head/binary, Bin/binary>>);
+ rcv(<<Head/binary, Bin/binary>>);
%% Or enough to know how many bytes to extract.
-rcv(Pid, {Len, N, Head, Acc}, Bin) ->
- rcv(Pid, Len, N + size(Bin), Head, [Bin | Acc]).
+rcv({Len, N, Head, Acc}, Bin) ->
+ rcv(Len, N + size(Bin), Head, [Bin | Acc]).
-%% rcv/5
+%% rcv/4
%% Extract a message for which we have all bytes.
-rcv(Pid, Len, N, Head, Acc)
+rcv(Len, N, Head, Acc)
when Len =< N ->
- rcv(Pid, rcv1(Pid, Len, bin(Head, Acc)));
+ rcv1(Len, bin(Head, Acc));
%% Wait for more packets.
-rcv(_, Len, N, Head, Acc) ->
+rcv(Len, N, Head, Acc) ->
{start_timer(), {Len, N, Head, Acc}}.
%% rcv/2
%% Nothing left.
-rcv(_, <<>> = Bin) ->
+rcv(<<>> = Bin) ->
Bin;
%% Well, this isn't good. Chances are things will go south from here
%% but if we're lucky then the bytes we have extend to an intended
%% message boundary and we can recover by simply discarding them,
%% which is the result of receiving them.
-rcv(Pid, <<_:1/binary, Len:24, _/binary>> = Bin)
+rcv(<<_:1/binary, Len:24, _/binary>> = Bin)
when Len < 20 ->
- diameter_peer:recv(Pid, Bin),
- <<>>;
+ {Bin, <<>>};
%% Enough bytes to extract a message.
-rcv(Pid, <<_:1/binary, Len:24, _/binary>> = Bin)
+rcv(<<_:1/binary, Len:24, _/binary>> = Bin)
when Len =< size(Bin) ->
- rcv(Pid, rcv1(Pid, Len, Bin));
+ rcv1(Len, Bin);
%% Or not: wait for more packets.
-rcv(_, <<_:1/binary, Len:24, _/binary>> = Head) ->
+rcv(<<_:1/binary, Len:24, _/binary>> = Head) ->
{start_timer(), {Len, size(Head), Head, []}};
%% Not even 4 bytes yet.
-rcv(_, Head) ->
+rcv(Head) ->
{start_timer(), Head}.
-%% rcv1/3
+%% rcv1/2
-rcv1(Pid, Len, Bin) ->
+rcv1(Len, Bin) ->
<<Msg:Len/binary, Rest/binary>> = Bin,
- diameter_peer:recv(Pid, Msg),
- Rest.
+ {Msg, Rest}.
%% bin/[12]
@@ -489,15 +651,18 @@ flush(_, S) ->
%% accept/2
-accept(gen_tcp, LSock) ->
- gen_tcp:accept(LSock);
+accept(ssl, LSock) ->
+ case ssl:transport_accept(LSock) of
+ {ok, Sock} ->
+ {ssl:ssl_accept(Sock), Sock};
+ {error, _} = No ->
+ No
+ end;
accept(Mod, LSock) ->
Mod:accept(LSock).
%% connect/4
-connect(gen_tcp, Host, Port, Opts) ->
- gen_tcp:connect(Host, Port, Opts);
connect(Mod, Host, Port, Opts) ->
Mod:connect(Host, Port, Opts).
@@ -505,6 +670,8 @@ connect(Mod, Host, Port, Opts) ->
send(gen_tcp, Sock, Bin) ->
gen_tcp:send(Sock, Bin);
+send(ssl, Sock, Bin) ->
+ ssl:send(Sock, Bin);
send(M, Sock, Bin) ->
M:send(Sock, Bin).
@@ -512,6 +679,8 @@ send(M, Sock, Bin) ->
setopts(gen_tcp, Sock, Opts) ->
inet:setopts(Sock, Opts);
+setopts(ssl, Sock, Opts) ->
+ ssl:setopts(Sock, Opts);
setopts(M, Sock, Opts) ->
M:setopts(Sock, Opts).
@@ -523,9 +692,16 @@ setopts(M, Sock) ->
X -> x({setopts, M, Sock, X}) %% possibly on peer disconnect
end.
-%% lport/2
+%% portnr/2
-lport(gen_tcp, Sock) ->
+portnr(gen_tcp, Sock) ->
inet:port(Sock);
-lport(M, Sock) ->
+portnr(ssl, Sock) ->
+ case ssl:sockname(Sock) of
+ {ok, {_Addr, PortNr}} ->
+ {ok, PortNr};
+ {error, _} = No ->
+ No
+ end;
+portnr(M, Sock) ->
M:port(Sock).
diff --git a/lib/diameter/src/transport/modules.mk b/lib/diameter/src/transport/modules.mk
deleted file mode 100644
index a0dc3cf2c0..0000000000
--- a/lib/diameter/src/transport/modules.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-#-*-makefile-*- ; force emacs to enter makefile-mode
-
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2010-2011. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-
-MODULES = \
- diameter_etcp \
- diameter_etcp_sup \
- diameter_tcp \
- diameter_tcp_sup \
- diameter_sctp \
- diameter_sctp_sup \
- diameter_transport_sup
-
-HRL_FILES =
diff --git a/lib/diameter/src/transport/.gitignore b/lib/diameter/test/.gitignore
index d9f072e262..df38dfc5e3 100644
--- a/lib/diameter/src/transport/.gitignore
+++ b/lib/diameter/test/.gitignore
@@ -1,3 +1,3 @@
+/log
/depend.mk
-
diff --git a/lib/diameter/test/Makefile b/lib/diameter/test/Makefile
index 823e2f0311..97d9069f4a 100644
--- a/lib/diameter/test/Makefile
+++ b/lib/diameter/test/Makefile
@@ -16,40 +16,27 @@
#
# %CopyrightEnd%
-ifneq ($(ERL_TOP),)
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-else
+ifeq ($(ERL_TOP),)
include $(DIAMETER_TOP)/make/target.mk
include $(DIAMETER_TOP)/make/$(TARGET)/rules.mk
+else
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
endif
# ----------------------------------------------------
# Application version
# ----------------------------------------------------
+
include ../vsn.mk
-VSN=$(DIAMETER_VSN)
+VSN = $(DIAMETER_VSN)
# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/diameter_test
-
-ifeq ($(findstring win32,$(TARGET)),win32)
-
-MAKEFILE_SRC = Makefile.win32.src
-
-else
-
-MAKEFILE_SRC = Makefile.src
-
-endif
-
-ifeq ($(TT_DIR),)
-TT_DIR = /tmp
-endif
+RELSYSDIR = $(RELEASE_PATH)/diameter_test
# ----------------------------------------------------
# Target Specs
@@ -57,352 +44,140 @@ endif
include modules.mk
-EBIN = .
-
-HRL_FILES = diameter_test_lib.hrl
-
-ERL_FILES = $(MODULES:%=%.erl)
-
-SOURCE = $(HRL_FILES) $(ERL_FILES)
-
+ERL_FILES = $(MODULES:%=%.erl)
TARGET_FILES = $(MODULES:%=%.$(EMULATOR))
-APP_CASES = app appup
-
-TRANSPORT_CASES = tcp
-
-ALL_CASES = \
- $(APP_CASES) \
- compiler conf sync session stats reg peer \
- $(TRANSPORT_CASES)
-
-
-EMAKEFILE = Emakefile
-ifneq ($(ERL_TOP),)
-MAKE_EMAKE = $(wildcard $(ERL_TOP)/make/make_emakefile)
-else
-MAKE_EMAKE = $(wildcard $(DIAMETER_TOP)/make/make_emakefile)
-endif
-
-ifeq ($(MAKE_EMAKE),)
-BUILDTARGET = $(TARGET_FILES)
-RELTEST_FILES = $(TEST_SPEC_FILE) $(COVER_SPEC_FILE) $(SOURCE)
-else
-BUILDTARGET = emakebuild
-RELTEST_FILES = $(EMAKEFILE) $(TEST_SPEC_FILE) $(COVER_SPEC_FILE) $(SOURCE)
-endif
-
+SUITE_MODULES = $(filter diameter_%_SUITE, $(MODULES))
+SUITES = $(SUITE_MODULES:diameter_%_SUITE=%)
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
-include ../src/app/diameter.mk
-
-ifeq ($(USE_DIAMETER_TEST_CODE),true)
-ERL_COMPILE_FLAGS += -DDIAMETER_TEST_CODE=mona_lisa_spelar_doom
-endif
-
-ifeq ($(USE_DIAMETER_HIPE),true)
-ERL_COMPILE_FLAGS += +native -DDIAMETER_hipe_special=true
-endif
-
-ifneq ($(ERL_TOP),)
-ERL_COMPILE_FLAGS += \
- $(DIAMETER_ERL_COMPILE_FLAGS) \
- -pa $(ERL_TOP)/lib/test_server/ebin \
- -I$(ERL_TOP)/lib/test_server/include
-else
-ERL_COMPILE_FLAGS += \
- $(DIAMETER_ERL_COMPILE_FLAGS) \
- -pa $(TEST_SERVER_DIR)/ebin \
- -I$(TEST_SERVER_DIR)/include
-endif
-
-ERL_PATH = \
- -pa ../../$(APPLICATION)/ebin \
- -pa ../../et/ebin
-
-ifndef SUITE
-SUITE = diameter_SUITE
-endif
-
-ESTOP = -s init stop
-
-ifeq ($(DONT_STOP),true)
-MAYBE_ESTOP =
-else
-MAYBE_ESTOP = $(ESTOP)
-endif
-
-ETVIEW = -s et_viewer
-ifeq ($(USE_ET_VIEWER),true)
-MAYBE_ETVIEW =
-else
-MAYBE_ETVIEW = $(ETVIEW)
-endif
-
-ifeq ($(MERL),)
-MERL = $(ERL)
-endif
-
-ARGS += -noshell
-
-ifeq ($(DISABLE_TC_TIMEOUT),true)
-ARGS += -diameter_test_timeout
-endif
-
-
-DIAMETER_TEST_SERVER = diameter_test_server
-
+# This is only used to compile suite locally when running with a
+# target like 'all' below. Target release_tests only installs source.
+ERL_COMPILE_FLAGS += +warn_export_vars \
+ +warn_unused_vars \
+ -I ../include \
+ -I ../src/gen
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-tests debug opt: $(BUILDTARGET)
+all: opt
-targets: $(TARGET_FILES)
+run: $(SUITES)
-.PHONY: emakebuild
-
-emakebuild: $(EMAKEFILE)
-
-$(EMAKEFILE):
- $(MAKE_EMAKE) $(ERL_COMPILE_FLAGS) -o$(EBIN) '*_SUITE_make' | grep -v Warning > $(EMAKEFILE)
- $(MAKE_EMAKE) $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) | grep -v Warning >> $(EMAKEFILE)
+debug opt: $(TARGET_FILES)
clean:
- rm -f $(EMAKEFILE)
rm -f $(TARGET_FILES)
- rm -f errs core *~
+ rm -f depend.mk
+
+realclean: clean
+ rm -rf log
docs:
+list = echo $(1):; echo $($(1)) | tr ' ' '\n' | sort | sed 's@^@ @'
+
info:
- @echo "MAKE_EMAKE = $(MAKE_EMAKE)"
- @echo "EMAKEFILE = $(EMAKEFILE)"
- @echo "BUILDTARGET = $(BUILDTARGET)"
- @echo ""
- @echo "ERL_COMPILE_FLAGS = $(ERL_COMPILE_FLAGS)"
- @echo "ERL = $(ERL)"
- @echo "ERLC = $(ERLC)"
- @echo "MERL = $(MERL)"
- @echo ""
- @echo "ARGS = $(ARGS)"
- @echo ""
- @echo "HRL_FILES = $(HRL_FILES)"
- @echo "ERL_FILES = $(ERL_FILES)"
- @echo "TARGET_FILES = $(TARGET_FILES)"
- @echo ""
+ @echo ========================================
+ @$(call list,MODULES)
+ @echo
+ @$(call list,HRL_FILES)
+ @echo
+ @$(call list,SUITES)
+ @echo ========================================
help:
- @echo ""
- @echo "This Makefile controls the test of the $(APPLICATION) application. "
- @echo ""
- @echo "There are two separate ways to perform the test of $(APPLICATION)."
- @echo ""
- @echo " a) Run the official OTP test-server (which we do not describe here)"
- @echo ""
- @echo " b) Run the test-server provided with this application. "
- @echo " There are a number of targets to run the entire or parts"
- @echo " of this applications ($(APPLICATION)) test-suite"
- @echo ""
- @echo "Targets:"
- @echo ""
- @echo " help"
- @echo " Print this info"
- @echo ""
- @echo " info"
- @echo " Prints various environment variables. "
- @echo " May be useful when debugging the Makefile. "
- @echo ""
- @echo " tests | debug | opt "
- @echo " Compile all test-code. "
- @echo ""
- @echo " clean "
- @echo " Remove all targets. "
- @echo ""
- @echo " test"
- @echo " Run the entire $(APPLICATION) test-suite. "
- @echo ""
- @echo " app"
- @echo " Run the $(APPLICATION) application sub-test-suite. "
- @echo ""
- @echo " appup"
- @echo " Run the $(APPLICATION) application upgrade (appup) sub-test-suite. "
- @echo ""
- @echo " compiler"
- @echo " Run the $(APPLICATION) compiler sub-test-suite(s). "
- @echo ""
- @echo " conf"
- @echo " Run the $(APPLICATION) config sub-test-suite. "
- @echo " Checks various aspects of the $(APPLICATION) configuration. "
- @echo ""
- @echo " sync"
- @echo " Run the $(APPLICATION) sync sub-test-suite. "
- @echo ""
- @echo " session"
- @echo " Run the $(APPLICATION) session sub-test-suite. "
- @echo ""
- @echo " stats"
- @echo " Run the $(APPLICATION) stats sub-test-suite. "
- @echo ""
- @echo " reg"
- @echo " Run the $(APPLICATION) reg sub-test-suite. "
- @echo ""
- @echo " peer"
- @echo " Run the $(APPLICATION) peer sub-test-suite"
- @echo ""
- @echo " ptab"
- @echo " Run the $(APPLICATION) persistent-table sub-test-suite"
- @echo ""
- @echo " tcp"
- @echo " Run the $(APPLICATION) tcp sub-test-suite"
- @echo ""
- @echo ""
-
+ @echo ========================================
+ @echo "Useful targets:"
+ @echo
+ @echo " all:"
+ @echo " Compile all test suites."
+ @echo
+ @echo " run:"
+ @echo " Compile and run all test suites."
+ @echo
+ @echo " $(SUITES):"
+ @echo " Compile and run a specific test suite."
+ @echo
+ @echo " clean | realclean:"
+ @echo " Remove generated files."
+ @echo
+ @echo " info:"
+ @echo " Echo some relevant variables."
+ @echo ========================================
+
+.PHONY: all run clean debug docs help info opt realclean
# ----------------------------------------------------
# Special Targets
# ----------------------------------------------------
-all: make
- @echo "make sure epmd is new"
- @epmd -kill > /dev/null
- @echo "Running all sub-suites separatelly"
- @for i in $(ALL_CASES); do \
- echo "SUITE: $$i"; \
- clearmake -V $$i > $$i.log; \
- done
-
-aall: make
- @echo "make sure epmd is new"
- @epmd -kill > /dev/null
- @echo "Running all app sub-suites separatelly"
- @for i in $(APP_CASES); do \
- echo "SUITE: $$i"; \
- clearmake -V $$i > $$i.log; \
- done
- echo "done"
-
-tall: make
- @echo "make sure epmd is new"
- @epmd -kill > /dev/null
- @echo "Running all transport sub-suites separatelly"
- @for i in $(TRANSPORT_CASES); do \
- echo "SUITE: $$i"; \
- clearmake -V $$i > $$i.log; \
- done
-
-make: targets
-
-test: make
- $(MERL) $(ARGS) -sname diameter_test $(ERL_PATH) \
- -s $(DIAMETER_TEST_SERVER) t $(SUITE) \
- $(MAYBE_ESTOP)
-
-utest: make
- $(MERL) $(ARGS) -sname diameter_utest $(ERL_PATH) \
- $(MAYBE_ETVIEW) \
- -s $(DIAMETER_TEST_SERVER) t $(SUITE) \
- $(ESTOP)
-
-# ftest: make
-# $(MERL) $(ARGS) -sname diameter_ftest $(ERL_PATH) \
-# -s diameter_filter \
-# -s $(DIAMETER_TEST_SERVER) t $(SUITE) \
-# $(ESTOP)
-#
-
-##########################
-
-# tickets: make
-# $(MERL) $(ARGS) -sname diameter_tickets $(ERL_PATH) \
-# -s $(DIAMETER_TEST_SERVER) tickets $(SUITE) \
-# $(ESTOP)
-#
-
-app: make
- $(MERL) $(ARGS) -sname diameter_app $(ERL_PATH) \
- -s $(DIAMETER_TEST_SERVER) t diameter_app_test \
- $(ESTOP)
-
-appup: make
- $(MERL) $(ARGS) -sname diameter_appup $(ERL_PATH) \
- -s $(DIAMETER_TEST_SERVER) t diameter_appup_test \
- $(ESTOP)
+# Exit with a non-zero status if the output looks to indicate failure.
+# diameter_ct:run/1 itself can't tell (it seems). The absolute -pa is
+# because ct will change directories.
+$(SUITES): log opt
+ $(ERL) -noshell \
+ -pa $(realpath ../ebin) \
+ -sname diameter_test_$@ \
+ -s diameter_ct run diameter_$@_SUITE \
+ -s init stop \
+ | awk '1{rc=0} {print} / FAILED /{rc=1} END{exit rc}'
+# Shorter in sed but requires a GNU extension (ie. Q).
-compiler: make
- $(MERL) $(ARGS) -sname diameter_compiler $(ERL_PATH) \
- -s $(DIAMETER_TEST_SERVER) t diameter_compiler_test \
- $(ESTOP)
+log:
+ mkdir $@
-conf: make
- $(MERL) $(ARGS) -sname diameter_config $(ERL_PATH) \
- -s $(DIAMETER_TEST_SERVER) t diameter_config_test \
- $(ESTOP)
+.PHONY: $(SUITES)
-sync: make
- $(MERL) $(ARGS) -sname diameter_sync $(ERL_PATH) \
- -s $(DIAMETER_TEST_SERVER) t diameter_sync_test \
- $(ESTOP)
-
-session: make
- $(MERL) $(ARGS) -sname diameter_session $(ERL_PATH) \
- -s $(DIAMETER_TEST_SERVER) t diameter_session_test \
- $(ESTOP)
+# ----------------------------------------------------
+# Release Targets
+# ----------------------------------------------------
-stats: make
- $(MERL) $(ARGS) -sname diameter_stats $(ERL_PATH) \
- -s $(DIAMETER_TEST_SERVER) t diameter_stats_test \
- $(ESTOP)
+/%: % force
+ sed -f release.sed $< > $(RELSYSDIR)$@
-reg: make
- $(MERL) $(ARGS) -sname diameter_reg $(ERL_PATH) \
- -s $(DIAMETER_TEST_SERVER) t diameter_reg_test \
- $(ESTOP)
+ifeq ($(ERL_TOP),)
+include $(DIAMETER_TOP)/make/release_targets.mk
+else
+include $(ERL_TOP)/make/otp_release_targets.mk
+endif
-peer: make
- $(MERL) $(ARGS) -sname diameter_peer $(ERL_PATH) \
- -s $(DIAMETER_TEST_SERVER) t diameter_peer_test \
- $(ESTOP)
+release_spec:
-ptab: make
- $(MERL) $(ARGS) -sname diameter_persistent_table $(ERL_PATH) \
- -s $(DIAMETER_TEST_SERVER) t diameter_persistent_table_test \
- $(ESTOP)
+release_docs_spec:
-tcp: make
- $(MERL) $(ARGS) -sname diameter_tcp $(ERL_PATH) \
- -s $(DIAMETER_TEST_SERVER) t diameter_tcp_test \
- $(ESTOP)
+release_tests_spec:
+ $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DATA) $(TEST_SPEC_FILE) \
+ $(COVER_SPEC_FILE) \
+ $(HRL_FILES) \
+ $(RELSYSDIR)
+ $(MAKE) $(ERL_FILES:%=/%)
+force:
-node:
- $(MERL) -sname diameter $(ERL_PATH)
+.PHONY: release_spec release_docs_spec release_test_specs
+.PHONY: force
+# Can't just make $(ERL_FILES:%=/%) phony since then implicit rule
+# searching is skipped.
# ----------------------------------------------------
-# Release Targets
-# ----------------------------------------------------
-ifneq ($(ERL_TOP),)
-include $(ERL_TOP)/make/otp_release_targets.mk
-else
-include $(DIAMETER_TOP)/make/release_targets.mk
-endif
+depend: depend.mk
-release_spec:
-
-release_docs_spec:
+# Generate dependencies makefile.
+depend.mk: depend.sed $(MODULES:%=%.erl) Makefile
+ (for f in $(MODULES); do \
+ (echo $$f; cat $$f.erl) | sed -f $<; \
+ done) \
+ > $@
-release_tests_spec: tests
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) $(RELTEST_FILES) $(RELSYSDIR)
-# $(INSTALL_DATA) $(TEST_SPEC_FILE) $(COVER_SPEC_FILE) \
-# $(HRL_FILES) $(ERL_FILES) \
-# $(RELSYSDIR)
-#
- chmod -f -R u+w $(RELSYSDIR)
+-include depend.mk
+.PHONY: depend
diff --git a/lib/diameter/src/app/depend.sed b/lib/diameter/test/depend.sed
index 9df0133960..95dca44984 100644
--- a/lib/diameter/src/app/depend.sed
+++ b/lib/diameter/test/depend.sed
@@ -18,14 +18,24 @@
#
#
-# Extract include dependencies from .erl files. The output is massaged
-# further in Makefile.
+# Extract local include dependencies from an .erl file. The first
+# input line is the module name.
#
+# Store the module name in the hold space.
+1{
+ h
+ d
+}
+
+# Throw away everything but local includes.
+/^-include_lib/d
/^-include/!d
-/"diameter/!d
+/diameter_gen/d
+/diameter\./d
-s@^-include_lib("[^/]*@$(DIAMETER_TOP)@
+# Output a dependency of the beam on the included file.
s@^-include("@@
s@".*@@
-s@^@$(EBIN)/.$(EMULATOR): @
+G
+s@^\(.*\)\n\(.*\)@$(EBIN)/\2.$(EMULATOR): \1@
diff --git a/lib/diameter/test/diameter.spec b/lib/diameter/test/diameter.spec
index a6e71762eb..fae7863bec 100644
--- a/lib/diameter/test/diameter.spec
+++ b/lib/diameter/test/diameter.spec
@@ -1,9 +1 @@
{suites, "../diameter_test", all}.
-%%{skip, {diameter_compiler_test, all, "Not yet implemented"}}.
-%%{skip, {diameter_config_test, all, "Not yet implemented"}}.
-%%{skip, {diameter_peer_test, all, "Not yet implemented"}}.
-%%{skip, {diameter_reg_test, all, "Not yet implemented"}}.
-%%{skip, {diameter_session_test, all, "Not yet implemented"}}.
-%%{skip, {diameter_stats_test, all, "Not yet implemented"}}.
-%%{skip, {diameter_sync_test, all, "Not yet implemented"}}.
-%%{skip, {diameter_tcp_test, all, "Not yet implemented"}}.
diff --git a/lib/diameter/test/diameter_SUITE.erl b/lib/diameter/test/diameter_SUITE.erl
deleted file mode 100644
index 443cf90e92..0000000000
--- a/lib/diameter/test/diameter_SUITE.erl
+++ /dev/null
@@ -1,108 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-%%----------------------------------------------------------------------
-%% Purpose: Test application config
-%%----------------------------------------------------------------------
-
--module(diameter_SUITE).
-
--export([
- suite/0,
- all/0,
- groups/0,
-
- init_per_testcase/2,
- fin_per_testcase/2,
-
- init_per_suite/1,
- end_per_suite/1,
-
- init_per_group/2,
- end_per_group/2,
-
- init/0
- ]).
-
--export([t/0, t/1]).
-
-
--include("diameter_test_lib.hrl").
-
-
-t() -> diameter_test_server:t(?MODULE).
-t(Case) -> diameter_test_server:t({?MODULE, Case}).
-
-%% Test server callbacks
-init_per_testcase(Case, Config) ->
- diameter_test_server:init_per_testcase(Case, Config).
-
-fin_per_testcase(Case, Config) ->
- diameter_test_server:fin_per_testcase(Case, Config).
-
-init() ->
- process_flag(trap_exit, true),
- ?FLUSH().
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Top test case
-
-suite() ->
- [{ct_hooks, [{ts_install_cth, [{nodenames,1}]}]}].
-
-all() ->
- [
- {group, app},
- {group, appup},
- {group, compiler},
- {group, config},
- {group, sync},
- {group, session},
- {group, stats},
- {group, reg},
- {group, peer},
- {group, tcp}
- ].
-
-groups() ->
- [{app, [], [{diameter_app_test, all}]},
- {appup, [], [{diameter_appup_test, all}]},
- {compiler, [], [{diameter_compiler_test, all}]},
- {config, [], [{diameter_config_test, all}]},
- {sync, [], [{diameter_sync_test, all}]},
- {session, [], [{diameter_session_test, all}]},
- {stats, [], [{diameter_stats_test, all}]},
- {reg, [], [{diameter_reg_test, all}]},
- {peer, [], [{diameter_peer_test, all}]},
- {tcp, [], [{diameter_tcp_test, all}]}].
-
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
diff --git a/lib/diameter/test/diameter_app_SUITE.erl b/lib/diameter/test/diameter_app_SUITE.erl
new file mode 100644
index 0000000000..7f53a4ddd4
--- /dev/null
+++ b/lib/diameter/test/diameter_app_SUITE.erl
@@ -0,0 +1,270 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests based on the contents of the diameter app file.
+%%
+
+-module(diameter_app_SUITE).
+
+-export([suite/0,
+ all/0,
+ init_per_suite/1,
+ end_per_suite/1]).
+
+%% testcases
+-export([keys/1,
+ vsn/1,
+ modules/1,
+ exports/1,
+ release/1,
+ xref/1,
+ relup/1]).
+
+-include("diameter_ct.hrl").
+
+-define(A, list_to_atom).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 10}}].
+
+all() ->
+ [keys,
+ vsn,
+ modules,
+ exports,
+ release,
+ xref,
+ relup].
+
+init_per_suite(Config) ->
+ [{application, ?APP, App}] = diameter_util:consult(?APP, app),
+ [{app, App} | Config].
+
+end_per_suite(_Config) ->
+ ok.
+
+%% ===========================================================================
+%% # keys/1
+%%
+%% Ensure that the app file contains selected keys. Some of these would
+%% also be caught by other testcases.
+%% ===========================================================================
+
+keys(Config) ->
+ App = fetch(app, Config),
+ [] = lists:filter(fun(K) -> not lists:keymember(K, 1, App) end,
+ [vsn, description, modules, registered, applications]).
+
+%% ===========================================================================
+%% # vsn/1
+%%
+%% Ensure that our app version sticks to convention.
+%% ===========================================================================
+
+vsn(Config) ->
+ true = is_vsn(fetch(vsn, fetch(app, Config))).
+
+%% ===========================================================================
+%% # modules/1
+%%
+%% Ensure that the app file modules and installed modules differ by
+%% compiler/help modules.
+%% ===========================================================================
+
+modules(Config) ->
+ Mods = fetch(modules, fetch(app, Config)),
+ Installed = code_mods(),
+ Help = [diameter_callback,
+ diameter_codegen,
+ diameter_dbg,
+ diameter_exprecs,
+ diameter_info,
+ diameter_make,
+ diameter_spec_scan,
+ diameter_spec_util],
+ {[], Help} = {Mods -- Installed, lists:sort(Installed -- Mods)}.
+
+code_mods() ->
+ Dir = code:lib_dir(?APP, ebin),
+ {ok, Files} = file:list_dir(Dir),
+ [?A(lists:reverse(R)) || N <- Files, "maeb." ++ R <- [lists:reverse(N)]].
+
+%% ===========================================================================
+%% # exports/1
+%%
+%% Ensure that no module does export_all.
+%% ===========================================================================
+
+exports(Config) ->
+ Mods = fetch(modules, fetch(app, Config)),
+ [] = [M || M <- Mods, exports_all(M)].
+
+exports_all(Mod) ->
+ Opts = fetch(options, Mod:module_info(compile)),
+
+ is_list(Opts) andalso lists:member(export_all, Opts).
+
+%% ===========================================================================
+%% # release/1
+%%
+%% Ensure that it's possible to build a minimal release with our app file.
+%% ===========================================================================
+
+release(Config) ->
+ App = fetch(app, Config),
+ Rel = {release,
+ {"diameter test release", fetch(vsn, App)},
+ {erts, erlang:system_info(version)},
+ [{A, appvsn(A)} || A <- [sasl | fetch(applications, App)]]},
+ Dir = fetch(priv_dir, Config),
+ ok = write_file(filename:join([Dir, "diameter_test.rel"]), Rel),
+ {ok, _, []} = systools:make_script("diameter_test", [{path, [Dir]},
+ {outdir, Dir},
+ silent]).
+
+%% sasl need to be included to avoid a missing_sasl warning, error
+%% in the case of relup/1.
+
+appvsn(Name) ->
+ [{application, Name, App}] = diameter_util:consult(Name, app),
+ fetch(vsn, App).
+
+%% ===========================================================================
+%% # xref/1
+%%
+%% Ensure that no function in our application calls an undefined function
+%% or one in an application we haven't specified as a dependency. (Almost.)
+%% ===========================================================================
+
+xref(Config) ->
+ App = fetch(app, Config),
+ Mods = fetch(modules, App),
+
+ {ok, XRef} = xref:start(make_name(xref_test_name)),
+ ok = xref:set_default(XRef, [{verbose, false}, {warnings, false}]),
+
+ %% Only add our application and those it's dependent on according
+ %% to the app file. Well, almost. erts beams are also required to
+ %% stop xref from complaining about calls to module erlang, which
+ %% was previously in kernel. Erts isn't an application however, in
+ %% the sense that there's no .app file, and isn't listed in
+ %% applications. Seems less than ideal. Also, diameter_tcp does
+ %% call ssl despite ssl not being listed as a dependency in the
+ %% app file since ssl is only required for TLS security: it's up
+ %% to a client who wants TLS it to start ssl.
+ ok = lists:foreach(fun(A) -> add_application(XRef, A) end,
+ [?APP, erts | fetch(applications, App)]),
+
+ {ok, Undefs} = xref:analyze(XRef, undefined_function_calls),
+
+ xref:stop(XRef),
+
+ %% Only care about calls from our own application.
+ [] = lists:filter(fun({{F,_,_},{T,_,_}}) ->
+ lists:member(F, Mods)
+ andalso {F,T} /= {diameter_tcp, ssl}
+ end,
+ Undefs).
+
+add_application(XRef, App) ->
+ add_application(XRef, App, code:lib_dir(App)).
+
+%% erts will not be in the lib directory before installation.
+add_application(XRef, erts, {error, _}) ->
+ Dir = filename:join([code:root_dir(), "erts", "preloaded", "ebin"]),
+ {ok, _} = xref:add_directory(XRef, Dir, []);
+add_application(XRef, App, Dir)
+ when is_list(Dir) ->
+ {ok, App} = xref:add_application(XRef, Dir, []).
+
+make_name(Suf) ->
+ list_to_atom(atom_to_list(?APP) ++ "_" ++ atom_to_list(Suf)).
+
+%% ===========================================================================
+%% # relup/1
+%%
+%% Ensure that we can generate release upgrade files using our appup file.
+%% ===========================================================================
+
+relup(Config) ->
+ [{Vsn, Up, Down}] = diameter_util:consult(?APP, appup),
+ true = is_vsn(Vsn),
+
+ App = fetch(app, Config),
+ Rel = [{erts, erlang:system_info(version)}
+ | [{A, appvsn(A)} || A <- [sasl | fetch(applications, App)]]],
+
+ Dir = fetch(priv_dir, Config),
+
+ Name = write_rel(Dir, Rel, Vsn),
+ UpFrom = acc_rel(Dir, Rel, Up),
+ DownTo = acc_rel(Dir, Rel, Down),
+
+ {[Name], [Name], [], []} %% no current in up/down and go both ways
+ = {[Name] -- UpFrom,
+ [Name] -- DownTo,
+ UpFrom -- DownTo,
+ DownTo -- UpFrom},
+
+ [[], []] = [S -- sets:to_list(sets:from_list(S))
+ || S <- [UpFrom, DownTo]],
+
+ {ok, _, _, []} = systools:make_relup(Name, UpFrom, DownTo, [{path, [Dir]},
+ {outdir, Dir},
+ silent]).
+
+acc_rel(Dir, Rel, List) ->
+ lists:foldl(fun(T,A) -> acc_rel(Dir, Rel, T, A) end,
+ [],
+ List).
+
+acc_rel(Dir, Rel, {Vsn, _}, Acc) ->
+ [write_rel(Dir, Rel, Vsn) | Acc].
+
+%% Write a rel file and return its name.
+write_rel(Dir, [Erts | Apps], Vsn) ->
+ true = is_vsn(Vsn),
+ Name = "diameter_test_" ++ Vsn,
+ ok = write_file(filename:join([Dir, Name ++ ".rel"]),
+ {release,
+ {"diameter " ++ Vsn ++ " test release", Vsn},
+ Erts,
+ Apps}),
+ Name.
+
+%% ===========================================================================
+%% ===========================================================================
+
+fetch(Key, List) ->
+ {Key, {Key, Val}} = {Key, lists:keyfind(Key, 1, List)}, %% useful badmatch
+ Val.
+
+write_file(Path, T) ->
+ file:write_file(Path, io_lib:format("~p.", [T])).
+
+%% Is a version string of the expected form? Return the argument
+%% itself for 'false' for a useful badmatch.
+is_vsn(V) ->
+ is_list(V)
+ andalso length(V) == string:span(V, "0123456789.")
+ andalso V == string:join(string:tokens(V, [$.]), ".") %% no ".."
+ orelse {error, V}.
diff --git a/lib/diameter/test/diameter_app_test.erl b/lib/diameter/test/diameter_app_test.erl
deleted file mode 100644
index 7173c39caf..0000000000
--- a/lib/diameter/test/diameter_app_test.erl
+++ /dev/null
@@ -1,393 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-%%----------------------------------------------------------------------
-%% Purpose: Verify the application specifics of the Diameter application
-%%----------------------------------------------------------------------
--module(diameter_app_test).
-
--export([
- init_per_testcase/2, fin_per_testcase/2,
-
- all/0,
- groups/0,
- init_per_suite/1, end_per_suite/1,
- suite_init/1, suite_fin/1,
- init_per_group/2, end_per_group/2,
-
- fields/1,
- modules/1,
- exportall/1,
- app_depend/1,
- undef_funcs/1
- ]).
-
--export([t/0, t/1]).
-
--include("diameter_test_lib.hrl").
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-t() -> diameter_test_server:t(?MODULE).
-t(Case) -> diameter_test_server:t({?MODULE, Case}).
-
-
-%% Test server callbacks
-init_per_testcase(undef_funcs = Case, Config) ->
- NewConfig = [{tc_timeout, ?MINUTES(10)} | Config],
- diameter_test_server:init_per_testcase(Case, NewConfig);
-init_per_testcase(Case, Config) ->
- diameter_test_server:init_per_testcase(Case, Config).
-
-fin_per_testcase(Case, Config) ->
- diameter_test_server:fin_per_testcase(Case, Config).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-all() ->
- [
- fields,
- modules,
- exportall,
- app_depend,
- undef_funcs
- ].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-suite_init(X) -> init_per_suite(X).
-
-init_per_suite(suite) -> [];
-init_per_suite(doc) -> [];
-init_per_suite(Config) when is_list(Config) ->
- io:format("~w:init_per_suite -> entry with"
- "~n Config: ~p"
- "~n", [?MODULE, Config]),
- case is_app(diameter) of
- {ok, AppFile} ->
- io:format("AppFile: ~n~p~n", [AppFile]),
- %% diameter:print_version_info(),
- [{app_file, AppFile}|Config];
- {error, Reason} ->
- ?FAIL(Reason)
- end.
-
-is_app(App) ->
- LibDir = code:lib_dir(App),
- File = filename:join([LibDir, "ebin", atom_to_list(App) ++ ".app"]),
- case file:consult(File) of
- {ok, [{application, App, AppFile}]} ->
- {ok, AppFile};
- Error ->
- {error, {invalid_format, Error}}
- end.
-
-
-suite_fin(X) -> end_per_suite(X).
-
-end_per_suite(suite) -> [];
-end_per_suite(doc) -> [];
-end_per_suite(Config) when is_list(Config) ->
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-fields(suite) ->
- [];
-fields(doc) ->
- [];
-fields(Config) when is_list(Config) ->
- AppFile = ?KEY1SEARCH(app_file, Config),
- Fields = [vsn, description, modules, registered, applications],
- case check_fields(Fields, AppFile, []) of
- [] ->
- ok;
- Missing ->
- ?FAIL({missing_fields, Missing})
- end.
-
-check_fields([], _AppFile, Missing) ->
- Missing;
-check_fields([Field|Fields], AppFile, Missing) ->
- check_fields(Fields, AppFile, check_field(Field, AppFile, Missing)).
-
-check_field(Name, AppFile, Missing) ->
- io:format("checking field: ~p~n", [Name]),
- case lists:keymember(Name, 1, AppFile) of
- true ->
- Missing;
- false ->
- [Name|Missing]
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-modules(suite) ->
- [];
-modules(doc) ->
- [];
-modules(Config) when is_list(Config) ->
- AppFile = ?KEY1SEARCH(app_file, Config),
- Mods = ?KEY1SEARCH(modules, AppFile),
- EbinList = get_ebin_mods(diameter),
- case missing_modules(Mods, EbinList, []) of
- [] ->
- ok;
- Missing ->
- throw({error, {missing_modules, Missing}})
- end,
- Allowed = [diameter_codegen,
- diameter_make,
- diameter_spec_scan,
- diameter_spec_util],
- case extra_modules(Mods, EbinList, Allowed, []) of
- [] ->
- ok;
- Extra ->
- throw({error, {extra_modules, Extra}})
- end,
- {ok, Mods}.
-
-get_ebin_mods(App) ->
- LibDir = code:lib_dir(App),
- EbinDir = filename:join([LibDir,"ebin"]),
- {ok, Files0} = file:list_dir(EbinDir),
- Files1 = [lists:reverse(File) || File <- Files0],
- [list_to_atom(lists:reverse(Name)) || [$m,$a,$e,$b,$.|Name] <- Files1].
-
-
-missing_modules([], _Ebins, Missing) ->
- Missing;
-missing_modules([Mod|Mods], Ebins, Missing) ->
- case lists:member(Mod, Ebins) of
- true ->
- missing_modules(Mods, Ebins, Missing);
- false ->
- io:format("missing module: ~p~n", [Mod]),
- missing_modules(Mods, Ebins, [Mod|Missing])
- end.
-
-
-extra_modules(_Mods, [], Allowed, Extra) ->
- Extra--Allowed;
-extra_modules(Mods, [Mod|Ebins], Allowed, Extra) ->
- case lists:member(Mod, Mods) of
- true ->
- extra_modules(Mods, Ebins, Allowed, Extra);
- false ->
- io:format("supefluous module: ~p~n", [Mod]),
- extra_modules(Mods, Ebins, Allowed, [Mod|Extra])
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
-exportall(suite) ->
- [];
-exportall(doc) ->
- [];
-exportall(Config) when is_list(Config) ->
- AppFile = ?KEY1SEARCH(app_file, Config),
- Mods = ?KEY1SEARCH(modules, AppFile),
- check_export_all(Mods).
-
-
-check_export_all([]) ->
- ok;
-check_export_all([Mod|Mods]) ->
- case (catch apply(Mod, module_info, [compile])) of
- {'EXIT', {undef, _}} ->
- check_export_all(Mods);
- O ->
- case lists:keysearch(options, 1, O) of
- false ->
- check_export_all(Mods);
- {value, {options, List}} ->
- case lists:member(export_all, List) of
- true ->
- throw({error, {export_all, Mod}});
- false ->
- check_export_all(Mods)
- end
- end
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-app_depend(suite) ->
- [];
-app_depend(doc) ->
- [];
-app_depend(Config) when is_list(Config) ->
- AppFile = ?KEY1SEARCH(app_file, Config),
- Apps = ?KEY1SEARCH(applications, AppFile),
- check_apps(Apps).
-
-
-check_apps([]) ->
- ok;
-check_apps([App|Apps]) ->
- case is_app(App) of
- {ok, _} ->
- check_apps(Apps);
- Error ->
- throw({error, {missing_app, {App, Error}}})
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-undef_funcs(suite) ->
- [];
-undef_funcs(doc) ->
- [];
-undef_funcs(Config) when is_list(Config) ->
- ?SKIP(diameter_not_known_by_xref),
- App = diameter,
- AppFile = ?KEY1SEARCH(app_file, Config),
- Mods = ?KEY1SEARCH(modules, AppFile),
- Root = code:root_dir(),
- LibDir = code:lib_dir(App),
- EbinDir = filename:join([LibDir,"ebin"]),
- XRefTestName = undef_funcs_make_name(App, xref_test_name),
- try
- begin
- XRef = xref_start(XRefTestName),
- xref_set_defaults(XRef, [{verbose,false},{warnings,false}]),
- XRefName = undef_funcs_make_name(App, xref_name),
- XRefName = xref_add_release(XRef, Root, XRefName),
- xref_replace_application(XRef, App, EbinDir),
- Undefs = xref_analyze(XRef),
- xref_stop(XRef),
- analyze_undefined_function_calls(Undefs, Mods, [])
- end
- catch
- throw:{error, Reason} ->
- ?FAIL(Reason)
- end.
-
-
-xref_start(XRefTestName) ->
- case (catch xref:start(XRefTestName)) of
- {ok, XRef} ->
- XRef;
- {error, Reason} ->
- throw({error, {failed_starting_xref, Reason}});
- Error ->
- throw({error, {failed_starting_xref, Error}})
- end.
-
-xref_set_defaults(XRef, Defs) ->
- case (catch xref:set_default(XRef, Defs)) of
- ok ->
- ok;
- Error ->
- throw({error, {failed_setting_defaults, Defs, Error}})
- end.
-
-xref_add_release(XRef, Root, Name) ->
- case (catch xref:add_release(XRef, Root, {name, Name})) of
- {ok, XRefName} ->
- XRefName;
- {error, Reason} ->
- throw({error, {failed_adding_release, Reason}});
- Error ->
- throw({error, {failed_adding_release, Error}})
- end.
-
-xref_replace_application(XRef, App, EbinDir) ->
- case (catch xref:replace_application(XRef, App, EbinDir)) of
- {ok, App} ->
- ok;
- {error, XRefMod, Reason} ->
- throw({error, {failed_replacing_app, XRefMod, Reason}});
- Error ->
- throw({error, {failed_replacing_app, Error}})
- end.
-
-xref_analyze(XRef) ->
- case (catch xref:analyze(XRef, undefined_function_calls)) of
- {ok, Undefs} ->
- Undefs;
- {error, Reason} ->
- throw({error, {failed_detecting_func_calls, Reason}});
- Error ->
- throw({error, {failed_detecting_func_calls, Error}})
- end.
-
-xref_stop(XRef) ->
- xref:stop(XRef).
-
-analyze_undefined_function_calls([], _, []) ->
- ok;
-analyze_undefined_function_calls([], _, AppUndefs) ->
- exit({suite_failed, {undefined_function_calls, AppUndefs}});
-analyze_undefined_function_calls([{{Mod, _F, _A}, _C} = AppUndef|Undefs],
- AppModules, AppUndefs) ->
- %% Check that this module is our's
- case lists:member(Mod,AppModules) of
- true ->
- {Calling,Called} = AppUndef,
- {Mod1,Func1,Ar1} = Calling,
- {Mod2,Func2,Ar2} = Called,
- io:format("undefined function call: "
- "~n ~w:~w/~w calls ~w:~w/~w~n",
- [Mod1,Func1,Ar1,Mod2,Func2,Ar2]),
- analyze_undefined_function_calls(Undefs, AppModules,
- [AppUndef|AppUndefs]);
- false ->
- io:format("dropping ~p~n", [Mod]),
- analyze_undefined_function_calls(Undefs, AppModules, AppUndefs)
- end.
-
-%% This function is used simply to avoid cut-and-paste errors later...
-undef_funcs_make_name(App, PostFix) ->
- list_to_atom(atom_to_list(App) ++ "_" ++ atom_to_list(PostFix)).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
-%% fail(Reason) ->
-%% exit({suite_failed, Reason}).
-
-%% ?KEY1SEARCH(Key, L) ->
-%% case lists:keysearch(Key, 1, L) of
-%% undefined ->
-%% fail({not_found, Key, L});
-%% {value, {Key, Value}} ->
-%% Value
-%% end.
diff --git a/lib/diameter/test/diameter_appup_test.erl b/lib/diameter/test/diameter_appup_test.erl
deleted file mode 100644
index 97a089e01a..0000000000
--- a/lib/diameter/test/diameter_appup_test.erl
+++ /dev/null
@@ -1,539 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-%%----------------------------------------------------------------------
-%% Purpose: Verify the application specifics of the Diameter application
-%%----------------------------------------------------------------------
--module(diameter_appup_test).
-
--export([
- init_per_testcase/2, fin_per_testcase/2,
-
- all/0,
- groups/0,
- init_per_suite/1, end_per_suite/1,
- suite_init/1, suite_fin/1,
- init_per_group/2, end_per_group/2,
-
- appup/1
- ]).
-
--export([t/0, t/1]).
-
--compile({no_auto_import,[error/1]}).
-
--include("diameter_test_lib.hrl").
-
--define(APPLICATION, diameter).
-
-t() -> diameter_test_server:t(?MODULE).
-t(Case) -> diameter_test_server:t({?MODULE, Case}).
-
-
-%% Test server callbacks
-init_per_testcase(Case, Config) ->
- diameter_test_server:init_per_testcase(Case, Config).
-
-fin_per_testcase(Case, Config) ->
- diameter_test_server:fin_per_testcase(Case, Config).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-all() ->
- [appup].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-suite_init(X) -> init_per_suite(X).
-
-init_per_suite(suite) -> [];
-init_per_suite(doc) -> [];
-init_per_suite(Config) when is_list(Config) ->
- AppFile = file_name(?APPLICATION, ".app"),
- AppupFile = file_name(?APPLICATION, ".appup"),
- [{app_file, AppFile}, {appup_file, AppupFile}|Config].
-
-
-file_name(App, Ext) ->
- LibDir = code:lib_dir(App),
- filename:join([LibDir, "ebin", atom_to_list(App) ++ Ext]).
-
-
-suite_fin(X) -> end_per_suite(X).
-
-end_per_suite(suite) -> [];
-end_per_suite(doc) -> [];
-end_per_suite(Config) when is_list(Config) ->
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-appup(suite) ->
- [];
-appup(doc) ->
- "perform a simple check of the appup file";
-appup(Config) when is_list(Config) ->
- AppupFile = key1search(appup_file, Config),
- AppFile = key1search(app_file, Config),
- Modules = modules(AppFile),
- check_appup(AppupFile, Modules).
-
-modules(File) ->
- case file:consult(File) of
- {ok, [{application,diameter,Info}]} ->
- case lists:keysearch(modules,1,Info) of
- {value, {modules, Modules}} ->
- Modules;
- false ->
- fail({bad_appinfo, Info})
- end;
- Error ->
- fail({bad_appfile, Error})
- end.
-
-
-check_appup(AppupFile, Modules) ->
- case file:consult(AppupFile) of
- {ok, [{V, UpFrom, DownTo}]} ->
- check_appup(V, UpFrom, DownTo, Modules);
- Else ->
- fail({bad_appupfile, Else})
- end.
-
-
-check_appup(V, UpFrom, DownTo, Modules) ->
- check_version(V),
- check_depends(up, UpFrom, Modules),
- check_depends(down, DownTo, Modules),
- check_module_subset(UpFrom),
- check_module_subset(DownTo),
- ok.
-
-
-check_depends(_, [], _) ->
- ok;
-check_depends(UpDown, [Dep|Deps], Modules) ->
- check_depend(UpDown, Dep, Modules),
- check_depends(UpDown, Deps, Modules).
-
-
-check_depend(up = UpDown, {add_application, ?APPLICATION} = Instr, Modules) ->
- d("check_instructions(~w) -> entry with"
- "~n Instruction: ~p"
- "~n Modules: ~p", [UpDown, Instr, Modules]),
- ok;
-check_depend(down = UpDown, {remove_application, ?APPLICATION} = Instr,
- Modules) ->
- d("check_instructions(~w) -> entry with"
- "~n Instruction: ~p"
- "~n Modules: ~p", [UpDown, Instr, Modules]),
- ok;
-check_depend(UpDown, {V, Instructions}, Modules) ->
- d("check_instructions(~w) -> entry with"
- "~n V: ~p"
- "~n Modules: ~p", [UpDown, V, Modules]),
- check_version(V),
- case check_instructions(UpDown,
- Instructions, Instructions, [], [], Modules) of
- {_Good, []} ->
- ok;
- {_, Bad} ->
- fail({bad_instructions, Bad, UpDown})
- end.
-
-
-check_instructions(_, [], _, Good, Bad, _) ->
- {lists:reverse(Good), lists:reverse(Bad)};
-check_instructions(UpDown, [Instr|Instrs], AllInstr, Good, Bad, Modules) ->
- d("check_instructions(~w) -> entry with"
- "~n Instr: ~p", [UpDown,Instr]),
- case (catch check_instruction(UpDown, Instr, AllInstr, Modules)) of
- ok ->
- check_instructions(UpDown, Instrs, AllInstr,
- [Instr|Good], Bad, Modules);
- {error, Reason} ->
- d("check_instructions(~w) -> bad instruction: "
- "~n Reason: ~p", [UpDown,Reason]),
- check_instructions(UpDown, Instrs, AllInstr, Good,
- [{Instr, Reason}|Bad], Modules)
- end.
-
-%% A new module is added
-check_instruction(up, {add_module, Module}, _, Modules)
- when is_atom(Module) ->
- d("check_instruction -> entry when up-add_module instruction with"
- "~n Module: ~p", [Module]),
- check_module(Module, Modules);
-
-%% An old module is re-added
-check_instruction(down, {add_module, Module}, _, Modules)
- when is_atom(Module) ->
- d("check_instruction -> entry when down-add_module instruction with"
- "~n Module: ~p", [Module]),
- case (catch check_module(Module, Modules)) of
- {error, {unknown_module, Module, Modules}} ->
- ok;
- ok ->
- error({existing_readded_module, Module})
- end;
-
-%% Removing a module on upgrade:
-%% - the module has been removed from the app-file.
-%% - check that no module depends on this (removed) module
-check_instruction(up, {remove, {Module, Pre, Post}}, _, Modules)
- when is_atom(Module) andalso is_atom(Pre) andalso is_atom(Post) ->
- d("check_instruction -> entry when up-remove instruction with"
- "~n Module: ~p"
- "~n Pre: ~p"
- "~n Post: ~p", [Module, Pre, Post]),
- case (catch check_module(Module, Modules)) of
- {error, {unknown_module, Module, Modules}} ->
- check_purge(Pre),
- check_purge(Post);
- ok ->
- error({existing_removed_module, Module})
- end;
-
-%% Removing a module on downgrade: the module exist
-%% in the app-file.
-check_instruction(down, {remove, {Module, Pre, Post}}, AllInstr, Modules)
- when is_atom(Module) andalso is_atom(Pre) andalso is_atom(Post) ->
- d("check_instruction -> entry when down-remove instruction with"
- "~n Module: ~p"
- "~n Pre: ~p"
- "~n Post: ~p", [Module, Pre, Post]),
- case (catch check_module(Module, Modules)) of
- ok ->
- check_purge(Pre),
- check_purge(Post),
- check_no_remove_depends(Module, AllInstr);
- {error, {unknown_module, Module, Modules}} ->
- error({nonexisting_removed_module, Module})
- end;
-
-check_instruction(_, {load_module, Module, Pre, Post, Depend},
- AllInstr, Modules)
- when is_atom(Module) andalso is_atom(Pre) andalso is_atom(Post) andalso is_list(Depend) ->
- d("check_instruction -> entry when load_module instruction with"
- "~n Module: ~p"
- "~n Pre: ~p"
- "~n Post: ~p"
- "~n Depend: ~p", [Module, Pre, Post, Depend]),
- check_module(Module, Modules),
- check_module_depend(Module, Depend, Modules),
- check_module_depend(Module, Depend, updated_modules(AllInstr, [])),
- check_purge(Pre),
- check_purge(Post);
-
-check_instruction(_, {update, Module, Change, Pre, Post, Depend},
- AllInstr, Modules)
- when is_atom(Module) andalso is_atom(Pre) andalso is_atom(Post) andalso is_list(Depend) ->
- d("check_instruction -> entry when update instruction with"
- "~n Module: ~p"
- "~n Change: ~p"
- "~n Pre: ~p"
- "~n Post: ~p"
- "~n Depend: ~p", [Module, Change, Pre, Post, Depend]),
- check_module(Module, Modules),
- check_module_depend(Module, Depend, Modules),
- check_module_depend(Module, Depend, updated_modules(AllInstr, [])),
- check_change(Change),
- check_purge(Pre),
- check_purge(Post);
-
-check_instruction(_, {update, Module, supervisor}, _, Modules)
- when is_atom(Module) ->
- check_module(Module, Modules);
-
-check_instruction(_, {apply, {Module, Function, Args}}, _, Modules)
- when is_atom(Module) andalso is_atom(Function) andalso is_list(Args) ->
- d("check_instruction -> entry when down-apply instruction with"
- "~n Module: ~p"
- "~n Function: ~p"
- "~n Args: ~p", [Module, Function, Args]),
- check_module(Module, Modules),
- check_apply(Module, Function, Args);
-
-check_instruction(_, {restart_application, ?APPLICATION}, _AllInstr, _Modules) ->
- ok;
-
-check_instruction(_, Instr, _AllInstr, _Modules) ->
- d("check_instruction -> entry when unknown instruction with"
- "~n Instr: ~p", [Instr]),
- error({error, {unknown_instruction, Instr}}).
-
-
-%% If Module X depends on Module Y, then module Y must have an update
-%% instruction of some sort (otherwise the depend is faulty).
-updated_modules([], Modules) ->
- d("update_modules -> entry when done with"
- "~n Modules: ~p", [Modules]),
- Modules;
-updated_modules([Instr|Instrs], Modules) ->
- d("update_modules -> entry with"
- "~n Instr: ~p"
- "~n Modules: ~p", [Instr,Modules]),
- Module = instruction_module(Instr),
- d("update_modules -> Module: ~p", [Module]),
- updated_modules(Instrs, [Module|Modules]).
-
-instruction_module({add_module, Module}) ->
- Module;
-instruction_module({remove, {Module, _, _}}) ->
- Module;
-instruction_module({load_module, Module, _, _, _}) ->
- Module;
-instruction_module({update, Module, _, _, _, _}) ->
- Module;
-instruction_module({apply, {Module, _, _}}) ->
- Module;
-instruction_module(Instr) ->
- d("instruction_module -> entry when unknown instruction with"
- "~n Instr: ~p", [Instr]),
- error({error, {unknown_instruction, Instr}}).
-
-
-%% Check that the modules handled in an instruction set for version X
-%% is a subset of the instruction set for version X-1.
-check_module_subset(Instructions) ->
- do_check_module_subset(modules_of(Instructions)).
-
-do_check_module_subset([]) ->
- ok;
-do_check_module_subset([_]) ->
- ok;
-do_check_module_subset([{_V1, Mods1}|T]) ->
- {V2, Mods2} = hd(T),
- %% Check that the modules in V1 is a subset of V2
- case do_check_module_subset2(Mods1, Mods2) of
- ok ->
- do_check_module_subset(T);
- {error, Modules} ->
- fail({subset_missing_instructions, V2, Modules})
- end.
-
-do_check_module_subset2(Mods1, Mods2) ->
- do_check_module_subset2(Mods1, Mods2, []).
-
-do_check_module_subset2([], _, []) ->
- ok;
-do_check_module_subset2([], _, Acc) ->
- {error, lists:reverse(Acc)};
-do_check_module_subset2([Mod|Mods], Mods2, Acc) ->
- case lists:member(Mod, Mods2) of
- true ->
- do_check_module_subset2(Mods, Mods2, Acc);
- false ->
- do_check_module_subset2(Mods, Mods2, [Mod|Acc])
- end.
-
-
-modules_of(Instructions) ->
- modules_of(Instructions, []).
-
-modules_of([], Acc) ->
- lists:reverse(Acc);
-modules_of([{V,Instructions}|T], Acc) ->
- Mods = modules_of2(Instructions, []),
- modules_of(T, [{V, Mods}|Acc]).
-
-modules_of2([], Acc) ->
- lists:reverse(Acc);
-modules_of2([Instr|Instructions], Acc) ->
- case module_of(Instr) of
- {value, Mod} ->
- modules_of2(Instructions, [Mod|Acc]);
- false ->
- modules_of2(Instructions, Acc)
- end.
-
-module_of({add_module, Module}) ->
- {value, Module};
-module_of({remove, {Module, _Pre, _Post}}) ->
- {value, Module};
-module_of({load_module, Module, _Pre, _Post, _Depend}) ->
- {value, Module};
-module_of({update, Module, _Change, _Pre, _Post, _Depend}) ->
- {value, Module};
-module_of(_) ->
- false.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%% The version is a string consting of numbers separated by dots: "."
-%% Example: "3.3.3"
-%%
-check_version(V) when is_list(V) ->
- case do_check_version(string:tokens(V, [$.])) of
- ok ->
- ok;
- {error, BadVersionPart} ->
- throw({error, {bad_version, V, BadVersionPart}})
- end;
-check_version(V) ->
- error({bad_version, V}).
-
-do_check_version([]) ->
- ok;
-do_check_version([H|T]) ->
- case (catch list_to_integer(H)) of
- I when is_integer(I) ->
- do_check_version(T);
- _ ->
- {error, H}
- end.
-
-check_module(M, Modules) when is_atom(M) ->
- case lists:member(M,Modules) of
- true ->
- ok;
- false ->
- error({unknown_module, M, Modules})
- end;
-check_module(M, _) ->
- error({bad_module, M}).
-
-
-check_module_depend(M, [], _) when is_atom(M) ->
- d("check_module_depend -> entry with"
- "~n M: ~p", [M]),
- ok;
-check_module_depend(M, Deps, Modules) when is_atom(M) andalso is_list(Deps) ->
- d("check_module_depend -> entry with"
- "~n M: ~p"
- "~n Deps: ~p"
- "~n Modules: ~p", [M, Deps, Modules]),
- case [Dep || Dep <- Deps, lists:member(Dep, Modules) == false] of
- [] ->
- ok;
- Unknown ->
- error({unknown_depend_modules, Unknown})
- end;
-check_module_depend(_M, D, _Modules) ->
- d("check_module_depend -> entry when bad depend with"
- "~n D: ~p", [D]),
- error({bad_depend, D}).
-
-
-check_no_remove_depends(_Module, []) ->
- ok;
-check_no_remove_depends(Module, [Instr|Instrs]) ->
- check_no_remove_depend(Module, Instr),
- check_no_remove_depends(Module, Instrs).
-
-check_no_remove_depend(Module, {load_module, Mod, _Pre, _Post, Depend}) ->
- case lists:member(Module, Depend) of
- true ->
- error({removed_module_in_depend, load_module, Mod, Module});
- false ->
- ok
- end;
-check_no_remove_depend(Module, {update, Mod, _Change, _Pre, _Post, Depend}) ->
- case lists:member(Module, Depend) of
- true ->
- error({removed_module_in_depend, update, Mod, Module});
- false ->
- ok
- end;
-check_no_remove_depend(_, _) ->
- ok.
-
-
-check_change(soft) ->
- ok;
-check_change({advanced, _Something}) ->
- ok;
-check_change(Change) ->
- error({bad_change, Change}).
-
-
-check_purge(soft_purge) ->
- ok;
-check_purge(brutal_purge) ->
- ok;
-check_purge(Purge) ->
- error({bad_purge, Purge}).
-
-
-check_apply(Module, Function, Args) ->
- case (catch Module:module_info()) of
- Info when is_list(Info) ->
- check_exported(Function, Args, Info);
- {'EXIT', {undef, _}} ->
- error({not_existing_module, Module})
- end.
-
-check_exported(Function, Args, Info) ->
- case lists:keysearch(exports, 1, Info) of
- {value, {exports, FuncList}} ->
- Arity = length(Args),
- Arities = [A || {F, A} <- FuncList, F == Function],
- case lists:member(Arity, Arities) of
- true ->
- ok;
- false ->
- error({not_exported_function, Function, Arity})
- end;
- _ ->
- error({bad_export, Info})
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-error(Reason) ->
- throw({error, Reason}).
-
-fail(Reason) ->
- exit({suite_failed, Reason}).
-
-key1search(Key, L) ->
- case lists:keysearch(Key, 1, L) of
- undefined ->
- fail({not_found, Key, L});
- {value, {Key, Value}} ->
- Value
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-d(F, A) ->
- d(false, F, A).
-
-d(true, F, A) ->
- io:format(F ++ "~n", A);
-d(_, _, _) ->
- ok.
-
-
diff --git a/lib/diameter/test/diameter_capx_SUITE.erl b/lib/diameter/test/diameter_capx_SUITE.erl
new file mode 100644
index 0000000000..e6b1558bf6
--- /dev/null
+++ b/lib/diameter/test/diameter_capx_SUITE.erl
@@ -0,0 +1,432 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests of capabilities exchange between Diameter nodes. In
+%% particular, of error and event handling.
+%%
+
+-module(diameter_capx_SUITE).
+
+-export([suite/0,
+ all/0,
+ groups/0,
+ init_per_group/2,
+ end_per_group/2,
+ init_per_testcase/2,
+ end_per_testcase/2]).
+
+%% testcases
+-export([start/1,
+ start_services/1,
+ add_listeners/1,
+ s_no_common_application/1,
+ c_no_common_application/1,
+ s_no_common_security/1,
+ c_no_common_security/1,
+ s_unknown_peer/1,
+ c_unknown_peer/1,
+ s_unable/1,
+ c_unable/1,
+ s_client_reject/1,
+ c_client_reject/1,
+ remove_listeners/1,
+ stop_services/1,
+ stop/1]).
+
+%% diameter callbacks
+-export([peer_up/4,
+ peer_down/4]).
+
+-include("diameter.hrl").
+-include("diameter_gen_base_rfc3588.hrl").
+
+%% ===========================================================================
+
+-define(util, diameter_util).
+
+-define(CLIENT, client).
+-define(SERVER, server).
+
+-define(ADDR, {127,0,0,1}).
+
+-define(REALM, "erlang.org").
+-define(HOST(Name), Name ++ "." ++ ?REALM).
+
+%% Config for diameter:start_service/2.
+-define(SERVICE(Name),
+ [{'Origin-Realm', ?REALM},
+ {'Host-IP-Address', [?ADDR]},
+ {'Vendor-Id', 12345},
+ {'Product-Name', "OTP/diameter"},
+ {'Auth-Application-Id', [?DIAMETER_APP_ID_COMMON]},
+ {'Acct-Application-Id', [?DIAMETER_APP_ID_ACCOUNTING]}
+ | [{application, [{alias, A},
+ {dictionary, D},
+ {module, [?MODULE, A]}]}
+ || {A,D} <- [{common, ?DIAMETER_DICT_COMMON},
+ {accounting, ?DIAMETER_DICT_ACCOUNTING}]]]).
+
+-define(A, list_to_atom).
+-define(L, atom_to_list).
+
+-define(event, #diameter_event).
+-define(caps, #diameter_caps).
+-define(packet, #diameter_packet).
+
+-define(cea, #diameter_base_CEA).
+-define(answer_message, #'diameter_base_answer-message').
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 10}}].
+
+all() ->
+ [start, start_services, add_listeners
+ | [{group, N} || {N, _, _} <- groups()]]
+ ++ [remove_listeners, stop_services, stop].
+
+groups() ->
+ Ts = testcases(),
+ [{grp(P), P, Ts} || P <- [[], [parallel]]].
+
+grp([]) ->
+ sequential;
+grp([parallel = P]) ->
+ P.
+
+init_per_group(_Name, Config) ->
+ Config.
+
+end_per_group(_, _) ->
+ ok.
+
+%% Generate a unique hostname for each testcase so that watchdogs
+%% don't prevent a connection from being brought up immediately.
+init_per_testcase(Name, Config) ->
+ Uniq = ["." ++ integer_to_list(N) || N <- tuple_to_list(now())],
+ [{host, lists:flatten([?L(Name) | Uniq])} | Config].
+
+end_per_testcase(N, _)
+ when N == start;
+ N == start_services;
+ N == add_listeners;
+ N == remove_listeners;
+ N == stop_services;
+ N == stop ->
+ ok;
+end_per_testcase(Name, Config) ->
+ CRef = ?util:read_priv(Config, Name),
+ ok = diameter:remove_transport(?CLIENT, CRef).
+
+%% Testcases all come in two flavours, client and server.
+testcases() ->
+ lists:flatmap(fun tc/1, tc()).
+
+tc(Name) ->
+ [?A([C,$_|?L(Name)]) || C <- "cs"].
+
+tc() ->
+ [no_common_application,
+ no_common_security,
+ unknown_peer,
+ unable,
+ client_reject].
+
+%% ===========================================================================
+%% start/stop testcases
+
+start(_Config) ->
+ ok = diameter:start().
+
+start_services(_Config) ->
+ ok = diameter:start_service(?SERVER, ?SERVICE(?SERVER)),
+ ok = diameter:start_service(?CLIENT, ?SERVICE(?CLIENT)).
+
+%% One server that responds only to base accounting, one that responds
+%% to both this and the common application. Share a common service just
+%% to simplify config, and because we can.
+add_listeners(Config) ->
+ Acct = listen(?SERVER,
+ [{capabilities, [{'Origin-Host', ?HOST("acct-srv")},
+ {'Auth-Application-Id', []}]},
+ {applications, [accounting]},
+ {capabilities_cb, [fun server_capx/3, acct]}]),
+ Base = listen(?SERVER,
+ [{capabilities, [{'Origin-Host', ?HOST("base-srv")}]},
+ {capabilities_cb, [fun server_capx/3, base]}]),
+ ?util:write_priv(Config, ?MODULE, {Base, Acct}). %% lref/2 reads
+
+remove_listeners(_Config) ->
+ ok = diameter:remove_transport(?SERVER, true).
+
+stop_services(_Config) ->
+ ok = diameter:stop_service(?CLIENT),
+ ok = diameter:stop_service(?SERVER).
+
+stop(_Config) ->
+ ok = diameter:stop().
+
+%% ===========================================================================
+%% All the testcases come in pairs, one for receiving an event on the
+%% client side, one on the server side. Note that testcases will
+%% receive events resulting from other testcases when running in
+%% parallel since the events are per service. The unique client
+%% Origin-Host for each testcase plus transport references are used to
+%% ensure that only the relevant event is extracted from the mailbox.
+%% Don't bother extracting events that aren't relevant.
+
+%% ====================
+%% Ask the accounting server to speak the common application and expect
+%% DIAMETER_NO_COMMON_APPLICATION = 5010.
+
+s_no_common_application(Config) ->
+ server_closed(Config, fun no_common_application/1, 5010).
+
+c_no_common_application(Config) ->
+ client_closed(Config, "acct-srv", fun no_common_application/1, 5010).
+
+no_common_application(Config) ->
+ connect(Config, acct, [{capabilities, [{'Acct-Application-Id', []}]},
+ {applications, [common]}]).
+
+%% ====================
+%% Ask the base server to speak accounting with an unknown security
+%% method and expect DIAMETER_NO_COMMON_SECURITY = 5017.
+
+s_no_common_security(Config) ->
+ server_closed(Config, fun no_common_security/1, 5017).
+
+c_no_common_security(Config) ->
+ client_closed(Config, "base-srv", fun no_common_security/1, 5017).
+
+no_common_security(Config) ->
+ connect(Config, base, [{capabilities, [{'Acct-Application-Id', []},
+ {'Inband-Security-Id', [17, 18]}]},
+ {applications, [common]}]).
+
+%% ====================
+%% Have the base server reject a decent CER with the protocol error
+%% DIAMETER_UNKNOWN_PEER = 3010.
+
+s_unknown_peer(Config) ->
+ server_reject(Config, fun base/1, 3010).
+
+c_unknown_peer(Config) ->
+ true = diameter:subscribe(?CLIENT),
+ OH = ?HOST("base-srv"),
+
+ {CRef, _} = base(Config),
+
+ {'CEA', ?caps{},
+ ?packet{msg = ?answer_message{'Origin-Host' = OH,
+ 'Result-Code' = 3010}}}
+ = client_recv(CRef).
+
+base(Config) ->
+ connect(Config, base, []).
+
+%% ====================
+%% Have the base server reject a decent CER with the non-protocol
+%% error DIAMETER_UNABLE_TO_COMPLY = 5012.
+
+s_unable(Config) ->
+ server_reject(Config, fun base/1, 5012).
+
+c_unable(Config) ->
+ client_closed(Config, "base-srv", fun base/1, 5012).
+
+%% ====================
+%% Have the client reject a decent CEA.
+
+s_client_reject(Config) ->
+ true = diameter:subscribe(?SERVER),
+ OH = host(Config),
+
+ {_, LRef} = client_reject(Config),
+
+ receive
+ ?event{service = ?SERVER,
+ info = {up, LRef,
+ {_, ?caps{origin_host = {_, OH}}},
+ {listen, _},
+ ?packet{}}}
+ = Info ->
+ Info
+ after 2000 ->
+ fail({LRef, OH})
+ end.
+
+c_client_reject(Config) ->
+ true = diameter:subscribe(?CLIENT),
+ OH = ?HOST("acct-srv"),
+
+ {CRef, _} = client_reject(Config),
+
+ {'CEA', {capabilities_cb, _, discard},
+ ?caps{origin_host = {_, OH}},
+ ?packet{msg = ?cea{'Result-Code' = 2001}}}
+ = client_recv(CRef).
+
+client_reject(Config) ->
+ connect(Config, acct, [{capabilities_cb, fun client_capx/2}]).
+
+%% ===========================================================================
+
+%% server_closed/3
+
+server_closed(Config, F, RC) ->
+ true = diameter:subscribe(?SERVER),
+ OH = host(Config),
+
+ {_, LRef} = F(Config),
+
+ receive
+ ?event{service = ?SERVER,
+ info = {closed, LRef,
+ {'CER', RC,
+ ?caps{origin_host = {_, OH}},
+ ?packet{}}
+ = Reason,
+ {listen, _}}} ->
+ Reason
+ after 2000 ->
+ fail({LRef, OH})
+ end.
+
+%% server_reject/3
+
+server_reject(Config, F, RC) ->
+ true = diameter:subscribe(?SERVER),
+ OH = host(Config),
+
+ {_, LRef} = F(Config),
+
+ receive
+ ?event{service = ?SERVER,
+ info = {closed, LRef,
+ {'CER', {capabilities_cb, _, RC},
+ ?caps{origin_host = {_, OH}},
+ ?packet{}}
+ = Reason,
+ {listen, _}}} ->
+ Reason
+ after 2000 ->
+ fail({LRef, OH})
+ end.
+
+%% cliient_closed/4
+
+client_closed(Config, Host, F, RC) ->
+ true = diameter:subscribe(?CLIENT),
+ OH = ?HOST(Host),
+
+ {CRef, _} = F(Config),
+
+ {'CEA', RC, ?caps{origin_host = {_, OH}}, ?packet{}}
+ = client_recv(CRef).
+
+%% client_recv/1
+
+client_recv(CRef) ->
+ receive
+ ?event{service = ?CLIENT,
+ info = {closed, CRef, Reason, {connect, _}}} ->
+ Reason
+ after 2000 ->
+ fail(CRef)
+ end.
+
+%% server_capx/3
+
+server_capx(_, ?caps{origin_host = {_, [_,$_|"unknown_peer." ++ _]}}, _) ->
+ unknown;
+
+server_capx(_, ?caps{origin_host = {_, [_,$_|"unable." ++ _]}}, _) ->
+ 5012; %% DIAMETER_UNABLE_TO_COMPLY
+
+server_capx(_, ?caps{origin_host = {OH,DH}}, _) ->
+ io:format("connection: ~p -> ~p~n", [DH,OH]),
+ ok.
+
+%% client_capx/2
+
+client_capx(_, ?caps{origin_host = {[_,$_|"client_reject." ++ _], _}}) ->
+ discard.
+
+%% ===========================================================================
+
+fail(T) ->
+ erlang:error({T, process_info(self(), messages)}).
+
+host(Config) ->
+ {_, H} = lists:keyfind(host, 1, Config),
+ ?HOST(H).
+
+listen(Name, Opts) ->
+ ?util:listen(Name, tcp, Opts).
+
+connect(Config, T, Opts) ->
+ {_, H} = lists:keyfind(host, 1, Config),
+ LRef = lref(Config, T),
+ CRef = connect(LRef, [{capabilities, [{'Origin-Host', ?HOST(H)}]}
+ | Opts]),
+ Name = lists:takewhile(fun(C) -> C /= $. end, H),
+ ?util:write_priv(Config, Name, CRef), %% end_per_testcase reads
+ {CRef, LRef}.
+
+connect(LRef, Opts) ->
+ [PortNr] = ?util:lport(tcp, LRef, 20),
+ {ok, CRef} = diameter:add_transport(?CLIENT,
+ {connect, opts(PortNr, Opts)}),
+ CRef.
+
+opts(PortNr, Opts) ->
+ [{transport_module, diameter_tcp},
+ {transport_config, [{raddr, ?ADDR},
+ {rport, PortNr},
+ {ip, ?ADDR},
+ {port, 0}]}
+ | Opts].
+
+lref(Config, T) ->
+ case ?util:read_priv(Config, ?MODULE) of
+ {LRef, _} when T == base ->
+ LRef;
+ {_, LRef} when T == acct ->
+ LRef
+ end.
+
+%% ===========================================================================
+%% diameter callbacks
+
+peer_up(?SERVER,
+ {_, ?caps{origin_host = {"acct-srv." ++ _,
+ [_,$_|"client_reject." ++ _]}}},
+ State,
+ _) ->
+ State.
+
+peer_down(?SERVER,
+ {_, ?caps{origin_host = {"acct-srv." ++ _,
+ [_,$_|"client_reject." ++ _]}}},
+ State,
+ _) ->
+ State.
diff --git a/lib/diameter/test/diameter_codec_SUITE.erl b/lib/diameter/test/diameter_codec_SUITE.erl
new file mode 100644
index 0000000000..30c60be8e9
--- /dev/null
+++ b/lib/diameter/test/diameter_codec_SUITE.erl
@@ -0,0 +1,76 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Test encode/decode of dictionary-related modules. Each test case
+%% runs multiple tests in parallel since many of the tests are just
+%% the same code with different in-data: implementing each test as a
+%% single testcase would make for much duplication with ct's current
+%% requirement of one function per testcase.
+%%
+
+-module(diameter_codec_SUITE).
+
+-export([suite/0,
+ all/0,
+ init_per_testcase/2,
+ end_per_testcase/2]).
+
+%% testcases
+-export([base/1,
+ gen/1,
+ lib/1]).
+
+-include("diameter_ct.hrl").
+
+-define(L, atom_to_list).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 10}}].
+
+all() ->
+ [base, gen, lib].
+
+init_per_testcase(gen, Config) ->
+ [{application, ?APP, App}] = diameter_util:consult(?APP, app),
+ {modules, Ms} = lists:keyfind(modules, 1, App),
+ [_|_] = Gs = lists:filter(fun(M) ->
+ lists:prefix("diameter_gen_", ?L(M))
+ end,
+ Ms),
+ [{dicts, Gs} | Config];
+
+init_per_testcase(_Name, Config) ->
+ Config.
+
+end_per_testcase(_, _) ->
+ ok.
+
+%% ===========================================================================
+
+base(_Config) ->
+ diameter_codec_test:base().
+
+gen([{dicts, Ms} | _]) ->
+ lists:foreach(fun diameter_codec_test:gen/1, Ms).
+
+lib(_Config) ->
+ diameter_codec_test:lib().
diff --git a/lib/diameter/test/diameter_codec_test.erl b/lib/diameter/test/diameter_codec_test.erl
new file mode 100644
index 0000000000..8046ca4c04
--- /dev/null
+++ b/lib/diameter/test/diameter_codec_test.erl
@@ -0,0 +1,500 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(diameter_codec_test).
+
+-compile(export_all).
+
+%%
+%% Test encode/decode of dictionary-related modules.
+%%
+
+-include("diameter.hrl").
+
+-define(BASE, diameter_gen_base_rfc3588).
+-define(BOOL, [true, false]).
+
+%% ===========================================================================
+%% Interface.
+
+base() ->
+ [] = run([{?MODULE, [base, T]} || T <- [zero, decode]]).
+
+gen(Mod) ->
+ Fs = [{Mod, F, []} || F <- [name, id, vendor_id, vendor_name]],
+ [] = run(Fs ++ [{?MODULE, [gen, Mod, T]} || T <- [messages,
+ command_codes,
+ avp_types,
+ grouped,
+ enums,
+ import_avps,
+ import_groups,
+ import_enums]]).
+
+lib() ->
+ Vs = {_,_} = values('Address'),
+ [] = run([[fun lib/2, N, Vs] || N <- [1,2]]).
+
+%% ===========================================================================
+%% Internal functions.
+
+lib(N, {_,_} = T) ->
+ B = 1 == N rem 2,
+ [] = run([[fun lib/2, A, B] || A <- element(N,T)]);
+
+lib(IP, B) ->
+ LA = tuple_to_list(IP),
+ {SA,Fun} = ip(LA),
+ [] = run([[fun lib/4, IP, B, Fun, A] || A <- [IP, LA, SA]]).
+
+lib(IP, B, Fun, A) ->
+ try Fun(A) of
+ IP when B ->
+ ok
+ catch
+ error:_ when not B ->
+ ok
+ end.
+
+ip([_,_,_,_] = A) ->
+ [$.|S] = lists:append(["." ++ integer_to_list(N) || N <- A]),
+ {S, fun diameter_lib:ip4address/1};
+ip([_,_,_,_,_,_,_,_] = A) ->
+ [$:|S] = lists:flatten([":" ++ io_lib:format("~.16B", [N]) || N <- A]),
+ {S, fun diameter_lib:ip6address/1}.
+
+%% ------------------------------------------------------------------------
+%% base/1
+%%
+%% Test of diameter_types.
+%% ------------------------------------------------------------------------
+
+base(T) ->
+ [] = run([{?MODULE, [base, T, F]} || F <- types()]).
+
+%% Ensure that 'zero' values encode only zeros.
+base(zero = T, F) ->
+ B = diameter_types:F(encode, T),
+ B = z(B);
+
+%% Ensure that we can decode what we encode and vice-versa, and that
+%% we can't decode invalid values.
+base(decode, F) ->
+ {Eq, Vs, Ns} = b(values(F)),
+ [] = run([{?MODULE, [base_decode, F, Eq, V]} || V <- Vs]),
+ [] = run([{?MODULE, [base_invalid, F, Eq, V]} || V <- Ns]).
+
+base_decode(F, Eq, Value) ->
+ d(fun(X,V) -> diameter_types:F(X,V) end, Eq, Value).
+
+base_invalid(F, Eq, Value) ->
+ try
+ base_decode(F, Eq, Value),
+ exit(nok)
+ catch
+ error: _ ->
+ ok
+ end.
+
+b({_,_,_} = T) ->
+ T;
+b({B,Vs})
+ when is_atom(B) ->
+ {B,Vs,[]};
+b({Vs,Ns}) ->
+ {true, Vs, Ns};
+b(Vs) ->
+ {true, Vs, []}.
+
+types() ->
+ [F || {F,2} <- diameter_types:module_info(exports)].
+
+%% ------------------------------------------------------------------------
+%% gen/2
+%%
+%% Test of generated encode/decode module.
+%% ------------------------------------------------------------------------
+
+gen(M, T) ->
+ [] = run(lists:map(fun(X) -> {?MODULE, [gen, M, T, X]} end,
+ fetch(T, M:dict()))).
+
+fetch(T, Spec) ->
+ case orddict:find(T, Spec) of
+ {ok, L} ->
+ L;
+ error ->
+ []
+ end.
+
+gen(M, messages, {Name, Code, Flags, _, _}) ->
+ Rname = M:msg2rec(Name),
+ Name = M:rec2msg(Rname),
+ {Code, F, _} = M:msg_header(Name),
+ 0 = F band 2#00001111,
+ Name = case M:msg_name(Code, lists:member('REQ', Flags)) of
+ N when Name /= 'answer-message' ->
+ N;
+ '' when Name == 'answer-message', M == ?BASE ->
+ Name
+ end,
+ [] = arity(M, Name, Rname);
+
+gen(M, command_codes = T, {Code, {Req, Abbr}, Ans}) ->
+ Rname = M:msg2rec(Req),
+ Rname = M:msg2rec(Abbr),
+ gen(M, T, {Code, Req, Ans});
+
+gen(M, command_codes = T, {Code, Req, {Ans, Abbr}}) ->
+ Rname = M:msg2rec(Ans),
+ Rname = M:msg2rec(Abbr),
+ gen(M, T, {Code, Req, Ans});
+
+gen(M, command_codes, {Code, Req, Ans}) ->
+ Msgs = orddict:fetch(messages, M:dict()),
+ {_, Code, _, _, _} = lists:keyfind(Req, 1, Msgs),
+ {_, Code, _, _, _} = lists:keyfind(Ans, 1, Msgs);
+
+gen(M, avp_types, {Name, Code, Type, _Flags, _Encr}) ->
+ {Code, Flags, VendorId} = M:avp_header(Name),
+ 0 = Flags band 2#00011111,
+ V = undefined /= VendorId,
+ V = 0 /= Flags band 2#10000000,
+ {Name, Type} = M:avp_name(Code, VendorId),
+ B = M:empty_value(Name),
+ B = z(B),
+ [] = avp_decode(M, Type, Name);
+
+gen(M, grouped, {Name, _, _, _}) ->
+ Rname = M:name2rec(Name),
+ [] = arity(M, Name, Rname);
+
+gen(M, enums, {Name, ED}) ->
+ [] = run([{?MODULE, [enum, M, Name, T]} || T <- ED]);
+
+gen(M, Tag, {_Mod, L}) ->
+ T = retag(Tag),
+ [] = run([{?MODULE, [gen, M, T, I]} || I <- L]).
+
+%% avp_decode/3
+
+avp_decode(Mod, Type, Name) ->
+ {Eq, Vs, _} = b(values(Type, Name, Mod)),
+ [] = run([{?MODULE, [avp_decode, Mod, Name, Type, Eq, V]}
+ || V <- v(Vs)]).
+
+avp_decode(Mod, Name, Type, Eq, Value) ->
+ d(fun(X,V) -> avp(Mod, X, V, Name, Type) end, Eq, Value).
+
+avp(Mod, decode = X, V, Name, 'Grouped') ->
+ {Rec, _} = Mod:avp(X, V, Name),
+ Rec;
+avp(Mod, X, V, Name, _) ->
+ Mod:avp(X, V, Name).
+
+%% v/1
+
+%% List of values ...
+v(Vs)
+ when is_list(Vs) ->
+ Vs;
+
+%% .. or enumeration for grouped avps. This could be quite large
+%% (millions of values) but since the avps are also tested
+%% individually don't bother trying everything. Instead, choose a
+%% reasonable number of values at random.
+v(E) ->
+ v(2000, E(0), E).
+
+v(Max, Ord, E)
+ when Ord =< Max ->
+ diameter_enum:to_list(E);
+v(Max, Ord, E) ->
+ {M,S,U} = now(),
+ random:seed(M,S,U),
+ v(Max, Ord, E, []).
+
+v(0, _, _, Acc) ->
+ Acc;
+v(N, Ord, E, Acc) ->
+ v(N-1, Ord, E, [E(random:uniform(Ord)) | Acc]).
+
+%% arity/3
+
+arity(M, Name, Rname) ->
+ Rec = M:'#new-'(Rname),
+ [] = run([{?MODULE, [arity, M, Name, F, Rec]}
+ || F <- M:'#info-'(Rname, fields)]).
+
+arity(M, Name, AvpName, Rec) ->
+ Def = M:'#get-'(AvpName, Rec),
+ Def = case M:avp_arity(Name, AvpName) of
+ 1 ->
+ undefined;
+ A when 0 /= A ->
+ []
+ end.
+
+%% enum/3
+
+enum(M, Name, {E,_}) ->
+ B = <<E:32/integer>>,
+ B = M:avp(encode, E, Name),
+ E = M:avp(decode, B, Name).
+
+retag(import_avps) -> avp_types;
+retag(import_groups) -> grouped;
+retag(import_enums) -> enums;
+
+retag(avp_types) -> import_avps;
+retag(enums) -> import_enums.
+
+%% ===========================================================================
+
+d(F, Eq, V) ->
+ B = F(encode, V),
+ D = F(decode, B),
+ V = if Eq -> %% test for value equality ...
+ D;
+ true -> %% ... or that encode/decode is idempotent
+ D = F(decode, F(encode, D)),
+ V
+ end.
+
+z(B) ->
+ << <<0>> || <<_>> <= B >>.
+
+%% values/1
+%%
+%% Return a list of base type values. Can also be wrapped in a tuple
+%% with 'false' to indicate that encode followed by decode may not be
+%% the identity map. (Although that this composition is idempotent is
+%% tested.)
+
+values('OctetString' = T) ->
+ {["", atom_to_list(T)], [-1, 256]};
+
+values('Integer32') ->
+ Mx = (1 bsl 31) - 1,
+ Mn = -1*Mx,
+ {[Mn, 0, random(Mn,Mx), Mx], [Mn - 1, Mx + 1]};
+
+values('Integer64') ->
+ Mx = (1 bsl 63) - 1,
+ Mn = -1*Mx,
+ {[Mn, 0, random(Mn,Mx), Mx], [Mn - 1, Mx + 1]};
+
+values('Unsigned32') ->
+ M = (1 bsl 32) - 1,
+ {[0, random(M), M], [-1, M + 1]};
+
+values('Unsigned64') ->
+ M = (1 bsl 64) - 1,
+ {[0, random(M), M], [-1, M + 1]};
+
+values('Float32') ->
+ E = (1 bsl 8) - 2,
+ F = (1 bsl 23) - 1,
+ <<Mx:32/float>> = <<0:1/integer, E:8/integer, F:23/integer>>,
+ <<Mn:32/float>> = <<1:1/integer, E:8/integer, F:23/integer>>,
+ {[0.0, infinity, '-infinity', Mx, Mn], [0]};
+
+values('Float64') ->
+ E = (1 bsl 11) - 2,
+ F = (1 bsl 52) - 1,
+ <<Mx:64/float>> = <<0:1/integer, E:11/integer, F:52/integer>>,
+ <<Mn:64/float>> = <<1:1/integer, E:11/integer, F:52/integer>>,
+ {[0.0, infinity, '-infinity', Mx, Mn], [0]};
+
+values('Address') ->
+ {[{255,0,random(16#FF),1}, {65535,0,0,random(16#FFFF),0,0,0,1}],
+ [{256,0,0,1}, {65536,0,0,0,0,0,0,1}]};
+
+values('DiameterIdentity') ->
+ {["x", "diameter.com"], [""]};
+
+values('DiameterURI') ->
+ {false, ["aaa" ++ S ++ "://diameter.se" ++ P ++ Tr ++ Pr
+ || S <- ["", "s"],
+ P <- ["", ":1234"],
+ Tr <- ["" | [";transport=" ++ X
+ || X <- ["tcp", "sctp", "udp"]]],
+ Pr <- ["" | [";protocol=" ++ X
+ || X <- ["diameter","radius","tacacs+"]]]]};
+
+values(T)
+ when T == 'IPFilterRule';
+ T == 'QoSFilterRule' ->
+ ["deny in 0 from 127.0.0.1 to 10.0.0.1"];
+
+%% RFC 3629 defines the UTF-8 encoding of U+0000 through U+10FFFF with the
+%% exception of U+D800 through U+DFFF.
+values('UTF8String') ->
+ {[[],
+ lists:seq(0,16#1FF),
+ [0,16#D7FF,16#E000,16#10FFFF],
+ [random(16#D7FF), random(16#E000,16#10FFFF)]],
+ [[-1],
+ [16#D800],
+ [16#DFFF],
+ [16#110000]]};
+
+values('Time') ->
+ {[{{1968,1,20},{3,14,8}}, %% 19000101T000000 + 1 bsl 31
+ {date(), time()},
+ {{2036,2,7},{6,28,15}},
+ {{2036,2,7},{6,28,16}}, %% 19000101T000000 + 2 bsl 31
+ {{2104,2,26},{9,42,23}}],
+ [{{1968,1,20},{3,14,7}},
+ {{2104,2,26},{9,42,24}}]}. %% 19000101T000000 + 3 bsl 31
+
+%% values/3
+%%
+%% Return list or enumerations of values for a given AVP. Can be
+%% wrapped as for values/1.
+
+values('Enumerated', Name, Mod) ->
+ {_Name, Vals} = lists:keyfind(Name, 1, types(enums, Mod)),
+ lists:map(fun({N,_}) -> N end, Vals);
+
+values('Grouped', Name, Mod) ->
+ Rname = Mod:name2rec(Name),
+ Rec = Mod:'#new-'(Rname),
+ Avps = Mod:'#info-'(Rname, fields),
+ Enum = diameter_enum:combine(lists:map(fun({_,Vs,_}) -> to_enum(Vs) end,
+ [values(F, Mod) || F <- Avps])),
+ {false, diameter_enum:append(group(Mod, Name, Rec, Avps, Enum))};
+
+values(_, 'Framed-IP-Address', _) ->
+ [{127,0,0,1}];
+
+values(Type, _, _) ->
+ values(Type).
+
+to_enum(Vs)
+ when is_list(Vs) ->
+ diameter_enum:new(Vs);
+to_enum(E) ->
+ E.
+
+%% values/2
+
+values('AVP', _) ->
+ {true, [#diameter_avp{code = 0, data = <<0>>}], []};
+
+values(Name, Mod) ->
+ Avps = types(avp_types, Mod),
+ {Name, _Code, Type, _Flags, _Encr} = lists:keyfind(Name, 1, Avps),
+ b(values(Type, Name, Mod)).
+
+%% group/5
+%%
+%% Pack four variants of group values: tagged list containing all
+%% values, the corresponding record, a minimal tagged list and the
+%% coresponding record.
+
+group(Mod, Name, Rec, Avps, Enum) ->
+ lists:map(fun(B) -> group(Mod, Name, Rec, Avps, Enum, B) end,
+ [{A,R} || A <- ?BOOL, R <- ?BOOL]).
+
+group(Mod, Name, Rec, Avps, Enum, B) ->
+ diameter_enum:map(fun(Vs) -> g(Mod, Name, Rec, Avps, Vs, B) end, Enum).
+
+g(Mod, Name, Rec, Avps, Values, {All, AsRec}) ->
+ {Tagged, []}
+ = lists:foldl(fun(N, {A, [V|Vs]}) ->
+ {pack(All, Mod:avp_arity(Name, N), N, V, A), Vs}
+ end,
+ {[], Values},
+ Avps),
+ g(AsRec, Mod, Tagged, Rec).
+
+g(true, Mod, Vals, Rec) ->
+ Mod:'#set-'(Vals, Rec);
+g(false, _, Vals, _) ->
+ Vals.
+
+pack(true, Arity, Avp, Value, Acc) ->
+ [all(Arity, Avp, Value) | Acc];
+pack(false, Arity, Avp, Value, Acc) ->
+ min(Arity, Avp, Value, Acc).
+
+all(Mod, Name, Avp, V) ->
+ all(Mod:avp_arity(Name, Avp), Avp, V).
+
+all(1, Avp, V) ->
+ {Avp, V};
+all({0,'*'}, Avp, V) ->
+ a(1, Avp, V);
+all({N,'*'}, Avp, V) ->
+ a(N, Avp, V);
+all({_,N}, Avp, V) ->
+ a(N, Avp, V).
+
+a(N, Avp, V)
+ when N /= 0 ->
+ {Avp, lists:duplicate(N,V)}.
+
+min(Mod, Name, Avp, V, Acc) ->
+ min(Mod:avp_arity(Name, Avp), Avp, V, Acc).
+
+min(1, Avp, V, Acc) ->
+ [{Avp, V} | Acc];
+min({0,_}, _, _, Acc) ->
+ Acc;
+min({N,_}, Avp, V, Acc) ->
+ [{Avp, lists:duplicate(N,V)} | Acc].
+
+%% types/2
+
+types(T, Mod) ->
+ types(T, retag(T), Mod).
+
+types(T, IT, Mod) ->
+ Dict = Mod:dict(),
+ fetch(T, Dict) ++ lists:flatmap(fun({_,As}) -> As end, fetch(IT, Dict)).
+
+%% random/[12]
+
+random(M) ->
+ random(0,M).
+
+random(Mn,Mx) ->
+ seed(get({?MODULE, seed})),
+ Mn + random:uniform(Mx - Mn + 1) - 1.
+
+seed(undefined) ->
+ put({?MODULE, seed}, true),
+ random:seed(now());
+
+seed(true) ->
+ ok.
+
+%% run/1
+%%
+%% Unravel nested badmatches resulting from [] matches on calls to
+%% run/1 to make for more readable failures.
+
+run(L) ->
+ lists:flatmap(fun flatten/1, diameter_util:run(L)).
+
+flatten({_, {{badmatch, [{_, {{badmatch, _}, _}} | _] = L}, _}}) ->
+ L;
+flatten(T) ->
+ [T].
diff --git a/lib/diameter/test/diameter_compiler_test.erl b/lib/diameter/test/diameter_compiler_test.erl
deleted file mode 100644
index ae4c9c668d..0000000000
--- a/lib/diameter/test/diameter_compiler_test.erl
+++ /dev/null
@@ -1,104 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-%%----------------------------------------------------------------------
-%% Purpose: Verify the dia compiler of the Diameter application
-%%----------------------------------------------------------------------
-%%
--module(diameter_compiler_test).
-
--export([
- init_per_testcase/2, fin_per_testcase/2,
-
- all/0,
- groups/0,
- init_per_suite/1, end_per_suite/1,
- suite_init/1, suite_fin/1,
- init_per_group/2, end_per_group/2
-
- %% foo/1
- ]).
-
--export([t/0, t/1]).
-
--include("diameter_test_lib.hrl").
-
-
-t() -> diameter_test_server:t(?MODULE).
-t(Case) -> diameter_test_server:t({?MODULE, Case}).
-
-
-%% Test server callbacks
-init_per_testcase(Case, Config) ->
- diameter_test_server:init_per_testcase(Case, Config).
-
-fin_per_testcase(Case, Config) ->
- diameter_test_server:fin_per_testcase(Case, Config).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-all() ->
- [].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-suite_init(X) -> init_per_suite(X).
-
-init_per_suite(suite) -> [];
-init_per_suite(doc) -> [];
-init_per_suite(Config) when is_list(Config) ->
- Config.
-
-
-suite_fin(X) -> end_per_suite(X).
-
-end_per_suite(suite) -> [];
-end_per_suite(doc) -> [];
-end_per_suite(Config) when is_list(Config) ->
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Test case example
-%%
-
-%% foo(suite) ->
-%% [];
-%% foo(doc) ->
-%% [];
-%% foo(Config) when is_list(Config) ->
-%% ok.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
diff --git a/lib/diameter/test/diameter_config_test.erl b/lib/diameter/test/diameter_config_test.erl
deleted file mode 100644
index c44fb654ab..0000000000
--- a/lib/diameter/test/diameter_config_test.erl
+++ /dev/null
@@ -1,105 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-%%----------------------------------------------------------------------
-%% Purpose: Verify the config server of the Diameter application
-%%----------------------------------------------------------------------
-%%
--module(diameter_config_test).
-
--export([
- init_per_testcase/2, fin_per_testcase/2,
-
- all/0,
- groups/0,
- init_per_suite/1, end_per_suite/1,
- suite_init/1, suite_fin/1,
- init_per_group/2, end_per_group/2
-
- %% foo/1
- ]).
-
--export([t/0, t/1]).
-
--include("diameter_test_lib.hrl").
-
-
-t() -> diameter_test_server:t(?MODULE).
-t(Case) -> diameter_test_server:t({?MODULE, Case}).
-
-
-%% Test server callbacks
-init_per_testcase(Case, Config) ->
- diameter_test_server:init_per_testcase(Case, Config).
-
-fin_per_testcase(Case, Config) ->
- diameter_test_server:fin_per_testcase(Case, Config).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-all() ->
- [].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-suite_init(X) -> init_per_suite(X).
-
-init_per_suite(suite) -> [];
-init_per_suite(doc) -> [];
-init_per_suite(Config) when is_list(Config) ->
- Config.
-
-
-suite_fin(X) -> end_per_suite(X).
-
-end_per_suite(suite) -> [];
-end_per_suite(doc) -> [];
-end_per_suite(Config) when is_list(Config) ->
-
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Test case example
-%%
-
-%% foo(suite) ->
-%% [];
-%% foo(doc) ->
-%% [];
-%% foo(Config) when is_list(Config) ->
-%% ok.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
diff --git a/lib/diameter/test/diameter_ct.erl b/lib/diameter/test/diameter_ct.erl
new file mode 100644
index 0000000000..f8ee3dc1d7
--- /dev/null
+++ b/lib/diameter/test/diameter_ct.erl
@@ -0,0 +1,55 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(diameter_ct).
+
+%%
+%% Module used to run suites from Makefile.
+%%
+
+-export([run/1]).
+
+%% ct:run_test/1 is currently documented as returning a list of test
+%% results ... but no. Instead it returns 'ok' regardless of whether
+%% or not the suite in question has failed testcases.
+
+run([Suite]) ->
+ Start = info(),
+ ok = ct:run_test([{suite, Suite},
+ {logdir, "./log"},
+ {auto_compile, false}]),
+ info(Start , info()).
+
+info() ->
+ [{time, now()},
+ {process_count, erlang:system_info(process_count)}
+ | erlang:memory()].
+
+info(L0, L1) ->
+ [T, C | M]
+ = lists:zipwith(fun({T,N0}, {T,N1}) -> {T, N1, diff(T, N0, N1)} end,
+ L0,
+ L1),
+ Diff = [T, C, {memory, M}],
+ ct:pal("INFO: ~p~n", [Diff]).
+
+diff(time, T0, T1) ->
+ timer:now_diff(T1, T0);
+diff(_, N0, N1) ->
+ N1 - N0.
diff --git a/lib/diameter/src/app/diameter.appup.src b/lib/diameter/test/diameter_ct.hrl
index 2b96153575..b6bd2ca9da 100644
--- a/lib/diameter/src/app/diameter.appup.src
+++ b/lib/diameter/test/diameter_ct.hrl
@@ -1,4 +1,3 @@
-%% This is an -*- erlang -*- file.
%%
%% %CopyrightBegin%
%%
@@ -18,10 +17,5 @@
%% %CopyrightEnd%
%%
-{"%VSN%",
- [
- ],
- [
- ]
-}.
-
+-define(APP, diameter).
+-define(ERROR(T), erlang:error({?MODULE, ?LINE, T})).
diff --git a/lib/diameter/test/diameter_dict_SUITE.erl b/lib/diameter/test/diameter_dict_SUITE.erl
new file mode 100644
index 0000000000..87bb9727fe
--- /dev/null
+++ b/lib/diameter/test/diameter_dict_SUITE.erl
@@ -0,0 +1,151 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests of the dict-like diameter_dict.
+%%
+
+-module(diameter_dict_SUITE).
+
+-export([suite/0,
+ all/0,
+ groups/0,
+ init_per_group/2,
+ end_per_group/2]).
+
+%% testcases
+-export([append/1,
+ fetch/1,
+ fetch_keys/1,
+ filter/1,
+ find/1,
+ fold/1,
+ is_key/1,
+ map/1,
+ merge/1,
+ update/1,
+ update_counter/1]).
+
+-include("diameter_ct.hrl").
+
+-define(dict, diameter_dict).
+-define(util, diameter_util).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 10}}].
+
+all() ->
+ [{group, all} | tc()].
+
+groups() ->
+ [{all, [parallel], tc()}].
+
+tc() ->
+ [append,
+ fetch,
+ fetch_keys,
+ filter,
+ find,
+ fold,
+ is_key,
+ map,
+ merge,
+ update,
+ update_counter].
+
+init_per_group(_, Config) ->
+ Config.
+
+end_per_group(_, _) ->
+ ok.
+
+%% ===========================================================================
+
+-define(KV100, [{N,[N]} || N <- lists:seq(1,100)]).
+
+append(_) ->
+ D = ?dict:append(k, v, ?dict:new()),
+ [{k,[v,v]}] = ?dict:to_list(?dict:append(k, v, D)).
+
+fetch(_) ->
+ D = ?dict:from_list(?KV100),
+ [50] = ?dict:fetch(50, D),
+ Ref = make_ref(),
+ Ref = try ?dict:fetch(Ref, D) catch _:_ -> Ref end.
+
+fetch_keys(_) ->
+ L = ?KV100,
+ D = ?dict:from_list(L),
+ L = [{N,[N]} || N <- lists:sort(?dict:fetch_keys(D))].
+
+filter(_) ->
+ L = ?KV100,
+ F = fun(K,[_]) -> 0 == K rem 2 end,
+ D = ?dict:filter(F, ?dict:from_list(L)),
+ true = [T || {K,V} = T <- L, F(K,V)] == lists:sort(?dict:to_list(D)).
+
+find(_) ->
+ D = ?dict:from_list(?KV100),
+ {ok, [50]} = ?dict:find(50, D),
+ error = ?dict:find(make_ref(), D).
+
+fold(_) ->
+ L = ?KV100,
+ S = lists:sum([N || {N,_} <- L]),
+ S = ?dict:fold(fun(K,[_],A) -> K + A end, 0, ?dict:from_list(L)).
+
+is_key(_) ->
+ L = ?KV100,
+ D = ?dict:from_list(L),
+ true = lists:all(fun({N,_}) -> ?dict:is_key(N,D) end, L),
+ false = ?dict:is_key(make_ref(), D).
+
+map(_) ->
+ L = ?KV100,
+ F = fun(_,V) -> [N] = V, N*2 end,
+ D = ?dict:map(F, ?dict:from_list(L)),
+ M = [{K, F(K,V)} || {K,V} <- L],
+ M = lists:sort(?dict:to_list(D)).
+
+merge(_) ->
+ L = ?KV100,
+ F = fun(_,V1,V2) -> V1 ++ V2 end,
+ D = ?dict:merge(F, ?dict:from_list(L), ?dict:from_list(L)),
+ M = [{K, F(K,V,V)} || {K,V} <- L],
+ M = lists:sort(?dict:to_list(D)).
+
+update(_) ->
+ L = ?KV100,
+ F = fun([V]) -> 2*V end,
+ D = ?dict:update(50, F, ?dict:from_list(L)),
+ 100 = ?dict:fetch(50, D),
+ Ref = make_ref(),
+ Ref = try ?dict:update(Ref, F, D) catch _:_ -> Ref end,
+ [Ref] = ?dict:fetch(Ref, ?dict:update(Ref,
+ fun(_,_) -> ?ERROR(i_think_not) end,
+ [Ref],
+ D)).
+
+update_counter(_) ->
+ L = [{N,2*N} || {N,_} <- ?KV100],
+ D = ?dict:update_counter(50, 20, ?dict:from_list(L)),
+ 120 = ?dict:fetch(50,D),
+ 2 = ?dict:fetch(1,D).
diff --git a/lib/diameter/test/diameter_enum.erl b/lib/diameter/test/diameter_enum.erl
new file mode 100644
index 0000000000..dfb6d04e3c
--- /dev/null
+++ b/lib/diameter/test/diameter_enum.erl
@@ -0,0 +1,406 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(diameter_enum).
+
+%%
+%% This module constructs finite enumerations.
+%%
+%% An enumeration is represented as a function on integers, 0 mapping
+%% to the number of values enumerated and successive integers mapping
+%% to enumerated values. The function will fail on anything but 0 and
+%% positive integers less then or equal to the value of the function
+%% at 0.
+%%
+%% The purpose of this is to provide a way of stepping through a large
+%% number of values without explicitly constructing the list of all
+%% possible values. For example, consider the following function that
+%% given a list of lists constructs the list of all possible lists
+%% constructed by choosing one element from each sublist.
+%%
+%% combine([H]) ->
+%% [[X] || X <- H];
+%% combine([H|T]) ->
+%% Ys = combine(T),
+%% [[X|Y] || X <- H, Y <- Ys].
+%%
+%% Eg. [[1,2],[3,4,5]] -> [[1,3],[1,4],[1,5],[2,3],[2,4],[2,5]]
+%%
+%% If L is a list of three 1000 element lists then combine(L) would
+%% construct a list of length 10^9 which will likely exhaust available
+%% memory. (Which is how this module came into being. A tail-recursive
+%% implementation doesn't fare much better.) By contrast,
+%%
+%% F = enum:combine([enum:new(L) || L <- Lists])
+%%
+%% only maps existing lists. It may still be undesirable to step
+%% through a very large number of values but it's possible, and easy
+%% to step through a selection of values as an alternative.
+%%
+
+%% Functions that return enumerations.
+-export([new/1,
+ combine/1,
+ reverse/1,
+ map/2,
+ append/1,
+ duplicate/2,
+ nthtail/2,
+ seq/2,
+ seq/3,
+ zip/1,
+ zip/2,
+ slice/3,
+ split/2]).
+
+%% Functions that operate on existing enumerations.
+-export([foreach/2,
+ foldl/3,
+ foldr/3,
+ all/2,
+ any/2,
+ member/2,
+ last/1,
+ nth/2,
+ to_list/1]).
+
+%% ------------------------------------------------------------------------
+%% new/1
+%%
+%% Turn a list/tuple of values into an enumeration that steps through
+%% each element. Turn anything else into an enumeration of that single
+%% value.
+%% ------------------------------------------------------------------------
+
+new(L)
+ when is_list(L) ->
+ new(list_to_tuple(L));
+
+new(T)
+ when is_tuple(T) ->
+ enum(size(T), fun(N) -> element(N,T) end);
+
+new(T) ->
+ fun(0) -> 1; (1) -> T end.
+
+enum(Ord, F) ->
+ fun(0) -> Ord; (N) when 0 < N, N =< Ord -> F(N) end.
+
+%% ------------------------------------------------------------------------
+%% combine/1
+%%
+%% Map a list/tuple of enumerations to the enumeration of all
+%% lists/tuples constructed by choosing one value from each
+%% enumeration in the list/tuple.
+%% ------------------------------------------------------------------------
+
+combine(T)
+ when is_tuple(T) ->
+ F = combine(tuple_to_list(T)),
+ enum(F(0), fun(N) -> list_to_tuple(F(N)) end);
+
+combine([]) ->
+ fun(0) -> 0 end;
+
+%% Given positive integers n_1,...,n_k, construct a bijection from
+%% {0,...,\prod_{i=1}^k} n_i - 1} to {0,...,n_1} x ... x {0,...,n_k}
+%% that maps N to (N_1,...,N_k) where:
+%%
+%% N_1 = (N div 1) rem n_1
+%% ...
+%% N_k = (N div n_1*...*n_{k-1}) rem n_k
+%%
+%% That is:
+%%
+%% N_i = (N div \prod_{j=1}^{i-1} n_j) rem n_i
+%%
+%% This corresponds to looping through N_1, incrementing N_2 as N_1
+%% loops, and so on up through N_k. The inverse map is as follows.
+%%
+%% (N_1,...,N_k) -> N = N_1 + N_2*n_1 + ... + N_k*n_{k-1}*...*n_1
+%%
+%% = \sum_{i=1}^k N_i*\prod_{j=i}^{i-1} n_j
+%%
+%% [Proof: Induction on k. For k=1 we have the identity map. If
+%% g_k : (N_1,...,N_k) |-> N above is bijective then consider
+%% the bijection
+%%
+%% G : (t,n) |--> t + n*K, K = n_k*...*n_1
+%%
+%% from {0,...,K-1} x {0,...,n_{k+1}-1} onto {0,...,n_{k+1}*K - 1}
+%% with inverse F : n |--> (n rem K, n div K). Since
+%%
+%% g_{k+1}(N_1,...,N_{k+1}) = g_k(N_1,...,N_K) + N_{k+1}*K
+%% = G(g_k(N_1,...,N_K), N_{k+1})
+%%
+%% and G, g_k and ((N-1,...,N_k),N_{k+1}) -> (N_1,...,N_{k+1})
+%% are all bijections, so is g_{k+1}.]
+
+combine([_|_] = L) ->
+ [Ord | Divs] = lists:foldl(fun(F,[D|_] = A) -> [F(0)*D | A] end, [1], L),
+ RL = lists:reverse(L),
+ enum(Ord, fun(N) -> combine(N, Ord, Divs, RL) end).
+
+%% Since we use 0 to return the number of elements enumerated, use
+%% bijections from {1,...,N} rather than {0,...,N-1}.
+
+combine(N, Ord, Divs, L)
+ when 0 < N, N =< Ord ->
+ {Vs, []} = lists:foldl(fun(F, {A, [D|Ds]}) ->
+ {[F(1 + (((N-1) div D) rem F(0))) | A], Ds}
+ end,
+ {[], Divs},
+ L),
+ Vs.
+
+%% ------------------------------------------------------------------------
+%% reverse/1
+%%
+%% Construct the enumeration that reverses the order in which values
+%% are traversed.
+%% ------------------------------------------------------------------------
+
+reverse(E) ->
+ Ord = E(0),
+ enum(Ord, fun(N) -> E(Ord + 1 - N) end).
+
+%% ------------------------------------------------------------------------
+%% map/2
+%%
+%% Construct an enumeration that maps enumerated values.
+%% ------------------------------------------------------------------------
+
+map(Fun, E) ->
+ enum(E(0), fun(N) -> Fun(E(N)) end).
+
+%% ------------------------------------------------------------------------
+%% append/2
+%%
+%% Construct an enumeration that successively steps through each of a
+%% list of enumerations.
+%% ------------------------------------------------------------------------
+
+append(Es) ->
+ [Ord | Os] = lists:foldl(fun(E, [N|_] = A) -> [N+E(0)|A] end, [0], Es),
+ Rev = lists:reverse(Es),
+ enum(Ord, fun(N) -> append(N, Os, Rev) end).
+
+append(N, [Ord | _], [E | _])
+ when N > Ord ->
+ E(N - Ord);
+append(N, [_|Os], [_|Es]) ->
+ append(N, Os, Es).
+
+%% ------------------------------------------------------------------------
+%% duplicate/2
+%%
+%% Construct an enumeration that traverses an enumeration multiple
+%% times. Equivalent to append(lists:duplicate(N, E)).
+%% ------------------------------------------------------------------------
+
+duplicate(N, E) ->
+ Ord = E(0),
+ enum(N*Ord, fun(M) -> E(1 + ((M-1) rem Ord)) end).
+
+%% ------------------------------------------------------------------------
+%% nthtail/2
+%%
+%% Construct an enumeration that omits values at the head of an
+%% existing enumeration.
+%% ------------------------------------------------------------------------
+
+nthtail(N, E)
+ when 0 =< N ->
+ nthtail(E(0) - N, N, E).
+
+nthtail(Ord, N, E)
+ when 0 =< Ord ->
+ enum(Ord, fun(M) -> E(M+N) end).
+
+%% ------------------------------------------------------------------------
+%% seq/[23]
+%%
+%% Construct an enumeration that steps through a sequence of integers.
+%% ------------------------------------------------------------------------
+
+seq(From, To) ->
+ seq(From, To, 1).
+
+seq(From, To, Incr)
+ when From =< To ->
+ enum((To - From + Incr) div Incr, fun(N) -> From + (N-1)*Incr end).
+
+%% ------------------------------------------------------------------------
+%% zip/[12]
+%%
+%% Construct an enumeration whose nth value is the list of nth values
+%% of a list of enumerations.
+%% ------------------------------------------------------------------------
+
+zip(Es) ->
+ zip(fun(T) -> T end, Es).
+
+zip(_, []) ->
+ [];
+zip(Fun, Es) ->
+ enum(lists:min([E(0) || E <- Es]), fun(N) -> Fun([E(N) || E <- Es]) end).
+
+%% ------------------------------------------------------------------------
+%% slice/3
+%%
+%% Construct an enumeration of a given length from a given starting point.
+%% ------------------------------------------------------------------------
+
+slice(N, Len, E)
+ when is_integer(N), N > 0, is_integer(Len), Len >= 0 ->
+ slice(N, Len, E(0) - (N - 1), E).
+
+slice(_, _, Tail, _)
+ when Tail < 1 ->
+ fun(0) -> 0 end;
+
+slice(N, Len, Tail, E) ->
+ enum(lists:min([Len, Tail]), fun(M) -> E(N-1+M) end).
+
+%% ------------------------------------------------------------------------
+%% split/2
+%%
+%% Split an enumeration into a list of enumerations of the specified
+%% length. The last enumeration of the list may have order less than
+%% this length.
+%% ------------------------------------------------------------------------
+
+split(Len, E)
+ when is_integer(Len), Len > 0 ->
+ split(1, E(0), Len, E, []).
+
+split(N, Ord, _, _, Acc)
+ when N > Ord ->
+ lists:reverse(Acc);
+
+split(N, Ord, Len, E, Acc) ->
+ split(N+Len, Ord, Len, E, [slice(N, Len, E) | Acc]).
+
+%% ------------------------------------------------------------------------
+%% foreach/2
+%%
+%% Apply a fun to each value of an enumeration.
+%% ------------------------------------------------------------------------
+
+foreach(Fun, E) ->
+ foldl(fun(N,ok) -> Fun(N), ok end, ok, E).
+
+%% ------------------------------------------------------------------------
+%% foldl/3
+%% foldr/3
+%%
+%% Fold through values in an enumeration.
+%% ------------------------------------------------------------------------
+
+foldl(Fun, Acc, E) ->
+ foldl(E(0), 1, Fun, Acc, E).
+
+foldl(M, N, _, Acc, _)
+ when N == M+1 ->
+ Acc;
+foldl(M, N, Fun, Acc, E) ->
+ foldl(M, N+1, Fun, Fun(E(N), Acc), E).
+
+foldr(Fun, Acc, E) ->
+ foldl(Fun, Acc, reverse(E)).
+
+%% ------------------------------------------------------------------------
+%% all/2
+%%
+%% Do all values of an enumeration satisfy a predicate?
+%% ------------------------------------------------------------------------
+
+all(Pred, E) ->
+ all(E(0), 1, Pred, E).
+
+all(M, N, _, _)
+ when N == M+1 ->
+ true;
+all(M, N, Pred, E) ->
+ Pred(E(N)) andalso all(M, N+1, Pred, E).
+
+%% Note that andalso/orelse are tail-recusive as of R13A.
+
+%% ------------------------------------------------------------------------
+%% any/2
+%%
+%% Does any value of an enumeration satisfy a predicate?
+%% ------------------------------------------------------------------------
+
+any(Pred, E) ->
+ any(E(0), 1, Pred, E).
+
+any(M, N, _, _)
+ when N == M+1 ->
+ false;
+any(M, N, Pred, E) ->
+ Pred(E(N)) orelse any(M, N+1, Pred, E).
+
+%% ------------------------------------------------------------------------
+%% member/2
+%%
+%% Does a value match any in an enumeration?
+%% ------------------------------------------------------------------------
+
+member(X, E) ->
+ member(E(0), 1, X, E).
+
+member(M, N, _, _)
+ when N == M+1 ->
+ false;
+member(M, N, X, E) ->
+ match(E(N), X) orelse member(M, N+1, X, E).
+
+match(X, X) ->
+ true;
+match(_, _) ->
+ false.
+
+%% ------------------------------------------------------------------------
+%% last/1
+%%
+%% Return the last value of an enumeration.
+%% ------------------------------------------------------------------------
+
+last(E) ->
+ E(E(0)).
+
+%% ------------------------------------------------------------------------
+%% nth/2
+%%
+%% Return a selected value of an enumeration.
+%% ------------------------------------------------------------------------
+
+nth(N, E) ->
+ E(N).
+
+%% ------------------------------------------------------------------------
+%% to_list/1
+%%
+%% Turn an enumeration into a list. Not good if the very many values
+%% are enumerated.
+%% ------------------------------------------------------------------------
+
+to_list(E) ->
+ foldr(fun(X,A) -> [X|A] end, [], E).
diff --git a/lib/diameter/test/diameter_etcp_test.beam b/lib/diameter/test/diameter_etcp_test.beam
deleted file mode 100644
index efaaec69d5..0000000000
--- a/lib/diameter/test/diameter_etcp_test.beam
+++ /dev/null
Binary files differ
diff --git a/lib/diameter/test/diameter_failover_SUITE.erl b/lib/diameter/test/diameter_failover_SUITE.erl
new file mode 100644
index 0000000000..f4d62f94c6
--- /dev/null
+++ b/lib/diameter/test/diameter_failover_SUITE.erl
@@ -0,0 +1,257 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests of traffic between six Diameter nodes in three realms,
+%% connected as follows.
+%%
+%% ----- SERVER1.REALM2
+%% /
+%% / ----- SERVER2.REALM2
+%% | /
+%% CLIENT.REALM1 ------ SERVER3.REALM2
+%% | \
+%% | \
+%% \ ---- SERVER1.REALM3
+%% \
+%% ----- SERVER2.REALM3
+%%
+
+-module(diameter_failover_SUITE).
+
+-export([suite/0,
+ all/0]).
+
+%% testcases
+-export([start/1,
+ start_services/1,
+ connect/1,
+ send_ok/1,
+ send_nok/1,
+ stop_services/1,
+ stop/1]).
+
+%% diameter callbacks
+-export([peer_up/3,
+ peer_down/3,
+ pick_peer/4,
+ prepare_request/3,
+ prepare_retransmit/3,
+ handle_answer/4,
+ handle_error/4,
+ handle_request/3]).
+
+-include("diameter.hrl").
+-include("diameter_gen_base_rfc3588.hrl").
+-include("diameter_ct.hrl").
+
+%% ===========================================================================
+
+-define(util, diameter_util).
+
+-define(ADDR, {127,0,0,1}).
+
+-define(CLIENT, "CLIENT.REALM1").
+-define(SERVER1, "SERVER1.REALM2").
+-define(SERVER2, "SERVER2.REALM2").
+-define(SERVER3, "SERVER3.REALM2").
+-define(SERVER4, "SERVER1.REALM3").
+-define(SERVER5, "SERVER2.REALM3").
+
+-define(SERVICES, [?CLIENT, ?SERVER1, ?SERVER2, ?SERVER3, ?SERVER4, ?SERVER5]).
+
+-define(DICT_COMMON, ?DIAMETER_DICT_COMMON).
+
+-define(APP_ALIAS, the_app).
+-define(APP_ID, ?DICT_COMMON:id()).
+
+%% Config for diameter:start_service/2.
+-define(SERVICE(Host, Dict),
+ [{'Origin-Host', Host},
+ {'Origin-Realm', realm(Host)},
+ {'Host-IP-Address', [?ADDR]},
+ {'Vendor-Id', 12345},
+ {'Product-Name', "OTP/diameter"},
+ {'Acct-Application-Id', [Dict:id()]},
+ {application, [{alias, ?APP_ALIAS},
+ {dictionary, Dict},
+ {module, ?MODULE},
+ {answer_errors, callback}]}]).
+
+-define(SUCCESS, 2001).
+
+-define(LOGOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_LOGOUT').
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 10}}].
+
+all() ->
+ [start,
+ start_services,
+ connect,
+ send_ok,
+ send_nok,
+ stop_services,
+ stop].
+
+%% ===========================================================================
+%% start/stop testcases
+
+start(_Config) ->
+ ok = diameter:start().
+
+start_services(_Config) ->
+ S = [server(N, ?DICT_COMMON) || N <- tl(?SERVICES)],
+
+ ok = diameter:start_service(?CLIENT, ?SERVICE(?CLIENT, ?DICT_COMMON)),
+
+ {save_config, [{?CLIENT, S}]}.
+
+connect(Config) ->
+ {_, Conns} = proplists:get_value(saved_config, Config),
+
+ lists:foreach(fun({CN,Ss}) -> connect(CN, Ss) end, Conns).
+
+stop_services(_Config) ->
+ [] = [{H,T} || H <- ?SERVICES,
+ T <- [diameter:stop_service(H)],
+ T /= ok].
+
+stop(_Config) ->
+ ok = diameter:stop().
+
+%% ----------------------------------------
+
+server(Name, Dict) ->
+ ok = diameter:start_service(Name, ?SERVICE(Name, Dict)),
+ {Name, ?util:listen(Name, tcp)}.
+
+connect(Name, Refs) ->
+ [{{Name, ?util:connect(Name, tcp, LRef)}, T} || {_, LRef} = T <- Refs].
+
+%% ===========================================================================
+%% traffic testcases
+
+%% Send an STR and expect success after SERVER3 answers after a couple
+%% of failovers.
+send_ok(_Config) ->
+ Req = ['STR', {'Destination-Realm', realm(?SERVER1)},
+ {'Termination-Cause', ?LOGOUT},
+ {'Auth-Application-Id', ?APP_ID}],
+ #diameter_base_STA{'Result-Code' = ?SUCCESS,
+ 'Origin-Host' = ?SERVER3}
+ = call(Req, [{filter, realm}]).
+
+%% Send an STR and expect failure when both servers fail.
+send_nok(_Config) ->
+ Req = ['STR', {'Destination-Realm', realm(?SERVER4)},
+ {'Termination-Cause', ?LOGOUT},
+ {'Auth-Application-Id', ?APP_ID}],
+ {error, failover} = call(Req, [{filter, realm}]).
+
+%% ===========================================================================
+
+realm(Host) ->
+ tl(lists:dropwhile(fun(C) -> C /= $. end, Host)).
+
+call(Req, Opts) ->
+ diameter:call(?CLIENT, ?APP_ALIAS, Req, Opts).
+
+set([H|T], Vs) ->
+ [H | Vs ++ T].
+
+%% ===========================================================================
+%% diameter callbacks
+
+%% peer_up/3
+
+peer_up(_SvcName, _Peer, State) ->
+ State.
+
+%% peer_down/3
+
+peer_down(_SvcName, _Peer, State) ->
+ State.
+
+%% pick_peer/4
+
+%% Choose a server other than SERVER3 or SERVER5 if possible.
+pick_peer(Peers, _, ?CLIENT, _State) ->
+ case lists:partition(fun({_, #diameter_caps{origin_host = {_, OH}}}) ->
+ OH /= ?SERVER3 andalso OH /= ?SERVER5
+ end,
+ Peers)
+ of
+ {[], [Peer]} ->
+ {ok, Peer};
+ {[Peer | _], _} ->
+ {ok, Peer}
+ end.
+
+%% prepare_request/3
+
+prepare_request(Pkt, ?CLIENT, {_Ref, Caps}) ->
+ {send, prepare(Pkt, Caps)}.
+
+prepare(#diameter_packet{msg = Req}, Caps) ->
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, _}}
+ = Caps,
+ set(Req, [{'Session-Id', diameter:session_id(OH)},
+ {'Origin-Host', OH},
+ {'Origin-Realm', OR}]).
+
+%% prepare_retransmit/3
+
+prepare_retransmit(Pkt, ?CLIENT, _Peer) ->
+ {send, Pkt}.
+
+%% handle_answer/4
+
+handle_answer(Pkt, _Req, ?CLIENT, _Peer) ->
+ #diameter_packet{msg = Rec, errors = []} = Pkt,
+ Rec.
+
+%% handle_error/4
+
+handle_error(Reason, _Req, ?CLIENT, _Peer) ->
+ {error, Reason}.
+
+%% handle_request/3
+
+%% Only SERVER3 actually answers.
+handle_request(Pkt, ?SERVER3, {_, Caps}) ->
+ #diameter_packet{msg = #diameter_base_STR{'Session-Id' = SId,
+ 'Origin-Host' = ?CLIENT}}
+ = Pkt,
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, _}}
+ = Caps,
+
+ {reply, #diameter_base_STA{'Result-Code' = ?SUCCESS,
+ 'Session-Id' = SId,
+ 'Origin-Host' = OH,
+ 'Origin-Realm' = OR}};
+
+%% Others kill the transport to force failover.
+handle_request(_, _, {TPid, _}) ->
+ exit(TPid, kill),
+ discard.
diff --git a/lib/diameter/test/diameter_peer_test.erl b/lib/diameter/test/diameter_peer_test.erl
deleted file mode 100644
index 27e75e26ef..0000000000
--- a/lib/diameter/test/diameter_peer_test.erl
+++ /dev/null
@@ -1,104 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-%%----------------------------------------------------------------------
-%% Purpose: Verify the peer component of the Diameter application
-%%----------------------------------------------------------------------
-%%
--module(diameter_peer_test).
-
--export([
- init_per_testcase/2, fin_per_testcase/2,
-
- all/0,
- groups/0,
- init_per_suite/1, end_per_suite/1,
- suite_init/1, suite_fin/1,
- init_per_group/2, end_per_group/2
-
- %% foo/1
- ]).
-
--export([t/0, t/1]).
-
--include("diameter_test_lib.hrl").
-
-
-t() -> diameter_test_server:t(?MODULE).
-t(Case) -> diameter_test_server:t({?MODULE, Case}).
-
-
-%% Test server callbacks
-init_per_testcase(Case, Config) ->
- diameter_test_server:init_per_testcase(Case, Config).
-
-fin_per_testcase(Case, Config) ->
- diameter_test_server:fin_per_testcase(Case, Config).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-all() ->
- [].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-suite_init(X) -> init_per_suite(X).
-
-init_per_suite(suite) -> [];
-init_per_suite(doc) -> [];
-init_per_suite(Config) when is_list(Config) ->
- Config.
-
-
-suite_fin(X) -> end_per_suite(X).
-
-end_per_suite(suite) -> [];
-end_per_suite(doc) -> [];
-end_per_suite(Config) when is_list(Config) ->
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Test case example
-%%
-
-%% foo(suite) ->
-%% [];
-%% foo(doc) ->
-%% [];
-%% foo(Config) when is_list(Config) ->
-%% ok.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
diff --git a/lib/diameter/test/diameter_reg_SUITE.erl b/lib/diameter/test/diameter_reg_SUITE.erl
new file mode 100644
index 0000000000..ade824c9dd
--- /dev/null
+++ b/lib/diameter/test/diameter_reg_SUITE.erl
@@ -0,0 +1,119 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests of the server implemented by diameter_reg.erl.
+%%
+
+-module(diameter_reg_SUITE).
+
+-export([suite/0,
+ all/0,
+ groups/0,
+ init_per_group/2,
+ end_per_group/2,
+ init_per_suite/1,
+ end_per_suite/1]).
+
+%% testcases
+-export([add/1,
+ add_new/1,
+ del/1,
+ repl/1,
+ terms/1,
+ pids/1]).
+
+-define(reg, diameter_reg).
+-define(util, diameter_util).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 10}}].
+
+all() ->
+ [{group, all} | tc()].
+
+groups() ->
+ [{all, [parallel], tc()}].
+
+tc() ->
+ [add,
+ add_new,
+ del,
+ repl,
+ terms,
+ pids].
+
+init_per_group(_, Config) ->
+ Config.
+
+end_per_group(_, _) ->
+ ok.
+
+init_per_suite(Config) ->
+ ok = diameter:start(),
+ Config.
+
+end_per_suite(_Config) ->
+ ok = diameter:stop().
+
+%% ===========================================================================
+
+add(_) ->
+ Ref = make_ref(),
+ true = ?reg:add(Ref),
+ true = ?reg:add(Ref),
+ [{Ref, Pid}] = ?reg:match(Ref),
+ Pid = self().
+
+add_new(_) ->
+ Ref = make_ref(),
+ true = ?reg:add_new(Ref),
+ false = ?reg:add_new(Ref).
+
+del(_) ->
+ Ref = make_ref(),
+ true = ?reg:add_new(Ref),
+ true = ?reg:add_new({Ref}),
+ true = ?reg:del({Ref}),
+ [{Ref, Pid}] = ?reg:match(Ref),
+ Pid = self().
+
+repl(_) ->
+ Ref = make_ref(),
+ true = ?reg:add_new({Ref}),
+ true = ?reg:repl({Ref}, Ref),
+ false = ?reg:add_new(Ref),
+ false = ?reg:repl({Ref}, Ref),
+ [{Ref, Pid}] = ?reg:match(Ref),
+ Pid = self().
+
+terms(_) ->
+ Ref = make_ref(),
+ true = ?reg:add_new(Ref),
+ [[Pid]] = [L || {T,L} <- ?reg:terms(), T == Ref],
+ Pid = self().
+
+pids(_) ->
+ Ref = make_ref(),
+ true = ?reg:add_new(Ref),
+ %% Don't match [[Ref]] since this will only necessarily be the
+ %% case when the test is run in its own process.
+ [_|_] = [L || {P,L} <- ?reg:pids(), P == self()].
diff --git a/lib/diameter/test/diameter_reg_test.erl b/lib/diameter/test/diameter_reg_test.erl
deleted file mode 100644
index a2638d6712..0000000000
--- a/lib/diameter/test/diameter_reg_test.erl
+++ /dev/null
@@ -1,104 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2010-2011_2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-%%----------------------------------------------------------------------
-%% Purpose: Verify the reg component of the Diameter application
-%%----------------------------------------------------------------------
-%%
--module(diameter_reg_test).
-
--export([
- init_per_testcase/2, fin_per_testcase/2,
-
- all/0,
- groups/0,
- init_per_suite/1, end_per_suite/1,
- suite_init/1, suite_fin/1,
- init_per_group/2, end_per_group/2
-
- %% foo/1
- ]).
-
--export([t/0, t/1]).
-
--include("diameter_test_lib.hrl").
-
-
-t() -> diameter_test_server:t(?MODULE).
-t(Case) -> diameter_test_server:t({?MODULE, Case}).
-
-
-%% Test server callbacks
-init_per_testcase(Case, Config) ->
- diameter_test_server:init_per_testcase(Case, Config).
-
-fin_per_testcase(Case, Config) ->
- diameter_test_server:fin_per_testcase(Case, Config).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-all() ->
- [].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-suite_init(X) -> init_per_suite(X).
-
-init_per_suite(suite) -> [];
-init_per_suite(doc) -> [];
-init_per_suite(Config) when is_list(Config) ->
- Config.
-
-
-suite_fin(X) -> end_per_suite(X).
-
-end_per_suite(suite) -> [];
-end_per_suite(doc) -> [];
-end_per_suite(Config) when is_list(Config) ->
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Test case example
-%%
-
-%% foo(suite) ->
-%% [];
-%% foo(doc) ->
-%% [];
-%% foo(Config) when is_list(Config) ->
-%% ok.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
diff --git a/lib/diameter/test/diameter_relay_SUITE.erl b/lib/diameter/test/diameter_relay_SUITE.erl
new file mode 100644
index 0000000000..40cbdf805a
--- /dev/null
+++ b/lib/diameter/test/diameter_relay_SUITE.erl
@@ -0,0 +1,363 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests of traffic between seven Diameter nodes connected as follows.
+%%
+%% --- SERVER1.REALM2
+%% /
+%% ---- RELAY.REALM2 ---- SERVER2.REALM2
+%% / |
+%% CLIENT.REALM1 |
+%% \ |
+%% ---- RELAY.REALM3 ---- SERVER1.REALM3
+%% \
+%% --- SERVER2.REALM3
+%%
+
+-module(diameter_relay_SUITE).
+
+-export([suite/0,
+ all/0,
+ groups/0,
+ init_per_group/2,
+ end_per_group/2]).
+
+%% testcases
+-export([start/1,
+ start_services/1,
+ connect/1,
+ send1/1,
+ send2/1,
+ send3/1,
+ send4/1,
+ send_loop/1,
+ send_timeout_1/1,
+ send_timeout_2/1,
+ disconnect/1,
+ stop_services/1,
+ stop/1]).
+
+%% diameter callbacks
+-export([peer_up/3,
+ peer_down/3,
+ pick_peer/4,
+ prepare_request/3,
+ prepare_retransmit/3,
+ handle_answer/4,
+ handle_error/4,
+ handle_request/3]).
+
+-include("diameter.hrl").
+-include("diameter_gen_base_rfc3588.hrl").
+-include("diameter_ct.hrl").
+
+%% ===========================================================================
+
+-define(util, diameter_util).
+
+-define(ADDR, {127,0,0,1}).
+
+-define(CLIENT, "CLIENT.REALM1").
+-define(RELAY1, "RELAY.REALM2").
+-define(SERVER1, "SERVER1.REALM2").
+-define(SERVER2, "SERVER2.REALM2").
+-define(RELAY2, "RELAY.REALM3").
+-define(SERVER3, "SERVER1.REALM3").
+-define(SERVER4, "SERVER2.REALM3").
+
+-define(SERVICES, [?CLIENT,
+ ?RELAY1, ?RELAY2,
+ ?SERVER1, ?SERVER2, ?SERVER3, ?SERVER4]).
+
+-define(DICT_COMMON, ?DIAMETER_DICT_COMMON).
+-define(DICT_RELAY, ?DIAMETER_DICT_RELAY).
+
+-define(APP_ALIAS, the_app).
+-define(APP_ID, ?DICT_COMMON:id()).
+
+%% Config for diameter:start_service/2.
+-define(SERVICE(Host, Dict),
+ [{'Origin-Host', Host},
+ {'Origin-Realm', realm(Host)},
+ {'Host-IP-Address', [?ADDR]},
+ {'Vendor-Id', 12345},
+ {'Product-Name', "OTP/diameter"},
+ {'Acct-Application-Id', [Dict:id()]},
+ {application, [{alias, ?APP_ALIAS},
+ {dictionary, Dict},
+ {module, ?MODULE},
+ {answer_errors, callback}]}]).
+
+-define(SUCCESS, 2001).
+-define(LOOP_DETECTED, 3005).
+-define(UNABLE_TO_DELIVER, 3002).
+
+-define(LOGOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_LOGOUT').
+-define(AUTHORIZE_ONLY, ?'DIAMETER_BASE_RE-AUTH-REQUEST-TYPE_AUTHORIZE_ONLY').
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 10}}].
+
+all() ->
+ [start, start_services, connect]
+ ++ tc()
+ ++ [{group, all},
+ disconnect,
+ stop_services,
+ stop].
+
+groups() ->
+ [{all, [parallel], tc()}].
+
+init_per_group(_, Config) ->
+ Config.
+
+end_per_group(_, _) ->
+ ok.
+
+%% Traffic cases run when services are started and connections
+%% established.
+tc() ->
+ [send1,
+ send2,
+ send3,
+ send4,
+ send_loop,
+ send_timeout_1,
+ send_timeout_2].
+
+%% ===========================================================================
+%% start/stop testcases
+
+start(_Config) ->
+ ok = diameter:start().
+
+start_services(_Config) ->
+ [S1,S2,S3,S4] = [server(N, ?DICT_COMMON) || N <- [?SERVER1,
+ ?SERVER2,
+ ?SERVER3,
+ ?SERVER4]],
+ [R1,R2] = [server(N, ?DICT_RELAY) || N <- [?RELAY1, ?RELAY2]],
+
+ ok = diameter:start_service(?CLIENT, ?SERVICE(?CLIENT, ?DICT_COMMON)),
+
+ {save_config, [{?RELAY1, [S1,S2,R2]},
+ {?RELAY2, [S3,S4]},
+ {?CLIENT, [R1,R2]}]}.
+
+connect(Config) ->
+ {_, Conns} = proplists:get_value(saved_config, Config),
+
+ ?util:write_priv(Config,
+ "cfg",
+ lists:flatmap(fun({CN,Ss}) -> connect(CN, Ss) end,
+ Conns)).
+
+disconnect(Config) ->
+ lists:foreach(fun({{CN,CR},{SN,SR}}) -> ?util:disconnect(CN,CR,SN,SR) end,
+ ?util:read_priv(Config, "cfg")).
+
+stop_services(_Config) ->
+ [] = [{H,T} || H <- ?SERVICES,
+ T <- [diameter:stop_service(H)],
+ T /= ok].
+
+stop(_Config) ->
+ ok = diameter:stop().
+
+%% ----------------------------------------
+
+server(Name, Dict) ->
+ ok = diameter:start_service(Name, ?SERVICE(Name, Dict)),
+ {Name, ?util:listen(Name, tcp)}.
+
+connect(Name, Refs) ->
+ [{{Name, ?util:connect(Name, tcp, LRef)}, T} || {_, LRef} = T <- Refs].
+
+%% ===========================================================================
+%% traffic testcases
+
+%% Send an STR intended for a specific server and expect success.
+send1(_Config) ->
+ call(?SERVER1).
+send2(_Config) ->
+ call(?SERVER2).
+send3(_Config) ->
+ call(?SERVER3).
+send4(_Config) ->
+ call(?SERVER4).
+
+%% Send an ASR that loops between the relays and expect the loop to
+%% be detected.
+send_loop(_Config) ->
+ Req = ['ASR', {'Destination-Realm', realm(?SERVER1)},
+ {'Destination-Host', ?SERVER1},
+ {'Auth-Application-Id', ?APP_ID}],
+ #'diameter_base_answer-message'{'Result-Code' = ?LOOP_DETECTED}
+ = call(Req, [{filter, realm}]).
+
+%% Send a RAR that is incorrectly routed and then discarded and expect
+%% different results depending on whether or not we or the relay
+%% timeout first.
+send_timeout_1(_Config) ->
+ #'diameter_base_answer-message'{'Result-Code' = ?UNABLE_TO_DELIVER}
+ = send_timeout(7000).
+send_timeout_2(_Config) ->
+ {error, timeout} = send_timeout(3000).
+
+send_timeout(Tmo) ->
+ Req = ['RAR', {'Destination-Realm', realm(?SERVER1)},
+ {'Destination-Host', ?SERVER1},
+ {'Auth-Application-Id', ?APP_ID},
+ {'Re-Auth-Request-Type', ?AUTHORIZE_ONLY}],
+ call(Req, [{filter, realm}, {timeout, Tmo}]).
+
+%% ===========================================================================
+
+realm(Host) ->
+ tl(lists:dropwhile(fun(C) -> C /= $. end, Host)).
+
+call(Server) ->
+ Realm = realm(Server),
+ Req = ['STR', {'Destination-Realm', Realm},
+ {'Destination-Host', [Server]},
+ {'Termination-Cause', ?LOGOUT},
+ {'Auth-Application-Id', ?APP_ID}],
+ #diameter_base_STA{'Result-Code' = ?SUCCESS,
+ 'Origin-Host' = Server,
+ 'Origin-Realm' = Realm}
+ = call(Req, [{filter, realm}]).
+
+call(Req, Opts) ->
+ diameter:call(?CLIENT, ?APP_ALIAS, Req, Opts).
+
+set([H|T], Vs) ->
+ [H | Vs ++ T].
+
+%% ===========================================================================
+%% diameter callbacks
+
+%% peer_up/3
+
+peer_up(_SvcName, _Peer, State) ->
+ State.
+
+%% peer_down/3
+
+peer_down(_SvcName, _Peer, State) ->
+ State.
+
+%% pick_peer/4
+
+pick_peer([Peer | _], _, Svc, _State)
+ when Svc == ?RELAY1;
+ Svc == ?RELAY2;
+ Svc == ?CLIENT ->
+ {ok, Peer}.
+
+%% prepare_request/3
+
+prepare_request(Pkt, Svc, _Peer)
+ when Svc == ?RELAY1;
+ Svc == ?RELAY2 ->
+ {send, Pkt};
+
+prepare_request(Pkt, ?CLIENT, {_Ref, Caps}) ->
+ {send, prepare(Pkt, Caps)}.
+
+prepare(#diameter_packet{msg = Req}, Caps) ->
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, _}}
+ = Caps,
+ set(Req, [{'Session-Id', diameter:session_id(OH)},
+ {'Origin-Host', OH},
+ {'Origin-Realm', OR}]).
+
+%% prepare_retransmit/3
+
+prepare_retransmit(_Pkt, false, _Peer) ->
+ discard.
+
+%% handle_answer/4
+
+%% A relay must return Pkt.
+handle_answer(Pkt, _Req, Svc, _Peer)
+ when Svc == ?RELAY1;
+ Svc == ?RELAY2 ->
+ Pkt;
+
+handle_answer(Pkt, _Req, ?CLIENT, _Peer) ->
+ #diameter_packet{msg = Rec, errors = []} = Pkt,
+ Rec.
+
+%% handle_error/4
+
+handle_error(Reason, _Req, _Svc, _Peer) ->
+ {error, Reason}.
+
+%% handle_request/3
+
+handle_request(Pkt, OH, {_Ref, #diameter_caps{origin_host = {OH,_}} = Caps})
+ when OH /= ?CLIENT ->
+ request(Pkt, Caps).
+
+%% RELAY1 routes any ASR or RAR to RELAY2 ...
+request(#diameter_packet{header = #diameter_header{cmd_code = C}},
+ #diameter_caps{origin_host = {?RELAY1, _}})
+ when C == 274; %% ASR
+ C == 258 -> %% RAR
+ {relay, [{filter, {realm, realm(?RELAY2)}}]};
+
+%% ... which in turn routes it back. Expect diameter to either answer
+%% either with DIAMETER_LOOP_DETECTED/DIAMETER_UNABLE_TO_COMPLY.
+request(#diameter_packet{header = #diameter_header{cmd_code = 274}},
+ #diameter_caps{origin_host = {?RELAY2, _}}) ->
+ {relay, [{filter, {host, ?RELAY1}}]};
+request(#diameter_packet{header = #diameter_header{cmd_code = 258}},
+ #diameter_caps{origin_host = {?RELAY2, _}}) ->
+ discard;
+
+%% Other request to a relay: send on to one of the servers in the
+%% same realm.
+request(_Pkt, #diameter_caps{origin_host = {OH, _}})
+ when OH == ?RELAY1;
+ OH == ?RELAY2 ->
+ {relay, [{filter, {all, [host, realm]}}]};
+
+%% Request received by a server: answer.
+request(#diameter_packet{msg = #diameter_base_STR{'Session-Id' = SId,
+ 'Origin-Host' = Host,
+ 'Origin-Realm' = Realm,
+ 'Route-Record' = Route}},
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, _}}) ->
+ %% The request should have the Origin-Host/Realm of the original
+ %% sender.
+ R = realm(?CLIENT),
+ {?CLIENT, R} = {Host, Realm},
+ %% A relay appends the identity of the peer that a request was
+ %% received from to the Route-Record avp.
+ [?CLIENT] = Route,
+ {reply, #diameter_base_STA{'Result-Code' = ?SUCCESS,
+ 'Session-Id' = SId,
+ 'Origin-Host' = OH,
+ 'Origin-Realm' = OR}}.
diff --git a/lib/diameter/test/diameter_session_test.erl b/lib/diameter/test/diameter_session_test.erl
deleted file mode 100644
index a32647d83d..0000000000
--- a/lib/diameter/test/diameter_session_test.erl
+++ /dev/null
@@ -1,104 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-%%----------------------------------------------------------------------
-%% Purpose: Verify the session component of the Diameter application
-%%----------------------------------------------------------------------
-%%
--module(diameter_session_test).
-
--export([
- init_per_testcase/2, fin_per_testcase/2,
-
- all/0,
- groups/0,
- init_per_suite/1, end_per_suite/1,
- suite_init/1, suite_fin/1,
- init_per_group/2, end_per_group/2
-
- %% foo/1
- ]).
-
--export([t/0, t/1]).
-
--include("diameter_test_lib.hrl").
-
-
-t() -> diameter_test_server:t(?MODULE).
-t(Case) -> diameter_test_server:t({?MODULE, Case}).
-
-
-%% Test server callbacks
-init_per_testcase(Case, Config) ->
- diameter_test_server:init_per_testcase(Case, Config).
-
-fin_per_testcase(Case, Config) ->
- diameter_test_server:fin_per_testcase(Case, Config).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-all() ->
- [].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-suite_init(X) -> init_per_suite(X).
-
-init_per_suite(suite) -> [];
-init_per_suite(doc) -> [];
-init_per_suite(Config) when is_list(Config) ->
- Config.
-
-
-suite_fin(X) -> end_per_suite(X).
-
-end_per_suite(suite) -> [];
-end_per_suite(doc) -> [];
-end_per_suite(Config) when is_list(Config) ->
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Test case example
-%%
-
-%% foo(suite) ->
-%% [];
-%% foo(doc) ->
-%% [];
-%% foo(Config) when is_list(Config) ->
-%% ok.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
diff --git a/lib/diameter/test/diameter_stats_SUITE.erl b/lib/diameter/test/diameter_stats_SUITE.erl
new file mode 100644
index 0000000000..e50a0050a6
--- /dev/null
+++ b/lib/diameter/test/diameter_stats_SUITE.erl
@@ -0,0 +1,92 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests of the server implemented by diameter_stats.erl.
+%%
+
+-module(diameter_stats_SUITE).
+
+-export([suite/0,
+ all/0,
+ groups/0,
+ init_per_group/2,
+ end_per_group/2,
+ init_per_suite/1,
+ end_per_suite/1]).
+
+%% testcases
+-export([an/1,
+ twa/1]).
+
+-define(stat, diameter_stats).
+-define(util, diameter_util).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 10}}].
+
+all() ->
+ [{group, all} | tc()].
+
+groups() ->
+ [{all, [parallel], tc()}].
+
+tc() ->
+ [an,
+ twa].
+
+init_per_group(_, Config) ->
+ Config.
+
+end_per_group(_, _) ->
+ ok.
+
+init_per_suite(Config) ->
+ ok = diameter:start(),
+ Config.
+
+end_per_suite(_Config) ->
+ ok = diameter:stop().
+
+%% ===========================================================================
+
+an(_) ->
+ Ref = {'_', make_ref()},
+ true = ?stat:reg(Ref),
+ true = ?stat:reg(Ref), %% duplicate
+ ok = ?stat:incr(x),
+ ok = ?stat:incr(x, Ref),
+ ok = ?stat:incr(y, 2),
+ ok = ?stat:incr(y, Ref),
+ %% Flushing a pid flushes even stats on the registered reference.
+ [{x,2},{y,3}] = lists:sort(?stat:flush()),
+ [] = ?stat:flush(Ref),
+ [] = ?stat:flush().
+
+twa(_) ->
+ Ref = make_ref(),
+ ok = ?stat:incr(x, 8),
+ ok = ?stat:incr(x, Ref, 7),
+ %% Flushing a reference doesn't affect registered pids.
+ [{x,7}] = ?stat:flush(Ref),
+ [] = ?stat:flush(Ref),
+ [{x,8}] = ?stat:flush(),
+ [] = ?stat:flush().
diff --git a/lib/diameter/test/diameter_stats_test.erl b/lib/diameter/test/diameter_stats_test.erl
deleted file mode 100644
index 8b666edf50..0000000000
--- a/lib/diameter/test/diameter_stats_test.erl
+++ /dev/null
@@ -1,104 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-%%----------------------------------------------------------------------
-%% Purpose: Verify the stats component of the Diameter application
-%%----------------------------------------------------------------------
-%%
--module(diameter_stats_test).
-
--export([
- init_per_testcase/2, fin_per_testcase/2,
-
- all/0,
- groups/0,
- init_per_suite/1, end_per_suite/1,
- suite_init/1, suite_fin/1,
- init_per_group/2, end_per_group/2
-
- %% foo/1
- ]).
-
--export([t/0, t/1]).
-
--include("diameter_test_lib.hrl").
-
-
-t() -> diameter_test_server:t(?MODULE).
-t(Case) -> diameter_test_server:t({?MODULE, Case}).
-
-
-%% Test server callbacks
-init_per_testcase(Case, Config) ->
- diameter_test_server:init_per_testcase(Case, Config).
-
-fin_per_testcase(Case, Config) ->
- diameter_test_server:fin_per_testcase(Case, Config).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-all() ->
- [].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-suite_init(X) -> init_per_suite(X).
-
-init_per_suite(suite) -> [];
-init_per_suite(doc) -> [];
-init_per_suite(Config) when is_list(Config) ->
- Config.
-
-
-suite_fin(X) -> end_per_suite(X).
-
-end_per_suite(suite) -> [];
-end_per_suite(doc) -> [];
-end_per_suite(Config) when is_list(Config) ->
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Test case example
-%%
-
-%% foo(suite) ->
-%% [];
-%% foo(doc) ->
-%% [];
-%% foo(Config) when is_list(Config) ->
-%% ok.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
diff --git a/lib/diameter/test/diameter_sync_SUITE.erl b/lib/diameter/test/diameter_sync_SUITE.erl
new file mode 100644
index 0000000000..84f77b6066
--- /dev/null
+++ b/lib/diameter/test/diameter_sync_SUITE.erl
@@ -0,0 +1,139 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests of the server implemented by diameter_sync.erl.
+%%
+
+-module(diameter_sync_SUITE).
+
+-export([suite/0,
+ all/0,
+ groups/0,
+ init_per_group/2,
+ end_per_group/2,
+ init_per_suite/1,
+ end_per_suite/1]).
+
+%% testcases
+-export([call/1,
+ cast/1,
+ timeout/1,
+ flush/1]).
+
+-define(sync, diameter_sync).
+-define(util, diameter_util).
+
+-define(TIMEOUT, infinity).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 10}}].
+
+all() ->
+ [{group, all} | tc()].
+
+groups() ->
+ [{all, [parallel], tc()}].
+
+tc() ->
+ [call,
+ cast,
+ timeout,
+ flush].
+
+init_per_group(_, Config) ->
+ Config.
+
+end_per_group(_, _) ->
+ ok.
+
+init_per_suite(Config) ->
+ ok = diameter:start(),
+ Config.
+
+end_per_suite(_Config) ->
+ ok = diameter:stop().
+
+%% ===========================================================================
+
+call(_) ->
+ Ref = make_ref(),
+ Q = {q, Ref},
+ F = fun() -> Ref end,
+ Ref = ?sync:call(Q, F, infinity, ?TIMEOUT),
+ Ref = ?sync:call(Q, F, 0, infinity),
+ Ref = call(Q, F),
+ Ref = call(Q, {fun(_) -> Ref end, x}),
+ timeout = call(Q, fun() -> exit(unexpected) end),
+ {_,_,_} = call(Q, {erlang, now, []}),
+ {_,_,_} = call(Q, [fun erlang:now/0]).
+
+cast(_) ->
+ Ref = make_ref(),
+ Q = {q, Ref},
+ false = ?sync:carp(Q),
+ [] = ?sync:pids(Q),
+ %% Queue a request that blocks until we send it Ref and another
+ %% that exits with Ref.
+ ok = cast(Q, fun() -> receive Ref -> ok end end),
+ ok = cast(Q, fun() -> exit(Ref) end),
+ [_,Pid] = ?sync:pids(Q),
+ %% Ensure some expected truths ...
+ 2 = ?sync:pending(Q),
+ true = 2 =< ?sync:pending(),
+ true = lists:member(Q, ?sync:queues()),
+ %% ... and that the max number of requests is respected.
+ rejected = ?sync:call(Q, {erlang, now, []}, 1, ?TIMEOUT),
+ rejected = ?sync:cast(Q, {erlang, now, []}, 1, ?TIMEOUT),
+ %% Monitor on the identifiable request and see that exits when we
+ %% let the blocking request finish.
+ MRef = erlang:monitor(process, Pid),
+ {value, P} = ?sync:carp(Q),
+ P ! Ref,
+ Ref = receive
+ {'DOWN', MRef, process, _, Reason} ->
+ Reason
+ after ?TIMEOUT ->
+ false
+ end.
+
+timeout(_) ->
+ Q = make_ref(),
+ ok = ?sync:cast(Q, {timer, sleep, [2000]}, infinity, 2000),
+ timeout = ?sync:call(Q, fun() -> ok end, infinity, 1000).
+
+flush(_) ->
+ Q = make_ref(),
+ F = {timer, sleep, [2000]},
+ ok = cast(Q, F),
+ ok = cast(Q, F),
+ 1 = ?sync:flush(Q).
+
+%% ===========================================================================
+
+call(Q, Req) ->
+ sync(call, Q, Req).
+
+cast(Q, Req) ->
+ sync(cast, Q, Req).
+
+sync(F, Q, Req) ->
+ ?sync:F(Q, Req, infinity, infinity).
diff --git a/lib/diameter/test/diameter_sync_test.erl b/lib/diameter/test/diameter_sync_test.erl
deleted file mode 100644
index 618fa5021b..0000000000
--- a/lib/diameter/test/diameter_sync_test.erl
+++ /dev/null
@@ -1,104 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-%%----------------------------------------------------------------------
-%% Purpose: Verify the sync component of the Diameter application
-%%----------------------------------------------------------------------
-%%
--module(diameter_sync_test).
-
--export([
- init_per_testcase/2, fin_per_testcase/2,
-
- all/0,
- groups/0,
- init_per_suite/1, end_per_suite/1,
- suite_init/1, suite_fin/1,
- init_per_group/2, end_per_group/2
-
- %% foo/1
- ]).
-
--export([t/0, t/1]).
-
--include("diameter_test_lib.hrl").
-
-
-t() -> diameter_test_server:t(?MODULE).
-t(Case) -> diameter_test_server:t({?MODULE, Case}).
-
-
-%% Test server callbacks
-init_per_testcase(Case, Config) ->
- diameter_test_server:init_per_testcase(Case, Config).
-
-fin_per_testcase(Case, Config) ->
- diameter_test_server:fin_per_testcase(Case, Config).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-all() ->
- [].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-suite_init(X) -> init_per_suite(X).
-
-init_per_suite(suite) -> [];
-init_per_suite(doc) -> [];
-init_per_suite(Config) when is_list(Config) ->
- Config.
-
-
-suite_fin(X) -> end_per_suite(X).
-
-end_per_suite(suite) -> [];
-end_per_suite(doc) -> [];
-end_per_suite(Config) when is_list(Config) ->
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Test case example
-%%
-
-%% foo(suite) ->
-%% [];
-%% foo(doc) ->
-%% [];
-%% foo(Config) when is_list(Config) ->
-%% ok.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
diff --git a/lib/diameter/test/diameter_tcp_test.erl b/lib/diameter/test/diameter_tcp_test.erl
deleted file mode 100644
index b002a3d289..0000000000
--- a/lib/diameter/test/diameter_tcp_test.erl
+++ /dev/null
@@ -1,482 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-%%----------------------------------------------------------------------
-%% Purpose: Verify the tcp transport component of the Diameter application
-%%----------------------------------------------------------------------
-%%
--module(diameter_tcp_test).
-
--export([
- init_per_testcase/2, fin_per_testcase/2,
-
- all/0,
- groups/0,
- init_per_suite/1, end_per_suite/1,
- suite_init/1, suite_fin/1,
- init_per_group/2, end_per_group/2,
-
- start_and_stop_transport_plain/1,
- start_and_listen/1,
- simple_connect/1,
- simple_send_and_recv/1
-
- ]).
-
--export([t/0, t/1]).
-
-%% diameter_peer (internal) callback API
--export([up/1, up/3, recv/2]).
-
--include("diameter_test_lib.hrl").
--include_lib("diameter/include/diameter.hrl").
-%% -include_lib("diameter/src/tcp/diameter_tcp.hrl").
-
-
-t() -> diameter_test_server:t(?MODULE).
-t(Case) -> diameter_test_server:t({?MODULE, Case}).
-
-
-%% Test server callbacks
-init_per_testcase(Case, Config) ->
- diameter_test_server:init_per_testcase(Case, Config).
-
-fin_per_testcase(Case, Config) ->
- diameter_test_server:fin_per_testcase(Case, Config).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-all() ->
- [
- {group, start},
- {group, simple}
- ].
-
-groups() ->
- [
- {start, [], [start_and_stop_transport_plain, start_and_listen]},
- {simple, [], [simple_connect, simple_send_and_recv]}
- ].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-suite_init(X) -> init_per_suite(X).
-
-init_per_suite(suite) -> [];
-init_per_suite(doc) -> [];
-init_per_suite(Config) when is_list(Config) ->
- Config.
-
-
-suite_fin(X) -> end_per_suite(X).
-
-end_per_suite(suite) -> [];
-end_per_suite(doc) -> [];
-end_per_suite(Config) when is_list(Config) ->
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Test case(s)
-%%
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Plain start and stop of TCP transport
-%%
-
-start_and_stop_transport_plain(suite) ->
- [];
-start_and_stop_transport_plain(doc) ->
- [];
-start_and_stop_transport_plain(Config) when is_list(Config) ->
-
- ?SKIP(not_yet_implemented),
-
- %% This has been changed *a lot* since it was written...
-
- process_flag(trap_exit, true),
- Transport = ensure_transport_started(),
- TcpTransport = ensure_tcp_transport_started(),
- ensure_tcp_transport_stopped(TcpTransport),
- ensure_transport_stopped(Transport),
- i("done"),
- ok.
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Start TCP transport and then create a listen socket
-%%
-
-start_and_listen(suite) ->
- [];
-start_and_listen(doc) ->
- [];
-start_and_listen(Config) when is_list(Config) ->
-
- ?SKIP(not_yet_implemented),
-
- %% This has been changed *a lot* since it was written...
-
- process_flag(trap_exit, true),
- Transport = ensure_transport_started(),
- TcpTransport = ensure_tcp_transport_started(),
-
- case listen([{port, 0}]) of
- {ok, Acceptor} when is_pid(Acceptor) ->
- Ref = erlang:monitor(process, Acceptor),
- [{Acceptor, Info}] = diameter_tcp:which_listeners(),
- case lists:keysearch(socket, 1, Info) of
- {value, {_, Listen}} ->
- i("Listen socket: ~p"
- "~n Opts: ~p"
- "~n Stats: ~p"
- "~n Name: ~p",
- [Listen,
- ok(inet:getopts(Listen, [keepalive, delay_send])),
- ok(inet:getstat(Listen)),
- ok(inet:sockname(Listen))
- ]),
- ok;
- _ ->
- ?FAIL({bad_listener_info, Acceptor, Info})
- end,
- Crash = simulate_crash,
- exit(Acceptor, Crash),
- receive
- {'DOWN', Ref, process, Acceptor, Crash} ->
- ?SLEEP(1000),
- case diameter_tcp:which_listeners() of
- [{NewAcceptor, _NewInfo}] ->
- diameter_tcp_accept:stop(NewAcceptor),
- ?SLEEP(1000),
- case diameter_tcp:which_listeners() of
- [] ->
- ok;
- UnexpectedListeners ->
- ?FAIL({unexpected_listeners, empty, UnexpectedListeners})
- end;
- UnexpectedListeners ->
- ?FAIL({unexpected_listeners, non_empty, UnexpectedListeners})
- end
- after 5000 ->
- ?FAIL({failed_killing, Acceptor})
- end;
- Error ->
- ?FAIL({failed_creating_acceptor, Error})
- end,
- ensure_tcp_transport_stopped(TcpTransport),
- ensure_transport_stopped(Transport),
- i("done"),
- ok.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% TCP transport connecting
-%%
-
-simple_connect(suite) ->
- [];
-simple_connect(doc) ->
- [];
-simple_connect(Config) when is_list(Config) ->
-
- ?SKIP(not_yet_implemented),
-
- %% This has been changed *a lot* since it was written...
-
- process_flag(trap_exit, true),
- Transport = ensure_transport_started(),
- TcpTransport = ensure_tcp_transport_started(),
- {_Acceptor, Port} = ensure_tcp_listener(),
-
- {ok, Hostname} = inet:gethostname(),
-
- i("try connect"),
- Opts = [{host, Hostname}, {port, Port}, {module, ?MODULE}],
- Conn = case connect(Opts) of
- {ok, C} ->
- C;
- Error ->
- ?FAIL({failed_connecting, Error})
- end,
- i("connected: ~p", [Conn]),
-
- %% Up for connect
- receive
- {diameter, {up, Host, Port}} ->
- i("Received expected connect up (~p:~p)", [Host, Port]),
- ok
- after 5000 ->
- ?FAIL(connect_up_confirmation_timeout)
- end,
-
- %% Up for accept
- receive
- {diameter, {up, _ConnPid}} ->
- i("Received expected accept up"),
- ok
- after 5000 ->
- ?FAIL(acceptor_up_confirmation_timeout)
- end,
-
- i("try disconnect"),
- diameter_tcp:disconnect(Conn),
- ensure_tcp_transport_stopped(TcpTransport),
- ensure_transport_stopped(Transport),
- i("done"),
- ok.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Plain start and stop of TCP transport
-%%
-
-simple_send_and_recv(suite) ->
- [];
-simple_send_and_recv(doc) ->
- [];
-simple_send_and_recv(Config) when is_list(Config) ->
-
- ?SKIP(not_yet_implemented),
-
- %% This has been changed *a lot* since it was written...
-
- process_flag(trap_exit, true),
- %% --------------------------------------------------
- %% Start the TCP transport sub-system
- %%
-
- Transport = ensure_transport_started(),
- TcpTransport = ensure_tcp_transport_started(),
-
- {_Acceptor, Port} = ensure_tcp_listener(),
-
- {ok, Hostname} = inet:gethostname(),
-
- i("try connect"),
- Opts = [{host, Hostname}, {port, Port}, {module, ?MODULE}],
- Conn = case connect(Opts) of
- {ok, C1} ->
- C1;
- Error ->
- ?FAIL({failed_connecting, Error})
- end,
- i("connected: ~p", [Conn]),
-
- %% Up for connect
- receive
- {diameter, {up, Host, Port}} ->
- i("Received expected connect up (~p:~p)", [Host, Port]),
- ok
- after 5000 ->
- ?FAIL(connect_up_confirmation_timeout)
- end,
-
- %% Up for accept
- APid =
- receive
- {diameter, {up, C2}} ->
- i("Received expected accept up"),
- C2
- after 5000 ->
- ?FAIL(acceptor_up_confirmation_timeout)
- end,
-
- %% --------------------------------------------------
- %% Start some stuff needed for the codec to run
- %%
-
- i("start persistent table"),
- {ok, _Pers} = diameter_persistent_table:start_link(),
-
- i("start session"),
- {ok, _Session} = diameter_session:start_link(),
-
- i("try decode a (DWR) message"),
- Base = diameter_gen_base_rfc3588,
- DWR = ['DWR',
- {'Origin-Host', Hostname},
- {'Origin-Realm', "whatever-realm"},
- {'Origin-State-Id', [10]}],
-
- #diameter_packet{msg = Msg} = diameter_codec:encode(Base, DWR),
-
-
- %% --------------------------------------------------
- %% Now try to send the message
- %%
- %% This is not the codec-test suite, so we dont really care what we
- %% send, as long as it encoded/decodes correctly in the transport
- %%
-
- i("try send from connect side"),
- ok = diameter_tcp:send_message(Conn, Msg),
-
- %% Wait for data on Accept side
- APkt =
- receive
- {diameter, {recv, A}} ->
- i("[accept] Received expected data message: ~p", [A]),
- A
- after 5000 ->
- ?FAIL(acceptor_up_confirmation_timeout)
- end,
-
- %% Send the same message back, just to have something to send...
- i("try send (\"reply\") from accept side"),
- ok = diameter_tcp:send_message(APid, APkt),
-
- %% Wait for data on Connect side
- receive
- {diameter, {recv, B}} ->
- i("[connect] Received expected data message: ~p", [B]),
- ok
- after 5000 ->
- ?FAIL(acceptor_up_confirmation_timeout)
- end,
-
- i("we are done - now close shop"),
- diameter_session:stop(),
- diameter_persistent_table:stop(),
-
- ensure_tcp_transport_stopped(TcpTransport),
- ensure_transport_stopped(Transport),
- i("done"),
- ok.
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-ensure_transport_started() ->
-%% i("start diameter transport (top) supervisor"),
- case diameter_transport_sup:start_link() of
- {ok, TransportSup} ->
- TransportSup;
- Error ->
- ?FAIL({failed_starting_transport_sup, Error})
- end.
-
-ensure_transport_stopped(Pid) when is_pid(Pid) ->
-%% i("stop diameter transport (top) supervisor"),
- Stop = fun(P) -> exit(P, kill) end,
- ensure_stopped(Pid, Stop, failed_stopping_transport_sup).
-
-ensure_tcp_transport_started() ->
-%% i("start diameter TCP transport"),
- case diameter_tcp:start_transport() of
- {ok, TcpTransport} when is_pid(TcpTransport) ->
- TcpTransport;
- Error ->
- ?FAIL({failed_starting_transport, Error})
- end.
-
-ensure_tcp_transport_stopped(Pid) when is_pid(Pid) ->
-%% i("stop diameter TCP transport supervisor"),
- Stop = fun(P) -> diameter_tcp:stop_transport(P) end,
- ensure_stopped(Pid, Stop, failed_stopping_tcp_transport).
-
-
-ensure_tcp_listener() ->
-%% i("create diameter TCP transport listen socket"),
- case listen([{port, 0}]) of
- {ok, Acceptor} ->
- [{Acceptor, Info}] = diameter_tcp:which_listeners(),
- case lists:keysearch(socket, 1, Info) of
- {value, {_, Listen}} ->
- {ok, Port} = inet:port(Listen),
- {Acceptor, Port};
- _ ->
- ?FAIL({failed_retrieving_listen_socket, Info})
- end;
- Error ->
- ?FAIL({failed_creating_listen_socket, Error})
- end.
-
-
-ensure_stopped(Pid, Stop, ReasonTag) when is_pid(Pid) ->
-%% i("ensure_stopped -> create monitor to ~p", [Pid]),
- Ref = erlang:monitor(process, Pid),
-%% i("ensure_stopped -> try stop"),
- Stop(Pid),
-%% i("ensure_stopped -> await DOWN message"),
- receive
- {'DOWN', Ref, process, Pid, _} ->
-%% i("ensure_stopped -> received DOWN message"),
- ok
- after 5000 ->
-%% i("ensure_stopped -> timeout"),
- ?FAIL({ReasonTag, Pid})
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-listen(Opts) ->
- diameter_tcp:listen([{module, ?MODULE} | Opts]).
-
-connect(Opts) ->
- diameter_tcp:connect([{module, ?MODULE} | Opts]).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-up(Pid, Host, Port) ->
- Pid ! {diameter, {up, Host, Port}},
- ok.
-
-up(Pid) ->
- Pid ! {diameter, {up, self()}},
- ok.
-
-recv(Pid, Pkt) ->
- Pid ! {diameter, {recv, Pkt}}.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-i(F) ->
- i(F, []).
-
-i(F, A) ->
- io:format(F ++ "~n", A).
-
-
-ok({ok, Whatever}) ->
- Whatever;
-ok(Crap) ->
- Crap.
-
-
diff --git a/lib/diameter/test/diameter_test_lib.erl b/lib/diameter/test/diameter_test_lib.erl
deleted file mode 100644
index 3d46236526..0000000000
--- a/lib/diameter/test/diameter_test_lib.erl
+++ /dev/null
@@ -1,478 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-%%----------------------------------------------------------------------
-%% Purpose: Lightweight test server
-%%----------------------------------------------------------------------
-%%
-
--module(diameter_test_lib).
-
--export([
- sleep/1,
-
- hours/1,
- minutes/1,
- seconds/1,
-
- key1search/2,
-
- non_pc_tc_maybe_skip/4,
- os_based_skip/1,
-
- fail/3,
- skip/3,
- fatal_skip/3,
-
- log/4,
- error/3,
-
- flush/0,
-
- proxy_start/1, proxy_start/2,
- proxy_init/2,
-
- still_alive/1,
-
- prepare_test_case/5,
- lookup_config/2,
-
- mk_nodes/2, start_nodes/3,
-
- display_system_info/1, display_system_info/2, display_system_info/3,
- display_alloc_info/0,
- alloc_info/0,
-
- report_event/3
-
- ]).
-
--include("diameter_test_lib.hrl").
-
--record('REASON', {mod, line, desc}).
-
-
-%% ----------------------------------------------------------------
-%% Time related function
-%%
-
-sleep(infinity) ->
- receive
- after infinity ->
- ok
- end;
-sleep(MSecs) ->
- receive
- after trunc(MSecs) ->
- ok
- end,
- ok.
-
-
-hours(N) -> trunc(N * 1000 * 60 * 60).
-minutes(N) -> trunc(N * 1000 * 60).
-seconds(N) -> trunc(N * 1000).
-
-
-%% ----------------------------------------------------------------
-
-key1search(Key, L) ->
- case lists:keysearch(Key, 1, L) of
- undefined ->
- fail({not_found, Key, L}, ?MODULE, ?LINE);
- {value, {Key, Value}} ->
- Value
- end.
-
-
-%% ----------------------------------------------------------------
-%% Conditional skip of testcases
-%%
-
-non_pc_tc_maybe_skip(Config, Condition, File, Line)
- when is_list(Config) andalso is_function(Condition) ->
- %% Check if we shall skip the skip
- case os:getenv("TS_OS_BASED_SKIP") of
- "false" ->
- ok;
- _ ->
- case lists:keysearch(ts, 1, Config) of
- {value, {ts, megaco}} ->
- %% Always run the testcase if we are using our own
- %% test-server...
- ok;
- _ ->
- case (catch Condition()) of
- true ->
- skip(non_pc_testcase, File, Line);
- _ ->
- ok
- end
- end
- end.
-
-
-os_based_skip(any) ->
- true;
-os_based_skip(Skippable) when is_list(Skippable) ->
- {OsFam, OsName} =
- case os:type() of
- {_Fam, _Name} = FamAndName ->
- FamAndName;
- Fam ->
- {Fam, undefined}
- end,
- case lists:member(OsFam, Skippable) of
- true ->
- true;
- false ->
- case lists:keysearch(OsFam, 1, Skippable) of
- {value, {OsFam, OsName}} ->
- true;
- {value, {OsFam, OsNames}} when is_list(OsNames) ->
- lists:member(OsName, OsNames);
- _ ->
- false
- end
- end;
-os_based_skip(_) ->
- false.
-
-
-%%----------------------------------------------------------------------
-
-error(Actual, Mod, Line) ->
- global:send(megaco_global_logger, {failed, Mod, Line}),
- log("<ERROR> Bad result: ~p~n", [Actual], Mod, Line),
- Label = lists:concat([Mod, "(", Line, ") unexpected result"]),
- report_event(60, Label, [{line, Mod, Line}, {error, Actual}]),
- case global:whereis_name(megaco_test_case_sup) of
- undefined ->
- ignore;
- Pid ->
- Fail = #'REASON'{mod = Mod, line = Line, desc = Actual},
- Pid ! {fail, self(), Fail}
- end,
- Actual.
-
-log(Format, Args, Mod, Line) ->
- case global:whereis_name(megaco_global_logger) of
- undefined ->
- io:format(user, "~p~p(~p): " ++ Format,
- [self(), Mod, Line] ++ Args);
- Pid ->
- io:format(Pid, "~p~p(~p): " ++ Format,
- [self(), Mod, Line] ++ Args)
- end.
-
-skip(Actual, File, Line) ->
- log("Skipping test case~n", [], File, Line),
- String = lists:flatten(io_lib:format("Skipping test case ~p(~p): ~p~n",
- [File, Line, Actual])),
- exit({skipped, String}).
-
-fatal_skip(Actual, File, Line) ->
- error(Actual, File, Line),
- exit(shutdown).
-
-
-fail(Actual, File, Line) ->
- log("Test case failing~n", [], File, Line),
- String = lists:flatten(io_lib:format("Test case failing ~p (~p): ~p~n",
- [File, Line, Actual])),
- exit({suite_failed, String}).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Flush the message queue and return its messages
-
-flush() ->
- receive
- Msg ->
- [Msg | flush()]
- after 1000 ->
- []
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% The proxy process
-
-proxy_start(ProxyId) ->
- spawn_link(?MODULE, proxy_init, [ProxyId, self()]).
-
-proxy_start(Node, ProxyId) ->
- spawn_link(Node, ?MODULE, proxy_init, [ProxyId, self()]).
-
-proxy_init(ProxyId, Controller) ->
- process_flag(trap_exit, true),
- ?LOG("[~p] proxy started by ~p~n",[ProxyId, Controller]),
- proxy_loop(ProxyId, Controller).
-
-proxy_loop(OwnId, Controller) ->
- receive
- {'EXIT', Controller, Reason} ->
- p("proxy_loop -> received exit from controller"
- "~n Reason: ~p"
- "~n", [Reason]),
- exit(Reason);
- {apply, Fun} ->
- p("proxy_loop -> received apply request~n", []),
- Res = Fun(),
- p("proxy_loop -> apply result: "
- "~n ~p"
- "~n", [Res]),
- Controller ! {res, OwnId, Res},
- proxy_loop(OwnId, Controller);
- OtherMsg ->
- p("proxy_loop -> received unknown message: "
- "~n OtherMsg: ~p"
- "~n", [OtherMsg]),
- Controller ! {msg, OwnId, OtherMsg},
- proxy_loop(OwnId, Controller)
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Check if process is alive and kicking
-still_alive(Pid) ->
- case catch erlang:is_process_alive(Pid) of % New BIF in Erlang/OTP R5
- true ->
- true;
- false ->
- false;
- {'EXIT', _} -> % Pre R5 backward compatibility
- case process_info(Pid, message_queue_len) of
- undefined -> false;
- _ -> true
- end
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-mk_nodes(0, Nodes) ->
- Nodes;
-mk_nodes(N, []) ->
- mk_nodes(N - 1, [node()]);
-mk_nodes(N, Nodes) when N > 0 ->
- Head = hd(Nodes),
- [Name, Host] = node_to_name_and_host(Head),
- Nodes ++ [mk_node(I, Name, Host) || I <- lists:seq(1, N)].
-
-mk_node(N, Name, Host) ->
- list_to_atom(lists:concat([Name ++ integer_to_list(N) ++ "@" ++ Host])).
-
-%% Returns [Name, Host]
-node_to_name_and_host(Node) ->
- string:tokens(atom_to_list(Node), [$@]).
-
-start_nodes([Node | Nodes], File, Line) ->
- case net_adm:ping(Node) of
- pong ->
- start_nodes(Nodes, File, Line);
- pang ->
- [Name, Host] = node_to_name_and_host(Node),
- case slave:start_link(Host, Name) of
- {ok, NewNode} when NewNode =:= Node ->
- Path = code:get_path(),
- {ok, Cwd} = file:get_cwd(),
- true = rpc:call(Node, code, set_path, [Path]),
- ok = rpc:call(Node, file, set_cwd, [Cwd]),
- true = rpc:call(Node, code, set_path, [Path]),
- {_, []} = rpc:multicall(global, sync, []),
- start_nodes(Nodes, File, Line);
- Other ->
- fatal_skip({cannot_start_node, Node, Other}, File, Line)
- end
- end;
-start_nodes([], _File, _Line) ->
- ok.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-display_alloc_info() ->
- io:format("Allocator memory information:~n", []),
- AllocInfo = alloc_info(),
- display_alloc_info(AllocInfo).
-
-display_alloc_info([]) ->
- ok;
-display_alloc_info([{Alloc, Mem}|AllocInfo]) ->
- io:format(" ~15w: ~10w~n", [Alloc, Mem]),
- display_alloc_info(AllocInfo).
-
-alloc_info() ->
- case erlang:system_info(allocator) of
- {_Allocator, _Version, Features, _Settings} ->
- alloc_info(Features);
- _ ->
- []
- end.
-
-alloc_info(Allocators) ->
- Allocs = [temp_alloc, sl_alloc, std_alloc, ll_alloc, eheap_alloc,
- ets_alloc, binary_alloc, driver_alloc],
- alloc_info(Allocators, Allocs, []).
-
-alloc_info([], _, Acc) ->
- lists:reverse(Acc);
-alloc_info([Allocator | Allocators], Allocs, Acc) ->
- case lists:member(Allocator, Allocs) of
- true ->
- Instances0 = erlang:system_info({allocator, Allocator}),
- Instances =
- if
- is_list(Instances0) ->
- [Instance || Instance <- Instances0,
- element(1, Instance) =:= instance];
- true ->
- []
- end,
- AllocatorMem = alloc_mem_info(Instances),
- alloc_info(Allocators, Allocs, [{Allocator, AllocatorMem} | Acc]);
-
- false ->
- alloc_info(Allocators, Allocs, Acc)
- end.
-
-alloc_mem_info(Instances) ->
- alloc_mem_info(Instances, []).
-
-alloc_mem_info([], Acc) ->
- lists:sum([Mem || {instance, _, Mem} <- Acc]);
-alloc_mem_info([{instance, N, Info}|Instances], Acc) ->
- InstanceMemInfo = alloc_instance_mem_info(Info),
- alloc_mem_info(Instances, [{instance, N, InstanceMemInfo} | Acc]).
-
-alloc_instance_mem_info(InstanceInfo) ->
- MBCS = alloc_instance_mem_info(mbcs, InstanceInfo),
- SBCS = alloc_instance_mem_info(sbcs, InstanceInfo),
- MBCS + SBCS.
-
-alloc_instance_mem_info(Key, InstanceInfo) ->
- case lists:keysearch(Key, 1, InstanceInfo) of
- {value, {Key, Info}} ->
- case lists:keysearch(blocks_size, 1, Info) of
- {value, {blocks_size, Mem, _, _}} ->
- Mem;
- _ ->
- 0
- end;
- _ ->
- 0
- end.
-
-
-display_system_info(WhenStr) ->
- display_system_info(WhenStr, undefined, undefined).
-
-display_system_info(WhenStr, undefined, undefined) ->
- display_system_info(WhenStr, "");
-display_system_info(WhenStr, Mod, Func) ->
- ModFuncStr = lists:flatten(io_lib:format(" ~w:~w", [Mod, Func])),
- display_system_info(WhenStr, ModFuncStr).
-
-display_system_info(WhenStr, ModFuncStr) ->
- Fun = fun(F) -> case (catch F()) of
- {'EXIT', _} ->
- undefined;
- Res ->
- Res
- end
- end,
- ProcCount = Fun(fun() -> erlang:system_info(process_count) end),
- ProcLimit = Fun(fun() -> erlang:system_info(process_limit) end),
- ProcMemAlloc = Fun(fun() -> erlang:memory(processes) end),
- ProcMemUsed = Fun(fun() -> erlang:memory(processes_used) end),
- ProcMemBin = Fun(fun() -> erlang:memory(binary) end),
- ProcMemTot = Fun(fun() -> erlang:memory(total) end),
- %% error_logger:info_msg(
- io:format("~n"
- "~n*********************************************"
- "~n"
- "System info ~s~s => "
- "~n Process count: ~w"
- "~n Process limit: ~w"
- "~n Process memory alloc: ~w"
- "~n Process memory used: ~w"
- "~n Memory for binaries: ~w"
- "~n Memory total: ~w"
- "~n"
- "~n*********************************************"
- "~n"
- "~n", [WhenStr, ModFuncStr,
- ProcCount, ProcLimit, ProcMemAlloc, ProcMemUsed,
- ProcMemBin, ProcMemTot]),
- ok.
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-prepare_test_case(Actions, N, Config, File, Line) ->
- OrigNodes = lookup_config(nodes, Config),
- TestNodes = lookup_config(nodenames, Config), %% For testserver
- This = node(),
- SomeNodes = OrigNodes ++ (TestNodes -- OrigNodes),
- AllNodes = [This | (SomeNodes -- [This])],
- Nodes = pick_n_nodes(N, AllNodes, File, Line),
- start_nodes(Nodes, File, Line),
- do_prepare_test_case(Actions, Nodes, Config, File, Line).
-
-do_prepare_test_case([init | Actions], Nodes, Config, File, Line) ->
- process_flag(trap_exit, true),
- megaco_test_lib:flush(),
- do_prepare_test_case(Actions, Nodes, Config, File, Line);
-do_prepare_test_case([{stop_app, App} | Actions], Nodes, Config, File, Line) ->
- _Res = rpc:multicall(Nodes, application, stop, [App]),
- do_prepare_test_case(Actions, Nodes, Config, File, Line);
-do_prepare_test_case([], Nodes, _Config, _File, _Line) ->
- Nodes.
-
-pick_n_nodes(all, AllNodes, _File, _Line) ->
- AllNodes;
-pick_n_nodes(N, AllNodes, _File, _Line)
- when is_integer(N) andalso (length(AllNodes) >= N) ->
- AllNodes -- lists:nthtail(N, AllNodes);
-pick_n_nodes(N, AllNodes, File, Line) ->
- fatal_skip({too_few_nodes, N, AllNodes}, File, Line).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-lookup_config(Key, Config) ->
- case lists:keysearch(Key, 1, Config) of
- {value, {Key, Val}} ->
- Val;
- _ ->
- []
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-report_event(_Severity, _Label, _Content) ->
- %% diameter:report_event(Severity, Label, Content).
- hopefully_traced.
-
-
-p(F,A) ->
- io:format("~p" ++ F ++ "~n", [self()|A]).
diff --git a/lib/diameter/test/diameter_test_lib.hrl b/lib/diameter/test/diameter_test_lib.hrl
deleted file mode 100644
index 0b86f38de7..0000000000
--- a/lib/diameter/test/diameter_test_lib.hrl
+++ /dev/null
@@ -1,106 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-%%----------------------------------------------------------------------
-%% Purpose: Define common macros for testing
-%%----------------------------------------------------------------------
-%%
-
--define(FLUSH(), diameter_test_lib:flush()).
-
--define(SLEEP(MSEC), diameter_test_lib:sleep(MSEC)).
--define(M(), diameter_test_lib:millis()).
--define(MDIFF(A,B), diameter_test_lib:millis_diff(A,B)).
-
--define(HOURS(T), diameter_test_lib:hours(T)).
--define(MINUTES(T), diameter_test_lib:minutes(T)).
--define(SECONDS(T), diameter_test_lib:seconds(T)).
-
--define(KEY1SEARCH(Key, L), diameter_test_lib:key1search(Key, L)).
-
-
--define(APPLY(Proxy, Fun),
- Proxy ! {apply, Fun}).
-
--define(LOG(Format, Args),
- diameter_test_lib:log(Format, Args, ?MODULE, ?LINE)).
-
--define(ERROR(Reason),
- diameter_test_lib:error(Reason, ?MODULE, ?LINE)).
-
--define(OS_BASED_SKIP(Skippable),
- diameter_test_lib:os_based_skip(Skippable)).
-
--define(NON_PC_TC_MAYBE_SKIP(Config, Condition),
- diameter_test_lib:non_pc_tc_maybe_skip(Config, Condition, ?MODULE, ?LINE)).
-
--define(FAIL(Reason),
- diameter_test_lib:fail(Reason, ?MODULE, ?LINE)).
-
--define(SKIP(Reason),
- diameter_test_lib:skip(Reason, ?MODULE, ?LINE)).
-
--define(VERIFYL(Expected, Expr),
- fun(A,B) when list(A), list(B) ->
- A1 = lists:sort(A),
- B1 = lists:sort(B),
- case A1 of
- B1 -> ?LOG("Ok, ~p~n", [B]);
- _ -> ?ERROR(B)
- end,
- B;
- (A,A) ->
- ?LOG("Ok, ~p~n", [A]),
- A;
- (A,B) ->
- ?ERROR(B),
- B
- end(Expected, (catch Expr))).
-
--define(VERIFY(Expected, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- Expected -> ?LOG("Ok, ~p~n", [AcTuAlReS]);
- _ -> ?ERROR(AcTuAlReS)
- end,
- AcTuAlReS
- end()).
-
--define(RECEIVE(Expected),
- ?VERIFY(Expected, ?FLUSH())).
-
--define(MULTI_RECEIVE(Expected),
- ?VERIFY(lists:sort(Expected), lists:sort(?FLUSH()))).
-
--define(ACQUIRE_NODES(N, Config),
- diameter_test_lib:prepare_test_case([init, {stop_app, diameter}],
- N, Config, ?FILE, ?LINE)).
-
-
--define(REPORT_IMPORTANT(Label, Content), ?REPORT_EVENT(20, Label, Content)).
--define(REPORT_VERBOSE(Label, Content), ?REPORT_EVENT(40, Label, Content)).
--define(REPORT_DEBUG(Label, Content), ?REPORT_EVENT(60, Label, Content)).
--define(REPORT_TRACE(Label, Content), ?REPORT_EVENT(80, Label, Content)).
-
--define(REPORT_EVENT(Severity, Label, Content),
- diameter_test_lib:report_event(Severity, Label,
- [{line, ?MODULE, ?LINE} | Content])).
-
diff --git a/lib/diameter/test/diameter_test_server.erl b/lib/diameter/test/diameter_test_server.erl
deleted file mode 100644
index e2ff73fb8e..0000000000
--- a/lib/diameter/test/diameter_test_server.erl
+++ /dev/null
@@ -1,551 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-%%----------------------------------------------------------------------
-%% Purpose: Lightweight test server
-%%----------------------------------------------------------------------
-
--module(diameter_test_server).
-
--export([
- t/1, t/2,
-
- init_per_testcase/2,
- fin_per_testcase/2
- ]).
-
--include("diameter_test_lib.hrl").
-
-
--define(GLOGGER, diameter_global_logger).
-
-
-%% ----------------------------------------------------------------
-%%
-
-t([Case]) when is_atom(Case) ->
- t(Case);
-t(Case) ->
- process_flag(trap_exit, true),
- MEM = fun() -> case (catch erlang:memory()) of
- {'EXIT', _} ->
- [];
- Res ->
- Res
- end
- end,
- Alloc1 = diameter_test_lib:alloc_info(),
- Mem1 = MEM(),
- Res = lists:flatten(t(Case, default_config())),
- Alloc2 = diameter_test_lib:alloc_info(),
- Mem2 = MEM(),
- %% io:format("Res: ~p~n", [Res]),
- display_result(Res, Alloc1, Mem1, Alloc2, Mem2),
- Res.
-
-
-groups(Mod) when is_atom(Mod) ->
- try Mod:groups() of
- Groups when is_list(Groups) ->
- Groups;
- BadGroups ->
- exit({bad_groups, Mod, BadGroups})
- catch
- _:_ ->
- []
- end.
-
-init_suite(Mod, Config) ->
- io:format("~w:init_suite -> entry with"
- "~n Mod: ~p"
- "~n Config: ~p"
- "~n", [?MODULE, Mod, Config]),
- Mod:init_per_suite(Config).
-
-end_suite(Mod, Config) ->
- Mod:end_per_suite(Config).
-
-init_group(Mod, Group, Config) ->
- Mod:init_per_group(Group, Config).
-
-end_group(Mod, Group, Config) ->
- Mod:init_per_group(Group, Config).
-
-%% This is for sub-SUITEs
-t({_Mod, {NewMod, all}, _Groups}, _Config) when is_atom(NewMod) ->
- io:format("~w:t(all) -> entry with"
- "~n NewMod: ~p"
- "~n", [?MODULE, NewMod]),
- t(NewMod);
-t({Mod, {group, Name} = Group, Groups}, Config)
- when is_atom(Mod) andalso is_atom(Name) andalso is_list(Groups) ->
- io:format("~w:t(group) -> entry with"
- "~n Mod: ~p"
- "~n Name: ~p"
- "~n Groups: ~p"
- "~n Config: ~p"
- "~n", [?MODULE, Mod, Name, Groups, Config]),
- case lists:keysearch(Name, 1, Groups) of
- {value, {Name, _Props, GroupsAndCases}} ->
- try init_group(Mod, Name, Config) of
- Config2 when is_list(Config2) ->
- Res = [t({Mod, Case, Groups}, Config2) ||
- Case <- GroupsAndCases],
- (catch end_group(Mod, Name, Config2)),
- Res;
- Error ->
- io:format(" => group (~w) init failed: ~p~n",
- [Name, Error]),
- [{failed, {Mod, Group}, Error}]
- catch
- exit:{skipped, SkipReason} ->
- io:format(" => skipping group: ~p~n", [SkipReason]),
- [{skipped, {Mod, Group}, SkipReason, 0}];
- exit:{undef, _} ->
- [t({Mod, Case, Groups}, Config) ||
- Case <- GroupsAndCases];
- T:E ->
- [{failed, {Mod, Group}, {T,E}, 0}]
- end;
- false ->
- exit({unknown_group, Mod, Name, Groups})
- end;
-t({Mod, Fun, _}, Config)
- when is_atom(Mod) andalso is_atom(Fun) ->
- io:format("~w:t -> entry with"
- "~n Mod: ~p"
- "~n Fun: ~p"
- "~n Config: ~p"
- "~n", [?MODULE, Mod, Fun, Config]),
- case catch apply(Mod, Fun, [suite]) of
- [] ->
- io:format("Eval: ~p:", [{Mod, Fun}]),
- Res = eval(Mod, Fun, Config),
- {R, _, _, _} = Res,
- io:format(" ~p~n", [R]),
- Res;
-
- Cases when is_list(Cases) ->
- io:format("Expand: ~p ...~n", [{Mod, Fun}]),
- Map = fun(Case) when is_atom(Case) -> {Mod, Case};
- (Case) -> Case
- end,
- t(lists:map(Map, Cases), Config);
-
- {'EXIT', {undef, _}} ->
- io:format("Undefined: ~p~n", [{Mod, Fun}]),
- [{nyi, {Mod, Fun}, ok, 0}];
-
- Error ->
- io:format("Ignoring: ~p: ~p~n", [{Mod, Fun}, Error]),
- [{failed, {Mod, Fun}, Error, 0}]
- end;
-t(Mod, Config) when is_atom(Mod) ->
- io:format("~w:t -> entry with"
- "~n Mod: ~p"
- "~n Config: ~p"
- "~n", [?MODULE, Mod, Config]),
- %% This is assumed to be a test suite, so we start by calling
- %% the top test suite function(s) (all/0 and groups/0).
- case (catch Mod:all()) of
- Cases when is_list(Cases) ->
- %% The list may contain atoms (actual test cases) and
- %% group-tuples (a tuple naming a group of test cases).
- %% A group is defined by the (optional) groups/0 function.
- io:format("~w:t -> suite all ok"
- "~n Cases: ~p"
- "~n", [?MODULE, Cases]),
- Groups = groups(Mod),
- io:format("~w:t -> "
- "~n Groups: ~p"
- "~n", [?MODULE, Groups]),
- try init_suite(Mod, Config) of
- Config2 when is_list(Config2) ->
- io:format("~w:t -> suite init ok"
- "~n Config2: ~p"
- "~n", [?MODULE, Config2]),
- Res = [t({Mod, Case, Groups}, Config2) || Case <- Cases],
- (catch end_suite(Mod, Config2)),
- Res;
- Error ->
- io:format(" => suite init failed: ~p~n", [Error]),
- [{failed, {Mod, init_per_suite}, Error}]
- catch
- exit:{skipped, SkipReason} ->
- io:format(" => skipping suite: ~p~n", [SkipReason]),
- [{skipped, {Mod, init_per_suite}, SkipReason, 0}];
- exit:{undef, _} ->
- io:format("~w:t -> suite init failed. exit undef(1)~n", [?MODULE]),
- [t({Mod, Case, Groups}, Config) || Case <- Cases];
- exit:undef ->
- io:format("~w:t -> suite init failed. exit undef(2)~n", [?MODULE]),
- [t({Mod, Case, Groups}, Config) || Case <- Cases];
- T:E ->
- io:format("~w:t -> suite init failed. "
- "~n T: ~p"
- "~n E: ~p"
- "~n", [?MODULE, T,E]),
- [{failed, {Mod, init_per_suite}, {T,E}, 0}]
- end;
- {'EXIT', {undef, _}} ->
- io:format("Undefined: ~p~n", [{Mod, all}]),
- [{nyi, {Mod, all}, ok, 0}];
-
- Crap ->
- io:format("~w:t -> suite all failed: "
- "~n Crap: ~p"
- "~n", [?MODULE, Crap]),
- Crap
- end;
-t(Bad, _Config) ->
- io:format("~w:t -> entry with"
- "~n Bad: ~p"
- "~n", [?MODULE, Bad]),
- [{badarg, Bad, ok, 0}].
-
-eval(Mod, Fun, Config) ->
- TestCase = {?MODULE, Mod, Fun},
- Label = lists:concat(["TEST CASE: ", Fun]),
- ?REPORT_VERBOSE(Label ++ " started", [TestCase, Config]),
- global:register_name(diameter_test_case_sup, self()),
- Flag = process_flag(trap_exit, true),
- put(diameter_test_server, true),
- Config2 = Mod:init_per_testcase(Fun, Config),
- Self = self(),
- Pid = spawn_link(fun() -> do_eval(Self, Mod, Fun, Config2) end),
- R = wait_for_evaluator(Pid, Mod, Fun, Config2, []),
- Mod:fin_per_testcase(Fun, Config2),
- erase(diameter_test_server),
- global:unregister_name(diameter_test_case_sup),
- process_flag(trap_exit, Flag),
- R.
-
-wait_for_evaluator(Pid, Mod, Fun, Config, Errors) ->
- wait_for_evaluator(Pid, Mod, Fun, Config, Errors, 0).
-wait_for_evaluator(Pid, Mod, Fun, Config, Errors, AccTime) ->
- TestCase = {?MODULE, Mod, Fun},
- Label = lists:concat(["TEST CASE: ", Fun]),
- receive
- {done, Pid, ok, Time} when Errors =:= [] ->
- ?REPORT_VERBOSE(Label ++ " ok",
- [{test_case, TestCase}, {config, Config}]),
- {ok, {Mod, Fun}, Errors, Time};
- {done, Pid, ok, Time} ->
- ?REPORT_VERBOSE(Label ++ " failed",
- [{test_case, TestCase}, {config, Config}]),
- {failed, {Mod, Fun}, Errors, Time};
- {done, Pid, {ok, _}, Time} when Errors =:= [] ->
- ?REPORT_VERBOSE(Label ++ " ok",
- [{test_case, TestCase}, {config, Config}]),
- {ok, {Mod, Fun}, Errors, Time};
- {done, Pid, {ok, _}, Time} ->
- ?REPORT_VERBOSE(Label ++ " failed",
- [{test_case, TestCase}, {config, Config}]),
- {failed, {Mod, Fun}, Errors, Time};
- {done, Pid, Fail, Time} ->
- ?REPORT_IMPORTANT(Label ++ " failed",
- [{test_case, TestCase},
- {config, Config},
- {return, Fail},
- {errors, Errors}]),
- {failed, {Mod, Fun}, Fail, Time};
- {'EXIT', Pid, {skipped, Reason}, Time} ->
- ?REPORT_IMPORTANT(Label ++ " skipped",
- [{test_case, TestCase},
- {config, Config},
- {skipped, Reason}]),
- {skipped, {Mod, Fun}, Errors, Time};
- {'EXIT', Pid, Reason, Time} ->
- ?REPORT_IMPORTANT(Label ++ " crashed",
- [{test_case, TestCase},
- {config, Config},
- {'EXIT', Reason}]),
- {crashed, {Mod, Fun}, [{'EXIT', Reason} | Errors], Time};
- {fail, Pid, Reason, Time} ->
- wait_for_evaluator(Pid, Mod, Fun, Config,
- Errors ++ [Reason], AccTime + Time)
- end.
-
-do_eval(ReplyTo, Mod, Fun, Config) ->
- diameter_test_lib:display_system_info("before", Mod, Fun),
- case timer:tc(Mod, Fun, [Config]) of
- {Time, {'EXIT', {skipped, Reason}}} ->
- display_tc_time(Time),
- diameter_test_lib:display_system_info("after (skipped)", Mod, Fun),
- ReplyTo ! {'EXIT', self(), {skipped, Reason}, Time};
- {Time, {'EXIT', Reason}} ->
- display_tc_time(Time),
- diameter_test_lib:display_system_info("after (crashed)", Mod, Fun),
- ReplyTo ! {'EXIT', self(), Reason, Time};
- {Time, Other} ->
- display_tc_time(Time),
- diameter_test_lib:display_system_info("after", Mod, Fun),
- ReplyTo ! {done, self(), Other, Time}
- end,
- unlink(ReplyTo),
- exit(shutdown).
-
-
-display_tc_time(Time) ->
- io:format("~n"
- "~n*********************************************"
- "~n"
- "~nTest case completion time: ~.3f sec (~w)"
- "~n", [(Time / 1000000), Time]),
- ok.
-
-
-display_result(Res, Alloc1, Mem1, Alloc2, Mem2) ->
- io:format("~nAllocator info: ~n", []),
- display_alloc(Alloc1, Alloc2),
- io:format("~nMemory info: ~n", []),
- display_memory(Mem1, Mem2),
- display_result(Res).
-
-display_alloc([], []) ->
- io:format("-~n", []),
- ok;
-display_alloc(A1, A2) ->
- do_display_alloc(A1, A2).
-
-do_display_alloc([], _) ->
- ok;
-do_display_alloc([{Alloc, Mem1}|AllocInfo1], AllocInfo2) ->
- Mem2 =
- case lists:keysearch(Alloc, 1, AllocInfo2) of
- {value, {_, Val}} ->
- Val;
- false ->
- undefined
- end,
- io:format("~15w: ~10w -> ~w~n", [Alloc, Mem1, Mem2]),
- do_display_alloc(AllocInfo1, AllocInfo2).
-
-display_memory([], []) ->
- io:format("-~n", []),
- ok;
-display_memory(Mem1, Mem2) ->
- do_display_memory(Mem1, Mem2).
-
-
-do_display_memory([], _) ->
- ok;
-do_display_memory([{Key, Mem1}|MemInfo1], MemInfo2) ->
- Mem2 =
- case lists:keysearch(Key, 1, MemInfo2) of
- {value, {_, Val}} ->
- Val;
- false ->
- undefined
- end,
- io:format("~15w: ~10w -> ~w~n", [Key, Mem1, Mem2]),
- do_display_memory(MemInfo1, MemInfo2).
-
-display_result([]) ->
- io:format("OK~n", []);
-display_result(Res) when is_list(Res) ->
- Ok = [{MF, Time} || {ok, MF, _, Time} <- Res],
- Nyi = [MF || {nyi, MF, _, _Time} <- Res],
- Skipped = [{MF, Reason} || {skipped, MF, Reason, _Time} <- Res],
- Failed = [{MF, Reason} || {failed, MF, Reason, _Time} <- Res],
- Crashed = [{MF, Reason} || {crashed, MF, Reason, _Time} <- Res],
- display_summery(Ok, Nyi, Skipped, Failed, Crashed),
- display_ok(Ok),
- display_skipped(Skipped),
- display_failed(Failed),
- display_crashed(Crashed).
-
-display_summery(Ok, Nyi, Skipped, Failed, Crashed) ->
- io:format("~nTest case summery:~n", []),
- display_summery(Ok, "successfull"),
- display_summery(Nyi, "not yet implemented"),
- display_summery(Skipped, "skipped"),
- display_summery(Failed, "failed"),
- display_summery(Crashed, "crashed"),
- io:format("~n", []).
-
-display_summery(Res, Info) ->
- io:format(" ~w test cases ~s~n", [length(Res), Info]).
-
-display_ok([]) ->
- ok;
-display_ok(Ok) ->
- io:format("Ok test cases:~n", []),
- F = fun({{M, F}, Time}) ->
- io:format(" ~w : ~w => ~.2f sec~n", [M, F, Time / 1000000])
- end,
- lists:foreach(F, Ok),
- io:format("~n", []).
-
-display_skipped([]) ->
- ok;
-display_skipped(Skipped) ->
- io:format("Skipped test cases:~n", []),
- F = fun({MF, Reason}) -> io:format(" ~p => ~p~n", [MF, Reason]) end,
- lists:foreach(F, Skipped),
- io:format("~n", []).
-
-
-display_failed([]) ->
- ok;
-display_failed(Failed) ->
- io:format("Failed test cases:~n", []),
- F = fun({MF, Reason}) -> io:format(" ~p => ~p~n", [MF, Reason]) end,
- lists:foreach(F, Failed),
- io:format("~n", []).
-
-display_crashed([]) ->
- ok;
-display_crashed(Crashed) ->
- io:format("Crashed test cases:~n", []),
- F = fun({MF, Reason}) -> io:format(" ~p => ~p~n", [MF, Reason]) end,
- lists:foreach(F, Crashed),
- io:format("~n", []).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Test server callbacks
-init_per_testcase(_Case, Config) ->
- Pid = group_leader(),
- Name = ?GLOGGER,
- case global:whereis_name(Name) of
- undefined ->
- global:register_name(?GLOGGER, Pid);
- Pid ->
- io:format("~w:init_per_testcase -> "
- "already registered to ~p~n", [?MODULE, Pid]),
- ok;
- OtherPid when is_pid(OtherPid) ->
- io:format("~w:init_per_testcase -> "
- "already registered to other ~p (~p)~n",
- [?MODULE, OtherPid, Pid]),
- exit({already_registered, {?GLOGGER, OtherPid, Pid}})
- end,
- set_kill_timer(Config).
-
-fin_per_testcase(_Case, Config) ->
- Name = ?GLOGGER,
- case global:whereis_name(Name) of
- undefined ->
- io:format("~w:fin_per_testcase -> already un-registered~n",
- [?MODULE]),
- ok;
- Pid when is_pid(Pid) ->
- global:unregister_name(?GLOGGER),
- ok
- end,
- reset_kill_timer(Config).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Set kill timer
-
-set_kill_timer(Config) ->
- case init:get_argument(diameter_test_timeout) of
- {ok, _} ->
- Config;
- _ ->
- Time =
- case lookup_config(tc_timeout, Config) of
- [] ->
- timer:minutes(5);
- ConfigTime when is_integer(ConfigTime) ->
- ConfigTime
- end,
- Dog =
- case get(diameter_test_server) of
- true ->
- Self = self(),
- spawn_link(fun() -> watchdog(Self, Time) end);
- _ ->
- test_server:timetrap(Time)
- end,
- [{kill_timer, Dog}|Config]
-
-
- end.
-
-reset_kill_timer(Config) ->
- DogKiller =
- case get(diameter_test_server) of
- true ->
- fun(P) when is_pid(P) -> P ! stop;
- (_) -> ok
- end;
- _ ->
- fun(Ref) -> test_server:timetrap_cancel(Ref) end
- end,
- case lists:keysearch(kill_timer, 1, Config) of
- {value, {kill_timer, Dog}} ->
- DogKiller(Dog),
- lists:keydelete(kill_timer, 1, Config);
- _ ->
- Config
- end.
-
-watchdog(Pid, Time) ->
- erlang:now(),
- receive
- stop ->
- ok
- after Time ->
- case (catch process_info(Pid)) of
- undefined ->
- ok;
- Info ->
- ?LOG("<ERROR> Watchdog in test case timed out "
- "for ~p after ~p min"
- "~n~p"
- "~n",
- [Pid, Time div (1000*60), Info]),
- exit(Pid, kill)
- end
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-lookup_config(Key, Config) ->
- diameter_test_lib:lookup_config(Key, Config).
-
-default_config() ->
- [{nodes, default_nodes()}, {ts, diameter}].
-
-default_nodes() ->
- mk_nodes(2, []).
-
-mk_nodes(0, Nodes) ->
- Nodes;
-mk_nodes(N, []) ->
- mk_nodes(N - 1, [node()]);
-mk_nodes(N, Nodes) when N > 0 ->
- Head = hd(Nodes),
- [Name, Host] = node_to_name_and_host(Head),
- Nodes ++ [mk_node(I, Name, Host) || I <- lists:seq(1, N)].
-
-mk_node(N, Name, Host) ->
- list_to_atom(lists:concat([Name ++ integer_to_list(N) ++ "@" ++ Host])).
-
-%% Returns [Name, Host]
-node_to_name_and_host(Node) ->
- string:tokens(atom_to_list(Node), [$@]).
-
-
-
-
diff --git a/lib/diameter/test/diameter_tls_SUITE.erl b/lib/diameter/test/diameter_tls_SUITE.erl
new file mode 100644
index 0000000000..127e3435dc
--- /dev/null
+++ b/lib/diameter/test/diameter_tls_SUITE.erl
@@ -0,0 +1,406 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests of traffic between six Diameter nodes connected as follows.
+%%
+%% ---- SERVER.REALM1 (TLS after capabilities exchange)
+%% /
+%% / ---- SERVER.REALM2 (ditto)
+%% | /
+%% CLIENT.REALM0 ----- SERVER.REALM3 (no security)
+%% | \
+%% \ ---- SERVER.REALM4 (TLS at connection establishment)
+%% \
+%% ---- SERVER.REALM5 (ditto)
+%%
+
+-module(diameter_tls_SUITE).
+
+-export([suite/0,
+ all/0,
+ groups/0,
+ init_per_group/2,
+ end_per_group/2,
+ init_per_suite/1,
+ end_per_suite/1]).
+
+%% testcases
+-export([start_ssl/1,
+ start_diameter/1,
+ make_certs/1, make_certs/0,
+ start_services/1,
+ add_transports/1,
+ send1/1,
+ send2/1,
+ send3/1,
+ send4/1,
+ send5/1,
+ remove_transports/1,
+ stop_services/1,
+ stop_diameter/1,
+ stop_ssl/1]).
+
+%% diameter callbacks
+-export([peer_up/3,
+ peer_down/3,
+ pick_peer/4,
+ prepare_request/3,
+ prepare_retransmit/3,
+ handle_answer/4,
+ handle_error/4,
+ handle_request/3]).
+
+-include("diameter.hrl").
+-include("diameter_gen_base_rfc3588.hrl").
+-include("diameter_ct.hrl").
+
+%% ===========================================================================
+
+-define(util, diameter_util).
+
+-define(ADDR, {127,0,0,1}).
+
+-define(CLIENT, "CLIENT.REALM0").
+-define(SERVER1, "SERVER.REALM1").
+-define(SERVER2, "SERVER.REALM2").
+-define(SERVER3, "SERVER.REALM3").
+-define(SERVER4, "SERVER.REALM4").
+-define(SERVER5, "SERVER.REALM5").
+
+-define(SERVERS, [?SERVER1, ?SERVER2, ?SERVER3, ?SERVER4, ?SERVER5]).
+
+-define(DICT_COMMON, ?DIAMETER_DICT_COMMON).
+
+-define(APP_ALIAS, the_app).
+-define(APP_ID, ?DICT_COMMON:id()).
+
+-define(NO_INBAND_SECURITY, 0).
+-define(TLS, 1).
+
+%% Config for diameter:start_service/2.
+-define(SERVICE(Host, Dict),
+ [{'Origin-Host', Host},
+ {'Origin-Realm', realm(Host)},
+ {'Host-IP-Address', [?ADDR]},
+ {'Vendor-Id', 12345},
+ {'Product-Name', "OTP/diameter"},
+ {'Inband-Security-Id', [?NO_INBAND_SECURITY]},
+ {'Auth-Application-Id', [Dict:id()]},
+ {application, [{alias, ?APP_ALIAS},
+ {dictionary, Dict},
+ {module, ?MODULE},
+ {answer_errors, callback}]}]).
+
+%% Config for diameter:add_transport/2. In the listening case, listen
+%% on a free port that we then lookup using the implementation detail
+%% that diameter_tcp registers the port with diameter_reg.
+-define(CONNECT(PortNr, Caps, Opts),
+ {connect, [{transport_module, diameter_tcp},
+ {transport_config, [{raddr, ?ADDR},
+ {rport, PortNr},
+ {ip, ?ADDR},
+ {port, 0}
+ | Opts]},
+ {capabilities, Caps}]}).
+-define(LISTEN(Caps, Opts),
+ {listen, [{transport_module, diameter_tcp},
+ {transport_config, [{ip, ?ADDR}, {port, 0} | Opts]},
+ {capabilities, Caps}]}).
+
+-define(SUCCESS, 2001).
+-define(LOGOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_LOGOUT').
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 10}}].
+
+all() ->
+ [start_ssl,
+ start_diameter,
+ make_certs,
+ start_services,
+ add_transports]
+ ++ [{group, N} || {N, _, _} <- groups()]
+ ++ [remove_transports, stop_services, stop_diameter, stop_ssl].
+
+groups() ->
+ Ts = tc(),
+ [{all, [], Ts},
+ {p, [parallel], Ts}].
+
+init_per_group(_, Config) ->
+ Config.
+
+end_per_group(_, _) ->
+ ok.
+
+init_per_suite(Config) ->
+ case os:find_executable("openssl") of
+ false ->
+ {skip, no_openssl};
+ _ ->
+ Config
+ end.
+
+end_per_suite(_Config) ->
+ ok.
+
+%% Testcases to run when services are started and connections
+%% established.
+tc() ->
+ [send1,
+ send2,
+ send3,
+ send4,
+ send5].
+
+%% ===========================================================================
+%% testcases
+
+start_ssl(_Config) ->
+ ok = ssl:start().
+
+start_diameter(_Config) ->
+ ok = diameter:start().
+
+make_certs() ->
+ [{timetrap, {seconds, 30}}].
+
+make_certs(Config) ->
+ Dir = proplists:get_value(priv_dir, Config),
+
+ [] = ?util:run([[fun make_cert/2, Dir, B] || B <- ["server1",
+ "server2",
+ "server4",
+ "server5",
+ "client"]]).
+
+start_services(Config) ->
+ Dir = proplists:get_value(priv_dir, Config),
+ Servers = [server(S, sopts(S, Dir)) || S <- ?SERVERS],
+
+ ok = diameter:start_service(?CLIENT, ?SERVICE(?CLIENT, ?DICT_COMMON)),
+
+ {save_config, [Dir | Servers]}.
+
+add_transports(Config) ->
+ {_, [Dir | Servers]} = proplists:get_value(saved_config, Config),
+
+ true = diameter:subscribe(?CLIENT),
+
+ Opts = ssl_options(Dir, "client"),
+ Connections = [connect(?CLIENT, S, copts(N, Opts))
+ || {S,N} <- lists:zip(Servers, ?SERVERS)],
+
+ ?util:write_priv(Config, "cfg", lists:zip(Servers, Connections)).
+
+
+%% Remove the client transports and expect the corresponding server
+%% transport to go down.
+remove_transports(Config) ->
+ Ts = ?util:read_priv(Config, "cfg"),
+ [] = [T || S <- ?SERVERS, T <- [diameter:subscribe(S)], T /= true],
+ lists:map(fun disconnect/1, Ts).
+
+stop_services(_Config) ->
+ [] = [{H,T} || H <- [?CLIENT | ?SERVERS],
+ T <- [diameter:stop_service(H)],
+ T /= ok].
+
+stop_diameter(_Config) ->
+ ok = diameter:stop().
+
+stop_ssl(_Config) ->
+ ok = ssl:stop().
+
+%% Send an STR intended for a specific server and expect success.
+send1(_Config) ->
+ call(?SERVER1).
+send2(_Config) ->
+ call(?SERVER2).
+send3(_Config) ->
+ call(?SERVER3).
+send4(_Config) ->
+ call(?SERVER4).
+send5(_Config) ->
+ call(?SERVER5).
+
+%% ===========================================================================
+%% diameter callbacks
+
+%% peer_up/3
+
+peer_up(_SvcName, _Peer, State) ->
+ State.
+
+%% peer_down/3
+
+peer_down(_SvcName, _Peer, State) ->
+ State.
+
+%% pick_peer/4
+
+pick_peer([Peer], _, ?CLIENT, _State) ->
+ {ok, Peer}.
+
+%% prepare_request/3
+
+prepare_request(#diameter_packet{msg = Req},
+ ?CLIENT,
+ {_Ref, Caps}) ->
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, _}}
+ = Caps,
+
+ {send, set(Req, [{'Session-Id', diameter:session_id(OH)},
+ {'Origin-Host', OH},
+ {'Origin-Realm', OR}])}.
+
+%% prepare_retransmit/3
+
+prepare_retransmit(_Pkt, false, _Peer) ->
+ discard.
+
+%% handle_answer/4
+
+handle_answer(Pkt, _Req, ?CLIENT, _Peer) ->
+ #diameter_packet{msg = Rec, errors = []} = Pkt,
+ Rec.
+
+%% handle_error/4
+
+handle_error(Reason, _Req, ?CLIENT, _Peer) ->
+ {error, Reason}.
+
+%% handle_request/3
+
+handle_request(#diameter_packet{msg = #diameter_base_STR{'Session-Id' = SId}},
+ OH,
+ {_Ref, #diameter_caps{origin_host = {OH,_},
+ origin_realm = {OR, _}}})
+ when OH /= ?CLIENT ->
+ {reply, #diameter_base_STA{'Result-Code' = ?SUCCESS,
+ 'Session-Id' = SId,
+ 'Origin-Host' = OH,
+ 'Origin-Realm' = OR}}.
+
+%% ===========================================================================
+%% support functions
+
+call(Server) ->
+ Realm = realm(Server),
+ Req = ['STR', {'Destination-Realm', Realm},
+ {'Termination-Cause', ?LOGOUT},
+ {'Auth-Application-Id', ?APP_ID}],
+ #diameter_base_STA{'Result-Code' = ?SUCCESS,
+ 'Origin-Host' = Server,
+ 'Origin-Realm' = Realm}
+ = call(Req, [{filter, realm}]).
+
+call(Req, Opts) ->
+ diameter:call(?CLIENT, ?APP_ALIAS, Req, Opts).
+
+set([H|T], Vs) ->
+ [H | Vs ++ T].
+
+disconnect({{LRef, _PortNr}, CRef}) ->
+ ok = diameter:remove_transport(?CLIENT, CRef),
+ ok = receive #diameter_event{info = {down, LRef, _, _}} -> ok
+ after 2000 -> false
+ end.
+
+realm(Host) ->
+ tl(lists:dropwhile(fun(C) -> C /= $. end, Host)).
+
+inband_security(Ids) ->
+ [{'Inband-Security-Id', Ids}].
+
+ssl_options(Dir, Base) ->
+ Root = filename:join([Dir, Base]),
+ [{ssl_options, [{certfile, Root ++ "_ca.pem"},
+ {keyfile, Root ++ "_key.pem"}]}].
+
+make_cert(Dir, Base) ->
+ make_cert(Dir, Base ++ "_key.pem", Base ++ "_ca.pem").
+
+make_cert(Dir, Keyfile, Certfile) ->
+ [K,C] = Paths = [filename:join([Dir, F]) || F <- [Keyfile, Certfile]],
+
+ KCmd = join(["openssl genrsa -out", K, "2048"]),
+ CCmd = join(["openssl req -new -x509 -key", K, "-out", C, "-days 7",
+ "-subj /C=SE/ST=./L=Stockholm/CN=www.erlang.org"]),
+
+ %% Hope for the best and only check that files are written.
+ os:cmd(KCmd),
+ os:cmd(CCmd),
+
+ [_,_] = [T || P <- Paths, {ok, T} <- [file:read_file_info(P)]],
+
+ {K,C}.
+
+join(Strs) ->
+ string:join(Strs, " ").
+
+%% server/2
+
+server(Host, {Caps, Opts}) ->
+ ok = diameter:start_service(Host, ?SERVICE(Host, ?DICT_COMMON)),
+ {ok, LRef} = diameter:add_transport(Host, ?LISTEN(Caps, Opts)),
+ {LRef, hd([_] = ?util:lport(tcp, LRef, 20))}.
+
+sopts(?SERVER1, Dir) ->
+ {inband_security([?TLS]),
+ ssl_options(Dir, "server1")};
+sopts(?SERVER2, Dir) ->
+ {inband_security([?NO_INBAND_SECURITY, ?TLS]),
+ ssl_options(Dir, "server2")};
+sopts(?SERVER3, _) ->
+ {[], []};
+sopts(?SERVER4, Dir) ->
+ {[], ssl(ssl_options(Dir, "server4"))};
+sopts(?SERVER5, Dir) ->
+ {[], ssl(ssl_options(Dir, "server5"))}.
+
+ssl([{ssl_options = T, Opts}]) ->
+ [{T, true} | Opts].
+
+%% connect/3
+
+connect(Host, {_LRef, PortNr}, {Caps, Opts}) ->
+ {ok, Ref} = diameter:add_transport(Host, ?CONNECT(PortNr, Caps, Opts)),
+ ok = receive
+ #diameter_event{service = Host,
+ info = {up, Ref, _, _, #diameter_packet{}}} ->
+ ok
+ after 2000 ->
+ false
+ end,
+ Ref.
+
+copts(S, Opts)
+ when S == ?SERVER1;
+ S == ?SERVER2;
+ S == ?SERVER3 ->
+ {inband_security([?NO_INBAND_SECURITY, ?TLS]), Opts};
+copts(S, Opts)
+ when S == ?SERVER4;
+ S == ?SERVER5 ->
+ {[], ssl(Opts)}.
diff --git a/lib/ssl/c_src/Makefile b/lib/diameter/test/diameter_tls_SUITE_data/Makefile.ca
index 52d9140153..3f2645add0 100644
--- a/lib/ssl/c_src/Makefile
+++ b/lib/diameter/test/diameter_tls_SUITE_data/Makefile.ca
@@ -1,26 +1,43 @@
-#
+# -*- makefile -*-
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2009. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 2011. All Rights Reserved.
+#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
# compliance with the License. You should have received a copy of the
# Erlang Public License along with this software. If not, it can be
# retrieved online at http://www.erlang.org/.
-#
+#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
# the License for the specific language governing rights and limitations
# under the License.
-#
-# %CopyrightEnd%
-#
-
#
+# %CopyrightEnd%
#
-# Invoke with GNU make or clearmake -C gnu.
+# Certificates are now generated from the suite itself but the
+# makefile itself is still useful.
#
-include $(ERL_TOP)/make/run_make.mk
+KEYS = $(HOSTS:%=%_key.pem)
+CERTS = $(HOSTS:%=%_ca.pem)
+
+all: $(CERTS)
+
+%_ca.pem: %_key.pem
+ openssl req -new -x509 -key $< -out $@ -days 1095 \
+ -subj '/C=SE/ST=./L=Stockholm/CN=www.erlang.org'
+
+%_key.pem:
+ openssl genrsa -out $@ 2048
+
+clean:
+ rm -f $(CERTS)
+
+realclean: clean
+ rm -f $(KEYS)
+
+.PRECIOUS: $(KEYS)
+.PHONY: all clean realclean
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
new file mode 100644
index 0000000000..55c5fc7c54
--- /dev/null
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -0,0 +1,753 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests of traffic between two Diameter nodes, one client, one server.
+%%
+
+-module(diameter_traffic_SUITE).
+
+-export([suite/0,
+ all/0,
+ groups/0,
+ init_per_group/2,
+ end_per_group/2,
+ init_per_testcase/2,
+ end_per_testcase/2]).
+
+%% testcases
+-export([start/1,
+ start_services/1,
+ add_transports/1,
+ result_codes/1,
+ send_ok/1,
+ send_arbitrary/1,
+ send_unknown/1,
+ send_unknown_mandatory/1,
+ send_noreply/1,
+ send_unsupported/1,
+ send_unsupported_app/1,
+ send_error_bit/1,
+ send_unsupported_version/1,
+ send_long/1,
+ send_nopeer/1,
+ send_noapp/1,
+ send_discard/1,
+ send_any_1/1,
+ send_any_2/1,
+ send_all_1/1,
+ send_all_2/1,
+ send_timeout/1,
+ send_error/1,
+ send_detach/1,
+ send_encode_error/1,
+ send_destination_1/1,
+ send_destination_2/1,
+ send_destination_3/1,
+ send_destination_4/1,
+ send_destination_5/1,
+ send_destination_6/1,
+ send_bad_option_1/1,
+ send_bad_option_2/1,
+ send_bad_filter_1/1,
+ send_bad_filter_2/1,
+ send_bad_filter_3/1,
+ send_bad_filter_4/1,
+ send_multiple_filters_1/1,
+ send_multiple_filters_2/1,
+ send_multiple_filters_3/1,
+ send_anything/1,
+ remove_transports/1,
+ stop_services/1,
+ stop/1]).
+
+%% diameter callbacks
+-export([peer_up/3,
+ peer_down/3,
+ pick_peer/5, pick_peer/6,
+ prepare_request/4, prepare_request/5,
+ prepare_retransmit/4,
+ handle_answer/5, handle_answer/6,
+ handle_error/5,
+ handle_request/3]).
+
+-include("diameter.hrl").
+-include("diameter_gen_base_rfc3588.hrl").
+-include("diameter_ct.hrl").
+
+%% ===========================================================================
+
+-define(util, diameter_util).
+
+-define(ADDR, {127,0,0,1}).
+
+-define(CLIENT, "CLIENT").
+-define(SERVER, "SERVER").
+-define(REALM, "erlang.org").
+-define(HOST(Host, Realm), Host ++ [$.|Realm]).
+
+-define(APP_ALIAS, base).
+-define(EXTRA, an_extra_argument).
+-define(ENCODINGS, [list, record]).
+
+-define(DICT, ?DIAMETER_DICT_COMMON).
+-define(APP_ID, ?DIAMETER_APP_ID_COMMON).
+
+%% Config for diameter:start_service/2.
+-define(SERVICE(Name),
+ [{'Origin-Host', Name ++ "." ++ ?REALM},
+ {'Origin-Realm', ?REALM},
+ {'Host-IP-Address', [?ADDR]},
+ {'Vendor-Id', 12345},
+ {'Product-Name', "OTP/diameter"},
+ {'Acct-Application-Id', [?DIAMETER_APP_ID_COMMON]},
+ {application, [{alias, ?APP_ALIAS},
+ {dictionary, ?DIAMETER_DICT_COMMON},
+ {module, ?MODULE},
+ {answer_errors, callback}]}]).
+
+-define(SUCCESS,
+ ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_SUCCESS').
+-define(COMMAND_UNSUPPORTED,
+ ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_COMMAND_UNSUPPORTED').
+-define(TOO_BUSY,
+ ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_TOO_BUSY').
+-define(APPLICATION_UNSUPPORTED,
+ ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_APPLICATION_UNSUPPORTED').
+-define(INVALID_HDR_BITS,
+ ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_INVALID_HDR_BITS').
+-define(AVP_UNSUPPORTED,
+ ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_AVP_UNSUPPORTED').
+-define(UNSUPPORTED_VERSION,
+ ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_UNSUPPORTED_VERSION').
+-define(REALM_NOT_SERVED,
+ ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_REALM_NOT_SERVED').
+-define(UNABLE_TO_DELIVER,
+ ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_UNABLE_TO_DELIVER').
+
+-define(EVENT_RECORD,
+ ?'DIAMETER_BASE_ACCOUNTING-RECORD-TYPE_EVENT_RECORD').
+-define(AUTHORIZE_ONLY,
+ ?'DIAMETER_BASE_RE-AUTH-REQUEST-TYPE_AUTHORIZE_ONLY').
+-define(AUTHORIZE_AUTHENTICATE,
+ ?'DIAMETER_BASE_RE-AUTH-REQUEST-TYPE_AUTHORIZE_AUTHENTICATE').
+
+-define(LOGOUT,
+ ?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_LOGOUT').
+-define(BAD_ANSWER,
+ ?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_BAD_ANSWER').
+
+-define(A, list_to_atom).
+-define(L, atom_to_list).
+-define(P(N), ?A("p_" ++ ?L(N))).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 10}}].
+
+all() ->
+ [start, start_services, add_transports, result_codes
+ | [{group, N} || {N, _, _} <- groups()]]
+ ++ [remove_transports, stop_services, stop].
+
+groups() ->
+ Ts = tc(),
+ [{grp(E,P), P, Ts} || E <- ?ENCODINGS, P <- [[], [parallel]]].
+
+grp(E, []) ->
+ E;
+grp(E, [parallel]) ->
+ ?P(E).
+
+init_per_group(Name, Config) ->
+ E = case ?L(Name) of
+ "p_" ++ Rest ->
+ ?A(Rest);
+ _ ->
+ Name
+ end,
+ [{encode, E} | Config].
+
+end_per_group(_, _) ->
+ ok.
+
+init_per_testcase(Name, Config) ->
+ [{testcase, Name} | Config].
+
+end_per_testcase(_, _) ->
+ ok.
+
+%% Testcases to run when services are started and connections
+%% established.
+tc() ->
+ [send_ok,
+ send_arbitrary,
+ send_unknown,
+ send_unknown_mandatory,
+ send_noreply,
+ send_unsupported,
+ send_unsupported_app,
+ send_error_bit,
+ send_unsupported_version,
+ send_long,
+ send_nopeer,
+ send_noapp,
+ send_discard,
+ send_any_1,
+ send_any_2,
+ send_all_1,
+ send_all_2,
+ send_timeout,
+ send_error,
+ send_detach,
+ send_encode_error,
+ send_destination_1,
+ send_destination_2,
+ send_destination_3,
+ send_destination_4,
+ send_destination_5,
+ send_destination_6,
+ send_bad_option_1,
+ send_bad_option_2,
+ send_bad_filter_1,
+ send_bad_filter_2,
+ send_bad_filter_3,
+ send_bad_filter_4,
+ send_multiple_filters_1,
+ send_multiple_filters_2,
+ send_multiple_filters_3,
+ send_anything].
+
+%% ===========================================================================
+%% start/stop testcases
+
+start(_Config) ->
+ ok = diameter:start().
+
+start_services(_Config) ->
+ ok = diameter:start_service(?SERVER, ?SERVICE(?SERVER)),
+ ok = diameter:start_service(?CLIENT, ?SERVICE(?CLIENT)).
+
+add_transports(Config) ->
+ LRef = ?util:listen(?SERVER, tcp, [{capabilities_cb, fun capx/2}]),
+ CRef = ?util:connect(?CLIENT, tcp, LRef),
+ ?util:write_priv(Config, "transport", {LRef, CRef}).
+
+remove_transports(Config) ->
+ {LRef, CRef} = ?util:read_priv(Config, "transport"),
+ ?util:disconnect(?CLIENT, CRef, ?SERVER, LRef).
+
+stop_services(_Config) ->
+ ok = diameter:stop_service(?CLIENT),
+ ok = diameter:stop_service(?SERVER).
+
+stop(_Config) ->
+ ok = diameter:stop().
+
+capx(_, #diameter_caps{origin_host = {OH,DH}}) ->
+ io:format("connection: ~p -> ~p~n", [DH,OH]),
+ ok.
+
+%% ===========================================================================
+
+%% Ensure that result codes have the expected values.
+result_codes(_Config) ->
+ {2001, 3001, 3002, 3003, 3004, 3007, 3008, 5001, 5011}
+ = {?SUCCESS,
+ ?COMMAND_UNSUPPORTED,
+ ?UNABLE_TO_DELIVER,
+ ?REALM_NOT_SERVED,
+ ?TOO_BUSY,
+ ?APPLICATION_UNSUPPORTED,
+ ?INVALID_HDR_BITS,
+ ?AVP_UNSUPPORTED,
+ ?UNSUPPORTED_VERSION}.
+
+%% Send an ACR and expect success.
+send_ok(Config) ->
+ Req = ['ACR', {'Accounting-Record-Type', ?EVENT_RECORD},
+ {'Accounting-Record-Number', 1}],
+ #diameter_base_ACA{'Result-Code' = ?SUCCESS}
+ = call(Config, Req).
+
+%% Send an ASR with an arbitrary AVP and expect success and the same
+%% AVP in the reply.
+send_arbitrary(Config) ->
+ Req = ['ASR', {'AVP', [#diameter_avp{name = 'Class', value = "XXX"}]}],
+ #diameter_base_ASA{'Result-Code' = ?SUCCESS,
+ 'AVP' = Avps}
+ = call(Config, Req),
+ [#diameter_avp{name = 'Class',
+ value = "XXX"}]
+ = Avps.
+
+%% Send an unknown AVP (to some client) and check that it comes back.
+send_unknown(Config) ->
+ Req = ['ASR', {'AVP', [#diameter_avp{code = 999,
+ is_mandatory = false,
+ data = <<17>>}]}],
+ #diameter_base_ASA{'Result-Code' = ?SUCCESS,
+ 'AVP' = Avps}
+ = call(Config, Req),
+ [#diameter_avp{code = 999,
+ is_mandatory = false,
+ data = <<17>>}]
+ = Avps.
+
+%% Ditto but set the M flag.
+send_unknown_mandatory(Config) ->
+ Req = ['ASR', {'AVP', [#diameter_avp{code = 999,
+ is_mandatory = true,
+ data = <<17>>}]}],
+ #diameter_base_ASA{'Result-Code' = ?AVP_UNSUPPORTED,
+ 'Failed-AVP' = Failed}
+ = call(Config, Req),
+ [#'diameter_base_Failed-AVP'{'AVP' = Avps}] = Failed,
+ [#diameter_avp{code = 999,
+ is_mandatory = true,
+ data = <<17>>}]
+ = Avps.
+
+%% Send an STR that the server ignores.
+send_noreply(Config) ->
+ Req = ['STR', {'Termination-Cause', ?BAD_ANSWER}],
+ {error, timeout} = call(Config, Req).
+
+%% Send an unsupported command and expect 3001.
+send_unsupported(Config) ->
+ Req = ['STR', {'Termination-Cause', ?BAD_ANSWER}],
+ #'diameter_base_answer-message'{'Result-Code' = ?COMMAND_UNSUPPORTED}
+ = call(Config, Req).
+
+%% Send an unsupported command and expect 3007.
+send_unsupported_app(Config) ->
+ Req = ['STR', {'Termination-Cause', ?BAD_ANSWER}],
+ #'diameter_base_answer-message'{'Result-Code' = ?APPLICATION_UNSUPPORTED}
+ = call(Config, Req).
+
+%% Send a request with the E bit set and expect 3008.
+send_error_bit(Config) ->
+ Req = ['STR', {'Termination-Cause', ?BAD_ANSWER}],
+ #'diameter_base_answer-message'{'Result-Code' = ?INVALID_HDR_BITS}
+ = call(Config, Req).
+
+%% Send a bad version and check that we get 5011.
+send_unsupported_version(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+ #diameter_base_STA{'Result-Code' = ?UNSUPPORTED_VERSION}
+ = call(Config, Req).
+
+%% Send something long that will be fragmented by TCP.
+send_long(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT},
+ {'User-Name', [lists:duplicate(1 bsl 20, $X)]}],
+ #diameter_base_STA{'Result-Code' = ?SUCCESS}
+ = call(Config, Req).
+
+%% Send something for which pick_peer finds no suitable peer.
+send_nopeer(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+ {error, no_connection} = call(Config, Req, [{extra, [?EXTRA]}]).
+
+%% Send something on an unconfigured application.
+send_noapp(_Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+ {error, no_connection} = diameter:call(?CLIENT, unknown_alias, Req).
+
+%% Send something that's discarded by prepare_request.
+send_discard(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+ {error, unprepared} = call(Config, Req).
+
+%% Send with a disjunctive filter.
+send_any_1(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+ {error, no_connection} = call(Config, Req, [{filter, {any, []}}]).
+send_any_2(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT},
+ {'Destination-Host', [?HOST(?SERVER, "unknown.org")]}],
+ #'diameter_base_answer-message'{'Result-Code' = ?UNABLE_TO_DELIVER}
+ = call(Config, Req, [{filter, {any, [host, realm]}}]).
+
+%% Send with a conjunctive filter.
+send_all_1(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+ Realm = lists:foldr(fun(C,A) -> [C,A] end, [], ?REALM),
+ #diameter_base_STA{'Result-Code' = ?SUCCESS}
+ = call(Config, Req, [{filter, {all, [{host, any},
+ {realm, Realm}]}}]).
+send_all_2(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT},
+ {'Destination-Host', [?HOST(?SERVER, "unknown.org")]}],
+ {error, no_connection}
+ = call(Config, Req, [{filter, {all, [host, realm]}}]).
+
+%% Timeout before the server manages an answer.
+send_timeout(Config) ->
+ Req = ['RAR', {'Re-Auth-Request-Type', ?AUTHORIZE_ONLY}],
+ {error, timeout} = call(Config, Req, [{timeout, 1000}]).
+
+%% Explicitly answer with an answer-message and ensure that we
+%% received the Session-Id.
+send_error(Config) ->
+ Req = ['RAR', {'Re-Auth-Request-Type', ?AUTHORIZE_AUTHENTICATE}],
+ #'diameter_base_answer-message'{'Result-Code' = ?TOO_BUSY,
+ 'Session-Id' = SId}
+ = call(Config, Req),
+ undefined /= SId.
+
+%% Send a request with the detached option and receive it as a message
+%% from handle_answer instead.
+send_detach(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+ Ref = make_ref(),
+ ok = call(Config, Req, [{extra, [{self(), Ref}]}, detach]),
+ #diameter_packet{msg = Rec, errors = []}
+ = receive {Ref, T} -> T after 2000 -> false end,
+ #diameter_base_STA{'Result-Code' = ?SUCCESS}
+ = Rec.
+
+%% Send a request which can't be encoded and expect {error, encode}.
+send_encode_error(Config) ->
+ {error, encode} = call(Config, ['STR']). %% No Termination-Cause
+
+%% Send with filtering and expect success.
+send_destination_1(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT},
+ {'Destination-Host', [?HOST(?SERVER, ?REALM)]}],
+ #diameter_base_STA{'Result-Code' = ?SUCCESS}
+ = call(Config, Req, [{filter, {all, [host, realm]}}]).
+send_destination_2(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+ #diameter_base_STA{'Result-Code' = ?SUCCESS}
+ = call(Config, Req, [{filter, {all, [host, realm]}}]).
+
+%% Send with filtering on and expect failure when specifying an
+%% unknown host or realm.
+send_destination_3(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT},
+ {'Destination-Realm', "unknown.org"}],
+ {error, no_connection}
+ = call(Config, Req, [{filter, {all, [host, realm]}}]).
+send_destination_4(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT},
+ {'Destination-Host', [?HOST(?SERVER, "unknown.org")]}],
+ {error, no_connection}
+ = call(Config, Req, [{filter, {all, [host, realm]}}]).
+
+%% Send without filtering and expect an error answer when specifying
+%% an unknown host or realm.
+send_destination_5(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT},
+ {'Destination-Realm', "unknown.org"}],
+ #'diameter_base_answer-message'{'Result-Code' = ?REALM_NOT_SERVED}
+ = call(Config, Req).
+send_destination_6(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT},
+ {'Destination-Host', [?HOST(?SERVER, "unknown.org")]}],
+ #'diameter_base_answer-message'{'Result-Code' = ?UNABLE_TO_DELIVER}
+ = call(Config, Req).
+
+%% Specify an invalid option and expect failure.
+send_bad_option_1(Config) ->
+ send_bad_option(Config, x).
+send_bad_option_2(Config) ->
+ send_bad_option(Config, {extra, false}).
+
+send_bad_option(Config, Opt) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+ try call(Config, Req, [Opt]) of
+ T -> erlang:error({?MODULE, ?LINE, T})
+ catch
+ error: _ -> ok
+ end.
+
+%% Specify an invalid filter and expect no matching peers.
+send_bad_filter_1(Config) ->
+ send_bad_filter(Config, {all, none}).
+send_bad_filter_2(Config) ->
+ send_bad_filter(Config, {host, x}).
+send_bad_filter_3(Config) ->
+ send_bad_filter(Config, {eval, fun() -> true end}).
+send_bad_filter_4(Config) ->
+ send_bad_filter(Config, {eval, {?MODULE, not_exported, []}}).
+
+send_bad_filter(Config, F) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+ {error, no_connection} = call(Config, Req, [{filter, F}]).
+
+%% Specify multiple filter options and expect them be conjunctive.
+send_multiple_filters_1(Config) ->
+ Fun = fun(#diameter_caps{}) -> true end,
+ #diameter_base_STA{'Result-Code' = ?SUCCESS}
+ = send_multiple_filters(Config, [host, {eval, Fun}]).
+send_multiple_filters_2(Config) ->
+ E = {erlang, is_tuple, []},
+ {error, no_connection}
+ = send_multiple_filters(Config, [realm, {neg, {eval, E}}]).
+send_multiple_filters_3(Config) ->
+ E1 = [fun(#diameter_caps{}, ok) -> true end, ok],
+ E2 = {erlang, is_tuple, []},
+ E3 = {erlang, is_record, [diameter_caps]},
+ E4 = [{erlang, is_record, []}, diameter_caps],
+ #diameter_base_STA{'Result-Code' = ?SUCCESS}
+ = send_multiple_filters(Config, [{eval, E} || E <- [E1,E2,E3,E4]]).
+
+send_multiple_filters(Config, Fs) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+ call(Config, Req, [{filter, F} || F <- Fs]).
+
+%% Ensure that we can pass a request in any form to diameter:call/4,
+%% only the return value from the prepare_request callback being
+%% significant.
+send_anything(Config) ->
+ #diameter_base_STA{'Result-Code' = ?SUCCESS}
+ = call(Config, anything).
+
+%% ===========================================================================
+
+call(Config, Req) ->
+ call(Config, Req, []).
+
+call(Config, Req, Opts) ->
+ Name = proplists:get_value(testcase, Config),
+ Enc = proplists:get_value(encode, Config),
+ diameter:call(?CLIENT,
+ ?APP_ALIAS,
+ msg(Req, Enc),
+ [{extra, [Name]} | Opts]).
+
+msg([_|_] = L, list) ->
+ L;
+msg([H|T], record) ->
+ ?DICT:'#new-'(?DICT:msg2rec(H), T);
+msg(T, _) ->
+ T.
+
+%% Set only values that aren't already.
+set([H|T], Vs) ->
+ [H | Vs ++ T];
+set(Rec, Vs) ->
+ lists:foldl(fun({F,_} = FV, A) -> set(?DICT:'#get-'(F, A), FV, A) end,
+ Rec,
+ Vs).
+
+set(E, FV, Rec)
+ when E == undefined;
+ E == [] ->
+ ?DICT:'#set-'(FV, Rec);
+set(_, _, Rec) ->
+ Rec.
+
+%% ===========================================================================
+%% diameter callbacks
+
+%% peer_up/3
+
+peer_up(_SvcName, _Peer, State) ->
+ State.
+
+%% peer_down/3
+
+peer_down(_SvcName, _Peer, State) ->
+ State.
+
+%% pick_peer/5/6
+
+pick_peer([Peer], _, ?CLIENT, _State, Name)
+ when Name /= send_detach ->
+ {ok, Peer}.
+
+pick_peer([_Peer], _, ?CLIENT, _State, send_nopeer, ?EXTRA) ->
+ false;
+
+pick_peer([Peer], _, ?CLIENT, _State, send_detach, {_,_}) ->
+ {ok, Peer}.
+
+%% prepare_request/4/5
+
+prepare_request(_Pkt, ?CLIENT, {_Ref, _Caps}, send_discard) ->
+ {discard, unprepared};
+
+prepare_request(Pkt, ?CLIENT, {_Ref, Caps}, Name) ->
+ {send, prepare(Pkt, Caps, Name)}.
+
+prepare_request(Pkt, ?CLIENT, {_Ref, Caps}, send_detach, _) ->
+ {send, prepare(Pkt, Caps)}.
+
+prepare(Pkt, Caps, send_unsupported) ->
+ Req = prepare(Pkt, Caps),
+ #diameter_packet{bin = <<H:5/binary, _CmdCode:3/binary, T/binary>>}
+ = E
+ = diameter_codec:encode(?DICT, Pkt#diameter_packet{msg = Req}),
+ E#diameter_packet{bin = <<H/binary, 42:24/integer, T/binary>>};
+
+prepare(Pkt, Caps, send_unsupported_app) ->
+ Req = prepare(Pkt, Caps),
+ #diameter_packet{bin = <<H:8/binary, _ApplId:4/binary, T/binary>>}
+ = E
+ = diameter_codec:encode(?DICT, Pkt#diameter_packet{msg = Req}),
+ E#diameter_packet{bin = <<H/binary, 42:32/integer, T/binary>>};
+
+prepare(Pkt, Caps, send_error_bit) ->
+ #diameter_packet{header = Hdr} = Pkt,
+ Pkt#diameter_packet{header = Hdr#diameter_header{is_error = true},
+ msg = prepare(Pkt, Caps)};
+
+prepare(Pkt, Caps, send_unsupported_version) ->
+ #diameter_packet{header = Hdr} = Pkt,
+ Pkt#diameter_packet{header = Hdr#diameter_header{version = 42},
+ msg = prepare(Pkt, Caps)};
+
+prepare(Pkt, Caps, send_anything) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+ prepare(Pkt#diameter_packet{msg = Req}, Caps);
+
+prepare(Pkt, Caps, _Name) ->
+ prepare(Pkt, Caps).
+
+prepare(#diameter_packet{msg = Req}, Caps)
+ when is_record(Req, diameter_base_ACR);
+ 'ACR' == hd(Req) ->
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, DR}}
+ = Caps,
+
+ set(Req, [{'Session-Id', diameter:session_id(OH)},
+ {'Origin-Host', OH},
+ {'Origin-Realm', OR},
+ {'Destination-Realm', DR}]);
+
+prepare(#diameter_packet{msg = Req}, Caps)
+ when is_record(Req, diameter_base_ASR);
+ 'ASR' == hd(Req) ->
+ #diameter_caps{origin_host = {OH, DH},
+ origin_realm = {OR, DR}}
+ = Caps,
+ set(Req, [{'Session-Id', diameter:session_id(OH)},
+ {'Origin-Host', OH},
+ {'Origin-Realm', OR},
+ {'Destination-Host', DH},
+ {'Destination-Realm', DR},
+ {'Auth-Application-Id', ?APP_ID}]);
+
+prepare(#diameter_packet{msg = Req}, Caps)
+ when is_record(Req, diameter_base_STR);
+ 'STR' == hd(Req) ->
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, DR}}
+ = Caps,
+ set(Req, [{'Session-Id', diameter:session_id(OH)},
+ {'Origin-Host', OH},
+ {'Origin-Realm', OR},
+ {'Destination-Realm', DR},
+ {'Auth-Application-Id', ?APP_ID}]);
+
+prepare(#diameter_packet{msg = Req}, Caps)
+ when is_record(Req, diameter_base_RAR);
+ 'RAR' == hd(Req) ->
+ #diameter_caps{origin_host = {OH, DH},
+ origin_realm = {OR, DR}}
+ = Caps,
+ set(Req, [{'Session-Id', diameter:session_id(OH)},
+ {'Origin-Host', OH},
+ {'Origin-Realm', OR},
+ {'Destination-Host', DH},
+ {'Destination-Realm', DR},
+ {'Auth-Application-Id', ?APP_ID}]).
+
+%% prepare_retransmit/4
+
+prepare_retransmit(_Pkt, false, _Peer, _Name) ->
+ discard.
+
+%% handle_answer/5/6
+
+handle_answer(Pkt, Req, ?CLIENT, Peer, Name) ->
+ answer(Pkt, Req, Peer, Name).
+
+handle_answer(Pkt, _Req, ?CLIENT, _Peer, send_detach, {Pid, Ref}) ->
+ Pid ! {Ref, Pkt}.
+
+answer(#diameter_packet{msg = Rec, errors = []}, _Req, _Peer, _) ->
+ Rec.
+
+%% handle_error/5
+
+handle_error(Reason, _Req, ?CLIENT, _Peer, _Name) ->
+ {error, Reason}.
+
+%% handle_request/3
+
+%% Note that diameter will set Result-Code and Failed-AVPs if
+%% #diameter_packet.errors is non-null.
+
+handle_request(Pkt, ?SERVER, {_Ref, Caps}) ->
+ request(Pkt, Caps).
+
+request(#diameter_packet{msg
+ = #diameter_base_ACR{'Session-Id' = SId,
+ 'Accounting-Record-Type' = RT,
+ 'Accounting-Record-Number' = RN}},
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, _}}) ->
+ {reply, ['ACA', {'Result-Code', ?SUCCESS},
+ {'Session-Id', SId},
+ {'Origin-Host', OH},
+ {'Origin-Realm', OR},
+ {'Accounting-Record-Type', RT},
+ {'Accounting-Record-Number', RN}]};
+
+request(#diameter_packet{msg = #diameter_base_ASR{'Session-Id' = SId,
+ 'AVP' = Avps}},
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, _}}) ->
+ {reply, #diameter_base_ASA{'Result-Code' = ?SUCCESS,
+ 'Session-Id' = SId,
+ 'Origin-Host' = OH,
+ 'Origin-Realm' = OR,
+ 'AVP' = Avps}};
+
+request(#diameter_packet{msg = #diameter_base_STR{'Termination-Cause' = T}},
+ _Caps)
+ when T /= ?LOGOUT ->
+ discard;
+
+request(#diameter_packet{msg = #diameter_base_STR{'Destination-Realm'= R}},
+ #diameter_caps{origin_realm = {OR, _}})
+ when R /= undefined, R /= OR ->
+ {protocol_error, ?REALM_NOT_SERVED};
+
+request(#diameter_packet{msg = #diameter_base_STR{'Destination-Host'= [H]}},
+ #diameter_caps{origin_host = {OH, _}})
+ when H /= OH ->
+ {protocol_error, ?UNABLE_TO_DELIVER};
+
+request(#diameter_packet{msg = #diameter_base_STR{'Session-Id' = SId}},
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, _}}) ->
+ {reply, #diameter_base_STA{'Result-Code' = ?SUCCESS,
+ 'Session-Id' = SId,
+ 'Origin-Host' = OH,
+ 'Origin-Realm' = OR}};
+
+request(#diameter_packet{msg = #diameter_base_RAR{}}, _Caps) ->
+ receive after 2000 -> ok end,
+ {protocol_error, ?TOO_BUSY}.
diff --git a/lib/diameter/test/diameter_transport_SUITE.erl b/lib/diameter/test/diameter_transport_SUITE.erl
new file mode 100644
index 0000000000..c22adc3334
--- /dev/null
+++ b/lib/diameter/test/diameter_transport_SUITE.erl
@@ -0,0 +1,436 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests of diameter_tcp/sctp as implementations of the diameter
+%% transport interface.
+%%
+
+-module(diameter_transport_SUITE).
+
+-export([suite/0,
+ all/0,
+ groups/0,
+ init_per_group/2,
+ end_per_group/2,
+ init_per_suite/1,
+ end_per_suite/1]).
+
+%% testcases
+-export([start/1,
+ tcp_accept/1,
+ tcp_connect/1,
+ sctp_accept/1,
+ sctp_connect/1,
+ stop/1]).
+
+-export([accept/1,
+ connect/1,
+ init/2]).
+
+-include_lib("kernel/include/inet_sctp.hrl").
+-include("diameter.hrl").
+-include("diameter_ct.hrl").
+
+-define(util, diameter_util).
+
+%% Corresponding to diameter_* transport modules.
+-define(TRANSPORTS, [tcp, sctp]).
+
+%% Receive a message.
+-define(RECV(Pat, Ret), receive Pat -> Ret end).
+-define(RECV(Pat), ?RECV(Pat, now())).
+
+%% Or not.
+-define(WAIT(Ms), receive after Ms -> now() end).
+
+%% Sockets are opened on the loopback address.
+-define(ADDR, {127,0,0,1}).
+
+%% diameter_tcp doesn't use anything but host_ip_address, and that
+%% only is a local address isn't configured as at transport start.
+-define(SVC(Addrs), #diameter_service{capabilities
+ = #diameter_caps{host_ip_address
+ = Addrs}}).
+
+%% The term we register after open a listening port with gen_tcp.
+-define(TEST_LISTENER(Ref, PortNr),
+ {?MODULE, listen, Ref, PortNr}).
+
+%% Message over the transport interface.
+-define(TMSG(T), {diameter, T}).
+
+%% Options for gen_tcp/gen_sctp.
+-define(TCP_OPTS, [binary, {active, true}, {packet, 0}]).
+-define(SCTP_OPTS, [binary, {active, true}, {sctp_initmsg, ?SCTP_INIT}]).
+
+%% Request a specific number of streams just because we can.
+-define(SCTP_INIT, #sctp_initmsg{num_ostreams = 5,
+ max_instreams = 5}).
+
+%% Messages from gen_sctp.
+-define(SCTP(Sock, Data), {sctp, Sock, _, _, Data}).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {minutes, 2}}].
+
+all() ->
+ [start | tc()] ++ [{group, all}, stop].
+
+groups() ->
+ [{all, [parallel], tc()}].
+
+tc() ->
+ [tcp_accept,
+ tcp_connect,
+ sctp_accept,
+ sctp_connect].
+
+init_per_group(_, Config) ->
+ Config.
+
+end_per_group(_, _) ->
+ ok.
+
+init_per_suite(Config) ->
+ [{sctp, have_sctp()} | Config].
+
+end_per_suite(_Config) ->
+ ok.
+
+%% ===========================================================================
+
+start(_Config) ->
+ ok = diameter:start().
+
+stop(_Config) ->
+ ok = diameter:stop().
+
+%% ===========================================================================
+%% tcp_accept/1
+%% sctp_accept/1
+%%
+%% diameter transport accepting, test code connecting.
+
+tcp_accept(_) ->
+ accept(tcp).
+
+sctp_accept(Config) ->
+ if_sctp(fun accept/1, Config).
+
+%% Start multiple accepting transport processes that are connected to
+%% with an equal number of connecting processes using gen_tcp/sctp
+%% directly.
+
+-define(PEER_COUNT, 8).
+
+accept(Prot) ->
+ T = {Prot, make_ref()},
+ [] = ?util:run(?util:scramble(acc(2*?PEER_COUNT, T, []))).
+
+acc(0, _, Acc) ->
+ Acc;
+acc(N, T, Acc) ->
+ acc(N-1, T, [{?MODULE, [init,
+ element(1 + N rem 2, {accept, gen_connect}),
+ T]}
+ | Acc]).
+
+%% ===========================================================================
+%% tcp_connect/1
+%% sctp_connect/1
+%%
+%% Test code accepting, diameter transport connecting.
+
+tcp_connect(_) ->
+ connect(tcp).
+
+sctp_connect(Config) ->
+ if_sctp(fun connect/1, Config).
+
+connect(Prot) ->
+ T = {Prot, make_ref()},
+ [] = ?util:run([{?MODULE, [init, X, T]} || X <- [gen_accept, connect]]).
+
+%% ===========================================================================
+%% ===========================================================================
+
+%% have_sctp/0
+
+have_sctp() ->
+ try gen_sctp:open() of
+ {ok, Sock} ->
+ gen_sctp:close(Sock),
+ true;
+ {error, eprotonosupport} -> %% fail on any other reason
+ false
+ catch
+ error: badarg ->
+ false
+ end.
+
+%% if_sctp/2
+
+if_sctp(F, Config) ->
+ case proplists:get_value(sctp, Config) of
+ true ->
+ F(sctp);
+ false ->
+ {skip, no_sctp}
+ end.
+
+%% init/2
+
+init(accept, {Prot, Ref}) ->
+ %% Start an accepting transport and receive notification of a
+ %% connection.
+ TPid = start_accept(Prot, Ref),
+
+ %% Receive a message and send it back.
+ <<_:8, Len:24, _/binary>> = Bin = bin(Prot, ?RECV(?TMSG({recv, P}), P)),
+
+ Len = size(Bin),
+ TPid ! ?TMSG({send, Bin}),
+
+ %% Expect the transport process to die as a result of the peer
+ %% closing the connection.
+ MRef = erlang:monitor(process, TPid),
+ ?RECV({'DOWN', MRef, process, _, _});
+
+init(gen_connect, {Prot, Ref}) ->
+ %% Lookup the peer's listening socket.
+ [PortNr] = ?util:lport(Prot, Ref, 20),
+
+ %% Connect, send a message and receive it back.
+ {ok, Sock} = gen_connect(Prot, PortNr, Ref),
+ Bin = make_msg(),
+ ok = gen_send(Prot, Sock, Bin),
+ Bin = gen_recv(Prot, Sock);
+
+init(gen_accept, {Prot, Ref}) ->
+ %% Open a listening socket and publish the port number.
+ {ok, LSock} = gen_listen(Prot),
+ {ok, PortNr} = inet:port(LSock),
+ true = diameter_reg:add_new(?TEST_LISTENER(Ref, PortNr)),
+
+ %% Accept a connection, receive a message and send it back.
+ {ok, Sock} = gen_accept(Prot, LSock),
+ Bin = gen_recv(Prot, Sock),
+ ok = gen_send(Prot, Sock, Bin);
+
+init(connect, {Prot, Ref}) ->
+ %% Lookup the peer's listening socket.
+ [{?TEST_LISTENER(_, PortNr), _}] = match(?TEST_LISTENER(Ref, '_')),
+
+ %% Start a connecting transport and receive notification of
+ %% the connection.
+ TPid = start_connect(Prot, PortNr, Ref),
+
+ %% Send a message and receive it back.
+ Bin = make_msg(),
+ TPid ! ?TMSG({send, Bin}),
+ Bin = bin(Prot, ?RECV(?TMSG({recv, P}), P)),
+
+ %% Expect the transport process to die as a result of the peer
+ %% closing the connection.
+ MRef = erlang:monitor(process, TPid),
+ ?RECV({'DOWN', MRef, process, _, _}).
+
+match(Pat) ->
+ match(Pat, 20).
+
+match(Pat, T) ->
+ L = diameter_reg:match(Pat),
+ if [] /= L orelse 1 == T ->
+ L;
+ true ->
+ ?WAIT(50),
+ match(Pat, T-1)
+ end.
+
+bin(sctp, #diameter_packet{bin = Bin}) ->
+ Bin;
+bin(tcp, Bin) ->
+ Bin.
+
+%% make_msg/0
+%%
+%% A valid Diameter message in as far as diameter_tcp examines it,
+%% the module examining the length in the Diameter header to locate
+%% message boundaries.
+
+make_msg() ->
+ N = 1024,
+ Bin = rand_bytes(4*N),
+ Len = 4*(N+1),
+ <<1:8, Len:24, Bin/binary>>.
+
+%% crypto:rand_bytes/1 isn't available on all platforms (since openssl
+%% isn't) so roll our own.
+rand_bytes(N) ->
+ random:seed(now()),
+ rand_bytes(N, <<>>).
+
+rand_bytes(0, Bin) ->
+ Bin;
+rand_bytes(N, Bin) ->
+ Oct = random:uniform(256) - 1,
+ rand_bytes(N-1, <<Oct, Bin/binary>>).
+
+%% ===========================================================================
+
+%% start_connect/3
+
+start_connect(Prot, PortNr, Ref) ->
+ {ok, TPid, [?ADDR]} = start_connect(Prot,
+ {connect, Ref},
+ ?SVC([]),
+ [{raddr, ?ADDR},
+ {rport, PortNr},
+ {ip, ?ADDR},
+ {port, 0}]),
+ ?RECV(?TMSG({TPid, connected, _})),
+ TPid.
+
+start_connect(sctp, T, Svc, Opts) ->
+ diameter_sctp:start(T, Svc, [{sctp_initmsg, ?SCTP_INIT} | Opts]);
+start_connect(tcp, T, Svc, Opts) ->
+ diameter_tcp:start(T, Svc, Opts).
+
+%% start_accept/2
+%%
+%% Start transports sequentially by having each wait for a message
+%% from a job in a queue before commencing. Only one transport with
+%% a pending accept is started at a time since diameter_sctp currently
+%% assumes (and diameter currently implements) this.
+
+start_accept(Prot, Ref) ->
+ Pid = sync(accept, Ref),
+
+ %% Configure the same port number for transports on the same
+ %% reference.
+ [PortNr | _] = ?util:lport(Prot, Ref) ++ [0],
+ {Mod, Opts} = tmod(Prot),
+
+ try
+ {ok, TPid, [?ADDR]} = Mod:start({accept, Ref},
+ ?SVC([?ADDR]),
+ [{port, PortNr} | Opts]),
+ ?RECV(?TMSG({TPid, connected})),
+ TPid
+ after
+ Pid ! Ref
+ end.
+
+sync(What, Ref) ->
+ ok = diameter_sync:cast({?MODULE, What, Ref},
+ [fun lock/2, Ref, self()],
+ infinity,
+ infinity),
+ receive {start, Ref, Pid} -> Pid end.
+
+lock(Ref, Pid) ->
+ Pid ! {start, Ref, self()},
+ erlang:monitor(process, Pid),
+ Ref = receive T -> T end.
+
+tmod(sctp) ->
+ {diameter_sctp, [{sctp_initmsg, ?SCTP_INIT}]};
+tmod(tcp) ->
+ {diameter_tcp, []}.
+
+%% ===========================================================================
+
+%% gen_connect/3
+
+gen_connect(Prot, PortNr, Ref) ->
+ Pid = sync(connect, Ref),
+
+ %% Stagger connect attempts to avoid the situation that no
+ %% transport process is accepting yet.
+ receive after 250 -> ok end,
+
+ try
+ gen_connect(Prot, PortNr)
+ after
+ Pid ! Ref
+ end.
+
+gen_connect(sctp = P, PortNr) ->
+ {ok, Sock} = Ok = gen_sctp:open([{ip, ?ADDR}, {port, 0} | ?SCTP_OPTS]),
+ ok = gen_sctp:connect_init(Sock, ?ADDR, PortNr, []),
+ Ok = gen_accept(P, Sock);
+gen_connect(tcp, PortNr) ->
+ gen_tcp:connect(?ADDR, PortNr, ?TCP_OPTS).
+
+%% gen_listen/1
+
+gen_listen(sctp) ->
+ {ok, Sock} = gen_sctp:open([{ip, ?ADDR}, {port, 0} | ?SCTP_OPTS]),
+ {gen_sctp:listen(Sock, true), Sock};
+gen_listen(tcp) ->
+ gen_tcp:listen(0, [{ip, ?ADDR} | ?TCP_OPTS]).
+
+%% gen_accept/2
+
+gen_accept(sctp, Sock) ->
+ Assoc = ?RECV(?SCTP(Sock, {_, #sctp_assoc_change{state = comm_up,
+ outbound_streams = O,
+ inbound_streams = I,
+ assoc_id = A}}),
+ {O, I, A}),
+ putr(assoc, Assoc),
+ {ok, Sock};
+gen_accept(tcp, LSock) ->
+ gen_tcp:accept(LSock).
+
+%% gen_send/3
+
+gen_send(sctp, Sock, Bin) ->
+ {OS, _IS, Id} = getr(assoc),
+ {_, _, Us} = now(),
+ gen_sctp:send(Sock, Id, Us rem OS, Bin);
+gen_send(tcp, Sock, Bin) ->
+ gen_tcp:send(Sock, Bin).
+
+%% gen_recv/2
+
+gen_recv(sctp, Sock) ->
+ {_OS, _IS, Id} = getr(assoc),
+ ?RECV(?SCTP(Sock, {[#sctp_sndrcvinfo{assoc_id = Id}], Bin}), Bin);
+gen_recv(tcp, Sock) ->
+ tcp_recv(Sock, <<>>).
+
+tcp_recv(_, <<_:8, Len:24, _/binary>> = Bin)
+ when Len =< size(Bin) ->
+ Bin;
+tcp_recv(Sock, B) ->
+ receive {tcp, Sock, Bin} -> tcp_recv(Sock, <<B/binary, Bin/binary>>) end.
+
+%% putr/2
+
+putr(Key, Val) ->
+ put({?MODULE, Key}, Val).
+
+%% getr/1
+
+getr(Key) ->
+ get({?MODULE, Key}).
diff --git a/lib/diameter/test/diameter_util.erl b/lib/diameter/test/diameter_util.erl
new file mode 100644
index 0000000000..6b1dc1f0c9
--- /dev/null
+++ b/lib/diameter/test/diameter_util.erl
@@ -0,0 +1,322 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(diameter_util).
+
+%%
+%% Utility functions.
+%%
+
+%% generic
+-export([consult/2,
+ run/1,
+ fold/3,
+ foldl/3,
+ scramble/1]).
+
+%% diameter-specific
+-export([lport/2,
+ lport/3,
+ listen/2, listen/3,
+ connect/3, connect/4,
+ disconnect/4]).
+
+%% common_test-specific
+-export([write_priv/3,
+ read_priv/2,
+ map_priv/3]).
+
+-define(L, atom_to_list).
+
+%% ---------------------------------------------------------------------------
+%% consult/2
+%%
+%% Extract info from the app/appup file (presumably) of the named
+%% application.
+
+consult(Name, Suf)
+ when is_atom(Name), is_atom(Suf) ->
+ case code:lib_dir(Name, ebin) of
+ {error = E, Reason} ->
+ {E, {Name, Reason}};
+ Dir ->
+ consult(filename:join([Dir, ?L(Name) ++ "." ++ ?L(Suf)]))
+ end.
+
+consult(Path) ->
+ case file:consult(Path) of
+ {ok, Terms} ->
+ Terms;
+ {error, Reason} ->
+ {error, {Path, Reason}}
+ end.
+%% Name/Path in the return value distinguish the errors and allow for
+%% a useful badmatch.
+
+%% ---------------------------------------------------------------------------
+%% run/1
+%%
+%% Evaluate functions in parallel and return a list of those that
+%% failed to return. The fun takes a boolean (did the function return
+%% or not), the function that was evaluated, the return value or exit
+%% reason and the prevailing accumulator.
+
+run(L) ->
+ fold(fun cons/4, [], L).
+
+cons(true, _, _, Acc) ->
+ Acc;
+cons(false, F, RC, Acc) ->
+ [{F, RC} | Acc].
+
+%% ---------------------------------------------------------------------------
+%% fold/3
+%%
+%% Parallel fold. Results are folded in the order received.
+
+fold(Fun, Acc0, L)
+ when is_function(Fun, 4) ->
+ Ref = make_ref(),
+ %% Spawn a middleman to collect down messages from processes
+ %% spawned for each function so as not to assume that all DOWN
+ %% messages are ours.
+ MRef = run1([fun fold/4, Ref, Fun, Acc0, L], Ref),
+ {Ref, RC} = down(MRef),
+ RC.
+
+fold(Ref, Fun, Acc0, L) ->
+ recv(run(Ref, L), Ref, Fun, Acc0).
+
+run(Ref, L) ->
+ [{run1(F, Ref), F} || F <- L].
+
+run1(F, Ref) ->
+ {_, MRef} = spawn_monitor(fun() -> exit({Ref, eval(F)}) end),
+ MRef.
+
+recv([], _, _, Acc) ->
+ Acc;
+recv(L, Ref, Fun, Acc) ->
+ {MRef, R} = down(),
+ {MRef, F} = lists:keyfind(MRef, 1, L),
+ recv(lists:keydelete(MRef, 1, L),
+ Ref,
+ Fun,
+ acc(R, Ref, F, Fun, Acc)).
+
+acc({Ref, RC}, Ref, F, Fun, Acc) ->
+ Fun(true, F, RC, Acc);
+acc(Reason, _, F, Fun, Acc) ->
+ Fun(false, F, Reason, Acc).
+
+down(MRef) ->
+ receive {'DOWN', MRef, process, _, Reason} -> Reason end.
+
+down() ->
+ receive {'DOWN', MRef, process, _, Reason} -> {MRef, Reason} end.
+
+%% ---------------------------------------------------------------------------
+%% foldl/3
+%%
+%% Parallel fold. Results are folded in order of the function list.
+
+foldl(Fun, Acc0, L)
+ when is_function(Fun, 4) ->
+ Ref = make_ref(),
+ recvl(run(Ref, L), Ref, Fun, Acc0).
+
+recvl([], _, _, Acc) ->
+ Acc;
+recvl([{MRef, F} | L], Ref, Fun, Acc) ->
+ R = down(MRef),
+ recvl(L, Ref, Fun, acc(R, Ref, F, Fun, Acc)).
+
+%% ---------------------------------------------------------------------------
+%% scramble/1
+%%
+%% Sort a list into random order.
+
+scramble(L) ->
+ foldl(fun(true, _, S, false) -> S end,
+ false,
+ [[fun s/1, L]]).
+
+s(L) ->
+ random:seed(now()),
+ s([], L).
+
+s(Acc, []) ->
+ Acc;
+s(Acc, L) ->
+ {H, [T|Rest]} = lists:split(random:uniform(length(L)) - 1, L),
+ s([T|Acc], H ++ Rest).
+
+%% ---------------------------------------------------------------------------
+%% eval/1
+%%
+%% Evaluate a function in one of a number of forms.
+
+eval({M,[F|A]})
+ when is_atom(F) ->
+ apply(M,F,A);
+
+eval({M,F,A}) ->
+ apply(M,F,A);
+
+eval([F|A])
+ when is_function(F) ->
+ apply(F,A);
+
+eval(L)
+ when is_list(L) ->
+ run(L);
+
+eval(F)
+ when is_function(F,0) ->
+ F().
+
+%% ---------------------------------------------------------------------------
+%% write_priv/3
+%%
+%% Write an arbitrary term to a named file.
+
+write_priv(Config, Name, Term) ->
+ write(path(Config, Name), Term).
+
+write(Path, Term) ->
+ ok = file:write_file(Path, term_to_binary(Term)).
+
+%% read_priv/2
+%%
+%% Read a term from a file.
+
+read_priv(Config, Name) ->
+ read(path(Config, Name)).
+
+read(Path) ->
+ {ok, Bin} = file:read_file(Path),
+ binary_to_term(Bin).
+
+%% map_priv/3
+%%
+%% Modify a term in a file and return both old and new values.
+
+map_priv(Config, Name, Fun1) ->
+ map(path(Config, Name), Fun1).
+
+map(Path, Fun1) ->
+ T0 = read(Path),
+ T1 = Fun1(T0),
+ write(Path, T1),
+ {T0, T1}.
+
+path(Config, Name)
+ when is_atom(Name) ->
+ path(Config, ?L(Name));
+path(Config, Name) ->
+ Dir = proplists:get_value(priv_dir, Config),
+ filename:join([Dir, Name]).
+
+%% ---------------------------------------------------------------------------
+%% lport/2-3
+%%
+%% Lookup the port number of a tcp/sctp listening transport.
+
+lport(M, Ref) ->
+ lport(M, Ref, 1).
+
+lport(M, Ref, Tries) ->
+ lp(tmod(M), Ref, Tries).
+
+lp(M, Ref, T) ->
+ L = [N || {listen, N, _} <- M:ports(Ref)],
+ if [] /= L orelse T =< 1 ->
+ L;
+ true ->
+ receive after 50 -> ok end,
+ lp(M, Ref, T-1)
+ end.
+
+%% ---------------------------------------------------------------------------
+%% listen/2-3
+%%
+%% Add a listening transport on the loopback address and a free port.
+
+listen(SvcName, Prot) ->
+ listen(SvcName, Prot, []).
+
+listen(SvcName, Prot, Opts) ->
+ add_transport(SvcName, {listen, opts(Prot, listen) ++ Opts}).
+
+%% ---------------------------------------------------------------------------
+%% connect/2-3
+%%
+%% Add a connecting transport on and connect to a listening transport
+%% with the specified reference.
+
+connect(Client, Prot, LRef) ->
+ connect(Client, Prot, LRef, []).
+
+connect(Client, Prot, LRef, Opts) ->
+ [PortNr] = lport(Prot, LRef, 20),
+ Ref = add_transport(Client, {connect, opts(Prot, PortNr) ++ Opts}),
+ true = diameter:subscribe(Client),
+ ok = receive
+ {diameter_event, Client, {up, Ref, _, _, _}} -> ok
+ after 2000 ->
+ {Client, Prot, PortNr, process_info(self(), messages)}
+ end,
+ Ref.
+
+%% ---------------------------------------------------------------------------
+%% disconnect/4
+%%
+%% Remove the client transport and expect the server transport to go
+%% down.
+
+disconnect(Client, Ref, Server, LRef) ->
+ true = diameter:subscribe(Server),
+ ok = diameter:remove_transport(Client, Ref),
+ ok = receive
+ {diameter_event, Server, {down, LRef, _, _}} -> ok
+ after 2000 ->
+ {Client, Ref, Server, LRef, process_info(self(), messages)}
+ end.
+
+%% ---------------------------------------------------------------------------
+
+-define(ADDR, {127,0,0,1}).
+
+add_transport(SvcName, T) ->
+ {ok, Ref} = diameter:add_transport(SvcName, T),
+ Ref.
+
+tmod(tcp) ->
+ diameter_tcp;
+tmod(sctp) ->
+ diameter_sctp.
+
+opts(Prot, T) ->
+ [{transport_module, tmod(Prot)},
+ {transport_config, [{ip, ?ADDR}, {port, 0} | opts(T)]}].
+
+opts(listen) ->
+ [];
+opts(PortNr) ->
+ [{raddr, ?ADDR}, {rport, PortNr}].
diff --git a/lib/diameter/test/diameter_watchdog_SUITE.erl b/lib/diameter/test/diameter_watchdog_SUITE.erl
new file mode 100644
index 0000000000..b40d7c104d
--- /dev/null
+++ b/lib/diameter/test/diameter_watchdog_SUITE.erl
@@ -0,0 +1,540 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests of the RFC3539 watchdog state machine as implemented by
+%% module diameter_watchdog.
+%%
+
+-module(diameter_watchdog_SUITE).
+
+-export([suite/0,
+ all/0,
+ init_per_suite/1,
+ end_per_suite/1]).
+
+%% testcases
+-export([reopen/1, reopen/4]).
+
+-export([start/3, %% diameter_transport callback
+ id/1, %% jitter callback
+ run/1]).
+
+-include("diameter.hrl").
+-include("diameter_ct.hrl").
+
+%% ===========================================================================
+
+-define(util, diameter_util).
+
+-define(BASE, diameter_gen_base_rfc3588).
+-define(APPL_ID, diameter_gen_base_rfc3588:id()).
+-define(SUCCESS, 2001). %% DIAMETER_SUCCESS
+
+%% Addresses for the local and remote diameter nodes. The values don't
+%% matter since we're faking transport.
+-define(LOCALHOST, {127,0,0,1}).
+-define(REMOTEHOST, {10,0,0,1}).
+
+-define(CAPS, #diameter_caps{origin_host = "node.innan.com",
+ origin_realm = "innan.com",
+ host_ip_address = [?LOCALHOST],
+ vendor_id = 1022,
+ product_name = "remote",
+ auth_application_id = [?APPL_ID]}).
+
+-define(APPL, #diameter_app{alias = ?MODULE,
+ dictionary = ?BASE,
+ module = [?MODULE],
+ init_state = now(),
+ id = ?APPL_ID,
+ mutable = false}).
+
+%% Service record maintained by our faked service process.
+-define(SERVICE, #diameter_service{pid = self(),
+ capabilities = ?CAPS,
+ applications = [?APPL]}).
+
+%% Watchdog timer as a callback.
+-define(WD(T), {?MODULE, id, [T]}).
+
+%% Watchdog timers used by the testcases. Note that the short timeout
+%% with random jitter is excluded since the reopen/1 isn't smart
+%% enough to deal with it: see ONE_WD below.
+-define(WD_TIMERS, [?WD(6000)
+ | [F_(T_) || T_ <- [10000, 20000, 30000],
+ F_ <- [fun(T__) -> T__ end,
+ fun(T__) -> ?WD(T__) end]]]).
+
+%% Transport types.
+-define(TRANSPORTS, [connect, accept]).
+
+%% Message over the transport interface.
+-define(TMSG(T), {diameter, T}).
+
+%% Receive a message within a specified time.
+-define(RECV(T, Timeout),
+ receive T -> now()
+ after Timeout -> ?ERROR({timeout, Timeout})
+ end).
+
+%% Receive a message in a given number of watchdogs, plus or minus
+%% half. Note that the call to now_diff assumes left to right
+%% evaluation order.
+-define(RECV(T, N, WdL, WdH),
+ [?ERROR({received, _Elapsed_, _LowerBound_, N, WdL})
+ || _UpperBound_ <- [(N)*(WdH) + (WdH) div 2],
+ _Elapsed_ <- [now_diff(now(), ?RECV(T, _UpperBound_))],
+ _LowerBound_ <- [(N)*(WdL) - (WdL) div 2],
+ _Elapsed_ =< _LowerBound_*1000]).
+
+%% A timeout that ensures one watchdog. The ensure only one watchdog
+%% requires (Wd + 2000) + 1000 < 2*(Wd - 2000) ==> 7000 < Wd for the
+%% case with random jitter.
+-define(ONE_WD(Wd), jitter(Wd,2000) + 1000).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {minutes, 6}}].%% enough for 11 watchdogs @ 30 sec plus jitter
+
+all() ->
+ [reopen].
+
+init_per_suite(Config) ->
+ ok = diameter:start(),
+ Config.
+
+end_per_suite(_Config) ->
+ ok = diameter:stop().
+
+%% ===========================================================================
+%% # reopen/1
+%% ===========================================================================
+
+%% Test the watchdog state machine for the required failover, failback
+%% and reopen behaviour. Do this by having the testcase replace
+%% diameter_service and start watchdogs, and having this module
+%% implement a transport process that plays the role of the peer
+%% Diameter node.
+
+reopen(_) ->
+ [] = ?util:run([{?MODULE, [run, [reopen, Wd, T, N, M]]}
+ || Wd <- ?WD_TIMERS,
+ T <- ?TRANSPORTS,
+ N <- [0,1,2],
+ M <- ['DWR', 'DWA', other]]).
+
+reopen(Wd, Type, N, What) ->
+ Ref = make_ref(),
+
+ %% The maker of transport processes.
+ TPid = start({N, Wd, What, Ref}),
+
+ %% Act like diameter_service and start the watchdog process, which
+ %% in turn starts a peer_fsm process, which in turn starts a
+ %% transport process by way of start/3. Messages received by the
+ %% testcase are those sent by diameter_watchdog to the service
+ %% process (= process starting the watchdog).
+ WPid1 = watchdog(Type, Ref, TPid, Wd),
+
+ %% Low/high watchdog timeouts.
+ WdL = jitter(Wd, -2000),
+ WdH = jitter(Wd, 2000),
+
+ %% Connection should come up immediately as a consequence of
+ %% starting the watchdog process. In the accepting case this
+ %% results in a new watchdog on a transport waiting for a new
+ %% connection.
+ ?RECV({connection_up, WPid1, _}, 1000),
+
+ WPid2 = case Type of
+ connect ->
+ WPid1;
+ accept ->
+ watchdog(Type, Ref, TPid, Wd)
+ end,
+
+ %% OKAY Timer expires & Failover()
+ %% Pending SetWatchdog() SUSPECT
+ %%
+ %% Since our transport is replying to N DWR's before becoming
+ %% silent, we should go down after N+2 watchdog_timer expirations:
+ %% that is, after the first unanswered DWR. Knowing the min/max
+ %% watchdog timeout values gives the time interval in which the
+ %% down message is expected.
+ ?RECV({connection_down, WPid1}, N+2, WdL, WdH),
+
+ %% SUSPECT Receive DWA Pending = FALSE
+ %% Failback()
+ %% SetWatchdog() OKAY
+ %%
+ %% SUSPECT Receive non-DWA Failback()
+ %% SetWatchdog() OKAY
+ %%
+ %% The transport receives a message before the expiry of another
+ %% watchdog to induce failback.
+ ?RECV({connection_up, WPid1}, WdH),
+
+ %% OKAY Timer expires & SendWatchdog()
+ %% !Pending SetWatchdog()
+ %% Pending = TRUE OKAY
+ %%
+ %% OKAY Timer expires & Failover()
+ %% Pending SetWatchdog() SUSPECT
+ %%
+ %% The transport is still not responding to watchdogs so the
+ %% connection should go back down after either one or two watchdog
+ %% expiries, depending on whether or not DWA restored the connection.
+ F = choose(What == 'DWA', 2, 1),
+ ?RECV({connection_down, WPid1}, F, WdL, WdH),
+
+ %% SUSPECT Timer expires CloseConnection()
+ %% SetWatchdog() DOWN
+ %%
+ %% DOWN Timer expires AttemptOpen()
+ %% SetWatchdog() DOWN
+ %%
+ %% Our transport tells us when the fake connection is
+ %% reestablished, which should happen after another couple of
+ %% watchdog expiries, the first bringing the watchdog to state
+ %% DOWN, the second triggering an attempt to reopen the
+ %% connection.
+ ?RECV({reopen, Ref}, 2, WdL, WdH),
+
+ %% DOWN Connection up NumDWA = 0
+ %% SendWatchdog()
+ %% SetWatchdog()
+ %% Pending = TRUE REOPEN
+ %%
+ %% REOPEN Receive DWA & Pending = FALSE
+ %% NumDWA < 2 NumDWA++ REOPEN
+ %%
+ %% REOPEN Receive DWA & Pending = FALSE
+ %% NumDWA == 2 NumDWA++
+ %% Failback() OKAY
+ %%
+ %% Now the watchdog should require three received DWA's before
+ %% taking the connection back up. The first DWR is sent directly
+ %% after capabilities exchange so it should take no more than two
+ %% watchdog expiries.
+ ?RECV({connection_up, WPid2, _}, 2, WdL, WdH).
+
+%% ===========================================================================
+
+%% Start the fake transport process. From diameter's point of view
+%% it's started when diameter calls start/3. We start it before this
+%% happens since we use the same fake transport each time diameter
+%% calls start/3. The process lives and dies with the test case.
+start(Config) ->
+ Pid = self(),
+ spawn(fun() -> loop(init(Pid, Config)) end).
+
+%% Transport start from diameter. This may be called multiple times
+%% depending on the testcase.
+start({Type, _Ref}, #diameter_service{}, Pid) ->
+ Ref = make_ref(),
+ MRef = erlang:monitor(process, Pid),
+ Pid ! {start, self(), Type, Ref},
+ {Ref, TPid} = receive
+ {Ref, _} = T ->
+ T;
+ {'DOWN', MRef, process, _, _} = T ->
+ T
+ end,
+ erlang:demonitor(MRef, [flush]),
+ {ok, TPid}.
+
+%% id/1
+
+id(T) ->
+ T.
+
+%% ===========================================================================
+
+choose(true, X, _) -> X;
+choose(false, _, X) -> X.
+
+%% run/1
+%%
+%% A more useful badmatch in case of failure.
+
+run([F|A]) ->
+ ok = try
+ apply(?MODULE, F, A),
+ ok
+ catch
+ E:R ->
+ {A, E, R, erlang:get_stacktrace()}
+ end.
+
+%% now_diff/2
+
+now_diff(T1, T2) ->
+ timer:now_diff(T2, T1).
+
+%% jitter/2
+
+jitter(?WD(T), _) ->
+ T;
+jitter(T,D) ->
+ T+D.
+
+%% watchdog/4
+%%
+%% Fake the call from diameter_service. The watchdog process will send
+%% messages to the calling "service" process so our tests are that the
+%% watchdog responds as expected.
+
+watchdog(Type, Ref, TPid, Wd) ->
+ Opts = [{transport_module, ?MODULE},
+ {transport_config, TPid},
+ {watchdog_timer, Wd}],
+ monitor(diameter_watchdog:start({Type, Ref},
+ {false, Opts, false, ?SERVICE})).
+
+monitor(Pid) ->
+ erlang:monitor(process, Pid),
+ Pid.
+
+%% ===========================================================================
+
+%% Transport process implmentation. Fakes reception of messages by
+%% sending fakes to the parent (peer fsm) process that called start/3.
+
+-record(transport,
+ {type, %% connect | accept | manager
+ parent, %% pid() of peer_fsm/ervice process
+ open = false, %% done with capabilities exchange?
+ config}).%% testcase-specific config
+
+%% init/2
+
+%% Testcase starting the manager.
+init(SvcPid, {_,_,_,_} = Config) ->
+ putr(peer, [{'Origin-Host', hostname() ++ ".utan.com"},
+ {'Origin-Realm', "utan.com"}]),
+ #transport{type = manager,
+ parent = monitor(SvcPid),
+ config = Config};
+
+%% Manager starting a transport.
+init(_, {Type, ParentPid, SvcPid, TwinPid, Peer, {N,_,_,_} = Config}) ->
+ putr(peer, Peer),
+ putr(service, SvcPid),
+ putr(count, init(Type, ParentPid, TwinPid, N)),%% number of DWR's to answer
+ #transport{type = Type,
+ parent = monitor(ParentPid),
+ config = Config}.
+
+init(Type, ParentPid, undefined, N) ->
+ connected(ParentPid, Type),
+ N;
+init(_, _, TPid, _) ->
+ monitor(TPid),
+ 3.
+
+%% Generate a unique hostname for the faked peer.
+hostname() ->
+ lists:flatten(io_lib:format("~p-~p-~p", tuple_to_list(now()))).
+
+%% loop/1
+
+loop(S) ->
+ loop(msg(receive T -> T end, S)).
+
+msg(T,S) ->
+ case transition(T,S) of
+ ok ->
+ S;
+ #transport{} = NS ->
+ NS;
+ {stop, Reason} ->
+ x(Reason)
+ end.
+
+x(Reason) ->
+ exit(Reason).
+
+%% transition/2
+
+%% Manager is being asked for a new transport process.
+transition({start, Pid, Type, Ref}, #transport{type = manager,
+ parent = SvcPid,
+ config = Config}) ->
+ TPid = start({Type, Pid, SvcPid, getr(transport), getr(peer), Config}),
+ Pid ! {Ref, TPid},
+ putr(transport, TPid),
+ ok;
+
+%% Peer fsm or testcase process has died.
+transition({'DOWN', _, process, Pid, _} = T, #transport{parent = Pid}) ->
+ {stop, T};
+
+%% Twin transport process has gone down. In the connect case, the
+%% transport isn't started until this happens in the first place so
+%% connect immediately. In the accept case, fake the peer reconnecting
+%% only after another watchdog expiry.
+transition({'DOWN', _, process, _, _}, #transport{type = Type,
+ config = {_, Wd, _, _}}) ->
+ Tmo = case Type of
+ connect ->
+ 0;
+ accept ->
+ ?ONE_WD(Wd)
+ end,
+ erlang:send_after(Tmo, self(), reconnect),
+ ok;
+
+transition(reconnect, #transport{type = Type,
+ parent = Pid,
+ config = {_,_,_,Ref}}) ->
+ getr(service) ! {reopen, Ref},
+ connected(Pid, Type),
+ ok;
+
+%% Peer fsm process is sending CER: fake the peer's CEA.
+transition(?TMSG({send, Bin}), #transport{type = connect,
+ open = false,
+ parent = Pid}
+ = S) ->
+ {Code, Flags, _} = ?BASE:msg_header('CER'),
+ <<_:32, Flags:8, Code:24, _:96, _/binary>> = Bin,
+ Hdr = make_header(Bin),
+ recv(Pid, {Hdr, make_cea()}),
+ S#transport{open = true};
+
+%% Peer fsm process is sending CEA.
+transition(?TMSG({send, Bin}), #transport{type = accept,
+ open = false}
+ = S) ->
+ {Code, Flags, _} = ?BASE:msg_header('CEA'),
+ <<_:32, Flags:8, Code:24, _:96, _/binary>> = Bin,
+ S#transport{open = true};
+
+%% Watchdog is sending DWR or DWA.
+transition(?TMSG({send, Bin}), #transport{open = true} = S) ->
+ {Code, _, _} = ?BASE:msg_header('DWR'),
+ {Code, _, _} = ?BASE:msg_header('DWA'),
+ <<_:32, R:1, 0:7, Code:24, _:96, _/binary>> = Bin,
+ Hdr = make_header(Bin),
+ dwa(1 == R, S, Hdr),
+ ok;
+
+%% We're telling ourselves to fake a received message.
+transition({recv, Msg}, #transport{parent = Pid}) ->
+ recv(Pid, Msg),
+ ok;
+
+%% We're telling ourselves to receive a message to induce failback.
+transition(failback = T, #transport{parent = Pid}) ->
+ recv(Pid, eraser(T)),
+ ok.
+
+make_header(Bin) ->
+ #diameter_header{end_to_end_id = E,
+ hop_by_hop_id = H}
+ = diameter_codec:decode_header(Bin),
+ #diameter_header{end_to_end_id = E,
+ hop_by_hop_id = H}.
+
+recv(Pid, Msg) ->
+ Pid ! ?TMSG({recv, encode(Msg)}).
+
+%% Replace the end-to-end/hop-by-hop identifiers with those from an
+%% incoming request to which we're constructing a reply.
+encode({Hdr, [_|_] = Msg}) ->
+ #diameter_header{hop_by_hop_id = HBH,
+ end_to_end_id = E2E}
+ = Hdr,
+ #diameter_packet{bin = Bin} = diameter_codec:encode(?BASE, Msg),
+ <<H:12/binary, _:64, T/binary>> = Bin,
+ <<H/binary, HBH:32, E2E:32, T/binary>>;
+
+encode([_|_] = Msg) ->
+ #diameter_packet{bin = Bin} = diameter_codec:encode(?BASE, Msg),
+ Bin.
+
+connected(Pid, connect) ->
+ Pid ! ?TMSG({self(), connected, make_ref()});
+connected(Pid, accept) ->
+ Pid ! ?TMSG({self(), connected}),
+ recv(Pid, make_cer()).
+
+make_cer() ->
+ ['CER' | getr(peer)] ++ [{'Host-IP-Address', [?REMOTEHOST]},
+ {'Vendor-Id', 1028},
+ {'Product-Name', "Utan"},
+ {'Auth-Application-Id', [?APPL_ID]}].
+
+make_cea() ->
+ ['CER' | Rest] = make_cer(),
+ ['CEA', {'Result-Code', ?SUCCESS} | Rest].
+
+make_dwr() ->
+ ['DWR' | getr(peer)].
+
+make_dwa() ->
+ ['DWR' | Rest] = make_dwr(),
+ ['DWA', {'Result-Code', ?SUCCESS} | Rest].
+
+dwa(false, _, _) -> %% outgoing was DWA ...
+ ok;
+dwa(true, S, Hdr) -> %% ... or DWR
+ dwa(getr(count), Hdr, S);
+
+%% React to the DWR only after another watchdog expiry. We shouldn't
+%% get another DWR while the answer is pending.
+dwa(0, Hdr, #transport{config = {_, Wd, What, _}}) ->
+ erlang:send_after(?ONE_WD(Wd), self(), failback),
+ putr(failback, make_msg(What, Hdr)),
+ eraser(count);
+
+dwa(undefined, _, _) ->
+ undefined = getr(failback), %% ensure this is after failback
+ ok;
+
+%% Reply with DWA.
+dwa(N, Hdr, #transport{parent = Pid}) ->
+ putr(count, N-1),
+ recv(Pid, {Hdr, make_dwa()}).
+
+%% Answer to received DWR.
+make_msg('DWA', Hdr) ->
+ {Hdr, make_dwa()};
+
+%% DWR from peer.
+make_msg('DWR', _) ->
+ make_dwr();
+
+%% An unexpected answer is discarded after passing through the
+%% watchdog state machine.
+make_msg(other, _) ->
+ ['RAA', {'Session-Id', diameter:session_id("abc")},
+ {'Result-Code', 2001}
+ | getr(peer)].
+
+putr(Key, Val) ->
+ put({?MODULE, Key}, Val).
+
+getr(Key) ->
+ get({?MODULE, Key}).
+
+eraser(Key) ->
+ erase({?MODULE, Key}).
diff --git a/lib/diameter/test/modules.mk b/lib/diameter/test/modules.mk
index ddc720d0c1..f88258c232 100644
--- a/lib/diameter/test/modules.mk
+++ b/lib/diameter/test/modules.mk
@@ -17,31 +17,27 @@
#
# %CopyrightEnd%
-TEST_SPEC_FILE = diameter.spec
-
+TEST_SPEC_FILE = diameter.spec
COVER_SPEC_FILE = diameter.cover
-BEHAVIOUR_MODULES =
-
MODULES = \
- $(BEHAVIOUR_MODULES) \
- diameter_SUITE \
- diameter_app_test \
- diameter_appup_test \
- diameter_compiler_test \
- diameter_config_test \
- diameter_peer_test \
- diameter_reg_test \
- diameter_session_test \
- diameter_stats_test \
- diameter_sync_test \
- diameter_tcp_test \
- diameter_test_lib \
- diameter_test_server
-
-
-INTERNAL_HRL_FILES = \
- diameter_test_lib.hrl
-
-
-
+ diameter_ct \
+ diameter_util \
+ diameter_enum \
+ diameter_codec_SUITE \
+ diameter_codec_test \
+ diameter_app_SUITE \
+ diameter_dict_SUITE \
+ diameter_reg_SUITE \
+ diameter_sync_SUITE \
+ diameter_stats_SUITE \
+ diameter_watchdog_SUITE \
+ diameter_transport_SUITE \
+ diameter_capx_SUITE \
+ diameter_traffic_SUITE \
+ diameter_relay_SUITE \
+ diameter_tls_SUITE \
+ diameter_failover_SUITE
+
+HRL_FILES = \
+ diameter_ct.hrl
diff --git a/lib/diameter/src/subdirs.mk b/lib/diameter/test/release.sed
index 3e12d935bc..2720b778f2 100644
--- a/lib/diameter/src/subdirs.mk
+++ b/lib/diameter/test/release.sed
@@ -1,5 +1,4 @@
-#-*-makefile-*- ; force emacs to enter makefile-mode
-
+#
# %CopyrightBegin%
#
# Copyright Ericsson AB 2010-2011. All Rights Reserved.
@@ -16,6 +15,21 @@
# under the License.
#
# %CopyrightEnd%
+#
+
+#
+# This bit of gymnastics is to replace the include of diameter's
+# public hrls by include_lib when releasing testsuites, so that they
+# compile both in the development filesystem (where generated hrls
+# aren't in diameter/include) and with common_test's autocompilation
+# on an installed release. Solving the problem by installing generated
+# hrls to ../include is anathema: that directory is for handwritten
+# source.)
+#
+
+/^-include("/!b
+/"diameter_gen_/b s
+/"diameter\./!b
-SUB_DIRS = compiler app transport
-SUB_DIRECTORIES = $(SUB_DIRS) \ No newline at end of file
+:s
+s@("@_lib&diameter/include/@
diff --git a/lib/diameter/test/slask/diameter_persistent_table_test.erl b/lib/diameter/test/slask/diameter_persistent_table_test.erl
deleted file mode 100644
index bb907a5777..0000000000
--- a/lib/diameter/test/slask/diameter_persistent_table_test.erl
+++ /dev/null
@@ -1,495 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-%%----------------------------------------------------------------------
-%% Purpose: Verify the persistent-table component of the Diameter application
-%%----------------------------------------------------------------------
-%%
--module(diameter_persistent_table_test).
-
--export([
- init_per_testcase/2, fin_per_testcase/2,
-
- all/1,
- suite_init/1, suite_fin/1,
-
- simple_start_and_stop/1,
- table_create_and_delete/1
-
- ]).
-
--export([t/0, t/1]).
-
--include("diameter_test_lib.hrl").
-
--record(command, {id, desc, cmd, verify}).
-
-
-t() -> diameter_test_server:t(?MODULE).
-t(Case) -> diameter_test_server:t({?MODULE, Case}).
-
-
-%% Test server callbacks
-init_per_testcase(Case, Config) ->
- diameter_test_server:init_per_testcase(Case, Config).
-
-fin_per_testcase(Case, Config) ->
- diameter_test_server:fin_per_testcase(Case, Config).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-all(suite) ->
- Cases =
- [
- simple_start_and_stop,
- table_create_and_delete
- ],
- {req, [], {conf, suite_init, Cases, suite_fin}}.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-suite_init(suite) -> [];
-suite_init(doc) -> [];
-suite_init(Config) when is_list(Config) ->
- Config.
-
-
-suite_fin(suite) -> [];
-suite_fin(doc) -> [];
-suite_fin(Config) when is_list(Config) ->
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Test case(s)
-%%
-
-simple_start_and_stop(suite) ->
- [];
-simple_start_and_stop(doc) ->
- [];
-simple_start_and_stop(Config) when is_list(Config) ->
- diameter:enable_trace(100, io),
- case diameter_persistent_table:start_link() of
- {ok, Pid} ->
- unlink(Pid);
- {error, Reason} ->
- exit({failed_starting, Reason})
- end,
-
- ok = diameter_persistent_table:stop(),
- ok.
-
-
-table_create_and_delete(suite) ->
- [];
-table_create_and_delete(doc) ->
- [];
-table_create_and_delete(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
-
- %% Command range values
- Initial = 100,
- ClientCreation = 200,
- Nice = 300,
- Evil = 400,
- End = 500,
-
- Verbosity = min,
- %% Verbosity = max,
-
- Data01 = lists:sort([{a, 10}, {b, 20}, {c, 30}]),
- Data02 = lists:sort([{x, 100}, {y, 200}, {z, 300}]),
-
- Commands =
- [
- %% Initial commands
- initial_command( Initial + 0,
- "enable trace",
- fun() -> diameter:enable_trace(Verbosity, io) end,
- ok),
- initial_command( Initial + 1,
- "start persistent-table process",
- fun() ->
- case diameter_persistent_table:start_link() of
- {ok, Pid} when is_pid(Pid) ->
- ok;
- Error ->
- Error
- end
- end,
- ok),
-
- client_create_command( ClientCreation + 1,
- "1",
- client01),
-
- client_create_command( ClientCreation + 2,
- "2",
- client02),
-
- nice_command( Nice + 1,
- "client 1 create table 1",
- fun() ->
- create_table(client01, tab01, []),
- diameter_persistent_table:which_tables()
- end,
- fun([tab01] = Tabs) ->
- {ok, Tabs};
- (Unexpected) ->
- {error, {bad_tables, Unexpected}}
- end),
-
- nice_command( Nice + 2,
- "client 1 create table 2",
- fun() ->
- create_table(client01, tab02, []),
- diameter_persistent_table:which_tables()
- end,
- fun([tab01, tab02] = Tabs) ->
- {ok, Tabs};
- ([tab02, tab01] = Tabs) ->
- {ok, Tabs};
- (Unexpected) ->
- {error, {bad_tables, Unexpected}}
- end),
-
- nice_command( Nice + 3,
- "client 2 create table 1",
- fun() ->
- create_table(client02, tab03, []),
- diameter_persistent_table:which_tables(whereis(client02))
- end,
- fun([tab03] = Tabs) ->
- {ok, Tabs};
- (Unexpected) ->
- {error, {bad_tables, Unexpected}}
- end),
-
- nice_command( Nice + 4,
- "client 1 delete table 1",
- fun() ->
- delete_table(client01, tab01),
- diameter_persistent_table:which_tables(whereis(client01))
- end,
- fun([tab02] = Tabs) ->
- {ok, Tabs};
- (Unexpected) ->
- {error, {bad_tables, Unexpected}}
- end),
-
- nice_command( Nice + 5,
- "client 1 fill in some data in tab02",
- fun() ->
- populate_table(client01, tab02, Data01),
- lists:sort(ets:tab2list(tab02))
- end,
- fun(Data) when Data =:= Data01 ->
- {ok, Data};
- (Unexpected) ->
- {error, {bad_data, Unexpected}}
- end),
-
- nice_command( Nice + 6,
- "client 2 fill in some data in tab03",
- fun() ->
- populate_table(client02, tab03, Data02),
- lists:sort(ets:tab2list(tab03))
- end,
- fun(Data) when Data =:= Data02 ->
- {ok, Data};
- (Unexpected) ->
- {error, {bad_data, Unexpected}}
- end),
-
- nice_command( Nice + 7,
- "simulate client 1 crash",
- fun() ->
- simulate_crash(client01)
- end,
- fun(ok) ->
- {ok, crashed};
- (Unexpected) ->
- {error, {bad_simulation_result, Unexpected}}
- end),
-
- client_create_command( Nice + 8,
- "1 restarted",
- client01),
-
- nice_command( Nice + 9,
- "client 1 create tab02 - verify data",
- fun() ->
- create_table(client01, tab02, []),
- lists:sort(ets:tab2list(tab02))
- end,
- fun(Data) when Data =:= Data01 ->
- {ok, Data};
- (Unexpected) ->
- {error, {bad_data, Unexpected}}
- end),
-
- evil_command( Evil + 1,
- "try (and fail) to delete the non-existing table tab04",
- fun() ->
- delete_table(client02, tab04)
- end,
- fun({error, {unknown_table, tab04}}) ->
- {ok, tab04};
- (X) ->
- {error, {bad_result, X}}
- end),
-
- evil_command( Evil + 2,
- "try (and fail) to delete a not owned table tab02",
- fun() ->
- delete_table(client02, tab02)
- end,
- fun({error, {not_owner, tab02}}) ->
- {ok, tab02};
- (X) ->
- {error, {bad_result, X}}
- end),
-
- evil_command( Evil + 3,
- "try (and fail) to create an already existing *and* owned table - tab03",
- fun() ->
- create_table(client02, tab03, [])
- end,
- fun({error, {already_owner, tab03}}) ->
- {ok, tab03};
- (X) ->
- {error, {bad_result, X}}
- end),
-
- evil_command( Evil + 4,
- "try (and fail) to create an already existing not owned table - tab02",
- fun() ->
- create_table(client02, tab02, [])
- end,
- fun({error, {not_owner, _Owner, tab02}}) ->
- {ok, tab02};
- (X) ->
- {error, {bad_result, X}}
- end),
-
- end_command( End + 1,
- "stop client01",
- fun() -> stop_client(client01) end),
-
- end_command( End + 2,
- "stop client02",
- fun() -> stop_client(client02) end),
-
- end_command( End + 2,
- "stop persistent-table",
- fun() -> diameter_persistent_table:stop() end),
-
- evil_command( Evil + 5,
- "try (and fail) to stop a not running persistent-table process",
- fun() ->
- diameter_persistent_table:stop()
- end,
- fun({'EXIT', {noproc, _}}) ->
- {ok, not_running};
- (X) ->
- {error, {bad_result, X}}
- end)
-
- ],
-
- exec(Commands).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%%
-%% Command engine
-%%
-
-exec([]) ->
- ok;
-exec([#command{id = No,
- desc = Desc,
- cmd = Cmd,
- verify = Verify}|Commands]) ->
- io:format("Executing command ~2w: ~s: ", [No, Desc]),
- case (catch Verify((catch Cmd()))) of
- {ok, OK} ->
- io:format("ok => ~p~n", [OK]),
- exec(Commands);
- {error, Reason} ->
- io:format("error => ~p~n", [Reason]),
- {error, {bad_result, No, Reason}};
- Error ->
- io:format("exit => ~p~n", [Error]),
- {error, {unexpected_result, No, Error}}
- end.
-
-initial_command(No, Desc0, Cmd, VerifyVal) when is_function(Cmd) ->
- Desc = lists:flatten(io_lib:format("Initial - ~s", [Desc0])),
- command(No, Desc, Cmd, VerifyVal).
-
-client_create_command(No, Desc0, Name) ->
- Desc = lists:flatten(io_lib:format("Client create - ~s", [Desc0])),
- Self = self(),
- Cmd = fun() -> start_client(Self, Name) end,
- command(No, Desc, Cmd, ok).
-
-nice_command(No, Desc0, Cmd, Verify)
- when is_function(Cmd) andalso is_function(Verify) ->
- Desc = lists:flatten(io_lib:format("Nice - ~s", [Desc0])),
- command(No, Desc, Cmd, Verify).
-
-evil_command(No, Desc0, Cmd, Verify)
- when is_function(Cmd) andalso is_function(Verify) ->
- Desc = lists:flatten(io_lib:format("Evil - ~s", [Desc0])),
- command(No, Desc, Cmd, Verify).
-
-end_command(No, Desc0, Cmd) when is_function(Cmd) ->
- Desc = lists:flatten(io_lib:format("End - ~s", [Desc0])),
- command(No, Desc, Cmd, ok).
-
-command(No, Desc, Cmd, Verify)
- when (is_integer(No) andalso
- is_list(Desc) andalso
- is_function(Cmd) andalso
- is_function(Verify)) ->
- #command{id = No,
- desc = Desc,
- cmd = Cmd,
- verify = Verify};
-command(No, Desc, Cmd, VerifyVal)
- when (is_integer(No) andalso
- is_list(Desc) andalso
- is_function(Cmd)) ->
- Verify =
- fun(Val) ->
- case Val of
- VerifyVal ->
- {ok, Val};
- _ ->
- {error, Val}
- end
- end,
- #command{id = No,
- desc = Desc,
- cmd = Cmd,
- verify = Verify}.
-
-
-start_client(Parent, Name) ->
- ClientPid = spawn_link(fun() -> client_init(Parent, Name) end),
- receive
- {ClientPid, started} ->
- ClientPid,
- ok;
- {'EXIT', ClientPid, Reason} ->
- {error, {failed_starting_client, Reason}}
- end.
-
-stop_client(Client) ->
- Pid = whereis(Client),
- Pid ! stop,
- receive
- {'EXIT', Pid, normal} ->
- ok
- end.
-
-create_table(Client, Tab, Opts) ->
- Self = self(),
- Pid = whereis(Client),
- Pid ! {create_table, Tab, Opts, Self},
- receive
- {Pid, created} ->
- ok;
- {Pid, {create_failed, Error}} ->
- Error
- end.
-
-delete_table(Client, Tab) ->
- Self = self(),
- Pid = whereis(Client),
- Pid ! {delete_table, Tab, Self},
- receive
- {Pid, deleted} ->
- ok;
- {Pid, {delete_failed, Error}} ->
- Error
- end.
-
-populate_table(Client, Tab, Data) ->
- Self = self(),
- Pid = whereis(Client),
- Pid ! {populate_table, Tab, Data, Self},
- receive
- {Pid, populated} ->
- ok
- end.
-
-simulate_crash(Client) ->
- Pid = whereis(Client),
- Pid ! simulate_crash,
- receive
- {'EXIT', Pid, simulated_crash} ->
- ok
- end.
-
-client_init(Parent, Name) ->
- erlang:register(Name, self()),
- process_flag(trap_exit, true),
- Parent ! {self(), started},
- client_loop().
-
-client_loop() ->
- receive
- stop ->
- exit(normal);
-
- {create_table, T, Opts, From} when is_atom(T) andalso is_list(Opts) ->
- case diameter_persistent_table:create(T, Opts) of
- ok ->
- From ! {self(), created};
- Error ->
- From ! {self(), {create_failed, Error}}
- end,
- client_loop();
-
- {delete_table, T, From} ->
- case diameter_persistent_table:delete(T) of
- ok ->
- From ! {self(), deleted};
- Error ->
- From ! {self(), {delete_failed, Error}}
- end,
- client_loop();
-
- {populate_table, Tab, Data, From} ->
- ets:insert(Tab, Data),
- From ! {self(), populated},
- client_loop();
-
- simulate_crash ->
- exit(simulated_crash)
- end.
-
diff --git a/lib/diameter/vsn.mk b/lib/diameter/vsn.mk
index 9f822e4e85..b1d3ba2241 100644
--- a/lib/diameter/vsn.mk
+++ b/lib/diameter/vsn.mk
@@ -18,7 +18,7 @@
# %CopyrightEnd%
APPLICATION = diameter
-DIAMETER_VSN = 0.9
+DIAMETER_VSN = 0.11
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(DIAMETER_VSN)$(PRE_VSN)"
diff --git a/lib/docbuilder/doc/src/notes.xml b/lib/docbuilder/doc/src/notes.xml
index d04c8dd839..95f24ea9ca 100644
--- a/lib/docbuilder/doc/src/notes.xml
+++ b/lib/docbuilder/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2007</year><year>2010</year>
+ <year>2007</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,22 @@
<p>This document describes the changes made to the DocBuilder
application.</p>
+<section><title>Docbuilder 0.9.8.11</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The docbuilder application has been deprecated and will
+ be removed in the R15 release.</p>
+ <p>
+ Own Id: OTP-9509</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Docbuilder 0.9.8.10</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/docbuilder/src/docb_gen.erl b/lib/docbuilder/src/docb_gen.erl
index 0d8d640324..75494314f1 100644
--- a/lib/docbuilder/src/docb_gen.erl
+++ b/lib/docbuilder/src/docb_gen.erl
@@ -18,6 +18,10 @@
-module(docb_gen).
-export([module/1, module/2, users_guide/1, users_guide/2]).
+-deprecated([{module,1,next_major_release},
+ {module,2,next_major_release},
+ {users_guide,1,next_major_release},
+ {users_guide,2,next_major_release}]).
-record(args, {suffix=".xml",
layout=docb_edoc_xml_cb,
diff --git a/lib/docbuilder/src/docb_main.erl b/lib/docbuilder/src/docb_main.erl
index 4f5f035a65..c20cfc8e67 100644
--- a/lib/docbuilder/src/docb_main.erl
+++ b/lib/docbuilder/src/docb_main.erl
@@ -436,11 +436,11 @@ transform(From, To, Opts, File, Tree) ->
case catch Filter:transform(File, Tree, Opts) of
%% R5C
- {'EXIT', {undef, [{Filter, transform, [File, Tree, Opts]}|_]}}->
+ {'EXIT', {undef, [{Filter, transform, [File, Tree, Opts],_}|_]}}->
%% No transformation defined
finish_transform(Tree, File, Opts, Filter);
- {'EXIT', {undef, {Filter, transform, [File, Tree, Opts]}}} ->
+ {'EXIT', {undef, {Filter, transform, [File, Tree, Opts],_}}} ->
%% No transformation defined
finish_transform(Tree, File, Opts, Filter);
@@ -507,16 +507,16 @@ pp({Tag, Optional, Args}, TagPath, Level, Filter, Opts) ->
Rule_3_result =
case catch Filter:rule(TagPath1, {Level,Optional1,Args},Opts) of
%% R5C
- {'EXIT', {undef, [{_, rule, _}|_]}} -> % No rule/3 defined
+ {'EXIT', {undef, [{_, rule, _, _}|_]}} -> % No rule/3 defined
failed;
- {'EXIT', {undef, {_, rule, _}}} -> % No rule/3 defined
+ {'EXIT', {undef, {_, rule, _, _}}} -> % No rule/3 defined
failed;
%% R5C
- {'EXIT', {function_clause, [{_, rule, _}|_]}} -> % No MATCHING rule/3
+ {'EXIT', {function_clause, [{_, rule, _, _}|_]}} -> % No MATCHING rule/3
failed;
- {'EXIT', {function_clause, {_, rule, _}}} -> % No MATCHING rule/3
+ {'EXIT', {function_clause, {_, rule, _, _}}} -> % No MATCHING rule/3
failed;
{'EXIT', What} ->
diff --git a/lib/docbuilder/src/docb_transform.erl b/lib/docbuilder/src/docb_transform.erl
index 9c7561b07b..736ac92274 100644
--- a/lib/docbuilder/src/docb_transform.erl
+++ b/lib/docbuilder/src/docb_transform.erl
@@ -18,6 +18,8 @@
-module(docb_transform).
-export([file/1, file/2]).
+-deprecated([{file,1,next_major_release},
+ {file,2,next_major_release}]).
%% file(File) -> ok | {error, Reason}
%% file(File, Opts) -> ok | {error, Reason}
diff --git a/lib/docbuilder/src/docb_xml_check.erl b/lib/docbuilder/src/docb_xml_check.erl
index 8ae5cd2eac..5912e22e7b 100644
--- a/lib/docbuilder/src/docb_xml_check.erl
+++ b/lib/docbuilder/src/docb_xml_check.erl
@@ -18,6 +18,7 @@
-module(docb_xml_check).
-export([validate/1]).
+-deprecated([{validate,1,next_major_release}]).
%% validate(File) -> ok | error | {error, badfile}
%% File = string(), file name with or without ".xml" extension
diff --git a/lib/docbuilder/test/docb_SUITE_data/cdata_problem.xml b/lib/docbuilder/test/docb_SUITE_data/cdata_problem.xml
index b7f6f5376e..b7f6f5376e 100755..100644
--- a/lib/docbuilder/test/docb_SUITE_data/cdata_problem.xml
+++ b/lib/docbuilder/test/docb_SUITE_data/cdata_problem.xml
diff --git a/lib/docbuilder/vsn.mk b/lib/docbuilder/vsn.mk
index 2475966ec2..6df438a537 100644
--- a/lib/docbuilder/vsn.mk
+++ b/lib/docbuilder/vsn.mk
@@ -1 +1 @@
-DOCB_VSN = 0.9.8.10
+DOCB_VSN = 0.9.8.11
diff --git a/lib/docbuilder/xsd/application.xsd b/lib/docbuilder/xsd/application.xsd
index eb666cb6c7..eb666cb6c7 100755..100644
--- a/lib/docbuilder/xsd/application.xsd
+++ b/lib/docbuilder/xsd/application.xsd
diff --git a/lib/docbuilder/xsd/appref.xsd b/lib/docbuilder/xsd/appref.xsd
index b63839e494..b63839e494 100755..100644
--- a/lib/docbuilder/xsd/appref.xsd
+++ b/lib/docbuilder/xsd/appref.xsd
diff --git a/lib/docbuilder/xsd/book.xsd b/lib/docbuilder/xsd/book.xsd
index b47962263a..b47962263a 100755..100644
--- a/lib/docbuilder/xsd/book.xsd
+++ b/lib/docbuilder/xsd/book.xsd
diff --git a/lib/docbuilder/xsd/chapter.xsd b/lib/docbuilder/xsd/chapter.xsd
index 4d89baa988..4d89baa988 100755..100644
--- a/lib/docbuilder/xsd/chapter.xsd
+++ b/lib/docbuilder/xsd/chapter.xsd
diff --git a/lib/docbuilder/xsd/common.entities.xsd b/lib/docbuilder/xsd/common.entities.xsd
index 52a5d35179..52a5d35179 100755..100644
--- a/lib/docbuilder/xsd/common.entities.xsd
+++ b/lib/docbuilder/xsd/common.entities.xsd
diff --git a/lib/docbuilder/xsd/common.header.xsd b/lib/docbuilder/xsd/common.header.xsd
index bfee4b8bb4..bfee4b8bb4 100755..100644
--- a/lib/docbuilder/xsd/common.header.xsd
+++ b/lib/docbuilder/xsd/common.header.xsd
diff --git a/lib/docbuilder/xsd/common.image.xsd b/lib/docbuilder/xsd/common.image.xsd
index 17054eb23c..17054eb23c 100755..100644
--- a/lib/docbuilder/xsd/common.image.xsd
+++ b/lib/docbuilder/xsd/common.image.xsd
diff --git a/lib/docbuilder/xsd/common.refs.xsd b/lib/docbuilder/xsd/common.refs.xsd
index 58b450669d..58b450669d 100755..100644
--- a/lib/docbuilder/xsd/common.refs.xsd
+++ b/lib/docbuilder/xsd/common.refs.xsd
diff --git a/lib/docbuilder/xsd/common.table.xsd b/lib/docbuilder/xsd/common.table.xsd
index cf63df4317..cf63df4317 100755..100644
--- a/lib/docbuilder/xsd/common.table.xsd
+++ b/lib/docbuilder/xsd/common.table.xsd
diff --git a/lib/docbuilder/xsd/common.xsd b/lib/docbuilder/xsd/common.xsd
index 3d43390bd8..3d43390bd8 100755..100644
--- a/lib/docbuilder/xsd/common.xsd
+++ b/lib/docbuilder/xsd/common.xsd
diff --git a/lib/docbuilder/xsd/comref.xsd b/lib/docbuilder/xsd/comref.xsd
index 61df4dd848..61df4dd848 100755..100644
--- a/lib/docbuilder/xsd/comref.xsd
+++ b/lib/docbuilder/xsd/comref.xsd
diff --git a/lib/docbuilder/xsd/cref.xsd b/lib/docbuilder/xsd/cref.xsd
index f1cbeddfff..f1cbeddfff 100755..100644
--- a/lib/docbuilder/xsd/cref.xsd
+++ b/lib/docbuilder/xsd/cref.xsd
diff --git a/lib/docbuilder/xsd/erlref.xsd b/lib/docbuilder/xsd/erlref.xsd
index f6011b7bea..f6011b7bea 100755..100644
--- a/lib/docbuilder/xsd/erlref.xsd
+++ b/lib/docbuilder/xsd/erlref.xsd
diff --git a/lib/docbuilder/xsd/fascicules.xsd b/lib/docbuilder/xsd/fascicules.xsd
index bfdb5bd604..bfdb5bd604 100755..100644
--- a/lib/docbuilder/xsd/fascicules.xsd
+++ b/lib/docbuilder/xsd/fascicules.xsd
diff --git a/lib/docbuilder/xsd/fileref.xsd b/lib/docbuilder/xsd/fileref.xsd
index 8038f2115f..8038f2115f 100755..100644
--- a/lib/docbuilder/xsd/fileref.xsd
+++ b/lib/docbuilder/xsd/fileref.xsd
diff --git a/lib/docbuilder/xsd/part.xsd b/lib/docbuilder/xsd/part.xsd
index 30d6ec0120..30d6ec0120 100755..100644
--- a/lib/docbuilder/xsd/part.xsd
+++ b/lib/docbuilder/xsd/part.xsd
diff --git a/lib/edoc/Makefile b/lib/edoc/Makefile
index e512e390e3..1add669398 100644
--- a/lib/edoc/Makefile
+++ b/lib/edoc/Makefile
@@ -13,8 +13,6 @@
# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
# AB. All Rights Reserved.''
#
-# $Id$
-#
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
diff --git a/lib/edoc/doc/Makefile b/lib/edoc/doc/Makefile
index a0f6484382..7a59809d9b 100644
--- a/lib/edoc/doc/Makefile
+++ b/lib/edoc/doc/Makefile
@@ -13,8 +13,6 @@
# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
# AB. All Rights Reserved.''
#
-# $Id: Makefile,v 1.1.1.1 2004/10/04 13:53:33 richardc Exp $
-#
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
@@ -80,12 +78,3 @@ release_docs_spec: docs
release_spec:
-
-
-
-# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-#-include make.dep
-
-
diff --git a/lib/edoc/doc/overview.edoc b/lib/edoc/doc/overview.edoc
index bd603b7a13..2af425272e 100644
--- a/lib/edoc/doc/overview.edoc
+++ b/lib/edoc/doc/overview.edoc
@@ -3,7 +3,7 @@
EDoc overview page
-@author Richard Carlsson <[email protected]>
+@author Richard Carlsson <[email protected]>
@copyright 2003-2006 Richard Carlsson
@version {@version}
@title Welcome to EDoc
@@ -277,12 +277,12 @@ The following tags can be used before a module declaration:
Examples:
```%% @author Richard Carlsson'''
-```%% @author Richard Carlsson <[email protected]>
+```%% @author Richard Carlsson <[email protected]>
%% [http://user.it.uu.se/~richardc/]'''
-```%% @author <[email protected]>'''
+```%% @author <[email protected]>'''
-```%% @author [email protected] [http://user.it.uu.se/~richardc/]'''
+```%% @author [email protected] [http://user.it.uu.se/~richardc/]'''
</dd>
<dt><a name="mtag-copyright">`@copyright'</a></dt>
@@ -1084,10 +1084,11 @@ Details:
the Erlang programming language.</li>
<li>`boolean()' is the subset of `atom()' consisting
of the atoms `true' and `false'.</li>
- <li>`char()' is a subset of
- `integer()' representing character codes.</li>
+ <li>`char()' is the subset of `integer()' representing
+ Unicode character codes: hex 000000-10FFFF.</li>
<li>`tuple()' is the set of all tuples `{...}'.</li>
- <li>`list(T)' is just an alias for `[T]'.</li>
+ <li>`list(T)' is just an alias for `[T]'; list() is an alias
+ for `list(any())', i.e., `[any()]'.</li>
<li>`nil()' is an alias for the empty list `[]'.</li>
<li>`cons(H,T)' is the list constructor. This is usually not
used directly. It is possible to recursively define `list(T)
diff --git a/lib/edoc/doc/src/Makefile b/lib/edoc/doc/src/Makefile
index 5ee0096f0f..b933094464 100644
--- a/lib/edoc/doc/src/Makefile
+++ b/lib/edoc/doc/src/Makefile
@@ -13,8 +13,6 @@
# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
# AB. All Rights Reserved.''
#
-# $Id$
-#
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
diff --git a/lib/edoc/doc/src/make.dep b/lib/edoc/doc/src/make.dep
deleted file mode 100644
index b46e36314f..0000000000
--- a/lib/edoc/doc/src/make.dep
+++ /dev/null
@@ -1,21 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex chapter.tex edoc.tex edoc_doclet.tex \
- edoc_extract.tex edoc_layout.tex edoc_lib.tex \
- edoc_run.tex part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/edoc/doc/src/notes.xml b/lib/edoc/doc/src/notes.xml
index 31a54788e5..b220067bbe 100644
--- a/lib/edoc/doc/src/notes.xml
+++ b/lib/edoc/doc/src/notes.xml
@@ -31,6 +31,57 @@
<p>This document describes the changes made to the EDoc
application.</p>
+<section><title>Edoc 0.7.9</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p><c>no_return</c> is a new built-in type. </p>
+ <p>
+ Own Id: OTP-9350</p>
+ </item>
+ <item>
+ <p>
+ synchronized with edoc development version</p>
+ <p>
+ forgot to ensure that xmerl is found in path for
+ include_lib to work</p>
+ <p>
+ fix -spec declaration that doesn't work in R13B04</p>
+ <p>
+ eliminate warnings about unused imports</p>
+ <p>
+ removed CVS-keywords from source files (Thanks to Richard
+ Carlsson )</p>
+ <p>
+ Own Id: OTP-9463</p>
+ </item>
+ <item>
+ <p>
+ Add a proplist() type</p>
+ <p>
+ Recently I was adding specs to an API and found that
+ there is no canonical proplist() type defined. (Thanks to
+ Ryan Zezeski)</p>
+ <p>
+ Own Id: OTP-9499</p>
+ </item>
+ <item>
+ <p>
+ Removed some never-matching clauses reported by dialyzer
+ Fix macro expansion in comments following Erlang types
+ URI-escape bytes as two hex digits always (reported by
+ Alfonso De Gregorio) Updated author e-mail Recognize some
+ more URI schemas in wiki text, in particular https
+ (Thanks to Richard Carlsson)</p>
+ <p>
+ Own Id: OTP-9590</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Edoc 0.7.8</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/edoc/include/Makefile b/lib/edoc/include/Makefile
index 0533c27567..5b2ad38c9d 100644
--- a/lib/edoc/include/Makefile
+++ b/lib/edoc/include/Makefile
@@ -13,8 +13,6 @@
# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
# AB. All Rights Reserved.''
#
-# $Id$
-#
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
diff --git a/lib/edoc/include/edoc_doclet.hrl b/lib/edoc/include/edoc_doclet.hrl
index a99ff1fbab..60ec7f44e4 100644
--- a/lib/edoc/include/edoc_doclet.hrl
+++ b/lib/edoc/include/edoc_doclet.hrl
@@ -18,7 +18,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% Author contact: [email protected]
+%% Author contact: [email protected]
%% =====================================================================
-define(NO_APP, []).
diff --git a/lib/edoc/priv/edoc_generate.src b/lib/edoc/priv/edoc_generate.src
index e87fdbc902..7ec89207b0 100644
--- a/lib/edoc/priv/edoc_generate.src
+++ b/lib/edoc/priv/edoc_generate.src
@@ -14,9 +14,6 @@
# Portions created by Ericsson are Copyright 1999-2000, Ericsson
# Utvecklings AB. All Rights Reserved.''
#
-# $Id$
-#
-#
#EDOC_DIR=/clearcase/otp/internal_tools/edoc
EDOC_DIR=/home/otp/sgml/edoc-%EDOC_VSN%
diff --git a/lib/edoc/src/Makefile b/lib/edoc/src/Makefile
index 9c5a9d30d1..fcb0b61292 100644
--- a/lib/edoc/src/Makefile
+++ b/lib/edoc/src/Makefile
@@ -23,7 +23,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/edoc-$(VSN)
EBIN = ../ebin
XMERL = ../../xmerl
-ERL_COMPILE_FLAGS += -I../include -I$(XMERL)/include +warn_unused_vars +nowarn_shadow_vars +warn_unused_import +warn_deprecated_guard
+ERL_COMPILE_FLAGS += -pa $(XMERL) -I../include -I$(XMERL)/include +warn_unused_vars +nowarn_shadow_vars +warn_unused_import +warn_deprecated_guard
SOURCES= \
edoc.erl edoc_data.erl edoc_doclet.erl edoc_extract.erl \
diff --git a/lib/edoc/src/edoc.erl b/lib/edoc/src/edoc.erl
index 360f2dbc9e..544465b14a 100644
--- a/lib/edoc/src/edoc.erl
+++ b/lib/edoc/src/edoc.erl
@@ -14,10 +14,8 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @copyright 2001-2007 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @version {@version}
%% @end
%% =====================================================================
@@ -60,8 +58,6 @@
-compile({no_auto_import,[error/1]}).
--import(edoc_report, [report/2, report/3, error/1, error/3]).
-
-include("edoc.hrl").
@@ -179,8 +175,8 @@ application(App, Options) when is_atom(App) ->
Dir when is_list(Dir) ->
application(App, Dir, Options);
_ ->
- report("cannot find application directory for '~s'.",
- [App]),
+ edoc_report:report("cannot find application directory for '~s'.",
+ [App]),
exit(error)
end.
@@ -663,8 +659,8 @@ read_source(Name, Opts0) ->
check_forms(Forms, Name),
Forms;
{error, R} ->
- error({"error reading file '~s'.",
- [edoc_lib:filename(Name)]}),
+ edoc_report:error({"error reading file '~s'.",
+ [edoc_lib:filename(Name)]}),
exit({error, R})
end.
@@ -688,11 +684,10 @@ check_forms(Fs, Name) ->
error_marker ->
case erl_syntax:error_marker_info(F) of
{L, M, D} ->
- error(L, Name, {format_error, M, D});
-
+ edoc_report:error(L, Name, {format_error, M, D});
Other ->
- report(Name, "unknown error in "
- "source code: ~w.", [Other])
+ edoc_report:report(Name, "unknown error in "
+ "source code: ~w.", [Other])
end,
exit(error);
_ ->
diff --git a/lib/edoc/src/edoc.hrl b/lib/edoc/src/edoc.hrl
index 31cf45ade9..98debba4ab 100644
--- a/lib/edoc/src/edoc.hrl
+++ b/lib/edoc/src/edoc.hrl
@@ -18,7 +18,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% Author contact: [email protected]
+%% Author contact: [email protected]
%% =====================================================================
%% Note: Documentation in this file is included by edoc_extract.erl
diff --git a/lib/edoc/src/edoc_data.erl b/lib/edoc/src/edoc_data.erl
index 27f43dca5a..aad0b14371 100644
--- a/lib/edoc/src/edoc_data.erl
+++ b/lib/edoc/src/edoc_data.erl
@@ -14,11 +14,9 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @private
%% @copyright 2003 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @see edoc
%% @end
%% =====================================================================
diff --git a/lib/edoc/src/edoc_doclet.erl b/lib/edoc/src/edoc_doclet.erl
index 30eef3e63a..385d20e9ae 100644
--- a/lib/edoc/src/edoc_doclet.erl
+++ b/lib/edoc/src/edoc_doclet.erl
@@ -14,10 +14,8 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @copyright 2003-2006 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @see edoc
%% @end
%% =====================================================================
@@ -52,7 +50,7 @@
-define(IMAGE, "erlang.png").
-define(NL, "\n").
--include("xmerl.hrl").
+-include_lib("xmerl/include/xmerl.hrl").
%% Sources is the list of inputs in the order they were found. Packages
%% and Modules are sorted lists of atoms without duplicates. (They
diff --git a/lib/edoc/src/edoc_extract.erl b/lib/edoc/src/edoc_extract.erl
index 5e28762c53..5a79e127f6 100644
--- a/lib/edoc/src/edoc_extract.erl
+++ b/lib/edoc/src/edoc_extract.erl
@@ -14,10 +14,8 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id: $
-%%
%% @copyright 2001-2003 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @see edoc
%% @end
%% =====================================================================
@@ -77,7 +75,7 @@ source(Forms, Comments, File, Env, Opts) when is_list(Forms) ->
source(Forms1, Comments, File, Env, Opts);
source(Forms, Comments, File, Env, Opts) ->
Tree = erl_recomment:quick_recomment_forms(Forms, Comments),
- TypeDocs = find_type_docs(Forms, Comments),
+ TypeDocs = find_type_docs(Forms, Comments, Env, File),
source1(Tree, File, Env, Opts, TypeDocs).
%% @spec source(Forms, File::filename(), Env::edoc_env(),
@@ -113,7 +111,7 @@ source(Forms, Comments, File, Env, Opts) ->
source(Forms, File, Env, Opts) when is_list(Forms) ->
source(erl_syntax:form_list(Forms), File, Env, Opts);
source(Tree, File0, Env, Opts) ->
- TypeDocs = find_type_docs(Tree, []),
+ TypeDocs = find_type_docs(Tree, [], Env, File0),
source1(Tree, File0, Env, Opts, TypeDocs).
%% Forms0 and Comments is used for extracting Erlang type documentation.
@@ -238,8 +236,8 @@ file(File, Context, Env, Opts) ->
case file:read_file(File) of
{ok, Bin} ->
{ok, text(binary_to_list(Bin), Context, Env, Opts, File)};
- {error, _R} = Error ->
- Error
+ {error, _} = Error ->
+ Error
end.
@@ -298,8 +296,8 @@ get_module_info(Forms, File) ->
{Name, Vars} = case lists:keyfind(module, 1, L) of
{module, N} when is_atom(N) ->
{N, none};
- {module, {N, _Vs} = NVs} when is_atom(N) ->
- NVs;
+ {module, {N, _}=Mod} when is_atom(N) ->
+ Mod;
_ ->
report(File, "module name missing.", []),
exit(error)
@@ -637,14 +635,17 @@ file_macros(_Context, Env) ->
%% The same thing using -type:
%% -type t() :: t1(). % Some docs of t/0;
%% Further docs of t/0.
-find_type_docs(Forms0, Comments) ->
+find_type_docs(Forms0, Comments, Env, File) ->
Tree = erl_recomment:recomment_forms(Forms0, Comments),
Forms = preprocess_forms(Tree),
- edoc_specs:docs(Forms, fun find_fun/2).
+ Env1 = add_macro_defs(edoc_macros:std_macros(Env), [], Env),
+ F = fun(C, Line) -> find_fun(C, Line, Env1, File) end,
+ edoc_specs:docs(Forms, F).
-find_fun(C0, Line) ->
+find_fun(C0, Line, Env, File) ->
C1 = comment_text(C0),
Text = lists:append([C#comment.text || C <- C1]),
Comm = #comment{line = Line, text = Text},
[Tag | _] = scan_tags([Comm]),
- Tag.
+ [Tag1] = edoc_macros:expand_tags([Tag], Env, File),
+ Tag1.
diff --git a/lib/edoc/src/edoc_layout.erl b/lib/edoc/src/edoc_layout.erl
index 3ec87b7060..951cec121c 100644
--- a/lib/edoc/src/edoc_layout.erl
+++ b/lib/edoc/src/edoc_layout.erl
@@ -14,9 +14,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id: $
-%%
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @copyright 2001-2006 Richard Carlsson
%% @see edoc
%% @end
@@ -33,7 +31,7 @@
-import(edoc_report, [report/2]).
--include("xmerl.hrl").
+-include_lib("xmerl/include/xmerl.hrl").
-define(HTML_EXPORT, xmerl_html).
-define(DEFAULT_XML_EXPORT, ?HTML_EXPORT).
@@ -959,12 +957,16 @@ local_label(R) ->
xhtml(Title, CSS, Body) ->
[{html, [?NL,
- {head, [?NL,
- {title, Title},
- ?NL] ++ CSS},
- ?NL,
- {body, [{bgcolor, "white"}], Body},
- ?NL]
+ {head, [?NL,
+ {meta, [{'http-equiv',"Content-Type"},
+ {content, "text/html; charset=ISO-8859-1"}],
+ []},
+ ?NL,
+ {title, Title},
+ ?NL] ++ CSS},
+ ?NL,
+ {body, [{bgcolor, "white"}], Body},
+ ?NL]
},
?NL].
diff --git a/lib/edoc/src/edoc_lib.erl b/lib/edoc/src/edoc_lib.erl
index 585e30a2d2..7fd8358add 100644
--- a/lib/edoc/src/edoc_lib.erl
+++ b/lib/edoc/src/edoc_lib.erl
@@ -14,10 +14,8 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @copyright 2001-2003 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @see edoc
%% @end
%% =====================================================================
@@ -40,7 +38,7 @@
-import(edoc_report, [report/2, warning/2]).
-include("edoc.hrl").
--include("xmerl.hrl").
+-include_lib("xmerl/include/xmerl.hrl").
-define(FILE_BASE, "/").
@@ -405,8 +403,13 @@ escape_uri([C | Cs]) ->
escape_uri([]) ->
[].
-escape_byte(C) ->
- "%" ++ hex_octet(C).
+escape_byte(C) when C >= 0, C =< 255 ->
+ [$%, hex_digit(C bsr 4), hex_digit(C band 15)].
+
+hex_digit(N) when N >= 0, N =< 9 ->
+ N + $0;
+hex_digit(N) when N > 9, N =< 15 ->
+ N + $a - 10.
% utf8([C | Cs]) when C > 16#7f ->
% [((C band 16#c0) bsr 6) + 16#c0, C band 16#3f ++ 16#80 | utf8(Cs)];
@@ -415,13 +418,6 @@ escape_byte(C) ->
% utf8([]) ->
% [].
-hex_octet(N) when N =< 9 ->
- [$0 + N];
-hex_octet(N) when N > 15 ->
- hex_octet(N bsr 4) ++ hex_octet(N band 15);
-hex_octet(N) ->
- [N - 10 + $a].
-
%% Please note that URI are *not* file names. Don't use the stdlib
%% 'filename' module for operations on (any parts of) URI.
@@ -494,7 +490,7 @@ uri_get_file(File0) ->
uri_get_http(URI) ->
%% Try using option full_result=false
case catch {ok, httpc:request(get, {URI,[]}, [],
- [{full_result, false}])} of
+ [{full_result, false}])} of
{'EXIT', _} ->
uri_get_http_r10(URI);
Result ->
diff --git a/lib/edoc/src/edoc_macros.erl b/lib/edoc/src/edoc_macros.erl
index 5b512cb53a..70fb38bf0a 100644
--- a/lib/edoc/src/edoc_macros.erl
+++ b/lib/edoc/src/edoc_macros.erl
@@ -16,7 +16,7 @@
%%
%% @private
%% @copyright 2001-2005 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @see edoc
%% @end
%% =====================================================================
diff --git a/lib/edoc/src/edoc_parser.yrl b/lib/edoc/src/edoc_parser.yrl
index 6943f1bdb8..4d6428f75b 100644
--- a/lib/edoc/src/edoc_parser.yrl
+++ b/lib/edoc/src/edoc_parser.yrl
@@ -22,10 +22,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% Author contact: [email protected]
-%%
-%% $Id $
-%%
+%% Author contact: [email protected]
%% =====================================================================
Nonterminals
@@ -258,7 +255,7 @@ throws -> etype where_defs:
%% "%% USA"
%% "%%"
%% "%% @private"
-%% "%% @author Richard Carlsson <[email protected]>"
+%% "%% @author Richard Carlsson <[email protected]>"
%% "%% ===================================================================="
%% .
@@ -362,10 +359,10 @@ parse_spec(S, L) ->
{ok, Spec} ->
Spec;
{error, E} ->
- throw_error(E, L)
+ throw_error({parse_spec, E}, L)
end;
{error, E, _} ->
- throw_error(E, L)
+ throw_error({parse_spec, E}, L)
end.
%% ---------------------------------------------------------------------
@@ -458,8 +455,6 @@ parse_throws(S, L) ->
-spec throw_error(term(), erl_scan:line()) -> no_return().
-throw_error({L, M, D}, _L0) ->
- throw({error,L,{format_error,M,D}});
throw_error({parse_spec, E}, L) ->
throw_error({"specification", E}, L);
throw_error({parse_typedef, E}, L) ->
@@ -471,7 +466,4 @@ throw_error({parse_throws, E}, L) ->
throw_error(parse_param, L) ->
throw({error, L, "missing parameter name"});
throw_error({Where, E}, L) when is_list(Where) ->
- throw({error,L,{"unknown error parsing ~s: ~P.",[Where,E,15]}});
-throw_error(E, L) ->
- %% Just in case.
- throw({error,L,{"unknown parse error: ~P.",[E,15]}}).
+ throw({error,L,{"unknown error parsing ~s: ~P.",[Where,E,15]}}).
diff --git a/lib/edoc/src/edoc_refs.erl b/lib/edoc/src/edoc_refs.erl
index b974cf77c1..1f578a3b83 100644
--- a/lib/edoc/src/edoc_refs.erl
+++ b/lib/edoc/src/edoc_refs.erl
@@ -16,7 +16,7 @@
%%
%% @private
%% @copyright 2003 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @see edoc
%% @see edoc_parse_ref
%% @end
diff --git a/lib/edoc/src/edoc_report.erl b/lib/edoc/src/edoc_report.erl
index ee54c60c90..9bec08ab97 100644
--- a/lib/edoc/src/edoc_report.erl
+++ b/lib/edoc/src/edoc_report.erl
@@ -14,11 +14,9 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @private
%% @copyright 2001-2003 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @see edoc
%% @end
%% =====================================================================
diff --git a/lib/edoc/src/edoc_run.erl b/lib/edoc/src/edoc_run.erl
index 96e5ea4631..48b6137ac1 100644
--- a/lib/edoc/src/edoc_run.erl
+++ b/lib/edoc/src/edoc_run.erl
@@ -14,10 +14,8 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @copyright 2003 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @see edoc
%% @end
%% =====================================================================
diff --git a/lib/edoc/src/edoc_scanner.erl b/lib/edoc/src/edoc_scanner.erl
index 9d2e6f3aed..754fcef643 100644
--- a/lib/edoc/src/edoc_scanner.erl
+++ b/lib/edoc/src/edoc_scanner.erl
@@ -13,12 +13,10 @@
%% AB. Portions created by Ericsson are Copyright 1999, Ericsson
%% Utvecklings AB. All Rights Reserved.''
%%
-%% $Id: $
-%%
%% @private
%% @copyright Richard Carlsson 2001-2003. Portions created by Ericsson
%% are Copyright 1999, Ericsson Utvecklings AB. All Rights Reserved.
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @see edoc
%% @end
diff --git a/lib/edoc/src/edoc_specs.erl b/lib/edoc/src/edoc_specs.erl
index 519ade726f..5acf8ac0d5 100644
--- a/lib/edoc/src/edoc_specs.erl
+++ b/lib/edoc/src/edoc_specs.erl
@@ -27,7 +27,6 @@
-include("edoc.hrl").
-include("edoc_types.hrl").
--type proplist() :: [proplists:property()].
-type syntaxTree() :: erl_syntax:syntaxTree().
-define(TOP_TYPE, term).
@@ -87,8 +86,9 @@ dummy_spec(Form) ->
#tag{name = spec, line = element(2, hd(TypeSpecs)),
origin = code, data = S}.
--spec docs(Forms::[syntaxTree()], CommentFun) -> dict() when
- CommentFun :: fun(([syntaxTree()], Line :: term()) -> #tag{}).
+-spec docs(Forms::[syntaxTree()],
+ CommentFun :: fun( ([syntaxTree()], Line :: term()) -> #tag{} ))
+ -> dict().
%% @doc Find comments after -type/-opaque declarations.
%% Postcomments "inside" the type are skipped.
@@ -98,7 +98,7 @@ docs(Forms, CommentFun) ->
-type entry() :: #entry{}.
-type module_info() :: #module{}.
-type entries() :: [entry()].
--spec add_data(Entries::entries(), Options::proplist(),
+-spec add_data(Entries::entries(), Options::proplists:proplist(),
File::file:filename(), Module::module_info()) -> entries().
%% @doc Create tags a la EDoc for Erlang specifications and types.
@@ -305,8 +305,6 @@ d2e({ann_type,_,[V, T0]}) ->
%% layout module.
T = d2e(T0),
?add_t_ann(T, element(3, V));
-d2e({type,_,no_return,[]}) ->
- #t_type{name = #t_name{name = none}};
d2e({remote_type,_,[{atom,_,M},{atom,_,F},Ts0]}) ->
Ts = d2e(Ts0),
typevar_anno(#t_type{name = #t_name{module = M, name = F}, args = Ts}, Ts);
diff --git a/lib/edoc/src/edoc_tags.erl b/lib/edoc/src/edoc_tags.erl
index 8ee8f87b5f..2d986988c2 100644
--- a/lib/edoc/src/edoc_tags.erl
+++ b/lib/edoc/src/edoc_tags.erl
@@ -14,11 +14,9 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @private
%% @copyright 2001-2003 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @see edoc
%% @end
%% =====================================================================
diff --git a/lib/edoc/src/edoc_types.erl b/lib/edoc/src/edoc_types.erl
index 1ded63dffe..60c6cecb97 100644
--- a/lib/edoc/src/edoc_types.erl
+++ b/lib/edoc/src/edoc_types.erl
@@ -14,11 +14,9 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @private
%% @copyright 2001-2003 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @see edoc
%% @end
%% =====================================================================
@@ -34,13 +32,13 @@
%% @headerfile "edoc_types.hrl"
-include("edoc_types.hrl").
--include("xmerl.hrl").
+-include_lib("xmerl/include/xmerl.hrl").
is_predefined(any, 0) -> true;
is_predefined(atom, 0) -> true;
is_predefined(binary, 0) -> true;
-is_predefined(bool, 0) -> true;
+is_predefined(bool, 0) -> true; % kept for backwards compatibility
is_predefined(char, 0) -> true;
is_predefined(cons, 2) -> true;
is_predefined(deep_string, 0) -> true;
@@ -51,6 +49,7 @@ is_predefined(list, 0) -> true;
is_predefined(list, 1) -> true;
is_predefined(nil, 0) -> true;
is_predefined(none, 0) -> true;
+is_predefined(no_return, 0) -> true;
is_predefined(number, 0) -> true;
is_predefined(pid, 0) -> true;
is_predefined(port, 0) -> true;
diff --git a/lib/edoc/src/edoc_types.hrl b/lib/edoc/src/edoc_types.hrl
index 1353bfb93a..05c61d70ff 100644
--- a/lib/edoc/src/edoc_types.hrl
+++ b/lib/edoc/src/edoc_types.hrl
@@ -18,7 +18,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% Author contact: [email protected]
+%% Author contact: [email protected]
%% =====================================================================
%% Type specification data structures
diff --git a/lib/edoc/src/edoc_wiki.erl b/lib/edoc/src/edoc_wiki.erl
index 9a31bc9a82..5c71658af5 100644
--- a/lib/edoc/src/edoc_wiki.erl
+++ b/lib/edoc/src/edoc_wiki.erl
@@ -14,11 +14,9 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @private
%% @copyright 2001-2003 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @see edoc
%% @end
%% =====================================================================
@@ -70,7 +68,7 @@
-export([parse_xml/2, expand_text/2]).
-include("edoc.hrl").
--include("xmerl.hrl").
+-include_lib("xmerl/include/xmerl.hrl").
-define(BASE_HEADING, 3).
@@ -82,8 +80,8 @@ parse_xml(Data, Line) ->
parse_xml_1(Text, Line) ->
Text1 = "<doc>" ++ Text ++ "</doc>",
- Options = [{line, Line}, {encoding, "iso-8859-1"}],
- case catch {ok, xmerl_scan:string(Text1, Options)} of
+ Opts = [{line, Line}, {encoding, 'iso-8859-1'}],
+ case catch {ok, xmerl_scan:string(Text1, Opts)} of
{ok, {E, _}} ->
E#xmlElement.content;
{'EXIT', {fatal, {Reason, L, _C}}} ->
@@ -251,10 +249,20 @@ expand_triple([], L, _, L0) ->
expand_uri("http:/" ++ Cs, L, As) ->
expand_uri(Cs, L, "/:ptth", As);
+expand_uri("https:/" ++ Cs, L, As) ->
+ expand_uri(Cs, L, "/:sptth", As);
expand_uri("ftp:/" ++ Cs, L, As) ->
expand_uri(Cs, L, "/:ptf", As);
expand_uri("file:/" ++ Cs, L, As) ->
expand_uri(Cs, L, "/:elif", As);
+expand_uri("mailto:/" ++ Cs, L, As) ->
+ expand_uri(Cs, L, "/:otliam", As);
+expand_uri("nfs:/" ++ Cs, L, As) ->
+ expand_uri(Cs, L, "/:sfn", As);
+expand_uri("shttp:/" ++ Cs, L, As) ->
+ expand_uri(Cs, L, "/:ptths", As);
+expand_uri("xmpp:/" ++ Cs, L, As) ->
+ expand_uri(Cs, L, "/:ppmx", As);
expand_uri(Cs, L, As) ->
expand(Cs, L, [$[ | As]).
@@ -360,10 +368,7 @@ par_text(Cs, As, Bs, E, Es) ->
[] -> Bs;
_ -> [#xmlElement{name = p, content = Es1} | Bs]
end,
- Bs1 = case Ss of
- [] -> Bs0;
- _ -> [#xmlText{value = Ss} | Bs0]
- end,
+ Bs1 = [#xmlText{value = Ss} | Bs0],
case Cs2 of
[] ->
par(Es, [], Bs1);
diff --git a/lib/edoc/src/otpsgml_layout.erl b/lib/edoc/src/otpsgml_layout.erl
index 45f74b299e..2c4cd919bb 100644
--- a/lib/edoc/src/otpsgml_layout.erl
+++ b/lib/edoc/src/otpsgml_layout.erl
@@ -14,9 +14,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @author Kenneth Lundin <[email protected]>
%% @copyright 2001-2004 Richard Carlsson
%% @see edoc_layout
@@ -34,7 +32,7 @@
-import(edoc_report, [report/2]).
--include("xmerl.hrl").
+-include_lib("xmerl/include/xmerl.hrl").
-define(SGML_EXPORT, xmerl_otpsgml).
-define(DEFAULT_XML_EXPORT, ?SGML_EXPORT).
diff --git a/lib/edoc/test/edoc_SUITE.erl b/lib/edoc/test/edoc_SUITE.erl
index 0d57591e3e..5b95c35756 100644
--- a/lib/edoc/test/edoc_SUITE.erl
+++ b/lib/edoc/test/edoc_SUITE.erl
@@ -13,8 +13,6 @@
%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
%% AB. All Rights Reserved.''
%%
-%% $Id$
-%%
-module(edoc_SUITE).
-include_lib("test_server/include/test_server.hrl").
diff --git a/lib/edoc/vsn.mk b/lib/edoc/vsn.mk
index 30cf191ffc..22f225dd9b 100644
--- a/lib/edoc/vsn.mk
+++ b/lib/edoc/vsn.mk
@@ -1 +1 @@
-EDOC_VSN = 0.7.8
+EDOC_VSN = 0.7.9
diff --git a/lib/erl_docgen/doc/src/notes.xml b/lib/erl_docgen/doc/src/notes.xml
index f79639769f..6a0eece56d 100644
--- a/lib/erl_docgen/doc/src/notes.xml
+++ b/lib/erl_docgen/doc/src/notes.xml
@@ -30,7 +30,51 @@
</header>
<p>This document describes the changes made to the erl_docgen application.</p>
- <section><title>Erl_Docgen 0.2.5</title>
+ <section><title>Erl_Docgen 0.2.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Bug fixes. </p>
+ <p>
+ Own Id: OTP-9360</p>
+ </item>
+ <item>
+ <p> The manpage generation has been improved. </p>
+ <p>
+ Own Id: OTP-9541 Aux Id: OTP-9550 </p>
+ </item>
+ <item>
+ <p> Fix eix file generation for new function spec
+ references. </p>
+ <p>
+ Own Id: OTP-9562</p>
+ </item>
+ <item>
+ <p> The function signatures in the pdf files was not in a
+ fixed font. </p>
+ <p>
+ Own Id: OTP-9563</p>
+ </item>
+ <item>
+ <p> The parts level in the system documentation was
+ missing in the bookmarks menu for the pdf and the
+ copyright year generation for PDF was not correct. </p>
+ <p>
+ Own Id: OTP-9576</p>
+ </item>
+ <item>
+ <p> The indentation after <c>Warning:</c> and
+ <c>Note:</c> in manpages has been improved. </p>
+ <p>
+ Own Id: OTP-9588</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Docgen 0.2.5</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/erl_docgen/priv/bin/xref_mod_app.escript b/lib/erl_docgen/priv/bin/xref_mod_app.escript
index 13671ef2f8..c2bd62f9e0 100755
--- a/lib/erl_docgen/priv/bin/xref_mod_app.escript
+++ b/lib/erl_docgen/priv/bin/xref_mod_app.escript
@@ -73,7 +73,12 @@ usage() ->
modapp(TopDir) ->
AppDirs = filelib:wildcard(filename:join([TopDir,"lib","*"])),
AM = [appmods(D) || D <- AppDirs],
- lists:keysort(1, [{M,A} || {A,Ms} <- AM, M <- Ms]).
+ ERTS = [preloaded(TopDir) || lists:keyfind("erts", 1, AM) =:= false],
+ lists:keysort(1, [{M,A} || {A,Ms} <- ERTS++AM, M <- Ms]).
+
+preloaded(TopDir) ->
+ {"preloaded",Mods} = appmods(filename:join([TopDir,"erts","preloaded"])),
+ {"erts",Mods}.
%% It's OK if too much data is generated as long as all applications
%% and all modules are mentioned.
diff --git a/lib/erl_docgen/priv/xsl/db_eix.xsl b/lib/erl_docgen/priv/xsl/db_eix.xsl
index 4545322bc2..7a648ddfd7 100644
--- a/lib/erl_docgen/priv/xsl/db_eix.xsl
+++ b/lib/erl_docgen/priv/xsl/db_eix.xsl
@@ -22,10 +22,16 @@
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ extension-element-prefixes="exsl"
xmlns:fn="http://www.w3.org/2005/02/xpath-functions">
<xsl:output method="text" encoding="UTF-8" indent="no"/>
+ <xsl:param name="specs_file" select="''"/>
+ <xsl:variable name="i" select="document($specs_file)"></xsl:variable>
+
+
<!-- Book -->
<xsl:template match="/book">
<xsl:text>%% &#10;%% Search data file for </xsl:text><xsl:value-of select="$appname"/><xsl:text> </xsl:text><xsl:value-of select="$appver"/>
@@ -50,9 +56,7 @@
<xsl:template match="erlref">
<xsl:text>{"</xsl:text><xsl:value-of select="module"/><xsl:text>.html", {function, {"</xsl:text><xsl:value-of select="$appname"/>
<xsl:text>", "</xsl:text><xsl:value-of select="module"/><xsl:text>"}},&#10;[&#10;</xsl:text>
- <xsl:apply-templates select="funcs">
- <xsl:with-param name="mod" select="module"/>
- </xsl:apply-templates>
+ <xsl:apply-templates select="funcs"/>
<xsl:text>]}.&#10;</xsl:text>
<xsl:text>{"</xsl:text><xsl:value-of select="module"/><xsl:text>.html", {module, "</xsl:text>
<xsl:value-of select="$appname"/><xsl:text>"}, ["</xsl:text><xsl:value-of select="module"/><xsl:text>"]}.&#10;</xsl:text>
@@ -62,9 +66,7 @@
<xsl:template match="cref">
<xsl:text>{"</xsl:text><xsl:value-of select="lib"/><xsl:text>.html", {function, {"</xsl:text><xsl:value-of select="$appname"/>
<xsl:text>", "</xsl:text><xsl:value-of select="lib"/><xsl:text>"}}, [&#10;</xsl:text>
- <xsl:apply-templates select="funcs">
- <xsl:with-param name="mod" select="lib"/>
- </xsl:apply-templates>
+ <xsl:apply-templates select="funcs"/>
<xsl:text>]}.&#10;</xsl:text>
<xsl:text>{"</xsl:text><xsl:value-of select="lib"/><xsl:text>.html", {clib, "</xsl:text>
<xsl:value-of select="$appname"/><xsl:text>"}, ["</xsl:text><xsl:value-of select="lib"/><xsl:text>"]}.&#10;</xsl:text>
@@ -91,69 +93,157 @@
<!-- Funcs -->
<xsl:template match="funcs">
- <xsl:param name="mod"/>
<xsl:variable name="lastfuncsblock">
<xsl:value-of select="position() = last()"/>
</xsl:variable>
<xsl:apply-templates select="func/name">
- <xsl:with-param name="mod" select="$mod"/>
<xsl:with-param name="lastfuncsblock" select="$lastfuncsblock"/>
</xsl:apply-templates>
</xsl:template>
+ <xsl:template match="name">
+ <xsl:param name="lastfuncsblock"/>
+ <xsl:choose>
+ <!-- @arity is mandatory when referring to a specification -->
+ <xsl:when test="string-length(@arity) > 0">
+ <xsl:call-template name="spec_name"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="err">
+ <xsl:param name="f"/>
+ <xsl:param name="m"/>
+ <xsl:param name="n"/>
+ <xsl:param name="a"/>
+ <xsl:param name="s"/>
+ <xsl:message terminate="yes">
+ Error <xsl:if test="$f != ''">in <xsl:value-of select ="$f"/>:</xsl:if>
+ <xsl:if test="$m != ''"><xsl:value-of select ="$m"/>:</xsl:if>
+ <xsl:value-of select="$n"/>
+ <xsl:if test="$a != ''">/<xsl:value-of
+ select ="$a"/></xsl:if>: <xsl:value-of select="$s"/>
+ </xsl:message>
+ </xsl:template>
+ <xsl:template name="find_spec">
+ <xsl:variable name="curModule" select="ancestor::erlref/module"/>
+ <xsl:variable name="mod" select="@mod"/>
+ <xsl:variable name="name" select="@name"/>
+ <xsl:variable name="arity" select="@arity"/>
+ <xsl:variable name="clause_i" select="@clause_i"/>
+ <xsl:variable name="spec0" select=
+ "$i/specs/module[@name=$curModule]/spec
+ [name=$name and arity=$arity
+ and (string-length($mod) = 0 or module = $mod)]"/>
+ <xsl:variable name="spec" select="$spec0[string-length($clause_i) = 0
+ or position() = $clause_i]"/>
- <xsl:template match="name">
- <xsl:param name="mod"/>
+ <xsl:if test="count($spec) != 1">
+ <xsl:variable name="why">
+ <xsl:choose>
+ <xsl:when test="count($spec) > 1">ambiguous spec</xsl:when>
+ <xsl:when test="count($spec) = 0">unknown spec</xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="err">
+ <xsl:with-param name="f" select="$curModule"/>
+ <xsl:with-param name="m" select="$mod"/>
+ <xsl:with-param name="n" select="$name"/>
+ <xsl:with-param name="a" select="$arity"/>
+ <xsl:with-param name="s" select="$why"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:copy-of select="$spec"/>
+ </xsl:template>
+
+
+ <xsl:template name="spec_name">
+ <xsl:param name="lastfuncsblock"/>
+ <xsl:variable name="fname" select="@name"/>
+ <xsl:variable name="arity" select="@arity"/>
+ <xsl:variable name="spec0">
+ <xsl:call-template name="find_spec"/>
+ </xsl:variable>
+ <xsl:variable name="spec" select="exsl:node-set($spec0)/spec"/>
+
+ <xsl:variable name="tmpstring">
+ <xsl:value-of select="substring-before($spec/contract/clause/head, ' ->')"/>
+ </xsl:variable>
+
+ <xsl:text> {"</xsl:text><xsl:value-of select="$fname"/>
+ <xsl:text>", "</xsl:text><xsl:value-of select="$tmpstring"/>
+ <xsl:text>", "</xsl:text><xsl:value-of select="$fname"/>
+ <xsl:text>-</xsl:text><xsl:value-of select="$arity"/><xsl:text>"}</xsl:text>
+
+ <xsl:choose>
+ <xsl:when test="($lastfuncsblock = 'true') and (position() = last())">
+ <xsl:text>&#10;</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>,&#10;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ </xsl:template>
+
+
+ <xsl:template name="name">
<xsl:param name="lastfuncsblock"/>
<xsl:variable name="tmpstring">
<xsl:value-of select="substring-before(substring-after(., '('), '->')"/>
- </xsl:variable>
+ </xsl:variable>
+
<xsl:variable name="ustring">
<xsl:choose>
- <xsl:when test="string-length($tmpstring) > 0">
- <xsl:call-template name="remove-paren">
- <xsl:with-param name="string" select="$tmpstring"/>
- </xsl:call-template>
- </xsl:when>
- <xsl:otherwise>
- <xsl:call-template name="remove-paren">
- <xsl:with-param name="string" select="substring-after(., '(')"/>
- </xsl:call-template>
- </xsl:otherwise>
+ <xsl:when test="string-length($tmpstring) > 0">
+ <xsl:call-template name="remove-paren">
+ <xsl:with-param name="string" select="$tmpstring"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="remove-paren">
+ <xsl:with-param name="string" select="substring-after(., '(')"/>
+ </xsl:call-template>
+ </xsl:otherwise>
</xsl:choose>
- </xsl:variable>
+ </xsl:variable>
+
<xsl:variable name="arity">
<xsl:call-template name="calc-arity">
- <xsl:with-param name="string" select="substring-before($ustring, ')')"/>
- <xsl:with-param name="no-of-pars" select="0"/>
+ <xsl:with-param name="string" select="substring-before($ustring, ')')"/>
+ <xsl:with-param name="no-of-pars" select="0"/>
</xsl:call-template>
- </xsl:variable>
+ </xsl:variable>
+
<xsl:variable name="fname">
<xsl:choose>
- <xsl:when test="ancestor::cref">
- <xsl:value-of select="substring-before(nametext, '(')"/>
- </xsl:when>
- <xsl:when test="ancestor::erlref">
- <xsl:variable name="fname1">
- <xsl:value-of select="substring-before(., '(')"/>
- </xsl:variable>
- <xsl:variable name="fname2">
- <xsl:value-of select="substring-after($fname1, 'erlang:')"/>
- </xsl:variable>
- <xsl:choose>
- <xsl:when test="string-length($fname2) > 0">
- <xsl:value-of select="$fname2"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="$fname1"/>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:when>
+ <xsl:when test="ancestor::cref">
+ <xsl:value-of select="substring-before(nametext, '(')"/>
+ </xsl:when>
+ <xsl:when test="ancestor::erlref">
+ <xsl:variable name="fname1">
+ <xsl:value-of select="substring-before(., '(')"/>
+ </xsl:variable>
+ <xsl:variable name="fname2">
+ <xsl:value-of select="substring-after($fname1, 'erlang:')"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="string-length($fname2) > 0">
+ <xsl:value-of select="$fname2"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$fname1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
</xsl:choose>
- </xsl:variable>
+ </xsl:variable>
+
<xsl:text> {"</xsl:text><xsl:value-of select="$fname"/>
<xsl:text>", "</xsl:text><xsl:value-of select="$fname"/>
<xsl:text>(</xsl:text><xsl:value-of select="normalize-space($tmpstring)"/>
diff --git a/lib/erl_docgen/priv/xsl/db_html.xsl b/lib/erl_docgen/priv/xsl/db_html.xsl
index 982572aeef..a9052f29e5 100644
--- a/lib/erl_docgen/priv/xsl/db_html.xsl
+++ b/lib/erl_docgen/priv/xsl/db_html.xsl
@@ -433,6 +433,8 @@
<!-- Search "local types" as well -->
<xsl:variable name="local_types"
select="ancestor::desc/preceding-sibling::type
+ [string-length(@name) > 0]
+ | ancestor::type_desc/preceding-sibling::type
[string-length(@name) > 0]"/>
<xsl:variable name="has_anno_in_local_type">
<xsl:for-each select="$local_types">
diff --git a/lib/erl_docgen/priv/xsl/db_man.xsl b/lib/erl_docgen/priv/xsl/db_man.xsl
index 25b62f68c5..0aca74bc97 100644
--- a/lib/erl_docgen/priv/xsl/db_man.xsl
+++ b/lib/erl_docgen/priv/xsl/db_man.xsl
@@ -25,12 +25,12 @@
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
- <xsl:preserve-space elements="code pre"/>
+ <xsl:preserve-space elements="code pre p"/>
<xsl:strip-space elements="*"/>
<xsl:output method="text" encoding="UTF-8" indent="no"/>
<!-- Start of Dialyzer type/spec tags. See also the templates
- matching "name" and "seealso"
+ matching "name", "seealso" and "br"
-->
<!-- Note: specs data for *one* module (as opposed to html and pdf) -->
@@ -137,8 +137,9 @@
(there is no spec with more than one clause) -->
<xsl:if test="count($clause/guard) > 0 or count($type) > 0">
<xsl:text>&#10;.RS</xsl:text>
- <xsl:text>&#10;.TP</xsl:text>
- <xsl:text>&#10;Types</xsl:text>
+ <xsl:text>&#10;.LP</xsl:text>
+ <xsl:text>&#10;Types:&#10;</xsl:text>
+ <xsl:text>&#10;.RS 3</xsl:text>
<xsl:choose>
<xsl:when test="$output_subtypes">
@@ -164,6 +165,8 @@
<xsl:with-param name="type_desc" select="$type_desc"/>
<xsl:with-param name="local_types" select="$local_types"/>
</xsl:call-template>
+ <xsl:text>&#10;.RE</xsl:text>
+
<xsl:text>&#10;.RE</xsl:text>
</xsl:if>
@@ -223,10 +226,13 @@
<xsl:for-each select="$subtype">
<xsl:variable name="tname" select="typename"/>
- <xsl:text>&#10;</xsl:text>
- <xsl:apply-templates select="string"/>
- <xsl:text>&#10;.br</xsl:text>
- <xsl:apply-templates select="$type_desc[@variable = $tname]"/>
+ <xsl:variable name="string" select="string"/>
+ <xsl:if test="string-length($string) > 0">
+ <xsl:text>&#10;</xsl:text>
+ <xsl:apply-templates select="$string"/>
+ <xsl:text>&#10;.br</xsl:text>
+ <xsl:apply-templates select="$type_desc[@variable = $tname]"/>
+ </xsl:if>
</xsl:for-each>
</xsl:template>
@@ -254,8 +260,8 @@
<!-- Similar to <d> -->
<xsl:template match="type_desc">
- <xsl:text>&#10;</xsl:text><xsl:apply-templates/>
- <xsl:text>&#10;.br</xsl:text>
+ <xsl:text>&#10;.RS 2&#10;</xsl:text><xsl:apply-templates/>
+ <xsl:text>&#10;.RE</xsl:text>
</xsl:template>
<!-- Datatypes -->
@@ -319,8 +325,7 @@
</xsl:template>
<xsl:template match="typehead">
- <xsl:text>&#10;.nf&#10;</xsl:text>
- <xsl:text>&#10;.B&#10;</xsl:text>
+ <xsl:text>&#10;.nf&#10;&#10;</xsl:text>
<xsl:apply-templates/>
<xsl:text>&#10;.br</xsl:text>
<xsl:text>&#10;.fi</xsl:text>
@@ -345,6 +350,13 @@
<xsl:text>&#10;.br</xsl:text>
</xsl:template>
+ <!-- The name of data types -->
+ <xsl:template match="marker">
+ <xsl:if test="string-length(.) != 0">
+ <xsl:text>\fB</xsl:text><xsl:apply-templates/><xsl:text>\fR\&amp;</xsl:text>
+ </xsl:if>
+ </xsl:template>
+
<!-- Used both in <datatype> and in <func>! -->
<xsl:template match="anno">
<xsl:variable name="curModule" select="ancestor::erlref/module"/>
@@ -363,6 +375,8 @@
<!-- Search "local types" as well -->
<xsl:variable name="local_types"
select="ancestor::desc/preceding-sibling::type
+ [string-length(@name) > 0]
+ | ancestor::type_desc/preceding-sibling::type
[string-length(@name) > 0]"/>
<xsl:variable name="has_anno_in_local_type">
<xsl:for-each select="$local_types">
@@ -463,13 +477,13 @@
<xsl:text>&#10;.TP 2&#10;</xsl:text>
<xsl:text>*&#10;</xsl:text>
<xsl:apply-templates/>
- <xsl:text>&#10;.LP&#10;</xsl:text>
+ <xsl:text>&#10;.LP</xsl:text>
</xsl:template>
<xsl:template match="taglist">
<xsl:text>&#10;.RS 2</xsl:text>
<xsl:apply-templates select="tag|item"/>
- <xsl:text>&#10;.RE&#10;</xsl:text>
+ <xsl:text>&#10;.RE</xsl:text>
</xsl:template>
<xsl:template match="taglist/tag">
@@ -492,7 +506,7 @@
</xsl:when>
<xsl:otherwise>
<xsl:text>&#10;.RS 2</xsl:text>
- <xsl:text>&#10;.LP&#10;&#10;.LP&#10;</xsl:text>
+ <xsl:text>&#10;.LP&#10;</xsl:text>
<xsl:value-of select="$content"/>
<xsl:text>&#10;.RE</xsl:text>
</xsl:otherwise>
@@ -501,18 +515,42 @@
<!-- Note -->
<xsl:template match="note">
- <xsl:text>&#10;.SS Note:</xsl:text>
+ <xsl:text>&#10;.LP&#10;</xsl:text>
+ <xsl:text>&#10;.RS -4</xsl:text>
+ <xsl:text>&#10;.B&#10;</xsl:text>
+ <xsl:text>Note:</xsl:text>
+ <xsl:text>&#10;.RE</xsl:text>
<xsl:apply-templates/>
<xsl:text>&#10;</xsl:text>
</xsl:template>
<!-- Warning -->
<xsl:template match="warning">
- <xsl:text>&#10;.SS Warning:</xsl:text>
+ <xsl:text>&#10;.LP&#10;</xsl:text>
+ <xsl:text>&#10;.RS -4</xsl:text>
+ <xsl:text>&#10;.B&#10;</xsl:text>
+ <xsl:text>Warning:</xsl:text>
+ <xsl:text>&#10;.RE</xsl:text>
<xsl:apply-templates/>
<xsl:text>&#10;</xsl:text>
</xsl:template>
+ <xsl:template match="warning/p | note/p">
+ <xsl:variable name="content">
+ <xsl:text>&#10;</xsl:text>
+ <xsl:apply-templates/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="position() = 1">
+ <xsl:value-of select="$content"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>&#10;.LP</xsl:text>
+ <xsl:value-of select="$content"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
<!-- Paragraph -->
<xsl:template match="p">
<xsl:text>&#10;.LP&#10;</xsl:text>
@@ -527,7 +565,16 @@
</xsl:template>
<xsl:template match="br">
- <xsl:text>&#10;.br&#10;</xsl:text>
+ <xsl:choose>
+ <xsl:when test="ancestor::head">
+ <!-- The header of Dialyzer specs.
+ .B makes next line appear in bold face -->
+ <xsl:text>&#10;.B&#10;</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>&#10;.br&#10;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
</xsl:template>
<xsl:template match="c">
@@ -545,17 +592,17 @@
<!-- Code -->
<xsl:template match="code">
<xsl:text>&#10;.LP&#10;</xsl:text>
- <xsl:text>&#10;.nf&#10;</xsl:text>
+ <xsl:text>.nf&#10;</xsl:text>
<xsl:apply-templates/>
- <xsl:text>&#10;.fi&#10;</xsl:text>
+ <xsl:text>&#10;.fi</xsl:text>
</xsl:template>
<!-- Pre -->
<xsl:template match="pre">
<xsl:text>&#10;.LP&#10;</xsl:text>
- <xsl:text>&#10;.nf&#10;</xsl:text>
+ <xsl:text>.nf&#10;</xsl:text>
<xsl:apply-templates/>
- <xsl:text>&#10;.fi&#10;</xsl:text>
+ <xsl:text>&#10;.fi</xsl:text>
</xsl:template>
@@ -713,24 +760,26 @@
<!-- The case where @name != 0 is taken care of in "type_name" -->
<xsl:if test="string-length(@name) = 0 and string-length(@variable) = 0">
<xsl:text>&#10;.RS</xsl:text>
- <xsl:text>&#10;.TP</xsl:text>
- <xsl:text>&#10;Types</xsl:text>
+ <xsl:text>&#10;.LP</xsl:text>
+ <xsl:text>&#10;Types:&#10;</xsl:text>
+ <xsl:text>&#10;.RS 3</xsl:text>
<xsl:apply-templates/>
<xsl:text>&#10;.RE</xsl:text>
+ <xsl:text>&#10;.RE</xsl:text>
</xsl:if>
</xsl:template>
<!-- V -->
<xsl:template match="v">
- <xsl:text>&#10;</xsl:text><xsl:value-of select="normalize-space(text())"/>
+ <xsl:text>&#10;</xsl:text><xsl:apply-templates/>
<xsl:text>&#10;.br</xsl:text>
</xsl:template>
<!-- D -->
<xsl:template match="d">
- <xsl:text>&#10;</xsl:text><xsl:apply-templates/>
- <xsl:text>&#10;.br</xsl:text>
+ <xsl:text>&#10;.RS 2&#10;</xsl:text><xsl:apply-templates/>
+ <xsl:text>&#10;.RE</xsl:text>
</xsl:template>
<!-- Desc -->
@@ -786,7 +835,36 @@
<!-- Replace ' by \&' ans . by \&. -->
<xsl:template match="text()">
<xsl:variable name="startstring">
- <xsl:value-of select="normalize-space()"/><xsl:text> </xsl:text>
+ <xsl:value-of select="normalize-space()"/>
+ </xsl:variable>
+ <!-- 'C' is just any character but whitespace -->
+ <xsl:variable name="tmp" select="normalize-space(concat('C',.,'C'))"/>
+ <xsl:variable name="space_before">
+ <xsl:choose>
+ <!-- '<p>A<marker id="swamp"/> swamp</p>' does not work; instead:
+ '<p>A <marker id="swamp"/>swamp</p>' -->
+ <xsl:when test="starts-with($tmp, 'C ')
+ and not (string(preceding-sibling::*[position()=1]) = ''
+ and parent::p)">
+ <!-- and not (position() = 1 and parent::p)"> -->
+ <xsl:text> </xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="space_after">
+ <xsl:choose>
+ <xsl:when test="substring($tmp, string-length($tmp)-1,1) = ' '
+ and $startstring != ''
+ and not (position() = last() and parent::p)">
+ <xsl:text> </xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text/>
+ </xsl:otherwise>
+ </xsl:choose>
</xsl:variable>
<xsl:variable name="rep1">
<xsl:call-template name="replace-string">
@@ -802,11 +880,16 @@
<xsl:with-param name="with" select="&quot;\&amp;&apos;&quot;" />
</xsl:call-template>
</xsl:variable>
- <xsl:call-template name="replace-string">
- <xsl:with-param name="text" select="$rep2" />
- <xsl:with-param name="replace" select="&quot;.&quot;" />
- <xsl:with-param name="with" select="&quot;\&amp;.&quot;" />
- </xsl:call-template>
+ <xsl:variable name="reply">
+ <xsl:call-template name="replace-string">
+ <xsl:with-param name="text" select="$rep2" />
+ <xsl:with-param name="replace" select="&quot;.&quot;" />
+ <xsl:with-param name="with" select="&quot;\&amp;.&quot;" />
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="$space_before"/>
+ <xsl:value-of select="$reply"/>
+ <xsl:value-of select="$space_after"/>
</xsl:template>
<!-- Template replace-string is borrowed at http://www.dpawson.co.uk/xsl/sect2/replace.html -->
diff --git a/lib/erl_docgen/priv/xsl/db_pdf.xsl b/lib/erl_docgen/priv/xsl/db_pdf.xsl
index 5119e3e36a..48a7a026c1 100644
--- a/lib/erl_docgen/priv/xsl/db_pdf.xsl
+++ b/lib/erl_docgen/priv/xsl/db_pdf.xsl
@@ -410,6 +410,8 @@
<!-- Search "local types" as well -->
<xsl:variable name="local_types"
select="ancestor::desc/preceding-sibling::type
+ [string-length(@name) > 0]
+ | ancestor::type_desc/preceding-sibling::type
[string-length(@name) > 0]"/>
<xsl:variable name="has_anno_in_local_type">
<xsl:for-each select="$local_types">
@@ -730,22 +732,23 @@
<xsl:template name="bookmarks1">
<xsl:param name="entries"/>
<xsl:if test="$entries != ''">
+ <xsl:for-each select="$entries">
- <fo:bookmark internal-destination="{generate-id(/book/parts/part)}"
- starting-state="hide">
- <fo:bookmark-title>User's Guide</fo:bookmark-title>
-
- <xsl:for-each select="$entries">
+ <fo:bookmark internal-destination="{generate-id(header/title)}"
+ starting-state="hide">
+ <fo:bookmark-title><xsl:value-of select="header/title"/></fo:bookmark-title>
+
<xsl:call-template name="bookmarks2">
<xsl:with-param name="entries"
select="chapter[header/title]"/>
</xsl:call-template>
- </xsl:for-each>
-
- </fo:bookmark>
+
+ </fo:bookmark>
+ </xsl:for-each>
</xsl:if>
</xsl:template>
+
<xsl:template name="bookmarks2">
<xsl:param name="entries"/>
<xsl:for-each select="$entries">
@@ -932,9 +935,9 @@
<xsl:template match="part">
<xsl:variable name="partnum"><xsl:number level="any" from="book" count="part|application"/></xsl:variable>
- <fo:block xsl:use-attribute-sets="h1" id="{generate-id()}">
+ <fo:block xsl:use-attribute-sets="h1" id="{generate-id(header/title)}">
<xsl:value-of select="$partnum"/>&#160;&#160;&#160;
- <xsl:text>User's Guide</xsl:text>
+ <xsl:value-of select="header/title"/>
</fo:block>
<xsl:apply-templates select="description">
@@ -1380,16 +1383,15 @@
<!-- Func -->
<xsl:template match="func">
<xsl:param name="partnum"/>
-
- <xsl:apply-templates select="name"/>
- <xsl:apply-templates
- select="name[string-length(@arity) > 0 and position()=last()]"
- mode="types"/>
-
- <xsl:apply-templates select="fsummary|type|desc">
- <xsl:with-param name="partnum" select="$partnum"/>
- </xsl:apply-templates>
-
+ <fo:block space-before="1.5em">
+ <xsl:apply-templates select="name"/>
+ <xsl:apply-templates
+ select="name[string-length(@arity) > 0 and position()=last()]"
+ mode="types"/>
+ <xsl:apply-templates select="fsummary|type|desc">
+ <xsl:with-param name="partnum" select="$partnum"/>
+ </xsl:apply-templates>
+ </fo:block>
</xsl:template>
@@ -1422,14 +1424,10 @@
<xsl:param name="partnum"/>
<xsl:choose>
<xsl:when test="ancestor::cref">
- <fo:block id="{generate-id(nametext)}">
- <xsl:value-of select="ret"/><xsl:text> </xsl:text><xsl:value-of select="nametext"/>
- </fo:block>
+ <fo:block id="{generate-id(nametext)}"><xsl:value-of select="ret"/><xsl:text></xsl:text><xsl:value-of select="nametext"/></fo:block>
</xsl:when>
<xsl:otherwise>
- <fo:block id="{generate-id(.)}">
- <xsl:value-of select="."/>
- </fo:block>
+ <fo:block id="{generate-id(.)}"><xsl:value-of select="."/></fo:block>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
@@ -1466,7 +1464,7 @@
</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()" format="justify">
- <fo:block font-weight="bold">
+ <fo:block font-weight="bold" font-family="monospace" >
<xsl:apply-templates>
<xsl:with-param name="partnum" select="$partnum"/>
</xsl:apply-templates>
diff --git a/lib/erl_docgen/priv/xsl/db_pdf_params.xsl b/lib/erl_docgen/priv/xsl/db_pdf_params.xsl
index 7de20f2092..4d9c08d0c3 100644
--- a/lib/erl_docgen/priv/xsl/db_pdf_params.xsl
+++ b/lib/erl_docgen/priv/xsl/db_pdf_params.xsl
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
- # Copyright Ericsson AB 2009-2010. All Rights Reserved.
+ # Copyright Ericsson AB 2009-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -29,7 +29,7 @@
<!-- Fixed strings -->
<xsl:variable name="companyname"><xsl:value-of select="/book/header/copyright/holder"/></xsl:variable>
- <xsl:variable name="copyright">Copyright &#169; <xsl:value-of select="/book/header/copyright/year[1]"/><xsl:text>-</xsl:text><xsl:value-of select="substring-after(substring-after($gendate, ' '), ' ')"/></xsl:variable>
+ <xsl:variable name="copyright">Copyright &#169; <xsl:value-of select="/book/header/copyright/year[1]"/><xsl:text>-</xsl:text><xsl:value-of select="substring-after(normalize-space(substring-after($gendate, ' ')), ' ')"/></xsl:variable>
<!-- FIXME: remove when appendix creation has been fixed -->
<!-- xsl:variable name="appendix_title"-->
@@ -316,8 +316,8 @@
<xsl:attribute name="font-family">monospace</xsl:attribute>
<!-- xsl:attribute name="font-size">0.8em</xsl:attribute -->
<xsl:attribute name="keep-with-next.within-page">always</xsl:attribute>
- <xsl:attribute name="space-after">0.3em</xsl:attribute>
- <xsl:attribute name="space-before">1.5em</xsl:attribute>
+ <xsl:attribute name="space-after">0.25em</xsl:attribute>
+ <!-- xsl:attribute name="space-before">1.5em</xsl:attribute -->
</xsl:attribute-set>
<xsl:attribute-set name="type-listblock">
diff --git a/lib/erl_docgen/vsn.mk b/lib/erl_docgen/vsn.mk
index cafb5287de..79c8c570bf 100644
--- a/lib/erl_docgen/vsn.mk
+++ b/lib/erl_docgen/vsn.mk
@@ -1,2 +1,2 @@
-ERL_DOCGEN_VSN = 0.2.5
+ERL_DOCGEN_VSN = 0.2.6
diff --git a/lib/erl_interface/doc/src/ei.xml b/lib/erl_interface/doc/src/ei.xml
index de4e4b4301..539e16d837 100644
--- a/lib/erl_interface/doc/src/ei.xml
+++ b/lib/erl_interface/doc/src/ei.xml
@@ -4,7 +4,7 @@
<cref>
<header>
<copyright>
- <year>2001</year><year>2010</year>
+ <year>2001</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -581,9 +581,9 @@ ei_x_encode_empty_list(&amp;x);
<c><![CDATA[term]]></c> union, it is decoded, and the appropriate field
in <c><![CDATA[term->value]]></c> is set, and <c><![CDATA[*index]]></c> is
incremented by the term size.</p>
- <p>The function returns 0 on successful decoding, -1 on error,
- and 1 if the term seems alright, but does not fit in the
- <c><![CDATA[term]]></c> structure. If it returns 0, the <c><![CDATA[index]]></c>
+ <p>The function returns 1 on successful decoding, -1 on error,
+ and 0 if the term seems alright, but does not fit in the
+ <c><![CDATA[term]]></c> structure. If it returns 1, the <c><![CDATA[index]]></c>
will be incremented, and the <c><![CDATA[term]]></c> contains the
decoded term.</p>
<p>The <c><![CDATA[term]]></c> structure will contain the arity for a tuple
diff --git a/lib/erl_interface/doc/src/erl_format.xml b/lib/erl_interface/doc/src/erl_format.xml
index 5699485845..f036b12879 100644
--- a/lib/erl_interface/doc/src/erl_format.xml
+++ b/lib/erl_interface/doc/src/erl_format.xml
@@ -4,7 +4,7 @@
<cref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -105,7 +105,7 @@ erl_format("[{name,~a},{age,~i},{data,~w}]",
values in <c><![CDATA[Term]]></c>. </p>
<p>If <c><![CDATA[Term]]></c> and <c><![CDATA[Pattern]]></c> can be matched, the
function returns a non-zero value and binds any unbound
- variables in <c><![CDATA[Pattern]]></c>. If <c><![CDATA[Term]]></c><c><![CDATA[Pattern]]></c> do
+ variables in <c><![CDATA[Pattern]]></c>. If <c><![CDATA[Term]]></c> <c><![CDATA[Pattern]]></c> do
not match, the function returns 0. For example:</p>
<code type="none"><![CDATA[
ETERM *term, *pattern, *pattern2;
diff --git a/lib/erl_interface/doc/src/make.dep b/lib/erl_interface/doc/src/make.dep
deleted file mode 100644
index 3f43cf64fe..0000000000
--- a/lib/erl_interface/doc/src/make.dep
+++ /dev/null
@@ -1,24 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin//docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex ei.tex ei_connect.tex ei_users_guide.tex \
- erl_call.tex erl_connect.tex erl_error.tex \
- erl_eterm.tex erl_format.tex erl_global.tex \
- erl_malloc.tex erl_marshal.tex part_ei.tex \
- ref_man.tex ref_man_ei.tex ref_man_erl_interface.tex \
- registry.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml ref_man_ei.xml ref_man_erl_interface.xml
-
diff --git a/lib/erl_interface/doc/src/notes.xml b/lib/erl_interface/doc/src/notes.xml
index 7055fcd5c9..9a42ebfddf 100644
--- a/lib/erl_interface/doc/src/notes.xml
+++ b/lib/erl_interface/doc/src/notes.xml
@@ -30,6 +30,53 @@
</header>
<p>This document describes the changes made to the Erl_interface application.</p>
+<section><title>Erl_Interface 3.7.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Align ei buffer according to size of pointers</p>
+ <p>
+ Own Id: OTP-9390</p>
+ </item>
+ <item>
+ <p> XML files have been corrected. </p>
+ <p>
+ Own Id: OTP-9550 Aux Id: OTP-9541 </p>
+ </item>
+ <item>
+ <p>
+ Make comment and documentation reflect code in
+ erl_interface/src/misc/ei_decode_term.c (Thanks to Anneli
+ Cuss)</p>
+ <p>
+ Own Id: OTP-9559</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ ei: integer overflow in string/atom encoding</p>
+ <p>
+ ei_encode_atom() and ei_encode_string() use strlen() to
+ get the length of the buffer. As strlen() returns an
+ unsigned long long and both ei functions take a signed
+ integer, the length fields may overflow.</p>
+ <p>
+ Check so that the results of strlen can be held in a
+ signed integer. (Thanks to Michael Santos)</p>
+ <p>
+ Own Id: OTP-9530</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erl_Interface 3.7.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/erl_interface/src/Makefile.in b/lib/erl_interface/src/Makefile.in
index 8ff142a366..0d841cfa48 100644
--- a/lib/erl_interface/src/Makefile.in
+++ b/lib/erl_interface/src/Makefile.in
@@ -143,7 +143,6 @@ BINDIR = $(ERL_TOP)/lib/erl_interface/bin/$(TARGET)
vpath %.c connect:encode:decode:misc:epmd:legacy:registry
-
###########################################################################
# List targets
###########################################################################
@@ -202,11 +201,6 @@ ifeq ($(USING_VC),yes)
# Windows targets
TARGETS = \
- $(BINDIR) \
- $(OBJDIR) \
- $(MT_OBJDIR) \
- $(MD_OBJDIR) \
- $(MDD_OBJDIR) \
$(OBJ_TARGETS) \
$(EXE_TARGETS)
@@ -236,9 +230,6 @@ else
ifeq ($USING_MINGW,yes)
TARGETS = \
- $(BINDIR) \
- $(OBJDIR) \
- $(MD_OBJDIR) \
$(OBJ_TARGETS) \
$(EXE_TARGETS)
@@ -257,10 +248,6 @@ else
ifdef THR_DEFS
TARGETS = \
- $(BINDIR) \
- $(OBJDIR) \
- $(ST_OBJDIR) \
- $(MT_OBJDIR) \
$(OBJ_TARGETS) \
$(EXE_TARGETS)
@@ -283,9 +270,6 @@ FAKE_TARGETS = \
else
TARGETS = \
- $(BINDIR) \
- $(OBJDIR) \
- $(ST_OBJDIR) \
$(OBJ_TARGETS) \
$(EXE_TARGETS)
@@ -601,23 +585,7 @@ $(MDD_OBJDIR)/%.o: %.c
# Create directories
###########################################################################
-$(BINDIR):
- mkdir -p $(BINDIR)
-
-$(OBJDIR):
- mkdir -p $(OBJDIR)
-
-$(ST_OBJDIR):
- mkdir -p $(ST_OBJDIR)
-
-$(MT_OBJDIR):
- mkdir -p $(MT_OBJDIR)
-
-$(MD_OBJDIR):
- mkdir -p $(MD_OBJDIR)
-
-$(MDD_OBJDIR):
- mkdir -p $(MDD_OBJDIR)
+_create_dirs := $(shell mkdir -p $(BINDIR) $(OBJDIR) $(ST_OBJDIR) $(MT_OBJDIR) $(MD_OBJDIR) $(MDD_OBJDIR))
###########################################################################
# Special rules
diff --git a/lib/erl_interface/src/connect/ei_resolve.c b/lib/erl_interface/src/connect/ei_resolve.c
index 50c5a4161d..ba8f8fbce3 100644
--- a/lib/erl_interface/src/connect/ei_resolve.c
+++ b/lib/erl_interface/src/connect/ei_resolve.c
@@ -185,7 +185,12 @@ static int verify_dns_configuration(void)
* align: increment buf until it is dword-aligned, reduce len by same amount.
* advance: increment buf by n bytes, reduce len by same amount .
*/
-#define align_buf(buf,len) for (;(((unsigned)buf)&0x3); (buf)++, len--)
+#if defined SIZEOF_VOID_P
+#define ALIGNBYTES (SIZEOF_VOID_P - 1)
+#else
+#define ALIGNBYTES (sizeof(void*) - 1)
+#endif
+#define align_buf(buf,len) for (;(((unsigned)buf) & ALIGNBYTES); (buf)++, len--)
#define advance_buf(buf,len,n) ((buf)+=(n),(len)-=(n))
/* "and now the tricky part..." */
diff --git a/lib/erl_interface/src/encode/encode_atom.c b/lib/erl_interface/src/encode/encode_atom.c
index 69f2d1451c..6f41f045e0 100644
--- a/lib/erl_interface/src/encode/encode_atom.c
+++ b/lib/erl_interface/src/encode/encode_atom.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -17,13 +17,17 @@
* %CopyrightEnd%
*/
#include <string.h>
+#include <limits.h>
#include "eidef.h"
#include "eiext.h"
#include "putget.h"
int ei_encode_atom(char *buf, int *index, const char *p)
{
- return ei_encode_atom_len(buf, index, p, strlen(p));
+ size_t len = strlen(p);
+
+ if (len >= INT_MAX) return -1;
+ return ei_encode_atom_len(buf, index, p, len);
}
int ei_encode_atom_len(char *buf, int *index, const char *p, int len)
diff --git a/lib/erl_interface/src/encode/encode_string.c b/lib/erl_interface/src/encode/encode_string.c
index 1d342cb605..d00d2f3e81 100644
--- a/lib/erl_interface/src/encode/encode_string.c
+++ b/lib/erl_interface/src/encode/encode_string.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -17,6 +17,7 @@
* %CopyrightEnd%
*/
#include <string.h>
+#include <limits.h>
#include "eidef.h"
#include "eiext.h"
#include "putget.h"
@@ -24,7 +25,10 @@
int ei_encode_string(char *buf, int *index, const char *p)
{
- return ei_encode_string_len(buf, index, p, strlen(p));
+ size_t len = strlen(p);
+
+ if (len >= INT_MAX) return -1;
+ return ei_encode_string_len(buf, index, p, len);
}
int ei_encode_string_len(char *buf, int *index, const char *p, int len)
diff --git a/lib/erl_interface/src/legacy/erl_fix_alloc.c b/lib/erl_interface/src/legacy/erl_fix_alloc.c
index 20f3024e41..2ed0dd1470 100644
--- a/lib/erl_interface/src/legacy/erl_fix_alloc.c
+++ b/lib/erl_interface/src/legacy/erl_fix_alloc.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -109,6 +109,10 @@ void *erl_eterm_alloc (void)
erl_eterm_state->freed--;
} else if ((b = malloc(sizeof(*b))) == NULL) {
erl_errno = ENOMEM;
+#ifdef _REENTRANT
+ ei_mutex_unlock(erl_eterm_state->lock);
+#endif /* _REENTRANT */
+ return NULL;
}
erl_eterm_state->allocated++;
b->free = 0;
diff --git a/lib/erl_interface/src/misc/ei_decode_term.c b/lib/erl_interface/src/misc/ei_decode_term.c
index bfb4571337..0b82ef0e35 100644
--- a/lib/erl_interface/src/misc/ei_decode_term.c
+++ b/lib/erl_interface/src/misc/ei_decode_term.c
@@ -25,8 +25,8 @@
#include "ei_decode_term.h"
#include "putget.h"
-/* Returns 0 on successful encoding, -1 on error, and 1 if the term seems
- alright, but does not fit in the term structure. If it returns 0, the
+/* Returns 1 on successful encoding, -1 on error, and 0 if the term seems
+ alright, but does not fit in the term structure. If it returns 1, the
index will be incremented, and the term contains the decoded term. */
int ei_decode_ei_term(const char* buf, int* index, ei_term* term)
@@ -111,10 +111,10 @@ int ei_decode_ei_term(const char* buf, int* index, ei_term* term)
break;
case ERL_SMALL_TUPLE_EXT:
term->arity = get8(s);
- break; /*return 0;*/
+ break;
case ERL_LARGE_TUPLE_EXT:
term->arity = get32be(s);
- break; /*return 0;*/
+ break;
case ERL_NIL_EXT:
term->arity = 0;
break;
@@ -123,7 +123,7 @@ int ei_decode_ei_term(const char* buf, int* index, ei_term* term)
return 0;
case ERL_LIST_EXT:
term->arity = get32be(s);
- break; /*return 0;*/
+ break;
case ERL_BINARY_EXT:
term->size = get32be(s);
return 0;
diff --git a/lib/erl_interface/src/registry/reg_dump.c b/lib/erl_interface/src/registry/reg_dump.c
index 1e640fb506..d2854c10b5 100644
--- a/lib/erl_interface/src/registry/reg_dump.c
+++ b/lib/erl_interface/src/registry/reg_dump.c
@@ -215,6 +215,7 @@ static int mn_send_write(int fd, erlang_pid *mnesia, const char *key, ei_reg_obj
else ei_encode_long(msgbuf,&index,(long)(obj->val.p)); /* just the pointer */
break;
default:
+ if (dbuf) free(dbuf);
return -1;
}
diff --git a/lib/erl_interface/src/registry/reg_restore.c b/lib/erl_interface/src/registry/reg_restore.c
index 765c3f4314..7bc1c758af 100644
--- a/lib/erl_interface/src/registry/reg_restore.c
+++ b/lib/erl_interface/src/registry/reg_restore.c
@@ -303,6 +303,9 @@ int ei_reg_restore(int fd, ei_reg *reg, const char *mntab)
if (mn_decode_insert(reg,msgbuf,&index,keybuf)) goto restore_failure;
}
+ if (keybuf) free(keybuf);
+ if (dbuf) free(dbuf);
+
/* wait for unlink */
if (mn_unlink(fd)) return -1;
@@ -310,8 +313,6 @@ int ei_reg_restore(int fd, ei_reg *reg, const char *mntab)
ei_hash_foreach(reg->tab,clean_obj);
/* success */
- if (keybuf) free(keybuf);
- if (dbuf) free(dbuf);
return 0;
restore_failure:
diff --git a/lib/erl_interface/test/all_SUITE_data/Makefile.src b/lib/erl_interface/test/all_SUITE_data/Makefile.src
index 9be2360656..42d4c6f27f 100644
--- a/lib/erl_interface/test/all_SUITE_data/Makefile.src
+++ b/lib/erl_interface/test/all_SUITE_data/Makefile.src
@@ -30,6 +30,8 @@ CHMOD=chmod
all: $(ALL_OBJS)
+$(EI_COMMON_OBJS): gccifier@exe@
+
@IFEQ@ (@erl_interface_cross_compile@, true)
gccifier@exe@:
$(CP) gccifier.sh gccifier@exe@
diff --git a/lib/erl_interface/test/all_SUITE_data/init_tc.erl b/lib/erl_interface/test/all_SUITE_data/init_tc.erl
index 8157d590fc..8db4667bf9 100644
--- a/lib/erl_interface/test/all_SUITE_data/init_tc.erl
+++ b/lib/erl_interface/test/all_SUITE_data/init_tc.erl
@@ -40,23 +40,11 @@ run([]) ->
run1(Name) ->
CFile = Name ++ ".c",
{ok, Bin} = file:read_file(CFile),
- String = binary_to_list(Bin),
-
- %% This ConstPart stuff is because you can't retrieve part of a match.
- %% Long live Perl!
-
- ConstPart = "\nTESTCASE\\(",
- ConstPartLen = 10,
- {match, Matches} = regexp:matches(String, ConstPart++"[_a-zA-Z]*"),
- Cases = get_names(Matches, ConstPartLen, Bin, []),
+ RE = "\nTESTCASE\\(([_a-zA-Z]*)\\)",
+ {match, Cases0} = re:run(Bin, RE, [{capture,all_but_first,list},global]),
+ Cases = lists:concat(Cases0),
generate(Name, Cases).
-get_names([{Start, Length}|Rest], Skip, Bin, Result) ->
- Name = binary_to_list(Bin, Start+Skip, Start+Length-1),
- get_names(Rest, Skip, Bin, [Name|Result]);
-get_names([], _Skip, _Bin, Result) ->
- lists:reverse(Result).
-
generate(TcName, Cases) ->
Hrl = TcName ++ "_cases.hrl",
{ok, HrlFile} = file:open(Hrl, write),
diff --git a/lib/erl_interface/test/port_call_SUITE_data/Makefile.src b/lib/erl_interface/test/port_call_SUITE_data/Makefile.src
index dc7385ba32..a512494aa3 100644
--- a/lib/erl_interface/test/port_call_SUITE_data/Makefile.src
+++ b/lib/erl_interface/test/port_call_SUITE_data/Makefile.src
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2009. All Rights Reserved.
+# Copyright Ericsson AB 2001-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -26,7 +26,7 @@ LIBPATH = @erl_interface_libpath@
LIBERL = $(LIBPATH)/@erl_interface_lib_drv@
LIBEI = $(LIBPATH)/@erl_interface_eilib_drv@
-SHLIB_EXTRA_LDLIBS = $(LIBERL) $(LIBEI)
+SHLIB_EXTRA_LDLIBS = $(LIBERL) $(LIBEI) @erl_interface_threadlib@
SHLIB_EXTRA_CFLAGS = -I@erl_interface_include@ -I../all_SUITE_data
diff --git a/lib/erl_interface/vsn.mk b/lib/erl_interface/vsn.mk
index 75f2b7101b..601958579c 100644
--- a/lib/erl_interface/vsn.mk
+++ b/lib/erl_interface/vsn.mk
@@ -1 +1 @@
-EI_VSN = 3.7.4
+EI_VSN = 3.7.5
diff --git a/lib/et/doc/src/notes.xml b/lib/et/doc/src/notes.xml
index e3be8422c8..acc6120fcd 100644
--- a/lib/et/doc/src/notes.xml
+++ b/lib/et/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2002</year><year>2010</year>
+ <year>2002</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -36,6 +36,20 @@
one section in this document. The title of each section is the
version number of <c>Event Tracer (ET)</c>.</p>
+<section><title>ET 1.4.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Dialyzer warnings have been fixed. </p>
+ <p>
+ Own Id: OTP-9470</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>ET 1.4.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/et/src/et_wx_viewer.erl b/lib/et/src/et_wx_viewer.erl
index 7d4286ed9d..386f8fc86b 100644
--- a/lib/et/src/et_wx_viewer.erl
+++ b/lib/et/src/et_wx_viewer.erl
@@ -257,10 +257,10 @@ parse_opt([H | T], S, CollectorOpt) ->
Actors = [create_actor(Name) || Name <- ActorNames2],
parse_opt(T, S#state{actors = Actors}, CollectorOpt);
{include, ActorNames} when is_list(ActorNames) ->
- Actors = [opt_create_actor(Name, include, S#state.actors) || Name <- ActorNames],
+ Actors = [opt_create_actor(Name, include, S) || Name <- ActorNames],
parse_opt(T, S#state{actors = Actors}, CollectorOpt);
{exclude, ActorNames} when is_list(ActorNames) ->
- Actors = [opt_create_actor(Name, exclude, S#state.actors) || Name <- ActorNames],
+ Actors = [opt_create_actor(Name, exclude, S) || Name <- ActorNames],
parse_opt(T, S#state{actors = Actors}, CollectorOpt);
{first_event, _FirstKey} ->
%% NYI
diff --git a/lib/et/vsn.mk b/lib/et/vsn.mk
index ea98aeba11..239a72ad73 100644
--- a/lib/et/vsn.mk
+++ b/lib/et/vsn.mk
@@ -1 +1 @@
-ET_VSN = 1.4.3
+ET_VSN = 1.4.4
diff --git a/lib/eunit/AUTHORS b/lib/eunit/AUTHORS
deleted file mode 100644
index b7c1426aff..0000000000
--- a/lib/eunit/AUTHORS
+++ /dev/null
@@ -1,2 +0,0 @@
-Richard Carlsson <[email protected]>
-Micka�l R�mond <[email protected]>
diff --git a/lib/eunit/Makefile b/lib/eunit/Makefile
index ee69d5e8e0..cd85dff06a 100644
--- a/lib/eunit/Makefile
+++ b/lib/eunit/Makefile
@@ -13,8 +13,6 @@
# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
# AB. All Rights Reserved.''
#
-# $Id$
-#
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
diff --git a/lib/eunit/doc/.gitignore b/lib/eunit/doc/.gitignore
new file mode 100644
index 0000000000..7fcda5db42
--- /dev/null
+++ b/lib/eunit/doc/.gitignore
@@ -0,0 +1,4 @@
+*.html
+stylesheet.css
+erlang.png
+edoc-info
diff --git a/lib/eunit/doc/edoc-info b/lib/eunit/doc/edoc-info
deleted file mode 100644
index 1c04b2ed1a..0000000000
--- a/lib/eunit/doc/edoc-info
+++ /dev/null
@@ -1,3 +0,0 @@
-{application,eunit}.
-{packages,[]}.
-{modules,[eunit,eunit_surefire]}.
diff --git a/lib/eunit/doc/erlang.png b/lib/eunit/doc/erlang.png
deleted file mode 100644
index 987a618e24..0000000000
--- a/lib/eunit/doc/erlang.png
+++ /dev/null
Binary files differ
diff --git a/lib/eunit/doc/eunit.html b/lib/eunit/doc/eunit.html
deleted file mode 100644
index a181d12ce3..0000000000
--- a/lib/eunit/doc/eunit.html
+++ /dev/null
@@ -1,71 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
-<title>Module eunit</title>
-<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
-</head>
-<body bgcolor="white">
-<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
-<hr>
-
-<h1>Module eunit</h1>
-<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>This module is the main EUnit user interface.
-<p>Copyright � 2004-2009 Micka�l R�mond, Richard Carlsson</p>
-
-<p><b>Version:</b> 2.1.1, Apr 22 2009 22:37:19</p>
-<p><b>Authors:</b> Micka�l R�mond (<a href="mailto:[email protected]"><tt>[email protected]</tt></a>) [<em>web site:</em> <tt><a href="http://www.process-one.net/" target="_top">http://www.process-one.net/</a></tt>], Richard Carlsson (<a href="mailto:[email protected]"><tt>[email protected]</tt></a>) [<em>web site:</em> <tt><a href="http://user.it.uu.se/~richardc/" target="_top">http://user.it.uu.se/~richardc/</a></tt>].</p>
-
-<h2><a name="description">Description</a></h2>This module is the main EUnit user interface.
-<h2><a name="index">Function Index</a></h2>
-<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#start-0">start/0</a></td><td>Starts the EUnit server.</td></tr>
-<tr><td valign="top"><a href="#stop-0">stop/0</a></td><td>Stops the EUnit server.</td></tr>
-<tr><td valign="top"><a href="#test-1">test/1</a></td><td>Equivalent to <a href="#test-2"><tt>test(Tests, [])</tt></a>.
-</td></tr>
-<tr><td valign="top"><a href="#test-2">test/2</a></td><td>Runs a set of tests.</td></tr>
-</table>
-
-<h2><a name="functions">Function Details</a></h2>
-
-<h3 class="function"><a name="start-0">start/0</a></h3>
-<div class="spec">
-<p><tt>start() -&gt; any()</tt></p>
-</div><p>Starts the EUnit server. Normally, you don't need to call this
- function; it is started automatically.</p>
-
-<h3 class="function"><a name="stop-0">stop/0</a></h3>
-<div class="spec">
-<p><tt>stop() -&gt; any()</tt></p>
-</div><p>Stops the EUnit server. Normally, you don't need to call this
- function.</p>
-
-<h3 class="function"><a name="test-1">test/1</a></h3>
-<div class="spec">
-<p><tt>test(Tests) -&gt; any()</tt></p>
-</div><p>Equivalent to <a href="#test-2"><tt>test(Tests, [])</tt></a>.</p>
-
-
-<h3 class="function"><a name="test-2">test/2</a></h3>
-<div class="spec">
-<p><tt>test(Tests::term(), Options::[term()]) -&gt; ok | {error, term()}</tt></p>
-</div><p><p>Runs a set of tests. The format of <code>Tests</code> is described in the
- section <a href="overview-summary.html#EUnit_test_representation">EUnit test
- representation</a> of the overview.</p>
-
- Example: <pre> eunit:test(fred)</pre><p> runs all tests in the module <code>fred</code>
- and also any tests in the module <code>fred_tests</code>, if that module exists.</p>
-
- Options:
- <dl>
- <dt><code>verbose</code></dt>
- <dd>Displays more details about the running tests.</dd>
- </dl>
-
- Options in the environment variable EUNIT are also included last in
- the option list, i.e., have lower precedence than those in <code>Options</code>.</p>
-<p><b>See also:</b> <a href="#test-1">test/1</a>.</p>
-<hr>
-
-<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
-<p><i>Generated by EDoc, Apr 22 2009, 22:37:19.</i></p>
-</body>
-</html>
diff --git a/lib/eunit/doc/eunit_surefire.html b/lib/eunit/doc/eunit_surefire.html
deleted file mode 100644
index f2ecbae572..0000000000
--- a/lib/eunit/doc/eunit_surefire.html
+++ /dev/null
@@ -1,78 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
-<title>Module eunit_surefire</title>
-<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
-</head>
-<body bgcolor="white">
-<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
-<hr>
-
-<h1>Module eunit_surefire</h1>
-<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>Surefire reports for EUnit (Format used by Maven and Atlassian
-Bamboo for example to integrate test results).
-<p>Copyright � 2009 Micka�l R�mond, Paul Guyot</p>
-
-<p><b>Behaviours:</b> <a href="eunit_listener.html"><tt>eunit_listener</tt></a>.</p>
-<p><b>Authors:</b> Micka�l R�mond (<a href="mailto:[email protected]"><tt>[email protected]</tt></a>).</p>
-<p><b>See also:</b> <a href="eunit.html">eunit</a>.</p>
-
-<h2><a name="description">Description</a></h2><p>Surefire reports for EUnit (Format used by Maven and Atlassian
-Bamboo for example to integrate test results). Based on initial code
-from Paul Guyot.</p>
-
- Example: Generate XML result file in the current directory:
- <pre> eunit:test([fib, eunit_examples],
- [{report,{eunit_surefire,[{dir,"."}]}}]).</pre>
-<h2><a name="index">Function Index</a></h2>
-<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#handle_begin-3">handle_begin/3</a></td><td></td></tr>
-<tr><td valign="top"><a href="#handle_cancel-3">handle_cancel/3</a></td><td></td></tr>
-<tr><td valign="top"><a href="#handle_end-3">handle_end/3</a></td><td></td></tr>
-<tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr>
-<tr><td valign="top"><a href="#start-0">start/0</a></td><td></td></tr>
-<tr><td valign="top"><a href="#start-1">start/1</a></td><td></td></tr>
-<tr><td valign="top"><a href="#terminate-2">terminate/2</a></td><td></td></tr>
-</table>
-
-<h2><a name="functions">Function Details</a></h2>
-
-<h3 class="function"><a name="handle_begin-3">handle_begin/3</a></h3>
-<div class="spec">
-<p><tt>handle_begin(X1, Data, St) -&gt; any()</tt></p>
-</div>
-
-<h3 class="function"><a name="handle_cancel-3">handle_cancel/3</a></h3>
-<div class="spec">
-<p><tt>handle_cancel(X1, Data, St) -&gt; any()</tt></p>
-</div>
-
-<h3 class="function"><a name="handle_end-3">handle_end/3</a></h3>
-<div class="spec">
-<p><tt>handle_end(X1, Data, St) -&gt; any()</tt></p>
-</div>
-
-<h3 class="function"><a name="init-1">init/1</a></h3>
-<div class="spec">
-<p><tt>init(Options) -&gt; any()</tt></p>
-</div>
-
-<h3 class="function"><a name="start-0">start/0</a></h3>
-<div class="spec">
-<p><tt>start() -&gt; any()</tt></p>
-</div>
-
-<h3 class="function"><a name="start-1">start/1</a></h3>
-<div class="spec">
-<p><tt>start(Options) -&gt; any()</tt></p>
-</div>
-
-<h3 class="function"><a name="terminate-2">terminate/2</a></h3>
-<div class="spec">
-<p><tt>terminate(X1, St) -&gt; any()</tt></p>
-</div>
-<hr>
-
-<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
-<p><i>Generated by EDoc, Apr 22 2009, 22:37:19.</i></p>
-</body>
-</html>
diff --git a/lib/eunit/doc/index.html b/lib/eunit/doc/index.html
deleted file mode 100644
index 9bd8e8cf6b..0000000000
--- a/lib/eunit/doc/index.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
-<title>The eunit application</title>
-</head>
-<frameset cols="20%,80%">
-<frame src="modules-frame.html" name="modulesFrame" title="">
-
-<frame src="overview-summary.html" name="overviewFrame" title="">
-<noframes>
-<h2>This page uses frames</h2>
-<p>Your browser does not accept frames.
-<br>You should go to the <a href="overview-summary.html">non-frame version</a> instead.
-</p>
-</noframes>
-</frameset>
-</html> \ No newline at end of file
diff --git a/lib/eunit/doc/modules-frame.html b/lib/eunit/doc/modules-frame.html
deleted file mode 100644
index a484e99d4c..0000000000
--- a/lib/eunit/doc/modules-frame.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
-<title>The eunit application</title>
-<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
-</head>
-<body bgcolor="white">
-<h2 class="indextitle">Modules</h2>
-<table width="100%" border="0" summary="list of modules">
-<tr><td><a href="eunit.html" target="overviewFrame" class="module">eunit</a></td></tr>
-<tr><td><a href="eunit_surefire.html" target="overviewFrame" class="module">eunit_surefire</a></td></tr></table>
-</body>
-</html> \ No newline at end of file
diff --git a/lib/eunit/doc/overview-summary.html b/lib/eunit/doc/overview-summary.html
deleted file mode 100644
index ea7beba8b3..0000000000
--- a/lib/eunit/doc/overview-summary.html
+++ /dev/null
@@ -1,1032 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
-<title>EUnit - a Lightweight Unit Testing Framework for Erlang
-</title>
-<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
-</head>
-<body bgcolor="white">
-<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
-<h1>EUnit - a Lightweight Unit Testing Framework for Erlang
-</h1>
-<p>Copyright � 2004-2007 Micka�l R�mond, Richard Carlsson</p>
-<p><b>Version:</b> 2.1.1, Apr 22 2009 22:37:19
-</p>
-<p><b>Authors:</b> Richard Carlsson (<a href="mailto:[email protected]"><tt>[email protected]</tt></a>) [<em>web site:</em> <tt><a href="http://user.it.uu.se/~richardc/" target="_top">http://user.it.uu.se/~richardc/</a></tt>], Micka�l R�mond (<a href="mailto:[email protected]"><tt>[email protected]</tt></a>) [<em>web site:</em> <tt><a href="http://www.process-one.net/" target="_top">http://www.process-one.net/</a></tt>].</p>
-<p>EUnit is a unit testing framework for Erlang. It is very powerful
-and flexible, is easy to use, and has small syntactical overhead.</p>
-
-<ul>
-<li><a href="#Unit_testing">Unit testing</a></li>
-<li><a href="#Terminology">Terminology</a></li>
-<li><a href="#Getting_started">Getting started</a></li>
-<li><a href="#EUnit_macros">EUnit macros</a></li>
-<li><a href="#EUnit_test_representation">EUnit test representation</a></li>
-</ul>
-
-<p>EUnit builds on ideas from the family of unit testing frameworks for
-Object Oriented languages that originated with JUnit by Beck and Gamma
-(and Beck's previous framework SUnit for Smalltalk). However, EUnit uses
-techniques more adapted to functional and concurrent programming, and is
-typically less verbose than its relatives.</p>
-
-<p>Although EUnit uses many preprocessor macros, they have been designed to
-be as nonintrusive as possible, and should not cause conflicts with
-existing code. Adding EUnit tests to a module should thus not normally
-require changing existing code. Furthermore, tests that only exercise
-the exported functions of a module can always be placed in a completely
-separate module, avoiding any conflicts entirely.</p>
-
-<h3><a name="Unit_testing">Unit testing</a></h3>
-
-<p>Unit Testing is testing of individual program "units" in relative
-isolation. There is no particular size requirement: a unit can be a
-function, a module, a process, or even a whole application, but the most
-typical testing units are individual functions or modules. In order to
-test a unit, you specify a set of individual tests, set up the smallest
-necessary environment for being able to run those tests (often, you
-don't need to do any setup at all), you run the tests and collect the
-results, and finally you do any necessary cleanup so that the test can
-be run again later. A Unit Testing Framework tries to help you in each
-stage of this process, so that it is easy to write tests, easy to run
-them, and easy to see which tests failed (so you can fix the bugs).</p>
-
-<h4><a name="Advantages_of_unit_testing">Advantages of unit testing</a></h4>
-
-<dl>
- <dt>Reduces the risks of changing the program</dt>
- <dd>Most programs will be modified during their lifetime: bugs will be
- fixed, features will be added, optimizations may become necessary, or
- the code will need to be refactored or cleaned up in other ways to
- make it easier to work with. But every change to a working program is
- a risk of introducing new bugs - or reintroducing bugs that had
- previously been fixed. Having a set of unit tests that you can run
- with very little effort makes it easy to know that the code still
- works as it should (this use is called <em>regression testing</em>;
- see <a href="#Terminology">Terminology</a>). This goes a long way to reduce the
- resistance to changing and refactoring code.</dd>
- <dt>Helps guide and speed up the development process</dt>
- <dd>By focusing on getting the code to pass the tests, the programmer
- can become more productive, not overspecify or get lost in premature
- optimizations, and create code that is correct from the very beginning
- (so-called <em>test-driven development</em>; see <a href="#Terminology">Terminology</a>).</dd>
- <dt>Helps separate interface from implementation</dt>
- <dd>When writing tests, the programmer may discover dependencies
- (in order to get the tests to run) that ought not to be there, and
- which need to be abstracted away to get a cleaner design. This helps
- eliminate bad dependencies before they spread throughout the
- code.</dd>
- <dt>Makes component integration easier</dt>
- <dd>By testing in a bottom-up fashion, beginning with the smallest
- program units and creating a confidence in that they work as they
- should, it becomes easier to test that a higher-level component,
- consisting of several such units, also behaves according to
- specification (known as <em>integration testing</em>; see <a href="#Terminology">Terminology</a>).</dd>
- <dt>Is self-documenting</dt>
- <dd>The tests can be read as documentation, typically showing both
- examples of correct and incorrect usage, along with the expected
- consequences.</dd>
-</dl>
-
-<h3><a name="Terminology">Terminology</a></h3>
-
-<dl>
- <dt>Unit testing</dt>
- <dd>Testing that a program unit behaves as it is supposed to do (in
- itself), according to its specifications. Unit tests have an important
- function as regression tests, when the program later is modified for
- some reason, since they check that the program still behaves according
- to specification.</dd>
- <dt>Regression testing</dt>
- <dd>Running a set of tests after making changes to a program, to check
- that the program behaves as it did before the changes (except, of
- course, for any intentional changes in behaviour). Unit tests are
- important as regression tests, but regression testing can involve more
- than just unit testing, and may also test behaviour that might not be
- part of the normal specification (such as bug-for-bug-compatibility).
- </dd>
- <dt>Integration testing</dt>
- <dd>Testing that a number of individually developed program units
- (assumed to already have been separately unit tested) work together as
- expected. Depending on the system being developed, integration testing
- may be as simple as "just another level of unit testing", but might
- also involve other kinds of tests (compare <em>system testing</em>).
-</dd>
- <dt>System testing</dt>
- <dd>Testing that a complete system behaves according to its
- specification. Specifically, system testing should not require knowing
- any details about the implementation. It typically involves testing
- many different aspects of the system behaviour apart from the basic
- functionality, such as performance, usability, and reliability.</dd>
- <dt>Test-driven development</dt>
- <dd>A program development technique where you continuously write tests
- <em>before</em> you implement the code that is supposed to pass those
- tests. This can help you focus on solving the right problems, and not
- make a more complicated implementation than necessary, by letting the
- unit tests determine when a program is "done": if it fulfils its
- specifications, there is no need to keep adding functionality.</dd>
- <dt>Mock object</dt>
- <dd>Sometimes, testing some unit <code>A</code> (e.g., a function) requires that
- it collaborates somehow with some other unit <code>B</code> (perhaps being passed
- as an argument, or by reference) - but <code>B</code> has not been implemented
- yet. A "mock object" - an object which, for the purposes of testing
- <code>A</code>, looks and behaves like a real <code>B</code> - might then be used instead.
- (This is of course only useful if it would be significantly more work
- to implement a real <code>B</code> than to create a mock object.)</dd>
- <dt>Test case</dt>
- <dd>A single, well-defined test, that somehow can be uniquely
- identified. When executed, the test case either <em>passes</em> or
- <em>fails</em>; the test report should identify exactly which test
- cases failed.</dd>
- <dt>Test suite</dt>
- <dd>A collection of test cases, generally with a specific, common
- target for testing, such as a single function, module, or subsystem. A
- test suite may also be recursively composed by smaller test
- suites.</dd>
-</dl>
-
-<h3><a name="Getting_started">Getting started</a></h3>
-<ul>
- <li><a href="#Including_the_EUnit_header_file">Including the EUnit header file</a></li>
- <li><a href="#Writing_simple_test_functions">Writing simple test functions</a></li>
- <li><a href="#Running_EUnit">Running EUnit</a></li>
- <li><a href="#Writing_test_generating_functions">Writing test generating functions</a></li>
- <li><a href="#An_example">An example</a></li>
- <li><a href="#Disabling_testing">Disabling testing</a></li>
- <li><a href="#Avoiding_compile-time_dependency_on_EUnit">Avoiding compile-time dependency on EUnit</a></li>
-</ul>
-
-<h4><a name="Including_the_EUnit_header_file">Including the EUnit header file</a></h4>
-
-The simplest way to use EUnit in an Erlang module is to add the
-following line at the beginning of the module (after the <code>-module</code>
-declaration, but before any function definitions):
-<pre> -include_lib("eunit/include/eunit.hrl").</pre>
-
-This will have the following effect:
-<ul>
- <li>Creates an exported function <code>test()</code> (unless testing is turned
- off, and the module does not already contain a test() function), that
- can be used to run all the unit tests defined in the module</li>
- <li>Causes all functions whose names match <code>..._test()</code> or <code>..._test_()</code>
- to be automatically exported from the module (unless testing is
- turned off, or the <code>EUNIT_NOAUTO</code> macro is defined)</li>
- <li>Makes all the preprocessor macros of EUnit available, to help
- writing tests</li>
-</ul>
-
-<strong>Note:</strong> For <code>-include_lib(...)</code> to work, the Erlang
-module search path <em>must</em> contain a directory whose name ends in
-<code>eunit/ebin</code> (pointing to the <code>ebin</code> subdirectory of the EUnit
-installation directory). If EUnit is installed as <code>lib/eunit</code> under your
-Erlang/OTP system directory, its <code>ebin</code> subdirectory will be
-automatically added to the search path when Erlang starts. Otherwise,
-you need to add the directory explicitly, by passing a <code>-pa</code> flag to the
-<code>erl</code> or <code>erlc</code> command. For example, a Makefile could contain the
-following action for compiling <code>.erl</code> files:
-<pre> erlc -pa "path/to/eunit/ebin" $(ERL_COMPILE_FLAGS) -o$(EBIN) $&lt;</pre>
-or if you want Eunit to always be available when you run Erlang
-interactively, you can add a line like the following to your
-<code>$HOME/.erlang</code> file:
-<pre> code:add_path("/path/to/eunit/ebin").</pre>
-
-<h4><a name="Writing_simple_test_functions">Writing simple test functions</a></h4>
-
-<p>The EUnit framework makes it extremely easy to write unit tests in
-Erlang. There are a few different ways of writing them, though, so we
-start with the simplest:</p>
-
-<p>A function with a name ending in <code>..._test()</code> is recognized by EUnit as
-a simple test function - it takes no arguments, and its execution either
-succeeds (returning some arbitrary value that EUnit will throw away), or
-fails by throwing an exception of some kind (or by not terminating, in
-which case it will be aborted after a while).</p>
-
-An example of a simple test function could be the following:
-<pre> reverse_test() -&gt; lists:reverse([1,2,3]).</pre><p>
-This just tests that the function <code>lists:reverse(List)</code> does not crash
-when <code>List</code> is <code>[1,2,3]</code>. It is not a great test, but many people write
-simple functions like this one to test the basic functionality of their
-code, and those tests can be used directly by EUnit, without changes,
-as long as their function names match.</p>
-
-<h5><a name="Use_exceptions_to_signal_failure">Use exceptions to signal failure</a></h5>
-
-To write more interesting tests, we need to make them crash (throw an
-exception) when they don't get the result they expect. A simple way of
-doing this is to use pattern matching with <code>=</code>, as in the following
-examples:
-<pre> reverse_nil_test() -&gt; [] = lists:reverse([]).
- reverse_one_test() -&gt; [1] = lists:reverse([1]).
- reverse_two_test() -&gt; [2,1] = lists:reverse([1,2]).</pre><p>
-If there was some bug in <code>lists:reverse/1</code> that made it return something
-other than <code>[2,1]</code> when it got <code>[1,2]</code> as input, then the last test
-above would throw a <code>badmatch</code> error. The first two (we assume they do
-not get a <code>badmatch</code>) would simply return <code>[]</code> and <code>[1]</code>, respectively,
-so both succeed. (Note that EUnit is not psychic: if you write a test
-that returns a value, even if it is the wrong value, EUnit will consider
-it a success. You must make sure that the test is written so that it
-causes a crash if the result is not what it should be.)</p>
-
-<h5><a name="Using_assert_macros">Using assert macros</a></h5>
-
-If you want to use Boolean operators for your tests, the <code>assert</code>
-macro comes in handy (see <a href="#EUnit_macros">EUnit macros</a> for details):
-<pre> length_test() -&gt; ?assert(length([1,2,3]) =:= 3).</pre><p>
-The <code>?assert(Expression)</code> macro will evaluate <code>Expression</code>, and if that
-does not evaluate to <code>true</code>, it will throw an exception; otherwise it
-just returns <code>ok</code>. In the above example, the test will thus fail if the
-call to <code>length</code> does not return 3.</p>
-
-<h4><a name="Running_EUnit">Running EUnit</a></h4>
-
-<p>If you have added the declaration
-<code>-include_lib("eunit/include/eunit.hrl")</code> to your module, as described
-above, you only need to compile the module, and run the automatically
-exported function <code>test()</code>. For example, if your module was named <code>m</code>,
-then calling <code>m:test()</code> will run EUnit on all the tests defined in the
-module. You do not need to write <code>-export</code> declarations for the test
-functions. This is all done by magic.</p>
-
-<p>You can also use the function <a href="eunit.html#test-1"><code>eunit:test/1</code></a> to run arbitrary
-tests, for example to try out some more advanced test descriptors (see
-<a href="#EUnit_test_representation">EUnit test representation</a>). For example, running
-<code>eunit:test(m)</code> does the same thing as the auto-generated function
-<code>m:test()</code>, while <code>eunit:test({inparallel, m})</code> runs the same test
-cases but executes them all in parallel.</p>
-
-<h5><a name="Putting_tests_in_separate_modules">Putting tests in separate modules</a></h5>
-
-<p>If you want to separate your test code from your normal code (at least
-for testing the exported functions), you can simply write the test
-functions in a module named <code>m_tests</code> (note: not <code>m_test</code>), if your
-module is named <code>m</code>. Then, whenever you ask EUnit to test the module
-<code>m</code>, it will also look for the module <code>m_tests</code> and run those tests as
-well. See <code>ModuleName</code> in the section <a href="#Primitives">Primitives</a> for details.</p>
-
-<h5><a name="EUnit_captures_standard_output">EUnit captures standard output</a></h5>
-
-<p>If your test code writes to the standard output, you may be surprised to
-see that the text does not appear on the console when the tests are
-running. This is because EUnit captures all standard output from test
-functions (this also includes setup and cleanup functions, but not
-generator functions), so that it can be included in the test report if
-errors occur. To bypass EUnit and print text directly to the console
-while testing, you can write to the <code>user</code> output stream, as in
-<code>io:format(user, "~w", [Term])</code>. The recommended way of doing this is to
-use the EUnit <a href="#Debugging_macros">Debugging macros</a>, which make it much simpler.</p>
-
-<h4><a name="Writing_test_generating_functions">Writing test generating functions</a></h4>
-
-<p>A drawback of simple test functions is that you must write a separate
-function (with a separate name) for each test case. A more compact way
-of writing tests (and much more flexible, as we shall see), is to write
-functions that <em>return</em> tests, instead of <em>being</em> tests.</p>
-
-<p>A function with a name ending in <code>..._test_()</code> (note the final
-underscore) is recognized by EUnit as a <em>test generator</em>
-function. Test generators return a <em>representation</em> of a <em>set
-of tests</em> to be executed by EUnit.</p>
-
-<h5><a name="Representing_a_test_as_data">Representing a test as data</a></h5>
-
-The most basic representation of a test is a single fun-expression that
-takes no arguments. For example, the following test generator:
-<pre> basic_test_() -&gt;
- fun () -&gt; ?assert(1 + 1 =:= 2) end.</pre>
-will have the same effect as the following simple test:
-<pre> simple_test() -&gt;
- ?assert(1 + 1 =:= 2).</pre><p>
-(in fact, EUnit will handle all simple tests just like it handles
-fun-expressions: it will put them in a list, and run them one by one).</p>
-
-<h5><a name="Using_macros_to_write_tests">Using macros to write tests</a></h5>
-
-To make tests more compact and readable, as well as automatically add
-information about the line number in the source code where a test
-occurred (and reduce the number of characters you have to type), you can
-use the <code>_test</code> macro (note the initial underscore character), like
-this:
-<pre> basic_test_() -&gt;
- ?_test(?assert(1 + 1 =:= 2)).</pre><p>
-The <code>_test</code> macro takes any expression (the "body") as argument, and
-places it within a fun-expression (along with some extra information).
-The body can be any kind of test expression, just like the body of a
-simple test function.</p>
-
-<h5><a name="Underscore-prefixed_macros_create_test_objects">Underscore-prefixed macros create test objects</a></h5>
-
-But this example can be made even shorter! Most test macros, such as the
-family of <code>assert</code> macros, have a corresponding form with an initial
-underscore character, which automatically adds a <code>?_test(...)</code> wrapper.
-The above example can then simply be written:
-<pre> basic_test_() -&gt;
- ?_assert(1 + 1 =:= 2).</pre><p>
-which has exactly the same meaning (note the <code>_assert</code> instead of
-<code>assert</code>). You can think of the initial underscore as signalling
-<em>test object</em>.</p>
-
-<h4><a name="An_example">An example</a></h4>
-
-Sometimes, an example says more than a thousand words. The following
-small Erlang module shows how EUnit can be used in practice.
-<pre> -module(fib).
- -export([fib/1]).
- -include_lib("eunit/include/eunit.hrl").
-
- fib(0) -&gt; 1;
- fib(1) -&gt; 1;
- fib(N) when N &gt; 1 -&gt; fib(N-1) + fib(N-2).
-
- fib_test_() -&gt;
- [?_assert(fib(0) =:= 1),
- ?_assert(fib(1) =:= 1),
- ?_assert(fib(2) =:= 2),
- ?_assert(fib(3) =:= 3),
- ?_assert(fib(4) =:= 5),
- ?_assert(fib(5) =:= 8),
- ?_assertException(error, function_clause, fib(-1)),
- ?_assert(fib(31) =:= 2178309)
- ].</pre>
-
-<p>(Author's note: When I first wrote this example, I happened to write a
-<code>*</code> instead of <code>+</code> in the <code>fib</code> function. Of course, this showed up
-immediately when I ran the tests.)</p>
-
-<p>See <a href="#EUnit_test_representation">EUnit test representation</a> for a full list of all the ways
-you can specify test sets in EUnit.</p>
-
-<h4><a name="Disabling_testing">Disabling testing</a></h4>
-
-Testing can be turned off by defining the <code>NOTEST</code> macro when compiling,
-for example as an option to <code>erlc</code>, as in:
-<pre> erlc -DNOTEST my_module.erl</pre>
-or by adding a macro definition to the code, <em>before the EUnit header
-file is included</em>:
-<pre> -define(NOTEST, 1).</pre><p>
-(the value is not important, but should typically be 1 or <code>true</code>).
-Note that unless the <code>EUNIT_NOAUTO</code> macro is defined, disabling testing
-will also automatically strip all test functions from the code, except
-for any that are explicitly declared as exported.</p>
-
-For instance, to use EUnit in your application, but with testing turned
-off by default, put the following lines in a header file:
-<pre> -define(NOTEST, true).
- -include_lib("eunit/include/eunit.hrl").</pre>
-and then make sure that every module of your application includes that
-header file. This means that you have a only a single place to modify in
-order to change the default setting for testing. To override the <code>NOTEST</code>
-setting without modifying the code, you can define <code>TEST</code> in a compiler
-option, like this:
-<pre> erlc -DTEST my_module.erl</pre>
-
-<p>See <a href="#Compilation_control_macros">Compilation control macros</a> for details about these
-macros.</p>
-
-<h4><a name="Avoiding_compile-time_dependency_on_EUnit">Avoiding compile-time dependency on EUnit</a></h4>
-
-If you are distributing the source code for your application for other
-people to compile and run, you probably want to ensure that the code
-compiles even if EUnit is not available. Like the example in the
-previous section, you can put the following lines in a common header
-file:
-<pre> -ifdef(TEST).
- -include_lib("eunit/include/eunit.hrl").
- -endif.</pre><p>
-and, of course, also make sure that you place all test code that uses
-EUnit macros within <code>-ifdef(TEST)</code> or <code>-ifdef(EUNIT)</code> sections.</p>
-
-
-<h3><a name="EUnit_macros">EUnit macros</a></h3>
-
-<p>Although all the functionality of EUnit is avaliable even without the
-use of preprocessor macros, the EUnit header file defines a number of
-such macros in order to make it as easy as possible to write unit tests
-as compactly as possible and without getting too many details in the
-way.</p>
-
-<p>Except where explicitly stated, using EUnit macros will never introduce
-run-time dependencies on the EUnit library code, regardless of whether
-your code is compiled with testing enabled or disabled.</p>
-
-<ul>
-<li><a href="#Basic_macros">Basic macros</a></li>
-<li><a href="#Compilation_control_macros">Compilation control macros</a></li>
-<li><a href="#Utility_macros">Utility macros</a></li>
-<li><a href="#Assert_macros">Assert macros</a></li>
-<li><a href="#Macros_for_running_external_commands">Macros for running external commands</a></li>
-<li><a href="#Debugging_macros">Debugging macros</a></li>
-</ul>
-
-<h4><a name="Basic_macros">Basic macros</a></h4>
-
-<dl>
-<dt><code>_test(Expr)</code></dt>
-<dd>Turns <code>Expr</code> into a "test object", by wrapping it in a
-fun-expression and a source line number. Technically, this is the same
-as <code>{?LINE, fun () -&gt; (Expr) end}</code>.
-</dd>
-</dl>
-
-<h4><a name="Compilation_control_macros">Compilation control macros</a></h4>
-
-<dl>
-<dt><code>EUNIT</code></dt>
-<dd>This macro is always defined to <code>true</code> whenever EUnit is enabled at
-compile time. This is typically used to place testing code within
-conditional compilation, as in:
-<pre> -ifdef(EUNIT).
- % test code here
- ...
- -endif.</pre>
-e.g., to ensure that the code can be compiled without including the
-EUnit header file, when testing is disabled. See also the macros <code>TEST</code>
-and <code>NOTEST</code>.
-</dd>
-
-<dt><code>EUNIT_NOAUTO</code></dt>
-<dd>If this macro is defined, the automatic exporting or stripping of
-test functions will be disabled.
-</dd>
-
-<dt><code>TEST</code></dt>
-<dd><p>This macro is always defined (to <code>true</code>, unless previously defined
-by the user to have another value) whenever EUnit is enabled at compile
-time. This can be used to place testing code within conditional
-compilation; see also the macros <code>NOTEST</code> and <code>EUNIT</code>.</p>
-
-<p>For testing code that is strictly dependent on EUnit, it may be
-preferable to use the <code>EUNIT</code> macro for this purpose, while for code
-that uses more generic testing conventions, using the <code>TEST</code> macro may
-be preferred.</p>
-
-The <code>TEST</code> macro can also be used to override the <code>NOTEST</code> macro. If
-<code>TEST</code> is defined <em>before</em> the EUnit header file is
-included (even if <code>NOTEST</code> is also defined), then the code will be
-compiled with EUnit enabled.
-</dd>
-
-<dt><code>NOTEST</code></dt>
-<dd><p>This macro is always defined (to <code>true</code>, unless previously defined
-by the user to have another value) whenever EUnit is <em>disabled</em>
-at compile time. (Compare the <code>TEST</code> macro.)</p>
-
-This macro can also be used for conditional compilation, but is more
-typically used to disable testing: If <code>NOTEST</code> is defined
-<em>before</em> the EUnit header file is included, and <code>TEST</code>
-is <em>not</em> defined, then the code will be compiled with EUnit
-disabled. See also <a href="#Disabling_testing">Disabling testing</a>.
-</dd>
-
-<dt><code>NOASSERT</code></dt>
-<dd>If this macro is defined, the assert macros will have no effect,
-when testing is also disabled. See <a href="#Assert_macros">Assert macros</a>. When
-testing is enabled, the assert macros are always enabled automatically
-and cannot be disabled.
-</dd>
-
-<dt><code>ASSERT</code></dt>
-<dd>If this macro is defined, it overrides the NOASSERT macro, forcing
-the assert macros to always be enabled regardless of other settings.
-</dd>
-
-<dt><code>NODEBUG</code></dt>
-<dd>If this macro is defined, the debugging macros will have no effect.
-See <a href="#Debugging_macros">Debugging macros</a>. <code>NODEBUG</code> also implies <code>NOASSERT</code>,
-unless testing is enabled.
-</dd>
-
-<dt><code>DEBUG</code></dt>
-<dd>If this macro is defined, it overrides the NODEBUG macro, forcing
-the debugging macros to be enabled.
-</dd>
-</dl>
-
-<h4><a name="Utility_macros">Utility macros</a></h4>
-
-<p>The following macros can make tests more compact and readable:</p>
-
-<dl>
-<dt><code>LET(Var,Arg,Expr)</code></dt>
-<dd>Creates a local binding <code>Var = Arg</code> in <code>Expr</code>. (This is the same as
-<code>(fun(Var)-&gt;(Expr)end)(Arg)</code>.) Note that the binding is not exported
-outside of <code>Expr</code>, and that within <code>Expr</code>, this binding of <code>Var</code> will
-shadow any binding of <code>Var</code> in the surrounding scope.
-</dd>
-<dt><code>IF(Cond,TrueCase,FalseCase)</code></dt>
-<dd>Evaluates <code>TrueCase</code> if <code>Cond</code> evaluates to <code>true</code>, or otherwise
-evaluates <code>FalseCase</code> if <code>Cond</code> evaluates to <code>false</code>. (This is the same
-as <code>(case (Cond) of true-&gt;(TrueCase); false-&gt;(FalseCase) end)</code>.) Note
-that it is an error if <code>Cond</code> does not yield a boolean value.
-</dd>
-</dl>
-
-<h4><a name="Assert_macros">Assert macros</a></h4>
-
-<p>(Note that these macros also have corresponding forms which start with
-an "<code>_</code>" (underscore) character, as in <code>?_assert(BoolExpr)</code>, that create
-a "test object" instead of performing the test immediately. This is
-equivalent to writing <code>?_test(assert(BoolExpr))</code>, etc.)</p>
-
-<p>If the macro <code>NOASSERT</code> is defined before the EUnit header file is
-included, these macros have no effect when testing is also disabled; see
-<a href="#Compilation_control_macros">Compilation control macros</a> for details.</p>
-
-<dl>
-<dt><code>assert(BoolExpr)</code></dt>
-<dd><p>Evaluates the expression <code>BoolExpr</code>, if testing is enabled. Unless
-the result is <code>true</code>, an informative exception will be generated. If
-there is no exception, the result of the macro expression is the atom
-<code>ok</code>, and the value of <code>BoolExpr</code> is discarded. If testing is disabled,
-the macro will not generate any code except the atom <code>ok</code>, and
-<code>BoolExpr</code> will not be evaluated.</p>
-
-Typical usage:
-<pre> ?assert(f(X, Y) =:= [])</pre>
-
-The <code>assert</code> macro can be used anywhere in a program, not just in unit
-tests, to check pre/postconditions and invariants. For example:
-<pre> some_recursive_function(X, Y, Z) -&gt;
- ?assert(X + Y &gt; Z),
- ...</pre>
-</dd>
-<dt><code>assertNot(BoolExpr)</code></dt>
-<dd>Equivalent to <code>assert(not (BoolExpr))</code>.
-</dd>
-<dt><code>assertMatch(GuardedPattern, Expr)</code></dt>
-<dd><p>Evaluates <code>Expr</code> and matches the result against <code>GuardedPattern</code>, if
-testing is enabled. If the match fails, an informative exception will be
-generated; see the <code>assert</code> macro for further details. <code>GuardedPattern</code>
-can be anything that you can write on the left hand side of the <code>-&gt;</code>
-symbol in a case-clause, except that it cannot contain comma-separated
-guard tests.</p>
-
-<p>The main reason for using <code>assertMatch</code> also for simple matches, instead
-of matching with <code>=</code>, is that it produces more detailed error messages.</p>
-
-Examples:
-<pre> ?assertMatch({found, {fred, _}}, lookup(bloggs, Table))</pre>
-<pre> ?assertMatch([X|_] when X &gt; 0, binary_to_list(B))</pre>
-</dd>
-<dt><code>assertEqual(Expect, Expr)</code></dt>
-<dd><p>Evaluates the expressions <code>Expect</code> and <code>Expr</code> and compares the
-results for equality, if testing is enabled. If the values are not
-equal, an informative exception will be generated; see the <code>assert</code>
-macro for further details.</p>
-
-<p><code>assertEqual</code> is more suitable than than <code>assertMatch</code> when the
-left-hand side is a computed value rather than a simple pattern, and
-gives more details than <code>?assert(Expect =:= Expr)</code>.</p>
-
-Examples:
-<pre> ?assertEqual("b" ++ "a", lists:reverse("ab"))</pre>
-<pre> ?assertEqual(foo(X), bar(Y))</pre>
-</dd>
-<dt><code>assertException(ClassPattern, TermPattern, Expr)</code></dt>
-<dt><code>assertError(TermPattern, Expr)</code></dt>
-<dt><code>assertExit(TermPattern, Expr)</code></dt>
-<dt><code>assertThrow(TermPattern, Expr)</code></dt>
-<dd><p>Evaluates <code>Expr</code>, catching any exception and testing that it matches
-the expected <code>ClassPattern:TermPattern</code>. If the match fails, or if no
-exception is thrown by <code>Expr</code>, an informative exception will be
-generated; see the <code>assert</code> macro for further details. The
-<code>assertError</code>, <code>assertExit</code>, and <code>assertThrow</code> macros, are equivalent to
-using <code>assertException</code> with a <code>ClassPattern</code> of <code>error</code>, <code>exit</code>, or
-<code>throw</code>, respectively.</p>
-
-Examples:
-<pre> ?assertError(badarith, X/0)</pre>
-<pre> ?assertExit(normal, exit(normal))</pre>
-<pre> ?assertException(throw, {not_found,_}, throw({not_found,42}))</pre>
-</dd>
-</dl>
-
-<h4><a name="Macros_for_running_external_commands">Macros for running external commands</a></h4>
-
-<p>Keep in mind that external commands are highly dependent on the
-operating system. You can use the standard library function <code>os:type()</code>
-in test generator functions, to produce different sets of tests
-depending on the current operating system.</p>
-
-<p>Note: these macros introduce a run-time dependency on the EUnit library
-code, if compiled with testing enabled.</p>
-
-<dl>
-<dt><code>assertCmd(CommandString)</code></dt>
-<dd><p>Runs <code>CommandString</code> as an external command, if testing is enabled.
-Unless the returned status value is 0, an informative exception will be
-generated. If there is no exception, the result of the macro expression
-is the atom <code>ok</code>. If testing is disabled, the macro will not generate
-any code except the atom <code>ok</code>, and the command will not be executed.</p>
-
-Typical usage:
-<pre> ?assertCmd("mkdir foo")</pre>
-</dd>
-<dt><code>assertCmdStatus(N, CommandString)</code></dt>
-<dd>Like the <code>assertCmd(CommandString)</code> macro, but generates an
-exception unless the returned status value is <code>N</code>.
-</dd>
-<dt><code>assertCmdOutput(Text, CommandString)</code></dt>
-<dd>Runs <code>CommandString</code> as an external command, if testing is enabled.
-Unless the output produced by the command exactly matches the specified
-string <code>Text</code>, an informative exception will be generated. (Note that
-the output is normalized to use a single LF character as line break on
-all platforms.) If there is no exception, the result of the macro
-expression is the atom <code>ok</code>. If testing is disabled, the macro will not
-generate any code except the atom <code>ok</code>, and the command will not be
-executed.
-</dd>
-<dt><code>cmd(CommandString)</code></dt>
-<dd><p>Runs <code>CommandString</code> as an external command. Unless the returned
-status value is 0 (indicating success), an informative exception will be
-generated; otherwise, the result of the macro expression is the output
-produced by the command, as a flat string. The output is normalized to
-use a single LF character as line break on all platforms.</p>
-
-<p>This macro is useful in the setup and cleanup sections of fixtures,
-e.g., for creating and deleting files or perform similar operating
-system specific tasks, to make sure that the test system is informed of
-any failures.</p>
-
-A Unix-specific example:
-<pre> {setup,
- fun () -&gt; ?cmd("mktemp") end,
- fun (FileName) -&gt; ?cmd("rm " ++ FileName) end,
- ...}</pre>
-</dd>
-</dl>
-
-<h4><a name="Debugging_macros">Debugging macros</a></h4>
-
-<p>To help with debugging, EUnit defines several useful macros for printing
-messages directly to the console (rather than to the standard output).
-Furthermore, these macros all use the same basic format, which includes
-the file and line number where they occur, making it possible in some
-development environments (e.g., when running Erlang in an Emacs buffer)
-to simply click on the message and jump directly to the corresponding
-line in the code.</p>
-
-<p>If the macro <code>NODEBUG</code> is defined before the EUnit header file is
-included, these macros have no effect; see
-<a href="#Compilation_control_macros">Compilation control macros</a> for details.</p>
-
-<dl>
-<dt><code>debugHere</code></dt>
-<dd>Just prints a marker showing the current file and line number. Note
-that this is an argument-less macro. The result is always <code>ok</code>.</dd>
-<dt><code>debugMsg(Text)</code></dt>
-<dd>Outputs the message <code>Text</code> (which can be a plain string, an IO-list,
-or just an atom). The result is always <code>ok</code>.</dd>
-<dt><code>debugFmt(FmtString, Args)</code></dt>
-<dd>This formats the text like <code>io:format(FmtString, Args)</code> and outputs
-it like <code>debugMsg</code>. The result is always <code>ok</code>.</dd>
-<dt><code>debugVal(Expr)</code></dt>
-<dd>Prints both the source code for <code>Expr</code> and its current value. E.g.,
-<code>?debugVal(f(X))</code> might be displayed as "<code>f(X) = 42</code>". (Large terms are
-shown truncated.) The result is always the value of <code>Expr</code>, so this
-macro can be wrapped around any expression to display its value when
-the code is compiled with debugging enabled.</dd>
-<dt><code>debugTime(Text,Expr)</code></dt>
-<dd>Prints <code>Text</code> and the wall clock time for evaluation of <code>Expr</code>. The
-result is always the value of <code>Expr</code>, so this macro can be wrapped
-around any expression to show its run time when the code is compiled
-with debugging enabled. For example, <code>List1 = ?debugTime("sorting",
-lists:sort(List))</code> might show as "<code>sorting: 0.015 s</code>".</dd>
-
-</dl>
-
-
-<h3><a name="EUnit_test_representation">EUnit test representation</a></h3>
-
-<p>The way EUnit represents tests and test sets as data is flexible,
-powerful, and concise. This section describes the representation in
-detail.</p>
-
-<ul>
-<li><a href="#Simple_test_objects">Simple test objects</a></li>
-<li><a href="#Test_sets_and_deep_lists">Test sets and deep lists</a></li>
-<li><a href="#Titles">Titles</a></li>
-<li><a href="#Primitives">Primitives</a></li>
-<li><a href="#Control">Control</a></li>
-<li><a href="#Fixtures">Fixtures</a></li>
-<li><a href="#Lazy_generators">Lazy generators</a></li>
-</ul>
-
-<h4><a name="Simple_test_objects">Simple test objects</a></h4>
-
-A <em>simple test object</em> is one of the following:
-<ul>
- <li>A nullary functional value (i.e., a fun that takes zero
- arguments). Examples:
-<pre> fun () -&gt; ... end</pre>
-<pre> fun some_function/0</pre>
-<pre> fun some_module:some_function/0</pre>
- </li>
- <li>A pair of atoms <code>{ModuleName, FunctionName}</code>, referring to the
- function <code>ModuleName:FunctionName/0</code></li>
- <li>A pair <code>{LineNumber, SimpleTest}</code>, where <code>LineNumber</code> is a
- nonnegative integer and <code>SimpleTest</code> is another simple test
- object. <code>LineNumber</code> should indicate the source line of the test.
- Pairs like this are usually only created via <code>?_test(...)</code> macros;
- see <a href="#Basic_macros">Basic macros</a>.</li>
-</ul><p>
-In brief, a simple test object consists of a single function that takes
-no arguments (possibly annotated with some additional metadata, i.e., a
-line number). Evaluation of the function either <em>succeeds</em>, by
-returning some value (which is ignored), or <em>fails</em>, by throwing
-an exception.</p>
-
-<h4><a name="Test_sets_and_deep_lists">Test sets and deep lists</a></h4>
-
-<p>A test set can be easily created by placing a sequence of test objects
-in a list. If <code>T_1</code>, ..., <code>T_N</code> are individual test objects, then <code>[T_1,
-..., T_N]</code> is a test set consisting of those objects (in that order).</p>
-
-<p>Test sets can be joined in the same way: if <code>S_1</code>, ..., <code>S_K</code> are test
-sets, then <code>[S_1, ..., S_K]</code> is also a test set, where the tests of
-<code>S_i</code> are ordered before those of <code>S_(i+1)</code>, for each subset <code>S_i</code>.</p>
-
-<p>Thus, the main representation of test sets is <em>deep lists</em>, and
-a simple test object can be viewed as a test set containing only a
-single test; there is no difference between <code>T</code> and <code>[T]</code>.</p>
-
-<p>A module can also be used to represent a test set; see <code>ModuleName</code>
-under <a href="#Primitives">Primitives</a> below.</p>
-
-<h4><a name="Titles">Titles</a></h4>
-
-<p>Any test or test set <code>T</code> can be annotated with a title, by wrapping it
-in a pair <code>{Title, T}</code>, where <code>Title</code> is a string. For convenience, any
-test which is normally represented using a tuple can simply be given a
-title string as the first element, i.e., writing <code>{"The Title", ...}</code>
-instead of adding an extra tuple wrapper as in <code>{"The Title", {...}}</code>.</p>
-
-
-<h4><a name="Primitives">Primitives</a></h4>
-
-The following are primitives, which do not contain other test sets as
-arguments:
-<dl>
-<dt><code>ModuleName::atom()</code>
-</dt>
-<dd>A single atom represents a module name, and is equivalent to
-<code>{module, ModuleName}</code>. This is often used as in the call
-<code>eunit:test(some_module)</code>.
-</dd>
-<dt><code>{module, ModuleName::atom()}</code>
-</dt>
-<dd><p>This composes a test set from the exported test functions of the
-named module, i.e., those functions with arity zero whose names end
-with <code>_test</code> or <code>_test_</code>. Basically, the <code>..._test()</code> functions become
-simple tests, while the <code>..._test_()</code> functions become generators.</p>
-
-In addition, EUnit will also look for another module whose name is
-<code>ModuleName</code> plus the suffix <code>_tests</code>, and if it exists, all the tests
-from that module will also be added. (If <code>ModuleName</code> already contains
-the suffix <code>_tests</code>, this is not done.) E.g., the specification
-<code>{module, mymodule}</code> will run all tests in the modules <code>mymodule</code> and
-<code>mymodule_tests</code>. Typically, the <code>_tests</code> module should only contain
-test cases that use the public interface of the main module (and no
-other code).
-</dd>
-<dt><code>{application, AppName::atom(), Info::list()}</code>
-</dt>
-<dd>This is a normal Erlang/OTP application descriptor, as found in an
- <code>.app</code> file. The resulting test set consists of the modules listed in
- the <code>modules</code> entry in <code>Info</code>.
-</dd>
-<dt><code>{application, AppName::atom()}</code>
-</dt>
-<dd>This creates a test set from all the modules belonging to the
-specified application, by consulting the application's <code>.app</code> file
-(see <code>{file, FileName}</code>), or if no such file exists, by testing all
-object files in the application's <tt>ebin</tt>-directory (see <code>{dir,
-Path}</code>); if that does not exist, the <code>code:lib_dir(AppName)</code> directory
-is used.
-</dd>
-<dt><code>Path::string()</code>
-</dt>
-<dd>A single string represents the path of a file or directory, and is
-equivalent to <code>{file, Path}</code>, or <code>{dir, Path}</code>, respectively, depending
-on what <code>Path</code> refers to in the file system.
-</dd>
-<dt><code>{file, FileName::string()}</code>
-</dt>
-<dd><p>If <code>FileName</code> has a suffix that indicates an object file (<code>.beam</code>),
-EUnit will try to reload the module from the specified file and test it.
-Otherwise, the file is assumed to be a text file containing test
-specifications, which will be read using the standard library function
-<code>file:path_consult/2</code>.</p>
-
-Unless the file name is absolute, the file is first searched for
-relative to the current directory, and then using the normal search path
-(<code>code:get_path()</code>). This means that the names of typical "app" files
-can be used directly, without a path, e.g., <code>"mnesia.app"</code>.
-</dd>
-<dt><code>{dir, Path::string()}</code>
-</dt>
-<dd>This tests all object files in the specified directory, as if they
-had been individually specified using <code>{file, FileName}</code>.
-</dd>
-<dt><code>{generator, GenFun::(() -&gt; Tests)}</code>
-</dt>
-<dd>The generator function <code>GenFun</code> is called to produce a test
-set.
-</dd>
-<dt><code>{generator, ModuleName::atom(), FunctionName::atom()}</code>
-</dt>
-<dd>The function <code>ModuleName:FunctionName()</code> is called to produce a test
-set.
-</dd>
-<dt><code>{with, X::any(), [AbstractTestFun::((any()) -&gt; any())]}</code>
-</dt>
-<dd>Distributes the value <code>X</code> over the unary functions in the list,
-turning them into nullary test functions. An <code>AbstractTestFun</code> is like
-an ordinary test fun, but takes one argument instead of zero - it's
-basically missing some information before it can be a proper test. In
-practice, <code>{with, X, [F_1, ..., F_N]}</code> is equivalent to <code>[fun () -&gt;
-F_1(X) end, ..., fun () -&gt; F_N(X) end]</code>. This is particularly useful if
-your abstract test functions are already implemented as proper
-functions: <code>{with, FD, [fun filetest_a/1, fun filetest_b/1, fun
-filetest_c/1]}</code> is equivalent to <code>[fun () -&gt; filetest_a(FD) end, fun ()
--&gt; filetest_b(FD) end, fun () -&gt; filetest_c(FD) end]</code>, but much more
-compact. See also <a href="#Fixtures">Fixtures</a>, below.
-</dd>
-</dl>
-
-<h4><a name="Control">Control</a></h4>
-
-The following representations control how and where tests are executed:
-<dl>
-<dt><code>{spawn, Tests}</code></dt>
-<dd>Runs the specified tests in a separate subprocess, while the current
-test process waits for it to finish. This is useful for tests that need
-a fresh, isolated process state. (Note that EUnit always starts at least
-one such a subprocess automatically; tests are never executed by the
-caller's own process.)</dd>
-<dt><code>{spawn, Node::atom(), Tests}</code></dt>
-<dd>Like <code>{spawn, Tests}</code>, but runs the specified tests on the given
-Erlang node.</dd>
-<dt><code>{timeout, Time::number(), Tests}</code></dt>
-<dd>Runs the specified tests under the given timeout. Time is in
-seconds; e.g., 60 means one minute and 0.1 means 1/10th of a second. If
-the timeout is exceeded, the unfinished tests will be forced to
-terminate. Note that if a timeout is set around a fixture, it includes
-the time for setup and cleanup, and if the timeout is triggered, the
-entire fixture is abruptly terminated (without running the
-cleanup).</dd>
-<dt><code>{inorder, Tests}</code></dt>
-<dd>Runs the specified tests in strict order. Also see <code>{inparallel,
-Tests}</code>. By default, tests are neither marked as <code>inorder</code> or
-<code>inparallel</code>, but may be executed as the test framework chooses.</dd>
-<dt><code>{inparallel, Tests}</code></dt>
-<dd>Runs the specified tests in parallel (if possible). Also see
-<code>{inorder, Tests}</code>.</dd>
-<dt><code>{inparallel, N::integer(), Tests}</code></dt>
-<dd>Like <code>{inparallel, Tests}</code>, but running no more than <code>N</code> subtests
-simultaneously.</dd>
-</dl>
-
-<h4><a name="Fixtures">Fixtures</a></h4>
-
-<p>A "fixture" is some state that is necessary for a particular set of
-tests to run. EUnit's support for fixtures makes it easy to set up such
-state locally for a test set, and automatically tear it down again when
-the test set is finished, regardless of the outcome (success, failures,
-timeouts, etc.).</p>
-
-<p>To make the descriptions simpler, we first list some definitions:
-<center>
-<table border="0" cellspacing="4">
-<tr>
-<td><code>Setup</code></td><td><code>() -&gt; (R::any())</code></td>
-</tr>
-<tr>
-<td><code>SetupX</code></td><td><code>(X::any()) -&gt; (R::any())</code></td>
-</tr>
-<tr>
-<td><code>Cleanup</code></td><td><code>(R::any()) -&gt; any()</code></td>
-</tr>
-<tr>
-<td><code>CleanupX</code></td><td><code>(X::any(), R::any()) -&gt; any()</code></td>
-</tr>
-<tr>
-<td><code>Instantiator</code></td><td><code>((R::any()) -&gt; Tests) | {with, [AbstractTestFun::((any()) -&gt; any())]}</code></td>
-</tr>
-<tr>
-<td><code>Where</code></td><td><code>local | spawn | {spawn, Node::atom()}</code></td>
-</tr>
-</table>
-</center>
-(these are explained in more detail further below.)</p>
-
-The following representations specify fixture handling for test sets:
-<dl>
-<dt><code>{setup, Setup, Tests | Instantiator}</code></dt>
-<dt><code>{setup, Setup, Cleanup, Tests | Instantiator}</code></dt>
-<dt><code>{setup, Where, Setup, Tests | Instantiator}</code></dt>
-<dt><code>{setup, Where, Setup, Cleanup, Tests | Instantiator}</code></dt>
-<dd><code>setup</code> sets up a single fixture for running all of the specified
-tests, with optional teardown afterwards. The arguments are described in
-detail below.
-</dd>
-<dt><code>{node, Node::atom(), Tests | Instantiator}</code></dt>
-<dt><code>{node, Node::atom(), Args::string(), Tests | Instantiator}</code></dt>
-<dd><code>node</code> is like <code>setup</code>, but with a built-in behaviour: it starts a
-slave node for the duration of the tests. The atom <code>Node</code> should have
-the format <code>[email protected]</code>, and <code>Args</code> are the optional
-arguments to the new node; see <code>slave:start_link/3</code> for details.
-</dd>
-<dt><code>{foreach, Where, Setup, Cleanup, [Tests | Instantiator]}</code></dt>
-<dt><code>{foreach, Setup, Cleanup, [Tests | Instantiator]}</code></dt>
-<dt><code>{foreach, Where, Setup, [Tests | Instantiator]}</code></dt>
-<dt><code>{foreach, Setup, [Tests | Instantiator]}</code></dt>
-<dd><code>foreach</code> is used to set up a fixture and optionally tear it down
-afterwards, repeated for each single one of the specified test sets.
-</dd>
-<dt><code>{foreachx, Where, SetupX, CleanupX,
- Pairs::[{X::any(), ((X::any(), R::any()) -&gt; Tests)}]}</code></dt>
-<dt><code>{foreachx, SetupX, CleanupX, Pairs}</code></dt>
-<dt><code>{foreachx, Where, SetupX, Pairs}</code></dt>
-<dt><code>{foreachx, SetupX, Pairs}</code></dt>
-<dd><code>foreachx</code> is like <code>foreach</code>, but uses a list of pairs, each
-containing an extra argument <code>X</code> and an extended instantiator function.
-</dd>
-</dl>
-
-<p>A <code>Setup</code> function is executed just before any of the specified tests
-are run, and a <code>Cleanup</code> function is executed when no more of the
-specified tests will be run, regardless of the reason. A <code>Setup</code>
-function takes no argument, and returns some value which will be passed
-as it is to the <code>Cleanup</code> function. A <code>Cleanup</code> function should do
-whatever necessary and return some arbitrary value, such as the atom
-<code>ok</code>. (<code>SetupX</code> and <code>CleanupX</code> functions are similar, but receive one
-additional argument: some value <code>X</code>, which depends on the context.) When
-no <code>Cleanup</code> function is specified, a dummy function is used which has
-no effect.</p>
-
-<p>An <code>Instantiator</code> function receives the same value as the <code>Cleanup</code>
-function, i.e., the value returned by the <code>Setup</code> function. It should
-then behave much like a generator (see <a href="#Primitives">Primitives</a>), and
-return a test set whose tests have been <em>instantiated</em> with the
-given value. A special case is the syntax <code>{with, [AbstractTestFun]}</code>
-which represents an instantiator function that distributes the value
-over a list of unary functions; see <a href="#Primitives">Primitives</a>: <code>{with, X,
-[...]}</code> for more details.</p>
-
-A <code>Where</code> term controls how the specified tests are executed. The
-default is <code>spawn</code>, which means that the current process handles the
-setup and teardown, while the tests are executed in a subprocess.
-<code>{spawn, Node}</code> is like <code>spawn</code>, but runs the subprocess on the
-specified node. <code>local</code> means that the current process will handle both
-setup/teardown and running the tests - the drawback is that if a test
-times out so that the process is killed, the <em>cleanup will not be
-performed</em>; hence, avoid this for persistent fixtures such as file
-operations. In general, 'local' should only be used when:
-<ul>
- <li>the setup/teardown needs to be executed by the process that will
- run the tests;</li>
- <li>no further teardown needs to be done if the process is killed
- (i.e., no state outside the process was affected by the setup)</li>
-</ul>
-
-<h4><a name="Lazy_generators">Lazy generators</a></h4>
-
-<p>Sometimes, it can be convenient not to produce the whole set of test
-descriptions before the testing begins; for example, if you want to
-generate a huge amount of tests that would take up too much space to
-keep in memory all at once.</p>
-
-<p>It is fairly easy to write a generator which, each time it is called,
-either produces an empty list if it is done, or otherwise produces a
-list containing a single test case plus a new generator which will
-produce the rest of the tests. This demonstrates the basic pattern:</p>
-
-<pre> lazy_test_() -&gt;
- lazy_gen(10000).
-
- lazy_gen(N) -&gt;
- {generator,
- fun () -&gt;
- if N &gt; 0 -&gt;
- [?_test(...)
- | lazy_gen(N-1)];
- true -&gt;
- []
- end
- end}.</pre>
-
-<p>When EUnit traverses the test representation in order to run the tests,
-the new generator will not be called to produce the next test until the
-previous test has been executed.</p>
-
-Note that it is easiest to write this kind of recursive generator using
-a help function, like the <code>lazy_gen/1</code> function above. It can also be
-written using a recursive fun, if you prefer to not clutter your
-function namespace and are comfortable with writing that kind of code.
-
-<hr>
-<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
-<p><i>Generated by EDoc, Apr 22 2009, 22:37:19.</i></p>
-</body>
-</html>
diff --git a/lib/eunit/doc/overview.edoc b/lib/eunit/doc/overview.edoc
index be05a13fba..ad449cb6fc 100644
--- a/lib/eunit/doc/overview.edoc
+++ b/lib/eunit/doc/overview.edoc
@@ -5,8 +5,7 @@
@title EUnit - a Lightweight Unit Testing Framework for Erlang
-@author Richard Carlsson <[email protected]>
- [http://user.it.uu.se/~richardc/]
+@author Richard Carlsson <[email protected]>
@author Micka�l R�mond <[email protected]>
[http://www.process-one.net/]
@copyright 2004-2007 Micka�l R�mond, Richard Carlsson
@@ -913,7 +912,7 @@ To make the descriptions simpler, we first list some definitions:
<td>`CleanupX'</td><td>`(X::any(), R::any()) -> any()'</td>
</tr>
<tr>
-<td>`Instantiator'</td><td>`((R::any()) -> Tests | {with, [AbstractTestFun::((any()) -> any())]}'</td>
+<td>`Instantiator'</td><td>`((R::any()) -> Tests) | {with, [AbstractTestFun::((any()) -> any())]}'</td>
</tr>
<tr>
<td>`Where'</td><td>`local | spawn | {spawn, Node::atom()}'</td>
diff --git a/lib/eunit/doc/packages-frame.html b/lib/eunit/doc/packages-frame.html
deleted file mode 100644
index 52b45534f5..0000000000
--- a/lib/eunit/doc/packages-frame.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
-<title>The eunit application</title>
-<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
-</head>
-<body bgcolor="white">
-<h2 class="indextitle">Packages</h2>
-<table width="100%" border="0" summary="list of packages"></table>
-</body>
-</html> \ No newline at end of file
diff --git a/lib/eunit/doc/src/make.dep b/lib/eunit/doc/src/make.dep
deleted file mode 100644
index d68f888403..0000000000
--- a/lib/eunit/doc/src/make.dep
+++ /dev/null
@@ -1,19 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex chapter.tex eunit.tex part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/eunit/doc/src/notes.xml b/lib/eunit/doc/src/notes.xml
index a02d76c5b9..e68330482c 100644
--- a/lib/eunit/doc/src/notes.xml
+++ b/lib/eunit/doc/src/notes.xml
@@ -32,6 +32,63 @@
</header>
<p>This document describes the changes made to the EUnit application.</p>
+<section><title>Eunit 2.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Generate separate surefire XMLs for each test suite</p>
+ <p>
+ Previously the test cases of all test suites (=modules)
+ were put in one and the same surefire report XML thereby
+ breaking the principle of least astonishment and making
+ post analysis harder. Assume the following layout:</p>
+ <p>
+ src/x.erl src/y.erl test/x_tests.erl test/y_tests.erl</p>
+ <p>
+ The results for both x_tests and y_tests were written to
+ only one report grouped under either module x or y
+ (seemingly randomly).</p>
+ <p>
+ Now two reports, one for module x and one for y are
+ generated. (Thanks to Klas Johansson)</p>
+ <p>
+ Own Id: OTP-9465</p>
+ </item>
+ <item>
+ <p>
+ Updated to EUnit version 2.2.0</p>
+ <p>
+ New macros assertNotMatch(Guard, Expr),
+ assertNotEqual(Unexpected, Expr), and
+ assertNotException(Class, Term, Expr). </p>
+ <p>
+ The debugMsg macro now also prints the pid of the current
+ process.</p>
+ <p>
+ When testing all modules in a directory, tests in
+ Module_tests.erl are no longer executed twice.</p>
+ <p>
+ The use of regexp internally has been replaced with re.
+ (Thanks to Richard Carlsson)</p>
+ <p>
+ Own Id: OTP-9505</p>
+ </item>
+ <item>
+ <p>
+ Removed some never-matching clauses reported by dialyzer
+ Updated author e-mails and homepages Removed cvs keywords
+ from files Removed files that should not be checked in
+ (Thanks to Richard Carlsson)</p>
+ <p>
+ Own Id: OTP-9591</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Eunit 2.1.7</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/eunit/doc/stylesheet.css b/lib/eunit/doc/stylesheet.css
deleted file mode 100644
index e426a90483..0000000000
--- a/lib/eunit/doc/stylesheet.css
+++ /dev/null
@@ -1,55 +0,0 @@
-/* standard EDoc style sheet */
-body {
- font-family: Verdana, Arial, Helvetica, sans-serif;
- margin-left: .25in;
- margin-right: .2in;
- margin-top: 0.2in;
- margin-bottom: 0.2in;
- color: #000000;
- background-color: #ffffff;
-}
-h1,h2 {
- margin-left: -0.2in;
-}
-div.navbar {
- background-color: #add8e6;
- padding: 0.2em;
-}
-h2.indextitle {
- padding: 0.4em;
- background-color: #add8e6;
-}
-h3.function,h3.typedecl {
- background-color: #add8e6;
- padding-left: 1em;
-}
-div.spec {
- margin-left: 2em;
- background-color: #eeeeee;
-}
-a.module,a.package {
- text-decoration:none
-}
-a.module:hover,a.package:hover {
- background-color: #eeeeee;
-}
-ul.definitions {
- list-style-type: none;
-}
-ul.index {
- list-style-type: none;
- background-color: #eeeeee;
-}
-
-/*
- * Minor style tweaks
- */
-ul {
- list-style-type: square;
-}
-table {
- border-collapse: collapse;
-}
-td {
- padding: 3
-}
diff --git a/lib/eunit/examples/Makefile b/lib/eunit/examples/Makefile
index d1b5bac224..48ec2ebf2b 100644
--- a/lib/eunit/examples/Makefile
+++ b/lib/eunit/examples/Makefile
@@ -13,8 +13,6 @@
# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
# AB. All Rights Reserved.''
#
-# $Id$
-#
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
diff --git a/lib/eunit/include/eunit.hrl b/lib/eunit/include/eunit.hrl
index 82ba982f03..db68d8ae60 100644
--- a/lib/eunit/include/eunit.hrl
+++ b/lib/eunit/include/eunit.hrl
@@ -13,8 +13,6 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id: eunit.hrl 337 2009-03-09 08:38:28Z rcarlsson $
-%%
%% Copyright (C) 2004-2006 Micka�l R�mond, Richard Carlsson
%% Including this file turns on testing and defines TEST, unless NOTEST
@@ -39,6 +37,7 @@
-ifndef(EUNIT_HRL).
-define(EUNIT_HRL, true).
+
%% allow defining TEST to override NOTEST
-ifdef(TEST).
-undef(NOTEST).
@@ -164,7 +163,7 @@
%% This is mostly a convenience which gives more detailed reports.
%% Note: Guard is a guarded pattern, and can not be used for value.
-ifdef(NOASSERT).
--define(assertMatch(Guard,Expr),ok).
+-define(assertMatch(Guard, Expr), ok).
-else.
-define(assertMatch(Guard, Expr),
((fun () ->
@@ -174,17 +173,37 @@
[{module, ?MODULE},
{line, ?LINE},
{expression, (??Expr)},
- {expected, (??Guard)},
+ {pattern, (??Guard)},
{value, __V}]})
end
end)())).
-endif.
-define(_assertMatch(Guard, Expr), ?_test(?assertMatch(Guard, Expr))).
+%% This is the inverse case of assertMatch, for convenience.
+-ifdef(NOASSERT).
+-define(assertNotMatch(Guard, Expr), ok).
+-else.
+-define(assertNotMatch(Guard, Expr),
+ ((fun () ->
+ __V = (Expr),
+ case __V of
+ Guard -> .erlang:error({assertNotMatch_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expression, (??Expr)},
+ {pattern, (??Guard)},
+ {value, __V}]});
+ _ -> ok
+ end
+ end)())).
+-endif.
+-define(_assertNotMatch(Guard, Expr), ?_test(?assertNotMatch(Guard, Expr))).
+
%% This is a convenience macro which gives more detailed reports when
%% the expected LHS value is not a pattern, but a computed value
-ifdef(NOASSERT).
--define(assertEqual(Expect,Expr),ok).
+-define(assertEqual(Expect, Expr), ok).
-else.
-define(assertEqual(Expect, Expr),
((fun (__X) ->
@@ -201,9 +220,29 @@
-endif.
-define(_assertEqual(Expect, Expr), ?_test(?assertEqual(Expect, Expr))).
+%% This is the inverse case of assertEqual, for convenience.
+-ifdef(NOASSERT).
+-define(assertNotEqual(Unexpected, Expr), ok).
+-else.
+-define(assertNotEqual(Unexpected, Expr),
+ ((fun (__X) ->
+ case (Expr) of
+ __X -> .erlang:error({assertNotEqual_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expression, (??Expr)},
+ {value, __X}]});
+ _ -> ok
+ end
+ end)(Unexpected))).
+-endif.
+-define(_assertNotEqual(Unexpected, Expr),
+ ?_test(?assertNotEqual(Unexpected, Expr))).
+
%% Note: Class and Term are patterns, and can not be used for value.
+%% Term can be a guarded pattern, but Class cannot.
-ifdef(NOASSERT).
--define(assertException(Class, Term, Expr),ok).
+-define(assertException(Class, Term, Expr), ok).
-else.
-define(assertException(Class, Term, Expr),
((fun () ->
@@ -212,7 +251,7 @@
[{module, ?MODULE},
{line, ?LINE},
{expression, (??Expr)},
- {expected,
+ {pattern,
"{ "++(??Class)++" , "++(??Term)
++" , [...] }"},
{unexpected_success, __V}]})
@@ -223,7 +262,7 @@
[{module, ?MODULE},
{line, ?LINE},
{expression, (??Expr)},
- {expected,
+ {pattern,
"{ "++(??Class)++" , "++(??Term)
++" , [...] }"},
{unexpected_exception,
@@ -243,6 +282,43 @@
-define(_assertExit(Term, Expr), ?_assertException(exit, Term, Expr)).
-define(_assertThrow(Term, Expr), ?_assertException(throw, Term, Expr)).
+%% This is the inverse case of assertException, for convenience.
+%% Note: Class and Term are patterns, and can not be used for value.
+%% Both Class and Term can be guarded patterns.
+-ifdef(NOASSERT).
+-define(assertNotException(Class, Term, Expr), ok).
+-else.
+-define(assertNotException(Class, Term, Expr),
+ ((fun () ->
+ try (Expr) of
+ _ -> ok
+ catch
+ __C:__T ->
+ case __C of
+ Class ->
+ case __T of
+ Term ->
+ .erlang:error({assertNotException_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expression, (??Expr)},
+ {pattern,
+ "{ "++(??Class)++" , "
+ ++(??Term)++" , [...] }"},
+ {unexpected_exception,
+ {__C, __T,
+ .erlang:get_stacktrace()
+ }}]});
+ _ -> ok
+ end;
+ _ -> ok
+ end
+ end
+ end)())).
+-endif.
+-define(_assertNotException(Class, Term, Expr),
+ ?_test(?assertNotException(Class, Term, Expr))).
+
%% Macros for running operating system commands. (Note that these
%% require EUnit to be present at runtime, or at least eunit_lib.)
@@ -267,7 +343,7 @@
%% these are only used for testing; they always return 'ok' on success,
%% and have no effect if debugging/testing is turned off
-ifdef(NOASSERT).
--define(assertCmdStatus(N, Cmd),ok).
+-define(assertCmdStatus(N, Cmd), ok).
-else.
-define(assertCmdStatus(N, Cmd),
((fun () ->
@@ -285,7 +361,7 @@
-define(assertCmd(Cmd), ?assertCmdStatus(0, Cmd)).
-ifdef(NOASSERT).
--define(assertCmdOutput(T, Cmd),ok).
+-define(assertCmdOutput(T, Cmd), ok).
-else.
-define(assertCmdOutput(T, Cmd),
((fun () ->
@@ -313,11 +389,12 @@
-define(debugHere, ok).
-define(debugFmt(S, As), ok).
-define(debugVal(E), (E)).
--define(debugTime(S,E), (E)).
+-define(debugTime(S, E), (E)).
-else.
-define(debugMsg(S),
(begin
- .io:fwrite(user, <<"~s:~w: ~s\n">>, [?FILE, ?LINE, S]),
+ .io:fwrite(user, <<"~s:~w:~w: ~s\n">>,
+ [?FILE, ?LINE, self(), S]),
ok
end)).
-define(debugHere, (?debugMsg("<-"))).
@@ -327,7 +404,7 @@
?debugFmt(<<"~s = ~P">>, [(??E), __V, 15]),
__V
end)(E))).
--define(debugTime(S,E),
+-define(debugTime(S, E),
((fun () ->
{__T0, _} = statistics(wall_clock),
__V = (E),
@@ -337,4 +414,5 @@
end)())).
-endif.
+
-endif. % EUNIT_HRL
diff --git a/lib/eunit/src/Makefile b/lib/eunit/src/Makefile
index 4897c20ec1..bec2fdbe0b 100644
--- a/lib/eunit/src/Makefile
+++ b/lib/eunit/src/Makefile
@@ -26,8 +26,9 @@ INCLUDE=../include
ERL_COMPILE_FLAGS += -pa $(EBIN) -I$(INCLUDE) +warn_unused_vars +nowarn_shadow_vars +warn_unused_import +warn_obsolete_guard
+PARSE_TRANSFORM = eunit_autoexport.erl
+
SOURCES= \
- eunit_autoexport.erl \
eunit_striptests.erl \
eunit.erl \
eunit_tests.erl \
@@ -43,6 +44,8 @@ SOURCES= \
INCLUDE_FILES = eunit.hrl
+PARSE_TRANSFORM_BIN = $(PARSE_TRANSFORM:%.erl=$(EBIN)/%.$(EMULATOR))
+
OBJECTS=$(SOURCES:%.erl=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET)
INCLUDE_DELIVERABLES = $(INCLUDE_FILES:%=$(INCLUDE)/%)
@@ -59,7 +62,7 @@ APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
# Targets
# ----------------------------------------------------
-debug opt: $(OBJECTS)
+debug opt: $(PARSE_TRANSFORM_BIN) $(OBJECTS)
docs:
@@ -86,6 +89,8 @@ realclean: clean
$(EBIN)/%.$(EMULATOR):%.erl
erlc -W $(ERL_COMPILE_FLAGS) -o$(EBIN) $<
+$(OBJECTS): $(PARSE_TRANSFORM_BIN)
+
# ----------------------------------------------------
# Special Build Targets
# ----------------------------------------------------
@@ -103,9 +108,9 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(OBJECTS) $(RELSYSDIR)/ebin
+ $(INSTALL_DATA) $(PARSE_TRANSFORM_BIN) $(OBJECTS) $(RELSYSDIR)/ebin
$(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(SOURCES) $(RELSYSDIR)/src
+ $(INSTALL_DATA) $(PARSE_TRANSFORM) $(SOURCES) $(RELSYSDIR)/src
$(INSTALL_DIR) $(RELSYSDIR)/include
$(INSTALL_DATA) $(INCLUDE_DELIVERABLES) $(RELSYSDIR)/include
diff --git a/lib/eunit/src/eunit.app.src b/lib/eunit/src/eunit.app.src
index 4fd76588c3..5e16dfa2ce 100644
--- a/lib/eunit/src/eunit.app.src
+++ b/lib/eunit/src/eunit.app.src
@@ -5,17 +5,17 @@
{vsn, "%VSN%"},
{modules, [eunit,
eunit_autoexport,
- eunit_striptests,
- eunit_server,
+ eunit_data,
+ eunit_lib,
+ eunit_listener,
eunit_proc,
eunit_serial,
+ eunit_server,
+ eunit_striptests,
+ eunit_surefire,
eunit_test,
eunit_tests,
- eunit_lib,
- eunit_listener,
- eunit_data,
- eunit_tty,
- eunit_surefire]},
+ eunit_tty]},
{registered,[]},
- {applications, [stdlib]},
+ {applications, [kernel,stdlib]},
{env, []}]}.
diff --git a/lib/eunit/src/eunit.erl b/lib/eunit/src/eunit.erl
index da35c5c2ec..95857e83c8 100644
--- a/lib/eunit/src/eunit.erl
+++ b/lib/eunit/src/eunit.erl
@@ -13,13 +13,10 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id: eunit.erl 339 2009-04-05 14:10:47Z rcarlsson $
-%%
%% @copyright 2004-2009 Micka�l R�mond, Richard Carlsson
-%% @author Micka&euml;l R&eacute;mond <[email protected]>
+%% @author Micka�l R�mond <[email protected]>
%% [http://www.process-one.net/]
-%% @author Richard Carlsson <[email protected]>
-%% [http://user.it.uu.se/~richardc/]
+%% @author Richard Carlsson <[email protected]>
%% @version {@version}, {@date} {@time}
%% @doc This module is the main EUnit user interface.
diff --git a/lib/eunit/src/eunit_autoexport.erl b/lib/eunit/src/eunit_autoexport.erl
index 7b153c1194..099bcb222e 100644
--- a/lib/eunit/src/eunit_autoexport.erl
+++ b/lib/eunit/src/eunit_autoexport.erl
@@ -13,9 +13,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id: eunit_autoexport.erl 329 2009-03-01 11:23:32Z rcarlsson $
-%%
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @copyright 2006 Richard Carlsson
%% @private
%% @see eunit
diff --git a/lib/eunit/src/eunit_data.erl b/lib/eunit/src/eunit_data.erl
index 0543b6c543..392d378a0e 100644
--- a/lib/eunit/src/eunit_data.erl
+++ b/lib/eunit/src/eunit_data.erl
@@ -13,9 +13,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @copyright 2006 Richard Carlsson
%% @private
%% @see eunit
@@ -146,8 +144,10 @@ iter_next(I = #iter{next = [T | Ts]}) ->
iter_prev(#iter{prev = []}) ->
none;
-iter_prev(#iter{prev = [T | Ts], next = Next, pos = Pos} = I) ->
- {T, I#iter{prev = Ts, next = [T | Next], pos = Pos - 1}}.
+iter_prev(#iter{prev = [T | Ts]} = I) ->
+ {T, I#iter{prev = Ts,
+ next = [T | I#iter.next],
+ pos = I#iter.pos - 1}}.
%% ---------------------------------------------------------------------
@@ -363,7 +363,8 @@ parse({file, F} = T) when is_list(F) ->
parse({dir, D}=T) when is_list(D) ->
case eunit_lib:is_string(D) of
true ->
- {data, {"directory \"" ++ D ++ "\"", get_directory_modules(D)}};
+ {data, {"directory \"" ++ D ++ "\"",
+ get_directory_module_tests(D)}};
false ->
bad_test(T)
end;
@@ -385,10 +386,10 @@ parse({S, T1} = T) when is_list(S) ->
end;
parse({S, T1}) when is_binary(S) ->
group(#group{tests = T1, desc = S});
-parse(T) when tuple_size(T) > 2, is_list(element(1, T)) ->
+parse(T) when is_tuple(T), size(T) > 2, is_list(element(1, T)) ->
[S | Es] = tuple_to_list(T),
parse({S, list_to_tuple(Es)});
-parse(T) when tuple_size(T) > 2, is_binary(element(1, T)) ->
+parse(T) when is_tuple(T), size(T) > 2, is_binary(element(1, T)) ->
[S | Es] = tuple_to_list(T),
parse({S, list_to_tuple(Es)});
parse(M) when is_atom(M) ->
@@ -596,7 +597,7 @@ testfuns(Es, M, TestSuffix, GeneratorSuffix) ->
%% ---------------------------------------------------------------------
-%% Getting a test set from a file
+%% Getting a test set from a file (text file or object file)
%% @throws {file_read_error, {Reason::atom(), Message::string(),
%% fileName()}}
@@ -625,17 +626,23 @@ get_file_tests(F) ->
is_module_filename(F) ->
filename:extension(F) =:= code:objfile_extension().
+objfile_test({M, File}) ->
+ {setup,
+ fun () ->
+ %% TODO: better error/stacktrace for this internal fun
+ code:purge(M),
+ {module,M} = code:load_abs(filename:rootname(File)),
+ ok
+ end,
+ {module, M}};
objfile_test(File) ->
+ objfile_test({objfile_module(File), File}).
+
+objfile_module(File) ->
try
- {module, M} = lists:keyfind(module, 1, beam_lib:info(File)),
- {setup,
- fun () ->
- %% TODO: better error/stacktrace for this internal fun
- code:purge(M),
- {module,M} = code:load_abs(filename:rootname(File)),
- ok
- end,
- {module, M}}
+ {value, {module, M}} = lists:keysearch(module, 1,
+ beam_lib:info(File)),
+ M
catch
_:_ ->
throw({file_read_error,
@@ -644,15 +651,34 @@ objfile_test(File) ->
%% ---------------------------------------------------------------------
-%% Getting a list of module names from object files in a directory
-
-%% @throws {file_read_error, {Reason::atom(), Message::string(),
-%% fileName()}}
+%% Getting a set of module tests from the object files in a directory
+
+%% @throws {file_read_error,
+%% {Reason::atom(), Message::string(), fileName()}}
+
+get_directory_module_tests(D) ->
+ Ms = get_directory_modules(D),
+ %% for all 'm' in the set, remove 'm_tests' if present
+ F = fun ({M,_}, S) ->
+ Name = atom_to_list(M),
+ case lists:suffix(?DEFAULT_TESTMODULE_SUFFIX, Name) of
+ false ->
+ Name1 = Name ++ ?DEFAULT_TESTMODULE_SUFFIX,
+ M1 = list_to_atom(Name1),
+ dict:erase(M1, S);
+ true ->
+ S
+ end
+ end,
+ [objfile_test(Obj)
+ || Obj <- dict:to_list(lists:foldl(F, dict:from_list(Ms), Ms))].
%% TODO: handle packages (recursive search for files)
-
get_directory_modules(D) ->
- [objfile_test(filename:join(D, F))
+ [begin
+ F1 = filename:join(D, F),
+ {objfile_module(F1), F1}
+ end
|| F <- eunit_lib:list_dir(D), is_module_filename(F)].
diff --git a/lib/eunit/src/eunit_internal.hrl b/lib/eunit/src/eunit_internal.hrl
index 8d0ac30bd7..92694ec39b 100644
--- a/lib/eunit/src/eunit_internal.hrl
+++ b/lib/eunit/src/eunit_internal.hrl
@@ -1,11 +1,7 @@
%% -------------------------------------------------------------------
%% File: eunit_internal.hrl
%%
-%% $Id: eunit_internal.hrl 329 2009-03-01 11:23:32Z rcarlsson $
-%%
-%% @author Richard Carlsson <[email protected]>
-%% @copyright 2006 Richard Carlsson
-%% @doc
+%% Copyright (C) 2006 Richard Carlsson <[email protected]>
-define(SERVER, eunit_server).
-define(DEFAULT_TEST_SUFFIX, "_test").
diff --git a/lib/eunit/src/eunit_lib.erl b/lib/eunit/src/eunit_lib.erl
index 45d2387e7b..1c41e229c5 100644
--- a/lib/eunit/src/eunit_lib.erl
+++ b/lib/eunit/src/eunit_lib.erl
@@ -13,13 +13,10 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id: eunit_lib.erl 339 2009-04-05 14:10:47Z rcarlsson $
-%%
%% @copyright 2004-2007 Micka�l R�mond, Richard Carlsson
%% @author Micka�l R�mond <[email protected]>
%% [http://www.process-one.net/]
-%% @author Richard Carlsson <[email protected]>
-%% [http://user.it.uu.se/~richardc/]
+%% @author Richard Carlsson <[email protected]>
%% @private
%% @see eunit
%% @doc Utility functions for eunit
diff --git a/lib/eunit/src/eunit_listener.erl b/lib/eunit/src/eunit_listener.erl
index 20faecbf01..ecaac424a2 100644
--- a/lib/eunit/src/eunit_listener.erl
+++ b/lib/eunit/src/eunit_listener.erl
@@ -13,9 +13,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @copyright 2009 Richard Carlsson
%% @private
%% @see eunit
diff --git a/lib/eunit/src/eunit_proc.erl b/lib/eunit/src/eunit_proc.erl
index e2d51d8bd5..ec7d93fd48 100644
--- a/lib/eunit/src/eunit_proc.erl
+++ b/lib/eunit/src/eunit_proc.erl
@@ -13,9 +13,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @copyright 2006 Richard Carlsson
%% @private
%% @see eunit
diff --git a/lib/eunit/src/eunit_serial.erl b/lib/eunit/src/eunit_serial.erl
index d9ccae86f9..80e79116e3 100644
--- a/lib/eunit/src/eunit_serial.erl
+++ b/lib/eunit/src/eunit_serial.erl
@@ -13,9 +13,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @copyright 2006 Richard Carlsson
%% @private
%% @see eunit
diff --git a/lib/eunit/src/eunit_server.erl b/lib/eunit/src/eunit_server.erl
index bf1bb9bcef..2002930abb 100644
--- a/lib/eunit/src/eunit_server.erl
+++ b/lib/eunit/src/eunit_server.erl
@@ -13,9 +13,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id: eunit_server.erl 267 2008-10-19 18:48:03Z rcarlsson $
-%%
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @copyright 2006 Richard Carlsson
%% @private
%% @see eunit
@@ -59,8 +57,9 @@ watch(Server, Module, Opts) when is_atom(Module) ->
watch_path(Server, Path, Opts) ->
command(Server, {watch, {path, filename:flatten(Path)}, Opts}).
+%% note that the user must use $ at the end to match whole paths only
watch_regexp(Server, Regex, Opts) ->
- case regexp:parse(Regex) of
+ case re:compile(Regex,[anchored]) of
{ok, R} ->
command(Server, {watch, {regexp, R}, Opts});
{error, _}=Error ->
@@ -278,8 +277,8 @@ is_watched(Path, St) ->
match_any(sets:to_list(St#state.regexps), Path).
match_any([R | Rs], Str) ->
- case regexp:first_match(Str, R) of
- {match, _, _} -> true;
+ case re:run(Str, R, [{capture,none}]) of
+ match -> true;
_ -> match_any(Rs, Str)
end;
match_any([], _Str) -> false.
diff --git a/lib/eunit/src/eunit_striptests.erl b/lib/eunit/src/eunit_striptests.erl
index 606e44b286..c6ade389ba 100644
--- a/lib/eunit/src/eunit_striptests.erl
+++ b/lib/eunit/src/eunit_striptests.erl
@@ -13,10 +13,8 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id: eunit_striptests.erl 329 2009-03-01 11:23:32Z rcarlsson $
-%%
-%% @author Richard Carlsson <[email protected]>
-%% @author Eric Merritt <[email protected]>
+%% @author Richard Carlsson <[email protected]>
+%% @author Eric Merritt <[email protected]>
%% @copyright 2006 Richard Carlsson, Eric Merritt
%% @private
%% @see eunit
diff --git a/lib/eunit/src/eunit_surefire.erl b/lib/eunit/src/eunit_surefire.erl
index dfb08c90b2..2a6cbca14d 100644
--- a/lib/eunit/src/eunit_surefire.erl
+++ b/lib/eunit/src/eunit_surefire.erl
@@ -13,9 +13,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id: $
-%%
-%% @author Micka&euml;l R&eacute;mond <[email protected]>
+%% @author Micka�l R�mond <[email protected]>
%% @copyright 2009 Micka�l R�mond, Paul Guyot
%% @see eunit
%% @doc Surefire reports for EUnit (Format used by Maven and Atlassian
@@ -58,12 +56,13 @@
{
name :: chars(),
description :: chars(),
- result :: ok | {failed, tuple()} | {aborted, tuple()} | {skipped, tuple()},
+ result :: ok | {failed, tuple()} | {aborted, tuple()} | {skipped, term()},
time :: integer(),
output :: binary()
}).
-record(testsuite,
{
+ id = 0 :: integer(),
name = <<>> :: binary(),
time = 0 :: integer(),
output = <<>> :: binary(),
@@ -76,7 +75,7 @@
-record(state, {verbose = false,
indent = 0,
xmldir = ".",
- testsuite = #testsuite{}
+ testsuites = [] :: [#testsuite{}]
}).
start() ->
@@ -89,55 +88,60 @@ init(Options) ->
XMLDir = proplists:get_value(dir, Options, ?XMLDIR),
St = #state{verbose = proplists:get_bool(verbose, Options),
xmldir = XMLDir,
- testsuite = #testsuite{}},
+ testsuites = []},
receive
{start, _Reference} ->
St
end.
terminate({ok, _Data}, St) ->
- TestSuite = St#state.testsuite,
+ TestSuites = St#state.testsuites,
XmlDir = St#state.xmldir,
- write_report(TestSuite, XmlDir),
+ write_reports(TestSuites, XmlDir),
ok;
terminate({error, _Reason}, _St) ->
%% Don't report any errors here, since eunit_tty takes care of that.
%% Just terminate.
ok.
-handle_begin(group, Data, St) ->
+handle_begin(Kind, Data, St) when Kind == group; Kind == test ->
+ %% Run this code both for groups and tests; test is a bit
+ %% surprising: This is a workaround for the fact that we don't get
+ %% a group (handle_begin(group, ...) for testsuites (modules)
+ %% which only have one test case. In that case we get a test case
+ %% with an id comprised of just one integer - the group id.
NewId = proplists:get_value(id, Data),
case NewId of
[] ->
St;
- [_GroupId] ->
+ [GroupId] ->
Desc = proplists:get_value(desc, Data),
- TestSuite = St#state.testsuite,
- NewTestSuite = TestSuite#testsuite{name = Desc},
- St#state{testsuite=NewTestSuite};
+ TestSuite = #testsuite{id = GroupId, name = Desc},
+ St#state{testsuites=store_suite(TestSuite, St#state.testsuites)};
%% Surefire format is not hierarchic: Ignore subgroups:
_ ->
St
- end;
-handle_begin(test, _Data, St) ->
- St.
+ end.
handle_end(group, Data, St) ->
%% Retrieve existing test suite:
case proplists:get_value(id, Data) of
[] ->
St;
- [_GroupId|_] ->
- TestSuite = St#state.testsuite,
+ [GroupId|_] ->
+ TestSuites = St#state.testsuites,
+ TestSuite = lookup_suite_by_group_id(GroupId, TestSuites),
%% Update TestSuite data:
Time = proplists:get_value(time, Data),
Output = proplists:get_value(output, Data),
NewTestSuite = TestSuite#testsuite{ time = Time, output = Output },
- St#state{testsuite=NewTestSuite}
+ St#state{testsuites=store_suite(NewTestSuite, TestSuites)}
end;
handle_end(test, Data, St) ->
%% Retrieve existing test suite:
- TestSuite = St#state.testsuite,
+ [GroupId|_] = proplists:get_value(id, Data),
+ TestSuites = St#state.testsuites,
+ TestSuite = lookup_suite_by_group_id(GroupId, TestSuites),
%% Create test case:
Name = format_name(proplists:get_value(source, Data),
@@ -149,7 +153,7 @@ handle_end(test, Data, St) ->
TestCase = #testcase{name = Name, description = Desc,
time = Time,output = Output},
NewTestSuite = add_testcase_to_testsuite(Result, TestCase, TestSuite),
- St#state{testsuite=NewTestSuite}.
+ St#state{testsuites=store_suite(NewTestSuite, TestSuites)}.
%% Cancel group does not give information on the individual cancelled test case
%% We ignore this event
@@ -157,7 +161,9 @@ handle_cancel(group, _Data, St) ->
St;
handle_cancel(test, Data, St) ->
%% Retrieve existing test suite:
- TestSuite = St#state.testsuite,
+ [GroupId|_] = proplists:get_value(id, Data),
+ TestSuites = St#state.testsuites,
+ TestSuite = lookup_suite_by_group_id(GroupId, TestSuites),
%% Create test case:
Name = format_name(proplists:get_value(source, Data),
@@ -171,7 +177,7 @@ handle_cancel(test, Data, St) ->
NewTestSuite = TestSuite#testsuite{
skipped = TestSuite#testsuite.skipped+1,
testcases=[TestCase|TestSuite#testsuite.testcases] },
- St#state{testsuite=NewTestSuite}.
+ St#state{testsuites=store_suite(NewTestSuite, TestSuites)}.
format_name({Module, Function, Arity}, Line) ->
lists:flatten([atom_to_list(Module), ":", atom_to_list(Function), "/",
@@ -183,6 +189,12 @@ format_desc(Desc) when is_binary(Desc) ->
format_desc(Desc) when is_list(Desc) ->
Desc.
+lookup_suite_by_group_id(GroupId, TestSuites) ->
+ #testsuite{} = lists:keyfind(GroupId, #testsuite.id, TestSuites).
+
+store_suite(#testsuite{id=GroupId} = TestSuite, TestSuites) ->
+ lists:keystore(GroupId, #testsuite.id, TestSuites, TestSuite).
+
%% Add testcase to testsuite depending on the result of the test.
add_testcase_to_testsuite(ok, TestCaseTmp, TestSuite) ->
TestCase = TestCaseTmp#testcase{ result = ok },
@@ -214,6 +226,10 @@ add_testcase_to_testsuite({error, Exception}, TestCaseTmp, TestSuite) ->
%% Write a report to the XML directory.
%% This function opens the report file, calls write_report_to/2 and closes the file.
%% ----------------------------------------------------------------------------
+write_reports(TestSuites, XmlDir) ->
+ lists:foreach(fun(TestSuite) -> write_report(TestSuite, XmlDir) end,
+ TestSuites).
+
write_report(#testsuite{name = Name} = TestSuite, XmlDir) ->
Filename = filename:join(XmlDir, lists:flatten(["TEST-", escape_suitename(Name)], ".xml")),
case file:open(Filename, [write, raw]) of
@@ -293,7 +309,6 @@ write_testcase(
output = Output},
FileDescriptor) ->
DescriptionAttr = case Description of
- <<>> -> [];
[] -> [];
_ -> [<<" description=\"">>, escape_attr(Description), <<"\"">>]
end,
@@ -302,7 +317,6 @@ write_testcase(
<<"\" name=\"">>, escape_attr(Name), <<"\"">>,
DescriptionAttr],
ContentAndEndTag = case {Result, Output} of
- {ok, []} -> [<<"/>">>, ?NEWLINE];
{ok, <<>>} -> [<<"/>">>, ?NEWLINE];
_ -> [<<">">>, ?NEWLINE, format_testcase_result(Result), format_testcase_output(Output), ?INDENT, <<"</testcase>">>, ?NEWLINE]
end,
@@ -351,7 +365,6 @@ format_testcase_result({skipped, Term}) ->
%% Empty output is simply the empty string.
%% Other output is inside a <system-out> xml tag.
%% ----------------------------------------------------------------------------
-format_testcase_output([]) -> [];
format_testcase_output(Output) ->
[?INDENT, ?INDENT, <<"<system-out>">>, escape_text(Output), ?NEWLINE, ?INDENT, ?INDENT, <<"</system-out>">>, ?NEWLINE].
@@ -369,8 +382,6 @@ format_time_s([Digit1, Digit2, Digit3 | Tail]) -> [lists:reverse(Tail), $., Digi
%% Escape a suite's name to generate the filename.
%% Remark: we might overwrite another testsuite's file.
%% ----------------------------------------------------------------------------
-escape_suitename([Head | _T] = List) when is_list(Head) ->
- escape_suitename(lists:flatten(List));
escape_suitename(Binary) when is_binary(Binary) ->
escape_suitename(binary_to_list(Binary));
escape_suitename("module '" ++ String) ->
@@ -378,7 +389,6 @@ escape_suitename("module '" ++ String) ->
escape_suitename(String) ->
escape_suitename(String, []).
-escape_suitename(Binary, Acc) when is_binary(Binary) -> escape_suitename(binary_to_list(Binary), Acc);
escape_suitename([], Acc) -> lists:reverse(Acc);
escape_suitename([$ | Tail], Acc) -> escape_suitename(Tail, [$_ | Acc]);
escape_suitename([$' | Tail], Acc) -> escape_suitename(Tail, Acc);
diff --git a/lib/eunit/src/eunit_test.erl b/lib/eunit/src/eunit_test.erl
index d322c4b420..bca49ae626 100644
--- a/lib/eunit/src/eunit_test.erl
+++ b/lib/eunit/src/eunit_test.erl
@@ -13,9 +13,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id: eunit_test.erl 336 2009-03-06 14:43:21Z rcarlsson $
-%%
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @copyright 2006 Richard Carlsson
%% @private
%% @see eunit
@@ -131,12 +129,27 @@ macro_test_() ->
[{module,_},
{line,_},
{expression,_},
- {expected,"[ _ ]"},
+ {pattern,"[ _ ]"},
{value,[]}]},
_}}
= run_testfun(F)
end),
?_test(begin
+ {?LINE, F} = ?_assertNotMatch(ok, error),
+ {ok, ok} = run_testfun(F)
+ end),
+ ?_test(begin
+ {?LINE, F} = ?_assertNotMatch([_], [42]),
+ {error,{error,{assertNotMatch_failed,
+ [{module,_},
+ {line,_},
+ {expression,_},
+ {pattern,"[ _ ]"},
+ {value,[42]}]},
+ _}}
+ = run_testfun(F)
+ end),
+ ?_test(begin
{?LINE, F} = ?_assertEqual(ok, ok),
{ok, ok} = run_testfun(F)
end),
@@ -152,6 +165,20 @@ macro_test_() ->
= run_testfun(F)
end),
?_test(begin
+ {?LINE, F} = ?_assertNotEqual(1, 0),
+ {ok, ok} = run_testfun(F)
+ end),
+ ?_test(begin
+ {?LINE, F} = ?_assertNotEqual(2, 1+1),
+ {error,{error,{assertNotEqual_failed,
+ [{module,_},
+ {line,_},
+ {expression,_},
+ {value,2}]},
+ _}}
+ = run_testfun(F)
+ end),
+ ?_test(begin
{?LINE, F} = ?_assertException(error, badarith,
erlang:error(badarith)),
{ok, ok} = run_testfun(F)
@@ -162,7 +189,7 @@ macro_test_() ->
[{module,_},
{line,_},
{expression,_},
- {expected,_},
+ {pattern,_},
{unexpected_success,ok}]},
_}}
= run_testfun(F)
@@ -174,15 +201,48 @@ macro_test_() ->
[{module,_},
{line,_},
{expression,_},
- {expected,_},
+ {pattern,_},
+ {unexpected_exception,
+ {error,badarith,_}}]},
+ _}}
+ = run_testfun(F)
+ end),
+ ?_test(begin
+ {?LINE, F} = ?_assertError(badarith,
+ erlang:error(badarith)),
+ {ok, ok} = run_testfun(F)
+ end),
+ ?_test(begin
+ {?LINE, F} = ?_assertExit(normal, exit(normal)),
+ {ok, ok} = run_testfun(F)
+ end),
+ ?_test(begin
+ {?LINE, F} = ?_assertThrow(foo, throw(foo)),
+ {ok, ok} = run_testfun(F)
+ end),
+ ?_test(begin
+ {?LINE, F} = ?_assertNotException(error, badarith, 42),
+ {ok, ok} = run_testfun(F)
+ end),
+ ?_test(begin
+ {?LINE, F} = ?_assertNotException(error, badarith,
+ erlang:error(badarg)),
+ {ok, ok} = run_testfun(F)
+ end),
+ ?_test(begin
+ {?LINE, F} = ?_assertNotException(error, badarith,
+ erlang:error(badarith)),
+ {error,{error,{assertNotException_failed,
+ [{module,_},
+ {line,_},
+ {expression,_},
+ {pattern,_},
{unexpected_exception,
{error,badarith,_}}]},
_}}
= run_testfun(F)
end)
]}.
-
-under_eunit_test() -> ?assert(?UNDER_EUNIT).
-endif.
diff --git a/lib/eunit/src/eunit_tests.erl b/lib/eunit/src/eunit_tests.erl
index 37c0b4d6ae..47ea0aaf46 100644
--- a/lib/eunit/src/eunit_tests.erl
+++ b/lib/eunit/src/eunit_tests.erl
@@ -13,9 +13,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id: eunit_tests.erl 238 2007-11-15 10:23:54Z mremond $
-%%
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @copyright 2007 Richard Carlsson
%% @private
%% @see eunit
@@ -26,17 +24,17 @@
-include("eunit.hrl").
-ifdef(TEST).
-%% Cause all the other modules to be tested as well as this one.
-full_test_() ->
- %%{application, eunit}. % this currently causes a loop
- %% We use the below until loop detection is implemented
- [eunit_autoexport,
- eunit_striptests,
- eunit_server,
- eunit_proc,
- eunit_serial,
- eunit_test,
- eunit_lib,
- eunit_data,
- eunit_tty].
+id(X) -> X. % for suppressing compiler warnings
-endif.
+
+under_eunit_test() -> ?assert(?UNDER_EUNIT).
+
+let_test() -> ?assertEqual(42, ?LET(X, 17, X+25)).
+
+if_test_() ->
+ [?_assertEqual(17, ?IF(id(1) > 0, 17, 42)),
+ ?_assertEqual(42, ?IF(id(1) < 0, 17, 42))].
+
+matches_test_() ->
+ [?_assert(?MATCHES("hel"++_, "hello")),
+ ?_assertNot(?MATCHES("hal"++_, "hello"))].
diff --git a/lib/eunit/src/eunit_tty.erl b/lib/eunit/src/eunit_tty.erl
index 5fe0140559..e3e7b710b2 100644
--- a/lib/eunit/src/eunit_tty.erl
+++ b/lib/eunit/src/eunit_tty.erl
@@ -13,9 +13,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id: eunit_tty.erl 330 2009-03-01 16:28:02Z rcarlsson $
-%%
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @copyright 2006-2009 Richard Carlsson
%% @private
%% @see eunit
diff --git a/lib/eunit/vsn.mk b/lib/eunit/vsn.mk
index d7edd7977b..b0a77a225b 100644
--- a/lib/eunit/vsn.mk
+++ b/lib/eunit/vsn.mk
@@ -1 +1 @@
-EUNIT_VSN = 2.1.7
+EUNIT_VSN = 2.2.1
diff --git a/lib/gs/contribs/bonk/sounder.erl b/lib/gs/contribs/bonk/sounder.erl
index 11ab03d167..e6f69a1616 100644
--- a/lib/gs/contribs/bonk/sounder.erl
+++ b/lib/gs/contribs/bonk/sounder.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -72,13 +72,13 @@ stop() ->
sounder ! {stop},
ok end.
-new(File) when list(File) -> new(list_to_atom(File));
-new(File) when atom(File) ->
+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 integer(No) ->
+play(No) when is_integer(No) ->
catch begin check(),
sounder ! {play, No, self()},
wait_for_ack(sounder) end.
@@ -94,14 +94,14 @@ go() ->
loop(Port) ->
receive
- {new, File, From} when atom(File) ->
+ {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 integer(No) ->
+ {play,No,From} when is_integer(No) ->
Port ! {self(),{command,[No]}},
From ! {sounder,wait_for_ack(Port)},
loop(Port);
@@ -118,13 +118,13 @@ loop(Port) ->
nosound() ->
receive
- {new,File,From} when atom(File) ->
+ {new,File,From} when is_atom(File) ->
From ! {sounder,{ok,silent}},
nosound();
{play,silent,From} ->
From ! {sounder,true},
nosound();
- {play,No,From} when integer(No) ->
+ {play,No,From} when is_integer(No) ->
From ! {sounder,{error,no_audio_cap}},
nosound();
{stop} ->
@@ -135,7 +135,7 @@ nosound() ->
wait_for_ack(sounder) ->
receive {sounder,Res} -> Res end;
-wait_for_ack(Port) when port(Port) ->
+wait_for_ack(Port) when is_port(Port) ->
receive
{Port,{data,"ok"}} ->
ok;
@@ -149,7 +149,7 @@ wait_for_ack(Port) when port(Port) ->
check() ->
case whereis(sounder) of
- Pid when pid(Pid) ->
+ Pid when is_pid(Pid) ->
ok;
undefined ->
throw({error,sounder_not_started})
diff --git a/lib/gs/contribs/cols/cols.erl b/lib/gs/contribs/cols/cols.erl
index 67b46d0dfb..111c9a58f1 100644
--- a/lib/gs/contribs/cols/cols.erl
+++ b/lib/gs/contribs/cols/cols.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -278,7 +278,7 @@ fall_column([], _X, _Y, ColumnAcc, ChecksAcc) ->
fall_column([black|Colors], X, Y, ColumnAcc, ChecksAcc) ->
case find_box(Colors) of
false -> {ColumnAcc, ChecksAcc};
- NewColors when list(NewColors) ->
+ NewColors when is_list(NewColors) ->
fall_one_step(NewColors, X, Y, ColumnAcc, ChecksAcc)
end;
fall_column([Color|Colors], X, Y, ColumnAcc, ChecksAcc) ->
@@ -330,7 +330,7 @@ new_column_list([], _, _) -> [].
%%----------------------------------------------------------------------
%% Returns: a reversed list of colors.
%%----------------------------------------------------------------------
-columntuple_to_list(ColumnTuple) when tuple(ColumnTuple) ->
+columntuple_to_list(ColumnTuple) when is_tuple(ColumnTuple) ->
columntuple_to_list(tuple_to_list(ColumnTuple),[]).
columntuple_to_list([],Acc) -> Acc;
diff --git a/lib/gs/contribs/mandel/mandel.erl b/lib/gs/contribs/mandel/mandel.erl
index d4d2452463..0f1df5c665 100644
--- a/lib/gs/contribs/mandel/mandel.erl
+++ b/lib/gs/contribs/mandel/mandel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -119,7 +119,7 @@ start_client(Opts,Nodes) ->
try_random(random,Low,High) ->
random:uniform()*(High-Low)+Low;
-try_random(Float,_Low,_High) when number(Float) -> Float.
+try_random(Float,_Low,_High) when is_number(Float) -> Float.
%%-----------------------------------------------------------------
diff --git a/lib/gs/contribs/othello/othello_board.erl b/lib/gs/contribs/othello/othello_board.erl
index 0206ba2ded..212ba9bfe1 100644
--- a/lib/gs/contribs/othello/othello_board.erl
+++ b/lib/gs/contribs/othello/othello_board.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -147,7 +147,7 @@ but_pressed("Help",_ButtId,_User,GamePid,_Shell,_Wids,_Op) ->
but_pressed("Newgame",_ButtId,_User,GamePid,_Shell,Wids,Options) ->
new_game(GamePid,Wids,Options);
but_pressed([],ButtId,User,GamePid,_Shell,_Wids,_Op)
- when pid(GamePid),User == player ->
+ when is_pid(GamePid),User == player ->
[C,R] = atom_to_list(ButtId),
GamePid ! {self(),position,othello_adt:pos(C-96,translate(R-48))},
GamePid;
@@ -243,7 +243,7 @@ game_msg(Msg,User,GamePid,Shell,Wids,Options) ->
end.
-new_game(GamePid,Wids,Options) when pid(GamePid) ->
+new_game(GamePid,Wids,Options) when is_pid(GamePid) ->
exit(GamePid,kill),
new_game(Wids,Options);
new_game(_,Wids,Options) ->
diff --git a/lib/gs/doc/src/make.dep b/lib/gs/doc/src/make.dep
deleted file mode 100644
index b33ed3b2de..0000000000
--- a/lib/gs/doc/src/make.dep
+++ /dev/null
@@ -1,58 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex gs.tex gs_chapter1.tex gs_chapter2.tex \
- gs_chapter3.tex gs_chapter4.tex gs_chapter5.tex \
- gs_chapter6.tex gs_chapter7.tex gs_chapter8.tex \
- part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-gs_chapter2.tex: examples/ex1.erl examples/ex2.erl
-
-gs_chapter4.tex: examples/ex3.erl examples/ex4.erl examples/ex5.erl \
- examples/ex6.erl
-
-gs_chapter5.tex: examples/ex15.erl
-
-gs_chapter6.tex: examples/ex16.erl
-
-gs_chapter7.tex: examples/ex17.erl
-
-gs_chapter8.tex: examples/ex10.erl examples/ex11.erl examples/ex12.erl \
- examples/ex13.erl examples/ex14.erl examples/ex7.erl \
- examples/ex8.erl examples/ex9.erl
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: pics/gs1-1-image-1.ps pics/gs1-1-image-2.ps \
- pics/gs1-1-image-3.ps
-
-book.dvi: pics/ex1.ps pics/gs1-1-image-4.ps
-
-book.dvi: pics/ex15.ps
-
-book.dvi: pics/ex16.ps
-
-book.dvi: pics/packer1.ps pics/packer2.ps
-
-book.dvi: pics/arc.ps pics/buttons.ps pics/ex10.ps pics/ex11.ps \
- pics/ex12.ps pics/ex13.ps pics/ex14.ps pics/ex8.ps \
- pics/ex9.ps pics/image.ps pics/line.ps pics/oval.ps \
- pics/polygon.ps pics/rectangle.ps pics/text.ps \
- pics/window.ps
-
diff --git a/lib/gs/doc/src/notes.xml b/lib/gs/doc/src/notes.xml
index 744efbd4fc..c32db495a1 100644
--- a/lib/gs/doc/src/notes.xml
+++ b/lib/gs/doc/src/notes.xml
@@ -30,7 +30,21 @@
</header>
<p>This document describes the changes made to the GS application.</p>
- <section><title>GS 1.5.13</title>
+ <section><title>GS 1.5.14</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Remove misc. compiler warnings</p>
+ <p>
+ Own Id: OTP-9542</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>GS 1.5.13</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/gs/examples/calc2.erl b/lib/gs/examples/calc2.erl
index d28780de01..0e841397f6 100644
--- a/lib/gs/examples/calc2.erl
+++ b/lib/gs/examples/calc2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -54,7 +54,7 @@ calc() ->
calc_loop(Lbl,M,V,Op) ->
receive
- {gs,_,click,D,_} when integer(D) ->
+ {gs,_,click,D,_} when is_integer(D) ->
digit_press(Lbl,M,V*10+D,Op);
{gs,_,click,'C',_} ->
c(Lbl,M,V,Op);
diff --git a/lib/gs/src/Makefile b/lib/gs/src/Makefile
index a648d3cf13..964966ba00 100644
--- a/lib/gs/src/Makefile
+++ b/lib/gs/src/Makefile
@@ -90,7 +90,7 @@ clean:
# Special Build Targets
# ----------------------------------------------------
-gstk_generic.hrl: gs_make.erl
+gstk_generic.hrl: gs_make.erl ../ebin/gs_make.$(EMULATOR) ../ebin/gs.$(EMULATOR)
$(ERL) -pa $(EBIN) -s gs_make -s erlang halt -noshell
$(APP_TARGET): $(APP_SRC) ../vsn.mk
@@ -99,6 +99,8 @@ $(APP_TARGET): $(APP_SRC) ../vsn.mk
$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
sed -e 's;%VSN%;$(VSN);' $< > $@
+$(GSTK_GENERIC_TARGET): gstk_generic.hrl
+
# ----------------------------------------------------
# Release Target
# ----------------------------------------------------
diff --git a/lib/gs/src/gstk_editor.erl b/lib/gs/src/gstk_editor.erl
index 3e0c8240e4..8cc7021cc6 100644
--- a/lib/gs/src/gstk_editor.erl
+++ b/lib/gs/src/gstk_editor.erl
@@ -243,14 +243,14 @@ option(Option, Gstkid, _MainW, DB, Editor) ->
Editor, " ins ",AI," ", gstk:to_ascii(Text)]};
clear -> {c, [Editor, " delete 1.0 end"]};
{load, File} ->
- {ok, F2,_} = regexp:gsub(File, [92,92], "/"),
+ F2 = re:replace(File, [92,92], "/", [global,{return,list}]),
case gstk:call(["ed_load ", Editor, " ", gstk:to_ascii(F2)]) of
{result, _} -> none;
{bad_result,Re} ->
{error,{no_such_file,editor,load,F2,Re}}
end;
{save, File} ->
- {ok, F2,_} = regexp:gsub(File, [92,92], "/"),
+ F2 = re:replace(File, [92,92], "/", [global,{return,list}]),
case gstk:call(["ed_save ",Editor," ",gstk:to_ascii(F2)]) of
{result, _} -> none;
{bad_result,Re} ->
diff --git a/lib/gs/src/gstk_generic.erl b/lib/gs/src/gstk_generic.erl
index 3ddb69efc5..2cc6c4c2d3 100644
--- a/lib/gs/src/gstk_generic.erl
+++ b/lib/gs/src/gstk_generic.erl
@@ -414,7 +414,7 @@ gen_font(_Opt,Gstkid,_TkW,DB,_ExtraArg) ->
gen_label({text,Text},Opts,Gstkid,TkW,DB,ExtraArg,S,P,C) ->
out_opts(Opts,Gstkid,TkW,DB,ExtraArg,[" -text ", gstk:to_ascii(Text), " -bi {}"|S],P,C);
gen_label({image,Img},Opts,Gstkid,TkW,DB,ExtraArg,S,P,C) ->
- {ok, I2,_} = regexp:gsub(Img, [92,92], "/"),
+ I2 = re:replace(Img, [92,92], "/", [global,{return,list}]),
out_opts(Opts,Gstkid,TkW,DB,ExtraArg,[" -bi \"@", I2, "\" -text {}"|S],P,C).
gen_label(_Opt,_Gstkid,TkW,_DB,_ExtraArg) ->
case gstk:call([TkW, " cg -bit"]) of
diff --git a/lib/gs/src/gstk_image.erl b/lib/gs/src/gstk_image.erl
index 5ad37cf6de..9adbe42386 100644
--- a/lib/gs/src/gstk_image.erl
+++ b/lib/gs/src/gstk_image.erl
@@ -227,10 +227,10 @@ event(DB, Gstkid, Etype, Edata, Args) ->
option(Option, Gstkid, _Canvas, _DB, _AItem) ->
case Option of
{bitmap, Bitmap} ->
- {ok, BF,_} = regexp:gsub(Bitmap, [92,92], "/"),
+ BF = re:replace(Bitmap, [92,92], "/", [global,{return,list}]),
{s, [" -bi @", BF]};
{load_gif, File} ->
- {ok, F2,_} = regexp:gsub(File, [92,92], "/"),
+ F2 = re:replace(File, [92,92], "/", [global,{return,list}]),
{Photo_item, _item} = Gstkid#gstkid.widget_data,
{c,[Photo_item, " configure -file ", gstk:to_ascii(F2)]};
{pix_val, {Coords,Color}} ->
diff --git a/lib/gs/src/tool_utils.erl b/lib/gs/src/tool_utils.erl
index b07e92c4f0..d09af5f22f 100644
--- a/lib/gs/src/tool_utils.erl
+++ b/lib/gs/src/tool_utils.erl
@@ -98,7 +98,8 @@ open_help_default(Parent, File) ->
_Else -> "netscape -remote \"openURL(file:" ++ File ++ ")\""
end;
{win32,_AnyType} ->
- "netscape.exe -h " ++ regexp:gsub(File,"\\\\","/");
+ "netscape.exe -h " ++
+ re:replace(File,"\\\\","/",[global,{return,list}]);
_Other ->
unknown
end;
diff --git a/lib/gs/vsn.mk b/lib/gs/vsn.mk
index 4c91857572..4894c6c13a 100644
--- a/lib/gs/vsn.mk
+++ b/lib/gs/vsn.mk
@@ -1,2 +1,2 @@
-GS_VSN = 1.5.13
+GS_VSN = 1.5.14
diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl
index 0b47c7b6e1..1483b2aee1 100644
--- a/lib/hipe/cerl/erl_bif_types.erl
+++ b/lib/hipe/cerl/erl_bif_types.erl
@@ -366,7 +366,7 @@ type(erlang, '>', 2, Xs = [Lhs, Rhs]) ->
is_integer(LhsMax), is_integer(RhsMin), RhsMin >= LhsMax -> F;
true -> t_boolean()
end;
- false -> t_boolean()
+ false -> compare('>', Lhs, Rhs)
end,
strict(Xs, Ans);
type(erlang, '>=', 2, Xs = [Lhs, Rhs]) ->
@@ -384,7 +384,7 @@ type(erlang, '>=', 2, Xs = [Lhs, Rhs]) ->
is_integer(LhsMax), is_integer(RhsMin), RhsMin > LhsMax -> F;
true -> t_boolean()
end;
- false -> t_boolean()
+ false -> compare('>=', Lhs, Rhs)
end,
strict(Xs, Ans);
type(erlang, '<', 2, Xs = [Lhs, Rhs]) ->
@@ -402,7 +402,7 @@ type(erlang, '<', 2, Xs = [Lhs, Rhs]) ->
is_integer(LhsMin), is_integer(RhsMax), RhsMax =< LhsMin -> F;
true -> t_boolean()
end;
- false -> t_boolean()
+ false -> compare('<', Lhs, Rhs)
end,
strict(Xs, Ans);
type(erlang, '=<', 2, Xs = [Lhs, Rhs]) ->
@@ -420,7 +420,7 @@ type(erlang, '=<', 2, Xs = [Lhs, Rhs]) ->
is_integer(LhsMin), is_integer(RhsMax), RhsMax < LhsMin -> F;
true -> t_boolean()
end;
- false -> t_boolean()
+ false -> compare('=<', Lhs, Rhs)
end,
strict(Xs, Ans);
type(erlang, '+', 1, Xs) ->
@@ -672,11 +672,12 @@ type(erlang, call_on_load_function, 1, Xs) ->
type(erlang, cancel_timer, 1, Xs) ->
strict(arg_types(erlang, cancel_timer, 1), Xs,
fun (_) -> t_sup(t_integer(), t_atom('false')) end);
+type(erlang, check_old_code, 1, Xs) ->
+ strict(arg_types(erlang, check_old_code, 1), Xs,
+ fun (_) -> t_boolean() end);
type(erlang, check_process_code, 2, Xs) ->
strict(arg_types(erlang, check_process_code, 2), Xs,
fun (_) -> t_boolean() end);
-type(erlang, concat_binary, 1, Xs) ->
- strict(arg_types(erlang, concat_binary, 1), Xs, fun (_) -> t_binary() end);
type(erlang, crc32, 1, Xs) ->
strict(arg_types(erlang, crc32, 1), Xs, fun (_) -> t_crc32() end);
type(erlang, crc32, 2, Xs) ->
@@ -702,7 +703,7 @@ type(erlang, demonitor, 1, Xs) ->
type(erlang, demonitor, 2, Xs) ->
strict(arg_types(erlang, demonitor, 2), Xs, fun (_) -> t_boolean() end);
type(erlang, disconnect_node, 1, Xs) ->
- strict(arg_types(erlang, disconnect_node, 1), Xs, fun (_) -> t_boolean() end);
+ strict(arg_types(erlang, disconnect_node, 1), Xs, fun (_) -> t_sup([t_boolean(), t_atom('ignored')]) end);
type(erlang, display, 1, _) -> t_atom('true');
type(erlang, display_string, 1, Xs) ->
strict(arg_types(erlang, display_string, 1), Xs, fun(_) -> t_atom('true') end);
@@ -736,6 +737,7 @@ type(erlang, element, 2, Xs) ->
type(erlang, erase, 0, _) -> t_any();
type(erlang, erase, 1, _) -> t_any();
type(erlang, external_size, 1, _) -> t_integer();
+type(erlang, external_size, 2, _) -> t_integer();
type(erlang, finish_after_on_load, 2, Xs) ->
%% Internal BIF used by on_load.
strict(arg_types(erlang, finish_after_on_load, 2), Xs,
@@ -797,7 +799,8 @@ type(erlang, get_module_info, 2, Xs) ->
end
end);
type(erlang, get_stacktrace, 0, _) ->
- t_list(t_tuple([t_atom(), t_atom(), t_sup([t_arity(), t_list()])]));
+ t_list(t_tuple([t_atom(), t_atom(), t_sup([t_arity(), t_list()]),
+ t_list()]));
type(erlang, group_leader, 0, _) -> t_pid();
type(erlang, group_leader, 2, Xs) ->
strict(arg_types(erlang, group_leader, 2), Xs,
@@ -1124,7 +1127,7 @@ type(erlang, nodes, 0, _) -> t_list(t_node());
type(erlang, nodes, 1, Xs) ->
strict(arg_types(erlang, nodes, 1), Xs, fun (_) -> t_list(t_node()) end);
type(erlang, now, 0, _) ->
- t_time();
+ t_timestamp();
type(erlang, open_port, 2, Xs) ->
strict(arg_types(erlang, open_port, 2), Xs, fun (_) -> t_port() end);
type(erlang, phash, 2, Xs) ->
@@ -1199,6 +1202,7 @@ type(erlang, process_flag, 2, Xs) ->
case t_atom_vals(Flag) of
['error_handler'] -> t_atom();
['min_heap_size'] -> t_non_neg_integer();
+ ['scheduler'] -> t_non_neg_integer();
['monitor_nodes'] -> t_boolean();
['priority'] -> t_process_priority_level();
['save_calls'] -> t_non_neg_integer();
@@ -1585,8 +1589,7 @@ type(erlang, system_info, 1, Xs) ->
['multi_scheduling_blockers'] ->
t_list(t_pid());
['os_type'] ->
- t_tuple([t_sup([t_atom('ose'), % XXX: undocumented
- t_atom('unix'),
+ t_tuple([t_sup([t_atom('unix'),
t_atom('vxworks'),
t_atom('win32')]),
t_atom()]);
@@ -1900,7 +1903,7 @@ type(prim_file, internal_native2name, 1, Xs) ->
fun (_) -> t_prim_file_name() end);
type(prim_file, internal_normalize_utf8, 1, Xs) ->
strict(arg_types(prim_file, internal_normalize_utf8, 1), Xs,
- fun (_) -> t_binary() end);
+ fun (_) -> t_unicode_string() end);
%%-- gen_tcp ------------------------------------------------------------------
%% NOTE: All type information for this module added to avoid loss of precision
type(gen_tcp, accept, 1, Xs) ->
@@ -2325,10 +2328,7 @@ type(lists, keyfind, 3, Xs) ->
case t_tuple_subtypes(Tuple) of
unknown -> Ret;
List ->
- Keys = [type(erlang, element, 2, [Y, S])
- || S <- List],
- Infs = [t_inf(Key, X) || Key <- Keys],
- case all_is_none(Infs) of
+ case key_comparisons_fail(X, Y, List) of
true -> t_atom('false');
false -> Ret
end
@@ -2358,9 +2358,7 @@ type(lists, keymember, 3, Xs) ->
case t_tuple_subtypes(Tuple) of
unknown -> t_boolean();
List ->
- Keys = [type(erlang, element, 2, [Y,S]) || S <- List],
- Infs = [t_inf(Key, X) || Key <- Keys],
- case all_is_none(Infs) of
+ case key_comparisons_fail(X, Y, List) of
true -> t_atom('false');
false -> t_boolean()
end
@@ -2390,10 +2388,7 @@ type(lists, keysearch, 3, Xs) ->
case t_tuple_subtypes(Tuple) of
unknown -> Ret;
List ->
- Keys = [type(erlang, element, 2, [Y, S])
- || S <- List],
- Infs = [t_inf(Key, X) || Key <- Keys],
- case all_is_none(Infs) of
+ case key_comparisons_fail(X, Y, List) of
true -> t_atom('false');
false -> Ret
end
@@ -2693,7 +2688,7 @@ type(os, getpid, 0, _) -> t_string();
type(os, putenv, 2, Xs) ->
strict(arg_types(os, putenv, 2), Xs, fun (_) -> t_atom('true') end);
type(os, timestamp, 0, _) ->
- t_time();
+ t_timestamp();
%%-- re -----------------------------------------------------------------------
type(re, compile, 1, Xs) ->
strict(arg_types(re, compile, 1), Xs,
@@ -2821,9 +2816,6 @@ list_replace(1, E, [_X | Xs]) ->
any_is_none_or_unit(Ts) ->
lists:any(fun erl_types:t_is_none_or_unit/1, Ts).
-all_is_none(Ts) ->
- lists:all(fun erl_types:t_is_none/1, Ts).
-
check_guard([X], Test, Type) ->
check_guard_single(X, Test, Type).
@@ -3176,6 +3168,59 @@ arith(Op, X1, X2) ->
end.
%%=============================================================================
+%% Comparison of terms
+%%=============================================================================
+
+compare(Op, Lhs, Rhs) ->
+ case t_is_none(t_inf(Lhs, Rhs)) of
+ false -> t_boolean();
+ true ->
+ case Op of
+ '<' -> always_smaller(Lhs, Rhs);
+ '>' -> always_smaller(Rhs, Lhs);
+ '=<' -> always_smaller(Lhs, Rhs);
+ '>=' -> always_smaller(Rhs, Lhs)
+ end
+ end.
+
+always_smaller(Type1, Type2) ->
+ {Min1, Max1} = type_ranks(Type1),
+ {Min2, Max2} = type_ranks(Type2),
+ if Max1 < Min2 -> t_atom('true');
+ Min1 > Max2 -> t_atom('false');
+ true -> t_boolean()
+ end.
+
+type_ranks(Type) ->
+ type_ranks(Type, 1, 0, 0, type_order()).
+
+type_ranks(_Type, _I, Min, Max, []) -> {Min, Max};
+type_ranks(Type, I, Min, Max, [TypeClass|Rest]) ->
+ {NewMin, NewMax} =
+ case t_is_none(t_inf(Type, TypeClass)) of
+ true -> {Min, Max};
+ false -> case Min of
+ 0 -> {I, I};
+ _ -> {Min, I}
+ end
+ end,
+ type_ranks(Type, I+1, NewMin, NewMax, Rest).
+
+type_order() ->
+ [t_number(), t_atom(), t_reference(), t_fun(), t_port(), t_pid(), t_tuple(),
+ t_list(), t_binary()].
+
+key_comparisons_fail(X0, KeyPos, TupleList) ->
+ X = case t_is_number(t_inf(X0, t_number())) of
+ false -> X0;
+ true -> t_number()
+ end,
+ lists:all(fun(Tuple) ->
+ Key = type(erlang, element, 2, [KeyPos, Tuple]),
+ t_is_none(t_inf(Key, X))
+ end, TupleList).
+
+%%=============================================================================
-spec arg_types(atom(), atom(), arity()) -> [erl_types:erl_type()] | 'unknown'.
@@ -3396,10 +3441,10 @@ arg_types(erlang, call_on_load_function, 1) ->
[t_atom()];
arg_types(erlang, cancel_timer, 1) ->
[t_reference()];
+arg_types(erlang, check_old_code, 1) ->
+ [t_atom()];
arg_types(erlang, check_process_code, 2) ->
[t_pid(), t_atom()];
-arg_types(erlang, concat_binary, 1) ->
- [t_list(t_binary())];
arg_types(erlang, crc32, 1) ->
[t_iodata()];
arg_types(erlang, crc32, 2) ->
@@ -3442,6 +3487,8 @@ arg_types(erlang, exit, 2) ->
[t_sup(t_pid(), t_port()), t_any()];
arg_types(erlang, external_size, 1) ->
[t_any()]; % takes any term as input
+arg_types(erlang, external_size, 2) ->
+ [t_any(), t_list()]; % takes any term as input and a list of options
arg_types(erlang, finish_after_on_load, 2) ->
[t_atom(), t_boolean()];
arg_types(erlang, float, 1) ->
@@ -3696,6 +3743,7 @@ arg_types(erlang, process_display, 2) ->
arg_types(erlang, process_flag, 2) ->
[t_sup([t_atom('trap_exit'), t_atom('error_handler'),
t_atom('min_heap_size'), t_atom('priority'), t_atom('save_calls'),
+ t_atom('scheduler'), % undocumented
t_atom('monitor_nodes'), % undocumented
t_tuple([t_atom('monitor_nodes'), t_list()])]), % undocumented
t_sup([t_boolean(), t_atom(), t_non_neg_integer()])];
@@ -3712,7 +3760,10 @@ arg_types(erlang, purge_module, 1) ->
arg_types(erlang, put, 2) ->
[t_any(), t_any()];
arg_types(erlang, raise, 3) ->
- [t_raise_errorclass(), t_any(), type(erlang, get_stacktrace, 0, [])];
+ OldStyleType = t_list(t_tuple([t_atom(), t_atom(),
+ t_sup([t_arity(), t_list()])])),
+ NewStyleType = type(erlang, get_stacktrace, 0, []),
+ [t_raise_errorclass(), t_any(), t_sup(OldStyleType, NewStyleType)];
arg_types(erlang, read_timer, 1) ->
[t_reference()];
arg_types(erlang, ref_to_list, 1) ->
@@ -3734,7 +3785,7 @@ arg_types(erlang, send, 3) ->
arg_types(erlang, send_after, 3) ->
[t_non_neg_integer(), t_sup(t_pid(), t_atom()), t_any()];
arg_types(erlang, seq_trace, 2) ->
- [t_atom(), t_sup([t_boolean(), t_tuple([t_fixnum(), t_fixnum()]), t_nil()])];
+ [t_atom(), t_sup([t_boolean(), t_tuple([t_fixnum(), t_fixnum()]), t_fixnum(), t_nil()])];
arg_types(erlang, seq_trace_info, 1) ->
[t_seq_trace_info()];
arg_types(erlang, seq_trace_print, 1) ->
@@ -3983,7 +4034,7 @@ arg_types(ets, match_object, 3) ->
arg_types(ets, match_spec_compile, 1) ->
[t_matchspecs()];
arg_types(ets, match_spec_run_r, 3) ->
- [t_matchspecs(), t_any(), t_list()];
+ [t_list(t_tuple()),t_matchspecs(), t_list()];
arg_types(ets, member, 2) ->
[t_tab(), t_any()];
arg_types(ets, new, 2) ->
@@ -4015,8 +4066,12 @@ arg_types(ets, select_reverse, 3) ->
arg_types(ets, slot, 2) ->
[t_tab(), t_non_neg_fixnum()]; % 2nd arg can be 0
arg_types(ets, setopts, 2) ->
- Opt = t_sup(t_tuple([t_atom('heir'), t_pid(), t_any()]),
- t_tuple([t_atom('heir'), t_atom('none')])),
+ Opt = t_sup([t_tuple([t_atom('heir'), t_pid(), t_any()]),
+ t_tuple([t_atom('heir'), t_atom('none')]),
+ t_tuple([t_atom('protection'),
+ t_sup([t_atom('protected'),
+ t_atom('private'),
+ t_atom('public')])])]),
[t_tab(), t_sup(Opt, t_list(Opt))];
arg_types(ets, update_counter, 3) ->
Int = t_integer(),
@@ -4458,6 +4513,9 @@ t_date() ->
t_time() ->
t_tuple([t_non_neg_fixnum(), t_non_neg_fixnum(), t_non_neg_fixnum()]).
+t_timestamp() ->
+ t_tuple([t_non_neg_fixnum(), t_non_neg_fixnum(), t_non_neg_fixnum()]).
+
t_packet() ->
t_sup([t_binary(), t_iolist(), t_httppacket()]).
@@ -4805,6 +4863,9 @@ t_ets_info_items() ->
t_atom('owner'),
t_atom('protection'),
t_atom('size'),
+ t_atom('compressed'),
+ t_atom('heir'),
+ t_atom('stats'),
t_atom('type')]).
%% =====================================================================
diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl
index 1748c1cc16..0ff827ac37 100644
--- a/lib/hipe/cerl/erl_types.erl
+++ b/lib/hipe/cerl/erl_types.erl
@@ -211,7 +211,8 @@
record_field_diffs_to_string/2,
subst_all_vars_to_any/1,
lift_list_to_pos_empty/1,
- is_erl_type/1
+ is_erl_type/1,
+ atom_to_string/1
]).
%%-define(DO_ERL_TYPES_TEST, true).
@@ -242,12 +243,11 @@
-define(REC_TYPE_LIMIT, 2).
-define(TUPLE_TAG_LIMIT, 5).
--define(TUPLE_ARITY_LIMIT, 10).
+-define(TUPLE_ARITY_LIMIT, 8).
-define(SET_LIMIT, 13).
-define(MAX_BYTE, 255).
-define(MAX_CHAR, 16#10ffff).
--define(WIDENING_LIMIT, 7).
-define(UNIT_MULTIPLIER, 8).
-define(TAG_IMMED1_SIZE, 4).
@@ -3360,14 +3360,14 @@ t_to_string(?var(Id), _RecDict) when is_integer(Id) ->
record_to_string(Tag, [_|Fields], FieldNames, RecDict) ->
FieldStrings = record_fields_to_string(Fields, FieldNames, RecDict, []),
- "#" ++ atom_to_list(Tag) ++ "{" ++ string:join(FieldStrings, ",") ++ "}".
+ "#" ++ atom_to_string(Tag) ++ "{" ++ string:join(FieldStrings, ",") ++ "}".
record_fields_to_string([F|Fs], [{FName, _DefType}|FDefs], RecDict, Acc) ->
NewAcc =
case t_is_any(F) orelse t_is_atom('undefined', F) of
true -> Acc;
false ->
- StrFV = atom_to_list(FName) ++ "::" ++ t_to_string(F, RecDict),
+ StrFV = atom_to_string(FName) ++ "::" ++ t_to_string(F, RecDict),
%% ActualDefType = t_subtract(DefType, t_atom('undefined')),
%% Str = case t_is_any(ActualDefType) of
%% true -> StrFV;
@@ -3393,7 +3393,7 @@ field_diffs([F|Fs], [{FName, DefType}|FDefs], RecDict, Acc) ->
case t_is_subtype(F, DefType) of
true -> Acc;
false ->
- Str = atom_to_list(FName) ++ "::" ++ t_to_string(DefType, RecDict),
+ Str = atom_to_string(FName) ++ "::" ++ t_to_string(DefType, RecDict),
[Str|Acc]
end,
field_diffs(Fs, FDefs, RecDict, NewAcc);
@@ -3906,7 +3906,7 @@ t_form_to_string({type, _L, union, Args}) ->
string:join(t_form_to_string_list(Args), " | ");
t_form_to_string({type, _L, Name, []} = T) ->
try t_to_string(t_from_form(T))
- catch throw:{error, _} -> atom_to_list(Name) ++ "()"
+ catch throw:{error, _} -> atom_to_string(Name) ++ "()"
end;
t_form_to_string({type, _L, Name, List}) ->
io_lib:format("~w(~s)",
@@ -3920,6 +3920,11 @@ t_form_to_string_list([H|T], Acc) ->
t_form_to_string_list([], Acc) ->
lists:reverse(Acc).
+-spec atom_to_string(atom()) -> string().
+
+atom_to_string(Atom) ->
+ lists:flatten(io_lib:format("~w", [Atom])).
+
%%=============================================================================
%%
%% Utilities
diff --git a/lib/hipe/doc/src/make.dep b/lib/hipe/doc/src/make.dep
deleted file mode 100644
index d5f5844c21..0000000000
--- a/lib/hipe/doc/src/make.dep
+++ /dev/null
@@ -1,13 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex
-
diff --git a/lib/hipe/doc/src/notes.xml b/lib/hipe/doc/src/notes.xml
index 4eb188f76f..6b601e3039 100644
--- a/lib/hipe/doc/src/notes.xml
+++ b/lib/hipe/doc/src/notes.xml
@@ -30,6 +30,69 @@
</header>
<p>This document describes the changes made to HiPE.</p>
+<section><title>Hipe 3.8.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Clean up hipe.hrl.src (Thanks to Tuncer Ayaz)</p>
+ <p>
+ Own Id: OTP-9511</p>
+ </item>
+ <item>
+ <p>
+ Fix bug with binary pattern matching of floats of
+ variable size</p>
+ <p>
+ Pattern matching of floats with variable size
+ (&lt;&lt;F:S/float&gt;&gt;) did always fail. Judging from
+ similar code for ints, this bug is simply a typo.(Thanks
+ to Paul Guyot)</p>
+ <p>
+ Own Id: OTP-9556</p>
+ </item>
+ <item>
+ <p>
+ Quote atoms if necessary in types</p>
+ <p>
+ Atoms in some occurrences were not correctly quoted when
+ formatted to strings, for instance by the typer program
+ (Thanks to Tomas Abrahamsson)</p>
+ <p>
+ Update Dialyzer's reference results</p>
+ <p>
+ Own Id: OTP-9560</p>
+ </item>
+ <item>
+ <p>
+ Fix typer's crash for nonexisting files Remove unused
+ macro Fix bug in dataflow Decrease tuple arity limit This
+ fixes a memory related crash.</p>
+ <p>
+ Own Id: OTP-9597</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Types for several BIFs have been extended/corrected. Also
+ the types for types for <c>lists:keyfind/3</c>,
+ <c>lists:keysearch/3</c>, and <c>lists:keyemember/3</c>
+ have been corrected. The incorrect/incomplete types could
+ cause false dialyzer warnings.</p>
+ <p>
+ Own Id: OTP-9496</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Hipe 3.8</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/hipe/icode/hipe_beam_to_icode.erl b/lib/hipe/icode/hipe_beam_to_icode.erl
index d7eb035551..45b390acbd 100644
--- a/lib/hipe/icode/hipe_beam_to_icode.erl
+++ b/lib/hipe/icode/hipe_beam_to_icode.erl
@@ -281,10 +281,14 @@ needs_redtest(Leafness) ->
%%-----------------------------------------------------------------------
%%--- label & func_info combo ---
+trans_fun([{label,_}=F,{func_info,_,_,_}=FI|Instructions], Env) ->
+ %% Handle old code without a line instruction.
+ trans_fun([F,{line,[]},FI|Instructions], Env);
trans_fun([{label,B},{label,_},
{func_info,M,F,A},{label,L}|Instructions], Env) ->
trans_fun([{label,B},{func_info,M,F,A},{label,L}|Instructions], Env);
trans_fun([{label,B},
+ {line,_},
{func_info,{atom,_M},{atom,_F},_A},
{label,L}|Instructions], Env) ->
%% Emit code to handle function_clause errors. The BEAM test instructions
@@ -720,7 +724,7 @@ trans_fun([{test,bs_get_float2,{f,Lbl},[Ms,_Live,Size,Unit,{field_flags,Flags0},
?EXIT({bad_bs_size_constant,Size});
BitReg ->
Bits = mk_var(BitReg),
- {{bs_get_float,Unit,Flags}, [Bits,MsVar]}
+ {{bs_get_float,Unit,Flags}, [MsVar,Bits]}
end,
trans_op_call({hipe_bs_primop,Name}, Lbl, Args, [Dst,MsVar], Env, Instructions);
trans_fun([{test,bs_get_integer2,{f,Lbl},[Ms,_Live,Size,Unit,{field_flags,Flags0},X]}|
@@ -1142,6 +1146,11 @@ trans_fun([{trim,N,NY}|Instructions], Env) ->
Moves = trans_trim(N, NY),
Moves ++ trans_fun(Instructions, Env);
%%--------------------------------------------------------------------
+%% New line/1 instruction in R15.
+%%--------------------------------------------------------------------
+trans_fun([{line,_}|Instructions], Env) ->
+ trans_fun(Instructions,Env);
+%%--------------------------------------------------------------------
%%--- ERROR HANDLING ---
%%--------------------------------------------------------------------
trans_fun([X|_], _) ->
@@ -1869,6 +1878,8 @@ patch_make_funs([], FunIndex, Acc) ->
find_mfa([{label,_}|Code]) ->
find_mfa(Code);
+find_mfa([{line,_}|Code]) ->
+ find_mfa(Code);
find_mfa([{func_info,{atom,M},{atom,F},A}|_])
when is_atom(M), is_atom(F), is_integer(A), 0 =< A, A =< 255 ->
{M, F, A}.
diff --git a/lib/hipe/icode/hipe_icode_pp.erl b/lib/hipe/icode/hipe_icode_pp.erl
index 575bbfe43d..575bbfe43d 100755..100644
--- a/lib/hipe/icode/hipe_icode_pp.erl
+++ b/lib/hipe/icode/hipe_icode_pp.erl
diff --git a/lib/hipe/icode/hipe_icode_ssa.erl b/lib/hipe/icode/hipe_icode_ssa.erl
index 719d5d8f45..719d5d8f45 100755..100644
--- a/lib/hipe/icode/hipe_icode_ssa.erl
+++ b/lib/hipe/icode/hipe_icode_ssa.erl
diff --git a/lib/hipe/main/hipe.hrl.src b/lib/hipe/main/hipe.hrl.src
index a1fbeda9cf..e74f31b19d 100644
--- a/lib/hipe/main/hipe.hrl.src
+++ b/lib/hipe/main/hipe.hrl.src
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -50,9 +50,8 @@
%% Flags:
%% DEBUG - Turns on debugging. (Can be defined to a integer
%% value to determine the level of debugging)
-%% VERBOSE - More info is printed...
%% HIPE_LOGGING - Turn on logging of messages with erl_logger.
-%% DO_ASSERT - Turn on Assertions.
+%% DO_ASSERT - Turn on assertions.
%% TIMING - Turn on timing.
%% HIPE_INSTRUMENT_COMPILER - Turn on instrumentation of the compiler.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -107,13 +106,9 @@
%%
%% Define the exit macro
%%
--ifdef(VERBOSE).
--define(EXIT(Reason), erlang:error({?MODULE,?LINE,Reason})).
--else.
-define(EXIT(Reason),
?msg("EXITED with reason ~w @~w:~w\n", [Reason,?MODULE,?LINE]),
erlang:error({?MODULE,?LINE,Reason})).
--endif.
%%
%% Assertions.
diff --git a/lib/hipe/regalloc/hipe_node_sets.erl b/lib/hipe/regalloc/hipe_node_sets.erl
index b5e2971c4d..be43ff2bfd 100644
--- a/lib/hipe/regalloc/hipe_node_sets.erl
+++ b/lib/hipe/regalloc/hipe_node_sets.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -29,7 +29,7 @@
-record(node_sets,
{spilled, % Nodes marked for spilling
- colored % Nodes succesfully colored
+ colored % Nodes successfully colored
}).
spilled(Node_sets) -> Node_sets#node_sets.spilled.
diff --git a/lib/hipe/rtl/Makefile b/lib/hipe/rtl/Makefile
index 55d20af8af..690045b978 100644
--- a/lib/hipe/rtl/Makefile
+++ b/lib/hipe/rtl/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2010. All Rights Reserved.
+# Copyright Ericsson AB 2001-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -108,10 +108,30 @@ release_spec: opt
release_docs_spec:
-HIPE_MKLITERALS=$(ERL_TOP)/bin/$(TARGET)/hipe_mkliterals
+ifeq ($(TYPE),debug)
+TYPE_STR=.debug
+else
+TYPE_STR=
+endif
+
+ifeq ($(FLAVOR),smp)
+FLAVOR_STR=.smp
+else
+FLAVOR_STR=
+endif
+
+ifeq ($(XCOMP),yes)
+MKLIT_FLAGS= -x
+else
+MKLIT_FLAGS=
+endif
+
+
+HIPE_MKLITERALS=$(ERL_TOP)/bin/$(TARGET)/hipe_mkliterals$(TYPE_STR)$(FLAVOR_STR)
+
hipe_literals.hrl: $(HIPE_MKLITERALS)
- $(HIPE_MKLITERALS) -e > hipe_literals.hrl
+ $(HIPE_MKLITERALS) $(MKLIT_FLAGS) -e > hipe_literals.hrl
# Need to generate hipe.hrl from one and only one target in one and only
# one makefile; otherwise, clearmake will force rebuilds of hipe over and
diff --git a/lib/hipe/rtl/hipe_rtl_lcm.erl b/lib/hipe/rtl/hipe_rtl_lcm.erl
index 5d65389d48..9224623c8b 100644
--- a/lib/hipe/rtl/hipe_rtl_lcm.erl
+++ b/lib/hipe/rtl/hipe_rtl_lcm.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -269,7 +269,7 @@ insert_expr_last(CFG0, Label, Instr) ->
%% is a branch operation).
insert_expr_last_work(_, Instr, []) ->
%% This case should not happen since this means that block was completely
- %% empty when the function was called. For compability we insert it last.
+ %% empty when the function was called. For compatibility we insert it last.
[Instr];
insert_expr_last_work(_, Instr, [Code1]) ->
%% We insert the code next to last.
diff --git a/lib/hipe/util/hipe_dot.erl b/lib/hipe/util/hipe_dot.erl
index d6ef801c88..d6ef801c88 100755..100644
--- a/lib/hipe/util/hipe_dot.erl
+++ b/lib/hipe/util/hipe_dot.erl
diff --git a/lib/hipe/vsn.mk b/lib/hipe/vsn.mk
index 58ebe68401..65e04ff7fa 100644
--- a/lib/hipe/vsn.mk
+++ b/lib/hipe/vsn.mk
@@ -1 +1 @@
-HIPE_VSN = 3.8
+HIPE_VSN = 3.8.1
diff --git a/lib/ic/c_src/Makefile.in b/lib/ic/c_src/Makefile.in
index 6eef7827b9..28040ca42d 100644
--- a/lib/ic/c_src/Makefile.in
+++ b/lib/ic/c_src/Makefile.in
@@ -125,13 +125,9 @@ docs:
# Special Build Targets
# ----------------------------------------------------
-$(OBJDIR):
- -mkdir -p $(OBJDIR)
+_create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR))
-$(LIBDIR):
- -mkdir -p $(LIBDIR)
-
-$(LIBRARY): $(OBJDIR) $(LIBDIR) $(OBJ_FILES)
+$(LIBRARY): $(OBJ_FILES)
-$(AR) $(AR_OUT) $@ $(OBJ_FILES)
-$(RANLIB) $@
diff --git a/lib/ic/doc/src/Makefile b/lib/ic/doc/src/Makefile
index 8eda436a24..1e93578cb1 100644
--- a/lib/ic/doc/src/Makefile
+++ b/lib/ic/doc/src/Makefile
@@ -26,13 +26,6 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
include ../../vsn.mk
VSN=$(IC_VSN)
APPLICATION=ic
-# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
# ----------------------------------------------------
# Java specific
@@ -96,32 +89,10 @@ EXTRA_FILES = summary.html.src \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
JAVA_SOURCE_FILES = \
Holder.java \
BooleanHolder.java \
@@ -209,8 +180,6 @@ JAVADOCFLAGS = \
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
ifneq (,$(JAVA))
docs: pdf html man $(JAVADOC_GENERATED_FILES)
else
@@ -229,38 +198,11 @@ clean clean_docs:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html $(JAVADOC_GENERATED_FILES) gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
+$(JAVADOC_GENERATED_FILES): JAVADOC-GENERATED
-html: $(HTML_FILES)
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ *xmls_output *xmls_errs $(LATEX_CLEAN)
- rm -rf $(JAVA_OUT_DIR)
-
-endif
-
-$(JAVA_OUT_DIR):
- mkdir $(JAVA_OUT_DIR)
-
-$(JAVADOC_GENERATED_FILES): $(JAVA_OUT_DIR)
+JAVADOC-GENERATED: $(JAVA_SOURCE_FILES:%=$(JAVA_SOURCE_DIR)/%)
@(cd ../../java_src; $(JAVADOC) $(JAVADOCFLAGS) com.ericsson.otp.ic)
+ >JAVADOC-GENERATED
man: $(MAN3_FILES)
@@ -277,8 +219,6 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
$(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
$(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
@@ -288,46 +228,4 @@ release_docs_spec: docs
$(INSTALL_DIR) $(RELEASE_PATH)/man/man3
$(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
-ifneq (,$(JAVA))
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html/java
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html/java/resources
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html/java/com
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html/java/com/ericsson
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html/java/com/ericsson/otp
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html/java/com/ericsson/otp/ic
- $(INSTALL_DATA) $(JAVADOC_INDEX_HTML_FILES) \
- $(RELSYSDIR)/doc/html/java
- $(INSTALL_DATA) $(JD_GIF_FILES) \
- $(RELSYSDIR)/doc/html/java/resources
- $(INSTALL_DATA) $(JAVADOC_PACK_HTML_FILES) \
- $(RELSYSDIR)/doc/html/java/com/ericsson/otp/ic
-endif
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-
-endif
-endif
-
-endif
-
-
release_spec:
-
-
diff --git a/lib/ic/doc/src/make.dep b/lib/ic/doc/src/make.dep
deleted file mode 100644
index 64694ee85a..0000000000
--- a/lib/ic/doc/src/make.dep
+++ /dev/null
@@ -1,24 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex c-part.tex ch_basic_idl.tex ch_c_client.tex \
- ch_c_corba_env.tex ch_c_mapping.tex ch_c_server.tex \
- ch_erl_genserv.tex ch_erl_plain.tex ch_ic_protocol.tex \
- ch_introduction.tex ch_java.tex erl-part.tex \
- ic.tex ic_c_protocol.tex ic_clib.tex java-part.tex \
- ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/ic/doc/src/notes.xml b/lib/ic/doc/src/notes.xml
index 5f6c31069c..ff289bd76c 100644
--- a/lib/ic/doc/src/notes.xml
+++ b/lib/ic/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1998</year><year>2010</year>
+ <year>1998</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,38 @@
</header>
<section>
+ <title>IC 4.2.28</title>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+ <list type="bulleted">
+ <item>
+ <p>
+ Incorrect use of ets:match changed to ets:match_object.</p>
+ <p>
+ Own Id: OTP-9630 </p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>IC 4.2.27</title>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>
+ Reduced compile overhead (Thanks to Haitao Li).</p>
+ <p>
+ Own Id: OTP-9460 </p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
<title>IC 4.2.26</title>
<section>
diff --git a/lib/ic/examples/pre_post_condition/Makefile b/lib/ic/examples/pre_post_condition/Makefile
index 68e2168e1e..d57133c964 100644
--- a/lib/ic/examples/pre_post_condition/Makefile
+++ b/lib/ic/examples/pre_post_condition/Makefile
@@ -100,7 +100,7 @@ YRL_FLAGS =
debug opt: $(TARGET_FILES)
clean:
- rm -f $(TARGET_FILES) $(GEN_ERL_MODULES:%=%.erl) $(GEN_HRL_FILES) $(CLASS_FILES)
+ rm -f $(TARGET_FILES) $(GEN_ERL_MODULES:%=%.erl) $(GEN_HRL_FILES) $(CLASS_FILES) IDL-GENERATED
rm -f errs core *~
docs:
@@ -108,9 +108,14 @@ docs:
test: $(TEST_TARGET_FILES)
-$(GEN_ERL_MODULES:%=%.erl) $(GEN_HRL_FILES): ex.idl
+IDL-GENERATED: ex.idl
erlc $(ERL_LOCAL_FLAGS) +'{precond,{tracer,pre}}' \
+'{{postcond,"m::i::f"},{tracer,post}}' ex.idl
+ >IDL-GENERATED
+
+$(GEN_ERL_MODULES:%=%.erl) $(GEN_HRL_FILES): IDL-GENERATED
+
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Target
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/ignore_config_record.inf b/lib/ic/java_src/com/ericsson/otp/ic/ignore_config_record.inf
deleted file mode 100644
index 34e5586175..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/ignore_config_record.inf
+++ /dev/null
@@ -1 +0,0 @@
-Dummy to speed up compilatio
diff --git a/lib/ic/src/ic.erl b/lib/ic/src/ic.erl
index 3c6ce3d9d6..50fad921c4 100644
--- a/lib/ic/src/ic.erl
+++ b/lib/ic/src/ic.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -320,7 +320,7 @@ pragma(G, File, T) ->
time,
time("pragma registration ", ic_pragma, pragma_reg, [G,T]),
ic_pragma:pragma_reg(G,T)) of
- %% All pragmas were succesfully applied
+ %% All pragmas were successfully applied
{ok,Clean} ->
typing(G, File, Clean);
diff --git a/lib/ic/src/ic_pp.erl b/lib/ic/src/ic_pp.erl
index db06118d32..8b53473caa 100644
--- a/lib/ic/src/ic_pp.erl
+++ b/lib/ic/src/ic_pp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -92,6 +92,14 @@
%%
%%======================================================================================
+%% Multiple Include Optimization
+%%
+%% Algorithm described at:
+%% http://gcc.gnu.org/onlinedocs/cppinternals/Guard-Macros.html
+-record(mio, {valid = true, %% multiple include valid
+ cmacro, %% controlling macro of the current conditional directive
+ depth = 0, %% conditional directive depth
+ included = []}).
@@ -130,7 +138,7 @@ run(FileList, FileName, IncDir, Flags) ->
%%----------------------------------------------------------
%% Run the second phase, i.e expand macros
%%----------------------------------------------------------
- {Out, Err, War, _Defs, IfCou} = expand(File, FileName, IncDir, Flags),
+ {Out, Err, War, _Defs, _Mio, IfCou} = expand(File, FileName, IncDir, Flags),
%%----------------------------------------------------------
%% Check if all #if #ifdef #ifndef have a matching #endif
@@ -155,9 +163,9 @@ run(FileList, FileName, IncDir, Flags) ->
%% The entry for all included files
%%
%%
-%% Output {Out, Defs, Err, War}
+%% Output {Out, Err, War, Defs, MultipleIncludeValid}
%%======================================================================================
-run_include(FileName, FileList, _Out, Defs, Err, War, IncLine, IncFile, IncDir) ->
+run_include(FileName, FileList, _Out, Defs, Err, War, IncLine, IncFile, IncDir, Mio) ->
%%----------------------------------------------------------
%% Run the first phase, i.e tokenise the file
@@ -169,18 +177,21 @@ run_include(FileName, FileList, _Out, Defs, Err, War, IncLine, IncFile, IncDir)
%%----------------------------------------------------------
%% Run the second phase, i.e expand macros
%%----------------------------------------------------------
-
- %% Try first pass without file info start/end
- {OutT, ErrT, WarT, DefsT, IfCouT} =
- expand(File, Defs, Err, War, [FileName|IncFile], IncDir),
-
- {Out2, Err2, War2, Defs2, IfCou2} =
- case only_nls(OutT) of
- true -> %% The file is defined before
- {["\n"], ErrT, WarT, DefsT, IfCouT};
- false -> %% The file is not defined before, try second pass
- expand([FileInfoStart|File]++FileInfoEnd, Defs, Err, War, [FileName|IncFile], IncDir)
- end,
+ {Out2, Err2, War2, Defs2, Mio2, IfCou2} =
+ expand([FileInfoStart|File]++FileInfoEnd, Defs, Err, War,
+ [FileName|IncFile], IncDir,
+ #mio{included=Mio#mio.included}),
+
+ MergeIncluded = sets:to_list(sets:from_list(Mio#mio.included ++ Mio2#mio.included)),
+
+ Mio3 =
+ case {Mio2#mio.valid, Mio2#mio.cmacro} of
+ {V, Macro} when V == false;
+ Macro == undefined ->
+ update_mio(Mio#mio{included=MergeIncluded});
+ {true, _} ->
+ update_mio({include, FileName}, Mio#mio{included=MergeIncluded})
+ end,
%%----------------------------------------------------------
%% Check if all #if #ifdef #ifndef have a matching #endif
@@ -192,26 +203,7 @@ run_include(FileName, FileList, _Out, Defs, Err, War, IncLine, IncFile, IncDir)
[]
end,
- {Out2, Defs2, Err2++IfError, War2}.
-
-
-
-%% Return true if there is no data
-%% other than new lines
-only_nls([]) ->
- true;
-only_nls(["\n"|Rem]) ->
- only_nls(Rem);
-only_nls(["\r","\n"|Rem]) ->
- only_nls(Rem);
-only_nls([_|_Rem]) ->
- false.
-
-
-
-
-
-
+ {Out2, Defs2, Err2++IfError, War2, Mio3}.
@@ -647,87 +639,86 @@ expand(List, FileName, IncDir, Flags) ->
%% Get all definitions from preprocessor commnads
%% and merge them on top of the file collected.
CLDefs = get_cmd_line_defs(Flags),
- expand(List, [], [], CLDefs, [FileName], IncDir, check_all, [], [], 1, FileName).
-
-expand(List, Defs, Err, War, [FileName|IncFile], IncDir) ->
- expand(List, [], [], Defs, [FileName|IncFile], IncDir, check_all, Err, War, 1, FileName).
+ expand(List, [], [], CLDefs, [FileName], IncDir, #mio{}, check_all, [], [], 1, FileName).
+expand(List, Defs, Err, War, [FileName|IncFile], IncDir, Mio) ->
+ expand(List, [], [], Defs, [FileName|IncFile], IncDir, Mio, check_all, Err, War, 1, FileName).
%%=======================================================
%% Main loop for the expansion
%%=======================================================
-expand([], Out, _SelfRef, Defs, _IncFile, _IncDir, IfCou, Err, War, _L, _FN) ->
+expand([], Out, _SelfRef, Defs, _IncFile, _IncDir, Mio, IfCou, Err, War, _L, _FN) ->
% io:format("~n ===============~n"),
% io:format(" definitions ~p~n",[lists:reverse(Defs)]),
% io:format(" found warnings ~p~n",[lists:reverse(War)]),
% io:format(" found errors ~p~n",[lists:reverse(Err)]),
% io:format(" ===============~n~n~n"),
- {Out, Err, War, Defs, IfCou};
+ {Out, Err, War, Defs, Mio, IfCou};
-expand([{file_info, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
- expand(Rem, Str++Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+expand([{file_info, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
+ expand(Rem, Str++Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN);
%%---------------------------------------
%% Searching for endif,
%% i.e skip all source lines until matching
%% end if is encountered
%%---------------------------------------
-expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN)
+expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN)
when Command == "ifdef" ->
{_Removed, Rem2, _Nl} = read_to_nl(Rem),
IfCou2 = {endif, Endif+1, IfLine},
- expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, IfCou2, Err, War, L, FN);
+ expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err, War, L, FN);
-expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN)
+expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN)
when Command == "ifndef" ->
{_Removed, Rem2, _Nl} = read_to_nl(Rem),
IfCou2 = {endif, Endif+1, IfLine},
- expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, IfCou2, Err, War, L, FN);
+ expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err, War, L, FN);
-expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN)
+expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN)
when Command == "if" ->
- case pp_command(Command, Rem, Defs, IncDir, Err, War, L, FN) of
+ case pp_command(Command, Rem, Defs, IncDir, Mio, Err, War, L, FN) of
{{'if', true}, Rem2, Err2, War2, Nl} ->
IfCou2 = {endif, Endif+1, IfLine},
- expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, IfCou2, Err2, War2, L+Nl, FN);
+ expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err2, War2, L+Nl, FN);
%% {{'if', false}, Rem2, Err2, War2, Nl} -> Not implemented yet
{{'if', error}, Rem2, Err2, War2, Nl} ->
IfCou2 = {endif, Endif, IfLine},
- expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, IfCou2, Err2, War2, L+Nl, FN)
+ expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err2, War2, L+Nl, FN)
end;
-expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN)
+expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN)
when Command == "endif" ->
{_Removed, Rem2, Nl} = read_to_nl(Rem),
case Endif of
1 ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err, War, L+Nl, FN);
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio, check_all, Err, War, L+Nl, FN);
_ ->
IfCou2 = {endif, Endif-1, IfLine},
- expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, IfCou2, Err, War, L+Nl, FN)
+ expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err, War, L+Nl, FN)
end;
-expand([{command,_Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN) ->
+expand([{command,_Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN) ->
{_Removed, Rem2, _Nl} = read_to_nl(Rem),
IfCou2 = {endif, Endif, IfLine},
- expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, IfCou2, Err, War, L, FN);
+ expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err, War, L, FN);
%% Solves a bug when spaces in front of hashmark !
-expand([space | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN) ->
- expand(Rem, Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN);
+expand([space | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN) ->
+ expand(Rem, Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN);
-expand([{nl,_Nl} | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN) ->
- expand(Rem, Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN);
+expand([{nl,_Nl} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN) ->
+ expand(Rem, Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN);
-expand([_X | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN) ->
+expand([_X | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN) ->
{_Removed, Rem2, Nl} = read_to_nl(Rem),
- Out2 = [lists:duplicate(Nl,$\n)|Out],
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN);
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN);
@@ -736,121 +727,132 @@ expand([_X | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine},
%%---------------------------------------
%% Check all tokens
%%---------------------------------------
-expand([{nl, _N} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
- expand(Rem, [$\n | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L+1, FN);
+expand([{nl, _N} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
+ expand(Rem, [$\n | Out], SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L+1, FN);
-expand([space | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
- expand(Rem, [?space | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+expand([space | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
+ expand(Rem, [?space | Out], SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN);
-expand([space_exp | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
- expand(Rem, [?space | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+expand([space_exp | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
+ expand(Rem, [?space | Out], SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN);
-expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, check_all, Err, War, L, FN) ->
- case pp_command(Command, Rem, Defs, IncDir, Err, War, L, FN) of
+expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, check_all, Err, War, L, FN) ->
+ case pp_command(Command, Rem, Defs, IncDir, Mio, Err, War, L, FN) of
{define, Rem2, Defs2, Err2, War2, Nl} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
- expand(Rem2, Out2, SelfRef, Defs2, IncFile, IncDir, check_all, Err2, War2, L+Nl, FN);
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
+ expand(Rem2, Out2, SelfRef, Defs2, IncFile, IncDir, update_mio(Mio), check_all, Err2, War2, L+Nl, FN);
{undef, Rem2, Defs2, Err2, War2, Nl} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
- expand(Rem2, Out2, SelfRef, Defs2, IncFile, IncDir, check_all, Err2, War2, L+Nl, FN);
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
+ expand(Rem2, Out2, SelfRef, Defs2, IncFile, IncDir, update_mio(Mio), check_all, Err2, War2, L+Nl, FN);
{{include, ok}, FileName, FileCont, Rem2, Nl, Err2, War2} ->
- {Out3, Defs3, Err3, War3} =
- run_include(FileName, FileCont, Out, Defs, Err2, War2, L+Nl, IncFile, IncDir),
+ {Out3, Defs3, Err3, War3, Mio2} =
+ run_include(FileName, FileCont, Out, Defs, Err2, War2, L+Nl, IncFile, IncDir, Mio),
Nls = [],
Out4 = Out3++Nls++Out,
- expand(Rem2, Out4, SelfRef, Defs3, IncFile, IncDir, check_all, Err3, War3, L+Nl, FN);
+ expand(Rem2, Out4, SelfRef, Defs3, IncFile, IncDir, Mio2, check_all, Err3, War3, L+Nl, FN);
{{include, error}, Rem2, Nl, Err2, War2} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err2, War2, L+Nl, FN);
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, Err2, War2, L+Nl, FN);
+
+ {{include, skip}, Rem2} ->
+ Out2 = [$\n|Out],
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, Err, War, L+1, FN);
{{ifdef, true}, Rem2, Err2, War2, Nl} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
IfCou2 = {endif, 1, L},
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, IfCou2, Err2, War2, L+Nl, FN);
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err2, War2, L+Nl, FN);
{{ifdef, false}, Rem2, Err2, War2, Nl} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err2, War2, L+Nl, FN);
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
+ Mio2 = update_mio(ifdef, Mio),
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err2, War2, L+Nl, FN);
{{ifndef, true}, Rem2, Err2, War2, Nl} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
IfCou2 = {endif, 1, L},
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, IfCou2, Err2, War2, L+Nl, FN);
- {{ifndef, false}, Rem2, Err2, War2, Nl} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err2, War2, L+Nl, FN);
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err2, War2, L+Nl, FN);
+ {{ifndef, false}, Macro, Rem2, Err2, War2, Nl} ->
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
+ Mio2 = update_mio({ifndef, Macro}, Mio),
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err2, War2, L+Nl, FN);
{endif, Rem2, Err2, War2, Nl} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err2, War2, L+Nl, FN);
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
+ Mio2 = update_mio(endif, Mio),
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err2, War2, L+Nl, FN);
{{'if', true}, Rem2, Err2, War2, Nl} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
IfCou2 = {endif, 1, L},
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, IfCou2, Err2, War2, L+Nl, FN);
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err2, War2, L+Nl, FN);
%% {{'if', false}, Removed, Rem2, Nl} -> Not implemented at present
{{'if', error}, Rem2, Err2, War2, Nl} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err2, War2, L+Nl, FN);
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
+ Mio2 = update_mio('if', Mio),
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err2, War2, L+Nl, FN);
{'else', {_Removed, Rem2, Nl}} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
Err2 = {FN, L, "`else' command is not implemented at present"},
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, [Err2|Err], War, L+Nl, FN);
+ Mio2 = update_mio('else', Mio),
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, [Err2|Err], War, L+Nl, FN);
{'elif', {_Removed, Rem2, Nl}} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
Err2 = {FN, L, "`elif' command is not implemented at present"},
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, [Err2|Err], War, L+Nl, FN);
+ Mio2 = update_mio('elif', Mio),
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, [Err2|Err], War, L+Nl, FN);
{warning, {WarningText, Rem2, Nl}} ->
[FileName|_More] = IncFile,
War2 = {FileName, L, "warning: #warning "++detokenise(WarningText)},
- Out2 = [lists:duplicate(Nl,$\n)|Out],
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err, [War2|War], L+Nl, FN);
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, Err, [War2|War], L+Nl, FN);
{error, {ErrorText, Rem2, Nl}} ->
[FileName|_More] = IncFile,
Err2 = {FileName, L, detokenise(ErrorText)},
- Out2 = [lists:duplicate(Nl,$\n)|Out],
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, [Err2|Err], War, L+Nl, FN);
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, [Err2|Err], War, L+Nl, FN);
{{line, ok}, {_Removed, Rem2, Nl}, L2, FN2, LineText} ->
Out2 = lists:duplicate(Nl,$\n)++LineText++Out,
[_X|IF] = IncFile,
IncFile2 = [FN2|IF],
- expand(Rem2, Out2, SelfRef, Defs, IncFile2, IncDir, check_all, Err, War, L2, FN2);
+ expand(Rem2, Out2, SelfRef, Defs, IncFile2, IncDir, update_mio(Mio), check_all, Err, War, L2, FN2);
{{line, error}, {_Removed, Rem2, Nl}, Err2} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, [Err2|Err], War, L+Nl, FN);
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, [Err2|Err], War, L+Nl, FN);
hash_mark ->
- expand(Rem, Out, SelfRef, Defs, IncFile, IncDir, check_all, Err, War, L, FN);
+ expand(Rem, Out, SelfRef, Defs, IncFile, IncDir, Mio, check_all, Err, War, L, FN);
{pragma, Rem2, Nl, Text} ->
Out2 = lists:duplicate(Nl,$\n)++Text++Out,
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err, War, L+Nl, FN);
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, Err, War, L+Nl, FN);
{ident, Rem2, Nl, Text} ->
Out2 = lists:duplicate(Nl,$\n)++Text++Out,
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err, War, L+Nl, FN);
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, Err, War, L+Nl, FN);
{not_recognised, {Removed, Rem2, Nl}} ->
Text = lists:reverse([$#|Command]),
RemovedS = lists:reverse([?space|detokenise(Removed)]),
Out2 = [$\n|RemovedS]++Text++Out,
+ Mio2 = update_mio(Mio),
case Command of
[X|_T] when ?is_upper(X) ->
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err, War, L+Nl, FN);
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err, War, L+Nl, FN);
[X|_T] when ?is_lower(X) ->
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err, War, L+Nl, FN);
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err, War, L+Nl, FN);
[X|_T] when ?is_underline(X) ->
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err, War, L+Nl, FN);
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err, War, L+Nl, FN);
_ ->
Err2 = {FN, L, "invalid preprocessing directive name"},
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, [Err2|Err], War, L+Nl, FN)
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, [Err2|Err], War, L+Nl, FN)
end;
Else ->
@@ -859,19 +861,19 @@ expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, check_all
end;
-expand([{var, "__LINE__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
+expand([{var, "__LINE__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
LL = io_lib:format("~p",[L]),
- expand(Rem, [LL | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+ expand(Rem, [LL | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-expand([{var, "__FILE__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
- expand(Rem, [$",FN,$" | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+expand([{var, "__FILE__"}|Rem], Out, SelfRef, Defs, IncFile, Mio, IncDir, IfCou, Err, War, L, FN) ->
+ expand(Rem, [$",FN,$" | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-expand([{var, "__DATE__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
+expand([{var, "__DATE__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
{{Y,M,D},{_H,_Mi,_S}} = calendar:universal_time(),
Date = io_lib:format("\"~s ~p ~p\"",[month(M),D,Y]),
- expand(Rem, [Date | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+ expand(Rem, [Date | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-expand([{var, "__TIME__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
+expand([{var, "__TIME__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
{{_Y,_M,_D},{H,Mi,S}} = calendar:universal_time(),
HS = if H < 10 -> "0"++integer_to_list(H);
true -> integer_to_list(H)
@@ -883,40 +885,40 @@ expand([{var, "__TIME__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err,
true -> integer_to_list(S)
end,
Time = io_lib:format("\"~s:~s:~s\"",[HS,MiS,SS]),
- expand(Rem, [Time | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+ expand(Rem, [Time | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-expand([{var, "__INCLUDE_LEVEL__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
+expand([{var, "__INCLUDE_LEVEL__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
IL = io_lib:format("~p",[length(IncFile)-1]),
- expand(Rem, [IL | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+ expand(Rem, [IL | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-expand([{var, "__BASE_FILE__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
+expand([{var, "__BASE_FILE__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
[BF|_T] = lists:reverse(IncFile),
- expand(Rem, [$",BF,$" | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+ expand(Rem, [$",BF,$" | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-expand([{var, Var} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
+expand([{var, Var} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
{Out2, Err2, War2, Rem2, SelfRef2} =
source_line(Var, Rem, SelfRef, Defs, Err, War, L, FN),
- expand(Rem2, [Out2 | Out], SelfRef2, Defs, IncFile, IncDir, IfCou, Err2, War2, L, FN);
+ expand(Rem2, [Out2 | Out], SelfRef2, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err2, War2, L, FN);
-expand([{char, Char} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
- expand(Rem, [Char | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+expand([{char, Char} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
+ expand(Rem, [Char | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-expand([{number, Number} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
- expand(Rem, [Number | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+expand([{number, Number} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
+ expand(Rem, [Number | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-expand([{expanded, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
- expand(Rem, [Str | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+expand([{expanded, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
+ expand(Rem, [Str | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-expand([{self_ref, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
+expand([{self_ref, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
SelfRef2 = lists:delete(Str,SelfRef),
- expand(Rem, Out, SelfRef2, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+ expand(Rem, Out, SelfRef2, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-expand([{string, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
- expand(Rem, [$", Str, $" | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+expand([{string, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
+ expand(Rem, [$", Str, $" | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-expand([{string_part, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
+expand([{string_part, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
{Str2, Rem2, Nl} = expand_string_part([$"|Str], Rem),
- expand(Rem2, [Str2| Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L+Nl, FN).
+ expand(Rem2, [Str2| Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L+Nl, FN).
@@ -954,13 +956,14 @@ expand_string_part([{string_part, Str_part} | Rem], Str, Nl) ->
get_cmd_line_defs(Flags) ->
Adjusted = parse_cmd_line(Flags,[]),
- {_Out, _Err, _War, Defs, _IfCou} =
+ {_Out, _Err, _War, Defs, _IfCou, _Mio} =
expand(tokenise(Adjusted,""),
[],
[],
[],
[],
[],
+ #mio{},
check_all,
[],
[],
@@ -1030,10 +1033,10 @@ collect_undefine([C|Rest],Found) ->
%%======================================================================================
%%======================================================================================
-pp_command(Command, [space|File], Defs, IncDir, Err, War, L, FN) ->
- pp_command(Command, File, Defs, IncDir, Err, War, L, FN);
+pp_command(Command, [space|File], Defs, IncDir, Mio, Err, War, L, FN) ->
+ pp_command(Command, File, Defs, IncDir, Mio, Err, War, L, FN);
-pp_command(Command, File, Defs, IncDir, Err, War, L, FN) ->
+pp_command(Command, File, Defs, IncDir, Mio, Err, War, L, FN) ->
case Command of
%%----------------------------------------
@@ -1081,14 +1084,16 @@ pp_command(Command, File, Defs, IncDir, Err, War, L, FN) ->
%% #include
%%----------------------------------------
"include" ->
- case include(File, IncDir) of
- {error, Rem, Nl, Err2} ->
- {{include, error}, Rem, Nl, [{FN, L, Err2}|Err], War};
- {error, Rem, Nl, Err2, NameNl} ->
- {{include, error}, Rem, Nl, [{FN, L+ NameNl, Err2}|Err], War};
- {ok, FileName, FileCont, Rem, Nl} ->
- {{include, ok}, FileName, FileCont, Rem, Nl, Err, War}
- end;
+ case include(File, IncDir, Mio) of
+ {error, Rem, Nl, Err2} ->
+ {{include, error}, Rem, Nl, [{FN, L, Err2}|Err], War};
+ {error, Rem, Nl, Err2, NameNl} ->
+ {{include, error}, Rem, Nl, [{FN, L+ NameNl, Err2}|Err], War};
+ {ok, FileNamePath, FileCont, Rem, Nl} ->
+ {{include, ok}, FileNamePath, FileCont, Rem, Nl, Err, War};
+ {skip, Rem} ->
+ {{include, skip}, Rem}
+ end;
%%----------------------------------------
%% #ifdef
@@ -1127,14 +1132,14 @@ pp_command(Command, File, Defs, IncDir, Err, War, L, FN) ->
yes ->
{{ifndef, true}, Rem, Err2, War2, Nl};
no ->
- {{ifndef, false}, Rem, Err2, War2, Nl}
+ {{ifndef, false}, Name, Rem, Err2, War2, Nl}
end;
{ok, Rem, Name, No_of_para, _Parameters, _Macro, Err2, War2, Nl} ->
case is_defined_before(Name, No_of_para, Defs) of
yes ->
{{ifndef, true}, Rem, Err2, War2, Nl};
no ->
- {{ifndef, false}, Rem, Err2, War2, Nl}
+ {{ifndef, false}, Name, Rem, Err2, War2, Nl}
end
end;
@@ -1408,29 +1413,32 @@ undef(_Rem) ->
%%===============================================================
%%===============================================================
-include(File, IncDir) ->
+include(File, IncDir, Mio) ->
case include2(File) of
- {ok, FileName, Rem, Nl, FileType} ->
- %% The error handling is lite strange just to make it compatible to gcc
- case {read_inc_file(FileName, IncDir), Nl, FileType} of
- {{ok, FileList, FileNamePath}, _, _} ->
- {ok, FileNamePath, FileList, Rem, Nl};
- {{error, Text}, _, own_file} ->
- NameNl = count_nl(FileName,0),
- Error = lists:flatten(io_lib:format("~s: ~s",[FileName,Text])),
- {error, Rem, Nl, Error, NameNl};
- {{error, Text}, 1, sys_file} ->
- NameNl = count_nl(FileName,0),
- Error = lists:flatten(io_lib:format("~s: ~s",[FileName,Text])),
- {error, Rem, Nl, Error, NameNl};
- {{error, _Text}, _, sys_file} ->
- {error, Rem, Nl, "`#include' expects \"FILENAME\" or <FILENAME>"}
- end;
-
- {error, {_Removed, Rem, Nl}} ->
- {error, Rem, Nl, "`#include' expects \"FILENAME\" or <FILENAME>"}
+ {ok, FileName, Rem, Nl, FileType} ->
+ Result = read_inc_file(FileName, IncDir, Mio),
+ case {Result, Nl, FileType} of
+ {{ok, FileNamePath, FileCont}, _, _} ->
+ {ok, FileNamePath, FileCont, Rem, Nl};
+ {skip, _, _} ->
+ {skip, Rem};
+ {{error, Text}, _, own_file} ->
+ NameNl = count_nl(FileName,0),
+ Error = lists:flatten(io_lib:format("~s: ~s",[FileName,Text])),
+ {error, Rem, Nl, Error, NameNl};
+ {{error, Text}, 1, sys_file} ->
+ NameNl = count_nl(FileName,0),
+ Error = lists:flatten(io_lib:format("~s: ~s",[FileName,Text])),
+ {error, Rem, Nl, Error, NameNl};
+ {{error, _Text}, _, sys_file} ->
+ {error, Rem, Nl, "`#include' expects \"FILENAME\" or <FILENAME>"}
+ end;
+ {error, {_Removed, Rem, Nl}} ->
+ {error, Rem, Nl, "`#include' expects \#FILENAME\" or <FILENAME>"}
end.
+
+
count_nl([],Nl) ->
Nl;
count_nl([$\n|T],Nl) ->
@@ -1909,18 +1917,37 @@ include_dir(Flags,IncDir) ->
%% Read a included file. Try current dir first then the IncDir list
%%===============================================================
-read_inc_file(FileName, IncDir) ->
- case catch file:read_file(FileName) of
- {ok, Bin} ->
- FileList = binary_to_list(Bin),
- {ok, FileList, FileName};
+read_inc_file(FileName, IncDir, Mio) ->
+ case find_inc_file(FileName, IncDir) of
+ {ok, AbsFile} ->
+ %% is included before?
+ case lists:member(FileName, Mio#mio.included) of
+ false ->
+ case catch file:read_file(AbsFile) of
+ {ok, Bin} ->
+ FileList = binary_to_list(Bin),
+ {ok, AbsFile, FileList};
+ {error, Text} ->
+ {error, Text}
+ end;
+ true ->
+ skip
+ end;
+ {error, Text} ->
+ {error, Text}
+ end.
+
+find_inc_file(FileName, IncDir) ->
+ case catch file:read_file_info(FileName) of
+ {ok, _} ->
+ {ok, FileName};
{error, _} ->
- read_inc_file2(FileName, IncDir)
+ find_inc_file2(FileName, IncDir)
end.
-read_inc_file2(_FileName, []) ->
+find_inc_file2(_FileName, []) ->
{error, "No such file or directory"};
-read_inc_file2(FileName, [D|Rem]) ->
+find_inc_file2(FileName, [D|Rem]) ->
Dir = case lists:last(D) of
$/ ->
D;
@@ -1928,17 +1955,14 @@ read_inc_file2(FileName, [D|Rem]) ->
D++"/"
end,
- case catch file:read_file(Dir++FileName) of
- {ok, Bin} ->
- FileList = binary_to_list(Bin),
- {ok, FileList, Dir++FileName};
+ case catch file:read_file_info(Dir++FileName) of
+ {ok, _} ->
+ {ok, Dir++FileName};
{error, _} ->
- read_inc_file2(FileName, Rem)
+ find_inc_file2(FileName, Rem)
end.
-
-
%%===============================================================
%% Read parameters of a macro or a variable in a source line
%%===============================================================
@@ -2135,5 +2159,73 @@ month(11) -> "Nov";
month(12) -> "Dec".
+%% Multiple Include Optimization
+%%
+%% Algorithm described at:
+%% http://gcc.gnu.org/onlinedocs/cppinternals/Guard-Macros.html
+update_mio({include, FileName}, #mio{included=Inc}=Mio) ->
+ Mio#mio{valid=false, included=[FileName|Inc]};
+
+%% valid=false & cmacro=undefined indicates it is already decided this file is
+%% not subject to MIO
+update_mio(_, #mio{valid=false, depth=0, cmacro=undefined}=Mio) ->
+ Mio;
+
+%% if valid=true, there is no non-whitespace tokens before this ifndef
+update_mio({'ifndef', Macro}, #mio{valid=true, depth=0, cmacro=undefined}=Mio) ->
+ Mio#mio{valid=false, cmacro=Macro, depth=1};
+
+%% detect any tokens before top level #ifndef
+update_mio(_, #mio{valid=true, depth=0, cmacro=undefined}=Mio) ->
+ Mio#mio{valid=false};
+
+%% If cmacro is alreay set, this is after the top level #endif
+update_mio({'ifndef', _}, #mio{valid=true, depth=0}=Mio) ->
+ Mio#mio{valid=false, cmacro=undefined};
+
+%% non-top level conditional, just update depth
+update_mio({'ifndef', _}, #mio{depth=D}=Mio) when D > 0 ->
+ Mio#mio{depth=D+1};
+update_mio('ifdef', #mio{depth=D}=Mio) ->
+ Mio#mio{depth=D+1};
+update_mio('if', #mio{depth=D}=Mio) ->
+ Mio#mio{depth=D+1};
+
+%% top level #else #elif invalidates multiple include optimization
+update_mio('else', #mio{depth=1}=Mio) ->
+ Mio#mio{valid=false, cmacro=undefined};
+update_mio('else', Mio) ->
+ Mio;
+update_mio('elif', #mio{depth=1}=Mio) ->
+ Mio#mio{valid=false, cmacro=undefined};
+update_mio('elif', Mio) ->
+ Mio;
+
+%% AT exit to top level, if the controlling macro is not set, this could be the
+%% end of a non-ifndef conditional block, or there were tokens before entering
+%% the #ifndef block. In either way, this invalidates the MIO
+%%
+%% It doesn't matter if `valid` is true at the time of exiting, it is set to
+%% true. This will be used to detect if more tokens are following the top
+%% level #endif.
+update_mio('endif', #mio{depth=1, cmacro=undefined}=Mio) ->
+ Mio#mio{valid=false, depth=0};
+update_mio('endif', #mio{depth=1}=Mio) ->
+ Mio#mio{valid=true, depth=0};
+update_mio('endif', #mio{depth=D}=Mio) when D > 1 ->
+ Mio#mio{valid=true, depth=D-1};
+
+%%if more tokens are following the top level #endif.
+update_mio('endif', #mio{depth=1, cmacro=undefined}=Mio) ->
+ Mio#mio{valid=false, depth=0};
+update_mio('endif', #mio{depth=D}=Mio) when D > 0 ->
+ Mio#mio{valid=true, depth=D-1};
+update_mio(_, Mio) ->
+ Mio#mio{valid=false}.
+
+%% clear `valid`, this doesn't matter since #endif will restore it if
+%% appropriate
+update_mio(Mio) ->
+ Mio#mio{valid=false}.
diff --git a/lib/ic/src/ic_pragma.erl b/lib/ic/src/ic_pragma.erl
index 45cb64c9c8..beaa2852ab 100644
--- a/lib/ic/src/ic_pragma.erl
+++ b/lib/ic/src/ic_pragma.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1600,9 +1600,8 @@ remove_inheriters(S,RS,InheriterList) ->
[_OneOnly] ->
ReducedInhList;
_Other ->
- EtsList = ets:tab2list(S),
CleanList =
- [X || X <- EtsList, element(1,X) == inherits],
+ ets:match_object(S, {inherits,'_','_'}),
% CodeOptList =
% [X || X <- EtsList, element(1,X) == codeopt],
NoInheriters =remove_inheriters2(S,ReducedInhList,CleanList),
@@ -1648,9 +1647,8 @@ remove_inh([X],[Y],List,EtsList) ->
%%% from others in the list
%%%----------------------------------------------
remove_inherited(S,InheriterList) ->
- EtsList = ets:tab2list(S),
CleanList =
- [X || X <- EtsList, element(1,X) == inherits],
+ ets:match_object(S, {inherits, '_', '_'}),
remove_inherited(S,InheriterList,CleanList).
@@ -1694,11 +1692,8 @@ remove_inhed([X],[Y],List,EtsList) ->
%% are inherited from scope in the list
%%%----------------------------------------------
get_inherited(S,Scope,OpScopeList) ->
- EtsList = ets:tab2list(S),
- [[element(3,X)] || X <- EtsList,
- element(1,X) == inherits,
- element(2,X) == Scope,
- member([element(3,X)],OpScopeList)].
+ EtsList1 = ets:match(S, {inherits, Scope, '$1'}),
+ [X || X <- EtsList1, member(X, OpScopeList)].
@@ -1771,9 +1766,7 @@ inherits2(_X,Y,Z,EtsList) ->
%% false otherwise
%%
is_inherited_by(Interface1,Interface2,PragmaTab) ->
- FullList = ets:tab2list(PragmaTab),
- InheritsList =
- [X || X <- FullList, element(1,X) == inherits],
+ InheritsList = ets:match_object(PragmaTab, {inherits, '_', '_'}),
inherits(Interface2,Interface1,InheritsList).
diff --git a/lib/ic/vsn.mk b/lib/ic/vsn.mk
index 6d6c7fa625..703c8d29eb 100644
--- a/lib/ic/vsn.mk
+++ b/lib/ic/vsn.mk
@@ -1 +1 @@
-IC_VSN = 4.2.26
+IC_VSN = 4.2.28
diff --git a/lib/inets/Makefile b/lib/inets/Makefile
index f4c2746b0a..4765a2ca3c 100644
--- a/lib/inets/Makefile
+++ b/lib/inets/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2010. All Rights Reserved.
+# Copyright Ericsson AB 1996-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/inets/doc/archive/rfc3986.txt b/lib/inets/doc/archive/rfc3986.txt
new file mode 100644
index 0000000000..c56ed4eb70
--- /dev/null
+++ b/lib/inets/doc/archive/rfc3986.txt
@@ -0,0 +1,3419 @@
+
+
+
+
+
+
+Network Working Group T. Berners-Lee
+Request for Comments: 3986 W3C/MIT
+STD: 66 R. Fielding
+Updates: 1738 Day Software
+Obsoletes: 2732, 2396, 1808 L. Masinter
+Category: Standards Track Adobe Systems
+ January 2005
+
+
+ Uniform Resource Identifier (URI): Generic Syntax
+
+Status of This Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2005).
+
+Abstract
+
+ A Uniform Resource Identifier (URI) is a compact sequence of
+ characters that identifies an abstract or physical resource. This
+ specification defines the generic URI syntax and a process for
+ resolving URI references that might be in relative form, along with
+ guidelines and security considerations for the use of URIs on the
+ Internet. The URI syntax defines a grammar that is a superset of all
+ valid URIs, allowing an implementation to parse the common components
+ of a URI reference without knowing the scheme-specific requirements
+ of every possible identifier. This specification does not define a
+ generative grammar for URIs; that task is performed by the individual
+ specifications of each URI scheme.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 1]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 4
+ 1.1. Overview of URIs . . . . . . . . . . . . . . . . . . . . 4
+ 1.1.1. Generic Syntax . . . . . . . . . . . . . . . . . 6
+ 1.1.2. Examples . . . . . . . . . . . . . . . . . . . . 7
+ 1.1.3. URI, URL, and URN . . . . . . . . . . . . . . . 7
+ 1.2. Design Considerations . . . . . . . . . . . . . . . . . 8
+ 1.2.1. Transcription . . . . . . . . . . . . . . . . . 8
+ 1.2.2. Separating Identification from Interaction . . . 9
+ 1.2.3. Hierarchical Identifiers . . . . . . . . . . . . 10
+ 1.3. Syntax Notation . . . . . . . . . . . . . . . . . . . . 11
+ 2. Characters . . . . . . . . . . . . . . . . . . . . . . . . . . 11
+ 2.1. Percent-Encoding . . . . . . . . . . . . . . . . . . . . 12
+ 2.2. Reserved Characters . . . . . . . . . . . . . . . . . . 12
+ 2.3. Unreserved Characters . . . . . . . . . . . . . . . . . 13
+ 2.4. When to Encode or Decode . . . . . . . . . . . . . . . . 14
+ 2.5. Identifying Data . . . . . . . . . . . . . . . . . . . . 14
+ 3. Syntax Components . . . . . . . . . . . . . . . . . . . . . . 16
+ 3.1. Scheme . . . . . . . . . . . . . . . . . . . . . . . . . 17
+ 3.2. Authority . . . . . . . . . . . . . . . . . . . . . . . 17
+ 3.2.1. User Information . . . . . . . . . . . . . . . . 18
+ 3.2.2. Host . . . . . . . . . . . . . . . . . . . . . . 18
+ 3.2.3. Port . . . . . . . . . . . . . . . . . . . . . . 22
+ 3.3. Path . . . . . . . . . . . . . . . . . . . . . . . . . . 22
+ 3.4. Query . . . . . . . . . . . . . . . . . . . . . . . . . 23
+ 3.5. Fragment . . . . . . . . . . . . . . . . . . . . . . . . 24
+ 4. Usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
+ 4.1. URI Reference . . . . . . . . . . . . . . . . . . . . . 25
+ 4.2. Relative Reference . . . . . . . . . . . . . . . . . . . 26
+ 4.3. Absolute URI . . . . . . . . . . . . . . . . . . . . . . 27
+ 4.4. Same-Document Reference . . . . . . . . . . . . . . . . 27
+ 4.5. Suffix Reference . . . . . . . . . . . . . . . . . . . . 27
+ 5. Reference Resolution . . . . . . . . . . . . . . . . . . . . . 28
+ 5.1. Establishing a Base URI . . . . . . . . . . . . . . . . 28
+ 5.1.1. Base URI Embedded in Content . . . . . . . . . . 29
+ 5.1.2. Base URI from the Encapsulating Entity . . . . . 29
+ 5.1.3. Base URI from the Retrieval URI . . . . . . . . 30
+ 5.1.4. Default Base URI . . . . . . . . . . . . . . . . 30
+ 5.2. Relative Resolution . . . . . . . . . . . . . . . . . . 30
+ 5.2.1. Pre-parse the Base URI . . . . . . . . . . . . . 31
+ 5.2.2. Transform References . . . . . . . . . . . . . . 31
+ 5.2.3. Merge Paths . . . . . . . . . . . . . . . . . . 32
+ 5.2.4. Remove Dot Segments . . . . . . . . . . . . . . 33
+ 5.3. Component Recomposition . . . . . . . . . . . . . . . . 35
+ 5.4. Reference Resolution Examples . . . . . . . . . . . . . 35
+ 5.4.1. Normal Examples . . . . . . . . . . . . . . . . 36
+ 5.4.2. Abnormal Examples . . . . . . . . . . . . . . . 36
+
+
+
+Berners-Lee, et al. Standards Track [Page 2]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ 6. Normalization and Comparison . . . . . . . . . . . . . . . . . 38
+ 6.1. Equivalence . . . . . . . . . . . . . . . . . . . . . . 38
+ 6.2. Comparison Ladder . . . . . . . . . . . . . . . . . . . 39
+ 6.2.1. Simple String Comparison . . . . . . . . . . . . 39
+ 6.2.2. Syntax-Based Normalization . . . . . . . . . . . 40
+ 6.2.3. Scheme-Based Normalization . . . . . . . . . . . 41
+ 6.2.4. Protocol-Based Normalization . . . . . . . . . . 42
+ 7. Security Considerations . . . . . . . . . . . . . . . . . . . 43
+ 7.1. Reliability and Consistency . . . . . . . . . . . . . . 43
+ 7.2. Malicious Construction . . . . . . . . . . . . . . . . . 43
+ 7.3. Back-End Transcoding . . . . . . . . . . . . . . . . . . 44
+ 7.4. Rare IP Address Formats . . . . . . . . . . . . . . . . 45
+ 7.5. Sensitive Information . . . . . . . . . . . . . . . . . 45
+ 7.6. Semantic Attacks . . . . . . . . . . . . . . . . . . . . 45
+ 8. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 46
+ 9. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 46
+ 10. References . . . . . . . . . . . . . . . . . . . . . . . . . . 46
+ 10.1. Normative References . . . . . . . . . . . . . . . . . . 46
+ 10.2. Informative References . . . . . . . . . . . . . . . . . 47
+ A. Collected ABNF for URI . . . . . . . . . . . . . . . . . . . . 49
+ B. Parsing a URI Reference with a Regular Expression . . . . . . 50
+ C. Delimiting a URI in Context . . . . . . . . . . . . . . . . . 51
+ D. Changes from RFC 2396 . . . . . . . . . . . . . . . . . . . . 53
+ D.1. Additions . . . . . . . . . . . . . . . . . . . . . . . 53
+ D.2. Modifications . . . . . . . . . . . . . . . . . . . . . 53
+ Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . . 60
+ Full Copyright Statement . . . . . . . . . . . . . . . . . . . . . 61
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 3]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+1. Introduction
+
+ A Uniform Resource Identifier (URI) provides a simple and extensible
+ means for identifying a resource. This specification of URI syntax
+ and semantics is derived from concepts introduced by the World Wide
+ Web global information initiative, whose use of these identifiers
+ dates from 1990 and is described in "Universal Resource Identifiers
+ in WWW" [RFC1630]. The syntax is designed to meet the
+ recommendations laid out in "Functional Recommendations for Internet
+ Resource Locators" [RFC1736] and "Functional Requirements for Uniform
+ Resource Names" [RFC1737].
+
+ This document obsoletes [RFC2396], which merged "Uniform Resource
+ Locators" [RFC1738] and "Relative Uniform Resource Locators"
+ [RFC1808] in order to define a single, generic syntax for all URIs.
+ It obsoletes [RFC2732], which introduced syntax for an IPv6 address.
+ It excludes portions of RFC 1738 that defined the specific syntax of
+ individual URI schemes; those portions will be updated as separate
+ documents. The process for registration of new URI schemes is
+ defined separately by [BCP35]. Advice for designers of new URI
+ schemes can be found in [RFC2718]. All significant changes from RFC
+ 2396 are noted in Appendix D.
+
+ This specification uses the terms "character" and "coded character
+ set" in accordance with the definitions provided in [BCP19], and
+ "character encoding" in place of what [BCP19] refers to as a
+ "charset".
+
+1.1. Overview of URIs
+
+ URIs are characterized as follows:
+
+ Uniform
+
+ Uniformity provides several benefits. It allows different types
+ of resource identifiers to be used in the same context, even when
+ the mechanisms used to access those resources may differ. It
+ allows uniform semantic interpretation of common syntactic
+ conventions across different types of resource identifiers. It
+ allows introduction of new types of resource identifiers without
+ interfering with the way that existing identifiers are used. It
+ allows the identifiers to be reused in many different contexts,
+ thus permitting new applications or protocols to leverage a pre-
+ existing, large, and widely used set of resource identifiers.
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 4]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ Resource
+
+ This specification does not limit the scope of what might be a
+ resource; rather, the term "resource" is used in a general sense
+ for whatever might be identified by a URI. Familiar examples
+ include an electronic document, an image, a source of information
+ with a consistent purpose (e.g., "today's weather report for Los
+ Angeles"), a service (e.g., an HTTP-to-SMS gateway), and a
+ collection of other resources. A resource is not necessarily
+ accessible via the Internet; e.g., human beings, corporations, and
+ bound books in a library can also be resources. Likewise,
+ abstract concepts can be resources, such as the operators and
+ operands of a mathematical equation, the types of a relationship
+ (e.g., "parent" or "employee"), or numeric values (e.g., zero,
+ one, and infinity).
+
+ Identifier
+
+ An identifier embodies the information required to distinguish
+ what is being identified from all other things within its scope of
+ identification. Our use of the terms "identify" and "identifying"
+ refer to this purpose of distinguishing one resource from all
+ other resources, regardless of how that purpose is accomplished
+ (e.g., by name, address, or context). These terms should not be
+ mistaken as an assumption that an identifier defines or embodies
+ the identity of what is referenced, though that may be the case
+ for some identifiers. Nor should it be assumed that a system
+ using URIs will access the resource identified: in many cases,
+ URIs are used to denote resources without any intention that they
+ be accessed. Likewise, the "one" resource identified might not be
+ singular in nature (e.g., a resource might be a named set or a
+ mapping that varies over time).
+
+ A URI is an identifier consisting of a sequence of characters
+ matching the syntax rule named <URI> in Section 3. It enables
+ uniform identification of resources via a separately defined
+ extensible set of naming schemes (Section 3.1). How that
+ identification is accomplished, assigned, or enabled is delegated to
+ each scheme specification.
+
+ This specification does not place any limits on the nature of a
+ resource, the reasons why an application might seek to refer to a
+ resource, or the kinds of systems that might use URIs for the sake of
+ identifying resources. This specification does not require that a
+ URI persists in identifying the same resource over time, though that
+ is a common goal of all URI schemes. Nevertheless, nothing in this
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 5]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ specification prevents an application from limiting itself to
+ particular types of resources, or to a subset of URIs that maintains
+ characteristics desired by that application.
+
+ URIs have a global scope and are interpreted consistently regardless
+ of context, though the result of that interpretation may be in
+ relation to the end-user's context. For example, "http://localhost/"
+ has the same interpretation for every user of that reference, even
+ though the network interface corresponding to "localhost" may be
+ different for each end-user: interpretation is independent of access.
+ However, an action made on the basis of that reference will take
+ place in relation to the end-user's context, which implies that an
+ action intended to refer to a globally unique thing must use a URI
+ that distinguishes that resource from all other things. URIs that
+ identify in relation to the end-user's local context should only be
+ used when the context itself is a defining aspect of the resource,
+ such as when an on-line help manual refers to a file on the end-
+ user's file system (e.g., "file:///etc/hosts").
+
+1.1.1. Generic Syntax
+
+ Each URI begins with a scheme name, as defined in Section 3.1, that
+ refers to a specification for assigning identifiers within that
+ scheme. As such, the URI syntax is a federated and extensible naming
+ system wherein each scheme's specification may further restrict the
+ syntax and semantics of identifiers using that scheme.
+
+ This specification defines those elements of the URI syntax that are
+ required of all URI schemes or are common to many URI schemes. It
+ thus defines the syntax and semantics needed to implement a scheme-
+ independent parsing mechanism for URI references, by which the
+ scheme-dependent handling of a URI can be postponed until the
+ scheme-dependent semantics are needed. Likewise, protocols and data
+ formats that make use of URI references can refer to this
+ specification as a definition for the range of syntax allowed for all
+ URIs, including those schemes that have yet to be defined. This
+ decouples the evolution of identification schemes from the evolution
+ of protocols, data formats, and implementations that make use of
+ URIs.
+
+ A parser of the generic URI syntax can parse any URI reference into
+ its major components. Once the scheme is determined, further
+ scheme-specific parsing can be performed on the components. In other
+ words, the URI generic syntax is a superset of the syntax of all URI
+ schemes.
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 6]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+1.1.2. Examples
+
+ The following example URIs illustrate several URI schemes and
+ variations in their common syntax components:
+
+ ftp://ftp.is.co.za/rfc/rfc1808.txt
+
+ http://www.ietf.org/rfc/rfc2396.txt
+
+ ldap://[2001:db8::7]/c=GB?objectClass?one
+
+
+ news:comp.infosystems.www.servers.unix
+
+ tel:+1-816-555-1212
+
+ telnet://192.0.2.16:80/
+
+ urn:oasis:names:specification:docbook:dtd:xml:4.1.2
+
+
+1.1.3. URI, URL, and URN
+
+ A URI can be further classified as a locator, a name, or both. The
+ term "Uniform Resource Locator" (URL) refers to the subset of URIs
+ that, in addition to identifying a resource, provide a means of
+ locating the resource by describing its primary access mechanism
+ (e.g., its network "location"). The term "Uniform Resource Name"
+ (URN) has been used historically to refer to both URIs under the
+ "urn" scheme [RFC2141], which are required to remain globally unique
+ and persistent even when the resource ceases to exist or becomes
+ unavailable, and to any other URI with the properties of a name.
+
+ An individual scheme does not have to be classified as being just one
+ of "name" or "locator". Instances of URIs from any given scheme may
+ have the characteristics of names or locators or both, often
+ depending on the persistence and care in the assignment of
+ identifiers by the naming authority, rather than on any quality of
+ the scheme. Future specifications and related documentation should
+ use the general term "URI" rather than the more restrictive terms
+ "URL" and "URN" [RFC3305].
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 7]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+1.2. Design Considerations
+
+1.2.1. Transcription
+
+ The URI syntax has been designed with global transcription as one of
+ its main considerations. A URI is a sequence of characters from a
+ very limited set: the letters of the basic Latin alphabet, digits,
+ and a few special characters. A URI may be represented in a variety
+ of ways; e.g., ink on paper, pixels on a screen, or a sequence of
+ character encoding octets. The interpretation of a URI depends only
+ on the characters used and not on how those characters are
+ represented in a network protocol.
+
+ The goal of transcription can be described by a simple scenario.
+ Imagine two colleagues, Sam and Kim, sitting in a pub at an
+ international conference and exchanging research ideas. Sam asks Kim
+ for a location to get more information, so Kim writes the URI for the
+ research site on a napkin. Upon returning home, Sam takes out the
+ napkin and types the URI into a computer, which then retrieves the
+ information to which Kim referred.
+
+ There are several design considerations revealed by the scenario:
+
+ o A URI is a sequence of characters that is not always represented
+ as a sequence of octets.
+
+ o A URI might be transcribed from a non-network source and thus
+ should consist of characters that are most likely able to be
+ entered into a computer, within the constraints imposed by
+ keyboards (and related input devices) across languages and
+ locales.
+
+ o A URI often has to be remembered by people, and it is easier for
+ people to remember a URI when it consists of meaningful or
+ familiar components.
+
+ These design considerations are not always in alignment. For
+ example, it is often the case that the most meaningful name for a URI
+ component would require characters that cannot be typed into some
+ systems. The ability to transcribe a resource identifier from one
+ medium to another has been considered more important than having a
+ URI consist of the most meaningful of components.
+
+ In local or regional contexts and with improving technology, users
+ might benefit from being able to use a wider range of characters;
+ such use is not defined by this specification. Percent-encoded
+ octets (Section 2.1) may be used within a URI to represent characters
+ outside the range of the US-ASCII coded character set if this
+
+
+
+Berners-Lee, et al. Standards Track [Page 8]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ representation is allowed by the scheme or by the protocol element in
+ which the URI is referenced. Such a definition should specify the
+ character encoding used to map those characters to octets prior to
+ being percent-encoded for the URI.
+
+1.2.2. Separating Identification from Interaction
+
+ A common misunderstanding of URIs is that they are only used to refer
+ to accessible resources. The URI itself only provides
+ identification; access to the resource is neither guaranteed nor
+ implied by the presence of a URI. Instead, any operation associated
+ with a URI reference is defined by the protocol element, data format
+ attribute, or natural language text in which it appears.
+
+ Given a URI, a system may attempt to perform a variety of operations
+ on the resource, as might be characterized by words such as "access",
+ "update", "replace", or "find attributes". Such operations are
+ defined by the protocols that make use of URIs, not by this
+ specification. However, we do use a few general terms for describing
+ common operations on URIs. URI "resolution" is the process of
+ determining an access mechanism and the appropriate parameters
+ necessary to dereference a URI; this resolution may require several
+ iterations. To use that access mechanism to perform an action on the
+ URI's resource is to "dereference" the URI.
+
+ When URIs are used within information retrieval systems to identify
+ sources of information, the most common form of URI dereference is
+ "retrieval": making use of a URI in order to retrieve a
+ representation of its associated resource. A "representation" is a
+ sequence of octets, along with representation metadata describing
+ those octets, that constitutes a record of the state of the resource
+ at the time when the representation is generated. Retrieval is
+ achieved by a process that might include using the URI as a cache key
+ to check for a locally cached representation, resolution of the URI
+ to determine an appropriate access mechanism (if any), and
+ dereference of the URI for the sake of applying a retrieval
+ operation. Depending on the protocols used to perform the retrieval,
+ additional information might be supplied about the resource (resource
+ metadata) and its relation to other resources.
+
+ URI references in information retrieval systems are designed to be
+ late-binding: the result of an access is generally determined when it
+ is accessed and may vary over time or due to other aspects of the
+ interaction. These references are created in order to be used in the
+ future: what is being identified is not some specific result that was
+ obtained in the past, but rather some characteristic that is expected
+ to be true for future results. In such cases, the resource referred
+ to by the URI is actually a sameness of characteristics as observed
+
+
+
+Berners-Lee, et al. Standards Track [Page 9]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ over time, perhaps elucidated by additional comments or assertions
+ made by the resource provider.
+
+ Although many URI schemes are named after protocols, this does not
+ imply that use of these URIs will result in access to the resource
+ via the named protocol. URIs are often used simply for the sake of
+ identification. Even when a URI is used to retrieve a representation
+ of a resource, that access might be through gateways, proxies,
+ caches, and name resolution services that are independent of the
+ protocol associated with the scheme name. The resolution of some
+ URIs may require the use of more than one protocol (e.g., both DNS
+ and HTTP are typically used to access an "http" URI's origin server
+ when a representation isn't found in a local cache).
+
+1.2.3. Hierarchical Identifiers
+
+ The URI syntax is organized hierarchically, with components listed in
+ order of decreasing significance from left to right. For some URI
+ schemes, the visible hierarchy is limited to the scheme itself:
+ everything after the scheme component delimiter (":") is considered
+ opaque to URI processing. Other URI schemes make the hierarchy
+ explicit and visible to generic parsing algorithms.
+
+ The generic syntax uses the slash ("/"), question mark ("?"), and
+ number sign ("#") characters to delimit components that are
+ significant to the generic parser's hierarchical interpretation of an
+ identifier. In addition to aiding the readability of such
+ identifiers through the consistent use of familiar syntax, this
+ uniform representation of hierarchy across naming schemes allows
+ scheme-independent references to be made relative to that hierarchy.
+
+ It is often the case that a group or "tree" of documents has been
+ constructed to serve a common purpose, wherein the vast majority of
+ URI references in these documents point to resources within the tree
+ rather than outside it. Similarly, documents located at a particular
+ site are much more likely to refer to other resources at that site
+ than to resources at remote sites. Relative referencing of URIs
+ allows document trees to be partially independent of their location
+ and access scheme. For instance, it is possible for a single set of
+ hypertext documents to be simultaneously accessible and traversable
+ via each of the "file", "http", and "ftp" schemes if the documents
+ refer to each other with relative references. Furthermore, such
+ document trees can be moved, as a whole, without changing any of the
+ relative references.
+
+ A relative reference (Section 4.2) refers to a resource by describing
+ the difference within a hierarchical name space between the reference
+ context and the target URI. The reference resolution algorithm,
+
+
+
+Berners-Lee, et al. Standards Track [Page 10]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ presented in Section 5, defines how such a reference is transformed
+ to the target URI. As relative references can only be used within
+ the context of a hierarchical URI, designers of new URI schemes
+ should use a syntax consistent with the generic syntax's hierarchical
+ components unless there are compelling reasons to forbid relative
+ referencing within that scheme.
+
+ NOTE: Previous specifications used the terms "partial URI" and
+ "relative URI" to denote a relative reference to a URI. As some
+ readers misunderstood those terms to mean that relative URIs are a
+ subset of URIs rather than a method of referencing URIs, this
+ specification simply refers to them as relative references.
+
+ All URI references are parsed by generic syntax parsers when used.
+ However, because hierarchical processing has no effect on an absolute
+ URI used in a reference unless it contains one or more dot-segments
+ (complete path segments of "." or "..", as described in Section 3.3),
+ URI scheme specifications can define opaque identifiers by
+ disallowing use of slash characters, question mark characters, and
+ the URIs "scheme:." and "scheme:..".
+
+1.3. Syntax Notation
+
+ This specification uses the Augmented Backus-Naur Form (ABNF)
+ notation of [RFC2234], including the following core ABNF syntax rules
+ defined by that specification: ALPHA (letters), CR (carriage return),
+ DIGIT (decimal digits), DQUOTE (double quote), HEXDIG (hexadecimal
+ digits), LF (line feed), and SP (space). The complete URI syntax is
+ collected in Appendix A.
+
+2. Characters
+
+ The URI syntax provides a method of encoding data, presumably for the
+ sake of identifying a resource, as a sequence of characters. The URI
+ characters are, in turn, frequently encoded as octets for transport
+ or presentation. This specification does not mandate any particular
+ character encoding for mapping between URI characters and the octets
+ used to store or transmit those characters. When a URI appears in a
+ protocol element, the character encoding is defined by that protocol;
+ without such a definition, a URI is assumed to be in the same
+ character encoding as the surrounding text.
+
+ The ABNF notation defines its terminal values to be non-negative
+ integers (codepoints) based on the US-ASCII coded character set
+ [ASCII]. Because a URI is a sequence of characters, we must invert
+ that relation in order to understand the URI syntax. Therefore, the
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 11]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ integer values used by the ABNF must be mapped back to their
+ corresponding characters via US-ASCII in order to complete the syntax
+ rules.
+
+ A URI is composed from a limited set of characters consisting of
+ digits, letters, and a few graphic symbols. A reserved subset of
+ those characters may be used to delimit syntax components within a
+ URI while the remaining characters, including both the unreserved set
+ and those reserved characters not acting as delimiters, define each
+ component's identifying data.
+
+2.1. Percent-Encoding
+
+ A percent-encoding mechanism is used to represent a data octet in a
+ component when that octet's corresponding character is outside the
+ allowed set or is being used as a delimiter of, or within, the
+ component. A percent-encoded octet is encoded as a character
+ triplet, consisting of the percent character "%" followed by the two
+ hexadecimal digits representing that octet's numeric value. For
+ example, "%20" is the percent-encoding for the binary octet
+ "00100000" (ABNF: %x20), which in US-ASCII corresponds to the space
+ character (SP). Section 2.4 describes when percent-encoding and
+ decoding is applied.
+
+ pct-encoded = "%" HEXDIG HEXDIG
+
+ The uppercase hexadecimal digits 'A' through 'F' are equivalent to
+ the lowercase digits 'a' through 'f', respectively. If two URIs
+ differ only in the case of hexadecimal digits used in percent-encoded
+ octets, they are equivalent. For consistency, URI producers and
+ normalizers should use uppercase hexadecimal digits for all percent-
+ encodings.
+
+2.2. Reserved Characters
+
+ URIs include components and subcomponents that are delimited by
+ characters in the "reserved" set. These characters are called
+ "reserved" because they may (or may not) be defined as delimiters by
+ the generic syntax, by each scheme-specific syntax, or by the
+ implementation-specific syntax of a URI's dereferencing algorithm.
+ If data for a URI component would conflict with a reserved
+ character's purpose as a delimiter, then the conflicting data must be
+ percent-encoded before the URI is formed.
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 12]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ reserved = gen-delims / sub-delims
+
+ gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+
+ sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+ / "*" / "+" / "," / ";" / "="
+
+ The purpose of reserved characters is to provide a set of delimiting
+ characters that are distinguishable from other data within a URI.
+ URIs that differ in the replacement of a reserved character with its
+ corresponding percent-encoded octet are not equivalent. Percent-
+ encoding a reserved character, or decoding a percent-encoded octet
+ that corresponds to a reserved character, will change how the URI is
+ interpreted by most applications. Thus, characters in the reserved
+ set are protected from normalization and are therefore safe to be
+ used by scheme-specific and producer-specific algorithms for
+ delimiting data subcomponents within a URI.
+
+ A subset of the reserved characters (gen-delims) is used as
+ delimiters of the generic URI components described in Section 3. A
+ component's ABNF syntax rule will not use the reserved or gen-delims
+ rule names directly; instead, each syntax rule lists the characters
+ allowed within that component (i.e., not delimiting it), and any of
+ those characters that are also in the reserved set are "reserved" for
+ use as subcomponent delimiters within the component. Only the most
+ common subcomponents are defined by this specification; other
+ subcomponents may be defined by a URI scheme's specification, or by
+ the implementation-specific syntax of a URI's dereferencing
+ algorithm, provided that such subcomponents are delimited by
+ characters in the reserved set allowed within that component.
+
+ URI producing applications should percent-encode data octets that
+ correspond to characters in the reserved set unless these characters
+ are specifically allowed by the URI scheme to represent data in that
+ component. If a reserved character is found in a URI component and
+ no delimiting role is known for that character, then it must be
+ interpreted as representing the data octet corresponding to that
+ character's encoding in US-ASCII.
+
+2.3. Unreserved Characters
+
+ Characters that are allowed in a URI but do not have a reserved
+ purpose are called unreserved. These include uppercase and lowercase
+ letters, decimal digits, hyphen, period, underscore, and tilde.
+
+ unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 13]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ URIs that differ in the replacement of an unreserved character with
+ its corresponding percent-encoded US-ASCII octet are equivalent: they
+ identify the same resource. However, URI comparison implementations
+ do not always perform normalization prior to comparison (see Section
+ 6). For consistency, percent-encoded octets in the ranges of ALPHA
+ (%41-%5A and %61-%7A), DIGIT (%30-%39), hyphen (%2D), period (%2E),
+ underscore (%5F), or tilde (%7E) should not be created by URI
+ producers and, when found in a URI, should be decoded to their
+ corresponding unreserved characters by URI normalizers.
+
+2.4. When to Encode or Decode
+
+ Under normal circumstances, the only time when octets within a URI
+ are percent-encoded is during the process of producing the URI from
+ its component parts. This is when an implementation determines which
+ of the reserved characters are to be used as subcomponent delimiters
+ and which can be safely used as data. Once produced, a URI is always
+ in its percent-encoded form.
+
+ When a URI is dereferenced, the components and subcomponents
+ significant to the scheme-specific dereferencing process (if any)
+ must be parsed and separated before the percent-encoded octets within
+ those components can be safely decoded, as otherwise the data may be
+ mistaken for component delimiters. The only exception is for
+ percent-encoded octets corresponding to characters in the unreserved
+ set, which can be decoded at any time. For example, the octet
+ corresponding to the tilde ("~") character is often encoded as "%7E"
+ by older URI processing implementations; the "%7E" can be replaced by
+ "~" without changing its interpretation.
+
+ Because the percent ("%") character serves as the indicator for
+ percent-encoded octets, it must be percent-encoded as "%25" for that
+ octet to be used as data within a URI. Implementations must not
+ percent-encode or decode the same string more than once, as decoding
+ an already decoded string might lead to misinterpreting a percent
+ data octet as the beginning of a percent-encoding, or vice versa in
+ the case of percent-encoding an already percent-encoded string.
+
+2.5. Identifying Data
+
+ URI characters provide identifying data for each of the URI
+ components, serving as an external interface for identification
+ between systems. Although the presence and nature of the URI
+ production interface is hidden from clients that use its URIs (and is
+ thus beyond the scope of the interoperability requirements defined by
+ this specification), it is a frequent source of confusion and errors
+ in the interpretation of URI character issues. Implementers have to
+ be aware that there are multiple character encodings involved in the
+
+
+
+Berners-Lee, et al. Standards Track [Page 14]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ production and transmission of URIs: local name and data encoding,
+ public interface encoding, URI character encoding, data format
+ encoding, and protocol encoding.
+
+ Local names, such as file system names, are stored with a local
+ character encoding. URI producing applications (e.g., origin
+ servers) will typically use the local encoding as the basis for
+ producing meaningful names. The URI producer will transform the
+ local encoding to one that is suitable for a public interface and
+ then transform the public interface encoding into the restricted set
+ of URI characters (reserved, unreserved, and percent-encodings).
+ Those characters are, in turn, encoded as octets to be used as a
+ reference within a data format (e.g., a document charset), and such
+ data formats are often subsequently encoded for transmission over
+ Internet protocols.
+
+ For most systems, an unreserved character appearing within a URI
+ component is interpreted as representing the data octet corresponding
+ to that character's encoding in US-ASCII. Consumers of URIs assume
+ that the letter "X" corresponds to the octet "01011000", and even
+ when that assumption is incorrect, there is no harm in making it. A
+ system that internally provides identifiers in the form of a
+ different character encoding, such as EBCDIC, will generally perform
+ character translation of textual identifiers to UTF-8 [STD63] (or
+ some other superset of the US-ASCII character encoding) at an
+ internal interface, thereby providing more meaningful identifiers
+ than those resulting from simply percent-encoding the original
+ octets.
+
+ For example, consider an information service that provides data,
+ stored locally using an EBCDIC-based file system, to clients on the
+ Internet through an HTTP server. When an author creates a file with
+ the name "Laguna Beach" on that file system, the "http" URI
+ corresponding to that resource is expected to contain the meaningful
+ string "Laguna%20Beach". If, however, that server produces URIs by
+ using an overly simplistic raw octet mapping, then the result would
+ be a URI containing "%D3%81%87%A4%95%81@%C2%85%81%83%88". An
+ internal transcoding interface fixes this problem by transcoding the
+ local name to a superset of US-ASCII prior to producing the URI.
+ Naturally, proper interpretation of an incoming URI on such an
+ interface requires that percent-encoded octets be decoded (e.g.,
+ "%20" to SP) before the reverse transcoding is applied to obtain the
+ local name.
+
+ In some cases, the internal interface between a URI component and the
+ identifying data that it has been crafted to represent is much less
+ direct than a character encoding translation. For example, portions
+ of a URI might reflect a query on non-ASCII data, or numeric
+
+
+
+Berners-Lee, et al. Standards Track [Page 15]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ coordinates on a map. Likewise, a URI scheme may define components
+ with additional encoding requirements that are applied prior to
+ forming the component and producing the URI.
+
+ When a new URI scheme defines a component that represents textual
+ data consisting of characters from the Universal Character Set [UCS],
+ the data should first be encoded as octets according to the UTF-8
+ character encoding [STD63]; then only those octets that do not
+ correspond to characters in the unreserved set should be percent-
+ encoded. For example, the character A would be represented as "A",
+ the character LATIN CAPITAL LETTER A WITH GRAVE would be represented
+ as "%C3%80", and the character KATAKANA LETTER A would be represented
+ as "%E3%82%A2".
+
+3. Syntax Components
+
+ The generic URI syntax consists of a hierarchical sequence of
+ components referred to as the scheme, authority, path, query, and
+ fragment.
+
+ URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
+
+ hier-part = "//" authority path-abempty
+ / path-absolute
+ / path-rootless
+ / path-empty
+
+ The scheme and path components are required, though the path may be
+ empty (no characters). When authority is present, the path must
+ either be empty or begin with a slash ("/") character. When
+ authority is not present, the path cannot begin with two slash
+ characters ("//"). These restrictions result in five different ABNF
+ rules for a path (Section 3.3), only one of which will match any
+ given URI reference.
+
+ The following are two example URIs and their component parts:
+
+ foo://example.com:8042/over/there?name=ferret#nose
+ \_/ \______________/\_________/ \_________/ \__/
+ | | | | |
+ scheme authority path query fragment
+ | _____________________|__
+ / \ / \
+ urn:example:animal:ferret:nose
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 16]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+3.1. Scheme
+
+ Each URI begins with a scheme name that refers to a specification for
+ assigning identifiers within that scheme. As such, the URI syntax is
+ a federated and extensible naming system wherein each scheme's
+ specification may further restrict the syntax and semantics of
+ identifiers using that scheme.
+
+ Scheme names consist of a sequence of characters beginning with a
+ letter and followed by any combination of letters, digits, plus
+ ("+"), period ("."), or hyphen ("-"). Although schemes are case-
+ insensitive, the canonical form is lowercase and documents that
+ specify schemes must do so with lowercase letters. An implementation
+ should accept uppercase letters as equivalent to lowercase in scheme
+ names (e.g., allow "HTTP" as well as "http") for the sake of
+ robustness but should only produce lowercase scheme names for
+ consistency.
+
+ scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+
+ Individual schemes are not specified by this document. The process
+ for registration of new URI schemes is defined separately by [BCP35].
+ The scheme registry maintains the mapping between scheme names and
+ their specifications. Advice for designers of new URI schemes can be
+ found in [RFC2718]. URI scheme specifications must define their own
+ syntax so that all strings matching their scheme-specific syntax will
+ also match the <absolute-URI> grammar, as described in Section 4.3.
+
+ When presented with a URI that violates one or more scheme-specific
+ restrictions, the scheme-specific resolution process should flag the
+ reference as an error rather than ignore the unused parts; doing so
+ reduces the number of equivalent URIs and helps detect abuses of the
+ generic syntax, which might indicate that the URI has been
+ constructed to mislead the user (Section 7.6).
+
+3.2. Authority
+
+ Many URI schemes include a hierarchical element for a naming
+ authority so that governance of the name space defined by the
+ remainder of the URI is delegated to that authority (which may, in
+ turn, delegate it further). The generic syntax provides a common
+ means for distinguishing an authority based on a registered name or
+ server address, along with optional port and user information.
+
+ The authority component is preceded by a double slash ("//") and is
+ terminated by the next slash ("/"), question mark ("?"), or number
+ sign ("#") character, or by the end of the URI.
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 17]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ authority = [ userinfo "@" ] host [ ":" port ]
+
+ URI producers and normalizers should omit the ":" delimiter that
+ separates host from port if the port component is empty. Some
+ schemes do not allow the userinfo and/or port subcomponents.
+
+ If a URI contains an authority component, then the path component
+ must either be empty or begin with a slash ("/") character. Non-
+ validating parsers (those that merely separate a URI reference into
+ its major components) will often ignore the subcomponent structure of
+ authority, treating it as an opaque string from the double-slash to
+ the first terminating delimiter, until such time as the URI is
+ dereferenced.
+
+3.2.1. User Information
+
+ The userinfo subcomponent may consist of a user name and, optionally,
+ scheme-specific information about how to gain authorization to access
+ the resource. The user information, if present, is followed by a
+ commercial at-sign ("@") that delimits it from the host.
+
+ userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
+
+ Use of the format "user:password" in the userinfo field is
+ deprecated. Applications should not render as clear text any data
+ after the first colon (":") character found within a userinfo
+ subcomponent unless the data after the colon is the empty string
+ (indicating no password). Applications may choose to ignore or
+ reject such data when it is received as part of a reference and
+ should reject the storage of such data in unencrypted form. The
+ passing of authentication information in clear text has proven to be
+ a security risk in almost every case where it has been used.
+
+ Applications that render a URI for the sake of user feedback, such as
+ in graphical hypertext browsing, should render userinfo in a way that
+ is distinguished from the rest of a URI, when feasible. Such
+ rendering will assist the user in cases where the userinfo has been
+ misleadingly crafted to look like a trusted domain name
+ (Section 7.6).
+
+3.2.2. Host
+
+ The host subcomponent of authority is identified by an IP literal
+ encapsulated within square brackets, an IPv4 address in dotted-
+ decimal form, or a registered name. The host subcomponent is case-
+ insensitive. The presence of a host subcomponent within a URI does
+ not imply that the scheme requires access to the given host on the
+ Internet. In many cases, the host syntax is used only for the sake
+
+
+
+Berners-Lee, et al. Standards Track [Page 18]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ of reusing the existing registration process created and deployed for
+ DNS, thus obtaining a globally unique name without the cost of
+ deploying another registry. However, such use comes with its own
+ costs: domain name ownership may change over time for reasons not
+ anticipated by the URI producer. In other cases, the data within the
+ host component identifies a registered name that has nothing to do
+ with an Internet host. We use the name "host" for the ABNF rule
+ because that is its most common purpose, not its only purpose.
+
+ host = IP-literal / IPv4address / reg-name
+
+ The syntax rule for host is ambiguous because it does not completely
+ distinguish between an IPv4address and a reg-name. In order to
+ disambiguate the syntax, we apply the "first-match-wins" algorithm:
+ If host matches the rule for IPv4address, then it should be
+ considered an IPv4 address literal and not a reg-name. Although host
+ is case-insensitive, producers and normalizers should use lowercase
+ for registered names and hexadecimal addresses for the sake of
+ uniformity, while only using uppercase letters for percent-encodings.
+
+ A host identified by an Internet Protocol literal address, version 6
+ [RFC3513] or later, is distinguished by enclosing the IP literal
+ within square brackets ("[" and "]"). This is the only place where
+ square bracket characters are allowed in the URI syntax. In
+ anticipation of future, as-yet-undefined IP literal address formats,
+ an implementation may use an optional version flag to indicate such a
+ format explicitly rather than rely on heuristic determination.
+
+ IP-literal = "[" ( IPv6address / IPvFuture ) "]"
+
+ IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
+
+ The version flag does not indicate the IP version; rather, it
+ indicates future versions of the literal format. As such,
+ implementations must not provide the version flag for the existing
+ IPv4 and IPv6 literal address forms described below. If a URI
+ containing an IP-literal that starts with "v" (case-insensitive),
+ indicating that the version flag is present, is dereferenced by an
+ application that does not know the meaning of that version flag, then
+ the application should return an appropriate error for "address
+ mechanism not supported".
+
+ A host identified by an IPv6 literal address is represented inside
+ the square brackets without a preceding version flag. The ABNF
+ provided here is a translation of the text definition of an IPv6
+ literal address provided in [RFC3513]. This syntax does not support
+ IPv6 scoped addressing zone identifiers.
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 19]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ A 128-bit IPv6 address is divided into eight 16-bit pieces. Each
+ piece is represented numerically in case-insensitive hexadecimal,
+ using one to four hexadecimal digits (leading zeroes are permitted).
+ The eight encoded pieces are given most-significant first, separated
+ by colon characters. Optionally, the least-significant two pieces
+ may instead be represented in IPv4 address textual format. A
+ sequence of one or more consecutive zero-valued 16-bit pieces within
+ the address may be elided, omitting all their digits and leaving
+ exactly two consecutive colons in their place to mark the elision.
+
+ IPv6address = 6( h16 ":" ) ls32
+ / "::" 5( h16 ":" ) ls32
+ / [ h16 ] "::" 4( h16 ":" ) ls32
+ / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
+ / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
+ / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
+ / [ *4( h16 ":" ) h16 ] "::" ls32
+ / [ *5( h16 ":" ) h16 ] "::" h16
+ / [ *6( h16 ":" ) h16 ] "::"
+
+ ls32 = ( h16 ":" h16 ) / IPv4address
+ ; least-significant 32 bits of address
+
+ h16 = 1*4HEXDIG
+ ; 16 bits of address represented in hexadecimal
+
+ A host identified by an IPv4 literal address is represented in
+ dotted-decimal notation (a sequence of four decimal numbers in the
+ range 0 to 255, separated by "."), as described in [RFC1123] by
+ reference to [RFC0952]. Note that other forms of dotted notation may
+ be interpreted on some platforms, as described in Section 7.4, but
+ only the dotted-decimal form of four octets is allowed by this
+ grammar.
+
+ IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
+
+ dec-octet = DIGIT ; 0-9
+ / %x31-39 DIGIT ; 10-99
+ / "1" 2DIGIT ; 100-199
+ / "2" %x30-34 DIGIT ; 200-249
+ / "25" %x30-35 ; 250-255
+
+ A host identified by a registered name is a sequence of characters
+ usually intended for lookup within a locally defined host or service
+ name registry, though the URI's scheme-specific semantics may require
+ that a specific registry (or fixed name table) be used instead. The
+ most common name registry mechanism is the Domain Name System (DNS).
+ A registered name intended for lookup in the DNS uses the syntax
+
+
+
+Berners-Lee, et al. Standards Track [Page 20]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ defined in Section 3.5 of [RFC1034] and Section 2.1 of [RFC1123].
+ Such a name consists of a sequence of domain labels separated by ".",
+ each domain label starting and ending with an alphanumeric character
+ and possibly also containing "-" characters. The rightmost domain
+ label of a fully qualified domain name in DNS may be followed by a
+ single "." and should be if it is necessary to distinguish between
+ the complete domain name and some local domain.
+
+ reg-name = *( unreserved / pct-encoded / sub-delims )
+
+ If the URI scheme defines a default for host, then that default
+ applies when the host subcomponent is undefined or when the
+ registered name is empty (zero length). For example, the "file" URI
+ scheme is defined so that no authority, an empty host, and
+ "localhost" all mean the end-user's machine, whereas the "http"
+ scheme considers a missing authority or empty host invalid.
+
+ This specification does not mandate a particular registered name
+ lookup technology and therefore does not restrict the syntax of reg-
+ name beyond what is necessary for interoperability. Instead, it
+ delegates the issue of registered name syntax conformance to the
+ operating system of each application performing URI resolution, and
+ that operating system decides what it will allow for the purpose of
+ host identification. A URI resolution implementation might use DNS,
+ host tables, yellow pages, NetInfo, WINS, or any other system for
+ lookup of registered names. However, a globally scoped naming
+ system, such as DNS fully qualified domain names, is necessary for
+ URIs intended to have global scope. URI producers should use names
+ that conform to the DNS syntax, even when use of DNS is not
+ immediately apparent, and should limit these names to no more than
+ 255 characters in length.
+
+ The reg-name syntax allows percent-encoded octets in order to
+ represent non-ASCII registered names in a uniform way that is
+ independent of the underlying name resolution technology. Non-ASCII
+ characters must first be encoded according to UTF-8 [STD63], and then
+ each octet of the corresponding UTF-8 sequence must be percent-
+ encoded to be represented as URI characters. URI producing
+ applications must not use percent-encoding in host unless it is used
+ to represent a UTF-8 character sequence. When a non-ASCII registered
+ name represents an internationalized domain name intended for
+ resolution via the DNS, the name must be transformed to the IDNA
+ encoding [RFC3490] prior to name lookup. URI producers should
+ provide these registered names in the IDNA encoding, rather than a
+ percent-encoding, if they wish to maximize interoperability with
+ legacy URI resolvers.
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 21]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+3.2.3. Port
+
+ The port subcomponent of authority is designated by an optional port
+ number in decimal following the host and delimited from it by a
+ single colon (":") character.
+
+ port = *DIGIT
+
+ A scheme may define a default port. For example, the "http" scheme
+ defines a default port of "80", corresponding to its reserved TCP
+ port number. The type of port designated by the port number (e.g.,
+ TCP, UDP, SCTP) is defined by the URI scheme. URI producers and
+ normalizers should omit the port component and its ":" delimiter if
+ port is empty or if its value would be the same as that of the
+ scheme's default.
+
+3.3. Path
+
+ The path component contains data, usually organized in hierarchical
+ form, that, along with data in the non-hierarchical query component
+ (Section 3.4), serves to identify a resource within the scope of the
+ URI's scheme and naming authority (if any). The path is terminated
+ by the first question mark ("?") or number sign ("#") character, or
+ by the end of the URI.
+
+ If a URI contains an authority component, then the path component
+ must either be empty or begin with a slash ("/") character. If a URI
+ does not contain an authority component, then the path cannot begin
+ with two slash characters ("//"). In addition, a URI reference
+ (Section 4.1) may be a relative-path reference, in which case the
+ first path segment cannot contain a colon (":") character. The ABNF
+ requires five separate rules to disambiguate these cases, only one of
+ which will match the path substring within a given URI reference. We
+ use the generic term "path component" to describe the URI substring
+ matched by the parser to one of these rules.
+
+ path = path-abempty ; begins with "/" or is empty
+ / path-absolute ; begins with "/" but not "//"
+ / path-noscheme ; begins with a non-colon segment
+ / path-rootless ; begins with a segment
+ / path-empty ; zero characters
+
+ path-abempty = *( "/" segment )
+ path-absolute = "/" [ segment-nz *( "/" segment ) ]
+ path-noscheme = segment-nz-nc *( "/" segment )
+ path-rootless = segment-nz *( "/" segment )
+ path-empty = 0<pchar>
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 22]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ segment = *pchar
+ segment-nz = 1*pchar
+ segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
+ ; non-zero-length segment without any colon ":"
+
+ pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
+
+ A path consists of a sequence of path segments separated by a slash
+ ("/") character. A path is always defined for a URI, though the
+ defined path may be empty (zero length). Use of the slash character
+ to indicate hierarchy is only required when a URI will be used as the
+ context for relative references. For example, the URI
+ <mailto:[email protected]> has a path of "[email protected]", whereas
+ the URI <foo://info.example.com?fred> has an empty path.
+
+ The path segments "." and "..", also known as dot-segments, are
+ defined for relative reference within the path name hierarchy. They
+ are intended for use at the beginning of a relative-path reference
+ (Section 4.2) to indicate relative position within the hierarchical
+ tree of names. This is similar to their role within some operating
+ systems' file directory structures to indicate the current directory
+ and parent directory, respectively. However, unlike in a file
+ system, these dot-segments are only interpreted within the URI path
+ hierarchy and are removed as part of the resolution process (Section
+ 5.2).
+
+ Aside from dot-segments in hierarchical paths, a path segment is
+ considered opaque by the generic syntax. URI producing applications
+ often use the reserved characters allowed in a segment to delimit
+ scheme-specific or dereference-handler-specific subcomponents. For
+ example, the semicolon (";") and equals ("=") reserved characters are
+ often used to delimit parameters and parameter values applicable to
+ that segment. The comma (",") reserved character is often used for
+ similar purposes. For example, one URI producer might use a segment
+ such as "name;v=1.1" to indicate a reference to version 1.1 of
+ "name", whereas another might use a segment such as "name,1.1" to
+ indicate the same. Parameter types may be defined by scheme-specific
+ semantics, but in most cases the syntax of a parameter is specific to
+ the implementation of the URI's dereferencing algorithm.
+
+3.4. Query
+
+ The query component contains non-hierarchical data that, along with
+ data in the path component (Section 3.3), serves to identify a
+ resource within the scope of the URI's scheme and naming authority
+ (if any). The query component is indicated by the first question
+ mark ("?") character and terminated by a number sign ("#") character
+ or by the end of the URI.
+
+
+
+Berners-Lee, et al. Standards Track [Page 23]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ query = *( pchar / "/" / "?" )
+
+ The characters slash ("/") and question mark ("?") may represent data
+ within the query component. Beware that some older, erroneous
+ implementations may not handle such data correctly when it is used as
+ the base URI for relative references (Section 5.1), apparently
+ because they fail to distinguish query data from path data when
+ looking for hierarchical separators. However, as query components
+ are often used to carry identifying information in the form of
+ "key=value" pairs and one frequently used value is a reference to
+ another URI, it is sometimes better for usability to avoid percent-
+ encoding those characters.
+
+3.5. Fragment
+
+ The fragment identifier component of a URI allows indirect
+ identification of a secondary resource by reference to a primary
+ resource and additional identifying information. The identified
+ secondary resource may be some portion or subset of the primary
+ resource, some view on representations of the primary resource, or
+ some other resource defined or described by those representations. A
+ fragment identifier component is indicated by the presence of a
+ number sign ("#") character and terminated by the end of the URI.
+
+ fragment = *( pchar / "/" / "?" )
+
+ The semantics of a fragment identifier are defined by the set of
+ representations that might result from a retrieval action on the
+ primary resource. The fragment's format and resolution is therefore
+ dependent on the media type [RFC2046] of a potentially retrieved
+ representation, even though such a retrieval is only performed if the
+ URI is dereferenced. If no such representation exists, then the
+ semantics of the fragment are considered unknown and are effectively
+ unconstrained. Fragment identifier semantics are independent of the
+ URI scheme and thus cannot be redefined by scheme specifications.
+
+ Individual media types may define their own restrictions on or
+ structures within the fragment identifier syntax for specifying
+ different types of subsets, views, or external references that are
+ identifiable as secondary resources by that media type. If the
+ primary resource has multiple representations, as is often the case
+ for resources whose representation is selected based on attributes of
+ the retrieval request (a.k.a., content negotiation), then whatever is
+ identified by the fragment should be consistent across all of those
+ representations. Each representation should either define the
+ fragment so that it corresponds to the same secondary resource,
+ regardless of how it is represented, or should leave the fragment
+ undefined (i.e., not found).
+
+
+
+Berners-Lee, et al. Standards Track [Page 24]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ As with any URI, use of a fragment identifier component does not
+ imply that a retrieval action will take place. A URI with a fragment
+ identifier may be used to refer to the secondary resource without any
+ implication that the primary resource is accessible or will ever be
+ accessed.
+
+ Fragment identifiers have a special role in information retrieval
+ systems as the primary form of client-side indirect referencing,
+ allowing an author to specifically identify aspects of an existing
+ resource that are only indirectly provided by the resource owner. As
+ such, the fragment identifier is not used in the scheme-specific
+ processing of a URI; instead, the fragment identifier is separated
+ from the rest of the URI prior to a dereference, and thus the
+ identifying information within the fragment itself is dereferenced
+ solely by the user agent, regardless of the URI scheme. Although
+ this separate handling is often perceived to be a loss of
+ information, particularly for accurate redirection of references as
+ resources move over time, it also serves to prevent information
+ providers from denying reference authors the right to refer to
+ information within a resource selectively. Indirect referencing also
+ provides additional flexibility and extensibility to systems that use
+ URIs, as new media types are easier to define and deploy than new
+ schemes of identification.
+
+ The characters slash ("/") and question mark ("?") are allowed to
+ represent data within the fragment identifier. Beware that some
+ older, erroneous implementations may not handle this data correctly
+ when it is used as the base URI for relative references (Section
+ 5.1).
+
+4. Usage
+
+ When applications make reference to a URI, they do not always use the
+ full form of reference defined by the "URI" syntax rule. To save
+ space and take advantage of hierarchical locality, many Internet
+ protocol elements and media type formats allow an abbreviation of a
+ URI, whereas others restrict the syntax to a particular form of URI.
+ We define the most common forms of reference syntax in this
+ specification because they impact and depend upon the design of the
+ generic syntax, requiring a uniform parsing algorithm in order to be
+ interpreted consistently.
+
+4.1. URI Reference
+
+ URI-reference is used to denote the most common usage of a resource
+ identifier.
+
+ URI-reference = URI / relative-ref
+
+
+
+Berners-Lee, et al. Standards Track [Page 25]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ A URI-reference is either a URI or a relative reference. If the
+ URI-reference's prefix does not match the syntax of a scheme followed
+ by its colon separator, then the URI-reference is a relative
+ reference.
+
+ A URI-reference is typically parsed first into the five URI
+ components, in order to determine what components are present and
+ whether the reference is relative. Then, each component is parsed
+ for its subparts and their validation. The ABNF of URI-reference,
+ along with the "first-match-wins" disambiguation rule, is sufficient
+ to define a validating parser for the generic syntax. Readers
+ familiar with regular expressions should see Appendix B for an
+ example of a non-validating URI-reference parser that will take any
+ given string and extract the URI components.
+
+4.2. Relative Reference
+
+ A relative reference takes advantage of the hierarchical syntax
+ (Section 1.2.3) to express a URI reference relative to the name space
+ of another hierarchical URI.
+
+ relative-ref = relative-part [ "?" query ] [ "#" fragment ]
+
+ relative-part = "//" authority path-abempty
+ / path-absolute
+ / path-noscheme
+ / path-empty
+
+ The URI referred to by a relative reference, also known as the target
+ URI, is obtained by applying the reference resolution algorithm of
+ Section 5.
+
+ A relative reference that begins with two slash characters is termed
+ a network-path reference; such references are rarely used. A
+ relative reference that begins with a single slash character is
+ termed an absolute-path reference. A relative reference that does
+ not begin with a slash character is termed a relative-path reference.
+
+ A path segment that contains a colon character (e.g., "this:that")
+ cannot be used as the first segment of a relative-path reference, as
+ it would be mistaken for a scheme name. Such a segment must be
+ preceded by a dot-segment (e.g., "./this:that") to make a relative-
+ path reference.
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 26]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+4.3. Absolute URI
+
+ Some protocol elements allow only the absolute form of a URI without
+ a fragment identifier. For example, defining a base URI for later
+ use by relative references calls for an absolute-URI syntax rule that
+ does not allow a fragment.
+
+ absolute-URI = scheme ":" hier-part [ "?" query ]
+
+ URI scheme specifications must define their own syntax so that all
+ strings matching their scheme-specific syntax will also match the
+ <absolute-URI> grammar. Scheme specifications will not define
+ fragment identifier syntax or usage, regardless of its applicability
+ to resources identifiable via that scheme, as fragment identification
+ is orthogonal to scheme definition. However, scheme specifications
+ are encouraged to include a wide range of examples, including
+ examples that show use of the scheme's URIs with fragment identifiers
+ when such usage is appropriate.
+
+4.4. Same-Document Reference
+
+ When a URI reference refers to a URI that is, aside from its fragment
+ component (if any), identical to the base URI (Section 5.1), that
+ reference is called a "same-document" reference. The most frequent
+ examples of same-document references are relative references that are
+ empty or include only the number sign ("#") separator followed by a
+ fragment identifier.
+
+ When a same-document reference is dereferenced for a retrieval
+ action, the target of that reference is defined to be within the same
+ entity (representation, document, or message) as the reference;
+ therefore, a dereference should not result in a new retrieval action.
+
+ Normalization of the base and target URIs prior to their comparison,
+ as described in Sections 6.2.2 and 6.2.3, is allowed but rarely
+ performed in practice. Normalization may increase the set of same-
+ document references, which may be of benefit to some caching
+ applications. As such, reference authors should not assume that a
+ slightly different, though equivalent, reference URI will (or will
+ not) be interpreted as a same-document reference by any given
+ application.
+
+4.5. Suffix Reference
+
+ The URI syntax is designed for unambiguous reference to resources and
+ extensibility via the URI scheme. However, as URI identification and
+ usage have become commonplace, traditional media (television, radio,
+ newspapers, billboards, etc.) have increasingly used a suffix of the
+
+
+
+Berners-Lee, et al. Standards Track [Page 27]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ URI as a reference, consisting of only the authority and path
+ portions of the URI, such as
+
+ www.w3.org/Addressing/
+
+ or simply a DNS registered name on its own. Such references are
+ primarily intended for human interpretation rather than for machines,
+ with the assumption that context-based heuristics are sufficient to
+ complete the URI (e.g., most registered names beginning with "www"
+ are likely to have a URI prefix of "http://"). Although there is no
+ standard set of heuristics for disambiguating a URI suffix, many
+ client implementations allow them to be entered by the user and
+ heuristically resolved.
+
+ Although this practice of using suffix references is common, it
+ should be avoided whenever possible and should never be used in
+ situations where long-term references are expected. The heuristics
+ noted above will change over time, particularly when a new URI scheme
+ becomes popular, and are often incorrect when used out of context.
+ Furthermore, they can lead to security issues along the lines of
+ those described in [RFC1535].
+
+ As a URI suffix has the same syntax as a relative-path reference, a
+ suffix reference cannot be used in contexts where a relative
+ reference is expected. As a result, suffix references are limited to
+ places where there is no defined base URI, such as dialog boxes and
+ off-line advertisements.
+
+5. Reference Resolution
+
+ This section defines the process of resolving a URI reference within
+ a context that allows relative references so that the result is a
+ string matching the <URI> syntax rule of Section 3.
+
+5.1. Establishing a Base URI
+
+ The term "relative" implies that a "base URI" exists against which
+ the relative reference is applied. Aside from fragment-only
+ references (Section 4.4), relative references are only usable when a
+ base URI is known. A base URI must be established by the parser
+ prior to parsing URI references that might be relative. A base URI
+ must conform to the <absolute-URI> syntax rule (Section 4.3). If the
+ base URI is obtained from a URI reference, then that reference must
+ be converted to absolute form and stripped of any fragment component
+ prior to its use as a base URI.
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 28]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ The base URI of a reference can be established in one of four ways,
+ discussed below in order of precedence. The order of precedence can
+ be thought of in terms of layers, where the innermost defined base
+ URI has the highest precedence. This can be visualized graphically
+ as follows:
+
+ .----------------------------------------------------------.
+ | .----------------------------------------------------. |
+ | | .----------------------------------------------. | |
+ | | | .----------------------------------------. | | |
+ | | | | .----------------------------------. | | | |
+ | | | | | <relative-reference> | | | | |
+ | | | | `----------------------------------' | | | |
+ | | | | (5.1.1) Base URI embedded in content | | | |
+ | | | `----------------------------------------' | | |
+ | | | (5.1.2) Base URI of the encapsulating entity | | |
+ | | | (message, representation, or none) | | |
+ | | `----------------------------------------------' | |
+ | | (5.1.3) URI used to retrieve the entity | |
+ | `----------------------------------------------------' |
+ | (5.1.4) Default Base URI (application-dependent) |
+ `----------------------------------------------------------'
+
+5.1.1. Base URI Embedded in Content
+
+ Within certain media types, a base URI for relative references can be
+ embedded within the content itself so that it can be readily obtained
+ by a parser. This can be useful for descriptive documents, such as
+ tables of contents, which may be transmitted to others through
+ protocols other than their usual retrieval context (e.g., email or
+ USENET news).
+
+ It is beyond the scope of this specification to specify how, for each
+ media type, a base URI can be embedded. The appropriate syntax, when
+ available, is described by the data format specification associated
+ with each media type.
+
+5.1.2. Base URI from the Encapsulating Entity
+
+ If no base URI is embedded, the base URI is defined by the
+ representation's retrieval context. For a document that is enclosed
+ within another entity, such as a message or archive, the retrieval
+ context is that entity. Thus, the default base URI of a
+ representation is the base URI of the entity in which the
+ representation is encapsulated.
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 29]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ A mechanism for embedding a base URI within MIME container types
+ (e.g., the message and multipart types) is defined by MHTML
+ [RFC2557]. Protocols that do not use the MIME message header syntax,
+ but that do allow some form of tagged metadata to be included within
+ messages, may define their own syntax for defining a base URI as part
+ of a message.
+
+5.1.3. Base URI from the Retrieval URI
+
+ If no base URI is embedded and the representation is not encapsulated
+ within some other entity, then, if a URI was used to retrieve the
+ representation, that URI shall be considered the base URI. Note that
+ if the retrieval was the result of a redirected request, the last URI
+ used (i.e., the URI that resulted in the actual retrieval of the
+ representation) is the base URI.
+
+5.1.4. Default Base URI
+
+ If none of the conditions described above apply, then the base URI is
+ defined by the context of the application. As this definition is
+ necessarily application-dependent, failing to define a base URI by
+ using one of the other methods may result in the same content being
+ interpreted differently by different types of applications.
+
+ A sender of a representation containing relative references is
+ responsible for ensuring that a base URI for those references can be
+ established. Aside from fragment-only references, relative
+ references can only be used reliably in situations where the base URI
+ is well defined.
+
+5.2. Relative Resolution
+
+ This section describes an algorithm for converting a URI reference
+ that might be relative to a given base URI into the parsed components
+ of the reference's target. The components can then be recomposed, as
+ described in Section 5.3, to form the target URI. This algorithm
+ provides definitive results that can be used to test the output of
+ other implementations. Applications may implement relative reference
+ resolution by using some other algorithm, provided that the results
+ match what would be given by this one.
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 30]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+5.2.1. Pre-parse the Base URI
+
+ The base URI (Base) is established according to the procedure of
+ Section 5.1 and parsed into the five main components described in
+ Section 3. Note that only the scheme component is required to be
+ present in a base URI; the other components may be empty or
+ undefined. A component is undefined if its associated delimiter does
+ not appear in the URI reference; the path component is never
+ undefined, though it may be empty.
+
+ Normalization of the base URI, as described in Sections 6.2.2 and
+ 6.2.3, is optional. A URI reference must be transformed to its
+ target URI before it can be normalized.
+
+5.2.2. Transform References
+
+ For each URI reference (R), the following pseudocode describes an
+ algorithm for transforming R into its target URI (T):
+
+ -- The URI reference is parsed into the five URI components
+ --
+ (R.scheme, R.authority, R.path, R.query, R.fragment) = parse(R);
+
+ -- A non-strict parser may ignore a scheme in the reference
+ -- if it is identical to the base URI's scheme.
+ --
+ if ((not strict) and (R.scheme == Base.scheme)) then
+ undefine(R.scheme);
+ endif;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 31]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ if defined(R.scheme) then
+ T.scheme = R.scheme;
+ T.authority = R.authority;
+ T.path = remove_dot_segments(R.path);
+ T.query = R.query;
+ else
+ if defined(R.authority) then
+ T.authority = R.authority;
+ T.path = remove_dot_segments(R.path);
+ T.query = R.query;
+ else
+ if (R.path == "") then
+ T.path = Base.path;
+ if defined(R.query) then
+ T.query = R.query;
+ else
+ T.query = Base.query;
+ endif;
+ else
+ if (R.path starts-with "/") then
+ T.path = remove_dot_segments(R.path);
+ else
+ T.path = merge(Base.path, R.path);
+ T.path = remove_dot_segments(T.path);
+ endif;
+ T.query = R.query;
+ endif;
+ T.authority = Base.authority;
+ endif;
+ T.scheme = Base.scheme;
+ endif;
+
+ T.fragment = R.fragment;
+
+5.2.3. Merge Paths
+
+ The pseudocode above refers to a "merge" routine for merging a
+ relative-path reference with the path of the base URI. This is
+ accomplished as follows:
+
+ o If the base URI has a defined authority component and an empty
+ path, then return a string consisting of "/" concatenated with the
+ reference's path; otherwise,
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 32]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ o return a string consisting of the reference's path component
+ appended to all but the last segment of the base URI's path (i.e.,
+ excluding any characters after the right-most "/" in the base URI
+ path, or excluding the entire base URI path if it does not contain
+ any "/" characters).
+
+5.2.4. Remove Dot Segments
+
+ The pseudocode also refers to a "remove_dot_segments" routine for
+ interpreting and removing the special "." and ".." complete path
+ segments from a referenced path. This is done after the path is
+ extracted from a reference, whether or not the path was relative, in
+ order to remove any invalid or extraneous dot-segments prior to
+ forming the target URI. Although there are many ways to accomplish
+ this removal process, we describe a simple method using two string
+ buffers.
+
+ 1. The input buffer is initialized with the now-appended path
+ components and the output buffer is initialized to the empty
+ string.
+
+ 2. While the input buffer is not empty, loop as follows:
+
+ A. If the input buffer begins with a prefix of "../" or "./",
+ then remove that prefix from the input buffer; otherwise,
+
+ B. if the input buffer begins with a prefix of "/./" or "/.",
+ where "." is a complete path segment, then replace that
+ prefix with "/" in the input buffer; otherwise,
+
+ C. if the input buffer begins with a prefix of "/../" or "/..",
+ where ".." is a complete path segment, then replace that
+ prefix with "/" in the input buffer and remove the last
+ segment and its preceding "/" (if any) from the output
+ buffer; otherwise,
+
+ D. if the input buffer consists only of "." or "..", then remove
+ that from the input buffer; otherwise,
+
+ E. move the first path segment in the input buffer to the end of
+ the output buffer, including the initial "/" character (if
+ any) and any subsequent characters up to, but not including,
+ the next "/" character or the end of the input buffer.
+
+ 3. Finally, the output buffer is returned as the result of
+ remove_dot_segments.
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 33]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ Note that dot-segments are intended for use in URI references to
+ express an identifier relative to the hierarchy of names in the base
+ URI. The remove_dot_segments algorithm respects that hierarchy by
+ removing extra dot-segments rather than treat them as an error or
+ leaving them to be misinterpreted by dereference implementations.
+
+ The following illustrates how the above steps are applied for two
+ examples of merged paths, showing the state of the two buffers after
+ each step.
+
+ STEP OUTPUT BUFFER INPUT BUFFER
+
+ 1 : /a/b/c/./../../g
+ 2E: /a /b/c/./../../g
+ 2E: /a/b /c/./../../g
+ 2E: /a/b/c /./../../g
+ 2B: /a/b/c /../../g
+ 2C: /a/b /../g
+ 2C: /a /g
+ 2E: /a/g
+
+ STEP OUTPUT BUFFER INPUT BUFFER
+
+ 1 : mid/content=5/../6
+ 2E: mid /content=5/../6
+ 2E: mid/content=5 /../6
+ 2C: mid /6
+ 2E: mid/6
+
+ Some applications may find it more efficient to implement the
+ remove_dot_segments algorithm by using two segment stacks rather than
+ strings.
+
+ Note: Beware that some older, erroneous implementations will fail
+ to separate a reference's query component from its path component
+ prior to merging the base and reference paths, resulting in an
+ interoperability failure if the query component contains the
+ strings "/../" or "/./".
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 34]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+5.3. Component Recomposition
+
+ Parsed URI components can be recomposed to obtain the corresponding
+ URI reference string. Using pseudocode, this would be:
+
+ result = ""
+
+ if defined(scheme) then
+ append scheme to result;
+ append ":" to result;
+ endif;
+
+ if defined(authority) then
+ append "//" to result;
+ append authority to result;
+ endif;
+
+ append path to result;
+
+ if defined(query) then
+ append "?" to result;
+ append query to result;
+ endif;
+
+ if defined(fragment) then
+ append "#" to result;
+ append fragment to result;
+ endif;
+
+ return result;
+
+ Note that we are careful to preserve the distinction between a
+ component that is undefined, meaning that its separator was not
+ present in the reference, and a component that is empty, meaning that
+ the separator was present and was immediately followed by the next
+ component separator or the end of the reference.
+
+5.4. Reference Resolution Examples
+
+ Within a representation with a well defined base URI of
+
+ http://a/b/c/d;p?q
+
+ a relative reference is transformed to its target URI as follows.
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 35]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+5.4.1. Normal Examples
+
+ "g:h" = "g:h"
+ "g" = "http://a/b/c/g"
+ "./g" = "http://a/b/c/g"
+ "g/" = "http://a/b/c/g/"
+ "/g" = "http://a/g"
+ "//g" = "http://g"
+ "?y" = "http://a/b/c/d;p?y"
+ "g?y" = "http://a/b/c/g?y"
+ "#s" = "http://a/b/c/d;p?q#s"
+ "g#s" = "http://a/b/c/g#s"
+ "g?y#s" = "http://a/b/c/g?y#s"
+ ";x" = "http://a/b/c/;x"
+ "g;x" = "http://a/b/c/g;x"
+ "g;x?y#s" = "http://a/b/c/g;x?y#s"
+ "" = "http://a/b/c/d;p?q"
+ "." = "http://a/b/c/"
+ "./" = "http://a/b/c/"
+ ".." = "http://a/b/"
+ "../" = "http://a/b/"
+ "../g" = "http://a/b/g"
+ "../.." = "http://a/"
+ "../../" = "http://a/"
+ "../../g" = "http://a/g"
+
+5.4.2. Abnormal Examples
+
+ Although the following abnormal examples are unlikely to occur in
+ normal practice, all URI parsers should be capable of resolving them
+ consistently. Each example uses the same base as that above.
+
+ Parsers must be careful in handling cases where there are more ".."
+ segments in a relative-path reference than there are hierarchical
+ levels in the base URI's path. Note that the ".." syntax cannot be
+ used to change the authority component of a URI.
+
+ "../../../g" = "http://a/g"
+ "../../../../g" = "http://a/g"
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 36]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ Similarly, parsers must remove the dot-segments "." and ".." when
+ they are complete components of a path, but not when they are only
+ part of a segment.
+
+ "/./g" = "http://a/g"
+ "/../g" = "http://a/g"
+ "g." = "http://a/b/c/g."
+ ".g" = "http://a/b/c/.g"
+ "g.." = "http://a/b/c/g.."
+ "..g" = "http://a/b/c/..g"
+
+ Less likely are cases where the relative reference uses unnecessary
+ or nonsensical forms of the "." and ".." complete path segments.
+
+ "./../g" = "http://a/b/g"
+ "./g/." = "http://a/b/c/g/"
+ "g/./h" = "http://a/b/c/g/h"
+ "g/../h" = "http://a/b/c/h"
+ "g;x=1/./y" = "http://a/b/c/g;x=1/y"
+ "g;x=1/../y" = "http://a/b/c/y"
+
+ Some applications fail to separate the reference's query and/or
+ fragment components from the path component before merging it with
+ the base path and removing dot-segments. This error is rarely
+ noticed, as typical usage of a fragment never includes the hierarchy
+ ("/") character and the query component is not normally used within
+ relative references.
+
+ "g?y/./x" = "http://a/b/c/g?y/./x"
+ "g?y/../x" = "http://a/b/c/g?y/../x"
+ "g#s/./x" = "http://a/b/c/g#s/./x"
+ "g#s/../x" = "http://a/b/c/g#s/../x"
+
+ Some parsers allow the scheme name to be present in a relative
+ reference if it is the same as the base URI scheme. This is
+ considered to be a loophole in prior specifications of partial URI
+ [RFC1630]. Its use should be avoided but is allowed for backward
+ compatibility.
+
+ "http:g" = "http:g" ; for strict parsers
+ / "http://a/b/c/g" ; for backward compatibility
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 37]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+6. Normalization and Comparison
+
+ One of the most common operations on URIs is simple comparison:
+ determining whether two URIs are equivalent without using the URIs to
+ access their respective resource(s). A comparison is performed every
+ time a response cache is accessed, a browser checks its history to
+ color a link, or an XML parser processes tags within a namespace.
+ Extensive normalization prior to comparison of URIs is often used by
+ spiders and indexing engines to prune a search space or to reduce
+ duplication of request actions and response storage.
+
+ URI comparison is performed for some particular purpose. Protocols
+ or implementations that compare URIs for different purposes will
+ often be subject to differing design trade-offs in regards to how
+ much effort should be spent in reducing aliased identifiers. This
+ section describes various methods that may be used to compare URIs,
+ the trade-offs between them, and the types of applications that might
+ use them.
+
+6.1. Equivalence
+
+ Because URIs exist to identify resources, presumably they should be
+ considered equivalent when they identify the same resource. However,
+ this definition of equivalence is not of much practical use, as there
+ is no way for an implementation to compare two resources unless it
+ has full knowledge or control of them. For this reason,
+ determination of equivalence or difference of URIs is based on string
+ comparison, perhaps augmented by reference to additional rules
+ provided by URI scheme definitions. We use the terms "different" and
+ "equivalent" to describe the possible outcomes of such comparisons,
+ but there are many application-dependent versions of equivalence.
+
+ Even though it is possible to determine that two URIs are equivalent,
+ URI comparison is not sufficient to determine whether two URIs
+ identify different resources. For example, an owner of two different
+ domain names could decide to serve the same resource from both,
+ resulting in two different URIs. Therefore, comparison methods are
+ designed to minimize false negatives while strictly avoiding false
+ positives.
+
+ In testing for equivalence, applications should not directly compare
+ relative references; the references should be converted to their
+ respective target URIs before comparison. When URIs are compared to
+ select (or avoid) a network action, such as retrieval of a
+ representation, fragment components (if any) should be excluded from
+ the comparison.
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 38]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+6.2. Comparison Ladder
+
+ A variety of methods are used in practice to test URI equivalence.
+ These methods fall into a range, distinguished by the amount of
+ processing required and the degree to which the probability of false
+ negatives is reduced. As noted above, false negatives cannot be
+ eliminated. In practice, their probability can be reduced, but this
+ reduction requires more processing and is not cost-effective for all
+ applications.
+
+ If this range of comparison practices is considered as a ladder, the
+ following discussion will climb the ladder, starting with practices
+ that are cheap but have a relatively higher chance of producing false
+ negatives, and proceeding to those that have higher computational
+ cost and lower risk of false negatives.
+
+6.2.1. Simple String Comparison
+
+ If two URIs, when considered as character strings, are identical,
+ then it is safe to conclude that they are equivalent. This type of
+ equivalence test has very low computational cost and is in wide use
+ in a variety of applications, particularly in the domain of parsing.
+
+ Testing strings for equivalence requires some basic precautions.
+ This procedure is often referred to as "bit-for-bit" or
+ "byte-for-byte" comparison, which is potentially misleading. Testing
+ strings for equality is normally based on pair comparison of the
+ characters that make up the strings, starting from the first and
+ proceeding until both strings are exhausted and all characters are
+ found to be equal, until a pair of characters compares unequal, or
+ until one of the strings is exhausted before the other.
+
+ This character comparison requires that each pair of characters be
+ put in comparable form. For example, should one URI be stored in a
+ byte array in EBCDIC encoding and the second in a Java String object
+ (UTF-16), bit-for-bit comparisons applied naively will produce
+ errors. It is better to speak of equality on a character-for-
+ character basis rather than on a byte-for-byte or bit-for-bit basis.
+ In practical terms, character-by-character comparisons should be done
+ codepoint-by-codepoint after conversion to a common character
+ encoding.
+
+ False negatives are caused by the production and use of URI aliases.
+ Unnecessary aliases can be reduced, regardless of the comparison
+ method, by consistently providing URI references in an already-
+ normalized form (i.e., a form identical to what would be produced
+ after normalization is applied, as described below).
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 39]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ Protocols and data formats often limit some URI comparisons to simple
+ string comparison, based on the theory that people and
+ implementations will, in their own best interest, be consistent in
+ providing URI references, or at least consistent enough to negate any
+ efficiency that might be obtained from further normalization.
+
+6.2.2. Syntax-Based Normalization
+
+ Implementations may use logic based on the definitions provided by
+ this specification to reduce the probability of false negatives.
+ This processing is moderately higher in cost than character-for-
+ character string comparison. For example, an application using this
+ approach could reasonably consider the following two URIs equivalent:
+
+ example://a/b/c/%7Bfoo%7D
+ eXAMPLE://a/./b/../b/%63/%7bfoo%7d
+
+ Web user agents, such as browsers, typically apply this type of URI
+ normalization when determining whether a cached response is
+ available. Syntax-based normalization includes such techniques as
+ case normalization, percent-encoding normalization, and removal of
+ dot-segments.
+
+6.2.2.1. Case Normalization
+
+ For all URIs, the hexadecimal digits within a percent-encoding
+ triplet (e.g., "%3a" versus "%3A") are case-insensitive and therefore
+ should be normalized to use uppercase letters for the digits A-F.
+
+ When a URI uses components of the generic syntax, the component
+ syntax equivalence rules always apply; namely, that the scheme and
+ host are case-insensitive and therefore should be normalized to
+ lowercase. For example, the URI <HTTP://www.EXAMPLE.com/> is
+ equivalent to <http://www.example.com/>. The other generic syntax
+ components are assumed to be case-sensitive unless specifically
+ defined otherwise by the scheme (see Section 6.2.3).
+
+6.2.2.2. Percent-Encoding Normalization
+
+ The percent-encoding mechanism (Section 2.1) is a frequent source of
+ variance among otherwise identical URIs. In addition to the case
+ normalization issue noted above, some URI producers percent-encode
+ octets that do not require percent-encoding, resulting in URIs that
+ are equivalent to their non-encoded counterparts. These URIs should
+ be normalized by decoding any percent-encoded octet that corresponds
+ to an unreserved character, as described in Section 2.3.
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 40]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+6.2.2.3. Path Segment Normalization
+
+ The complete path segments "." and ".." are intended only for use
+ within relative references (Section 4.1) and are removed as part of
+ the reference resolution process (Section 5.2). However, some
+ deployed implementations incorrectly assume that reference resolution
+ is not necessary when the reference is already a URI and thus fail to
+ remove dot-segments when they occur in non-relative paths. URI
+ normalizers should remove dot-segments by applying the
+ remove_dot_segments algorithm to the path, as described in
+ Section 5.2.4.
+
+6.2.3. Scheme-Based Normalization
+
+ The syntax and semantics of URIs vary from scheme to scheme, as
+ described by the defining specification for each scheme.
+ Implementations may use scheme-specific rules, at further processing
+ cost, to reduce the probability of false negatives. For example,
+ because the "http" scheme makes use of an authority component, has a
+ default port of "80", and defines an empty path to be equivalent to
+ "/", the following four URIs are equivalent:
+
+ http://example.com
+ http://example.com/
+ http://example.com:/
+ http://example.com:80/
+
+ In general, a URI that uses the generic syntax for authority with an
+ empty path should be normalized to a path of "/". Likewise, an
+ explicit ":port", for which the port is empty or the default for the
+ scheme, is equivalent to one where the port and its ":" delimiter are
+ elided and thus should be removed by scheme-based normalization. For
+ example, the second URI above is the normal form for the "http"
+ scheme.
+
+ Another case where normalization varies by scheme is in the handling
+ of an empty authority component or empty host subcomponent. For many
+ scheme specifications, an empty authority or host is considered an
+ error; for others, it is considered equivalent to "localhost" or the
+ end-user's host. When a scheme defines a default for authority and a
+ URI reference to that default is desired, the reference should be
+ normalized to an empty authority for the sake of uniformity, brevity,
+ and internationalization. If, however, either the userinfo or port
+ subcomponents are non-empty, then the host should be given explicitly
+ even if it matches the default.
+
+ Normalization should not remove delimiters when their associated
+ component is empty unless licensed to do so by the scheme
+
+
+
+Berners-Lee, et al. Standards Track [Page 41]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ specification. For example, the URI "http://example.com/?" cannot be
+ assumed to be equivalent to any of the examples above. Likewise, the
+ presence or absence of delimiters within a userinfo subcomponent is
+ usually significant to its interpretation. The fragment component is
+ not subject to any scheme-based normalization; thus, two URIs that
+ differ only by the suffix "#" are considered different regardless of
+ the scheme.
+
+ Some schemes define additional subcomponents that consist of case-
+ insensitive data, giving an implicit license to normalizers to
+ convert this data to a common case (e.g., all lowercase). For
+ example, URI schemes that define a subcomponent of path to contain an
+ Internet hostname, such as the "mailto" URI scheme, cause that
+ subcomponent to be case-insensitive and thus subject to case
+ normalization (e.g., "mailto:[email protected]" is equivalent to
+ "mailto:[email protected]", even though the generic syntax considers
+ the path component to be case-sensitive).
+
+ Other scheme-specific normalizations are possible.
+
+6.2.4. Protocol-Based Normalization
+
+ Substantial effort to reduce the incidence of false negatives is
+ often cost-effective for web spiders. Therefore, they implement even
+ more aggressive techniques in URI comparison. For example, if they
+ observe that a URI such as
+
+ http://example.com/data
+
+ redirects to a URI differing only in the trailing slash
+
+ http://example.com/data/
+
+ they will likely regard the two as equivalent in the future. This
+ kind of technique is only appropriate when equivalence is clearly
+ indicated by both the result of accessing the resources and the
+ common conventions of their scheme's dereference algorithm (in this
+ case, use of redirection by HTTP origin servers to avoid problems
+ with relative references).
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 42]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+7. Security Considerations
+
+ A URI does not in itself pose a security threat. However, as URIs
+ are often used to provide a compact set of instructions for access to
+ network resources, care must be taken to properly interpret the data
+ within a URI, to prevent that data from causing unintended access,
+ and to avoid including data that should not be revealed in plain
+ text.
+
+7.1. Reliability and Consistency
+
+ There is no guarantee that once a URI has been used to retrieve
+ information, the same information will be retrievable by that URI in
+ the future. Nor is there any guarantee that the information
+ retrievable via that URI in the future will be observably similar to
+ that retrieved in the past. The URI syntax does not constrain how a
+ given scheme or authority apportions its namespace or maintains it
+ over time. Such guarantees can only be obtained from the person(s)
+ controlling that namespace and the resource in question. A specific
+ URI scheme may define additional semantics, such as name persistence,
+ if those semantics are required of all naming authorities for that
+ scheme.
+
+7.2. Malicious Construction
+
+ It is sometimes possible to construct a URI so that an attempt to
+ perform a seemingly harmless, idempotent operation, such as the
+ retrieval of a representation, will in fact cause a possibly damaging
+ remote operation. The unsafe URI is typically constructed by
+ specifying a port number other than that reserved for the network
+ protocol in question. The client unwittingly contacts a site running
+ a different protocol service, and data within the URI contains
+ instructions that, when interpreted according to this other protocol,
+ cause an unexpected operation. A frequent example of such abuse has
+ been the use of a protocol-based scheme with a port component of
+ "25", thereby fooling user agent software into sending an unintended
+ or impersonating message via an SMTP server.
+
+ Applications should prevent dereference of a URI that specifies a TCP
+ port number within the "well-known port" range (0 - 1023) unless the
+ protocol being used to dereference that URI is compatible with the
+ protocol expected on that well-known port. Although IANA maintains a
+ registry of well-known ports, applications should make such
+ restrictions user-configurable to avoid preventing the deployment of
+ new services.
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 43]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ When a URI contains percent-encoded octets that match the delimiters
+ for a given resolution or dereference protocol (for example, CR and
+ LF characters for the TELNET protocol), these percent-encodings must
+ not be decoded before transmission across that protocol. Transfer of
+ the percent-encoding, which might violate the protocol, is less
+ harmful than allowing decoded octets to be interpreted as additional
+ operations or parameters, perhaps triggering an unexpected and
+ possibly harmful remote operation.
+
+7.3. Back-End Transcoding
+
+ When a URI is dereferenced, the data within it is often parsed by
+ both the user agent and one or more servers. In HTTP, for example, a
+ typical user agent will parse a URI into its five major components,
+ access the authority's server, and send it the data within the
+ authority, path, and query components. A typical server will take
+ that information, parse the path into segments and the query into
+ key/value pairs, and then invoke implementation-specific handlers to
+ respond to the request. As a result, a common security concern for
+ server implementations that handle a URI, either as a whole or split
+ into separate components, is proper interpretation of the octet data
+ represented by the characters and percent-encodings within that URI.
+
+ Percent-encoded octets must be decoded at some point during the
+ dereference process. Applications must split the URI into its
+ components and subcomponents prior to decoding the octets, as
+ otherwise the decoded octets might be mistaken for delimiters.
+ Security checks of the data within a URI should be applied after
+ decoding the octets. Note, however, that the "%00" percent-encoding
+ (NUL) may require special handling and should be rejected if the
+ application is not expecting to receive raw data within a component.
+
+ Special care should be taken when the URI path interpretation process
+ involves the use of a back-end file system or related system
+ functions. File systems typically assign an operational meaning to
+ special characters, such as the "/", "\", ":", "[", and "]"
+ characters, and to special device names like ".", "..", "...", "aux",
+ "lpt", etc. In some cases, merely testing for the existence of such
+ a name will cause the operating system to pause or invoke unrelated
+ system calls, leading to significant security concerns regarding
+ denial of service and unintended data transfer. It would be
+ impossible for this specification to list all such significant
+ characters and device names. Implementers should research the
+ reserved names and characters for the types of storage device that
+ may be attached to their applications and restrict the use of data
+ obtained from URI components accordingly.
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 44]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+7.4. Rare IP Address Formats
+
+ Although the URI syntax for IPv4address only allows the common
+ dotted-decimal form of IPv4 address literal, many implementations
+ that process URIs make use of platform-dependent system routines,
+ such as gethostbyname() and inet_aton(), to translate the string
+ literal to an actual IP address. Unfortunately, such system routines
+ often allow and process a much larger set of formats than those
+ described in Section 3.2.2.
+
+ For example, many implementations allow dotted forms of three
+ numbers, wherein the last part is interpreted as a 16-bit quantity
+ and placed in the right-most two bytes of the network address (e.g.,
+ a Class B network). Likewise, a dotted form of two numbers means
+ that the last part is interpreted as a 24-bit quantity and placed in
+ the right-most three bytes of the network address (Class A), and a
+ single number (without dots) is interpreted as a 32-bit quantity and
+ stored directly in the network address. Adding further to the
+ confusion, some implementations allow each dotted part to be
+ interpreted as decimal, octal, or hexadecimal, as specified in the C
+ language (i.e., a leading 0x or 0X implies hexadecimal; a leading 0
+ implies octal; otherwise, the number is interpreted as decimal).
+
+ These additional IP address formats are not allowed in the URI syntax
+ due to differences between platform implementations. However, they
+ can become a security concern if an application attempts to filter
+ access to resources based on the IP address in string literal format.
+ If this filtering is performed, literals should be converted to
+ numeric form and filtered based on the numeric value, and not on a
+ prefix or suffix of the string form.
+
+7.5. Sensitive Information
+
+ URI producers should not provide a URI that contains a username or
+ password that is intended to be secret. URIs are frequently
+ displayed by browsers, stored in clear text bookmarks, and logged by
+ user agent history and intermediary applications (proxies). A
+ password appearing within the userinfo component is deprecated and
+ should be considered an error (or simply ignored) except in those
+ rare cases where the 'password' parameter is intended to be public.
+
+7.6. Semantic Attacks
+
+ Because the userinfo subcomponent is rarely used and appears before
+ the host in the authority component, it can be used to construct a
+ URI intended to mislead a human user by appearing to identify one
+ (trusted) naming authority while actually identifying a different
+ authority hidden behind the noise. For example
+
+
+
+Berners-Lee, et al. Standards Track [Page 45]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ ftp://cnn.example.com&[email protected]/top_story.htm
+
+ might lead a human user to assume that the host is 'cnn.example.com',
+ whereas it is actually '10.0.0.1'. Note that a misleading userinfo
+ subcomponent could be much longer than the example above.
+
+ A misleading URI, such as that above, is an attack on the user's
+ preconceived notions about the meaning of a URI rather than an attack
+ on the software itself. User agents may be able to reduce the impact
+ of such attacks by distinguishing the various components of the URI
+ when they are rendered, such as by using a different color or tone to
+ render userinfo if any is present, though there is no panacea. More
+ information on URI-based semantic attacks can be found in [Siedzik].
+
+8. IANA Considerations
+
+ URI scheme names, as defined by <scheme> in Section 3.1, form a
+ registered namespace that is managed by IANA according to the
+ procedures defined in [BCP35]. No IANA actions are required by this
+ document.
+
+9. Acknowledgements
+
+ This specification is derived from RFC 2396 [RFC2396], RFC 1808
+ [RFC1808], and RFC 1738 [RFC1738]; the acknowledgements in those
+ documents still apply. It also incorporates the update (with
+ corrections) for IPv6 literals in the host syntax, as defined by
+ Robert M. Hinden, Brian E. Carpenter, and Larry Masinter in
+ [RFC2732]. In addition, contributions by Gisle Aas, Reese Anschultz,
+ Daniel Barclay, Tim Bray, Mike Brown, Rob Cameron, Jeremy Carroll,
+ Dan Connolly, Adam M. Costello, John Cowan, Jason Diamond, Martin
+ Duerst, Stefan Eissing, Clive D.W. Feather, Al Gilman, Tony Hammond,
+ Elliotte Harold, Pat Hayes, Henry Holtzman, Ian B. Jacobs, Michael
+ Kay, John C. Klensin, Graham Klyne, Dan Kohn, Bruce Lilly, Andrew
+ Main, Dave McAlpin, Ira McDonald, Michael Mealling, Ray Merkert,
+ Stephen Pollei, Julian Reschke, Tomas Rokicki, Miles Sabin, Kai
+ Schaetzl, Mark Thomson, Ronald Tschalaer, Norm Walsh, Marc Warne,
+ Stuart Williams, and Henry Zongaro are gratefully acknowledged.
+
+10. References
+
+10.1. Normative References
+
+ [ASCII] American National Standards Institute, "Coded Character
+ Set -- 7-bit American Standard Code for Information
+ Interchange", ANSI X3.4, 1986.
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 46]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ [RFC2234] Crocker, D. and P. Overell, "Augmented BNF for Syntax
+ Specifications: ABNF", RFC 2234, November 1997.
+
+ [STD63] Yergeau, F., "UTF-8, a transformation format of
+ ISO 10646", STD 63, RFC 3629, November 2003.
+
+ [UCS] International Organization for Standardization,
+ "Information Technology - Universal Multiple-Octet Coded
+ Character Set (UCS)", ISO/IEC 10646:2003, December 2003.
+
+10.2. Informative References
+
+ [BCP19] Freed, N. and J. Postel, "IANA Charset Registration
+ Procedures", BCP 19, RFC 2978, October 2000.
+
+ [BCP35] Petke, R. and I. King, "Registration Procedures for URL
+ Scheme Names", BCP 35, RFC 2717, November 1999.
+
+ [RFC0952] Harrenstien, K., Stahl, M., and E. Feinler, "DoD Internet
+ host table specification", RFC 952, October 1985.
+
+ [RFC1034] Mockapetris, P., "Domain names - concepts and facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC1123] Braden, R., "Requirements for Internet Hosts - Application
+ and Support", STD 3, RFC 1123, October 1989.
+
+ [RFC1535] Gavron, E., "A Security Problem and Proposed Correction
+ With Widely Deployed DNS Software", RFC 1535,
+ October 1993.
+
+ [RFC1630] Berners-Lee, T., "Universal Resource Identifiers in WWW: A
+ Unifying Syntax for the Expression of Names and Addresses
+ of Objects on the Network as used in the World-Wide Web",
+ RFC 1630, June 1994.
+
+ [RFC1736] Kunze, J., "Functional Recommendations for Internet
+ Resource Locators", RFC 1736, February 1995.
+
+ [RFC1737] Sollins, K. and L. Masinter, "Functional Requirements for
+ Uniform Resource Names", RFC 1737, December 1994.
+
+ [RFC1738] Berners-Lee, T., Masinter, L., and M. McCahill, "Uniform
+ Resource Locators (URL)", RFC 1738, December 1994.
+
+ [RFC1808] Fielding, R., "Relative Uniform Resource Locators",
+ RFC 1808, June 1995.
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 47]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ [RFC2046] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part Two: Media Types", RFC 2046,
+ November 1996.
+
+ [RFC2141] Moats, R., "URN Syntax", RFC 2141, May 1997.
+
+ [RFC2396] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
+ Resource Identifiers (URI): Generic Syntax", RFC 2396,
+ August 1998.
+
+ [RFC2518] Goland, Y., Whitehead, E., Faizi, A., Carter, S., and D.
+ Jensen, "HTTP Extensions for Distributed Authoring --
+ WEBDAV", RFC 2518, February 1999.
+
+ [RFC2557] Palme, J., Hopmann, A., and N. Shelness, "MIME
+ Encapsulation of Aggregate Documents, such as HTML
+ (MHTML)", RFC 2557, March 1999.
+
+ [RFC2718] Masinter, L., Alvestrand, H., Zigmond, D., and R. Petke,
+ "Guidelines for new URL Schemes", RFC 2718, November 1999.
+
+ [RFC2732] Hinden, R., Carpenter, B., and L. Masinter, "Format for
+ Literal IPv6 Addresses in URL's", RFC 2732, December 1999.
+
+ [RFC3305] Mealling, M. and R. Denenberg, "Report from the Joint
+ W3C/IETF URI Planning Interest Group: Uniform Resource
+ Identifiers (URIs), URLs, and Uniform Resource Names
+ (URNs): Clarifications and Recommendations", RFC 3305,
+ August 2002.
+
+ [RFC3490] Faltstrom, P., Hoffman, P., and A. Costello,
+ "Internationalizing Domain Names in Applications (IDNA)",
+ RFC 3490, March 2003.
+
+ [RFC3513] Hinden, R. and S. Deering, "Internet Protocol Version 6
+ (IPv6) Addressing Architecture", RFC 3513, April 2003.
+
+ [Siedzik] Siedzik, R., "Semantic Attacks: What's in a URL?",
+ April 2001, <http://www.giac.org/practical/gsec/
+ Richard_Siedzik_GSEC.pdf>.
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 48]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+Appendix A. Collected ABNF for URI
+
+ URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
+
+ hier-part = "//" authority path-abempty
+ / path-absolute
+ / path-rootless
+ / path-empty
+
+ URI-reference = URI / relative-ref
+
+ absolute-URI = scheme ":" hier-part [ "?" query ]
+
+ relative-ref = relative-part [ "?" query ] [ "#" fragment ]
+
+ relative-part = "//" authority path-abempty
+ / path-absolute
+ / path-noscheme
+ / path-empty
+
+ scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+
+ authority = [ userinfo "@" ] host [ ":" port ]
+ userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
+ host = IP-literal / IPv4address / reg-name
+ port = *DIGIT
+
+ IP-literal = "[" ( IPv6address / IPvFuture ) "]"
+
+ IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
+
+ IPv6address = 6( h16 ":" ) ls32
+ / "::" 5( h16 ":" ) ls32
+ / [ h16 ] "::" 4( h16 ":" ) ls32
+ / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
+ / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
+ / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
+ / [ *4( h16 ":" ) h16 ] "::" ls32
+ / [ *5( h16 ":" ) h16 ] "::" h16
+ / [ *6( h16 ":" ) h16 ] "::"
+
+ h16 = 1*4HEXDIG
+ ls32 = ( h16 ":" h16 ) / IPv4address
+ IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 49]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ dec-octet = DIGIT ; 0-9
+ / %x31-39 DIGIT ; 10-99
+ / "1" 2DIGIT ; 100-199
+ / "2" %x30-34 DIGIT ; 200-249
+ / "25" %x30-35 ; 250-255
+
+ reg-name = *( unreserved / pct-encoded / sub-delims )
+
+ path = path-abempty ; begins with "/" or is empty
+ / path-absolute ; begins with "/" but not "//"
+ / path-noscheme ; begins with a non-colon segment
+ / path-rootless ; begins with a segment
+ / path-empty ; zero characters
+
+ path-abempty = *( "/" segment )
+ path-absolute = "/" [ segment-nz *( "/" segment ) ]
+ path-noscheme = segment-nz-nc *( "/" segment )
+ path-rootless = segment-nz *( "/" segment )
+ path-empty = 0<pchar>
+
+ segment = *pchar
+ segment-nz = 1*pchar
+ segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
+ ; non-zero-length segment without any colon ":"
+
+ pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
+
+ query = *( pchar / "/" / "?" )
+
+ fragment = *( pchar / "/" / "?" )
+
+ pct-encoded = "%" HEXDIG HEXDIG
+
+ unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+ reserved = gen-delims / sub-delims
+ gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+ sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+ / "*" / "+" / "," / ";" / "="
+
+Appendix B. Parsing a URI Reference with a Regular Expression
+
+ As the "first-match-wins" algorithm is identical to the "greedy"
+ disambiguation method used by POSIX regular expressions, it is
+ natural and commonplace to use a regular expression for parsing the
+ potential five components of a URI reference.
+
+ The following line is the regular expression for breaking-down a
+ well-formed URI reference into its components.
+
+
+
+Berners-Lee, et al. Standards Track [Page 50]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
+ 12 3 4 5 6 7 8 9
+
+ The numbers in the second line above are only to assist readability;
+ they indicate the reference points for each subexpression (i.e., each
+ paired parenthesis). We refer to the value matched for subexpression
+ <n> as $<n>. For example, matching the above expression to
+
+ http://www.ics.uci.edu/pub/ietf/uri/#Related
+
+ results in the following subexpression matches:
+
+ $1 = http:
+ $2 = http
+ $3 = //www.ics.uci.edu
+ $4 = www.ics.uci.edu
+ $5 = /pub/ietf/uri/
+ $6 = <undefined>
+ $7 = <undefined>
+ $8 = #Related
+ $9 = Related
+
+ where <undefined> indicates that the component is not present, as is
+ the case for the query component in the above example. Therefore, we
+ can determine the value of the five components as
+
+ scheme = $2
+ authority = $4
+ path = $5
+ query = $7
+ fragment = $9
+
+ Going in the opposite direction, we can recreate a URI reference from
+ its components by using the algorithm of Section 5.3.
+
+Appendix C. Delimiting a URI in Context
+
+ URIs are often transmitted through formats that do not provide a
+ clear context for their interpretation. For example, there are many
+ occasions when a URI is included in plain text; examples include text
+ sent in email, USENET news, and on printed paper. In such cases, it
+ is important to be able to delimit the URI from the rest of the text,
+ and in particular from punctuation marks that might be mistaken for
+ part of the URI.
+
+ In practice, URIs are delimited in a variety of ways, but usually
+ within double-quotes "http://example.com/", angle brackets
+ <http://example.com/>, or just by using whitespace:
+
+
+
+Berners-Lee, et al. Standards Track [Page 51]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ http://example.com/
+
+ These wrappers do not form part of the URI.
+
+ In some cases, extra whitespace (spaces, line-breaks, tabs, etc.) may
+ have to be added to break a long URI across lines. The whitespace
+ should be ignored when the URI is extracted.
+
+ No whitespace should be introduced after a hyphen ("-") character.
+ Because some typesetters and printers may (erroneously) introduce a
+ hyphen at the end of line when breaking it, the interpreter of a URI
+ containing a line break immediately after a hyphen should ignore all
+ whitespace around the line break and should be aware that the hyphen
+ may or may not actually be part of the URI.
+
+ Using <> angle brackets around each URI is especially recommended as
+ a delimiting style for a reference that contains embedded whitespace.
+
+ The prefix "URL:" (with or without a trailing space) was formerly
+ recommended as a way to help distinguish a URI from other bracketed
+ designators, though it is not commonly used in practice and is no
+ longer recommended.
+
+ For robustness, software that accepts user-typed URI should attempt
+ to recognize and strip both delimiters and embedded whitespace.
+
+ For example, the text
+
+ Yes, Jim, I found it under "http://www.w3.org/Addressing/",
+ but you can probably pick it up from <ftp://foo.example.
+ com/rfc/>. Note the warning in <http://www.ics.uci.edu/pub/
+ ietf/uri/historical.html#WARNING>.
+
+ contains the URI references
+
+ http://www.w3.org/Addressing/
+ ftp://foo.example.com/rfc/
+ http://www.ics.uci.edu/pub/ietf/uri/historical.html#WARNING
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 52]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+Appendix D. Changes from RFC 2396
+
+D.1. Additions
+
+ An ABNF rule for URI has been introduced to correspond to one common
+ usage of the term: an absolute URI with optional fragment.
+
+ IPv6 (and later) literals have been added to the list of possible
+ identifiers for the host portion of an authority component, as
+ described by [RFC2732], with the addition of "[" and "]" to the
+ reserved set and a version flag to anticipate future versions of IP
+ literals. Square brackets are now specified as reserved within the
+ authority component and are not allowed outside their use as
+ delimiters for an IP literal within host. In order to make this
+ change without changing the technical definition of the path, query,
+ and fragment components, those rules were redefined to directly
+ specify the characters allowed.
+
+ As [RFC2732] defers to [RFC3513] for definition of an IPv6 literal
+ address, which, unfortunately, lacks an ABNF description of
+ IPv6address, we created a new ABNF rule for IPv6address that matches
+ the text representations defined by Section 2.2 of [RFC3513].
+ Likewise, the definition of IPv4address has been improved in order to
+ limit each decimal octet to the range 0-255.
+
+ Section 6, on URI normalization and comparison, has been completely
+ rewritten and extended by using input from Tim Bray and discussion
+ within the W3C Technical Architecture Group.
+
+D.2. Modifications
+
+ The ad-hoc BNF syntax of RFC 2396 has been replaced with the ABNF of
+ [RFC2234]. This change required all rule names that formerly
+ included underscore characters to be renamed with a dash instead. In
+ addition, a number of syntax rules have been eliminated or simplified
+ to make the overall grammar more comprehensible. Specifications that
+ refer to the obsolete grammar rules may be understood by replacing
+ those rules according to the following table:
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 53]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ +----------------+--------------------------------------------------+
+ | obsolete rule | translation |
+ +----------------+--------------------------------------------------+
+ | absoluteURI | absolute-URI |
+ | relativeURI | relative-part [ "?" query ] |
+ | hier_part | ( "//" authority path-abempty / |
+ | | path-absolute ) [ "?" query ] |
+ | | |
+ | opaque_part | path-rootless [ "?" query ] |
+ | net_path | "//" authority path-abempty |
+ | abs_path | path-absolute |
+ | rel_path | path-rootless |
+ | rel_segment | segment-nz-nc |
+ | reg_name | reg-name |
+ | server | authority |
+ | hostport | host [ ":" port ] |
+ | hostname | reg-name |
+ | path_segments | path-abempty |
+ | param | *<pchar excluding ";"> |
+ | | |
+ | uric | unreserved / pct-encoded / ";" / "?" / ":" |
+ | | / "@" / "&" / "=" / "+" / "$" / "," / "/" |
+ | | |
+ | uric_no_slash | unreserved / pct-encoded / ";" / "?" / ":" |
+ | | / "@" / "&" / "=" / "+" / "$" / "," |
+ | | |
+ | mark | "-" / "_" / "." / "!" / "~" / "*" / "'" |
+ | | / "(" / ")" |
+ | | |
+ | escaped | pct-encoded |
+ | hex | HEXDIG |
+ | alphanum | ALPHA / DIGIT |
+ +----------------+--------------------------------------------------+
+
+ Use of the above obsolete rules for the definition of scheme-specific
+ syntax is deprecated.
+
+ Section 2, on characters, has been rewritten to explain what
+ characters are reserved, when they are reserved, and why they are
+ reserved, even when they are not used as delimiters by the generic
+ syntax. The mark characters that are typically unsafe to decode,
+ including the exclamation mark ("!"), asterisk ("*"), single-quote
+ ("'"), and open and close parentheses ("(" and ")"), have been moved
+ to the reserved set in order to clarify the distinction between
+ reserved and unreserved and, hopefully, to answer the most common
+ question of scheme designers. Likewise, the section on
+ percent-encoded characters has been rewritten, and URI normalizers
+ are now given license to decode any percent-encoded octets
+
+
+
+Berners-Lee, et al. Standards Track [Page 54]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ corresponding to unreserved characters. In general, the terms
+ "escaped" and "unescaped" have been replaced with "percent-encoded"
+ and "decoded", respectively, to reduce confusion with other forms of
+ escape mechanisms.
+
+ The ABNF for URI and URI-reference has been redesigned to make them
+ more friendly to LALR parsers and to reduce complexity. As a result,
+ the layout form of syntax description has been removed, along with
+ the uric, uric_no_slash, opaque_part, net_path, abs_path, rel_path,
+ path_segments, rel_segment, and mark rules. All references to
+ "opaque" URIs have been replaced with a better description of how the
+ path component may be opaque to hierarchy. The relativeURI rule has
+ been replaced with relative-ref to avoid unnecessary confusion over
+ whether they are a subset of URI. The ambiguity regarding the
+ parsing of URI-reference as a URI or a relative-ref with a colon in
+ the first segment has been eliminated through the use of five
+ separate path matching rules.
+
+ The fragment identifier has been moved back into the section on
+ generic syntax components and within the URI and relative-ref rules,
+ though it remains excluded from absolute-URI. The number sign ("#")
+ character has been moved back to the reserved set as a result of
+ reintegrating the fragment syntax.
+
+ The ABNF has been corrected to allow the path component to be empty.
+ This also allows an absolute-URI to consist of nothing after the
+ "scheme:", as is present in practice with the "dav:" namespace
+ [RFC2518] and with the "about:" scheme used internally by many WWW
+ browser implementations. The ambiguity regarding the boundary
+ between authority and path has been eliminated through the use of
+ five separate path matching rules.
+
+ Registry-based naming authorities that use the generic syntax are now
+ defined within the host rule. This change allows current
+ implementations, where whatever name provided is simply fed to the
+ local name resolution mechanism, to be consistent with the
+ specification. It also removes the need to re-specify DNS name
+ formats here. Furthermore, it allows the host component to contain
+ percent-encoded octets, which is necessary to enable
+ internationalized domain names to be provided in URIs, processed in
+ their native character encodings at the application layers above URI
+ processing, and passed to an IDNA library as a registered name in the
+ UTF-8 character encoding. The server, hostport, hostname,
+ domainlabel, toplabel, and alphanum rules have been removed.
+
+ The resolving relative references algorithm of [RFC2396] has been
+ rewritten with pseudocode for this revision to improve clarity and
+ fix the following issues:
+
+
+
+Berners-Lee, et al. Standards Track [Page 55]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ o [RFC2396] section 5.2, step 6a, failed to account for a base URI
+ with no path.
+
+ o Restored the behavior of [RFC1808] where, if the reference
+ contains an empty path and a defined query component, the target
+ URI inherits the base URI's path component.
+
+ o The determination of whether a URI reference is a same-document
+ reference has been decoupled from the URI parser, simplifying the
+ URI processing interface within applications in a way consistent
+ with the internal architecture of deployed URI processing
+ implementations. The determination is now based on comparison to
+ the base URI after transforming a reference to absolute form,
+ rather than on the format of the reference itself. This change
+ may result in more references being considered "same-document"
+ under this specification than there would be under the rules given
+ in RFC 2396, especially when normalization is used to reduce
+ aliases. However, it does not change the status of existing
+ same-document references.
+
+ o Separated the path merge routine into two routines: merge, for
+ describing combination of the base URI path with a relative-path
+ reference, and remove_dot_segments, for describing how to remove
+ the special "." and ".." segments from a composed path. The
+ remove_dot_segments algorithm is now applied to all URI reference
+ paths in order to match common implementations and to improve the
+ normalization of URIs in practice. This change only impacts the
+ parsing of abnormal references and same-scheme references wherein
+ the base URI has a non-hierarchical path.
+
+Index
+
+ A
+ ABNF 11
+ absolute 27
+ absolute-path 26
+ absolute-URI 27
+ access 9
+ authority 17, 18
+
+ B
+ base URI 28
+
+ C
+ character encoding 4
+ character 4
+ characters 8, 11
+ coded character set 4
+
+
+
+Berners-Lee, et al. Standards Track [Page 56]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ D
+ dec-octet 20
+ dereference 9
+ dot-segments 23
+
+ F
+ fragment 16, 24
+
+ G
+ gen-delims 13
+ generic syntax 6
+
+ H
+ h16 20
+ hier-part 16
+ hierarchical 10
+ host 18
+
+ I
+ identifier 5
+ IP-literal 19
+ IPv4 20
+ IPv4address 19, 20
+ IPv6 19
+ IPv6address 19, 20
+ IPvFuture 19
+
+ L
+ locator 7
+ ls32 20
+
+ M
+ merge 32
+
+ N
+ name 7
+ network-path 26
+
+ P
+ path 16, 22, 26
+ path-abempty 22
+ path-absolute 22
+ path-empty 22
+ path-noscheme 22
+ path-rootless 22
+ path-abempty 16, 22, 26
+ path-absolute 16, 22, 26
+ path-empty 16, 22, 26
+
+
+
+Berners-Lee, et al. Standards Track [Page 57]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ path-rootless 16, 22
+ pchar 23
+ pct-encoded 12
+ percent-encoding 12
+ port 22
+
+ Q
+ query 16, 23
+
+ R
+ reg-name 21
+ registered name 20
+ relative 10, 28
+ relative-path 26
+ relative-ref 26
+ remove_dot_segments 33
+ representation 9
+ reserved 12
+ resolution 9, 28
+ resource 5
+ retrieval 9
+
+ S
+ same-document 27
+ sameness 9
+ scheme 16, 17
+ segment 22, 23
+ segment-nz 23
+ segment-nz-nc 23
+ sub-delims 13
+ suffix 27
+
+ T
+ transcription 8
+
+ U
+ uniform 4
+ unreserved 13
+ URI grammar
+ absolute-URI 27
+ ALPHA 11
+ authority 18
+ CR 11
+ dec-octet 20
+ DIGIT 11
+ DQUOTE 11
+ fragment 24
+ gen-delims 13
+
+
+
+Berners-Lee, et al. Standards Track [Page 58]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ h16 20
+ HEXDIG 11
+ hier-part 16
+ host 19
+ IP-literal 19
+ IPv4address 20
+ IPv6address 20
+ IPvFuture 19
+ LF 11
+ ls32 20
+ OCTET 11
+ path 22
+ path-abempty 22
+ path-absolute 22
+ path-empty 22
+ path-noscheme 22
+ path-rootless 22
+ pchar 23
+ pct-encoded 12
+ port 22
+ query 24
+ reg-name 21
+ relative-ref 26
+ reserved 13
+ scheme 17
+ segment 23
+ segment-nz 23
+ segment-nz-nc 23
+ SP 11
+ sub-delims 13
+ unreserved 13
+ URI 16
+ URI-reference 25
+ userinfo 18
+ URI 16
+ URI-reference 25
+ URL 7
+ URN 7
+ userinfo 18
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 59]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+Authors' Addresses
+
+ Tim Berners-Lee
+ World Wide Web Consortium
+ Massachusetts Institute of Technology
+ 77 Massachusetts Avenue
+ Cambridge, MA 02139
+ USA
+
+ Phone: +1-617-253-5702
+ Fax: +1-617-258-5999
+ URI: http://www.w3.org/People/Berners-Lee/
+
+
+ Roy T. Fielding
+ Day Software
+ 5251 California Ave., Suite 110
+ Irvine, CA 92617
+ USA
+
+ Phone: +1-949-679-2960
+ Fax: +1-949-679-2972
+ URI: http://roy.gbiv.com/
+
+
+ Larry Masinter
+ Adobe Systems Incorporated
+ 345 Park Ave
+ San Jose, CA 95110
+ USA
+
+ Phone: +1-408-536-3024
+ URI: http://larry.masinter.net/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 60]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2005).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the IETF's procedures with respect to rights in IETF Documents can
+ be found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at ietf-
+
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 61]
+
diff --git a/lib/inets/doc/src/Makefile b/lib/inets/doc/src/Makefile
index e4cb0c4e48..82f2a5829f 100644
--- a/lib/inets/doc/src/Makefile
+++ b/lib/inets/doc/src/Makefile
@@ -26,16 +26,6 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
include ../../vsn.mk
VSN=$(INETS_VSN)
-
-# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-
# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
@@ -98,37 +88,10 @@ EXTRA_FILES = summary.html.src \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = \
- $(XML_PART_FILES:%.xml=%.tex) \
- $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_REF6_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-TOP_HTML_FILES =
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -141,8 +104,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
ldocs: local_docs
@@ -156,33 +117,6 @@ html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs: clean_html clean_man clean_pdf
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES) $(TOP_HTML_FILES) gifs
-
-clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
-
-clean: clean_tex clean_html clean_man
- rm -f *.xmls_output *.xmls_errs
- rm -f $(TOP_PDF_FILE)
- rm -f errs core *~
-endif
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -204,10 +138,7 @@ clean_man:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
- @echo "release_docs_spec(docs) when DOCSUPPORT=$DOCSUPPORT"
$(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
$(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
$(INSTALL_DIR) $(RELSYSDIR)/doc/html
@@ -215,33 +146,6 @@ release_docs_spec: docs
$(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
$(INSTALL_DIR) $(RELEASE_PATH)/man/man3
$(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- @echo "release_docs_spec(pdf)"
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- @echo "release_docs_spec(ps)"
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- @echo "release_docs_spec(docs)"
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-
-endif
-endif
-
-endif
release_spec:
diff --git a/lib/inets/doc/src/ftp.xml b/lib/inets/doc/src/ftp.xml
index ca902d8d9d..f8f11ec705 100644
--- a/lib/inets/doc/src/ftp.xml
+++ b/lib/inets/doc/src/ftp.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd">
<erlref>
<header>
<copyright>
- <year>1997</year><year>2010</year>
+ <year>1997</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -141,11 +141,21 @@
<tag>{timeout, Timeout}</tag>
<item>
<marker id="timeout"></marker>
- <p>Timeout = <c>integer() >= 0</c> </p>
+ <p>Timeout = <c>non_neg_integer()</c> </p>
<p>Connection timeout. </p>
<p>Default is 60000 (milliseconds). </p>
</item>
+ <tag>{dtimeout, DTimeout}</tag>
+ <item>
+ <marker id="dtimeout"></marker>
+ <p>DTimeout = <c>non_neg_integer() | infinity</c> </p>
+ <p>Data Connect timeout.
+ The time the client will wait for the server to connect to the
+ data socket. </p>
+ <p>Default is infinity. </p>
+ </item>
+
<tag>{progress, Progress}</tag>
<item>
<marker id="progress"></marker>
@@ -542,11 +552,12 @@
<v>verbose() = boolean() (defaults to false)</v>
<v>debug() = disable | debug | trace (defaults to disable)</v>
<!-- <v>open_options() = [open_option()]</v> -->
- <v>open_option() = {ipfamily, ipfamily()} | {port, port()} | {mode, mode()} | {timeout, timeout()} | {progress, progress()}</v>
+ <v>open_option() = {ipfamily, ipfamily()} | {port, port()} | {mode, mode()} | {timeout, timeout()} | {dtimeout, dtimeout()} | {progress, progress()}</v>
<v>ipfamily() = inet | inet6 | inet6fb4 (defaults to inet)</v>
<v>port() = integer() > 0 (defaults to 21)</v>
<v>mode() = active | passive (defaults to passive)</v>
- <v>timeout() = integer() >= 0 (defaults to 60000 milliseconds)</v>
+ <v>timeout() = integer() > 0 (defaults to 60000 milliseconds)</v>
+ <v>dtimeout() = integer() > 0 | infinity (defaults to infinity)</v>
<v>pogress() = ignore | {module(), function(), initial_data()} (defaults to ignore)</v>
<v>module() = atom()</v>
<v>function() = atom()</v>
diff --git a/lib/inets/doc/src/http_server.xml b/lib/inets/doc/src/http_server.xml
index 599a939913..f29b505bc7 100644
--- a/lib/inets/doc/src/http_server.xml
+++ b/lib/inets/doc/src/http_server.xml
@@ -406,7 +406,7 @@ http://your.server.org/***/Module[:/]Function(?QueryString|/PathInfo)
phase instead of first generating the whole web page and
then sending it to the client. The option to implement a
function with arity two is only kept for
- backwardcompatibilty reasons.
+ backwards compatibility reasons.
See <seealso marker="mod_esi">mod_esi(3)</seealso> for
implementation details of the esi callback function.</p>
</section>
diff --git a/lib/inets/doc/src/httpc.xml b/lib/inets/doc/src/httpc.xml
index d1671ac9bd..b1f964ae69 100644
--- a/lib/inets/doc/src/httpc.xml
+++ b/lib/inets/doc/src/httpc.xml
@@ -28,8 +28,10 @@
<date></date>
<rev></rev>
</header>
+
<module>httpc</module>
<modulesummary>An HTTP/1.1 client </modulesummary>
+
<description>
<p>This module provides the API to a HTTP/1.1 compatible client according
to RFC 2616, caching is currently not supported.</p>
@@ -167,7 +169,6 @@ filename() = string()
<v>http_option() = {timeout, timeout()} |
{connect_timeout, timeout()} |
{ssl, ssloptions()} |
- {ossl, ssloptions()} |
{essl, ssloptions()} |
{autoredirect, boolean()} |
{proxy_auth, {userstring(), passwordstring()}} |
@@ -206,6 +207,7 @@ filename() = string()
to the <c>receiver</c> depending on that value. </p>
<p>Http option (<c>http_option()</c>) details: </p>
+ <marker id="request2_http_options"></marker>
<taglist>
<tag><c><![CDATA[timeout]]></c></tag>
<item>
@@ -231,16 +233,9 @@ filename() = string()
<p>Defaults to <c>[]</c>. </p>
</item>
- <tag><c><![CDATA[ossl]]></c></tag>
- <item>
- <p>If using the OpenSSL based (old) implementation of SSL,
- these SSL-specific options are used. </p>
- <p>Defaults to <c>[]</c>. </p>
- </item>
-
<tag><c><![CDATA[essl]]></c></tag>
<item>
- <p>If using the Erlang based (new) implementation of SSL,
+ <p>If using the Erlang based implementation of SSL,
these SSL-specific options are used. </p>
<p>Defaults to <c>[]</c>. </p>
</item>
diff --git a/lib/inets/doc/src/httpd.xml b/lib/inets/doc/src/httpd.xml
index edacb73b65..f88099a82e 100644
--- a/lib/inets/doc/src/httpd.xml
+++ b/lib/inets/doc/src/httpd.xml
@@ -148,13 +148,11 @@
in the apache like configuration file.
</item>
- <tag>{socket_type, ip_comm | ssl | ossl | essl}</tag>
+ <tag>{socket_type, ip_comm | ssl | essl}</tag>
<item>
- <p>When using ssl, there are several alternatives.
- <c>ossl</c> specifically uses the OpenSSL based (old) SSL.
- <c>essl</c> specifically uses the Erlang based (new) SSL.
- When using <c>ssl</c> it <em>currently</em> defaults to
- <c>essl</c>. </p>
+ <p>When using ssl, there are currently only one alternative.
+ <c>essl</c> specifically uses the Erlang based SSL.
+ <c>ssl</c> defaults to <c>essl</c>. </p>
<p>Defaults to <c>ip_comm</c>. </p>
</item>
@@ -162,7 +160,7 @@
<item>
<p>Defaults to <c>inet6fb4. </c> </p>
<p>Note that this option is only used when the option
- <c>socket_type</c> has the value <c>ip_comm</c>. </p>
+ <c>socket_type</c> has the value <c>ip_comm</c>. </p>
</item>
</taglist>
diff --git a/lib/inets/doc/src/make.dep b/lib/inets/doc/src/make.dep
deleted file mode 100644
index 8deb7e7a5a..0000000000
--- a/lib/inets/doc/src/make.dep
+++ /dev/null
@@ -1,47 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2010. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-#
-
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex ftp.tex ftp_client.tex httpc.tex http_client.tex \
- http_server.tex httpd.tex httpd_conf.tex httpd_socket.tex \
- httpd_util.tex inets.tex inets_services.tex \
- mod_alias.tex mod_auth.tex mod_esi.tex mod_security.tex \
- part.tex ref_man.tex tftp.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-ftp.tex: ../../../../system/doc/definitions/term.defs
-
-inets_services.tex: ../../../../system/doc/definitions/term.defs
-
diff --git a/lib/inets/doc/src/mod_auth.xml b/lib/inets/doc/src/mod_auth.xml
index 42c49e9c35..2134ebeeae 100644
--- a/lib/inets/doc/src/mod_auth.xml
+++ b/lib/inets/doc/src/mod_auth.xml
@@ -80,7 +80,7 @@
<marker id="delete_user"></marker>
<p><c>delete_user/2, delete_user/3</c> and <c>delete_user/4</c>
deletes a user
- from the user database. If the operation is succesfull, this
+ from the user database. If the operation is successful, this
function returns <c>true</c>. If an error occurs,
<c>{error,Reason}</c> is returned. When <c>delete_user/2</c> is
called the Port and Dir options are mandatory.</p>
diff --git a/lib/inets/doc/src/mod_esi.xml b/lib/inets/doc/src/mod_esi.xml
index 9674cd9a88..9906ae0895 100644
--- a/lib/inets/doc/src/mod_esi.xml
+++ b/lib/inets/doc/src/mod_esi.xml
@@ -31,8 +31,8 @@
<module>mod_esi</module>
<modulesummary>Erlang Server Interface </modulesummary>
<description>
- <p>This module defines the API - Erlang Server Interface (ESI).
- Which is a more efficient way of writing erlang scripts
+ <p>This module defines the Erlang Server Interface (ESI) API.
+ It is a more efficient way of writing erlang scripts
for your Inets web server than writing them as common CGI scripts.</p>
<marker id="deliver"></marker>
@@ -95,12 +95,12 @@
the server uses when <c>deliver/2</c> is called; do not
assume anything about the datatype.</p>
<p>Use this callback function to dynamically generate dynamic web
- content. when a part of the page is generated send the
+ content. When a part of the page is generated send the
data back to the client through <c>deliver/2</c>. Note
that the first chunk of data sent to the client must at
least contain all HTTP header fields that the response
will generate. If the first chunk does not contain the
- <em>End of HTTP the header</em>, that is <c>"\r\n\r\n",</c>
+ <em>End of HTTP header</em>, that is <c>"\r\n\r\n",</c>
the server will
assume that no HTTP header fields will be generated.</p>
</desc>
@@ -118,8 +118,8 @@
<desc>
<p>This callback format consumes a lot of memory since the
whole response must be generated before it is sent to the
- user. This functions is deprecated and only keept for backwards
- compatibility.
+ user. This function is deprecated and only kept for backwards
+ compatibility.
For new development Module:Function/3 should be used.</p>
</desc>
</func>
diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml
index 34f26bf45b..59c2f8a2df 100644
--- a/lib/inets/doc/src/notes.xml
+++ b/lib/inets/doc/src/notes.xml
@@ -32,6 +32,190 @@
<file>notes.xml</file>
</header>
+ <section><title>Inets 5.8</title>
+
+ <section><title>Improvements and New Features</title>
+<!--
+ <p>-</p>
+-->
+
+ <list>
+ <item>
+ <p>[ftpc] Add a config option to specify a
+ <seealso marker="ftp#dtimeout">data connect timeout</seealso>.
+ That is how long the ftp client will wait for the server to connect
+ to the data socket. If this timeout occurs, an error will be
+ returned to the caller and the ftp client process will be
+ terminated. </p>
+ <p>Own Id: OTP-9545</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <p>-</p>
+
+<!--
+ <list>
+ <item>
+ <p>[httpc] Remove unnecessary usage of iolist_to_binary when
+ processing body (for PUT and POST). </p>
+ <p>Filipe David Manana</p>
+ <p>Own Id: OTP-9317</p>
+ </item>
+
+ </list>
+-->
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+<!--
+ <p>-</p>
+-->
+
+ <list>
+ <item>
+ <p>[httpc] Deprecated interface module <c>http</c> has been removed.
+ It has (long) been replaced by http client interface module
+ <seealso marker="httpc#">httpc</seealso>. </p>
+ <p>Own Id: OTP-9359</p>
+ </item>
+
+ <item>
+ <p>[httpc|httpd] The old ssl implementation (based on OpenSSL),
+ has been deprecated. The config option that specified usage of
+ this version of the ssl app, <c>ossl</c>, has been removed. </p>
+ <p>Own Id: OTP-9522</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ </section> <!-- 5.8 -->
+
+
+ <section><title>Inets 5.7.2</title>
+ <section><title>Improvements and New Features</title>
+ <p>-</p>
+
+<!--
+ <list>
+ <item>
+ <p>[httpc|httpd] Added support for IPv6 with ssl. </p>
+ <p>Own Id: OTP-5566</p>
+ </item>
+
+ </list>
+-->
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+<!--
+ <p>-</p>
+-->
+
+ <list>
+ <item>
+ <p>[httpc] Deprecated interface module <c>http</c> has been removed.
+ It has (long) been replaced by http client interface module
+ <seealso marker="httpc#">httpc</seealso>. </p>
+ <p>Own Id: OTP-9359</p>
+ </item>
+
+ <item>
+ <p>[httpc|httpd] The old ssl implementation (based on OpenSSL),
+ has been deprecated. The config option that specified usage of
+ this version of the ssl app, <c>ossl</c>, has been removed. </p>
+ <p>Own Id: OTP-9522</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+<!--
+ <p>-</p>
+-->
+
+ <list>
+ <item>
+ <p>[httpd] XSS prevention did not work for hex-encoded URL's. </p>
+ <p>Own Id: OTP-9655</p>
+ </item>
+
+ <item>
+ <p>[httpd] GET request with malformed header date caused
+ server crash (non-fatal) with no reply to client. Will
+ now result in a reply with status code 400. </p>
+ <p>Own Id: OTP-9674</p>
+ <p>Aux Id: seq11936</p>
+ </item>
+
+ </list>
+ </section>
+
+ </section> <!-- 5.7.2 -->
+
+
+ <section><title>Inets 5.7.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <p>-</p>
+
+<!--
+ <list>
+ <item>
+ <p>[httpc|httpd] Added support for IPv6 with ssl. </p>
+ <p>Own Id: OTP-5566</p>
+ </item>
+
+ </list>
+-->
+
+ </section>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+<!--
+ <p>-</p>
+-->
+
+ <list>
+ <item>
+ <p>[httpc] Parsing of a cookie expire date should be more forgiving.
+ That is, if the parsing fails, the date should be ignored.
+ Also added support for (yet another) date format:
+ "Tue Jan 01 08:00:01 2036 GMT". </p>
+ <p>Own Id: OTP-9433</p>
+ </item>
+
+ <item>
+ <p>[httpc] Rewrote cookie parsing. Among other things solving
+ cookie processing from www.expedia.com. </p>
+ <p>Own Id: OTP-9434</p>
+ </item>
+
+ <item>
+ <p>[httpd] Fix httpd directory traversal on Windows.
+ Directory traversal was possible on Windows where
+ backward slash is used as directory separator. </p>
+ <p>Andr�s Veres-Szentkir�lyi.</p>
+ <p>Own Id: OTP-9561</p>
+ </item>
+
+ </list>
+ </section>
+
+ </section> <!-- 5.7.1 -->
+
+
<section><title>Inets 5.7</title>
<section><title>Improvements and New Features</title>
@@ -1044,570 +1228,11 @@
</section> <!-- 5.1 -->
+ <!--
+ <p>For information about older versions see
+ <url href="part_notes_history_frame.html">release notes history</url>.</p>
+ -->
- <section><title>Inets 5.0.14</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- [tftp] The callback watchdog has been removed, as it
- turned out to be counter productive when the disk was
- overloaded. Earlier a connection was aborted when a
- callback (which performs the file access in the TFTP
- server) took too long time.</p>
- <p>
- [tftp] The error message "Too many connections" has been
- reclassified to be a warning.</p>
- <p>
- Own Id: OTP-7888</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>[httpc] - Incorrect http version option check. </p>
- <p>Mats Cronqvist</p>
- <p>Own Id: OTP-7882</p>
- </item>
-
- <item>
- <p>[httpc] - Unnecessary error report when client
- terminating as a result of the server closed the
- socket unexpectedly. </p>
- <p>Own Id: OTP-7883</p>
- </item>
-
- <item>
- <p>[httpc] - Failed transforming a relative URI to
- an absolute URI. </p>
- <p>Own Id: OTP-7950</p>
- </item>
-
- <item>
- <p>[httpd] - The HTTP server did not handle the config
- option ssl_ca_certificate_file. </p>
- <p>Own Id: OTP-7976</p>
- </item>
-
- </list>
- </section>
-
- </section> <!-- 5.0.14 -->
-
-
- <section><title>Inets 5.0.13</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Ssl did not work correctly with the use of new style
- configuration due to sn old internal format that was not
- changed correctly in all places.</p>
- <p>
- Own Id: OTP-7723 Aux Id: seq11143 </p>
- </item>
- <item>
- <p>
- [httpc] - Now streams 200 and 206 results and not only
- 200 results.</p>
- <p>
- Own Id: OTP-7857</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- [httpc] - The inets http client will now use persistent
- connections without pipelining as default and if a
- pipeline timeout is set it will pipeline the requests on
- the persistent connections.</p>
- <p>
- *** POTENTIAL INCOMPATIBILITY ***</p>
- <p>
- Own Id: OTP-7463</p>
- </item>
- <item>
- <p>
- [httpd] - added option ssl_password_callback_arguments.</p>
- <p>
- Own Id: OTP-7724 Aux Id: seq11151 </p>
- </item>
- <item>
- <p>
- Changed the socket use so that it will become more robust
- to non-functional ipv6 and fallback on ipv4. This changes
- may for very special os-configurations cause a problem
- when used with erts-versions pre R13.</p>
- <p>
- Own Id: OTP-7726</p>
- </item>
- <item>
- <p>
- Removed deprecated function httpd_util:key1search/[2,3]</p>
- <p>
- Own Id: OTP-7815</p>
- </item>
- </list>
- </section>
-
- </section>
-
- <section><title>Inets 5.0.12</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- [httpd] - Updated inets so that it not uses the deprecated
- function ssl:accept/[2,3].</p>
- <p>
- Own Id: OTP-7636 Aux Id: seq11086 </p>
- </item>
- </list>
- </section>
-
- </section>
-
-
- <section><title>Inets 5.0.11</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Transient bug related to hot code swap of the TFTP server is
- now fixed. It could happen that the first TFTP server that was
- started after a code upgrade to Inets-5.0.6 crashed with a
- function clause error in tftp_engine:service_init/2.</p>
- <p> Own Id: OTP-7574 Aux Id: seq11069 </p>
- </item>
- <item>
- <p>
- [httpd] - Validation of ssl_password_callback_module was
- incorrect.</p>
- <p>
- Own Id: OTP-7597 Aux Id: seq11074 </p>
- </item>
- <item>
- <p>
- [httpd] - Misspelling in old apachelike configuration
- directive TransferDiskLogSize has been corrected.</p>
- <p> Own Id: OTP-7598 Aux Id: seq11059 </p>
- </item>
- <item>
- <p>
- Minor problems found by dialyzer has been fixed.</p>
- <p>
- Own Id: OTP-7605</p>
- </item>
- </list>
- </section>
-
- </section>
-
-<section><title>Inets 5.0.10</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Enhanched an info report.</p>
- <p>
- Own Id: OTP-7450</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Changed errro message from
- {wrong_type,{document_root,"/tmp/htdocs"}} to
- {invalid_option,{non_existing,
- document_root,"/tmp/htdocs"}}.</p>
- <p>
- Own Id: OTP-7454</p>
- </item>
- <item>
- <p>
- Relative paths in directory authentication did not work
- as intended, this has now been fixed.</p>
- <p>
- Own Id: OTP-7490</p>
- </item>
- <item>
- <p>
- The query-string passed to the callback function was not
- compliant with the documentation, it is now.</p>
- <p>
- Own Id: OTP-7512</p>
- </item>
- </list>
- </section>
-
-</section>
-
- <section><title>Inets 5.0.9</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Parameters to error_logger:error_report/1 has been
- corrected.</p>
- <p>
- Own Id: OTP-7257 Aux Id: OTP-7294, OTP-7258 </p>
- </item>
- <item>
- <p>
- [httpd] - If a Module/Function request matching an
- erl_script_alias registration does not exist as a function in
- the module registered a 404 error will now be issued instead of a
- 500 error.</p>
- <p>
- Own Id: OTP-7323</p>
- </item>
- <item>
- <p>
- [httpd] -The option auth_type for mod_auth is no longer
- mandatory, for backward-compatibility reasons.</p>
- <p>
- Own Id: OTP-7341</p>
- </item>
- </list>
- </section>
-
- </section>
-
- <section><title>Inets 5.0.8</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- [httpd] - Spelling error caused client connection header
- to be ignored.</p>
- <p>
- Own Id: OTP-7315 Aux Id: seq10951 </p>
- </item>
- <item>
- <p>
- [httpd] - Call to the function
- mod_get:get_modification_date/1 was made too early
- resulting in that httpd did not send the 404 file missing
- response.</p>
- <p>
- Own Id: OTP-7321</p>
- </item>
- </list>
- </section>
-
- </section>
-
- <section><title>Inets 5.0.7</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- [httpc, httpd] - Now follows the recommendation regarding
- line terminators in section 19.3 in RFC 2616 e.i: "The
- line terminator for message-header fields is the sequence
- CRLF. However, we recommend that applications, when
- parsing such headers, recognize a single LF as a line
- terminator and ignore the leading CR".</p>
- <p>
- Own Id: OTP-7304 Aux Id: seq10944 </p>
- </item>
- </list>
- </section>
-
- </section>
-
- <section><title>Inets 5.0.6</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- [tftp] If a callback (which performs the file access in
- the TFTP server) takes too long time (more than the
- double TFTP timeout), the server will abort the
- connection and send an error reply to the client. This
- implies that the server will release resources attached
- to the connection faster than before. The server simply
- assumes that the client has given up.</p>
- <p>
- [tftp] If the TFTP server receives yet another request
- from the same client (same host and port) while it
- already has an active connection to the client, it will
- simply ignore the new request if the request is equal
- with the first one (same filename and options). This
- implies that the (new) client will be served by the
- already ongoing connection on the server side. By not
- setting up yet another connection, in parallel with the
- ongoing one, the server will consumer lesser resources.</p>
- <p>
- [tftp] netascii mode is now supported when the
- client/server has native ascii support (Windows). The new
- optional parameter native_ascii in the tftp_binary and
- tftp_file callback modules can be used to override the
- default behavior.</p>
- <p>
- [tftp] Yet another callback module has been added in
- order to allow customized handling of error, warning and
- info messages. See the new configuration parameter,
- logger.</p>
- <p>
- [tftp] Yet another configuration parameter, max_retries,
- has been added in order to control the number of times a
- packet can be resent. The default is 5.</p>
- <p>
- [tftp] tftp:info/1 and tftp:change_config/2 can now be
- applied to all daemons or all servers in one command
- without bothering about their process identifiers.</p>
- <p>
- External TR HI89527.</p>
- <p>
- Own Id: OTP-7266</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Inets 5.0.5</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- [tftp] Blocks with too low block numbers are silently
- discarded. For example if a server receives block #5 when
- it expects block #7 it will discard the block without
- interrupting the file transfer. Too high block numbers
- does still imply an error. External TR HI96072.</p>
- <p>
- Own Id: OTP-7220</p>
- </item>
- <item>
- <p>
- [tftp] The problem with occasional case_clause errors in
- tftp_engine:common_read/7 has been fixed. External TR
- HI97362.</p>
- <p>
- Own Id: OTP-7221</p>
- </item>
- </list>
- </section>
-
-</section>
-
- <section><title>Inets 5.0.4</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Changed calls to file open to concur with the API and not
- use deprecated syntax.</p>
- <p>
- Own Id: OTP-7172</p>
- </item>
- <item>
- <p>
- [tftp] Server lost the first packet when the client timed
- out</p>
- <p>
- Own Id: OTP-7173</p>
- </item>
- </list>
- </section>
-
- </section>
-
- <section><title>Inets 5.0.3</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Updated copyright headers and fixed backwards
- compatibility for an undocumented feature, for now. This
- feature will later be removed and a new and documented
- option will take its place.</p>
- <p>
- Own Id: OTP-7144</p>
- </item>
- </list>
- </section>
-
- </section>
-
- <section><title>Inets 5.0.2</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- [httpd] - Error logs now has a pretty and a compact
- format and access logs can be written on the common log
- format or the extended common log format.</p>
- <p>
- Own Id: OTP-6661 Aux Id: Seq 7764 </p>
- </item>
- <item>
- <p>
- [httpc] - Added acceptance of missing reason phrase to
- the relaxed mode.</p>
- <p>
- Own Id: OTP-7024</p>
- </item>
- <item>
- <p>
- [httpc] - A new option has been added to enable the
- client to act as lower version clients, by default the
- client is an HTTP/1.1 client.</p>
- <p>
- Own Id: OTP-7043</p>
- </item>
- </list>
- </section>
-
- </section>
-
- <section><title>Inets 5.0.1</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- [httpd] - Deprecated function httpd:start/1 did not
- accept all inputs that it had done previously. This
- should now work again.</p>
- <p>
- Own Id: OTP-7040</p>
- </item>
- </list>
- </section>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- [httpd] - Changed validity check on bind_address so that
- it uses inet:getaddr instead of inet:gethostbyaddr as the
- former puts a too hard restriction on the bind_address.</p>
- <p>
- Own Id: OTP-7041 Aux Id: seq10829 </p>
- </item>
- <item>
- <p>
- [httpc] - Internal process now does try-catch and
- terminates normally in case of HTTP parse errors.
- Semantical the client works just as before returning an
- error message to the client, even if the error massage
- has been enhanced, but there is no supervisor report in
- the shell of a internal process crashing. (Which was the
- expected behavior and not a fault.)</p>
- <p>
- Own Id: OTP-7042</p>
- </item>
- </list>
- </section>
-
- </section>
-
- <section><title>Inets 5.0</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- [httpd, httpc] - Deprecated base64 decode/encode
- functions have been removed. Inets uses base64 in STDLIB
- instead.</p>
- <p>
- *** POTENTIAL INCOMPATIBILITY ***</p>
- <p>
- Own Id: OTP-6485</p>
- </item>
- <item>
- <p>
- [httpd] - It is now possible to restrict the length of
- acceptable URI:s in the HTTP server.</p>
- <p>
- Own Id: OTP-6572</p>
- </item>
- <item>
- <p>
- [httpc] - Profiles are now supported i.e. the options
- available in set_options/1 can be set locally for a
- certain profile and do not have to affect all
- HTTP-requests issued in the Erlang node. Calls to the
- HTTP client API functions not using the profile argument
- will use the default profile.</p>
- <p>
- Own Id: OTP-6690</p>
- </item>
- <item>
- <p>
- A new uniform Inets interface provides a flexible way to
- start/stop Inets services and get information about
- running services. See inets(3). This also means that
- inflexibilities in the HTTP server has been removed and
- more default values has been added.</p>
- <p>
- Own Id: OTP-6705</p>
- </item>
- <item>
- <p>
- [tftp] Logged errors have been changed to be logged
- warnings.</p>
- <p>
- Own Id: OTP-6916 Aux Id: seq10737 </p>
- </item>
- <item>
- <p>
- [httpc] - The client will now return the proper value
- when receiving a HTTP 204 code instead of hanging.</p>
- <p>
- Own Id: OTP-6982</p>
- </item>
- <item>
- <p>
- The Inets application now has to be explicitly started
- and stopped i.e. it will not automatically be started as
- a temporary application as it did before. Although a
- practical feature when testing things in the shell it is
- not desirable that people take advantage of this and not
- start the Inets application in a correct way in their
- products. Added functions to the Inets API that call
- application:start/stop.</p>
- <p>
- *** POTENTIAL INCOMPATIBILITY ***</p>
- <p>
- Own Id: OTP-6993</p>
- </item>
- </list>
- </section>
-
- <!-- p>For information about older versions see
- <url href="part_notes_history_frame.html">release notes history</url>.</p -->
- </section>
</chapter>
diff --git a/lib/inets/doc/src/notes_history.xml b/lib/inets/doc/src/notes_history.xml
index 6480bad758..151bec375e 100644
--- a/lib/inets/doc/src/notes_history.xml
+++ b/lib/inets/doc/src/notes_history.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -123,7 +123,7 @@
re-receive of acknowledgments. If multiple copies of the
same acknowledgments is received the spurious ones are
silently ignored. This fix was intended for inets-4.7.14
- but accidentaly it was not included in that release.</p>
+ but accidentally it was not included in that release.</p>
<p>Own Id: OTP-6706 Aux Id: OTP-6691 </p>
</item>
</list>
diff --git a/lib/inets/src/ftp/ftp.erl b/lib/inets/src/ftp/ftp.erl
index ac72963347..b6da92947c 100644
--- a/lib/inets/src/ftp/ftp.erl
+++ b/lib/inets/src/ftp/ftp.erl
@@ -55,9 +55,10 @@
-include("ftp_internal.hrl").
%% Constante used in internal state definition
--define(CONNECTION_TIMEOUT, 60*1000).
--define(DEFAULT_MODE, passive).
--define(PROGRESS_DEFAULT, ignore).
+-define(CONNECTION_TIMEOUT, 60*1000).
+-define(DATA_ACCEPT_TIMEOUT, infinity).
+-define(DEFAULT_MODE, passive).
+-define(PROGRESS_DEFAULT, ignore).
%% Internal Constants
-define(FTP_PORT, 21).
@@ -88,7 +89,8 @@
%% data needed further on.
caller = undefined, % term()
ipfamily, % inet | inet6 | inet6fb4
- progress = ignore % ignore | pid()
+ progress = ignore, % ignore | pid()
+ dtimeout = ?DATA_ACCEPT_TIMEOUT % non_neg_integer() | infinity
}).
@@ -847,6 +849,7 @@ start_options(Options) ->
%% host
%% port
%% timeout
+%% dtimeout
%% progress
open_options(Options) ->
?fcrt("open_options", [{options, Options}]),
@@ -875,7 +878,12 @@ open_options(Options) ->
(_) -> false
end,
ValidateTimeout =
- fun(Timeout) when is_integer(Timeout) andalso (Timeout > 0) -> true;
+ fun(Timeout) when is_integer(Timeout) andalso (Timeout >= 0) -> true;
+ (_) -> false
+ end,
+ ValidateDTimeout =
+ fun(DTimeout) when is_integer(DTimeout) andalso (DTimeout >= 0) -> true;
+ (infinity) -> true;
(_) -> false
end,
ValidateProgress =
@@ -893,6 +901,7 @@ open_options(Options) ->
{port, ValidatePort, false, ?FTP_PORT},
{ipfamily, ValidateIpFamily, false, inet},
{timeout, ValidateTimeout, false, ?CONNECTION_TIMEOUT},
+ {dtimeout, ValidateDTimeout, false, ?DATA_ACCEPT_TIMEOUT},
{progress, ValidateProgress, false, ?PROGRESS_DEFAULT}],
validate_options(Options, ValidOptions, []).
@@ -1037,13 +1046,15 @@ handle_call({_, {open, ip_comm, Opts}}, From, State) ->
Mode = key_search(mode, Opts, ?DEFAULT_MODE),
Port = key_search(port, Opts, ?FTP_PORT),
Timeout = key_search(timeout, Opts, ?CONNECTION_TIMEOUT),
+ DTimeout = key_search(dtimeout, Opts, ?DATA_ACCEPT_TIMEOUT),
Progress = key_search(progress, Opts, ignore),
IpFamily = key_search(ipfamily, Opts, inet),
-
+
State2 = State#state{client = From,
mode = Mode,
progress = progress(Progress),
- ipfamily = IpFamily},
+ ipfamily = IpFamily,
+ dtimeout = DTimeout},
?fcrd("handle_call(open) -> setup ctrl connection with",
[{host, Host}, {port, Port}, {timeout, Timeout}]),
@@ -1064,11 +1075,13 @@ handle_call({_, {open, ip_comm, Host, Opts}}, From, State) ->
Mode = key_search(mode, Opts, ?DEFAULT_MODE),
Port = key_search(port, Opts, ?FTP_PORT),
Timeout = key_search(timeout, Opts, ?CONNECTION_TIMEOUT),
+ DTimeout = key_search(dtimeout, Opts, ?DATA_ACCEPT_TIMEOUT),
Progress = key_search(progress, Opts, ignore),
State2 = State#state{client = From,
mode = Mode,
- progress = progress(Progress)},
+ progress = progress(Progress),
+ dtimeout = DTimeout},
case setup_ctrl_connection(Host, Port, Timeout, State2) of
{ok, State3, WaitTimeout} ->
@@ -1657,9 +1670,19 @@ handle_ctrl_result({pos_compl, Lines},
%%--------------------------------------------------------------------------
%% Directory listing
handle_ctrl_result({pos_prel, _}, #state{caller = {dir, Dir}} = State) ->
- NewState = accept_data_connection(State),
- activate_data_connection(NewState),
- {noreply, NewState#state{caller = {handle_dir_result, Dir}}};
+ case accept_data_connection(State) of
+ {ok, NewState} ->
+ activate_data_connection(NewState),
+ {noreply, NewState#state{caller = {handle_dir_result, Dir}}};
+ {error, _Reason} = ERROR ->
+ case State#state.client of
+ undefined ->
+ {stop, ERROR, State};
+ From ->
+ gen_server:reply(From, ERROR),
+ {stop, normal, State#state{client = undefined}}
+ end
+ end;
handle_ctrl_result({pos_compl, _}, #state{caller = {handle_dir_result, Dir,
Data}, client = From}
@@ -1756,9 +1779,19 @@ handle_ctrl_result({Status, _},
%%--------------------------------------------------------------------------
%% File handling - recv_bin
handle_ctrl_result({pos_prel, _}, #state{caller = recv_bin} = State) ->
- NewState = accept_data_connection(State),
- activate_data_connection(NewState),
- {noreply, NewState};
+ case accept_data_connection(State) of
+ {ok, NewState} ->
+ activate_data_connection(NewState),
+ {noreply, NewState};
+ {error, _Reason} = ERROR ->
+ case State#state.client of
+ undefined ->
+ {stop, ERROR, State};
+ From ->
+ gen_server:reply(From, ERROR),
+ {stop, normal, State#state{client = undefined}}
+ end
+ end;
handle_ctrl_result({pos_compl, _}, #state{caller = {recv_bin, Data},
client = From} = State) ->
@@ -1780,16 +1813,37 @@ handle_ctrl_result({Status, _}, #state{caller = {recv_bin, _}} = State) ->
handle_ctrl_result({pos_prel, _}, #state{client = From,
caller = start_chunk_transfer}
= State) ->
- NewState = accept_data_connection(State),
- gen_server:reply(From, ok),
- {noreply, NewState#state{chunk = true, client = undefined,
- caller = undefined}};
+ case accept_data_connection(State) of
+ {ok, NewState} ->
+ gen_server:reply(From, ok),
+ {noreply, NewState#state{chunk = true, client = undefined,
+ caller = undefined}};
+ {error, _Reason} = ERROR ->
+ case State#state.client of
+ undefined ->
+ {stop, ERROR, State};
+ From ->
+ gen_server:reply(From, ERROR),
+ {stop, normal, State#state{client = undefined}}
+ end
+ end;
+
%%--------------------------------------------------------------------------
%% File handling - recv_file
handle_ctrl_result({pos_prel, _}, #state{caller = {recv_file, _}} = State) ->
- NewState = accept_data_connection(State),
- activate_data_connection(NewState),
- {noreply, NewState};
+ case accept_data_connection(State) of
+ {ok, NewState} ->
+ activate_data_connection(NewState),
+ {noreply, NewState};
+ {error, _Reason} = ERROR ->
+ case State#state.client of
+ undefined ->
+ {stop, ERROR, State};
+ From ->
+ gen_server:reply(From, ERROR),
+ {stop, normal, State#state{client = undefined}}
+ end
+ end;
handle_ctrl_result({Status, _}, #state{caller = {recv_file, Fd}} = State) ->
file_close(Fd),
@@ -1800,17 +1854,38 @@ handle_ctrl_result({Status, _}, #state{caller = {recv_file, Fd}} = State) ->
%% File handling - transfer_*
handle_ctrl_result({pos_prel, _}, #state{caller = {transfer_file, Fd}}
= State) ->
- NewState = accept_data_connection(State),
- send_file(Fd, NewState);
+ case accept_data_connection(State) of
+ {ok, NewState} ->
+ send_file(Fd, NewState);
+ {error, _Reason} = ERROR ->
+ case State#state.client of
+ undefined ->
+ {stop, ERROR, State};
+ From ->
+ gen_server:reply(From, ERROR),
+ {stop, normal, State#state{client = undefined}}
+ end
+ end;
handle_ctrl_result({pos_prel, _}, #state{caller = {transfer_data, Bin}}
= State) ->
- NewState = accept_data_connection(State),
- send_data_message(NewState, Bin),
- close_data_connection(NewState),
- activate_ctrl_connection(NewState),
- {noreply, NewState#state{caller = transfer_data_second_phase,
- dsock = undefined}};
+ case accept_data_connection(State) of
+ {ok, NewState} ->
+ send_data_message(NewState, Bin),
+ close_data_connection(NewState),
+ activate_ctrl_connection(NewState),
+ {noreply, NewState#state{caller = transfer_data_second_phase,
+ dsock = undefined}};
+ {error, _Reason} = ERROR ->
+ case State#state.client of
+ undefined ->
+ {stop, ERROR, State};
+ From ->
+ gen_server:reply(From, ERROR),
+ {stop, normal, State#state{client = undefined}}
+ end
+ end;
+
%%--------------------------------------------------------------------------
%% Default
handle_ctrl_result({Status, Lines}, #state{client = From} = State)
@@ -2009,16 +2084,20 @@ connect2(Host, Port, IpFam, Timeout) ->
Error
end.
-
-accept_data_connection(#state{mode = active,
- dsock = {lsock, LSock}} = State) ->
- {ok, Socket} = gen_tcp:accept(LSock),
- gen_tcp:close(LSock),
- State#state{dsock = Socket};
+accept_data_connection(#state{mode = active,
+ dtimeout = DTimeout,
+ dsock = {lsock, LSock}} = State) ->
+ case gen_tcp:accept(LSock, DTimeout) of
+ {ok, Socket} ->
+ gen_tcp:close(LSock),
+ {ok, State#state{dsock = Socket}};
+ {error, Reason} ->
+ {error, {data_connect_failed, Reason}}
+ end;
accept_data_connection(#state{mode = passive} = State) ->
- State.
+ {ok, State}.
send_ctrl_message(#state{csock = Socket, verbose = Verbose}, Message) ->
%% io:format("send control message: ~n~p~n", [lists:flatten(Message)]),
diff --git a/lib/inets/src/http_client/Makefile b/lib/inets/src/http_client/Makefile
index 0397b48ab2..3960c36d00 100644
--- a/lib/inets/src/http_client/Makefile
+++ b/lib/inets/src/http_client/Makefile
@@ -41,7 +41,6 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
# Target Specs
# ----------------------------------------------------
MODULES = \
- http \
httpc \
httpc_cookie \
httpc_handler \
diff --git a/lib/inets/src/http_client/http.erl b/lib/inets/src/http_client/http.erl
deleted file mode 100644
index bbe2fec267..0000000000
--- a/lib/inets/src/http_client/http.erl
+++ /dev/null
@@ -1,132 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
-%%% Description: OLD API MODULE - USE httpc INSTEAD
-
--module(http).
-
--deprecated({request, 1, next_major_release}).
--deprecated({request, 2, next_major_release}).
--deprecated({request, 4, next_major_release}).
--deprecated({request, 5, next_major_release}).
--deprecated({cancel_request, 1, next_major_release}).
--deprecated({cancel_request, 2, next_major_release}).
--deprecated({set_option, 2, next_major_release}).
--deprecated({set_option, 3, next_major_release}).
--deprecated({set_options, 1, next_major_release}).
--deprecated({set_options, 2, next_major_release}).
--deprecated({verify_cookies, 2, next_major_release}).
--deprecated({verify_cookies, 3, next_major_release}).
--deprecated({cookie_header, 1, next_major_release}).
--deprecated({cookie_header, 2, next_major_release}).
--deprecated({stream_next, 1, next_major_release}).
--deprecated({default_profile, 0, next_major_release}).
-
-%% Deprecated
--export([
- request/1, request/2, request/4, request/5,
- cancel_request/1, cancel_request/2,
- set_option/2, set_option/3,
- set_options/1, set_options/2,
- verify_cookies/2, verify_cookies/3,
- cookie_header/1, cookie_header/2,
- stream_next/1,
- default_profile/0
- ]).
-
-
-%%%=========================================================================
-%%% API
-%%%=========================================================================
-
-%%--------------------------------------------------------------------------
-%% request(Url [, Profile]) ->
-%% request(Method, Request, HTTPOptions, Options [, Profile])
-%%--------------------------------------------------------------------------
-
-request(Url) -> httpc:request(Url).
-request(Url, Profile) -> httpc:request(Url, Profile).
-
-request(Method, Request, HttpOptions, Options) ->
- httpc:request(Method, Request, HttpOptions, Options).
-request(Method, Request, HttpOptions, Options, Profile) ->
- httpc:request(Method, Request, HttpOptions, Options, Profile).
-
-
-%%--------------------------------------------------------------------------
-%% cancel_request(RequestId [, Profile])
-%%-------------------------------------------------------------------------
-
-cancel_request(RequestId) ->
- httpc:cancel_request(RequestId).
-cancel_request(RequestId, Profile) ->
- httpc:cancel_request(RequestId, Profile).
-
-
-%%--------------------------------------------------------------------------
-%% set_options(Options [, Profile])
-%% set_option(Key, Value [, Profile])
-%%-------------------------------------------------------------------------
-
-set_options(Options) ->
- httpc:set_options(Options).
-set_options(Options, Profile) ->
- httpc:set_options(Options, Profile).
-
-set_option(Key, Value) ->
- httpc:set_option(Key, Value).
-set_option(Key, Value, Profile) ->
- httpc:set_option(Key, Value, Profile).
-
-
-%%--------------------------------------------------------------------------
-%% verify_cookies(SetCookieHeaders, Url [, Profile])
-%%-------------------------------------------------------------------------
-
-verify_cookies(SetCookieHeaders, Url) ->
- httpc:store_cookies(SetCookieHeaders, Url).
-verify_cookies(SetCookieHeaders, Url, Profile) ->
- httpc:store_cookies(SetCookieHeaders, Url, Profile).
-
-
-%%--------------------------------------------------------------------------
-%% cookie_header(Url [, Profile])
-%%-------------------------------------------------------------------------
-
-cookie_header(Url) ->
- httpc:cookie_header(Url).
-cookie_header(Url, Profile) ->
- httpc:cookie_header(Url, Profile).
-
-
-%%--------------------------------------------------------------------------
-%% stream_next(Pid)
-%%-------------------------------------------------------------------------
-
-stream_next(Pid) ->
- httpc:stream_next(Pid).
-
-
-%%--------------------------------------------------------------------------
-%% default_profile()
-%%-------------------------------------------------------------------------
-
-default_profile() ->
- httpc:default_profile().
diff --git a/lib/inets/src/http_client/httpc.erl b/lib/inets/src/http_client/httpc.erl
index fe8e93af1f..d72c34fa6b 100644
--- a/lib/inets/src/http_client/httpc.erl
+++ b/lib/inets/src/http_client/httpc.erl
@@ -105,7 +105,6 @@ request(Url, Profile) ->
%% {ssl, SSLOptions} | {proxy_auth, {User, Password}}
%% Ssloptions = ssl_options() |
%% {ssl, ssl_options()} |
-%% {ossl, ssl_options()} |
%% {essl, ssl_options()}
%% ssl_options() = [ssl_option()]
%% ssl_option() = {verify, code()} |
@@ -142,7 +141,9 @@ request(Url, Profile) ->
request(Method, Request, HttpOptions, Options) ->
request(Method, Request, HttpOptions, Options, default_profile()).
-request(Method, {Url, Headers}, HTTPOptions, Options, Profile)
+request(Method,
+ {Url, Headers},
+ HTTPOptions, Options, Profile)
when (Method =:= options) orelse
(Method =:= get) orelse
(Method =:= head) orelse
@@ -155,15 +156,17 @@ request(Method, {Url, Headers}, HTTPOptions, Options, Profile)
{http_options, HTTPOptions},
{options, Options},
{profile, Profile}]),
- case http_uri:parse(Url) of
+ case http_uri:parse(Url, Options) of
{error, Reason} ->
{error, Reason};
- ParsedUrl ->
+ {ok, ParsedUrl} ->
handle_request(Method, Url, ParsedUrl, Headers, [], [],
HTTPOptions, Options, Profile)
end;
-request(Method, {Url,Headers,ContentType,Body}, HTTPOptions, Options, Profile)
+request(Method,
+ {Url, Headers, ContentType, Body},
+ HTTPOptions, Options, Profile)
when ((Method =:= post) orelse (Method =:= put)) andalso
(is_atom(Profile) orelse is_pid(Profile)) ->
?hcrt("request", [{method, Method},
@@ -174,10 +177,10 @@ request(Method, {Url,Headers,ContentType,Body}, HTTPOptions, Options, Profile)
{http_options, HTTPOptions},
{options, Options},
{profile, Profile}]),
- case http_uri:parse(Url) of
+ case http_uri:parse(Url, Options) of
{error, Reason} ->
{error, Reason};
- ParsedUrl ->
+ {ok, ParsedUrl} ->
handle_request(Method, Url,
ParsedUrl, Headers, ContentType, Body,
HTTPOptions, Options, Profile)
@@ -268,7 +271,10 @@ store_cookies(SetCookieHeaders, Url, Profile)
{profile, Profile}]),
try
begin
- {_, _, Host, Port, Path, _} = http_uri:parse(Url),
+ %% Since the Address part is not actually used
+ %% by the manager when storing cookies, we dont
+ %% care about ipv6-host-with-brackets.
+ {ok, {_, _, Host, Port, Path, _}} = http_uri:parse(Url),
Address = {Host, Port},
ProfileName = profile_name(Profile),
Cookies = httpc_cookie:cookies(SetCookieHeaders, Path, Host),
@@ -465,6 +471,8 @@ handle_request(Method, Url,
HeadersRecord = header_record(NewHeaders, Host2, HTTPOptions),
Receiver = proplists:get_value(receiver, Options),
SocketOpts = proplists:get_value(socket_opts, Options),
+ BracketedHost = proplists:get_value(ipv6_host_with_brackets,
+ Options),
MaybeEscPath = maybe_encode_uri(HTTPOptions, Path),
MaybeEscQuery = maybe_encode_uri(HTTPOptions, Query),
AbsUri = maybe_encode_uri(HTTPOptions, Url),
@@ -483,7 +491,8 @@ handle_request(Method, Url,
stream = Stream,
headers_as_is = headers_as_is(Headers0, Options),
socket_opts = SocketOpts,
- started = Started},
+ started = Started,
+ ipv6_host_with_brackets = BracketedHost},
case httpc_manager:request(Request, profile_name(Profile)) of
{ok, RequestId} ->
@@ -644,8 +653,6 @@ http_options_default() ->
{ok, {?HTTP_DEFAULT_SSL_KIND, Value}};
({ssl, SslOptions}) when is_list(SslOptions) ->
{ok, {?HTTP_DEFAULT_SSL_KIND, SslOptions}};
- ({ossl, SslOptions}) when is_list(SslOptions) ->
- {ok, {ossl, SslOptions}};
({essl, SslOptions}) when is_list(SslOptions) ->
{ok, {essl, SslOptions}};
(_) ->
@@ -742,14 +749,17 @@ request_options_defaults() ->
error
end,
+ VerifyBrackets = VerifyBoolean,
+
[
- {sync, true, VerifySync},
- {stream, none, VerifyStream},
- {body_format, string, VerifyBodyFormat},
- {full_result, true, VerifyFullResult},
- {headers_as_is, false, VerifyHeaderAsIs},
- {receiver, self(), VerifyReceiver},
- {socket_opts, undefined, VerifySocketOpts}
+ {sync, true, VerifySync},
+ {stream, none, VerifyStream},
+ {body_format, string, VerifyBodyFormat},
+ {full_result, true, VerifyFullResult},
+ {headers_as_is, false, VerifyHeaderAsIs},
+ {receiver, self(), VerifyReceiver},
+ {socket_opts, undefined, VerifySocketOpts},
+ {ipv6_host_with_brackets, false, VerifyBrackets}
].
request_options(Options) ->
diff --git a/lib/inets/src/http_client/httpc_cookie.erl b/lib/inets/src/http_client/httpc_cookie.erl
index 4d61f82b5a..69900bae65 100644
--- a/lib/inets/src/http_client/httpc_cookie.erl
+++ b/lib/inets/src/http_client/httpc_cookie.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -18,12 +18,32 @@
%%
%% Description: Cookie handling according to RFC 2109
+%% The syntax for the Set-Cookie response header is
+%%
+%% set-cookie = "Set-Cookie:" cookies
+%% cookies = 1#cookie
+%% cookie = NAME "=" VALUE *(";" cookie-av)
+%% NAME = attr
+%% VALUE = value
+%% cookie-av = "Comment" "=" value
+%% | "Domain" "=" value
+%% | "Max-Age" "=" value
+%% | "Path" "=" value
+%% | "Secure"
+%% | "Version" "=" 1*DIGIT
+
+
+%% application:start(inets).
+%% httpc:set_options([{cookies, enabled}, {proxy, {{"www-proxy.ericsson.se",8080}, ["*.ericsson.se"]}}]).
+%% (catch httpc:request("http://www.expedia.com")).
+
-module(httpc_cookie).
-include("httpc_internal.hrl").
-export([open_db/3, close_db/1, insert/2, header/4, cookies/3]).
-export([reset_db/1, which_cookies/1]).
+-export([image_of/2, print/2]).
-record(cookie_db, {db, session_db}).
@@ -125,7 +145,7 @@ insert(#cookie_db{db = Db} = CookieDb,
name = Name,
path = Path,
max_age = 0}) ->
- ?hcrt("insert", [{domain, Key}, {name, Name}, {path, Path}]),
+ ?hcrt("insert cookie", [{domain, Key}, {name, Name}, {path, Path}]),
Pattern = #http_cookie{domain = Key, name = Name, path = Path, _ = '_'},
case dets:match_object(Db, Pattern) of
[] ->
@@ -136,7 +156,7 @@ insert(#cookie_db{db = Db} = CookieDb,
ok;
insert(#cookie_db{db = Db} = CookieDb,
#http_cookie{domain = Key, name = Name, path = Path} = Cookie) ->
- ?hcrt("insert", [{cookie, Cookie}]),
+ ?hcrt("insert cookie", [{cookie, Cookie}]),
Pattern = #http_cookie{domain = Key,
name = Name,
path = Path,
@@ -163,6 +183,7 @@ header(CookieDb, Scheme, {Host, _}, Path) ->
[] ->
{"cookie", ""};
Cookies ->
+ %% print_cookies("Header Cookies", Cookies),
{"cookie", cookies_to_string(Scheme, Cookies)}
end.
@@ -173,11 +194,20 @@ header(CookieDb, Scheme, {Host, _}, Path) ->
%%--------------------------------------------------------------------
cookies(Headers, RequestPath, RequestHost) ->
+
?hcrt("cookies", [{headers, Headers},
{request_path, RequestPath},
{request_host, RequestHost}]),
+
Cookies = parse_set_cookies(Headers, {RequestPath, RequestHost}),
- accept_cookies(Cookies, RequestPath, RequestHost).
+
+ %% print_cookies("Parsed Cookies", Cookies),
+
+ AcceptedCookies = accept_cookies(Cookies, RequestPath, RequestHost),
+
+ %% print_cookies("Accepted Cookies", AcceptedCookies),
+
+ AcceptedCookies.
%%--------------------------------------------------------------------
@@ -266,7 +296,8 @@ cookies_to_string(_, [], CookieStrs) ->
lists:flatten(lists:reverse(CookieStrs))
end;
-cookies_to_string(https, [#http_cookie{secure = true} = Cookie| Cookies],
+cookies_to_string(https = Scheme,
+ [#http_cookie{secure = true} = Cookie| Cookies],
CookieStrs) ->
Str = case Cookies of
[] ->
@@ -274,7 +305,7 @@ cookies_to_string(https, [#http_cookie{secure = true} = Cookie| Cookies],
_ ->
cookie_to_string(Cookie) ++ "; "
end,
- cookies_to_string(https, Cookies, [Str | CookieStrs]);
+ cookies_to_string(Scheme, Cookies, [Str | CookieStrs]);
cookies_to_string(Scheme, [#http_cookie{secure = true}| Cookies],
CookieStrs) ->
@@ -303,63 +334,54 @@ add_domain(Str, #http_cookie{domain_default = true}) ->
add_domain(Str, #http_cookie{domain = Domain}) ->
Str ++ "; $Domain=" ++ Domain.
-parse_set_cookies(OtherHeaders, DefaultPathDomain) ->
- SetCookieHeaders =
- lists:foldl(fun({"set-cookie", Value}, Acc) ->
- [string:tokens(Value, ",")| Acc];
- (_, Acc) ->
- Acc
- end, [], OtherHeaders),
-
- lists:flatten(
- lists:map(fun(CookieHeader) ->
- NewHeader = fix_netscape_cookie(CookieHeader, []),
- parse_set_cookie(NewHeader, [], DefaultPathDomain)
- end,
- SetCookieHeaders)).
-
-parse_set_cookie([], AccCookies, _) ->
- AccCookies;
-parse_set_cookie([CookieHeader | CookieHeaders], AccCookies,
- Defaults = {DefaultPath, DefaultDomain}) ->
- [CookieStr | Attributes] = case string:tokens(CookieHeader, ";") of
- [CStr] ->
- [CStr, ""];
- [CStr | Attr] ->
- [CStr, Attr]
- end,
- Pos = string:chr(CookieStr, $=),
- Name = string:substr(CookieStr, 1, Pos - 1),
- Value = string:substr(CookieStr, Pos + 1),
- Cookie = #http_cookie{name = string:strip(Name),
- value = string:strip(Value)},
- NewAttributes = parse_set_cookie_attributes(Attributes),
- TmpCookie = cookie_attributes(NewAttributes, Cookie),
+parse_set_cookies(CookieHeaders, DefaultPathDomain) ->
+ SetCookieHeaders = [Value || {"set-cookie", Value} <- CookieHeaders],
+ Cookies = [parse_set_cookie(SetCookieHeader, DefaultPathDomain) ||
+ SetCookieHeader <- SetCookieHeaders],
+ %% print_cookies("Parsed Cookies", Cookies),
+ Cookies.
+
+parse_set_cookie(CookieHeader, {DefaultPath, DefaultDomain}) ->
+ %% io:format("Raw Cookie: ~s~n", [CookieHeader]),
+ Pos = string:chr(CookieHeader, $=),
+ Name = string:substr(CookieHeader, 1, Pos - 1),
+ {Value, Attrs} =
+ case string:substr(CookieHeader, Pos + 1) of
+ [$;|ValueAndAttrs] ->
+ {"", string:tokens(ValueAndAttrs, ";")};
+ ValueAndAttrs ->
+ [V | A] = string:tokens(ValueAndAttrs, ";"),
+ {V, A}
+ end,
+ Cookie = #http_cookie{name = string:strip(Name),
+ value = string:strip(Value)},
+ Attributes = parse_set_cookie_attributes(Attrs),
+ TmpCookie = cookie_attributes(Attributes, Cookie),
%% Add runtime defult values if necessary
- NewCookie = domain_default(path_default(TmpCookie, DefaultPath),
- DefaultDomain),
- parse_set_cookie(CookieHeaders, [NewCookie | AccCookies], Defaults).
-
-parse_set_cookie_attributes([]) ->
- [];
-parse_set_cookie_attributes([Attributes]) ->
- lists:map(fun(Attr) ->
- [AttrName, AttrValue] =
- case string:tokens(Attr, "=") of
- %% All attributes have the form
- %% Name=Value except "secure"!
- [Name] ->
- [Name, ""];
- [Name, Value] ->
- [Name, Value];
- %% Anything not expected will be
- %% disregarded
- _ ->
- ["Dummy",""]
- end,
- {http_util:to_lower(string:strip(AttrName)),
- string:strip(AttrValue)}
- end, Attributes).
+ NewCookie = domain_default(path_default(TmpCookie, DefaultPath),
+ DefaultDomain),
+ NewCookie.
+
+parse_set_cookie_attributes(Attributes) when is_list(Attributes) ->
+ [parse_set_cookie_attribute(A) || A <- Attributes].
+
+parse_set_cookie_attribute(Attribute) ->
+ {AName, AValue} =
+ case string:tokens(Attribute, "=") of
+ %% All attributes have the form
+ %% Name=Value except "secure"!
+ [Name] ->
+ {Name, ""};
+ [Name, Value] ->
+ {Name, Value};
+ %% Anything not expected will be
+ %% disregarded
+ _ ->
+ {"Dummy", ""}
+ end,
+ StrippedName = http_util:to_lower(string:strip(AName)),
+ StrippedValue = string:strip(AValue),
+ {StrippedName, StrippedValue}.
cookie_attributes([], Cookie) ->
Cookie;
@@ -375,10 +397,15 @@ cookie_attributes([{"max-age", Value}| Attributes], Cookie) ->
Cookie#http_cookie{max_age = ExpireTime});
%% Backwards compatibility with netscape cookies
cookie_attributes([{"expires", Value}| Attributes], Cookie) ->
- Time = http_util:convert_netscapecookie_date(Value),
- ExpireTime = calendar:datetime_to_gregorian_seconds(Time),
- cookie_attributes(Attributes,
- Cookie#http_cookie{max_age = ExpireTime});
+ try http_util:convert_netscapecookie_date(Value) of
+ Time ->
+ ExpireTime = calendar:datetime_to_gregorian_seconds(Time),
+ cookie_attributes(Attributes,
+ Cookie#http_cookie{max_age = ExpireTime})
+ catch
+ _:_ ->
+ cookie_attributes(Attributes, Cookie)
+ end;
cookie_attributes([{"path", Value}| Attributes], Cookie) ->
cookie_attributes(Attributes,
Cookie#http_cookie{path = Value});
@@ -404,7 +431,7 @@ path_default(#http_cookie{path = undefined} = Cookie, DefaultPath) ->
path_default(Cookie, _) ->
Cookie.
-%% Note: if the path is only / that / will be keept
+%% Note: if the path is only / that / will be kept
skip_right_most_slash("/") ->
"/";
skip_right_most_slash(Str) ->
@@ -476,20 +503,43 @@ path_sort(Cookies)->
lists:reverse(lists:keysort(#http_cookie.path, Cookies)).
-%% Informally, the Set-Cookie response header comprises the token
-%% Set-Cookie:, followed by a comma-separated list of one or more
-%% cookies. Netscape cookies expires attribute may also have a,
-%% in this case the header list will have been incorrectly split
-%% in parse_set_cookies/2 this functions fix that problem.
-fix_netscape_cookie([Cookie1, Cookie2 | Rest], Acc) ->
- case inets_regexp:match(string:to_lower(Cookie1), "expires=") of
- {_, _, _} ->
- fix_netscape_cookie(Rest, [Cookie1 ++ Cookie2 | Acc]);
- nomatch ->
- fix_netscape_cookie([Cookie2 |Rest], [Cookie1| Acc])
- end;
-fix_netscape_cookie([Cookie | Rest], Acc) ->
- fix_netscape_cookie(Rest, [Cookie | Acc]);
-
-fix_netscape_cookie([], Acc) ->
- Acc.
+%% print_cookies(Header, Cookies) ->
+%% io:format("~s:~n", [Header]),
+%% Prefix = " ",
+%% lists:foreach(fun(Cookie) -> print(Prefix, Cookie) end, Cookies).
+
+image_of(Prefix,
+ #http_cookie{domain = Domain,
+ domain_default = DomainDef,
+ name = Name,
+ value = Value,
+ comment = Comment,
+ max_age = MaxAge,
+ path = Path,
+ path_default = PathDef,
+ secure = Sec,
+ version = Version}) ->
+ lists:flatten(
+ io_lib:format("~sCookie ~s: "
+ "~n~s Value: ~p"
+ "~n~s Domain: ~p"
+ "~n~s DomainDef: ~p"
+ "~n~s Comment: ~p"
+ "~n~s MaxAge: ~p"
+ "~n~s Path: ~p"
+ "~n~s PathDef: ~p"
+ "~n~s Secure: ~p"
+ "~n~s Version: ~p",
+ [Prefix, Name,
+ Prefix, Value,
+ Prefix, Domain,
+ Prefix, DomainDef,
+ Prefix, Comment,
+ Prefix, MaxAge,
+ Prefix, Path,
+ Prefix, PathDef,
+ Prefix, Sec,
+ Prefix, Version])).
+
+print(Prefix, Cookie) when is_record(Cookie, http_cookie) ->
+ io:format("~s~n", [image_of(Prefix, Cookie)]).
diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl
index 9ac9ee6f7b..587e24cc8d 100644
--- a/lib/inets/src/http_client/httpc_handler.erl
+++ b/lib/inets/src/http_client/httpc_handler.erl
@@ -1157,7 +1157,7 @@ handle_cookies(Headers, Request, #options{cookies = enabled}, ProfileName) ->
httpc_manager:store_cookies(Cookies, Request#request.address,
ProfileName).
-%% This request could not be pipelined or used as sequential keept alive
+%% This request could not be pipelined or used as sequential keep alive
%% queue
handle_queue(#state{status = close} = State, _) ->
{stop, normal, State};
diff --git a/lib/inets/src/http_client/httpc_internal.hrl b/lib/inets/src/http_client/httpc_internal.hrl
index 1d8a5b6a92..e4127d992d 100644
--- a/lib/inets/src/http_client/httpc_internal.hrl
+++ b/lib/inets/src/http_client/httpc_internal.hrl
@@ -90,25 +90,28 @@
%%% All data associated to a specific HTTP request
-record(request,
{
- id, % ref() - Request Id
- from, % pid() - Caller
- redircount = 0,% Number of redirects made for this request
- scheme, % http | https
- address, % ({Host,Port}) Destination Host and Port
- path, % string() - Path of parsed URL
- pquery, % string() - Rest of parsed URL
- method, % atom() - HTTP request Method
- headers, % #http_request_h{}
- content, % {ContentType, Body} - Current HTTP request
- settings, % #http_options{} - User defined settings
- abs_uri, % string() ex: "http://www.erlang.org"
- userinfo, % string() - optinal "<userinfo>@<host>:<port>"
- stream, % Boolean() - stream async reply?
- headers_as_is, % Boolean() - workaround for servers that does
- % not honor the http standard, can also be used for testing purposes.
- started, % integer() > 0 - When we started processing the request
- timer, % undefined | ref()
- socket_opts % undefined | [socket_option()]
+ id, % ref() - Request Id
+ from, % pid() - Caller
+ redircount = 0,% Number of redirects made for this request
+ scheme, % http | https
+ address, % ({Host,Port}) Destination Host and Port
+ path, % string() - Path of parsed URL
+ pquery, % string() - Rest of parsed URL
+ method, % atom() - HTTP request Method
+ headers, % #http_request_h{}
+ content, % {ContentType, Body} - Current HTTP request
+ settings, % #http_options{} - User defined settings
+ abs_uri, % string() ex: "http://www.erlang.org"
+ userinfo, % string() - optinal "<userinfo>@<host>:<port>"
+ stream, % boolean() - stream async reply?
+ headers_as_is, % boolean() - workaround for servers that does
+ % not honor the http standard, can also be used
+ % for testing purposes.
+ started, % integer() > 0 - When we started processing the
+ % request
+ timer, % undefined | ref()
+ socket_opts, % undefined | [socket_option()]
+ ipv6_host_with_brackets % boolean()
}
).
diff --git a/lib/inets/src/http_client/httpc_manager.erl b/lib/inets/src/http_client/httpc_manager.erl
index 9015bf1ce2..ab575d867e 100644
--- a/lib/inets/src/http_client/httpc_manager.erl
+++ b/lib/inets/src/http_client/httpc_manager.erl
@@ -256,19 +256,27 @@ reset_cookies(ProfileName) ->
%%--------------------------------------------------------------------
-%% Function: which_cookies(Url, ProfileName) -> [cookie()]
+%% Function: which_cookies(ProfileName) -> [cookie()]
+%% which_cookies(Url, ProfileName) -> [cookie()]
+%% which_cookies(Url, Options, ProfileName) -> [cookie()]
%%
%% Url = string()
+%% Options = [option()]
%% ProfileName = atom()
+%% option() = {ipv6_host_with_brackets, boolean()}
%%
%% Description: Retrieves the cookies that would be sent when
%% requesting <Url>.
%%--------------------------------------------------------------------
-which_cookies(ProfileName) ->
+which_cookies(ProfileName) when is_atom(ProfileName) ->
call(ProfileName, which_cookies).
-which_cookies(Url, ProfileName) ->
- call(ProfileName, {which_cookies, Url}).
+which_cookies(Url, ProfileName)
+ when is_list(Url) andalso is_atom(ProfileName) ->
+ call(ProfileName, {which_cookies, Url, []}).
+which_cookies(Url, Options, ProfileName)
+ when is_list(Url) andalso is_list(Options) andalso is_atom(ProfileName) ->
+ call(ProfileName, {which_cookies, Url, Options}).
%%--------------------------------------------------------------------
@@ -395,15 +403,16 @@ handle_call(which_cookies, _, #state{cookie_db = CookieDb} = State) ->
CookieHeaders = httpc_cookie:which_cookies(CookieDb),
{reply, CookieHeaders, State};
-handle_call({which_cookies, Url}, _, #state{cookie_db = CookieDb} = State) ->
- ?hcrv("which cookies", [{url, Url}]),
- case http_uri:parse(Url) of
- {Scheme, _, Host, Port, Path, _} ->
+handle_call({which_cookies, Url, Options}, _,
+ #state{cookie_db = CookieDb} = State) ->
+ ?hcrv("which cookies", [{url, Url}, {options, Options}]),
+ case http_uri:parse(Url, Options) of
+ {ok, {Scheme, _, Host, Port, Path, _}} ->
CookieHeaders =
httpc_cookie:header(CookieDb, Scheme, {Host, Port}, Path),
{reply, CookieHeaders, State};
- Msg ->
- {reply, Msg, State}
+ {error, _} = ERROR ->
+ {reply, ERROR, State}
end;
handle_call(info, _, State) ->
diff --git a/lib/inets/src/http_client/httpc_response.erl b/lib/inets/src/http_client/httpc_response.erl
index 207b96271c..2414ed0911 100644
--- a/lib/inets/src/http_client/httpc_response.erl
+++ b/lib/inets/src/http_client/httpc_response.erl
@@ -340,7 +340,9 @@ redirect(Response = {StatusLine, Headers, Body}, Request) ->
undefined ->
transparent(Response, Request);
RedirUrl ->
- case http_uri:parse(RedirUrl) of
+ UrlParseOpts = [{ipv6_host_with_brackets,
+ Request#request.ipv6_host_with_brackets}],
+ case http_uri:parse(RedirUrl, UrlParseOpts) of
{error, no_scheme} when
(Request#request.settings)#http_options.relaxed ->
NewLocation = fix_relative_uri(Request, RedirUrl),
@@ -350,10 +352,9 @@ redirect(Response = {StatusLine, Headers, Body}, Request) ->
{error, Reason} ->
{ok, error(Request, Reason), Data};
%% Automatic redirection
- {Scheme, _, Host, Port, Path, Query} ->
+ {ok, {Scheme, _, Host, Port, Path, Query}} ->
NewHeaders =
- (Request#request.headers)#http_request_h{host =
- Host},
+ (Request#request.headers)#http_request_h{host = Host},
NewRequest =
Request#request{redircount =
Request#request.redircount+1,
diff --git a/lib/inets/src/http_lib/http_internal.hrl b/lib/inets/src/http_lib/http_internal.hrl
index 2e924667c6..97cf474ab9 100644
--- a/lib/inets/src/http_lib/http_internal.hrl
+++ b/lib/inets/src/http_lib/http_internal.hrl
@@ -28,7 +28,6 @@
-define(HTTP_MAX_URI_SIZE, nolimit).
-ifndef(HTTP_DEFAULT_SSL_KIND).
-%% -define(HTTP_DEFAULT_SSL_KIND, ossl).
-define(HTTP_DEFAULT_SSL_KIND, essl).
-endif. % -ifdef(HTTP_DEFAULT_SSL_KIND).
diff --git a/lib/inets/src/http_lib/http_transport.erl b/lib/inets/src/http_lib/http_transport.erl
index 9b8190ebed..5eb827032f 100644
--- a/lib/inets/src/http_lib/http_transport.erl
+++ b/lib/inets/src/http_lib/http_transport.erl
@@ -62,8 +62,6 @@ start(ip_comm) ->
%% This is just for backward compatibillity
start({ssl, _}) ->
do_start_ssl();
-start({ossl, _}) ->
- do_start_ssl();
start({essl, _}) ->
do_start_ssl().
@@ -126,22 +124,6 @@ connect(ip_comm = _SocketType, {Host, Port}, Opts0, Timeout)
connect({ssl, SslConfig}, Address, Opts, Timeout) ->
connect({?HTTP_DEFAULT_SSL_KIND, SslConfig}, Address, Opts, Timeout);
-connect({ossl, SslConfig}, {Host, Port}, _, Timeout) ->
- Opts = [binary, {active, false}, {ssl_imp, old}] ++ SslConfig,
- ?hlrt("connect using ossl",
- [{host, Host},
- {port, Port},
- {ssl_config, SslConfig},
- {timeout, Timeout}]),
- case (catch ssl:connect(Host, Port, Opts, Timeout)) of
- {'EXIT', Reason} ->
- {error, {eoptions, Reason}};
- {ok, _} = OK ->
- OK;
- {error, _} = ERROR ->
- ERROR
- end;
-
connect({essl, SslConfig}, {Host, Port}, Opts0, Timeout) ->
Opts = [binary, {active, false}, {ssl_imp, new} | Opts0] ++ SslConfig,
?hlrt("connect using essl",
@@ -187,13 +169,6 @@ listen({ssl, SSLConfig}, Addr, Port) ->
{ssl_config, SSLConfig}]),
listen({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Addr, Port);
-listen({ossl, SSLConfig}, Addr, Port) ->
- ?hlrt("listen (ossl)",
- [{addr, Addr},
- {port, Port},
- {ssl_config, SSLConfig}]),
- listen_ssl(Addr, Port, [{ssl_imp, old} | SSLConfig]);
-
listen({essl, SSLConfig}, Addr, Port) ->
?hlrt("listen (essl)",
[{addr, Addr},
@@ -353,8 +328,6 @@ accept(ip_comm, ListenSocket, Timeout) ->
accept({ssl, SSLConfig}, ListenSocket, Timeout) ->
accept({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, ListenSocket, Timeout);
-accept({ossl, _SSLConfig}, ListenSocket, Timeout) ->
- ssl:transport_accept(ListenSocket, Timeout);
accept({essl, _SSLConfig}, ListenSocket, Timeout) ->
ssl:transport_accept(ListenSocket, Timeout).
@@ -374,9 +347,6 @@ controlling_process(ip_comm, Socket, NewOwner) ->
controlling_process({ssl, SSLConfig}, Socket, NewOwner) ->
controlling_process({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, NewOwner);
-controlling_process({ossl, _}, Socket, NewOwner) ->
- ssl:controlling_process(Socket, NewOwner);
-
controlling_process({essl, _}, Socket, NewOwner) ->
ssl:controlling_process(Socket, NewOwner).
@@ -397,13 +367,6 @@ setopts(ip_comm, Socket, Options) ->
setopts({ssl, SSLConfig}, Socket, Options) ->
setopts({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Options);
-setopts({ossl, _}, Socket, Options) ->
- ?hlrt("[o]ssl setopts", [{socket, Socket}, {options, Options}]),
- Reason = (catch ssl:setopts(Socket, Options)),
- ?hlrt("[o]ssl setopts result", [{reason, Reason}]),
- Reason;
-
-
setopts({essl, _}, Socket, Options) ->
?hlrt("[e]ssl setopts", [{socket, Socket}, {options, Options}]),
Reason = (catch ssl:setopts(Socket, Options)),
@@ -435,10 +398,6 @@ getopts(ip_comm, Socket, Options) ->
getopts({ssl, SSLConfig}, Socket, Options) ->
getopts({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Options);
-getopts({ossl, _}, Socket, Options) ->
- ?hlrt("ssl getopts", [{socket, Socket}, {options, Options}]),
- getopts_ssl(Socket, Options);
-
getopts({essl, _}, Socket, Options) ->
?hlrt("essl getopts", [{socket, Socket}, {options, Options}]),
getopts_ssl(Socket, Options).
@@ -472,9 +431,6 @@ getstat(ip_comm = _SocketType, Socket) ->
getstat({ssl, SSLConfig}, Socket) ->
getstat({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket);
-getstat({ossl, _} = _SocketType, _Socket) ->
- [];
-
getstat({essl, _} = _SocketType, _Socket) ->
[].
@@ -493,9 +449,6 @@ send(ip_comm, Socket, Message) ->
send({ssl, SSLConfig}, Socket, Message) ->
send({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Message);
-send({ossl, _}, Socket, Message) ->
- ssl:send(Socket, Message);
-
send({essl, _}, Socket, Message) ->
ssl:send(Socket, Message).
@@ -514,9 +467,6 @@ close(ip_comm, Socket) ->
close({ssl, SSLConfig}, Socket) ->
close({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket);
-close({ossl, _}, Socket) ->
- ssl:close(Socket);
-
close({essl, _}, Socket) ->
ssl:close(Socket).
@@ -538,9 +488,6 @@ peername(ip_comm, Socket) ->
peername({ssl, SSLConfig}, Socket) ->
peername({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket);
-peername({ossl, _}, Socket) ->
- do_peername(ssl:peername(Socket));
-
peername({essl, _}, Socket) ->
do_peername(ssl:peername(Socket)).
@@ -573,9 +520,6 @@ sockname(ip_comm, Socket) ->
sockname({ssl, SSLConfig}, Socket) ->
sockname({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket);
-sockname({ossl, _}, Socket) ->
- do_sockname(ssl:sockname(Socket));
-
sockname({essl, _}, Socket) ->
do_sockname(ssl:sockname(Socket)).
@@ -651,9 +595,6 @@ negotiate(ip_comm,_,_) ->
negotiate({ssl, SSLConfig}, Socket, Timeout) ->
?hlrt("negotiate(ssl)", []),
negotiate({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Timeout);
-negotiate({ossl, _}, Socket, Timeout) ->
- ?hlrt("negotiate(ossl)", []),
- negotiate_ssl(Socket, Timeout);
negotiate({essl, _}, Socket, Timeout) ->
?hlrt("negotiate(essl)", []),
negotiate_ssl(Socket, Timeout).
diff --git a/lib/inets/src/http_lib/http_uri.erl b/lib/inets/src/http_lib/http_uri.erl
index 44b9face0b..32c6305a79 100644
--- a/lib/inets/src/http_lib/http_uri.erl
+++ b/lib/inets/src/http_lib/http_uri.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -16,23 +16,30 @@
%%
%% %CopyrightEnd%
%%
-%%
+%%
+%% RFC 3986
+%%
-module(http_uri).
--export([parse/1, encode/1, decode/1]).
+-export([parse/1, parse/2,
+ encode/1, decode/1]).
+
%%%=========================================================================
%%% API
%%%=========================================================================
parse(AbsURI) ->
+ parse(AbsURI, []).
+
+parse(AbsURI, Opts) ->
case parse_scheme(AbsURI) of
{error, Reason} ->
{error, Reason};
{Scheme, Rest} ->
- case (catch parse_uri_rest(Scheme, Rest)) of
+ case (catch parse_uri_rest(Scheme, Rest, Opts)) of
{UserInfo, Host, Port, Path, Query} ->
- {Scheme, UserInfo, Host, Port, Path, Query};
+ {ok, {Scheme, UserInfo, Host, Port, Path, Query}};
_ ->
{error, {malformed_url, AbsURI}}
end
@@ -42,35 +49,38 @@ encode(URI) ->
Reserved = sets:from_list([$;, $:, $@, $&, $=, $+, $,, $/, $?,
$#, $[, $], $<, $>, $\", ${, $}, $|,
$\\, $', $^, $%, $ ]),
- lists:append(lists:map(fun(Char) ->
- uri_encode(Char, Reserved)
- end, URI)).
-
-decode([$%,Hex1,Hex2|Rest]) ->
- [hex2dec(Hex1)*16+hex2dec(Hex2)|decode(Rest)];
-decode([First|Rest]) ->
- [First|decode(Rest)];
-decode([]) ->
+ %% lists:append(lists:map(fun(Char) -> uri_encode(Char, Reserved) end, URI)).
+ lists:append([uri_encode(Char, Reserved) || Char <- URI]).
+
+decode(String) ->
+ do_decode(String).
+
+do_decode([$%,Hex1,Hex2|Rest]) ->
+ [hex2dec(Hex1)*16+hex2dec(Hex2)|do_decode(Rest)];
+do_decode([First|Rest]) ->
+ [First|do_decode(Rest)];
+do_decode([]) ->
[].
+
%%%========================================================================
%%% Internal functions
%%%========================================================================
+
parse_scheme(AbsURI) ->
case split_uri(AbsURI, ":", {error, no_scheme}, 1, 1) of
{error, no_scheme} ->
{error, no_scheme};
{StrScheme, Rest} ->
case list_to_atom(http_util:to_lower(StrScheme)) of
- Scheme when Scheme == http; Scheme == https ->
+ Scheme when (Scheme =:= http) orelse (Scheme =:= https) ->
{Scheme, Rest};
Scheme ->
{error, {not_supported_scheme, Scheme}}
end
end.
-parse_uri_rest(Scheme, "//" ++ URIPart) ->
-
+parse_uri_rest(Scheme, "//" ++ URIPart, Opts) ->
{Authority, PathQuery} =
case split_uri(URIPart, "/", URIPart, 1, 0) of
Split = {_, _} ->
@@ -85,8 +95,8 @@ parse_uri_rest(Scheme, "//" ++ URIPart) ->
end,
{UserInfo, HostPort} = split_uri(Authority, "@", {"", Authority}, 1, 1),
- {Host, Port} = parse_host_port(Scheme, HostPort),
- {Path, Query} = parse_path_query(PathQuery),
+ {Host, Port} = parse_host_port(Scheme, HostPort, Opts),
+ {Path, Query} = parse_path_query(PathQuery),
{UserInfo, Host, Port, Path, Query}.
@@ -94,13 +104,14 @@ parse_path_query(PathQuery) ->
{Path, Query} = split_uri(PathQuery, "\\?", {PathQuery, ""}, 1, 0),
{path(Path), Query}.
-parse_host_port(Scheme,"[" ++ HostPort) -> %ipv6
+parse_host_port(Scheme,"[" ++ HostPort, Opts) -> %ipv6
DefaultPort = default_port(Scheme),
{Host, ColonPort} = split_uri(HostPort, "\\]", {HostPort, ""}, 1, 1),
+ Host2 = maybe_ipv6_host_with_brackets(Host, Opts),
{_, Port} = split_uri(ColonPort, ":", {"", DefaultPort}, 0, 1),
- {Host, int_port(Port)};
+ {Host2, int_port(Port)};
-parse_host_port(Scheme, HostPort) ->
+parse_host_port(Scheme, HostPort, _Opts) ->
DefaultPort = default_port(Scheme),
{Host, Port} = split_uri(HostPort, ":", {HostPort, DefaultPort}, 1, 1),
{Host, int_port(Port)}.
@@ -114,6 +125,14 @@ split_uri(UriPart, SplitChar, NoMatchResult, SkipLeft, SkipRight) ->
NoMatchResult
end.
+maybe_ipv6_host_with_brackets(Host, Opts) ->
+ case lists:keysearch(ipv6_host_with_brackets, 1, Opts) of
+ {value, {ipv6_host_with_brackets, true}} ->
+ "[" ++ Host ++ "]";
+ _ ->
+ Host
+ end.
+
default_port(http) ->
80;
default_port(https) ->
diff --git a/lib/inets/src/http_lib/http_util.erl b/lib/inets/src/http_lib/http_util.erl
index 5511ed388d..5b21170b78 100644
--- a/lib/inets/src/http_lib/http_util.erl
+++ b/lib/inets/src/http_lib/http_util.erl
@@ -104,6 +104,22 @@ convert_netscapecookie_date([_D,_A,_Y, $ ,
Sec = list_to_integer([S1,S2]),
{{Year,Month,Day},{Hour,Min,Sec}};
+%% Example: Tue Jan 01 08:00:01 2036 GMT
+convert_netscapecookie_date([_D,_A,_Y, $ ,
+ M,O,N, $ ,
+ D1,D2, $ ,
+ H1,H2, $:,
+ M1,M2, $:,
+ S1,S2, $ ,
+ Y1,Y2,Y3,Y4, $ |_Rest]) ->
+ Year = list_to_integer([Y1,Y2,Y3,Y4]),
+ Day = list_to_integer([D1,D2]),
+ Month = convert_month([M,O,N]),
+ Hour = list_to_integer([H1,H2]),
+ Min = list_to_integer([M1,M2]),
+ Sec = list_to_integer([S1,S2]),
+ {{Year,Month,Day},{Hour,Min,Sec}};
+
%% Sloppy...
convert_netscapecookie_date([_D,_A,_Y, $,, _SP,
D1,D2,_DA,
@@ -190,9 +206,7 @@ timeout(Timeout, Started) ->
html_encode(Chars) ->
Reserved = sets:from_list([$&, $<, $>, $\", $', $/]),
- lists:append(lists:map(fun(Char) ->
- char_to_html_entity(Char, Reserved)
- end, Chars)).
+ lists:append([char_to_html_entity(Char, Reserved) || Char <- Chars]).
%%%========================================================================
diff --git a/lib/inets/src/http_server/httpd_conf.erl b/lib/inets/src/http_server/httpd_conf.erl
index f4d8a6c09f..7646300409 100644
--- a/lib/inets/src/http_server/httpd_conf.erl
+++ b/lib/inets/src/http_server/httpd_conf.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -219,9 +219,8 @@ load("ServerName " ++ ServerName, []) ->
load("SocketType " ++ SocketType, []) ->
%% ssl is the same as HTTP_DEFAULT_SSL_KIND
- %% ossl is ssl based on OpenSSL (the "old" ssl)
%% essl is the pure Erlang-based ssl (the "new" ssl)
- case check_enum(clean(SocketType), ["ssl", "ossl", "essl", "ip_comm"]) of
+ case check_enum(clean(SocketType), ["ssl", "essl", "ip_comm"]) of
{ok, ValidSocketType} ->
{ok, [], {socket_type, ValidSocketType}};
{error,_} ->
@@ -305,7 +304,7 @@ load("MaxKeepAliveRequests " ++ MaxRequests, []) ->
" is an invalid MaxKeepAliveRequests")}
end;
-%% This clause is keept for backwards compability
+%% This clause is kept for backwards compatibility
load("MaxKeepAliveRequest " ++ MaxRequests, []) ->
case make_integer(MaxRequests) of
{ok, Integer} ->
@@ -541,7 +540,6 @@ validate_config_params([{server_name, Value} | _]) ->
validate_config_params([{socket_type, Value} | Rest])
when (Value =:= ip_comm) orelse
(Value =:= ssl) orelse
- (Value =:= ossl) orelse
(Value =:= essl) ->
validate_config_params(Rest);
validate_config_params([{socket_type, Value} | _]) ->
@@ -811,7 +809,7 @@ lookup_socket_type(ConfigDB) ->
case httpd_util:lookup(ConfigDB, socket_type, ip_comm) of
ip_comm ->
ip_comm;
- SSL when (SSL =:= ssl) orelse (SSL =:= ossl) orelse (SSL =:= essl) ->
+ SSL when (SSL =:= ssl) orelse (SSL =:= essl) ->
SSLTag =
if
(SSL =:= ssl) ->
diff --git a/lib/inets/src/http_server/httpd_esi.erl b/lib/inets/src/http_server/httpd_esi.erl
index 026ec9a5fe..000874d0a3 100644
--- a/lib/inets/src/http_server/httpd_esi.erl
+++ b/lib/inets/src/http_server/httpd_esi.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -39,7 +39,7 @@
%% body part. Note that it is presumed that <Data> starts with a
%% string including "\r\n\r\n" if there is any header information
%% present. The returned headers will not contain the HTTP header body
-%% delimiter \r\n. (All header, header delimiters are keept.)
+%% delimiter \r\n. (All header, header delimiters are kept.)
%% Ex: ["Content-Type : text/html\r\n Connection : closing \r\n\r\n" |
%% io_list()] --> {"Content-Type : text/html\r\n Connection : closing \r\n",
%% io_list()}
diff --git a/lib/inets/src/http_server/httpd_file.erl b/lib/inets/src/http_server/httpd_file.erl
index ccc1f7874a..f2ba33099e 100644
--- a/lib/inets/src/http_server/httpd_file.erl
+++ b/lib/inets/src/http_server/httpd_file.erl
@@ -33,12 +33,12 @@ handle_error(enotdir, Op, ModData, Path) ->
handle_error(404, Op, ModData, Path,
": A component of the file name is not a directory");
handle_error(emfile, Op, _ModData, Path) ->
- handle_error(500, Op, none, Path, ": To many open files");
+ handle_error(500, Op, none, Path, ": Too many open files");
handle_error({enfile,_}, Op, _ModData, Path) ->
handle_error(500, Op, none, Path, ": File table overflow");
-handle_error(_Reason, Op, ModData, Path) ->
- handle_error(404, Op, ModData, Path, ": File not found").
-
+handle_error(_Reason, Op, _ModData, Path) ->
+ handle_error(500, Op, none, Path, "").
+
handle_error(StatusCode, Op, none, Path, Reason) ->
{StatusCode, none, ?NICE("Can't " ++ Op ++ " " ++ Path ++ Reason)};
handle_error(StatusCode, Op, ModData, Path, Reason) ->
diff --git a/lib/inets/src/http_server/httpd_request.erl b/lib/inets/src/http_server/httpd_request.erl
index 7084d9824a..5ba79b2706 100644
--- a/lib/inets/src/http_server/httpd_request.erl
+++ b/lib/inets/src/http_server/httpd_request.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -309,12 +309,12 @@ validate_uri(RequestURI) ->
(catch http_uri:decode(string:left(RequestURI, Ndx)))
end,
case UriNoQueryNoHex of
- {'EXIT',_Reason} ->
+ {'EXIT', _Reason} ->
{error, {bad_request, {malformed_syntax, RequestURI}}};
_ ->
- Path = format_request_uri(UriNoQueryNoHex),
- Path2=[X||X<-string:tokens(Path, "/"),X=/="."], %% OTP-5938
- validate_path( Path2,0, RequestURI)
+ Path = format_request_uri(UriNoQueryNoHex),
+ Path2 = [X||X<-string:tokens(Path, "/"),X=/="."], %% OTP-5938
+ validate_path(Path2, 0, RequestURI)
end.
validate_path([], _, _) ->
diff --git a/lib/inets/src/http_server/httpd_request_handler.erl b/lib/inets/src/http_server/httpd_request_handler.erl
index c3b47ce390..d2f22fce93 100644
--- a/lib/inets/src/http_server/httpd_request_handler.erl
+++ b/lib/inets/src/http_server/httpd_request_handler.erl
@@ -1,8 +1,8 @@
%%
%% %CopyrightBegin%
-%%
+%%
%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
-%%
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
@@ -355,7 +355,7 @@ handle_http_msg({Method, Uri, Version, {RecordHeaders, Headers}, Body},
Reason = io_lib:format("Forbidden URI: ~p~n", [URI]),
error_log(Reason, ModData),
{stop, normal, State#state{response_sent = true}};
- {error,{bad_request, {malformed_syntax, URI}}} ->
+ {error, {bad_request, {malformed_syntax, URI}}} ->
?hdrd("validation failed: bad request - malformed syntax",
[{uri, URI}]),
httpd_response:send_status(ModData#mod{http_version = Version},
diff --git a/lib/inets/src/http_server/httpd_response.erl b/lib/inets/src/http_server/httpd_response.erl
index ea9cfbf4f2..dd7223876e 100644
--- a/lib/inets/src/http_server/httpd_response.erl
+++ b/lib/inets/src/http_server/httpd_response.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -78,6 +78,7 @@ traverse_modules(ModData,[Module|Rest]) ->
[Module, Reason])),
report_error(mod_log, ModData#mod.config_db, String),
report_error(mod_disk_log, ModData#mod.config_db, String),
+ send_status(ModData, 500, none),
done;
done ->
?hdrt("traverse modules - done", []),
@@ -100,12 +101,19 @@ send_status(#mod{socket_type = SocketType,
socket = Socket,
config_db = ConfigDB} = ModData, StatusCode, PhraseArgs) ->
+ ?hdrd("send status", [{status_code, StatusCode},
+ {phrase_args, PhraseArgs}]),
+
ReasonPhrase = httpd_util:reason_phrase(StatusCode),
Message = httpd_util:message(StatusCode, PhraseArgs, ConfigDB),
Body = get_body(ReasonPhrase, Message),
- send_header(ModData, StatusCode, [{content_type, "text/html"},
- {content_length, integer_to_list(length(Body))}]),
+ ?hdrt("send status - header", [{reason_phrase, ReasonPhrase},
+ {message, Message}]),
+ send_header(ModData, StatusCode,
+ [{content_type, "text/html"},
+ {content_length, integer_to_list(length(Body))}]),
+
httpd_socket:deliver(SocketType, Socket, Body).
@@ -345,8 +353,9 @@ transform({Field, Value}) when is_list(Field) ->
%% Leave this method and go on to the newer form of response
%% OTP-4408
%%----------------------------------------------------------------------
-send_response_old(#mod{method = "HEAD"} = ModData,
+send_response_old(#mod{method = "HEAD"} = ModData,
StatusCode, Response) ->
+
NewResponse = lists:flatten(Response),
case httpd_util:split(NewResponse, [?CR, ?LF, ?CR, ?LF],2) of
diff --git a/lib/inets/src/http_server/httpd_util.erl b/lib/inets/src/http_server/httpd_util.erl
index c051422529..b0b18b9c3d 100644
--- a/lib/inets/src/http_server/httpd_util.erl
+++ b/lib/inets/src/http_server/httpd_util.erl
@@ -178,11 +178,12 @@ message(301,URL,_) ->
"The document has moved <A HREF=\""++ maybe_encode(URL) ++"\">here</A>.";
message(304, _URL,_) ->
"The document has not been changed.";
-message(400,none,_) ->
- "Your browser sent a query that this server could not understand.";
-message(400,Msg,_) ->
- "Your browser sent a query that this server could not understand. "++ http_util:html_encode(Msg);
-message(401,none,_) ->
+message(400, none, _) ->
+ "Your browser sent a query that this server could not understand. ";
+message(400, Msg, _) ->
+ "Your browser sent a query that this server could not understand. " ++
+ html_encode(Msg);
+message(401, none, _) ->
"This server could not verify that you
are authorized to access the document you
requested. Either you supplied the wrong
@@ -190,40 +191,49 @@ credentials (e.g., bad password), or your
browser doesn't understand how to supply
the credentials required.";
message(403,RequestURI,_) ->
- "You don't have permission to access "++ http_util:html_encode(RequestURI) ++" on this server.";
+ "You don't have permission to access " ++
+ html_encode(RequestURI) ++
+ " on this server.";
message(404,RequestURI,_) ->
- "The requested URL " ++ http_util:html_encode(RequestURI) ++ " was not found on this server.";
+ "The requested URL " ++
+ html_encode(RequestURI) ++
+ " was not found on this server.";
message(408, Timeout, _) ->
Timeout;
message(412,none,_) ->
"The requested preconditions were false";
message(413, Reason,_) ->
- "Entity: " ++ http_util:html_encode(Reason);
+ "Entity: " ++ html_encode(Reason);
message(414,ReasonPhrase,_) ->
- "Message "++ http_util:html_encode(ReasonPhrase) ++".";
+ "Message " ++ html_encode(ReasonPhrase) ++ ".";
message(416,ReasonPhrase,_) ->
- http_util:html_encode(ReasonPhrase);
+ html_encode(ReasonPhrase);
message(500,_,ConfigDB) ->
ServerAdmin=lookup(ConfigDB,server_admin,"unknown@unknown"),
"The server encountered an internal error or "
"misconfiguration and was unable to complete "
"your request.<P>Please contact the server administrator "
- ++ http_util:html_encode(ServerAdmin) ++ ", and inform them of the time the error occurred "
+ ++ html_encode(ServerAdmin) ++
+ ", and inform them of the time the error occurred "
"and anything you might have done that may have caused the error.";
message(501,{Method, RequestURI, HTTPVersion}, _ConfigDB) ->
if
is_atom(Method) ->
- http_util:html_encode(atom_to_list(Method))++
- " to "++ http_util:html_encode(RequestURI)++" ("++ http_util:html_encode(HTTPVersion)++") not supported.";
+ atom_to_list(Method) ++
+ " to " ++
+ html_encode(RequestURI) ++
+ " (" ++ HTTPVersion ++ ") not supported.";
is_list(Method) ->
- http_util:html_encode(Method)++
- " to "++ http_util:html_encode(RequestURI)++" ("++ http_util:html_encode(HTTPVersion)++") not supported."
+ Method ++
+ " to " ++
+ html_encode(RequestURI) ++
+ " (" ++ HTTPVersion ++ ") not supported."
end;
message(503, String, _ConfigDB) ->
- "This service in unavailable due to: "++ http_util:html_encode(String).
+ "This service in unavailable due to: " ++ html_encode(String).
maybe_encode(URI) ->
Decoded = try http_uri:decode(URI) of
@@ -233,6 +243,15 @@ maybe_encode(URI) ->
end,
http_uri:encode(Decoded).
+html_encode(String) ->
+ try http_uri:decode(String) of
+ Decoded when is_list(Decoded) ->
+ http_util:html_encode(Decoded)
+ catch
+ _:_ ->
+ http_util:html_encode(String)
+ end.
+
%%convert_rfc_date(Date)->{{YYYY,MM,DD},{HH,MIN,SEC}}
convert_request_date([D,A,Y,DateType| Rest])->
@@ -245,7 +264,7 @@ convert_request_date([D,A,Y,DateType| Rest])->
fun convert_rfc850_date/1
end,
case catch Func([D,A,Y,DateType| Rest]) of
- {ok,Date} ->
+ {ok, Date} ->
Date;
_Error->
bad_date
diff --git a/lib/inets/src/http_server/mod_auth_mnesia.erl b/lib/inets/src/http_server/mod_auth_mnesia.erl
index ffe028617b..91beb0e062 100644
--- a/lib/inets/src/http_server/mod_auth_mnesia.erl
+++ b/lib/inets/src/http_server/mod_auth_mnesia.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -55,7 +55,7 @@ store_directory_data(_Directory, _DirData, _Server_root) ->
%% API
%%
-%% Compability API
+%% Compatibility API
store_user(UserName, Password, Port, Dir, _AccessPassword) ->
%% AccessPassword is ignored - was not used in previous version
diff --git a/lib/inets/src/http_server/mod_responsecontrol.erl b/lib/inets/src/http_server/mod_responsecontrol.erl
index 5d5b60cdbd..989f45db20 100644
--- a/lib/inets/src/http_server/mod_responsecontrol.erl
+++ b/lib/inets/src/http_server/mod_responsecontrol.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -209,14 +209,14 @@ compare_etags(Tag,Etags) ->
nomatch
end.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%%Control if the file is modificated %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% %%
+%% Control if the file is modificated %%
+%% %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%----------------------------------------------------------------------
-%%Control the If-Modified-Since and If-Not-Modified-Since header fields
+%% Control the If-Modified-Since and If-Not-Modified-Since header fields
%%----------------------------------------------------------------------
control_modification(Path,Info,FileInfo)->
?DEBUG("control_modification() -> entry",[]),
@@ -227,6 +227,8 @@ control_modification(Path,Info,FileInfo)->
continue;
unmodified->
{304, Info, Path};
+ {bad_date, _} = BadDate->
+ {400, Info, BadDate};
undefined ->
case control_modification_data(Info,
FileInfo#file_info.mtime,
@@ -253,21 +255,27 @@ control_modification_data(Info, ModificationTime, HeaderField)->
undefined->
undefined;
LastModified0 ->
- LastModified = calendar:universal_time_to_local_time(
- httpd_util:convert_request_date(LastModified0)),
- ?DEBUG("control_modification_data() -> "
- "~n Request-Field: ~s"
- "~n FileLastModified: ~p"
- "~n FieldValue: ~p",
- [HeaderField, ModificationTime, LastModified]),
- FileTime =
- calendar:datetime_to_gregorian_seconds(ModificationTime),
- FieldTime = calendar:datetime_to_gregorian_seconds(LastModified),
- if
- FileTime =< FieldTime ->
- ?DEBUG("File unmodified~n", []), unmodified;
- FileTime >= FieldTime ->
- ?DEBUG("File modified~n", []), modified
+ case httpd_util:convert_request_date(LastModified0) of
+ bad_date ->
+ {bad_date, LastModified0};
+ ConvertedReqDate ->
+ LastModified =
+ calendar:universal_time_to_local_time(ConvertedReqDate),
+ ?DEBUG("control_modification_data() -> "
+ "~n Request-Field: ~s"
+ "~n FileLastModified: ~p"
+ "~n FieldValue: ~p",
+ [HeaderField, ModificationTime, LastModified]),
+ FileTime =
+ calendar:datetime_to_gregorian_seconds(ModificationTime),
+ FieldTime =
+ calendar:datetime_to_gregorian_seconds(LastModified),
+ if
+ FileTime =< FieldTime ->
+ ?DEBUG("File unmodified~n", []), unmodified;
+ FileTime >= FieldTime ->
+ ?DEBUG("File modified~n", []), modified
+ end
end
end.
@@ -285,6 +293,9 @@ strip_date([C | Rest]) ->
send_return_value({412,_,_}, _FileInfo)->
{status,{412,none,"Precondition Failed"}};
+send_return_value({400,_, {bad_date, BadDate}}, _FileInfo)->
+ {status, {400, none, "Bad date: " ++ BadDate}};
+
send_return_value({304,Info,Path}, FileInfo)->
Suffix = httpd_util:suffix(Path),
MimeType = httpd_util:lookup_mime_default(Info#mod.config_db,Suffix,
diff --git a/lib/inets/src/inets_app/Makefile b/lib/inets/src/inets_app/Makefile
index 20e22917e2..63ab0a5bae 100644
--- a/lib/inets/src/inets_app/Makefile
+++ b/lib/inets/src/inets_app/Makefile
@@ -30,6 +30,7 @@ include ../../vsn.mk
VSN = $(INETS_VSN)
+
# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
@@ -41,8 +42,8 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
# ----------------------------------------------------
MODULES = \
- inets_service \
inets \
+ inets_service \
inets_app \
inets_sup \
inets_regexp
diff --git a/lib/inets/src/inets_app/inets.app.src b/lib/inets/src/inets_app/inets.app.src
index cb036157a5..4d0defb329 100644
--- a/lib/inets/src/inets_app/inets.app.src
+++ b/lib/inets/src/inets_app/inets.app.src
@@ -34,8 +34,7 @@
ftp_sup,
%% HTTP client:
- http, %% Old client API module
- httpc, %% New client API module
+ httpc,
httpc_handler,
httpc_handler_sup,
httpc_manager,
diff --git a/lib/inets/src/inets_app/inets.appup.src b/lib/inets/src/inets_app/inets.appup.src
index 8b0fcb185d..779dd8e439 100644
--- a/lib/inets/src/inets_app/inets.appup.src
+++ b/lib/inets/src/inets_app/inets.appup.src
@@ -18,65 +18,47 @@
{"%VSN%",
[
- {"5.6",
- [
- {load_module, httpc, soft_purge, soft_purge, [httpc_manager]},
- {load_module, http_transport, soft_purge, soft_purge, [http_transport]},
- {update, httpc_handler, soft, soft_purge, soft_purge, []},
- {update, httpc_manager, soft, soft_purge, soft_purge, [httpc_handler]},
- {update, ftp, soft, soft_purge, soft_purge, []}
- ]
- },
- {"5.5.2",
+ {"5.7.2",
[
{restart_application, inets}
]
},
- {"5.5.1",
+ {"5.7.1",
[
{restart_application, inets}
]
},
- {"5.5",
+ {"5.7",
[
{restart_application, inets}
]
},
- {"5.4",
+ {"5.6",
[
{restart_application, inets}
]
}
],
[
- {"5.6",
- [
- {load_module, httpc, soft_purge, soft_purge, [httpc_manager]},
- {load_module, http_transport, soft_purge, soft_purge, [http_transport]},
- {update, httpc_handler, soft, soft_purge, soft_purge, []},
- {update, httpc_manager, soft, soft_purge, soft_purge, [httpc_handler]},
- {update, ftp, soft, soft_purge, soft_purge, []}
- ]
- },
- {"5.5.2",
+ {"5.7.2",
[
{restart_application, inets}
]
- },
- {"5.5.1",
+ },
+ {"5.7.1",
[
{restart_application, inets}
]
},
- {"5.5",
+ {"5.7",
[
{restart_application, inets}
]
- },
- {"5.4",
+ },
+ {"5.6",
[
{restart_application, inets}
]
- }
+ }
]
}.
diff --git a/lib/inets/src/inets_app/inets.mk b/lib/inets/src/inets_app/inets.mk
index b6e9fe1d96..35fb0d7eca 100644
--- a/lib/inets/src/inets_app/inets.mk
+++ b/lib/inets/src/inets_app/inets.mk
@@ -33,6 +33,10 @@ ifeq ($(WARN_UNUSED_WARS), true)
ERL_COMPILE_FLAGS += +warn_unused_vars
endif
+ifeq ($(shell erl -noshell -eval 'io:format("~4s", [erlang:system_info(otp_release)])' -s init stop), R14B)
+INETS_ERL_COMPILE_FLAGS += -D'OTP-R14B-COMPILER'
+endif
+
INETS_APP_VSN_COMPILE_FLAGS = \
+'{parse_transform,sys_pre_attributes}' \
+'{attribute,insert,app_vsn,$(APP_VSN)}'
diff --git a/lib/inets/src/inets_app/inets_service.erl b/lib/inets/src/inets_app/inets_service.erl
index e9eb9892f2..a057a51e2c 100644
--- a/lib/inets/src/inets_app/inets_service.erl
+++ b/lib/inets/src/inets_app/inets_service.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -20,24 +20,35 @@
-module(inets_service).
+-ifdef('OTP-R14B-COMPILER').
+
-export([behaviour_info/1]).
behaviour_info(callbacks) ->
- [{start_standalone, 1},
- {start_service, 1},
- {stop_service, 1},
- {services, 0},
- {service_info, 1}];
+ [{start_standalone, 1},
+ {start_service, 1},
+ {stop_service, 1},
+ {services, 0},
+ {service_info, 1}];
behaviour_info(_) ->
- undefined.
+ undefined.
+
+-else.
%% Starts service stand-alone
%% start_standalone(Config) -> % {ok, Pid} | {error, Reason}
%% <service>:start_link(Config).
+-callback start_standalone(Config :: term()) ->
+ {ok, pid()} | {error, Reason :: term()}.
+
%% Starts service as part of inets
%% start_service(Config) -> % {ok, Pid} | {error, Reason}
%% <service_sup>:start_child(Config).
+
+-callback start_service(Config :: term()) ->
+ {ok, pid()} | {error, Reason :: term()}.
+
%% Stop service
%% stop_service(Pid) -> % ok | {error, Reason}
%% <service_sup>:stop_child(maybe_map_pid_to_other_ref(Pid)).
@@ -51,6 +62,9 @@ behaviour_info(_) ->
%% Error
%% end.
+-callback stop_service(Service :: term()) ->
+ ok | {error, Reason :: term()}.
+
%% Returns list of running services. Services started as stand alone
%% are not listed
%% services() -> % [{Service, Pid}]
@@ -59,7 +73,14 @@ behaviour_info(_) ->
%% [{httpc, Pid} || {_, Pid, _, _} <-
%% supervisor:which_children(httpc_profile_sup)].
+-callback services() ->
+ [{Service :: term(), pid()}].
-%% service_info() -> [{Property, Value}] | {error, Reason}
+%% service_info() -> {ok, [{Property, Value}]} | {error, Reason}
%% ex: httpc:service_info() -> [{profile, ProfileName}]
%% httpd:service_info() -> [{host, Host}, {port, Port}]
+
+-callback service_info(Service :: term()) ->
+ {ok, [{Property :: term(), Value :: term()}]} | {error, Reason :: term()}.
+
+-endif.
diff --git a/lib/inets/src/tftp/tftp.erl b/lib/inets/src/tftp/tftp.erl
index bfdb4c0030..8d8fce388d 100644
--- a/lib/inets/src/tftp/tftp.erl
+++ b/lib/inets/src/tftp/tftp.erl
@@ -215,8 +215,6 @@
start/0
]).
--export([behaviour_info/1]).
-
%% Application local functions
-export([
start_standalone/1,
@@ -226,14 +224,67 @@
service_info/1
]).
+-ifdef('OTP-R14B-COMPILER').
+
+-export([behaviour_info/1]).
behaviour_info(callbacks) ->
- [{prepare, 6}, {open, 6}, {read, 1}, {write, 2}, {abort, 3}];
+ [{prepare, 6},
+ {open, 6},
+ {read, 1},
+ {write, 2},
+ {abort, 3}];
behaviour_info(_) ->
undefined.
+-else.
+
+-type peer() :: {PeerType :: inet | inet6,
+ PeerHost :: inet:ip_address(),
+ PeerPort :: port()}.
+
+-type access() :: read | write.
+
+-type options() :: [{Key :: string(), Value :: string()}].
+
+-type error_code() :: undef | enoent | eacces | enospc |
+ badop | eexist | baduser | badopt |
+ integer().
+
+-callback prepare(Peer :: peer(),
+ Access :: access(),
+ Filename :: file:name(),
+ Mode :: string(),
+ SuggestedOptions :: options(),
+ InitialState :: [] | [{root_dir, string()}]) ->
+ {ok, AcceptedOptions :: options(), NewState :: term()} |
+ {error, {Code :: error_code(), string()}}.
+
+-callback open(Peer :: peer(),
+ Access :: access(),
+ Filename :: file:name(),
+ Mode :: string(),
+ SuggestedOptions :: options(),
+ State :: [] | [{root_dir, string()}] | term()) ->
+ {ok, AcceptedOptions :: options(), NewState :: term()} |
+ {error, {Code :: error_code(), string()}}.
+
+-callback read(State :: term()) -> {more, binary(), NewState :: term()} |
+ {last, binary(), integer()} |
+ {error, {Code :: error_code(), string()}}.
+
+-callback write(binary(), State :: term()) ->
+ {more, NewState :: term()} |
+ {last, FileSize :: integer()} |
+ {error, {Code :: error_code(), string()}}.
+
+-callback abort(Code :: error_code(), string(), State :: term()) -> 'ok'.
+
+-endif.
+
-include("tftp.hrl").
+
%%-------------------------------------------------------------------
%% read_file(RemoteFilename, LocalFilename, Options) ->
%% {ok, LastCallbackState} | {error, Reason}
diff --git a/lib/inets/test/ftp_suite_lib.erl b/lib/inets/test/ftp_suite_lib.erl
index 3ebd02229e..ffb58c91b6 100644
--- a/lib/inets/test/ftp_suite_lib.erl
+++ b/lib/inets/test/ftp_suite_lib.erl
@@ -196,7 +196,9 @@ test_filenames() ->
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
init_per_testcase(Case, Config)
- when (Case =:= open) orelse (Case =:= open_port) ->
+ when (Case =:= open) orelse
+ (Case =:= open_port) ->
+ put(ftp_testcase, Case),
io:format(user, "~n~n*** INIT ~w:~w ***~n~n", [?MODULE, Case]),
inets:start(),
NewConfig = data_dir(Config),
@@ -266,7 +268,7 @@ do_init_per_testcase(Case, Config) ->
end,
Opts2 =
case string:tokens(atom_to_list(Case), [$_]) of
- [_, "active" | _] ->
+ ["active" | _] ->
[{mode, active} | Opts1];
_ ->
[{mode, passive} | Opts1]
@@ -367,8 +369,11 @@ open(Config) when is_list(Config) ->
tc_open(Host) ->
+ p("tc_open -> entry with"
+ "~n Host: ~p", [Host]),
{ok, Pid} = ?ftp_open(Host, []),
ok = ftp:close(Pid),
+ p("tc_open -> try (ok) open 1"),
{ok, Pid1} =
ftp:open({option_list, [{host,Host},
{port, ?FTP_PORT},
@@ -376,11 +381,13 @@ tc_open(Host) ->
{timeout, 30000}]}),
ok = ftp:close(Pid1),
+ p("tc_open -> try (fail) open 2"),
{error, ehost} =
ftp:open({option_list, [{port, ?FTP_PORT}, {flags, [verbose]}]}),
{ok, Pid2} = ftp:open(Host),
ok = ftp:close(Pid2),
+ p("tc_open -> try (ok) open 3"),
{ok, NewHost} = inet:getaddr(Host, inet),
{ok, Pid3} = ftp:open(NewHost),
ftp:user(Pid3, ?FTP_USER, ?FTP_PASS),
@@ -392,33 +399,68 @@ tc_open(Host) ->
%% Bad input that has default values are ignored and the defult
%% is used.
+ p("tc_open -> try (ok) open 4"),
{ok, Pid4} =
- ftp:open({option_list, [{host, Host}, {port, badarg},
- {flags, [verbose]},
+ ftp:open({option_list, [{host, Host},
+ {port, badarg},
+ {flags, [verbose]},
{timeout, 30000}]}),
test_server:sleep(100),
ok = ftp:close(Pid4),
+
+ p("tc_open -> try (ok) open 5"),
{ok, Pid5} =
- ftp:open({option_list, [{host, Host}, {port, ?FTP_PORT},
- {flags, [verbose]},
+ ftp:open({option_list, [{host, Host},
+ {port, ?FTP_PORT},
+ {flags, [verbose]},
{timeout, -42}]}),
test_server:sleep(100),
ok = ftp:close(Pid5),
+
+ p("tc_open -> try (ok) open 6"),
{ok, Pid6} =
- ftp:open({option_list, [{host, Host}, {port, ?FTP_PORT},
+ ftp:open({option_list, [{host, Host},
+ {port, ?FTP_PORT},
{flags, [verbose]},
- {mode, cool}]}),
+ {mode, cool}]}),
test_server:sleep(100),
ok = ftp:close(Pid6),
+ p("tc_open -> try (ok) open 7"),
{ok, Pid7} =
ftp:open(Host, [{port, ?FTP_PORT}, {verbose, true}, {timeout, 30000}]),
ok = ftp:close(Pid7),
+ p("tc_open -> try (ok) open 8"),
{ok, Pid8} =
ftp:open(Host, ?FTP_PORT),
ok = ftp:close(Pid8),
+ p("tc_open -> try (ok) open 9"),
+ {ok, Pid9} =
+ ftp:open(Host, [{port, ?FTP_PORT},
+ {verbose, true},
+ {timeout, 30000},
+ {dtimeout, -99}]),
+ ok = ftp:close(Pid9),
+
+ p("tc_open -> try (ok) open 10"),
+ {ok, Pid10} =
+ ftp:open(Host, [{port, ?FTP_PORT},
+ {verbose, true},
+ {timeout, 30000},
+ {dtimeout, "foobar"}]),
+ ok = ftp:close(Pid10),
+
+ p("tc_open -> try (ok) open 11"),
+ {ok, Pid11} =
+ ftp:open(Host, [{port, ?FTP_PORT},
+ {verbose, true},
+ {timeout, 30000},
+ {dtimeout, 1}]),
+ ok = ftp:close(Pid11),
+
+ p("tc_open -> done"),
ok.
@@ -445,7 +487,7 @@ passive_user(suite) ->
[];
passive_user(Config) when is_list(Config) ->
Pid = ?config(ftp, Config),
- io:format("Pid: ~p~n",[Pid]),
+ p("Pid: ~p",[Pid]),
do_user(Pid).
@@ -967,13 +1009,13 @@ api_missuse(doc)->
["Test that behaviour of the ftp process if the api is abused"];
api_missuse(suite) -> [];
api_missuse(Config) when is_list(Config) ->
- io:format("api_missuse -> entry~n", []),
+ p("api_missuse -> entry"),
Flag = process_flag(trap_exit, true),
Pid = ?config(ftp, Config),
Host = ftp_host(Config),
%% Serious programming fault, connetion will be shut down
- io:format("api_missuse -> verify bad call termination (~p)~n", [Pid]),
+ p("api_missuse -> verify bad call termination (~p)", [Pid]),
case (catch gen_server:call(Pid, {self(), foobar, 10}, infinity)) of
{error, {connection_terminated, 'API_violation'}} ->
ok;
@@ -983,23 +1025,23 @@ api_missuse(Config) when is_list(Config) ->
test_server:sleep(500),
undefined = process_info(Pid, status),
- io:format("api_missuse -> start new client~n", []),
+ p("api_missuse -> start new client"),
{ok, Pid2} = ?ftp_open(Host, []),
%% Serious programming fault, connetion will be shut down
- io:format("api_missuse -> verify bad cast termination~n", []),
+ p("api_missuse -> verify bad cast termination"),
gen_server:cast(Pid2, {self(), foobar, 10}),
test_server:sleep(500),
undefined = process_info(Pid2, status),
- io:format("api_missuse -> start new client~n", []),
+ p("api_missuse -> start new client"),
{ok, Pid3} = ?ftp_open(Host, []),
%% Could be an innocent misstake the connection lives.
- io:format("api_missuse -> verify bad bang~n", []),
+ p("api_missuse -> verify bad bang"),
Pid3 ! foobar,
test_server:sleep(500),
{status, _} = process_info(Pid3, status),
process_flag(trap_exit, Flag),
- io:format("api_missuse -> done~n", []),
+ p("api_missuse -> done"),
ok.
@@ -1567,9 +1609,9 @@ split([], I, Is) ->
lists:reverse([lists:reverse(I)| Is]).
do_ftp_open(Host, Opts) ->
- io:format("do_ftp_open -> entry with"
- "~n Host: ~p"
- "~n Opts: ~p", [Host, Opts]),
+ p("do_ftp_open -> entry with"
+ "~n Host: ~p"
+ "~n Opts: ~p", [Host, Opts]),
case ftp:open(Host, Opts) of
{ok, _} = OK ->
OK;
@@ -1595,7 +1637,7 @@ passwd() ->
ftpd_hosts(Config) ->
DataDir = ?config(data_dir, Config),
FileName = filename:join([DataDir, "../ftp_SUITE_data/", ftpd_hosts]),
- io:format("FileName: ~p~n", [FileName]),
+ p("FileName: ~p", [FileName]),
case file:consult(FileName) of
{ok, [Hosts]} when is_list(Hosts) ->
Hosts;
diff --git a/lib/inets/test/ftp_windows_2003_server_test.erl b/lib/inets/test/ftp_windows_2003_server_test.erl
index 57f1ae8358..32f25713f8 100644
--- a/lib/inets/test/ftp_windows_2003_server_test.erl
+++ b/lib/inets/test/ftp_windows_2003_server_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -87,14 +87,22 @@ end_per_testcase(Case, Config) ->
%% Description: Returns a list of all test cases in this test suite
%%--------------------------------------------------------------------
all() ->
- [open, open_port, {group, passive}, {group, active},
- api_missuse, not_owner, {group, progress_report}].
+ [
+ open,
+ open_port,
+ {group, passive},
+ {group, active},
+ api_missuse,
+ not_owner,
+ {group, progress_report}
+ ].
groups() ->
- [{passive, [], ftp_suite_lib:passive(suite)},
- {active, [], ftp_suite_lib:active(suite)},
- {progress_report, [],
- ftp_suite_lib:progress_report(suite)}].
+ [
+ {passive, [], ftp_suite_lib:passive(suite)},
+ {active, [], ftp_suite_lib:active(suite)},
+ {progress_report, [], ftp_suite_lib:progress_report(suite)}
+ ].
init_per_group(_GroupName, Config) ->
Config.
diff --git a/lib/inets/test/http_format_SUITE.erl b/lib/inets/test/http_format_SUITE.erl
index 931ac6e024..04c7358715 100644
--- a/lib/inets/test/http_format_SUITE.erl
+++ b/lib/inets/test/http_format_SUITE.erl
@@ -584,7 +584,9 @@ convert_netscapecookie_date(Config) when is_list(Config) ->
http_util:convert_netscapecookie_date("Sun, 12-Dec-06 08:59:38 GMT"),
{{2006,12,12},{8,59,38}} =
http_util:convert_netscapecookie_date("Sun 12-Dec-06 08:59:38 GMT"),
- ok.
+ {{2036,1,1},{8,0,1}} =
+ http_util:convert_netscapecookie_date("Tue Jan 01 08:00:01 2036 GMT"),
+ ok.
%%--------------------------------------------------------------------
%%% Internal functions
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl
index 6edd5371af..d86e52f3d5 100644
--- a/lib/inets/test/httpc_SUITE.erl
+++ b/lib/inets/test/httpc_SUITE.erl
@@ -113,13 +113,10 @@ groups() ->
proxy_page_does_not_exist,
proxy_https_not_supported]},
{ssl, [], [ssl_head,
- ossl_head,
essl_head,
ssl_get,
- ossl_get,
essl_get,
ssl_trace,
- ossl_trace,
essl_trace]},
{stream, [], [http_stream,
http_stream_once,
@@ -253,10 +250,10 @@ init_per_testcase(Case, Config) ->
init_per_testcase(Case, 2, Config).
init_per_testcase(Case, Timeout, Config) ->
- io:format(user, "~n~n*** INIT ~w:~w[~w] ***~n~n",
- [?MODULE, Case, Timeout]),
- PrivDir = ?config(priv_dir, Config),
- tsp("init_per_testcase -> stop inets"),
+ io:format(user,
+ "~n~n*** INIT ~w:~w[~w] ***"
+ "~n~n", [?MODULE, Case, Timeout]),
+ PrivDir = ?config(priv_dir, Config),
application:stop(inets),
Dog = test_server:timetrap(inets_test_lib:minutes(Timeout)),
TmpConfig = lists:keydelete(watchdog, 1, Config),
@@ -273,10 +270,6 @@ init_per_testcase(Case, Timeout, Config) ->
init_per_testcase_ssl(ssl, PrivDir, SslConfFile,
[{watchdog, Dog} | TmpConfig]);
- [$o, $s, $s, $l | _] ->
- init_per_testcase_ssl(ossl, PrivDir, SslConfFile,
- [{watchdog, Dog} | TmpConfig]);
-
[$e, $s, $s, $l | _] ->
init_per_testcase_ssl(essl, PrivDir, SslConfFile,
[{watchdog, Dog} | TmpConfig]);
@@ -296,12 +289,12 @@ init_per_testcase(Case, Timeout, Config) ->
throw:{error, {failed_starting, App, _}} ->
SkipString =
"Could not start " ++ atom_to_list(App),
- {skip, SkipString};
- _:X ->
+ skip(SkipString);
+ _:X ->
SkipString =
lists:flatten(
io_lib:format("Failed starting apps: ~p", [X])),
- {skip, SkipString}
+ skip(SkipString)
end;
_ ->
@@ -330,14 +323,14 @@ init_per_testcase(Case, Timeout, Config) ->
],
case lists:member(Rest, BadCases) of
true ->
- [{skip, "TC and server not compatible"}|
+ [skip("TC and server not compatible") |
TmpConfig];
false ->
inets:start(),
[{watchdog, Dog} | TmpConfig]
end;
false ->
- [{skip, "proxy not responding"} | TmpConfig]
+ [skip("proxy not responding") | TmpConfig]
end
end;
@@ -367,20 +360,19 @@ init_per_testcase(Case, Timeout, Config) ->
io_lib:format("Failed starting apps: ~p", [X])),
{skip, SkipString}
end;
+
_ ->
TmpConfig2 = lists:keydelete(local_server, 1, TmpConfig),
- Server =
- %% Will start inets
- inets_test_lib:start_http_server(
- filename:join(PrivDir, IpConfFile)),
+ %% Will start inets
+ Server = start_http_server(PrivDir, IpConfFile),
[{watchdog, Dog}, {local_server, Server} | TmpConfig2]
end,
%% This will fail for the ipv6_ - cases (but that is ok)
- httpc:set_options([{proxy, {{?PROXY, ?PROXY_PORT},
- ["localhost", ?IPV6_LOCAL_HOST]}},
- {ipfamily, inet6fb4}]),
-
+ ProxyExceptions = ["localhost", ?IPV6_LOCAL_HOST],
+ http:set_options([{proxy, {{?PROXY, ?PROXY_PORT}, ProxyExceptions}}]),
+ inets:enable_trace(max, io, httpc),
+ %% inets:enable_trace(max, io, all),
%% snmp:set_trace([gen_tcp]),
NewConfig.
@@ -397,7 +389,10 @@ init_per_testcase_ssl(Tag, PrivDir, SslConfFile, Config) ->
tsp("init_per_testcase(~w) -> Server: ~p", [Tag, Server]),
[{local_ssl_server, Server} | Config2].
-
+start_http_server(ConfDir, ConfFile) ->
+ inets_test_lib:start_http_server( filename:join(ConfDir, ConfFile) ).
+
+
%%--------------------------------------------------------------------
%% Function: end_per_testcase(Case, Config) -> _
%% Case - atom()
@@ -733,7 +728,7 @@ test_pipeline(URL) ->
p("test_pipeline -> received reply for (async) request 2"),
ok;
{http, Msg1} ->
- test_server:fail(Msg1)
+ tsf(Msg1)
end;
{http, {RequestId2, {{_, 200, _}, _, _}}} ->
io:format("test_pipeline -> received reply for (async) request 2 - now wait for 1"),
@@ -742,14 +737,14 @@ test_pipeline(URL) ->
io:format("test_pipeline -> received reply for (async) request 1"),
ok;
{http, Msg2} ->
- test_server:fail(Msg2)
+ tsf(Msg2)
end;
{http, Msg3} ->
- test_server:fail(Msg3)
+ tsf(Msg3)
after 60000 ->
receive Any1 ->
tsp("received crap after timeout: ~n ~p", [Any1]),
- test_server:fail({error, {timeout, Any1}})
+ tsf({error, {timeout, Any1}})
end
end,
@@ -774,7 +769,7 @@ test_pipeline(URL) ->
p("test_pipeline -> expect *no* reply for cancelled (async) request 4 (for 3 secs)"),
receive
{http, {RequestId3, _}} ->
- test_server:fail(http_cancel_request_failed)
+ tsf(http_cancel_request_failed)
after 3000 ->
ok
end,
@@ -787,11 +782,11 @@ test_pipeline(URL) ->
tsp("Receive : ~p", [Res]),
BinBody4;
{http, Msg4} ->
- test_server:fail(Msg4)
+ tsf(Msg4)
after 60000 ->
receive Any2 ->
tsp("received crap after timeout: ~n ~p", [Any2]),
- test_server:fail({error, {timeout, Any2}})
+ tsf({error, {timeout, Any2}})
end
end,
@@ -801,7 +796,7 @@ test_pipeline(URL) ->
p("test_pipeline -> ensure no unexpected incomming"),
receive
{http, Any} ->
- test_server:fail({unexpected_message, Any})
+ tsf({unexpected_message, Any})
after 500 ->
ok
end,
@@ -823,11 +818,11 @@ http_trace(Config) when is_list(Config) ->
{ok, {{_,200,_}, [_ | _], "TRACE /dummy.html" ++ _}} ->
ok;
{ok, {{_,200,_}, [_ | _], WrongBody}} ->
- test_server:fail({wrong_body, WrongBody});
+ tsf({wrong_body, WrongBody});
{ok, WrongReply} ->
- test_server:fail({wrong_reply, WrongReply});
+ tsf({wrong_reply, WrongReply});
Error ->
- test_server:fail({failed, Error})
+ tsf({failed, Error})
end;
_ ->
{skip, "Failed to start local http-server"}
@@ -850,7 +845,7 @@ http_async(Config) when is_list(Config) ->
{http, {RequestId, {{_, 200, _}, _, BinBody}}} ->
BinBody;
{http, Msg} ->
- test_server:fail(Msg)
+ tsf(Msg)
end,
inets_test_lib:check_body(binary_to_list(Body)),
@@ -860,7 +855,7 @@ http_async(Config) when is_list(Config) ->
ok = httpc:cancel_request(NewRequestId),
receive
{http, {NewRequestId, _NewResult}} ->
- test_server:fail(http_cancel_request_failed)
+ tsf(http_cancel_request_failed)
after 3000 ->
ok
end;
@@ -909,7 +904,7 @@ http_save_to_file_async(Config) when is_list(Config) ->
{http, {RequestId, saved_to_file}} ->
ok;
{http, Msg} ->
- test_server:fail(Msg)
+ tsf(Msg)
end,
{ok, Bin} = file:read_file(FilePath),
@@ -1076,13 +1071,6 @@ ssl_head(suite) ->
ssl_head(Config) when is_list(Config) ->
ssl_head(ssl, Config).
-ossl_head(doc) ->
- ["Same as http_head/1 but over ssl sockets."];
-ossl_head(suite) ->
- [];
-ossl_head(Config) when is_list(Config) ->
- ssl_head(ossl, Config).
-
essl_head(doc) ->
["Same as http_head/1 but over ssl sockets."];
essl_head(suite) ->
@@ -1105,8 +1093,6 @@ ssl_head(SslTag, Config) ->
case SslTag of
ssl ->
SSLOptions;
- ossl ->
- {ossl, SSLOptions};
essl ->
{essl, SSLOptions}
end,
@@ -1131,13 +1117,6 @@ ssl_get(suite) ->
ssl_get(Config) when is_list(Config) ->
ssl_get(ssl, Config).
-ossl_get(doc) ->
- ["Same as http_get/1 but over ssl sockets."];
-ossl_get(suite) ->
- [];
-ossl_get(Config) when is_list(Config) ->
- ssl_get(ossl, Config).
-
essl_get(doc) ->
["Same as http_get/1 but over ssl sockets."];
essl_get(suite) ->
@@ -1157,8 +1136,6 @@ ssl_get(SslTag, Config) when is_list(Config) ->
case SslTag of
ssl ->
SSLOptions;
- ossl ->
- {ossl, SSLOptions};
essl ->
{essl, SSLOptions}
end,
@@ -1184,13 +1161,6 @@ ssl_trace(suite) ->
ssl_trace(Config) when is_list(Config) ->
ssl_trace(ssl, Config).
-ossl_trace(doc) ->
- ["Same as http_trace/1 but over ssl sockets."];
-ossl_trace(suite) ->
- [];
-ossl_trace(Config) when is_list(Config) ->
- ssl_trace(ossl, Config).
-
essl_trace(doc) ->
["Same as http_trace/1 but over ssl sockets."];
essl_trace(suite) ->
@@ -1210,8 +1180,6 @@ ssl_trace(SslTag, Config) when is_list(Config) ->
case SslTag of
ssl ->
SSLOptions;
- ossl ->
- {ossl, SSLOptions};
essl ->
{essl, SSLOptions}
end,
@@ -1482,10 +1450,10 @@ proxy_options(Config) when is_list(Config) ->
{value, {"allow", _}} ->
ok;
_ ->
- test_server:fail(http_options_request_failed)
+ tsf(http_options_request_failed)
end;
Unexpected ->
- test_server:fail({unexpected_result, Unexpected})
+ tsf({unexpected_result, Unexpected})
end;
Reason ->
{skip, Reason}
@@ -1506,7 +1474,7 @@ proxy_head(Config) when is_list(Config) ->
{ok, {{_,200, _}, [_ | _], []}} ->
ok;
Unexpected ->
- test_server:fail({unexpected_result, Unexpected})
+ tsf({unexpected_result, Unexpected})
end;
Reason ->
{skip, Reason}
@@ -1525,7 +1493,7 @@ proxy_get(Config) when is_list(Config) ->
{ok, {{_,200,_}, [_ | _], Body = [_ | _]}} ->
inets_test_lib:check_body(Body);
Unexpected ->
- test_server:fail({unexpected_result, Unexpected})
+ tsf({unexpected_result, Unexpected})
end;
Reason ->
{skip, Reason}
@@ -1604,7 +1572,7 @@ proxy_post(Config) when is_list(Config) ->
{ok, {{_,405,_}, [_ | _], [_ | _]}} ->
ok;
Unexpected ->
- test_server:fail({unexpected_result, Unexpected})
+ tsf({unexpected_result, Unexpected})
end;
Reason ->
{skip, Reason}
@@ -1629,7 +1597,7 @@ proxy_put(Config) when is_list(Config) ->
{ok, {{_,405,_}, [_ | _], [_ | _]}} ->
ok;
Unexpected ->
- test_server:fail({unexpected_result, Unexpected})
+ tsf({unexpected_result, Unexpected})
end;
Reason ->
{skip, Reason}
@@ -1654,7 +1622,7 @@ proxy_delete(Config) when is_list(Config) ->
{ok, {{_,404,_}, [_ | _], [_ | _]}} ->
ok;
Unexpected ->
- test_server:fail({unexpected_result, Unexpected})
+ tsf({unexpected_result, Unexpected})
end;
Reason ->
{skip, Reason}
@@ -1710,7 +1678,7 @@ proxy_auth(Config) when is_list(Config) ->
{ok, {{_,200, _}, [_ | _], [_|_]}} ->
ok;
Unexpected ->
- test_server:fail({unexpected_result, Unexpected})
+ tsf({unexpected_result, Unexpected})
end;
Reason ->
{skip, Reason}
@@ -1796,7 +1764,7 @@ http_stream(Config) when is_list(Config) ->
{http, {RequestId, stream_start, _Headers}} ->
ok;
{http, Msg} ->
- test_server:fail(Msg)
+ tsf(Msg)
end,
StreamedBody = receive_streamed_body(RequestId, <<>>),
@@ -1851,7 +1819,7 @@ once(URL) ->
[RequestId, Pid]),
Pid;
{http, Msg} ->
- test_server:fail(Msg)
+ tsf(Msg)
end,
tsp("once -> request handler: ~p", [NewPid]),
@@ -1894,7 +1862,7 @@ proxy_stream(Config) when is_list(Config) ->
{http, {RequestId, stream_start, _Headers}} ->
ok;
{http, Msg} ->
- test_server:fail(Msg)
+ tsf(Msg)
end,
StreamedBody = receive_streamed_body(RequestId, <<>>),
@@ -1912,22 +1880,31 @@ parse_url(suite) ->
[];
parse_url(Config) when is_list(Config) ->
%% ipv6
- {http,[],"2010:836B:4179::836B:4179",80,"/foobar.html",[]}
- = http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html"),
+ {ok, {http,[],"2010:836B:4179::836B:4179",80,"/foobar.html",[]}} =
+ http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html"),
+ {ok, {http,[],"[2010:836B:4179::836B:4179]",80,"/foobar.html",[]}} =
+ http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html",
+ [{ipv6_host_with_brackets, true}]),
+ {ok, {http,[],"2010:836B:4179::836B:4179",80,"/foobar.html",[]}} =
+ http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html",
+ [{ipv6_host_with_brackets, false}]),
+ {ok, {http,[],"2010:836B:4179::836B:4179",80,"/foobar.html",[]}} =
+ http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html",
+ [{foo, false}]),
{error,
{malformed_url,"http://2010:836B:4179::836B:4179/foobar.html"}} =
http_uri:parse("http://2010:836B:4179::836B:4179/foobar.html"),
%% ipv4
- {http,[],"127.0.0.1",80,"/foobar.html",[]} =
+ {ok, {http,[],"127.0.0.1",80,"/foobar.html",[]}} =
http_uri:parse("http://127.0.0.1/foobar.html"),
%% host
- {http,[],"localhost",8888,"/foobar.html",[]} =
+ {ok, {http,[],"localhost",8888,"/foobar.html",[]}} =
http_uri:parse("http://localhost:8888/foobar.html"),
%% Userinfo
- {http,"nisse:foobar","localhost",8888,"/foobar.html",[]} =
+ {ok, {http,"nisse:foobar","localhost",8888,"/foobar.html",[]}} =
http_uri:parse("http://nisse:foobar@localhost:8888/foobar.html"),
%% Scheme error
@@ -1936,18 +1913,20 @@ parse_url(Config) when is_list(Config) ->
http_uri:parse("localhost:8888/foobar.html"),
%% Query
- {http,[],"localhost",8888,"/foobar.html","?foo=bar&foobar=42"} =
+ {ok, {http,[],"localhost",8888,"/foobar.html","?foo=bar&foobar=42"}} =
http_uri:parse("http://localhost:8888/foobar.html?foo=bar&foobar=42"),
%% Esc chars
- {http,[],"www.somedomain.com",80,"/%2Eabc",[]} =
+ {ok, {http,[],"www.somedomain.com",80,"/%2Eabc",[]}} =
http_uri:parse("http://www.somedomain.com/%2Eabc"),
- {http,[],"www.somedomain.com",80,"/%252Eabc",[]} =
+ {ok, {http,[],"www.somedomain.com",80,"/%252Eabc",[]}} =
http_uri:parse("http://www.somedomain.com/%252Eabc"),
- {http,[],"www.somedomain.com",80,"/%25abc",[]} =
+ {ok, {http,[],"www.somedomain.com",80,"/%25abc",[]}} =
http_uri:parse("http://www.somedomain.com/%25abc"),
- {http,[],"www.somedomain.com",80,"/%25abc", "?foo=bar"} =
+ {ok, {http,[],"www.somedomain.com",80,"/%25abc", "?foo=bar"}} =
http_uri:parse("http://www.somedomain.com/%25abc?foo=bar"),
+
+
ok.
@@ -2092,12 +2071,14 @@ http_invalid_http(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
+-define(GOOGLE, "www.google.com").
+
hexed_query_otp_6191(doc) ->
[];
hexed_query_otp_6191(suite) ->
[];
hexed_query_otp_6191(Config) when is_list(Config) ->
- Google = "www.google.com",
+ Google = ?GOOGLE,
GoogleSearch = "http://" ++ Google ++ "/search",
Search1 = "?hl=en&q=a%D1%85%D1%83%D0%B9&btnG=Google+Search",
URI1 = GoogleSearch ++ Search1,
@@ -2106,11 +2087,32 @@ hexed_query_otp_6191(Config) when is_list(Config) ->
Search3 = "?hl=en&q=%foo",
URI3 = GoogleSearch ++ Search3,
- {http, [], Google, 80, "/search", _} = http_uri:parse(URI1),
- {http, [], Google, 80, "/search", _} = http_uri:parse(URI2),
- {http, [], Google, 80, "/search", _} = http_uri:parse(URI3),
+ Verify1 =
+ fun({http, [], ?GOOGLE, 80, "/search", _}) -> ok;
+ (_) -> error
+ end,
+ Verify2 = Verify1,
+ Verify3 = Verify1,
+ verify_uri(URI1, Verify1),
+ verify_uri(URI2, Verify2),
+ verify_uri(URI3, Verify3),
ok.
+verify_uri(URI, Verify) ->
+ case http_uri:parse(URI) of
+ {ok, ParsedURI} ->
+ case Verify(ParsedURI) of
+ ok ->
+ ok;
+ error ->
+ Reason = {unexpected_parse_result, URI, ParsedURI},
+ ERROR = {error, Reason},
+ throw(ERROR)
+ end;
+ {error, _} = ERROR ->
+ throw(ERROR)
+ end.
+
%%-------------------------------------------------------------------------
@@ -2979,7 +2981,7 @@ receive_streamed_body(RequestId, Body) ->
{http, {RequestId, stream_end, _Headers}} ->
Body;
{http, Msg} ->
- test_server:fail(Msg)
+ tsf(Msg)
end.
receive_streamed_body(RequestId, Body, Pid) ->
@@ -2993,7 +2995,7 @@ receive_streamed_body(RequestId, Body, Pid) ->
{http, {RequestId, stream_end, _Headers}} ->
Body;
{http, Msg} ->
- test_server:fail(Msg)
+ tsf(Msg)
end.
%% Perform a synchronous stop
@@ -3038,10 +3040,6 @@ dummy_server_init(Caller, essl, IpV, SSLOptions) ->
BaseOpts = [{ssl_imp, new},
{backlog, 128}, binary, {reuseaddr,true}, {active, false} |
SSLOptions],
- dummy_ssl_server_init(Caller, BaseOpts, IpV);
-dummy_server_init(Caller, ossl, IpV, SSLOptions) ->
- BaseOpts = [{ssl_imp, old},
- {backlog, 128}, binary, {active, false} | SSLOptions],
dummy_ssl_server_init(Caller, BaseOpts, IpV).
dummy_ssl_server_init(Caller, BaseOpts, IpV) ->
@@ -3455,7 +3453,7 @@ handle_auth("Basic " ++ UserInfo, Challange, DefaultResponse) ->
end.
check_cookie([]) ->
- test_server:fail(no_cookie_header);
+ tsf(no_cookie_header);
check_cookie(["cookie:" ++ _Value | _]) ->
ok;
check_cookie([_Head | Tail]) ->
@@ -3513,9 +3511,9 @@ p(F, A) ->
io:format("~p ~w:" ++ F ++ "~n", [self(), ?MODULE | A]).
tsp(F) ->
- tsp(F, []).
+ inets_test_lib:tsp(F).
tsp(F, A) ->
- test_server:format("~p ~p:" ++ F ++ "~n", [self(), ?MODULE | A]).
+ inets_test_lib:tsp(F, A).
tsf(Reason) ->
test_server:fail(Reason).
@@ -3570,3 +3568,6 @@ ensure_started(App) when is_atom(App) ->
throw({error, {failed_starting, App, Error}})
end.
+
+skip(Reason) ->
+ {skip, Reason}.
diff --git a/lib/inets/test/httpc_cookie_SUITE.erl b/lib/inets/test/httpc_cookie_SUITE.erl
index feef5f1eea..93dbc270c5 100644
--- a/lib/inets/test/httpc_cookie_SUITE.erl
+++ b/lib/inets/test/httpc_cookie_SUITE.erl
@@ -55,7 +55,7 @@ init_per_testcase(session_cookies_only = Case, Config0) ->
"~n Config0: ~p", [Case, Config0]),
Config = init_workdir(Case, Config0),
application:start(inets),
- http:set_options([{cookies, verify}]),
+ httpc:set_options([{cookies, verify}]),
watch_dog(Config);
init_per_testcase(Case, Config0) ->
@@ -66,7 +66,7 @@ init_per_testcase(Case, Config0) ->
application:load(inets),
application:set_env(inets, services, [{httpc, {default, CaseDir}}]),
application:start(inets),
- http:set_options([{cookies, verify}]),
+ httpc:set_options([{cookies, verify}]),
watch_dog(Config).
watch_dog(Config) ->
@@ -119,10 +119,18 @@ end_per_testcase(Case, Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [session_cookies_only, netscape_cookies, cookie_cancel,
- cookie_expires, persistent_cookie, domain_cookie,
- secure_cookie, update_cookie, update_cookie_session,
- cookie_attributes].
+ [
+ session_cookies_only,
+ netscape_cookies,
+ cookie_cancel,
+ cookie_expires,
+ persistent_cookie,
+ domain_cookie,
+ secure_cookie,
+ update_cookie,
+ update_cookie_session,
+ cookie_attributes
+ ].
groups() ->
[].
@@ -152,12 +160,12 @@ session_cookies_only(Config) when is_list(Config) ->
SetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/;"
";max-age=60000"}],
- http:verify_cookies(SetCookieHeaders, ?URL),
- {"cookie","$Version=0; test_cookie=true; $Path=/"}
- = http:cookie_header(?URL),
+ httpc:store_cookies(SetCookieHeaders, ?URL),
+ {"cookie", "$Version=0; test_cookie=true; $Path=/"} =
+ httpc:cookie_header(?URL),
application:stop(inets),
application:start(inets),
- {"cookie",""} = http:cookie_header(?URL),
+ {"cookie", ""} = httpc:cookie_header(?URL),
tsp("session_cookies_only -> Cookies 2: ~p", [httpc:which_cookies()]),
ok.
@@ -172,9 +180,9 @@ netscape_cookies(Config) when is_list(Config) ->
Expires = future_netscape_date(),
SetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/; "
"expires=" ++ Expires}],
- http:verify_cookies(SetCookieHeaders, ?URL),
- {"cookie","$Version=0; test_cookie=true; $Path=/"} =
- http:cookie_header(?URL),
+ httpc:store_cookies(SetCookieHeaders, ?URL),
+ {"cookie", "$Version=0; test_cookie=true; $Path=/"} =
+ httpc:cookie_header(?URL),
tsp("netscape_cookies -> Cookies 2: ~p", [httpc:which_cookies()]),
ok.
@@ -189,13 +197,13 @@ cookie_cancel(Config) when is_list(Config) ->
SetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/;"
"max-age=60000"}],
- http:verify_cookies(SetCookieHeaders, ?URL),
- {"cookie","$Version=0; test_cookie=true; $Path=/"}
- = http:cookie_header(?URL),
- NewSetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/;"
- "max-age=0"}],
- http:verify_cookies(NewSetCookieHeaders, ?URL),
- {"cookie", ""} = http:cookie_header(?URL),
+ httpc:store_cookies(SetCookieHeaders, ?URL),
+ {"cookie", "$Version=0; test_cookie=true; $Path=/"} =
+ httpc:cookie_header(?URL),
+ NewSetCookieHeaders =
+ [{"set-cookie", "test_cookie=true; path=/;max-age=0"}],
+ httpc:store_cookies(NewSetCookieHeaders, ?URL),
+ {"cookie", ""} = httpc:cookie_header(?URL),
tsp("cookie_cancel -> Cookies 2: ~p", [httpc:which_cookies()]),
ok.
@@ -209,11 +217,11 @@ cookie_expires(Config) when is_list(Config) ->
SetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/;"
"max-age=5"}],
- http:verify_cookies(SetCookieHeaders, ?URL),
- {"cookie","$Version=0; test_cookie=true; $Path=/"}
- = http:cookie_header(?URL),
+ httpc:store_cookies(SetCookieHeaders, ?URL),
+ {"cookie", "$Version=0; test_cookie=true; $Path=/"} =
+ httpc:cookie_header(?URL),
test_server:sleep(10000),
- {"cookie", ""} = http:cookie_header(?URL),
+ {"cookie", ""} = httpc:cookie_header(?URL),
tsp("cookie_expires -> Cookies 2: ~p", [httpc:which_cookies()]),
ok.
@@ -227,16 +235,16 @@ persistent_cookie(Config) when is_list(Config)->
SetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/;"
"max-age=60000"}],
- http:verify_cookies(SetCookieHeaders, ?URL),
- {"cookie","$Version=0; test_cookie=true; $Path=/"} =
- http:cookie_header(?URL),
+ httpc:store_cookies(SetCookieHeaders, ?URL),
+ {"cookie", "$Version=0; test_cookie=true; $Path=/"} =
+ httpc:cookie_header(?URL),
CaseDir = ?config(case_top_dir, Config),
application:stop(inets),
application:load(inets),
application:set_env(inets, services, [{httpc, {default, CaseDir}}]),
application:start(inets),
- http:set_options([{cookies, enabled}]),
- {"cookie","$Version=0; test_cookie=true; $Path=/"} = http:cookie_header(?URL),
+ httpc:set_options([{cookies, enabled}]),
+ {"cookie","$Version=0; test_cookie=true; $Path=/"} = httpc:cookie_header(?URL),
tsp("persistent_cookie -> Cookies 2: ~p", [httpc:which_cookies()]),
ok.
@@ -251,10 +259,10 @@ domain_cookie(Config) when is_list(Config) ->
SetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/;"
"domain=.cookie.test.org"}],
- http:verify_cookies(SetCookieHeaders, ?URL),
+ httpc:store_cookies(SetCookieHeaders, ?URL),
{"cookie","$Version=0; test_cookie=true; $Path=/; "
"$Domain=.cookie.test.org"} =
- http:cookie_header(?URL_DOMAIN),
+ httpc:cookie_header(?URL_DOMAIN),
tsp("domain_cookie -> Cookies 2: ~p", [httpc:which_cookies()]),
ok.
@@ -275,8 +283,8 @@ secure_cookie(Config) when is_list(Config) ->
tsp("secure_cookie -> Cookies 1: ~p", [httpc:which_cookies()]),
SetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/; secure"}],
- tsp("secure_cookie -> verify cookies (1)"),
- ok = http:verify_cookies(SetCookieHeaders, ?URL),
+ tsp("secure_cookie -> store cookies (1)"),
+ ok = httpc:store_cookies(SetCookieHeaders, ?URL),
tsp("secure_cookie -> Cookies 2: ~p", [httpc:which_cookies()]),
@@ -286,9 +294,9 @@ secure_cookie(Config) when is_list(Config) ->
tsp("secure_cookie -> check cookie (plain)"),
check_cookie("", ?URL),
- tsp("secure_cookie -> verify cookies (2)"),
+ tsp("secure_cookie -> store cookies (2)"),
SetCookieHeaders1 = [{"set-cookie", "test1_cookie=true; path=/; secure"}],
- ok = http:verify_cookies(SetCookieHeaders1, ?URL),
+ ok = httpc:store_cookies(SetCookieHeaders1, ?URL),
tsp("secure_cookie -> Cookies 3: ~p", [httpc:which_cookies()]),
@@ -297,7 +305,7 @@ secure_cookie(Config) when is_list(Config) ->
"test1_cookie=true; $Path=/",
?URL_SECURE),
%% {"cookie","$Version=0; test_cookie=true; $Path=/; "
-%% "test1_cookie=true; $Path=/"} = http:cookie_header(?URL_SECURE),
+%% "test1_cookie=true; $Path=/"} = httpc:cookie_header(?URL_SECURE),
tsp("secure_cookie -> Cookies 4: ~p", [httpc:which_cookies()]),
@@ -305,38 +313,93 @@ secure_cookie(Config) when is_list(Config) ->
tsp("secure_cookie -> done"),
ok.
+expect_cookie_header(No, ExpectedCookie) ->
+ case httpc:cookie_header(?URL) of
+ {"cookie", ExpectedCookie} ->
+ ok;
+ {"cookie", BadCookie} ->
+ io:format("Bad Cookie ~w: "
+ "~n Expected: ~s"
+ "~n Received: ~s"
+ "~n", [No, ExpectedCookie, BadCookie]),
+ exit({bad_cookie_header, No, ExpectedCookie, BadCookie})
+ end.
+
+print_cookies(Pre) ->
+ io:format("~s: ", [Pre]),
+ print_cookies2(httpc:which_cookies()).
+
+print_cookies2([]) ->
+ ok;
+print_cookies2([{cookies, Cookies}|Rest]) ->
+ print_cookies3("Cookies", Cookies),
+ print_cookies2(Rest);
+print_cookies2([{session_cookies, Cookies}|Rest]) ->
+ print_cookies3("Session Cookies", Cookies),
+ print_cookies2(Rest);
+print_cookies2([_|Rest]) ->
+ print_cookies2(Rest).
+
+print_cookies3(Header, []) ->
+ io:format(" ~s: []", [Header]);
+print_cookies3(Header, Cookies) ->
+ io:format(" ~s: ", [Header]),
+ Prefix = " ",
+ PrintCookie =
+ fun(Cookie) ->
+ io:format("~s", [httpc_cookie:image_of(Prefix, Cookie)])
+ end,
+ lists:foreach(PrintCookie, Cookies).
+
update_cookie(doc)->
- ["Test that a cookie can be updated."];
+ ["Test that a (plain) cookie can be updated."];
update_cookie(suite) ->
[];
-update_cookie(Config) when is_list(Config)->
- SetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/;"
- "max-age=6500"},
- {"set-cookie", "test_cookie2=true; path=/;"
- "max-age=6500"}],
- http:verify_cookies(SetCookieHeaders, ?URL),
- {"cookie", "$Version=0; test_cookie2=true; $Path=/; "
- "test_cookie=true; $Path=/"} = http:cookie_header(?URL),
- NewSetCookieHeaders = [{"set-cookie", "test_cookie=false; "
- "path=/;max-age=6500"}],
- http:verify_cookies(NewSetCookieHeaders, ?URL),
- {"cookie", "$Version=0; test_cookie2=true; $Path=/; "
- "test_cookie=false; $Path=/"} = http:cookie_header(?URL).
-
+update_cookie(Config) when is_list(Config) ->
+ print_cookies("Cookies before store"),
+
+ SetCookieHeaders =
+ [{"set-cookie", "test_cookie=true; path=/; max-age=6500"},
+ {"set-cookie", "test_cookie2=true; path=/; max-age=6500"}],
+ httpc:store_cookies(SetCookieHeaders, ?URL),
+ print_cookies("Cookies after first store"),
+ ExpectCookie1 =
+ "$Version=0; "
+ "test_cookie=true; $Path=/; "
+ "test_cookie2=true; $Path=/",
+ expect_cookie_header(1, ExpectCookie1),
+
+ NewSetCookieHeaders =
+ [{"set-cookie", "test_cookie=false; path=/; max-age=6500"}],
+ httpc:store_cookies(NewSetCookieHeaders, ?URL),
+ print_cookies("Cookies after second store"),
+ ExpectCookie2 =
+ "$Version=0; "
+ "test_cookie2=true; $Path=/; "
+ "test_cookie=false; $Path=/",
+ expect_cookie_header(2, ExpectCookie2).
+
update_cookie_session(doc)->
- ["Test that a cookie can be updated."];
+ ["Test that a session cookie can be updated."];
update_cookie_session(suite) ->
[];
update_cookie_session(Config) when is_list(Config)->
+ print_cookies("Cookies before store"),
+
SetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/"},
{"set-cookie", "test_cookie2=true; path=/"}],
- http:verify_cookies(SetCookieHeaders, ?URL),
- {"cookie", "$Version=0; test_cookie2=true; $Path=/; "
- "test_cookie=true; $Path=/"} = http:cookie_header(?URL),
+ httpc:store_cookies(SetCookieHeaders, ?URL),
+ print_cookies("Cookies after first store"),
+ ExpectedCookie1 =
+ "$Version=0; test_cookie=true; $Path=/; test_cookie2=true; $Path=/",
+ expect_cookie_header(1, ExpectedCookie1),
+
NewSetCookieHeaders = [{"set-cookie", "test_cookie=false; path=/"}],
- http:verify_cookies(NewSetCookieHeaders, ?URL),
- {"cookie", "$Version=0; test_cookie2=true; $Path=/; "
- "test_cookie=false; $Path=/"} = http:cookie_header(?URL).
+ httpc:store_cookies(NewSetCookieHeaders, ?URL),
+ print_cookies("Cookies after second store"),
+ ExpectedCookie2 =
+ "$Version=0; test_cookie2=true; $Path=/; test_cookie=false; $Path=/",
+ expect_cookie_header(2, ExpectedCookie2).
cookie_attributes(doc) ->
@@ -348,8 +411,8 @@ cookie_attributes(Config) when is_list(Config) ->
"comment=foobar; "%% Comment
"foo=bar;" %% Nonsense should be ignored
"max-age=60000"}],
- http:verify_cookies(SetCookieHeaders, ?URL),
- {"cookie","$Version=1; test_cookie=true"} = http:cookie_header(?URL),
+ httpc:store_cookies(SetCookieHeaders, ?URL),
+ {"cookie","$Version=1; test_cookie=true"} = httpc:cookie_header(?URL),
ok.
@@ -358,7 +421,7 @@ cookie_attributes(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
check_cookie(Expect, URL) ->
- case http:cookie_header(URL) of
+ case httpc:cookie_header(URL) of
{"cookie", Expect} ->
ok;
{"cookie", Unexpected} ->
diff --git a/lib/inets/test/httpd_1_1.erl b/lib/inets/test/httpd_1_1.erl
index 2a6110e3ea..07d94ea97a 100644
--- a/lib/inets/test/httpd_1_1.erl
+++ b/lib/inets/test/httpd_1_1.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,7 +19,6 @@
%%
-module(httpd_1_1).
--author('[email protected]').
-include("test_server.hrl").
-include("test_server_line.hrl").
@@ -159,70 +158,79 @@ if_test(Type, Port, Host, Node, DocRoot)->
calendar:datetime_to_gregorian_seconds(FileInfo#file_info.mtime),
Mod = httpd_util:rfc1123_date(calendar:gregorian_seconds_to_datetime(
- CreatedSec-1)),
-
+ CreatedSec-1)),
+
%% Test that we get the data when the file is modified
ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
- "GET / HTTP/1.1\r\nHost:" ++ Host ++
- "\r\nIf-Modified-Since:" ++
- Mod ++ "\r\n\r\n",
- [{statuscode, 200}]),
- Mod1 = httpd_util:rfc1123_date(calendar:gregorian_seconds_to_datetime(
- CreatedSec+100)),
- ok = httpd_test_lib:verify_request(Type,Host,Port,Node,
- "GET / HTTP/1.1\r\nHost:"
- ++ Host ++"\r\nIf-Modified-Since:"
- ++ Mod1 ++"\r\n\r\n",
- [{statuscode, 304}]),
+ "GET / HTTP/1.1\r\nHost:" ++ Host ++
+ "\r\nIf-Modified-Since:" ++
+ Mod ++ "\r\n\r\n",
+ [{statuscode, 200}]),
+ Mod1 = httpd_util:rfc1123_date(calendar:gregorian_seconds_to_datetime(
+ CreatedSec+100)),
+ ok = httpd_test_lib:verify_request(Type,Host,Port,Node,
+ "GET / HTTP/1.1\r\nHost:"
+ ++ Host ++"\r\nIf-Modified-Since:"
+ ++ Mod1 ++"\r\n\r\n",
+ [{statuscode, 304}]),
+
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET / HTTP/1.1\r\nHost:" ++ Host ++
+ "\r\nIf-Modified-Since:" ++
+ "AAA[...]AAAA" ++ "\r\n\r\n",
+ [{statuscode, 400}]),
+
+
Mod2 = httpd_util:rfc1123_date(calendar:gregorian_seconds_to_datetime(
- CreatedSec+1)),
+ CreatedSec+1)),
%% Control that the If-Unmodified-Header lmits the response
ok = httpd_test_lib:verify_request(Type,Host,Port,Node,
- "GET / HTTP/1.1\r\nHost:"
- ++ Host ++
- "\r\nIf-Unmodified-Since:" ++ Mod2
- ++ "\r\n\r\n",
- [{statuscode, 200}]),
+ "GET / HTTP/1.1\r\nHost:"
+ ++ Host ++
+ "\r\nIf-Unmodified-Since:" ++ Mod2
+ ++ "\r\n\r\n",
+ [{statuscode, 200}]),
Mod3 = httpd_util:rfc1123_date(calendar:gregorian_seconds_to_datetime(
- CreatedSec-1)),
+ CreatedSec-1)),
ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
- "GET / HTTP/1.1\r\nHost:"
- ++ Host ++
- "\r\nIf-Unmodified-Since:"++ Mod3
- ++"\r\n\r\n",
- [{statuscode, 412}]),
-
+ "GET / HTTP/1.1\r\nHost:"
+ ++ Host ++
+ "\r\nIf-Unmodified-Since:"++ Mod3
+ ++"\r\n\r\n",
+ [{statuscode, 412}]),
+
%% Control that we get the body when the etag match
ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
- "GET / HTTP/1.1\r\nHost:" ++ Host
- ++"\r\n"++
- "If-Match:"++
- httpd_util:create_etag(FileInfo)++
- "\r\n\r\n",
- [{statuscode, 200}]),
+ "GET / HTTP/1.1\r\nHost:" ++ Host
+ ++"\r\n"++
+ "If-Match:"++
+ httpd_util:create_etag(FileInfo)++
+ "\r\n\r\n",
+ [{statuscode, 200}]),
ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
- "GET / HTTP/1.1\r\nHost:" ++
- Host ++ "\r\n"++
- "If-Match:NotEtag\r\n\r\n",
- [{statuscode, 412}]),
+ "GET / HTTP/1.1\r\nHost:" ++
+ Host ++ "\r\n"++
+ "If-Match:NotEtag\r\n\r\n",
+ [{statuscode, 412}]),
%% Control the response when the if-none-match header is there
ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
- "GET / HTTP/1.1\r\nHost:"
- ++ Host ++"\r\n"++
- "If-None-Match:NoTaag," ++
- httpd_util:create_etag(FileInfo) ++
- "\r\n\r\n",
- [{statuscode, 304}]),
-
+ "GET / HTTP/1.1\r\nHost:"
+ ++ Host ++"\r\n"++
+ "If-None-Match:NoTaag," ++
+ httpd_util:create_etag(FileInfo) ++
+ "\r\n\r\n",
+ [{statuscode, 304}]),
+
ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
- "GET / HTTP/1.1\r\nHost:"
- ++ Host ++ "\r\n"++
- "If-None-Match:NotEtag,"
- "NeihterEtag\r\n\r\n",
- [{statuscode,200}]).
+ "GET / HTTP/1.1\r\nHost:"
+ ++ Host ++ "\r\n"++
+ "If-None-Match:NotEtag,"
+ "NeihterEtag\r\n\r\n",
+ [{statuscode,200}]),
+ ok.
http_trace(Type, Port, Host, Node)->
ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl
index c4d4bf969b..ba31788ccc 100644
--- a/lib/inets/test/httpd_SUITE.erl
+++ b/lib/inets/test/httpd_SUITE.erl
@@ -68,127 +68,96 @@
-export([
pssl_mod_alias/1,
- ossl_mod_alias/1,
essl_mod_alias/1,
pssl_mod_actions/1,
- ossl_mod_actions/1,
essl_mod_actions/1,
pssl_mod_security/1,
- ossl_mod_security/1,
essl_mod_security/1,
pssl_mod_auth/1,
- ossl_mod_auth/1,
essl_mod_auth/1,
pssl_mod_auth_api/1,
- ossl_mod_auth_api/1,
essl_mod_auth_api/1,
pssl_mod_auth_mnesia_api/1,
- ossl_mod_auth_mnesia_api/1,
essl_mod_auth_mnesia_api/1,
pssl_mod_htaccess/1,
- ossl_mod_htaccess/1,
essl_mod_htaccess/1,
pssl_mod_cgi/1,
- ossl_mod_cgi/1,
essl_mod_cgi/1,
pssl_mod_esi/1,
- ossl_mod_esi/1,
essl_mod_esi/1,
pssl_mod_get/1,
- ossl_mod_get/1,
essl_mod_get/1,
pssl_mod_head/1,
- ossl_mod_head/1,
essl_mod_head/1,
pssl_mod_all/1,
- ossl_mod_all/1,
essl_mod_all/1,
pssl_load_light/1,
- ossl_load_light/1,
essl_load_light/1,
pssl_load_medium/1,
- ossl_load_medium/1,
essl_load_medium/1,
pssl_load_heavy/1,
- ossl_load_heavy/1,
essl_load_heavy/1,
pssl_dos_hostname/1,
- ossl_dos_hostname/1,
essl_dos_hostname/1,
pssl_time_test/1,
- ossl_time_test/1,
essl_time_test/1,
pssl_restart_no_block/1,
- ossl_restart_no_block/1,
essl_restart_no_block/1,
pssl_restart_disturbing_block/1,
- ossl_restart_disturbing_block/1,
essl_restart_disturbing_block/1,
pssl_restart_non_disturbing_block/1,
- ossl_restart_non_disturbing_block/1,
essl_restart_non_disturbing_block/1,
pssl_block_disturbing_idle/1,
- ossl_block_disturbing_idle/1,
essl_block_disturbing_idle/1,
pssl_block_non_disturbing_idle/1,
- ossl_block_non_disturbing_idle/1,
essl_block_non_disturbing_idle/1,
pssl_block_503/1,
- ossl_block_503/1,
essl_block_503/1,
pssl_block_disturbing_active/1,
- ossl_block_disturbing_active/1,
essl_block_disturbing_active/1,
pssl_block_non_disturbing_active/1,
- ossl_block_non_disturbing_active/1,
essl_block_non_disturbing_active/1,
pssl_block_disturbing_active_timeout_not_released/1,
- ossl_block_disturbing_active_timeout_not_released/1,
essl_block_disturbing_active_timeout_not_released/1,
pssl_block_disturbing_active_timeout_released/1,
- ossl_block_disturbing_active_timeout_released/1,
essl_block_disturbing_active_timeout_released/1,
pssl_block_non_disturbing_active_timeout_not_released/1,
- ossl_block_non_disturbing_active_timeout_not_released/1,
essl_block_non_disturbing_active_timeout_not_released/1,
pssl_block_non_disturbing_active_timeout_released/1,
- ossl_block_non_disturbing_active_timeout_released/1,
essl_block_non_disturbing_active_timeout_released/1,
pssl_block_disturbing_blocker_dies/1,
- ossl_block_disturbing_blocker_dies/1,
essl_block_disturbing_blocker_dies/1,
pssl_block_non_disturbing_blocker_dies/1,
- ossl_block_non_disturbing_blocker_dies/1,
essl_block_non_disturbing_blocker_dies/1
]).
@@ -272,8 +241,7 @@ groups() ->
ip_block_non_disturbing_active_timeout_released,
ip_block_disturbing_blocker_dies,
ip_block_non_disturbing_blocker_dies]},
- {ssl, [],
- [{group, pssl}, {group, ossl}, {group, essl}]},
+ {ssl, [], [{group, pssl}, {group, essl}]},
{pssl, [],
[pssl_mod_alias, pssl_mod_actions, pssl_mod_security,
pssl_mod_auth, pssl_mod_auth_api,
@@ -293,25 +261,6 @@ groups() ->
pssl_block_non_disturbing_active_timeout_released,
pssl_block_disturbing_blocker_dies,
pssl_block_non_disturbing_blocker_dies]},
- {ossl, [],
- [ossl_mod_alias, ossl_mod_actions, ossl_mod_security,
- ossl_mod_auth, ossl_mod_auth_api,
- ossl_mod_auth_mnesia_api, ossl_mod_htaccess,
- ossl_mod_cgi, ossl_mod_esi, ossl_mod_get, ossl_mod_head,
- ossl_mod_all, ossl_load_light, ossl_load_medium,
- ossl_load_heavy, ossl_dos_hostname, ossl_time_test,
- ossl_restart_no_block, ossl_restart_disturbing_block,
- ossl_restart_non_disturbing_block,
- ossl_block_disturbing_idle,
- ossl_block_non_disturbing_idle, ossl_block_503,
- ossl_block_disturbing_active,
- ossl_block_non_disturbing_active,
- ossl_block_disturbing_active_timeout_not_released,
- ossl_block_disturbing_active_timeout_released,
- ossl_block_non_disturbing_active_timeout_not_released,
- ossl_block_non_disturbing_active_timeout_released,
- ossl_block_disturbing_blocker_dies,
- ossl_block_non_disturbing_blocker_dies]},
{essl, [],
[essl_mod_alias, essl_mod_actions, essl_mod_security,
essl_mod_auth, essl_mod_auth_api,
@@ -493,7 +442,6 @@ init_per_testcase2(Case, Config) ->
[X, $s, $s, $l | _] ->
case X of
$p -> ssl;
- $o -> ossl;
$e -> essl
end;
_ ->
@@ -636,7 +584,6 @@ init_per_testcase3(Case, Config) ->
SslTag =
case X of
$p -> ssl; % plain
- $o -> ossl; % OpenSSL based ssl
$e -> essl % Erlang based ssl
end,
case inets_test_lib:start_http_server_ssl(
@@ -646,14 +593,13 @@ init_per_testcase3(Case, Config) ->
ok ->
"mod_htaccess";
Other ->
- error_logger:info_report("Other: ~p~n", [Other]),
+ error_logger:info_msg("Other: ~p~n", [Other]),
{skip, "SSL does not seem to be supported"}
end;
[X, $s, $s, $l, $_ | Rest] ->
SslTag =
case X of
$p -> ssl;
- $o -> ossl;
$e -> essl
end,
case inets_test_lib:start_http_server_ssl(
@@ -663,7 +609,7 @@ init_per_testcase3(Case, Config) ->
ok ->
Rest;
Other ->
- error_logger:info_report("Other: ~p~n", [Other]),
+ error_logger:info_msg("Other: ~p~n", [Other]),
{skip, "SSL does not seem to be supported"}
end;
"ipv6_" ++ _ = TestCaseStr ->
@@ -740,6 +686,19 @@ end_per_testcase2(Case, Config) ->
%%-------------------------------------------------------------------------
+http_1_1_ip(doc) ->
+ ["HTTP/1.1"];
+http_1_1_ip(suite) ->
+ [
+ ip_host,
+ ip_chunked,
+ ip_expect,
+ ip_range,
+ ip_if_test,
+ ip_http_trace,
+ ip_http1_1_head,
+ ip_mod_cgi_chunked_encoding_test
+ ].
%%-------------------------------------------------------------------------
@@ -1158,13 +1117,6 @@ pssl_mod_alias(suite) ->
pssl_mod_alias(Config) when is_list(Config) ->
ssl_mod_alias(ssl, Config).
-ossl_mod_alias(doc) ->
- ["Module test: mod_alias - using new of configure old SSL"];
-ossl_mod_alias(suite) ->
- [];
-ossl_mod_alias(Config) when is_list(Config) ->
- ssl_mod_alias(ossl, Config).
-
essl_mod_alias(doc) ->
["Module test: mod_alias - using new of configure new SSL"];
essl_mod_alias(suite) ->
@@ -1188,13 +1140,6 @@ pssl_mod_actions(suite) ->
pssl_mod_actions(Config) when is_list(Config) ->
ssl_mod_actions(ssl, Config).
-ossl_mod_actions(doc) ->
- ["Module test: mod_actions - using new of configure old SSL"];
-ossl_mod_actions(suite) ->
- [];
-ossl_mod_actions(Config) when is_list(Config) ->
- ssl_mod_actions(ossl, Config).
-
essl_mod_actions(doc) ->
["Module test: mod_actions - using new of configure new SSL"];
essl_mod_actions(suite) ->
@@ -1220,13 +1165,6 @@ pssl_mod_security(suite) ->
pssl_mod_security(Config) when is_list(Config) ->
ssl_mod_security(ssl, Config).
-ossl_mod_security(doc) ->
- ["Module test: mod_security - using new of configure old SSL"];
-ossl_mod_security(suite) ->
- [];
-ossl_mod_security(Config) when is_list(Config) ->
- ssl_mod_security(ossl, Config).
-
essl_mod_security(doc) ->
["Module test: mod_security - using new of configure new SSL"];
essl_mod_security(suite) ->
@@ -1253,13 +1191,6 @@ pssl_mod_auth(suite) ->
pssl_mod_auth(Config) when is_list(Config) ->
ssl_mod_auth(ssl, Config).
-ossl_mod_auth(doc) ->
- ["Module test: mod_auth - using new of configure old SSL"];
-ossl_mod_auth(suite) ->
- [];
-ossl_mod_auth(Config) when is_list(Config) ->
- ssl_mod_auth(ossl, Config).
-
essl_mod_auth(doc) ->
["Module test: mod_auth - using new of configure new SSL"];
essl_mod_auth(suite) ->
@@ -1284,13 +1215,6 @@ pssl_mod_auth_api(suite) ->
pssl_mod_auth_api(Config) when is_list(Config) ->
ssl_mod_auth_api(ssl, Config).
-ossl_mod_auth_api(doc) ->
- ["Module test: mod_auth - using new of configure old SSL"];
-ossl_mod_auth_api(suite) ->
- [];
-ossl_mod_auth_api(Config) when is_list(Config) ->
- ssl_mod_auth_api(ossl, Config).
-
essl_mod_auth_api(doc) ->
["Module test: mod_auth - using new of configure new SSL"];
essl_mod_auth_api(suite) ->
@@ -1317,13 +1241,6 @@ pssl_mod_auth_mnesia_api(suite) ->
pssl_mod_auth_mnesia_api(Config) when is_list(Config) ->
ssl_mod_auth_mnesia_api(ssl, Config).
-ossl_mod_auth_mnesia_api(doc) ->
- ["Module test: mod_auth_mnesia_api - using new of configure old SSL"];
-ossl_mod_auth_mnesia_api(suite) ->
- [];
-ossl_mod_auth_mnesia_api(Config) when is_list(Config) ->
- ssl_mod_auth_mnesia_api(ossl, Config).
-
essl_mod_auth_mnesia_api(doc) ->
["Module test: mod_auth_mnesia_api - using new of configure new SSL"];
essl_mod_auth_mnesia_api(suite) ->
@@ -1348,13 +1265,6 @@ pssl_mod_htaccess(suite) ->
pssl_mod_htaccess(Config) when is_list(Config) ->
ssl_mod_htaccess(ssl, Config).
-ossl_mod_htaccess(doc) ->
- ["Module test: mod_htaccess - using new of configure old SSL"];
-ossl_mod_htaccess(suite) ->
- [];
-ossl_mod_htaccess(Config) when is_list(Config) ->
- ssl_mod_htaccess(ossl, Config).
-
essl_mod_htaccess(doc) ->
["Module test: mod_htaccess - using new of configure new SSL"];
essl_mod_htaccess(suite) ->
@@ -1379,13 +1289,6 @@ pssl_mod_cgi(suite) ->
pssl_mod_cgi(Config) when is_list(Config) ->
ssl_mod_cgi(ssl, Config).
-ossl_mod_cgi(doc) ->
- ["Module test: mod_cgi - using new of configure old SSL"];
-ossl_mod_cgi(suite) ->
- [];
-ossl_mod_cgi(Config) when is_list(Config) ->
- ssl_mod_cgi(ossl, Config).
-
essl_mod_cgi(doc) ->
["Module test: mod_cgi - using new of configure new SSL"];
essl_mod_cgi(suite) ->
@@ -1415,13 +1318,6 @@ pssl_mod_esi(suite) ->
pssl_mod_esi(Config) when is_list(Config) ->
ssl_mod_esi(ssl, Config).
-ossl_mod_esi(doc) ->
- ["Module test: mod_esi - using new of configure old SSL"];
-ossl_mod_esi(suite) ->
- [];
-ossl_mod_esi(Config) when is_list(Config) ->
- ssl_mod_esi(ossl, Config).
-
essl_mod_esi(doc) ->
["Module test: mod_esi - using new of configure new SSL"];
essl_mod_esi(suite) ->
@@ -1446,13 +1342,6 @@ pssl_mod_get(suite) ->
pssl_mod_get(Config) when is_list(Config) ->
ssl_mod_get(ssl, Config).
-ossl_mod_get(doc) ->
- ["Module test: mod_get - using new of configure old SSL"];
-ossl_mod_get(suite) ->
- [];
-ossl_mod_get(Config) when is_list(Config) ->
- ssl_mod_get(ossl, Config).
-
essl_mod_get(doc) ->
["Module test: mod_get - using new of configure new SSL"];
essl_mod_get(suite) ->
@@ -1477,13 +1366,6 @@ pssl_mod_head(suite) ->
pssl_mod_head(Config) when is_list(Config) ->
ssl_mod_head(ssl, Config).
-ossl_mod_head(doc) ->
- ["Module test: mod_head - using new of configure old SSL"];
-ossl_mod_head(suite) ->
- [];
-ossl_mod_head(Config) when is_list(Config) ->
- ssl_mod_head(ossl, Config).
-
essl_mod_head(doc) ->
["Module test: mod_head - using new of configure new SSL"];
essl_mod_head(suite) ->
@@ -1508,13 +1390,6 @@ pssl_mod_all(suite) ->
pssl_mod_all(Config) when is_list(Config) ->
ssl_mod_all(ssl, Config).
-ossl_mod_all(doc) ->
- ["All modules test - using new of configure old SSL"];
-ossl_mod_all(suite) ->
- [];
-ossl_mod_all(Config) when is_list(Config) ->
- ssl_mod_all(ossl, Config).
-
essl_mod_all(doc) ->
["All modules test - using new of configure new SSL"];
essl_mod_all(suite) ->
@@ -1539,13 +1414,6 @@ pssl_load_light(suite) ->
pssl_load_light(Config) when is_list(Config) ->
ssl_load_light(ssl, Config).
-ossl_load_light(doc) ->
- ["Test light load - using new of configure old SSL"];
-ossl_load_light(suite) ->
- [];
-ossl_load_light(Config) when is_list(Config) ->
- ssl_load_light(ossl, Config).
-
essl_load_light(doc) ->
["Test light load - using new of configure new SSL"];
essl_load_light(suite) ->
@@ -1571,13 +1439,6 @@ pssl_load_medium(suite) ->
pssl_load_medium(Config) when is_list(Config) ->
ssl_load_medium(ssl, Config).
-ossl_load_medium(doc) ->
- ["Test medium load - using new of configure old SSL"];
-ossl_load_medium(suite) ->
- [];
-ossl_load_medium(Config) when is_list(Config) ->
- ssl_load_medium(ossl, Config).
-
essl_load_medium(doc) ->
["Test medium load - using new of configure new SSL"];
essl_load_medium(suite) ->
@@ -1609,13 +1470,6 @@ pssl_load_heavy(suite) ->
pssl_load_heavy(Config) when is_list(Config) ->
ssl_load_heavy(ssl, Config).
-ossl_load_heavy(doc) ->
- ["Test heavy load - using new of configure old SSL"];
-ossl_load_heavy(suite) ->
- [];
-ossl_load_heavy(Config) when is_list(Config) ->
- ssl_load_heavy(ossl, Config).
-
essl_load_heavy(doc) ->
["Test heavy load - using new of configure new SSL"];
essl_load_heavy(suite) ->
@@ -1647,13 +1501,6 @@ pssl_dos_hostname(suite) ->
pssl_dos_hostname(Config) when is_list(Config) ->
ssl_dos_hostname(ssl, Config).
-ossl_dos_hostname(doc) ->
- ["Denial Of Service (DOS) attack test case - using new of configure old SSL"];
-ossl_dos_hostname(suite) ->
- [];
-ossl_dos_hostname(Config) when is_list(Config) ->
- ssl_dos_hostname(ossl, Config).
-
essl_dos_hostname(doc) ->
["Denial Of Service (DOS) attack test case - using new of configure new SSL"];
essl_dos_hostname(suite) ->
@@ -1679,13 +1526,6 @@ pssl_time_test(suite) ->
pssl_time_test(Config) when is_list(Config) ->
ssl_time_test(ssl, Config).
-ossl_time_test(doc) ->
- ["using new of configure old SSL"];
-ossl_time_test(suite) ->
- [];
-ossl_time_test(Config) when is_list(Config) ->
- ssl_time_test(ossl, Config).
-
essl_time_test(doc) ->
["using new of configure new SSL"];
essl_time_test(suite) ->
@@ -1725,14 +1565,6 @@ pssl_block_503(suite) ->
pssl_block_503(Config) when is_list(Config) ->
ssl_block_503(ssl, Config).
-ossl_block_503(doc) ->
- ["Check that you will receive status code 503 when the server"
- " is blocked and 200 when its not blocked - using new of configure old SSL."];
-ossl_block_503(suite) ->
- [];
-ossl_block_503(Config) when is_list(Config) ->
- ssl_block_503(ossl, Config).
-
essl_block_503(doc) ->
["Check that you will receive status code 503 when the server"
" is blocked and 200 when its not blocked - using new of configure new SSL."];
@@ -1760,15 +1592,6 @@ pssl_block_disturbing_idle(suite) ->
pssl_block_disturbing_idle(Config) when is_list(Config) ->
ssl_block_disturbing_idle(ssl, Config).
-ossl_block_disturbing_idle(doc) ->
- ["Check that you can block/unblock an idle server. The strategy "
- "distribing does not really make a difference in this case."
- "Using new of configure old SSL"];
-ossl_block_disturbing_idle(suite) ->
- [];
-ossl_block_disturbing_idle(Config) when is_list(Config) ->
- ssl_block_disturbing_idle(ossl, Config).
-
essl_block_disturbing_idle(doc) ->
["Check that you can block/unblock an idle server. The strategy "
"distribing does not really make a difference in this case."
@@ -1797,15 +1620,6 @@ pssl_block_non_disturbing_idle(suite) ->
pssl_block_non_disturbing_idle(Config) when is_list(Config) ->
ssl_block_non_disturbing_idle(ssl, Config).
-ossl_block_non_disturbing_idle(doc) ->
- ["Check that you can block/unblock an idle server. The strategy "
- "non distribing does not really make a difference in this case."
- "Using new of configure old SSL"];
-ossl_block_non_disturbing_idle(suite) ->
- [];
-ossl_block_non_disturbing_idle(Config) when is_list(Config) ->
- ssl_block_non_disturbing_idle(ossl, Config).
-
essl_block_non_disturbing_idle(doc) ->
["Check that you can block/unblock an idle server. The strategy "
"non distribing does not really make a difference in this case."
@@ -1834,15 +1648,6 @@ pssl_block_disturbing_active(suite) ->
pssl_block_disturbing_active(Config) when is_list(Config) ->
ssl_block_disturbing_active(ssl, Config).
-ossl_block_disturbing_active(doc) ->
- ["Check that you can block/unblock an active server. The strategy "
- "distribing means ongoing requests should be terminated."
- "Using new of configure old SSL"];
-ossl_block_disturbing_active(suite) ->
- [];
-ossl_block_disturbing_active(Config) when is_list(Config) ->
- ssl_block_disturbing_active(ossl, Config).
-
essl_block_disturbing_active(doc) ->
["Check that you can block/unblock an active server. The strategy "
"distribing means ongoing requests should be terminated."
@@ -1871,15 +1676,6 @@ pssl_block_non_disturbing_active(suite) ->
pssl_block_non_disturbing_active(Config) when is_list(Config) ->
ssl_block_non_disturbing_active(ssl, Config).
-ossl_block_non_disturbing_active(doc) ->
- ["Check that you can block/unblock an idle server. The strategy "
- "non distribing means the ongoing requests should be compleated."
- "Using new of configure old SSL"];
-ossl_block_non_disturbing_active(suite) ->
- [];
-ossl_block_non_disturbing_active(Config) when is_list(Config) ->
- ssl_block_non_disturbing_active(ossl, Config).
-
essl_block_non_disturbing_active(doc) ->
["Check that you can block/unblock an idle server. The strategy "
"non distribing means the ongoing requests should be compleated."
@@ -1910,17 +1706,6 @@ pssl_block_disturbing_active_timeout_not_released(Config)
when is_list(Config) ->
ssl_block_disturbing_active_timeout_not_released(ssl, Config).
-ossl_block_disturbing_active_timeout_not_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "distribing means ongoing requests should be compleated"
- "if the timeout does not occur."
- "Using new of configure old SSL"];
-ossl_block_disturbing_active_timeout_not_released(suite) ->
- [];
-ossl_block_disturbing_active_timeout_not_released(Config)
- when is_list(Config) ->
- ssl_block_disturbing_active_timeout_not_released(ossl, Config).
-
essl_block_disturbing_active_timeout_not_released(doc) ->
["Check that you can block an active server. The strategy "
"distribing means ongoing requests should be compleated"
@@ -1954,17 +1739,6 @@ pssl_block_disturbing_active_timeout_released(Config)
when is_list(Config) ->
ssl_block_disturbing_active_timeout_released(ssl, Config).
-ossl_block_disturbing_active_timeout_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "distribing means ongoing requests should be terminated when"
- "the timeout occurs."
- "Using new of configure old SSL"];
-ossl_block_disturbing_active_timeout_released(suite) ->
- [];
-ossl_block_disturbing_active_timeout_released(Config)
- when is_list(Config) ->
- ssl_block_disturbing_active_timeout_released(ossl, Config).
-
essl_block_disturbing_active_timeout_released(doc) ->
["Check that you can block an active server. The strategy "
"distribing means ongoing requests should be terminated when"
@@ -1999,16 +1773,6 @@ pssl_block_non_disturbing_active_timeout_not_released(Config)
when is_list(Config) ->
ssl_block_non_disturbing_active_timeout_not_released(ssl, Config).
-ossl_block_non_disturbing_active_timeout_not_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "non non distribing means ongoing requests should be completed."
- "Using new of configure old SSL"];
-ossl_block_non_disturbing_active_timeout_not_released(suite) ->
- [];
-ossl_block_non_disturbing_active_timeout_not_released(Config)
- when is_list(Config) ->
- ssl_block_non_disturbing_active_timeout_not_released(ossl, Config).
-
essl_block_non_disturbing_active_timeout_not_released(doc) ->
["Check that you can block an active server. The strategy "
"non non distribing means ongoing requests should be completed."
@@ -2043,17 +1807,6 @@ pssl_block_non_disturbing_active_timeout_released(Config)
when is_list(Config) ->
ssl_block_non_disturbing_active_timeout_released(ssl, Config).
-ossl_block_non_disturbing_active_timeout_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "non distribing means ongoing requests should be completed. "
- "When the timeout occurs the block operation sohould be canceled."
- "Using new of configure old SSL"];
-ossl_block_non_disturbing_active_timeout_released(suite) ->
- [];
-ossl_block_non_disturbing_active_timeout_released(Config)
- when is_list(Config) ->
- ssl_block_non_disturbing_active_timeout_released(ossl, Config).
-
essl_block_non_disturbing_active_timeout_released(doc) ->
["Check that you can block an active server. The strategy "
"non distribing means ongoing requests should be completed. "
@@ -2087,13 +1840,6 @@ pssl_block_disturbing_blocker_dies(suite) ->
pssl_block_disturbing_blocker_dies(Config) when is_list(Config) ->
ssl_block_disturbing_blocker_dies(ssl, Config).
-ossl_block_disturbing_blocker_dies(doc) ->
- ["using new of configure old SSL"];
-ossl_block_disturbing_blocker_dies(suite) ->
- [];
-ossl_block_disturbing_blocker_dies(Config) when is_list(Config) ->
- ssl_block_disturbing_blocker_dies(ossl, Config).
-
essl_block_disturbing_blocker_dies(doc) ->
["using new of configure new SSL"];
essl_block_disturbing_blocker_dies(suite) ->
@@ -2118,13 +1864,6 @@ pssl_block_non_disturbing_blocker_dies(suite) ->
pssl_block_non_disturbing_blocker_dies(Config) when is_list(Config) ->
ssl_block_non_disturbing_blocker_dies(ssl, Config).
-ossl_block_non_disturbing_blocker_dies(doc) ->
- ["using new of configure old SSL"];
-ossl_block_non_disturbing_blocker_dies(suite) ->
- [];
-ossl_block_non_disturbing_blocker_dies(Config) when is_list(Config) ->
- ssl_block_non_disturbing_blocker_dies(ossl, Config).
-
essl_block_non_disturbing_blocker_dies(doc) ->
["using new of configure new SSL"];
essl_block_non_disturbing_blocker_dies(suite) ->
@@ -2149,13 +1888,6 @@ pssl_restart_no_block(suite) ->
pssl_restart_no_block(Config) when is_list(Config) ->
ssl_restart_no_block(ssl, Config).
-ossl_restart_no_block(doc) ->
- ["using new of configure old SSL"];
-ossl_restart_no_block(suite) ->
- [];
-ossl_restart_no_block(Config) when is_list(Config) ->
- ssl_restart_no_block(ossl, Config).
-
essl_restart_no_block(doc) ->
["using new of configure new SSL"];
essl_restart_no_block(suite) ->
@@ -2180,13 +1912,6 @@ pssl_restart_disturbing_block(suite) ->
pssl_restart_disturbing_block(Config) when is_list(Config) ->
ssl_restart_disturbing_block(ssl, Config).
-ossl_restart_disturbing_block(doc) ->
- ["using new of configure old SSL"];
-ossl_restart_disturbing_block(suite) ->
- [];
-ossl_restart_disturbing_block(Config) when is_list(Config) ->
- ssl_restart_disturbing_block(ossl, Config).
-
essl_restart_disturbing_block(doc) ->
["using new of configure new SSL"];
essl_restart_disturbing_block(suite) ->
@@ -2244,13 +1969,6 @@ pssl_restart_non_disturbing_block(suite) ->
pssl_restart_non_disturbing_block(Config) when is_list(Config) ->
ssl_restart_non_disturbing_block(ssl, Config).
-ossl_restart_non_disturbing_block(doc) ->
- ["using new of configure old SSL"];
-ossl_restart_non_disturbing_block(suite) ->
- [];
-ossl_restart_non_disturbing_block(Config) when is_list(Config) ->
- ssl_restart_non_disturbing_block(ossl, Config).
-
essl_restart_non_disturbing_block(doc) ->
["using new of configure new SSL"];
essl_restart_non_disturbing_block(suite) ->
@@ -2571,24 +2289,24 @@ ticket_5913(doc) ->
["Tests that a header without last-modified is handled"];
ticket_5913(suite) -> [];
ticket_5913(Config) ->
- ok=httpd_test_lib:verify_request(ip_comm, ?config(host, Config),
- ?IP_PORT, ?config(node, Config),
+ ok = httpd_test_lib:verify_request(ip_comm, ?config(host, Config),
+ ?IP_PORT, ?config(node, Config),
"GET /cgi-bin/erl/httpd_example:get_bin "
"HTTP/1.0\r\n\r\n",
[{statuscode, 200},
- {version, "HTTP/1.0"}]),
+ {version, "HTTP/1.0"}]),
ok.
ticket_6003(doc) ->
["Tests that a URI with a bad hexadecimal code is handled"];
ticket_6003(suite) -> [];
ticket_6003(Config) ->
- ok=httpd_test_lib:verify_request(ip_comm, ?config(host, Config),
- ?IP_PORT, ?config(node, Config),
- "GET http://www.erlang.org/%skalle "
- "HTTP/1.0\r\n\r\n",
- [{statuscode, 400},
- {version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(ip_comm, ?config(host, Config),
+ ?IP_PORT, ?config(node, Config),
+ "GET http://www.erlang.org/%skalle "
+ "HTTP/1.0\r\n\r\n",
+ [{statuscode, 400},
+ {version, "HTTP/1.0"}]),
ok.
ticket_7304(doc) ->
@@ -2646,7 +2364,6 @@ create_config(Config, Access, FileName) ->
SSL =
if
(Type =:= ssl) orelse
- (Type =:= ossl) orelse
(Type =:= essl) ->
[cline(["SSLCertificateFile ",
filename:join(ServerRoot, "ssl/ssl_server.pem")]),
@@ -3041,7 +2758,6 @@ create_ipv6_config(Config, FileName, Ipv6Address) ->
SSL =
if
(SockType =:= ssl) orelse
- (SockType =:= ossl) orelse
(SockType =:= essl) ->
[cline(["SSLCertificateFile ",
filename:join(ServerRoot, "ssl/ssl_server.pem")]),
diff --git a/lib/inets/test/httpd_basic_SUITE.erl b/lib/inets/test/httpd_basic_SUITE.erl
index f23d0b4765..4cd38f2ec4 100644
--- a/lib/inets/test/httpd_basic_SUITE.erl
+++ b/lib/inets/test/httpd_basic_SUITE.erl
@@ -59,9 +59,28 @@ init_per_suite(Config) ->
"~n Config: ~p", [Config]),
ok = inets:start(),
PrivDir = ?config(priv_dir, Config),
- HttpdConf = [{port, 0}, {ipfamily, inet},
- {server_name, "httpd_test"}, {server_root, PrivDir},
- {document_root, PrivDir}, {bind_address, "localhost"}],
+
+ Dummy =
+"<HTML>
+<HEAD>
+<TITLE>/index.html</TITLE>
+</HEAD>
+<BODY>
+DUMMY
+</BODY>
+</HTML>",
+
+ DummyFile = filename:join([PrivDir,"dummy.html"]),
+ {ok, Fd} = file:open(DummyFile, [write]),
+ ok = file:write(Fd, Dummy),
+ ok = file:close(Fd),
+ HttpdConf = [{port, 0},
+ {ipfamily, inet},
+ {server_name, "httpd_test"},
+ {server_root, PrivDir},
+ {document_root, PrivDir},
+ {bind_address, "localhost"}],
+
[{httpd_conf, HttpdConf} | Config].
%%--------------------------------------------------------------------
@@ -133,6 +152,10 @@ uri_too_long_414(Config) when is_list(Config) ->
{version, "HTTP/0.9"}]),
inets:stop(httpd, Pid).
+
+%%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
+
header_too_long_413(doc) ->
["Test that too long headers's get 413 HTTP code"];
header_too_long_413(suite) ->
@@ -152,34 +175,92 @@ header_too_long_413(Config) when is_list(Config) ->
{version, "HTTP/1.1"}]),
inets:stop(httpd, Pid).
+
+%%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
+
escaped_url_in_error_body(doc) ->
["Test Url-encoding see OTP-8940"];
escaped_url_in_error_body(suite) ->
[];
escaped_url_in_error_body(Config) when is_list(Config) ->
- tsp("escaped_url_in_error_body -> entry with"
- "~n Config: ~p", [Config]),
- HttpdConf = ?config(httpd_conf, Config),
- {ok, Pid} = inets:start(httpd, [{port, 0} | HttpdConf]),
- Info = httpd:info(Pid),
- Port = proplists:get_value(port, Info),
- _Address = proplists:get_value(bind_address, Info),
- Path = "/<b>this_is_bold</b>",
- URL = ?URL_START ++ integer_to_list(Port) ++ Path,
- EscapedPath = http_uri:encode(Path),
- {ok, {404, Body1}} = httpc:request(get, {URL, []},
- [{url_encode, true},
- {version, "HTTP/1.0"}],
- [{full_result, false}]),
- EscapedPath = find_URL_path(string:tokens(Body1, " ")),
- {ok, {404, Body2}} = httpc:request(get, {URL, []},
- [{url_encode, false},
- {version, "HTTP/1.0"}],
- [{full_result, false}]),
+ tsp("escaped_url_in_error_body -> entry"),
+ HttpdConf = ?config(httpd_conf, Config),
+ {ok, Pid} = inets:start(httpd, [{port, 0} | HttpdConf]),
+ Info = httpd:info(Pid),
+ Port = proplists:get_value(port, Info),
+ _Address = proplists:get_value(bind_address, Info),
+
+ %% Request 1
+ tsp("escaped_url_in_error_body -> request 1"),
+ URL1 = ?URL_START ++ integer_to_list(Port),
+ %% Make sure the server is ok, by making a request for a valid page
+ case httpc:request(get, {URL1 ++ "/dummy.html", []},
+ [{url_encode, false},
+ {version, "HTTP/1.0"}],
+ [{full_result, false}]) of
+ {ok, {200, _}} ->
+ %% Don't care about the the body, just that we get a ok response
+ ok;
+ {ok, UnexpectedOK1} ->
+ tsf({unexpected_ok_1, UnexpectedOK1})
+ end,
+
+ %% Request 2
+ tsp("escaped_url_in_error_body -> request 2"),
+ %% Make sure the server is ok, by making a request for a valid page
+ case httpc:request(get, {URL1 ++ "/dummy.html", []},
+ [{url_encode, true},
+ {version, "HTTP/1.0"}],
+ [{full_result, false}]) of
+ {ok, {200, _}} ->
+ %% Don't care about the the body, just that we get a ok response
+ ok;
+ {ok, UnexpectedOK2} ->
+ tsf({unexpected_ok_2, UnexpectedOK2})
+ end,
+
+ %% Request 3
+ tsp("escaped_url_in_error_body -> request 3"),
+ %% Ask for a non-existing page(1)
+ Path = "/<b>this_is_bold<b>",
HTMLEncodedPath = http_util:html_encode(Path),
- HTMLEncodedPath = find_URL_path(string:tokens(Body2, " ")),
+ URL2 = URL1 ++ Path,
+ case httpc:request(get, {URL2, []},
+ [{url_encode, true},
+ {version, "HTTP/1.0"}],
+ [{full_result, false}]) of
+ {ok, {404, Body3}} ->
+ case find_URL_path(string:tokens(Body3, " ")) of
+ HTMLEncodedPath ->
+ ok;
+ BadPath3 ->
+ tsf({unexpected_path_3, HTMLEncodedPath, BadPath3})
+ end;
+ {ok, UnexpectedOK3} ->
+ tsf({unexpected_ok_1, UnexpectedOK3})
+ end,
+
+ %% Request 4
+ tsp("escaped_url_in_error_body -> request 4"),
+ %% Ask for a non-existing page(2)
+ case httpc:request(get, {URL2, []},
+ [{url_encode, false},
+ {version, "HTTP/1.0"}],
+ [{full_result, false}]) of
+ {ok, {404, Body4}} ->
+ case find_URL_path(string:tokens(Body4, " ")) of
+ HTMLEncodedPath ->
+ ok;
+ BadPath4 ->
+ tsf({unexpected_path_2, HTMLEncodedPath, BadPath4})
+ end;
+ {ok, UnexpectedOK4} ->
+ tsf({unexpected_ok_4, UnexpectedOK4})
+ end,
+ tsp("escaped_url_in_error_body -> stop inets"),
inets:stop(httpd, Pid),
- tsp("escaped_url_in_error_body -> done"),
+ tsp("escaped_url_in_error_body -> done"),
ok.
find_URL_path([]) ->
@@ -191,7 +272,14 @@ find_URL_path([_ | Rest]) ->
tsp(F) ->
- tsp(F, []).
+ inets_test_lib:tsp(F).
tsp(F, A) ->
- test_server:format("~p ~p:" ++ F ++ "~n", [self(), ?MODULE | A]).
+ inets_test_lib:tsp(F, A).
+
+tsf(Reason) ->
+ test_server:fail(Reason).
+
+
+skip(Reason) ->
+ {skip, Reason}.
diff --git a/lib/inets/test/httpd_mod.erl b/lib/inets/test/httpd_mod.erl
index 1754cec7bc..5016cdb9e6 100644
--- a/lib/inets/test/httpd_mod.erl
+++ b/lib/inets/test/httpd_mod.erl
@@ -1,8 +1,8 @@
%%
%% %CopyrightBegin%
-%%
+%%
%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
-%%
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
@@ -88,13 +88,13 @@ actions(Type, Port, Host, Node) ->
%%-------------------------------------------------------------------------
security(ServerRoot, Type, Port, Host, Node) ->
-%% io:format(user, "~w:security -> entry with"
-%% "~n ServerRoot: ~p"
-%% "~n Type: ~p"
-%% "~n Port: ~p"
-%% "~n Host: ~p"
-%% "~n Node: ~p"
-%% "~n", [?MODULE, ServerRoot, Type, Port, Host, Node]),
+ %% io:format(user, "~w:security -> entry with"
+ %% "~n ServerRoot: ~p"
+ %% "~n Type: ~p"
+ %% "~n Port: ~p"
+ %% "~n Host: ~p"
+ %% "~n Node: ~p"
+ %% "~n", [?MODULE, ServerRoot, Type, Port, Host, Node]),
%% io:format(user, "~w:security -> register~n", [?MODULE]),
global:register_name(mod_security_test, self()), % Receive events
@@ -175,8 +175,8 @@ security(ServerRoot, Type, Port, Host, Node) ->
[{"one",_, Port, OpenDir,_}] ->
ok;
Blocked ->
- io:format(user, "~w:security -> Blocked: ~p"
- "~n", [?MODULE, Blocked]),
+ %% io:format(user, "~w:security -> Blocked: ~p"
+ %% "~n", [?MODULE, Blocked]),
exit({unexpected_blocked, Blocked})
end,
@@ -917,11 +917,11 @@ list_users(Node, Root, _Host, Port, Dir) ->
receive_security_event(Event, Node, Port) ->
-%% io:format(user, "~w:receive_security_event -> entry with"
-%% "~n Event: ~p"
-%% "~n Node: ~p"
-%% "~n Port: ~p"
-%% "~n", [?MODULE, Event, Node, Port]),
+ %% io:format(user, "~w:receive_security_event -> entry with"
+ %% "~n Event: ~p"
+ %% "~n Node: ~p"
+ %% "~n Port: ~p"
+ %% "~n", [?MODULE, Event, Node, Port]),
receive
Event ->
ok;
diff --git a/lib/inets/test/httpd_test_lib.erl b/lib/inets/test/httpd_test_lib.erl
index 2903aaafa5..1c7bb512cc 100644
--- a/lib/inets/test/httpd_test_lib.erl
+++ b/lib/inets/test/httpd_test_lib.erl
@@ -1,8 +1,8 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
@@ -140,6 +140,9 @@ request(#state{mfa = {Module, Function, Args},
HeadRequest = lists:sublist(RequestStr, 1, 4),
receive
{tcp, Socket, Data} ->
+ io:format("~p ~w[~w]request -> received (tcp) data"
+ "~n Data: ~p"
+ "~n", [self(), ?MODULE, ?LINE, Data]),
print(tcp, Data, State),
case Module:Function([Data | Args]) of
{ok, Parsed} ->
@@ -150,11 +153,19 @@ request(#state{mfa = {Module, Function, Args},
request(State#state{mfa = NewMFA}, TimeOut)
end;
{tcp_closed, Socket} when Function =:= whole_body ->
+ io:format("~p ~w[~w]request -> "
+ "received (tcp) closed when whole_body"
+ "~n", [self(), ?MODULE, ?LINE]),
print(tcp, "closed", State),
State#state{body = hd(Args)};
{tcp_closed, Socket} ->
+ io:format("~p ~w[~w]request -> received (tcp) closed"
+ "~n", [self(), ?MODULE, ?LINE]),
test_server:fail(connection_closed);
{tcp_error, Socket, Reason} ->
+ io:format("~p ~w[~w]request -> received (tcp) error"
+ "~n Reason: ~p"
+ "~n", [self(), ?MODULE, ?LINE, Reason]),
test_server:fail({tcp_error, Reason});
{ssl, Socket, Data} ->
print(ssl, Data, State),
@@ -174,11 +185,21 @@ request(#state{mfa = {Module, Function, Args},
{ssl_error, Socket, Reason} ->
test_server:fail({ssl_error, Reason})
after TimeOut ->
+ io:format("~p ~w[~w]request -> timeout"
+ "~n", [self(), ?MODULE, ?LINE]),
test_server:fail(connection_timed_out)
end.
handle_http_msg({Version, StatusCode, ReasonPharse, Headers, Body},
State = #state{request = RequestStr}) ->
+ io:format("~p ~w[~w]handle_http_msg -> entry with"
+ "~n Version: ~p"
+ "~n StatusCode: ~p"
+ "~n ReasonPharse: ~p"
+ "~n Headers: ~p"
+ "~n Body: ~p"
+ "~n", [self(), ?MODULE, ?LINE,
+ Version, StatusCode, ReasonPharse, Headers, Body]),
case is_expect(RequestStr) of
true ->
State#state{status_line = {Version,
@@ -235,13 +256,14 @@ handle_http_body(Body, State = #state{headers = Headers,
end.
validate(RequestStr, #state{status_line = {Version, StatusCode, _},
- headers = Headers,
- body = Body}, Options, N, P) ->
+ headers = Headers,
+ body = Body}, Options, N, P) ->
%% tsp("validate -> entry with"
%% "~n StatusCode: ~p"
%% "~n Headers: ~p"
%% "~n Body: ~p", [StatusCode, Headers, Body]),
+
check_version(Version, Options),
case lists:keysearch(statuscode, 1, Options) of
{value, _} ->
@@ -255,6 +277,7 @@ validate(RequestStr, #state{status_line = {Version, StatusCode, _},
list_to_integer(Headers#http_response_h.'content-length'),
Body).
+
%%--------------------------------------------------------------------
%% Internal functions
%%------------------------------------------------------------------
@@ -263,21 +286,20 @@ check_version(Version, Options) ->
{value, {version, Version}} ->
ok;
{value, {version, Ver}} ->
- test_server:fail({wrong_version, [{got, Version},
- {expected, Ver}]});
+ tsf({wrong_version, [{got, Version},
+ {expected, Ver}]});
_ ->
case Version of
"HTTP/1.1" ->
ok;
_ ->
- test_server:fail({wrong_version, [{got, Version},
- {expected, "HTTP/1.1"}]})
+ tsf({wrong_version, [{got, Version},
+ {expected, "HTTP/1.1"}]})
end
end.
check_status_code(StatusCode, [], Options) ->
- test_server:fail({wrong_status_code, [{got, StatusCode},
- {expected, Options}]});
+ tsf({wrong_status_code, [{got, StatusCode}, {expected, Options}]});
check_status_code(StatusCode, Current = [_ | Rest], Options) ->
case lists:keysearch(statuscode, 1, Current) of
{value, {statuscode, StatusCode}} ->
@@ -285,8 +307,7 @@ check_status_code(StatusCode, Current = [_ | Rest], Options) ->
{value, {statuscode, _OtherStatus}} ->
check_status_code(StatusCode, Rest, Options);
false ->
- test_server:fail({wrong_status_code, [{got, StatusCode},
- {expected, Options}]})
+ tsf({wrong_status_code, [{got, StatusCode}, {expected, Options}]})
end.
do_validate(_, [], _, _) ->
@@ -317,8 +338,7 @@ do_validate(Header, [{header, HeaderField, Value}|Rest],N,P) ->
Header})
end,
do_validate(Header, Rest, N, P);
-do_validate(Header,[{no_last_modified,HeaderField}|Rest],N,P) ->
-% io:format("Header: ~p~nHeaderField: ~p~n",[Header,HeaderField]),
+do_validate(Header,[{no_last_modified, HeaderField}|Rest],N,P) ->
case lists:keysearch(HeaderField,1,Header) of
{value,_} ->
test_server:fail({wrong_header_field_value, HeaderField,
@@ -331,7 +351,6 @@ do_validate(Header, [_Unknown | Rest], N, P) ->
do_validate(Header, Rest, N, P).
is_expect(RequestStr) ->
-
case inets_regexp:match(RequestStr, "xpect:100-continue") of
{match, _, _}->
true;
@@ -340,15 +359,15 @@ is_expect(RequestStr) ->
end.
%% OTP-5775, content-length
-check_body("GET /cgi-bin/erl/httpd_example:get_bin HTTP/1.0\r\n\r\n", 200, "text/html", Length, _Body) when Length /= 274->
- test_server:fail(content_length_error);
+check_body("GET /cgi-bin/erl/httpd_example:get_bin HTTP/1.0\r\n\r\n", 200, "text/html", Length, _Body) when (Length =/= 274) ->
+ tsf(content_length_error);
check_body("GET /cgi-bin/cgi_echo HTTP/1.0\r\n\r\n", 200, "text/plain",
_, Body) ->
case size(Body) of
100 ->
ok;
_ ->
- test_server:fail(content_length_error)
+ tsf(content_length_error)
end;
check_body(RequestStr, 200, "text/html", _, Body) ->
diff --git a/lib/inets/test/httpd_time_test.erl b/lib/inets/test/httpd_time_test.erl
index f39f9faff0..c54674be36 100644
--- a/lib/inets/test/httpd_time_test.erl
+++ b/lib/inets/test/httpd_time_test.erl
@@ -19,7 +19,7 @@
%%
-module(httpd_time_test).
--export([t/3, t1/2, t2/2, t3/2, t4/2]).
+-export([t/3, t1/2, t2/2, t4/2]).
-export([do/1, do/2, do/3, do/4, do/5]).
@@ -45,10 +45,6 @@ t2(Host, Port) ->
t(ssl, Host, Port).
-t3(Host, Port) ->
- t(ossl, Host, Port).
-
-
t4(Host, Port) ->
t(essl, Host, Port).
diff --git a/lib/inets/test/inets_test_lib.erl b/lib/inets/test/inets_test_lib.erl
index 2e19c41f16..ddb1a49394 100644
--- a/lib/inets/test/inets_test_lib.erl
+++ b/lib/inets/test/inets_test_lib.erl
@@ -340,9 +340,6 @@ connect_bin(SockType, Host, Port) ->
connect_bin(ssl, Host, Port, Opts0) ->
Opts = [binary, {packet,0} | Opts0],
connect(ssl, Host, Port, Opts);
-connect_bin(ossl, Host, Port, Opts0) ->
- Opts = [{ssl_imp, old}, binary, {packet,0} | Opts0],
- connect(ssl, Host, Port, Opts);
connect_bin(essl, Host, Port, Opts0) ->
Opts = [{ssl_imp, new}, binary, {packet,0}, {reuseaddr, true} | Opts0],
connect(ssl, Host, Port, Opts);
@@ -357,9 +354,6 @@ connect_byte(SockType, Host, Port) ->
connect_byte(ssl, Host, Port, Opts0) ->
Opts = [{packet,0} | Opts0],
connect(ssl, Host, Port, Opts);
-connect_byte(ossl, Host, Port, Opts0) ->
- Opts = [{ssl_imp, old}, {packet,0} | Opts0],
- connect(ssl, Host, Port, Opts);
connect_byte(essl, Host, Port, Opts0) ->
Opts = [{ssl_imp, new}, {packet,0} | Opts0],
connect(ssl, Host, Port, Opts);
@@ -421,8 +415,6 @@ connect(ip_comm, Host, Port, Opts) ->
send(ssl, Socket, Data) ->
ssl:send(Socket, Data);
-send(ossl, Socket, Data) ->
- ssl:send(Socket, Data);
send(essl, Socket, Data) ->
ssl:send(Socket, Data);
send(ip_comm,Socket,Data) ->
@@ -431,8 +423,6 @@ send(ip_comm,Socket,Data) ->
close(ssl,Socket) ->
catch ssl:close(Socket);
-close(ossl,Socket) ->
- catch ssl:close(Socket);
close(essl,Socket) ->
catch ssl:close(Socket);
close(ip_comm,Socket) ->
diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk
index 4abc1733d3..1df4558e45 100644
--- a/lib/inets/vsn.mk
+++ b/lib/inets/vsn.mk
@@ -18,7 +18,7 @@
# %CopyrightEnd%
APPLICATION = inets
-INETS_VSN = 5.7
+INETS_VSN = 5.8
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)"
diff --git a/lib/inviso/doc/src/make.dep b/lib/inviso/doc/src/make.dep
deleted file mode 100644
index 9459f74e6d..0000000000
--- a/lib/inviso/doc/src/make.dep
+++ /dev/null
@@ -1,27 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex inviso.tex inviso_as_lib.tex inviso_chapter.tex \
- inviso_lfm.tex inviso_lfm_tpfreader.tex inviso_rt.tex \
- inviso_rt_meta.tex part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: inviso_users_guide_pic1.ps
-
diff --git a/lib/inviso/src/inviso_tool_lib.erl b/lib/inviso/src/inviso_tool_lib.erl
index 7953acedd6..f221c4b6de 100644
--- a/lib/inviso/src/inviso_tool_lib.erl
+++ b/lib/inviso/src/inviso_tool_lib.erl
@@ -19,7 +19,7 @@
%% Support module to the inviso tool.
%%
%% Authors:
-%% Lennart �hman, [email protected]
+%% Lennart Öhman, [email protected]
%% -----------------------------------------------------------------------------
-module(inviso_tool_lib).
@@ -145,10 +145,10 @@ expand_module_names_2(Nodes,DirStr,ModStr,Opts) ->
%% Always returns a regexp or {error,Reason}.
expand_module_names_special_regexp(Str) ->
StrLen=length(Str),
- case regexp:first_match(Str,"[0-9a-zA-Z_/]*") of
- {match,1,StrLen} -> % Ok, it is the special case.
+ case re:run(Str,"[0-9a-zA-Z_/]*") of
+ {match,[{0,StrLen}]} -> % Ok, it is the special case.
{ok,".*"++Str++".*"}; % Convert it to a proper regexp.
- {match,_,_} ->
+ {match,_} ->
{ok,Str}; % Keep it and hope it is a regexp.
nomatch ->
{ok,Str}; % Keep it and hope it is a regexp.
diff --git a/lib/jinterface/doc/src/make.dep b/lib/jinterface/doc/src/make.dep
deleted file mode 100644
index a1b3c322c6..0000000000
--- a/lib/jinterface/doc/src/make.dep
+++ /dev/null
@@ -1,20 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex jinterface.tex jinterface_users_guide.tex \
- part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/jinterface/java_src/Makefile b/lib/jinterface/java_src/Makefile
index 755ef46a8b..19f99831eb 100644
--- a/lib/jinterface/java_src/Makefile
+++ b/lib/jinterface/java_src/Makefile
@@ -29,9 +29,7 @@ VSN=$(JINTERFACE_VSN)
# Common Macros
# ----------------------------------------------------
-# call recursive make explicitly below
-# due to separate makefiles for Ronja & OTP
-# SUB_DIRECTORIES = com/ericsson/otp/erlang
+SUB_DIRECTORIES = com/ericsson/otp/erlang
SPECIAL_TARGETS =
@@ -51,15 +49,5 @@ POM_SRC= $(POM_FILE).src
$(POM_TARGET): $(POM_SRC) ../vsn.mk
sed -e 's;%VSN%;$(VSN);' $< > $@
-# ----------------------------------------------------
-# Default Subdir Targets
-# ----------------------------------------------------
-
-.PHONY: debug opt instr release docs release_docs tests release_tests clean depend
-
-debug opt instr release docs release_docs tests release_tests clean depend: $(TARGET_FILES)
- set -e; set -x; \
- case "$(MAKE)" in *clearmake*) tflag="-T";; *) tflag="";; esac; \
- if test -f com/ericsson/otp/erlang/ignore_config_record.inf; then xflag=$$tflag; fi; \
- (cd com/ericsson/otp/erlang && $(MAKE) -f Makefile.otp $$xflag $@)
+include $(ERL_TOP)/make/otp_subdir.mk
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile.otp b/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile
index d0ff9cda34..e772a2b0a5 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile.otp
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile
@@ -96,7 +96,7 @@ docs:
# include $(ERL_TOP)/make/otp_release_targets.mk
release release_docs release_tests release_html:
- $(MAKE) -f Makefile.otp $(MFLAGS) RELEASE_PATH=$(RELEASE_PATH) $(TARGET_MAKEFILE) $@_spec
+ $(MAKE) $(MFLAGS) RELEASE_PATH=$(RELEASE_PATH) $(TARGET_MAKEFILE) $@_spec
release_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)/java_src/com/ericsson/otp/erlang
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangString.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangString.java
index 19ee92e0d0..23734bf83b 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangString.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangString.java
@@ -166,7 +166,7 @@ public class OtpErlangString extends OtpErlangObject implements Serializable,
/**
* Validate a code point according to Erlang definition; Unicode 3.0.
* That is; valid in the range U+0..U+10FFFF, but not in the range
- * U+D800..U+DFFF (surrogat pairs), nor U+FFFE..U+FFFF (non-characters).
+ * U+D800..U+DFFF (surrogat pairs).
*
* @param cp
* the code point value to validate
@@ -179,8 +179,7 @@ public class OtpErlangString extends OtpErlangObject implements Serializable,
// Erlang definition of valid Unicode code points;
// Unicode 3.0, XML, et.al.
return (cp>>>16) <= 0x10 // in 0..10FFFF; Unicode range
- && (cp & ~0x7FF) != 0xD800 // not in D800..DFFF; surrogate range
- && (cp & ~1) != 0xFFFE; // not in FFFE..FFFF; non-characters
+ && (cp & ~0x7FF) != 0xD800; // not in D800..DFFF; surrogate range
}
/**
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/ignore_config_record.inf b/lib/jinterface/java_src/com/ericsson/otp/erlang/ignore_config_record.inf
deleted file mode 100644
index 0a5053eba3..0000000000
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/ignore_config_record.inf
+++ /dev/null
@@ -1 +0,0 @@
-This file makes clearmake use the -T switch for this subdirectory
diff --git a/lib/kernel/doc/src/Makefile b/lib/kernel/doc/src/Makefile
index de10e31d36..214e994889 100644
--- a/lib/kernel/doc/src/Makefile
+++ b/lib/kernel/doc/src/Makefile
@@ -104,6 +104,8 @@ TOP_SPECS_FILE = specs.xml
# ----------------------------------------------------
XML_FLAGS +=
+SPECS_ESRC = ../../src
+
SPECS_FLAGS = -I../../include
# ----------------------------------------------------
diff --git a/lib/kernel/doc/src/app.xml b/lib/kernel/doc/src/app.xml
index ef1f5985f4..ff8a12fe97 100644
--- a/lib/kernel/doc/src/app.xml
+++ b/lib/kernel/doc/src/app.xml
@@ -4,7 +4,7 @@
<fileref>
<header>
<copyright>
- <year>1997</year><year>2009</year>
+ <year>1997</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -170,7 +170,6 @@ Phases [{Phase,PhaseArgs}] undefined
start phase defined by the <c>start_phases</c> key, and only
after this extended start procedure will
<c>application:start(Application)</c> return.</p>
- <p></p>
<p>Start phases may be used to synchronize startup of an
application and its included applications. In this case,
the <c>mod</c> key must be specified as:</p>
@@ -182,7 +181,6 @@ Phases [{Phase,PhaseArgs}] undefined
for the primary application) both for the primary application
and for each of its included application, for which the start
phase is defined.</p>
- <p></p>
<p>This implies that for an included application, the set of
start phases must be a subset of the set of phases defined
for the primary application. Refer to <em>OTP Design Principles</em> for more information.</p>
diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml
index 6f85388c22..6b89711924 100644
--- a/lib/kernel/doc/src/code.xml
+++ b/lib/kernel/doc/src/code.xml
@@ -177,9 +177,9 @@
archives. But the functions in <c>erl_prim_loader</c> may also be
used by other applications to read files from archives. For
example, the call
- <c>erl_prim_loader:list_dir("/otp/root/lib/mnesia-4.4.7.ez/mnesia-4.4.7/examples/bench)"</c>
+ <c>erl_prim_loader:list_dir( "/otp/root/lib/mnesia-4.4.7.ez/mnesia-4.4.7/examples/bench)"</c>
would list the contents of a directory inside an archive.
- See <seealso marker="erts:erl_prim_loader">erl_prim_loader(3)</seealso></p>
+ See <seealso marker="erts:erl_prim_loader">erl_prim_loader(3)</seealso></p>.
<p>An application archive file and a regular application directory
may coexist. This may be useful when there is a need of having
@@ -288,196 +288,156 @@
<datatypes>
<datatype>
+ <name name="load_ret"/>
+ </datatype>
+ <datatype>
<name name="load_error_rsn"/>
</datatype>
</datatypes>
<funcs>
<func>
- <name>set_path(Path) -> true | {error, What}</name>
+ <name name="set_path" arity="1"/>
<fsummary>Set the code server search path</fsummary>
- <type>
- <v>Path = [Dir]</v>
- <v>Dir = string()</v>
- <v>What = bad_directory | bad_path</v>
- </type>
<desc>
- <p>Sets the code path to the list of directories <c>Path</c>.</p>
+ <p>Sets the code path to the list of directories <c><anno>Path</anno></c>.</p>
<p>Returns <c>true</c> if successful, or
- <c>{error, bad_directory}</c> if any <c>Dir</c> is not
+ <c>{error, bad_directory}</c> if any <c><anno>Dir</anno></c> is not
the name of a directory, or <c>{error, bad_path}</c> if
the argument is invalid.</p>
</desc>
</func>
<func>
- <name>get_path() -> Path</name>
+ <name name="get_path" arity="0"/>
<fsummary>Return the code server search path</fsummary>
- <type>
- <v>Path = [Dir]</v>
- <v>Dir = string()</v>
- </type>
<desc>
<p>Returns the code path</p>
</desc>
</func>
<func>
- <name>add_path(Dir) -> true | {error, What}</name>
- <name>add_pathz(Dir) -> true | {error, What}</name>
+ <name name="add_path" arity="1"/>
+ <name name="add_pathz" arity="1"/>
<fsummary>Add a directory to the end of the code path</fsummary>
- <type>
- <v>Dir = string()</v>
- <v>What = bad_directory</v>
- </type>
+ <type name="add_path_ret"/>
<desc>
- <p>Adds <c>Dir</c> to the code path. The directory is added as
- the last directory in the new path. If <c>Dir</c> already
+ <p>Adds <c><anno>Dir</anno></c> to the code path. The directory is added as
+ the last directory in the new path. If <c><anno>Dir</anno></c> already
exists in the path, it is not added.</p>
<p>Returns <c>true</c> if successful, or
- <c>{error, bad_directory}</c> if <c>Dir</c> is not the name
+ <c>{error, bad_directory}</c> if <c><anno>Dir</anno></c> is not the name
of a directory.</p>
</desc>
</func>
<func>
- <name>add_patha(Dir) -> true | {error, What}</name>
+ <name name="add_patha" arity="1"/>
<fsummary>Add a directory to the beginning of the code path</fsummary>
- <type>
- <v>Dir = string()</v>
- <v>What = bad_directory</v>
- </type>
+ <type name="add_path_ret"/>
<desc>
- <p>Adds <c>Dir</c> to the beginning of the code path. If
- <c>Dir</c> already exists, it is removed from the old
+ <p>Adds <c><anno>Dir</anno></c> to the beginning of the code path. If
+ <c><anno>Dir</anno></c> already exists, it is removed from the old
position in the code path.</p>
<p>Returns <c>true</c> if successful, or
- <c>{error, bad_directory}</c> if <c>Dir</c> is not the name
+ <c>{error, bad_directory}</c> if <c><anno>Dir</anno></c> is not the name
of a directory.</p>
</desc>
</func>
<func>
- <name>add_paths(Dirs) -> ok</name>
- <name>add_pathsz(Dirs) -> ok</name>
+ <name name="add_paths" arity="1"/>
+ <name name="add_pathsz" arity="1"/>
<fsummary>Add directories to the end of the code path</fsummary>
- <type>
- <v>Dirs = [Dir]</v>
- <v>Dir = string()</v>
- </type>
<desc>
- <p>Adds the directories in <c>Dirs</c> to the end of the code
- path. If a <c>Dir</c> already exists, it is not added. This
+ <p>Adds the directories in <c><anno>Dirs</anno></c> to the end of the code
+ path. If a <c><anno>Dir</anno></c> already exists, it is not added. This
function always returns <c>ok</c>, regardless of the validity
- of each individual <c>Dir</c>.</p>
+ of each individual <c><anno>Dir</anno></c>.</p>
</desc>
</func>
<func>
- <name>add_pathsa(Dirs) -> ok</name>
+ <name name="add_pathsa" arity="1"/>
<fsummary>Add directories to the beginning of the code path</fsummary>
- <type>
- <v>Dirs = [Dir]</v>
- <v>Dir = string()</v>
- </type>
<desc>
- <p>Adds the directories in <c>Dirs</c> to the beginning of
- the code path. If a <c>Dir</c> already exists, it is removed
+ <p>Adds the directories in <c><anno>Dirs</anno></c> to the beginning of
+ the code path. If a <c><anno>Dir</anno></c> already exists, it is removed
from the old position in the code path. This function always
returns <c>ok</c>, regardless of the validity of each
- individual <c>Dir</c>.</p>
+ individual <c><anno>Dir</anno></c>.</p>
</desc>
</func>
<func>
- <name>del_path(Name | Dir) -> true | false | {error, What}</name>
+ <name name="del_path" arity="1"/>
<fsummary>Delete a directory from the code path</fsummary>
- <type>
- <v>Name = atom()</v>
- <v>Dir = string()</v>
- <v>What = bad_name</v>
- </type>
<desc>
<p>Deletes a directory from the code path. The argument can be
- an atom <c>Name</c>, in which case the directory with
- the name <c>.../Name[-Vsn][/ebin]</c> is deleted from the code
+ an atom <c><anno>Name</anno></c>, in which case the directory with
+ the name <c>.../<anno>Name</anno>[-Vsn][/ebin]</c> is deleted from the code
path. It is also possible to give the complete directory name
- <c>Dir</c> as argument.</p>
+ <c><anno>Dir</anno></c> as argument.</p>
<p>Returns <c>true</c> if successful, or <c>false</c> if
the directory is not found, or <c>{error, bad_name}</c> if
the argument is invalid.</p>
</desc>
</func>
<func>
- <name>replace_path(Name, Dir) -> true | {error, What}</name>
+ <name name="replace_path" arity="2"/>
<fsummary>Replace a directory with another in the code path</fsummary>
- <type>
- <v>Name = atom()</v>
- <v>Dir = string()</v>
- <v>What = bad_name | bad_directory | {badarg, term()}</v>
- </type>
<desc>
<p>This function replaces an old occurrence of a directory
- named <c>.../Name[-Vsn][/ebin]</c>, in the code path, with
- <c>Dir</c>. If <c>Name</c> does not exist, it adds the new
- directory <c>Dir</c> last in the code path. The new directory
- must also be named <c>.../Name[-Vsn][/ebin]</c>. This function
+ named <c>.../<anno>Name</anno>[-Vsn][/ebin]</c>, in the code path, with
+ <c><anno>Dir</anno></c>. If <c><anno>Name</anno></c> does not exist, it adds the new
+ directory <c><anno>Dir</anno></c> last in the code path. The new directory
+ must also be named <c>.../<anno>Name</anno>[-Vsn][/ebin]</c>. This function
should be used if a new version of the directory (library) is
added to a running system.</p>
<p>Returns <c>true</c> if successful, or
- <c>{error, bad_name}</c> if <c>Name</c> is not found, or
- <c>{error, bad_directory}</c> if <c>Dir</c> does not exist, or
- <c>{error, {badarg, [Name, Dir]}}</c> if <c>Name</c> or
- <c>Dir</c> is invalid.</p>
+ <c>{error, bad_name}</c> if <c><anno>Name</anno></c> is not found, or
+ <c>{error, bad_directory}</c> if <c><anno>Dir</anno></c> does not exist, or
+ <c>{error, {badarg, [<anno>Name</anno>, <anno>Dir</anno>]}}</c> if <c><anno>Name</anno></c> or
+ <c><anno>Dir</anno></c> is invalid.</p>
</desc>
</func>
<func>
- <name>load_file(Module) -> {module, Module} | {error, What}</name>
+ <name name="load_file" arity="1"/>
<fsummary>Load a module</fsummary>
- <type>
- <v>Module = atom()</v>
- <v>What = nofile | sticky_directory | badarg | term()</v>
- </type>
+ <type name="load_ret"/>
<desc>
- <p>Tries to load the Erlang module <c>Module</c>, using
+ <p>Tries to load the Erlang module <c><anno>Module</anno></c>, using
the code path. It looks for the object code file with an
extension that corresponds to the Erlang machine used, for
- example <c>Module.beam</c>. The loading fails if the module
+ example <c><anno>Module</anno>.beam</c>. The loading fails if the module
name found in the object code differs from the name
- <c>Module</c>.
+ <c><anno>Module</anno></c>.
<seealso marker="#load_binary/3">load_binary/3</seealso> must
be used to load object code with a module name that is
different from the file name.</p>
- <p>Returns <c>{module, Module}</c> if successful, or
+ <p>Returns <c>{module, <anno>Module</anno>}</c> if successful, or
<c>{error, nofile}</c> if no object code is found, or
<c>{error, sticky_directory}</c> if the object code resides in
- a sticky directory, or <c>{error, badarg}</c> if the argument
- is invalid. Also if the loading fails, an error tuple is
+ a sticky directory. Also if the loading fails, an error tuple is
returned. See
<seealso marker="erts:erlang#load_module/2">erlang:load_module/2</seealso>
- for possible values of <c>What</c>.</p>
+ for possible values of <c><anno>What</anno></c>.</p>
</desc>
</func>
<func>
- <name>load_abs(Filename) -> {module, Module} | {error, What}</name>
+ <name name="load_abs" arity="1"/>
<fsummary>Load a module, residing in a given file</fsummary>
- <type>
- <v>Filename = string()</v>
- <v>Module = atom()</v>
- <v>What = nofile | sticky_directory | badarg | term()</v>
- </type>
+ <type name="load_ret"/>
+ <type name="loaded_filename"/>
+ <type name="loaded_ret_atoms"/>
<desc>
- <p>Does the same as <c>load_file(Module)</c>, but
- <c>Filename</c> is either an absolute file name, or a
+ <p>Does the same as <c>load_file(<anno>Module</anno>)</c>, but
+ <c><anno>Filename</anno></c> is either an absolute file name, or a
relative file name. The code path is not searched. It returns
a value in the same way as
<seealso marker="#load_file/1">load_file/1</seealso>. Note
- that <c>Filename</c> should not contain the extension (for
+ that <c><anno>Filename</anno></c> should not contain the extension (for
example <c>".beam"</c>); <c>load_abs/1</c> adds the correct
extension itself.</p>
</desc>
</func>
<func>
- <name>ensure_loaded(Module) -> {module, Module} | {error, What}</name>
+ <name name="ensure_loaded" arity="1"/>
<fsummary>Ensure that a module is loaded</fsummary>
- <type>
- <v>Module = atom()</v>
- <v>What = nofile | sticky_directory | embedded | badarg | term()</v>
- </type>
<desc>
<p>Tries to to load a module in the same way as
<seealso marker="#load_file/1">load_file/1</seealso>,
@@ -487,54 +447,45 @@
</desc>
</func>
<func>
- <name>load_binary(Module, Filename, Binary) -> {module, Module} | {error, What}</name>
+ <name name="load_binary" arity="3"/>
<fsummary>Load object code for a module</fsummary>
- <type>
- <v>Module = atom()</v>
- <v>Filename = string()</v>
- <v>What = sticky_directory | badarg | term()</v>
- </type>
+ <type name="loaded_filename"/>
+ <type name="loaded_ret_atoms"/>
<desc>
<p>This function can be used to load object code on remote
- Erlang nodes. The argument <c>Binary</c> must contain
- object code for <c>Module</c>.
- <c>Filename</c> is only used by the code server to keep a
- record of from which file the object code for <c>Module</c>
- comes. Accordingly, <c>Filename</c> is not opened and read by
+ Erlang nodes. The argument <c><anno>Binary</anno></c> must contain
+ object code for <c><anno>Module</anno></c>.
+ <c><anno>Filename</anno></c> is only used by the code server to keep a
+ record of from which file the object code for <c><anno>Module</anno></c>
+ comes. Accordingly, <c><anno>Filename</anno></c> is not opened and read by
the code server.</p>
- <p>Returns <c>{module, Module}</c> if successful, or
+ <p>Returns <c>{module, <anno>Module</anno>}</c> if successful, or
<c>{error, sticky_directory}</c> if the object code resides in
a sticky directory, or <c>{error, badarg}</c> if any argument
is invalid. Also if the loading fails, an error tuple is
returned. See
<seealso marker="erts:erlang#load_module/2">erlang:load_module/2</seealso>
- for possible values of <c>What</c>.</p>
+ for possible values of <c><anno>What</anno></c>.</p>
</desc>
</func>
<func>
- <name>delete(Module) -> true | false</name>
+ <name name="delete" arity="1"/>
<fsummary>Removes current code for a module</fsummary>
- <type>
- <v>Module = atom()</v>
- </type>
<desc>
- <p>Removes the current code for <c>Module</c>, that is,
- the current code for <c>Module</c> is made old. This means
+ <p>Removes the current code for <c><anno>Module</anno></c>, that is,
+ the current code for <c><anno>Module</anno></c> is made old. This means
that processes can continue to execute the code in the module,
but that no external function calls can be made to it.</p>
<p>Returns <c>true</c> if successful, or <c>false</c> if there
- is old code for <c>Module</c> which must be purged first, or
- if <c>Module</c> is not a (loaded) module.</p>
+ is old code for <c><anno>Module</anno></c> which must be purged first, or
+ if <c><anno>Module</anno></c> is not a (loaded) module.</p>
</desc>
</func>
<func>
- <name>purge(Module) -> true | false</name>
+ <name name="purge" arity="1"/>
<fsummary>Removes old code for a module</fsummary>
- <type>
- <v>Module = atom()</v>
- </type>
<desc>
- <p>Purges the code for <c>Module</c>, that is, removes code
+ <p>Purges the code for <c><anno>Module</anno></c>, that is, removes code
marked as old. If some processes still linger in the old code,
these processes are killed before the code is removed.</p>
<p>Returns <c>true</c> if successful and any process needed to
@@ -542,31 +493,26 @@
</desc>
</func>
<func>
- <name>soft_purge(Module) -> true | false</name>
+ <name name="soft_purge" arity="1"/>
<fsummary>Removes old code for a module, unless no process uses it</fsummary>
- <type>
- <v>Module = atom()</v>
- </type>
<desc>
- <p>Purges the code for <c>Module</c>, that is, removes code
+ <p>Purges the code for <c><anno>Module</anno></c>, that is, removes code
marked as old, but only if no processes linger in it.</p>
<p>Returns <c>false</c> if the module could not be purged due
to processes lingering in old code, otherwise <c>true</c>.</p>
</desc>
</func>
<func>
- <name>is_loaded(Module) -> {file, Loaded} | false</name>
+ <name name="is_loaded" arity="1"/>
<fsummary>Check if a module is loaded</fsummary>
- <type>
- <v>Module = atom()</v>
- <v>Loaded = Absname | preloaded | cover_compiled</v>
- <v>Absname = string()</v>
- </type>
- <desc>
- <p>Checks if <c>Module</c> is loaded. If it is,
- <c>{file, Loaded}</c> is returned, otherwise <c>false</c>.</p>
- <p>Normally, <c>Loaded</c> is the absolute file name
- <c>Absname</c> from which the code was obtained. If the module
+ <type name="loaded_filename"/>
+ <type name="loaded_ret_atoms"/>
+ <type_desc name="loaded_filename"><c><anno>Filename</anno></c> is an absolute filename</type_desc>
+ <desc>
+ <p>Checks if <c><anno>Module</anno></c> is loaded. If it is,
+ <c>{file, <anno>Loaded</anno>}</c> is returned, otherwise <c>false</c>.</p>
+ <p>Normally, <c><anno>Loaded</anno></c> is the absolute file name
+ <c>Filename</c> from which the code was obtained. If the module
is preloaded (see
<seealso marker="sasl:script">script(4)</seealso>),
<c>Loaded==preloaded</c>. If the module is Cover compiled (see
@@ -575,32 +521,26 @@
</desc>
</func>
<func>
- <name>all_loaded() -> [{Module, Loaded}]</name>
+ <name name="all_loaded" arity="0"/>
<fsummary>Get all loaded modules</fsummary>
- <type>
- <v>Module = atom()</v>
- <v>Loaded = Absname | preloaded | cover_compiled</v>
- <v>Absname = string()</v>
- </type>
+ <type name="loaded_filename"/>
+ <type name="loaded_ret_atoms"/>
+ <type_desc name="loaded_filename"><c><anno>Filename</anno></c> is an absolute filename</type_desc>
<desc>
- <p>Returns a list of tuples <c>{Module, Loaded}</c> for all
- loaded modules. <c>Loaded</c> is normally the absolute file
+ <p>Returns a list of tuples <c>{<anno>Module</anno>, <anno>Loaded</anno>}</c> for all
+ loaded modules. <c><anno>Loaded</anno></c> is normally the absolute file
name, as described for
<seealso marker="#is_loaded/1">is_loaded/1</seealso>.</p>
</desc>
</func>
<func>
- <name>which(Module) -> Which</name>
+ <name name="which" arity="1"/>
<fsummary>The object code file of a module</fsummary>
- <type>
- <v>Module = atom()</v>
- <v>Which = Filename | non_existing | preloaded | cover_compiled</v>
- <v>Filename = string()</v>
- </type>
+ <type name="loaded_ret_atoms"/>
<desc>
<p>If the module is not loaded, this function searches the code
path for the first file which contains object code for
- <c>Module</c> and returns the absolute file name. If
+ <c><anno>Module</anno></c> and returns the absolute file name. If
the module is loaded, it returns the name of the file which
contained the loaded object code. If the module is pre-loaded,
<c>preloaded</c> is returned. If the module is Cover compiled,
@@ -609,21 +549,16 @@
</desc>
</func>
<func>
- <name>get_object_code(Module) -> {Module, Binary, Filename} | error</name>
+ <name name="get_object_code" arity="1"/>
<fsummary>Get the object code for a module</fsummary>
- <type>
- <v>Module = atom()</v>
- <v>Binary = binary()</v>
- <v>Filename = string()</v>
- </type>
<desc>
<p>Searches the code path for the object code of the module
- <c>Module</c>. It returns <c>{Module, Binary, Filename}</c>
- if successful, and <c>error</c> if not. <c>Binary</c> is a
+ <c><anno>Module</anno></c>. It returns <c>{<anno>Module</anno>, <anno>Binary</anno>, <anno>Filename</anno>}</c>
+ if successful, and <c>error</c> if not. <c><anno>Binary</anno></c> is a
binary data object which contains the object code for
the module. This can be useful if code is to be loaded on a
remote node in a distributed system. For example, loading
- module <c>Module</c> on a node <c>Node</c> is done as
+ module <c><anno>Module</anno></c> on a node <c>Node</c> is done as
follows:</p>
<code type="none">
...
@@ -633,7 +568,7 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name>root_dir() -> string()</name>
+ <name name="root_dir" arity="0"/>
<fsummary>Root directory of Erlang/OTP</fsummary>
<desc>
<p>Returns the root directory of Erlang/OTP, which is
@@ -644,7 +579,7 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name>lib_dir() -> string()</name>
+ <name name="lib_dir" arity="0"/>
<fsummary>Library directory of Erlang/OTP</fsummary>
<desc>
<p>Returns the library directory, <c>$OTPROOT/lib</c>, where
@@ -655,19 +590,16 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name>lib_dir(Name) -> string() | {error, bad_name}</name>
+ <name name="lib_dir" arity="1"/>
<fsummary>Library directory for an application</fsummary>
- <type>
- <v>Name = atom()</v>
- </type>
<desc>
<p>This function is mainly intended for finding out the path
for the "library directory", the top directory, for an
- application <c>Name</c> located under <c>$OTPROOT/lib</c> or
+ application <c><anno>Name</anno></c> located under <c>$OTPROOT/lib</c> or
on a directory referred to via the <c>ERL_LIBS</c>
environment variable.</p>
- <p>If there is a regular directory called <c>Name</c> or
- <c>Name-Vsn</c> in the code path with an <c>ebin</c>
+ <p>If there is a regular directory called <c><anno>Name</anno></c> or
+ <c><anno>Name</anno>-Vsn</c> in the code path with an <c>ebin</c>
subdirectory, the path to this directory is returned (not
the <c>ebin</c> directory). If the directory refers to a
directory in an archive, the archive name is stripped away
@@ -681,23 +613,19 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
<pre>
> <input>code:lib_dir(mnesia).</input>
"/usr/local/otp/lib/mnesia-4.2.2"</pre>
- <p>Returns <c>{error, bad_name}</c> if <c>Name</c>
+ <p>Returns <c>{error, bad_name}</c> if <c><anno>Name</anno></c>
is not the name of an application under <c>$OTPROOT/lib</c> or
on a directory referred to via the <c>ERL_LIBS</c>
environment variable. Fails with an exception if <c>Name</c>
has the wrong type.</p>
- <warning><p>For backward compatibility, <c>Name</c> is also allowed to
+ <warning><p>For backward compatibility, <c><anno>Name</anno></c> is also allowed to
be a string. That will probably change in a future release.</p></warning>
</desc>
</func>
<func>
- <name>lib_dir(Name, SubDir) -> string() | {error, bad_name}</name>
+ <name name="lib_dir" arity="2"/>
<fsummary>subdirectory for an application</fsummary>
- <type>
- <v>Name = atom()</v>
- <v>SubDir = atom()</v>
- </type>
<desc>
<p>Returns the path to a subdirectory directly under the top
directory of an application. Normally the subdirectories
@@ -711,12 +639,12 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
> <input>code:lib_dir(megaco, priv).</input>
"/usr/local/otp/lib/megaco-3.9.1.1/priv"</pre>
- <p>Fails with an exception if <c>Name</c> or <c>SubDir</c> has
+ <p>Fails with an exception if <c><anno>Name</anno></c> or <c><anno>SubDir</anno></c> has
the wrong type.</p>
</desc>
</func>
<func>
- <name>compiler_dir() -> string()</name>
+ <name name="compiler_dir" arity="0"/>
<fsummary>Library directory for the compiler</fsummary>
<desc>
<p>Returns the compiler library directory. Equivalent to
@@ -724,21 +652,18 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name>priv_dir(Name) -> string() | {error, bad_name}</name>
+ <name name="priv_dir" arity="1"/>
<fsummary>Priv directory for an application</fsummary>
- <type>
- <v>Name = atom()</v>
- </type>
<desc>
<p>Returns the path to the <c>priv</c> directory in an
- application. Equivalent to <c>code:lib_dir(Name,priv).</c>.</p>
+ application. Equivalent to <c>code:lib_dir(<anno>Name</anno>, priv).</c>.</p>
- <warning><p>For backward compatibility, <c>Name</c> is also allowed to
+ <warning><p>For backward compatibility, <c><anno>Name</anno></c> is also allowed to
be a string. That will probably change in a future release.</p></warning>
</desc>
</func>
<func>
- <name>objfile_extension() -> ".beam"</name>
+ <name name="objfile_extension" arity="0"/>
<fsummary>Object code file extension</fsummary>
<desc>
<p>Returns the object code file extension that corresponds to
@@ -746,24 +671,16 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name>stick_dir(Dir) -> ok | error</name>
+ <name name="stick_dir" arity="1"/>
<fsummary>Mark a directory as sticky</fsummary>
- <type>
- <v>Dir = string()</v>
- <v>What = term()</v>
- </type>
<desc>
- <p>This function marks <c>Dir</c> as sticky.</p>
+ <p>This function marks <c><anno>Dir</anno></c> as sticky.</p>
<p>Returns <c>ok</c> if successful or <c>error</c> if not.</p>
</desc>
</func>
<func>
- <name>unstick_dir(Dir) -> ok | error</name>
+ <name name="unstick_dir" arity="1"/>
<fsummary>Remove a sticky directory mark</fsummary>
- <type>
- <v>Dir = string()</v>
- <v>What = term()</v>
- </type>
<desc>
<p>This function unsticks a directory which has been marked as
sticky.</p>
@@ -771,45 +688,39 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name>is_sticky(Module) -> true | false</name>
+ <name name="is_sticky" arity="1"/>
<fsummary>Test whether a module is sticky</fsummary>
- <type>
- <v>Module = atom()</v>
- </type>
<desc>
- <p>This function returns <c>true</c> if <c>Module</c> is the
+ <p>This function returns <c>true</c> if <c><anno>Module</anno></c> is the
name of a module that has been loaded from a sticky directory
(or in other words: an attempt to reload the module will fail),
- or <c>false</c> if <c>Module</c> is not a loaded module or is
+ or <c>false</c> if <c><anno>Module</anno></c> is not a loaded module or is
not sticky.</p>
</desc>
</func>
<func>
- <name>rehash() -> ok</name>
+ <name name="rehash" arity="0"/>
<fsummary>Rehash or create code path cache</fsummary>
<desc>
<p>This function creates or rehashes the code path cache.</p>
</desc>
</func>
<func>
- <name>where_is_file(Filename) -> Absname | non_existing</name>
+ <name name="where_is_file" arity="1"/>
<fsummary>Full name of a file located in the code path</fsummary>
- <type>
- <v>Filename = Absname = string()</v>
- </type>
<desc>
- <p>Searches the code path for <c>Filename</c>, a file of
+ <p>Searches the code path for <c><anno>Filename</anno></c>, a file of
arbitrary type. If found, the full name is returned.
<c>non_existing</c> is returned if the file cannot be found.
The function can be useful, for example, to locate
application resource files. If the code path cache is used,
the code server will efficiently read the full name from
- the cache, provided that <c>Filename</c> is an object code
+ the cache, provided that <c><anno>Filename</anno></c> is an object code
file or an <c>.app</c> file.</p>
</desc>
</func>
<func>
- <name>clash() -> ok</name>
+ <name name="clash" arity="0"/>
<fsummary>Search for modules with identical names.</fsummary>
<desc>
<p>Searches the entire code space for module names with
@@ -817,10 +728,10 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name>is_module_native(Module) -> true | false | undefined</name>
+ <name>is_module_native(Module) -> boolean() | undefined</name>
<fsummary>Test whether a module has native code</fsummary>
<type>
- <v>Module = atom()</v>
+ <v>Module = module()</v>
</type>
<desc>
<p>This function returns <c>true</c> if <c>Module</c> is
diff --git a/lib/kernel/doc/src/disk_log.xml b/lib/kernel/doc/src/disk_log.xml
index 9721907162..d278d54d93 100644
--- a/lib/kernel/doc/src/disk_log.xml
+++ b/lib/kernel/doc/src/disk_log.xml
@@ -475,8 +475,7 @@
<fsummary>Close a disk log.</fsummary>
<type name="close_error_rsn"/>
<desc>
- <p> <marker id="close_1"></marker>
-The function <c>close/1</c> closes a
+ <p><marker id="close_1"></marker>The function <c>close/1</c> closes a
local or distributed disk log properly. An internally
formatted log must be closed before the Erlang system is
stopped, otherwise the log is regarded as unclosed and the
diff --git a/lib/kernel/doc/src/erl_ddll.xml b/lib/kernel/doc/src/erl_ddll.xml
index f9514dda2f..1911fb628e 100644
--- a/lib/kernel/doc/src/erl_ddll.xml
+++ b/lib/kernel/doc/src/erl_ddll.xml
@@ -989,7 +989,7 @@
<c>{ok, pending_driver}</c> or <c>{ok, pending_process}</c>.</p>
</item>
</taglist>
- <p>The <c>pending_driver</c><c>MonitorOption</c> is by far
+ <p>The <c>pending_driver</c> <c>MonitorOption</c> is by far
the most useful and it has to be used to ensure that the
driver has really been unloaded and the ports closed
whenever the <c>kill_ports</c> option is used or the
diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml
index e0feaf6ee7..7db20e6343 100644
--- a/lib/kernel/doc/src/file.xml
+++ b/lib/kernel/doc/src/file.xml
@@ -60,11 +60,13 @@
converted, why the Unicode mode for file names is not default on
systems having completely transparent file naming.</p>
- <note>As of R14B01, the most basic file handling modules
- (<c>file</c>, <c>prim_file</c>, <c>filelib</c> and
- <c>filename</c>) accept raw file names, but the rest of OTP is not
- guaranteed to handle them, why Unicode file naming on systems
- where it is not default is still considered experimental.</note>
+ <note>
+ <p>As of R14B01, the most basic file handling modules
+ (<c>file</c>, <c>prim_file</c>, <c>filelib</c> and
+ <c>filename</c>) accept raw file names, but the rest of OTP is not
+ guaranteed to handle them, why Unicode file naming on systems
+ where it is not default is still considered experimental.</p>
+ </note>
<p>Raw file names is a new feature in OTP R14B01, which allows the
user to supply completely uninterpreted file names to the
@@ -95,9 +97,6 @@
<datatypes>
<datatype>
- <name name="bindings"/>
- </datatype>
- <datatype>
<name name="deep_list"/>
</datatype>
<datatype>
@@ -136,12 +135,6 @@
</desc>
</datatype>
<datatype>
- <name name="date"/>
- </datatype>
- <datatype>
- <name name="time"/>
- </datatype>
- <datatype>
<name name="date_time"/>
<desc>
<p>Must denote a valid date and time.</p>
@@ -258,11 +251,9 @@
</item>
</taglist>
<p>Example:</p>
- <code type="none">
-f.txt: {person, "kalle", 25}.
+<code type="none">f.txt: {person, "kalle", 25}.
{person, "pelle", 30}.</code>
- <pre>
-1> <input>file:consult("f.txt").</input>
+<pre>1> <input>file:consult("f.txt").</input>
{ok,[{person,"kalle",25},{person,"pelle",30}]}</pre>
</desc>
</func>
@@ -371,7 +362,6 @@ f.txt: {person, "kalle", 25}.
<p>In a future release, a bad type for the
<c><anno>Filename</anno></c> argument will probably generate
an exception.</p>
- <p></p>
</warning>
</desc>
</func>
@@ -1220,15 +1210,15 @@ f.txt: {person, "kalle", 25}.
<item>
<p>The current system access to the file.</p>
</item>
- <tag><c>atime = time()</c></tag>
+ <tag><c>atime = <seealso marker="#type-date_time">date_time()</seealso></c></tag>
<item>
<p>The last (local) time the file was read.</p>
</item>
- <tag><c>mtime = time()</c></tag>
+ <tag><c>mtime = <seealso marker="#type-date_time">date_time()</seealso></c></tag>
<item>
<p>The last (local) time the file was written.</p>
</item>
- <tag><c>ctime = time()</c></tag>
+ <tag><c>ctime = <seealso marker="#type-date_time">date_time()</seealso></c></tag>
<item>
<p>The interpretation of this time field depends on
the operating system. On Unix, it is the last time
@@ -1532,7 +1522,6 @@ f.txt: {person, "kalle", 25}.
<p>In a future release, a bad type for the
<c><anno>Dir</anno></c>
argument will probably generate an exception.</p>
- <p></p>
</warning>
</desc>
</func>
@@ -1669,15 +1658,15 @@ f.txt: {person, "kalle", 25}.
<p>The following fields are used from the record, if they are
given.</p>
<taglist>
- <tag><c>atime = time()</c></tag>
+ <tag><c>atime = <seealso marker="#type-date_time">date_time()</seealso></c></tag>
<item>
<p>The last (local) time the file was read.</p>
</item>
- <tag><c>mtime = time()</c></tag>
+ <tag><c>mtime = <seealso marker="#type-date_time">date_time()</seealso></c></tag>
<item>
<p>The last (local) time the file was written.</p>
</item>
- <tag><c>ctime = time()</c></tag>
+ <tag><c>ctime = <seealso marker="#type-date_time">date_time()</seealso></c></tag>
<item>
<p>On Unix, any value give for this field will be ignored
(the "ctime" for the file will be set to the current
diff --git a/lib/kernel/doc/src/gen_sctp.xml b/lib/kernel/doc/src/gen_sctp.xml
index 5ceb82ae41..418bfae4b8 100644
--- a/lib/kernel/doc/src/gen_sctp.xml
+++ b/lib/kernel/doc/src/gen_sctp.xml
@@ -45,10 +45,17 @@
SUSE Linux Enterprise Server 10 (x86_64) kernel 2.6.16.27-0.6-smp,
with lksctp-tools-1.0.6, briefly on Solaris 10, and later on
SUSE Linux Enterprise Server 10 Service Pack 1 (x86_64)
- kernel 2.6.16.54-0.2.3-smp with lksctp-tools-1.0.7.</p>
+ kernel 2.6.16.54-0.2.3-smp with lksctp-tools-1.0.7,
+ and later also on FreeBSD 8.2.
+ </p>
+ <p>
+ This module was written for one-to-many style sockets
+ (type <c>seqpacket</c>). With the addition of
+ <seealso marker="#peeloff/2">peeloff/2</seealso>, one-to-one style
+ sockets (type <c>stream</c>) were introduced.
+ </p>
<p>Record definitions for the <c>gen_sctp</c> module can be found using:</p>
- <pre>
- -include_lib("kernel/include/inet_sctp.hrl"). </pre>
+<pre> -include_lib("kernel/include/inet_sctp.hrl"). </pre>
<p>These record definitions use the "new" spelling 'adaptation',
not the deprecated 'adaption', regardless of which
spelling the underlying C API uses.</p>
@@ -63,14 +70,13 @@
<item><seealso marker="#options">SCTP SOCKET OPTIONS</seealso></item>
<item><seealso marker="#examples">SCTP EXAMPLES</seealso></item>
<item><seealso marker="#seealso">SEE ALSO</seealso></item>
- <item><seealso marker="#authors">AUTHORS</seealso></item>
</list>
<marker id="types"></marker>
</section>
<datatypes>
<datatype>
- <name name="assoc_id"/>
+ <name><marker id="type-assoc_id">assoc_id()</marker></name>
<desc>
<p>An opaque term returned in for example #sctp_paddr_change{}
that identifies an association for an SCTP socket. The term
@@ -80,36 +86,18 @@
</desc>
</datatype>
<datatype>
- <name name="hostname"/>
- </datatype>
- <datatype>
- <name name="ip_address"/>
- <desc>
- <p>Represents an address of an SCTP socket.
- It is a tuple as explained in
- <seealso marker="inet">inet(3)</seealso>.</p>
- </desc>
- </datatype>
- <datatype>
- <name name="port_number"/>
- </datatype>
- <datatype>
- <name name="posix"/>
- <desc>
- <p>See <seealso marker="inet#error_codes">
- inet(3); POSIX Error Codes</seealso>.</p>
- </desc>
- </datatype>
- <datatype>
- <name name="sctp_option"/>
+ <name name="option"/>
<desc>
<p>One of the
<seealso marker="#options">SCTP Socket Options.</seealso></p>
- <marker id="type-sctp_socket"></marker>
</desc>
</datatype>
<datatype>
- <name name="sctp_socket"/>
+ <name name="option_name"/>
+ <desc><marker id="type-sctp_socket"></marker></desc>
+ </datatype>
+ <datatype>
+ <name><marker id="type-sctp_socket">sctp_socket()</marker></name>
<desc>
<p>Socket identifier returned from <c>open/*</c>.</p>
<marker id="exports"></marker>
@@ -171,19 +159,17 @@
The result of <c>connect/*</c> is an <c>#sctp_assoc_change{}</c>
event which contains, in particular, the new
<seealso marker="#type-assoc_id">Association ID</seealso>.</p>
- <pre>
- #sctp_assoc_change{
+<pre> #sctp_assoc_change{
state = atom(),
error = atom(),
- outbound_streams = int(),
- inbound_streams = int(),
+ outbound_streams = integer(),
+ inbound_streams = integer(),
assoc_id = assoc_id()
} </pre>
<p>The number of outbound and inbound streams can be set by
giving an <c>sctp_initmsg</c> option to <c>connect</c>
as in:</p>
- <pre>
- connect(<anno>Socket</anno>, Ip, <anno>Port</anno>,
+<pre> connect(<anno>Socket</anno>, Ip, <anno>Port</anno>,
[{sctp_initmsg,#sctp_initmsg{num_ostreams=OutStreams,
max_instreams=MaxInStreams}}]) </pre>
<p>All options <c><anno>Opt</anno></c> are set on the socket before the
@@ -276,15 +262,19 @@
</desc>
</func>
<func>
- <name name="listen" arity="2"/>
+ <name name="listen" arity="2" clause_i="1"/>
+ <name name="listen" arity="2" clause_i="2"/>
<fsummary>Set up a socket to listen.</fsummary>
<desc>
<p>Sets up a socket to listen on the IP address and port number
- it is bound to. <c><anno>IsServer</anno></c> must be <c>true</c>
- or <c>false</c>.
- In the contrast to TCP, in SCTP there is no listening queue length.
- If <c><anno>IsServer</anno></c> is <c>true</c> the socket accepts new associations, i.e.
- it will become an SCTP server socket.</p>
+ it is bound to.</p>
+ <p>For type <c>seqpacket</c> sockets (the default)
+ <c><anno>IsServer</anno></c> must be <c>true</c> or <c>false</c>.
+ In the contrast to TCP, in SCTP there is no listening queue length.
+ If <c><anno>IsServer</anno></c> is <c>true</c> the socket accepts new associations, i.e.
+ it will become an SCTP server socket.</p>
+ <p>For type <c>stream</c> sockets <anno>Backlog</anno> defines
+ the backlog queue length just like in TCP.</p>
</desc>
</func>
<func>
@@ -300,16 +290,57 @@
The default <c><anno>IP</anno></c> and <c><anno>Port</anno></c> are <c>any</c>
and <c>0</c>, meaning bind to all local addresses on any
one free port.</p>
+
+ <p>Other options are:</p>
+ <taglist>
+ <tag><c>inet6</c></tag>
+ <item>
+ <p>Set up the socket for IPv6.</p>
+ </item>
+ <tag><c>inet</c></tag>
+ <item>
+ <p>Set up the socket for IPv4. This is the default.</p>
+ </item>
+ </taglist>
+
<p>A default set of socket <seealso marker="#options">options</seealso>
is used. In particular, the socket is opened in
<seealso marker="#option-binary">binary</seealso> and
<seealso marker="#option-active">passive</seealso> mode,
+ with <anno>SockType</anno> <c>seqpacket</c>,
and with reasonably large
<seealso marker="#option-sndbuf">kernel</seealso> and driver
<seealso marker="#option-buffer">buffers.</seealso></p>
</desc>
</func>
<func>
+ <name name="peeloff" arity="2"/>
+ <fsummary>
+ Peel off a type <c>stream</c> socket from a type <c>seqpacket</c> one
+ </fsummary>
+ <desc>
+ <p>
+ Branch off an existing association <anno>Assoc</anno>
+ in a socket <anno>Socket</anno> of type <c>seqpacket</c>
+ (one-to-may style) into
+ a new socket <anno>NewSocket</anno> of type <c>stream</c>
+ (one-to-one style).
+ </p>
+ <p>
+ The existing association argument <anno>Assoc</anno>
+ can be either a
+ <seealso marker="#record-sctp_assoc_change">
+ #sctp_assoc_change{}
+ </seealso>
+ record as returned from e.g
+ <seealso marker="#recv-2">recv/*</seealso>,
+ <seealso marker="#connect-5">connect/*</seealso> or
+ from a listening socket in active mode. Or it can be just
+ the field <c>assoc_id</c> integer from such a record.
+ </p>
+ </desc>
+ </func>
+ <func>
<name name="recv" arity="1"/>
<name name="recv" arity="2"/>
<fsummary>Receive a message from a socket</fsummary>
@@ -346,11 +377,10 @@
<p><seealso marker="#record-sctp_assoc_change">#sctp_assoc_change{}</seealso>;</p>
</item>
<item>
- <pre>
- #sctp_paddr_change{
+<pre> #sctp_paddr_change{
addr = {ip_address(),port()},
state = atom(),
- error = int(),
+ error = integer(),
assoc_id = assoc_id()
} </pre>
<p>Indicates change of the status of the peer's IP address given by
@@ -384,10 +414,9 @@
converted into a string using <c>error_string/1</c>.</p>
</item>
<item>
- <pre>
- #sctp_send_failed{
+<pre> #sctp_send_failed{
flags = true | false,
- error = int(),
+ error = integer(),
info = #sctp_sndrcvinfo{},
assoc_id = assoc_id()
data = binary()
@@ -405,9 +434,8 @@
returned by <c>recv/*</c>.</p>
</item>
<item>
- <pre>
- #sctp_adaptation_event{
- adaptation_ind = int(),
+<pre> #sctp_adaptation_event{
+ adaptation_ind = integer(),
assoc_id = assoc_id()
} </pre>
<p>Delivered when a peer sends an Adaptation Layer Indication
@@ -417,8 +445,7 @@
the Erlang/SCTP binding, this event is disabled by default.</p>
</item>
<item>
- <pre>
- #sctp_pdapi_event{
+<pre> #sctp_pdapi_event{
indication = sctp_partial_delivery_aborted,
assoc_id = assoc_id()
} </pre>
@@ -475,7 +502,7 @@
<marker id="option-binary"></marker>
<marker id="option-list"></marker>
<taglist>
- <tag><c>{mode, list|binary}</c>or just <c>list</c> or <c>binary</c>.</tag>
+ <tag><c>{mode, list|binary}</c> or just <c>list</c> or <c>binary</c></tag>
<item>
<p>Determines the type of data returned from <c>gen_sctp:recv/1,2</c>.</p>
<marker id="option-active"></marker>
@@ -505,7 +532,7 @@
</list>
<marker id="option-buffer"></marker>
</item>
- <tag><c>{buffer, int()}</c></tag>
+ <tag><c>{buffer, integer()}</c></tag>
<item>
<p>Determines the size of the user-level software buffer used by
the SCTP driver. Not to be confused with <c>sndbuf</c>
@@ -515,7 +542,7 @@
In fact, the <c>val(buffer)</c> is automatically set to
the above maximum when <c>sndbuf</c> or <c>recbuf</c> values are set.</p>
</item>
- <tag><c>{tos, int()}</c></tag>
+ <tag><c>{tos, integer()}</c></tag>
<item>
<p>Sets the Type-Of-Service field on the IP datagrams being sent,
to the given value, which effectively determines a prioritization
@@ -523,7 +550,7 @@
are system-dependent. TODO: we do not provide
symbolic names for these values yet.</p>
</item>
- <tag><c>{priority, int()}</c></tag>
+ <tag><c>{priority, integer()}</c></tag>
<item>
<p>A protocol-independent equivalent of <c>tos</c> above. Setting
priority implies setting tos as well.</p>
@@ -542,7 +569,7 @@
required for high-throughput servers).</p>
<marker id="option-linger"></marker>
</item>
- <tag><c>{linger, {true|false, int()}</c></tag>
+ <tag><c>{linger, {true|false, integer()}</c></tag>
<item>
<p>Determines the timeout in seconds for flushing unsent data in the
<c>gen_sctp:close/1</c> socket call. If the 1st component of the value
@@ -552,14 +579,14 @@
the flushing time-out in seconds.</p>
<marker id="option-sndbuf"></marker>
</item>
- <tag><c>{sndbuf, int()}</c></tag>
+ <tag><c>{sndbuf, integer()}</c></tag>
<item>
<p>The size, in bytes, of the *kernel* send buffer for this socket.
Sending errors would occur for datagrams larger than
<c>val(sndbuf)</c>. Setting this option also adjusts
the size of the driver buffer (see <c>buffer</c> above).</p>
</item>
- <tag><c>{recbuf, int()}</c></tag>
+ <tag><c>{recbuf, integer()}</c></tag>
<item>
<p>The size, in bytes, of the *kernel* recv buffer for this socket.
Sending errors would occur for datagrams larger than
@@ -568,12 +595,11 @@
</item>
<tag><c>{sctp_rtoinfo, #sctp_rtoinfo{}}</c></tag>
<item>
- <pre>
- #sctp_rtoinfo{
+<pre> #sctp_rtoinfo{
assoc_id = assoc_id(),
- initial = int(),
- max = int(),
- min = int()
+ initial = integer(),
+ max = integer(),
+ min = integer()
} </pre>
<p>Determines re-transmission time-out parameters, in milliseconds,
for the association(s) given by <c>assoc_id</c>.
@@ -583,14 +609,13 @@
</item>
<tag><c>{sctp_associnfo, #sctp_assocparams{}}</c></tag>
<item>
- <pre>
- #sctp_assocparams{
+<pre> #sctp_assocparams{
assoc_id = assoc_id(),
- asocmaxrxt = int(),
- number_peer_destinations = int(),
- peer_rwnd = int(),
- local_rwnd = int(),
- cookie_life = int()
+ asocmaxrxt = integer(),
+ number_peer_destinations = integer(),
+ peer_rwnd = integer(),
+ local_rwnd = integer(),
+ cookie_life = integer()
} </pre>
<p>Determines association parameters for the association(s) given by
<c>assoc_id</c>. <c>assoc_id = 0</c> (default) indicates
@@ -599,12 +624,11 @@
</item>
<tag><c>{sctp_initmsg, #sctp_initmsg{}}</c></tag>
<item>
- <pre>
- #sctp_initmsg{
- num_ostreams = int(),
- max_instreams = int(),
- max_attempts = int(),
- max_init_timeo = int()
+<pre> #sctp_initmsg{
+ num_ostreams = integer(),
+ max_instreams = integer(),
+ max_attempts = integer(),
+ max_init_timeo = integer()
} </pre>
<p>Determines the default parameters which this socket attempts
to negotiate with its peer while establishing an association with it.
@@ -628,12 +652,12 @@
for establishing an association.</p>
</item>
</list>
- <p></p>
</item>
- <tag><c>{sctp_autoclose, int()|infinity}</c></tag>
+ <tag><c>{sctp_autoclose, integer() >= 0}</c></tag>
<item>
<p>Determines the time (in seconds) after which an idle association is
- automatically closed.</p>
+ automatically closed. <c>0</c> means that the association is
+ never automatically closed.</p>
</item>
<tag><c>{sctp_nodelay, true|false}</c></tag>
<item>
@@ -655,15 +679,14 @@
<p>Turns on|off automatic mapping of IPv4 addresses into IPv6 ones
(if the socket address family is AF_INET6).</p>
</item>
- <tag><c>{sctp_maxseg, int()}</c></tag>
+ <tag><c>{sctp_maxseg, integer()}</c></tag>
<item>
<p>Determines the maximum chunk size if message fragmentation is used.
If <c>0</c>, the chunk size is limited by the Path MTU only.</p>
</item>
<tag><c>{sctp_primary_addr, #sctp_prim{}}</c></tag>
<item>
- <pre>
- #sctp_prim{
+<pre> #sctp_prim{
assoc_id = assoc_id(),
addr = {IP, Port}
}
@@ -676,8 +699,7 @@
</item>
<tag><c>{sctp_set_peer_primary_addr, #sctp_setpeerprim{}}</c></tag>
<item>
- <pre>
- #sctp_setpeerprim{
+<pre> #sctp_setpeerprim{
assoc_id = assoc_id(),
addr = {IP, Port}
}
@@ -691,9 +713,8 @@
<tag><c>{sctp_adaptation_layer, #sctp_setadaptation{}}</c></tag>
<item>
<marker id="record-sctp_setadaptation"></marker>
- <pre>
- #sctp_setadaptation{
- adaptation_ind = int()
+<pre> #sctp_setadaptation{
+ adaptation_ind = integer()
} </pre>
<p>When set, requests that the local endpoint uses the value given by
<c>adaptation_ind</c> as the Adaptation Indication parameter for
@@ -703,14 +724,13 @@
</item>
<tag><c>{sctp_peer_addr_params, #sctp_paddrparams{}}</c></tag>
<item>
- <pre>
- #sctp_paddrparams{
+<pre> #sctp_paddrparams{
assoc_id = assoc_id(),
address = {IP, Port},
- hbinterval = int(),
- pathmaxrxt = int(),
- pathmtu = int(),
- sackdelay = int(),
+ hbinterval = integer(),
+ pathmaxrxt = integer(),
+ pathmtu = integer(),
+ sackdelay = integer(),
flags = list()
}
IP = ip_address()
@@ -761,24 +781,21 @@
<p><c>sackdelay_disable</c>: disable SAC delay.</p>
</item>
</list>
- <p></p>
</item>
</list>
- <p></p>
</item>
<tag><c>{sctp_default_send_param, #sctp_sndrcvinfo{}}</c></tag>
<item>
<marker id="record-sctp_sndrcvinfo"></marker>
- <pre>
- #sctp_sndrcvinfo{
- stream = int(),
- ssn = int(),
+<pre> #sctp_sndrcvinfo{
+ stream = integer(),
+ ssn = integer(),
flags = list(),
- ppid = int(),
- context = int(),
- timetolive = int(),
- tsn = int(),
- cumtsn = int(),
+ ppid = integer(),
+ context = integer(),
+ timetolive = integer(),
+ tsn = integer(),
+ cumtsn = integer(),
assoc_id = assoc_id()
} </pre>
<p><c>#sctp_sndrcvinfo{}</c> is used both in this socket option, and as
@@ -812,20 +829,17 @@
association, with flushing of unsent data.</p>
</item>
</list>
- <p></p>
<p>Other fields are rarely used. See
<url href="http://www.rfc-archive.org/getrfc.php?rfc=2960">RFC2960</url> and
<url href="http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13">Sockets API Extensions for SCTP</url> for full information.</p>
</item>
</list>
- <p></p>
<marker id="option-sctp_events"></marker>
</item>
<tag><c>{sctp_events, #sctp_event_subscribe{}}</c></tag>
<item>
<marker id="record-sctp_event_subscribe"></marker>
- <pre>
- #sctp_event_subscribe{
+<pre> #sctp_event_subscribe{
data_io_event = true | false,
association_event = true | false,
address_event = true | false,
@@ -850,10 +864,9 @@
</item>
<tag><c>{sctp_delayed_ack_time, #sctp_assoc_value{}}</c></tag>
<item>
- <pre>
- #sctp_assoc_value{
+<pre> #sctp_assoc_value{
assoc_id = assoc_id(),
- assoc_value = int()
+ assoc_value = integer()
} </pre>
<p>Rarely used. Determines the ACK time
(given by <c>assoc_value</c> in milliseconds) for
@@ -862,16 +875,15 @@
</item>
<tag><c>{sctp_status, #sctp_status{}}</c></tag>
<item>
- <pre>
- #sctp_status{
+<pre> #sctp_status{
assoc_id = assoc_id(),
state = atom(),
- rwnd = int(),
- unackdata = int(),
- penddata = int(),
- instrms = int(),
- outstrms = int(),
- fragmentation_point = int(),
+ rwnd = integer(),
+ unackdata = integer(),
+ penddata = integer(),
+ instrms = integer(),
+ outstrms = integer(),
+ fragmentation_point = integer(),
primary = #sctp_paddrinfo{}
} </pre>
<p>This option is read-only. It determines the status of
@@ -935,21 +947,19 @@
address (see below for the format of <c>#sctp_paddrinfo{}</c>).</p>
</item>
</list>
- <p></p>
<marker id="option-sctp_get_peer_addr_info"></marker>
</item>
<tag><c>{sctp_get_peer_addr_info, #sctp_paddrinfo{}}</c></tag>
<item>
<marker id="record-sctp_paddrinfo"></marker>
- <pre>
- #sctp_paddrinfo{
+<pre> #sctp_paddrinfo{
assoc_id = assoc_id(),
address = {IP, Port},
state = inactive | active,
- cwnd = int(),
- srtt = int(),
- rto = int(),
- mtu = int()
+ cwnd = integer(),
+ srtt = integer(),
+ rto = integer(),
+ mtu = integer()
}
IP = ip_address()
Port = port_number() </pre>
@@ -973,8 +983,7 @@
<item>
<p>Example of an Erlang SCTP Server which receives SCTP messages and
prints them on the standard output:</p>
- <pre>
- -module(sctp_server).
+<pre> -module(sctp_server).
-export([server/0,server/1,server/2]).
-include_lib("kernel/include/inet.hrl").
@@ -990,7 +999,7 @@
server(IP, Port) when is_tuple(IP) orelse IP == any orelse IP == loopback,
is_integer(Port) -&gt;
- {ok,S} = gen_sctp:open([{ip,IP},{port,Port}],[{recbuf,65536}]),
+ {ok,S} = gen_sctp:open(Port, [{recbuf,65536}, {ip,IP}]),
io:format("Listening on ~w:~w. ~w~n", [IP,Port,S]),
ok = gen_sctp:listen(S, true),
server_loop(S).
@@ -1003,7 +1012,6 @@
io:format("Received: ~p~n", [Data])
end,
server_loop(S). </pre>
- <p></p>
</item>
<item>
<p>Example of an Erlang SCTP Client which interacts with the above Server.
@@ -1013,8 +1021,7 @@
over Stream 5 fails. The client then <c>abort</c>s the association,
which results in the corresponding Event being received on
the Server side.</p>
- <pre>
- -module(sctp_client).
+<pre> -module(sctp_client).
-export([client/0, client/1, client/2]).
-include_lib("kernel/include/inet.hrl").
@@ -1047,13 +1054,11 @@
timer:sleep(1000),
gen_sctp:close(S). </pre>
- <p></p>
</item>
<item>
<p>A very simple Erlang SCTP Client which uses the
connect_init API.</p>
- <pre>
--module(ex3).
+<pre>-module(ex3).
-export([client/4]).
-include_lib("kernel/include/inet.hrl").
@@ -1106,7 +1111,6 @@ client_loop(S, Peer1, Port1, AssocId1, Peer2, Port2, AssocId2) -&gt;
ok
end.
</pre>
- <p></p>
</item>
</list>
</section>
@@ -1119,7 +1123,6 @@ client_loop(S, Peer1, Port1, AssocId1, Peer2, Port2, AssocId2) -&gt;
<seealso marker="gen_udp">gen_udp(3)</seealso>,
<url href="http://www.rfc-archive.org/getrfc.php?rfc=2960">RFC2960</url> (Stream Control Transmission Protocol),
<url href="http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13">Sockets API Extensions for SCTP.</url></p>
- <marker id="authors"></marker>
</section>
</erlref>
diff --git a/lib/kernel/doc/src/gen_tcp.xml b/lib/kernel/doc/src/gen_tcp.xml
index f1d42d9faa..8a5d40bb16 100644
--- a/lib/kernel/doc/src/gen_tcp.xml
+++ b/lib/kernel/doc/src/gen_tcp.xml
@@ -37,7 +37,7 @@
binary and closing the connection:</p>
<code type="none">
client() ->
- SomeHostInNet = "localhost" % to make it runnable on one machine
+ SomeHostInNet = "localhost", % to make it runnable on one machine
{ok, Sock} = gen_tcp:connect(SomeHostInNet, 5678,
[binary, {packet, 0}]),
ok = gen_tcp:send(Sock, "Some Data"),
@@ -65,25 +65,16 @@ do_recv(Sock, Bs) ->
<datatypes>
<datatype>
- <name name="hostname"/>
+ <name name="option"/>
</datatype>
<datatype>
- <name name="ip_address"/>
- <desc>
- <p>Represents an address of a TCP socket.
- It is a tuple as explained in
- <seealso marker="inet">inet(3)</seealso>.</p>
- </desc>
+ <name name="option_name"/>
</datatype>
<datatype>
- <name name="port_number"/>
+ <name name="connect_option"/>
</datatype>
<datatype>
- <name name="posix"/>
- <desc>
- <p>See <seealso marker="inet#error_codes">
- inet(3); POSIX Error Codes</seealso>.</p>
- </desc>
+ <name name="listen_option"/>
</datatype>
<datatype>
<name><marker id="type-socket">socket()</marker></name>
@@ -122,7 +113,7 @@ do_recv(Sock, Bs) ->
<item>
<p>Specify which local port number to use.</p>
</item>
- <tag><c>{fd, int()}</c></tag>
+ <tag><c>{fd, integer() >= 0}</c></tag>
<item>
<p>If a socket has somehow been connected without using
<c>gen_tcp</c>, use this option to pass the file
@@ -196,6 +187,10 @@ do_recv(Sock, Bs) ->
<p>If the host has several network interfaces, this option
specifies which one to listen on.</p>
</item>
+ <tag><c>{port, Port}</c></tag>
+ <item>
+ <p>Specify which local port number to use.</p>
+ </item>
<tag><c>{fd, Fd}</c></tag>
<item>
<p>If a socket has somehow been connected without using
diff --git a/lib/kernel/doc/src/gen_udp.xml b/lib/kernel/doc/src/gen_udp.xml
index c0e783f508..daa9b7d887 100644
--- a/lib/kernel/doc/src/gen_udp.xml
+++ b/lib/kernel/doc/src/gen_udp.xml
@@ -36,25 +36,10 @@
<datatypes>
<datatype>
- <name name="hostname"/>
+ <name name="option"/>
</datatype>
<datatype>
- <name name="ip_address"/>
- <desc>
- <p>Represents an address of a TCP socket.
- It is a tuple as explained in
- <seealso marker="inet">inet(3)</seealso>.</p>
- </desc>
- </datatype>
- <datatype>
- <name name="port_number"/>
- </datatype>
- <datatype>
- <name name="posix"/>
- <desc>
- <p>See <seealso marker="inet#error_codes">
- inet(3); POSIX Error Codes</seealso>.</p>
- </desc>
+ <name name="option_name"/>
</datatype>
<datatype>
<name><marker id="type-socket">socket()</marker></name>
@@ -87,7 +72,7 @@
<p>If the host has several network interfaces, this option
specifies which one to use.</p>
</item>
- <tag><c>{fd, int()}</c></tag>
+ <tag><c>{fd, integer() >= 0}</c></tag>
<item>
<p>If a socket has somehow been opened without using
<c>gen_udp</c>, use this option to pass the file
diff --git a/lib/kernel/doc/src/heart.xml b/lib/kernel/doc/src/heart.xml
index e2dbcbe63d..26d1e27822 100644
--- a/lib/kernel/doc/src/heart.xml
+++ b/lib/kernel/doc/src/heart.xml
@@ -42,7 +42,7 @@
system.</p>
<p>An Erlang runtime system to be monitored by a heart program,
should be started with the command line flag <c>-heart</c> (see
- also <seealso marker="erts:erl">erl(1)</seealso>. The <c>heart</c>
+ also <seealso marker="erts:erl">erl(1)</seealso>). The <c>heart</c>
process is then started automatically:</p>
<pre>
% <input>erl -heart ...</input></pre>
diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml
index fd843b00d9..fad5af85bb 100644
--- a/lib/kernel/doc/src/inet.xml
+++ b/lib/kernel/doc/src/inet.xml
@@ -105,6 +105,9 @@ fe80::204:acff:fe17:bf38
<name name="ip6_address"/>
</datatype>
<datatype>
+ <name name="port_number"/>
+ </datatype>
+ <datatype>
<name name="posix"/>
<desc><p>An atom which is named from the Posix error codes
used in Unix, and in the runtime libraries of most
@@ -119,7 +122,7 @@ fe80::204:acff:fe17:bf38
</desc>
</datatype>
<datatype>
- <name name="family_option"/>
+ <name name="address_family"/>
</datatype>
</datatypes>
@@ -250,26 +253,15 @@ fe80::204:acff:fe17:bf38
</func>
<func>
- <name>getopts(Socket, Options) -> {ok, OptionValues} | {error, posix()}</name>
+ <name name="getopts" arity="2"/>
<fsummary>Get one or more options for a socket</fsummary>
- <type>
- <v>Socket = term()</v>
- <v>Options = [Opt | RawOptReq]</v>
- <v>Opt = atom()</v>
- <v>RawOptReq = {raw, Protocol, OptionNum, ValueSpec}</v>
- <v>Protocol = integer()</v>
- <v>OptionNum = integer()</v>
- <v>ValueSpec = ValueSize | ValueBin</v>
- <v>ValueSize = integer()</v>
- <v>ValueBin = binary()</v>
- <v>OptionValues = [{Opt, Val} | {raw, Protocol, OptionNum, ValueBin}]</v>
- </type>
<type name="socket_getopt"/>
+ <type name="socket_setopt"/>
<desc>
<p>Gets one or more options for a socket.
See <seealso marker="#setopts/2">setopts/2</seealso>
for a list of available options.</p>
- <p>The number of elements in the returned <c>OptionValues</c>
+ <p>The number of elements in the returned <c><anno>OptionValues</anno></c>
list does not necessarily correspond to the number of options
asked for. If the operating system fails to support an option,
it is simply left out in the returned list. An error tuple is only
@@ -277,12 +269,12 @@ fe80::204:acff:fe17:bf38
(i.e. the socket is closed or the buffer size in a raw request
is too large). This behavior is kept for backward
compatibility reasons.</p>
- <p>A <c>RawOptReq</c> can be used to get information about
+ <p>A raw option request <c>RawOptReq = {raw, Protocol, OptionNum, ValueSpec}</c> can be used to get information about
socket options not (explicitly) supported by the emulator. The
use of raw socket options makes the code non portable, but
allows the Erlang programmer to take advantage of unusual features
present on the current platform.</p>
- <p>The <c>RawOptReq</c> consists of the tag <c>raw</c> followed
+ <p>The <c>RawOptReq</c> consists of the tag <c>raw</c> followed
by the protocol level, the option number and either a binary
or the size, in bytes, of the
buffer in which the option value is to be stored. A binary
@@ -325,19 +317,14 @@ fe80::204:acff:fe17:bf38
</func>
<func>
- <name>getstat(Socket)</name>
- <name>getstat(Socket, Options) -> {ok, OptionValues} | {error, posix()}</name>
+ <name name="getstat" arity="1"/>
+ <name name="getstat" arity="2"/>
<fsummary>Get one or more statistic options for a socket</fsummary>
- <type>
- <v>Socket = term()</v>
- <v>Options = [Opt]</v>
- <v>OptionValues = [{Opt, Val}]</v>
- <v>&nbsp;Opt, Val -- see below</v>
- </type>
+ <type name="stat_option"/>
<desc>
<p>Gets one or more statistic options for a socket.</p>
- <p><c>getstat(Socket)</c> is equivalent to
- <c>getstat(Socket,&nbsp;[recv_avg,&nbsp;recv_cnt,&nbsp;recv_dvi,&nbsp;recv_max,&nbsp;recv_oct,&nbsp;send_avg,&nbsp;send_cnt,&nbsp;send_dvi,&nbsp;send_max,&nbsp;send_oct])</c></p>
+ <p><c>getstat(<anno>Socket</anno>)</c> is equivalent to
+ <c>getstat(<anno>Socket</anno>,&nbsp;[recv_avg,&nbsp;recv_cnt,&nbsp;recv_dvi,&nbsp;recv_max,&nbsp;recv_oct,&nbsp;send_avg,&nbsp;send_cnt,&nbsp;send_dvi,&nbsp;send_max,&nbsp;send_oct])</c></p>
<p>The following options are available:</p>
<taglist>
<tag><c>recv_avg</c></tag>
@@ -394,12 +381,8 @@ fe80::204:acff:fe17:bf38
</desc>
</func>
<func>
- <name>port(Socket) -> {ok, Port} | {error, any()}</name>
+ <name name="port" arity="1"/>
<fsummary>Return the local port number for a socket</fsummary>
- <type>
- <v>Socket = socket()</v>
- <v>Port = integer()</v>
- </type>
<desc>
<p>Returns the local port number for a socket.</p>
</desc>
@@ -412,16 +395,9 @@ fe80::204:acff:fe17:bf38
</desc>
</func>
<func>
- <name>setopts(Socket, Options) -> ok | {error, posix()}</name>
+ <name name="setopts" arity="2"/>
<fsummary>Set one or more options for a socket</fsummary>
- <type>
- <v>Socket = term()</v>
- <v>Options = [{Opt, Val} | {raw, Protocol, Option, ValueBin}]</v>
- <v>Protocol = integer()</v>
- <v>OptionNum = integer()</v>
- <v>ValueBin = binary()</v>
- <v>&nbsp;Opt, Val -- see below</v>
- </type>
+ <type name="socket_setopt"/>
<desc>
<p>Sets one or more options for a socket. The following options
are available:</p>
@@ -579,8 +555,14 @@ fe80::204:acff:fe17:bf38
mode will return <c>{ok, HttpPacket}</c> from <c>gen_tcp:recv</c>
while an active socket will send messages like <c>{http,
Socket, HttpPacket}</c>.</p>
- <p>Note that the packet type <c>httph</c> is not
- needed when reading from a socket.</p>
+ </item>
+ <tag><c>httph | httph_bin</c></tag>
+ <item>
+ <p>These two types are often not needed as the socket will
+ automatically switch from <c>http</c>/<c>http_bin</c> to
+ <c>httph</c>/<c>httph_bin</c> internally after the first line
+ has been read. There might be occasions however when they are
+ useful, such as parsing trailers from chunked encoding.</p>
</item>
</taglist>
</item>
diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml
index bf513b7815..0f71a4f0f2 100644
--- a/lib/kernel/doc/src/kernel_app.xml
+++ b/lib/kernel/doc/src/kernel_app.xml
@@ -4,7 +4,7 @@
<appref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -231,6 +231,15 @@ MaxT = TickTime + TickTime / 4</code>
<p><em>Note:</em> Normally, a terminating node is detected
immediately.</p>
</item>
+ <tag><c>shutdown_timeout = integer() | infinity</c></tag>
+ <item>
+ <p>Specifies the time <c>application_controller</c> will wait
+ for an application to terminate during node shutdown. If the
+ timer expires, <c>application_controller</c> will brutally
+ kill <c>application_master</c> of the hanging
+ application. If this parameter is undefined, it defaults
+ to <c>infinity</c>.</p>
+ </item>
<tag><c>sync_nodes_mandatory = [NodeName]</c></tag>
<item>
<p>Specifies which other nodes <em>must</em> be alive in order
diff --git a/lib/kernel/doc/src/make.dep b/lib/kernel/doc/src/make.dep
deleted file mode 100644
index f79d1c6367..0000000000
--- a/lib/kernel/doc/src/make.dep
+++ /dev/null
@@ -1,28 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: app.tex application.tex auth.tex book.tex \
- code.tex config.tex disk_log.tex erl_boot_server.tex \
- erl_ddll.tex erl_prim_loader_stub.tex erlang_stub.tex \
- error_handler.tex error_logger.tex file.tex \
- gen_sctp.tex gen_tcp.tex gen_udp.tex global.tex \
- global_group.tex heart.tex inet.tex inet_res.tex \
- init_stub.tex kernel_app.tex net_adm.tex net_kernel.tex \
- os.tex packages.tex pg2.tex ref_man.tex rpc.tex \
- seq_trace.tex user.tex wrap_log_reader.tex \
- zlib_stub.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/kernel/doc/src/net_kernel.xml b/lib/kernel/doc/src/net_kernel.xml
index 96e2aa665d..e54a427ff0 100644
--- a/lib/kernel/doc/src/net_kernel.xml
+++ b/lib/kernel/doc/src/net_kernel.xml
@@ -37,13 +37,10 @@
monitoring of the network.</p>
<p>An Erlang node is started using the command line flag
<c>-name</c> or <c>-sname</c>:</p>
- <pre>
-$ <input>erl -sname foobar</input></pre>
+<pre>$ <input>erl -sname foobar</input></pre>
<p>It is also possible to call <c>net_kernel:start([foobar])</c>
directly from the normal Erlang shell prompt:</p>
- <p></p>
- <pre>
-1> <input>net_kernel:start([foobar, shortnames]).</input>
+<pre>1> <input>net_kernel:start([foobar, shortnames]).</input>
{ok,&lt;0.64.0>}
(foobar@gringotts)2></pre>
<p>If the node is started with the command line flag <c>-sname</c>,
@@ -213,6 +210,10 @@ $ <input>erl -sname foobar</input></pre>
<p><c>net_kernel</c> is currently changing
<c>net_ticktime</c> to <c><anno>NetTicktime</anno></c> seconds.</p>
</item>
+ <tag><c>ignored</c></tag>
+ <item>
+ <p>The local node is not alive.</p>
+ </item>
</taglist>
</desc>
</func>
@@ -226,7 +227,6 @@ $ <input>erl -sname foobar</input></pre>
<c><anno>NetTicktime</anno></c> seconds. <c><anno>TransitionPeriod</anno></c> defaults
to 60.</p>
<p>Some definitions:</p>
- <p></p>
<taglist>
<tag>The minimum transition traffic interval (<c>MTTI</c>)</tag>
<item>
diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml
index e325443f6c..ec57b03bd9 100644
--- a/lib/kernel/doc/src/notes.xml
+++ b/lib/kernel/doc/src/notes.xml
@@ -30,6 +30,62 @@
</header>
<p>This document describes the changes made to the Kernel application.</p>
+<section><title>Kernel 2.14.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix type of Packet arg of gen_tcp:send/2 and
+ gen_udp:send/4</p>
+ <p>
+ The type is marked as a binary() or a string() but in
+ practice it can be an iodata(). The test suite was
+ updated to confirm the gen_tcp/2 and gen_udp:send/4
+ functions accept iodata() (iolists) packets. (Thanks to
+ Filipe David Manana)</p>
+ <p>
+ Own Id: OTP-9514</p>
+ </item>
+ <item>
+ <p> XML files have been corrected. </p>
+ <p>
+ Own Id: OTP-9550 Aux Id: OTP-9541 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> The types and specifications of the inet modules have
+ been improved. </p>
+ <p>
+ Own Id: OTP-9260</p>
+ </item>
+ <item>
+ <p> Types and specifications have been added. </p>
+ <p>
+ Own Id: OTP-9356</p>
+ </item>
+ <item>
+ <p> Contracts in STDLIB and Kernel have been improved and
+ type errors have been corrected. </p>
+ <p>
+ Own Id: OTP-9485</p>
+ </item>
+ <item>
+ <p> Update documentation and specifications of some of
+ the zlib functions. </p>
+ <p>
+ Own Id: OTP-9506</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Kernel 2.14.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -2535,7 +2591,7 @@
<c>badarg</c> if a process is already registered. As it
turns out there is no check in <c>global</c> if a process is
registered under more than one name. If some process is
- accidentaly or by design given several names, it is
+ accidentally or by design given several names, it is
possible that the name registry becomes inconsistent due
to the way the resolve function is called when name
clashes are discovered (see <c>register_name/3</c> in
diff --git a/lib/kernel/doc/src/os.xml b/lib/kernel/doc/src/os.xml
index 56fc1834ec..e94119845a 100644
--- a/lib/kernel/doc/src/os.xml
+++ b/lib/kernel/doc/src/os.xml
@@ -126,9 +126,10 @@ DirOut = os:cmd("dir"), % on Win32 platform</code>
</desc>
</func>
<func>
- <name>timestamp() -> {MegaSecs, Secs, MicroSecs}</name>
+ <name>timestamp() -> Timestamp</name>
<fsummary>Returna a timestamp from the OS in the erlang:now/0 format</fsummary>
<type>
+ <v>Timestamp = {MegaSecs, Secs, MicroSecs} = <seealso marker="erts:erlang#type-timestamp">erlang:timestamp()</seealso></v>
<v>MegaSecs = Secs = MicroSecs = integer() >= 0</v>
</type>
<desc>
diff --git a/lib/kernel/examples/uds_dist/c_src/uds_drv.c b/lib/kernel/examples/uds_dist/c_src/uds_drv.c
index fb10a375f4..9327ab19dc 100644
--- a/lib/kernel/examples/uds_dist/c_src/uds_drv.c
+++ b/lib/kernel/examples/uds_dist/c_src/uds_drv.c
@@ -111,7 +111,7 @@ do { \
typedef enum {
portTypeUnknown, /* An uninitialized port */
portTypeListener, /* A listening port/socket */
- portTypeAcceptor, /* An intermidiate stage when accepting
+ portTypeAcceptor, /* An intermediate stage when accepting
on a listen port */
portTypeConnector, /* An intermediate stage when connecting */
portTypeCommand, /* A connected open port in command mode */
@@ -401,7 +401,7 @@ static void uds_finish(void)
/*
** Protocol to control:
** 'C': Set port in command mode.
-** 'I': Set port in intermidiate mode
+** 'I': Set port in intermediate mode
** 'D': Set port in data mode
** 'N': Get identification number for listen port
** 'S': Get statistics
@@ -1000,7 +1000,7 @@ static int ensure_dir(char *path)
/*
** Try to open a lock file and lock the first byte write-only (advisory)
-** return the file descriptor if succesful, otherwise -1 (<0).
+** return the file descriptor if successful, otherwise -1 (<0).
*/
static int try_lock(char *sockname, Byte *p_creation)
{
diff --git a/lib/ssl/src/ssl_broker_sup.erl b/lib/kernel/include/dist.hrl
index 6d56a5fcf6..aea1ab81ba 100644
--- a/lib/ssl/src/ssl_broker_sup.erl
+++ b/lib/kernel/include/dist.hrl
@@ -18,29 +18,21 @@
%%
%%
+%% Distribution capabilities flags (corresponds with dist.h).
+%%
-%%% Purpose : Supervisor for brokers
-
--module(ssl_broker_sup).
-
--behaviour(supervisor).
-
--export([start_link/0]).
-
-%% supervisor callbacks
--export([init/1]).
-
-start_link() ->
- supervisor:start_link({local, ssl_broker_sup}, ssl_broker_sup,
- []).
-
-init([]) ->
- {ok, {{simple_one_for_one, 10, 3600},
- [{ssl_broker,
- {ssl_broker, start_link, []},
- temporary,
- 100,
- worker,
- [ssl_broker]}
- ]}}.
-
+-define(DFLAG_PUBLISHED,1).
+-define(DFLAG_ATOM_CACHE,2).
+-define(DFLAG_EXTENDED_REFERENCES,4).
+-define(DFLAG_DIST_MONITOR,8).
+-define(DFLAG_FUN_TAGS,16#10).
+-define(DFLAG_DIST_MONITOR_NAME,16#20).
+-define(DFLAG_HIDDEN_ATOM_CACHE,16#40).
+-define(DFLAG_NEW_FUN_TAGS,16#80).
+-define(DFLAG_EXTENDED_PIDS_PORTS,16#100).
+-define(DFLAG_EXPORT_PTR_TAG,16#200).
+-define(DFLAG_BIT_BINARIES,16#400).
+-define(DFLAG_NEW_FLOATS,16#800).
+-define(DFLAG_UNICODE_IO,16#1000).
+-define(DFLAG_DIST_HDR_ATOM_CACHE,16#2000).
+-define(DFLAG_SMALL_ATOM_TAGS, 16#4000).
diff --git a/lib/kernel/include/dist_util.hrl b/lib/kernel/include/dist_util.hrl
new file mode 100644
index 0000000000..f2b0598532
--- /dev/null
+++ b/lib/kernel/include/dist_util.hrl
@@ -0,0 +1,87 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%% uncomment this if tracing of handshake etc is wanted
+%%-define(dist_trace, true).
+%%-define(dist_debug, true).
+
+
+-ifdef(dist_debug).
+-define(debug(Term), erlang:display(Term)).
+-else.
+-define(debug(Term), ok).
+-endif.
+
+-ifdef(dist_trace).
+-define(trace(Fmt,Args), io:format("~p ~p:~s",[erlang:now(),node(),lists:flatten(io_lib:format(Fmt, Args))])).
+% Use the one below for config-file (early boot) connection tracing
+%-define(trace(Fmt,Args), erlang:display([erlang:now(),node(),lists:flatten(io_lib:format(Fmt, Args))])).
+-define(trace_factor,8).
+-else.
+-define(trace(Fmt,Args), ok).
+-define(trace_factor,1).
+-endif.
+
+-define(shutdown(Data), dist_util:shutdown(?MODULE, ?LINE, Data)).
+-define(shutdown2(Data, Reason), dist_util:shutdown(?MODULE, ?LINE, Data, Reason)).
+
+%% Handshake state structure
+-record(hs_data, {
+ kernel_pid, %% Pid of net_kernel
+ other_node, %% Name of peer
+ this_node, %% my nodename
+ socket, %% The connection "socket"
+ timer, %% The setup timer
+ %% (stream_dist_handshake:start_timer)
+ this_flags, %% Flags my node should use
+ allowed, %% Allowed nodes list
+ other_version, %% The other nodes distribution version
+ other_flags, %% The other nodes flags.
+ other_started, %% True if the other node initiated.
+ f_send, %% Fun that behaves like gen_tcp:send
+ f_recv, %% Fun that behaves like gen_tcp:recv
+ f_setopts_pre_nodeup, %% Sets "socket" options before
+ %% nodeup is delivered to net_kernel
+ f_setopts_post_nodeup, %% Sets "socket" options after
+ %% nodeup is delivered
+ f_getll, %% Get low level port or pid.
+ f_address, %% The address of the "socket",
+ %% generated from Socket,Node
+ %% These two are used in the tick loop,
+ %% so they are not fun's to avoid holding old code.
+ mf_tick, %% Takes the socket as parameters and
+ %% sends a tick, this is no fun, it
+ %% is a tuple {M,F}.
+ %% Is should place {tcp_closed, Socket}
+ %% in the message queue on failure.
+ mf_getstat, %% Returns
+ %% {ok, RecvCnt, SendCnt, SendPend} for
+ %% a given socket. This is a {M,F},
+ %% returning {error, Reason on failure}
+ request_type = normal
+}).
+
+
+%% The following should be filled in upon enter of...
+%% - handshake_we_started:
+%% kernel_pid, other_node, this_node, socket, timer,
+%% this_flags, other_version, All fun's/mf's.
+%% - handshake_other_started:
+%% kernel_pid, this_node, socket, timer,
+%% this_flags, allowed, All fun's/mf's.
+
diff --git a/lib/kernel/include/net_address.hrl b/lib/kernel/include/net_address.hrl
new file mode 100644
index 0000000000..5342076507
--- /dev/null
+++ b/lib/kernel/include/net_address.hrl
@@ -0,0 +1,28 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%% Generic address format
+
+-record(net_address,
+ {
+ address, %% opaque address
+ host, %% host name
+ protocol, %% protocol
+ family %% address family
+ }).
diff --git a/lib/kernel/src/Makefile b/lib/kernel/src/Makefile
index 9db6014a7d..02be6b5036 100644
--- a/lib/kernel/src/Makefile
+++ b/lib/kernel/src/Makefile
@@ -118,11 +118,14 @@ MODULES = \
user_sup \
wrap_log_reader
-HRL_FILES= ../include/file.hrl ../include/inet.hrl ../include/inet_sctp.hrl
+HRL_FILES= ../include/file.hrl ../include/inet.hrl ../include/inet_sctp.hrl \
+ ../include/dist.hrl ../include/dist_util.hrl \
+ ../include/net_address.hrl
+
INTERNAL_HRL_FILES= application_master.hrl disk_log.hrl \
- net_address.hrl inet_dns.hrl inet_res.hrl \
+ inet_dns.hrl inet_res.hrl \
inet_boot.hrl inet_config.hrl inet_int.hrl \
- dist.hrl dist_util.hrl inet_dns_record_adts.hrl
+ inet_dns_record_adts.hrl
ERL_FILES= $(MODULES:%=%.erl)
@@ -215,7 +218,7 @@ $(EBIN)/code_server.beam: ../include/file.hrl
$(EBIN)/disk_log.beam: disk_log.hrl
$(EBIN)/disk_log_1.beam: disk_log.hrl ../include/file.hrl
$(EBIN)/disk_log_server.beam: disk_log.hrl
-$(EBIN)/dist_util.beam: dist_util.hrl dist.hrl
+$(EBIN)/dist_util.beam: ../include/dist_util.hrl ../include/dist.hrl
$(EBIN)/erl_boot_server.beam: inet_boot.hrl
$(EBIN)/erl_epmd.beam: inet_int.hrl erl_epmd.hrl
$(EBIN)/file.beam: ../include/file.hrl
@@ -226,7 +229,7 @@ $(EBIN)/global.beam: ../../stdlib/include/ms_transform.hrl
$(EBIN)/hipe_unified_loader.beam: ../../hipe/main/hipe.hrl hipe_ext_format.hrl
$(EBIN)/inet.beam: ../include/inet.hrl inet_int.hrl ../include/inet_sctp.hrl
$(EBIN)/inet6_tcp.beam: inet_int.hrl
-$(EBIN)/inet6_tcp_dist.beam: net_address.hrl dist.hrl dist_util.hrl
+$(EBIN)/inet6_tcp_dist.beam: ../include/net_address.hrl ../include/dist.hrl ../include/dist_util.hrl
$(EBIN)/inet6_udp.beam: inet_int.hrl
$(EBIN)/inet6_sctp.beam: inet_int.hrl
$(EBIN)/inet_config.beam: inet_config.hrl ../include/inet.hrl
@@ -237,10 +240,10 @@ $(EBIN)/inet_hosts.beam: ../include/inet.hrl
$(EBIN)/inet_parse.beam: ../include/file.hrl
$(EBIN)/inet_res.beam: ../include/inet.hrl inet_res.hrl inet_dns.hrl inet_int.hrl
$(EBIN)/inet_tcp.beam: inet_int.hrl
-$(EBIN)/inet_udp_dist.beam: net_address.hrl dist.hrl dist_util.hrl
+$(EBIN)/inet_udp_dist.beam: ../include/net_address.hrl ../include/dist.hrl ../include/dist_util.hrl
$(EBIN)/inet_udp.beam: inet_int.hrl
$(EBIN)/inet_sctp.beam: inet_int.hrl ../include/inet_sctp.hrl
-$(EBIN)/net_kernel.beam: net_address.hrl
+$(EBIN)/net_kernel.beam: ../include/net_address.hrl
$(EBIN)/os.beam: ../include/file.hrl
$(EBIN)/ram_file.beam: ../include/file.hrl
$(EBIN)/wrap_log_reader.beam: disk_log.hrl ../include/file.hrl
diff --git a/lib/kernel/src/application.erl b/lib/kernel/src/application.erl
index fa3a4c3d36..caac4d926c 100644
--- a/lib/kernel/src/application.erl
+++ b/lib/kernel/src/application.erl
@@ -28,8 +28,6 @@
-export([get_application/0, get_application/1, info/0]).
-export([start_type/0]).
--export([behaviour_info/1]).
-
%%%-----------------------------------------------------------------
-type start_type() :: 'normal'
@@ -59,12 +57,12 @@
%%------------------------------------------------------------------
--spec behaviour_info(atom()) -> 'undefined' | [{atom(), byte()}].
+-callback start(StartType :: normal | {takeover, node()} | {failover, node()},
+ StartArgs :: term()) ->
+ {ok, pid()} | {ok, pid(), State :: term()} | {error, Reason :: term}.
-behaviour_info(callbacks) ->
- [{start,2},{stop,1}];
-behaviour_info(_Other) ->
- undefined.
+-callback stop(State :: term()) ->
+ term().
%%%-----------------------------------------------------------------
%%% This module is API towards application_controller and
diff --git a/lib/kernel/src/application_controller.erl b/lib/kernel/src/application_controller.erl
index 42f527f400..ebfe84463a 100644
--- a/lib/kernel/src/application_controller.erl
+++ b/lib/kernel/src/application_controller.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1180,10 +1180,27 @@ terminate(Reason, S) ->
_ ->
ok
end,
+ ShutdownTimeout =
+ case application:get_env(kernel, shutdown_timeout) of
+ undefined -> infinity;
+ {ok,T} -> T
+ end,
foreach(fun({_AppName, Id}) when is_pid(Id) ->
+ Ref = erlang:monitor(process, Id),
+ unlink(Id),
exit(Id, shutdown),
receive
+ %% Proc died before link
{'EXIT', Id, _} -> ok
+ after 0 ->
+ receive
+ {'DOWN', Ref, process, Id, _} -> ok
+ after ShutdownTimeout ->
+ exit(Id, kill),
+ receive
+ {'DOWN', Ref, process, Id, _} -> ok
+ end
+ end
end;
(_) -> ok
end,
diff --git a/lib/kernel/src/auth.erl b/lib/kernel/src/auth.erl
index 25c88a4e1d..c329a5652a 100644
--- a/lib/kernel/src/auth.erl
+++ b/lib/kernel/src/auth.erl
@@ -58,7 +58,7 @@ start_link() ->
%%--Deprecated interface------------------------------------------------
-spec is_auth(Node) -> 'yes' | 'no' when
- Node :: Node :: node().
+ Node :: node().
is_auth(Node) ->
case net_adm:ping(Node) of
@@ -212,7 +212,7 @@ handle_info({From,badcookie,net_kernel,{From,spawn_link,_M,_F,_A,_Gleader}}, O)
{noreply, O};
handle_info({_From,badcookie,ddd_server,_Mess}, O) ->
%% Ignore bad messages to the ddd server, they will be resent
- %% If the authentication is succesful
+ %% If the authentication is successful
{noreply, O};
handle_info({From,badcookie,rex,_Msg}, O) ->
auth:print(getnode(From),
diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl
index b0f99305f2..882e9625fe 100644
--- a/lib/kernel/src/code.erl
+++ b/lib/kernel/src/code.erl
@@ -82,7 +82,8 @@
%% add_pathsa([Dir]) -> ok
%% add_pathsz([Dir]) -> ok
%% del_path(Dir) -> boolean() | {error, bad_name}
-%% replace_path(Name, Dir) -> true | replace_path_error()
+%% replace_path(Name, Dir) -> true | {error, bad_directory | bad_name
+%% | {badarg,_}}
%% load_file(Module) -> {module, Module} | {error, What :: atom()}
%% load_abs(File) -> {module, Module} | {error, What :: atom()}
%% load_abs(File, Module) -> {module, Module} | {error, What :: atom()}
@@ -113,11 +114,16 @@
%% Some types for basic exported functions of this module
%%----------------------------------------------------------------------------
--type load_error_rsn() :: 'badfile' | 'native_code' | 'nofile' | 'not_purged'
- | 'sticky_directory'. % for some functions only
--type load_ret() :: {'error', load_error_rsn()} | {'module', atom()}.
+-type load_error_rsn() :: 'badfile'
+ | 'native_code'
+ | 'nofile'
+ | 'not_purged'
+ | 'on_load'
+ | 'sticky_directory'.
+-type load_ret() :: {'error', What :: load_error_rsn()}
+ | {'module', Module :: module()}.
-type loaded_ret_atoms() :: 'cover_compiled' | 'preloaded'.
--type loaded_filename() :: file:filename() | loaded_ret_atoms().
+-type loaded_filename() :: (Filename :: file:filename()) | loaded_ret_atoms().
%%----------------------------------------------------------------------------
%% User interface
@@ -127,55 +133,74 @@
objfile_extension() ->
init:objfile_extension().
--spec load_file(Module :: atom()) -> load_ret().
+-spec load_file(Module) -> load_ret() when
+ Module :: module().
load_file(Mod) when is_atom(Mod) ->
call({load_file,Mod}).
--spec ensure_loaded(Module :: atom()) -> load_ret().
+-spec ensure_loaded(Module) -> {module, Module} | {error, What} when
+ Module :: module(),
+ What :: embedded | badfile | native_code | nofile | on_load.
ensure_loaded(Mod) when is_atom(Mod) ->
call({ensure_loaded,Mod}).
%% XXX File as an atom is allowed only for backwards compatibility.
--spec load_abs(Filename :: file:filename()) -> load_ret().
+-spec load_abs(Filename) -> load_ret() when
+ Filename :: file:filename().
load_abs(File) when is_list(File); is_atom(File) -> call({load_abs,File,[]}).
%% XXX Filename is also an atom(), e.g. 'cover_compiled'
--spec load_abs(Filename :: loaded_filename(), Module :: atom()) -> load_ret().
+-spec load_abs(Filename :: loaded_filename(), Module :: module()) -> load_ret().
load_abs(File, M) when (is_list(File) orelse is_atom(File)), is_atom(M) ->
call({load_abs,File,M}).
%% XXX Filename is also an atom(), e.g. 'cover_compiled'
--spec load_binary(Module :: atom(), Filename :: loaded_filename(), Binary :: binary()) -> load_ret().
+-spec load_binary(Module, Filename, Binary) ->
+ {module, Module} | {error, What} when
+ Module :: module(),
+ Filename :: loaded_filename(),
+ Binary :: binary(),
+ What :: badarg | load_error_rsn().
load_binary(Mod, File, Bin)
when is_atom(Mod), (is_list(File) orelse is_atom(File)), is_binary(Bin) ->
call({load_binary,Mod,File,Bin}).
--spec load_native_partial(Module :: atom(), Binary :: binary()) -> load_ret().
+-spec load_native_partial(Module :: module(), Binary :: binary()) -> load_ret().
load_native_partial(Mod, Bin) when is_atom(Mod), is_binary(Bin) ->
call({load_native_partial,Mod,Bin}).
--spec load_native_sticky(Module :: atom(), Binary :: binary(), WholeModule :: 'false' | binary()) -> load_ret().
+-spec load_native_sticky(Module :: module(), Binary :: binary(), WholeModule :: 'false' | binary()) -> load_ret().
load_native_sticky(Mod, Bin, WholeModule)
when is_atom(Mod), is_binary(Bin),
(is_binary(WholeModule) orelse WholeModule =:= false) ->
call({load_native_sticky,Mod,Bin,WholeModule}).
--spec delete(Module :: atom()) -> boolean().
+-spec delete(Module) -> boolean() when
+ Module :: module().
delete(Mod) when is_atom(Mod) -> call({delete,Mod}).
--spec purge(Module :: atom()) -> boolean().
+-spec purge(Module) -> boolean() when
+ Module :: module().
purge(Mod) when is_atom(Mod) -> call({purge,Mod}).
--spec soft_purge(Module :: atom()) -> boolean().
+-spec soft_purge(Module) -> boolean() when
+ Module :: module().
soft_purge(Mod) when is_atom(Mod) -> call({soft_purge,Mod}).
--spec is_loaded(Module :: atom()) -> {'file', loaded_filename()} | 'false'.
+-spec is_loaded(Module) -> {'file', Loaded} | false when
+ Module :: module(),
+ Loaded :: loaded_filename().
is_loaded(Mod) when is_atom(Mod) -> call({is_loaded,Mod}).
--spec get_object_code(Module :: atom()) -> {atom(), binary(), file:filename()} | 'error'.
+-spec get_object_code(Module) -> {Module, Binary, Filename} | error when
+ Module :: module(),
+ Binary :: binary(),
+ Filename :: file:filename().
get_object_code(Mod) when is_atom(Mod) -> call({get_object_code, Mod}).
--spec all_loaded() -> [{atom(), loaded_filename()}].
+-spec all_loaded() -> [{Module, Loaded}] when
+ Module :: module(),
+ Loaded :: loaded_filename().
all_loaded() -> call(all_loaded).
-spec stop() -> no_return().
@@ -188,65 +213,86 @@ root_dir() -> call({dir,root_dir}).
lib_dir() -> call({dir,lib_dir}).
%% XXX is_list() is for backwards compatibility -- take out in future version
--spec lib_dir(App :: atom()) -> file:filename() | {'error', 'bad_name'}.
+-spec lib_dir(Name) -> file:filename() | {'error', 'bad_name'} when
+ Name :: atom().
lib_dir(App) when is_atom(App) ; is_list(App) -> call({dir,{lib_dir,App}}).
--spec lib_dir(App :: atom(), SubDir :: atom()) -> file:filename() | {'error', 'bad_name'}.
+-spec lib_dir(Name, SubDir) -> file:filename() | {'error', 'bad_name'} when
+ Name :: atom(),
+ SubDir :: atom().
lib_dir(App, SubDir) when is_atom(App), is_atom(SubDir) -> call({dir,{lib_dir,App,SubDir}}).
-spec compiler_dir() -> file:filename().
compiler_dir() -> call({dir,compiler_dir}).
%% XXX is_list() is for backwards compatibility -- take out in future version
--spec priv_dir(App :: atom()) -> file:filename() | {'error', 'bad_name'}.
+-spec priv_dir(Name) -> file:filename() | {'error', 'bad_name'} when
+ Name :: atom().
priv_dir(App) when is_atom(App) ; is_list(App) -> call({dir,{priv_dir,App}}).
--spec stick_dir(Directory :: file:filename()) -> 'ok' | 'error'.
+-spec stick_dir(Dir) -> 'ok' | 'error' when
+ Dir :: file:filename().
stick_dir(Dir) when is_list(Dir) -> call({stick_dir,Dir}).
--spec unstick_dir(Directory :: file:filename()) -> 'ok' | 'error'.
+-spec unstick_dir(Dir) -> 'ok' | 'error' when
+ Dir :: file:filename().
unstick_dir(Dir) when is_list(Dir) -> call({unstick_dir,Dir}).
--spec stick_mod(Module :: atom()) -> 'true'.
+-spec stick_mod(Module :: module()) -> 'true'.
stick_mod(Mod) when is_atom(Mod) -> call({stick_mod,Mod}).
--spec unstick_mod(Module :: atom()) -> 'true'.
+-spec unstick_mod(Module :: module()) -> 'true'.
unstick_mod(Mod) when is_atom(Mod) -> call({unstick_mod,Mod}).
--spec is_sticky(Module :: atom()) -> boolean().
+-spec is_sticky(Module) -> boolean() when
+ Module :: module().
is_sticky(Mod) when is_atom(Mod) -> call({is_sticky,Mod}).
--spec set_path(Directories :: [file:filename()]) ->
- 'true' | {'error', 'bad_directory' | 'bad_path'}.
+-spec set_path(Path) -> 'true' | {'error', What} when
+ Path :: [Dir :: file:filename()],
+ What :: 'bad_directory' | 'bad_path'.
set_path(PathList) when is_list(PathList) -> call({set_path,PathList}).
--spec get_path() -> [file:filename()].
+-spec get_path() -> Path when
+ Path :: [Dir :: file:filename()].
get_path() -> call(get_path).
-type add_path_ret() :: 'true' | {'error', 'bad_directory'}.
--spec add_path(Directory :: file:filename()) -> add_path_ret().
+-spec add_path(Dir) -> add_path_ret() when
+ Dir :: file:filename().
add_path(Dir) when is_list(Dir) -> call({add_path,last,Dir}).
--spec add_pathz(Directory :: file:filename()) -> add_path_ret().
+-spec add_pathz(Dir) -> add_path_ret() when
+ Dir :: file:filename().
add_pathz(Dir) when is_list(Dir) -> call({add_path,last,Dir}).
--spec add_patha(Directory :: file:filename()) -> add_path_ret().
+-spec add_patha(Dir) -> add_path_ret() when
+ Dir :: file:filename().
add_patha(Dir) when is_list(Dir) -> call({add_path,first,Dir}).
--spec add_paths(Directories :: [file:filename()]) -> 'ok'.
+-spec add_paths(Dirs) -> 'ok' when
+ Dirs :: [Dir :: file:filename()].
add_paths(Dirs) when is_list(Dirs) -> call({add_paths,last,Dirs}).
--spec add_pathsz(Directories :: [file:filename()]) -> 'ok'.
+-spec add_pathsz(Dirs) -> 'ok' when
+ Dirs :: [Dir :: file:filename()].
add_pathsz(Dirs) when is_list(Dirs) -> call({add_paths,last,Dirs}).
--spec add_pathsa(Directories :: [file:filename()]) -> 'ok'.
+-spec add_pathsa(Dirs) -> 'ok' when
+ Dirs :: [Dir :: file:filename()].
add_pathsa(Dirs) when is_list(Dirs) -> call({add_paths,first,Dirs}).
--spec del_path(Name :: file:filename() | atom()) -> boolean() | {'error', 'bad_name'}.
+-spec del_path(NameOrDir) -> boolean() | {'error', What} when
+ NameOrDir :: Name | Dir,
+ Name :: atom(),
+ Dir :: file:filename(),
+ What :: 'bad_name'.
del_path(Name) when is_list(Name) ; is_atom(Name) -> call({del_path,Name}).
--type replace_path_error() :: {'error', 'bad_directory' | 'bad_name' | {'badarg',_}}.
--spec replace_path(Name:: atom(), Dir :: file:filename()) -> 'true' | replace_path_error().
+-spec replace_path(Name, Dir) -> 'true' | {'error', What} when
+ Name:: atom(),
+ Dir :: file:filename(),
+ What :: 'bad_directory' | 'bad_name' | {'badarg',_}.
replace_path(Name, Dir) when (is_atom(Name) orelse is_list(Name)),
(is_atom(Dir) orelse is_list(Dir)) ->
call({replace_path,Name,Dir}).
@@ -351,10 +397,9 @@ get_mode(Flags) ->
%% In that case return the name of the file which contains
%% the loaded object code
--type which_ret_atoms() :: loaded_ret_atoms() | 'non_existing'.
-
--spec which(Module :: atom()) -> file:filename() | which_ret_atoms().
-
+-spec which(Module) -> Which when
+ Module :: module(),
+ Which :: file:filename() | loaded_ret_atoms() | non_existing.
which(Module) when is_atom(Module) ->
case is_loaded(Module) of
false ->
@@ -394,9 +439,9 @@ which(File, Base, [Directory|Tail]) ->
%% Search the code path for a specific file. Try to locate
%% it in the code path cache if possible.
--spec where_is_file(Filename :: file:filename()) ->
- 'non_existing' | file:filename().
-
+-spec where_is_file(Filename) -> non_existing | Absname when
+ Filename :: file:filename(),
+ Absname :: file:filename().
where_is_file(File) when is_list(File) ->
case call({is_cached,File}) of
no ->
diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl
index 4a1fc7df34..e3d22e7999 100644
--- a/lib/kernel/src/code_server.erl
+++ b/lib/kernel/src/code_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1379,8 +1379,12 @@ absname_vr([[X, $:]|Name], _, _AbsBase) ->
%% Kill all processes running code from *old* Module, and then purge the
%% module. Return true if any processes killed, else false.
-do_purge(Mod) ->
- do_purge(processes(), to_atom(Mod), false).
+do_purge(Mod0) ->
+ Mod = to_atom(Mod0),
+ case erlang:check_old_code(Mod) of
+ false -> false;
+ true -> do_purge(processes(), Mod, false)
+ end.
do_purge([P|Ps], Mod, Purged) ->
case erlang:check_process_code(P, Mod) of
@@ -1399,16 +1403,19 @@ do_purge([], Mod, Purged) ->
Purged.
%% do_soft_purge(Module)
-%% Purge old code only if no procs remain that run old code
+%% Purge old code only if no procs remain that run old code.
%% Return true in that case, false if procs remain (in this
%% case old code is not purged)
do_soft_purge(Mod) ->
- catch do_soft_purge(processes(), Mod).
+ case erlang:check_old_code(Mod) of
+ false -> true;
+ true -> do_soft_purge(processes(), Mod)
+ end.
do_soft_purge([P|Ps], Mod) ->
case erlang:check_process_code(P, Mod) of
- true -> throw(false);
+ true -> false;
false -> do_soft_purge(Ps, Mod)
end;
do_soft_purge([], Mod) ->
diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl
index 9b8d2db437..d6bc23be6d 100644
--- a/lib/kernel/src/disk_log.erl
+++ b/lib/kernel/src/disk_log.erl
@@ -1240,20 +1240,29 @@ is_owner(Pid, L) ->
%% ok | throw(Error)
rename_file(File, NewFile, halt) ->
- file:rename(File, NewFile);
+ case file:rename(File, NewFile) of
+ ok ->
+ ok;
+ Else ->
+ file_error(NewFile, Else)
+ end;
rename_file(File, NewFile, wrap) ->
rename_file(wrap_file_extensions(File), File, NewFile, ok).
-rename_file([Ext|Exts], File, NewFile, Res) ->
- NRes = case file:rename(add_ext(File, Ext), add_ext(NewFile, Ext)) of
+rename_file([Ext|Exts], File, NewFile0, Res) ->
+ NewFile = add_ext(NewFile0, Ext),
+ NRes = case file:rename(add_ext(File, Ext), NewFile) of
ok ->
Res;
Else ->
- Else
+ file_error(NewFile, Else)
end,
- rename_file(Exts, File, NewFile, NRes);
+ rename_file(Exts, File, NewFile0, NRes);
rename_file([], _File, _NewFiles, Res) -> Res.
+file_error(FileName, {error, Error}) ->
+ {error, {file_error, FileName, Error}}.
+
%% "Old" error messages have been kept, arg_mismatch has been added.
%%-spec compare_arg(dlog_options(), #arg{},
compare_arg([], _A, none, _OrigHead) ->
@@ -1947,7 +1956,8 @@ monitor_request(Pid, Req) ->
receive
{'DOWN', Ref, process, Pid, _Info} ->
{error, no_such_log};
- {disk_log, Pid, Reply} ->
+ {disk_log, Pid, Reply} when not is_tuple(Reply) orelse
+ element(2, Reply) =/= disk_log_stopped ->
erlang:demonitor(Ref),
receive
{'DOWN', Ref, process, Pid, _Reason} ->
diff --git a/lib/kernel/src/error_handler.erl b/lib/kernel/src/error_handler.erl
index e1f99bf417..a67b11a888 100644
--- a/lib/kernel/src/error_handler.erl
+++ b/lib/kernel/src/error_handler.erl
@@ -88,12 +88,12 @@ int() -> int.
-spec crash(atom(), [term()]) -> no_return().
crash(Fun, Args) ->
- crash({Fun,Args}).
+ crash({Fun,Args,[]}).
-spec crash(atom(), atom(), arity()) -> no_return().
crash(M, F, A) ->
- crash({M,F,A}).
+ crash({M,F,A,[]}).
-spec crash(tuple()) -> no_return().
@@ -101,7 +101,8 @@ crash(Tuple) ->
try erlang:error(undef)
catch
error:undef ->
- erlang:raise(error, undef, [Tuple|tl(erlang:get_stacktrace())])
+ Stk = [Tuple|tl(erlang:get_stacktrace())],
+ erlang:raise(error, undef, Stk)
end.
%% If the code_server has not been started yet dynamic code loading
@@ -127,7 +128,7 @@ ensure_loaded(Module) ->
-spec stub_function(atom(), atom(), [_]) -> no_return().
stub_function(Mod, Func, Args) ->
- exit({undef,[{Mod,Func,Args}]}).
+ exit({undef,[{Mod,Func,Args,[]}]}).
check_inheritance(Module, Args) ->
Attrs = erlang:get_module_info(Module, attributes),
diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl
index f1a8aa9f77..706c60caaf 100644
--- a/lib/kernel/src/file.erl
+++ b/lib/kernel/src/file.erl
@@ -100,15 +100,7 @@
| 'enotblk' | 'enotdir' | 'enotsup' | 'enxio' | 'eperm'
| 'epipe' | 'erofs' | 'espipe' | 'esrch' | 'estale'
| 'exdev'.
--type bindings() :: erl_eval:binding_struct().
-
--type date() :: {Year :: pos_integer(),
- Month :: pos_integer(),
- Day ::pos_integer()}.
--type time() :: {Hour :: non_neg_integer(),
- Minute :: non_neg_integer(),
- Second :: non_neg_integer()}.
--type date_time() :: {date(), time()}.
+-type date_time() :: calendar:datetime().
-type posix_file_advise() :: 'normal' | 'sequential' | 'random'
| 'no_reuse' | 'will_need' | 'dont_need'.
@@ -920,7 +912,7 @@ eval(File) ->
-spec eval(Filename, Bindings) -> ok | {error, Reason} when
Filename :: name(),
- Bindings :: bindings(),
+ Bindings :: erl_eval:binding_struct(),
Reason :: posix() | badarg | terminated | system_limit
| {Line :: integer(), Mod :: module(), Term :: term()}.
@@ -948,7 +940,7 @@ path_eval(Path, File) ->
{ok, FullName} | {error, Reason} when
Path :: [Dir :: name()],
Filename :: name(),
- Bindings :: bindings(),
+ Bindings :: erl_eval:binding_struct(),
FullName :: filename(),
Reason :: posix() | badarg | terminated | system_limit
| {Line :: integer(), Mod :: module(), Term :: term()}.
@@ -979,7 +971,7 @@ script(File) ->
-spec script(Filename, Bindings) -> {ok, Value} | {error, Reason} when
Filename :: name(),
- Bindings :: bindings(),
+ Bindings :: erl_eval:binding_struct(),
Value :: term(),
Reason :: posix() | badarg | terminated | system_limit
| {Line :: integer(), Mod :: module(), Term :: term()}.
@@ -1010,7 +1002,7 @@ path_script(Path, File) ->
{ok, Value, FullName} | {error, Reason} when
Path :: [Dir :: name()],
Filename :: name(),
- Bindings :: bindings(),
+ Bindings :: erl_eval:binding_struct(),
Value :: term(),
FullName :: filename(),
Reason :: posix() | badarg | terminated | system_limit
@@ -1171,7 +1163,7 @@ path_open_first([Path|Rest], Name, Mode, LastError) ->
{error, _} = Error ->
Error;
FilePath ->
- FileName = filename:join(FilePath, Name),
+ FileName = fname_join(FilePath, Name),
case open(FileName, Mode) of
{ok, Fd} ->
{ok, Fd, FileName};
@@ -1184,6 +1176,11 @@ path_open_first([Path|Rest], Name, Mode, LastError) ->
path_open_first([], _Name, _Mode, LastError) ->
{error, LastError}.
+fname_join(".", Name) ->
+ Name;
+fname_join(Dir, Name) ->
+ filename:join(Dir, Name).
+
%%%-----------------------------------------------------------------
%%% Utility functions.
diff --git a/lib/kernel/src/gen_sctp.erl b/lib/kernel/src/gen_sctp.erl
index 004f03f231..77ca26b845 100644
--- a/lib/kernel/src/gen_sctp.erl
+++ b/lib/kernel/src/gen_sctp.erl
@@ -27,61 +27,94 @@
-include("inet_sctp.hrl").
-export([open/0,open/1,open/2,close/1]).
--export([listen/2,connect/4,connect/5,connect_init/4,connect_init/5]).
+-export([listen/2,peeloff/2]).
+-export([connect/4,connect/5,connect_init/4,connect_init/5]).
-export([eof/2,abort/2]).
-export([send/3,send/4,recv/1,recv/2]).
-export([error_string/1]).
-export([controlling_process/2]).
--opaque assoc_id() :: term().
--type hostname() :: inet:hostname().
--type ip_address() :: inet:ip_address().
--type port_number() :: 0..65535.
--type posix() :: inet:posix().
--type sctp_option() ::
- {mode, list | binary} | list | binary
- | {active, true | false | once}
- | {buffer, non_neg_integer()}
- | {tos, integer()}
- | {priority, integer()}
- | {dontroute, boolean()}
- | {reuseaddr, boolean()}
- | {linger, {boolean(), non_neg_integer()}}
- | {sndbuf, non_neg_integer()}
- | {recbuf, non_neg_integer()}
- | {sctp_rtoinfo, #sctp_rtoinfo{}}
- | {sctp_associnfo, #sctp_assocparams{}}
- | {sctp_initmsg, #sctp_initmsg{}}
- | {sctp_autoclose, timeout()}
- | {sctp_nodelay, boolean()}
- | {sctp_disable_fragments, boolean()}
- | {sctp_i_want_mapped_v4_addr, boolean()}
- | {sctp_maxseg, non_neg_integer()}
- | {sctp_primary_addr, #sctp_prim{}}
- | {sctp_set_peer_primary_addr, #sctp_setpeerprim{}}
- | {sctp_adaptation_layer, #sctp_setadaptation{}}
- | {sctp_peer_addr_params, #sctp_paddrparams{}}
- | {sctp_default_send_param, #sctp_sndrcvinfo{}}
- | {sctp_events, #sctp_event_subscribe{}}
- | {sctp_delayed_ack_time, #sctp_assoc_value{}}
- | {sctp_status, #sctp_status{}}
- | {sctp_get_peer_addr_info, #sctp_paddrinfo{}}.
--opaque sctp_socket() :: port().
-
--spec open() -> {ok, Socket} | {error, posix()} when
+-type assoc_id() :: term().
+-type option() ::
+ {active, true | false | once} |
+ {buffer, non_neg_integer()} |
+ {dontroute, boolean()} |
+ {linger, {boolean(), non_neg_integer()}} |
+ {mode, list | binary} | list | binary |
+ {priority, non_neg_integer()} |
+ {recbuf, non_neg_integer()} |
+ {reuseaddr, boolean()} |
+ {sctp_adaptation_layer, #sctp_setadaptation{}} |
+ {sctp_associnfo, #sctp_assocparams{}} |
+ {sctp_autoclose, non_neg_integer()} |
+ {sctp_default_send_param, #sctp_sndrcvinfo{}} |
+ {sctp_delayed_ack_time, #sctp_assoc_value{}} |
+ {sctp_disable_fragments, boolean()} |
+ {sctp_events, #sctp_event_subscribe{}} |
+ {sctp_get_peer_addr_info, #sctp_paddrinfo{}} |
+ {sctp_i_want_mapped_v4_addr, boolean()} |
+ {sctp_initmsg, #sctp_initmsg{}} |
+ {sctp_maxseg, non_neg_integer()} |
+ {sctp_nodelay, boolean()} |
+ {sctp_peer_addr_params, #sctp_paddrparams{}} |
+ {sctp_primary_addr, #sctp_prim{}} |
+ {sctp_rtoinfo, #sctp_rtoinfo{}} |
+ {sctp_set_peer_primary_addr, #sctp_setpeerprim{}} |
+ {sctp_status, #sctp_status{}} |
+ {sndbuf, non_neg_integer()} |
+ {tos, non_neg_integer()}.
+-type option_name() ::
+ active |
+ buffer |
+ dontroute |
+ linger |
+ mode |
+ priority |
+ recbuf |
+ reuseaddr |
+ sctp_adaptation_layer |
+ sctp_associnfo |
+ sctp_autoclose |
+ sctp_default_send_param |
+ sctp_delayed_ack_time |
+ sctp_disable_fragments |
+ sctp_events |
+ sctp_get_peer_addr_info |
+ sctp_i_want_mapped_v4_addr |
+ sctp_initmsg |
+ sctp_maxseg |
+ sctp_nodelay |
+ sctp_peer_addr_params |
+ sctp_primary_addr |
+ sctp_rtoinfo |
+ sctp_set_peer_primary_addr |
+ sctp_status |
+ sndbuf |
+ tos.
+-type sctp_socket() :: port().
+
+-export_type([assoc_id/0, option/0, option_name/0, sctp_socket/0]).
+
+-spec open() -> {ok, Socket} | {error, inet:posix()} when
Socket :: sctp_socket().
open() ->
open([]).
--spec open(Port) -> {ok, Socket} | {error, posix()} when
- Port :: port_number(),
+-spec open(Port) -> {ok, Socket} | {error, inet:posix()} when
+ Port :: inet:port_number(),
Socket :: sctp_socket();
- (Opts) -> {ok, Socket} | {error, posix()} when
+ (Opts) -> {ok, Socket} | {error, inet:posix()} when
Opts :: [Opt],
- Opt :: {ip,IP} | {ifaddr,IP} | {port,Port} | sctp_option(),
- IP :: ip_address() | any | loopback,
- Port :: port_number(),
+ Opt :: {ip,IP}
+ | {ifaddr,IP}
+ | inet:address_family()
+ | {port,Port}
+ | {type,SockType}
+ | option(),
+ IP :: inet:ip_address() | any | loopback,
+ Port :: inet:port_number(),
+ SockType :: seqpacket | stream,
Socket :: sctp_socket().
open(Opts) when is_list(Opts) ->
@@ -98,11 +131,17 @@ open(Port) when is_integer(Port) ->
open(X) ->
erlang:error(badarg, [X]).
--spec open(Port, Opts) -> {ok, Socket} | {error, posix()} when
+-spec open(Port, Opts) -> {ok, Socket} | {error, inet:posix()} when
Opts :: [Opt],
- Opt :: {ip,IP} | {ifaddr,IP} | {port,Port} | sctp_option(),
- IP :: ip_address() | any | loopback,
- Port :: port_number(),
+ Opt :: {ip,IP}
+ | {ifaddr,IP}
+ | inet:address_family()
+ | {port,Port}
+ | {type,SockType}
+ | option(),
+ IP :: inet:ip_address() | any | loopback,
+ Port :: inet:port_number(),
+ SockType :: seqpacket | stream,
Socket :: sctp_socket().
open(Port, Opts) when is_integer(Port), is_list(Opts) ->
@@ -110,7 +149,7 @@ open(Port, Opts) when is_integer(Port), is_list(Opts) ->
open(Port, Opts) ->
erlang:error(badarg, [Port,Opts]).
--spec close(Socket) -> ok | {error, posix()} when
+-spec close(Socket) -> ok | {error, inet:posix()} when
Socket :: sctp_socket().
close(S) when is_port(S) ->
@@ -127,33 +166,54 @@ close(S) ->
-spec listen(Socket, IsServer) -> ok | {error, Reason} when
Socket :: sctp_socket(),
IsServer :: boolean(),
+ Reason :: term();
+ (Socket, Backlog) -> ok | {error, Reason} when
+ Socket :: sctp_socket(),
+ Backlog :: integer(),
Reason :: term().
-listen(S, Flag) when is_port(S), is_boolean(Flag) ->
+listen(S, Backlog)
+ when is_port(S), is_boolean(Backlog);
+ is_port(S), is_integer(Backlog) ->
case inet_db:lookup_socket(S) of
{ok,Mod} ->
- Mod:listen(S, Flag);
+ Mod:listen(S, Backlog);
Error -> Error
end;
listen(S, Flag) ->
erlang:error(badarg, [S,Flag]).
--spec connect(Socket, Addr, Port, Opts) -> {ok, Assoc} | {error, posix()} when
+-spec peeloff(Socket, Assoc) -> {ok, NewSocket} | {error, Reason} when
+ Socket :: sctp_socket(),
+ Assoc :: #sctp_assoc_change{} | assoc_id(),
+ NewSocket :: sctp_socket(),
+ Reason :: term().
+
+peeloff(S, #sctp_assoc_change{assoc_id=AssocId}) when is_port(S) ->
+ peeloff(S, AssocId);
+peeloff(S, AssocId) when is_port(S), is_integer(AssocId) ->
+ case inet_db:lookup_socket(S) of
+ {ok,Mod} ->
+ Mod:peeloff(S, AssocId);
+ Error -> Error
+ end.
+
+-spec connect(Socket, Addr, Port, Opts) -> {ok, Assoc} | {error, inet:posix()} when
Socket :: sctp_socket(),
- Addr :: ip_address() | hostname(),
- Port :: port_number(),
- Opts :: [Opt :: sctp_option()],
+ Addr :: inet:ip_address() | inet:hostname(),
+ Port :: inet:port_number(),
+ Opts :: [Opt :: option()],
Assoc :: #sctp_assoc_change{}.
connect(S, Addr, Port, Opts) ->
connect(S, Addr, Port, Opts, infinity).
-spec connect(Socket, Addr, Port, Opts, Timeout) ->
- {ok, Assoc} | {error, posix()} when
+ {ok, Assoc} | {error, inet:posix()} when
Socket :: sctp_socket(),
- Addr :: ip_address() | hostname(),
- Port :: port_number(),
- Opts :: [Opt :: sctp_option()],
+ Addr :: inet:ip_address() | inet:hostname(),
+ Port :: inet:port_number(),
+ Opts :: [Opt :: option()],
Timeout :: timeout(),
Assoc :: #sctp_assoc_change{}.
@@ -166,21 +226,21 @@ connect(S, Addr, Port, Opts, Timeout) ->
end.
-spec connect_init(Socket, Addr, Port, Opts) ->
- ok | {error, posix()} when
+ ok | {error, inet:posix()} when
Socket :: sctp_socket(),
- Addr :: ip_address() | hostname(),
- Port :: port_number(),
- Opts :: [sctp_option()].
+ Addr :: inet:ip_address() | inet:hostname(),
+ Port :: inet:port_number(),
+ Opts :: [option()].
connect_init(S, Addr, Port, Opts) ->
connect_init(S, Addr, Port, Opts, infinity).
-spec connect_init(Socket, Addr, Port, Opts, Timeout) ->
- ok | {error, posix()} when
+ ok | {error, inet:posix()} when
Socket :: sctp_socket(),
- Addr :: ip_address() | hostname(),
- Port :: port_number(),
- Opts :: [sctp_option()],
+ Addr :: inet:ip_address() | inet:hostname(),
+ Port :: inet:port_number(),
+ Opts :: [option()],
Timeout :: timeout().
connect_init(S, Addr, Port, Opts, Timeout) ->
@@ -232,7 +292,7 @@ eof(S, #sctp_assoc_change{assoc_id=AssocId}) when is_port(S) ->
eof(S, Assoc) ->
erlang:error(badarg, [S,Assoc]).
--spec abort(Socket, Assoc) -> ok | {error, posix()} when
+-spec abort(Socket, Assoc) -> ok | {error, inet:posix()} when
Socket :: sctp_socket(),
Assoc :: #sctp_assoc_change{}.
@@ -294,13 +354,13 @@ send(S, AssocChange, Stream, Data) ->
-spec recv(Socket) -> {ok, {FromIP, FromPort, AncData, Data}}
| {error, Reason} when
Socket :: sctp_socket(),
- FromIP :: ip_address(),
- FromPort :: port_number(),
+ FromIP :: inet:ip_address(),
+ FromPort :: inet:port_number(),
AncData :: [#sctp_sndrcvinfo{}],
Data :: binary() | string() | #sctp_sndrcvinfo{}
| #sctp_assoc_change{} | #sctp_paddr_change{}
| #sctp_adaptation_event{},
- Reason :: posix() | #sctp_send_failed{} | #sctp_paddr_change{}
+ Reason :: inet:posix() | #sctp_send_failed{} | #sctp_paddr_change{}
| #sctp_pdapi_event{} | #sctp_remote_error{}
| #sctp_shutdown_event{}.
@@ -311,13 +371,13 @@ recv(S) ->
| {error, Reason} when
Socket :: sctp_socket(),
Timeout :: timeout(),
- FromIP :: ip_address(),
- FromPort :: port_number(),
+ FromIP :: inet:ip_address(),
+ FromPort :: inet:port_number(),
AncData :: [#sctp_sndrcvinfo{}],
Data :: binary() | string() | #sctp_sndrcvinfo{}
| #sctp_assoc_change{} | #sctp_paddr_change{}
| #sctp_adaptation_event{},
- Reason :: posix() | #sctp_send_failed{} | #sctp_paddr_change{}
+ Reason :: inet:posix() | #sctp_send_failed{} | #sctp_paddr_change{}
| #sctp_pdapi_event{} | #sctp_remote_error{}
| #sctp_shutdown_event{}.
diff --git a/lib/kernel/src/gen_tcp.erl b/lib/kernel/src/gen_tcp.erl
index bee61ca84a..8ab18c01b4 100644
--- a/lib/kernel/src/gen_tcp.erl
+++ b/lib/kernel/src/gen_tcp.erl
@@ -28,34 +28,108 @@
-include("inet_int.hrl").
--type hostname() :: inet:hostname().
--type ip_address() :: inet:ip_address().
--type port_number() :: 0..65535.
--type posix() :: inet:posix().
+-type option() ::
+ {active, true | false | once} |
+ {bit8, clear | set | on | off} |
+ {buffer, non_neg_integer()} |
+ {delay_send, boolean()} |
+ {deliver, port | term} |
+ {dontroute, boolean()} |
+ {exit_on_close, boolean()} |
+ {header, non_neg_integer()} |
+ {high_watermark, non_neg_integer()} |
+ {keepalive, boolean()} |
+ {linger, {boolean(), non_neg_integer()}} |
+ {low_watermark, non_neg_integer()} |
+ {mode, list | binary} | list | binary |
+ {nodelay, boolean()} |
+ {packet,
+ 0 | 1 | 2 | 4 | raw | sunrm | asn1 |
+ cdr | fcgi | line | tpkt | http | httph | http_bin | httph_bin } |
+ {packet_size, non_neg_integer()} |
+ {priority, non_neg_integer()} |
+ {raw,
+ Protocol :: non_neg_integer(),
+ OptionNum :: non_neg_integer(),
+ ValueBin :: binary()} |
+ {recbuf, non_neg_integer()} |
+ {reuseaddr, boolean()} |
+ {send_timeout, non_neg_integer() | infinity} |
+ {send_timeout_close, boolean()} |
+ {sndbuf, non_neg_integer()} |
+ {tos, non_neg_integer()}.
+-type option_name() ::
+ active |
+ bit8 |
+ buffer |
+ delay_send |
+ deliver |
+ dontroute |
+ exit_on_close |
+ header |
+ high_watermark |
+ keepalive |
+ linger |
+ low_watermark |
+ mode |
+ nodelay |
+ packet |
+ packet_size |
+ priority |
+ {raw,
+ Protocol :: non_neg_integer(),
+ OptionNum :: non_neg_integer(),
+ ValueSpec :: (ValueSize :: non_neg_integer()) |
+ (ValueBin :: binary())} |
+ recbuf |
+ reuseaddr |
+ send_timeout |
+ send_timeout_close |
+ sndbuf |
+ tos.
+-type connect_option() ::
+ {ip, inet:ip_address()} |
+ {fd, Fd :: non_neg_integer()} |
+ {ifaddr, inet:ip_address()} |
+ inet:address_family() |
+ {port, inet:port_number()} |
+ {tcp_module, module()} |
+ option().
+-type listen_option() ::
+ {ip, inet:ip_address()} |
+ {fd, Fd :: non_neg_integer()} |
+ {ifaddr, inet:ip_address()} |
+ inet:address_family() |
+ {port, inet:port_number()} |
+ {backlog, B :: non_neg_integer()} |
+ {tcp_module, module()} |
+ option().
-type socket() :: port().
+-export_type([option/0, option_name/0, connect_option/0, listen_option/0]).
+
%%
%% Connect a socket
%%
-spec connect(Address, Port, Options) -> {ok, Socket} | {error, Reason} when
- Address :: ip_address() | hostname(),
- Port :: port_number(),
- Options :: [Opt :: term()],
+ Address :: inet:ip_address() | inet:hostname(),
+ Port :: inet:port_number(),
+ Options :: [connect_option()],
Socket :: socket(),
- Reason :: posix().
+ Reason :: inet:posix().
connect(Address, Port, Opts) ->
connect(Address,Port,Opts,infinity).
-spec connect(Address, Port, Options, Timeout) ->
{ok, Socket} | {error, Reason} when
- Address :: ip_address() | hostname(),
- Port :: port_number(),
- Options :: [Opt :: term()],
+ Address :: inet:ip_address() | inet:hostname(),
+ Port :: inet:port_number(),
+ Options :: [connect_option()],
Timeout :: timeout(),
Socket :: socket(),
- Reason :: posix().
+ Reason :: inet:posix().
connect(Address, Port, Opts, Time) ->
Timer = inet:start_timer(Time),
@@ -97,10 +171,10 @@ try_connect([], _Port, _Opts, _Timer, _Mod, Err) ->
%%
-spec listen(Port, Options) -> {ok, ListenSocket} | {error, Reason} when
- Port :: port_number(),
- Options :: [Opt :: term()],
+ Port :: inet:port_number(),
+ Options :: [listen_option()],
ListenSocket :: socket(),
- Reason :: posix().
+ Reason :: inet:posix().
listen(Port, Opts) ->
Mod = mod(Opts, undefined),
@@ -119,7 +193,7 @@ listen(Port, Opts) ->
-spec accept(ListenSocket) -> {ok, Socket} | {error, Reason} when
ListenSocket :: socket(),
Socket :: socket(),
- Reason :: closed | timeout | posix().
+ Reason :: closed | timeout | inet:posix().
accept(S) ->
case inet_db:lookup_socket(S) of
@@ -133,7 +207,7 @@ accept(S) ->
ListenSocket :: socket(),
Timeout :: timeout(),
Socket :: socket(),
- Reason :: closed | timeout | posix().
+ Reason :: closed | timeout | inet:posix().
accept(S, Time) when is_port(S) ->
case inet_db:lookup_socket(S) of
@@ -150,7 +224,7 @@ accept(S, Time) when is_port(S) ->
-spec shutdown(Socket, How) -> ok | {error, Reason} when
Socket :: socket(),
How :: read | write | read_write,
- Reason :: posix().
+ Reason :: inet:posix().
shutdown(S, How) when is_port(S) ->
case inet_db:lookup_socket(S) of
@@ -176,8 +250,8 @@ close(S) ->
-spec send(Socket, Packet) -> ok | {error, Reason} when
Socket :: socket(),
- Packet :: string() | binary(),
- Reason :: posix().
+ Packet :: iodata(),
+ Reason :: inet:posix().
send(S, Packet) when is_port(S) ->
case inet_db:lookup_socket(S) of
@@ -195,7 +269,7 @@ send(S, Packet) when is_port(S) ->
Socket :: socket(),
Length :: non_neg_integer(),
Packet :: string() | binary() | HttpPacket,
- Reason :: closed | posix(),
+ Reason :: closed | inet:posix(),
HttpPacket :: term().
recv(S, Length) when is_port(S) ->
@@ -211,7 +285,7 @@ recv(S, Length) when is_port(S) ->
Length :: non_neg_integer(),
Timeout :: timeout(),
Packet :: string() | binary() | HttpPacket,
- Reason :: closed | posix(),
+ Reason :: closed | inet:posix(),
HttpPacket :: term().
recv(S, Length, Time) when is_port(S) ->
@@ -237,7 +311,7 @@ unrecv(S, Data) when is_port(S) ->
-spec controlling_process(Socket, Pid) -> ok | {error, Reason} when
Socket :: socket(),
Pid :: pid(),
- Reason :: closed | not_owner | posix().
+ Reason :: closed | not_owner | inet:posix().
controlling_process(S, NewOwner) ->
case inet_db:lookup_socket(S) of
diff --git a/lib/kernel/src/gen_udp.erl b/lib/kernel/src/gen_udp.erl
index 7d14615c04..8688799ae9 100644
--- a/lib/kernel/src/gen_udp.erl
+++ b/lib/kernel/src/gen_udp.erl
@@ -25,25 +25,74 @@
-include("inet_int.hrl").
--type hostname() :: inet:hostname().
--type ip_address() :: inet:ip_address().
--type port_number() :: 0..65535.
--type posix() :: inet:posix().
+-type option() ::
+ {active, true | false | once} |
+ {add_membership, {inet:ip_address(), inet:ip_address()}} |
+ {broadcast, boolean()} |
+ {buffer, non_neg_integer()} |
+ {deliver, port | term} |
+ {dontroute, boolean()} |
+ {drop_membership, {inet:ip_address(), inet:ip_address()}} |
+ {header, non_neg_integer()} |
+ {mode, list | binary} | list | binary |
+ {multicast_if, inet:ip_address()} |
+ {multicast_loop, boolean()} |
+ {multicast_ttl, non_neg_integer()} |
+ {priority, non_neg_integer()} |
+ {raw,
+ Protocol :: non_neg_integer(),
+ OptionNum :: non_neg_integer(),
+ ValueBin :: binary()} |
+ {read_packets, non_neg_integer()} |
+ {recbuf, non_neg_integer()} |
+ {reuseaddr, boolean()} |
+ {sndbuf, non_neg_integer()} |
+ {tos, non_neg_integer()}.
+-type option_name() ::
+ active |
+ broadcast |
+ buffer |
+ deliver |
+ dontroute |
+ header |
+ mode |
+ multicast_if |
+ multicast_loop |
+ multicast_ttl |
+ priority |
+ {raw,
+ Protocol :: non_neg_integer(),
+ OptionNum :: non_neg_integer(),
+ ValueSpec :: (ValueSize :: non_neg_integer()) |
+ (ValueBin :: binary())} |
+ read_packets |
+ recbuf |
+ reuseaddr |
+ sndbuf |
+ tos.
-type socket() :: port().
+-export_type([option/0, option_name/0]).
+
-spec open(Port) -> {ok, Socket} | {error, Reason} when
- Port :: port_number(),
+ Port :: inet:port_number(),
Socket :: socket(),
- Reason :: posix().
+ Reason :: inet:posix().
open(Port) ->
open(Port, []).
-spec open(Port, Opts) -> {ok, Socket} | {error, Reason} when
- Port :: port_number(),
- Opts :: [Opt :: term()],
+ Port :: inet:port_number(),
+ Opts :: [Option],
+ Option :: {ip, inet:ip_address()}
+ | {fd, non_neg_integer()}
+ | {ifaddr, inet:ip_address()}
+ | inet:address_family()
+ | {port, inet:port_number()}
+ | option(),
Socket :: socket(),
- Reason :: posix().
+ Reason :: inet:posix().
open(Port, Opts) ->
Mod = mod(Opts, undefined),
@@ -58,10 +107,10 @@ close(S) ->
-spec send(Socket, Address, Port, Packet) -> ok | {error, Reason} when
Socket :: socket(),
- Address :: ip_address() | hostname(),
- Port :: port_number(),
- Packet :: string() | binary(),
- Reason :: not_owner | posix().
+ Address :: inet:ip_address() | inet:hostname(),
+ Port :: inet:port_number(),
+ Packet :: iodata(),
+ Reason :: not_owner | inet:posix().
send(S, Address, Port, Packet) when is_port(S) ->
case inet_db:lookup_socket(S) of
@@ -92,10 +141,10 @@ send(S, Packet) when is_port(S) ->
{ok, {Address, Port, Packet}} | {error, Reason} when
Socket :: socket(),
Length :: non_neg_integer(),
- Address :: ip_address(),
- Port :: port_number(),
+ Address :: inet:ip_address(),
+ Port :: inet:port_number(),
Packet :: string() | binary(),
- Reason :: not_owner | posix().
+ Reason :: not_owner | inet:posix().
recv(S,Len) when is_port(S), is_integer(Len) ->
case inet_db:lookup_socket(S) of
@@ -110,10 +159,10 @@ recv(S,Len) when is_port(S), is_integer(Len) ->
Socket :: socket(),
Length :: non_neg_integer(),
Timeout :: timeout(),
- Address :: ip_address(),
- Port :: port_number(),
+ Address :: inet:ip_address(),
+ Port :: inet:port_number(),
Packet :: string() | binary(),
- Reason :: not_owner | posix().
+ Reason :: not_owner | inet:posix().
recv(S,Len,Time) when is_port(S) ->
case inet_db:lookup_socket(S) of
diff --git a/lib/kernel/src/global.erl b/lib/kernel/src/global.erl
index 7d15f8bf83..fa97614eca 100644
--- a/lib/kernel/src/global.erl
+++ b/lib/kernel/src/global.erl
@@ -28,7 +28,7 @@
%% External exports
-export([start/0, start_link/0, stop/0, sync/0, sync/1,
- safe_whereis_name/1, whereis_name/1, register_name/2,
+ whereis_name/1, register_name/2,
register_name/3, register_name_external/2, register_name_external/3,
unregister_name_external/1,re_register_name/2, re_register_name/3,
unregister_name/1, registered_names/0, send/2, node_disconnected/1,
@@ -203,10 +203,6 @@ send(Name, Msg) ->
whereis_name(Name) ->
where(Name).
--spec safe_whereis_name(term()) -> pid() | 'undefined'.
-safe_whereis_name(Name) ->
- gen_server:call(global_name_server, {whereis, Name}, infinity).
-
node_disconnected(Node) ->
global_name_server ! {nodedown, Node}.
@@ -510,8 +506,7 @@ init([]) ->
%% delay can sometimes be quite substantial. Global guarantees that
%% the name will eventually be removed, but there is no
%% synchronization between nodes; the name can be removed from some
-%% node(s) long before it is removed from other nodes. Using
-%% safe_whereis_name is no cure.
+%% node(s) long before it is removed from other nodes.
%%
%% - Global cannot handle problems with the distribution very well.
%% Depending on the value of the kernel variable 'net_ticktime' long
@@ -589,10 +584,6 @@ init([]) ->
{'reply', term(), state()} |
{'stop', 'normal', 'stopped', state()}.
-handle_call({whereis, Name}, From, S) ->
- do_whereis(Name, From),
- {noreply, S};
-
handle_call({registrar, Fun}, From, S) ->
S#state.the_registrar ! {trans_all_known, Fun, From},
{noreply, S};
@@ -1235,7 +1226,15 @@ ins_name_ext(Name, Pid, Method, RegNode, FromPidOrNode, ExtraInfo, S0) ->
where(Name) ->
case ets:lookup(global_names, Name) of
- [{_Name, Pid, _Method, _RPid, _Ref}] -> Pid;
+ [{_Name, Pid, _Method, _RPid, _Ref}] ->
+ if node(Pid) == node() ->
+ case is_process_alive(Pid) of
+ true -> Pid;
+ false -> undefined
+ end;
+ true ->
+ Pid
+ end;
[] -> undefined
end.
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl
index 5649188c38..b60c68e3a1 100644
--- a/lib/kernel/src/inet.erl
+++ b/lib/kernel/src/inet.erl
@@ -36,7 +36,7 @@
-export([i/0, i/1, i/2]).
--export([getll/1, getfd/1, open/7, fdopen/5]).
+-export([getll/1, getfd/1, open/8, fdopen/6]).
-export([tcp_controlling_process/2, udp_controlling_process/2,
tcp_close/1, udp_close/1]).
@@ -63,8 +63,9 @@
%% timer interface
-export([start_timer/1, timeout/1, timeout/2, stop_timer/1]).
--export_type([family_option/0, hostent/0, hostname/0, ip4_address/0,
- ip6_address/0, ip_address/0, posix/0, socket/0]).
+-export_type([address_family/0, hostent/0, hostname/0, ip4_address/0,
+ ip6_address/0, ip_address/0, posix/0, socket/0,
+ port_number/0]).
%% imports
-import(lists, [append/1, duplicate/2, filter/2, foldl/3]).
@@ -87,98 +88,15 @@
-type ip6_address() :: {0..65535,0..65535,0..65535,0..65535,
0..65535,0..65535,0..65535,0..65535}.
-type ip_address() :: ip4_address() | ip6_address().
--type ip_port() :: 0..65535.
+-type port_number() :: 0..65535.
-type posix() :: exbadport | exbadseq | file:posix().
-type socket() :: port().
-type socket_setopt() ::
- {'raw', non_neg_integer(), non_neg_integer(), binary()} |
- %% TCP/UDP options
- {'reuseaddr', boolean()} |
- {'keepalive', boolean()} |
- {'dontroute', boolean()} |
- {'linger', {boolean(), non_neg_integer()}} |
- {'broadcast', boolean()} |
- {'sndbuf', non_neg_integer()} |
- {'recbuf', non_neg_integer()} |
- {'priority', non_neg_integer()} |
- {'tos', non_neg_integer()} |
- {'nodelay', boolean()} |
- {'multicast_ttl', non_neg_integer()} |
- {'multicast_loop', boolean()} |
- {'multicast_if', ip_address()} |
- {'add_membership', {ip_address(), ip_address()}} |
- {'drop_membership', {ip_address(), ip_address()}} |
- {'header', non_neg_integer()} |
- {'buffer', non_neg_integer()} |
- {'active', boolean() | 'once'} |
- {'packet',
- 0 | 1 | 2 | 4 | 'raw' | 'sunrm' | 'asn1' |
- 'cdr' | 'fcgi' | 'line' | 'tpkt' | 'http' | 'httph' | 'http_bin' | 'httph_bin' } |
- {'mode', 'list' | 'binary'} |
- {'port', 'port', 'term'} |
- {'exit_on_close', boolean()} |
- {'low_watermark', non_neg_integer()} |
- {'high_watermark', non_neg_integer()} |
- {'bit8', 'clear' | 'set' | 'on' | 'off'} |
- {'send_timeout', non_neg_integer() | 'infinity'} |
- {'send_timeout_close', boolean()} |
- {'delay_send', boolean()} |
- {'packet_size', non_neg_integer()} |
- {'read_packets', non_neg_integer()} |
- %% SCTP options
- {'sctp_rtoinfo', #sctp_rtoinfo{}} |
- {'sctp_associnfo', #sctp_assocparams{}} |
- {'sctp_initmsg', #sctp_initmsg{}} |
- {'sctp_nodelay', boolean()} |
- {'sctp_autoclose', non_neg_integer()} |
- {'sctp_disable_fragments', boolean()} |
- {'sctp_i_want_mapped_v4_addr', boolean()} |
- {'sctp_maxseg', non_neg_integer()} |
- {'sctp_primary_addr', #sctp_prim{}} |
- {'sctp_set_peer_primary_addr', #sctp_setpeerprim{}} |
- {'sctp_adaptation_layer', #sctp_setadaptation{}} |
- {'sctp_peer_addr_params', #sctp_paddrparams{}} |
- {'sctp_default_send_param', #sctp_sndrcvinfo{}} |
- {'sctp_events', #sctp_event_subscribe{}} |
- {'sctp_delayed_ack_time', #sctp_assoc_value{}}.
+ gen_sctp:option() | gen_tcp:option() | gen_udp:option().
-type socket_getopt() ::
- {'raw',
- non_neg_integer(), non_neg_integer(), binary()|non_neg_integer()} |
- %% TCP/UDP options
- 'reuseaddr' | 'keepalive' | 'dontroute' | 'linger' |
- 'broadcast' | 'sndbuf' | 'recbuf' | 'priority' | 'tos' | 'nodelay' |
- 'multicast_ttl' | 'multicast_loop' | 'multicast_if' |
- 'add_membership' | 'drop_membership' |
- 'header' | 'buffer' | 'active' | 'packet' | 'mode' | 'port' |
- 'exit_on_close' | 'low_watermark' | 'high_watermark' | 'bit8' |
- 'send_timeout' | 'send_timeout_close' |
- 'delay_send' | 'packet_size' | 'read_packets' |
- %% SCTP options
- {'sctp_status', #sctp_status{}} |
- 'sctp_get_peer_addr_info' |
- {'sctp_get_peer_addr_info', #sctp_status{}} |
- 'sctp_rtoinfo' |
- {'sctp_rtoinfo', #sctp_rtoinfo{}} |
- 'sctp_associnfo' |
- {'sctp_associnfo', #sctp_assocparams{}} |
- 'sctp_initmsg' |
- {'sctp_initmsg', #sctp_initmsg{}} |
- 'sctp_nodelay' | 'sctp_autoclose' | 'sctp_disable_fragments' |
- 'sctp_i_want_mapped_v4_addr' | 'sctp_maxseg' |
- {'sctp_primary_addr', #sctp_prim{}} |
- {'sctp_set_peer_primary_addr', #sctp_setpeerprim{}} |
- 'sctp_adaptation_layer' |
- {'sctp_adaptation_layer', #sctp_setadaptation{}} |
- {'sctp_peer_addr_params', #sctp_paddrparams{}} |
- 'sctp_default_send_param' |
- {'sctp_default_send_param', #sctp_sndrcvinfo{}} |
- 'sctp_events' |
- {'sctp_events', #sctp_event_subscribe{}} |
- 'sctp_delayed_ack_time' |
- {'sctp_delayed_ack_time', #sctp_assoc_value{}}.
-
+ gen_sctp:option_name() | gen_tcp:option_name() | gen_udp:option_name().
-type ether_address() :: [0..255].
-type if_setopt() ::
@@ -196,8 +114,9 @@
'addr' | 'broadaddr' | 'dstaddr' |
'mtu' | 'netmask' | 'flags' |'hwaddr'.
--type family_option() :: 'inet' | 'inet6'.
--type protocol_option() :: 'tcp' | 'udp' | 'sctp'.
+-type address_family() :: 'inet' | 'inet6'.
+-type socket_protocol() :: 'tcp' | 'udp' | 'sctp'.
+-type socket_type() :: 'stream' | 'dgram' | 'seqpacket'.
-type stat_option() ::
'recv_cnt' | 'recv_max' | 'recv_avg' | 'recv_oct' | 'recv_dvi' |
'send_cnt' | 'send_max' | 'send_avg' | 'send_oct' | 'send_pend'.
@@ -229,7 +148,7 @@ close(Socket) ->
peername(Socket) ->
prim_inet:peername(Socket).
--spec setpeername(Socket :: socket(), Address :: {ip_address(), ip_port()}) ->
+-spec setpeername(Socket :: socket(), Address :: {ip_address(), port_number()}) ->
'ok' | {'error', any()}.
setpeername(Socket, {IP,Port}) ->
@@ -246,7 +165,7 @@ setpeername(Socket, undefined) ->
sockname(Socket) ->
prim_inet:sockname(Socket).
--spec setsockname(Socket :: socket(), Address :: {ip_address(), ip_port()}) ->
+-spec setsockname(Socket :: socket(), Address :: {ip_address(), port_number()}) ->
'ok' | {'error', any()}.
setsockname(Socket, {IP,Port}) ->
@@ -254,7 +173,9 @@ setsockname(Socket, {IP,Port}) ->
setsockname(Socket, undefined) ->
prim_inet:setsockname(Socket, undefined).
--spec port(Socket :: socket()) -> {'ok', ip_port()} | {'error', any()}.
+-spec port(Socket) -> {'ok', Port} | {'error', any()} when
+ Socket :: socket(),
+ Port :: port_number().
port(Socket) ->
case prim_inet:sockname(Socket) of
@@ -268,16 +189,18 @@ port(Socket) ->
send(Socket, Packet) ->
prim_inet:send(Socket, Packet).
--spec setopts(Socket :: socket(), Opts :: [socket_setopt()]) ->
- 'ok' | {'error', posix()}.
+-spec setopts(Socket, Options) -> ok | {error, posix()} when
+ Socket :: socket(),
+ Options :: [socket_setopt()].
setopts(Socket, Opts) ->
prim_inet:setopts(Socket, Opts).
-spec getopts(Socket, Options) ->
- {'ok', [socket_setopt()]} | {'error', posix()} when
+ {'ok', OptionValues} | {'error', posix()} when
Socket :: socket(),
- Options :: [socket_getopt()].
+ Options :: [socket_getopt()],
+ OptionValues :: [socket_setopt()].
getopts(Socket, Opts) ->
prim_inet:getopts(Socket, Opts).
@@ -419,14 +342,19 @@ gethostname() ->
gethostname(Socket) ->
prim_inet:gethostname(Socket).
--spec getstat(Socket :: socket()) ->
- {'ok', [{stat_option(), integer()}]} | {'error', posix()}.
+-spec getstat(Socket) ->
+ {ok, OptionValues} | {error, posix()} when
+ Socket :: socket(),
+ OptionValues :: [{stat_option(), integer()}].
getstat(Socket) ->
prim_inet:getstat(Socket, stats()).
--spec getstat(Socket :: socket(), Statoptions :: [stat_option()]) ->
- {'ok', [{stat_option(), integer()}]} | {'error', posix()}.
+-spec getstat(Socket, Options) ->
+ {ok, OptionValues} | {error, posix()} when
+ Socket :: socket(),
+ Options :: [stat_option()],
+ OptionValues :: [{stat_option(), integer()}].
getstat(Socket,What) ->
prim_inet:getstat(Socket, What).
@@ -441,14 +369,14 @@ gethostbyname(Name) ->
-spec gethostbyname(Hostname, Family) ->
{ok, Hostent} | {error, posix()} when
Hostname :: hostname(),
- Family :: family_option(),
+ Family :: address_family(),
Hostent :: hostent().
gethostbyname(Name,Family) ->
gethostbyname_tm(Name, Family, false).
-spec gethostbyname(Name :: hostname(),
- Family :: family_option(),
+ Family :: address_family(),
Timeout :: non_neg_integer() | 'infinity') ->
{'ok', #hostent{}} | {'error', posix()}.
@@ -527,14 +455,14 @@ getfd(Socket) ->
-spec getaddr(Host, Family) -> {ok, Address} | {error, posix()} when
Host :: ip_address() | hostname(),
- Family :: family_option(),
+ Family :: address_family(),
Address :: ip_address().
getaddr(Address, Family) ->
getaddr(Address, Family, infinity).
-spec getaddr(Host :: ip_address() | hostname(),
- Family :: family_option(),
+ Family :: address_family(),
Timeout :: non_neg_integer() | 'infinity') ->
{'ok', ip_address()} | {'error', posix()}.
@@ -553,14 +481,14 @@ getaddr_tm(Address, Family, Timer) ->
-spec getaddrs(Host, Family) ->
{ok, Addresses} | {error, posix()} when
Host :: ip_address() | hostname(),
- Family :: family_option(),
+ Family :: address_family(),
Addresses :: [ip_address()].
getaddrs(Address, Family) ->
getaddrs(Address, Family, infinity).
-spec getaddrs(Host :: ip_address() | string() | atom(),
- Family :: family_option(),
+ Family :: address_family(),
Timeout :: non_neg_integer() | 'infinity') ->
{'ok', [ip_address()]} | {'error', posix()}.
@@ -570,7 +498,7 @@ getaddrs(Address, Family, Timeout) ->
stop_timer(Timer),
Res.
--spec getservbyport(Port :: ip_port(), Protocol :: atom() | string()) ->
+-spec getservbyport(Port :: port_number(), Protocol :: atom() | string()) ->
{'ok', string()} | {'error', posix()}.
getservbyport(Port, Proto) ->
@@ -584,7 +512,7 @@ getservbyport(Port, Proto) ->
-spec getservbyname(Name :: atom() | string(),
Protocol :: atom() | string()) ->
- {'ok', ip_port()} | {'error', posix()}.
+ {'ok', port_number()} | {'error', posix()}.
getservbyname(Name, Protocol) when is_atom(Name) ->
case inet_udp:open(0, []) of
@@ -821,6 +749,8 @@ sctp_opt([Opt|Opts], Mod, R, As) ->
sctp_opt(Opts, Mod, R#sctp_opts{port=P}, As);
Error -> Error
end;
+ {type,Type} when Type =:= seqpacket; Type =:= stream ->
+ sctp_opt(Opts, Mod, R#sctp_opts{type=Type}, As);
binary -> sctp_opt (Opts, Mod, R, As, mode, binary);
list -> sctp_opt (Opts, Mod, R, As, mode, list);
{sctp_module,_} -> sctp_opt (Opts, Mod, R, As); % Done with
@@ -1067,15 +997,16 @@ gethostbyaddr_tm_native(Addr, Timer, Opts) ->
-spec open(Fd :: integer(),
Addr :: ip_address(),
- Port :: ip_port(),
+ Port :: port_number(),
Opts :: [socket_setopt()],
- Protocol :: protocol_option(),
- Family :: 'inet' | 'inet6',
+ Protocol :: socket_protocol(),
+ Family :: address_family(),
+ Type :: socket_type(),
Module :: atom()) ->
{'ok', socket()} | {'error', posix()}.
-open(Fd, Addr, Port, Opts, Protocol, Family, Module) when Fd < 0 ->
- case prim_inet:open(Protocol, Family) of
+open(Fd, Addr, Port, Opts, Protocol, Family, Type, Module) when Fd < 0 ->
+ case prim_inet:open(Protocol, Family, Type) of
{ok,S} ->
case prim_inet:setopts(S, Opts) of
ok ->
@@ -1102,18 +1033,19 @@ open(Fd, Addr, Port, Opts, Protocol, Family, Module) when Fd < 0 ->
Error ->
Error
end;
-open(Fd, _Addr, _Port, Opts, Protocol, Family, Module) ->
- fdopen(Fd, Opts, Protocol, Family, Module).
+open(Fd, _Addr, _Port, Opts, Protocol, Family, Type, Module) ->
+ fdopen(Fd, Opts, Protocol, Family, Type, Module).
-spec fdopen(Fd :: non_neg_integer(),
Opts :: [socket_setopt()],
- Protocol :: protocol_option(),
- Family :: family_option(),
+ Protocol :: socket_protocol(),
+ Family :: address_family(),
+ Type :: socket_type(),
Module :: atom()) ->
{'ok', socket()} | {'error', posix()}.
-fdopen(Fd, Opts, Protocol, Family, Module) ->
- case prim_inet:fdopen(Protocol, Fd, Family) of
+fdopen(Fd, Opts, Protocol, Family, Type, Module) ->
+ case prim_inet:fdopen(Protocol, Family, Type, Fd) of
{ok, S} ->
case prim_inet:setopts(S, Opts) of
ok ->
@@ -1129,18 +1061,24 @@ fdopen(Fd, Opts, Protocol, Family, Module) ->
%% socket stat
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-i() -> i(tcp), i(udp).
+i() -> i(tcp), i(udp), i(sctp).
i(Proto) -> i(Proto, [port, module, recv, sent, owner,
- local_address, foreign_address, state]).
+ local_address, foreign_address, state, type]).
i(tcp, Fs) ->
ii(tcp_sockets(), Fs, tcp);
i(udp, Fs) ->
- ii(udp_sockets(), Fs, udp).
+ ii(udp_sockets(), Fs, udp);
+i(sctp, Fs) ->
+ ii(sctp_sockets(), Fs, sctp).
ii(Ss, Fs, Proto) ->
- LLs = [h_line(Fs) | info_lines(Ss, Fs, Proto)],
+ LLs =
+ case info_lines(Ss, Fs, Proto) of
+ [] -> [];
+ InfoLines -> [h_line(Fs) | InfoLines]
+ end,
Maxs = foldl(
fun(Line,Max0) -> smax(Max0,Line) end,
duplicate(length(Fs),0),LLs),
@@ -1208,6 +1146,7 @@ info(S, F, Proto) ->
case prim_inet:gettype(S) of
{ok,{_,stream}} -> "STREAM";
{ok,{_,dgram}} -> "DGRAM";
+ {ok,{_,seqpacket}} -> "SEQPACKET";
_ -> " "
end;
fd ->
@@ -1259,6 +1198,7 @@ fmt_port(N, Proto) ->
%% Return a list of all tcp sockets
tcp_sockets() -> port_list("tcp_inet").
udp_sockets() -> port_list("udp_inet").
+sctp_sockets() -> port_list("sctp_inet").
%% Return all ports having the name 'Name'
port_list(Name) ->
diff --git a/lib/kernel/src/inet6_sctp.erl b/lib/kernel/src/inet6_sctp.erl
index 5bf3fca647..c47483bbdd 100644
--- a/lib/kernel/src/inet6_sctp.erl
+++ b/lib/kernel/src/inet6_sctp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -32,7 +32,8 @@
-define(FAMILY, inet6).
-export([getserv/1,getaddr/1,getaddr/2,translate_ip/1]).
--export([open/1,close/1,listen/2,connect/5,sendmsg/3,send/4,recv/2]).
+-export([open/1,close/1,listen/2,peeloff/2,connect/5]).
+-export([sendmsg/3,send/4,recv/2]).
@@ -54,8 +55,8 @@ translate_ip(IP) ->
open(Opts) ->
case inet:sctp_options(Opts, ?MODULE) of
- {ok,#sctp_opts{fd=Fd,ifaddr=Addr,port=Port,opts=SOs}} ->
- inet:open(Fd, Addr, Port, SOs, sctp, ?FAMILY, ?MODULE);
+ {ok,#sctp_opts{fd=Fd,ifaddr=Addr,port=Port,type=Type,opts=SOs}} ->
+ inet:open(Fd, Addr, Port, SOs, sctp, ?FAMILY, Type, ?MODULE);
Error -> Error
end.
@@ -65,6 +66,14 @@ close(S) ->
listen(S, Flag) ->
prim_inet:listen(S, Flag).
+peeloff(S, AssocId) ->
+ case prim_inet:peeloff(S, AssocId) of
+ {ok, NewS}=Result ->
+ inet_db:register_socket(NewS, ?MODULE),
+ Result;
+ Error -> Error
+ end.
+
connect(S, Addr, Port, Opts, Timer) ->
inet_sctp:connect(S, Addr, Port, Opts, Timer).
diff --git a/lib/kernel/src/inet6_tcp.erl b/lib/kernel/src/inet6_tcp.erl
index cc45f6c7f6..c714b2bee0 100644
--- a/lib/kernel/src/inet6_tcp.erl
+++ b/lib/kernel/src/inet6_tcp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -93,7 +93,7 @@ do_connect(Addr = {A,B,C,D,E,F,G,H}, Port, Opts, Time) when
port=BPort,
opts=SockOpts}}
when ?ip6(Ab,Bb,Cb,Db,Eb,Fb,Gb,Hb), ?port(BPort) ->
- case inet:open(Fd,BAddr,BPort,SockOpts,tcp,inet6,?MODULE) of
+ case inet:open(Fd,BAddr,BPort,SockOpts,tcp,inet6,stream,?MODULE) of
{ok, S} ->
case prim_inet:connect(S, Addr, Port, Time) of
ok -> {ok,S};
@@ -115,7 +115,7 @@ listen(Port, Opts) ->
port=BPort,
opts=SockOpts}=R}
when ?ip6(A,B,C,D,E,F,G,H), ?port(BPort) ->
- case inet:open(Fd,BAddr,BPort,SockOpts,tcp,inet6,?MODULE) of
+ case inet:open(Fd,BAddr,BPort,SockOpts,tcp,inet6,stream,?MODULE) of
{ok, S} ->
case prim_inet:listen(S, R#listen_opts.backlog) of
ok -> {ok, S};
@@ -149,5 +149,5 @@ accept(L,Timeout) ->
%% Create a port/socket from a file descriptor
%%
fdopen(Fd, Opts) ->
- inet:fdopen(Fd, Opts, tcp, inet6, ?MODULE).
+ inet:fdopen(Fd, Opts, tcp, inet6, stream, ?MODULE).
diff --git a/lib/kernel/src/inet6_udp.erl b/lib/kernel/src/inet6_udp.erl
index e81d417151..ca43c94211 100644
--- a/lib/kernel/src/inet6_udp.erl
+++ b/lib/kernel/src/inet6_udp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -45,7 +45,7 @@ open(Port, Opts) ->
port=BPort,
opts=SockOpts}}
when ?ip6(A,B,C,D,E,F,G,H), ?port(BPort) ->
- inet:open(Fd,BAddr,BPort,SockOpts,udp,inet6,?MODULE);
+ inet:open(Fd,BAddr,BPort,SockOpts,udp,inet6,dgram,?MODULE);
{ok, _} -> exit(badarg)
end.
@@ -84,4 +84,4 @@ controlling_process(Socket, NewOwner) ->
%% Create a port/socket from a file descriptor
%%
fdopen(Fd, Opts) ->
- inet:fdopen(Fd, Opts, udp, inet6, ?MODULE).
+ inet:fdopen(Fd, Opts, udp, inet6, dgram, ?MODULE).
diff --git a/lib/kernel/src/inet_config.erl b/lib/kernel/src/inet_config.erl
index 2458876326..1ddbdcec25 100644
--- a/lib/kernel/src/inet_config.erl
+++ b/lib/kernel/src/inet_config.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -44,26 +44,6 @@
%%
-spec init() -> 'ok'.
init() ->
- OsType = os:type(),
- case OsType of
- {ose,_} ->
- case init:get_argument(loader) of
- {ok,[["ose_inet"]]} ->
- %% port already started by prim_loader
- ok;
- _Other ->
- %% Setup reserved port for ose_inet driver (only OSE)
- case catch erlang:open_port({spawn,"ose_inet"}, [binary]) of
- {'EXIT',Why} ->
- error("can't open port for ose_inet: ~p", [Why]);
- OseInetPort ->
- erlang:display({ose_inet_port,OseInetPort})
- end
- end;
- _ ->
- ok
- end,
-
set_hostname(),
%% Note: In shortnames (or non-distributed) mode we don't need to know
@@ -71,6 +51,7 @@ init() ->
%% the user to provide it (by means of inetrc), so we need to look
%% for it ourselves.
+ OsType = os:type(),
do_load_resolv(OsType, erl_dist_mode()),
case OsType of
@@ -226,35 +207,6 @@ do_load_resolv(vxworks, _) ->
load_resolv(Resolv, resolv)
end;
-do_load_resolv({ose,_Type}, _) ->
- inet_db:set_lookup([file, dns]),
- case os:getenv("NAMESERVER") of
- false ->
- case os:getenv("RESOLVFILE") of
- false ->
- erlang:display('Warning: No NAMESERVER or RESOLVFILE specified!'),
- no_resolv;
- Resolv ->
- load_resolv(Resolv, resolv)
- end;
- Ns ->
- {ok,IP} = inet_parse:address(Ns),
- inet_db:add_rc_list([{nameserver,IP}])
- end,
- case os:getenv("DOMAIN") of
- false ->
- no_domain;
- D ->
- ok = inet_db:add_rc_list([{domain,D}])
- end,
- case os:getenv("HOSTSFILE") of
- false ->
- erlang:display('Warning: No HOSTSFILE specified!'),
- no_hosts_file;
- File ->
- load_hosts(File, ose)
- end;
-
do_load_resolv(_, _) ->
inet_db:set_lookup([native]).
diff --git a/lib/kernel/src/inet_dns_record_adts.pl b/lib/kernel/src/inet_dns_record_adts.pl
index b1d8fab939..da50c7114f 100644
--- a/lib/kernel/src/inet_dns_record_adts.pl
+++ b/lib/kernel/src/inet_dns_record_adts.pl
@@ -2,7 +2,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009. All Rights Reserved.
+# Copyright Ericsson AB 2009-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -73,6 +73,10 @@ while( my ($Name, $r) = each(%Names)) {
# "@Values" = "V1,V2"...",VN"
my @D = @DATA;
foreach my $line (@D) {
+ # Ignore !name lines
+ if ($line =~ s/^\!(\S+)\s+//) {
+ next if $1 eq $Name;
+ }
my $m = 1;
# For leading * iterate $n times, otherwise once
$line =~ s/^\s*[*]// and $m = $n;
@@ -155,9 +159,9 @@ make_Name() -> \
make_Name(L) when is_list(L) -> \
make_Name(#Record{}, L).
-%% Generate #Record{} with one updated field
-%%
-*make_Name(Field, Value) -> \
+!dns_rr_opt %% Generate #Record{} with one updated field
+!dns_rr_opt %%
+!dns_rr_opt *make_Name(Field, Value) -> \
#Record{Field=Value};
%%
%% Update #Record{} from property list
diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl
index 6f1688c6a2..f8984b13fe 100644
--- a/lib/kernel/src/inet_int.hrl
+++ b/lib/kernel/src/inet_int.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -29,7 +29,7 @@
-define(INET_AF_ANY, 3). % Fake for ANY in any address family
-define(INET_AF_LOOPBACK, 4). % Fake for LOOPBACK in any address family
-%% type codes (gettype, INET_REQ_GETTYPE)
+%% type codes to open and gettype - INET_REQ_GETTYPE
-define(INET_TYPE_STREAM, 1).
-define(INET_TYPE_DGRAM, 2).
-define(INET_TYPE_SEQPACKET, 3).
@@ -83,16 +83,19 @@
-define(INET_REQ_IFSET, 23).
-define(INET_REQ_SUBSCRIBE, 24).
-define(INET_REQ_GETIFADDRS, 25).
+-define(INET_REQ_ACCEPT, 26).
+-define(INET_REQ_LISTEN, 27).
%% TCP requests
--define(TCP_REQ_ACCEPT, 40).
--define(TCP_REQ_LISTEN, 41).
+%%-define(TCP_REQ_ACCEPT, 40). MOVED
+%%-define(TCP_REQ_LISTEN, 41). MERGED
-define(TCP_REQ_RECV, 42).
-define(TCP_REQ_UNRECV, 43).
-define(TCP_REQ_SHUTDOWN, 44).
%% UDP and SCTP requests
-define(PACKET_REQ_RECV, 60).
--define(SCTP_REQ_LISTEN, 61).
+%%-define(SCTP_REQ_LISTEN, 61). MERGED
-define(SCTP_REQ_BINDX, 62). %% Multi-home SCTP bind
+-define(SCTP_REQ_PEELOFF, 63).
%% subscribe codes, INET_REQ_SUBSCRIBE
-define(INET_SUBS_EMPTY_OUT_Q, 1).
@@ -100,7 +103,7 @@
%% reply codes for *_REQ_*
-define(INET_REP_ERROR, 0).
-define(INET_REP_OK, 1).
--define(INET_REP_SCTP, 2).
+-define(INET_REP, 2).
%% INET, TCP and UDP options:
-define(INET_OPT_REUSEADDR, 0).
@@ -399,6 +402,7 @@
ifaddr,
port = 0,
fd = -1,
+ type = seqpacket,
opts = [{mode, binary},
{buffer, ?SCTP_DEF_BUFSZ},
{sndbuf, ?SCTP_DEF_BUFSZ},
diff --git a/lib/kernel/src/inet_res.erl b/lib/kernel/src/inet_res.erl
index d1f5644ff7..59ba408d7a 100644
--- a/lib/kernel/src/inet_res.erl
+++ b/lib/kernel/src/inet_res.erl
@@ -407,7 +407,7 @@ gethostbyname(Name) ->
-spec gethostbyname(Name, Family) -> {ok, Hostent} | {error, Reason} when
Name :: dns_name(),
Hostent :: inet:hostent(),
- Family :: inet:family_option(),
+ Family :: inet:address_family(),
Reason :: inet:posix() | res_error().
gethostbyname(Name,Family) ->
@@ -418,7 +418,7 @@ gethostbyname(Name,Family) ->
Name :: dns_name(),
Hostent :: inet:hostent(),
Timeout :: timeout(),
- Family :: inet:family_option(),
+ Family :: inet:address_family(),
Reason :: inet:posix() | res_error().
gethostbyname(Name,Family,Timeout) ->
diff --git a/lib/kernel/src/inet_sctp.erl b/lib/kernel/src/inet_sctp.erl
index de74b573bd..2d799d79fa 100644
--- a/lib/kernel/src/inet_sctp.erl
+++ b/lib/kernel/src/inet_sctp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -31,7 +31,8 @@
-define(FAMILY, inet).
-export([getserv/1,getaddr/1,getaddr/2,translate_ip/1]).
--export([open/1,close/1,listen/2,connect/5,sendmsg/3,send/4,recv/2]).
+-export([open/1,close/1,listen/2,peeloff/2,connect/5]).
+-export([sendmsg/3,send/4,recv/2]).
@@ -53,8 +54,8 @@ translate_ip(IP) ->
open(Opts) ->
case inet:sctp_options(Opts, ?MODULE) of
- {ok,#sctp_opts{fd=Fd,ifaddr=Addr,port=Port,opts=SOs}} ->
- inet:open(Fd, Addr, Port, SOs, sctp, ?FAMILY, ?MODULE);
+ {ok,#sctp_opts{fd=Fd,ifaddr=Addr,port=Port,type=Type,opts=SOs}} ->
+ inet:open(Fd, Addr, Port, SOs, sctp, ?FAMILY, Type, ?MODULE);
Error -> Error
end.
@@ -64,6 +65,14 @@ close(S) ->
listen(S, Flag) ->
prim_inet:listen(S, Flag).
+peeloff(S, AssocId) ->
+ case prim_inet:peeloff(S, AssocId) of
+ {ok, NewS}=Result ->
+ inet_db:register_socket(NewS, ?MODULE),
+ Result;
+ Error -> Error
+ end.
+
%% A non-blocking connect is implemented when the initial call is to
%% gen_sctp:connect_init which passes the value nowait as the Timer
connect(S, Addr, Port, Opts, Timer) ->
@@ -102,7 +111,7 @@ connect(S, Addr, Port, Opts, Timer) ->
connect_get_assoc(S, Addr, Port, false, Timer) ->
case recv(S, inet:timeout(Timer)) of
- {ok, {Addr, Port, [], #sctp_assoc_change{state=St}=Ev}} ->
+ {ok, {Addr, Port, _, #sctp_assoc_change{state=St}=Ev}} ->
if St =:= comm_up ->
%% Yes, successfully connected, return the whole
%% sctp_assoc_change event (containing, in particular,
@@ -123,7 +132,7 @@ connect_get_assoc(S, Addr, Port, false, Timer) ->
connect_get_assoc(S, Addr, Port, Active, Timer) ->
Timeout = inet:timeout(Timer),
receive
- {sctp,S,Addr,Port,{[],#sctp_assoc_change{state=St}=Ev}} ->
+ {sctp,S,Addr,Port,{_,#sctp_assoc_change{state=St}=Ev}} ->
case Active of
once ->
prim_inet:setopt(S, active, once);
diff --git a/lib/kernel/src/inet_tcp.erl b/lib/kernel/src/inet_tcp.erl
index 6dadccd6a9..4c2db16ce3 100644
--- a/lib/kernel/src/inet_tcp.erl
+++ b/lib/kernel/src/inet_tcp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -95,7 +95,7 @@ do_connect({A,B,C,D}, Port, Opts, Time) when ?ip(A,B,C,D), ?port(Port) ->
port=BPort,
opts=SockOpts}}
when ?ip(Ab,Bb,Cb,Db), ?port(BPort) ->
- case inet:open(Fd,BAddr,BPort,SockOpts,tcp,inet,?MODULE) of
+ case inet:open(Fd,BAddr,BPort,SockOpts,tcp,inet,stream,?MODULE) of
{ok, S} ->
case prim_inet:connect(S, {A,B,C,D}, Port, Time) of
ok -> {ok,S};
@@ -117,7 +117,7 @@ listen(Port, Opts) ->
port=BPort,
opts=SockOpts}=R}
when ?ip(A,B,C,D), ?port(BPort) ->
- case inet:open(Fd,BAddr,BPort,SockOpts,tcp,inet,?MODULE) of
+ case inet:open(Fd,BAddr,BPort,SockOpts,tcp,inet,stream,?MODULE) of
{ok, S} ->
case prim_inet:listen(S, R#listen_opts.backlog) of
ok -> {ok, S};
@@ -150,4 +150,4 @@ accept(L,Timeout) ->
%% Create a port/socket from a file descriptor
%%
fdopen(Fd, Opts) ->
- inet:fdopen(Fd, Opts, tcp, inet, ?MODULE).
+ inet:fdopen(Fd, Opts, tcp, inet, stream, ?MODULE).
diff --git a/lib/kernel/src/inet_udp.erl b/lib/kernel/src/inet_udp.erl
index 60bd96f332..80d930fe10 100644
--- a/lib/kernel/src/inet_udp.erl
+++ b/lib/kernel/src/inet_udp.erl
@@ -52,7 +52,7 @@ open(Port, Opts) ->
ifaddr=BAddr={A,B,C,D},
port=BPort,
opts=SockOpts}} when ?ip(A,B,C,D), ?port(BPort) ->
- inet:open(Fd,BAddr,BPort,SockOpts,udp,inet,?MODULE);
+ inet:open(Fd,BAddr,BPort,SockOpts,udp,inet,dgram,?MODULE);
{ok, _} -> exit(badarg)
end.
@@ -93,7 +93,7 @@ controlling_process(Socket, NewOwner) ->
fdopen(Fd, Opts) ->
inet:fdopen(Fd,
optuniquify([{recbuf, ?RECBUF} | Opts]),
- udp, inet, ?MODULE).
+ udp, inet, dgram, ?MODULE).
%% Remove all duplicate options from an option list.
diff --git a/lib/kernel/src/rpc.erl b/lib/kernel/src/rpc.erl
index be35f99ed2..e214ffa404 100644
--- a/lib/kernel/src/rpc.erl
+++ b/lib/kernel/src/rpc.erl
@@ -662,9 +662,10 @@ async_call(Node, Mod, Fun, Args) ->
ReplyTo ! {self(), {promise_reply, R}} %% self() is key
end).
--spec yield(Key) -> {value, Val} | timeout when
+-spec yield(Key) -> Res | {badrpc, Reason} when
Key :: key(),
- Val :: (Res :: term()) | {badrpc, Reason :: term()}.
+ Res :: term(),
+ Reason :: term().
yield(Key) when is_pid(Key) ->
{value,R} = do_yield(Key, infinity),
diff --git a/lib/kernel/src/user_drv.erl b/lib/kernel/src/user_drv.erl
index c34f2ddeb0..e33b4830ab 100644
--- a/lib/kernel/src/user_drv.erl
+++ b/lib/kernel/src/user_drv.erl
@@ -117,8 +117,9 @@ server1(Iport, Oport, Shell) ->
{Curr,Shell1} =
case init:get_argument(remsh) of
{ok,[[Node]]} ->
- RShell = {list_to_atom(Node),shell,start,[]},
- RGr = group:start(self(), RShell),
+ ANode = list_to_atom(Node),
+ RShell = {ANode,shell,start,[]},
+ RGr = group:start(self(), RShell, rem_sh_opts(ANode)),
{RGr,RShell};
E when E =:= error ; E =:= {ok,[[]]} ->
{group:start(self(), Shell),Shell}
@@ -134,6 +135,9 @@ server1(Iport, Oport, Shell) ->
%% Enter the server loop.
server_loop(Iport, Oport, Curr, User, Gr).
+rem_sh_opts(Node) ->
+ [{expand_fun,fun(B)-> rpc:call(Node,edlin_expand,expand,[B]) end}].
+
%% start_user()
%% Start a group leader process and register it as 'user', unless,
%% of course, a 'user' already exists.
diff --git a/lib/kernel/test/application_SUITE.erl b/lib/kernel/test/application_SUITE.erl
index 4ae4151004..f469a0af98 100644
--- a/lib/kernel/test/application_SUITE.erl
+++ b/lib/kernel/test/application_SUITE.erl
@@ -33,7 +33,7 @@
-export([config_change/1,
distr_changed_tc1/1, distr_changed_tc2/1,
- shutdown_func/1, do_shutdown/1]).
+ shutdown_func/1, do_shutdown/1, shutdown_timeout/1]).
-define(TESTCASE, testcase_name).
-define(testcase, ?config(?TESTCASE, Config)).
@@ -50,7 +50,7 @@ all() ->
load_use_cache, {group, reported_bugs}, start_phases,
script_start, nodedown_start, permit_false_start_local,
permit_false_start_dist, get_key,
- {group, distr_changed}, config_change, shutdown_func].
+ {group, distr_changed}, config_change, shutdown_func, shutdown_timeout].
groups() ->
[{reported_bugs, [],
@@ -967,7 +967,7 @@ otp_1586(doc) ->
["Test recursive load of applications."];
otp_1586(Conf) when is_list(Conf) ->
Dir = ?config(priv_dir,Conf),
- {ok, Fd} = file:open(filename:join(Dir, "app5.app"), write),
+ {ok, Fd} = file:open(filename:join(Dir, "app5.app"), [write]),
w_app5(Fd),
file:close(Fd),
?line code:add_patha(Dir),
@@ -1021,10 +1021,10 @@ otp_2012(Conf) when is_list(Conf) ->
?line yes = global:register_name(conf_change, CcPid),
% Write a .app file
- {ok, Fd} = file:open("app1.app", write),
+ {ok, Fd} = file:open("app1.app", [write]),
w_app1(Fd),
file:close(Fd),
- {ok, Fd2} = file:open("app2.app", write),
+ {ok, Fd2} = file:open("app2.app", [write]),
w_app1(Fd2),
file:close(Fd2),
@@ -1096,7 +1096,7 @@ otp_2973(doc) ->
["Test of two processes simultanously starting the same application."];
otp_2973(Conf) when is_list(Conf) ->
% Write a .app file
- {ok, Fd} = file:open("app0.app", write),
+ {ok, Fd} = file:open("app0.app", [write]),
w_app(Fd, app0()),
file:close(Fd),
@@ -1138,7 +1138,7 @@ otp_2973(Conf) when is_list(Conf) ->
% Write a .app file
- ?line {ok, Fda} = file:open("app_start_error.app", write),
+ ?line {ok, Fda} = file:open("app_start_error.app", [write]),
?line w_app_start_error(Fda),
?line file:close(Fda),
@@ -1273,12 +1273,12 @@ otp_4066(Conf) when is_list(Conf) ->
App1Nodes = {app1, AllNodes},
Dir = ?config(priv_dir,Conf),
- ?line {ok, FdC} = file:open(filename:join(Dir, "otp_4066.config"), write),
+ ?line {ok, FdC} = file:open(filename:join(Dir, "otp_4066.config"), [write]),
?line write_config(FdC, config_4066(AllNodes, 5000, [App1Nodes])),
?line file:close(FdC),
% Write the app1.app file
- ?line {ok, FdA12} = file:open(filename:join(Dir, "app1.app"), write),
+ ?line {ok, FdA12} = file:open(filename:join(Dir, "app1.app"), [write]),
?line w_app1(FdA12),
?line file:close(FdA12),
@@ -1441,7 +1441,7 @@ otp_5606(Conf) when is_list(Conf) ->
%% Write a config file
Dir = ?config(priv_dir, Conf),
- {ok, Fd} = file:open(filename:join(Dir, "sys.config"), write),
+ {ok, Fd} = file:open(filename:join(Dir, "sys.config"), [write]),
NodeNames = [Ncp1, Ncp2] = node_names([cp1, cp2], Conf),
(config4(NodeNames))(Fd, 10000),
file:close(Fd),
@@ -1915,6 +1915,32 @@ do_shutdown(Reason) ->
+%%%-----------------------------------------------------------------
+%%% Tests the 'shutdown_timeout' kernel config parameter
+%%%-----------------------------------------------------------------
+shutdown_timeout(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Cp1} = start_node(?MODULE_STRING++"_shutdown_timeout"),
+ wait_for_ready_net(),
+ ok = rpc:call(Cp1, application, set_env, [kernel, shutdown_timeout, 1000]),
+ rpc:call(Cp1, code, add_path, [filename:join([DataDir,deadlock])]),
+ ok = rpc:call(Cp1, application, start, [sasl]),
+ ok = rpc:call(Cp1, application, start, [deadlock]),
+ rpc:call(Cp1, deadlock, restart_and_fail, []),
+
+ ok = net_kernel:monitor_nodes(true),
+ _ = rpc:call(Cp1, init, stop, []),
+ receive
+ {nodedown,Cp1} ->
+ ok
+ after 10000 ->
+ ct:fail("timeout 10 sec: node termination hangs")
+ end,
+ ok.
+
+
+
+
%%-----------------------------------------------------------------
%% Utility functions
%%-----------------------------------------------------------------
@@ -2436,7 +2462,7 @@ start_node_config_sf(Name, SysConfigFun, Conf) ->
write_config_file(SysConfigFun, Conf) ->
Dir = ?config(priv_dir, Conf),
- {ok, Fd} = file:open(filename:join(Dir, "sys.config"), write),
+ {ok, Fd} = file:open(filename:join(Dir, "sys.config"), [write]),
SysConfigFun(Fd),
file:close(Fd),
filename:join(Dir,"sys").
@@ -2571,15 +2597,15 @@ cc(List) ->
create_app() ->
?line Dir = "./",
?line App1 = Dir ++ "app1",
- ?line {ok, Fd1} = file:open(App1++".app",write),
+ ?line {ok, Fd1} = file:open(App1++".app",[write]),
?line io:format(Fd1, "~p. \n", [app1()]),
?line file:close(Fd1),
?line App2 = Dir ++ "app2",
- ?line {ok, Fd2} = file:open(App2++".app",write),
+ ?line {ok, Fd2} = file:open(App2++".app",[write]),
?line io:format(Fd2, "~p. \n", [app2()]),
?line file:close(Fd2),
?line App3 = Dir ++ "app_sp",
- ?line {ok, Fd3} = file:open(App3++".app",write),
+ ?line {ok, Fd3} = file:open(App3++".app",[write]),
?line io:format(Fd3, "~p. \n", [app_sp()]),
?line file:close(Fd3),
ok.
@@ -2591,7 +2617,7 @@ create_script(ScriptName) ->
?line Apps = which_applications(),
?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
- ?line {ok,Fd} = file:open(Name++".rel",write),
+ ?line {ok,Fd} = file:open(Name++".rel",[write]),
?line io:format(Fd,
"{release, {\"Test release 3\", \"LATEST\"}, \n"
" {erts, \"4.4\"}, \n"
@@ -2610,7 +2636,7 @@ create_script_dc(ScriptName) ->
?line Apps = which_applications(),
?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
- ?line {ok,Fd} = file:open(Name++".rel",write),
+ ?line {ok,Fd} = file:open(Name++".rel",[write]),
?line io:format(Fd,
"{release, {\"Test release 3\", \"LATEST\"}, \n"
" {erts, \"4.4\"}, \n"
@@ -2630,7 +2656,7 @@ create_script_3002(ScriptName) ->
?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
?line {value,{_,_,SaslVer}} = lists:keysearch(sasl,1,Apps),
- ?line {ok,Fd} = file:open(Name++".rel",write),
+ ?line {ok,Fd} = file:open(Name++".rel",[write]),
?line io:format(Fd,
"{release, {\"Test release 3\", \"LATEST\"}, \n"
" {erts, \"4.4\"}, \n"
@@ -2646,22 +2672,22 @@ create_script_3002(ScriptName) ->
distr_changed_prep(Conf) when is_list(Conf) ->
% Write .app files
- ?line {ok, Fd1} = file:open("app1.app", write),
+ ?line {ok, Fd1} = file:open("app1.app", [write]),
?line w_app1(Fd1),
?line file:close(Fd1),
- ?line {ok, Fd2} = file:open("app2.app", write),
+ ?line {ok, Fd2} = file:open("app2.app", [write]),
?line w_app2(Fd2),
?line file:close(Fd2),
- ?line {ok, Fd3} = file:open("app3.app", write),
+ ?line {ok, Fd3} = file:open("app3.app", [write]),
?line w_app3(Fd3),
?line file:close(Fd3),
- ?line {ok, Fd4} = file:open("app6.app", write),
+ ?line {ok, Fd4} = file:open("app6.app", [write]),
?line w_app6(Fd4),
?line file:close(Fd4),
- ?line {ok, Fd5} = file:open("app7.app", write),
+ ?line {ok, Fd5} = file:open("app7.app", [write]),
?line w_app7(Fd5),
?line file:close(Fd5),
- ?line {ok, Fd6} = file:open("app8.app", write),
+ ?line {ok, Fd6} = file:open("app8.app", [write]),
?line w_app8(Fd6),
?line file:close(Fd6),
@@ -2683,7 +2709,7 @@ distr_changed_prep(Conf) when is_list(Conf) ->
WithSyncTime = config_fun(config_dc(NodeNames)),
?line Dir = ?config(priv_dir,Conf),
- ?line {ok, Fd_dc2} = file:open(filename:join(Dir, "sys2.config"), write),
+ ?line {ok, Fd_dc2} = file:open(filename:join(Dir, "sys2.config"), [write]),
?line (config_dc2(NodeNames))(Fd_dc2),
?line file:close(Fd_dc2),
?line Config2 = filename:join(Dir, "sys2"),
diff --git a/lib/kernel/test/application_SUITE_data/Makefile.src b/lib/kernel/test/application_SUITE_data/Makefile.src
index a237f6badb..abc3c82907 100644
--- a/lib/kernel/test/application_SUITE_data/Makefile.src
+++ b/lib/kernel/test/application_SUITE_data/Makefile.src
@@ -2,7 +2,8 @@ EFLAGS=+debug_info
all: app_start_error.@EMULATOR@ trans_abnormal_sup.@EMULATOR@ \
trans_normal_sup.@EMULATOR@ transient.@EMULATOR@ \
- group_leader_sup.@EMULATOR@ group_leader.@EMULATOR@
+ group_leader_sup.@EMULATOR@ group_leader.@EMULATOR@ \
+ deadlock/deadlock.@EMULATOR@
app_start_error.@EMULATOR@: app_start_error.erl
erlc $(EFLAGS) app_start_error.erl
@@ -22,3 +23,5 @@ group_leader.@EMULATOR@: group_leader.erl
group_leader_sup.@EMULATOR@: group_leader_sup.erl
erlc $(EFLAGS) group_leader_sup.erl
+deadlock/deadlock.@EMULATOR@: deadlock/deadlock.erl
+ erlc $(EFLAGS) -o deadlock deadlock/deadlock.erl \ No newline at end of file
diff --git a/lib/kernel/test/application_SUITE_data/deadlock/deadlock.app b/lib/kernel/test/application_SUITE_data/deadlock/deadlock.app
new file mode 100644
index 0000000000..0c1001bed6
--- /dev/null
+++ b/lib/kernel/test/application_SUITE_data/deadlock/deadlock.app
@@ -0,0 +1,8 @@
+{application, deadlock, [
+ {vsn, "1"},
+ {registered, []},
+ {applications, [kernel, stdlib, sasl]},
+ {modules, [deadlock]},
+ {mod, {deadlock, []}},
+ {env, [{fail_start, false}]}
+]}.
diff --git a/lib/kernel/test/application_SUITE_data/deadlock/deadlock.erl b/lib/kernel/test/application_SUITE_data/deadlock/deadlock.erl
new file mode 100644
index 0000000000..5f68bf9078
--- /dev/null
+++ b/lib/kernel/test/application_SUITE_data/deadlock/deadlock.erl
@@ -0,0 +1,69 @@
+-module(deadlock).
+-behaviour(application).
+-compile(export_all).
+-define(SUP,deadlock_sup).
+-define(CHILD,deadlock_child).
+
+
+%%%-----------------------------------------------------------------
+%%% application callbacks
+start(_StartType, _StartArgs) ->
+ supervisor:start_link({local, ?SUP}, ?MODULE, [sup]).
+
+stop(_State) ->
+ ok.
+
+
+
+%%%-----------------------------------------------------------------
+%%% supervisor callbacks
+init([sup]) ->
+ {ok, {{one_for_one, 5, 10}, [
+ {
+ sasl_syslog_dm, {?MODULE, start_link, []},
+ permanent, brutal_kill, worker,
+ [deadlock]
+ }
+ ]}};
+
+
+%%%-----------------------------------------------------------------
+%%% gen_server callbacks
+init([child]) ->
+ case application:get_env(deadlock, fail_start) of
+ {ok, false} ->
+ %% we must not fail on the first init, otherwise supervisor
+ %% terminates immediately
+ {ok, []};
+ {ok, true} ->
+ timer:sleep(infinity), % init hangs!!!!
+ {ok, []}
+ end.
+
+handle_call(_Req, _From, State) ->
+ {reply, ok, State}.
+
+handle_cast(restart, State) ->
+ {stop, error, State}.
+
+handle_info(_Msg, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+
+%%%-----------------------------------------------------------------
+%%% Start child
+start_link() ->
+ gen_server:start_link({local, ?CHILD}, ?MODULE, [child], []).
+
+
+%%%-----------------------------------------------------------------
+%%% Provoke hanging
+restart_and_fail() ->
+ application:set_env(deadlock, fail_start, true), % next init will hang
+ gen_server:cast(?CHILD, restart).
diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl
index 3ad49254f1..10ab3e4370 100644
--- a/lib/kernel/test/code_SUITE.erl
+++ b/lib/kernel/test/code_SUITE.erl
@@ -81,6 +81,13 @@ init_per_suite(Config) ->
end_per_suite(Config) ->
Config.
+init_per_testcase(big_boot_embedded, Config) ->
+ case catch crypto:start() of
+ ok ->
+ init_per_testcase(do_big_boot_embedded, Config);
+ _Else ->
+ {skip, "Needs crypto!"}
+ end;
init_per_testcase(_Func, Config) ->
Dog=?t:timetrap(?t:minutes(5)),
P=code:get_path(),
@@ -258,8 +265,8 @@ replace_path(Config) when is_list(Config) ->
%% Add a completly new application.
- NewAppName = "blurf_blarfer",
- ?line NewAppDir = filename:join(Cwd, NewAppName ++ "-6.33.1"),
+ NewAppName = 'blurf_blarfer',
+ ?line NewAppDir = filename:join(Cwd, atom_to_list(NewAppName) ++ "-6.33.1"),
?line ok = file:make_dir(NewAppDir),
?line true = code:replace_path(NewAppName, NewAppDir),
?line NewAppDir = code:lib_dir(NewAppName),
@@ -410,8 +417,10 @@ all_loaded_1() ->
?line Loaded2 = match_and_remove(Preloaded, Loaded1),
ObjExt = code:objfile_extension(),
- ?line [] = lists:filter(fun({Mod,AbsName}) when is_atom(Mod), is_list(AbsName) ->
- Mod =:= filename:basename(AbsName, ObjExt);
+ ?line [] = lists:filter(fun({Mod,AbsName}) when is_atom(Mod),
+ is_list(AbsName) ->
+ Mod =/= list_to_atom(filename:basename(AbsName,
+ ObjExt));
(_) -> true
end,
Loaded2),
@@ -571,11 +580,13 @@ add_del_path(Config) when is_list(Config) ->
clash(Config) when is_list(Config) ->
DDir = ?config(data_dir,Config)++"clash/",
P = code:get_path(),
+ [TestServerPath|_] = [Path || Path <- code:get_path(),
+ re:run(Path,"test_server/?$",[]) /= nomatch],
%% test non-clashing entries
- %% remove "." to prevent clash with test-server path
- ?line true = code:del_path("."),
+ %% remove TestServerPath to prevent clash with test-server path
+ ?line true = code:del_path(TestServerPath),
?line true = code:add_path(DDir++"foobar-0.1/ebin"),
?line true = code:add_path(DDir++"zork-0.8/ebin"),
test_server:capture_start(),
@@ -587,8 +598,8 @@ clash(Config) when is_list(Config) ->
%% test clashing entries
- %% remove "." to prevent clash with test-server path
- ?line true = code:del_path("."),
+ %% remove TestServerPath to prevent clash with test-server path
+ ?line true = code:del_path(TestServerPath),
?line true = code:add_path(DDir++"foobar-0.1/ebin"),
?line true = code:add_path(DDir++"foobar-0.1.ez/foobar-0.1/ebin"),
test_server:capture_start(),
@@ -601,9 +612,9 @@ clash(Config) when is_list(Config) ->
%% test "Bad path can't read"
- %% remove "." to prevent clash with test-server path
+ %% remove TestServerPath to prevent clash with test-server path
Priv = ?config(priv_dir, Config),
- ?line true = code:del_path("."),
+ ?line true = code:del_path(TestServerPath),
TmpEzFile = Priv++"foobar-0.tmp.ez",
?line {ok, _} = file:copy(DDir++"foobar-0.1.ez", TmpEzFile),
?line true = code:add_path(TmpEzFile++"/foobar-0.1/ebin"),
@@ -984,9 +995,9 @@ purge_stacktrace(Config) when is_list(Config) ->
error:function_clause ->
?line code:load_file(code_b_test),
?line case erlang:get_stacktrace() of
- [{?MODULE,_,[a]},
- {code_b_test,call,2},
- {?MODULE,purge_stacktrace,1}|_] ->
+ [{?MODULE,_,[a],_},
+ {code_b_test,call,2,_},
+ {?MODULE,purge_stacktrace,1,_}|_] ->
?line false = code:purge(code_b_test),
?line [] = erlang:get_stacktrace()
end
@@ -996,8 +1007,8 @@ purge_stacktrace(Config) when is_list(Config) ->
error:function_clause ->
?line code:load_file(code_b_test),
?line case erlang:get_stacktrace() of
- [{code_b_test,call,[nofun,2]},
- {?MODULE,purge_stacktrace,1}|_] ->
+ [{code_b_test,call,[nofun,2],_},
+ {?MODULE,purge_stacktrace,1,_}|_] ->
?line false = code:purge(code_b_test),
?line [] = erlang:get_stacktrace()
end
@@ -1008,8 +1019,8 @@ purge_stacktrace(Config) when is_list(Config) ->
error:badarg ->
?line code:load_file(code_b_test),
?line case erlang:get_stacktrace() of
- [{code_b_test,call,Args},
- {?MODULE,purge_stacktrace,1}|_] ->
+ [{code_b_test,call,Args,_},
+ {?MODULE,purge_stacktrace,1,_}|_] ->
?line false = code:purge(code_b_test),
?line [] = erlang:get_stacktrace()
end
@@ -1023,8 +1034,8 @@ mult_lib_roots(Config) when is_list(Config) ->
"my_dummy_app-c/ebin/code_SUITE_mult_root_module"),
%% Set up ERL_LIBS and start a slave node.
- ErlLibs = filename:join(DataDir, first_root) ++ mult_lib_sep() ++
- filename:join(DataDir, second_root),
+ ErlLibs = filename:join(DataDir, "first_root") ++ mult_lib_sep() ++
+ filename:join(DataDir, "second_root"),
?line {ok,Node} =
?t:start_node(mult_lib_roots, slave,
@@ -1344,7 +1355,7 @@ create_script(Config) ->
?line Apps = application_controller:which_applications(),
?line {value,{_,_,KernelVer}} = lists:keysearch(kernel, 1, Apps),
?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib, 1, Apps),
- ?line {ok,Fd} = file:open(Name ++ ".rel", write),
+ ?line {ok,Fd} = file:open(Name ++ ".rel", [write]),
?line io:format(Fd,
"{release, {\"Test release 3\", \"P2A\"}, \n"
" {erts, \"9.42\"}, \n"
@@ -1409,7 +1420,7 @@ create_big_script(Config,Local) ->
%% Now we should have only "real" applications...
?line [application:load(list_to_atom(Y)) || {match,[Y]} <- [ re:run(X,code:lib_dir()++"/"++"([^/-]*).*/ebin",[{capture,[1],list}]) || X <- code:get_path()],filter_app(Y,Local)],
?line Apps = [ {N,V} || {N,_,V} <- application:loaded_applications()],
- ?line {ok,Fd} = file:open(Name ++ ".rel", write),
+ ?line {ok,Fd} = file:open(Name ++ ".rel", [write]),
?line io:format(Fd,
"{release, {\"Test release 3\", \"P2A\"}, \n"
" {erts, \"9.42\"}, \n"
@@ -1470,7 +1481,7 @@ do_on_load_error(ReturnValue) ->
?line ErrorPid ! ReturnValue,
receive
{'DOWN',Ref,process,_,Exit} ->
- ?line {undef,[{on_load_error,main,[]}|_]} = Exit
+ ?line {undef,[{on_load_error,main,[],_}|_]} = Exit
end.
native_early_modules(suite) -> [];
diff --git a/lib/kernel/test/disk_log_SUITE.erl b/lib/kernel/test/disk_log_SUITE.erl
index 4ae47b4762..ad987fe7a7 100644
--- a/lib/kernel/test/disk_log_SUITE.erl
+++ b/lib/kernel/test/disk_log_SUITE.erl
@@ -1831,11 +1831,16 @@ block_queue2(Conf) when is_list(Conf) ->
%% Asynchronous stuff is ignored.
?line ok = disk_log:balog_terms(n, [<<"foo">>,<<"bar">>]),
?line ok = disk_log:balog_terms(n, [<<"more">>,<<"terms">>]),
+ Parent = self(),
?line Fun =
- fun() -> {error,disk_log_stopped} = disk_log:sync(n)
+ fun() ->
+ {error,no_such_log} = disk_log:sync(n),
+ receive {disk_log, _, {error, disk_log_stopped}} -> ok end,
+ Parent ! disk_log_stopped_ok
end,
?line spawn(Fun),
?line ok = sync_do(Pid, close),
+ ?line receive disk_log_stopped_ok -> ok end,
?line sync_do(Pid, terminate),
?line {ok,<<>>} = file:read_file(File ++ ".1"),
?line del(File, No),
@@ -2708,7 +2713,7 @@ error_log(Conf) when is_list(Conf) ->
% reopen (rename) fails, the log is terminated, ./File.2/ exists
?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
{format, external},{size, 100000}]),
- ?line {error, eisdir} = disk_log:reopen(n, LDir),
+ ?line {error, {file_error, _, eisdir}} = disk_log:reopen(n, LDir),
?line true = (P0 == pps()),
?line file:delete(File),
@@ -2719,7 +2724,7 @@ error_log(Conf) when is_list(Conf) ->
?line {ok, n} = disk_log:open([{name, n}, {file, File2}, {type, wrap},
{format, external},{size, {100, No}}]),
?line ok = disk_log:blog_terms(n, [B,B,B]),
- ?line {error, eisdir} = disk_log:reopen(n, File),
+ ?line {error, {file_error, _, eisdir}} = disk_log:reopen(n, File),
?line {error, no_such_log} = disk_log:close(n),
?line del(File2, No),
?line del(File, No),
@@ -4917,7 +4922,7 @@ mark(FileName, What) ->
ok = file:close(Fd).
crash(File, Where) ->
- {ok, Fd} = file:open(File, read_write),
+ {ok, Fd} = file:open(File, [read,write]),
file:position(Fd, Where),
ok = file:write(Fd, [10]),
ok = file:close(Fd).
@@ -4933,7 +4938,7 @@ writable(Fname) ->
file:write_file_info(Fname, Info#file_info{mode = Mode}).
truncate(File, Where) ->
- {ok, Fd} = file:open(File, read_write),
+ {ok, Fd} = file:open(File, [read,write]),
file:position(Fd, Where),
ok = file:truncate(Fd),
ok = file:close(Fd).
diff --git a/lib/kernel/test/erl_boot_server_SUITE.erl b/lib/kernel/test/erl_boot_server_SUITE.erl
index cea3715ce4..bb64c01058 100644
--- a/lib/kernel/test/erl_boot_server_SUITE.erl
+++ b/lib/kernel/test/erl_boot_server_SUITE.erl
@@ -346,7 +346,7 @@ good_hosts(_Config) ->
[GoodHost1, GoodHost2, GoodHost3].
open_udp() ->
- ?line {ok, S} = prim_inet:open(udp, inet),
+ ?line {ok, S} = prim_inet:open(udp, inet, dgram),
?line ok = prim_inet:setopts(S, [{mode,list},{active,true},
{deliver,term},{broadcast,true}]),
?line {ok,_} = prim_inet:bind(S, {0,0,0,0}, 0),
diff --git a/lib/kernel/test/erl_prim_loader_SUITE.erl b/lib/kernel/test/erl_prim_loader_SUITE.erl
index f47c4603cf..7599a89779 100644
--- a/lib/kernel/test/erl_prim_loader_SUITE.erl
+++ b/lib/kernel/test/erl_prim_loader_SUITE.erl
@@ -547,8 +547,6 @@ host() ->
stop_node(Node) ->
test_server:stop_node(Node).
-get_loader_flag({ose,_}) ->
- " -loader ose_inet ";
get_loader_flag(_) ->
" -loader inet ".
diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl
index fdab2eb02b..77fc7e73f9 100644
--- a/lib/kernel/test/file_SUITE.erl
+++ b/lib/kernel/test/file_SUITE.erl
@@ -2165,7 +2165,7 @@ write_compressed(Config) when is_list(Config) ->
?line Second = io:get_line(Fd1, ''),
?line ok = ?FILE_MODULE:close(Fd1),
- %% Verify succesful compression by uncompressing the file
+ %% Verify successful compression by uncompressing the file
%% using zlib:gunzip/1.
?line {ok,Contents} = file:read_file(MyFile),
diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl
index 03e734445c..300152ddce 100644
--- a/lib/kernel/test/gen_sctp_SUITE.erl
+++ b/lib/kernel/test/gen_sctp_SUITE.erl
@@ -30,33 +30,29 @@
-export(
[basic/1,
api_open_close/1,api_listen/1,api_connect_init/1,api_opts/1,
- xfer_min/1,xfer_active/1,def_sndrcvinfo/1,implicit_inet6/1]).
+ xfer_min/1,xfer_active/1,def_sndrcvinfo/1,implicit_inet6/1,
+ basic_stream/1, xfer_stream_min/1, peeloff/1, buffers/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[basic, api_open_close, api_listen, api_connect_init,
- api_opts, xfer_min, xfer_active, def_sndrcvinfo,
- implicit_inet6].
+ api_opts, xfer_min, xfer_active, def_sndrcvinfo, implicit_inet6,
+ basic_stream, xfer_stream_min, peeloff, buffers].
groups() ->
[].
-init_per_suite(Config) ->
- try gen_sctp:open() of
+init_per_suite(_Config) ->
+ case gen_sctp:open() of
{ok,Socket} ->
gen_sctp:close(Socket),
[];
- _ ->
- []
- catch
- error:badarg ->
- {skip,"SCTP not supported on this machine"};
- _:_ ->
- Config
+ {error,eprotonosupport} ->
+ {skip,"SCTP not supported on this machine"}
end.
-end_per_suite(_Conifig) ->
+end_per_suite(_Config) ->
ok.
init_per_group(_GroupName, Config) ->
@@ -96,7 +92,7 @@ xfer_min(Config) when is_list(Config) ->
?line Stream = 0,
?line Data = <<"The quick brown fox jumps over a lazy dog 0123456789">>,
?line Loopback = {127,0,0,1},
- ?line {ok,Sb} = gen_sctp:open(),
+ ?line {ok,Sb} = gen_sctp:open([{type,seqpacket}]),
?line {ok,Pb} = inet:port(Sb),
?line ok = gen_sctp:listen(Sb, true),
@@ -108,29 +104,44 @@ xfer_min(Config) when is_list(Config) ->
inbound_streams=SaInboundStreams,
assoc_id=SaAssocId}=SaAssocChange} =
gen_sctp:connect(Sa, Loopback, Pb, []),
- ?line {ok,{Loopback,
- Pa,[],
+ ?line {SbAssocId,SaOutboundStreams,SaInboundStreams} =
+ case recv_event(log_ok(gen_sctp:recv(Sb, infinity))) of
+ {Loopback,Pa,
#sctp_assoc_change{state=comm_up,
error=0,
outbound_streams=SbOutboundStreams,
inbound_streams=SbInboundStreams,
- assoc_id=SbAssocId}}} =
- gen_sctp:recv(Sb, infinity),
- ?line SaOutboundStreams = SbInboundStreams,
- ?line SbOutboundStreams = SaInboundStreams,
+ assoc_id=AssocId}} ->
+ {AssocId,SbInboundStreams,SbOutboundStreams};
+ {Loopback,Pa,
+ #sctp_paddr_change{state=addr_confirmed,
+ addr={Loopback,Pa},
+ error=0,
+ assoc_id=AssocId}} ->
+ {Loopback,Pa,
+ #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=SbOutboundStreams,
+ inbound_streams=SbInboundStreams,
+ assoc_id=AssocId}} =
+ ?line recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
+ {AssocId,SbInboundStreams,SbOutboundStreams}
+ end,
+
?line ok = gen_sctp:send(Sa, SaAssocId, 0, Data),
- ?line case gen_sctp:recv(Sb, infinity) of
- {ok,{Loopback,
- Pa,
- [#sctp_sndrcvinfo{stream=Stream,
- assoc_id=SbAssocId}],
- Data}} -> ok;
- {ok,{Loopback,
- Pa,[],
+ ?line case log_ok(gen_sctp:recv(Sb, infinity)) of
+ {Loopback,
+ Pa,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SbAssocId}],
+ Data} -> ok;
+ Event1 ->
+ {Loopback,Pa,
#sctp_paddr_change{addr = {Loopback,_},
state = addr_available,
error = 0,
- assoc_id = SbAssocId}}} ->
+ assoc_id = SbAssocId}} =
+ recv_event(Event1),
{ok,{Loopback,
Pa,
[#sctp_sndrcvinfo{stream=Stream,
@@ -138,30 +149,40 @@ xfer_min(Config) when is_list(Config) ->
Data}} = gen_sctp:recv(Sb, infinity)
end,
?line ok = gen_sctp:send(Sb, SbAssocId, 0, Data),
- ?line {ok,{Loopback,
- Pb,
+ ?line case log_ok(gen_sctp:recv(Sa, infinity)) of
+ {Loopback,Pb,
[#sctp_sndrcvinfo{stream=Stream,
assoc_id=SaAssocId}],
- Data}} =
- gen_sctp:recv(Sa, infinity),
+ Data} ->
+ ok;
+ Event2 ->
+ {Loopback,Pb,
+ #sctp_paddr_change{addr={_,Pb},
+ state=addr_confirmed,
+ error=0,
+ assoc_id=SaAssocId}} =
+ ?line recv_event(Event2),
+ ?line {Loopback,
+ Pb,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SaAssocId}],
+ Data} =
+ log_ok(gen_sctp:recv(Sa, infinity))
+ end,
%%
?line ok = gen_sctp:eof(Sa, SaAssocChange),
- ?line {ok,{Loopback,
- Pa,[],
- #sctp_shutdown_event{assoc_id=SbAssocId}}} =
- gen_sctp:recv(Sb, infinity),
- ?line {ok,{Loopback,
- Pb,[],
- #sctp_assoc_change{state=shutdown_comp,
- error=0,
- assoc_id=SaAssocId}}} =
- gen_sctp:recv(Sa, infinity),
- ?line {ok,{Loopback,
- Pa,[],
- #sctp_assoc_change{state=shutdown_comp,
- error=0,
- assoc_id=SbAssocId}}} =
- gen_sctp:recv(Sb, infinity),
+ ?line {Loopback,Pa,#sctp_shutdown_event{assoc_id=SbAssocId}} =
+ recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
+ ?line {Loopback,Pb,
+ #sctp_assoc_change{state=shutdown_comp,
+ error=0,
+ assoc_id=SaAssocId}} =
+ recv_event(log_ok(gen_sctp:recv(Sa, infinity))),
+ ?line {Loopback,Pa,
+ #sctp_assoc_change{state=shutdown_comp,
+ error=0,
+ assoc_id=SbAssocId}} =
+ recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
?line ok = gen_sctp:close(Sa),
?line ok = gen_sctp:close(Sb),
@@ -186,52 +207,62 @@ xfer_active(Config) when is_list(Config) ->
?line {ok,Sa} = gen_sctp:open([{active,true}]),
?line {ok,Pa} = inet:port(Sa),
- ?line {ok,#sctp_assoc_change{state=comm_up,
- error=0,
- outbound_streams=SaOutboundStreams,
- inbound_streams=SaInboundStreams,
- assoc_id=SaAssocId}=SaAssocChange} =
- gen_sctp:connect(Sa, Loopback, Pb, []),
+ ?line ok = gen_sctp:connect_init(Sa, Loopback, Pb, []),
+ ?line #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=SaOutboundStreams,
+ inbound_streams=SaInboundStreams,
+ assoc_id=SaAssocId} = SaAssocChange =
+ recv_assoc_change(Sa, Loopback, Pb, Timeout),
?line io:format("Sa=~p, Pa=~p, Sb=~p, Pb=~p, SaAssocId=~p, "
"SaOutboundStreams=~p, SaInboundStreams=~p~n",
[Sa,Pa,Sb,Pb,SaAssocId,
SaOutboundStreams,SaInboundStreams]),
- ?line SbAssocId =
- receive
- {sctp,Sb,Loopback,Pa,
- {[],
- #sctp_assoc_change{state=comm_up,
- error=0,
- outbound_streams=SbOutboundStreams,
- inbound_streams=SbInboundStreams,
- assoc_id=SBAI}}} ->
- ?line SaOutboundStreams = SbInboundStreams,
- ?line SaInboundStreams = SbOutboundStreams,
- SBAI
- after Timeout ->
- ?line test_server:fail({unexpected,flush()})
- end,
+ ?line #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=SbOutboundStreams,
+ inbound_streams=SbInboundStreams,
+ assoc_id=SbAssocId} =
+ recv_assoc_change(Sb, Loopback, Pa, Timeout),
+ ?line SbOutboundStreams = SaInboundStreams,
+ ?line SbInboundStreams = SaOutboundStreams,
?line io:format("SbAssocId=~p~n", [SbAssocId]),
- ?line ok = gen_sctp:send(Sa, SaAssocId, 0, Data),
+
+ ?line case recv_paddr_change(Sa, Loopback, Pb, 314) of
+ #sctp_paddr_change{state=addr_confirmed,
+ addr={_,Pb},
+ error=0,
+ assoc_id=SaAssocId} -> ok;
+ #sctp_paddr_change{state=addr_available,
+ addr={_,Pb},
+ error=0,
+ assoc_id=SaAssocId} -> ok;
+ timeout -> ok
+ end,
+ ?line case recv_paddr_change(Sb, Loopback, Pa, 314) of
+ #sctp_paddr_change{state=addr_confirmed,
+ addr={Loopback,Pa},
+ error=0,
+ assoc_id=SbAssocId} -> ok;
+ #sctp_paddr_change{state=addr_available,
+ addr={Loopback,P},
+ error=0,
+ assoc_id=SbAssocId} ->
+ ?line match_unless_solaris(Pa, P);
+ timeout -> ok
+ end,
+ ?line [] = flush(),
+
+ ?line ok =
+ do_from_other_process(
+ fun () -> gen_sctp:send(Sa, SaAssocId, 0, Data) end),
?line receive
{sctp,Sb,Loopback,Pa,
{[#sctp_sndrcvinfo{stream=Stream,
assoc_id=SbAssocId}],
- Data}} -> ok;
- {sctp,Sb,Loopback,Pa,
- {[],
- #sctp_paddr_change{addr = {Loopback,_},
- state = addr_available,
- error = 0,
- assoc_id = SbAssocId}}} ->
- ?line receive
- {sctp,Sb,Loopback,Pa,
- {[#sctp_sndrcvinfo{stream=Stream,
- assoc_id=SbAssocId}],
- Data}} -> ok
- end
+ Data}} -> ok
after Timeout ->
- ?line test_server:fail({unexpected,flush()})
+ ?line test_server:fail({timeout,flush()})
end,
?line ok = gen_sctp:send(Sb, SbAssocId, 0, Data),
?line receive
@@ -240,31 +271,28 @@ xfer_active(Config) when is_list(Config) ->
assoc_id=SaAssocId}],
Data}} -> ok
after Timeout ->
- ?line test_server:fail({unexpected,flush()})
+ ?line test_server:fail({timeout,flush()})
end,
%%
?line ok = gen_sctp:abort(Sa, SaAssocChange),
- ?line receive
- {sctp,Sb,Loopback,Pa,
- {[],
- #sctp_assoc_change{state=comm_lost,
- assoc_id=SbAssocId}}} -> ok
- after Timeout ->
- ?line test_server:fail({unexpected,flush()})
+ ?line case recv_assoc_change(Sb, Loopback, Pa, Timeout) of
+ #sctp_assoc_change{state=comm_lost,
+ assoc_id=SbAssocId} -> ok;
+ timeout ->
+ ?line test_server:fail({timeout,flush()})
end,
?line ok = gen_sctp:close(Sb),
+ ?line case recv_assoc_change(Sa, Loopback, Pb, Timeout) of
+ #sctp_assoc_change{state=comm_lost,
+ assoc_id=SaAssocId} -> ok;
+ timeout ->
+ ?line io:format("timeout waiting for comm_lost on Sa~n"),
+ ?line match_unless_solaris(ok, {timeout,flush()})
+ end,
?line receive
- {sctp,Sa,Loopback,Pb,
- {[],
- #sctp_assoc_change{state=comm_lost,
- assoc_id=SaAssocId}}} -> ok
- after Timeout ->
- ?line test_server:fail({unexpected,flush()})
- end,
- ?line receive
- {sctp_error,Sa,enotconn} -> ok % Solaris
- after 17 -> ok %% Only happens on Solaris
- end,
+ {sctp_error,Sa,enotconn} -> ok % Solaris
+ after 17 -> ok
+ end,
?line ok = gen_sctp:close(Sa),
%%
?line receive
@@ -273,6 +301,30 @@ xfer_active(Config) when is_list(Config) ->
end,
ok.
+recv_assoc_change(S, Addr, Port, Timeout) ->
+ receive
+ {sctp,S,Addr,Port,{[], #sctp_assoc_change{}=AssocChange}} ->
+ AssocChange;
+ {sctp,S,Addr,Port,
+ {[#sctp_sndrcvinfo{assoc_id=AssocId}],
+ #sctp_assoc_change{assoc_id=AssocId}=AssocChange}} ->
+ AssocChange
+ after Timeout ->
+ timeout
+ end.
+
+recv_paddr_change(S, Addr, Port, Timeout) ->
+ receive
+ {sctp,S,Addr,Port,{[], #sctp_paddr_change{}=PaddrChange}} ->
+ PaddrChange;
+ {sctp,S,Addr,Port,
+ {[#sctp_sndrcvinfo{assoc_id=AssocId}],
+ #sctp_paddr_change{assoc_id=AssocId}=PaddrChange}} ->
+ PaddrChange
+ after Timeout ->
+ timeout
+ end.
+
def_sndrcvinfo(doc) ->
"Test that #sctp_sndrcvinfo{} parameters set on a socket "
"are used by gen_sctp:send/4";
@@ -283,11 +335,11 @@ def_sndrcvinfo(Config) when is_list(Config) ->
?line Data = <<"What goes up, must come down.">>,
%%
?line S1 =
- ok(gen_sctp:open(
+ log_ok(gen_sctp:open(
0, [{sctp_default_send_param,#sctp_sndrcvinfo{ppid=17}}])),
?LOGVAR(S1),
?line P1 =
- ok(inet:port(S1)),
+ log_ok(inet:port(S1)),
?LOGVAR(P1),
?line #sctp_sndrcvinfo{ppid=17, context=0, timetolive=0, assoc_id=0} =
getopt(S1, sctp_default_send_param),
@@ -295,10 +347,10 @@ def_sndrcvinfo(Config) when is_list(Config) ->
gen_sctp:listen(S1, true),
%%
?line S2 =
- ok(gen_sctp:open()),
+ log_ok(gen_sctp:open()),
?LOGVAR(S2),
?line P2 =
- ok(inet:port(S2)),
+ log_ok(inet:port(S2)),
?LOGVAR(P2),
?line #sctp_sndrcvinfo{ppid=0, context=0, timetolive=0, assoc_id=0} =
getopt(S2, sctp_default_send_param),
@@ -307,32 +359,57 @@ def_sndrcvinfo(Config) when is_list(Config) ->
state=comm_up,
error=0,
assoc_id=S2AssocId} = S2AssocChange =
- ok(gen_sctp:connect(S2, Loopback, P1, [])),
+ log_ok(gen_sctp:connect(S2, Loopback, P1, [])),
?LOGVAR(S2AssocChange),
- ?line case ok(gen_sctp:recv(S1)) of
- {Loopback, P2,[],
+ ?line case recv_event(log_ok(gen_sctp:recv(S1))) of
+ {Loopback,P2,
#sctp_assoc_change{
+ state=comm_up,
+ error=0,
+ assoc_id=S1AssocId}} ->
+ ?LOGVAR(S1AssocId);
+ {Loopback,P2,
+ #sctp_paddr_change{
+ state=addr_confirmed,
+ error=0,
+ assoc_id=S1AssocId}} ->
+ ?LOGVAR(S1AssocId),
+ {Loopback,P2,
+ #sctp_assoc_change{
state=comm_up,
error=0,
- assoc_id=S1AssocId}} ->
- ?LOGVAR(S1AssocId)
+ assoc_id=S1AssocId}} =
+ recv_event(log_ok(gen_sctp:recv(S1)))
end,
+
?line #sctp_sndrcvinfo{
- ppid=17, context=0, timetolive=0, assoc_id=S1AssocId} =
+ ppid=17, context=0, timetolive=0} = %, assoc_id=S1AssocId} =
getopt(
S1, sctp_default_send_param, #sctp_sndrcvinfo{assoc_id=S1AssocId}),
?line #sctp_sndrcvinfo{
- ppid=0, context=0, timetolive=0, assoc_id=S2AssocId} =
+ ppid=0, context=0, timetolive=0} = %, assoc_id=S2AssocId} =
getopt(
S2, sctp_default_send_param, #sctp_sndrcvinfo{assoc_id=S2AssocId}),
%%
?line ok =
gen_sctp:send(S1, S1AssocId, 1, <<"1: ",Data/binary>>),
- ?line case ok(gen_sctp:recv(S2)) of
+ ?line case log_ok(gen_sctp:recv(S2)) of
{Loopback,P1,
[#sctp_sndrcvinfo{
stream=1, ppid=17, context=0, assoc_id=S2AssocId}],
- <<"1: ",Data/binary>>} -> ok
+ <<"1: ",Data/binary>>} -> ok;
+ Event1 ->
+ ?line {Loopback,P1,
+ #sctp_paddr_change{state=addr_confirmed,
+ addr={_,P1},
+ error=0,
+ assoc_id=S2AssocId}} =
+ recv_event(Event1),
+ ?line {Loopback,P1,
+ [#sctp_sndrcvinfo{
+ stream=1, ppid=17, context=0, assoc_id=S2AssocId}],
+ <<"1: ",Data/binary>>} =
+ log_ok(gen_sctp:recv(S2))
end,
%%
?line ok =
@@ -352,7 +429,7 @@ def_sndrcvinfo(Config) when is_list(Config) ->
%%
?line ok =
gen_sctp:send(S1, S1AssocId, 0, <<"2: ",Data/binary>>),
- ?line case ok(gen_sctp:recv(S2)) of
+ ?line case log_ok(gen_sctp:recv(S2)) of
{Loopback,P1,
[#sctp_sndrcvinfo{
stream=0, ppid=19, context=0, assoc_id=S2AssocId}],
@@ -360,16 +437,18 @@ def_sndrcvinfo(Config) when is_list(Config) ->
end,
?line ok =
gen_sctp:send(S2, S2AssocChange, 1, <<"3: ",Data/binary>>),
- ?line case ok(gen_sctp:recv(S1)) of
+ ?line case log_ok(gen_sctp:recv(S1)) of
{Loopback,P2,
[#sctp_sndrcvinfo{
stream=1, ppid=0, context=0, assoc_id=S1AssocId}],
<<"3: ",Data/binary>>} -> ok;
- {Loopback,P2,[],
- #sctp_paddr_change{
- addr={Loopback,_}, state=addr_available,
- error=0, assoc_id=S1AssocId}} ->
- ?line case ok(gen_sctp:recv(S1)) of
+ Event2 ->
+ {Loopback,P2,
+ #sctp_paddr_change{
+ addr={Loopback,_}, state=addr_available,
+ error=0, assoc_id=S1AssocId}} =
+ recv_event(Event2),
+ ?line case log_ok(gen_sctp:recv(S1)) of
{Loopback,P2,
[#sctp_sndrcvinfo{
stream=1, ppid=0, context=0,
@@ -378,11 +457,14 @@ def_sndrcvinfo(Config) when is_list(Config) ->
end
end,
?line ok =
- gen_sctp:send(
- S2,
- #sctp_sndrcvinfo{stream=0, ppid=20, assoc_id=S2AssocId},
- <<"4: ",Data/binary>>),
- ?line case ok(gen_sctp:recv(S1)) of
+ do_from_other_process(
+ fun () ->
+ gen_sctp:send(
+ S2,
+ #sctp_sndrcvinfo{stream=0, ppid=20, assoc_id=S2AssocId},
+ <<"4: ",Data/binary>>)
+ end),
+ ?line case log_ok(do_from_other_process(fun() -> gen_sctp:recv(S1) end)) of
{Loopback,P2,
[#sctp_sndrcvinfo{
stream=0, ppid=20, context=0, assoc_id=S1AssocId}],
@@ -411,8 +493,12 @@ getopt(S, Opt, Param) ->
setopt(S, Opt, Val) ->
inet:setopts(S, [{Opt,Val}]).
-ok({ok,X}) ->
- io:format("OK: ~p~n", [X]),
+log_ok(X) -> log(ok(X)).
+
+ok({ok,X}) -> X.
+
+log(X) ->
+ io:format("LOG[~w]: ~p~n", [self(),X]),
X.
flush() ->
@@ -515,7 +601,10 @@ api_listen(Config) when is_list(Config) ->
#sctp_assoc_change{
state=comm_lost}}} =
gen_sctp:recv(Sa, infinity);
- {error,#sctp_assoc_change{state=cant_assoc}} -> ok
+ {error,#sctp_assoc_change{state=cant_assoc}} ->
+ ok%;
+ %% {error,{Localhost,Pb,_,#sctp_assoc_change{state=cant_assoc}}} ->
+ %% ok
end,
?line ok = gen_sctp:listen(Sb, true),
?line {ok,#sctp_assoc_change{state=comm_up,
@@ -547,34 +636,48 @@ api_connect_init(Config) when is_list(Config) ->
?line {ok,Sa} = gen_sctp:open(),
?line case gen_sctp:connect_init(Sa, localhost, Pb, []) of
{error,econnrefused} ->
- ?line {ok,{Localhost,
- Pb,[],
- #sctp_assoc_change{state=comm_lost}}} =
- gen_sctp:recv(Sa, infinity);
+ ?line {Localhost,Pb,#sctp_assoc_change{state=comm_lost}} =
+ recv_event(log_ok(gen_sctp:recv(Sa, infinity)));
ok ->
- ?line {ok,{Localhost,
- Pb,[],
- #sctp_assoc_change{state=cant_assoc}}} =
- gen_sctp:recv(Sa, infinity)
+ ?line {Localhost,Pb,#sctp_assoc_change{state=cant_assoc}} =
+ recv_event(log_ok(gen_sctp:recv(Sa, infinity)))
end,
?line ok = gen_sctp:listen(Sb, true),
?line case gen_sctp:connect_init(Sa, localhost, Pb, []) of
ok ->
- ?line {ok,{Localhost,
- Pb,[],
- #sctp_assoc_change{
- state = comm_up}}} =
- gen_sctp:recv(Sa, infinity)
+ ?line {Localhost,Pb,#sctp_assoc_change{state=comm_up}} =
+ recv_event(log_ok(gen_sctp:recv(Sa, infinity)))
end,
?line ok = gen_sctp:close(Sa),
?line ok = gen_sctp:close(Sb),
ok.
+recv_event({Addr,Port,[],#sctp_assoc_change{}=AssocChange}) ->
+ {Addr,Port,AssocChange};
+recv_event({Addr,Port,
+ [#sctp_sndrcvinfo{assoc_id=Assoc}],
+ #sctp_assoc_change{assoc_id=Assoc}=AssocChange}) ->
+ {Addr,Port,AssocChange};
+recv_event({Addr,Port,[],#sctp_paddr_change{}=PaddrChange}) ->
+ {Addr,Port,PaddrChange};
+recv_event({Addr,Port,
+ [#sctp_sndrcvinfo{assoc_id=Assoc}],
+ #sctp_paddr_change{assoc_id=Assoc}=PaddrChange}) ->
+ {Addr,Port,PaddrChange};
+recv_event({Addr,Port,[],#sctp_shutdown_event{}=ShutdownEvent}) ->
+ {Addr,Port,ShutdownEvent};
+recv_event({Addr,Port,
+ [#sctp_sndrcvinfo{assoc_id=Assoc}],
+ #sctp_shutdown_event{assoc_id=Assoc}=ShutdownEvent}) ->
+ {Addr,Port,ShutdownEvent}.
+
api_opts(doc) ->
"Test socket options";
api_opts(suite) ->
[];
api_opts(Config) when is_list(Config) ->
+ ?line Sndbuf = 32768,
+ ?line Recbuf = 65536,
?line {ok,S} = gen_sctp:open(0),
?line OSType = os:type(),
?line case {inet:setopts(S, [{linger,{true,2}}]),OSType} of
@@ -582,10 +685,18 @@ api_opts(Config) when is_list(Config) ->
ok;
{{error,einval},{unix,sunos}} ->
ok
- end.
+ end,
+ ?line ok = inet:setopts(S, [{sndbuf,Sndbuf}]),
+ ?line ok = inet:setopts(S, [{recbuf,Recbuf}]),
+ ?line case inet:getopts(S, [sndbuf]) of
+ {ok,[{sndbuf,SB}]} when SB >= Sndbuf -> ok
+ end,
+ ?line case inet:getopts(S, [recbuf]) of
+ {ok,[{recbuf,RB}]} when RB >= Recbuf -> ok
+ end.
implicit_inet6(Config) when is_list(Config) ->
- ?line Hostname = ok(inet:gethostname()),
+ ?line Hostname = log_ok(inet:gethostname()),
?line
case gen_sctp:open(0, [inet6]) of
{ok,S1} ->
@@ -598,16 +709,16 @@ implicit_inet6(Config) when is_list(Config) ->
?line ok = gen_sctp:close(S1),
%%
?line Localhost =
- ok(inet:getaddr("localhost", inet6)),
+ log_ok(inet:getaddr("localhost", inet6)),
?line io:format("~s ~p~n", ["localhost",Localhost]),
?line S2 =
- ok(gen_sctp:open(0, [{ip,Localhost}])),
+ log_ok(gen_sctp:open(0, [{ip,Localhost}])),
?line implicit_inet6(S2, Localhost),
?line ok = gen_sctp:close(S2),
%%
?line io:format("~s ~p~n", [Hostname,Host]),
?line S3 =
- ok(gen_sctp:open(0, [{ifaddr,Host}])),
+ log_ok(gen_sctp:open(0, [{ifaddr,Host}])),
?line implicit_inet6(S3, Host),
?line ok = gen_sctp:close(S1);
{error,eafnosupport} ->
@@ -620,21 +731,599 @@ implicit_inet6(Config) when is_list(Config) ->
implicit_inet6(S1, Addr) ->
?line ok = gen_sctp:listen(S1, true),
- ?line P1 = ok(inet:port(S1)),
- ?line S2 = ok(gen_sctp:open(0, [inet6])),
- ?line P2 = ok(inet:port(S2)),
+ ?line P1 = log_ok(inet:port(S1)),
+ ?line S2 = log_ok(gen_sctp:open(0, [inet6])),
+ ?line P2 = log_ok(inet:port(S2)),
?line #sctp_assoc_change{state=comm_up} =
- ok(gen_sctp:connect(S2, Addr, P1, [])),
- ?line case ok(gen_sctp:recv(S1)) of
- {Addr,P2,[],#sctp_assoc_change{state=comm_up}} ->
- ok
+ log_ok(gen_sctp:connect(S2, Addr, P1, [])),
+ ?line case recv_event(log_ok(gen_sctp:recv(S1))) of
+ {Addr,P2,#sctp_assoc_change{state=comm_up}} ->
+ ok;
+ {Addr,P2,#sctp_paddr_change{state=addr_confirmed,
+ addr={Addr,P2},
+ error=0}} ->
+ {Addr,P2,#sctp_assoc_change{state=comm_up}} =
+ recv_event(log_ok(gen_sctp:recv(S1)))
end,
- ?line case ok(inet:sockname(S1)) of
+ ?line case log_ok(inet:sockname(S1)) of
{Addr,P1} -> ok;
{{0,0,0,0,0,0,0,0},P1} -> ok
end,
- ?line case ok(inet:sockname(S2)) of
+ ?line case log_ok(inet:sockname(S2)) of
{Addr,P2} -> ok;
{{0,0,0,0,0,0,0,0},P2} -> ok
end,
?line ok = gen_sctp:close(S2).
+
+basic_stream(doc) ->
+ "Hello world stream socket";
+basic_stream(suite) ->
+ [];
+basic_stream(Config) when is_list(Config) ->
+ ?line {ok,S} = gen_sctp:open([{type,stream}]),
+ ?line ok = gen_sctp:listen(S, true),
+ ?line ok =
+ do_from_other_process(
+ fun () -> gen_sctp:listen(S, 10) end),
+ ?line ok = gen_sctp:close(S),
+ ok.
+
+xfer_stream_min(doc) ->
+ "Minimal data transfer";
+xfer_stream_min(suite) ->
+ [];
+xfer_stream_min(Config) when is_list(Config) ->
+ ?line Stream = 0,
+ ?line Data = <<"The quick brown fox jumps over a lazy dog 0123456789">>,
+ ?line Loopback = {127,0,0,1},
+ ?line {ok,Sb} = gen_sctp:open([{type,seqpacket}]),
+ ?line ?LOGVAR(Sb),
+ ?line {ok,Pb} = inet:port(Sb),
+ ?line ?LOGVAR(Pb),
+ ?line ok = gen_sctp:listen(Sb, true),
+
+ ?line {ok,Sa} = gen_sctp:open([{type,stream}]),
+ ?line ?LOGVAR(Sa),
+ ?line {ok,Pa} = inet:port(Sa),
+ ?line ?LOGVAR(Pa),
+ ?line #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=SaOutboundStreams,
+ inbound_streams=SaInboundStreams,
+ assoc_id=SaAssocId_X} =
+ log_ok(gen_sctp:connect(Sa, Loopback, Pb, [])),
+ ?line ?LOGVAR(SaAssocId_X),
+ ?line [{_,#sctp_paddrinfo{assoc_id=SaAssocId,state=active}}] =
+ log_ok(inet:getopts(Sa, [{sctp_get_peer_addr_info,
+ #sctp_paddrinfo{address={Loopback,Pb}}}])),
+ ?line ?LOGVAR(SaAssocId),
+ ?line match_unless_solaris(SaAssocId_X, SaAssocId),
+
+ ?line {SbOutboundStreams,SbInboundStreams,SbAssocId} =
+ case recv_event(log_ok(gen_sctp:recv(Sb, infinity))) of
+ {Loopback,Pa,
+ #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=OS,
+ inbound_streams=IS,
+ assoc_id=AI}} ->
+ {OS,IS,AI};
+ {Loopback,Pa,
+ #sctp_paddr_change{state=addr_confirmed,
+ addr={Loopback,Pa},
+ error=0,
+ assoc_id=AI}} ->
+ {Loopback,Pa,
+ ?line #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=OS,
+ inbound_streams=IS,
+ assoc_id=AI}} =
+ recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
+ {OS,IS,AI}
+ end,
+ ?line ?LOGVAR(SbAssocId),
+ ?line SaOutboundStreams = SbInboundStreams,
+ ?line ?LOGVAR(SaOutboundStreams),
+ ?line SbOutboundStreams = SaInboundStreams,
+ ?line ?LOGVAR(SbOutboundStreams),
+ ?line ok = gen_sctp:send(Sa, SaAssocId, 0, Data),
+ ?line case gen_sctp:recv(Sb, infinity) of
+ {ok,{Loopback,
+ Pa,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SbAssocId}],
+ Data}} -> ok;
+ {ok,{Loopback,
+ Pa,[],
+ #sctp_paddr_change{addr = {Loopback,_},
+ state = addr_available,
+ error = 0,
+ assoc_id = SbAssocId}}} ->
+ {ok,{Loopback,
+ Pa,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SbAssocId}],
+ Data}} = gen_sctp:recv(Sb, infinity)
+ end,
+ ?line ok =
+ do_from_other_process(
+ fun () -> gen_sctp:send(Sb, SbAssocId, 0, Data) end),
+ ?line case log_ok(gen_sctp:recv(Sa, infinity)) of
+ {Loopback,Pb,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SaAssocId}],
+ Data} -> ok;
+ Event1 ->
+ ?line {Loopback,Pb,
+ #sctp_paddr_change{state=addr_confirmed,
+ addr={_,Pb},
+ error=0,
+ assoc_id=SaAssocId}} =
+ recv_event(Event1),
+ ?line {Loopback,Pb,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SaAssocId}],
+ Data} =
+ log_ok(gen_sctp:recv(Sa, infinity))
+ end,
+ ?line ok = gen_sctp:close(Sa),
+ ?line {Loopback,Pa,
+ #sctp_shutdown_event{assoc_id=SbAssocId}} =
+ recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
+ ?line {Loopback,Pa,
+ #sctp_assoc_change{state=shutdown_comp,
+ error=0,
+ assoc_id=SbAssocId}} =
+ recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
+ ?line ok = gen_sctp:close(Sb),
+
+ ?line receive
+ Msg -> test_server:fail({received,Msg})
+ after 17 -> ok
+ end,
+ ok.
+
+
+
+do_from_other_process(Fun) ->
+ Parent = self(),
+ Ref = make_ref(),
+ Child =
+ spawn(fun () ->
+ try Fun() of
+ Result ->
+ Parent ! {Ref,Result}
+ catch
+ Class:Reason ->
+ Stacktrace = erlang:get_stacktrace(),
+ Parent ! {Ref,Class,Reason,Stacktrace}
+ end
+ end),
+ Mref = erlang:monitor(process, Child),
+ receive
+ {Ref,Result} ->
+ receive {'DOWN',Mref,_,_,_} -> Result end;
+ {Ref,Class,Reason,Stacktrace} ->
+ receive {'DOWN',Mref,_,_,_} ->
+ erlang:raise(Class, Reason, Stacktrace)
+ end;
+ {'DOWN',Mref,_,_,Reason} ->
+ erlang:exit(Reason)
+ end.
+
+
+
+peeloff(doc) ->
+ "Peel off an SCTP stream socket";
+peeloff(suite) ->
+ [];
+peeloff(Config) when is_list(Config) ->
+ ?line Addr = {127,0,0,1},
+ ?line Stream = 0,
+ ?line Timeout = 333,
+ ?line S1 = socket_open([{ifaddr,Addr}], Timeout),
+ ?line ?LOGVAR(S1),
+ ?line P1 = socket_call(S1, get_port),
+ ?line ?LOGVAR(P1),
+ ?line Socket1 = socket_call(S1, get_socket),
+ ?line ?LOGVAR(Socket1),
+ ?line socket_call(S1, {listen,true}),
+ ?line S2 = socket_open([{ifaddr,Addr}], Timeout),
+ ?line ?LOGVAR(S2),
+ ?line P2 = socket_call(S2, get_port),
+ ?line ?LOGVAR(P2),
+ ?line Socket2 = socket_call(S2, get_socket),
+ ?line ?LOGVAR(Socket2),
+ %%
+ ?line socket_call(S2, {connect_init,Addr,P1,[]}),
+ ?line S2Ai =
+ receive
+ {S2,{Addr,P1,
+ #sctp_assoc_change{
+ state=comm_up,
+ assoc_id=AssocId2}}} -> AssocId2
+ after Timeout ->
+ socket_bailout([S1,S2])
+ end,
+ ?line ?LOGVAR(S2Ai),
+ ?line S1Ai =
+ receive
+ {S1,{Addr,P2,
+ #sctp_assoc_change{
+ state=comm_up,
+ assoc_id=AssocId1}}} -> AssocId1
+ after Timeout ->
+ socket_bailout([S1,S2])
+ end,
+ ?line ?LOGVAR(S1Ai),
+ %%
+ ?line socket_call(S2, {send,S2Ai,Stream,<<"Number one">>}),
+ ?line
+ receive
+ {S1,{Addr,P2,S1Ai,Stream,<<"Number one">>}} -> ok
+ after Timeout ->
+ socket_bailout([S1,S2])
+ end,
+ ?line socket_call(S2, {send,Socket1,S1Ai,Stream,<<"Number two">>}),
+ ?line
+ receive
+ {S2,{Addr,P1,S2Ai,Stream,<<"Number two">>}} -> ok
+ after Timeout ->
+ socket_bailout([S1,S2])
+ end,
+ %%
+ ?line S3 = socket_peeloff(Socket1, S1Ai, Timeout),
+ ?line ?LOGVAR(S3),
+ ?line P3_X = socket_call(S3, get_port),
+ ?line ?LOGVAR(P3_X),
+ ?line P3 = case P3_X of 0 -> P1; _ -> P3_X end,
+ ?line [{_,#sctp_paddrinfo{assoc_id=S3Ai,state=active}}] =
+ socket_call(S3,
+ {getopts,[{sctp_get_peer_addr_info,
+ #sctp_paddrinfo{address={Addr,P2}}}]}),
+ %%?line S3Ai = S1Ai,
+ ?line ?LOGVAR(S3Ai),
+ %%
+ ?line socket_call(S3, {send,S3Ai,Stream,<<"Number three">>}),
+ ?line
+ receive
+ {S2,{Addr,P3,S2Ai,Stream,<<"Number three">>}} -> ok
+ after Timeout ->
+ socket_bailout([S1,S2,S3])
+ end,
+ ?line socket_call(S3, {send,Socket2,S2Ai,Stream,<<"Number four">>}),
+ ?line
+ receive
+ {S3,{Addr,P2,S3Ai,Stream,<<"Number four">>}} -> ok
+ after Timeout ->
+ socket_bailout([S1,S2,S3])
+ end,
+ %%
+ ?line inet:i(sctp),
+ ?line socket_close_verbose(S1),
+ ?line socket_close_verbose(S2),
+ ?line
+ receive
+ {S3,{Addr,P2,#sctp_shutdown_event{assoc_id=S3Ai_X}}} ->
+ ?line match_unless_solaris(S3Ai, S3Ai_X)
+ after Timeout ->
+ socket_bailout([S3])
+ end,
+ ?line
+ receive
+ {S3,{Addr,P2,#sctp_assoc_change{state=shutdown_comp,
+ assoc_id=S3Ai}}} -> ok
+ after Timeout ->
+ socket_bailout([S3])
+ end,
+ ?line socket_close_verbose(S3),
+ ?line [] = flush(),
+ ok.
+
+
+
+buffers(doc) ->
+ ["Check sndbuf and recbuf behaviour"];
+buffers(suite) ->
+ [];
+buffers(Config) when is_list(Config) ->
+ ?line Limit = 4096,
+ ?line Addr = {127,0,0,1},
+ ?line Stream = 1,
+ ?line Timeout = 3333,
+ ?line S1 = socket_open([{ip,Addr}], Timeout),
+ ?line ?LOGVAR(S1),
+ ?line P1 = socket_call(S1, get_port),
+ ?line ?LOGVAR(P1),
+ ?line ok = socket_call(S1, {listen,true}),
+ ?line S2 = socket_open([{ip,Addr}], Timeout),
+ ?line ?LOGVAR(S2),
+ ?line P2 = socket_call(S2, get_port),
+ ?line ?LOGVAR(P2),
+ %%
+ ?line socket_call(S2, {connect_init,Addr,P1,[]}),
+ ?line S2Ai =
+ receive
+ {S2,{Addr,P1,
+ #sctp_assoc_change{
+ state=comm_up,
+ assoc_id=AssocId2}}} -> AssocId2
+ after Timeout ->
+ socket_bailout([S1,S2])
+ end,
+ ?line S1Ai =
+ receive
+ {S1,{Addr,P2,
+ #sctp_assoc_change{
+ state=comm_up,
+ assoc_id=AssocId1}}} -> AssocId1
+ after Timeout ->
+ socket_bailout([S1,S2])
+ end,
+ %%
+ ?line socket_call(S1, {setopts,[{recbuf,Limit}]}),
+ ?line Recbuf =
+ case socket_call(S1, {getopts,[recbuf]}) of
+ [{recbuf,RB1}] when RB1 >= Limit -> RB1
+ end,
+ ?line Data = mk_data(Recbuf+Limit),
+ ?line socket_call(S2, {setopts,[{sndbuf,Recbuf+Limit}]}),
+ ?line socket_call(S2, {send,S2Ai,Stream,Data}),
+ ?line
+ receive
+ {S1,{Addr,P2,S1Ai,Stream,Data}} -> ok
+ after Timeout ->
+ socket_bailout([S1,S2])
+ end,
+ %%
+ ?line socket_close_verbose(S1),
+ ?line
+ receive
+ {S2,{Addr,P1,#sctp_shutdown_event{assoc_id=S2Ai}}} -> ok
+ after Timeout ->
+ socket_bailout([S2])
+ end,
+ ?line
+ receive
+ {S2,{Addr,P1,#sctp_assoc_change{state=shutdown_comp,
+ assoc_id=S2Ai}}} -> ok
+ after Timeout ->
+ socket_bailout([S2])
+ end,
+ ?line socket_close_verbose(S2),
+ ?line [] = flush(),
+ ok.
+
+mk_data(Bytes) ->
+ mk_data(0, Bytes, <<>>).
+%%
+mk_data(N, Bytes, Bin) when N < Bytes ->
+ mk_data(N+4, Bytes, <<Bin/binary,N:32>>);
+mk_data(_, _, Bin) ->
+ Bin.
+
+%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%% socket gen_server ultra light
+
+socket_open(SocketOpts, Timeout) ->
+ Opts = [{type,seqpacket},{active,once},binary|SocketOpts],
+ Starter =
+ fun () ->
+ {ok,Socket} =
+ gen_sctp:open(Opts),
+ Socket
+ end,
+ s_start(Starter, Timeout).
+
+socket_peeloff(Socket, AssocId, Timeout) ->
+ Opts = [{active,once},binary],
+ Starter =
+ fun () ->
+ {ok,NewSocket} =
+ gen_sctp:peeloff(Socket, AssocId),
+ ok = inet:setopts(NewSocket, Opts),
+ NewSocket
+ end,
+ s_start(Starter, Timeout).
+
+socket_close_verbose(S) ->
+ History = socket_history(socket_close(S)),
+ io:format("socket_close ~p:~n ~p.~n", [S,History]),
+ History.
+
+socket_close(S) ->
+ s_req(S, close).
+
+socket_call(S, Request) ->
+ s_req(S, {Request}).
+
+%% socket_get(S, Key) ->
+%% s_req(S, {get,Key}).
+
+socket_bailout([S|Ss]) ->
+ History = socket_history(socket_close(S)),
+ io:format("bailout ~p:~n ~p.~n", [S,History]),
+ socket_bailout(Ss);
+socket_bailout([]) ->
+ io:format("flush: ~p.~n", [flush()]),
+ test_server:fail(socket_bailout).
+
+socket_history({State,Flush}) ->
+ {lists:keysort(
+ 2,
+ lists:flatten(
+ [[{Key,Val} || Val <- Vals]
+ || {Key,Vals} <- gb_trees:to_list(State)])),
+ Flush}.
+
+s_handler(Socket) ->
+ fun ({listen,Listen}) ->
+ ok = gen_sctp:listen(Socket, Listen);
+ (get_port) ->
+ ok(inet:port(Socket));
+ (get_socket) ->
+ Socket;
+ ({connect_init,ConAddr,ConPort,ConOpts}) ->
+ ok = gen_sctp:connect_init(Socket, ConAddr, ConPort, ConOpts);
+ ({send,AssocId,Stream,Data}) ->
+ ok = gen_sctp:send(Socket, AssocId, Stream, Data);
+ ({send,OtherSocket,AssocId,Stream,Data}) ->
+ ok = gen_sctp:send(OtherSocket, AssocId, Stream, Data);
+ ({setopts,Opts}) ->
+ ok = inet:setopts(Socket, Opts);
+ ({getopts,Optnames}) ->
+ ok(inet:getopts(Socket, Optnames))
+ end.
+
+s_req(S, Req) ->
+ Mref = erlang:monitor(process, S),
+ S ! {self(),Mref,Req},
+ receive
+ {'DOWN',Mref,_,_,Error} ->
+ exit(Error);
+ {S,Mref,Reply} ->
+ erlang:demonitor(Mref),
+ receive {'DOWN',Mref,_,_,_} -> ok after 0 -> ok end,
+ Reply
+ end.
+
+s_start(Starter, Timeout) ->
+ Parent = self(),
+ Owner =
+ spawn_link(
+ fun () ->
+ s_start(Starter(), Timeout, Parent)
+ end),
+ Owner.
+
+s_start(Socket, Timeout, Parent) ->
+ Handler = s_handler(Socket),
+ try
+ s_loop(Socket, Timeout, Parent, Handler, gb_trees:empty())
+ catch
+ Class:Reason ->
+ Stacktrace = erlang:get_stacktrace(),
+ io:format(?MODULE_STRING":socket exception ~w:~w at~n"
+ "~p.~n", [Class,Reason,Stacktrace]),
+ erlang:raise(Class, Reason, Stacktrace)
+ end.
+
+s_loop(Socket, Timeout, Parent, Handler, State) ->
+ receive
+ {Parent,Ref,close} -> % socket_close()
+ erlang:send_after(Timeout, self(), {Parent,Ref,exit}),
+ s_loop(Socket, Timeout, Parent, Handler, State);
+ {Parent,Ref,exit} ->
+ ok = gen_sctp:close(Socket),
+ Key = exit,
+ Val = {now(),Socket},
+ NewState = gb_push(Key, Val, State),
+ Parent ! {self(),Ref,{NewState,flush()}};
+ {Parent,Ref,{Msg}} ->
+ Result = Handler(Msg),
+ Key = req,
+ Val = {now(),{Msg,Result}},
+ NewState = gb_push(Key, Val, State),
+ Parent ! {self(),Ref,Result},
+ s_loop(Socket, Timeout, Parent, Handler, NewState);
+ %% {Parent,Ref,{get,Key}} ->
+ %% Parent ! {self(),Ref,gb_get(Key, State)},
+ %% s_loop(Socket, Timeout, Parent, Handler, State);
+ {sctp,Socket,Addr,Port,
+ {[#sctp_sndrcvinfo{stream=Stream,assoc_id=AssocId}=SRI],Data}}
+ when not is_tuple(Data) ->
+ case gb_get({assoc_change,AssocId}, State) of
+ [{_,{Addr,Port,
+ #sctp_assoc_change{
+ state=comm_up,
+ inbound_streams=Is}}}|_]
+ when 0 =< Stream, Stream < Is-> ok;
+ [] -> ok
+ end,
+ Key = {msg,AssocId,Stream},
+ Val = {now(),{Addr,Port,SRI,Data}},
+ NewState = gb_push(Key, Val, State),
+ Parent ! {self(),{Addr,Port,AssocId,Stream,Data}},
+ again(Socket),
+ s_loop(Socket, Timeout, Parent, Handler, NewState);
+ {sctp,Socket,Addr,Port,
+ {SRI,#sctp_assoc_change{assoc_id=AssocId,state=St}=SAC}} ->
+ case SRI of
+ [#sctp_sndrcvinfo{assoc_id=AssocId,stream=0}] -> ok;
+ [] -> ok
+ end,
+ Key = {assoc_change,AssocId},
+ Val = {now(),{Addr,Port,SAC}},
+ case {gb_get(Key, State),St} of
+ {[],_} -> ok;
+ {[{_,{Addr,Port,#sctp_assoc_change{state=comm_up}}}|_],_}
+ when St =:= comm_lost; St =:= shutdown_comp -> ok
+ end,
+ NewState = gb_push(Key, Val, State),
+ Parent ! {self(),{Addr,Port,SAC}},
+ again(Socket),
+ s_loop(Socket, Timeout, Parent, Handler, NewState);
+ {sctp,Socket,Addr,Port,
+ {SRI,#sctp_paddr_change{assoc_id=AssocId,
+ addr={_,P},
+ state=St}=SPC}} ->
+ match_unless_solaris(Port, P),
+ case SRI of
+ [#sctp_sndrcvinfo{assoc_id=AssocId,stream=0}] -> ok;
+ [] -> ok
+ end,
+ case {gb_get({assoc_change,AssocId}, State),St} of
+ {[{_,{Addr,Port,#sctp_assoc_change{state=comm_up}}}|_],
+ addr_available} -> ok;
+ {[],addr_confirmed} -> ok
+ end,
+ Key = {paddr_change,AssocId},
+ Val = {now(),{Addr,Port,SPC}},
+ NewState = gb_push(Key, Val, State),
+ again(Socket),
+ s_loop(Socket, Timeout, Parent, Handler, NewState);
+ {sctp,Socket,Addr,Port,
+ {SRI,#sctp_shutdown_event{assoc_id=AssocId}=SSE}} ->
+ case SRI of
+ [#sctp_sndrcvinfo{assoc_id=AssocId,stream=0}] -> ok;
+ [] -> ok
+ end,
+ case gb_get({assoc_change,AssocId}, State) of
+ [{_,{Addr,Port,#sctp_assoc_change{state=comm_up}}}|_] -> ok;
+ [] -> ok
+ end,
+ Key = {shutdown_event,AssocId},
+ Val = {now(),{Addr,Port}},
+ NewState = gb_push(Key, Val, State),
+ Parent ! {self(), {Addr,Port,SSE}},
+ again(Socket),
+ s_loop(Socket, Timeout, Parent, Handler, NewState);
+ Unexpected ->
+ erlang:error({unexpected,Unexpected})
+ end.
+
+again(Socket) ->
+ inet:setopts(Socket, [{active,once}]).
+
+gb_push(Key, Val, GBT) ->
+ case gb_trees:lookup(Key, GBT) of
+ none ->
+ gb_trees:insert(Key, [Val], GBT);
+ {value,V} ->
+ gb_trees:update(Key, [Val|V], GBT)
+ end.
+
+gb_get(Key, GBT) ->
+ case gb_trees:lookup(Key, GBT) of
+ none ->
+ [];
+ {value,V} ->
+ V
+ end.
+
+match_unless_solaris(A, B) ->
+ case os:type() of
+ {unix,sunos} -> B;
+ _ -> A = B
+ end.
diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl
index fd4685cdad..cbaec2d6dd 100644
--- a/lib/kernel/test/gen_tcp_api_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_api_SUITE.erl
@@ -158,6 +158,10 @@ t_shutdown_error(Config) when is_list(Config) ->
t_fdopen(Config) when is_list(Config) ->
?line Question = "Aaaa... Long time ago in a small town in Germany,",
+ ?line Question1 = list_to_binary(Question),
+ ?line Question2 = [<<"Aaaa">>, "... ", $L, <<>>, $o, "ng time ago ",
+ ["in ", [], <<"a small town">>, [" in Germany,", <<>>]]],
+ ?line Question1 = iolist_to_binary(Question2),
?line Answer = "there was a shoemaker, Schumacher was his name.",
?line {ok, L} = gen_tcp:listen(0, [{active, false}]),
?line {ok, Port} = inet:port(L),
@@ -167,6 +171,10 @@ t_fdopen(Config) when is_list(Config) ->
?line {ok, Server} = gen_tcp:fdopen(FD, []),
?line ok = gen_tcp:send(Client, Question),
?line {ok, Question} = gen_tcp:recv(Server, length(Question), 2000),
+ ?line ok = gen_tcp:send(Client, Question1),
+ ?line {ok, Question} = gen_tcp:recv(Server, length(Question), 2000),
+ ?line ok = gen_tcp:send(Client, Question2),
+ ?line {ok, Question} = gen_tcp:recv(Server, length(Question), 2000),
?line ok = gen_tcp:send(Server, Answer),
?line {ok, Answer} = gen_tcp:recv(Client, length(Answer), 2000),
?line ok = gen_tcp:close(Client),
diff --git a/lib/kernel/test/gen_udp_SUITE.erl b/lib/kernel/test/gen_udp_SUITE.erl
index d8a5519195..514deaf065 100644
--- a/lib/kernel/test/gen_udp_SUITE.erl
+++ b/lib/kernel/test/gen_udp_SUITE.erl
@@ -201,13 +201,21 @@ binary_passive_recv(suite) ->
binary_passive_recv(doc) ->
["OTP-3823 gen_udp:recv does not return address in binary mode"];
binary_passive_recv(Config) when is_list(Config) ->
- ?line D = "The quick brown fox jumps over a lazy dog",
- ?line B = list_to_binary(D),
+ ?line D1 = "The quick brown fox jumps over a lazy dog",
+ ?line D2 = list_to_binary(D1),
+ ?line D3 = ["The quick", <<" brown ">>, "fox jumps ", <<"over ">>,
+ <<>>, $a, [[], " lazy ", <<"dog">>]],
+ ?line D2 = iolist_to_binary(D3),
+ ?line B = D2,
?line {ok, R} = gen_udp:open(0, [binary, {active, false}]),
?line {ok, RP} = inet:port(R),
?line {ok, S} = gen_udp:open(0),
?line {ok, SP} = inet:port(S),
- ?line ok = gen_udp:send(S, localhost, RP, D),
+ ?line ok = gen_udp:send(S, localhost, RP, D1),
+ ?line {ok, {{127, 0, 0, 1}, SP, B}} = gen_udp:recv(R, byte_size(B)+1),
+ ?line ok = gen_udp:send(S, localhost, RP, D2),
+ ?line {ok, {{127, 0, 0, 1}, SP, B}} = gen_udp:recv(R, byte_size(B)+1),
+ ?line ok = gen_udp:send(S, localhost, RP, D3),
?line {ok, {{127, 0, 0, 1}, SP, B}} = gen_udp:recv(R, byte_size(B)+1),
?line ok = gen_udp:close(S),
?line ok = gen_udp:close(R),
@@ -400,6 +408,7 @@ open_fd(Config) when is_list(Config) ->
{ok,S1} = gen_udp:open(0),
{ok,P2} = inet:port(S1),
{ok,FD} = prim_inet:getfd(S1),
+ {error,einval} = gen_udp:open(P2, [inet6, {fd,FD}]),
{ok,S2} = gen_udp:open(P2, [{fd,FD}]),
{ok,S3} = gen_udp:open(0),
{ok,P3} = inet:port(S3),
diff --git a/lib/kernel/test/global_SUITE.erl b/lib/kernel/test/global_SUITE.erl
index 1e7bcf1766..60035b50a0 100644
--- a/lib/kernel/test/global_SUITE.erl
+++ b/lib/kernel/test/global_SUITE.erl
@@ -436,7 +436,7 @@ lock_global2(Id, Parent) ->
%cp1 - cp3 are started, and the name 'test' registered for a process on
%test_server. Then it is checked that the name is registered on all
-%nodes, using whereis_name and safe_whereis_name. Check that the same
+%nodes, using whereis_name. Check that the same
%name can't be registered with another value. Exit the registered
%process and check that the name disappears. Register a new process
%(Pid2) under the name 'test'. Let another new process (Pid3)
@@ -465,10 +465,6 @@ names(Config) when is_list(Config) ->
% test that it is registered at all nodes
?line
?UNTIL(begin
- (Pid =:= global:safe_whereis_name(test)) and
- (Pid =:= rpc:call(Cp1, global, safe_whereis_name, [test])) and
- (Pid =:= rpc:call(Cp2, global, safe_whereis_name, [test])) and
- (Pid =:= rpc:call(Cp3, global, safe_whereis_name, [test])) and
(Pid =:= global:whereis_name(test)) and
(Pid =:= rpc:call(Cp1, global, whereis_name, [test])) and
(Pid =:= rpc:call(Cp2, global, whereis_name, [test])) and
@@ -566,10 +562,7 @@ names_hidden(Config) when is_list(Config) ->
% Check that it didn't get registered on visible nodes
?line
- ?UNTIL((undefined =:= global:safe_whereis_name(test)) and
- (undefined =:= rpc:call(Cp1, global, safe_whereis_name, [test])) and
- (undefined =:= rpc:call(Cp2, global, safe_whereis_name, [test])) and
- (undefined =:= global:whereis_name(test)) and
+ ?UNTIL((undefined =:= global:whereis_name(test)) and
(undefined =:= rpc:call(Cp1, global, whereis_name, [test])) and
(undefined =:= rpc:call(Cp2, global, whereis_name, [test]))),
@@ -579,11 +572,7 @@ names_hidden(Config) when is_list(Config) ->
% test that it is registered at all nodes
?line
- ?UNTIL((Pid =:= global:safe_whereis_name(test)) and
- (Pid =:= rpc:call(Cp1, global, safe_whereis_name, [test])) and
- (Pid =:= rpc:call(Cp2, global, safe_whereis_name, [test])) and
- (HPid =:= rpc:call(Cp3, global, safe_whereis_name, [test])) and
- (Pid =:= global:whereis_name(test)) and
+ ?UNTIL((Pid =:= global:whereis_name(test)) and
(Pid =:= rpc:call(Cp1, global, whereis_name, [test])) and
(Pid =:= rpc:call(Cp2, global, whereis_name, [test])) and
(HPid =:= rpc:call(Cp3, global, whereis_name, [test])) and
diff --git a/lib/kernel/test/global_group_SUITE.erl b/lib/kernel/test/global_group_SUITE.erl
index 13b2fd07b5..799b0d9d05 100644
--- a/lib/kernel/test/global_group_SUITE.erl
+++ b/lib/kernel/test/global_group_SUITE.erl
@@ -100,7 +100,7 @@ start_gg_proc(Config) when is_list(Config) ->
?line Dir = ?config(priv_dir, Config),
?line File = filename:join(Dir, "global_group.config"),
- ?line {ok, Fd}=file:open(File, write),
+ ?line {ok, Fd}=file:open(File, [write]),
[Ncp1,Ncp2,Ncp3] = node_names([cp1, cp2, cp3], Config),
?line config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"),
@@ -135,7 +135,7 @@ no_gg_proc(Config) when is_list(Config) ->
?line Dir = ?config(priv_dir, Config),
?line File = filename:join(Dir, "no_global_group.config"),
- ?line {ok, Fd} = file:open(File, write),
+ ?line {ok, Fd} = file:open(File, [write]),
?line config_no(Fd),
?line NN = node_name(atom_to_list(node())),
@@ -308,7 +308,7 @@ no_gg_proc_sync(Config) when is_list(Config) ->
?line Dir = ?config(priv_dir, Config),
?line File = filename:join(Dir, "no_global_group_sync.config"),
- ?line {ok, Fd} = file:open(File, write),
+ ?line {ok, Fd} = file:open(File, [write]),
[Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz] =
node_names([cp1,cp2,cp3,cpx,cpy,cpz], Config),
@@ -482,7 +482,7 @@ compatible(Config) when is_list(Config) ->
?line Dir = ?config(priv_dir, Config),
?line File = filename:join(Dir, "global_group_comp.config"),
- ?line {ok, Fd} = file:open(File, write),
+ ?line {ok, Fd} = file:open(File, [write]),
[Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz] =
node_names([cp1,cp2,cp3,cpx,cpy,cpz], Config),
@@ -655,7 +655,7 @@ one_grp(Config) when is_list(Config) ->
?line Dir = ?config(priv_dir, Config),
?line File = filename:join(Dir, "global_group.config"),
- ?line {ok, Fd} = file:open(File, write),
+ ?line {ok, Fd} = file:open(File, [write]),
[Ncp1,Ncp2,Ncp3] = node_names([cp1, cp2, cp3], Config),
?line config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"),
@@ -742,7 +742,7 @@ one_grp_x(Config) when is_list(Config) ->
?line Dir = ?config(priv_dir, Config),
?line File = filename:join(Dir, "global_group.config"),
- ?line {ok, Fd} = file:open(File, write),
+ ?line {ok, Fd} = file:open(File, [write]),
[Ncp1,Ncp2,Ncp3] = node_names([cp1, cp2, cp3], Config),
?line config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"),
@@ -804,7 +804,7 @@ two_grp(Config) when is_list(Config) ->
?line Dir = ?config(priv_dir, Config),
?line File = filename:join(Dir, "global_group.config"),
- ?line {ok, Fd} = file:open(File, write),
+ ?line {ok, Fd} = file:open(File, [write]),
[Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz,Ncpq] =
node_names([cp1,cp2,cp3,cpx,cpy,cpz,cpq], Config),
@@ -1104,7 +1104,7 @@ hidden_groups(Config) when is_list(Config) ->
?line Dir = ?config(priv_dir, Config),
?line File = filename:join(Dir, "global_group.config"),
- ?line {ok, Fd} = file:open(File, write),
+ ?line {ok, Fd} = file:open(File, [write]),
[Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz,Ncpq] =
node_names([cp1,cp2,cp3,cpx,cpy,cpz,cpq], Config),
diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl
index 1bb173a3ac..aaa20b7398 100644
--- a/lib/kernel/test/inet_SUITE.erl
+++ b/lib/kernel/test/inet_SUITE.erl
@@ -294,7 +294,7 @@ t_getaddr_v6(Config) when is_list(Config) ->
?line {Name,FullName,IPStr,_IP,_,IP_46_Str,IP46} =
ct:get_config(test_host_ipv4_only),
case {inet:getaddr(IP_46_Str, inet6),inet:getaddr(Name, inet6)} of
- {{ok,IP46},{ok,_}} ->
+ {{ok,IP46},{ok,V4Addr}} when V4Addr /= {0,0,0,0,0,0,0,1} ->
%% Since we suceeded in parsing an IPv6 address string and
%% look up the name, this computer fully supports IPv6.
?line {ok,IP46} = inet:getaddr(IP46, inet6),
diff --git a/lib/kernel/test/inet_res_SUITE.erl b/lib/kernel/test/inet_res_SUITE.erl
index 6064a9b2d9..15b0ed5718 100644
--- a/lib/kernel/test/inet_res_SUITE.erl
+++ b/lib/kernel/test/inet_res_SUITE.erl
@@ -117,9 +117,15 @@ ns_init(ZoneDir, PrivDir, DataDir) ->
case os:type() of
{unix,_} when ZoneDir =:= undefined -> undefined;
{unix,_} ->
- {ok,S} = gen_udp:open(0, [{reuseaddr,true}]),
- {ok,PortNum} = inet:port(S),
- gen_udp:close(S),
+ PortNum = case {os:type(),os:version()} of
+ {{unix,solaris},{M,V,_}} when M =< 5, V < 10 ->
+ 11895 + random:uniform(100);
+ _ ->
+ {ok,S} = gen_udp:open(0, [{reuseaddr,true}]),
+ {ok,PNum} = inet:port(S),
+ gen_udp:close(S),
+ PNum
+ end,
RunNamed = filename:join(DataDir, ?RUN_NAMED),
NS = {{127,0,0,1},PortNum},
P = erlang:open_port({spawn_executable,RunNamed},
@@ -130,21 +136,22 @@ ns_init(ZoneDir, PrivDir, DataDir) ->
atom_to_list(ZoneDir)]},
stderr_to_stdout,
eof]),
- ns_start(ZoneDir, NS, P);
+ ns_start(ZoneDir, PrivDir, NS, P);
_ ->
throw("Only run on Unix")
end.
-ns_start(ZoneDir, NS, P) ->
+ns_start(ZoneDir, PrivDir, NS, P) ->
case ns_collect(P) of
eof ->
erlang:error(eof);
"Running: "++_ ->
{ZoneDir,NS,P};
"Error: "++Error ->
+ ns_printlog(filename:join([PrivDir,ZoneDir,"named.log"])),
throw(Error);
_ ->
- ns_start(ZoneDir, NS, P)
+ ns_start(ZoneDir, PrivDir, NS, P)
end.
ns_end(undefined, _PrivDir) -> undefined;
diff --git a/lib/kernel/test/inet_res_SUITE_data/run-named b/lib/kernel/test/inet_res_SUITE_data/run-named
index b418607d48..39e7b1d5aa 100755
--- a/lib/kernel/test/inet_res_SUITE_data/run-named
+++ b/lib/kernel/test/inet_res_SUITE_data/run-named
@@ -2,7 +2,7 @@
##
## %CopyrightBegin%
##
-## Copyright Ericsson AB 2009. All Rights Reserved.
+## Copyright Ericsson AB 2009-2011. All Rights Reserved.
##
## The contents of this file are subject to the Erlang Public License,
## Version 1.1, (the "License"); you may not use this file except in
@@ -47,6 +47,7 @@ CONF_FILE=named.conf
INC_FILE=named_inc.conf
PID_FILE=named.pid
LOG_FILE=named.log
+EXIT_FILE=named.exit
error () {
r=$?
@@ -71,10 +72,14 @@ test -d "$SRCDIR" || \
test -f "$SRCDIR/$INC_FILE" || \
error "Missing file: $SRCDIR/$INC_FILE !"
-# Locate named and check version
+# Locate named and check version.
+# The bind-named name is used for tricking Apparmor and such
+# by copying/hardlinking the real named to that name.
NAMED=named
-for n in /usr/sbin/named /usr/sbin/in.named; do
- test -x "$n" && NAMED="$n"
+for n in /usr/local/bin/bind-named /usr/local/bin/named \
+ /usr/sbin/bind-named /usr/sbin/named /usr/sbin/in.named
+do
+ test -x "$n" && NAMED="$n" && break
done
NAMED_VER="`"$NAMED" -v 2>&1`" || \
error "Name server not found!"
@@ -145,19 +150,27 @@ cat >>"$CONF_FILE" <<-CONF_FILE
( cd "$SRCDIR" && ls -1 ) | while read f; do
cp -fp "$SRCDIR/$f" .
done
+rm -f "$EXIT_FILE"
# Start nameserver
echo "Cwd: `pwd`"
echo "Nameserver: $NAMED_VER"
echo "Port: $2"
echo "ZoneDir: $3"
-$NAMED $NAMED_FG -c "$CONF_FILE" >"$LOG_FILE" 2>&1 </dev/null &
-NAMED=$!
-trap "kill -TERM $NAMED >/dev/null 2>&1; wait $NAMED >/dev/null 2>&1" \
+echo "Command: $NAMED $NAMED_FG -c $CONF_FILE"
+($NAMED $NAMED_FG -c "$CONF_FILE" >"$LOG_FILE" 2>&1 </dev/null; \
+ echo "$?" >"$EXIT_FILE")&
+NAMED_PID=$!
+trap "kill -TERM $NAMED_PID >/dev/null 2>&1; wait $NAMED_PID >/dev/null 2>&1" \
0 1 2 3 15
-sleep 1 # Give name server time to load its zone files
-echo "Running: Enter \`\`quit'' to terminate nameserver[$NAMED]..."
-while read LINE; do
- test :"$LINE" = :'quit' && break
-done
+sleep 2 # Give name server time to load its zone files
+if [ -f "$EXIT_FILE" ]; then
+ ERROR="`cat "$EXIT_FILE"`"
+ (exit "$ERROR")& error "$NAMED returned $ERROR on start"
+else
+ echo "Running: Enter \`\`quit'' to terminate nameserver[$NAMED_PID]..."
+ while read LINE; do
+ test :"$LINE" = :'quit' && break
+ done
+fi
echo "Closing: Terminating nameserver..."
diff --git a/lib/kernel/test/init_SUITE.erl b/lib/kernel/test/init_SUITE.erl
index 2db0f7dcb8..b39fadd65f 100644
--- a/lib/kernel/test/init_SUITE.erl
+++ b/lib/kernel/test/init_SUITE.erl
@@ -656,7 +656,7 @@ create_script(Config) ->
?line Apps = application_controller:which_applications(),
?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
- ?line {ok,Fd} = file:open(Name ++ ".rel", write),
+ ?line {ok,Fd} = file:open(Name ++ ".rel", [write]),
?line io:format(Fd,
"{release, {\"Test release 3\", \"P2A\"}, \n"
" {erts, \"4.4\"}, \n"
diff --git a/lib/kernel/test/pg2_SUITE.erl b/lib/kernel/test/pg2_SUITE.erl
index 0ac34e735c..520b53b4e4 100644
--- a/lib/kernel/test/pg2_SUITE.erl
+++ b/lib/kernel/test/pg2_SUITE.erl
@@ -47,6 +47,7 @@ init_per_testcase(Case, Config) ->
[{?TESTCASE, Case}, {watchdog, Dog} | Config].
end_per_testcase(_Case, _Config) ->
+ test_server_ctrl:kill_slavenodes(),
Dog = ?config(watchdog, _Config),
test_server:timetrap_cancel(Dog),
ok.
diff --git a/lib/kernel/test/ram_file_SUITE.erl b/lib/kernel/test/ram_file_SUITE.erl
index 9b3fbb91fc..ab95a3ff5f 100644
--- a/lib/kernel/test/ram_file_SUITE.erl
+++ b/lib/kernel/test/ram_file_SUITE.erl
@@ -552,7 +552,7 @@ large_file_light(Config) when is_list(Config) ->
?line PrivDir = ?config(priv_dir, Config),
%% Marker for next test case that is to heavy to run in a suite.
?line ok = ?FILE_MODULE:write_file(
- filename:join(PrivDir, large_file_light),
+ filename:join(PrivDir, "large_file_light"),
<<"TAG">>),
%%
?line Data = "abcdefghijklmnopqrstuvwzyz",
@@ -582,7 +582,7 @@ large_file_heavy(Config) when is_list(Config) ->
?line PrivDir = ?config(priv_dir, Config),
%% Check previous test case marker.
case ?FILE_MODULE:read_file_info(
- filename:join(PrivDir, large_file_light)) of
+ filename:join(PrivDir, "large_file_light")) of
{ok,_} ->
{skipped,"Too heavy for casual testing!"};
_ ->
diff --git a/lib/kernel/test/zlib_SUITE.erl b/lib/kernel/test/zlib_SUITE.erl
index 9eb84c9167..74bafe8935 100644
--- a/lib/kernel/test/zlib_SUITE.erl
+++ b/lib/kernel/test/zlib_SUITE.erl
@@ -42,8 +42,8 @@
end
end()).
--define(BARG, {'EXIT',{badarg,[{zlib,_,_}|_]}}).
--define(DATA_ERROR, {'EXIT',{data_error,[{zlib,_,_}|_]}}).
+-define(BARG, {'EXIT',{badarg,[{zlib,_,_,_}|_]}}).
+-define(DATA_ERROR, {'EXIT',{data_error,[{zlib,_,_,_}|_]}}).
init_per_testcase(_Func, Config) ->
Dog = test_server:timetrap(test_server:seconds(60)),
@@ -412,6 +412,7 @@ api_crc32(Config) when is_list(Config) ->
Compressed = list_to_binary(Compressed1 ++ Compressed2),
CRC1 = ?m( CRC1 when is_integer(CRC1), zlib:crc32(Z1)),
?m(CRC1 when is_integer(CRC1), zlib:crc32(Z1,Bin)),
+ ?m(CRC1 when is_integer(CRC1), zlib:crc32(Z1,binary_to_list(Bin))),
?m(CRC2 when is_integer(CRC2), zlib:crc32(Z1,Compressed)),
CRC2 = ?m(CRC2 when is_integer(CRC2), zlib:crc32(Z1,0,Compressed)),
?m(CRC3 when CRC2 /= CRC3, zlib:crc32(Z1,234,Compressed)),
@@ -437,6 +438,7 @@ api_adler32(Config) when is_list(Config) ->
Compressed2 = ?m(_, zlib:deflate(Z1, <<>>, finish)),
Compressed = list_to_binary(Compressed1 ++ Compressed2),
?m(ADLER1 when is_integer(ADLER1), zlib:adler32(Z1,Bin)),
+ ?m(ADLER1 when is_integer(ADLER1), zlib:adler32(Z1,binary_to_list(Bin))),
ADLER2 = ?m(ADLER2 when is_integer(ADLER2), zlib:adler32(Z1,Compressed)),
?m(ADLER2 when is_integer(ADLER2), zlib:adler32(Z1,1,Compressed)),
?m(ADLER3 when ADLER2 /= ADLER3, zlib:adler32(Z1,234,Compressed)),
@@ -464,6 +466,7 @@ api_un_compress(Config) when is_list(Config) ->
?m({'EXIT',{data_error,_}}, zlib:uncompress(<<120,156,3>>)),
?m({'EXIT',{data_error,_}}, zlib:uncompress(<<120,156,3,0>>)),
?m({'EXIT',{data_error,_}}, zlib:uncompress(<<0,156,3,0,0,0,0,1>>)),
+ ?m(Bin, zlib:uncompress(binary_to_list(Comp))),
?m(Bin, zlib:uncompress(Comp)).
api_un_zip(doc) -> "Test zip";
@@ -472,10 +475,12 @@ api_un_zip(Config) when is_list(Config) ->
?m(?BARG,zlib:zip(not_a_binary)),
Bin = <<1,11,1,23,45>>,
?line Comp = zlib:zip(Bin),
+ ?m(Comp, zlib:zip(binary_to_list(Bin))),
?m(?BARG,zlib:unzip(not_a_binary)),
?m({'EXIT',{data_error,_}}, zlib:unzip(<<171,171,171,171,171>>)),
?m({'EXIT',{data_error,_}}, zlib:unzip(<<>>)),
?m(Bin, zlib:unzip(Comp)),
+ ?m(Bin, zlib:unzip(binary_to_list(Comp))),
%% OTP-6396
B = <<131,104,19,100,0,13,99,95,99,105,100,95,99,115,103,115,110,95,50,97,1,107,0,4,208,161,246,29,107,0,3,237,166,224,107,0,6,66,240,153,0,2,10,1,0,8,97,116,116,97,99,104,101,100,104,2,100,0,22,117,112,100,97,116,101,95,112,100,112,95,99,111,110,116,101,120,116,95,114,101,113,107,0,114,69,3,12,1,11,97,31,113,150,64,104,132,61,64,104,12,3,197,31,113,150,64,104,132,61,64,104,12,1,11,97,31,115,150,64,104,116,73,64,104,0,0,0,0,0,0,65,149,16,61,65,149,16,61,1,241,33,4,5,0,33,4,4,10,6,10,181,4,10,6,10,181,38,15,99,111,109,109,97,110,100,1,114,45,97,112,110,45,49,3,99,111,109,5,109,110,99,57,57,6,109,99,99,50,52,48,4,103,112,114,115,8,0,104,2,104,2,100,0,8,97,99,116,105,118,97,116,101,104,23,100,0,11,112,100,112,95,99,111,110,116,1,120,116,100,0,7,112,114,105,109,97,114,121,97,1,100,0,9,117,110,100,101,102,105,110,101,100,97,1,97,4,97,4,97,7,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110,10100,100,0,9,117,110,100,101,102,105,110,101,100,100,0,5,102,97,108,115,101,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,1,101,100,97,0,100,0,9,117,110,100,101,102,105,110,101,100,107,0,4,16,0,1,144,107,0,4,61,139,186,181,107,0,4,10,8,201,49,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,0,101,100,100,0,9,117,110,100,101,102,105,110,101,100,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,16,97,21,106,108,0,0,0,3,104,2,97,1,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,167,20,104,2,97,4,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,16,97,21,104,2,97,10,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,16,97,26,106,100,0,5,118,101,114,57,57,100,0,9,117,110,0,101,102,105,110,101,100,107,0,2,0,244,107,0,4,10,6,102,195,107,0,4,10,6,102,195,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,107,0,125,248,143,0,203,25115,157,116,65,185,65,172,55,87,164,88,225,50,203,251,115,157,116,65,185,65,172,55,87,164,88,225,50,0,0,82,153,50,0,200,98,87,148,237,193,185,65,149,167,69,144,14,16,153,50,3,81,70,94,13,109,193,1,120,5,181,113,198,118,50,3,81,70,94,13,109,193,185,120,5,181,113,198,118,153,3,81,70,94,13,109,193,185,120,5,181,113,198,118,153,50,16,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,113,92,2,119,128,0,0,108,0,0,1,107,0,114,69,3,12,1,11,97,31,113,150,64,104,132,61,64,104,12,3,11,97,31,113,150,64,104,132,61,64,104,12,1,11,97,31,115,150,64,104,116,73,64,104,0,0,0,0,0,0,65,149,16,61,65,149,16,61,1,241,33,4,0,33,4,4,10,6,10,181,4,10,6,10,181,38,15,99,111,109,109,97,110,100,101,114,45,97,112,110,45,49,3,99,111,109,5,109,110,99,57,57,6,109,99,99,50,52,48,4,103,112,114,115,8,0,106>>,
@@ -504,10 +509,12 @@ api_g_un_zip(Config) when is_list(Config) ->
?m(?BARG,zlib:gzip(not_a_binary)),
Bin = <<1,11,1,23,45>>,
?line Comp = zlib:gzip(Bin),
+ ?m(Comp, zlib:gzip(binary_to_list(Bin))),
?m(?BARG, zlib:gunzip(not_a_binary)),
?m(?DATA_ERROR, zlib:gunzip(<<171,171,171,171,171>>)),
?m(?DATA_ERROR, zlib:gunzip(<<>>)),
?m(Bin, zlib:gunzip(Comp)),
+ ?m(Bin, zlib:gunzip(binary_to_list(Comp))),
%% Bad CRC; bad length.
BadCrc = bad_crc_data(),
@@ -844,6 +851,7 @@ dictionary_usage({run}) ->
?m(ok, zlib:inflateInit(Z2)),
?line {'EXIT',{{need_dictionary,DictID},_}} = (catch zlib:inflate(Z2, Compressed)),
?m(ok, zlib:inflateSetDictionary(Z2, Dict)),
+ ?m(ok, zlib:inflateSetDictionary(Z2, binary_to_list(Dict))),
?line Uncompressed = ?m(B when is_list(B), zlib:inflate(Z2, [])),
?m(ok, zlib:inflateEnd(Z2)),
?m(ok, zlib:close(Z2)),
diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk
index e7b71cc168..76c62ece67 100644
--- a/lib/kernel/vsn.mk
+++ b/lib/kernel/vsn.mk
@@ -1 +1 @@
-KERNEL_VSN = 2.14.4
+KERNEL_VSN = 2.15
diff --git a/lib/megaco/.gitignore b/lib/megaco/.gitignore
new file mode 100644
index 0000000000..1c5979cd62
--- /dev/null
+++ b/lib/megaco/.gitignore
@@ -0,0 +1,3 @@
+examples/meas/Makefile
+examples/meas/meas.sh.skel
+examples/meas/mstone1.sh.skel
diff --git a/lib/megaco/configure.in b/lib/megaco/configure.in
index 8f94a4efcf..b88e17ec85 100644
--- a/lib/megaco/configure.in
+++ b/lib/megaco/configure.in
@@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script. -*-m4-*-
dnl
dnl %CopyrightBegin%
dnl
-dnl Copyright Ericsson AB 2001-2010. All Rights Reserved.
+dnl Copyright Ericsson AB 2001-2011. All Rights Reserved.
dnl
dnl The contents of this file are subject to the Erlang Public License,
dnl Version 1.1, (the "License"); you may not use this file except in
@@ -273,5 +273,6 @@ if test "$PERL" = no_perl; then
AC_MSG_ERROR([Perl is required to build the flex scanner!])
fi
+AC_OUTPUT(examples/meas/Makefile:examples/meas/Makefile.in)
AC_OUTPUT(src/flex/$host/Makefile:src/flex/Makefile.in)
diff --git a/lib/megaco/doc/src/Makefile b/lib/megaco/doc/src/Makefile
index 4b3c117b20..f782afc3f6 100644
--- a/lib/megaco/doc/src/Makefile
+++ b/lib/megaco/doc/src/Makefile
@@ -27,14 +27,6 @@ VSN=$(MEGACO_VSN)
APPLICATION=megaco
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -73,35 +65,10 @@ EXTRA_FILES = \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi $(APP_FILE)
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-
-TOP_HTML_FILES = $(INDEX_TARGET)
-
-endif
-
INDEX_FILE = index.html
INDEX_SRC = $(INDEX_FILE).src
INDEX_TARGET = $(DOCDIR)/$(INDEX_FILE)
@@ -131,8 +98,6 @@ $(HTMLDIR)/%.jpg: %.jpg
$(HTMLDIR)/%.png: %.png
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
ldocs: local_docs $(INDEX_TARGET)
@@ -147,41 +112,6 @@ clean clean_docs: clean_html clean_man
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html imgs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: imgs $(HTML_FILES) $(TOP_HTML_FILES)
-
-mhtml: html $(HTML_REF3_FILES) $(HTML_CHAPTER_FILES)
-
-clean: clean_html clean_man clean_pdf
- rm -f core *~
- rm -f *.aux *.cites *.citeshd *.dvi *.idx *.ilg *.ind
- rm -f *.indhd *.lof *.lofhd *.lot *.lothd *.otpdef
- rm -f *.otpuse *.terms *.termshd *.toc *.makeindexlog *.dvipslog
- rm -f *.bib *.bbl *.blg *.bibhd
-
-clean_pdf:
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f $(TEX_FILES_USERS_GUIDE)
- rm -f $(TEX_FILES_REF_MAN)
- rm -f $(TEX_FILES_BOOK)
-
-endif
-
clean_man:
rm -f $(MAN3DIR)/*
@@ -203,8 +133,6 @@ debug opt:
info:
@echo "->Makefile<-"
@echo ""
- @echo "DOCSUPPORT = $(DOCSUPPORT)"
- @echo ""
@echo "INDEX_FILE = $(INDEX_FILE)"
@echo "INDEX_SRC = $(INDEX_SRC)"
@echo "INDEX_TARGET = $(INDEX_TARGET)"
@@ -216,10 +144,6 @@ info:
@echo ""
@echo "IMG_FILES = $(IMG_FILES)"
@echo ""
- @echo "TEX_FILES_USERS_GUIDE = $(TEX_FILES_USERS_GUIDE)"
- @echo "TEX_FILES_REF_MAN = $(TEX_FILES_REF_MAN)"
- @echo "TEX_FILES_BOOK = $(TEX_FILES_BOOK)"
- @echo ""
@echo "MAN3_FILES = $(MAN3_FILES)"
@echo ""
@echo "HTML_FILES = $(HTML_FILES)"
@@ -236,8 +160,6 @@ info:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
$(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
$(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
@@ -250,33 +172,6 @@ release_docs_spec: docs
$(INSTALL_DIR) $(RELSYSDIR)/doc/standard
$(INSTALL_DATA) $(STANDARDS) $(RELSYSDIR)/doc/standard
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(IMG_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(TOP_HTML_FILES) $(RELSYSDIR)/doc
- $(INSTALL_DIR) $(RELSYSDIR)/doc/standard
- $(INSTALL_DATA) $(STANDARDS) $(RELSYSDIR)/doc/standard
-endif
-endif
-
-endif
-
release_spec:
$(HTMLDIR)/megaco_architecture.html: megaco_architecture.xml
diff --git a/lib/megaco/doc/src/make.dep b/lib/megaco/doc/src/make.dep
deleted file mode 100644
index 0e2040ab50..0000000000
--- a/lib/megaco/doc/src/make.dep
+++ /dev/null
@@ -1,59 +0,0 @@
-#-*-makefile-*- ; force emacs to enter makefile-mode
-
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2001-2009. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex megaco.tex megaco_architecture.tex \
- megaco_codec_meas.tex \
- megaco_codec_mstone1.tex megaco_codec_mstone2.tex \
- megaco_codec_transform.tex \
- megaco_debug.tex megaco_edist_compress.tex \
- megaco_encode.tex megaco_encoder.tex megaco_examples.tex \
- megaco_flex_scanner.tex megaco_intro.tex megaco_mib.tex \
- megaco_performance.tex megaco_run.tex megaco_tcp.tex \
- megaco_transport.tex megaco_transport_mechanisms.tex \
- megaco_udp.tex megaco_user.tex part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: call_flow.ps call_flow_cont.ps distr_node_config.ps \
- megaco_sys_arch.ps single_node_config.ps
-
-book.dvi: mstone1.ps
-
-book.dvi: MG-startup_flow_noMID.ps MGC_startup_call_flow.ps \
- MG_startup_call_flow.ps
-
diff --git a/lib/megaco/doc/src/megaco.xml b/lib/megaco/doc/src/megaco.xml
index b9bf414299..5dd622368c 100644
--- a/lib/megaco/doc/src/megaco.xml
+++ b/lib/megaco/doc/src/megaco.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2000</year><year>2010</year>
+ <year>2000</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -646,7 +646,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
segments has not yet been received.</p>
<p>When the timer finally expires, a "megaco segments not
received" (459) error message is sent to the other side
- and the user is notified with a <c><![CDATA[segment timeout]]></c><c><![CDATA[UserReply]]></c> in either the
+ and the user is notified with a <c><![CDATA[segment timeout]]></c> <c><![CDATA[UserReply]]></c> in either the
<seealso marker="megaco_user#trans_reply">handle_trans_reply</seealso> callback function or
the return value of the
<seealso marker="megaco#call">call</seealso> function. </p>
@@ -1165,7 +1165,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
<p>When the timer finally expires, a "megaco segments not
received" (459) error message is sent to the other side
and the user is notified with a
- <c><![CDATA[segment timeout]]></c><c><![CDATA[UserReply]]></c> in either the
+ <c><![CDATA[segment timeout]]></c> <c><![CDATA[UserReply]]></c> in either the
<seealso marker="megaco_user#trans_reply">handle_trans_reply</seealso>
callback function or
the return value of the
diff --git a/lib/megaco/doc/src/notes.xml b/lib/megaco/doc/src/notes.xml
index 4f678a2a1b..baf8c6a201 100644
--- a/lib/megaco/doc/src/notes.xml
+++ b/lib/megaco/doc/src/notes.xml
@@ -36,6 +36,103 @@
section is the version number of Megaco.</p>
+ <section><title>Megaco 3.15.1.2</title>
+
+ <p>Version 3.15.1.2 supports code replacement in runtime from/to
+ version 3.15.1.1, 3.15.1 and 3.15.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+
+<!--
+ <p>-</p>
+-->
+
+ <list type="bulleted">
+ <item>
+ <p>Minor improvemnts to the emasurement tool mstone1. </p>
+ <p>Own Id: OTP-9604</p>
+ </item>
+
+ <item>
+ <p>ASN.1 no longer makes use of a driver to accelerate encode/decode,
+ instead it uses NIFs. The encoding config option is <em>still</em>
+ the same, i.e. <c>driver</c>. </p>
+ <p>Own Id: OTP-9672</p>
+ </item>
+
+ <item>
+ <p>The profiling test tool has been rewritten. </p>
+ <p>H&aring;kan Mattsson</p>
+ <p>Own Id: OTP-9679</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Fixed bugs and malfunctions</title>
+
+ <p>-</p>
+
+ <!--
+ <list type="bulleted">
+ <item>
+ <p>Fixing miscellaneous things detected by dialyzer. </p>
+ <p>Own Id: OTP-9075</p>
+ </item>
+
+ </list>
+ -->
+
+ </section>
+
+ </section> <!-- 3.15.1.2 -->
+
+
+ <section><title>Megaco 3.15.1.1</title>
+
+ <p>Version 3.15.1.1 supports code replacement in runtime from/to
+ version 3.15.1 and 3.15.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+
+<!--
+ <p>-</p>
+-->
+
+ <list type="bulleted">
+ <item>
+ <p>Correct various XML errors. </p>
+ <p>Own Id: OTP-9550</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Fixed bugs and malfunctions</title>
+
+ <p>-</p>
+
+ <!--
+ <list type="bulleted">
+ <item>
+ <p>Fixing miscellaneous things detected by dialyzer. </p>
+ <p>Own Id: OTP-9075</p>
+ </item>
+
+ </list>
+ -->
+
+ </section>
+
+ </section> <!-- 3.15.1.1 -->
+
+
<section><title>Megaco 3.15.1</title>
<p>Version 3.15.1 supports code replacement in runtime from/to
diff --git a/lib/megaco/examples/meas/Makefile b/lib/megaco/examples/meas/Makefile.in
index 0a6cbb44a6..6af7ef6c65 100644
--- a/lib/megaco/examples/meas/Makefile
+++ b/lib/megaco/examples/meas/Makefile.in
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2002-2009. All Rights Reserved.
+# Copyright Ericsson AB 2002-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -35,12 +35,19 @@ VSN=$(MEGACO_VSN)
# ----------------------------------------------------
+# Configured variables
+# ----------------------------------------------------
+PERL = @PERL@
+
+
+# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/megaco-$(VSN)
EXAMPLE_RELSYSDIR = $(RELSYSDIR)/examples
MEAS_RELSYSDIR = $(EXAMPLE_RELSYSDIR)/meas
+
# ----------------------------------------------------
# Target Specs
# ----------------------------------------------------
@@ -49,9 +56,13 @@ include modules.mk
ERL_FILES = $(MODULES:%=%.erl)
-TARGET_FILES = \
+SCRIPT_SKELETONS = $(SCRIPT_SKELETON_SRC:%.src=%)
+
+ERL_TARGETS = \
$(ERL_FILES:%.erl=$(EBIN)/%.$(EMULATOR))
+TARGET_FILES = $(SCRIPT_SKELETONS) $(ERL_TARGETS)
+
# ----------------------------------------------------
# FLAGS
@@ -91,12 +102,27 @@ debug:
opt: $(TARGET_FILES)
+script_skeletons: $(SCRIPT_SKELETONS)
+
+info:
+ @echo "MODULES = $(MODULES)"
+ @echo "ERL_FILED = $(ERL_FILES)"
+ @echo ""
+ @echo "SCRIPT_SKELETON_SRC = $(SCRIPT_SKELETON_SRC)"
+ @echo "SCRIPT_SKELETONS = $(SCRIPT_SKELETONS)"
+ @echo ""
+ @echo "TARGET_FILES = $(TARGET_FILES)"
+ @echo ""
+
clean:
rm -f $(TARGET_FILES)
rm -f errs core *~
docs:
+conf:
+ cd ../..; $(MAKE) conf
+
# ----------------------------------------------------
# Release Target
@@ -120,6 +146,14 @@ release_docs_spec:
# Include dependencies
# ----------------------------------------------------
+meas.sh.skel: meas.sh.skel.src
+ @echo "transforming $< to $@"
+ $(PERL) -p -e 's?%VSN%?$(VSN)? ' < $< > $@
+
+mstone1.sh.skel: mstone1.sh.skel.src
+ @echo "transforming $< to $@"
+ $(PERL) -p -e 's?%VSN%?$(VSN)? ' < $< > $@
+
megaco_codec_transform.$(EMULATOR): megaco_codec_transform.erl
megaco_codec_meas.$(EMULATOR): megaco_codec_meas.erl
diff --git a/lib/megaco/examples/meas/meas.sh.skel b/lib/megaco/examples/meas/meas.sh.skel.src
index 76745ed8f4..c7bd6cdd2a 100644
--- a/lib/megaco/examples/meas/meas.sh.skel
+++ b/lib/megaco/examples/meas/meas.sh.skel.src
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2007-2010. All Rights Reserved.
+# Copyright Ericsson AB 2007-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -22,7 +22,7 @@
#
ERL_HOME=<path to otp top dir>
-MEGACO_HOME=$ERL_HOME/lib/erlang/lib/<megaco dir>
+MEGACO_HOME=$ERL_HOME/lib/erlang/lib/megaco-%VSN%
MEAS_HOME=$MEGACO_HOME/examples/meas
PATH=$ERL_HOME/bin:$PATH
diff --git a/lib/megaco/examples/meas/modules.mk b/lib/megaco/examples/meas/modules.mk
index 8f1b45c8a6..26979933d7 100644
--- a/lib/megaco/examples/meas/modules.mk
+++ b/lib/megaco/examples/meas/modules.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2002-2009. All Rights Reserved.
+# Copyright Ericsson AB 2002-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -17,9 +17,9 @@
#
# %CopyrightEnd%
-SCRIPT_SKELETONS = \
- meas.sh.skel \
- mstone1.sh.skel
+SCRIPT_SKELETON_SRC = \
+ meas.sh.skel.src \
+ mstone1.sh.skel.src
MESSAGE_PACKAGES = \
time_test.msgs
diff --git a/lib/megaco/examples/meas/mstone1.sh.skel b/lib/megaco/examples/meas/mstone1.sh.skel.src
index b7c7e41007..54a6c61a58 100644
--- a/lib/megaco/examples/meas/mstone1.sh.skel
+++ b/lib/megaco/examples/meas/mstone1.sh.skel.src
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2007-2009. All Rights Reserved.
+# Copyright Ericsson AB 2007-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -59,7 +59,7 @@ Options:
"
ERL_HOME=<path to otp top dir>
-MEGACO_HOME=$ERL_HOME/lib/erlang/lib/<megaco dir>
+MEGACO_HOME=$ERL_HOME/lib/erlang/lib/megaco-%VSN%
MEAS_HOME=$MEGACO_HOME/examples/meas
PATH=$ERL_HOME/bin:$PATH
diff --git a/lib/megaco/src/app/megaco.appup.src b/lib/megaco/src/app/megaco.appup.src
index 01b070d79f..7f6fe0c733 100644
--- a/lib/megaco/src/app/megaco.appup.src
+++ b/lib/megaco/src/app/megaco.appup.src
@@ -136,10 +136,24 @@
%% |
%% v
%% 3.15.1
+%% |
+%% v
+%% 3.15.1.1
+%% |
+%% v
+%% 3.15.1.2
%%
%%
{"%VSN%",
[
+ {"3.15.1.1",
+ [
+ ]
+ },
+ {"3.15.1",
+ [
+ ]
+ },
{"3.15",
[
{load_module, megaco_flex_scanner, soft_purge, soft_purge, []},
@@ -153,6 +167,14 @@
}
],
[
+ {"3.15.1.1",
+ [
+ ]
+ },
+ {"3.15.1",
+ [
+ ]
+ },
{"3.15",
[
{load_module, megaco_flex_scanner, soft_purge, soft_purge, []},
diff --git a/lib/megaco/src/binary/depend.mk b/lib/megaco/src/binary/depend.mk
index 5ec4977175..c9ca34bcf6 100644
--- a/lib/megaco/src/binary/depend.mk
+++ b/lib/megaco/src/binary/depend.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2009. All Rights Reserved.
+# Copyright Ericsson AB 2001-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -24,9 +24,9 @@
# but for per_bin it means that a stage in the encode
# is done in the asn1 driver.
#
-# +driver
+# +nif
# For ber_bin this means that part of the decode is done
-# in the asn1 driver.
+# in the asn1 nif.
#
# +asn1config
# This is only used by the ber_bin, and means that
@@ -45,22 +45,22 @@ endif
BER_V1_FLAGS = $(ASN1_CT_OPTS)
BER_BIN_V1_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize
-BER_BIN_DRV_V1_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +driver
+BER_BIN_DRV_V1_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +nif
BER_V2_FLAGS = $(ASN1_CT_OPTS)
BER_BIN_V2_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize
-BER_BIN_DRV_V2_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +driver
+BER_BIN_DRV_V2_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +nif
BER_PREV3A_FLAGS = $(ASN1_CT_OPTS)
BER_BIN_PREV3A_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize
-BER_BIN_DRV_PREV3A_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +driver
+BER_BIN_DRV_PREV3A_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +nif
BER_PREV3B_FLAGS = $(ASN1_CT_OPTS)
BER_BIN_PREV3B_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize
-BER_BIN_DRV_PREV3B_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +driver
+BER_BIN_DRV_PREV3B_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +nif
BER_PREV3C_FLAGS = $(ASN1_CT_OPTS)
BER_BIN_PREV3C_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize
-BER_BIN_DRV_PREV3C_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +driver
+BER_BIN_DRV_PREV3C_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +nif
BER_V3_FLAGS = $(ASN1_CT_OPTS)
BER_BIN_V3_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize
-BER_BIN_DRV_V3_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +driver
+BER_BIN_DRV_V3_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +nif
PER_V1_FLAGS = $(ASN1_CT_OPTS)
PER_BIN_V1_FLAGS = $(ASN1_CT_OPTS)
PER_BIN_DRV_V1_FLAGS = $(ASN1_CT_OPTS) +optimize
@@ -83,17 +83,16 @@ PER_BIN_DRV_V3_FLAGS = $(ASN1_CT_OPTS) +optimize
# --- Version 1 ---
-$(BER_ASN1_V1_SPEC).erl $(BER_ASN1_V1_SPEC).hrl: \
+$(BER_ASN1_V1_SPEC).erl: \
$(BER_ASN1_V1_SPEC).set.asn \
$(ASN1_V1_SPEC).asn
@echo "$(BER_ASN1_V1_SPEC):"
$(ERLC) -bber $(BER_V1_FLAGS) $(BER_ASN1_V1_SPEC).set.asn
$(EBIN)/$(BER_ASN1_V1_SPEC).$(EMULATOR): \
- $(BER_ASN1_V1_SPEC).erl \
- $(BER_ASN1_V1_SPEC).hrl
+ $(BER_ASN1_V1_SPEC).erl
-$(BER_BIN_ASN1_V1_SPEC).erl $(BER_BIN_ASN1_V1_SPEC).hrl: \
+$(BER_BIN_ASN1_V1_SPEC).erl: \
$(BER_BIN_ASN1_V1_SPEC).set.asn \
$(BER_BIN_ASN1_V1_SPEC).asn1config \
$(ASN1_V1_SPEC).asn
@@ -101,10 +100,9 @@ $(BER_BIN_ASN1_V1_SPEC).erl $(BER_BIN_ASN1_V1_SPEC).hrl: \
$(ERLC) -bber_bin $(BER_BIN_V1_FLAGS) $(BER_BIN_ASN1_V1_SPEC).set.asn
$(EBIN)/$(BER_BIN_ASN1_V1_SPEC).$(EMULATOR): \
- $(BER_BIN_ASN1_V1_SPEC).erl \
- $(BER_BIN_ASN1_V1_SPEC).hrl
+ $(BER_BIN_ASN1_V1_SPEC).erl
-$(BER_BIN_DRV_ASN1_V1_SPEC).erl $(BER_BIN_DRV_ASN1_V1_SPEC).hrl: \
+$(BER_BIN_DRV_ASN1_V1_SPEC).erl: \
$(BER_BIN_DRV_ASN1_V1_SPEC).set.asn \
$(BER_BIN_DRV_ASN1_V1_SPEC).asn1config \
$(ASN1_V1_SPEC).asn
@@ -112,53 +110,48 @@ $(BER_BIN_DRV_ASN1_V1_SPEC).erl $(BER_BIN_DRV_ASN1_V1_SPEC).hrl: \
$(ERLC) -bber_bin $(BER_BIN_DRV_V1_FLAGS) $(BER_BIN_DRV_ASN1_V1_SPEC).set.asn
$(EBIN)/$(BER_BIN_DRV_ASN1_V1_SPEC).$(EMULATOR): \
- $(BER_BIN_DRV_ASN1_V1_SPEC).erl \
- $(BER_BIN_DRV_ASN1_V1_SPEC).hrl
+ $(BER_BIN_DRV_ASN1_V1_SPEC).erl
-$(PER_ASN1_V1_SPEC).erl $(PER_ASN1_V1_SPEC).hrl: \
+$(PER_ASN1_V1_SPEC).erl: \
$(PER_ASN1_V1_SPEC).set.asn \
$(ASN1_V1_SPEC).asn
@echo "$(PER_ASN1_V1_SPEC):"
$(ERLC) -bper $(PER_V1_FLAGS) $(PER_ASN1_V1_SPEC).set.asn
$(EBIN)/$(PER_ASN1_V1_SPEC).$(EMULATOR): \
- $(PER_ASN1_V1_SPEC).erl \
- $(PER_ASN1_V1_SPEC).hrl
+ $(PER_ASN1_V1_SPEC).erl
-$(PER_BIN_ASN1_V1_SPEC).erl $(PER_BIN_ASN1_V1_SPEC).hrl: \
+$(PER_BIN_ASN1_V1_SPEC).erl: \
$(PER_BIN_ASN1_V1_SPEC).set.asn \
$(ASN1_V1_SPEC).asn
@echo "$(PER_BIN_ASN1_V1_SPEC):"
$(ERLC) -bper_bin $(PER_BIN_V1_FLAGS) $(PER_BIN_ASN1_V1_SPEC).set.asn
$(EBIN)/$(PER_BIN_ASN1_V1_SPEC).$(EMULATOR): \
- $(PER_BIN_ASN1_V1_SPEC).erl \
- $(PER_BIN_ASN1_V1_SPEC).hrl
+ $(PER_BIN_ASN1_V1_SPEC).erl
-$(PER_BIN_DRV_ASN1_V1_SPEC).erl $(PER_BIN_DRV_ASN1_V1_SPEC).hrl: \
+$(PER_BIN_DRV_ASN1_V1_SPEC).erl: \
$(PER_BIN_DRV_ASN1_V1_SPEC).set.asn \
$(ASN1_V1_SPEC).asn
@echo "$(PER_BIN_DRV_ASN1_V1_SPEC):"
$(ERLC) -bper_bin $(PER_BIN_DRV_V1_FLAGS) $(PER_BIN_DRV_ASN1_V1_SPEC).set.asn
$(EBIN)/$(PER_BIN_DRV_ASN1_V1_SPEC).$(EMULATOR): \
- $(PER_BIN_DRV_ASN1_V1_SPEC).erl \
- $(PER_BIN_DRV_ASN1_V1_SPEC).hrl
+ $(PER_BIN_DRV_ASN1_V1_SPEC).erl
# --- Version 2 ---
-$(BER_ASN1_V2_SPEC).erl $(BER_ASN1_V2_SPEC).hrl: \
+$(BER_ASN1_V2_SPEC).erl: \
$(BER_ASN1_V2_SPEC).set.asn \
$(ASN1_V2_SPEC).asn
@echo "$(BER_ASN1_V2_SPEC):"
$(ERLC) -bber $(BER_V2_FLAGS) $(BER_ASN1_V2_SPEC).set.asn
$(EBIN)/$(BER_ASN1_V2_SPEC).$(EMULATOR): \
- $(BER_ASN1_V2_SPEC).erl \
- $(BER_ASN1_V2_SPEC).hrl
+ $(BER_ASN1_V2_SPEC).erl
-$(BER_BIN_ASN1_V2_SPEC).erl $(BER_BIN_ASN1_V2_SPEC).hrl: \
+$(BER_BIN_ASN1_V2_SPEC).erl: \
$(BER_BIN_ASN1_V2_SPEC).set.asn \
$(BER_BIN_ASN1_V2_SPEC).asn1config \
$(ASN1_V2_SPEC).asn
@@ -166,10 +159,9 @@ $(BER_BIN_ASN1_V2_SPEC).erl $(BER_BIN_ASN1_V2_SPEC).hrl: \
$(ERLC) -bber_bin $(BER_BIN_V2_FLAGS) $(BER_BIN_ASN1_V2_SPEC).set.asn
$(EBIN)/$(BER_BIN_ASN1_V2_SPEC).$(EMULATOR): \
- $(BER_BIN_ASN1_V2_SPEC).erl \
- $(BER_BIN_ASN1_V2_SPEC).hrl
+ $(BER_BIN_ASN1_V2_SPEC).erl
-$(BER_BIN_DRV_ASN1_V2_SPEC).erl $(BER_BIN_DRV_ASN1_V2_SPEC).hrl: \
+$(BER_BIN_DRV_ASN1_V2_SPEC).erl: \
$(BER_BIN_DRV_ASN1_V2_SPEC).set.asn \
$(BER_BIN_DRV_ASN1_V2_SPEC).asn1config \
$(ASN1_V2_SPEC).asn
@@ -177,55 +169,50 @@ $(BER_BIN_DRV_ASN1_V2_SPEC).erl $(BER_BIN_DRV_ASN1_V2_SPEC).hrl: \
$(ERLC) -bber_bin $(BER_BIN_DRV_V2_FLAGS) $(BER_BIN_DRV_ASN1_V2_SPEC).set.asn
$(EBIN)/$(BER_BIN_DRV_ASN1_V2_SPEC).$(EMULATOR): \
- $(BER_BIN_DRV_ASN1_V2_SPEC).erl \
- $(BER_BIN_DRV_ASN1_V2_SPEC).hrl
+ $(BER_BIN_DRV_ASN1_V2_SPEC).erl
-$(PER_ASN1_V2_SPEC).erl $(PER_ASN1_V2_SPEC).hrl: \
+$(PER_ASN1_V2_SPEC).erl: \
$(PER_ASN1_V2_SPEC).set.asn \
$(ASN1_V2_SPEC).asn
@echo "$(PER_ASN1_V2_SPEC):"
$(ERLC) -bper $(PER_V2_FLAGS) $(PER_ASN1_V2_SPEC).set.asn
$(EBIN)/$(PER_ASN1_V2_SPEC).$(EMULATOR): \
- $(PER_ASN1_V2_SPEC).erl \
- $(PER_ASN1_V2_SPEC).hrl
+ $(PER_ASN1_V2_SPEC).erl
-$(PER_BIN_ASN1_V2_SPEC).erl $(PER_BIN_ASN1_V2_SPEC).hrl: \
+$(PER_BIN_ASN1_V2_SPEC).erl: \
$(PER_BIN_ASN1_V2_SPEC).set.asn \
$(ASN1_V2_SPEC).asn
@echo "$(PER_BIN_ASN1_V2_SPEC):"
$(ERLC) -bper_bin $(PER_BIN_V2_FLAGS) $(PER_BIN_ASN1_V2_SPEC).set.asn
$(EBIN)/$(PER_BIN_ASN1_V2_SPEC).$(EMULATOR): \
- $(PER_BIN_ASN1_V2_SPEC).erl \
- $(PER_BIN_ASN1_V2_SPEC).hrl
+ $(PER_BIN_ASN1_V2_SPEC).erl
-$(PER_BIN_DRV_ASN1_V2_SPEC).erl $(PER_BIN_DRV_ASN1_V2_SPEC).hrl: \
+$(PER_BIN_DRV_ASN1_V2_SPEC).erl: \
$(PER_BIN_DRV_ASN1_V2_SPEC).set.asn \
$(ASN1_V2_SPEC).asn
@echo "$(PER_BIN_DRV_ASN1_V2_SPEC):"
$(ERLC) -bper_bin $(PER_BIN_DRV_V2_FLAGS) $(PER_BIN_DRV_ASN1_V2_SPEC).set.asn
$(EBIN)/$(PER_BIN_DRV_ASN1_V2_SPEC).$(EMULATOR): \
- $(PER_BIN_DRV_ASN1_V2_SPEC).erl \
- $(PER_BIN_DRV_ASN1_V2_SPEC).hrl
+ $(PER_BIN_DRV_ASN1_V2_SPEC).erl
# --- Version 3 ---
# -- (prev3a) --
-$(BER_ASN1_PREV3A_SPEC).erl $(BER_ASN1_PREV3A_SPEC).hrl: \
+$(BER_ASN1_PREV3A_SPEC).erl: \
$(BER_ASN1_PREV3A_SPEC).set.asn \
$(ASN1_PREV3A_SPEC).asn
@echo "$(BER_ASN1_PREV3A_SPEC):"
$(ERLC) -bber $(BER_PREV3A_FLAGS) $(BER_ASN1_PREV3A_SPEC).set.asn
$(EBIN)/$(BER_ASN1_PREV3A_SPEC).$(EMULATOR): \
- $(BER_ASN1_PREV3A_SPEC).erl \
- $(BER_ASN1_PREV3A_SPEC).hrl
+ $(BER_ASN1_PREV3A_SPEC).erl
-$(BER_BIN_ASN1_PREV3A_SPEC).erl $(BER_BIN_ASN1_PREV3A_SPEC).hrl: \
+$(BER_BIN_ASN1_PREV3A_SPEC).erl: \
$(BER_BIN_ASN1_PREV3A_SPEC).set.asn \
$(BER_BIN_ASN1_PREV3A_SPEC).asn1config \
$(ASN1_PREV3A_SPEC).asn
@@ -233,10 +220,9 @@ $(BER_BIN_ASN1_PREV3A_SPEC).erl $(BER_BIN_ASN1_PREV3A_SPEC).hrl: \
$(ERLC) -bber_bin $(BER_BIN_PREV3A_FLAGS) $(BER_BIN_ASN1_PREV3A_SPEC).set.asn
$(EBIN)/$(BER_BIN_ASN1_PREV3A_SPEC).$(EMULATOR): \
- $(BER_BIN_ASN1_PREV3A_SPEC).erl \
- $(BER_BIN_ASN1_PREV3A_SPEC).hrl
+ $(BER_BIN_ASN1_PREV3A_SPEC).erl
-$(BER_BIN_DRV_ASN1_PREV3A_SPEC).erl $(BER_BIN_DRV_ASN1_PREV3A_SPEC).hrl: \
+$(BER_BIN_DRV_ASN1_PREV3A_SPEC).erl: \
$(BER_BIN_DRV_ASN1_PREV3A_SPEC).set.asn \
$(BER_BIN_DRV_ASN1_PREV3A_SPEC).asn1config \
$(ASN1_PREV3A_SPEC).asn
@@ -244,52 +230,47 @@ $(BER_BIN_DRV_ASN1_PREV3A_SPEC).erl $(BER_BIN_DRV_ASN1_PREV3A_SPEC).hrl: \
$(ERLC) -bber_bin $(BER_BIN_DRV_PREV3A_FLAGS) $(BER_BIN_DRV_ASN1_PREV3A_SPEC).set.asn
$(EBIN)/$(BER_BIN_DRV_ASN1_PREV3A_SPEC).$(EMULATOR): \
- $(BER_BIN_DRV_ASN1_PREV3A_SPEC).erl \
- $(BER_BIN_DRV_ASN1_PREV3A_SPEC).hrl
+ $(BER_BIN_DRV_ASN1_PREV3A_SPEC).erl
-$(PER_ASN1_PREV3A_SPEC).erl $(PER_ASN1_PREV3A_SPEC).hrl: \
+$(PER_ASN1_PREV3A_SPEC).erl: \
$(PER_ASN1_PREV3A_SPEC).set.asn \
$(ASN1_PREV3A_SPEC).asn
@echo "$(PER_ASN1_PREV3A_SPEC):"
$(ERLC) -bper $(PER_PREV3A_FLAGS) $(PER_ASN1_PREV3A_SPEC).set.asn
$(EBIN)/$(PER_ASN1_PREV3A_SPEC).$(EMULATOR): \
- $(PER_ASN1_PREV3A_SPEC).erl \
- $(PER_ASN1_PREV3A_SPEC).hrl
+ $(PER_ASN1_PREV3A_SPEC).erl
-$(PER_BIN_ASN1_PREV3A_SPEC).erl $(PER_BIN_ASN1_PREV3A_SPEC).hrl: \
+$(PER_BIN_ASN1_PREV3A_SPEC).erl: \
$(PER_BIN_ASN1_PREV3A_SPEC).set.asn \
$(ASN1_PREV3A_SPEC).asn
@echo "$(PER_BIN_ASN1_PREV3A_SPEC):"
$(ERLC) -bper_bin $(PER_BIN_PREV3A_FLAGS) $(PER_BIN_ASN1_PREV3A_SPEC).set.asn
$(EBIN)/$(PER_BIN_ASN1_PREV3A_SPEC).$(EMULATOR): \
- $(PER_BIN_ASN1_PREV3A_SPEC).erl \
- $(PER_BIN_ASN1_PREV3A_SPEC).hrl
+ $(PER_BIN_ASN1_PREV3A_SPEC).erl
-$(PER_BIN_DRV_ASN1_PREV3A_SPEC).erl $(PER_BIN_DRV_ASN1_PREV3A_SPEC).hrl: \
+$(PER_BIN_DRV_ASN1_PREV3A_SPEC).erl: \
$(PER_BIN_DRV_ASN1_PREV3A_SPEC).set.asn \
$(ASN1_PREV3A_SPEC).asn
@echo "$(PER_BIN_DRV_ASN1_PREV3A_SPEC):"
$(ERLC) -bper_bin $(PER_BIN_DRV_PREV3A_FLAGS) $(PER_BIN_DRV_ASN1_PREV3A_SPEC).set.asn
$(EBIN)/$(PER_BIN_DRV_ASN1_PREV3A_SPEC).$(EMULATOR): \
- $(PER_BIN_DRV_ASN1_PREV3A_SPEC).erl \
- $(PER_BIN_DRV_ASN1_PREV3A_SPEC).hrl
+ $(PER_BIN_DRV_ASN1_PREV3A_SPEC).erl
# -- (prev3b) --
-$(BER_ASN1_PREV3B_SPEC).erl $(BER_ASN1_PREV3B_SPEC).hrl: \
+$(BER_ASN1_PREV3B_SPEC).erl: \
$(BER_ASN1_PREV3B_SPEC).set.asn \
$(ASN1_PREV3B_SPEC).asn
@echo "$(BER_ASN1_PREV3B_SPEC):"
$(ERLC) -bber $(BER_PREV3B_FLAGS) $(BER_ASN1_PREV3B_SPEC).set.asn
$(EBIN)/$(BER_ASN1_PREV3B_SPEC).$(EMULATOR): \
- $(BER_ASN1_PREV3B_SPEC).erl \
- $(BER_ASN1_PREV3B_SPEC).hrl
+ $(BER_ASN1_PREV3B_SPEC).erl
-$(BER_BIN_ASN1_PREV3B_SPEC).erl $(BER_BIN_ASN1_PREV3B_SPEC).hrl: \
+$(BER_BIN_ASN1_PREV3B_SPEC).erl: \
$(BER_BIN_ASN1_PREV3B_SPEC).set.asn \
$(BER_BIN_ASN1_PREV3B_SPEC).asn1config \
$(ASN1_PREV3B_SPEC).asn
@@ -297,10 +278,9 @@ $(BER_BIN_ASN1_PREV3B_SPEC).erl $(BER_BIN_ASN1_PREV3B_SPEC).hrl: \
$(ERLC) -bber_bin $(BER_BIN_PREV3B_FLAGS) $(BER_BIN_ASN1_PREV3B_SPEC).set.asn
$(EBIN)/$(BER_BIN_ASN1_PREV3B_SPEC).$(EMULATOR): \
- $(BER_BIN_ASN1_PREV3B_SPEC).erl \
- $(BER_BIN_ASN1_PREV3B_SPEC).hrl
+ $(BER_BIN_ASN1_PREV3B_SPEC).erl
-$(BER_BIN_DRV_ASN1_PREV3B_SPEC).erl $(BER_BIN_DRV_ASN1_PREV3B_SPEC).hrl: \
+$(BER_BIN_DRV_ASN1_PREV3B_SPEC).erl: \
$(BER_BIN_DRV_ASN1_PREV3B_SPEC).set.asn \
$(BER_BIN_DRV_ASN1_PREV3B_SPEC).asn1config \
$(ASN1_PREV3B_SPEC).asn
@@ -308,53 +288,48 @@ $(BER_BIN_DRV_ASN1_PREV3B_SPEC).erl $(BER_BIN_DRV_ASN1_PREV3B_SPEC).hrl: \
$(ERLC) -bber_bin $(BER_BIN_DRV_PREV3B_FLAGS) $(BER_BIN_DRV_ASN1_PREV3B_SPEC).set.asn
$(EBIN)/$(BER_BIN_DRV_ASN1_PREV3B_SPEC).$(EMULATOR): \
- $(BER_BIN_DRV_ASN1_PREV3B_SPEC).erl \
- $(BER_BIN_DRV_ASN1_PREV3B_SPEC).hrl
+ $(BER_BIN_DRV_ASN1_PREV3B_SPEC).erl
-$(PER_ASN1_PREV3B_SPEC).erl $(PER_ASN1_PREV3B_SPEC).hrl: \
+$(PER_ASN1_PREV3B_SPEC).erl: \
$(PER_ASN1_PREV3B_SPEC).set.asn \
$(ASN1_PREV3B_SPEC).asn
@echo "$(PER_ASN1_PREV3B_SPEC):"
$(ERLC) -bper $(PER_PREV3B_FLAGS) $(PER_ASN1_PREV3B_SPEC).set.asn
$(EBIN)/$(PER_ASN1_PREV3B_SPEC).$(EMULATOR): \
- $(PER_ASN1_PREV3B_SPEC).erl \
- $(PER_ASN1_PREV3B_SPEC).hrl
+ $(PER_ASN1_PREV3B_SPEC).erl
-$(PER_BIN_ASN1_PREV3B_SPEC).erl $(PER_BIN_ASN1_PREV3B_SPEC).hrl: \
+$(PER_BIN_ASN1_PREV3B_SPEC).erl: \
$(PER_BIN_ASN1_PREV3B_SPEC).set.asn \
$(ASN1_PREV3B_SPEC).asn
@echo "$(PER_BIN_ASN1_PREV3B_SPEC):"
$(ERLC) -bper_bin $(PER_BIN_PREV3B_FLAGS) $(PER_BIN_ASN1_PREV3B_SPEC).set.asn
$(EBIN)/$(PER_BIN_ASN1_PREV3B_SPEC).$(EMULATOR): \
- $(PER_BIN_ASN1_PREV3B_SPEC).erl \
- $(PER_BIN_ASN1_PREV3B_SPEC).hrl
+ $(PER_BIN_ASN1_PREV3B_SPEC).erl
-$(PER_BIN_DRV_ASN1_PREV3B_SPEC).erl $(PER_BIN_DRV_ASN1_PREV3B_SPEC).hrl: \
+$(PER_BIN_DRV_ASN1_PREV3B_SPEC).erl: \
$(PER_BIN_DRV_ASN1_PREV3B_SPEC).set.asn \
$(ASN1_PREV3B_SPEC).asn
@echo "$(PER_BIN_DRV_ASN1_PREV3B_SPEC):"
$(ERLC) -bper_bin $(PER_BIN_DRV_PREV3B_FLAGS) $(PER_BIN_DRV_ASN1_PREV3B_SPEC).set.asn
$(EBIN)/$(PER_BIN_DRV_ASN1_PREV3B_SPEC).$(EMULATOR): \
- $(PER_BIN_DRV_ASN1_PREV3B_SPEC).erl \
- $(PER_BIN_DRV_ASN1_PREV3B_SPEC).hrl
+ $(PER_BIN_DRV_ASN1_PREV3B_SPEC).erl
# -- (prev3c) --
-$(BER_ASN1_PREV3C_SPEC).erl $(BER_ASN1_PREV3C_SPEC).hrl: \
+$(BER_ASN1_PREV3C_SPEC).erl: \
$(BER_ASN1_PREV3C_SPEC).set.asn \
$(ASN1_PREV3C_SPEC).asn
@echo "$(BER_ASN1_PREV3C_SPEC):"
$(ERLC) -bber $(BER_PREV3C_FLAGS) $(BER_ASN1_PREV3C_SPEC).set.asn
$(EBIN)/$(BER_ASN1_PREV3C_SPEC).$(EMULATOR): \
- $(BER_ASN1_PREV3C_SPEC).erl \
- $(BER_ASN1_PREV3C_SPEC).hrl
+ $(BER_ASN1_PREV3C_SPEC).erl
-$(BER_BIN_ASN1_PREV3C_SPEC).erl $(BER_BIN_ASN1_PREV3C_SPEC).hrl: \
+$(BER_BIN_ASN1_PREV3C_SPEC).erl: \
$(BER_BIN_ASN1_PREV3C_SPEC).set.asn \
$(BER_BIN_ASN1_PREV3C_SPEC).asn1config \
$(ASN1_PREV3C_SPEC).asn
@@ -362,10 +337,9 @@ $(BER_BIN_ASN1_PREV3C_SPEC).erl $(BER_BIN_ASN1_PREV3C_SPEC).hrl: \
$(ERLC) -bber_bin $(BER_BIN_PREV3C_FLAGS) $(BER_BIN_ASN1_PREV3C_SPEC).set.asn
$(EBIN)/$(BER_BIN_ASN1_PREV3C_SPEC).$(EMULATOR): \
- $(BER_BIN_ASN1_PREV3C_SPEC).erl \
- $(BER_BIN_ASN1_PREV3C_SPEC).hrl
+ $(BER_BIN_ASN1_PREV3C_SPEC).erl
-$(BER_BIN_DRV_ASN1_PREV3C_SPEC).erl $(BER_BIN_DRV_ASN1_PREV3C_SPEC).hrl: \
+$(BER_BIN_DRV_ASN1_PREV3C_SPEC).erl: \
$(BER_BIN_DRV_ASN1_PREV3C_SPEC).set.asn \
$(BER_BIN_DRV_ASN1_PREV3C_SPEC).asn1config \
$(ASN1_PREV3C_SPEC).asn
@@ -373,53 +347,48 @@ $(BER_BIN_DRV_ASN1_PREV3C_SPEC).erl $(BER_BIN_DRV_ASN1_PREV3C_SPEC).hrl: \
$(ERLC) -bber_bin $(BER_BIN_DRV_PREV3C_FLAGS) $(BER_BIN_DRV_ASN1_PREV3C_SPEC).set.asn
$(EBIN)/$(BER_BIN_DRV_ASN1_PREV3C_SPEC).$(EMULATOR): \
- $(BER_BIN_DRV_ASN1_PREV3C_SPEC).erl \
- $(BER_BIN_DRV_ASN1_PREV3C_SPEC).hrl
+ $(BER_BIN_DRV_ASN1_PREV3C_SPEC).erl
-$(PER_ASN1_PREV3C_SPEC).erl $(PER_ASN1_PREV3C_SPEC).hrl: \
+$(PER_ASN1_PREV3C_SPEC).erl: \
$(PER_ASN1_PREV3C_SPEC).set.asn \
$(ASN1_PREV3C_SPEC).asn
@echo "$(PER_ASN1_PREV3C_SPEC):"
$(ERLC) -bper $(PER_PREV3C_FLAGS) $(PER_ASN1_PREV3C_SPEC).set.asn
$(EBIN)/$(PER_ASN1_PREV3C_SPEC).$(EMULATOR): \
- $(PER_ASN1_PREV3C_SPEC).erl \
- $(PER_ASN1_PREV3C_SPEC).hrl
+ $(PER_ASN1_PREV3C_SPEC).erl
-$(PER_BIN_ASN1_PREV3C_SPEC).erl $(PER_BIN_ASN1_PREV3C_SPEC).hrl: \
+$(PER_BIN_ASN1_PREV3C_SPEC).erl: \
$(PER_BIN_ASN1_PREV3C_SPEC).set.asn \
$(ASN1_PREV3C_SPEC).asn
@echo "$(PER_BIN_ASN1_PREV3C_SPEC):"
$(ERLC) -bper_bin $(PER_BIN_PREV3C_FLAGS) $(PER_BIN_ASN1_PREV3C_SPEC).set.asn
$(EBIN)/$(PER_BIN_ASN1_PREV3C_SPEC).$(EMULATOR): \
- $(PER_BIN_ASN1_PREV3C_SPEC).erl \
- $(PER_BIN_ASN1_PREV3C_SPEC).hrl
+ $(PER_BIN_ASN1_PREV3C_SPEC).erl
-$(PER_BIN_DRV_ASN1_PREV3C_SPEC).erl $(PER_BIN_DRV_ASN1_PREV3C_SPEC).hrl: \
+$(PER_BIN_DRV_ASN1_PREV3C_SPEC).erl: \
$(PER_BIN_DRV_ASN1_PREV3C_SPEC).set.asn \
$(ASN1_PREV3C_SPEC).asn
@echo "$(PER_BIN_DRV_ASN1_PREV3C_SPEC):"
$(ERLC) -bper_bin $(PER_BIN_DRV_PREV3C_FLAGS) $(PER_BIN_DRV_ASN1_PREV3C_SPEC).set.asn
$(EBIN)/$(PER_BIN_DRV_ASN1_PREV3C_SPEC).$(EMULATOR): \
- $(PER_BIN_DRV_ASN1_PREV3C_SPEC).erl \
- $(PER_BIN_DRV_ASN1_PREV3C_SPEC).hrl
+ $(PER_BIN_DRV_ASN1_PREV3C_SPEC).erl
# -- (v3) --
-$(BER_ASN1_V3_SPEC).erl $(BER_ASN1_V3_SPEC).hrl: \
+$(BER_ASN1_V3_SPEC).erl: \
$(BER_ASN1_V3_SPEC).set.asn \
$(ASN1_V3_SPEC).asn
@echo "$(BER_ASN1_V3_SPEC):"
$(ERLC) -bber $(BER_V3_FLAGS) $(BER_ASN1_V3_SPEC).set.asn
$(EBIN)/$(BER_ASN1_V3_SPEC).$(EMULATOR): \
- $(BER_ASN1_V3_SPEC).erl \
- $(BER_ASN1_V3_SPEC).hrl
+ $(BER_ASN1_V3_SPEC).erl
-$(BER_BIN_ASN1_V3_SPEC).erl $(BER_BIN_ASN1_V3_SPEC).hrl: \
+$(BER_BIN_ASN1_V3_SPEC).erl: \
$(BER_BIN_ASN1_V3_SPEC).set.asn \
$(BER_BIN_ASN1_V3_SPEC).asn1config \
$(ASN1_V3_SPEC).asn
@@ -427,10 +396,9 @@ $(BER_BIN_ASN1_V3_SPEC).erl $(BER_BIN_ASN1_V3_SPEC).hrl: \
$(ERLC) -bber_bin $(BER_BIN_V3_FLAGS) $(BER_BIN_ASN1_V3_SPEC).set.asn
$(EBIN)/$(BER_BIN_ASN1_V3_SPEC).$(EMULATOR): \
- $(BER_BIN_ASN1_V3_SPEC).erl \
- $(BER_BIN_ASN1_V3_SPEC).hrl
+ $(BER_BIN_ASN1_V3_SPEC).erl
-$(BER_BIN_DRV_ASN1_V3_SPEC).erl $(BER_BIN_DRV_ASN1_V3_SPEC).hrl: \
+$(BER_BIN_DRV_ASN1_V3_SPEC).erl: \
$(BER_BIN_DRV_ASN1_V3_SPEC).set.asn \
$(BER_BIN_DRV_ASN1_V3_SPEC).asn1config \
$(ASN1_V3_SPEC).asn
@@ -438,38 +406,34 @@ $(BER_BIN_DRV_ASN1_V3_SPEC).erl $(BER_BIN_DRV_ASN1_V3_SPEC).hrl: \
$(ERLC) -bber_bin $(BER_BIN_DRV_V3_FLAGS) $(BER_BIN_DRV_ASN1_V3_SPEC).set.asn
$(EBIN)/$(BER_BIN_DRV_ASN1_V3_SPEC).$(EMULATOR): \
- $(BER_BIN_DRV_ASN1_V3_SPEC).erl \
- $(BER_BIN_DRV_ASN1_V3_SPEC).hrl
+ $(BER_BIN_DRV_ASN1_V3_SPEC).erl
-$(PER_ASN1_V3_SPEC).erl $(PER_ASN1_V3_SPEC).hrl: \
+$(PER_ASN1_V3_SPEC).erl: \
$(PER_ASN1_V3_SPEC).set.asn \
$(ASN1_V3_SPEC).asn
@echo "$(PER_ASN1_V3_SPEC):"
$(ERLC) -bper $(PER_V3_FLAGS) $(PER_ASN1_V3_SPEC).set.asn
$(EBIN)/$(PER_ASN1_V3_SPEC).$(EMULATOR): \
- $(PER_ASN1_V3_SPEC).erl \
- $(PER_ASN1_V3_SPEC).hrl
+ $(PER_ASN1_V3_SPEC).erl
-$(PER_BIN_ASN1_V3_SPEC).erl $(PER_BIN_ASN1_V3_SPEC).hrl: \
+$(PER_BIN_ASN1_V3_SPEC).erl: \
$(PER_BIN_ASN1_V3_SPEC).set.asn \
$(ASN1_V3_SPEC).asn
@echo "$(PER_BIN_ASN1_V3_SPEC):"
$(ERLC) -bper_bin $(PER_BIN_V3_FLAGS) $(PER_BIN_ASN1_V3_SPEC).set.asn
$(EBIN)/$(PER_BIN_ASN1_V3_SPEC).$(EMULATOR): \
- $(PER_BIN_ASN1_V3_SPEC).erl \
- $(PER_BIN_ASN1_V3_SPEC).hrl
+ $(PER_BIN_ASN1_V3_SPEC).erl
-$(PER_BIN_DRV_ASN1_V3_SPEC).erl $(PER_BIN_DRV_ASN1_V3_SPEC).hrl: \
+$(PER_BIN_DRV_ASN1_V3_SPEC).erl: \
$(PER_BIN_DRV_ASN1_V3_SPEC).set.asn \
$(ASN1_V3_SPEC).asn
@echo "$(PER_BIN_DRV_ASN1_V3_SPEC):"
$(ERLC) -bper_bin $(PER_BIN_DRV_V3_FLAGS) $(PER_BIN_DRV_ASN1_V3_SPEC).set.asn
$(EBIN)/$(PER_BIN_DRV_ASN1_V3_SPEC).$(EMULATOR): \
- $(PER_BIN_DRV_ASN1_V3_SPEC).erl \
- $(PER_BIN_DRV_ASN1_V3_SPEC).hrl
+ $(PER_BIN_DRV_ASN1_V3_SPEC).erl
# -------------
diff --git a/lib/megaco/src/flex/Makefile.in b/lib/megaco/src/flex/Makefile.in
index 5af651d89b..2c46a673e4 100644
--- a/lib/megaco/src/flex/Makefile.in
+++ b/lib/megaco/src/flex/Makefile.in
@@ -391,7 +391,9 @@ $(STD_DRV).c: $(STD_DRV).flex
$(MT_DRV).c: $(MT_DRV).flex
$(LEX) $(MT_LEX_FLAGS) -P$* -o$@ $<
-solibs: $(LIBDIR) $(OBJDIR) $(SOLIBS)
+_create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR))
+
+solibs: $(SOLIBS)
$(OBJDIR)/$(STD_DRV).o: $(STD_DRV).c
@echo "compiling std driver:"
@@ -411,10 +413,3 @@ $(LIBDIR)/$(STD_DRV).$(DED_EXT): $(OBJDIR)/$(STD_DRV).o
$(LIBDIR)/$(MT_DRV).$(DED_EXT): $(OBJDIR)/$(MT_DRV).o
@echo "linking multi-threaded driver:"
$(LD) $(LDFLAGS) -o $@ $<
-
-$(LIBDIR):
- -mkdir -p $(LIBDIR)
-
-$(OBJDIR):
- -mkdir -p $(OBJDIR)
-
diff --git a/lib/megaco/test/megaco_codec_v1_test.erl b/lib/megaco/test/megaco_codec_v1_test.erl
index 3a548c4d9e..e9c19605dd 100644
--- a/lib/megaco/test/megaco_codec_v1_test.erl
+++ b/lib/megaco/test/megaco_codec_v1_test.erl
@@ -371,9 +371,9 @@ profile_decode_text_messages(Slogan, Codec, Config, Msgs0) ->
decode_text_messages(Codec, Config, Bins, [])
end,
%% Make a dry run, just to make sure all modules are loaded:
- io:format("make a dry run..~n", []),
+ io:format("make a dry run...~n", []),
(catch Fun()),
- io:format("make the run..~n", []),
+ io:format("make the run...~n", []),
megaco_profile:profile(Slogan, Fun).
%% (catch megaco_codec_v1_test:profile_encode_compact_text_messages()).
diff --git a/lib/megaco/test/megaco_codec_v2_test.erl b/lib/megaco/test/megaco_codec_v2_test.erl
index c3a80febba..1d3fcb36e9 100644
--- a/lib/megaco/test/megaco_codec_v2_test.erl
+++ b/lib/megaco/test/megaco_codec_v2_test.erl
@@ -346,9 +346,9 @@ profile_decode_text_messages(Slogan, Codec, Config, Msgs0) ->
decode_text_messages(Codec, Config, Bins, [])
end,
%% Make a dry run, just to make sure all modules are loaded:
- io:format("make a dry run..~n", []),
+ io:format("make a dry run...~n", []),
(catch Fun()),
- io:format("make the run..~n", []),
+ io:format("make the run...~n", []),
megaco_profile:profile(Slogan, Fun).
%% (catch megaco_codec_v2_test:profile_encode_compact_text_messages()).
diff --git a/lib/megaco/test/megaco_mess_test.erl b/lib/megaco/test/megaco_mess_test.erl
index ded1506271..383e3df774 100644
--- a/lib/megaco/test/megaco_mess_test.erl
+++ b/lib/megaco/test/megaco_mess_test.erl
@@ -34,12 +34,12 @@
%% -compile(export_all).
-export([
- all/0,groups/0,init_per_group/2,end_per_group/2,
- init_per_testcase/2,
- end_per_testcase/2,
+ all/0, groups/0,
+ init_per_suite/1, end_per_suite/1,
+ init_per_group/2, end_per_group/2,
+ init_per_testcase/2, end_per_testcase/2,
connect/1,
-
request_and_reply_plain/1,
request_and_no_reply/1,
@@ -347,39 +347,83 @@ end_per_testcase(Case, Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
all() ->
- [connect, {group, request_and_reply},
- {group, pending_ack}, dist, {group, tickets}].
+ [
+ connect,
+ {group, request_and_reply},
+ {group, pending_ack},
+ dist,
+ {group, tickets}
+ ].
groups() ->
- [{request_and_reply, [],
- [request_and_reply_plain, request_and_no_reply,
+ [
+ {request_and_reply, [],
+ [request_and_reply_plain,
+ request_and_no_reply,
request_and_reply_pending_ack_no_pending,
request_and_reply_pending_ack_one_pending,
single_trans_req_and_reply,
single_trans_req_and_reply_sendopts,
- request_and_reply_and_ack, request_and_reply_and_no_ack,
+ request_and_reply_and_ack,
+ request_and_reply_and_no_ack,
request_and_reply_and_late_ack,
trans_req_and_reply_and_req]},
{pending_ack, [],
[pending_ack_plain,
request_and_pending_and_late_reply]},
{tickets, [],
- [otp_4359, otp_4836, otp_5805, otp_5881, otp_5887,
- otp_6253, otp_6275, otp_6276, {group, otp_6442},
- {group, otp_6865}, otp_7189, otp_7259, otp_7713,
- {group, otp_8183}, otp_8212]},
+ [otp_4359,
+ otp_4836,
+ otp_5805,
+ otp_5881,
+ otp_5887,
+ otp_6253,
+ otp_6275,
+ otp_6276,
+ {group, otp_6442},
+ {group, otp_6865},
+ otp_7189,
+ otp_7259,
+ otp_7713,
+ {group, otp_8183},
+ otp_8212]},
{otp_6442, [],
- [otp_6442_resend_request1, otp_6442_resend_request2,
- otp_6442_resend_reply1, otp_6442_resend_reply2]},
+ [otp_6442_resend_request1,
+ otp_6442_resend_request2,
+ otp_6442_resend_reply1,
+ otp_6442_resend_reply2]},
{otp_6865, [],
[otp_6865_request_and_reply_plain_extra1,
otp_6865_request_and_reply_plain_extra2]},
- {otp_8183, [], [otp_8183_request1]}].
+ {otp_8183, [], [otp_8183_request1]}
+ ].
+
+
+init_per_suite(Config) ->
+ io:format("~w:init_per_suite -> entry with"
+ "~n Config: ~p"
+ "~n", [?MODULE, Config]),
+ Config.
+
+end_per_suite(_Config) ->
+ io:format("~w:end_per_suite -> entry with"
+ "~n _Config: ~p"
+ "~n", [?MODULE, _Config]),
+ ok.
+
init_per_group(_GroupName, Config) ->
+ io:format("~w:init_per_group -> entry with"
+ "~n _GroupName: ~p"
+ "~n Config: ~p"
+ "~n", [?MODULE, _GroupName, Config]),
Config.
end_per_group(_GroupName, Config) ->
+ io:format("~w:end_per_group -> entry with"
+ "~n _GroupName: ~p"
+ "~n Config: ~p"
+ "~n", [?MODULE, _GroupName, Config]),
Config.
@@ -394,12 +438,16 @@ connect(Config) when is_list(Config) ->
PrelMid = preliminary_mid,
MgMid = ipv4_mid(4711),
+ d("connect -> start megaco app",[]),
?VERIFY(ok, application:start(megaco)),
+ d("connect -> start (MG) user ~p",[MgMid]),
?VERIFY(ok, megaco:start_user(MgMid, [{send_mod, bad_send_mod},
{request_timer, infinity},
{reply_timer, infinity}])),
+ d("connect -> get receive info for ~p",[MgMid]),
MgRH = user_info(MgMid, receive_handle),
+ d("connect -> (MG) try connect to MGC",[]),
{ok, PrelCH} = ?VERIFY({ok, _}, megaco:connect(MgRH, PrelMid, sh, self())),
connections([PrelCH]),
@@ -6776,16 +6824,12 @@ rapalr_mg_notify_request_ar(Rid, Tid, Cid) ->
-
-
-
-
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
dist(suite) ->
[];
dist(Config) when is_list(Config) ->
+ ?SKIP("Needs a re-write..."),
[_Local, Dist] = ?ACQUIRE_NODES(2, Config),
d("dist -> start proxy",[]),
megaco_mess_user_test:start_proxy(),
@@ -6897,7 +6941,11 @@ dist(Config) when is_list(Config) ->
?VERIFY(ok, application:stop(megaco)),
?RECEIVE([]),
- d("dist -> done",[]),
+
+ d("dist -> stop proxy",[]),
+ megaco_mess_user_test:stop_proxy(),
+
+ d("dist -> done", []),
ok.
diff --git a/lib/megaco/test/megaco_profile.erl b/lib/megaco/test/megaco_profile.erl
index d0b62610e1..344c551970 100644
--- a/lib/megaco/test/megaco_profile.erl
+++ b/lib/megaco/test/megaco_profile.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -24,50 +24,102 @@
-module(megaco_profile).
--export([profile/2]).
-
+-export([profile/2, prepare/2, analyse/1,
+ fprof_to_calltree/1, fprof_to_calltree/2, fprof_to_calltree/3]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Execute Fun and profile it with fprof.
-profile(Slogan, Fun) when is_function(Fun) ->
+profile(Slogan, Fun) when is_function(Fun, 0) ->
Pids = [self()],
- profile(Slogan, Fun, Pids).
+ {ok, TraceFile} = prepare(Slogan, Pids),
+ Res = (catch Fun()),
+ {ok, _DestFile} = analyse(Slogan),
+ ok = file:delete(TraceFile),
+ {ok, _TreeFile} = fprof_to_calltree(Slogan),
+ Res.
-profile(Slogan, Fun, Pids) ->
+%% Prepare for tracing
+prepare(Slogan, Pids) ->
TraceFile = lists:concat(["profile_", Slogan, "-fprof.trace"]),
- DestFile = lists:concat(["profile_", Slogan, ".fprof"]),
- TreeFile = lists:concat(["profile_", Slogan, ".calltree"]),
- erlang:garbage_collect(),
{ok, _Pid} = fprof:start(),
+ erlang:garbage_collect(),
TraceOpts = [start,
- {cpu_time, false},
- {procs, Pids},
- {file, TraceFile}
+ {cpu_time, false},
+ {procs, Pids},
+ {file, TraceFile}
],
- ok = fprof:trace(TraceOpts),
- Res = (catch Fun()),
- ok = fprof:trace(stop),
- ok = fprof:profile([{file, TraceFile}]),
- ok = fprof:analyse([{dest, DestFile}]),
- ok = fprof:stop(),
- ok = file:delete(TraceFile),
- reformat_total(DestFile, TreeFile),
- Res.
+ ok = fprof:trace(TraceOpts),
+ {ok, TraceFile}.
-reformat_total(FromFile, ToFile) ->
- {ok, ConsultedFromFile} = file:consult(FromFile),
- [_AnalysisOpts, [Totals] | Terms] = ConsultedFromFile,
- {totals, _, TotalAcc, _} = Totals,
+%% Stop tracing and analyse it
+analyse(Slogan) ->
+ fprof:trace(stop),
+ TraceFile = lists:concat(["profile_", Slogan, "-fprof.trace"]),
+ DestFile = lists:concat(["profile_", Slogan, ".fprof"]),
+ try
+ case fprof:profile([{file, TraceFile}]) of
+ ok ->
+ ok = fprof:analyse([{dest, DestFile}, {totals, false}]),
+ {ok, DestFile};
+ {error, Reason} ->
+ {error, Reason}
+ end
+ after
+ fprof:stop()
+ end.
+
+fprof_to_calltree(Slogan) ->
+ fprof_to_calltree(Slogan, 0).
+
+fprof_to_calltree(Slogan, MinPercent) ->
+ DestFile = lists:concat(["profile_", Slogan, ".fprof"]),
+ TreeFile = lists:concat(["profile_", Slogan, ".calltree"]),
+ fprof_to_calltree(DestFile, TreeFile, MinPercent).
+
+%% Create a calltree from an fprof file
+fprof_to_calltree(FromFile, ToFile, MinPercent) ->
+ ReplyTo = self(),
+ Ref = make_ref(),
+ spawn_link(fun() ->
+ ReplyTo ! {Ref, do_fprof_to_calltree(FromFile, ToFile, MinPercent)}
+ end),
+ wait_for_reply(Ref).
+
+wait_for_reply(Ref) ->
+ receive
+ {Ref, Res} ->
+ Res;
+ {'EXIT', normal} ->
+ wait_for_reply(Ref);
+ {'EXIT', Reason} ->
+ exit(Reason)
+ end.
+
+do_fprof_to_calltree(FromFile, ToFile, MinPercent) ->
{ok, Fd} = file:open(ToFile, [write, raw]),
- Indent = "",
- log(Fd, Indent, TotalAcc, Totals),
- Processes = split_processes(Terms, [], []),
- Reformat = fun(P) -> reformat_process(Fd, " " ++ Indent, TotalAcc, P) end,
- lists:foreach(Reformat, Processes),
- file:close(Fd).
+ {ok, ConsultedFromFile} = file:consult(FromFile),
+ [_AnalysisOpts, [_Totals] | Terms] = ConsultedFromFile,
+ Processes = split_processes(Terms, [], []),
+ Indent = "",
+ Summary = collapse_processes(Processes),
+ {_Label, _Cnt, Acc, _Own, _Roots, Details} = Summary,
+ %% log(Fd, Label, Indent, Acc, {Label, Cnt, Acc, Own}, [], 0),
+ gen_calltree(Fd, Indent, Acc, Summary, MinPercent),
+ Delim = io_lib:format("\n~80..=c\n\n", [$=]),
+ Write =
+ fun(P) ->
+ file:write(Fd, Delim),
+ gen_calltree(Fd, Indent, Acc, P, MinPercent)
+ end,
+ lists:foreach(Write, Processes),
+ file:write(Fd, Delim),
+ gen_details(Fd, Acc, Details),
+ file:close(Fd),
+ {ok, ToFile}.
+%% Split all fprof terms into a list of processes
split_processes([H | T], ProcAcc, TotalAcc) ->
if
is_tuple(H) ->
@@ -75,64 +127,185 @@ split_processes([H | T], ProcAcc, TotalAcc) ->
is_list(H), ProcAcc =:= [] ->
split_processes(T, [H], TotalAcc);
is_list(H) ->
- split_processes(T, [H], [lists:reverse(ProcAcc) | TotalAcc])
+ ProcAcc2 = rearrange_process(lists:reverse(ProcAcc)),
+ split_processes(T, [H], [ProcAcc2 | TotalAcc])
end;
split_processes([], [], TotalAcc) ->
- lists:reverse(TotalAcc);
+ lists:reverse(lists:keysort(3, TotalAcc));
split_processes([], ProcAcc, TotalAcc) ->
- lists:reverse([lists:reverse(ProcAcc) | TotalAcc]).
-
-reformat_process(Fd, Indent, TotalAcc, Terms) ->
- case Terms of
- [[{ProcLabel, _, _, _}] | All] -> ok;
- [[{ProcLabel,_,_,_} | _] | All] -> ok
- end,
- [{_, {TopKey, TopCnt, TopAcc, TopOwn}, _} | _] = All,
- Process = {ProcLabel, TopCnt, TopAcc, TopOwn},
- log(Fd, Indent, TotalAcc, Process),
- reformat_calls(Fd, " " ++ Indent, TotalAcc, TopKey, All, []).
-
-reformat_calls(Fd, Indent, TotalAcc, Key, Terms, Stack) ->
- {_CalledBy, Current, Calls} = find(Key, Terms),
- log(Fd, Indent, TotalAcc, Current),
- case lists:member(Key, Stack) of
- true ->
- ok;
- false ->
- case Key of
- {io_lib, _, _} ->
- ok;
- {disk_log, _, _} ->
- ok;
- {lists, flatten, _} ->
- ok;
- {lists, keysort, _} ->
- ok;
- _ ->
- Fun = fun({NextKey, _, _, _}) ->
- reformat_calls(Fd,
- " " ++ Indent,
- TotalAcc,
- NextKey,
- Terms,
- [Key | Stack])
- end,
- lists:foreach(Fun, Calls)
- end
+ ProcAcc2 = rearrange_process(lists:reverse(ProcAcc)),
+ lists:reverse(lists:keysort(3, [ProcAcc2 | TotalAcc])).
+
+%% Rearrange the raw process list into a more useful format
+rearrange_process([[{Label, _Cnt, _Acc, _Own} | _ ] | Details]) ->
+ do_rearrange_process(Details, Details, Label, [], []).
+
+do_rearrange_process([{CalledBy, Current, _Calls} | T], Orig, Label, Roots, Undefs) ->
+ case [{undefined, Cnt, safe_max(Acc, Own), Own} ||
+ {undefined, Cnt, Acc, Own} <- CalledBy] of
+ [] ->
+ do_rearrange_process(T, Orig, Label, Roots, Undefs);
+ NewUndefs ->
+ do_rearrange_process(T, Orig, Label, [Current | Roots], NewUndefs ++ Undefs)
+ end;
+do_rearrange_process([], Details, Label, Roots, Undefs) ->
+ [{undefined, Cnt, Acc, Own}] = collapse_calls(Undefs, []),
+ Details2 = sort_details(3, Details),
+ {Label, Cnt, Acc, Own, lists:reverse(lists:keysort(3, Roots)), Details2}.
+
+%% Compute a summary of the rearranged process info
+collapse_processes(Processes) ->
+ Headers = lists:map(fun({_L, C, A, O, _R, _D}) -> {"SUMMARY", C, A, O} end,
+ Processes),
+ [{Label, Cnt, Acc, Own}] = collapse_calls(Headers, []),
+ Details = lists:flatmap(fun({_L, _C, _A, _O, _R, D}) -> D end, Processes),
+ Details2 = do_collapse_processes(sort_details(1, Details), []),
+ Roots = lists:flatmap(fun({_L, _C, _A, _O, R, _D}) -> R end, Processes),
+ RootMFAs = lists:usort([MFA || {MFA, _, _, _} <- Roots]),
+ Roots2 = [R || RootMFA <- RootMFAs,
+ {_, {MFA, _, _, _} = R, _} <- Details2,
+ MFA =:= RootMFA],
+ Roots3 = collapse_calls(Roots2, []),
+ {Label, Cnt, Acc, Own, Roots3, Details2}.
+
+do_collapse_processes([{CalledBy1, {MFA, Cnt1, Acc1, Own1}, Calls1} | T1],
+ [{CalledBy2, {MFA, Cnt2, Acc2, Own2}, Calls2} | T2]) ->
+ Cnt = Cnt1 + Cnt2,
+ Acc = Acc1 + Acc2,
+ Own = Own1 + Own2,
+ Current = {MFA, Cnt, Acc, Own},
+ CalledBy0 = CalledBy1 ++ CalledBy2,
+ Calls0 = Calls1 ++ Calls2,
+ CalledBy = collapse_calls(lists:keysort(3, CalledBy0), []),
+ Calls = collapse_calls(lists:keysort(3, Calls0), []),
+ do_collapse_processes(T1, [{CalledBy, Current, Calls} | T2]);
+do_collapse_processes([{CalledBy, Current, Calls} | T1],
+ T2) ->
+ do_collapse_processes(T1, [{CalledBy, Current, Calls} | T2]);
+do_collapse_processes([],
+ T2) ->
+ sort_details(3, T2).
+
+%% Reverse sort on acc field
+sort_details(Pos, Details) ->
+ Pivot = fun({_CalledBy1, Current1, _Calls1},
+ {_CalledBy2, Current2, _Calls2}) ->
+ element(Pos, Current1) =< element(Pos, Current2)
+ end,
+ lists:reverse(lists:sort(Pivot, Details)).
+
+%% Compute a summary from a list of call tuples
+collapse_calls([{MFA, Cnt1, Acc1, Own1} | T1],
+ [{MFA, Cnt2, Acc2, Own2} | T2]) ->
+ Cnt = Cnt1 + Cnt2,
+ Acc = safe_sum(Acc1, Acc2),
+ Own = Own1 + Own2,
+ collapse_calls(T1, [{MFA, Cnt, Acc, Own} | T2]);
+collapse_calls([{MFA, Cnt, Acc, Own} | T1],
+ T2) ->
+ collapse_calls(T1, [{MFA, Cnt, Acc, Own} | T2]);
+collapse_calls([],
+ T2) ->
+ lists:reverse(lists:keysort(3, T2)).
+
+safe_sum(Int1, Int2) ->
+ if
+ Int1 =:= undefined -> Int2;
+ Int2 =:= undefined -> Int1;
+ true -> Int1 + Int2
+ end.
+
+safe_max(Int1, Int2) ->
+ if
+ Int1 =:= undefined ->
+ io:format("111\n", []),
+ Int2;
+ Int2 =:= undefined ->
+ io:format("222\n", []),
+ Int1;
+ Int2 > Int1 -> Int2;
+ true -> Int1
+ end.
+
+%% Compute a calltree and write it to file
+gen_calltree(Fd, Indent, TotalAcc, {Label, Cnt, Acc, Own, Roots, Details}, MinPercent) ->
+ Header = {Label, Cnt, Acc, Own},
+ MetaLabel = "Process",
+ Diff = length(Label) - length(MetaLabel),
+ IoList = io_lib:format("~s~s Lvl Pct Cnt Acc Own Calls => MFA\n",
+ [MetaLabel, lists:duplicate(Diff, $\ )]),
+ file:write(Fd, IoList),
+ log(Fd, Label, Indent, TotalAcc, Header, Roots, MinPercent),
+ NewIndent = " " ++ Indent,
+ Fun = fun({MFA, _C, _A, _O}) ->
+ [put_detail(Label, D) || D <- Details],
+ gen_calls(Fd, Label, NewIndent, TotalAcc, MFA, MinPercent)
+ end,
+ lists:foreach(Fun, Roots).
+
+gen_calls(Fd, Label, Indent, TotalAcc, MFA, MinPercent) ->
+ case get_detail(Label, MFA) of
+ {read, {_CalledBy, Current, _Calls}} ->
+ log(Fd, Label, Indent, TotalAcc, Current, -1, MinPercent);
+ {unread, {_CalledBy, Current, Calls}} ->
+ log(Fd, Label, Indent, TotalAcc, Current, Calls, MinPercent),
+ NewIndent = " " ++ Indent,
+ Fun = fun({NextMFA, _, _, _}) ->
+ gen_calls(Fd, Label, NewIndent, TotalAcc,
+ NextMFA, MinPercent)
+ end,
+ lists:foreach(Fun, Calls)
+ end.
+
+put_detail(Label, {_, {MFA, _, _, _}, _} = Detail) ->
+ put({Label, MFA}, {unread, Detail}).
+
+get_detail(Label, MFA) ->
+ Val = get({Label, MFA}),
+ case Val of
+ {unread, Detail} ->
+ put({Label, MFA}, {read, Detail}),
+ Val;
+ {read, _Detail} ->
+ Val
+ end.
+
+gen_details(Fd, Total, Details) ->
+ IoList = io_lib:format("Pct Cnt Acc Own MFA\n", []),
+ file:write(Fd, IoList),
+ do_gen_details(Fd, Total, Details).
+
+do_gen_details(Fd, Total, [{_CalledBy, {MFA, Cnt, Acc, Own}, _Calls} | Details]) ->
+ MFAStr = io_lib:format("~p", [MFA]),
+ {_, Percent} = calc_percent(Acc, Own, Total),
+ IoList = io_lib:format("~3.. B% ~10.3B ~10.3f ~10.3f => ~s\n",
+ [Percent, Cnt, Acc, Own, MFAStr]),
+ file:write(Fd, IoList),
+ do_gen_details(Fd, Total, Details);
+do_gen_details(_Fd, _Total, []) ->
+ ok.
+
+log(Fd, Label, Indent, Acc, Current, Calls, MinPercent) when is_list(Calls) ->
+ log(Fd, Label, Indent, Acc, Current, length(Calls), MinPercent);
+log(Fd, Label, Indent, Total, {MFA, Cnt, Acc, Own}, N, MinPercent) ->
+ {Max, Percent} = calc_percent(Acc, Own, Total),
+ if
+ Percent >= MinPercent ->
+ do_log(Fd, Label, Indent, Percent, MFA, Cnt, Max, Own, N);
+ true ->
+ ok
end.
-find(Key, [{_, {Key, _, _, _}, _} = H | _]) ->
- H;
-find(Key, [{_, {_, _, _, _}, _} | T]) ->
- find(Key, T).
-
-log(Fd, Indent, Total, {Label, Cnt, Acc, Own}) ->
- Percent = case Acc of
- undefined -> 100;
- _ -> trunc((lists:max([Acc, Own]) * 100) / Total)
- end,
- Label2 = io_lib:format("~p", [Label]),
- IoList = io_lib:format("~s~p% ~s \t~p \t~p \t~p\n",
- [Indent, Percent, Label2, Cnt, trunc(Acc), trunc(Own)]),
+do_log(Fd, Label, Indent, Percent, MFA, Cnt, Acc, Own, N) ->
+ MFAStr = io_lib:format("~p", [MFA]),
+ CallsStr = io_lib:format(" ~5.. s ", [lists:concat([N])]),
+ IoList = io_lib:format("~s ~3.. B "
+ "~s~3.. B% ~10.. B ~10.. B ~10.. B ~s => ~s\n",
+ [Label, length(Indent) div 2,
+ Indent, Percent, Cnt,
+ round(Acc), round(Own), CallsStr, MFAStr]),
file:write(Fd, IoList).
+calc_percent(Acc, Own, Total) ->
+ Max = safe_max(Acc, Own),
+ {Max, round((Max * 100) / Total)}.
diff --git a/lib/megaco/test/megaco_test_lib.erl b/lib/megaco/test/megaco_test_lib.erl
index 41f6c2c4cb..282fd91b44 100644
--- a/lib/megaco/test/megaco_test_lib.erl
+++ b/lib/megaco/test/megaco_test_lib.erl
@@ -21,6 +21,7 @@
%%----------------------------------------------------------------------
%% Purpose: Lightweight test server
%%----------------------------------------------------------------------
+%%
-module(megaco_test_lib).
@@ -684,7 +685,7 @@ skip(Actual, File, Line) ->
fatal_skip(Actual, File, Line) ->
error(Actual, File, Line),
- exit(shutdown).
+ exit({skipped, {fatal, Actual, File, Line}}).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -749,6 +750,7 @@ proxy_loop(OwnId, Controller) ->
proxy_loop(OwnId, Controller)
end.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Test server callbacks
init_per_testcase(_Case, Config) ->
@@ -852,10 +854,10 @@ watchdog(Pid, Time) ->
prepare_test_case(Actions, N, Config, File, Line) ->
OrigNodes = lookup_config(nodes, Config),
TestNodes = lookup_config(nodenames, Config), %% For testserver
- This = node(),
+ This = node(),
SomeNodes = OrigNodes ++ (TestNodes -- OrigNodes),
- AllNodes = [This | (SomeNodes -- [This])],
- Nodes = pick_n_nodes(N, AllNodes, File, Line),
+ AllNodes = [This | (SomeNodes -- [This])],
+ Nodes = pick_n_nodes(N, AllNodes, File, Line),
start_nodes(Nodes, File, Line),
do_prepare_test_case(Actions, Nodes, Config, File, Line).
diff --git a/lib/megaco/vsn.mk b/lib/megaco/vsn.mk
index 5f71712360..35acffcb64 100644
--- a/lib/megaco/vsn.mk
+++ b/lib/megaco/vsn.mk
@@ -18,6 +18,6 @@
# %CopyrightEnd%
APPLICATION = megaco
-MEGACO_VSN = 3.15.1
+MEGACO_VSN = 3.15.1.2
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(MEGACO_VSN)$(PRE_VSN)"
diff --git a/lib/mnesia/doc/src/Makefile b/lib/mnesia/doc/src/Makefile
index f45b5137a3..f2e581f9d3 100644
--- a/lib/mnesia/doc/src/Makefile
+++ b/lib/mnesia/doc/src/Makefile
@@ -29,14 +29,6 @@ VSN=$(MNESIA_VSN)
APPLICATION=mnesia
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -105,31 +97,10 @@ EXTRA_FILES = summary.html.src \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -142,8 +113,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -158,33 +127,6 @@ clean clean_docs:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES)
-
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ *xmls_output *xmls_errs $(LATEX_CLEAN)
-
-endif
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -199,8 +141,6 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
$(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
$(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
@@ -211,30 +151,4 @@ release_docs_spec: docs
$(INSTALL_DIR) $(RELEASE_PATH)/man/man3
$(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-endif
-endif
-
-endif
-
-
release_spec:
-
diff --git a/lib/mnesia/doc/src/make.dep b/lib/mnesia/doc/src/make.dep
deleted file mode 100644
index 6e79484cb3..0000000000
--- a/lib/mnesia/doc/src/make.dep
+++ /dev/null
@@ -1,46 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: Mnesia_App_A.tex Mnesia_App_B.tex Mnesia_App_C.tex \
- Mnesia_App_D.tex Mnesia_chap1.tex Mnesia_chap2.tex \
- Mnesia_chap3.tex Mnesia_chap4.tex Mnesia_chap5.tex \
- Mnesia_chap7.tex Mnesia_chap8.tex book.tex \
- mnesia.tex mnesia_frag_hash.tex mnesia_registry.tex \
- part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-Mnesia_App_B.tex: ../../src/mnesia_backup.erl
-
-Mnesia_App_C.tex: ../../src/mnesia_frag.erl
-
-Mnesia_App_D.tex: ../../src/mnesia_frag_hash.erl
-
-Mnesia_chap2.tex: company.erl company.hrl
-
-Mnesia_chap3.tex: company.erl
-
-Mnesia_chap4.tex: company.erl
-
-Mnesia_chap5.tex: FRUITS company.erl company_o.erl company_o.hrl
-
-Mnesia_chap7.tex: bup.erl
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: company.ps
-
diff --git a/lib/mnesia/doc/src/mnesia.xml b/lib/mnesia/doc/src/mnesia.xml
index 7a8f796cee..19ec70118f 100644
--- a/lib/mnesia/doc/src/mnesia.xml
+++ b/lib/mnesia/doc/src/mnesia.xml
@@ -246,7 +246,7 @@ If a new item is inserted with the same key as
</p>
</item>
<item>
- <p><c>{max,MaxTabs}</c><c>MaxTabs</c> is a list of
+ <p><c>{max,MaxTabs}</c>. <c>MaxTabs</c> is a list of
tables that should be included in the checkpoint. The
default is []. For these tables, the redundancy will be
maximized and checkpoint information will be retained together
@@ -274,7 +274,7 @@ If a new item is inserted with the same key as
</p>
</item>
<item>
- <p><c>{ram_overrides_dump,Bool} </c> Only applicable
+ <p><c>{ram_overrides_dump,Bool}</c>. Only applicable
for <c>ram_copies</c>. <c>Bool</c> allows you to choose
to backup the table state as it is in RAM, or as it is on
disc. <c>true</c> means that the latest committed
diff --git a/lib/mnesia/doc/src/mnesia_frag_hash.xml b/lib/mnesia/doc/src/mnesia_frag_hash.xml
index 73162c3974..665796f20d 100644
--- a/lib/mnesia/doc/src/mnesia_frag_hash.xml
+++ b/lib/mnesia/doc/src/mnesia_frag_hash.xml
@@ -64,7 +64,7 @@
<p>Note that the <c>add_frag/2</c> function will be invoked
one time each for the rest of the fragments (all but number 1)
as a part of the table creation procedure.</p>
- <p><c>State</c> is the initial value of the <c>hash_state</c><c>frag_property</c>. The <c>NewState</c> will be stored as
+ <p><c>State</c> is the initial value of the <c>hash_state</c> <c>frag_property</c>. The <c>NewState</c> will be stored as
<c>hash_state</c> among the other <c>frag_properties</c>.
</p>
</desc>
diff --git a/lib/mnesia/doc/src/notes.xml b/lib/mnesia/doc/src/notes.xml
index 7f50dc049a..1bb80f8fe3 100644
--- a/lib/mnesia/doc/src/notes.xml
+++ b/lib/mnesia/doc/src/notes.xml
@@ -38,7 +38,78 @@
thus constitutes one section in this document. The title of each
section is the version number of Mnesia.</p>
- <section><title>Mnesia 4.4.19</title>
+ <section><title>Mnesia 4.5.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix deadlock in mnesia:del_table_copy/2.</p>
+ <p>
+ Own Id: OTP-9689 Aux Id: seq11927 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Allow schema operations when using different mnesia
+ versions.</p>
+ <p>
+ Own Id: OTP-9657 Aux Id: seq11926 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix protocol issues. Mnesia-4.4.19 could not communicate
+ with to older nodes.</p>
+ <p>
+ Own Id: OTP-9473</p>
+ </item>
+ <item>
+ <p> XML files have been corrected. </p>
+ <p>
+ Own Id: OTP-9550 Aux Id: OTP-9541 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Dump the log even if no transactions have been invoked on
+ local node, otherwise the log will grow forever with
+ decisions from the other nodes who have tables on disk.
+ Thanks Marek Majkowski.</p>
+ <p>
+ Own Id: OTP-9551</p>
+ </item>
+ <item>
+ <p>
+ Use dedicated api for clear_table, i.e. instead of
+ match_delete use delete_all_objects. Thanks KukHyun Lee.</p>
+ <p>
+ Own Id: OTP-9558</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.4.19</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/mnesia/src/Makefile b/lib/mnesia/src/Makefile
index e032f563fa..1c8ec54605 100644
--- a/lib/mnesia/src/Makefile
+++ b/lib/mnesia/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2009. All Rights Reserved.
+# Copyright Ericsson AB 1996-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -113,6 +113,8 @@ clean:
docs:
+$(TARGET_FILES): $(HRL_FILES)
+
# ----------------------------------------------------
# Special Build Targets
# ----------------------------------------------------
diff --git a/lib/mnesia/src/mnesia.appup.src b/lib/mnesia/src/mnesia.appup.src
index 3691aa249a..e0954ad206 100644
--- a/lib/mnesia/src/mnesia.appup.src
+++ b/lib/mnesia/src/mnesia.appup.src
@@ -1,11 +1,15 @@
%% -*- erlang -*-
-{"%VSN%",
+{"%VSN%",
[
+ {"4.5", [{restart_application, mnesia}]},
+ {"4.4.19", [{restart_application, mnesia}]},
{"4.4.18", [{restart_application, mnesia}]},
{"4.4.17", [{restart_application, mnesia}]},
{"4.4.16", [{restart_application, mnesia}]}
],
[
+ {"4.5", [{restart_application, mnesia}]},
+ {"4.4.19", [{restart_application, mnesia}]},
{"4.4.18", [{restart_application, mnesia}]},
{"4.4.17", [{restart_application, mnesia}]},
{"4.4.16", [{restart_application, mnesia}]}
diff --git a/lib/mnesia/src/mnesia_bup.erl b/lib/mnesia/src/mnesia_bup.erl
index 47dcdad7ac..14414537b9 100644
--- a/lib/mnesia/src/mnesia_bup.erl
+++ b/lib/mnesia/src/mnesia_bup.erl
@@ -372,7 +372,9 @@ mk_str() ->
lists:concat([node()] ++ Now ++ ".TMP").
make_initial_backup(Ns, Opaque, Mod) ->
- Schema = [{schema, schema, mnesia_schema:get_initial_schema(disc_copies, Ns)}],
+ Orig = mnesia_schema:get_initial_schema(disc_copies, Ns),
+ Modded = proplists:delete(storage_properties, proplists:delete(majority, Orig)),
+ Schema = [{schema, schema, Modded}],
O2 = do_apply(Mod, open_write, [Opaque], Opaque),
O3 = do_apply(Mod, write, [O2, [mnesia_log:backup_log_header()]], O2),
O4 = do_apply(Mod, write, [O3, Schema], O3),
diff --git a/lib/mnesia/src/mnesia_controller.erl b/lib/mnesia/src/mnesia_controller.erl
index d4b2c7b5cc..6a561394d5 100644
--- a/lib/mnesia/src/mnesia_controller.erl
+++ b/lib/mnesia/src/mnesia_controller.erl
@@ -57,7 +57,8 @@
release_schema_commit_lock/0,
create_table/1,
get_disc_copy/1,
- get_cstructs/0,
+ get_remote_cstructs/0, % new function
+ get_cstructs/0, % old function
sync_and_block_table_whereabouts/4,
sync_del_table_copy_whereabouts/2,
block_table/1,
@@ -278,9 +279,18 @@ rec_tabs([], _, _, Init) ->
unlink(Init),
ok.
-get_cstructs() ->
+%% New function that does exactly what get_cstructs() used to do.
+%% When this function is called, we know that the calling node knows
+%% how to convert cstructs on the receiving end (should they differ).
+get_remote_cstructs() ->
call(get_cstructs).
+%% Old function kept for backwards compatibility; converts cstructs before sending.
+get_cstructs() ->
+ {cstructs, Cstructs, Running} = call(get_cstructs),
+ Node = node(group_leader()),
+ {cstructs, mnesia_schema:normalize_cs(Cstructs, Node), Running}.
+
update(Fun) ->
call({update,Fun}).
diff --git a/lib/mnesia/src/mnesia_dumper.erl b/lib/mnesia/src/mnesia_dumper.erl
index 92fd9dfade..f8d7664156 100644
--- a/lib/mnesia/src/mnesia_dumper.erl
+++ b/lib/mnesia/src/mnesia_dumper.erl
@@ -214,7 +214,12 @@ insert_rec(Rec, InPlace, InitBy, LogV) when is_record(Rec, commit) ->
{Tid, committed} ->
do_insert_rec(Tid, Rec, InPlace, InitBy, LogV);
{Tid, aborted} ->
- mnesia_schema:undo_prepare_commit(Tid, Rec)
+ case InitBy of
+ startup ->
+ mnesia_schema:undo_prepare_commit(Tid, Rec);
+ _ ->
+ ok
+ end
end;
insert_rec(H, _InPlace, _InitBy, _LogV) when is_record(H, log_header) ->
CurrentVersion = mnesia_log:version(),
@@ -359,7 +364,7 @@ dets_insert(Op,Tab,Key,Val) ->
ok = dets:delete_object(Tab, Val);
clear_table ->
dets_cleared(Tab),
- ok = dets:match_delete(Tab, '_')
+ ok = dets:delete_all_objects(Tab)
end.
dets_updated(Tab,Key) ->
diff --git a/lib/mnesia/src/mnesia_event.erl b/lib/mnesia/src/mnesia_event.erl
index ec6b99ecaa..5a060a28ff 100644
--- a/lib/mnesia/src/mnesia_event.erl
+++ b/lib/mnesia/src/mnesia_event.erl
@@ -121,7 +121,7 @@ handle_system_event({mnesia_up, Node}, State) ->
{ok, State#state{nodes = Nodes}};
handle_system_event({mnesia_down, Node}, State) ->
- case mnesia:system_info(fallback_activated) of
+ case mnesia:system_info(fallback_activated) andalso Node =/= node() of
true ->
case mnesia_monitor:get_env(fallback_error_function) of
{mnesia, lkill} ->
@@ -129,8 +129,8 @@ handle_system_event({mnesia_down, Node}, State) ->
"must be restarted. Forcing shutdown "
"after mnesia_down from ~p...~n",
report_fatal(Msg, [Node], nocore, State#state.dumped_core),
- mnesia:lkill(),
- exit(fatal);
+ catch exit(whereis(mnesia_monitor), fatal),
+ {ok, State};
{UserMod, UserFunc} ->
Msg = "Warning: A fallback is installed and Mnesia got mnesia_down "
"from ~p. ~n",
diff --git a/lib/mnesia/src/mnesia_frag.erl b/lib/mnesia/src/mnesia_frag.erl
index 9e77fe0b9f..4a1616e054 100644
--- a/lib/mnesia/src/mnesia_frag.erl
+++ b/lib/mnesia/src/mnesia_frag.erl
@@ -758,7 +758,7 @@ make_activate(Tab, Props) ->
[] ->
Cs2 = Cs#cstruct{frag_properties = Props},
[Cs3] = expand_cstruct(Cs2, activate),
- TabDef = mnesia_schema:cs2list(Cs3),
+ TabDef = mnesia_schema:vsn_cs2list(Cs3),
Op = {op, change_table_frag, activate, TabDef},
[[Op]];
BadProps ->
@@ -783,7 +783,7 @@ make_deactivate(Tab) ->
mnesia:abort({combine_error, Tab, "Too many fragments"});
true ->
Cs2 = Cs#cstruct{frag_properties = []},
- TabDef = mnesia_schema:cs2list(Cs2),
+ TabDef = mnesia_schema:vsn_cs2list(Cs2),
Op = {op, change_table_frag, deactivate, TabDef},
[[Op]]
end.
@@ -850,7 +850,7 @@ make_add_frag(Tab, SortedNs) ->
SplitOps = split(Tab, FH2, FromIndecies, FragNames, []),
Cs2 = replace_frag_hash(Cs, FH2),
- TabDef = mnesia_schema:cs2list(Cs2),
+ TabDef = mnesia_schema:vsn_cs2list(Cs2),
BaseOp = {op, change_table_frag, {add_frag, SortedNs}, TabDef},
[BaseOp, NewOp | SplitOps].
@@ -962,7 +962,7 @@ make_del_frag(Tab) ->
LastFrag = element(N, FragNames),
[LastOp] = mnesia_schema:make_delete_table(LastFrag, single_frag),
Cs2 = replace_frag_hash(Cs, FH2),
- TabDef = mnesia_schema:cs2list(Cs2),
+ TabDef = mnesia_schema:vsn_cs2list(Cs2),
BaseOp = {op, change_table_frag, del_frag, TabDef},
[BaseOp, LastOp | MergeOps];
_ ->
@@ -1075,7 +1075,7 @@ make_add_node(Tab, Node) when is_atom(Node) ->
Props = Cs#cstruct.frag_properties,
Props2 = lists:keyreplace(node_pool, 1, Props, {node_pool, Pool2}),
Cs2 = Cs#cstruct{frag_properties = Props2},
- TabDef = mnesia_schema:cs2list(Cs2),
+ TabDef = mnesia_schema:vsn_cs2list(Cs2),
Op = {op, change_table_frag, {add_node, Node}, TabDef},
[Op];
true ->
@@ -1104,7 +1104,7 @@ make_del_node(Tab, Node) when is_atom(Node) ->
Pool2 = Pool -- [Node],
Props = lists:keyreplace(node_pool, 1, Cs#cstruct.frag_properties, {node_pool, Pool2}),
Cs2 = Cs#cstruct{frag_properties = Props},
- TabDef = mnesia_schema:cs2list(Cs2),
+ TabDef = mnesia_schema:vsn_cs2list(Cs2),
Op = {op, change_table_frag, {del_node, Node}, TabDef},
[Op];
false ->
diff --git a/lib/mnesia/src/mnesia_lib.erl b/lib/mnesia/src/mnesia_lib.erl
index 7e926a6258..ae6631646c 100644
--- a/lib/mnesia/src/mnesia_lib.erl
+++ b/lib/mnesia/src/mnesia_lib.erl
@@ -413,7 +413,7 @@ pr_other(Var, Other) ->
[self(), process_info(self(), registered_name),
Var, Other, Why]),
case Other of
- {badarg, [{ets, lookup_element, _}|_]} ->
+ {badarg, [{ets, lookup_element, _, _}|_]} ->
exit(Why);
_ ->
erlang:error(Why)
@@ -1141,12 +1141,18 @@ db_erase(ram_copies, Tab, Key) -> ?ets_delete(Tab, Key), ok;
db_erase(disc_copies, Tab, Key) -> ?ets_delete(Tab, Key), ok;
db_erase(disc_only_copies, Tab, Key) -> dets:delete(Tab, Key).
+db_match_erase(Tab, '_') ->
+ db_delete_all(val({Tab, storage_type}),Tab);
db_match_erase(Tab, Pat) ->
db_match_erase(val({Tab, storage_type}), Tab, Pat).
db_match_erase(ram_copies, Tab, Pat) -> ?ets_match_delete(Tab, Pat), ok;
db_match_erase(disc_copies, Tab, Pat) -> ?ets_match_delete(Tab, Pat), ok;
db_match_erase(disc_only_copies, Tab, Pat) -> dets:match_delete(Tab, Pat).
+db_delete_all(ram_copies, Tab) -> ets:delete_all_objects(Tab);
+db_delete_all(disc_copies, Tab) -> ets:delete_all_objects(Tab);
+db_delete_all(disc_only_copies, Tab) -> dets:delete_all_objects(Tab).
+
db_first(Tab) ->
db_first(val({Tab, storage_type}), Tab).
db_first(ram_copies, Tab) -> ?ets_first(Tab);
diff --git a/lib/mnesia/src/mnesia_loader.erl b/lib/mnesia/src/mnesia_loader.erl
index e785b795d1..c4b22814a8 100644
--- a/lib/mnesia/src/mnesia_loader.erl
+++ b/lib/mnesia/src/mnesia_loader.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -27,7 +27,6 @@
net_load_table/4,
send_table/3]).
--export([old_node_init_table/6]). %% Spawned old node protocol conversion hack
-export([spawned_receiver/8]). %% Spawned lock taking process
-import(mnesia_lib, [set/2, fatal/2, verbose/2, dbg_out/2]).
@@ -36,7 +35,7 @@
val(Var) ->
case ?catch_val(Var) of
- {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
+ {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
Value -> Value
end.
@@ -51,7 +50,7 @@ disc_load_table(Tab, Reason) ->
?eval_debug_fun({?MODULE, do_get_disc_copy},
[{tab, Tab},
{reason, Reason},
- {storage, Storage},
+ {storage, Storage},
{type, Type}]),
do_get_disc_copy2(Tab, Reason, Storage, Type).
@@ -63,19 +62,19 @@ do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == disc_copies ->
%% NOW we create the actual table
Repair = mnesia_monitor:get_env(auto_repair),
Args = [{keypos, 2}, public, named_table, Type],
- case Reason of
+ case Reason of
{dumper, _} -> %% Resources allready allocated
ignore;
_ ->
mnesia_monitor:mktab(Tab, Args),
- Count = mnesia_log:dcd2ets(Tab, Repair),
+ Count = mnesia_log:dcd2ets(Tab, Repair),
case ets:info(Tab, size) of
X when X < Count * 4 ->
- ok = mnesia_log:ets2dcd(Tab);
+ ok = mnesia_log:ets2dcd(Tab);
_ ->
ignore
end
- end,
+ end,
mnesia_index:init_index(Tab, Storage),
snmpify(Tab, Storage),
set({Tab, load_node}, node()),
@@ -84,7 +83,7 @@ do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == disc_copies ->
do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == ram_copies ->
Args = [{keypos, 2}, public, named_table, Type],
- case Reason of
+ case Reason of
{dumper, _} -> %% Resources allready allocated
ignore;
_ ->
@@ -94,12 +93,12 @@ do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == ram_copies ->
Repair = mnesia_monitor:get_env(auto_repair),
case mnesia_monitor:use_dir() of
true ->
- case mnesia_lib:exists(Fname) of
+ case mnesia_lib:exists(Fname) of
true -> mnesia_log:dcd2ets(Tab, Repair);
false ->
case mnesia_lib:exists(Datname) of
true ->
- mnesia_lib:dets_to_ets(Tab, Tab, Datname,
+ mnesia_lib:dets_to_ets(Tab, Tab, Datname,
Type, Repair, no);
false ->
false
@@ -154,11 +153,11 @@ do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == disc_only_copies -
%% Disable rehashing of table
%% Release read lock on table
%% Send table to receiver in chunks
-%%
+%%
%% Grab read lock on table
%% Block dirty updates
%% Update wherabouts
-%%
+%%
%% Cancel the update subscription
%% Process the subscription events
%% Optionally dump to disc
@@ -166,7 +165,7 @@ do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == disc_only_copies -
%% Release read lock on table
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--define(MAX_TRANSFER_SIZE, 7500).
+-define(MAX_TRANSFER_SIZE, 7500).
-define(MAX_RAM_FILE_SIZE, 1000000).
-define(MAX_RAM_TRANSFERS, (?MAX_RAM_FILE_SIZE div ?MAX_TRANSFER_SIZE) + 1).
-define(MAX_NOPACKETS, 20).
@@ -187,14 +186,14 @@ try_net_load_table(Tab, Reason, Ns, Cs) ->
do_get_network_copy(Tab, _Reason, _Ns, unknown, _Cs) ->
verbose("Local table copy of ~p has recently been deleted, ignored.~n", [Tab]),
{not_loaded, storage_unknown};
-do_get_network_copy(Tab, Reason, Ns, Storage, Cs) ->
+do_get_network_copy(Tab, Reason, Ns, Storage, Cs) ->
[Node | Tail] = Ns,
case lists:member(Node,val({current, db_nodes})) of
true ->
dbg_out("Getting table ~p (~p) from node ~p: ~p~n",
[Tab, Storage, Node, Reason]),
?eval_debug_fun({?MODULE, do_get_network_copy},
- [{tab, Tab}, {reason, Reason},
+ [{tab, Tab}, {reason, Reason},
{nodes, Ns}, {storage, Storage}]),
case init_receiver(Node, Tab, Storage, Cs, Reason) of
ok ->
@@ -208,7 +207,7 @@ do_get_network_copy(Tab, Reason, Ns, Storage, Cs) ->
restart ->
try_net_load_table(Tab, Reason, Tail ++ [Node], Cs);
down ->
- try_net_load_table(Tab, Reason, Tail, Cs)
+ try_net_load_table(Tab, Reason, Tail, Cs)
end;
false ->
try_net_load_table(Tab, Reason, Tail, Cs)
@@ -223,10 +222,10 @@ do_snmpify(Tab, Us, Storage) ->
Snmp = mnesia_snmp_hook:create_table(Us, Tab, Storage),
set({Tab, {index, snmp}}, Snmp).
-%% Start the recieiver
+%% Start the recieiver
init_receiver(Node, Tab, Storage, Cs, Reas={dumper,add_table_copy}) ->
case start_remote_sender(Node, Tab, Storage) of
- {SenderPid, TabSize, DetsData} ->
+ {SenderPid, TabSize, DetsData} ->
start_receiver(Tab,Storage,Cs,SenderPid,TabSize,DetsData,Reas);
Else ->
Else
@@ -234,21 +233,21 @@ init_receiver(Node, Tab, Storage, Cs, Reas={dumper,add_table_copy}) ->
init_receiver(Node, Tab,Storage,Cs,Reason) ->
%% Grab a schema lock to avoid deadlock between table_loader and schema_commit dumping.
%% Both may grab tables-locks in different order.
- Load =
- fun() ->
- {_,Tid,Ts} = get(mnesia_activity_state),
+ Load =
+ fun() ->
+ {_,Tid,Ts} = get(mnesia_activity_state),
mnesia_locker:rlock(Tid, Ts#tidstore.store, {schema, Tab}),
- %% Check that table still exists
+ %% Check that table still exists
Active = val({Tab, active_replicas}),
%% Check that we havn't loaded it already
case val({Tab,where_to_read}) == node() of
true -> ok;
_ ->
- %% And that sender still got a copy
- %% (something might have happend while
+ %% And that sender still got a copy
+ %% (something might have happend while
%% we where waiting for the lock)
true = lists:member(Node, Active),
- {SenderPid, TabSize, DetsData} =
+ {SenderPid, TabSize, DetsData} =
start_remote_sender(Node,Tab,Storage),
Init = table_init_fun(SenderPid),
Args = [self(),Tab,Storage,Cs,SenderPid,
@@ -258,18 +257,18 @@ init_receiver(Node, Tab,Storage,Cs,Reason) ->
wait_on_load_complete(Pid)
end
end,
- Res =
+ Res =
case mnesia:transaction(Load, 20) of
- {atomic, {error,Result}} when
- element(1,Reason) == dumper ->
+ {atomic, {error,Result}} when
+ element(1,Reason) == dumper ->
{error,Result};
- {atomic, {error,Result}} ->
+ {atomic, {error,Result}} ->
fatal("Cannot create table ~p: ~p~n",
[[Tab, Storage], Result]);
{atomic, Result} -> Result;
{aborted, nomore} -> restart;
- {aborted, _Reas} ->
- verbose("Receiver failed on ~p from ~p:~nReason: ~p~n",
+ {aborted, _Reas} ->
+ verbose("Receiver failed on ~p from ~p:~nReason: ~p~n",
[Tab,Node,_Reas]),
down %% either this node or sender is dying
end,
@@ -279,7 +278,7 @@ init_receiver(Node, Tab,Storage,Cs,Reason) ->
start_remote_sender(Node,Tab,Storage) ->
mnesia_controller:start_remote_sender(Node, Tab, self(), Storage),
put(mnesia_table_sender_node, {Tab, Node}),
- receive
+ receive
{SenderPid, {first, TabSize}} ->
{SenderPid, TabSize, false};
{SenderPid, {first, TabSize, DetsData}} ->
@@ -291,22 +290,14 @@ start_remote_sender(Node,Tab,Storage) ->
end.
table_init_fun(SenderPid) ->
- PConv = mnesia_monitor:needs_protocol_conversion(node(SenderPid)),
- MeMyselfAndI = self(),
fun(read) ->
- Receiver =
- if
- PConv == true ->
- MeMyselfAndI ! {actual_tabrec, self()},
- MeMyselfAndI; %% Old mnesia
- PConv == false -> self()
- end,
+ Receiver = self(),
SenderPid ! {Receiver, more},
get_data(SenderPid, Receiver)
end.
%% Add_table_copy get's it's own locks.
-start_receiver(Tab,Storage,Cs,SenderPid,TabSize,DetsData,{dumper,add_table_copy}) ->
+start_receiver(Tab,Storage,Cs,SenderPid,TabSize,DetsData,{dumper,add_table_copy}) ->
Init = table_init_fun(SenderPid),
case do_init_table(Tab,Storage,Cs,SenderPid,TabSize,DetsData,self(), Init) of
Err = {error, _} ->
@@ -317,8 +308,8 @@ start_receiver(Tab,Storage,Cs,SenderPid,TabSize,DetsData,{dumper,add_table_copy}
end.
spawned_receiver(ReplyTo,Tab,Storage,Cs, SenderPid,TabSize,DetsData, Init) ->
- process_flag(trap_exit, true),
- Done = do_init_table(Tab,Storage,Cs,
+ process_flag(trap_exit, true),
+ Done = do_init_table(Tab,Storage,Cs,
SenderPid,TabSize,DetsData,
ReplyTo, Init),
ReplyTo ! {self(),Done},
@@ -327,17 +318,17 @@ spawned_receiver(ReplyTo,Tab,Storage,Cs, SenderPid,TabSize,DetsData, Init) ->
exit(normal).
wait_on_load_complete(Pid) ->
- receive
- {Pid, Res} ->
+ receive
+ {Pid, Res} ->
Res;
- {'EXIT', Pid, Reason} ->
+ {'EXIT', Pid, Reason} ->
exit(Reason);
- Else ->
+ Else ->
Pid ! Else,
wait_on_load_complete(Pid)
end.
-do_init_table(Tab,Storage,Cs,SenderPid,
+do_init_table(Tab,Storage,Cs,SenderPid,
TabSize,DetsInfo,OrigTabRec,Init) ->
case create_table(Tab, TabSize, Storage, Cs) of
{Storage,Tab} ->
@@ -345,11 +336,9 @@ do_init_table(Tab,Storage,Cs,SenderPid,
Node = node(SenderPid),
put(mnesia_table_receiver, {Tab, Node, SenderPid}),
mnesia_tm:block_tab(Tab),
- PConv = mnesia_monitor:needs_protocol_conversion(Node),
-
- case init_table(Tab,Storage,Init,PConv,DetsInfo,SenderPid) of
- ok ->
- tab_receiver(Node,Tab,Storage,Cs,PConv,OrigTabRec);
+ case init_table(Tab,Storage,Init,DetsInfo,SenderPid) of
+ ok ->
+ tab_receiver(Node,Tab,Storage,Cs,OrigTabRec);
Reason ->
Msg = "[d]ets:init table failed",
verbose("~s: ~p: ~p~n", [Msg, Tab, Reason]),
@@ -360,7 +349,7 @@ do_init_table(Tab,Storage,Cs,SenderPid,
end.
create_table(Tab, TabSize, Storage, Cs) ->
- if
+ if
Storage == disc_only_copies ->
mnesia_lib:lock_table(Tab),
Tmp = mnesia_lib:tab2tmp(Tab),
@@ -390,54 +379,30 @@ create_table(Tab, TabSize, Storage, Cs) ->
end
end.
-tab_receiver(Node, Tab, Storage, Cs, PConv, OrigTabRec) ->
+tab_receiver(Node, Tab, Storage, Cs, OrigTabRec) ->
receive
- {SenderPid, {no_more, DatBin}} when PConv == false ->
+ {SenderPid, {no_more, DatBin}} ->
finish_copy(Storage,Tab,Cs,SenderPid,DatBin,OrigTabRec);
-
- %% Protocol conversion hack
- {SenderPid, {no_more, DatBin}} when is_pid(PConv) ->
- PConv ! {SenderPid, no_more},
- receive
- {old_init_table_complete, ok} ->
- finish_copy(Storage, Tab, Cs, SenderPid, DatBin,OrigTabRec);
- {old_init_table_complete, Reason} ->
- Msg = "OLD: [d]ets:init table failed",
- verbose("~s: ~p: ~p~n", [Msg, Tab, Reason]),
- down(Tab, Storage)
- end;
-
- {actual_tabrec, Pid} ->
- tab_receiver(Node, Tab, Storage, Cs, Pid,OrigTabRec);
-
- {SenderPid, {more, [Recs]}} when is_pid(PConv) ->
- PConv ! {SenderPid, {more, Recs}}, %% Forward Msg to OldNodes
- tab_receiver(Node, Tab, Storage, Cs, PConv,OrigTabRec);
- {'EXIT', PConv, Reason} -> %% [d]ets:init process crashed
- Msg = "Receiver crashed",
- verbose("~s: ~p: ~p~n", [Msg, Tab, Reason]),
- down(Tab, Storage);
-
%% Protocol conversion hack
{copier_done, Node} ->
verbose("Sender of table ~p crashed on node ~p ~n", [Tab, Node]),
down(Tab, Storage);
-
+
{'EXIT', Pid, Reason} ->
handle_exit(Pid, Reason),
- tab_receiver(Node, Tab, Storage, Cs, PConv,OrigTabRec)
+ tab_receiver(Node, Tab, Storage, Cs, OrigTabRec)
end.
make_table_fun(Pid, TabRec) ->
fun(close) ->
ok;
(read) ->
- get_data(Pid, TabRec)
+ get_data(Pid, TabRec)
end.
get_data(Pid, TabRec) ->
- receive
+ receive
{Pid, {more_z, CompressedRecs}} when is_binary(CompressedRecs) ->
Pid ! {TabRec, more},
{zlib_uncompress(CompressedRecs), make_table_fun(Pid,TabRec)};
@@ -448,7 +413,7 @@ get_data(Pid, TabRec) ->
end_of_input;
{copier_done, Node} ->
case node(Pid) of
- Node ->
+ Node ->
{copier_done, Node};
_ ->
get_data(Pid, TabRec)
@@ -458,13 +423,13 @@ get_data(Pid, TabRec) ->
get_data(Pid, TabRec)
end.
-init_table(Tab, disc_only_copies, Fun, false, DetsInfo,Sender) ->
+init_table(Tab, disc_only_copies, Fun, DetsInfo,Sender) ->
ErtsVer = erlang:system_info(version),
case DetsInfo of
- {ErtsVer, DetsData} ->
+ {ErtsVer, DetsData} ->
Res = (catch dets:is_compatible_bchunk_format(Tab, DetsData)),
case Res of
- {'EXIT',{undef,[{dets,_,_}|_]}} ->
+ {'EXIT',{undef,[{dets,_,_,_}|_]}} ->
Sender ! {self(), {old_protocol, Tab}},
dets:init_table(Tab, Fun); %% Old dets version
{'EXIT', What} ->
@@ -481,28 +446,19 @@ init_table(Tab, disc_only_copies, Fun, false, DetsInfo,Sender) ->
_ ->
dets:init_table(Tab, Fun)
end;
-init_table(Tab, _, Fun, false, _DetsInfo,_) ->
+init_table(Tab, _, Fun, _DetsInfo,_) ->
case catch ets:init_table(Tab, Fun) of
true ->
ok;
{'EXIT', Else} -> Else
- end;
-init_table(Tab, Storage, Fun, true, _DetsInfo, Sender) -> %% Old Nodes
- spawn_link(?MODULE, old_node_init_table,
- [Tab, Storage, Fun, self(), false, Sender]),
- ok.
+ end.
-old_node_init_table(Tab, Storage, Fun, TabReceiver, DetsInfo,Sender) ->
- Res = init_table(Tab, Storage, Fun, false, DetsInfo,Sender),
- TabReceiver ! {old_init_table_complete, Res},
- unlink(TabReceiver),
- ok.
finish_copy(Storage,Tab,Cs,SenderPid,DatBin,OrigTabRec) ->
TabRef = {Storage, Tab},
subscr_receiver(TabRef, Cs#cstruct.record_name),
case handle_last(TabRef, Cs#cstruct.type, DatBin) of
- ok ->
+ ok ->
mnesia_index:init_index(Tab, Storage),
snmpify(Tab, Storage),
%% OrigTabRec must not be the spawned tab-receiver
@@ -534,7 +490,7 @@ subscr_receiver(TabRef = {_, Tab}, RecName) ->
ok
end.
-handle_event(TabRef, write, Rec) ->
+handle_event(TabRef, write, Rec) ->
db_put(TabRef, Rec);
handle_event(TabRef, delete, {_Tab, Key}) ->
db_erase(TabRef, Key);
@@ -545,8 +501,8 @@ handle_event(TabRef, clear_table, {_Tab, _Key}) ->
handle_last({disc_copies, Tab}, _Type, nobin) ->
Ret = mnesia_log:ets2dcd(Tab),
- Fname = mnesia_lib:tab2dat(Tab),
- case mnesia_lib:exists(Fname) of
+ Fname = mnesia_lib:tab2dat(Tab),
+ case mnesia_lib:exists(Fname) of
true -> %% Remove old .DAT files.
file:delete(Fname);
false ->
@@ -653,31 +609,29 @@ send_table(Pid, Tab, RemoteS) ->
{error, {no_exists, Tab}};
Storage ->
%% Send first
- TabSize = mnesia:table_info(Tab, size),
- Pconvert = mnesia_monitor:needs_protocol_conversion(node(Pid)),
+ TabSize = mnesia:table_info(Tab, size),
KeysPerTransfer = calc_nokeys(Storage, Tab),
ChunkData = dets:info(Tab, bchunk_format),
- UseDetsChunk =
- Storage == RemoteS andalso
- Storage == disc_only_copies andalso
- ChunkData /= undefined andalso
- Pconvert == false,
- if
+ UseDetsChunk =
+ Storage == RemoteS andalso
+ Storage == disc_only_copies andalso
+ ChunkData /= undefined,
+ if
UseDetsChunk == true ->
DetsInfo = erlang:system_info(version),
Pid ! {self(), {first, TabSize, {DetsInfo, ChunkData}}};
true ->
Pid ! {self(), {first, TabSize}}
end,
-
+
%% Debug info
put(mnesia_table_sender, {Tab, node(Pid), Pid}),
{Init, Chunk} = reader_funcs(UseDetsChunk, Tab, Storage, KeysPerTransfer),
-
+
SendIt = fun() ->
prepare_copy(Pid, Tab, Storage),
- send_more(Pid, 1, Chunk, Init(), Tab, Pconvert),
+ send_more(Pid, 1, Chunk, Init(), Tab),
finish_copy(Pid, Tab, Storage, RemoteS)
end,
@@ -698,7 +652,7 @@ send_table(Pid, Tab, RemoteS) ->
{error, Reason}
end
end.
-
+
prepare_copy(Pid, Tab, Storage) ->
Trans =
fun() ->
@@ -717,11 +671,11 @@ prepare_copy(Pid, Tab, Storage) ->
update_where_to_write(Tab, Node) ->
case val({Tab, access_mode}) of
- read_only ->
+ read_only ->
ignore;
- read_write ->
+ read_write ->
Current = val({current, db_nodes}),
- Ns =
+ Ns =
case lists:member(Node, Current) of
true -> Current;
false -> [Node | Current]
@@ -729,27 +683,27 @@ update_where_to_write(Tab, Node) ->
update_where_to_write(Ns, Tab, Node)
end.
-update_where_to_write([], _, _) ->
+update_where_to_write([], _, _) ->
ok;
update_where_to_write([H|T], Tab, AddNode) ->
- rpc:call(H, mnesia_controller, call,
+ rpc:call(H, mnesia_controller, call,
[{update_where_to_write, [add, Tab, AddNode], self()}]),
update_where_to_write(T, Tab, AddNode).
-send_more(Pid, N, Chunk, DataState, Tab, OldNode) ->
+send_more(Pid, N, Chunk, DataState, Tab) ->
receive
{NewPid, more} ->
- case send_packet(N - 1, NewPid, Chunk, DataState, OldNode) of
- New when is_integer(New) ->
+ case send_packet(N - 1, NewPid, Chunk, DataState) of
+ New when is_integer(New) ->
New - 1;
NewData ->
- send_more(NewPid, ?MAX_NOPACKETS, Chunk, NewData, Tab, OldNode)
+ send_more(NewPid, ?MAX_NOPACKETS, Chunk, NewData, Tab)
end;
{_NewPid, {old_protocol, Tab}} ->
Storage = val({Tab, storage_type}),
- {Init, NewChunk} =
+ {Init, NewChunk} =
reader_funcs(false, Tab, Storage, calc_nokeys(Storage, Tab)),
- send_more(Pid, 1, NewChunk, Init(), Tab, OldNode);
+ send_more(Pid, 1, NewChunk, Init(), Tab);
{copier_done, Node} when Node == node(Pid)->
verbose("Receiver of table ~p crashed on ~p (more)~n", [Tab, Node]),
@@ -770,7 +724,7 @@ dets_bchunk(Tab, Chunk) -> %% Arrg
case dets:bchunk(Tab, Chunk) of
{Cont, Data} -> {Data, Cont};
Else -> Else
- end.
+ end.
zlib_compress(Data, Level) ->
BinData = term_to_binary(Data),
@@ -793,28 +747,20 @@ compression_level() ->
Val -> Val
end.
-send_packet(N, Pid, _Chunk, '$end_of_table', OldNode) ->
- case OldNode of
- true -> ignore; %% Old nodes can't handle the new no_more
- false -> Pid ! {self(), no_more}
- end,
+send_packet(N, Pid, _Chunk, '$end_of_table') ->
+ Pid ! {self(), no_more},
N;
-send_packet(N, Pid, Chunk, {[], Cont}, OldNode) ->
- send_packet(N, Pid, Chunk, Chunk(Cont), OldNode);
-send_packet(N, Pid, Chunk, {Recs, Cont}, OldNode) when N < ?MAX_NOPACKETS ->
- case OldNode of
- true ->
- Pid ! {self(), {more, [Recs]}}; %% Old need's wrapping list
- false ->
- case compression_level() of
- 0 ->
- Pid ! {self(), {more, Recs}};
- Level ->
- Pid ! {self(), {more_z, zlib_compress(Recs, Level)}}
- end
+send_packet(N, Pid, Chunk, {[], Cont}) ->
+ send_packet(N, Pid, Chunk, Chunk(Cont));
+send_packet(N, Pid, Chunk, {Recs, Cont}) when N < ?MAX_NOPACKETS ->
+ case compression_level() of
+ 0 ->
+ Pid ! {self(), {more, Recs}};
+ Level ->
+ Pid ! {self(), {more_z, zlib_compress(Recs, Level)}}
end,
- send_packet(N+1, Pid, Chunk, Chunk(Cont), OldNode);
-send_packet(_N, _Pid, _Chunk, DataState, _OldNode) ->
+ send_packet(N+1, Pid, Chunk, Chunk(Cont));
+send_packet(_N, _Pid, _Chunk, DataState) ->
DataState.
finish_copy(Pid, Tab, Storage, RemoteS) ->
@@ -855,5 +801,5 @@ dat2bin(_Tab, _LocalS, _RemoteS) ->
handle_exit(Pid, Reason) when node(Pid) == node() ->
exit(Reason);
-handle_exit(_Pid, _Reason) -> %% Not from our node, this will be handled by
+handle_exit(_Pid, _Reason) -> %% Not from our node, this will be handled by
ignore. %% mnesia_down soon.
diff --git a/lib/mnesia/src/mnesia_log.erl b/lib/mnesia/src/mnesia_log.erl
index 9e804cc4c2..94153473cb 100644
--- a/lib/mnesia/src/mnesia_log.erl
+++ b/lib/mnesia/src/mnesia_log.erl
@@ -1021,7 +1021,8 @@ add_recs([LogH|Rest], N)
LogH#log_header.log_version >= "1.0" ->
add_recs(Rest, N);
add_recs([{{Tab, _Key}, _Val, clear_table} | Rest], N) ->
- true = ets:match_delete(Tab, '_'),
- add_recs(Rest, N+ets:info(Tab, size));
+ Size = ets:info(Tab, size),
+ true = ets:delete_all_objects(Tab),
+ add_recs(Rest, N+Size);
add_recs([], N) ->
N.
diff --git a/lib/mnesia/src/mnesia_monitor.erl b/lib/mnesia/src/mnesia_monitor.erl
index b6eda9ad3a..8cb2e92c08 100644
--- a/lib/mnesia/src/mnesia_monitor.erl
+++ b/lib/mnesia/src/mnesia_monitor.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -76,13 +76,13 @@
-include("mnesia.hrl").
--record(state, {supervisor, pending_negotiators = [],
+-record(state, {supervisor, pending_negotiators = [],
going_down = [], tm_started = false, early_connects = [],
connecting, mq = []}).
--define(current_protocol_version, {7,6}).
+-define(current_protocol_version, {8,0}).
--define(previous_protocol_version, {7,5}).
+-define(previous_protocol_version, {7,6}).
start() ->
gen_server:start_link({local, ?MODULE}, ?MODULE,
@@ -151,12 +151,12 @@ check_protocol([{Node, {accept, Mon, Version, Protocol}} | Tail], Protocols) ->
case lists:member(Protocol, Protocols) of
true ->
case Protocol == protocol_version() of
- true ->
+ true ->
set({protocol, Node}, {Protocol, false});
false ->
set({protocol, Node}, {Protocol, true})
end,
- [node(Mon) | check_protocol(Tail, Protocols)];
+ [node(Mon) | check_protocol(Tail, Protocols)];
false ->
verbose("Failed to connect with ~p. ~p protocols rejected. "
"expected version = ~p, expected protocol = ~p~n",
@@ -179,7 +179,7 @@ check_protocol([], [Protocol | _Protocols]) ->
set(protocol_version, Protocol),
[].
-protocol_version() ->
+protocol_version() ->
case ?catch_val(protocol_version) of
{'EXIT', _} -> ?current_protocol_version;
Version -> Version
@@ -189,14 +189,14 @@ protocol_version() ->
%% preferred protocols are first in the list
acceptable_protocol_versions() ->
[protocol_version(), ?previous_protocol_version].
-
+
needs_protocol_conversion(Node) ->
case {?catch_val({protocol, Node}), protocol_version()} of
{{'EXIT', _}, _} ->
false;
- {{_, Bool}, ?current_protocol_version} ->
+ {{_, Bool}, ?current_protocol_version} ->
Bool;
- {{_, Bool}, _} ->
+ {{_, Bool}, _} ->
not Bool
end.
@@ -255,15 +255,15 @@ terminate_proc(Who, Reason, _State) ->
%%----------------------------------------------------------------------
init([Parent]) ->
process_flag(trap_exit, true),
- ?ets_new_table(mnesia_gvar, [set, public, named_table]),
- ?ets_new_table(mnesia_stats, [set, public, named_table]),
+ ?ets_new_table(mnesia_gvar, [set, public, named_table]),
+ ?ets_new_table(mnesia_stats, [set, public, named_table]),
set(subscribers, []),
set(activity_subscribers, []),
mnesia_lib:verbose("~p starting: ~p~n", [?MODULE, self()]),
Version = mnesia:system_info(version),
set(version, Version),
dbg_out("Version: ~p~n", [Version]),
-
+
case catch process_config_args(env()) of
ok ->
mnesia_lib:set({'$$$_report', current_pos}, 0),
@@ -283,7 +283,7 @@ init([Parent]) ->
set(checkpoints, []),
set(pending_checkpoints, []),
set(pending_checkpoint_pids, []),
-
+
{ok, #state{supervisor = Parent}};
{'EXIT', Reason} ->
mnesia_lib:report_fatal("Bad configuration: ~p~n", [Reason]),
@@ -398,9 +398,9 @@ handle_call({unsafe_close_log, Name}, _From, State) ->
disk_log:close(Name),
{reply, ok, State};
-handle_call({negotiate_protocol, Mon, _Version, _Protocols}, _From, State)
+handle_call({negotiate_protocol, Mon, _Version, _Protocols}, _From, State)
when State#state.tm_started == false ->
- State2 = State#state{early_connects = [node(Mon) | State#state.early_connects]},
+ State2 = State#state{early_connects = [node(Mon) | State#state.early_connects]},
{reply, {node(), {reject, self(), uninitialized, uninitialized}}, State2};
%% From remote monitor..
@@ -412,7 +412,7 @@ handle_call({negotiate_protocol, Mon, Version, Protocols}, From, State)
true ->
accept_protocol(Mon, MyVersion, Protocol, From, State);
false ->
- %% in this release we should be able to handle the previous
+ %% in this release we should be able to handle the previous
%% protocol
case hd(Protocols) of
?previous_protocol_version ->
@@ -427,7 +427,7 @@ handle_call({negotiate_protocol, Mon, Version, Protocols}, From, State)
end;
%% Local request to negotiate with other monitors (nodes).
-handle_call({negotiate_protocol, Nodes}, From, State) ->
+handle_call({negotiate_protocol, Nodes}, From, State) ->
case mnesia_lib:intersect(State#state.going_down, Nodes) of
[] ->
spawn_link(?MODULE, negotiate_protocol_impl, [Nodes, From]),
@@ -461,7 +461,7 @@ accept_protocol(Mon, Version, Protocol, From, State) ->
%% No need for wait
link(Mon), %% link to remote Monitor
case Protocol == protocol_version() of
- true ->
+ true ->
set({protocol, Node}, {Protocol, false});
false ->
set({protocol, Node}, {Protocol, true})
@@ -509,7 +509,7 @@ handle_cast({disconnect, Node}, State) ->
ignore;
undefined ->
ignore;
- RemoteMon when is_pid(RemoteMon) ->
+ RemoteMon when is_pid(RemoteMon) ->
unlink(RemoteMon)
end,
{noreply, State};
@@ -534,9 +534,13 @@ handle_info({'EXIT', Pid, R}, State) when Pid == State#state.supervisor ->
dbg_out("~p was ~p by supervisor~n",[?MODULE, R]),
{stop, R, State};
-handle_info({'EXIT', Pid, fatal}, State) when node(Pid) == node() ->
+handle_info({'EXIT', Pid, fatal}, State) when node(Pid) == node() ->
dbg_out("~p got FATAL ERROR from: ~p~n",[?MODULE, Pid]),
- exit(State#state.supervisor, shutdown),
+ %% This may hang supervisor if a shutdown happens at the same time as an fatal
+ %% is in progress
+ %% exit(State#state.supervisor, shutdown),
+ %% It is better to kill an innocent process
+ catch exit(whereis(mnesia_locker), kill),
{noreply, State};
handle_info(Msg = {'EXIT',Pid,_}, State) ->
@@ -550,7 +554,7 @@ handle_info(Msg = {'EXIT',Pid,_}, State) ->
Node /= node() ->
{noreply, State#state{mq = State#state.mq ++ [{info, Msg}]}};
true ->
- %% We have probably got an exit signal from
+ %% We have probably got an exit signal from
%% disk_log or dets
Hint = "Hint: check that the disk still is writable",
fatal("~p got unexpected info: ~p; ~p~n",
@@ -567,10 +571,10 @@ handle_info({nodeup, Node}, State) ->
%% Let's check if Mnesia is running there in order
%% to detect if the network has been partitioned
%% due to communication failure.
-
+
HasDown = mnesia_recover:has_mnesia_down(Node),
ImRunning = mnesia_lib:is_running(),
-
+
if
%% If I'm not running the test will be made later.
HasDown == true, ImRunning == yes ->
@@ -589,7 +593,7 @@ handle_info({disk_log, _Node, Log, Info}, State) ->
{truncated, _No} ->
ok;
_ ->
- mnesia_lib:important("Warning Log file ~p error reason ~s~n",
+ mnesia_lib:important("Warning Log file ~p error reason ~s~n",
[Log, disk_log:format_error(Info)])
end,
{noreply, State};
@@ -681,38 +685,38 @@ env() ->
send_compressed
].
-default_env(access_module) ->
+default_env(access_module) ->
mnesia;
-default_env(auto_repair) ->
+default_env(auto_repair) ->
true;
-default_env(backup_module) ->
+default_env(backup_module) ->
mnesia_backup;
-default_env(debug) ->
+default_env(debug) ->
none;
default_env(dir) ->
Name = lists:concat(["Mnesia.", node()]),
filename:absname(Name);
-default_env(dump_log_load_regulation) ->
+default_env(dump_log_load_regulation) ->
false;
-default_env(dump_log_time_threshold) ->
+default_env(dump_log_time_threshold) ->
timer:minutes(3);
-default_env(dump_log_update_in_place) ->
+default_env(dump_log_update_in_place) ->
true;
default_env(dump_log_write_threshold) ->
1000;
-default_env(embedded_mnemosyne) ->
+default_env(embedded_mnemosyne) ->
false;
-default_env(event_module) ->
+default_env(event_module) ->
mnesia_event;
-default_env(extra_db_nodes) ->
+default_env(extra_db_nodes) ->
[];
-default_env(ignore_fallback_at_startup) ->
+default_env(ignore_fallback_at_startup) ->
false;
default_env(fallback_error_function) ->
{mnesia, lkill};
-default_env(max_wait_for_decision) ->
+default_env(max_wait_for_decision) ->
infinity;
-default_env(schema_location) ->
+default_env(schema_location) ->
opt_disc;
default_env(core_dir) ->
false;
@@ -732,7 +736,7 @@ check_type(Env, Val) ->
NewVal ->
NewVal
end.
-
+
do_check_type(access_module, A) when is_atom(A) -> A;
do_check_type(auto_repair, B) -> bool(B);
do_check_type(backup_module, B) when is_atom(B) -> B;
@@ -749,7 +753,7 @@ do_check_type(dump_log_update_in_place, B) -> bool(B);
do_check_type(dump_log_write_threshold, I) when is_integer(I), I > 0 -> I;
do_check_type(event_module, A) when is_atom(A) -> A;
do_check_type(ignore_fallback_at_startup, B) -> bool(B);
-do_check_type(fallback_error_function, {Mod, Func})
+do_check_type(fallback_error_function, {Mod, Func})
when is_atom(Mod), is_atom(Func) -> {Mod, Func};
do_check_type(embedded_mnemosyne, B) -> bool(B);
do_check_type(extra_db_nodes, L) when is_list(L) ->
@@ -804,8 +808,8 @@ detect_inconcistency(Nodes, Context) ->
has_remote_mnesia_down(Node) ->
HasDown = mnesia_recover:has_mnesia_down(Node),
Master = mnesia_recover:get_master_nodes(schema),
- if
- HasDown == true, Master == [] ->
+ if
+ HasDown == true, Master == [] ->
{true, node()};
true ->
{false, node()}
diff --git a/lib/mnesia/src/mnesia_recover.erl b/lib/mnesia/src/mnesia_recover.erl
index b3eed1de6e..4750291a10 100644
--- a/lib/mnesia/src/mnesia_recover.erl
+++ b/lib/mnesia/src/mnesia_recover.erl
@@ -227,11 +227,13 @@ do_log_decision(D, DoTell, NodeD) ->
note_outcome(D2),
case mnesia_monitor:use_dir() of
true ->
- mnesia_log:append(latest_log, D2),
if
DoTell == true, Outcome /= unclear ->
tell_im_certain(NodeD#decision.disc_nodes--[node()],D2),
- tell_im_certain(NodeD#decision.ram_nodes--[node()], D2);
+ tell_im_certain(NodeD#decision.ram_nodes--[node()], D2),
+ mnesia_log:log(D2);
+ Outcome /= unclear ->
+ mnesia_log:log(D2);
true ->
ignore
end;
diff --git a/lib/mnesia/src/mnesia_schema.erl b/lib/mnesia/src/mnesia_schema.erl
index fef72ad39c..179e15197e 100644
--- a/lib/mnesia/src/mnesia_schema.erl
+++ b/lib/mnesia/src/mnesia_schema.erl
@@ -39,9 +39,10 @@
change_table_load_order/2,
change_table_majority/2,
change_table_frag/2,
- clear_table/1,
+%% clear_table/1, %% removed since it is not a schema op anymore
create_table/1,
cs2list/1,
+ vsn_cs2list/1,
del_snmp/1,
del_table_copy/2,
del_table_index/2,
@@ -65,6 +66,7 @@
merge_schema/0,
merge_schema/1,
move_table/3,
+ normalize_cs/2,
opt_create_dir/2,
prepare_commit/3,
purge_dir/2,
@@ -100,7 +102,7 @@
]).
%% Needed outside to be able to use/set table_properties
-%% from user (not supported)
+%% from user (not supported)
-export([schema_transaction/1,
insert_schema_ops/2,
do_create_table/1,
@@ -118,9 +120,9 @@
%% Here comes the init function which also resides in
%% this module, it is called upon by the trans server
%% at startup of the system
-%%
+%%
%% We have a meta table which looks like
-%% {table, schema,
+%% {table, schema,
%% {type, set},
%% {disc_copies, all},
%% {arity, 2}
@@ -149,14 +151,14 @@ exit_on_error(GoodRes) ->
val(Var) ->
case ?catch_val(Var) of
- {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
- Value -> Value
+ {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
+ Value -> Value
end.
%% This function traverses all cstructs in the schema and
%% sets all values in mnesia_gvar accordingly for each table/cstruct
-set_schema('$end_of_table') ->
+set_schema('$end_of_table') ->
[];
set_schema(Tab) ->
do_set_schema(Tab),
@@ -253,8 +255,8 @@ version() ->
incr_version(Cs) ->
{{Major, Minor}, _} = Cs#cstruct.version,
Nodes = mnesia_lib:intersect(val({schema, disc_copies}),
- mnesia_lib:cs_to_nodes(Cs)),
- V =
+ mnesia_lib:cs_to_nodes(Cs)),
+ V =
case Nodes -- val({Cs#cstruct.name, active_replicas}) of
[] -> {Major + 1, 0}; % All replicas are active
_ -> {Major, Minor + 1} % Some replicas are inactive
@@ -359,7 +361,7 @@ delete_schema2() ->
{error, Reason} ->
{error, Reason}
end.
-
+
ensure_no_schema([H|T]) when is_atom(H) ->
case rpc:call(H, ?MODULE, remote_read_schema, []) of
{badrpc, Reason} ->
@@ -407,7 +409,7 @@ opt_create_dir(UseDir, Dir) when UseDir == true->
check_can_write(Dir);
false ->
case file:make_dir(Dir) of
- ok ->
+ ok ->
verbose("Create Directory ~p~n", [Dir]),
ok;
{error, Reason} ->
@@ -417,7 +419,7 @@ opt_create_dir(UseDir, Dir) when UseDir == true->
end;
opt_create_dir(false, _) ->
{error, {has_no_disc, node()}}.
-
+
check_can_write(Dir) ->
case file:read_file_info(Dir) of
{ok, FI} when FI#file_info.type == directory,
@@ -450,7 +452,7 @@ read_schema(Keep) ->
read_schema(Keep, IgnoreFallback) ->
lock_schema(),
- Res =
+ Res =
case mnesia:system_info(is_running) of
yes ->
{ok, ram, get_create_list(schema)};
@@ -477,7 +479,7 @@ read_disc_schema(Keep, IgnoreFallback) ->
case mnesia_bup:fallback_exists() of
true when IgnoreFallback == false, Running /= yes ->
mnesia_bup:fallback_to_schema();
- _ ->
+ _ ->
%% If we're running, we read the schema file even
%% if fallback exists
Dat = mnesia_lib:tab2dat(schema),
@@ -499,7 +501,7 @@ read_disc_schema(Keep, IgnoreFallback) ->
end.
do_read_disc_schema(Fname, Keep) ->
- T =
+ T =
case Keep of
false ->
Args = [{keypos, 2}, public, set],
@@ -523,7 +525,7 @@ do_read_disc_schema(Fname, Keep) ->
get_initial_schema(SchemaStorage, Nodes) ->
Cs = #cstruct{name = schema,
record_name = schema,
- attributes = [table, cstruct]},
+ attributes = [table, cstruct]},
Cs2 =
case SchemaStorage of
ram_copies -> Cs#cstruct{ram_copies = Nodes};
@@ -532,7 +534,7 @@ get_initial_schema(SchemaStorage, Nodes) ->
cs2list(Cs2).
read_cstructs_from_disc() ->
- %% Assumptions:
+ %% Assumptions:
%% - local schema lock in global
%% - use_dir is true
%% - Mnesia is not running
@@ -552,14 +554,14 @@ read_cstructs_from_disc() ->
end,
Cstructs = dets:traverse(Tab, Fun),
dets:close(Tab),
- {ok, Cstructs};
+ {ok, Cstructs};
{error, Reason} ->
{error, Reason}
end;
false ->
{error, "No schema file exists"}
end.
-
+
%% We run a very special type of transactions when we
%% we want to manipulate the schema.
@@ -593,20 +595,20 @@ schema_transaction(Fun) ->
%% This process may dump the transaction log, and should
%% therefore not be run in an application process
-%%
+%%
schema_coordinator(Client, _Fun, undefined) ->
Res = {aborted, {node_not_running, node()}},
Client ! {transaction_done, Res, self()},
unlink(Client);
-
+
schema_coordinator(Client, Fun, Controller) when is_pid(Controller) ->
%% Do not trap exit in order to automatically die
%% when the controller dies
link(Controller),
unlink(Client),
-
- %% Fulfull the transaction even if the client dies
+
+ %% Fulfull the transaction even if the client dies
Res = mnesia:transaction(Fun),
Client ! {transaction_done, Res, self()},
unlink(Controller), % Avoids spurious exit message
@@ -619,24 +621,82 @@ schema_coordinator(Client, Fun, Controller) when is_pid(Controller) ->
insert_schema_ops({_Mod, _Tid, Ts}, SchemaIOps) ->
do_insert_schema_ops(Ts#tidstore.store, SchemaIOps).
-
+
do_insert_schema_ops(Store, [Head | Tail]) ->
?ets_insert(Store, Head),
do_insert_schema_ops(Store, Tail);
do_insert_schema_ops(_Store, []) ->
ok.
+api_list2cs(List) when is_list(List) ->
+ Name = pick(unknown, name, List, must),
+ Keys = check_keys(Name, List, record_info(fields, cstruct)),
+ check_duplicates(Name, Keys),
+ list2cs(List);
+api_list2cs(Other) ->
+ mnesia:abort({badarg, Other}).
+
+vsn_cs2list(Cs) ->
+ cs2list(need_old_cstructs(), Cs).
+
cs2list(Cs) when is_record(Cs, cstruct) ->
Tags = record_info(fields, cstruct),
- rec2list(Tags, 2, Cs);
+ rec2list(Tags, Tags, 2, Cs);
cs2list(CreateList) when is_list(CreateList) ->
- CreateList.
-
-rec2list([Tag | Tags], Pos, Rec) ->
+ CreateList;
+%% 4.4.19
+cs2list(Cs) when element(1, Cs) == cstruct, tuple_size(Cs) == 18 ->
+ Tags = [name,type,ram_copies,disc_copies,disc_only_copies,
+ load_order,access_mode,majority,index,snmp,local_content,
+ record_name,attributes,user_properties,frag_properties,
+ cookie,version],
+ rec2list(Tags, Tags, 2, Cs);
+%% 4.4.18 and earlier
+cs2list(Cs) when element(1, Cs) == cstruct, tuple_size(Cs) == 17 ->
+ Tags = [name,type,ram_copies,disc_copies,disc_only_copies,
+ load_order,access_mode,index,snmp,local_content,
+ record_name,attributes,user_properties,frag_properties,
+ cookie,version],
+ rec2list(Tags, Tags, 2, Cs).
+
+cs2list(false, Cs) ->
+ cs2list(Cs);
+cs2list(ver4_4_18, Cs) -> %% Or earlier
+ Orig = record_info(fields, cstruct),
+ Tags = [name,type,ram_copies,disc_copies,disc_only_copies,
+ load_order,access_mode,index,snmp,local_content,
+ record_name,attributes,user_properties,frag_properties,
+ cookie,version],
+ rec2list(Tags, Orig, 2, Cs);
+cs2list(ver4_4_19, Cs) ->
+ Orig = record_info(fields, cstruct),
+ Tags = [name,type,ram_copies,disc_copies,disc_only_copies,
+ load_order,access_mode,majority,index,snmp,local_content,
+ record_name,attributes,user_properties,frag_properties,
+ cookie,version],
+ rec2list(Tags, Orig, 2, Cs).
+
+rec2list([Tag | Tags], [Tag | Orig], Pos, Rec) ->
Val = element(Pos, Rec),
- [{Tag, Val} | rec2list(Tags, Pos + 1, Rec)];
-rec2list([], _Pos, _Rec) ->
- [].
+ [{Tag, Val} | rec2list(Tags, Orig, Pos + 1, Rec)];
+rec2list([], _, _Pos, _Rec) ->
+ [];
+rec2list(Tags, [_|Orig], Pos, Rec) ->
+ rec2list(Tags, Orig, Pos+1, Rec).
+
+normalize_cs(Cstructs, Node) ->
+ %% backward-compatibility hack; normalize before returning
+ case need_old_cstructs([Node]) of
+ false ->
+ Cstructs;
+ Version ->
+ %% some other format
+ [convert_cs(Version, Cs) || Cs <- Cstructs]
+ end.
+
+convert_cs(Version, Cs) ->
+ Fields = [Value || {_, Value} <- cs2list(Version, Cs)],
+ list_to_tuple([cstruct|Fields]).
list2cs(List) when is_list(List) ->
Name = pick(unknown, name, List, must),
@@ -667,10 +727,7 @@ list2cs(List) when is_list(List) ->
Frag = pick(Name, frag_properties, List, []),
verify({alt, [nil, list]}, mnesia_lib:etype(Frag),
- {badarg, Name, {frag_properties, Frag}}),
-
- Keys = check_keys(Name, List, record_info(fields, cstruct)),
- check_duplicates(Name, Keys),
+ {badarg, Name, {frag_properties, Frag}}),
#cstruct{name = Name,
ram_copies = Rc,
disc_copies = Dc,
@@ -687,9 +744,7 @@ list2cs(List) when is_list(List) ->
user_properties = lists:sort(UserProps),
frag_properties = lists:sort(Frag),
cookie = Cookie,
- version = Version};
-list2cs(Other) ->
- mnesia:abort({badarg, Other}).
+ version = Version}.
pick(Tab, Key, List, Default) ->
case lists:keysearch(Key, 1, List) of
@@ -708,7 +763,7 @@ attr_tab_to_pos(_Tab, Pos) when is_integer(Pos) ->
Pos;
attr_tab_to_pos(Tab, Attr) ->
attr_to_pos(Attr, val({Tab, attributes})).
-
+
%% Convert attribute name to integer if neccessary
attr_to_pos(Pos, _Attrs) when is_integer(Pos) ->
Pos;
@@ -723,7 +778,7 @@ attr_to_pos(Attr, [_ | Attrs], Pos) ->
attr_to_pos(Attr, Attrs, Pos + 1);
attr_to_pos(Attr, _, _) ->
mnesia:abort({bad_type, Attr}).
-
+
check_keys(Tab, [{Key, _Val} | Tail], Items) ->
case lists:member(Key, Items) of
true -> [Key | check_keys(Tab, Tail, Items)];
@@ -759,7 +814,7 @@ verify_cstruct(Cs) when is_record(Cs, cstruct) ->
{bad_type, Tab, {type, Type}}),
%% Currently ordered_set is not supported for disk_only_copies.
- if
+ if
Type == ordered_set, Cs#cstruct.disc_only_copies /= [] ->
mnesia:abort({bad_type, Tab, {not_supported, Type, disc_only_copies}});
true ->
@@ -776,10 +831,10 @@ verify_cstruct(Cs) when is_record(Cs, cstruct) ->
Arity = length(Attrs) + 1,
verify(true, Arity > 2, {bad_type, Tab, {attributes, Attrs}}),
-
+
lists:foldl(fun(Attr,_Other) when Attr == snmp ->
mnesia:abort({bad_type, Tab, {attributes, [Attr]}});
- (Attr,Other) ->
+ (Attr,Other) ->
verify(atom, mnesia_lib:etype(Attr),
{bad_type, Tab, {attributes, [Attr]}}),
verify(false, lists:member(Attr, Other),
@@ -792,7 +847,7 @@ verify_cstruct(Cs) when is_record(Cs, cstruct) ->
Index = Cs#cstruct.index,
verify({alt, [nil, list]}, mnesia_lib:etype(Index),
{bad_type, Tab, {index, Index}}),
-
+
IxFun =
fun(Pos) ->
verify(true, fun() ->
@@ -807,7 +862,7 @@ verify_cstruct(Cs) when is_record(Cs, cstruct) ->
{bad_type, Tab, {index, [Pos]}})
end,
lists:foreach(IxFun, Index),
-
+
LC = Cs#cstruct.local_content,
verify({alt, [true, false]}, LC,
{bad_type, Tab, {local_content, LC}}),
@@ -834,7 +889,7 @@ verify_cstruct(Cs) when is_record(Cs, cstruct) ->
lists:foreach(CheckProp, Cs#cstruct.user_properties),
case Cs#cstruct.cookie of
- {{MegaSecs, Secs, MicroSecs}, _Node}
+ {{MegaSecs, Secs, MicroSecs}, _Node}
when is_integer(MegaSecs), is_integer(Secs),
is_integer(MicroSecs), is_atom(node) ->
ok;
@@ -870,15 +925,15 @@ verify_nodes(Cs) ->
end,
verify(integer, mnesia_lib:etype(LoadOrder),
{bad_type, Tab, {load_order, LoadOrder}}),
-
+
Nodes = Ram ++ Disc ++ DiscOnly,
verify(list, mnesia_lib:etype(Nodes),
{combine_error, Tab,
[{ram_copies, []}, {disc_copies, []}, {disc_only_copies, []}]}),
verify(false, has_duplicates(Nodes), {combine_error, Tab, Nodes}),
- AtomCheck = fun(N) -> verify(atom, mnesia_lib:etype(N), {bad_type, Tab, N}) end,
+ AtomCheck = fun(N) -> verify(atom, mnesia_lib:etype(N), {bad_type, Tab, N}) end,
lists:foreach(AtomCheck, Nodes).
-
+
verify(Expected, Fun, Error) when is_function(Fun) ->
do_verify(Expected, catch Fun(), Error);
verify(Expected, Actual, Error) ->
@@ -909,7 +964,7 @@ ensure_active(Cs, What) ->
W = {Tab, What},
ensure_non_empty(W),
Nodes = mnesia_lib:intersect(val({schema, disc_copies}),
- mnesia_lib:cs_to_nodes(Cs)),
+ mnesia_lib:cs_to_nodes(Cs)),
case Nodes -- val(W) of
[] ->
ok;
@@ -936,7 +991,7 @@ ensure_non_empty({Tab, Vhat}) ->
ensure_not_active(Tab = schema, Node) ->
Active = val({Tab, active_replicas}),
- case lists:member(Node, Active) of
+ case lists:member(Node, Active) of
false when Active =/= [] ->
ok;
false ->
@@ -970,7 +1025,7 @@ create_table(TabDef) ->
do_multi_create_table(TabDef) ->
get_tid_ts_and_lock(schema, write),
ensure_writable(schema),
- Cs = list2cs(TabDef),
+ Cs = api_list2cs(TabDef),
case Cs#cstruct.frag_properties of
[] ->
do_create_table(Cs);
@@ -999,7 +1054,7 @@ unsafe_make_create_table(Cs) ->
{_Mod, Tid, Ts} = get_tid_ts_and_lock(schema, none),
verify_cstruct(Cs),
Tab = Cs#cstruct.name,
-
+
%% Check that we have all disc replica nodes running
DiscNodes = Cs#cstruct.disc_copies ++ Cs#cstruct.disc_only_copies,
RunningNodes = val({current, db_nodes}),
@@ -1012,12 +1067,12 @@ unsafe_make_create_table(Cs) ->
Nodes = mnesia_lib:intersect(mnesia_lib:cs_to_nodes(Cs), RunningNodes),
Store = Ts#tidstore.store,
mnesia_locker:wlock_no_exist(Tid, Store, Tab, Nodes),
- [{op, create_table, cs2list(Cs)}].
+ [{op, create_table, vsn_cs2list(Cs)}].
check_if_exists(Tab) ->
TidTs = get_tid_ts_and_lock(schema, write),
{_, _, Ts} = TidTs,
- Store = Ts#tidstore.store,
+ Store = Ts#tidstore.store,
ets:foldl(
fun({op, create_table, [{name, T}|_]}, _Acc) when T==Tab ->
true;
@@ -1054,7 +1109,7 @@ make_delete_table(Tab, Mode) ->
%% nodes etc.
TidTs = get_tid_ts_and_lock(schema, write),
{_, _, Ts} = TidTs,
- Store = Ts#tidstore.store,
+ Store = Ts#tidstore.store,
Deleted = ets:select_delete(
Store, [{{op,'$1',[{name,Tab}|'_']},
[{'or',
@@ -1077,9 +1132,9 @@ make_delete_table(Tab, Mode) ->
[] ->
[make_delete_table2(Tab)];
_Props ->
- %% Check if it is a base table
- mnesia_frag:lookup_frag_hash(Tab),
-
+ %% Check if it is a base table
+ mnesia_frag:lookup_frag_hash(Tab),
+
%% Check for foreigners
F = mnesia_frag:lookup_foreigners(Tab),
verify([], F, {combine_error,
@@ -1097,11 +1152,11 @@ make_delete_table2(Tab) ->
Cs = val({Tab, cstruct}),
ensure_active(Cs),
ensure_writable(Tab),
- {op, delete_table, cs2list(Cs)}.
+ {op, delete_table, vsn_cs2list(Cs)}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Change fragmentation of a table
-
+
change_table_frag(Tab, Change) ->
schema_transaction(fun() -> do_change_table_frag(Tab, Change) end).
@@ -1112,14 +1167,10 @@ do_change_table_frag(Tab, Change) when is_atom(Tab), Tab /= schema ->
ok;
do_change_table_frag(Tab, _Change) ->
mnesia:abort({bad_type, Tab}).
-
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Clear a table
-%% No need for a schema transaction
-clear_table(Tab) ->
- schema_transaction(fun() -> do_clear_table(Tab) end).
-
do_clear_table(schema) ->
mnesia:abort({bad_type, schema});
do_clear_table(Tab) ->
@@ -1130,7 +1181,7 @@ do_clear_table(Tab) ->
make_clear_table(Tab) ->
Cs = val({Tab, cstruct}),
ensure_writable(Tab),
- [{op, clear_table, cs2list(Cs)}].
+ [{op, clear_table, vsn_cs2list(Cs)}].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1150,7 +1201,7 @@ make_add_table_copy(Tab, Node, Storage) ->
verify(false, lists:member(Node, Ns), {already_exists, Tab, Node}),
Cs2 = new_cs(Cs, Node, Storage, add),
verify_cstruct(Cs2),
-
+
%% Check storage and if node is running
IsRunning = lists:member(Node, val({current, db_nodes})),
if
@@ -1170,28 +1221,28 @@ make_add_table_copy(Tab, Node, Storage) ->
IsRunning == false ->
mnesia:abort({not_active, schema, Node})
end,
- [{op, add_table_copy, Storage, Node, cs2list(Cs2)}].
+ [{op, add_table_copy, Storage, Node, vsn_cs2list(Cs2)}].
del_table_copy(Tab, Node) ->
schema_transaction(fun() -> do_del_table_copy(Tab, Node) end).
do_del_table_copy(Tab, Node) when is_atom(Node) ->
TidTs = get_tid_ts_and_lock(schema, write),
-%% get_tid_ts_and_lock(Tab, write),
+%% get_tid_ts_and_lock(Tab, write),
insert_schema_ops(TidTs, make_del_table_copy(Tab, Node));
do_del_table_copy(Tab, Node) ->
mnesia:abort({badarg, Tab, Node}).
-
+
make_del_table_copy(Tab, Node) ->
ensure_writable(schema),
Cs = incr_version(val({Tab, cstruct})),
Storage = mnesia_lib:schema_cs_to_storage_type(Node, Cs),
- Cs2 = new_cs(Cs, Node, Storage, del),
+ Cs2 = new_cs(Cs, Node, Storage, del),
case mnesia_lib:cs_to_nodes(Cs2) of
[] when Tab == schema ->
mnesia:abort({combine_error, Tab, "Last replica"});
[] ->
- ensure_active(Cs),
+ ensure_active(Cs),
dbg_out("Last replica deleted in table ~p~n", [Tab]),
make_delete_table(Tab, whole_table);
_ when Tab == schema ->
@@ -1199,25 +1250,25 @@ make_del_table_copy(Tab, Node) ->
ensure_not_active(Tab, Node),
verify_cstruct(Cs2),
Ops = remove_node_from_tabs(val({schema, tables}), Node),
- [{op, del_table_copy, ram_copies, Node, cs2list(Cs2)} | Ops];
+ [{op, del_table_copy, ram_copies, Node, vsn_cs2list(Cs2)} | Ops];
_ ->
ensure_active(Cs),
verify_cstruct(Cs2),
- [{op, del_table_copy, Storage, Node, cs2list(Cs2)}]
+ [{op, del_table_copy, Storage, Node, vsn_cs2list(Cs2)}]
end.
remove_node_from_tabs([], _Node) ->
[];
remove_node_from_tabs([schema|Rest], Node) ->
remove_node_from_tabs(Rest, Node);
-remove_node_from_tabs([Tab|Rest], Node) ->
- {Cs, IsFragModified} =
+remove_node_from_tabs([Tab|Rest], Node) ->
+ {Cs, IsFragModified} =
mnesia_frag:remove_node(Node, incr_version(val({Tab, cstruct}))),
case mnesia_lib:schema_cs_to_storage_type(Node, Cs) of
unknown ->
case IsFragModified of
true ->
- [{op, change_table_frag, {del_node, Node}, cs2list(Cs)} |
+ [{op, change_table_frag, {del_node, Node}, vsn_cs2list(Cs)} |
remove_node_from_tabs(Rest, Node)];
false ->
remove_node_from_tabs(Rest, Node)
@@ -1226,11 +1277,11 @@ remove_node_from_tabs([Tab|Rest], Node) ->
Cs2 = new_cs(Cs, Node, Storage, del),
case mnesia_lib:cs_to_nodes(Cs2) of
[] ->
- [{op, delete_table, cs2list(Cs)} |
+ [{op, delete_table, vsn_cs2list(Cs)} |
remove_node_from_tabs(Rest, Node)];
_Ns ->
verify_cstruct(Cs2),
- [{op, del_table_copy, ram_copies, Node, cs2list(Cs2)}|
+ [{op, del_table_copy, ram_copies, Node, vsn_cs2list(Cs2)}|
remove_node_from_tabs(Rest, Node)]
end
end.
@@ -1246,7 +1297,7 @@ new_cs(Cs, Node, ram_copies, del) ->
new_cs(Cs, Node, disc_copies, del) ->
Cs#cstruct{disc_copies = lists:delete(Node , Cs#cstruct.disc_copies)};
new_cs(Cs, Node, disc_only_copies, del) ->
- Cs#cstruct{disc_only_copies =
+ Cs#cstruct{disc_only_copies =
lists:delete(Node , Cs#cstruct.disc_only_copies)};
new_cs(Cs, _Node, Storage, _Op) ->
mnesia:abort({badarg, Cs#cstruct.name, Storage}).
@@ -1278,13 +1329,13 @@ make_move_table(Tab, FromNode, ToNode) ->
Running = val({current, db_nodes}),
Storage = mnesia_lib:schema_cs_to_storage_type(FromNode, Cs),
verify(true, lists:member(ToNode, Running), {not_active, schema, ToNode}),
-
+
Cs2 = new_cs(Cs, ToNode, Storage, add),
Cs3 = new_cs(Cs2, FromNode, Storage, del),
verify_cstruct(Cs3),
- [{op, add_table_copy, Storage, ToNode, cs2list(Cs2)},
+ [{op, add_table_copy, Storage, ToNode, vsn_cs2list(Cs2)},
{op, sync_trans},
- {op, del_table_copy, Storage, FromNode, cs2list(Cs3)}].
+ {op, del_table_copy, Storage, FromNode, vsn_cs2list(Cs3)}].
%% end of functions to add and delete nodes to tables
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1306,7 +1357,7 @@ make_change_table_copy_type(Tab, Node, unknown) ->
make_change_table_copy_type(Tab, Node, ToS) ->
ensure_writable(schema),
Cs = incr_version(val({Tab, cstruct})),
- FromS = mnesia_lib:storage_type_at_node(Node, Tab),
+ FromS = mnesia_lib:storage_type_at_node(Node, Tab),
case compare_storage_type(false, FromS, ToS) of
{same, _} ->
@@ -1320,12 +1371,12 @@ make_change_table_copy_type(Tab, Node, ToS) ->
Cs2 = new_cs(Cs, Node, FromS, del),
Cs3 = new_cs(Cs2, Node, ToS, add),
verify_cstruct(Cs3),
-
- [{op, change_table_copy_type, Node, FromS, ToS, cs2list(Cs3)}].
+
+ [{op, change_table_copy_type, Node, FromS, ToS, vsn_cs2list(Cs3)}].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% change index functions ....
-%% Pos is allready added by 1 in both of these functions
+%% Pos is allready added by 1 in both of these functions
add_table_index(Tab, Pos) ->
schema_transaction(fun() -> do_add_table_index(Tab, Pos) end).
@@ -1347,7 +1398,7 @@ make_add_table_index(Tab, Pos) ->
Ix2 = lists:sort([Pos | Ix]),
Cs2 = Cs#cstruct{index = Ix2},
verify_cstruct(Cs2),
- [{op, add_index, Pos, cs2list(Cs2)}].
+ [{op, add_index, Pos, vsn_cs2list(Cs2)}].
del_table_index(Tab, Pos) ->
schema_transaction(fun() -> do_del_table_index(Tab, Pos) end).
@@ -1368,7 +1419,7 @@ make_del_table_index(Tab, Pos) ->
verify(true, lists:member(Pos, Ix), {no_exists, Tab, Pos}),
Cs2 = Cs#cstruct{index = lists:delete(Pos, Ix)},
verify_cstruct(Cs2),
- [{op, del_index, Pos, cs2list(Cs2)}].
+ [{op, del_index, Pos, vsn_cs2list(Cs2)}].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1391,7 +1442,7 @@ make_add_snmp(Tab, Ustruct) ->
verify(true, mnesia_snmp_hook:check_ustruct(Ustruct), Error),
Cs2 = Cs#cstruct{snmp = Ustruct},
verify_cstruct(Cs2),
- [{op, add_snmp, Ustruct, cs2list(Cs2)}].
+ [{op, add_snmp, Ustruct, vsn_cs2list(Cs2)}].
del_snmp(Tab) ->
schema_transaction(fun() -> do_del_snmp(Tab) end).
@@ -1409,17 +1460,17 @@ make_del_snmp(Tab) ->
ensure_active(Cs),
Cs2 = Cs#cstruct{snmp = []},
verify_cstruct(Cs2),
- [{op, del_snmp, cs2list(Cs2)}].
+ [{op, del_snmp, vsn_cs2list(Cs2)}].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
+%%
-transform_table(Tab, Fun, NewAttrs, NewRecName)
- when is_function(Fun), is_list(NewAttrs), is_atom(NewRecName) ->
+transform_table(Tab, Fun, NewAttrs, NewRecName)
+ when is_function(Fun), is_list(NewAttrs), is_atom(NewRecName) ->
schema_transaction(fun() -> do_transform_table(Tab, Fun, NewAttrs, NewRecName) end);
-transform_table(Tab, ignore, NewAttrs, NewRecName)
- when is_list(NewAttrs), is_atom(NewRecName) ->
+transform_table(Tab, ignore, NewAttrs, NewRecName)
+ when is_list(NewAttrs), is_atom(NewRecName) ->
schema_transaction(fun() -> do_transform_table(Tab, ignore, NewAttrs, NewRecName) end);
transform_table(Tab, Fun, NewAttrs, NewRecName) ->
@@ -1438,33 +1489,33 @@ make_transform(Tab, Fun, NewAttrs, NewRecName) ->
ensure_active(Cs),
ensure_writable(Tab),
case mnesia_lib:val({Tab, index}) of
- [] ->
+ [] ->
Cs2 = Cs#cstruct{attributes = NewAttrs, record_name = NewRecName},
verify_cstruct(Cs2),
- [{op, transform, Fun, cs2list(Cs2)}];
+ [{op, transform, Fun, vsn_cs2list(Cs2)}];
PosList ->
DelIdx = fun(Pos, Ncs) ->
Ix = Ncs#cstruct.index,
Ncs1 = Ncs#cstruct{index = lists:delete(Pos, Ix)},
- Op = {op, del_index, Pos, cs2list(Ncs1)},
+ Op = {op, del_index, Pos, vsn_cs2list(Ncs1)},
{Op, Ncs1}
end,
AddIdx = fun(Pos, Ncs) ->
Ix = Ncs#cstruct.index,
Ix2 = lists:sort([Pos | Ix]),
Ncs1 = Ncs#cstruct{index = Ix2},
- Op = {op, add_index, Pos, cs2list(Ncs1)},
+ Op = {op, add_index, Pos, vsn_cs2list(Ncs1)},
{Op, Ncs1}
end,
{DelOps, Cs1} = lists:mapfoldl(DelIdx, Cs, PosList),
Cs2 = Cs1#cstruct{attributes = NewAttrs, record_name = NewRecName},
{AddOps, Cs3} = lists:mapfoldl(AddIdx, Cs2, PosList),
verify_cstruct(Cs3),
- lists:flatten([DelOps, {op, transform, Fun, cs2list(Cs2)}, AddOps])
+ lists:flatten([DelOps, {op, transform, Fun, vsn_cs2list(Cs2)}, AddOps])
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
+%%
change_table_access_mode(Tab, Mode) ->
schema_transaction(fun() -> do_change_table_access_mode(Tab, Mode) end).
@@ -1484,7 +1535,7 @@ make_change_table_access_mode(Tab, Mode) ->
verify(false, OldMode == Mode, {already_exists, Tab, Mode}),
Cs2 = Cs#cstruct{access_mode = Mode},
verify_cstruct(Cs2),
- [{op, change_table_access_mode, cs2list(Cs2), OldMode, Mode}].
+ [{op, change_table_access_mode, vsn_cs2list(Cs2), OldMode, Mode}].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1505,7 +1556,7 @@ make_change_table_load_order(Tab, LoadOrder) ->
OldLoadOrder = Cs#cstruct.load_order,
Cs2 = Cs#cstruct{load_order = LoadOrder},
verify_cstruct(Cs2),
- [{op, change_table_load_order, cs2list(Cs2), OldLoadOrder, LoadOrder}].
+ [{op, change_table_load_order, vsn_cs2list(Cs2), OldLoadOrder, LoadOrder}].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1535,14 +1586,14 @@ make_change_table_majority(Tab, Majority) ->
ensure_active(CsT),
CsT2 = CsT#cstruct{majority = Majority},
verify_cstruct(CsT2),
- {op, change_table_majority, cs2list(CsT2),
+ {op, change_table_majority, vsn_cs2list(CsT2),
OldMajority, Majority}
end, FragNames);
false -> [];
{_, _} -> mnesia:abort({bad_type, Tab})
end,
verify_cstruct(Cs2),
- [{op, change_table_majority, cs2list(Cs2), OldMajority, Majority} | FragOps].
+ [{op, change_table_majority, vsn_cs2list(Cs2), OldMajority, Majority} | FragOps].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1583,7 +1634,7 @@ make_write_table_properties(Tab, [Prop | Props], Cs) ->
MergedProps = lists:merge(DelProps, [Prop]),
Cs2 = Cs#cstruct{user_properties = MergedProps},
verify_cstruct(Cs2),
- [{op, write_property, cs2list(Cs2), Prop} |
+ [{op, write_property, vsn_cs2list(Cs2), Prop} |
make_write_table_properties(Tab, Props, Cs2)];
make_write_table_properties(_Tab, [], _Cs) ->
[].
@@ -1598,9 +1649,9 @@ change_prop_in_existing_op(Tab, Prop, How, Store) ->
false ->
false
end.
-
-update_existing_op([{op, Op, L = [{name,Tab}|_], _OldProp}|Ops],
- Tab, Prop, How, Acc) when Op == write_property;
+
+update_existing_op([{op, Op, L = [{name,Tab}|_], _OldProp}|Ops],
+ Tab, Prop, How, Acc) when Op == write_property;
Op == delete_property ->
%% Apparently, mnesia_dumper doesn't care about OldProp here -- just L,
%% so we will throw away OldProp (not that it matters...) and insert Prop.
@@ -1625,7 +1676,7 @@ update_existing_op([], _, _, _, _) ->
do_read_table_property(Tab, Key) ->
TidTs = get_tid_ts_and_lock(schema, read),
{_, _, Ts} = TidTs,
- Store = Ts#tidstore.store,
+ Store = Ts#tidstore.store,
Props = ets:foldl(
fun({op, create_table, [{name, T}|Opts]}, _Acc)
when T==Tab ->
@@ -1689,7 +1740,7 @@ do_delete_table_property(Tab, PropKey) ->
[Tab,PropKey]),
%% this must be an existing table
get_tid_ts_and_lock(Tab, none),
- insert_schema_ops(TidTs,
+ insert_schema_ops(TidTs,
make_delete_table_properties(Tab, [PropKey]))
end.
@@ -1704,24 +1755,24 @@ make_delete_table_properties(Tab, [PropKey | PropKeys], Cs) ->
Props = lists:keydelete(PropKey, 1, OldProps),
Cs2 = Cs#cstruct{user_properties = Props},
verify_cstruct(Cs2),
- [{op, delete_property, cs2list(Cs2), PropKey} |
+ [{op, delete_property, vsn_cs2list(Cs2), PropKey} |
make_delete_table_properties(Tab, PropKeys, Cs2)];
make_delete_table_properties(_Tab, [], _Cs) ->
[].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Ensure that the transaction can be committed even
+%% Ensure that the transaction can be committed even
%% if the node crashes and Mnesia is restarted
prepare_commit(Tid, Commit, WaitFor) ->
case Commit#commit.schema_ops of
[] ->
{false, Commit, optional};
OrigOps ->
- {Modified, Ops, DumperMode} =
+ {Modified, Ops, DumperMode} =
prepare_ops(Tid, OrigOps, WaitFor, false, [], optional),
InitBy = schema_prepare,
- GoodRes = {Modified,
+ GoodRes = {Modified,
Commit#commit{schema_ops = lists:reverse(Ops)},
DumperMode},
case DumperMode of
@@ -1737,7 +1788,7 @@ prepare_commit(Tid, Commit, WaitFor) ->
end
end,
case Ops of
- [] ->
+ [] ->
ignore;
_ ->
%% We need to grab a dumper lock here, the log may not
@@ -1749,20 +1800,20 @@ prepare_commit(Tid, Commit, WaitFor) ->
prepare_ops(Tid, [Op | Ops], WaitFor, Changed, Acc, DumperMode) ->
case prepare_op(Tid, Op, WaitFor) of
- {true, mandatory} ->
+ {true, mandatory} ->
prepare_ops(Tid, Ops, WaitFor, Changed, [Op | Acc], mandatory);
- {true, optional} ->
+ {true, optional} ->
prepare_ops(Tid, Ops, WaitFor, Changed, [Op | Acc], DumperMode);
- {true, Ops2, mandatory} ->
+ {true, Ops2, mandatory} ->
prepare_ops(Tid, Ops, WaitFor, true, Ops2 ++ Acc, mandatory);
- {true, Ops2, optional} ->
+ {true, Ops2, optional} ->
prepare_ops(Tid, Ops, WaitFor, true, Ops2 ++ Acc, DumperMode);
- {false, optional} ->
+ {false, optional} ->
prepare_ops(Tid, Ops, WaitFor, true, Acc, DumperMode)
end;
prepare_ops(_Tid, [], _WaitFor, Changed, Acc, DumperMode) ->
{Changed, Acc, DumperMode}.
-
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Prepare for commit
%% returns true if Op should be included, i.e. unmodified
@@ -1781,8 +1832,8 @@ prepare_op(_Tid, {op, rec, unknown, Rec}, _WaitFor) ->
prepare_op(_Tid, {op, announce_im_running, Node, SchemaDef, Running, RemoteRunning}, _WaitFor) ->
SchemaCs = list2cs(SchemaDef),
- if
- Node == node() -> %% Announce has already run on local node
+ if
+ Node == node() -> %% Announce has already run on local node
ignore; %% from do_merge_schema
true ->
%% If a node has restarted it may still linger in db_nodes,
@@ -1794,9 +1845,9 @@ prepare_op(_Tid, {op, announce_im_running, Node, SchemaDef, Running, RemoteRunni
end,
{false, optional};
-prepare_op(_Tid, {op, sync_trans}, {part, CoordPid}) ->
+prepare_op(_Tid, {op, sync_trans}, {part, CoordPid}) ->
CoordPid ! {sync_trans, self()},
- receive
+ receive
{sync_trans, CoordPid} ->
{false, optional};
{mnesia_down, _Node} = Else ->
@@ -1807,7 +1858,7 @@ prepare_op(_Tid, {op, sync_trans}, {part, CoordPid}) ->
mnesia:abort(Else)
end;
-prepare_op(_Tid, {op, sync_trans}, {coord, Nodes}) ->
+prepare_op(_Tid, {op, sync_trans}, {coord, Nodes}) ->
case receive_sync(Nodes, []) of
{abort, Reason} ->
mnesia_lib:verbose("sync_op terminated due to ~p~n", [Reason]),
@@ -1838,7 +1889,7 @@ prepare_op(Tid, {op, create_table, TabDef}, _WaitFor) ->
create_ram_table(Tab, Cs#cstruct.type),
create_disc_table(Tab),
insert_cstruct(Tid, Cs, false),
- {true, optional};
+ {true, optional};
disc_only_copies ->
mnesia_lib:set({Tab, create_table},true),
create_disc_only_table(Tab,Cs#cstruct.type),
@@ -1857,15 +1908,15 @@ prepare_op(Tid, {op, add_table_copy, Storage, Node, TabDef}, _WaitFor) ->
if
Tab == schema ->
{true, optional};
-
+
Node == node() ->
- case mnesia_lib:val({schema, storage_type}) of
- ram_copies when Storage /= ram_copies ->
+ case mnesia_lib:val({schema, storage_type}) of
+ ram_copies when Storage /= ram_copies ->
Error = {combine_error, Tab, "has no disc", Node},
mnesia:abort(Error);
_ ->
ok
- end,
+ end,
%% Tables are created by mnesia_loader get_network code
insert_cstruct(Tid, Cs, true),
case mnesia_controller:get_network_copy(Tab, Cs) of
@@ -1902,22 +1953,22 @@ prepare_op(Tid, {op, add_table_copy, Storage, Node, TabDef}, _WaitFor) ->
prepare_op(Tid, {op, del_table_copy, _Storage, Node, TabDef}, _WaitFor) ->
Cs = list2cs(TabDef),
Tab = Cs#cstruct.name,
-
+
if
%% Schema table lock is always required to run a schema op.
%% No need to look it.
- node(Tid#tid.pid) == node(), Tab /= schema ->
+ node(Tid#tid.pid) == node(), Tab /= schema ->
Self = self(),
Pid = spawn_link(fun() -> lock_del_table(Tab, Node, Cs, Self) end),
put(mnesia_lock, Pid),
- receive
- {Pid, updated} ->
+ receive
+ {Pid, updated} ->
{true, optional};
{Pid, FailReason} ->
mnesia:abort(FailReason);
{'EXIT', Pid, Reason} ->
mnesia:abort(Reason)
- end;
+ end;
true ->
{true, optional}
end;
@@ -1928,12 +1979,12 @@ prepare_op(_Tid, {op, change_table_copy_type, N, FromS, ToS, TabDef}, _WaitFor)
Tab = Cs#cstruct.name,
NotActive = mnesia_lib:not_active_here(Tab),
-
- if
+
+ if
NotActive == true ->
mnesia:abort({not_active, Tab, node()});
-
- Tab == schema ->
+
+ Tab == schema ->
case {FromS, ToS} of
{ram_copies, disc_copies} ->
case mnesia:system_info(schema_location) of
@@ -1943,7 +1994,7 @@ prepare_op(_Tid, {op, change_table_copy_type, N, FromS, ToS, TabDef}, _WaitFor)
mnesia:abort({combine_error, Tab, node(),
"schema_location must be opt_disc"})
end,
- Dir = mnesia_lib:dir(),
+ Dir = mnesia_lib:dir(),
case opt_create_dir(true, Dir) of
ok ->
purge_dir(Dir, []),
@@ -1967,18 +2018,18 @@ prepare_op(_Tid, {op, change_table_copy_type, N, FromS, ToS, TabDef}, _WaitFor)
_ ->
mnesia:abort({combine_error, Tab, ToS})
end;
-
- FromS == ram_copies ->
+
+ FromS == ram_copies ->
case mnesia_monitor:use_dir() of
- true ->
+ true ->
Dat = mnesia_lib:tab2dcd(Tab),
case mnesia_lib:exists(Dat) of
true ->
mnesia:abort({combine_error, Tab, node(),
"Table dump exists"});
false ->
- case ToS of
- disc_copies ->
+ case ToS of
+ disc_copies ->
mnesia_log:ets2dcd(Tab, dmp);
disc_only_copies ->
mnesia_dumper:raw_named_dump_table(Tab, dmp)
@@ -1988,7 +2039,7 @@ prepare_op(_Tid, {op, change_table_copy_type, N, FromS, ToS, TabDef}, _WaitFor)
false ->
mnesia:abort({has_no_disc, node()})
end;
-
+
FromS == disc_copies, ToS == disc_only_copies ->
mnesia_dumper:raw_named_dump_table(Tab, dmp);
FromS == disc_only_copies ->
@@ -2020,7 +2071,7 @@ prepare_op(_Tid, {op, dump_table, unknown, TabDef}, _WaitFor) ->
case lists:member(node(), Cs#cstruct.ram_copies) of
true ->
case mnesia_monitor:use_dir() of
- true ->
+ true ->
mnesia_log:ets2dcd(Tab, dmp),
Size = mnesia:table_info(Tab, size),
{true, [{op, dump_table, Size, TabDef}], optional};
@@ -2058,7 +2109,7 @@ prepare_op(_Tid, {op, transform, Fun, TabDef}, _WaitFor) ->
mnesia_lib:db_fixtable(Storage, Tab, true),
Key = mnesia_lib:db_first(Tab),
Op = {op, transform, Fun, TabDef},
- case catch transform_objs(Fun, Tab, RecName,
+ case catch transform_objs(Fun, Tab, RecName,
Key, NewArity, Storage, Type, [Op]) of
{'EXIT', Reason} ->
mnesia_lib:db_fixtable(Storage, Tab, false),
@@ -2072,7 +2123,7 @@ prepare_op(_Tid, {op, transform, Fun, TabDef}, _WaitFor) ->
prepare_op(_Tid, {op, merge_schema, TabDef}, _WaitFor) ->
Cs = list2cs(TabDef),
case verify_merge(Cs) of
- ok ->
+ ok ->
{true, optional};
Error ->
verbose("Merge_Schema ~p failed on ~p: ~p~n", [_Tid,node(),Error]),
@@ -2093,7 +2144,7 @@ create_ram_table(Tab, Type) ->
create_disc_table(Tab) ->
File = mnesia_lib:tab2dcd(Tab),
file:delete(File),
- FArg = [{file, File}, {name, {mnesia,create}},
+ FArg = [{file, File}, {name, {mnesia,create}},
{repair, false}, {mode, read_write}],
case mnesia_monitor:open_log(FArg) of
{ok,Log} ->
@@ -2124,32 +2175,37 @@ receive_sync([], Pids) ->
receive_sync(Nodes, Pids) ->
receive
{sync_trans, Pid} ->
- Node = node(Pid),
+ Node = node(Pid),
receive_sync(lists:delete(Node, Nodes), [Pid | Pids]);
Else ->
{abort, Else}
end.
-lock_del_table(Tab, Node, Cs, Father) ->
+lock_del_table(Tab, NewNode, Cs0, Father) ->
Ns = val({schema, active_replicas}),
process_flag(trap_exit,true),
Lock = fun() ->
mnesia:write_lock_table(Tab),
- {Res, []} = rpc:multicall(Ns, ?MODULE, set_where_to_read, [Tab, Node, Cs]),
+ %% Sigh using cs record
+ Set = fun(Node) ->
+ [Cs] = normalize_cs([Cs0], Node),
+ rpc:call(Node, ?MODULE, set_where_to_read, [Tab, NewNode, Cs])
+ end,
+ Res = [Set(Node) || Node <- Ns],
Filter = fun(ok) ->
false;
({badrpc, {'EXIT', {undef, _}}}) ->
%% This will be the case we talks with elder nodes
- %% than 3.8.2, they will set where_to_read without
- %% getting a lock.
+ %% than 3.8.2, they will set where_to_read without
+ %% getting a lock.
false;
(_) ->
true
end,
case lists:filter(Filter, Res) of
- [] ->
+ [] ->
Father ! {self(), updated},
- %% When transaction is commited the process dies
+ %% When transaction is commited the process dies
%% and the lock is released.
receive _ -> ok end;
Err ->
@@ -2166,7 +2222,7 @@ lock_del_table(Tab, Node, Cs, Father) ->
exit(normal).
set_where_to_read(Tab, Node, Cs) ->
- case mnesia_lib:val({Tab, where_to_read}) of
+ case mnesia_lib:val({Tab, where_to_read}) of
Node ->
case Cs#cstruct.local_content of
true ->
@@ -2185,16 +2241,16 @@ transform_objs(_Fun, _Tab, _RT, '$end_of_table', _NewArity, _Storage, _Type, Acc
transform_objs(Fun, Tab, RecName, Key, A, Storage, Type, Acc) ->
Objs = mnesia_lib:db_get(Tab, Key),
NextKey = mnesia_lib:db_next_key(Tab, Key),
- Oid = {Tab, Key},
+ Oid = {Tab, Key},
NewObjs = {Ws, Ds} = transform_obj(Tab, RecName, Key, Fun, Objs, A, Type, [], []),
- if
- NewObjs == {[], []} ->
+ if
+ NewObjs == {[], []} ->
transform_objs(Fun, Tab, RecName, NextKey, A, Storage, Type, Acc);
- Type == bag ->
+ Type == bag ->
transform_objs(Fun, Tab, RecName, NextKey, A, Storage, Type,
[{op, rec, Storage, {Oid, Ws, write}},
{op, rec, Storage, {Oid, [Oid], delete}} | Acc]);
- Ds == [] ->
+ Ds == [] ->
%% Type is set or ordered_set, no need to delete the record first
transform_objs(Fun, Tab, RecName, NextKey, A, Storage, Type,
[{op, rec, Storage, {Oid, Ws, write}} | Acc]);
@@ -2215,15 +2271,15 @@ transform_obj(Tab, RecName, Key, Fun, [Obj|Rest], NewArity, Type, Ws, Ds) ->
NewObj == Obj ->
transform_obj(Tab, RecName, Key, Fun, Rest, NewArity, Type, Ws, Ds);
RecName == element(1, NewObj), Key == element(2, NewObj) ->
- transform_obj(Tab, RecName, Key, Fun, Rest, NewArity,
+ transform_obj(Tab, RecName, Key, Fun, Rest, NewArity,
Type, [NewObj | Ws], Ds);
- NewObj == delete ->
- case Type of
+ NewObj == delete ->
+ case Type of
bag -> %% Just don't write that object
- transform_obj(Tab, RecName, Key, Fun, Rest,
- NewArity, Type, Ws, Ds);
+ transform_obj(Tab, RecName, Key, Fun, Rest,
+ NewArity, Type, Ws, Ds);
_ ->
- transform_obj(Tab, RecName, Key, Fun, Rest, NewArity,
+ transform_obj(Tab, RecName, Key, Fun, Rest, NewArity,
Type, Ws, [NewObj | Ds])
end;
true ->
@@ -2247,7 +2303,7 @@ undo_prepare_commit(Tid, Commit) ->
%% Undo in reverse order
undo_prepare_ops(Tid, [Op | Ops]) ->
- case element(1, Op) of
+ case element(1, Op) of
TheOp when TheOp /= op, TheOp /= restore_op ->
undo_prepare_ops(Tid, Ops);
_ ->
@@ -2274,7 +2330,7 @@ undo_prepare_op(Tid, {op, create_table, TabDef}) ->
mnesia_lib:unset({Tab, create_table}),
delete_cstruct(Tid, Cs),
case mnesia_lib:cs_to_storage_type(node(), Cs) of
- unknown ->
+ unknown ->
ok;
ram_copies ->
ram_delete_table(Tab, ram_copies);
@@ -2289,7 +2345,7 @@ undo_prepare_op(Tid, {op, create_table, TabDef}) ->
%% disc_delete_table(Tab, Storage),
file:delete(Dat)
end;
-
+
undo_prepare_op(Tid, {op, add_table_copy, Storage, Node, TabDef}) ->
Cs = list2cs(TabDef),
Tab = Cs#cstruct.name,
@@ -2314,21 +2370,22 @@ undo_prepare_op(Tid, {op, add_table_copy, Storage, Node, TabDef}) ->
Cs2 = new_cs(Cs, Node, Storage, del),
insert_cstruct(Tid, Cs2, true) % Don't care about the version
end;
-
-undo_prepare_op(_Tid, {op, del_table_copy, _, Node, TabDef})
+
+undo_prepare_op(_Tid, {op, del_table_copy, _, Node, TabDef})
when Node == node() ->
+ WriteLocker = get(mnesia_lock),
+ WriteLocker =/= undefined andalso (WriteLocker ! die),
Cs = list2cs(TabDef),
Tab = Cs#cstruct.name,
mnesia_lib:set({Tab, where_to_read}, Node);
-
-undo_prepare_op(_Tid, {op, change_table_copy_type, N, FromS, ToS, TabDef})
+undo_prepare_op(_Tid, {op, change_table_copy_type, N, FromS, ToS, TabDef})
when N == node() ->
Cs = list2cs(TabDef),
Tab = Cs#cstruct.name,
mnesia_checkpoint:tm_change_table_copy_type(Tab, ToS, FromS),
Dmp = mnesia_lib:tab2dmp(Tab),
-
+
case {FromS, ToS} of
{ram_copies, disc_copies} when Tab == schema ->
file:delete(Dmp),
@@ -2382,9 +2439,9 @@ ram_delete_table(Tab, Storage) ->
ignore;
disc_only_copies ->
ignore;
- _Else ->
+ _Else ->
%% delete possible index files and data .....
- %% Got to catch this since if no info has been set in the
+ %% Got to catch this since if no info has been set in the
%% mnesia_gvar it will crash
catch mnesia_index:del_transient(Tab, Storage),
case ?catch_val({Tab, {index, snmp}}) of
@@ -2454,7 +2511,7 @@ has_known_suffix(File, [Suffix | Tail], false) ->
has_known_suffix(File, Tail, lists:suffix(Suffix, File));
has_known_suffix(_File, [], Bool) ->
Bool.
-
+
known_suffixes() -> real_suffixes() ++ tmp_suffixes().
real_suffixes() -> [".DAT", ".LOG", ".BUP", ".DCL", ".DCD"].
@@ -2477,11 +2534,11 @@ info2(Tab, [{frag_hash, _V} | Tail]) -> % Ignore frag_hash
info2(Tab, [{P, V} | Tail]) ->
io:format("~-20w -> ~p~n",[P,V]),
info2(Tab, Tail);
-info2(_, []) ->
+info2(_, []) ->
io:format("~n", []).
get_table_properties(Tab) ->
- case catch mnesia_lib:db_match_object(ram_copies,
+ case catch mnesia_lib:db_match_object(ram_copies,
mnesia_gvar, {{Tab, '_'}, '_'}) of
{'EXIT', _} ->
mnesia:abort({no_exists, Tab, all});
@@ -2509,9 +2566,9 @@ get_table_properties(Tab) ->
recs = error_recs
}).
-restore(Opaque) ->
+restore(Opaque) ->
restore(Opaque, [], mnesia_monitor:get_env(backup_module)).
-restore(Opaque, Args) when is_list(Args) ->
+restore(Opaque, Args) when is_list(Args) ->
restore(Opaque, Args, mnesia_monitor:get_env(backup_module));
restore(_Opaque, BadArg) ->
{aborted, {badarg, BadArg}}.
@@ -2522,7 +2579,7 @@ restore(Opaque, Args, Module) when is_list(Args), is_atom(Module) ->
case mnesia_bup:read_schema(R#r.module, Opaque) of
{error, Reason} ->
{aborted, Reason};
- BupSchema ->
+ BupSchema ->
schema_transaction(fun() -> do_restore(R, BupSchema) end)
end;
{'EXIT', Reason} ->
@@ -2556,8 +2613,8 @@ check_restore_arg({keep_tables, List}, R) when is_list(List) ->
check_restore_arg({skip_tables, List}, R) when is_list(List) ->
TableList = [{Tab, skip_tables} || Tab <- List],
R#r{table_options = R#r.table_options ++ TableList};
-check_restore_arg({default_op, Op}, R) ->
- case Op of
+check_restore_arg({default_op, Op}, R) ->
+ case Op of
clear_tables -> ok;
recreate_tables -> ok;
keep_tables -> ok;
@@ -2588,12 +2645,12 @@ restore_items([Rec | Recs], Header, Schema, R) ->
case lists:keysearch(Tab, 1, R#r.tables) of
{value, {Tab, Where0, Snmp, RecName}} ->
Where = case Where0 of
- undefined ->
+ undefined ->
val({Tab, where_to_commit});
_ ->
Where0
end,
- {Rest, NRecs} = restore_tab_items([Rec | Recs], Tab,
+ {Rest, NRecs} = restore_tab_items([Rec | Recs], Tab,
RecName, Where, Snmp,
R#r.recs, R#r.insert_op),
restore_items(Rest, Header, Schema, R#r{recs = NRecs});
@@ -2601,12 +2658,12 @@ restore_items([Rec | Recs], Header, Schema, R) ->
Rest = skip_tab_items(Recs, Tab),
restore_items(Rest, Header, Schema, R)
end;
-
+
restore_items([], _Header, _Schema, R) ->
R.
restore_func(Tab, R) ->
- case lists:keysearch(Tab, 1, R#r.table_options) of
+ case lists:keysearch(Tab, 1, R#r.table_options) of
{value, {Tab, OP}} ->
OP;
false ->
@@ -2618,24 +2675,24 @@ where_to_commit(Tab, CsList) ->
Disc = [{N, disc_copies} || N <- pick(Tab, disc_copies, CsList, [])],
DiscO = [{N, disc_only_copies} || N <- pick(Tab, disc_only_copies, CsList, [])],
Ram ++ Disc ++ DiscO.
-
+
%% Changes of the Meta info of schema itself is not allowed
restore_schema([{schema, schema, _List} | Schema], R) ->
restore_schema(Schema, R);
restore_schema([{schema, Tab, List} | Schema], R) ->
case restore_func(Tab, R) of
- clear_tables ->
+ clear_tables ->
do_clear_table(Tab),
- Snmp = val({Tab, snmp}),
- RecName = val({Tab, record_name}),
+ Snmp = val({Tab, snmp}),
+ RecName = val({Tab, record_name}),
R2 = R#r{tables = [{Tab, undefined, Snmp, RecName} | R#r.tables]},
restore_schema(Schema, R2);
- recreate_tables ->
+ recreate_tables ->
case ?catch_val({Tab, cstruct}) of
- {'EXIT', _} ->
+ {'EXIT', _} ->
TidTs = {_Mod, Tid, Ts} = get(mnesia_activity_state),
RunningNodes = val({current, db_nodes}),
- Nodes = mnesia_lib:intersect(mnesia_lib:cs_to_nodes(list2cs(List)),
+ Nodes = mnesia_lib:intersect(mnesia_lib:cs_to_nodes(list2cs(List)),
RunningNodes),
mnesia_locker:wlock_no_exist(Tid, Ts#tidstore.store, Tab, Nodes),
TidTs;
@@ -2643,20 +2700,20 @@ restore_schema([{schema, Tab, List} | Schema], R) ->
TidTs = get_tid_ts_and_lock(Tab, write)
end,
NC = {cookie, ?unique_cookie},
- List2 = lists:keyreplace(cookie, 1, List, NC),
+ List2 = lists:keyreplace(cookie, 1, List, NC),
Where = where_to_commit(Tab, List2),
Snmp = pick(Tab, snmp, List2, []),
RecName = pick(Tab, record_name, List2, Tab),
insert_schema_ops(TidTs, [{op, restore_recreate, List2}]),
R2 = R#r{tables = [{Tab, Where, Snmp, RecName} | R#r.tables]},
restore_schema(Schema, R2);
- keep_tables ->
+ keep_tables ->
get_tid_ts_and_lock(Tab, write),
Snmp = val({Tab, snmp}),
- RecName = val({Tab, record_name}),
+ RecName = val({Tab, record_name}),
R2 = R#r{tables = [{Tab, undefined, Snmp, RecName} | R#r.tables]},
restore_schema(Schema, R2);
- skip_tables ->
+ skip_tables ->
restore_schema(Schema, R)
end;
@@ -2667,7 +2724,7 @@ restore_schema([{schema, Tab} | Schema], R) ->
restore_schema([], R) ->
R.
-restore_tab_items([Rec | Rest], Tab, RecName, Where, Snmp, Recs, Op)
+restore_tab_items([Rec | Rest], Tab, RecName, Where, Snmp, Recs, Op)
when element(1, Rec) == Tab ->
NewRecs = Op(Rec, Recs, RecName, Where, Snmp),
restore_tab_items(Rest, Tab, RecName, Where, Snmp, NewRecs, Op);
@@ -2675,7 +2732,7 @@ restore_tab_items([Rec | Rest], Tab, RecName, Where, Snmp, Recs, Op)
restore_tab_items(Rest, _Tab, _RecName, _Where, _Snmp, Recs, _Op) ->
{Rest, Recs}.
-skip_tab_items([Rec| Rest], Tab)
+skip_tab_items([Rec| Rest], Tab)
when element(1, Rec) == Tab ->
skip_tab_items(Rest, Tab);
skip_tab_items(Recs, _) ->
@@ -2710,7 +2767,6 @@ merge_schema() ->
merge_schema(UserFun) ->
schema_transaction(fun() -> UserFun(fun(Arg) -> do_merge_schema(Arg) end) end).
-
do_merge_schema(LockTabs0) ->
{_Mod, Tid, Ts} = get_tid_ts_and_lock(schema, write),
LockTabs = [{T, tab_to_nodes(T)} || T <- LockTabs0],
@@ -2732,14 +2788,14 @@ do_merge_schema(LockTabs0) ->
[mnesia_locker:wlock_no_exist(
Tid, Store, T, mnesia_lib:intersect(Ns, OtherNodes))
|| {T,Ns} <- LockTabs],
- case rpc:call(Node, mnesia_controller, get_cstructs, []) of
+ case fetch_cstructs(Node) of
{cstructs, Cstructs, RemoteRunning1} ->
LockedAlready = Running ++ [Node],
{New, Old} = mnesia_recover:connect_nodes(RemoteRunning1),
RemoteRunning = mnesia_lib:intersect(New ++ Old, RemoteRunning1),
- if
+ if
RemoteRunning /= RemoteRunning1 ->
- mnesia_lib:error("Mnesia on ~p could not connect to node(s) ~p~n",
+ mnesia_lib:error("Mnesia on ~p could not connect to node(s) ~p~n",
[node(), RemoteRunning1 -- RemoteRunning]),
mnesia:abort({node_not_running, RemoteRunning1 -- RemoteRunning});
true -> ok
@@ -2749,24 +2805,24 @@ do_merge_schema(LockTabs0) ->
[mnesia_locker:wlock_no_exist(Tid, Store, T,
mnesia_lib:intersect(Ns,NeedsLock))
|| {T,Ns} <- LockTabs],
- {value, SchemaCs} =
- lists:keysearch(schema, #cstruct.name, Cstructs),
+ NeedsConversion = need_old_cstructs(NeedsLock ++ LockedAlready),
+ {value, SchemaCs} = lists:keysearch(schema, #cstruct.name, Cstructs),
+ SchemaDef = cs2list(NeedsConversion, SchemaCs),
%% Announce that Node is running
- A = [{op, announce_im_running, node(),
- cs2list(SchemaCs), Running, RemoteRunning}],
+ A = [{op, announce_im_running, node(), SchemaDef, Running, RemoteRunning}],
do_insert_schema_ops(Store, A),
-
+
%% Introduce remote tables to local node
- do_insert_schema_ops(Store, make_merge_schema(Node, Cstructs)),
-
+ do_insert_schema_ops(Store, make_merge_schema(Node, NeedsConversion, Cstructs)),
+
%% Introduce local tables to remote nodes
Tabs = val({schema, tables}),
Ops = [{op, merge_schema, get_create_list(T)}
|| T <- Tabs,
not lists:keymember(T, #cstruct.name, Cstructs)],
do_insert_schema_ops(Store, Ops),
-
+
%% Ensure that the txn will be committed on all nodes
NewNodes = RemoteRunning -- Running,
mnesia_lib:set(prepare_op, {announce_im_running,NewNodes}),
@@ -2782,19 +2838,52 @@ do_merge_schema(LockTabs0) ->
not_merged
end.
+fetch_cstructs(Node) ->
+ case mnesia_monitor:needs_protocol_conversion(Node) of
+ true ->
+ case rpc:call(Node, mnesia_controller, get_cstructs, []) of
+ {cstructs, Cs0, RR} ->
+ {cstructs, [list2cs(cs2list(Cs)) || Cs <- Cs0], RR};
+ Err -> Err
+ end;
+ false ->
+ rpc:call(Node, mnesia_controller, get_remote_cstructs, [])
+ end.
+
+need_old_cstructs() ->
+ need_old_cstructs(val({schema, where_to_write})).
+
+need_old_cstructs(Nodes) ->
+ Filter = fun(Node) -> not mnesia_monitor:needs_protocol_conversion(Node) end,
+ case lists:dropwhile(Filter, Nodes) of
+ [] -> false;
+ [Node|_] ->
+ case rpc:call(Node, mnesia_lib, val, [{schema,cstruct}]) of
+ #cstruct{} ->
+ %% mnesia_lib:warning("Mnesia on ~p do not need to convert cstruct (~p)~n",
+ %% [node(), Node]),
+ false;
+ {badrpc, _} ->
+ need_old_cstructs(lists:delete(Node,Nodes));
+ Cs when element(1, Cs) == cstruct, tuple_size(Cs) == 17 ->
+ ver4_4_18; % Without majority
+ Cs when element(1, Cs) == cstruct, tuple_size(Cs) == 18 ->
+ ver4_4_19 % With majority
+ end
+ end.
+
tab_to_nodes(Tab) when is_atom(Tab) ->
Cs = val({Tab, cstruct}),
mnesia_lib:cs_to_nodes(Cs).
-make_merge_schema(Node, [Cs | Cstructs]) ->
- Ops = do_make_merge_schema(Node, Cs),
- Ops ++ make_merge_schema(Node, Cstructs);
-make_merge_schema(_Node, []) ->
+make_merge_schema(Node, NeedsConv, [Cs | Cstructs]) ->
+ Ops = do_make_merge_schema(Node, NeedsConv, Cs),
+ Ops ++ make_merge_schema(Node, NeedsConv, Cstructs);
+make_merge_schema(_Node, _, []) ->
[].
%% Merge definitions of schema table
-do_make_merge_schema(Node, RemoteCs)
- when RemoteCs#cstruct.name == schema ->
+do_make_merge_schema(Node, NeedsConv, RemoteCs = #cstruct{name = schema}) ->
Cs = val({schema, cstruct}),
Masters = mnesia_recover:get_master_nodes(schema),
HasRemoteMaster = lists:member(Node, Masters),
@@ -2804,15 +2893,15 @@ do_make_merge_schema(Node, RemoteCs)
StCsLocal = mnesia_lib:cs_to_storage_type(node(), Cs),
StRcsLocal = mnesia_lib:cs_to_storage_type(node(), RemoteCs),
StCsRemote = mnesia_lib:cs_to_storage_type(Node, Cs),
- StRcsRemote = mnesia_lib:cs_to_storage_type(Node, RemoteCs),
-
+ StRcsRemote = mnesia_lib:cs_to_storage_type(Node, RemoteCs),
+
if
Cs#cstruct.cookie == RemoteCs#cstruct.cookie,
Cs#cstruct.version == RemoteCs#cstruct.version ->
%% Great, we have the same cookie and version
%% and do not need to merge cstructs
[];
-
+
Cs#cstruct.cookie /= RemoteCs#cstruct.cookie,
Cs#cstruct.disc_copies /= [],
RemoteCs#cstruct.disc_copies /= [] ->
@@ -2823,14 +2912,14 @@ do_make_merge_schema(Node, RemoteCs)
HasRemoteMaster == false ->
%% Choose local cstruct,
%% since it's the master
- [{op, merge_schema, cs2list(Cs)}];
+ [{op, merge_schema, cs2list(NeedsConv, Cs)}];
HasRemoteMaster == true,
HasLocalMaster == false ->
%% Choose remote cstruct,
%% since it's the master
- [{op, merge_schema, cs2list(RemoteCs)}];
-
+ [{op, merge_schema, cs2list(NeedsConv, RemoteCs)}];
+
true ->
Str = io_lib:format("Incompatible schema cookies. "
"Please, restart from old backup."
@@ -2838,12 +2927,12 @@ do_make_merge_schema(Node, RemoteCs)
[Node, cs2list(RemoteCs), node(), cs2list(Cs)]),
throw(Str)
end;
-
+
StCsLocal /= StRcsLocal, StRcsLocal /= unknown, StCsLocal /= ram_copies ->
Str = io_lib:format("Incompatible schema storage types (local). "
"on ~w storage ~w, on ~w storage ~w~n",
[node(), StCsLocal, Node, StRcsLocal]),
- throw(Str);
+ throw(Str);
StCsRemote /= StRcsRemote, StCsRemote /= unknown, StRcsRemote /= ram_copies ->
Str = io_lib:format("Incompatible schema storage types (remote). "
"on ~w cs ~w, on ~w rcs ~w~n",
@@ -2854,27 +2943,27 @@ do_make_merge_schema(Node, RemoteCs)
%% Choose local cstruct,
%% since it involves disc nodes
MergedCs = merge_cstructs(Cs, RemoteCs, Force),
- [{op, merge_schema, cs2list(MergedCs)}];
-
+ [{op, merge_schema, cs2list(NeedsConv, MergedCs)}];
+
RemoteCs#cstruct.disc_copies /= [] ->
%% Choose remote cstruct,
%% since it involves disc nodes
MergedCs = merge_cstructs(RemoteCs, Cs, Force),
- [{op, merge_schema, cs2list(MergedCs)}];
+ [{op, merge_schema, cs2list(NeedsConv, MergedCs)}];
Cs > RemoteCs ->
%% Choose remote cstruct
MergedCs = merge_cstructs(RemoteCs, Cs, Force),
- [{op, merge_schema, cs2list(MergedCs)}];
-
+ [{op, merge_schema, cs2list(NeedsConv, MergedCs)}];
+
true ->
%% Choose local cstruct
MergedCs = merge_cstructs(Cs, RemoteCs, Force),
- [{op, merge_schema, cs2list(MergedCs)}]
+ [{op, merge_schema, cs2list(NeedsConv, MergedCs)}]
end;
%% Merge definitions of normal table
-do_make_merge_schema(Node, RemoteCs) ->
+do_make_merge_schema(Node, NeedsConv, RemoteCs = #cstruct{}) ->
Tab = RemoteCs#cstruct.name,
Masters = mnesia_recover:get_master_nodes(schema),
HasRemoteMaster = lists:member(Node, Masters),
@@ -2883,27 +2972,27 @@ do_make_merge_schema(Node, RemoteCs) ->
case ?catch_val({Tab, cstruct}) of
{'EXIT', _} ->
%% A completely new table, created while Node was down
- [{op, merge_schema, cs2list(RemoteCs)}];
+ [{op, merge_schema, cs2list(NeedsConv, RemoteCs)}];
Cs when Cs#cstruct.cookie == RemoteCs#cstruct.cookie ->
if
Cs#cstruct.version == RemoteCs#cstruct.version ->
%% We have exactly the same version of the
%% table def
[];
-
+
Cs#cstruct.version > RemoteCs#cstruct.version ->
%% Oops, we have different versions
%% of the table def, lets merge them.
%% The only changes that may have occurred
%% is that new replicas may have been added.
MergedCs = merge_cstructs(Cs, RemoteCs, Force),
- [{op, merge_schema, cs2list(MergedCs)}];
-
+ [{op, merge_schema, cs2list(NeedsConv, MergedCs)}];
+
Cs#cstruct.version < RemoteCs#cstruct.version ->
%% Oops, we have different versions
%% of the table def, lets merge them
MergedCs = merge_cstructs(RemoteCs, Cs, Force),
- [{op, merge_schema, cs2list(MergedCs)}]
+ [{op, merge_schema, cs2list(NeedsConv, MergedCs)}]
end;
Cs ->
%% Different cookies, not possible to merge
@@ -2912,14 +3001,14 @@ do_make_merge_schema(Node, RemoteCs) ->
HasRemoteMaster == false ->
%% Choose local cstruct,
%% since it's the master
- [{op, merge_schema, cs2list(Cs)}];
+ [{op, merge_schema, cs2list(NeedsConv, Cs)}];
HasRemoteMaster == true,
HasLocalMaster == false ->
%% Choose remote cstruct,
%% since it's the master
- [{op, merge_schema, cs2list(RemoteCs)}];
-
+ [{op, merge_schema, cs2list(NeedsConv, RemoteCs)}];
+
true ->
Str = io_lib:format("Bad cookie in table definition"
" ~w: ~w = ~w, ~w = ~w~n",
@@ -2989,7 +3078,7 @@ compare_storage_type(true, One, Another) ->
compare_storage_type(false, Another, One);
compare_storage_type(false, _One, _Another) ->
incompatible.
-
+
change_storage_type(N, ram_copies, Cs) ->
Nodes = [N | Cs#cstruct.ram_copies],
Cs#cstruct{ram_copies = mnesia_lib:uniq(Nodes)};
@@ -3071,14 +3160,14 @@ verify_merge(RemoteCs) ->
if
StCsLocal == StRcsLocal -> ok;
StCsLocal == unknown -> ok;
- (StRcsLocal == unknown), (HasRemoteMaster == false) ->
+ (StRcsLocal == unknown), (HasRemoteMaster == false) ->
{merge_error, Cs, RemoteCs};
%% Trust the merger
true -> ok
end
end.
-announce_im_running([N | Ns], SchemaCs) ->
+announce_im_running([N | Ns], SchemaCs) ->
{L1, L2} = mnesia_recover:connect_nodes([N]),
case lists:member(N, L1) or lists:member(N, L2) of
true ->
@@ -3095,7 +3184,7 @@ announce_im_running([], _) ->
unannounce_im_running([N | Ns]) ->
mnesia_lib:del({current, db_nodes}, N),
- mnesia_controller:del_active_replica(schema, N),
+ mnesia_controller:del_active_replica(schema, N),
unannounce_im_running(Ns);
unannounce_im_running([]) ->
ok.
diff --git a/lib/mnesia/test/mnesia_evil_backup.erl b/lib/mnesia/test/mnesia_evil_backup.erl
index 63f4146d98..9e0a8db1ae 100644
--- a/lib/mnesia/test/mnesia_evil_backup.erl
+++ b/lib/mnesia/test/mnesia_evil_backup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -244,9 +244,9 @@ restore(Config, Op) ->
[rpc:call(Node, ?MODULE, check_tab, [Res31, ?LINE]) || Node <- Nodes],
%% Restore all tables on it's nodes
- mnesia_schema:clear_table(Tab1),
- mnesia_schema:clear_table(Tab2),
- mnesia_schema:clear_table(Tab3),
+ mnesia:clear_table(Tab1),
+ mnesia:clear_table(Tab2),
+ mnesia:clear_table(Tab3),
[mnesia:dirty_write({Tab1, N, N+1}) || N <- lists:seq(1, 11)],
[mnesia:dirty_write({Tab2, N, N+1}) || N <- lists:seq(1, 11)],
[mnesia:dirty_write({Tab3, N, N+1}) || N <- lists:seq(1, 11)],
diff --git a/lib/mnesia/test/mnesia_evil_coverage_test.erl b/lib/mnesia/test/mnesia_evil_coverage_test.erl
index 668eba176f..17d6c6c212 100644
--- a/lib/mnesia/test/mnesia_evil_coverage_test.erl
+++ b/lib/mnesia/test/mnesia_evil_coverage_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1795,7 +1795,7 @@ subscribe_extended(Config) when is_list(Config) ->
?match({mnesia_table_event, {delete, schema, {schema, Tab1}, [{schema, Tab1, _}],_}}, recv_event()),
?match({mnesia_table_event, {write, schema, {schema, Tab1, _}, [], _}}, recv_event()),
- ?match({atomic, ok}, mnesia_schema:clear_table(Tab2)),
+ ?match({atomic, ok}, mnesia:clear_table(Tab2)),
?match({mnesia_table_event, {delete, schema, {schema, Tab2}, [{schema, Tab2, _}],_}},
recv_event()),
?match({mnesia_table_event, {write, schema, {schema, Tab2, _}, [], _}}, recv_event()),
diff --git a/lib/mnesia/test/mnesia_install_test.erl b/lib/mnesia/test/mnesia_install_test.erl
index 5d55fcac0e..3a2d44aa95 100644
--- a/lib/mnesia/test/mnesia_install_test.erl
+++ b/lib/mnesia/test/mnesia_install_test.erl
@@ -205,7 +205,7 @@ silly_upgrade(Config) when is_list(Config) ->
?match(ok, mnesia:install_fallback(Bup2)),
file:delete(Bup2),
%% Will generate intentional crash, fatal error
- ?match([], mnesia_test_lib:stop_mnesia([Node2])),
+ ?match([], mnesia_test_lib:stop_mnesia([Node2])),
wait_till_dead([Node1, Node2]),
?match([], mnesia_test_lib:start_mnesia([Node1, Node2], [Tab1, Tab2])),
?match(match, verify_state(Tab1, Tab2, CpState)),
@@ -213,22 +213,29 @@ silly_upgrade(Config) when is_list(Config) ->
?match(ok, mnesia:install_fallback(Bup)),
file:delete(Bup),
%% Will generate intentional crash, fatal error
- ?match([], mnesia_test_lib:stop_mnesia([Node1, Node2])),
+ ?match([], mnesia_test_lib:stop_mnesia([Node1, Node2])),
wait_till_dead([Node1, Node2]),
?match([], mnesia_test_lib:start_mnesia([Node1, Node2], [Tab1, Tab2])),
CpState2 = [X || X <- CpState, element(1, X) /= Tab1],
?match(match, verify_state(Tab1, Tab2, CpState2)),
?verify_mnesia(Nodes, []).
-wait_till_dead([]) -> ok;
-wait_till_dead([N|Ns]) ->
+wait_till_dead([]) ->
+ ok; %% timer:sleep(5);
+wait_till_dead(Repeat = [N|Ns]) ->
Apps = rpc:call(N, application, which_applications, []),
case lists:keymember(mnesia, 1, Apps) of
- true ->
+ true ->
timer:sleep(10),
- wait_till_dead([N|Ns]);
- false ->
- wait_till_dead(Ns)
+ wait_till_dead(Repeat);
+ false ->
+ case rpc:call(N, erlang, whereis, [mnesia_monitor]) of
+ undefined ->
+ wait_till_dead(Ns);
+ _ ->
+ timer:sleep(10),
+ wait_till_dead(Repeat)
+ end
end.
add_some_records(Tab1, Tab2, Old) ->
diff --git a/lib/mnesia/vsn.mk b/lib/mnesia/vsn.mk
index 2fa629d064..ebf79dd2ae 100644
--- a/lib/mnesia/vsn.mk
+++ b/lib/mnesia/vsn.mk
@@ -1 +1 @@
-MNESIA_VSN = 4.4.19
+MNESIA_VSN = 4.5.1
diff --git a/lib/observer/doc/src/make.dep b/lib/observer/doc/src/make.dep
deleted file mode 100644
index 3c1b3df771..0000000000
--- a/lib/observer/doc/src/make.dep
+++ /dev/null
@@ -1,29 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex crashdump.tex crashdump_ug.tex etop.tex \
- etop_ug.tex observer_app.tex part.tex ref_man.tex \
- ttb.tex ttb_ug.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: etop_5.ps etop_lines.ps etop_main.ps etop_opt.ps
-
-book.dvi: et_modsprocs.ps et_processes.ps
-
diff --git a/lib/observer/doc/src/notes.xml b/lib/observer/doc/src/notes.xml
index 73eb992323..baa1354268 100644
--- a/lib/observer/doc/src/notes.xml
+++ b/lib/observer/doc/src/notes.xml
@@ -31,6 +31,22 @@
<p>This document describes the changes made to the Observer
application.</p>
+<section><title>Observer 0.9.10</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Do not install *.bat files on non-win32 machines (Thanks
+ to Hans Ulrich Niedermann)</p>
+ <p>
+ Own Id: OTP-9515</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Observer 0.9.9</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/observer/doc/src/ttb.xml b/lib/observer/doc/src/ttb.xml
index 2c80891925..4e63aecbf2 100644
--- a/lib/observer/doc/src/ttb.xml
+++ b/lib/observer/doc/src/ttb.xml
@@ -25,11 +25,12 @@
<title>ttb</title>
<prepared>Siri hansen</prepared>
+ <prepared>Bartlomiej Puzon</prepared>
<responsible></responsible>
<docno>1</docno>
<approved></approved>
<checked></checked>
- <date>2002-02-25</date>
+ <date>2010-08-13</date>
<rev>PA1</rev>
<file>ttb.sgml</file>
</header>
@@ -43,6 +44,35 @@
</description>
<funcs>
<func>
+ <name>start_trace(Nodes, Patterns, FlagSpec, Opts) -> Result</name>
+ <fsummary>Start a trace port on each given node.</fsummary>
+ <type>
+ <v>Result = see p/2</v>
+ <v>Nodes = see tracer/2</v>
+ <v>Patterns = [tuple()]</v>
+ <v>FlagSpec = {Procs, Flags}</v>
+ <v>Proc = see p/2</v>
+ <v>Flags = see p/2</v>
+ <v>Opts = see tracer/2</v>
+ </type>
+ <desc>
+ <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">
+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">
+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>
<name>tracer() -> Result</name>
<fsummary>This is equivalent to tracer(node()).</fsummary>
<desc>
@@ -50,6 +80,17 @@
</desc>
</func>
<func>
+ <name>tracer(Shortcut) -> Result</name>
+ <fsummary>Handy shortcuts for common tracing settings</fsummary>
+ <type>
+ <v>Shortcut = shell | dbg</v>
+ </type>
+ <desc>
+ <p><c>shell</c> is equivalent to <c>tracer(node(),[{file, {local, "ttb"}}, shell])</c>.</p>
+ <p><c>dbg</c> is equivalent to <c>tracer(node(),[{shell, only}])</c>.</p>
+ </desc>
+ </func>
+ <func>
<name>tracer(Nodes) -> Result</name>
<fsummary>This is equivalent to tracer(Nodes,[]).</fsummary>
<desc>
@@ -62,14 +103,21 @@
<type>
<v>Result = {ok, ActivatedNodes} | {error,Reason}</v>
<v>Nodes = atom() | [atom()] | all | existing | new</v>
- <v>Opts = [Opt]</v>
- <v>Opt = {file,Client} | {handler, FormatHandler} | {process_info,PI}</v>
+ <v>Opts = Opt | [Opt]</v>
+ <v>Opt = {file,Client} | {handler, FormatHandler} | {process_info,PI} |
+ shell | {shell, ShellSpec} | {timer, TimerSpec} | {overload, {MSec, Module, Function}}
+ | {flush, MSec} | resume | {resume, FetchTimeout}</v>
+ <v>TimerSpec = MSec | {MSec, StopOpts}</v>
+ <v>MSec = FetchTimeout = integer()</v>
+ <v>Module = Function = atom() </v>
+ <v>StopOpts = see stop/2</v>
<v>Client = File | {local, File}</v>
<v>File = Filename | Wrap</v>
<v>Filename = string()</v>
<v>Wrap = {wrap,Filename} | {wrap,Filename,Size,Count}</v>
<v>FormatHandler = See format/2</v>
<v>PI = true | false </v>
+ <v>ShellSpec = true | false | only</v>
</type>
<desc>
<p>This function starts a file trace port on all given nodes
@@ -96,7 +144,70 @@
is the process' registered name its globally registered name,
or its initial function. It is possible to turn off this
functionality by setting <c>PI = false</c>.
- </p>
+ </p>
+ <p>The <c>{shell, ShellSpec}</c> option indicates that the trace messages should
+ be printed on the console as they are received by the tracing
+ process. This implies <c>{local, File}</c> trace client. If the ShellSpec
+ is <c>only</c> (instead of <c>true</c>), no trace logs are stored.
+ </p>
+ <p>The <c>shell</c> option is a shortcut for <c>{shell, true}</c>.</p>
+ <p>The <c>timer</c> option indicates that the trace should be
+ automatically stopped after <c>MSec</c> milliseconds. <c>StopOpts</c>
+ are passed to <c>ttb:stop/2</c> command if specified (default is <c>[]</c>).
+ Note that the timing is approximate, as delays related to
+ network communication are always present. The timer starts after
+ <c>ttb:p/2</c> is issued, so you can set up your trace patterns before.
+ </p>
+ <p>The <c>overload</c> option allows to enable overload
+ checking on the nodes under trace. <c>Module:Function(check)</c>
+ is performed each <c>MSec</c> milliseconds. If the check returns
+ <c>true</c>, the tracing is disabled on a given node.<br/>
+ <c>Module:Function</c> should be able to handle at least three
+ atoms: <c>init</c>, <c>check</c> and <c>stop</c>. <c>init</c> and
+ <c>stop</c> give the user a possibility to initialize and clean
+ up the check environment.<br/>
+ When a node gets overloaded, it is not possible to issue <c>ttb:p</c>
+ nor any command from the <c>ttb:tp</c> family, as it would lead to
+ inconsistent tracing state (different trace specifications on
+ different node).
+ </p>
+ <p>The <c>flush</c> option periodically flushes all file trace
+ port clients (see <c>dbg:flush_trace_port/1</c>). When enabled,
+ the buffers are freed each <c>MSec</c> milliseconds. This option is
+ not allowed with <c>{file, {local, File}}</c> tracing.
+ </p>
+ <p><c>{resume, FetchTimeout}</c> enables the autoresume feature.
+ Whenever enabled, remote nodes try to reconnect to the controlling node
+ in case they were restarted. The feature requires <c>runtime_tools</c>
+ application to be started (so it has to be present in the <c>.boot</c>
+ scripts if the traced nodes run with embedded erlang). If this is
+ not possible, resume may be performed manually by starting
+ <c>runtime_tools</c> remotely using <c>rpc:call/4</c>.<br/>
+ <c>ttb</c> tries to fetch all logs from a reconnecting node before
+ reinitializing the trace. This has to finish within FetchTimeout milliseconds
+ or is aborted<br/>
+ By default, autostart information is stored in a file called
+ <c>ttb_autostart.bin</c> on each node. If this is not desired
+ (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:
+ <taglist>
+ <tag><c>write_config(Data) -> ok</c></tag>
+ <item>Store the provided data for further retrieval. It is
+ important to realize that the data storage used must not
+ be affected by the node crash.</item>
+ <tag><c>read_config() -> {ok, Data} | {error, Error}</c></tag>
+ <item>Retrieve configuration stored with <c>write_config(Data)</c>.</item>
+ <tag><c>delete_config() -> ok</c></tag>
+ <item>Delete configuration stored with <c>write_config(Data)</c>.
+ Note that after this call any subsequent calls to <c>read_config</c>
+ 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>
</func>
<func>
@@ -110,7 +221,7 @@
</type>
<desc>
<p>This function sets the given trace flags on the given
- processes.
+ processes. The <c>timestamp</c> flag is always turned on.
</p>
<p>Please turn to the Reference manual for module <c>dbg</c>
for details about the possible trace flags. The parameter
@@ -119,6 +230,9 @@
registered names or process identifiers. If a registered name
is given, the flags are set on processes with this name on all
active nodes.</p>
+ <p>Issuing this command starts the timer for this trace if
+ <c>timer</c> option was specified with <c>tracer/2</c>.
+ </p>
</desc>
</func>
<func>
@@ -155,6 +269,18 @@
<tag><c>ctpg</c></tag>
<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:
+ <taglist>
+ <item><c>return</c> - for <c>[{'_',[],[{return_trace}]}]</c>
+ (report the return value)</item>
+ <item><c>caller</c> - for <c>[{'_',[],[{message,{caller}}]}]</c>
+ (report the calling function)</item>
+ <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>
@@ -189,7 +315,7 @@
</desc>
</func>
<func>
- <name>write_config(ConfigFile,Config,Opt) -> ok | {error,Reason}</name>
+ <name>write_config(ConfigFile,Config,Opts) -> ok | {error,Reason}</name>
<fsummary>Creates a config file.</fsummary>
<type>
<v>ConfigFile = string()</v>
@@ -197,7 +323,8 @@
<v>Mod = atom()</v>
<v>Func = atom()</v>
<v>Args = [term()]</v>
- <v>Opt = [] | [append]</v>
+ <v>Opts = Opt | [Opt]</v>
+ <v>Opt = append</v>
</type>
<desc>
<p>This function creates or extends a config file which can be
@@ -213,9 +340,9 @@
should be a list of integers pointing out the entries to be
stored.
</p>
- <p>If <c>Opt</c> is not given or if it is <c>[]</c>,
+ <p>If <c>Opts</c> is not given or if it is <c>[]</c>,
<c>ConfigFile</c> is deleted and a new file is created. If
- <c>Opt = [append]</c>, <c>ConfigFile</c> will not be deleted.
+ <c>Opts = [append]</c>, <c>ConfigFile</c> will not be deleted.
The new information will be appended at the end of the file.</p>
</desc>
</func>
@@ -226,7 +353,9 @@
<v>ConfigFile = string()</v>
</type>
<desc>
- <p>Executes all entries in the given config file.</p>
+ <p>Executes all entries in the given config file. Note that the history
+ of the last trace is always available in the file named
+ <c>ttb_last_config</c>.</p>
</desc>
</func>
<func>
@@ -243,6 +372,9 @@
</p>
<p>The content of a config file can be listed with
<c>list_config/1</c>.</p>
+ <p> Note that the history
+ of the last trace is always available in the file named
+ <c>ttb_last_config</c>.</p>
</desc>
</func>
<func>
@@ -334,29 +466,51 @@
</desc>
</func>
<func>
- <name>stop(Opts) -> stopped</name>
+ <name>stop(Opts) -> stopped | {stopped, Dir}</name>
<fsummary>Stop tracing and fetch/format logs from all nodes</fsummary>
<type>
- <v>Opts = [Opt]</v>
- <v>Opt = fetch | format</v>
+ <v>Opts = Opt | [Opt]</v>
+ <v>Opt = nofetch | {fetch_dir, Dir} | format | {format, FormatOpts} | return_fetch_dir</v>
+ <v>Dir = string()</v>
+ <v>FormatOpts = see format/2</v>
</type>
<desc>
- <p>Stops tracing on all nodes.
- </p>
- <p>The <c>fetch</c> option indicates that trace logs shall be
- collected from all nodes after tracing is stopped. This option
- is useful if nodes on remote machines are traced. Logs and
- trace information files are then sent to the trace control
+ <p>Stops tracing on all nodes. Logs and
+ trace information files are sent to the trace control
node and stored in a directory named
- <c>ttb_upload-Timestamp</c>, where <c>Timestamp</c> is on the
+ <c>ttb_upload_FileName-Timestamp</c>, where <c>Filename</c> is
+ the one provided with <c>{file, File}</c> during trace setup
+ and <c>Timestamp</c> is of the
form <c>yyyymmdd-hhmmss</c>. Even logs from nodes on the same
machine as the trace control node are moved to this directory.
- </p>
+ The history list is saved to a file named <c>ttb_last_config</c>
+ for further reference (as it will be not longer accessible
+ through history and configuration management functions (like
+ <c>ttb:list_history/0</c>).
+ </p>
+ <p>The <c>nofetch</c> option indicates that trace logs shall not be
+ collected after tracing is stopped.
+ </p>
+ <p>The <c>{fetch, Dir}</c> option allows to specify the directory
+ to fetch the data to. If the directory already exists, an
+ error is thrown.
+ </p>
<p>The <c>format</c> option indicates that the trace logs
- shall be formatted after tracing is stopped. Note that this
- option also implies the <c>fetch</c> option, i.e. logs are
- collected in a new directory on the trace control node before
- formatting. All logs in the directory will be merged.</p>
+ shall be formatted after tracing is stopped. All logs in the fetch directory will be merged.
+ You may use <c>{format, FormatOpts}</c> to pass additional
+ arguments to <c>format/2</c>.</p>
+ <p>The <c>return_fetch_dir</c> option indicates that the return value
+ should be <c>{stopped, Dir}</c> and not just <c>stopped</c>.
+ This implies <c>fetch</c>.
+ </p>
+ </desc>
+ </func>
+ <func>
+ <name>get_et_handler()</name>
+ <fsummary>Returns <c>et</c> handler.</fsummary>
+ <desc>
+ <p>The <c>et</c> handler returned by the function may be used with <c>format/2</c>
+ or <c>tracer/2</c>. Example: <c>ttb:format(Dir, [{handler, ttb:get_et_handler()}])</c>.</p>
</desc>
</func>
<func>
@@ -372,37 +526,40 @@
<type>
<v>File = string() | [string()]</v>
<d>This can be the name of a binary log, a list of such logs or the name of a directory containing one or more binary logs.</d>
- <v>Options = [Opt]</v>
- <v>Opt = {out,Out} | {handler,FormatHandler}</v>
+ <v>Options = Opt | [Opt]</v>
+ <v>Opt = {out,Out} | {handler,FormatHandler} | disable_sort</v>
<v>Out = standard_io | string()</v>
- <v>FormatHandler = {Function, InitialState} | et</v>
+ <v>FormatHandler = {Function, InitialState}</v>
<v>Function = fun(Fd,Trace,TraceInfo,State) -> State</v>
<v>Fd = standard_io | FileDescriptor</v>
<d>This is the file descriptor of the destination file <c>Out</c></d>
<v>Trace = tuple()</v>
<d>This is the trace message. Please turn to the Reference manual for the <c>erlang</c>module for details.</d>
<v>TraceInfo = [{Key,ValueList}]</v>
- <d>This includes the keys <c>flags</c>, <c>client</c>and <c>node</c>, and if <c>handler</c>is given as option to the tracer function, this is also included. In addition all information written with the <c>write_trace_info/2</c>function is included. </d>
+ <d>This includes the keys <c>flags</c>, <c>client</c> and <c>node</c>, and if <c>handler</c> is given as option to the tracer function, this is also included. In addition all information written with the <c>write_trace_info/2</c>function is included. </d>
</type>
<desc>
- <p>Reads the given binary trace log(s). If a directory or a
- list of logs is given and the <c>timestamp</c> flag was set
- during tracing, the trace messages from the different logs are
- merged according to the timestamps.
- </p>
+ <p>Reads the given binary trace log(s). The logs are processed
+ in the order of their timestamp as long as <c>disable_sort</c>
+ option is not given.
+ </p>
<p>If <c>FormatHandler = {Function,InitialState}</c>,
<c>Function</c> will be called for each trace message. If
- <c>FormatHandler = et</c>, <c>et_viewer</c> in the <em>Event Tracer</em> application (<c>et</c>) is used for presenting the
- trace log graphically. <c>ttb</c> provides a few different
+ <c>FormatHandler = get_et_handler()</c>, <c>et_viewer</c> in
+ the <em>Event Tracer</em> application (<c>et</c>) is used for presenting
+ the trace log graphically. <c>ttb</c> provides a few different
filters which can be selected from the Filter menu in the
<c>et_viewer</c>. If <c>FormatHandler</c> is not given, a
default handler is used which presents each trace message as a
line of text.
</p>
+ <p>The state returned from each call of <c>Function</c> is passed to the next call,
+ even if next call is to format a message from another log file.
+ </p>
<p>If <c>Out</c> is given, <c>FormatHandler</c> gets the
- filedescriptor to <c>Out</c> as the first parameter.
+ file descriptor to <c>Out</c> as the first parameter.
</p>
- <p><c>Out</c> is ignored if <c>FormatHandler = et</c>.
+ <p><c>Out</c> is ignored if <c>et</c> format handler is used.
</p>
<p>Wrap logs can be formatted one by one or all in one go. To
format one of the wrap logs in a set, give the exact name of
diff --git a/lib/observer/doc/src/ttb_ug.xml b/lib/observer/doc/src/ttb_ug.xml
index 44b7b08fd3..4f2b55a22a 100644
--- a/lib/observer/doc/src/ttb_ug.xml
+++ b/lib/observer/doc/src/ttb_ug.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2002</year><year>2009</year>
+ <year>2002</year><year>2010</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -48,11 +48,13 @@
<item>Formatting of binary trace logs and merging of logs from
multiple nodes.</item>
</list>
- <p>Even though the intention of the Trace Tool Builder is to serve
- as a base for tailor made trace tools, it is of course possible
- to use it directly from the erlang shell. The application only
- allows the use of file port tracer, so if you would like would
- like to use other types of trace clients you will be better off
+ <p>The intention of the Trace Tool Builder is to serve
+ as a base for tailor made trace tools, but you may use it directly
+ from the erlang shell (it may mimic <c>dbg</c> behaviour while
+ still providing useful additions like match specification shortcuts).
+ The application only
+ allows the use of file port tracer, so if you would like
+ to use other types of trace clients you will be better off
using <c>dbg</c> directly instead.</p>
</section>
@@ -64,14 +66,15 @@
trace flags on the processes you want to trace with
<c>ttb:p/2</c>. Then, when the tracing is completed, you must stop
the tracer with <c>ttb:stop/0/1</c> and format the trace log with
- <c>ttb:format/1/2</c>.
+ <c>ttb:format/1/2</c> (as long as there is anything to format, of
+ course).
</p>
- <p><c>ttb:tracer/0/1/2</c> opens a file trace port on each node
- that shall be traced. All trace messages will be written to this
- port and end up in a binary file (the binary trace log).
+ <p><c>ttb:tracer/0/1/2</c> opens a trace port on each node
+ that shall be traced. By default, trace messages are written
+ to binary files on remote nodes(the binary trace log).
</p>
- <p><c>ttb:p/2</c> specifies which processes that shall be
- traced. Trace flags given in this call specifies what to trace on
+ <p><c>ttb:p/2</c> specifies which processes shall be
+ traced. Trace flags given in this call specify what to trace on
each process. You can call this function several times if you like
different trace flags to be set on different processes.
</p>
@@ -105,14 +108,15 @@
-export([f/0]).
f() ->
receive
- From when pid(From) ->
+ From when is_pid(From) ->
Now = erlang:now(),
From ! {self(),Now}
end. </code>
<p>The following example shows the basic use of <c>ttb</c> from
the erlang shell. Default options are used both for starting the
- tracer and for formatting. This gives a trace log named
- <c>Node-ttb</c>, where <c>Node</c> is the name of the node. The
+ tracer and for formatting (the custom fetch dir is however provided).
+ This gives a trace log named <c>Node-ttb</c> in the newly-created
+ directory, where <c>Node</c> is the name of the node. The
default handler prints the formatted trace messages in the
shell.</p>
<code type="none"><![CDATA[
@@ -131,11 +135,11 @@ f() ->
(tiger@durin)50>
(tiger@durin)50> %% Here I set a trace pattern on erlang:now/0
(tiger@durin)50> %% The trace pattern is a simple match spec
-(tiger@durin)50> %% generated by dbg:fun2ms/1. It indicates that
-(tiger@durin)50> %% the return value shall be traced.
-(tiger@durin)50> MS = dbg:fun2ms(fun(_) -> return_trace() end).
-[{'_',[],[{return_trace}]}]
-(tiger@durin)51> ttb:tp(erlang,now,MS).
+(tiger@durin)50> %% indicating that the return value should be
+(tiger@durin)50> %% traced. Refer to the reference_manual for
+(tiger@durin)50> %% the full list of match spec shortcuts
+(tiger@durin)50> %% available.
+(tiger@durin)51> ttb:tp(erlang,now,return).
{ok,[{matched,tiger@durin,1},{saved,1}]}
(tiger@durin)52>
(tiger@durin)52> %% I run my test (i.e. send a message to
@@ -145,11 +149,11 @@ f() ->
(tiger@durin)53>
(tiger@durin)53> %% And then I have to stop ttb in order to flush
(tiger@durin)53> %% the trace port buffer
-(tiger@durin)53> ttb:stop().
-stopped
+(tiger@durin)53> ttb:stop([return, {fetch_dir, "fetch"}]).
+{stopped, "fetch"}
(tiger@durin)54>
(tiger@durin)54> %% Finally I format my trace log
-(tiger@durin)54> ttb:format("tiger@durin-ttb").
+(tiger@durin)54> ttb:format("fetch").
({<0.125.0>,{m,f,0},tiger@durin}) call erlang:now()
({<0.125.0>,{m,f,0},tiger@durin}) returned from erlang:now/0 ->
{1031,133451,667611}
@@ -166,11 +170,9 @@ ok ]]></code>
-module(mydebug).
-export([start/0,trc/1,stop/0,format/1]).
-export([print/4]).
-
%% Include ms_transform.hrl so that I can use dbg:fun2ms/2 to
%% generate match specifications.
-include_lib("stdlib/include/ms_transform.hrl").
-
%%% -------------Tool API-------------
%%% ----------------------------------
%%% Star the "mydebug" tool
@@ -180,28 +182,28 @@ start() ->
%% module shall be used as format handler
ttb:tracer(all,[{file,"debug_log"},{handler,{{?MODULE,print},0}}]),
%% All processes (existing and new) shall trace function calls
- %% and include a timestamp in each trace message
- ttb:p(all,[call,timestamp]).
+ %% We want trace messages to be sorted upon format, which requires
+ %% timestamp flag. The flag is however enabled by default in ttb.
+ ttb:p(all,call).
%%% Set trace pattern on function(s)
-trc(M) when atom(M) ->
+trc(M) when is_atom(M) ->
trc({M,'_','_'});
-trc({M,F}) when atom(M), atom(F) ->
+trc({M,F}) when is_atom(M), is_atom(F) ->
trc({M,F,'_'});
-trc({M,F,_A}=MFA) when atom(M), atom(F) ->
- %% This match spec specifies that return values shall
- %% be traced. NOTE that ms_transform.hrl must be included
- %% if dbg:fun2ms/1 shall be used!
+trc({M,F,_A}=MFA) when is_atom(M), is_atom(F) ->
+ %% This match spec shortcut specifies that return values shall
+ %% be traced.
MatchSpec = dbg:fun2ms(fun(_) -> return_trace() end),
ttb:tpl(MFA,MatchSpec).
%%% Format a binary trace log
-format(File) ->
- ttb:format(File).
+format(Dir) ->
+ ttb:format(Dir).
%%% Stop the "mydebug" tool
stop() ->
- ttb:stop().
+ ttb:stop(return).
%%% --------Internal functions--------
%%% ----------------------------------
@@ -226,9 +228,9 @@ do_print(Out,{trace_ts,P,return_from,{M,F,A},R,Ts},N) ->
[N,Ts,P,M,F,A,R]). ]]></code>
<p>To distinguish trace logs produced with this tool from other
logs, the <c>file</c> option is used in <c>tracer/2</c>. The
- logs will therefore be named <c>Node-debug_log</c>, where
- <c>Node</c> is the name of the node where the log is produced.
- </p>
+ logs will therefore be fetched to a directory named
+ <c>ttb_upload_debug_log-YYYYMMDD-HHMMSS</c>
+ </p>
<p>By using the <c>handler</c> option when starting the tracer,
the information about how to format the file is stored in the
trace information file (<c>.ti</c>). This is not necessary, as
@@ -278,13 +280,157 @@ do_print(Out,{trace_ts,P,return_from,{M,F,A},R,Ts},N) ->
must be given to the <c>tracer/2</c> function with the value
<c>{local, File}</c>, e.g.</p>
<code type="none">
-(trace_control@durin)1> ttb:tracer(mynode@diskless,[{file,{local,
-{wrap,"mytrace"}}}]).
+(trace_control@durin)1> ttb:tracer(mynode@diskless,{file,{local,
+{wrap,"mytrace"}}}).
{ok,[mynode@diskless]} </code>
</section>
</section>
<section>
+ <title>Additional tracing options</title>
+ <p>When setting up a trace, several features may be turned on:</p>
+ <list type="bulleted">
+ <item>time-constrained tracing,</item>
+ <item>overload protection,</item>
+ <item>autoresuming.</item>
+ </list>
+ <section>
+ <title>Time-constrained tracing</title>
+ <p>Sometimes, it may be helpful to enable trace for a
+ given period of time (i.e. to monitor a system for 24 hours
+ or half of a second). This may be done by issuing additional
+ <c>{timer, TimerSpec}</c> option. If <c>TimerSpec</c> has the
+ form of <c>MSec</c>, the trace is stopped after <c>MSec</c>
+ milliseconds using <c>ttb:stop/0</c>. If any additional options
+ are provided (<c>TimerSpec = {MSec, Opts}</c>), <c>ttb:stop/1</c>
+ is called instead with <c>Opts</c> as the arguments. The timer
+ is started with <c>ttb:p/2</c>, so any trace patterns should
+ be set up before. <c>ttb:start_trace/4</c>
+ always sets up all pattern before invoking <c>ttb:p/2</c>.
+ Note that due to network and processing delays the the period
+ of tracing is approximate.
+ The example below shows how to set up a trace which will be
+ automatically stopped and formatted after 5 seconds
+ </p><code>
+(tiger@durin)1>ttb:start_trace([node()],
+ [{erlang, now,[]}],
+ {all, call},
+ [{timer, {5000, format}}]).
+</code>
+ </section>
+ <section>
+ <label>Overload protection</label>
+ <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>
+ <p><c>{overload, MSec, Module, Function}</c> instructs the ttb backend
+ (called <c>observer_backend</c>, part of the <c>runtime_tools</c>
+ application) to perform overload check every <c>MSec</c> milliseconds.
+ If the check (namely <c>Module:Function(check)</c>) returns
+ <c>true</c>, tracing is disabled on the selected node.</p>
+ <p>Overload protection activated on one node does not
+ affect other nodes, where the tracing continues as normal.
+ <c>ttb:stop/0/1</c> fetches data from all clients, including everything
+ that has been collected before overload protection was activated.
+ Note that
+ changing trace details (with <c>ttb:p</c> and <c>ttb:tp/tpl...</c>)
+ once overload protection gets activated in one of the traced
+ nodes is not permitted in order not to allow trace setup
+ to be inconsistent between nodes.
+ </p>
+ <p><c>Module:Function</c> provided with the <c>overload</c> option must
+ handle three calls: <c>init</c>, <c>check</c> and <c>stop</c>. <c>init</c>
+ and <c>stop</c> allows to perform some setup and teardown required by
+ the check. An overload check module could look like this (note that
+ <c>check</c> is always called by the same process, so <c>put</c> and
+ <c>get</c> are possible).
+ </p><code>
+-module(overload).
+-export([check/1]).
+
+check(init) ->
+ Pid = sophisticated_module:start(),
+ put(pid, Pid);
+check(check) ->
+ get(pid) ! is_overloaded,
+ receive
+ Reply ->
+ Reply
+ after 5000 ->
+ true
+ end;
+check(stop) ->
+ get(pid) ! stop.</code>
+ </section>
+ <section>
+ <title>Autoresume</title>
+ <p>It is possible that a node (probably a buggy one, hence traced)
+ crashes. In order to automatically resume tracing on the node
+ as soon as it gets back, <c>resume</c> has to be used. When
+ it is, the failing node tries to reconnect
+ to trace control node as soon as <c>runtime tools</c> is started.
+ This implies that <c>runtime_tools</c> must be included in
+ other node's startup chain (if it is not, one could still
+ resume tracing by starting <c>runtime_tools</c> manually,
+ i.e. by an RPC call).</p>
+ <p>In order not to loose the data that the failing node stored
+ up to the point of crash, the control node will try to fetch
+ it before restarting trace. This must happen within the allowed
+ time frame or is aborted (default is 10 seconds, can be customized with
+ <c>{resume, MSec}</c>). The data fetched this way is then
+ merged with all other traces.</p>
+ <p>Autostart feature requires additional data to be stored on
+ traced nodes. By default, the data is stored automatically
+ to the file called "ttb_autostart.bin" in the traced node's cwd.
+ Users may decide to change this behaviour (i.e. on diskless
+ nodes) by specifying their own module to handle autostart data
+ storage and retrieval (<c>ttb_autostart_module</c>
+ environment variable of <c>runtime_tools</c>). Please see the
+ ttb's reference manual to see the module's API. This example
+ shows the default handler</p>
+ <code>
+-module(ttb_autostart).
+-export([read_config/0,
+ write_config/1,
+ delete_config/0]).
+
+-define(AUTOSTART_FILENAME, "ttb_autostart.bin").
+
+delete_config() ->
+ file:delete(?AUTOSTART_FILENAME).
+
+read_config() ->
+ case file:read_file(?AUTOSTART_FILENAME) of
+ {ok, Data} -> {ok, binary_to_term(Data)};
+ Error -> Error
+ end.
+
+write_config(Data) ->
+ file:write_file(?AUTOSTART_FILENAME, term_to_binary(Data)).
+ </code>
+ <p>Remember that file trace ports buffer the data
+ by default. If the node crashes, trace messages are not
+ flushed to the binary log. If the chance of failure is
+ high, it might be a good idea to automatically flush
+ the buffers every now and then. Passing <c>{flush, MSec}</c>
+ as one of <c>ttb:tracer/2</c> option flushes all buffers
+ every <c>MSec</c> milliseconds.</p>
+ </section>
+ <section>
+ <title>dbg mode</title>
+ <p>The <c>{shell, ShellType}</c> option allows to make <c>ttb</c>
+ operation similar to <c>dbg</c>. Using <c>{shell, true}</c>
+ displays all trace messages in the shell before storing them.
+ <c>{shell, only}</c> additionally disables message storage
+ (so that the tool behaves exactly like dbg). This is allowed
+ only with ip trace ports (<c>{trace, {local, File}}</c>).
+ </p>
+ <p>The command <c>ttb:tracer(dbg)</c> is a shortcut for the pure-dbg
+ mode (<c>{shell, only}</c>).</p>
+ </section>
+ </section>
+
+ <section>
<marker id="trace_info"></marker>
<title>Trace Information and the .ti File</title>
<p>In addition to the trace log file(s), a file with the extension
@@ -292,13 +438,9 @@ do_print(Out,{trace_ts,P,return_from,{M,F,A},R,Ts},N) ->
is the trace information file. It is a binary file, and it
contains the process information, trace flags used, the name of
the node to which it belongs and all information written with the
- <c>write_trace_info/2</c> function.
- </p>
- <p>To be able to use all this information during formatting, it is
- important that the trace information file exists in the same
- directory as the trace log, and that it has the same name as the
- trace log with the additional extension <c>.ti</c>.
- </p>
+ <c>write_trace_info/2</c> function. .ti files are always fetched
+ with other logs when the trace is stopped.
+ </p>
<p>Except for the process information, everything in the trace
information file is passed on to the handler function when
formatting. The <c>TI</c> parameter is a list of
@@ -327,7 +469,12 @@ do_print(Out,{trace_ts,P,return_from,{M,F,A},R,Ts},N) ->
each log. <c>ttb</c> will create a new binary log each time a log
reaches the maximum size. When the the maximum number of logs are
reached, the oldest log is deleted before a new one is created.
- </p>
+ </p>
+ <p>Note that the overall size of data generated by ttb may be greater
+ than the wrap specification would suggest - if a traced node restarts
+ and autoresume is enabled, old wrap log is always stored and
+ a new one is created.
+ </p>
<p>Wrap logs can be formatted one by one or all at once. See
<seealso marker="#format">Formatting</seealso>.
</p>
@@ -348,12 +495,10 @@ do_print(Out,{trace_ts,P,return_from,{M,F,A},R,Ts},N) ->
present the trace log graphically (see <seealso marker="#et_viewer">Presenting trace logs with Event Tracer</seealso>).
</p>
<p>The first argument to <c>ttb:format/1/2</c> specifies which
- binary log(s) to format. This can be the name of one binary log, a
- list of such logs or the name of a directory containing one or
- more binary logs. If this argument indicates more than one log,
- and the <c>timestamp</c> flag was set when tracing, the trace
- messages from the different logs will be merged according to the
- timestamps in each message.
+ binary log(s) to format. This is usually the name of a directory
+ that ttb created during log fetch. Unless there is the <c>disable_sort</c>
+ option provided, the logs from different files are always sorted
+ according to timestamp in traces.
</p>
<p>The second argument to <c>ttb:format/2</c> is a list of
options. The <c>out</c> option specifies the destination where the
@@ -363,7 +508,10 @@ do_print(Out,{trace_ts,P,return_from,{M,F,A},R,Ts},N) ->
option is not given, the <c>handler</c> option given when starting
the tracer is used. If the <c>handler</c> option was not given
when starting the tracer either, a default handler is used, which
- prints each trace message as a line of text.
+ prints each trace message as a line of text. The <c>disable_sort</c>
+ option indicates that there logs should not be merged according to
+ timestamp, but processed one file after another (this might be
+ a bit faster).
</p>
<p>A format handler is a fun taking four arguments. This fun will
be called for each trace message in the binary log(s). A simple
@@ -396,10 +544,24 @@ end </code>
<c>handle_gc/4</c> in the module <c>multitrace.erl</c> which can
be found in the <c>src</c> directory of the Observer application.
</p>
- <p>By giving the format handler <c>et</c>, you can have the trace
+ <p>The actual trace message is passed as the second argument (<c>Trace</c>).
+ The possible values of <c>Trace</c> are:</p>
+ <list type="bulleted">
+ <item>all trace messages described in <c>erlang:trace/3</c> documentation,
+ </item>
+ <item><c>{drop, N}</c> if ip tracer is used (see <c>dbg:trace_port/2</c>),
+ </item>
+ <item><c>end_of_trace</c> received once when all trace messages have
+ been processed.</item>
+ </list>
+ <p>By giving the format handler <c>ttb:get_et_handler()</c>, you can have the trace
log presented graphically with <c>et_viewer</c> in the Event
Tracer application (see <seealso marker="#et_viewer">Presenting trace logs with Event Tracer</seealso>).
- </p>
+ </p>
+ <p>You may always decide not to format the whole trace data contained
+ in the fetch directory, but analyze single files instead. In order
+ to do so, a single file (or list of files) have to be passed as
+ the first argument to <c>format/1/2</c>.</p>
<p>Wrap logs can be formatted one by one or all in one go. To
format one of the wrap logs in a set, give the exact name of the
file. To format the whole set of wrap logs, give the name with '*'
@@ -407,7 +569,7 @@ end </code>
</p>
<p>Start tracing:</p>
<code type="none">
-(tiger@durin)1> ttb:tracer(node(),[{file,{wrap,"trace"}}]).
+(tiger@durin)1> ttb:tracer(node(),{file,{wrap,"trace"}}).
{ok,[tiger@durin]}
(tiger@durin)2> ttb:p(...)
... </code>
@@ -443,7 +605,7 @@ ok
to the User's Guide and Reference Manuals for the <c>et</c>
application.
</p>
- <p>By giving the format handler <c>et</c>, you can have the
+ <p>By giving the format handler <c>ttb:get_et_handler()</c>, you can have the
trace log presented graphically with <c>et_viewer</c> in the
Event Tracer application. <c>ttb</c> provides a few different
filters which can be selected from the Filter menu in the
@@ -495,9 +657,23 @@ ok
filters respectively, except that each module or function can
have several vertical lines, one for each process it resides on.
</p>
- <p>As an example this module is used, and the function
- <c>bar:f1()</c> is called from another module <c>foo</c>.</p>
+ <p>In the next example, modules <c>foo</c> and <c>bar</c> are used:</p>
<code type="none">
+-module(foo).
+-export([start/0,go/0]).
+
+start() ->
+ spawn(?MODULE, go, []).
+
+go() ->
+ receive
+ stop ->
+ ok;
+ go ->
+ bar:f1(),
+ go()
+ end.
+</code><code type="none">
-module(bar).
-export([f1/0,f3/0]).
f1() ->
@@ -506,12 +682,23 @@ f1() ->
f2() ->
spawn(?MODULE,f3,[]).
f3() ->
- ok. </code>
- <p>The <c>call</c> and <c>return_to</c> flags are used, and
- trace pattern is set on local calls in module <c>bar</c>.
- </p>
- <p><c>ttb:format("tiger@durin-ttb", [{handler, et}])</c> gives the
- following result:
+ ok.</code>
+
+ <p>Now let's set up the trace.</p>
+<code>
+(tiger@durin)1>%%First we retrieve the Pid to limit traced processes set
+(tiger@durin)1>Pid = foo:start().
+(tiger@durin)2>%%Now we set up tracing
+(tiger@durin)2>ttb:tracer().
+(tiger@durin)3>ttb:p(Pid, [call, return_to, procs, set_on_spawn]).
+(tiger@durin)4>ttb:tpl(bar, []).
+(tiger@durin)5>%%Invoke our test function and see output with et viewer
+(tiger@durin)5>Pid ! go.
+(tiger@durin)6>ttb:stop({format, {handler, ttb:get_et_handler()}}).
+</code>
+
+ <p>This shoud render a result similar to the
+ following:
</p>
<p></p>
<image file="et_processes.gif">
@@ -520,25 +707,37 @@ f3() ->
<image file="et_modsprocs.gif">
<icaption>Filter: "mods_and_procs"</icaption>
</image>
+
+ <p>Note, that we can use <c>ttb:start_trace/4</c> function to help
+ us here:</p>
+<code>
+(tiger@durin)1>Pid = foo:start().
+(tiger@durin)2>ttb:start_trace([node()],
+ [{bar,[]}],
+ {Pid, [call, return_to, procs, set_on_spawn]}
+ {handler, ttb:get_et_handler()}).
+(tiger@durin)3>Pid ! go.
+(tiger@durin)4>ttb:stop(format).
+</code>
+
</section>
</section>
<section>
<marker id="fetch_format"></marker>
<title>Automatically collect and format logs from all nodes</title>
- <p>If the option <c>fetch</c> is given to the <c>ttb:stop/1</c>
- function, trace logs and trace information files are fetched
- from all nodes after tracing is stopped. The logs are stored in a
- new directory named <c>ttb_upload-Timestamp</c> under the working
- directory of the trace control node.
+ <p>By default <c>ttb:stop/1</c> fetches trace logs and
+ trace information files from all nodes. The logs are stored in a
+ new directory named <c>ttb_upload-Filename-Timestamp</c> under the working
+ directory of the trace control node. Fetching may be disabled by
+ providing the <c>nofetch</c> option to <c>ttb:stop/1</c>. User can
+ specify a fetch directory of his choice passing the
+ <c>{fetch_dir, Dir}</c> option.
</p>
<p>If the option <c>format</c> is given to <c>ttb:stop/1</c>, the
trace logs are automatically formatted after tracing is
- stopped. Note that <c>format</c> also implies <c>fetch</c>,
- i.e. the trace logs will be collected from all nodes as for the
- <c>fetch</c> option before they are formatted. All logs in the
- upload directory are merged during formatting.
- </p>
+ stopped.
+ </p>
</section>
<section>
@@ -546,13 +745,18 @@ f3() ->
<p>For the tracing functionality, <c>dbg</c> could be used instead
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>. The only
- thing added by <c>ttb</c> for these functions is that all calls
- are stored in the history buffer and can be recalled and stored in
- a configuration file. This makes it easy to setup the same trace
- environment e.g. if you want to compare two test runs. It also
- reduces the amount of typing when using <c>ttb</c> from the erlang
- shell.
+ <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:
+ <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
+ easy to setup the same trace environment e.g. if you want to
+ compare two test runs. It also reduces the amount of
+ 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>).
+ </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.
@@ -574,7 +778,8 @@ f3() ->
selected entries from the history by calling
<c>ttb:write_config(ConfigFile,NumList)</c>, where
<c>NumList</c> is a list of integers pointing out the history
- entries to write.
+ entries to write. Moreover, the history buffer is always dumped
+ to <c>ttb_last_config</c> when <c>ttb:stop/0/1</c> is called.
</p>
<p>User defined entries can also be written to a config file by
calling the function
@@ -720,9 +925,7 @@ ok
{ok,[{matched,1},{saved,1}]}
(tiger@durin)113> dbg:get_tracer(), seq_trace:reset_trace().
true
-(tiger@durin)114> ttb:stop().
-ok
-(tiger@durin)115> ttb:format("tiger@durin-ttb").
+(tiger@durin)114> ttb:stop(format).
({<0.158.0>,{shell,evaluator,3},tiger@durin}) call dbg:get_tracer()
SeqTrace [0]: ({<0.158.0>,{shell,evaluator,3},tiger@durin})
{<0.237.0>,dbg,tiger@durin} ! {<0.158.0>,{get_tracer,tiger@durin}}
@@ -743,9 +946,7 @@ ok
(tiger@durin)117> seq_trace:set_token(send,true), dbg:get_tracer(),
seq_trace:reset_trace().
true
-(tiger@durin)118> ttb:stop().
-ok
-(tiger@durin)119> ttb:format("tiger@durin-ttb").
+(tiger@durin)118> ttb:stop(format).
SeqTrace [0]: ({<0.158.0>,{shell,evaluator,3},tiger@durin})
{<0.246.0>,dbg,tiger@durin} ! {<0.158.0>,{get_tracer,tiger@durin}}
[Serial: {0,1}]
diff --git a/lib/observer/src/Makefile b/lib/observer/src/Makefile
index 2d06cb6bc4..3875b62101 100644
--- a/lib/observer/src/Makefile
+++ b/lib/observer/src/Makefile
@@ -56,13 +56,16 @@ TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET)
PRIVDIR= ../priv
WEBTOOLFILES= $(PRIVDIR)/crashdump_viewer.tool
BINDIR= $(PRIVDIR)/bin
+ifeq ($(findstring win32,$(TARGET)),win32)
+WIN32_EXECUTABLES= $(BINDIR)/etop.bat $(BINDIR)/getop.bat $(BINDIR)/cdv.bat
+else
+WIN32_EXECUTABLES=
+endif
EXECUTABLES= \
$(BINDIR)/etop \
$(BINDIR)/getop \
$(BINDIR)/cdv \
- $(BINDIR)/etop.bat \
- $(BINDIR)/getop.bat \
- $(BINDIR)/cdv.bat
+ $(WIN32_EXECUTABLES)
CDVDIR= $(PRIVDIR)/crashdump_viewer
GIF_FILES= \
$(CDVDIR)/collapsd.gif \
diff --git a/lib/observer/src/ttb.erl b/lib/observer/src/ttb.erl
index 221b71df6a..1471be92e5 100644
--- a/lib/observer/src/ttb.erl
+++ b/lib/observer/src/ttb.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -18,9 +18,11 @@
%%
-module(ttb).
-author('[email protected]').
+-author('[email protected]').
%% API
--export([tracer/0,tracer/1,tracer/2,p/2,stop/0,stop/1]).
+-export([tracer/0,tracer/1,tracer/2,p/2,stop/0,stop/1,start_trace/4]).
+-export([get_et_handler/0]).
-export([tp/2, tp/3, tp/4, ctp/0, ctp/1, ctp/2, ctp/3, tpl/2, tpl/3, tpl/4,
ctpl/0, ctpl/1, ctpl/2, ctpl/3, ctpg/0, ctpg/1, ctpg/2, ctpg/3]).
-export([seq_trigger_ms/0,seq_trigger_ms/1]).
@@ -34,24 +36,38 @@
-include_lib("kernel/include/file.hrl").
-define(meta_time,5000).
+-define(fetch_time, 10000).
-define(history_table,ttb_history_table).
-define(seq_trace_flags,[send,'receive',print,timestamp]).
--define(upload_dir,"ttb_upload").
+-define(upload_dir(Logname),"ttb_upload_"++Logname).
+-define(last_config, "ttb_last_config").
+-define(partial_dir, "ttb_partial_result").
-ifdef(debug).
--define(get_status,;get_status -> erlang:display(dict:to_list(NodeInfo)),loop(NodeInfo)).
+-define(get_status,;get_status -> erlang:display(dict:to_list(NodeInfo),loop(NodeInfo, TraceInfo)).
-else.
-define(get_status,).
-endif.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%% Shortcut
+start_trace(Nodes, Patterns, {Procs, Flags}, Options) ->
+ {ok, _} = tracer(Nodes, Options),
+ [{ok, _} = apply(?MODULE, tpl, tuple_to_list(Args)) || Args <- Patterns],
+ {ok, _} = p(Procs, Flags).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Open a trace port on all given nodes and create the meta data file
tracer() -> tracer(node()).
+tracer(shell) -> tracer(node(), shell);
+tracer(dbg) -> tracer(node(), {shell, only});
tracer(Nodes) -> tracer(Nodes,[]).
tracer(Nodes,Opt) ->
- start(),
- store(tracer,[Nodes,Opt]),
{PI,Client,Traci} = opt(Opt),
- do_tracer(Nodes,PI,Client,Traci).
+ %%We use initial Traci as SessionInfo for loop/2
+ Pid = start(Traci),
+ store(tracer,[Nodes,Opt]),
+ do_tracer(Nodes,PI,Client,[{ttb_control, Pid}|Traci]).
do_tracer(Nodes0,PI,Client,Traci) ->
Nodes = nods(Nodes0),
@@ -59,9 +75,14 @@ do_tracer(Nodes0,PI,Client,Traci) ->
do_tracer(Clients,PI,Traci).
do_tracer(Clients,PI,Traci) ->
+ ShellOutput = proplists:get_value(shell, Traci, false),
{ClientSucc,Succ} =
lists:foldl(
fun({N,{local,File},TF},{CS,S}) ->
+ TF2 = case ShellOutput of
+ only -> none;
+ _ -> TF
+ end,
[_Sname,Host] = string:tokens(atom_to_list(N),"@"),
case catch dbg:tracer(N,port,dbg:trace_port(ip,0)) of
{ok,N} ->
@@ -69,8 +90,8 @@ do_tracer(Clients,PI,Traci) ->
{ok,T} = dbg:get_tracer(N),
rpc:call(N,seq_trace,set_system_tracer,[T]),
dbg:trace_client(ip,{Host,Port},
- {fun ip_to_file/2,{file,File}}),
- {[{N,{local,File,Port},TF}|CS], [N|S]};
+ {fun ip_to_file/2,{{file,File}, ShellOutput}}),
+ {[{N,{local,File,Port},TF2}|CS], [N|S]};
Other ->
display_warning(N,{cannot_open_ip_trace_port,
Host,
@@ -98,17 +119,54 @@ do_tracer(Clients,PI,Traci) ->
{ok,Succ}
end.
+opt(Opt) when is_list(Opt) ->
+ opt(Opt,{true,?MODULE,[]});
opt(Opt) ->
- opt(Opt,{true,?MODULE,[]}).
+ opt([Opt]).
opt([{process_info,PI}|O],{_,Client,Traci}) ->
opt(O,{PI,Client,Traci});
opt([{file,Client}|O],{PI,_,Traci}) ->
- opt(O,{PI,Client,Traci});
+ opt(O,{PI,Client,[{logfile,get_logname(Client)}|Traci]});
opt([{handler,Handler}|O],{PI,Client,Traci}) ->
opt(O,{PI,Client,[{handler,Handler}|Traci]});
+opt([{timer, {MSec, StopOpts}}|O],{PI,Client,Traci}) ->
+ opt(O,{PI,Client,[{timer,{MSec, StopOpts}}|Traci]});
+opt([{timer, MSec}|O],{PI,Client,Traci}) ->
+ opt(O,{PI,Client,[{timer,{MSec, []}}|Traci]});
+opt([{overload_check, {MSec,M,F}}|O],{PI,Client,Traci}) ->
+ opt(O,{PI,Client,[{overload_check,{MSec,M,F}}|Traci]});
+opt([shell|O],{PI,Client,Traci}) ->
+ opt(O,{PI,Client,[{shell, true}|Traci]});
+opt([{shell,Type}|O],{PI,Client,Traci}) ->
+ opt(O,{PI,Client,[{shell, Type}|Traci]});
+opt([resume|O],{PI,Client,Traci}) ->
+ opt(O,{PI,Client,[{resume, {true, ?fetch_time}}|Traci]});
+opt([{resume,MSec}|O],{PI,Client,Traci}) ->
+ opt(O,{PI,Client,[{resume, {true, MSec}}|Traci]});
+opt([{flush,MSec}|O],{PI,Client,Traci}) ->
+ opt(O,{PI,Client,[{flush, MSec}|Traci]});
opt([],Opt) ->
- Opt.
+ ensure_opt(Opt).
+
+ensure_opt({PI,Client,Traci}) ->
+ case {proplists:get_value(flush, Traci), Client} of
+ {undefined, _} -> ok;
+ {_, {local, _}} -> exit(flush_unsupported_with_ip_trace_port);
+ {_,_} -> ok
+ end,
+ NeedIpTracer = proplists:get_value(shell, Traci, false) /= false,
+ case {NeedIpTracer, Client} of
+ {false, _} -> {PI, Client, Traci};
+ {true, ?MODULE} -> {PI, {local, ?MODULE}, Traci};
+ {true, {local, File}} -> {PI, {local, File}, Traci};
+ {true, _} -> exit(local_client_required_on_shell_tracing)
+ end.
+
+get_logname({local, F}) -> get_logname(F);
+get_logname({wrap, F}) -> filename:basename(F);
+get_logname({wrap, F, _, _}) -> filename:basename(F);
+get_logname(F) -> filename:basename(F).
nods(all) ->
Nodes1 = remove_active([node()|nodes()]),
@@ -205,17 +263,29 @@ run_history([H|T]) ->
ok -> run_history(T);
{error,not_found} -> {error,{not_found,H}}
end;
+
+run_history(all) ->
+ CurrentHist = ets:tab2list(?history_table),
+ ets:delete_all_objects(?history_table),
+ [run_printed(MFA,true) || {_, MFA} <- CurrentHist];
+run_history(all_silent) ->
+ CurrentHist = ets:tab2list(?history_table),
+ ets:delete_all_objects(?history_table),
+ [run_printed(MFA,false) || {_, MFA} <- CurrentHist];
run_history([]) ->
ok;
run_history(N) ->
case catch ets:lookup(?history_table,N) of
[{N,{M,F,A}}] ->
- print_func(M,F,A),
- R = apply(M,F,A),
- print_result(R);
+ run_printed({M,F,A},true);
_ ->
{error, not_found}
end.
+
+run_printed({M,F,A},Verbose) ->
+ Verbose andalso print_func(M,F,A),
+ R = apply(M,F,A),
+ Verbose andalso print_result(R).
write_config(ConfigFile,all) ->
write_config(ConfigFile,['_']);
@@ -223,6 +293,8 @@ write_config(ConfigFile,Config) ->
write_config(ConfigFile,Config,[]).
write_config(ConfigFile,all,Opt) ->
write_config(ConfigFile,['_'],Opt);
+write_config(ConfigFile,Config,Opt) when not(is_list(Opt)) ->
+ write_config(ConfigFile,Config,[Opt]);
write_config(ConfigFile,Nums,Opt) when is_list(Nums), is_integer(hd(Nums));
Nums=:=['_'] ->
F = fun(N) -> ets:select(?history_table,
@@ -313,6 +385,7 @@ arg_list([A1|A],Acc) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Set trace flags on processes
p(Procs0,Flags0) ->
+ ensure_no_overloaded_nodes(),
store(p,[Procs0,Flags0]),
no_store_p(Procs0,Flags0).
no_store_p(Procs0,Flags0) ->
@@ -327,11 +400,12 @@ no_store_p(Procs0,Flags0) ->
{error,Reason} ->
display_warning(P,Reason),
{PMatched,Ps}
- end
+ end
end,{[],[]},Procs) of
{[],[]} -> {error, no_match};
{SuccMatched,Succ} ->
no_store_write_trace_info(flags,{Succ,Flags}),
+ ?MODULE ! trace_started,
{ok,SuccMatched}
end
end.
@@ -339,7 +413,7 @@ no_store_p(Procs0,Flags0) ->
transform_flags([clear]) ->
[clear];
transform_flags(Flags) ->
- dbg:transform_flags(Flags).
+ dbg:transform_flags([timestamp | Flags]).
procs(Procs) when is_list(Procs) ->
@@ -365,24 +439,30 @@ proc({global,Name}) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Trace pattern
tp(A,B) ->
- store(tp,[A,B]),
- dbg:tp(A,B).
+ ensure_no_overloaded_nodes(),
+ store(tp,[A,ms(B)]),
+ dbg:tp(A,ms(B)).
tp(A,B,C) ->
- store(tp,[A,B,C]),
- dbg:tp(A,B,C).
+ ensure_no_overloaded_nodes(),
+ store(tp,[A,B,ms(C)]),
+ dbg:tp(A,B,ms(C)).
tp(A,B,C,D) ->
- store(tp,[A,B,C,D]),
- dbg:tp(A,B,C,D).
+ ensure_no_overloaded_nodes(),
+ store(tp,[A,B,C,ms(D)]),
+ dbg:tp(A,B,C,ms(D)).
tpl(A,B) ->
- store(tpl,[A,B]),
- dbg:tpl(A,B).
+ ensure_no_overloaded_nodes(),
+ store(tpl,[A,ms(B)]),
+ dbg:tpl(A,ms(B)).
tpl(A,B,C) ->
- store(tpl,[A,B,C]),
- dbg:tpl(A,B,C).
+ ensure_no_overloaded_nodes(),
+ store(tpl,[A,B,ms(C)]),
+ dbg:tpl(A,B,ms(C)).
tpl(A,B,C,D) ->
- store(tpl,[A,B,C,D]),
- dbg:tpl(A,B,C,D).
+ ensure_no_overloaded_nodes(),
+ store(tpl,[A,B,C,ms(D)]),
+ dbg:tpl(A,B,C,ms(D)).
ctp() ->
store(ctp,[]),
@@ -423,6 +503,56 @@ ctpg(A,B,C) ->
store(ctpg,[A,B,C]),
dbg:ctpg(A,B,C).
+ms(return) ->
+ [{'_',[],[{return_trace}]}];
+ms(caller) ->
+ [{'_',[],[{message,{caller}}]}];
+ms({codestr, FunStr}) ->
+ {ok, MS} = string2ms(FunStr),
+ MS;
+ms(Other) ->
+ Other.
+
+ensure_no_overloaded_nodes() ->
+ Overloaded = case whereis(?MODULE) of
+ undefined ->
+ [];
+ _ ->
+ ?MODULE ! {get_overloaded, self()},
+ receive {overloaded,O} -> O end
+ end,
+ case Overloaded of
+ [] -> ok;
+ Overloaded -> exit({error, overload_protection_active, Overloaded})
+ end.
+
+-spec string2ms(string()) -> {ok, list()} | {error, fun_format}.
+string2ms(FunStr) ->
+ case erl_scan:string(fix_dot(FunStr)) of
+ {ok, Tokens, _} ->
+ case erl_parse:parse_exprs(Tokens) of
+ {ok, [Expression]} ->
+ case Expression of
+ {_, _, {clauses, Clauses}} ->
+ {ok, ms_transform:transform_from_shell(dbg, Clauses, [])};
+ _ ->
+ {error, fun_format}
+ end;
+ _ ->
+ {error, fun_format}
+ end;
+ _ ->{error, fun_format}
+ end.
+
+-spec fix_dot(string()) -> string().
+fix_dot(FunStr) ->
+ [H | Rest] = lists:reverse(FunStr),
+ case H of
+ $. ->
+ FunStr;
+ H ->
+ lists:reverse([$., H | Rest])
+ end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Support for sequential trace
@@ -457,66 +587,114 @@ no_store_write_trace_info(Key,What) ->
%%% Stop tracing on all nodes
stop() ->
stop([]).
-stop(Opts) ->
+stop(Opts) when is_list(Opts) ->
Fetch = stop_opts(Opts),
- case whereis(?MODULE) of
- undefined -> ok;
- Pid when is_pid(Pid) ->
- ?MODULE ! {stop,Fetch,self()},
- receive {?MODULE,stopped} -> ok end
+ Result =
+ case whereis(?MODULE) of
+ undefined -> ok;
+ Pid when is_pid(Pid) ->
+ ?MODULE ! {stop,Fetch,self()},
+ receive {?MODULE,R} -> R end
+ end,
+ case {Fetch, Result} of
+ {nofetch, _} ->
+ ok;
+ {_, {stopped, _}} ->
+ %% Printout moved out of the ttb loop to avoid occasional deadlock
+ io:format("Stored logs in ~s~n", [element(2, Result)]);
+ {_, _} ->
+ ok
end,
- stopped.
+ stop_return(Result,Opts);
+stop(Opts) ->
+ stop([Opts]).
stop_opts(Opts) ->
- case lists:member(format,Opts) of
- true ->
- format; % format implies fetch
- false ->
- case lists:member(fetch,Opts) of
- true -> fetch;
- false -> nofetch
- end
+ FetchDir = proplists:get_value(fetch_dir, Opts),
+ ensure_fetch_dir(FetchDir),
+ FormatData = case proplists:get_value(format, Opts) of
+ undefined -> false;
+ true -> {format, []};
+ FOpts -> {format, FOpts}
+ end,
+ case {FormatData, lists:member(return_fetch_dir, Opts)} of
+ {false, true} ->
+ {fetch, FetchDir}; % if we specify return_fetch_dir, the data should be fetched
+ {false, false} ->
+ case lists:member(nofetch,Opts) of
+ false -> {fetch, FetchDir};
+ true -> nofetch
+ end;
+ {FormatData, _} ->
+ {FormatData, FetchDir}
+ end.
+
+ensure_fetch_dir(undefined) -> ok;
+ensure_fetch_dir(Dir) ->
+ case filelib:is_file(Dir) of
+ true ->
+ throw({error, exists, Dir});
+ false ->
+ ok
+ end.
+
+stop_return(R,Opts) ->
+ case {lists:member(return_fetch_dir,Opts),R} of
+ {true,_} ->
+ R;
+ {false,{stopped,_}} ->
+ stopped;
+ {false,_} ->
+ %% Anything other than 'stopped' would not be bw compatible...
+ stopped
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Process implementation
-start() ->
+start(SessionInfo) ->
case whereis(?MODULE) of
undefined ->
Parent = self(),
- Pid = spawn(fun() -> init(Parent) end),
- receive {started,Pid} -> ok end;
+ Pid = spawn(fun() -> init(Parent, SessionInfo) end),
+ receive {started,Pid} -> ok end,
+ Pid;
Pid when is_pid(Pid) ->
- ok
+ Pid
end.
-
-init(Parent) ->
+init(Parent, SessionInfo) ->
register(?MODULE,self()),
ets:new(?history_table,[ordered_set,named_table,public]),
Parent ! {started,self()},
- loop(dict:new()).
+ NewSessionInfo = [{partials, 0}, {dead_nodes, []} | SessionInfo],
+ try_send_flush_tick(NewSessionInfo),
+ loop(dict:new(), NewSessionInfo).
-loop(NodeInfo) ->
+loop(NodeInfo, SessionInfo) ->
receive
{init_node,Node,MetaFile,PI,Traci} ->
erlang:monitor_node(Node,true),
- MetaPid =
+ {AbsoluteMetaFile, MetaPid} =
case rpc:call(Node,
observer_backend,
ttb_init_node,
[MetaFile,PI,Traci]) of
- {ok,MP} ->
- MP;
+ {ok,MF,MP} ->
+ {MF,MP};
{badrpc,nodedown} ->
%% We will get a nodedown message
- undefined
+ {MetaFile,undefined}
end,
- loop(dict:store(Node,{MetaFile,MetaPid},NodeInfo));
+ loop(dict:store(Node,{AbsoluteMetaFile,MetaPid},NodeInfo), SessionInfo);
+ {ip_to_file_trace_port,Port,Sender} ->
+ Ports = proplists:get_value(ip_to_file_trace_ports, SessionInfo, []),
+ NewSessionInfo = [{ip_to_file_trace_ports,[Port|Ports]}|SessionInfo],
+ Sender ! {?MODULE,ok},
+ loop(NodeInfo, NewSessionInfo);
{get_nodes,Sender} ->
Sender ! {?MODULE,dict:fetch_keys(NodeInfo)},
- loop(NodeInfo);
+ loop(NodeInfo, SessionInfo);
{write_trace_info,Key,What} ->
dict:fold(fun(Node,{_MetaFile,MetaPid},_) ->
rpc:call(Node,observer_backend,
@@ -524,55 +702,136 @@ loop(NodeInfo) ->
end,
ok,
NodeInfo),
- loop(NodeInfo);
+ loop(NodeInfo, SessionInfo);
{nodedown,Node} ->
- loop(dict:erase(Node,NodeInfo));
+ NewState = make_node_dead(Node, NodeInfo, SessionInfo),
+ loop(dict:erase(Node,NodeInfo), NewState);
+ {noderesumed,Node,Reporter} ->
+ {MetaFile, CurrentSuffix, NewState} = make_node_alive(Node, SessionInfo),
+ fetch_partial_result(Node, MetaFile, CurrentSuffix),
+ spawn(fun() -> resume_trace(Reporter) end),
+ loop(NodeInfo, NewState);
+ {timeout, StopOpts} ->
+ spawn(?MODULE, stop, [StopOpts]),
+ loop(NodeInfo, SessionInfo);
+ {node_overloaded, Node} ->
+ io:format("Overload check activated on node: ~p.~n", [Node]),
+ {Overloaded, SI} = {proplists:get_value(overloaded, SessionInfo, []),
+ lists:keydelete(overloaded, 1, SessionInfo)},
+ loop(NodeInfo, [{overloaded, [Node|Overloaded]} | SI]);
+ {get_overloaded, Pid} ->
+ Pid ! {overloaded,proplists:get_value(overloaded, SessionInfo, [])},
+ loop(NodeInfo, SessionInfo);
+ trace_started ->
+ case proplists:get_value(timer, SessionInfo) of
+ undefined -> ok;
+ {MSec, StopOpts} -> erlang:send_after(MSec, self(), {timeout, StopOpts})
+ end,
+ loop(NodeInfo, SessionInfo);
+ flush_timeout ->
+ [ dbg:flush_trace_port(Node) || Node <- dict:fetch_keys(NodeInfo) ],
+ try_send_flush_tick(SessionInfo),
+ loop(NodeInfo, SessionInfo);
{stop,nofetch,Sender} ->
- dict:fold(
- fun(Node,{_,MetaPid},_) ->
- rpc:call(Node,observer_backend,ttb_stop,[MetaPid])
- end,
- ok,
- NodeInfo),
- dbg:stop_clear(),
- ets:delete(?history_table),
- Sender ! {?MODULE,stopped};
- {stop,FetchOrFormat,Sender} ->
- Localhost = host(node()),
- Dir = ?upload_dir++ts(),
- file:make_dir(Dir),
- %% The nodes are traversed twice here because
- %% the meta tracing in observer_backend must be
- %% stopped before dbg is stopped, and dbg must
- %% be stopped before the trace logs are moved orelse
- %% windows complains.
- AllNodesAndMeta =
- dict:fold(
- fun(Node,{MetaFile,MetaPid},Nodes) ->
- rpc:call(Node,observer_backend,ttb_stop,[MetaPid]),
- [{Node,MetaFile}|Nodes]
- end,
- [],
- NodeInfo),
- dbg:stop_clear(),
- AllNodes =
- lists:map(
- fun({Node,MetaFile}) ->
- spawn(fun() -> fetch(Localhost,Dir,Node,MetaFile) end),
- Node
+ do_stop(nofetch, Sender, NodeInfo, SessionInfo);
+ {stop,FetchSpec,Sender} ->
+ case proplists:get_value(shell, SessionInfo, false) of
+ only -> do_stop(nofetch, Sender, NodeInfo, SessionInfo);
+ _ -> do_stop(FetchSpec, Sender, NodeInfo, SessionInfo)
+ end
+ end.
+
+do_stop(nofetch, Sender, NodeInfo, SessionInfo) ->
+ write_config(?last_config, all),
+ dict:fold(
+ fun(Node,{_,MetaPid},_) ->
+ rpc:call(Node,observer_backend,ttb_stop,[MetaPid])
+ end,
+ ok,
+ NodeInfo),
+ stop_ip_to_file_trace_ports(SessionInfo),
+ dbg:stop_clear(),
+ ets:delete(?history_table),
+ Sender ! {?MODULE, stopped};
+
+do_stop({FetchOrFormat, UserDir}, Sender, NodeInfo, SessionInfo) ->
+ write_config(?last_config, all),
+ Localhost = host(node()),
+ Dir = get_fetch_dir(UserDir, proplists:get_value(logfile, SessionInfo)),
+ file:make_dir(Dir),
+ %% The nodes are traversed twice here because
+ %% the meta tracing in observer_backend must be
+ %% stopped before dbg is stopped, and dbg must
+ %% be stopped before the trace logs are moved orelse
+ %% windows complains.
+ AllNodesAndMeta =
+ dict:fold(
+ fun(Node,{MetaFile,MetaPid},Nodes) ->
+ rpc:call(Node,observer_backend,ttb_stop,[MetaPid]),
+ [{Node,MetaFile}|Nodes]
+ end,
+ [],
+ NodeInfo),
+ stop_ip_to_file_trace_ports(SessionInfo),
+ dbg:stop_clear(),
+ AllNodes =
+ lists:map(
+ fun({Node,MetaFile}) ->
+ spawn(fun() -> fetch_report(Localhost,Dir,Node,MetaFile) end),
+ Node
+ end,
+ AllNodesAndMeta),
+ ets:delete(?history_table),
+ wait_for_fetch(AllNodes),
+ copy_partials(Dir, proplists:get_value(partials, SessionInfo)),
+ Absname = filename:absname(Dir),
+ case FetchOrFormat of
+ fetch -> ok;
+ {format, Opts} -> format(Dir, Opts)
+ end,
+ Sender ! {?MODULE,{stopped,Absname}}.
+
+stop_ip_to_file_trace_ports(SessionInfo) ->
+ lists:foreach(fun(Port) ->
+ case lists:member(Port,erlang:ports()) of
+ true ->
+ dbg:deliver_and_flush(Port),
+ erlang:port_close(Port);
+ false ->
+ ok
+ end
end,
- AllNodesAndMeta),
- ets:delete(?history_table),
- wait_for_fetch(AllNodes),
- io:format("Stored logs in ~s~n",[filename:absname(Dir)]),
- case FetchOrFormat of
- format -> format(Dir);
- fetch -> ok
- end,
- Sender ! {?MODULE,stopped}
- ?get_status
+ proplists:get_value(ip_to_file_trace_ports,SessionInfo,[])).
+
+
+make_node_dead(Node, NodeInfo, SessionInfo) ->
+ {MetaFile,_} = dict:fetch(Node, NodeInfo),
+ NewDeadNodes = [{Node, MetaFile} | proplists:get_value(dead_nodes, SessionInfo)],
+ [{dead_nodes, NewDeadNodes} | lists:keydelete(dead_nodes, 1, SessionInfo)].
+
+make_node_alive(Node, SessionInfo) ->
+ DeadNodes = proplists:get_value(dead_nodes, SessionInfo),
+ Partials = proplists:get_value(partials, SessionInfo),
+ {value, {_, MetaFile}, Dn2} = lists:keytake(Node, 1, DeadNodes),
+ SessionInfo2 = lists:keyreplace(dead_nodes, 1, SessionInfo, {dead_nodes, Dn2}),
+ {MetaFile, Partials + 1, lists:keyreplace(partials, 1, SessionInfo2, {partials, Partials + 1})}.
+
+try_send_flush_tick(State) ->
+ case proplists:get_value(flush, State) of
+ undefined ->
+ ok;
+ MSec ->
+ erlang:send_after(MSec, self(), flush_timeout)
end.
+get_fetch_dir(undefined,undefined) -> ?upload_dir(?MODULE_STRING) ++ ts();
+get_fetch_dir(undefined,Logname) -> ?upload_dir(Logname) ++ ts();
+get_fetch_dir(Dir,_) -> Dir.
+
+resume_trace(Reporter) ->
+ ?MODULE:run_history(all_silent),
+ Reporter ! trace_resumed.
+
get_nodes() ->
?MODULE ! {get_nodes,self()},
receive {?MODULE,Nodes} -> Nodes end.
@@ -582,19 +841,40 @@ ts() ->
io_lib:format("-~4.4.0w~2.2.0w~2.2.0w-~2.2.0w~2.2.0w~2.2.0w",
[Y,M,D,H,Min,S]).
+copy_partials(_, 0) ->
+ ok;
+copy_partials(Dir, Num) ->
+ PartialDir = ?partial_dir ++ integer_to_list(Num),
+ file:rename(PartialDir, filename:join(Dir,PartialDir)),
+ copy_partials(Dir, Num - 1).
+
+fetch_partial_result(Node,MetaFile,Current) ->
+ DirName = ?partial_dir ++ integer_to_list(Current),
+ case file:list_dir(DirName) of
+ {error, enoent} ->
+ ok;
+ {ok, Files} ->
+ [ file:delete(filename:join(DirName, File)) || File <- Files ],
+ file:del_dir(DirName)
+ end,
+ file:make_dir(DirName),
+ fetch(host(node()), DirName, Node, MetaFile).
+fetch_report(Localhost, Dir, Node, MetaFile) ->
+ fetch(Localhost,Dir,Node,MetaFile),
+ ?MODULE ! {fetch_complete,Node}.
fetch(Localhost,Dir,Node,MetaFile) ->
- case host(Node) of
- Localhost -> % same host, just move the files
- Files = rpc:call(Node,observer_backend,ttb_get_filenames,[MetaFile]),
+ case (host(Node) == Localhost) orelse is_local(MetaFile) of
+ true -> % same host, just move the files
+ Files = get_filenames(Node,MetaFile),
lists:foreach(
- fun(File0) ->
- File = filename:join(Dir,filename:basename(File0)),
- file:rename(File0,File)
- end,
- Files);
- _Otherhost ->
+ fun(File0) ->
+ Dest = filename:join(Dir,filename:basename(File0)),
+ file:rename(File0, Dest)
+ end,
+ Files);
+ false ->
{ok, LSock} = gen_tcp:listen(0, [binary,{packet,2},{active,false}]),
{ok,Port} = inet:port(LSock),
rpc:cast(Node,observer_backend,ttb_fetch,
@@ -603,8 +883,17 @@ fetch(Localhost,Dir,Node,MetaFile) ->
receive_files(Dir,Sock,undefined),
ok = gen_tcp:close(LSock),
ok = gen_tcp:close(Sock)
- end,
- ?MODULE ! {fetch_complete,Node}.
+ end.
+
+is_local({local, _, _}) ->
+ true;
+is_local(_) ->
+ false.
+
+get_filenames(_N, {local,F,_}) ->
+ observer_backend:ttb_get_filenames(F);
+get_filenames(N, F) ->
+ rpc:call(N, observer_backend,ttb_get_filenames,[F]).
receive_files(Dir,Sock,Fd) ->
case gen_tcp:recv(Sock, 0) of
@@ -646,9 +935,16 @@ wait_for_fetch(Nodes) ->
%%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
write_info(Nodes,PI,Traci) ->
- lists:foreach(fun({N,{local,C,_},F}) ->
- MetaFile = F ++ ".ti",
- file:delete(MetaFile),
+ {ok, Cwd} = file:get_cwd(),
+ lists:foreach(fun({N,{local,C,_},F}) ->
+ MetaFile = case F of
+ none ->
+ none;
+ F ->
+ AbsFile = filename:join(Cwd, F) ++ ".ti",
+ file:delete(AbsFile),
+ AbsFile
+ end,
Traci1 = [{node,N},{file,C}|Traci],
{ok,Port} = dbg:get_tracer(N),
?MODULE !
@@ -662,38 +958,35 @@ write_info(Nodes,PI,Traci) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Format binary trace logs
+get_et_handler() ->
+ {fun ttb_et:handler/4, initial}.
+
format(Files) ->
format(Files,[]).
format(Files,Opt) ->
- {Out,Handler} = format_opt(Opt),
+ {Out,Handler,DisableSort} = format_opt(Opt),
ets:new(?MODULE,[named_table]),
- format(Files,Out,Handler).
-format(File,Out,Handler) when is_list(File), is_integer(hd(File)) ->
+ format(Files,Out,Handler, DisableSort).
+format(File,Out,Handler,DisableSort) when is_list(File), is_integer(hd(File)) ->
Files =
case filelib:is_dir(File) of
true -> % will merge all files in the directory
- MetaFiles = filelib:wildcard(filename:join(File,"*.ti")),
- lists:map(fun(M) ->
- Sub = string:left(M,length(M)-3),
- case filelib:is_file(Sub) of
- true -> Sub;
- false -> Sub++".*.wrp"
- end
- end,
- MetaFiles);
+ List = filelib:wildcard(filename:join(File, ?partial_dir++"*")),
+ lists:append(collect_files([File | List]));
false -> % format one file
[File]
end,
- format(Files,Out,Handler);
-format(Files,Out,Handler) when is_list(Files), is_list(hd(Files)) ->
+ format(Files,Out,Handler,DisableSort);
+format(Files,Out,Handler,DisableSort) when is_list(Files), is_list(hd(Files)) ->
StopDbg = case whereis(dbg) of
undefined -> true;
_ -> false
end,
- Details = lists:foldl(fun(File,Acc) -> [prepare(File,Handler)|Acc] end,
+ Details = lists:foldl(fun(File,Acc) -> [prepare(File)|Acc] end,
[],Files),
Fd = get_fd(Out),
- R = do_format(Fd,Details),
+ RealHandler = get_handler(Handler, Files),
+ R = do_format(Fd,Details,DisableSort,RealHandler),
file:close(Fd),
ets:delete(?MODULE),
case StopDbg of
@@ -702,7 +995,30 @@ format(Files,Out,Handler) when is_list(Files), is_list(hd(Files)) ->
end,
R.
-prepare(File,Handler) ->
+collect_files(Dirs) ->
+ lists:map(fun(Dir) ->
+ MetaFiles = filelib:wildcard(filename:join(Dir,"*.ti")),
+ lists:map(fun(M) ->
+ Sub = string:left(M,length(M)-3),
+ case filelib:is_file(Sub) of
+ true -> Sub;
+ false -> Sub++".*.wrp"
+ end
+ end,
+ MetaFiles)
+ end, Dirs).
+
+get_handler(undefined, Files) ->
+ %%We retrieve traci from the first available file
+ {Traci, _} = read_traci(hd(Files)),
+ case dict:find(handler, Traci) of
+ error -> {fun defaulthandler/4, initial};
+ {ok, [Handler]} -> Handler
+ end;
+get_handler(Handler, _) ->
+ Handler.
+
+prepare(File) ->
{Traci,Proci} = read_traci(File),
Node = get_node(Traci),
lists:foreach(fun({Pid,PI}) ->
@@ -714,19 +1030,21 @@ prepare(File,Handler) ->
ets:insert(?MODULE,{Pid,PI,Node})
end,Proci),
FileOrWrap = get_file(File,Traci),
- Handler1 = get_handler(Handler,Traci),
- {FileOrWrap,Traci,Handler1}.
+ {FileOrWrap,Traci}.
-format_opt(Opt) ->
+format_opt(Opt) when is_list(Opt) ->
Out = case lists:keysearch(out,1,Opt) of
{value,{out,O}} -> O;
_ -> standard_io
end,
Handler = case lists:keysearch(handler,1,Opt) of
- {value,{handler,H}} -> H;
- _ -> undefined
+ {value,{handler,H}} -> H;
+ _ -> undefined
end,
- {Out,Handler}.
+ DisableSort = proplists:get_value(disable_sort, Opt, false),
+ {Out,Handler,DisableSort};
+format_opt(Opt) ->
+ format_opt([Opt]).
read_traci(File) ->
@@ -800,75 +1118,61 @@ check_client(Client,File) when is_tuple(Client),element(2,Client)==wrap ->
check_exists(File) ->
case file:read_file_info(File) of
{ok,#file_info{type=regular}} -> File;
- _ ->
+ _ ->
exit({error,no_file})
end.
-
-get_handler(Handler,Traci) ->
- case Handler of
- undefined ->
- case dict:find(handler,Traci) of
- {ok,[H]} -> H;
- error -> undefined
- end;
- _ ->
- Handler
- end.
-do_format(Fd,Details) ->
- Clients = lists:foldl(fun({FileOrWrap,Traci,Handler},Acc) ->
- [start_client(FileOrWrap,Traci,Handler)
- |Acc]
+do_format(Fd,Details,DisableSort,Handler) ->
+ Clients = lists:foldl(fun({FileOrWrap,Traci},Acc) ->
+ [start_client(FileOrWrap,Traci)|Acc]
end,[],Details),
- init_collector(Fd,Clients).
-
-
-start_client(FileOrWrap,Traci,et) ->
- dbg:trace_client(file, FileOrWrap,
- {fun handler/2,
- {dict:to_list(Traci),{{ttb_et,handler},initial}}});
-start_client(FileOrWrap,Traci,undefined) ->
- dbg:trace_client(file, FileOrWrap,
- {fun handler/2,
- {dict:to_list(Traci),{fun defaulthandler/4,initial}}});
-start_client(FileOrWrap,Traci,Handler) ->
- dbg:trace_client(file, FileOrWrap,
- {fun handler/2, {dict:to_list(Traci),Handler}}).
-
-handler(Trace,State) ->
- %% State here is only used for the initial state. The accumulated
- %% State is maintained by collector!!!
- receive
- {get,Collector} -> Collector ! {self(),{Trace,State}};
+ init_collector(Fd,Clients,DisableSort,Handler).
+
+start_client(FileOrWrap,Traci) ->
+ dbg:trace_client(file, FileOrWrap,
+ {fun handler/2, dict:to_list(Traci)}).
+
+handler(Trace,Traci) ->
+ %%We return our own Traci so that it not necesarry to look it up
+ %%This may take time if something huge has been written to it
+ receive
+ {get,Collector} -> Collector ! {self(),{Trace,Traci}};
done -> ok
end,
- State.
+ Traci.
-handler1(Trace,{Fd,{Traci,{Fun,State}}}) when is_function(Fun) ->
- {Traci,{Fun,Fun(Fd,Trace,Traci,State)}};
-handler1(Trace,{Fd,{Traci,{{M,F},State}}}) when is_atom(M), is_atom(F) ->
- {Traci,{{M,F},M:F(Fd,Trace,Traci,State)}}.
+%%Used to handle common state (the same for all clients)
+handler2(Trace,{Fd,Traci,{Fun,State}}) when is_function(Fun) ->
+ {Fun, Fun(Fd, Trace, Traci, State)};
+handler2(Trace,{Fd,Traci,{{M,F},State}}) when is_atom(M), is_atom(F) ->
+ {{M,F}, M:F(Fd, Trace, Traci, State)}.
defaulthandler(Fd,Trace,_Traci,initial) ->
dbg:dhandler(Trace,Fd);
defaulthandler(_Fd,Trace,_Traci,State) ->
dbg:dhandler(Trace,State).
-init_collector(Fd,Clients) ->
+init_collector(Fd,Clients,DisableSort,Handler) ->
Collected = get_first(Clients),
- collector(Fd,sort(Collected)).
+ case DisableSort of
+ true -> collector(Fd,Collected, DisableSort, Handler);
+ false -> collector(Fd,sort(Collected), DisableSort, Handler)
+ end.
-collector(Fd,[{_,{Client,{Trace,State}}}|Rest]) ->
+collector(Fd,[{_,{Client,{Trace,Traci}}} |Rest], DisableSort, CommonState) ->
Trace1 = update_procinfo(Trace),
- State1 = handler1(Trace1,{Fd,State}),
- case get_next(Client,State1) of
- end_of_trace ->
- handler1(end_of_trace,{Fd,State1}),
- collector(Fd,Rest);
- Next -> collector(Fd,sort([Next|Rest]))
+ CommonState2 = handler2(Trace1, {Fd, Traci, CommonState}),
+ case get_next(Client) of
+ end_of_trace ->
+ collector(Fd,Rest,DisableSort, CommonState2);
+ Next -> case DisableSort of
+ false -> collector(Fd,sort([Next|Rest]), DisableSort, CommonState2);
+ true -> collector(Fd,[Next|Rest], DisableSort, CommonState2)
+ end
end;
-collector(_Fd,[]) ->
+collector(Fd,[], _, CommonState) ->
+ handler2(end_of_trace, {Fd, end_of_trace, CommonState}),
ok.
update_procinfo({drop,_N}=Trace) ->
@@ -895,7 +1199,7 @@ update_procinfo(Trace) ->
ProcInfo = get_procinfo(Pid),
setelement(2,Trace,ProcInfo).
-get_procinfo(Pid) when is_pid(Pid) ->
+get_procinfo(Pid) when is_pid(Pid); is_port(Pid) ->
case ets:lookup(?MODULE,Pid) of
[PI] -> PI;
[] -> Pid
@@ -913,21 +1217,21 @@ get_procinfo({Name,Node}) when is_atom(Name) ->
get_first([Client|Clients]) ->
Client ! {get,self()},
- receive
- {Client,{end_of_trace,_}} ->
+ receive
+ {Client,{end_of_trace,_}} ->
get_first(Clients);
- {Client,{Trace,_State}}=Next ->
+ {Client,{Trace,_}}=Next ->
[{timestamp(Trace),Next}|get_first(Clients)]
end;
get_first([]) -> [].
-get_next(Client,State) when is_pid(Client) ->
+get_next(Client) when is_pid(Client) ->
Client ! {get,self()},
- receive
- {Client,{end_of_trace,_}} ->
+ receive
+ {Client,{end_of_trace,_}} ->
end_of_trace;
- {Client,{Trace,_OldState}} ->
- {timestamp(Trace),{Client,{Trace,State}}} % inserting new state!!
+ {Client,{Trace, Traci}} ->
+ {timestamp(Trace),{Client,{Trace,Traci}}}
end.
sort(List) ->
@@ -971,19 +1275,37 @@ display_warning(Item,Warning) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Trace client which reads an IP port and puts data directly to a file.
%%% This is used when tracing remote nodes with no file system.
-ip_to_file(Trace,{file,File}) ->
+ip_to_file({metadata,_,_},{_, only} = State) ->
+ State;
+ip_to_file(Trace, {_, only} = State) ->
+ dbg:dhandler(Trace, standard_io),
+ State;
+ip_to_file(Trace,{{file,File}, ShellOutput}) ->
Fun = dbg:trace_port(file,File), %File can be a filename or a wrap spec
Port = Fun(),
- ip_to_file(Trace,Port);
-ip_to_file({metadata,MetaFile,MetaData},Port) ->
+ %% Store the port so it can be properly closed
+ ?MODULE ! {ip_to_file_trace_port, Port, self()},
+ receive {?MODULE,ok} -> ok end,
+ case Trace of
+ {metadata, _, _} -> ok;
+ Trace -> show_trace(Trace, ShellOutput)
+ end,
+ ip_to_file(Trace,{Port,ShellOutput});
+ip_to_file({metadata,MetaFile,MetaData},State) ->
{ok,MetaFd} = file:open(MetaFile,[write,raw,append]),
file:write(MetaFd,MetaData),
file:close(MetaFd),
- Port;
-ip_to_file(Trace,Port) ->
+ State;
+ip_to_file(Trace,{Port, ShellOutput}) ->
+ show_trace(Trace, ShellOutput),
B = term_to_binary(Trace),
erlang:port_command(Port,B),
- Port.
+ {Port, ShellOutput}.
+
+show_trace(Trace, true) ->
+ dbg:dhandler(Trace, standard_io);
+show_trace(_, _) ->
+ ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% For debugging
@@ -996,5 +1318,3 @@ dump_ti(<<>>,Acc) ->
dump_ti(B,Acc) ->
{Term,Rest} = get_term(B),
dump_ti(Rest,[Term|Acc]).
-
-
diff --git a/lib/observer/test/Makefile b/lib/observer/test/Makefile
index 6073e6ea00..bf99f07081 100644
--- a/lib/observer/test/Makefile
+++ b/lib/observer/test/Makefile
@@ -22,7 +22,10 @@ MODULES = \
observer_SUITE \
crashdump_viewer_SUITE \
etop_SUITE \
+ ttb_helper \
ttb_SUITE \
+ client \
+ server \
crashdump_helper
ERL_FILES= $(MODULES:%=%.erl)
diff --git a/lib/observer/test/client.erl b/lib/observer/test/client.erl
new file mode 100644
index 0000000000..90b72d3f8f
--- /dev/null
+++ b/lib/observer/test/client.erl
@@ -0,0 +1,28 @@
+-module(client).
+-compile(export_all).
+
+init(Node) ->
+ application:start(runtime_tools),
+ net_kernel:connect_node(Node).
+
+init() ->
+ init(server_node()).
+
+restart() ->
+ init:restart().
+
+server_node() ->
+ {ok,HostName} = inet:gethostname(),
+ list_to_atom("server@" ++ HostName).
+
+get() ->
+ erlang:send({server,server_node()}, {get,self()}),
+ receive Data -> Data
+ after 1000 -> no_reply
+ end.
+
+put(Thing) ->
+ erlang:send({server,server_node()}, {put,self(),Thing}),
+ receive ok -> timer:sleep(2), ok
+ after 1000 -> no_reply
+ end.
diff --git a/lib/observer/test/server.erl b/lib/observer/test/server.erl
new file mode 100644
index 0000000000..f6d3542c96
--- /dev/null
+++ b/lib/observer/test/server.erl
@@ -0,0 +1,44 @@
+-module(server).
+-compile(export_all).
+
+start() ->
+ application:start(runtime_tools),
+ Pid = spawn(?MODULE,loop,[[], 0]),
+ register(server,Pid).
+
+stop() ->
+ case lists:member(server, registered()) of
+ true ->
+ server ! stop;
+ false ->
+ ok
+ end.
+
+loop(Data, Num) ->
+ receive
+ {put,From,Ting} -> timer:sleep(2),
+ received(From,Ting),
+ From ! ok,
+ loop([Ting|Data], Num+1);
+ {get,From} -> From ! Data,
+ loop(Data, Num+1);
+ stop -> stopped;
+ clear -> loop([], Num+1);
+ {cnt, From} -> From ! Num,
+ loop(Data, Num)
+ end.
+
+counter() ->
+ server ! {cnt, self()},
+ receive
+ Num ->
+ Num
+ end.
+
+received(From, Thing) ->
+ case Thing of
+ never_send_this_atom ->
+ loop(Thing, 0);
+ _ ->
+ {return, 27, Thing, From}
+ end.
diff --git a/lib/observer/test/ttb_SUITE.erl b/lib/observer/test/ttb_SUITE.erl
index 24b4a22aa9..695d41b48a 100644
--- a/lib/observer/test/ttb_SUITE.erl
+++ b/lib/observer/test/ttb_SUITE.erl
@@ -1,7 +1,7 @@
-%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
+%%
+%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -33,12 +33,34 @@
-include_lib("test_server/include/test_server.hrl").
-define(default_timeout, ?t:minutes(1)).
+-define(OUTPUT, "handler_output").
+-define(FNAME, "temptest").
+-define(DIRNAME, "ddtemp").
-init_per_testcase(_Case, Config) ->
- ttb:stop(),
+init_per_testcase(Case, Config) ->
?line Dog=test_server:timetrap(?default_timeout),
+ ttb:stop(),
+ rm(?OUTPUT),
+ [rm(Upload) || Upload<-filelib:wildcard("ttb_upload*")],
+ rm(?DIRNAME),
+ [rm(At) || At <- filelib:wildcard("*@*")],
+ rm("ttb_last_config"),
+ %% Workaround for bug(?) in test_server - if the test case fails
+ %% with a timetrap timeout, then end_per_testcase will run with
+ %% faulty group_leader - which in turn makes test_server:stop_node
+ %% hang (stop_node is called by most of the cleanup functions).
+ %% Therefore we do the cleanup before each testcase instead - this
+ %% is obviously not 100% correct, but it will at least make sure
+ %% that the nodes which are to be started in a test case at are
+ %% terminated.
+ try apply(?MODULE,Case,[cleanup,Config])
+ catch error:undef -> ok
+ end,
[{watchdog, Dog}|Config].
-end_per_testcase(_Case, Config) ->
+end_per_testcase(Case, Config) ->
+ %% try apply(?MODULE,Case,[cleanup,Config])
+ %% catch error:undef -> ok
+ %% end,
Dog=?config(watchdog, Config),
?t:timetrap_cancel(Dog),
ok.
@@ -49,12 +71,31 @@ all() ->
[file, file_no_pi, file_fetch, wrap, wrap_merge,
wrap_merge_fetch_format, write_config1, write_config2,
write_config3, history, write_trace_info, seq_trace,
- diskless, otp_4967_1, otp_4967_2].
+ diskless, diskless_wrap, otp_4967_1, otp_4967_2,
+ fetch_when_no_option_given, basic_ttb_run_ip_port, basic_ttb_run_file_port,
+ return_fetch_dir_implies_fetch, logfile_name_in_fetch_dir, upload_to_my_logdir,
+ upload_to_my_existing_logdir, fetch_with_options_not_as_list,
+ error_when_formatting_multiple_files_4393, format_on_trace_stop,
+ trace_to_remote_files_on_localhost_with_different_pwd,
+ trace_to_local_files_on_localhost_with_different_pwd,
+ trace_to_remote_files_on_localhost_with_different_pwd_abs,
+ changing_cwd_on_control_node, changing_cwd_on_remote_node,
+ changing_cwd_on_control_node_with_local_trace,
+ one_command_trace_setup, dbg_style_fetch, shell_tracing_init,
+ only_one_state_for_format_handler, only_one_state_with_default_format_handler,
+ only_one_state_with_initial_format_handler, run_trace_with_shortcut1,
+ run_trace_with_shortcut2, run_trace_with_shortcut3, run_trace_with_shortcut4,
+ cant_specify_local_and_flush, trace_sorted_by_default,disable_sorting,
+ trace_resumed_after_node_restart, trace_resumed_after_node_restart_ip,
+ trace_resumed_after_node_restart_wrap,
+ trace_resumed_after_node_restart_wrap_mult
+].
groups() ->
[].
init_per_suite(Config) ->
+ clean_priv_dir(Config),
Config.
end_per_suite(_Config) ->
@@ -76,7 +117,7 @@ file(Config) when is_list(Config) ->
?line {ok,OtherNode} = ?t:start_node(node2,slave,[]),
?line c:nl(?MODULE),
?line S = self(),
- ?line Privdir=?config(priv_dir, Config),
+ ?line Privdir=priv_dir(Config),
?line File = filename:join(Privdir,"file"),
?line {ok,[Node]} =
ttb:tracer(Node,[{file, File},
@@ -92,18 +133,20 @@ file(Config) when is_list(Config) ->
?line {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop(),
- ?line ?t:stop_node(OtherNode),
+ ?line ttb:stop([nofetch]),
?line ok = ttb:format(filename:join(Privdir,atom_to_list(Node)++"-file")),
?line ok = ttb:format(filename:join(Privdir,
atom_to_list(OtherNode)++"-file")),
- ?line [{trace,{S,_,Node},call,{?MODULE,foo,[]}},
+ ?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace,
- {trace,{_,_,OtherNode},call,{?MODULE,foo,[]}},
+ {trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
ok.
+file(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
+
file_no_pi(suite) ->
[];
file_no_pi(doc) ->
@@ -113,7 +156,7 @@ file_no_pi(Config) when is_list(Config) ->
?line {ok,OtherNode} = ?t:start_node(node2,slave,[]),
?line c:nl(?MODULE),
?line S = self(),
- ?line Privdir=?config(priv_dir, Config),
+ ?line Privdir=priv_dir(Config),
?line File = filename:join(Privdir,"file"),
?line {ok,[_,_]} =
ttb:tracer([Node,OtherNode],[{file, File},
@@ -123,20 +166,23 @@ file_no_pi(Config) when is_list(Config) ->
?line {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop(),
- ?line ?t:stop_node(OtherNode),
+ ?line ttb:stop([nofetch]),
?line ok = ttb:format(filename:join(Privdir,atom_to_list(Node)++"-file")),
?line ok = ttb:format(filename:join(Privdir,
atom_to_list(OtherNode)++"-file")),
- ?line [{trace,LocalProc,call,{?MODULE,foo,[]}},
+ ?line [{trace_ts,LocalProc,call,{?MODULE,foo,[]}, {_,_,_}},
end_of_trace,
- {trace,RemoteProc,call,{?MODULE,foo,[]}},
+ {trace_ts,RemoteProc,call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
?line true = is_pid(LocalProc),
?line true = is_pid(RemoteProc),
ok.
+file_no_pi(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
+
+
file_fetch(suite) ->
[];
file_fetch(doc) ->
@@ -146,7 +192,7 @@ file_fetch(Config) when is_list(Config) ->
?line {ok,OtherNode} = ?t:start_node(node2,slave,[]),
?line c:nl(?MODULE),
?line S = self(),
- ?line Privdir=?config(priv_dir, Config),
+ ?line Privdir=priv_dir(Config),
?line ThisDir = filename:join(Privdir,this),
?line ok = file:make_dir(ThisDir),
?line OtherDir = filename:join(Privdir,other),
@@ -170,12 +216,11 @@ file_fetch(Config) when is_list(Config) ->
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
?line ?t:capture_start(),
- ?line ttb:stop([fetch]),
+ ?line ttb:stop([return_fetch_dir]),
?line ?t:capture_stop(),
?line [StoreString] = ?t:capture_get(),
?line UploadDir =
lists:last(string:tokens(lists:flatten(StoreString),"$ \n")),
- ?line ?t:stop_node(OtherNode),
%% check that files are no longer in original directories...
?line ok = check_gone(ThisDir,atom_to_list(Node)++"-file_fetch"),
@@ -194,14 +239,18 @@ file_fetch(Config) when is_list(Config) ->
?line ok = ttb:format(filename:join(UploadDir,
atom_to_list(OtherNode)++"-file_fetch")),
- ?line [{trace,{S,_,Node},call,{?MODULE,foo,[]}},
+ ?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace,
- {trace,{_,_,OtherNode},call,{?MODULE,foo,[]}},
+ {trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
?line ok = file:set_cwd(Cwd),
ok.
+file_fetch(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
+
+
wrap(suite) ->
[];
wrap(doc) ->
@@ -211,7 +260,7 @@ wrap(Config) when is_list(Config) ->
?line {ok,OtherNode} = ?t:start_node(node2,slave,[]),
?line c:nl(?MODULE),
?line S = self(),
- ?line Privdir=?config(priv_dir, Config),
+ ?line Privdir=priv_dir(Config),
?line File = filename:join(Privdir,"wrap"),
?line {ok,[_,_]} =
ttb:tracer([Node,OtherNode],[{file, {wrap,File,200,3}},
@@ -224,19 +273,18 @@ wrap(Config) when is_list(Config) ->
?line rpc:call(OtherNode,?MODULE,foo,[]),
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop(),
- ?line ?t:stop_node(OtherNode),
+ ?line ttb:stop([nofetch]),
?line ok = ttb:format(filename:join(Privdir,
atom_to_list(Node)++"-wrap.*.wrp")),
- ?line [{trace,{S,_,Node},call,{?MODULE,foo,[]}},
- {trace,{S,_,Node},call,{?MODULE,foo,[]}},
- {trace,{S,_,Node},call,{?MODULE,foo,[]}},
+ ?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
+ {trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
+ {trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
?line ok = ttb:format(filename:join(Privdir,
atom_to_list(OtherNode)++"-wrap.*.wrp")),
- ?line [{trace,{_,_,OtherNode},call,{?MODULE,foo,[]}},
- {trace,{_,_,OtherNode},call,{?MODULE,foo,[]}},
- {trace,{_,_,OtherNode},call,{?MODULE,foo,[]}},
+ ?line [{trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},
+ {trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},
+ {trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
%% Check that merge does not crash even if the timestamp flag is not on.
@@ -244,17 +292,19 @@ wrap(Config) when is_list(Config) ->
[filename:join(Privdir,
atom_to_list(Node)++"-wrap.*.wrp"),
filename:join(Privdir,
- atom_to_list(OtherNode)++"-wrap.*.wrp")]),
- ?line [{trace,{S,_,Node},call,{?MODULE,foo,[]}},
- {trace,{S,_,Node},call,{?MODULE,foo,[]}},
- {trace,{S,_,Node},call,{?MODULE,foo,[]}},
- end_of_trace,
- {trace,{_,_,OtherNode},call,{?MODULE,foo,[]}},
- {trace,{_,_,OtherNode},call,{?MODULE,foo,[]}},
- {trace,{_,_,OtherNode},call,{?MODULE,foo,[]}},
+ atom_to_list(OtherNode)++"-wrap.*.wrp")],[{disable_sort,true}]),
+ ?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
+ {trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
+ {trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
+ {trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},
+ {trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},
+ {trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
ok.
+wrap(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
+
wrap_merge(suite) ->
[];
wrap_merge(doc) ->
@@ -264,7 +314,7 @@ wrap_merge(Config) when is_list(Config) ->
?line {ok,OtherNode} = ?t:start_node(node2,slave,[]),
?line c:nl(?MODULE),
?line S = self(),
- ?line Privdir=?config(priv_dir, Config),
+ ?line Privdir=priv_dir(Config),
?line File = filename:join(Privdir,"wrap_merge"),
?line {ok,[_,_]} =
ttb:tracer([Node,OtherNode],[{file, {wrap,File,200,3}},
@@ -277,8 +327,7 @@ wrap_merge(Config) when is_list(Config) ->
?line rpc:call(OtherNode,?MODULE,foo,[]),
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop(),
- ?line ?t:stop_node(OtherNode),
+ ?line ttb:stop([nofetch]),
?line ok = ttb:format(
[filename:join(Privdir,
atom_to_list(Node)++"-wrap_merge.*.wrp"),
@@ -289,11 +338,13 @@ wrap_merge(Config) when is_list(Config) ->
{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},_},
{trace_ts,_,call,{?MODULE,foo,[]},_},
{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},_},
- end_of_trace,
{trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},_},
end_of_trace] = flush(),
ok.
+wrap_merge(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
+
wrap_merge_fetch_format(suite) ->
[];
@@ -304,7 +355,7 @@ wrap_merge_fetch_format(Config) when is_list(Config) ->
?line {ok,OtherNode} = ?t:start_node(node2,slave,[]),
?line c:nl(?MODULE),
?line S = self(),
- ?line Privdir=?config(priv_dir, Config),
+ ?line Privdir=priv_dir(Config),
?line File = filename:join(Privdir,"wrap_merge_fetch_format"),
%% I'm setting priv_dir as cwd, so ttb_upload directory is created there
@@ -324,19 +375,19 @@ wrap_merge_fetch_format(Config) when is_list(Config) ->
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
?line ttb:stop([format]),
- ?line ?t:stop_node(OtherNode),
?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},_},
{trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},_},
{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},_},
{trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},_},
{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},_},
- end_of_trace,
{trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},_},
end_of_trace] = flush(),
?line ok = file:set_cwd(Cwd),
ok.
+wrap_merge_fetch_format(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
write_config1(suite) ->
[];
@@ -348,7 +399,7 @@ write_config1(Config) when is_list(Config) ->
?line c:nl(?MODULE),
?line S = self(),
- ?line Privdir=?config(priv_dir, Config),
+ ?line Privdir=priv_dir(Config),
?line File = filename:join(Privdir,"write_config1"),
?line ok = ttb:write_config(File,
[{ttb,tracer,[[Node,OtherNode],
@@ -360,16 +411,14 @@ write_config1(Config) when is_list(Config) ->
?line ok = ttb:run_config(File),
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop(),
- ?line ?t:stop_node(OtherNode),
+ ?line ttb:stop([nofetch]),
?line ok = ttb:format(
[filename:join(Privdir,
atom_to_list(Node)++"-write_config1"),
filename:join(Privdir,
atom_to_list(OtherNode)++"-write_config1")]),
- ?line [{trace,{S,_,Node},call,{?MODULE,foo,[]}},
- end_of_trace,
- {trace,Other,call,{?MODULE,foo,[]}},
+ ?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
+ {trace_ts,Other,call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
case metatest(Other,OtherNode,Privdir,"-write_config1.ti") of
@@ -388,6 +437,10 @@ write_config1(Config) when is_list(Config) ->
end,
ok.
+
+write_config1(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
+
write_config2(suite) ->
[];
write_config2(doc) ->
@@ -397,7 +450,7 @@ write_config2(Config) when is_list(Config) ->
?line {ok,OtherNode} = ?t:start_node(node2,slave,[]),
?line c:nl(?MODULE),
?line S = self(),
- ?line Privdir=?config(priv_dir, Config),
+ ?line Privdir=priv_dir(Config),
?line File = filename:join(Privdir,"write_config2"),
?line {ok,[_,_]} =
ttb:tracer([Node,OtherNode],[{file, File},
@@ -410,16 +463,14 @@ write_config2(Config) when is_list(Config) ->
?line ok = ttb:run_config(File),
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop(),
- ?line ?t:stop_node(OtherNode),
+ ?line ttb:stop([nofetch]),
?line ok = ttb:format(
[filename:join(Privdir,
atom_to_list(Node)++"-write_config2"),
filename:join(Privdir,
atom_to_list(OtherNode)++"-write_config2")]),
- ?line [{trace,{S,_,Node},call,{?MODULE,foo,[]}},
- end_of_trace,
- {trace,Other,call,{?MODULE,foo,[]}},
+ ?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
+ {trace_ts,Other,call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
case metatest(Other,OtherNode,Privdir,"-write_config2.ti") of
@@ -438,6 +489,10 @@ write_config2(Config) when is_list(Config) ->
end,
ok.
+write_config2(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
+
+
write_config3(suite) ->
[];
write_config3(doc) ->
@@ -447,7 +502,7 @@ write_config3(Config) when is_list(Config) ->
?line {ok,OtherNode} = ?t:start_node(node2,slave,[]),
?line c:nl(?MODULE),
?line S = self(),
- ?line Privdir=?config(priv_dir, Config),
+ ?line Privdir=priv_dir(Config),
?line File = filename:join(Privdir,"write_config3"),
?line {ok,[_,_]} =
ttb:tracer([Node,OtherNode],[{file, File},
@@ -455,18 +510,18 @@ write_config3(Config) when is_list(Config) ->
?line {ok,[{all,[{matched,_,_},{matched,_,_}]}]} = ttb:p(all,call),
?line {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
?line ok = ttb:write_config(File,[1,2]),
- ?line ttb:stop(),
+ ?line ttb:stop([nofetch]),
?line [_,_] = ttb:list_config(File),
?line ok = ttb:run_config(File),
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop(),
+ ?line ttb:stop([nofetch]),
?line ok = ttb:format(
[filename:join(Privdir,
atom_to_list(Node)++"-write_config3"),
filename:join(Privdir,
atom_to_list(OtherNode)++"-write_config3")]),
- ?line [] = flush(), %foo is not traced
+ ?line [end_of_trace] = flush(), %foo is not traced
?line ok = ttb:write_config(File,[{ttb,tp,[?MODULE,foo,[]]}],
[append]),
@@ -474,16 +529,14 @@ write_config3(Config) when is_list(Config) ->
?line ok = ttb:run_config(File),
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop(),
- ?line ?t:stop_node(OtherNode),
+ ?line ttb:stop([nofetch]),
?line ok = ttb:format(
[filename:join(Privdir,
atom_to_list(Node)++"-write_config3"),
filename:join(Privdir,
atom_to_list(OtherNode)++"-write_config3")]),
- ?line [{trace,{S,_,Node},call,{?MODULE,foo,[]}},
- end_of_trace,
- {trace,Other,call,{?MODULE,foo,[]}},
+ ?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
+ {trace_ts,Other,call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
case metatest(Other,OtherNode,Privdir,"-write_config3.ti") of
@@ -502,6 +555,10 @@ write_config3(Config) when is_list(Config) ->
end,
ok.
+write_config3(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
+
+
history(suite) ->
[];
@@ -514,7 +571,7 @@ history(Config) when is_list(Config) ->
?line S = self(),
?line Nodes = [Node,OtherNode],
- ?line Privdir=?config(priv_dir, Config),
+ ?line Privdir=priv_dir(Config),
?line File = filename:join(Privdir,"history"),
?line StartOpts = [{file, File},
{handler,{fun myhandler/4, S}}],
@@ -531,15 +588,16 @@ history(Config) when is_list(Config) ->
?line ?MODULE:foo(),
?line ok = ttb:run_history([3,4]),
?line ?MODULE:foo(),
- ?line ttb:stop(),
- ?line ?t:stop_node(OtherNode),
+ ?line ttb:stop([nofetch]),
?line ok = ttb:format(
[filename:join(Privdir,atom_to_list(Node)++"-history"),
filename:join(Privdir,atom_to_list(OtherNode)++"-history")]),
- ?line [{trace,{S,_,Node},call,{?MODULE,foo,[]}},
+ ?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
ok.
-
+
+history(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
write_trace_info(suite) ->
@@ -551,7 +609,7 @@ write_trace_info(Config) when is_list(Config) ->
?line {ok,OtherNode} = ?t:start_node(node2,slave,[]),
?line c:nl(?MODULE),
?line S = self(),
- ?line Privdir=?config(priv_dir, Config),
+ ?line Privdir=priv_dir(Config),
?line File = filename:join(Privdir,"write_trace_info"),
?line {ok,[_,_]} =
ttb:tracer([Node,OtherNode],[{file, File},
@@ -561,20 +619,21 @@ write_trace_info(Config) when is_list(Config) ->
?line ok = ttb:write_trace_info(mytraceinfo,fun() -> node() end),
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop(),
- ?line ?t:stop_node(OtherNode),
+ ?line ttb:stop([nofetch]),
?line ok = ttb:format(
[filename:join(Privdir,atom_to_list(Node)++"-write_trace_info"),
filename:join(Privdir,
atom_to_list(OtherNode)++"-write_trace_info")],
[{handler,{fun otherhandler/4,S}}]),
- ?line [{{trace,{S,_,Node},call,{?MODULE,foo,[]}},[Node]},
- {end_of_trace,[Node]},
- {{trace,{_,_,OtherNode},call,{?MODULE,foo,[]}},[OtherNode]},
- {end_of_trace,[OtherNode]}] = flush(),
+ ?line [{{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},[Node]},
+ {{trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},[OtherNode]},
+ end_of_trace] = flush(),
ok.
+write_trace_info(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
+
seq_trace(suite) ->
[];
@@ -583,7 +642,7 @@ seq_trace(doc) ->
seq_trace(Config) when is_list(Config) ->
?line S = self(),
- ?line Privdir=?config(priv_dir, Config),
+ ?line Privdir=priv_dir(Config),
?line File = filename:join(Privdir,"seq_trace"),
?line {ok,[Node]} = ttb:tracer(node(),[{file,File},
{handler,{fun myhandler/4, S}}]),
@@ -593,10 +652,10 @@ seq_trace(Config) when is_list(Config) ->
?line Start = spawn(fun() -> seq() end),
?line timer:sleep(300),
- ?line ttb:stop(),
+ ?line ttb:stop([nofetch]),
?line ok = ttb:format(
[filename:join(Privdir,atom_to_list(Node)++"-seq_trace")]),
- ?line [{trace,StartProc,call,{?MODULE,seq,[]}},
+ ?line [{trace_ts,StartProc,call,{?MODULE,seq,[]},{_,_,_}},
{seq_trace,0,{send,{0,1},StartProc,P1Proc,{Start,P2}}},
{seq_trace,0,{send,{1,2},P1Proc,P2Proc,{P1,Start}}},
{seq_trace,0,{send,{2,3},P2Proc,StartProc,{P2,P1}}},
@@ -650,7 +709,7 @@ diskless(Config) when is_list(Config) ->
?line {ok,RemoteNode} = ?t:start_node(node2,slave,[]),
?line c:nl(?MODULE),
?line S = self(),
- ?line Privdir=?config(priv_dir, Config),
+ ?line Privdir=priv_dir(Config),
?line File = filename:join(Privdir,"diskless"),
?line {ok,[RemoteNode]} =
ttb:tracer([RemoteNode],[{file, {local, File}},
@@ -660,15 +719,45 @@ diskless(Config) when is_list(Config) ->
?line rpc:call(RemoteNode,?MODULE,foo,[]),
?line timer:sleep(500), % needed for the IP port to flush
- ?line ttb:stop(),
- ?line ?t:stop_node(RemoteNode),
+ ?line ttb:stop([nofetch]),
?line ok = ttb:format(filename:join(Privdir,
atom_to_list(RemoteNode)++"-diskless")),
- ?line [{trace,{_,_,RemoteNode},call,{?MODULE,foo,[]}},
+ ?line [{trace_ts,{_,_,RemoteNode},call,{?MODULE,foo,[]},{_,_,_}},
+ end_of_trace] = flush(),
+ ok.
+
+diskless(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
+
+diskless_wrap(suite) ->
+ [];
+diskless_wrap(doc) ->
+ ["Start tracing on diskless remote node, save to local wrapped file"];
+diskless_wrap(Config) when is_list(Config) ->
+ ?line {ok,RemoteNode} = ?t:start_node(node2,slave,[]),
+ ?line c:nl(?MODULE),
+ ?line S = self(),
+ ?line Privdir=priv_dir(Config),
+ ?line File = filename:join(Privdir,"diskless"),
+ ?line {ok,[RemoteNode]} =
+ ttb:tracer([RemoteNode],[{file, {local, {wrap,File,200,3}}},
+ {handler,{fun myhandler/4, S}}]),
+ ?line {ok,[{all,[{matched,RemoteNode,_}]}]} = ttb:p(all,call),
+ ?line {ok,[{matched,RemoteNode,1}]} = ttb:tp(?MODULE,foo,[]),
+
+ ?line rpc:call(RemoteNode,?MODULE,foo,[]),
+ ?line timer:sleep(500), % needed for the IP port to flush
+ ?line ttb:stop([nofetch]),
+ ?line ok = ttb:format(filename:join(Privdir,
+ atom_to_list(RemoteNode)++"-diskless.*.wrp")),
+
+ ?line [{trace_ts,{_,_,RemoteNode},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
ok.
+diskless_wrap(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
otp_4967_1(suite) ->
[];
@@ -688,7 +777,7 @@ otp_4967_2(doc) ->
["OTP-4967: Trace message sent to {Name, Node}"];
otp_4967_2(Config) when is_list(Config) ->
io:format("1: ~p",[now()]),
- ?line Privdir = ?config(priv_dir,Config),
+ ?line Privdir = priv_dir(Config),
io:format("2: ~p",[now()]),
?line File = filename:join(Privdir,"otp_4967"),
io:format("3: ~p",[now()]),
@@ -715,19 +804,41 @@ otp_4967_2(Config) when is_list(Config) ->
io:format("11: ~p",[now()]),
?line true = lists:member(heihopp,Msgs), % the heihopp message itself
io:format("13: ~p",[now()]),
- ?line {value,{trace,_,send,heihopp,{_,otp_4967,Node}}} =
+ ?line {value,{trace_ts,_,send,heihopp,{_,otp_4967,Node},{_,_,_}}} =
lists:keysearch(heihopp,4,Msgs), % trace trace of the heihopp message
io:format("14: ~p",[now()]),
?line end_of_trace = lists:last(Msgs), % end of the trace
ok.
-
-
myhandler(_Fd,Trace,_,Relay) ->
Relay ! Trace,
Relay.
+simple_call_handler() ->
+ {fun(A, {trace_ts, _, call, _, _} ,_,_) -> io:format(A, "ok.~n", []);
+ (_, end_of_trace, _, _) -> ok end, []}.
+
+marking_call_handler() ->
+ {fun(_, _, _, initial) -> file:write_file("HANDLER_OK", []);
+ (_,_,_,_) -> ok end, initial}.
+
+counter_call_handler() ->
+ {fun(_, {trace_ts, _, call, _, _} ,_,State) -> State + 1;
+ (A, end_of_trace, _, State) -> io:format(A,"~p.~n", [State]) end, 0}.
+
+ret_caller_call_handler() ->
+ {fun(A, {trace_ts, _, call, _, _, _} ,_,_) -> io:format(A, "ok.~n", []);
+ (A, {trace_ts, _, return_from, _, _, _}, _, _) -> io:format(A, "ok.~n", []);
+ (_, _, _, _) -> ok end, []}.
+
+node_call_handler() ->
+ {fun(A, {trace_ts, {_,_,Node}, call, _, _} ,_,_) -> io:format(A, "~p.~n", [Node]);
+ (_, end_of_trace, _, _) -> ok end, []}.
+
+otherhandler(_Fd,_,end_of_trace,Relay) ->
+ Relay ! end_of_trace,
+ Relay;
otherhandler(_Fd,Trace,TI,Relay) ->
{value,{mytraceinfo,I}} = lists:keysearch(mytraceinfo,1,TI),
Relay ! {Trace,I},
@@ -794,3 +905,630 @@ check_gone(Dir,File) ->
false ->
ok
end.
+
+start_client_and_server() ->
+ ?line {ok,ClientNode} = ?t:start_node(client,slave,[]),
+ ?line ok = ttb_helper:c(code, add_paths, [code:get_path()]),
+ ?line {ok,ServerNode} = ?t:start_node(server,slave,[]),
+ ?line ok = ttb_helper:s(code, add_paths, [code:get_path()]),
+ ?line ttb_helper:clear(),
+ {ServerNode, ClientNode}.
+
+stop_client_and_server() ->
+ ClientNode = ttb_helper:get_node(client),
+ ServerNode = ttb_helper:get_node(server),
+ erlang:monitor_node(ClientNode,true),
+ erlang:monitor_node(ServerNode,true),
+ ?line ?t:stop_node(ClientNode),
+ ?line ?t:stop_node(ServerNode),
+ wait_for_client_and_server_stop(ClientNode,ServerNode).
+
+wait_for_client_and_server_stop(undefined,undefined) ->
+ ok;
+wait_for_client_and_server_stop(ClientNode,ServerNode) ->
+ receive
+ {nodedown,ClientNode} ->
+ erlang:monitor_node(ClientNode,false),
+ wait_for_client_and_server_stop(undefined,ServerNode);
+ {nodedown,ServerNode} ->
+ erlang:monitor_node(ServerNode,false),
+ wait_for_client_and_server_stop(ClientNode,undefined)
+ end.
+
+begin_trace(ServerNode, ClientNode, Dest) ->
+ ?line {ok, _} =
+ ttb:tracer([ServerNode,ClientNode],[{file, Dest}]),
+ ?line ttb:p(all, call),
+ ?line ttb:tp(server, received, []),
+ ?line ttb:tp(client, put, []),
+ ?line ttb:tp(client, get, []).
+
+begin_trace_local(ServerNode, ClientNode, Dest) ->
+ ?line {ok, _} =
+ ttb:tracer([ServerNode,ClientNode],[{file, Dest}]),
+ ?line ttb:p(all, call),
+ ?line ttb:tpl(server, received, []),
+ ?line ttb:tpl(client, put, []),
+ ?line ttb:tpl(client, get, []).
+
+check_size(N, Dest, Output, ServerNode, ClientNode) ->
+ ?line begin_trace(ServerNode, ClientNode, Dest),
+ ?line case Dest of
+ {local, _} ->
+ ?line ttb_helper:msgs_ip(N);
+ _ ->
+ ?line ttb_helper:msgs(N)
+ end,
+ ?line {_, D} = ttb:stop([fetch, return_fetch_dir]),
+ ?line ttb:format(D, [{out, Output}, {handler, simple_call_handler()}]),
+ ?line {ok, Ret} = file:consult(Output),
+ ?line true = (N + 1 == length(Ret)).
+
+fetch_when_no_option_given(suite) ->
+ [];
+fetch_when_no_option_given(doc) ->
+ ["Fetch when no option given"];
+fetch_when_no_option_given(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line {ok, Privdir} = file:get_cwd(),
+ ?line [] = filelib:wildcard(filename:join(Privdir,"ttb_upload_temptest*")),
+ begin_trace(ServerNode, ClientNode, ?FNAME),
+ ?line ttb_helper:msgs(4),
+ ?line stopped = ttb:stop(),
+ ?line [_] = filelib:wildcard(filename:join(Privdir,"ttb_upload_temptest*")).
+
+fetch_when_no_option_given(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+
+basic_ttb_run_ip_port(suite) ->
+ [];
+basic_ttb_run_ip_port(doc) ->
+ ["Basic ttb run ip port"];
+basic_ttb_run_ip_port(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line check_size(1, {local, ?FNAME}, ?OUTPUT, ServerNode, ClientNode),
+ ?line check_size(2, {local, ?FNAME}, ?OUTPUT, ServerNode, ClientNode),
+ ?line check_size(10, {local, ?FNAME}, ?OUTPUT, ServerNode, ClientNode).
+basic_ttb_run_ip_port(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+basic_ttb_run_file_port(suite) ->
+ [];
+basic_ttb_run_file_port(doc) ->
+ ["Basic ttb run file port"];
+basic_ttb_run_file_port(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line check_size(1, ?FNAME, ?OUTPUT, ServerNode, ClientNode),
+ ?line check_size(2, ?FNAME, ?OUTPUT, ServerNode, ClientNode),
+ ?line check_size(10, ?FNAME, ?OUTPUT, ServerNode, ClientNode).
+basic_ttb_run_file_port(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+return_fetch_dir_implies_fetch(suite) ->
+ [];
+return_fetch_dir_implies_fetch(doc) ->
+ ["Return_fetch_dir implies fetch"];
+return_fetch_dir_implies_fetch(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace(ServerNode, ClientNode, ?FNAME),
+ ?line ttb_helper:msgs(2),
+ ?line {_,_} = ttb:stop([return_fetch_dir]).
+return_fetch_dir_implies_fetch(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+logfile_name_in_fetch_dir(suite) ->
+ [];
+logfile_name_in_fetch_dir(doc) ->
+ ["Logfile name in fetch dir"];
+logfile_name_in_fetch_dir(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace(ServerNode, ClientNode, {local, ?FNAME}),
+ ?line {_,Dir} = ttb:stop([return_fetch_dir]),
+ ?line P1 = lists:nth(3, string:tokens(filename:basename(Dir), "_")),
+ ?line P2 = hd(string:tokens(P1, "-")),
+ ?line _File = P2.
+logfile_name_in_fetch_dir(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+upload_to_my_logdir(suite) ->
+ [];
+upload_to_my_logdir(doc) ->
+ ["Upload to my logdir"];
+upload_to_my_logdir(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line {ok, _} =
+ ttb:tracer([ServerNode,ClientNode],[{file, ?FNAME}]),
+ ?line {stopped,_} = ttb:stop([return_fetch_dir, {fetch_dir, ?DIRNAME}]),
+ ?line true = filelib:is_file(?DIRNAME),
+ ?line [] = filelib:wildcard("ttb_upload_"++?FNAME).
+upload_to_my_logdir(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+upload_to_my_existing_logdir(suite) ->
+ [];
+upload_to_my_existing_logdir(doc) ->
+ ["Upload to my existing logdir"];
+upload_to_my_existing_logdir(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line ok = file:make_dir(?DIRNAME),
+ ?line {ok, _} =
+ ttb:tracer([ServerNode,ClientNode],[{file, ?FNAME}]),
+ ?line {error,_,_} = (catch ttb:stop([return_fetch_dir, {fetch_dir, ?DIRNAME}])),
+ ?line {stopped,_} = ttb:stop(return_fetch_dir).
+upload_to_my_existing_logdir(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+fetch_with_options_not_as_list(suite) ->
+ [];
+fetch_with_options_not_as_list(doc) ->
+ ["Fetch with options not as list"];
+fetch_with_options_not_as_list(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line {ok, _} =
+ ttb:tracer([ServerNode,ClientNode],[{file, ?FNAME}]),
+ ?line {stopped, D} = ttb:stop(return_fetch_dir),
+ ?line false = filelib:is_file(?OUTPUT),
+ ?line ttb:format(D, {out, ?OUTPUT}),
+ ?line true = filelib:is_file(?OUTPUT).
+fetch_with_options_not_as_list(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+error_when_formatting_multiple_files_4393(suite) ->
+ [];
+error_when_formatting_multiple_files_4393(doc) ->
+ ["Error when formatting multiple files"];
+error_when_formatting_multiple_files_4393(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace(ServerNode, ClientNode, ?FNAME),
+ ?line ttb_helper:msgs(2),
+ ?line {_, Dir} = ttb:stop(return_fetch_dir),
+ ?line Files = [filename:join(Dir, atom_to_list(ServerNode) ++ "-" ++ ?FNAME),
+ filename:join(Dir, atom_to_list(ClientNode) ++ "-" ++ ?FNAME)],
+ ?line ok = ttb:format(Files).
+error_when_formatting_multiple_files_4393(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+format_on_trace_stop(suite) ->
+ [];
+format_on_trace_stop(doc) ->
+ ["Format on trace stop"];
+format_on_trace_stop(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace(ServerNode, ClientNode, {local, ?FNAME}),
+ ?line ttb_helper:msgs_ip(2),
+ ?line file:delete("HANDLER_OK"),
+ ?line {_,_} = ttb:stop([fetch, return_fetch_dir, {format, {handler, marking_call_handler()}}]),
+ ?line true = filelib:is_file("HANDLER_OK"),
+ ?line ok = file:delete("HANDLER_OK").
+format_on_trace_stop(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+%% The following three tests are for the issue "fixes fetch fail when nodes on the same host
+%% have different cwd"
+trace_to_remote_files_on_localhost_with_different_pwd(suite) ->
+ [];
+trace_to_remote_files_on_localhost_with_different_pwd(doc) ->
+ ["Trace to remote files on localhost with different pwd"];
+trace_to_remote_files_on_localhost_with_different_pwd(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+ ?line ok = file:set_cwd(".."),
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line check_size(2, ?FNAME, ?OUTPUT, ServerNode, ClientNode),
+ ?line ok = file:set_cwd(OldDir).
+trace_to_remote_files_on_localhost_with_different_pwd(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+trace_to_local_files_on_localhost_with_different_pwd(suite) ->
+ [];
+trace_to_local_files_on_localhost_with_different_pwd(doc) ->
+ ["Trace to local files on localhost with different pwd"];
+trace_to_local_files_on_localhost_with_different_pwd(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+ ?line ok = file:set_cwd(".."),
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line check_size(2, {local, ?FNAME}, ?OUTPUT, ServerNode, ClientNode),
+ ?line ok = file:set_cwd(OldDir).
+trace_to_local_files_on_localhost_with_different_pwd(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+trace_to_remote_files_on_localhost_with_different_pwd_abs(suite) ->
+ [];
+trace_to_remote_files_on_localhost_with_different_pwd_abs(doc) ->
+ ["Trace to remote files on localhost with different pwd abs"];
+trace_to_remote_files_on_localhost_with_different_pwd_abs(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+ ?line ok = file:set_cwd(".."),
+ ?line {ok, Path} = file:get_cwd(),
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line File = filename:join(Path, ?FNAME),
+ ?line check_size(2, File, ?OUTPUT, ServerNode, ClientNode),
+ ?line ok = file:set_cwd(OldDir).
+trace_to_remote_files_on_localhost_with_different_pwd_abs(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+%% Trace is not affected by changes of cwd on control node or remote nodes during tracing
+%% (three tests)
+changing_cwd_on_control_node(suite) ->
+ [];
+changing_cwd_on_control_node(doc) ->
+ ["Changing cwd on control node during tracing is safe"];
+changing_cwd_on_control_node(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace(ServerNode, ClientNode, ?FNAME),
+ ?line NumMsgs = 3,
+ ?line ttb_helper:msgs(NumMsgs),
+ ?line ok = file:set_cwd(".."),
+ ?line ttb_helper:msgs(NumMsgs),
+ ?line {_, D} = ttb:stop([fetch, return_fetch_dir]),
+ ?line ttb:format(D, [{out, ?OUTPUT}, {handler, simple_call_handler()}]),
+ ?line {ok, Ret} = file:consult(?OUTPUT),
+ ?line true = (2*(NumMsgs + 1) == length(Ret)),
+ ?line ok = file:set_cwd(OldDir).
+changing_cwd_on_control_node(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+changing_cwd_on_control_node_with_local_trace(suite) ->
+ [];
+changing_cwd_on_control_node_with_local_trace(doc) ->
+ ["Changing cwd on control node during local tracing is safe"];
+changing_cwd_on_control_node_with_local_trace(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace(ServerNode, ClientNode, {local, ?FNAME}),
+ ?line NumMsgs = 3,
+ ?line ttb_helper:msgs_ip(NumMsgs),
+ ?line ok = file:set_cwd(".."),
+ ?line ttb_helper:msgs_ip(NumMsgs),
+ ?line {_, D} = ttb:stop([fetch, return_fetch_dir]),
+ ?line ttb:format(D, [{out, ?OUTPUT}, {handler, simple_call_handler()}]),
+ ?line {ok, Ret} = file:consult(?OUTPUT),
+ ?line true = (2*(NumMsgs + 1) == length(Ret)),
+ ?line ok = file:set_cwd(OldDir).
+changing_cwd_on_control_node_with_local_trace(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+changing_cwd_on_remote_node(suite) ->
+ [];
+changing_cwd_on_remote_node(doc) ->
+ ["Changing cwd on remote node during tracing is safe"];
+changing_cwd_on_remote_node(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace(ServerNode, ClientNode, ?FNAME),
+ ?line NumMsgs = 2,
+ ?line ttb_helper:msgs(NumMsgs),
+ ?line ok = rpc:call(ClientNode, file, set_cwd, [".."]),
+ ?line ttb_helper:msgs(NumMsgs),
+ ?line {_, D} = ttb:stop([fetch, return_fetch_dir]),
+ ?line ttb:format(D, [{out, ?OUTPUT}, {handler, simple_call_handler()}]),
+ ?line {ok, Ret} = file:consult(?OUTPUT),
+ ?line true = (2*(NumMsgs + 1) == length(Ret)).
+changing_cwd_on_remote_node(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+one_command_trace_setup(suite) ->
+ [];
+one_command_trace_setup(doc) ->
+ ["One command trace setup"];
+one_command_trace_setup(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line ttb:start_trace([ClientNode, ServerNode],
+ [{server, received, '_', []},
+ {client, put, 1, []},
+ {client, get, '_', []}],
+ {all, call},
+ [{file, ?FNAME}]),
+ ?line ttb_helper:msgs(2),
+ ?line {_, D} = ttb:stop(return_fetch_dir),
+ ?line ttb:format(D, [{out, ?OUTPUT}, {handler, simple_call_handler()}]),
+ ?line {ok, Ret} = file:consult(?OUTPUT),
+ ?line 5 = length(Ret).
+one_command_trace_setup(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+dbg_style_fetch(suite) ->
+ [];
+dbg_style_fetch(doc) ->
+ ["Dbg style fetch"];
+dbg_style_fetch(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line DirSize = length(element(2, file:list_dir("."))),
+ ?line ttb:start_trace([ClientNode, ServerNode],
+ [{server, received, '_', []},
+ {client, put, 1, []},
+ {client, get, '_', []}],
+ {all, call},
+ [{shell, only}]),
+ ?line DirSize = length(element(2, file:list_dir("."))),
+ ?line ttb_helper:msgs(2),
+ ?line DirSize = length(element(2, file:list_dir("."))),
+ ?line stopped, ttb:stop(format),
+ %%+1 -> ttb_last_trace
+ ?line true = (DirSize + 1 == length(element(2, file:list_dir(".")))),
+ ?line {ok,[{all, [{matched,_,_}, {matched,_,_}]}]} =
+ ttb:start_trace([ClientNode, ServerNode],
+ [{server, received, '_', []},
+ {client, put, 1, []},
+ {client, get, '_', []}],
+ {all, call},
+ [{shell, only}]),
+ ?line ttb:stop().
+dbg_style_fetch(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+shell_tracing_init(suite) ->
+ [];
+shell_tracing_init(doc) ->
+ ["Shell tracing init"];
+shell_tracing_init(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line ttb:tracer([ClientNode, ServerNode], shell),
+ ?line ttb:stop(),
+ ?line ttb:tracer([ClientNode, ServerNode],
+ [{file, {local, ?FNAME}}, shell]),
+ ?line ttb:stop(),
+ ?line local_client_required_on_shell_tracing =
+ try ttb:tracer([ClientNode, ServerNode],[{file, ?FNAME}, shell])
+ catch
+ exit:local_client_required_on_shell_tracing ->
+ local_client_required_on_shell_tracing
+ end.
+shell_tracing_init(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+only_one_state_for_format_handler(suite) ->
+ [];
+only_one_state_for_format_handler(doc) ->
+ ["Only one state for format handler"];
+only_one_state_for_format_handler(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace_local(ServerNode, ClientNode, ?FNAME),
+ ?line ttb_helper:msgs(2),
+ ?line {_, D} = ttb:stop([return_fetch_dir]),
+ ?line ttb:format(D, [{out, ?OUTPUT}, {handler, counter_call_handler()}]),
+ ?line {ok, Ret} = file:consult(?OUTPUT),
+ ?line [5] = Ret.
+only_one_state_for_format_handler(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+only_one_state_with_default_format_handler(suite) ->
+ [];
+only_one_state_with_default_format_handler(doc) ->
+ ["Only one state with default format handler"];
+only_one_state_with_default_format_handler(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace_local(ServerNode, ClientNode, ?FNAME),
+ ?line ttb_helper:msgs(2),
+ ?line {_, D} = ttb:stop([return_fetch_dir]),
+ ?line ttb:format(D, [{out, ?OUTPUT}]),
+ ?line true = filelib:is_file(?OUTPUT).
+only_one_state_with_default_format_handler(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+only_one_state_with_initial_format_handler(suite) ->
+ [];
+only_one_state_with_initial_format_handler(doc) ->
+ ["Only one state with initial format handler"];
+only_one_state_with_initial_format_handler(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line {ok, _} =
+ ttb:tracer([ServerNode,ClientNode],[{file, ?FNAME}, {handler, counter_call_handler()}]),
+ ?line ttb:p(all, call),
+ ?line ttb:tpl(server, received, []),
+ ?line ttb:tpl(client, put, []),
+ ?line ttb:tpl(client, get, []),
+ ?line ttb_helper:msgs(2),
+ ?line {_, D} = ttb:stop([return_fetch_dir]),
+ ?line ttb:format(D, [{out, ?OUTPUT}]),
+ ?line {ok, Ret} = file:consult(?OUTPUT),
+ ?line [5] = Ret.
+only_one_state_with_initial_format_handler(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+run_trace_with_shortcut(Shortcut, Ret, F) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line {ok, _} =
+ ttb:tracer([ServerNode,ClientNode],[{file, ?FNAME}]),
+ ?line ttb:p(all, call),
+ ?line ttb:F(client, put, Shortcut),
+ ?line ttb_helper:msgs(2),
+ ?line {_, D} = ttb:stop([return_fetch_dir]),
+ ?line ttb:format(D, [{out, ?OUTPUT}, {handler, ret_caller_call_handler()}]),
+ ?line {ok, Ret} =file:consult(?OUTPUT),
+ ?line stop_client_and_server().
+
+fun_for(return) ->
+ {codestr, "fun(_) -> return_trace() end"};
+fun_for(msg_false) ->
+ {codestr, "fun(_) -> message(false) end"}.
+
+run_trace_with_shortcut1(suite) ->
+ [];
+run_trace_with_shortcut1(doc) ->
+ ["Run trace with shortcut 1"];
+run_trace_with_shortcut1(Config) when is_list(Config) ->
+ ?line run_trace_with_shortcut(caller, [ok,ok], tp),
+ ?line run_trace_with_shortcut(caller, [ok,ok], tpl).
+run_trace_with_shortcut1(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+run_trace_with_shortcut2(suite) ->
+ [];
+run_trace_with_shortcut2(doc) ->
+ ["Run trace with shortcut 2"];
+run_trace_with_shortcut2(Config) when is_list(Config) ->
+ ?line run_trace_with_shortcut(return, [ok,ok], tp),
+ ?line run_trace_with_shortcut(return, [ok,ok], tpl).
+run_trace_with_shortcut2(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+run_trace_with_shortcut3(suite) ->
+ [];
+run_trace_with_shortcut3(doc) ->
+ ["Run trace with shortcut 3"];
+run_trace_with_shortcut3(Config) when is_list(Config) ->
+ ?line run_trace_with_shortcut(fun_for(return), [ok,ok], tp),
+ ?line run_trace_with_shortcut(fun_for(return), [ok,ok], tpl).
+run_trace_with_shortcut3(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+run_trace_with_shortcut4(suite) ->
+ [];
+run_trace_with_shortcut4(doc) ->
+ ["Run trace with shortcut 4"];
+run_trace_with_shortcut4(Config) when is_list(Config) ->
+ ?line run_trace_with_shortcut(fun_for(msg_false), [], tp),
+ ?line run_trace_with_shortcut(fun_for(msg_false), [], tpl).
+run_trace_with_shortcut4(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+cant_specify_local_and_flush(suite) ->
+ [];
+cant_specify_local_and_flush(doc) ->
+ ["Can't specify local and flush"];
+cant_specify_local_and_flush(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line flush_unsupported_with_ip_trace_port =
+ try ttb:tracer([ServerNode, ClientNode],
+ [{flush, 1000}, {file, {local, ?FNAME}}])
+ catch
+ exit:flush_unsupported_with_ip_trace_port ->
+ flush_unsupported_with_ip_trace_port
+ end.
+cant_specify_local_and_flush(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+trace_sorted_by_default(suite) ->
+ [];
+trace_sorted_by_default(doc) ->
+ ["Trace sorted by default"];
+trace_sorted_by_default(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace_local(ServerNode, ClientNode, ?FILE),
+ ?line ttb_helper:msgs(2),
+ ?line {_, D} = ttb:stop([return_fetch_dir]),
+ ?line ttb:format(D, [{out, ?OUTPUT}, {handler, node_call_handler()}, {disable_sort, false}]),
+ {ok, Ret} = file:consult(?OUTPUT),
+ ?line [ClientNode,ServerNode,ClientNode,ServerNode,ServerNode] = Ret.
+trace_sorted_by_default(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+disable_sorting(suite) ->
+ [];
+disable_sorting(doc) ->
+ ["Disable sorting"];
+disable_sorting(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace_local(ServerNode, ClientNode, ?FILE),
+ ?line ttb_helper:msgs(2),
+ ?line {_, D} = ttb:stop([return_fetch_dir]),
+ ?line ttb:format(D, [{out, ?OUTPUT}, {handler, node_call_handler()}, {disable_sort, true}]),
+ {ok, Ret} = file:consult(?OUTPUT),
+ ?line [ClientNode,ClientNode,ServerNode,ServerNode,ServerNode] = Ret.
+disable_sorting(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+%% -----------------------------------------------------------------------------
+%% tests for autoresume of tracing
+%% -----------------------------------------------------------------------------
+
+trace_resumed_after_node_restart(suite) ->
+ [];
+trace_resumed_after_node_restart(doc) ->
+ ["Test trace resumed after node restart, trace to files on remote node."];
+trace_resumed_after_node_restart(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace_with_resume(ServerNode, ClientNode, ?FNAME),
+ ?line logic(2,6,file).
+trace_resumed_after_node_restart(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+trace_resumed_after_node_restart_ip(suite) ->
+ [];
+trace_resumed_after_node_restart_ip(doc) ->
+ ["Test trace resumed after node restart, trace via tcp/ip to local node."];
+trace_resumed_after_node_restart_ip(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace_with_resume(ServerNode, ClientNode, {local, ?FNAME}),
+ ?line logic(2,6,local).
+trace_resumed_after_node_restart_ip(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+trace_resumed_after_node_restart_wrap(suite) ->
+ [];
+trace_resumed_after_node_restart_wrap(doc) ->
+ ["Test trace resumed after node restart, wrap option."];
+trace_resumed_after_node_restart_wrap(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace_with_resume(ServerNode, ClientNode, {wrap, ?FNAME, 10, 4}),
+ ?line logic(1,4,file).
+trace_resumed_after_node_restart_wrap(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+trace_resumed_after_node_restart_wrap_mult(suite) ->
+ [];
+trace_resumed_after_node_restart_wrap_mult(doc) ->
+ ["Test trace resumed after node restart, wrap option, multiple files."];
+trace_resumed_after_node_restart_wrap_mult(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace_with_resume(ServerNode, ClientNode, {wrap, ?FNAME, 10, 4}),
+ ?line logic(20,8,file).
+trace_resumed_after_node_restart_wrap_mult(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+logic(N, M, TracingType) ->
+ helper_msgs(N, TracingType),
+ ?t:stop_node(ttb_helper:get_node(client)),
+ timer:sleep(2500),
+ ?line {ok,_ClientNode} = ?t:start_node(client,slave,[]),
+ ?line ok = ttb_helper:c(code, add_paths, [code:get_path()]),
+ ?line ttb_helper:c(client, init, []),
+ ?line helper_msgs(N, TracingType),
+ ?line {_, D} = ttb:stop([return_fetch_dir]),
+ ?line ttb:format(D, [{out, ?OUTPUT}, {handler, ret_caller_call_handler2()}]),
+ ?line {ok, Ret} = file:consult(?OUTPUT),
+ ?line M = length(Ret).
+
+begin_trace_with_resume(ServerNode, ClientNode, Dest) ->
+ ?line {ok, _} = ttb:tracer([ServerNode,ClientNode], [{file, Dest}, resume]),
+ ?line ttb:p(all, [call, timestamp]),
+ ?line ttb:tp(server, received, []),
+ ?line ttb:tp(client, put, []),
+ ?line ttb:tp(client, get, []).
+
+ret_caller_call_handler2() ->
+ {fun(A, {trace_ts, _, call, _, _} ,_,_) -> io:format(A, "ok.~n", []);
+ (_, _, _, _) -> ok end, []}.
+
+helper_msgs(N, TracingType) ->
+ case TracingType of
+ local ->
+ ttb_helper:msgs_ip(N);
+ _ ->
+ ttb_helper:msgs(N)
+ end.
+
+priv_dir(Conf) ->
+ %% Due to problem with long paths on windows => creating a new
+ %% priv_dir under data_dir
+ Dir = filename:absname(filename:join(?config(data_dir, Conf),priv_dir)),
+ filelib:ensure_dir(filename:join(Dir,"*")),
+ Dir.
+
+clean_priv_dir(Config) ->
+ PrivDir = priv_dir(Config),
+ case filelib:is_dir(PrivDir) of
+ true -> rm(PrivDir);
+ false -> ok
+ end.
+
+rm(This) ->
+ case filelib:is_dir(This) of
+ true ->
+ {ok,Files} = file:list_dir(This),
+ [rm(filename:join(This,F)) || F <- Files],
+ file:del_dir(This);
+ false ->
+ file:delete(This)
+ end.
diff --git a/lib/observer/test/ttb_helper.erl b/lib/observer/test/ttb_helper.erl
new file mode 100644
index 0000000000..76b06cd3ce
--- /dev/null
+++ b/lib/observer/test/ttb_helper.erl
@@ -0,0 +1,157 @@
+-module(ttb_helper). %%Nodes control
+-compile(export_all).
+
+%%API
+%%get() -> client:get()
+%%put(X) -> client:put(X)
+%%msgs(N) -> N times client:put(test_msg)
+%%clear() -> restart server
+%%ensure_running() / stop() -> start/stop nodes
+%%get_node(atom) -> return atom@hostname
+
+-define(NODE_CMD(Name),
+ "erl -sname " ++ atom_to_list(Name) ++
+ " -pa .. -pa . -detached -run ttb_helper send_ok").
+-define(REG_NAME, nc_testing).
+
+new_fun() ->
+ fun(_, end_of_trace, _, Dict) -> io:format("~p~n", [dict:to_list(Dict)]);
+ (_, T, _, Dict) -> case element(2, T) of
+ {Pid, _, _} ->
+ dict:update_counter(Pid, 1, Dict);
+ Pid ->
+ dict:update_counter(Pid, 1, Dict)
+ end
+ end.
+
+new_fun_2() ->
+ fun(_, end_of_trace, _, Dict) -> io:format("~p~n", [dict:to_list(Dict)]);
+ (_, T, _, Dict) -> case element(2, T) of
+ {_, Name, _} when is_atom(Name)->
+ dict:update_counter(Name, 1, Dict);
+ Pid ->
+ dict:update_counter(Pid, 1, Dict)
+ end
+
+ end.
+
+
+ensure_running() ->
+ try_start_node(server),
+ try_start_node(client),
+ clear().
+
+try_start_node(Node) ->
+ global:unregister_name(?REG_NAME),
+ global:register_name(?REG_NAME, self()),
+ global:sync(),
+ N = get_node(Node),
+ case net_adm:ping(N) of
+ pong ->
+ io:format("Node ~p already running~n", [N]);
+ _ ->
+ io:format("Starting node ~p... ~p ", [Node, os:cmd(?NODE_CMD(Node))]),
+ recv()
+ end.
+
+clear() ->
+ s(server, stop, []),
+ init().
+
+stop() ->
+ s(init, stop, []),
+ c(init, stop, []).
+
+msgs(N) ->
+ [c(client, put, [test_msg]) || _ <- lists:seq(1, N)],
+ s(server, received, [a,b]),
+ [dbg:flush_trace_port(Node) || Node <- [get_node(client), get_node(server)]].
+
+msgs_ip(N) ->
+ [c(client, put, [test_msg]) || _ <- lists:seq(1, N)],
+ s(server, received, [a,b]),
+ timer:sleep(200). %% allow trace messages to arrive over tcp/ip
+
+run() ->
+ ttb({local, "A"}),
+ msgs(2),
+ c(erlang, whereis, [ttbt]).
+
+get() -> c(client, get, []).
+put(Thing) -> c(client, put, [Thing]).
+
+get_node(Node) ->
+ {ok, Host} = inet:gethostname(),
+ list_to_atom(atom_to_list(Node) ++ "@" ++ Host).
+
+trace_setup() ->
+ ttb:p(all, call),
+ ttb:tp(server, received, []),
+ ttb:tp(client, put, []),
+ ttb:tp(client, get, []).
+
+ttb() -> ttb("A").
+ttb(File) ->
+ ttb:tracer([get_node(client), get_node(server)], [{file, File}, resume]),
+ ttb:p(all, [call, timestamp]),
+ ttb:tp(client, put, []),
+ ttb:tp(client, get, []),
+ ttb:tp(server, received, []).
+
+tc() ->
+ TC = example_config_gen:create_trace_case("dummy comment"),
+ Patterns = example_config_gen:create_pattern(client, put, 1, return),
+ Flags = example_config_gen:create_flags(all, call),
+ Merge = example_config_gen:create_merge_conf(show_handler(), "dummy merge comment"),
+ Merge2 = example_config_gen:create_merge_conf(undefined, "dummy merge comment"),
+ TC2 = example_config_gen:add_pattern(Patterns, TC),
+ TC3 = example_config_gen:add_flags(Flags, TC2),
+ TC4 = example_config_gen:add_merge_conf(Merge, TC3),
+ TC5 = example_config_gen:add_merge_conf(Merge2, TC4),
+ example_config_gen:add_nodes([get_node(client), get_node(server)], TC5).
+
+
+show(X) ->
+ io:format(user, "Showing: ~p~n", [X]).
+
+state_handler() ->
+ {fun(_,_,I,S) -> io:format(user, "Got from ~p: ~p~n", [I,S]), S+1 end, 0}.
+
+show_handler() ->
+ {fun(A,B,_,_) -> io:format(A, "~p~n", [B]) end, []}.
+
+opts() ->
+ [[get_node(client), get_node(server)],
+ [{server, received, '_', []},
+ {client, put, '_', []},
+ {client, get, '_', []}],
+ {all, call},
+ [{file, "TEST"}]].
+
+overload_check(check) ->
+ true;
+overload_check(_) ->
+ ok.
+%%%Internal
+s(M, F, A) -> rpc:call(get_node(server), M, F, A).
+c(M, F, A) -> rpc:call(get_node(client), M, F, A).
+
+send_ok() ->
+ pong = net_adm:ping(get_node(test)),
+ global:sync(),
+ global:send(?REG_NAME, node()).
+
+init() ->
+ True = s(server, start, []),
+ io:format("ok1: ~p~n", [True]),
+ true = c(client, init, [get_node(server)]).
+
+recv() ->
+ receive
+ Node ->
+ io:format("Node ~p ready.~n", [Node]),
+ ok
+ after 5000 ->
+ io:format("Startup failed~n",[]),
+ throw(startup_failed)
+ end.
diff --git a/lib/observer/vsn.mk b/lib/observer/vsn.mk
index 14c8f54ba3..76e2f591fa 100644
--- a/lib/observer/vsn.mk
+++ b/lib/observer/vsn.mk
@@ -1 +1 @@
-OBSERVER_VSN = 0.9.9
+OBSERVER_VSN = 0.9.10
diff --git a/lib/odbc/c_src/Makefile.in b/lib/odbc/c_src/Makefile.in
index ed3eeb1d42..dda896bcd2 100644
--- a/lib/odbc/c_src/Makefile.in
+++ b/lib/odbc/c_src/Makefile.in
@@ -89,9 +89,10 @@ TARGET_FLAGS = @TARGET_FLAGS@
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
+_create_dirs := $(shell mkdir -p $(OBJ_DIR) $(BIN_DIR))
ifdef EXE_TARGET
-opt debug: create_dirs $(EXE_TARGET)
+opt debug: $(EXE_TARGET)
else
opt debug:
endif
@@ -119,10 +120,6 @@ endif
$(OBJ_DIR)/odbcserver.o: odbcserver.c
$(CC) $(CFLAGS) $(INCLUDES) $(TARGET_FLAGS) -o $@ -c odbcserver.c
-create_dirs:
- $(INSTALL_DIR) $(OBJ_DIR)
- $(INSTALL_DIR) $(BIN_DIR)
-
# ----------------------------------------------------
# Release Target
# ----------------------------------------------------
diff --git a/lib/odbc/c_src/odbcserver.c b/lib/odbc/c_src/odbcserver.c
index d61ce940c3..ab2d7fe210 100644
--- a/lib/odbc/c_src/odbcserver.c
+++ b/lib/odbc/c_src/odbcserver.c
@@ -90,7 +90,7 @@
Datatype - USER_INT | USER_SMALL_INT | {USER_DECIMAL, Precision, Scale} |
{USER_NMERIC, Precision, Scale} | {USER_CHAR, Max} | {USER_VARCHAR, Max} |
{USER_WVARCHAR, Max} | {USER_FLOAT, Precision} | USER_REAL | USER_DOUBLE |
- USER_TIMESTAMP
+ USER_TIMESTAMP | {USER_WLONGVARCHAR, Max}
Scale - integer
Precision - integer
Max - integer
@@ -173,7 +173,7 @@ static db_result_msg encode_row_count(SQLINTEGER num_of_rows,
db_state *state);
static void encode_column_dyn(db_column column, int column_nr,
db_state *state);
-static void encode_data_type(SQLINTEGER sql_type, SQLINTEGER size,
+static void encode_data_type(SQLSMALLINT sql_type, SQLINTEGER size,
SQLSMALLINT decimal_digits, db_state *state);
static Boolean decode_params(db_state *state, byte *buffer, int *index, param_array **params,
int i, int j);
@@ -221,7 +221,7 @@ static void init_param_column(param_array *params, byte *buffer, int *index,
int num_param_values, db_state* state);
static void init_param_statement(int cols,
- int num_param_values,
+ SQLLEN num_param_values,
db_state *state,
param_status *status);
@@ -435,7 +435,7 @@ static db_result_msg db_connect(byte *args, db_state *state)
diagnos diagnos;
byte *connStrIn;
int erl_auto_commit_mode, erl_trace_driver,
- use_srollable_cursors, tuple_row_state, binary_strings;
+ use_srollable_cursors, tuple_row_state, binary_strings;
erl_auto_commit_mode = args[0];
erl_trace_driver = args[1];
@@ -757,8 +757,9 @@ static db_result_msg db_select(byte *args, db_state *state)
static db_result_msg db_param_query(byte *buffer, db_state *state)
{
byte *sql;
- db_result_msg msg;
- int i, num_param_values, ver = 0,
+ db_result_msg msg;
+ SQLLEN num_param_values;
+ int i, ver = 0,
erl_type = 0, index = 0, size = 0, cols = 0;
long long_num_param_values;
param_status param_status;
@@ -771,6 +772,7 @@ static db_result_msg db_param_query(byte *buffer, db_state *state)
}
associated_result_set(state) = FALSE;
param_query(state) = TRUE;
+ out_params(state) = FALSE;
msg = encode_empty_message();
@@ -785,7 +787,7 @@ static db_result_msg db_param_query(byte *buffer, db_state *state)
ei_decode_long(buffer, &index, &long_num_param_values);
- num_param_values = (int)long_num_param_values;
+ num_param_values = (SQLLEN)long_num_param_values;
ei_decode_list_header(buffer, &index, &cols);
@@ -1002,12 +1004,16 @@ static db_result_msg encode_result(db_state *state)
db_result_msg msg;
int elements, update, num_of_rows = 0;
char *atom;
+ diagnos diagnos;
msg = encode_empty_message();
if(!sql_success(SQLNumResultCols(statement_handle(state),
&num_of_columns))) {
- DO_EXIT(EXIT_COLS);
+ diagnos = get_diagnos(SQL_HANDLE_STMT, statement_handle(state));
+ msg = encode_error_message(diagnos.error_msg);
+ clean_state(state);
+ return msg;
}
if (num_of_columns == 0) {
@@ -1021,7 +1027,10 @@ static db_result_msg encode_result(db_state *state)
}
if(!sql_success(SQLRowCount(statement_handle(state), &RowCountPtr))) {
- DO_EXIT(EXIT_ROWS);
+ diagnos = get_diagnos(SQL_HANDLE_STMT, statement_handle(state));
+ msg = encode_error_message(diagnos.error_msg);
+ clean_state(state);
+ return msg;
}
if(param_query(state) && update) {
@@ -1220,7 +1229,7 @@ static db_result_msg encode_column_name_list(SQLSMALLINT num_of_columns,
&nullable)))
DO_EXIT(EXIT_DESC);
- if(sql_type == SQL_LONGVARCHAR || sql_type == SQL_LONGVARBINARY)
+ if(sql_type == SQL_LONGVARCHAR || sql_type == SQL_LONGVARBINARY || sql_type == SQL_WLONGVARCHAR)
size = MAXCOLSIZE;
(columns(state)[i]).type.decimal_digits = dec_digits;
@@ -1452,7 +1461,7 @@ static void encode_column_dyn(db_column column, int column_nr,
}
}
-static void encode_data_type(SQLINTEGER sql_type, SQLINTEGER size,
+static void encode_data_type(SQLSMALLINT sql_type, SQLINTEGER size,
SQLSMALLINT decimal_digits, db_state *state)
{
switch(sql_type) {
@@ -1529,6 +1538,11 @@ static void encode_data_type(SQLINTEGER sql_type, SQLINTEGER size,
case SQL_LONGVARCHAR:
ei_x_encode_atom(&dynamic_buffer(state), "SQL_LONGVARCHAR");
break;
+ case SQL_WLONGVARCHAR:
+ ei_x_encode_tuple_header(&dynamic_buffer(state), 2);
+ ei_x_encode_atom(&dynamic_buffer(state), "sql_wlongvarchar");
+ ei_x_encode_long(&dynamic_buffer(state), size);
+ break;
case SQL_VARBINARY:
ei_x_encode_atom(&dynamic_buffer(state), "SQL_VARBINARY");
break;
@@ -2007,7 +2021,7 @@ static void init_driver(int erl_auto_commit_mode, int erl_trace_driver,
db_state *state)
{
- int auto_commit_mode, trace_driver;
+ SQLLEN auto_commit_mode, trace_driver;
if(erl_auto_commit_mode == ON) {
auto_commit_mode = SQL_AUTOCOMMIT_ON;
@@ -2057,7 +2071,7 @@ static void init_param_column(param_array *params, byte *buffer, int *index,
ei_decode_long(buffer, index, &user_type);
- params->type.strlen_or_indptr = (SQLINTEGER)NULL;
+ params->type.strlen_or_indptr = (SQLLEN)NULL;
params->type.strlen_or_indptr_array = NULL;
params->type.decimal_digits = (SQLINTEGER)0;
@@ -2131,10 +2145,14 @@ static void init_param_column(param_array *params, byte *buffer, int *index,
break;
case USER_WCHAR:
case USER_WVARCHAR:
- if(user_type == USER_WCHAR) {
- params->type.sql = SQL_WCHAR;
- } else {
- params->type.sql = SQL_WVARCHAR;
+ case USER_WLONGVARCHAR:
+ switch (user_type) {
+ case USER_WCHAR:
+ params->type.sql = SQL_WCHAR; break;
+ case USER_WVARCHAR:
+ params->type.sql = SQL_WVARCHAR; break;
+ default:
+ params->type.sql = SQL_WLONGVARCHAR; break;
}
ei_decode_long(buffer, index, &length);
/* Max string length + string terminator */
@@ -2206,7 +2224,7 @@ static void init_param_column(param_array *params, byte *buffer, int *index,
}
-static void init_param_statement(int cols, int num_param_values,
+static void init_param_statement(int cols, SQLLEN num_param_values,
db_state *state, param_status *status)
{
int i;
@@ -2234,11 +2252,11 @@ static void init_param_statement(int cols, int num_param_values,
DO_EXIT(EXIT_PARAM_ARRAY);
}
- /* Note the (int *) cast is correct as the API function SQLSetStmtAttr
+ /* Note the (SQLLEN *) cast is correct as the API function SQLSetStmtAttr
takes either an interger or a pointer depending on the attribute */
if(!sql_success(SQLSetStmtAttr(statement_handle(state),
SQL_ATTR_PARAMSET_SIZE,
- (int *)num_param_values,
+ (SQLLEN *)num_param_values,
0))) {
DO_EXIT(EXIT_PARAM_ARRAY);
}
@@ -2300,6 +2318,7 @@ static db_result_msg map_sql_2_c_column(db_column* column)
break;
case SQL_WCHAR:
case SQL_WVARCHAR:
+ case SQL_WLONGVARCHAR:
column -> type.len = (column -> type.col_size + 1)*sizeof(SQLWCHAR);
column -> type.c = SQL_C_WCHAR;
column -> type.strlen_or_indptr = SQL_NTS;
@@ -2308,21 +2327,21 @@ static db_result_msg map_sql_2_c_column(db_column* column)
case SQL_DECIMAL:
map_dec_num_2_c_column(&(column -> type), column -> type.col_size,
column -> type.decimal_digits);
- column -> type.strlen_or_indptr = (SQLINTEGER)NULL;
+ column -> type.strlen_or_indptr = (SQLLEN)NULL;
break;
case SQL_TINYINT:
case SQL_INTEGER:
case SQL_SMALLINT:
column -> type.len = sizeof(SQLINTEGER);
column -> type.c = SQL_C_SLONG;
- column -> type.strlen_or_indptr = (SQLINTEGER)NULL;
+ column -> type.strlen_or_indptr = (SQLLEN)NULL;
break;
case SQL_REAL:
case SQL_FLOAT:
case SQL_DOUBLE:
column -> type.len = sizeof(double);
column -> type.c = SQL_C_DOUBLE;
- column -> type.strlen_or_indptr = (SQLINTEGER)NULL;
+ column -> type.strlen_or_indptr = (SQLLEN)NULL;
break;
case SQL_TYPE_DATE:
case SQL_TYPE_TIME:
@@ -2334,17 +2353,17 @@ static db_result_msg map_sql_2_c_column(db_column* column)
case SQL_TYPE_TIMESTAMP:
column -> type.len = sizeof(TIMESTAMP_STRUCT);
column -> type.c = SQL_C_TYPE_TIMESTAMP;
- column -> type.strlen_or_indptr = (SQLINTEGER)NULL;
+ column -> type.strlen_or_indptr = (SQLLEN)NULL;
break;
case SQL_BIGINT:
column -> type.len = DEC_NUM_LENGTH;
column -> type.c = SQL_C_CHAR;
- column -> type.strlen_or_indptr = (SQLINTEGER)NULL;
+ column -> type.strlen_or_indptr = (SQLLEN)NULL;
break;
case SQL_BIT:
column -> type.len = sizeof(byte);
column -> type.c = SQL_C_BIT;
- column -> type.strlen_or_indptr = (SQLINTEGER)NULL;
+ column -> type.strlen_or_indptr = (SQLLEN)NULL;
break;
case SQL_UNKNOWN_TYPE:
msg = encode_error_message("Unknown column type");
diff --git a/lib/odbc/c_src/odbcserver.h b/lib/odbc/c_src/odbcserver.h
index 3e2b22ab7d..56b6148777 100644
--- a/lib/odbc/c_src/odbcserver.h
+++ b/lib/odbc/c_src/odbcserver.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -115,6 +115,7 @@
#define USER_WCHAR 12
#define USER_WVARCHAR 13
#define USER_TIMESTAMP 14
+#define USER_WLONGVARCHAR 15
/*------------------------ TYPDEFS ----------------------------------*/
diff --git a/lib/odbc/doc/src/Makefile b/lib/odbc/doc/src/Makefile
index e2f09733d0..3e648d854d 100644
--- a/lib/odbc/doc/src/Makefile
+++ b/lib/odbc/doc/src/Makefile
@@ -29,14 +29,6 @@ VSN=$(ODBC_VSN)
APPLICATION=odbc
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -89,32 +81,10 @@ EXTRA_FILES = $(DEFAULT_GIF_FILES) \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -128,8 +98,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif # Copy them to ../html
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -144,32 +112,6 @@ clean clean_docs:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES)
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ *xmls_output *xmls_errs $(LATEX_CLEAN)
-
-endif
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%) # We depend just to copy them to ../html
@@ -182,8 +124,6 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
$(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
$(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
@@ -193,32 +133,5 @@ release_docs_spec: docs
$(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
$(INSTALL_DIR) $(RELEASE_PATH)/man/man3
$(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-endif
-endif
-
-endif
release_spec:
-
-
-
-
diff --git a/lib/odbc/doc/src/databases.xml b/lib/odbc/doc/src/databases.xml
index a6ba0e5245..34e1d51255 100644
--- a/lib/odbc/doc/src/databases.xml
+++ b/lib/odbc/doc/src/databases.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2002</year><year>2010</year>
+ <year>2002</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -205,6 +205,10 @@ when p >= 16 </cell>
<cell align="left" valign="middle">String | Binary (configurable)</cell>
</row>
<row>
+ <cell align="left" valign="middle">SQL_WLONGVARCHAR(size) </cell>
+ <cell align="left" valign="middle">Unicode binary encoded as UTF16 little endian.</cell>
+ </row>
+ <row>
<cell align="left" valign="middle">SQL_BINARY</cell>
<cell align="left" valign="middle">String | Binary (configurable)</cell>
</row>
diff --git a/lib/odbc/doc/src/make.dep b/lib/odbc/doc/src/make.dep
deleted file mode 100644
index d62e8dd8f0..0000000000
--- a/lib/odbc/doc/src/make.dep
+++ /dev/null
@@ -1,27 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex databases.tex error_handling.tex \
- getting_started.tex introduction.tex odbc.tex \
- part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: odbc_app_arc.ps
-
diff --git a/lib/odbc/doc/src/notes.xml b/lib/odbc/doc/src/notes.xml
index e15e7dea7d..9c6ca8a017 100644
--- a/lib/odbc/doc/src/notes.xml
+++ b/lib/odbc/doc/src/notes.xml
@@ -31,7 +31,49 @@
<p>This document describes the changes made to the odbc application.
</p>
- <section><title>ODBC 2.10.10</title>
+ <section><title>ODBC 2.10.11</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ When using output parameters the internal odbc state was
+ not correctly cleaned causing the next call to
+ param_query to misbehave.</p>
+ <p>
+ Own Id: OTP-9444</p>
+ </item>
+ <item>
+ <p> XML files have been corrected. </p>
+ <p>
+ Own Id: OTP-9550 Aux Id: OTP-9541 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add code to handle old ODBC drivers on solaris. Also adds
+ tests with MySQL.</p>
+ <p>
+ Own Id: OTP-8407</p>
+ </item>
+ <item>
+ <p>
+ Odbc now supports SQL_WLONGVARCHAR, thanks to Hanfei Shen
+ for the patch.</p>
+ <p>
+ Own Id: OTP-8493</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>ODBC 2.10.10</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/odbc/doc/src/odbc.xml b/lib/odbc/doc/src/odbc.xml
index 70d8cfbe22..8a58dc2848 100644
--- a/lib/odbc/doc/src/odbc.xml
+++ b/lib/odbc/doc/src/odbc.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1999</year><year>2010</year>
+ <year>1999</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -102,7 +102,7 @@
{sql_decimal, precision(), scale()} |
{sql_numeric, precision(), scale()} |
{sql_char, size()} | {sql_wchar, size()} | {sql_varchar, size()} | {sql_wvarchar, size()}| {sql_float, precision()} |
- {sql_float, precision()} | sql_real | sql_double | sql_bit | atom()
+ {sql_wlongvarchar, size()} | {sql_float, precision()} | sql_real | sql_double | sql_bit | atom()
</code>
<code type="none">
precision() = integer() </code>
@@ -138,7 +138,7 @@
<fsummary>Opens a connection to the database. </fsummary>
<type>
<v>ConnectStr = string()</v>
- <d>An example of a connection string:<c>"DSN=sql-server;UID=aladdin;PWD=sesame"</c>where DSN is your ODBC Data Source Name, UID is a database user id and PWD is the password for that user. These are usually the attributes required in the connection string, but some drivers have other driver specific attributes, for example<c>"DSN=Oracle8;DBQ=gandalf;UID=aladdin;PWD=sesame"</c>where DBQ is your TNSNAMES.ORA entry name e.g. some Oracle specific configuration attribute.</d>
+ <d>An example of a connection string: <c>"DSN=sql-server;UID=aladdin;PWD=sesame"</c> where DSN is your ODBC Data Source Name, UID is a database user id and PWD is the password for that user. These are usually the attributes required in the connection string, but some drivers have other driver specific attributes, for example <c>"DSN=Oracle8;DBQ=gandalf;UID=aladdin;PWD=sesame"</c> where DBQ is your TNSNAMES.ORA entry name e.g. some Oracle specific configuration attribute.</d>
<v>Options = [] | [option()]</v>
<d>All options has default values. </d>
<v>option() = {auto_commit, on | off} | {timeout, milliseconds()}
@@ -432,7 +432,7 @@
<desc>
<p>Selects <c>N</c> consecutive rows of the result set. If
<c>Position</c> is <c>next</c> it is semantically equivalent
- of calling <c>next/[1,2]</c><c>N</c> times. If
+ of calling <c>next/[1,2]</c> <c>N</c> times. If
<c>Position</c> is <c>{relative, Pos}</c>, <c>Pos</c> will be
used as an offset from the current cursor position to
determine the first selected row. If <c>Position</c> is
diff --git a/lib/odbc/src/odbc.appup.src b/lib/odbc/src/odbc.appup.src
index 2a6667ccd3..f3a3af8c29 100644
--- a/lib/odbc/src/odbc.appup.src
+++ b/lib/odbc/src/odbc.appup.src
@@ -1,8 +1,10 @@
%% -*- erlang -*-
{"%VSN%",
[
- {"2.10.9", [{restart_application, ssl}]}
+ {"2.10.10", [{restart_application, odbc}]},
+ {"2.10.9", [{restart_application, odbc}]}
],
[
- {"2.10.9", [{restart_application, ssl}]}
+ {"2.10.10", [{restart_application, odbc}]},
+ {"2.10.9", [{restart_application, odbc}]}
]}.
diff --git a/lib/odbc/src/odbc.erl b/lib/odbc/src/odbc.erl
index 83d9f33102..68497292db 100644
--- a/lib/odbc/src/odbc.erl
+++ b/lib/odbc/src/odbc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -431,7 +431,7 @@ init(Args) ->
erlang:monitor(process, ClientPid),
- Inet = case gen_tcp:listen(0, [inet6]) of
+ Inet = case gen_tcp:listen(0, [inet6, {ip, loopback}]) of
{ok, Dummyport} ->
gen_tcp:close(Dummyport),
inet6;
@@ -925,6 +925,9 @@ fix_params({{sql_wchar, Max}, InOut, Values}) ->
fix_params({{sql_wvarchar, Max}, InOut, Values}) ->
NewValues = string_terminate(Values),
{?USER_WVARCHAR, Max, fix_inout(InOut), NewValues};
+fix_params({{sql_wlongvarchar, Max}, InOut, Values}) ->
+ NewValues = string_terminate(Values),
+ {?USER_WLONGVARCHAR, Max, fix_inout(InOut), NewValues};
fix_params({{sql_float, Precision}, InOut, Values}) ->
{?USER_FLOAT, Precision, fix_inout(InOut), Values};
fix_params({sql_real, InOut, Values}) ->
diff --git a/lib/odbc/src/odbc_internal.hrl b/lib/odbc/src/odbc_internal.hrl
index aa60120f9a..bd80cdc659 100644
--- a/lib/odbc/src/odbc_internal.hrl
+++ b/lib/odbc/src/odbc_internal.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -72,6 +72,7 @@
-define(USER_WCHAR, 12).
-define(USER_WVARCHAR, 13).
-define(USER_TIMESTAMP, 14).
+-define(USER_WLONGVARCHAR, 15).
%% INPUT & OUTPUT TYPE
-define(IN, 0).
diff --git a/lib/odbc/test/Makefile b/lib/odbc/test/Makefile
index ec2bcc67b5..bc6449242e 100644
--- a/lib/odbc/test/Makefile
+++ b/lib/odbc/test/Makefile
@@ -34,7 +34,8 @@ MODULES= \
odbc_test_lib \
oracle \
sqlserver \
- postgres
+ postgres \
+ mysql
EBIN = .
diff --git a/lib/odbc/test/mysql.erl b/lib/odbc/test/mysql.erl
new file mode 100644
index 0000000000..c990793213
--- /dev/null
+++ b/lib/odbc/test/mysql.erl
@@ -0,0 +1,277 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(mysql).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+%-------------------------------------------------------------------------
+connection_string() ->
+ case test_server:os_type() of
+ {unix, linux} ->
+ "DSN=MySQL;Database=odbctest;Uid=odbctest;Pwd=gurka;CHARSET=utf8;SSTMT=SET NAMES 'utf8';";
+ {unix, sunos} ->
+ solaris_str();
+ {unix, darwin} ->
+ "DSN=MySQLMac;Database=odbctest;Uid=odbctest;Pwd=gurka;CHARSET=utf8;SSTMT=SET NAMES 'utf8';"
+ end.
+
+solaris_str() ->
+ case erlang:system_info(system_architecture) of
+ "sparc" ++ _ ->
+ "DSN=MySQLSolaris10;Database=odbctest;Uid=odbctest;Pwd=gurka;CHARSET=utf8;SSTMT=SET NAMES 'utf8';";
+ "i386" ++ _ ->
+ "DSN=MySQLSolaris10i386;Database=odbctest;Uid=odbctest;Pwd=gurka;CHARSET=utf8;SSTMT=SET NAMES 'utf8';"
+ end.
+
+%-------------------------------------------------------------------------
+insert_result() ->
+ {selected,["ID","DATA"],[{1,"bar"}]}.
+
+update_result() ->
+ {selected,["ID","DATA"],[{1,"foo"}]}.
+
+selected_ID(N, next) ->
+ {selected,["ID"],[{N}]};
+
+selected_ID(_, _) ->
+ {error, driver_does_not_support_function}.
+
+selected_next_N(1)->
+ {selected,["ID"],
+ [{1},
+ {2},
+ {3}]};
+
+selected_next_N(2)->
+ {selected,["ID"],
+ [{4},
+ {5}]}.
+
+selected_relative_N(_)->
+ {error, driver_does_not_support_function}.
+
+selected_absolute_N(_)->
+ {error, driver_does_not_support_function}.
+
+selected_list_rows() ->
+ {selected,["ID", "DATA"],[[1, "bar"],[2,"foo"]]}.
+
+first_list_rows() ->
+ {error, driver_does_not_support_function}.
+last_list_rows() ->
+ {error, driver_does_not_support_function}.
+prev_list_rows() ->
+ {error, driver_does_not_support_function}.
+next_list_rows() ->
+ {selected,["ID","DATA"],[[1,"bar"]]}.
+
+multiple_select()->
+ [{selected,["ID", "DATA"],[{1, "bar"},{2, "foo"}]},
+ {selected,["ID"],[{"foo"}]}].
+
+multiple_mix()->
+ [{updated, 1},{updated, 1},
+ {selected,["ID", "DATA"],[{1, "foobar"},{2, "foo"}]},
+ {updated, 1}, {selected,["DATA"],[{"foo"}]}].
+
+%-------------------------------------------------------------------------
+var_char_min() ->
+ 0.
+var_char_max() ->
+ 65535.
+
+create_var_char_table(Size) ->
+ " (FIELD varchar(" ++ integer_to_list(Size) ++ "))".
+
+%-------------------------------------------------------------------------
+text_min() ->
+ 1.
+text_max() ->
+ 2147483646. % 2147483647. %% 2^31 - 1
+
+create_text_table() ->
+ " (FIELD text)".
+
+%-------------------------------------------------------------------------
+create_timestamp_table() ->
+ " (FIELD TIMESTAMP)".
+
+%-------------------------------------------------------------------------
+tiny_int_min() ->
+ -128.
+tiny_int_max() ->
+ 127.
+
+create_tiny_int_table() ->
+ " (FIELD tinyint)".
+
+tiny_int_min_selected() ->
+ {selected,["FIELD"],[{tiny_int_min()}]}.
+
+tiny_int_max_selected() ->
+ {selected,["FIELD"], [{tiny_int_max()}]}.
+
+%-------------------------------------------------------------------------
+small_int_min() ->
+ -32768.
+small_int_max() ->
+ 32767.
+
+create_small_int_table() ->
+ " (FIELD smallint)".
+
+small_int_min_selected() ->
+ {selected,["FIELD"],[{-32768}]}.
+
+small_int_max_selected() ->
+ {selected,["FIELD"], [{32767}]}.
+
+%-------------------------------------------------------------------------
+int_min() ->
+ -2147483648.
+int_max() ->
+ 2147483647.
+
+create_int_table() ->
+ " (FIELD int)".
+
+int_min_selected() ->
+ {selected,["FIELD"],[{-2147483648}]}.
+
+int_max_selected() ->
+ {selected,["FIELD"], [{2147483647}]}.
+
+%-------------------------------------------------------------------------
+big_int_min() ->
+ -9223372036854775808.
+
+big_int_max() ->
+ 9223372036854775807.
+
+create_big_int_table() ->
+ " (FIELD bigint )".
+
+big_int_min_selected() ->
+ {selected,["FIELD"], [{"-9223372036854775808"}]}.
+
+big_int_max_selected() ->
+ {selected,["FIELD"], [{"9223372036854775807"}]}.
+
+%-------------------------------------------------------------------------
+bit_false() ->
+ 0.
+bit_true() ->
+ 1.
+
+create_bit_table() ->
+ " (FIELD bit)".
+
+bit_false_selected() ->
+ {selected,["FIELD"],[{"0"}]}.
+
+bit_true_selected() ->
+ {selected,["FIELD"], [{"1"}]}.
+
+%-------------------------------------------------------------------------
+
+%% Do not test float min/max as value is only theoretical defined in
+%% mysql and may vary depending on hardware.
+
+create_float_table() ->
+ " (FIELD float)".
+
+float_zero_selected() ->
+ {selected,["FIELD"],[{0.00000e+0}]}.
+
+%-------------------------------------------------------------------------
+real_min() ->
+ -3.40e+38.
+real_max() ->
+ 3.40e+38.
+
+real_underflow() ->
+ "-3.41e+38".
+
+real_overflow() ->
+ "3.41e+38".
+
+create_real_table() ->
+ " (FIELD real)".
+
+real_zero_selected() ->
+ {selected,["FIELD"],[{0.00000e+0}]}.
+
+%-------------------------------------------------------------------------
+param_select_small_int() ->
+ {selected,["FIELD"],[{1}, {2}]}.
+
+param_select_int() ->
+ Int = small_int_max() + 1,
+ {selected,["FIELD"],[{1}, {Int}]}.
+
+param_select_decimal() ->
+ {selected,["FIELD"],[{1},{2}]}.
+
+param_select_numeric() ->
+ {selected,["FIELD"],[{1},{2}]}.
+
+param_select_float() ->
+ {selected,["FIELD"],[{1.30000},{1.20000}]}.
+
+param_select_real() ->
+ {selected,["FIELD"],[{1.30000},{1.20000}]}.
+
+param_select_double() ->
+ {selected,["FIELD"],[{1.30000},{1.20000}]}.
+
+param_select_mix() ->
+ {selected,["ID","DATA"],[{1, "foo"}, {2, "bar"}]}.
+
+param_update() ->
+ {selected,["ID","DATA"],[{1, "foobar"}, {2, "foobar"}, {3, "baz"}]}.
+
+param_delete() ->
+ {selected,["ID","DATA"],[{3, "baz"}]}.
+
+param_select() ->
+ {selected,["ID","DATA"],[{1, "foo"},{3, "foo"}]}.
+
+%-------------------------------------------------------------------------
+describe_integer() ->
+ {ok,[{"myint1",sql_smallint},
+ {"myint2",sql_integer},
+ {"myint3",sql_integer}]}.
+
+describe_string() ->
+ {ok,[{"str1",{sql_char,10}},
+ {"str2",{sql_char,10}},
+ {"str3",{sql_varchar,10}},
+ {"str4",{sql_varchar,10}}]}.
+
+describe_floating() ->
+ {ok,[{"f",sql_real},{"r",sql_double},{"d",sql_double}]}.
+describe_dec_num() ->
+ {ok,[{"mydec",{sql_decimal,9,3}},{"mynum",{sql_decimal,9,2}}]}.
+
+describe_timestamp() ->
+ {ok, [{"FIELD", sql_timestamp}]}.
diff --git a/lib/odbc/test/odbc.dynspec b/lib/odbc/test/odbc.dynspec
deleted file mode 100644
index bb15edceed..0000000000
--- a/lib/odbc/test/odbc.dynspec
+++ /dev/null
@@ -1,31 +0,0 @@
-%% -*- erlang -*-
-%% You can test this file using this command.
-%% file:script("odbc.dynspec", [{'Os',"Unix"}]).
-
-Exists =
-fun() ->
- case code:lib_dir(odbc) of
- {error,bad_name} ->
- false;
- P ->
- %% Make sure that the odbc directory really
- %% contains the application (and not only documentation).
- case filelib:is_file(filename:join(P, "ebin/odbc.beam")) of
- false -> false;
- true ->
- %% We know that we don't have any odbc libraries
- %% installed on this computer.
- {ok,Host} = inet:gethostname(),
- Host =/= "netsim200"
- end
- end
-end,
-case Exists() of
- false ->
- NoOdbc = "No odbc application",
- [{skip, {odbc_connect_SUITE, NoOdbc}},
- {skip, {odbc_data_type_SUITE, NoOdbc}},
- {skip, {odbc_query_SUITE, NoOdbc}}];
- true ->
- []
-end.
diff --git a/lib/odbc/test/odbc.spec b/lib/odbc/test/odbc.spec
index edaf821c91..653f1a780e 100644
--- a/lib/odbc/test/odbc.spec
+++ b/lib/odbc/test/odbc.spec
@@ -1,25 +1 @@
{suites,"../odbc_test",all}.
-{skip_cases,"../odbc_test",odbc_data_type_SUITE,
- [varchar_upper_limit],
- "Known bug in database"}.
-{skip_cases,"../odbc_test",odbc_data_type_SUITE,
- [text_upper_limit],
- "Consumes too much resources"}.
-{skip_cases,"../odbc_test",odbc_data_type_SUITE,
- [bit_true],
- "Not supported by driver"}.
-{skip_cases,"../odbc_test",odbc_data_type_SUITE,
- [bit_false],
- "Not supported by driver"}.
-{skip_cases,"../odbc_test",odbc_query_SUITE,
- [multiple_select_result_sets],
- "Not supported by driver"}.
-{skip_cases,"../odbc_test",odbc_query_SUITE,
- [multiple_mix_result_sets],
- "Not supported by driver"}.
-{skip_cases,"../odbc_test",odbc_query_SUITE,
- [multiple_result_sets_error],
- "Not supported by driver"}.
-{skip_cases,"../odbc_test",odbc_query_SUITE,
- [param_insert_tiny_int],
- "Not supported by driver"}.
diff --git a/lib/odbc/test/odbc.spec.win b/lib/odbc/test/odbc.spec.win
deleted file mode 100644
index 1fd349d2c3..0000000000
--- a/lib/odbc/test/odbc.spec.win
+++ /dev/null
@@ -1,5 +0,0 @@
-{topcase, {dir, "../odbc_test"}}.
-{skip, {odbc_data_type_SUITE, big_int_lower_limit, "Not supported by sqlserver 7.0"}}.
-{skip, {odbc_data_type_SUITE, big_int_upper_limit, "Not supported by sqlserver7.0"}}.
-{skip, {odbc_data_type_SUITE, text_upper_limit, "Consumes too much resources"}}.
-
diff --git a/lib/odbc/test/odbc_connect_SUITE.erl b/lib/odbc/test/odbc_connect_SUITE.erl
index 6a2268f40e..a076c4dfff 100644
--- a/lib/odbc/test/odbc_connect_SUITE.erl
+++ b/lib/odbc/test/odbc_connect_SUITE.erl
@@ -76,16 +76,26 @@ end_per_group(_GroupName, Config) ->
%% Note: This function is free to add any key/value pairs to the Config
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
-init_per_suite(Config) ->
- application:start(odbc),
- case catch odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]) of
- {ok, Ref} ->
- odbc:disconnect(Ref),
- [{tableName, odbc_test_lib:unique_table_name()} | Config];
- _ ->
- {skip, "ODBC is not properly setup"}
- end.
+init_per_suite(Config) when is_list(Config) ->
+ case odbc_test_lib:skip() of
+ true ->
+ {skip, "ODBC not supported"};
+ false ->
+ case (catch odbc:start()) of
+ ok ->
+ case catch odbc:connect(?RDBMS:connection_string(),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()) of
+ {ok, Ref} ->
+ odbc:disconnect(Ref),
+ [{tableName, odbc_test_lib:unique_table_name()} | Config];
+ _ ->
+ {skip, "ODBC is not properly setup"}
+ end;
+ _ ->
+ {skip,"ODBC not startable"}
+ end
+ end.
+
%%--------------------------------------------------------------------
%% Function: end_per_suite(Config) -> _
%% Config - [tuple()]
@@ -93,8 +103,7 @@ init_per_suite(Config) ->
%% Description: Cleanup after the whole suite
%%--------------------------------------------------------------------
end_per_suite(_Config) ->
- application:stop(odbc),
- ok.
+ application:stop(odbc).
%%--------------------------------------------------------------------
%% Function: init_per_testcase(Case, Config) -> Config
@@ -124,15 +133,13 @@ init_per_testcase(_TestCase, Config) ->
%% Description: Cleanup after each test case
%%--------------------------------------------------------------------
end_per_testcase(_TestCase, Config) ->
- %% Clean up if needed
Table = ?config(tableName, Config),
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
- Result = odbc:sql_query(Ref, "DROP TABLE " ++ Table),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
+ Result = odbc:sql_query(Ref, "DROP TABLE " ++ Table),
io:format("Drop table: ~p ~p~n", [Table, Result]),
odbc:disconnect(Ref),
Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
+ test_server:timetrap_cancel(Dog).
%%-------------------------------------------------------------------------
%% Test cases starts here.
@@ -142,13 +149,15 @@ commit(doc)->
commit(suite) -> [];
commit(Config) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
Table = ?config(tableName, Config),
+ TransStr = transaction_support_str(?RDBMS),
+
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
- " (ID integer, DATA varchar(10))"),
+ " (ID integer, DATA varchar(10))" ++ TransStr),
{updated, 1} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(1,'bar')"),
@@ -173,50 +182,47 @@ commit(Config) ->
{'EXIT', {function_clause, _}} =
(catch odbc:commit(Ref, commit, -1)),
- ok = odbc:disconnect(Ref),
-
- ok.
+ ok = odbc:disconnect(Ref).
%%-------------------------------------------------------------------------
rollback(doc)->
["Test the use of explicit rollback"];
rollback(suite) -> [];
rollback(Config) ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
Table = ?config(tableName, Config),
- {updated, _} =
- odbc:sql_query(Ref,
+ TransStr = transaction_support_str(?RDBMS),
+
+ {updated, _} =
+ odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
- " (ID integer, DATA varchar(10))"),
- {updated, 1} =
+ " (ID integer, DATA varchar(10))" ++ TransStr),
+ {updated, 1} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++ " VALUES(1,'bar')"),
ok = odbc:commit(Ref, commit),
- {updated, 1} =
+ {updated, 1} =
odbc:sql_query(Ref, "UPDATE " ++ Table ++
- " SET DATA = 'foo' WHERE ID = 1"),
+ " SET DATA = 'foo' WHERE ID = 1"),
ok = odbc:commit(Ref, rollback),
InsertResult = ?RDBMS:insert_result(),
- InsertResult =
+ InsertResult =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
-
- {updated, 1} =
+ {updated, 1} =
odbc:sql_query(Ref, "UPDATE " ++ Table ++
- " SET DATA = 'foo' WHERE ID = 1"),
+ " SET DATA = 'foo' WHERE ID = 1"),
ok = odbc:commit(Ref, rollback, ?TIMEOUT),
InsertResult = ?RDBMS:insert_result(),
- InsertResult =
+ InsertResult =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
+ {'EXIT', {function_clause, _}} =
+ (catch odbc:commit(Ref, rollback, -1)),
- {'EXIT', {function_clause, _}} =
- (catch odbc:commit(Ref, rollback, -1)),
-
- ok = odbc:disconnect(Ref),
- ok.
+ ok = odbc:disconnect(Ref).
%%-------------------------------------------------------------------------
not_explicit_commit(doc) ->
@@ -224,20 +230,20 @@ not_explicit_commit(doc) ->
not_explicit_commit(suite) -> [];
not_explicit_commit(_Config) ->
{ok, Ref} =
- odbc:connect(?RDBMS:connection_string(), [{auto_commit, on}]),
+ odbc:connect(?RDBMS:connection_string(), [{auto_commit, on}] ++
+ odbc_test_lib:platform_options()),
{error, _} = odbc:commit(Ref, commit),
- ok = odbc:disconnect(Ref),
- ok.
+ ok = odbc:disconnect(Ref).
%%-------------------------------------------------------------------------
not_exist_db(doc) ->
["Tests valid data format but invalid data in the connection parameters."];
not_exist_db(suite) -> [];
not_exist_db(_Config) ->
- {error, _} = odbc:connect("DSN=foo;UID=bar;PWD=foobar", []),
+ {error, _} = odbc:connect("DSN=foo;UID=bar;PWD=foobar",
+ odbc_test_lib:platform_options()),
%% So that the odbc control server can be stoped "in the correct way"
- test_server:sleep(100),
- ok.
+ test_server:sleep(100).
%%-------------------------------------------------------------------------
no_c_node(doc) ->
@@ -252,7 +258,8 @@ no_c_node(_Config) ->
FileName2 = filename:nativename(filename:join(Dir, "odbcsrv")),
ok = file:rename(FileName1, FileName2),
Result =
- case catch odbc:connect(?RDBMS:connection_string(), []) of
+ case catch odbc:connect(?RDBMS:connection_string(),
+ odbc_test_lib:platform_options()) of
{error, port_program_executable_not_found} ->
ok;
Else ->
@@ -267,7 +274,7 @@ port_dies(doc) ->
"Tests what happens if the port program dies";
port_dies(suite) -> [];
port_dies(_Config) ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
{status, _} = process_info(Ref, status),
process_flag(trap_exit, true),
Port = lists:last(erlang:ports()),
@@ -275,26 +282,23 @@ port_dies(_Config) ->
%% Wait for exit_status from port 5000 ms (will not get a exit
%% status in this case), then wait a little longer to make sure
%% the port and the controlprocess has had time to terminate.
- test_server:sleep(7000),
- undefined = process_info(Ref, status),
- ok.
+ test_server:sleep(10000),
+ undefined = process_info(Ref, status).
%%-------------------------------------------------------------------------
control_process_dies(doc) ->
"Tests what happens if the Erlang control process dies";
control_process_dies(suite) -> [];
control_process_dies(_Config) ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
process_flag(trap_exit, true),
Port = lists:last(erlang:ports()),
{connected, Ref} = erlang:port_info(Port, connected),
exit(Ref, kill),
- test_server:sleep(100),
- undefined = erlang:port_info(Port, connected),
+ test_server:sleep(500),
+ undefined = erlang:port_info(Port, connected).
%% Check for c-program still running, how?
- ok.
-%%-------------------------------------------------------------------------
%%-------------------------------------------------------------------------
client_dies_normal(doc) ->
@@ -319,7 +323,7 @@ client_dies_normal(Config) when is_list(Config) ->
end.
client_normal(Pid) ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
Pid ! {dbRef, Ref},
receive
continue ->
@@ -351,7 +355,7 @@ client_dies_timeout(Config) when is_list(Config) ->
end.
client_timeout(Pid) ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
Pid ! {dbRef, Ref},
receive
continue ->
@@ -383,7 +387,7 @@ client_dies_error(Config) when is_list(Config) ->
end.
client_error(Pid) ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
Pid ! {dbRef, Ref},
receive
continue ->
@@ -398,7 +402,10 @@ connect_timeout(doc) ->
connect_timeout(suite) -> [];
connect_timeout(Config) when is_list(Config) ->
{'EXIT',timeout} = (catch odbc:connect(?RDBMS:connection_string(),
- [{timeout, 0}])),
+ [{timeout, 0}] ++
+ odbc_test_lib:platform_options())),
+ %% Need to return ok here "{'EXIT',timeout} return value" will
+ %% be interpreted as that the testcase has timed out.
ok.
%%-------------------------------------------------------------------------
timeout(doc) ->
@@ -411,10 +418,12 @@ timeout(Config) when is_list(Config) ->
[{auto_commit, off}]),
Table = ?config(tableName, Config),
+ TransStr = transaction_support_str(?RDBMS),
+
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
- " (ID integer, DATA varchar(10), PRIMARY KEY(ID))"),
+ " (ID integer, DATA varchar(10), PRIMARY KEY(ID))" ++ TransStr),
{updated, 1} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++ " VALUES(1,'bar')"),
@@ -446,14 +455,12 @@ timeout(Config) when is_list(Config) ->
["DATA"] = odbc_test_lib:to_upper(Fields),
ok = odbc:commit(Ref, commit),
- ok = odbc:disconnect(Ref),
- ok.
-
+ ok = odbc:disconnect(Ref).
update_table_timeout(Table, TimeOut, Pid) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
UpdateQuery = "UPDATE " ++ Table ++ " SET DATA = 'foobar' WHERE ID = 1",
case catch odbc:sql_query(Ref, UpdateQuery, TimeOut) of
@@ -474,15 +481,16 @@ update_table_timeout(Table, TimeOut, Pid) ->
odbc:sql_query(Ref, "SELECT DATA FROM " ++ Table ++ " WHERE ID = 2"),
["DATA"] = odbc_test_lib:to_upper(Fields),
- {updated, 1} = odbc:sql_query(Ref, UpdateQuery, TimeOut),
+ %% Do not check {updated, 1} as some drivers will return 0
+ %% even though the update is done, which is checked by the test
+ %% case when the altered message is recived.
+ {updated, _} = odbc:sql_query(Ref, UpdateQuery, TimeOut),
ok = odbc:commit(Ref, commit),
Pid ! altered,
- ok = odbc:disconnect(Ref),
-
- ok.
+ ok = odbc:disconnect(Ref).
%%-------------------------------------------------------------------------
many_timeouts(doc) ->
["Tests that many consecutive timeouts lead to that the connection "
@@ -490,14 +498,15 @@ many_timeouts(doc) ->
many_timeouts(suite) -> [];
many_timeouts(Config) when is_list(Config) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
Table = ?config(tableName, Config),
+ TransStr = transaction_support_str(?RDBMS),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
- " (ID integer, DATA varchar(10), PRIMARY KEY(ID))"),
+ " (ID integer, DATA varchar(10), PRIMARY KEY(ID))" ++ TransStr),
{updated, 1} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++ " VALUES(1,'bar')"),
@@ -517,22 +526,20 @@ many_timeouts(Config) when is_list(Config) ->
end,
ok = odbc:commit(Ref, commit),
- ok = odbc:disconnect(Ref),
- ok.
+ ok = odbc:disconnect(Ref).
update_table_many_timeouts(Table, TimeOut, Pid) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
UpdateQuery = "UPDATE " ++ Table ++ " SET DATA = 'foobar' WHERE ID = 1",
ok = loop_many_timouts(Ref, UpdateQuery, TimeOut),
Pid ! many_timeouts_occurred,
- ok = odbc:disconnect(Ref),
- ok.
+ ok = odbc:disconnect(Ref).
loop_many_timouts(Ref, UpdateQuery, TimeOut) ->
@@ -546,18 +553,19 @@ loop_many_timouts(Ref, UpdateQuery, TimeOut) ->
end.
%%-------------------------------------------------------------------------
timeout_reset(doc) ->
- ["Check that the number of consecutive timouts is reset to 0 when "
+ ["Check that the number of consecutive timouts is reset to 0 when "
"a successful call to the database is made."];
timeout_reset(suite) -> [];
timeout_reset(Config) when is_list(Config) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
Table = ?config(tableName, Config),
+ TransStr = transaction_support_str(?RDBMS),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
- " (ID integer, DATA varchar(10), PRIMARY KEY(ID))"),
+ " (ID integer, DATA varchar(10), PRIMARY KEY(ID))" ++ TransStr),
{updated, 1} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++ " VALUES(1,'bar')"),
@@ -593,13 +601,12 @@ timeout_reset(Config) when is_list(Config) ->
["DATA"] = odbc_test_lib:to_upper(Fields),
ok = odbc:commit(Ref, commit),
- ok = odbc:disconnect(Ref),
- ok.
+ ok = odbc:disconnect(Ref).
update_table_timeout_reset(Table, TimeOut, Pid) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
UpdateQuery = "UPDATE " ++ Table ++ " SET DATA = 'foobar' WHERE ID = 1",
ok = loop_timout_reset(Ref, UpdateQuery, TimeOut,
@@ -616,15 +623,16 @@ update_table_timeout_reset(Table, TimeOut, Pid) ->
odbc:sql_query(Ref, "SELECT DATA FROM " ++ Table ++ " WHERE ID = 2"),
["DATA"] = odbc_test_lib:to_upper(Fields),
- {updated,1} = odbc:sql_query(Ref, UpdateQuery, TimeOut),
+ %% Do not check {updated, 1} as some drivers will return 0
+ %% even though the update is done, which is checked by the test
+ %% case when the altered message is recived.
+ {updated, _} = odbc:sql_query(Ref, UpdateQuery, TimeOut),
ok = odbc:commit(Ref, commit),
Pid ! altered,
- ok = odbc:disconnect(Ref),
-
- ok.
+ ok = odbc:disconnect(Ref).
loop_timout_reset(_, _, _, 0) ->
ok;
@@ -648,13 +656,14 @@ disconnect_on_timeout(suite) -> [];
disconnect_on_timeout(Config) when is_list(Config) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
Table = ?config(tableName, Config),
+ TransStr = transaction_support_str(?RDBMS),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
- " (ID integer, DATA varchar(10), PRIMARY KEY(ID))"),
+ " (ID integer, DATA varchar(10), PRIMARY KEY(ID))" ++ TransStr),
{updated, 1} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++ " VALUES(1,'bar')"),
@@ -678,7 +687,7 @@ disconnect_on_timeout(Config) when is_list(Config) ->
update_table_disconnect_on_timeout(Table, TimeOut, Pid) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
UpdateQuery = "UPDATE " ++ Table ++ " SET DATA = 'foobar' WHERE ID = 1",
case catch odbc:sql_query(Ref, UpdateQuery, TimeOut) of
@@ -695,7 +704,7 @@ connection_closed(doc) ->
" use a connection that has been closed"];
connection_closed(suite) -> [];
connection_closed(Config) when is_list(Config) ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
Table = ?config(tableName, Config),
{updated, _} =
@@ -714,8 +723,7 @@ connection_closed(Config) when is_list(Config) ->
{error, connection_closed} = odbc:next(Ref),
{error, connection_closed} = odbc:prev(Ref),
{error, connection_closed} = odbc:select(Ref, next, 3),
- {error, connection_closed} = odbc:commit(Ref, commit),
- ok.
+ {error, connection_closed} = odbc:commit(Ref, commit).
%%-------------------------------------------------------------------------
disable_scrollable_cursors(doc) ->
@@ -753,8 +761,7 @@ disable_scrollable_cursors(Config) when is_list(Config) ->
{error, scrollable_cursors_disabled} =
odbc:select(Ref, {absolute, 2}, 5),
- {selected, _ColNames,[]} = odbc:select(Ref, next, 1),
- ok.
+ {selected, _ColNames,[]} = odbc:select(Ref, next, 1).
%%-------------------------------------------------------------------------
return_rows_as_lists(doc)->
@@ -763,7 +770,7 @@ return_rows_as_lists(doc)->
return_rows_as_lists(suite) -> [];
return_rows_as_lists(Config) when is_list(Config) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{tuple_row, off}]),
+ [{tuple_row, off}] ++ odbc_test_lib:platform_options()),
Table = ?config(tableName, Config),
@@ -784,16 +791,21 @@ return_rows_as_lists(Config) when is_list(Config) ->
{ok, _} = odbc:select_count(Ref, "SELECT * FROM " ++ Table),
- First = ?RDBMS:first_list_rows(),
- Last = ?RDBMS:last_list_rows(),
- Prev = ?RDBMS:prev_list_rows(),
- Next = ?RDBMS:next_list_rows(),
-
- Last = odbc:last(Ref),
- Prev = odbc:prev(Ref),
- First = odbc:first(Ref),
- Next = odbc:next(Ref),
- ok.
+ case proplists:get_value(scrollable_cursors, odbc_test_lib:platform_options()) of
+ off ->
+ Next = ?RDBMS:next_list_rows(),
+ Next = odbc:next(Ref);
+ _ ->
+ First = ?RDBMS:first_list_rows(),
+ Last = ?RDBMS:last_list_rows(),
+ Prev = ?RDBMS:prev_list_rows(),
+ Next = ?RDBMS:next_list_rows(),
+
+ Last = odbc:last(Ref),
+ Prev = odbc:prev(Ref),
+ First = odbc:first(Ref),
+ Next = odbc:next(Ref)
+ end.
%%-------------------------------------------------------------------------
@@ -802,22 +814,27 @@ api_missuse(doc)->
api_missuse(suite) -> [];
api_missuse(Config) when is_list(Config)->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
%% Serious programming fault, connetion will be shut down
gen_server:call(Ref, {self(), foobar, 10}, infinity),
test_server:sleep(10),
undefined = process_info(Ref, status),
- {ok, Ref2} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref2} = odbc:connect(?RDBMS:connection_string(),
+ odbc_test_lib:platform_options()),
%% Serious programming fault, connetion will be shut down
gen_server:cast(Ref2, {self(), foobar, 10}),
test_server:sleep(10),
undefined = process_info(Ref2, status),
- {ok, Ref3} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref3} = odbc:connect(?RDBMS:connection_string(),
+ odbc_test_lib:platform_options()),
%% Could be an innocent misstake the connection lives.
Ref3 ! foobar,
test_server:sleep(10),
- {status, _} = process_info(Ref3, status),
- ok.
+ {status, _} = process_info(Ref3, status).
+transaction_support_str(mysql) ->
+ "ENGINE = InnoDB";
+transaction_support_str(_) ->
+ "".
diff --git a/lib/odbc/test/odbc_data_type_SUITE.erl b/lib/odbc/test/odbc_data_type_SUITE.erl
index bfb1e4b329..d61a91f973 100644
--- a/lib/odbc/test/odbc_data_type_SUITE.erl
+++ b/lib/odbc/test/odbc_data_type_SUITE.erl
@@ -44,24 +44,29 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
case odbc_test_lib:odbc_check() of
ok ->
- [{group, char}, {group, int}, {group, floats},
+ [{group, char},{group, fixed_char}, {group, binary_char},
+ {group, fixed_binary_char}, {group, unicode},
+ {group, int}, {group, floats},
{group, dec_and_num}, timestamp];
Other -> {skip, Other}
end.
groups() ->
[{char, [],
- [char_fixed_lower_limit, char_fixed_upper_limit,
- char_fixed_padding, varchar_lower_limit,
+ [varchar_lower_limit,
varchar_upper_limit, varchar_no_padding,
- text_lower_limit, text_upper_limit, unicode]},
+ text_lower_limit, text_upper_limit]},
+ {fixed_char, [],
+ [char_fixed_lower_limit, char_fixed_upper_limit,
+ char_fixed_padding]},
{binary_char, [],
- [binary_char_fixed_lower_limit,
- binary_char_fixed_upper_limit,
- binary_char_fixed_padding, binary_varchar_lower_limit,
+ [binary_varchar_lower_limit,
binary_varchar_upper_limit, binary_varchar_no_padding,
- binary_text_lower_limit, binary_text_upper_limit,
- unicode]},
+ binary_text_lower_limit, binary_text_upper_limit]},
+ {fixed_binary_char, [], [binary_char_fixed_lower_limit,
+ binary_char_fixed_upper_limit,
+ binary_char_fixed_padding]},
+ {unicode, [], [utf8, nchar, nvarchar]},
{int, [],
[tiny_int_lower_limit, tiny_int_upper_limit,
small_int_lower_limit, small_int_upper_limit,
@@ -74,14 +79,31 @@ groups() ->
[dec_long, dec_double, dec_bignum, num_long, num_double,
num_bignum]}].
+init_per_group(GroupName, Config) when GroupName == fixed_char;
+ GroupName == fixed_binary_char ->
+ case ?RDBMS of
+ mysql ->
+ {skip, "No supported by MYSQL"};
+ _ ->
+ Config
+ end;
+
+init_per_group(unicode, Config) ->
+ case {os:type(), erlang:system_info({wordsize, external})} of
+ {{unix, _}, 4} ->
+ Config;
+ {{unix, _}, _} ->
+ {skip, "Postgres drivers pre version psqlODBC 08.04.0200 have utf8-problems"};
+ _ ->
+ Config
+ end;
+
init_per_group(_GroupName, Config) ->
Config.
end_per_group(_GroupName, Config) ->
Config.
-
-
%%--------------------------------------------------------------------
%% Function: init_per_suite(Config) -> Config
%% Config - [tuple()]
@@ -91,10 +113,18 @@ end_per_group(_GroupName, Config) ->
%% Note: This function is free to add any key/value pairs to the Config
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
-init_per_suite(Config) ->
- application:start(odbc),
- [{tableName, odbc_test_lib:unique_table_name()} | Config].
-
+init_per_suite(Config) when is_list(Config) ->
+ case odbc_test_lib:skip() of
+ true ->
+ {skip, "ODBC not supported"};
+ false ->
+ case (catch odbc:start()) of
+ ok ->
+ [{tableName, odbc_test_lib:unique_table_name()}| Config];
+ _ ->
+ {skip, "ODBC not startable"}
+ end
+ end.
%%--------------------------------------------------------------------
%% Function: end_per_suite(Config) -> _
%% Config - [tuple()]
@@ -117,22 +147,81 @@ end_per_suite(_Config) ->
%% Note: This function is free to add any key/value pairs to the Config
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
+init_per_testcase(Case, Config) when Case == varchar_upper_limit;
+ Case == binary_varchar_upper_limit;
+ Case == varchar_no_padding;
+ Case == binary_varchar_no_padding ->
+ case is_fixed_upper_limit(?RDBMS) of
+ true ->
+ common_init_per_testcase(Case, Config);
+ false ->
+ {skip, "Upper limit is not fixed in" ++ atom_to_list(?RDBMS)}
+ end;
+
+init_per_testcase(text_upper_limit, _Config) ->
+ {skip, "Consumes too much resources"};
+
+init_per_testcase(Case, Config) when Case == bit_true; Case == bit_false ->
+ case is_supported_bit(?RDBMS) of
+ true ->
+ common_init_per_testcase(Case, Config);
+ false ->
+ {skip, "Not supported by driver"}
+ end;
+
+init_per_testcase(param_insert_tiny_int = Case, Config) ->
+ case is_supported_tinyint(?RDBMS) of
+ true ->
+ common_init_per_testcase(Case, Config);
+ false ->
+ {skip, "Not supported by driver"}
+ end;
+
+init_per_testcase(Case, Config) when Case == nchar;
+ Case == nvarchar ->
+ case ?RDBMS of
+ sqlserver ->
+ common_init_per_testcase(Case, Config);
+ _ ->
+ {skip, "Not supported by driver"}
+ end;
+
init_per_testcase(Case, Config) ->
+ common_init_per_testcase(Case, Config).
+
+common_init_per_testcase(Case, Config) ->
+ PlatformOptions = odbc_test_lib:platform_options(),
case atom_to_list(Case) of
"binary" ++ _ ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{binary_strings, on}]);
- "unicode" ->
+ [{binary_strings, on}] ++ PlatformOptions);
+ LCase when LCase == "utf8";
+ LCase == "nchar";
+ LCase == "nvarchar" ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{binary_strings, on}]);
+ [{binary_strings, on}] ++ PlatformOptions);
_ ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), [])
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), PlatformOptions)
end,
+ odbc_test_lib:strict(Ref, ?RDBMS),
Dog = test_server:timetrap(?default_timeout),
Temp = lists:keydelete(connection_ref, 1, Config),
NewConfig = lists:keydelete(watchdog, 1, Temp),
[{watchdog, Dog}, {connection_ref, Ref} | NewConfig].
+is_fixed_upper_limit(mysql) ->
+ false;
+is_fixed_upper_limit(_) ->
+ true.
+is_supported_tinyint(sqlserver) ->
+ true;
+is_supported_tinyint(_) ->
+ false.
+is_supported_bit(sqlserver) ->
+ true;
+is_supported_bit(_) ->
+ false.
+
%%--------------------------------------------------------------------
%% Function: end_per_testcase(Case, Config) -> _
%% Case - atom()
@@ -146,7 +235,7 @@ end_per_testcase(_TestCase, Config) ->
ok = odbc:disconnect(Ref),
%% Clean up if needed
Table = ?config(tableName, Config),
- {ok, NewRef} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, NewRef} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
odbc:sql_query(NewRef, "DROP TABLE " ++ Table),
odbc:disconnect(NewRef),
Dog = ?config(watchdog, Config),
@@ -169,18 +258,18 @@ char_fixed_lower_limit(Config) when is_list(Config) ->
{error, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
- ?RDBMS:create_fixed_char_table(
+ ?RDBMS:create_fixed_char_table(
(?RDBMS:fixed_char_min() - 1))),
%% Lower limit
{updated, _} = % Value == 0 || -1 driver dependent!
odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
- ?RDBMS:create_fixed_char_table(
- ?RDBMS:fixed_char_min())),
+ ?RDBMS:create_fixed_char_table(
+ ?RDBMS:fixed_char_min())),
%% Right length data
{updated, _} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
- "'" ++ string:chars($a, ?RDBMS:fixed_char_min())
+ "'" ++ string:chars($a, ?RDBMS:fixed_char_min())
++ "')"),
%% Select data
{selected, Fields,[{"a"}]} =
@@ -191,11 +280,11 @@ char_fixed_lower_limit(Config) when is_list(Config) ->
%% Too long data
{error, _} =
odbc:sql_query(Ref,"INSERT INTO " ++ Table ++" VALUES(" ++
- "'" ++ string:chars($a,
- (?RDBMS:fixed_char_min()
- + 1))
- ++ "')"),
- ok.
+ "'" ++ string:chars($a,
+ (?RDBMS:fixed_char_min()
+ + 1))
+ ++ "')").
+
%%-------------------------------------------------------------------------
char_fixed_upper_limit(doc) ->
@@ -243,8 +332,7 @@ char_fixed_upper_limit(Config) when is_list(Config) ->
{error, _} =
odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
?RDBMS:create_fixed_char_table(
- (?RDBMS:fixed_char_max() + 1))),
- ok
+ (?RDBMS:fixed_char_max() + 1)))
end.
%%-------------------------------------------------------------------------
@@ -261,20 +349,20 @@ char_fixed_padding(Config) when is_list(Config) ->
%% Data should be padded with blanks
{updated, _} = % Value == 0 || -1 driver dependent!
odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
- ?RDBMS:create_fixed_char_table(
- ?RDBMS:fixed_char_max())),
+ ?RDBMS:create_fixed_char_table(
+ ?RDBMS:fixed_char_max())),
- {updated, _} =
+ {updated, _} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
- "'" ++ string:chars($a,
- ?RDBMS:fixed_char_min())
+ "'" ++ string:chars($a,
+ ?RDBMS:fixed_char_min())
++ "')"),
{selected, Fields, [{CharStr}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
true = length(CharStr) == ?RDBMS:fixed_char_max(),
- ["FIELD"] = odbc_test_lib:to_upper(Fields),
- ok.
+ ["FIELD"] = odbc_test_lib:to_upper(Fields).
+
%%-------------------------------------------------------------------------
varchar_lower_limit(doc) ->
@@ -287,33 +375,33 @@ varchar_lower_limit(Config) when is_list(Config) ->
%% Below limit
{error, _} =
- odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
- ?RDBMS:create_var_char_table(
- ?RDBMS:var_char_min() - 1)),
+ odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
+ ?RDBMS:create_var_char_table(
+ ?RDBMS:var_char_min() - 1)),
%% Lower limit
{updated, _} = % Value == 0 || -1 driver dependent!
odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
- ?RDBMS:create_var_char_table(
- ?RDBMS:var_char_min())),
+ ?RDBMS:create_var_char_table(
+ ?RDBMS:var_char_min())),
+
+ Str = string:chars($a, ?RDBMS:var_char_min()),
%% Right length data
{updated, _} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
- "'" ++ string:chars($a, ?RDBMS:var_char_min())
- ++ "')"),
+ "'" ++ Str ++ "')"),
%% Select data
- {selected, Fields, [{"a"}]} =
+ {selected, Fields, [{Str}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
["FIELD"] = odbc_test_lib:to_upper(Fields),
- %% Too long data
- {error, _} =
- odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
- "'" ++ string:chars($a,
- (?RDBMS:var_char_min()+1))
- ++ "')"),
- ok.
+ %% Too long datae
+ {error, _} =
+ odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
+ "'" ++ string:chars($a,
+ (?RDBMS:var_char_min()+1))
+ ++ "')").
%%-------------------------------------------------------------------------
@@ -389,8 +477,7 @@ varchar_no_padding(Config) when is_list(Config) ->
{selected, Fields, [{CharStr}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
true = length(CharStr) /= ?RDBMS:var_char_max(),
- ["FIELD"] = odbc_test_lib:to_upper(Fields),
- ok.
+ ["FIELD"] = odbc_test_lib:to_upper(Fields).
%%-------------------------------------------------------------------------
@@ -413,8 +500,7 @@ text_lower_limit(Config) when is_list(Config) ->
{selected, Fields, [{"a"}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
- ["FIELD"] = odbc_test_lib:to_upper(Fields),
- ok.
+ ["FIELD"] = odbc_test_lib:to_upper(Fields).
%%-------------------------------------------------------------------------
@@ -444,8 +530,7 @@ text_upper_limit(Config) when is_list(Config) ->
%% {error, _} =
%% odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
%% "'" ++ string:chars($a, (?RDBMS:text_max()+1))
-%% ++ "')"),
-%% ok.
+%% ++ "')").
%%-------------------------------------------------------------------------
@@ -469,13 +554,18 @@ binary_char_fixed_lower_limit(Config) when is_list(Config) ->
?RDBMS:create_fixed_char_table(
?RDBMS:fixed_char_min())),
+ Str = string:chars($a, ?RDBMS:fixed_char_min()),
+
%% Right length data
{updated, _} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
- "'" ++ string:chars($a, ?RDBMS:fixed_char_min())
+ "'" ++ Str
++ "')"),
+
+ Bin = list_to_binary(Str),
+
%% Select data
- {selected, Fields,[{<<"a">>}]} =
+ {selected, Fields,[{Bin}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
["FIELD"] = odbc_test_lib:to_upper(Fields),
@@ -486,8 +576,7 @@ binary_char_fixed_lower_limit(Config) when is_list(Config) ->
"'" ++ string:chars($a,
(?RDBMS:fixed_char_min()
+ 1))
- ++ "')"),
- ok.
+ ++ "')").
%%-------------------------------------------------------------------------
binary_char_fixed_upper_limit(doc) ->
@@ -565,8 +654,8 @@ binary_char_fixed_padding(Config) when is_list(Config) ->
{selected, Fields, [{CharBin}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
true = size(CharBin) == ?RDBMS:fixed_char_max(),
- ["FIELD"] = odbc_test_lib:to_upper(Fields),
- ok.
+ ["FIELD"] = odbc_test_lib:to_upper(Fields).
+
%%-------------------------------------------------------------------------
binary_varchar_lower_limit(doc) ->
@@ -588,13 +677,17 @@ binary_varchar_lower_limit(Config) when is_list(Config) ->
?RDBMS:create_var_char_table(
?RDBMS:var_char_min())),
+ Str = string:chars($a, ?RDBMS:var_char_min()),
+
%% Right length data
{updated, _} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
- "'" ++ string:chars($a, ?RDBMS:var_char_min())
+ "'" ++ Str
++ "')"),
+ BinStr = list_to_binary(Str),
+
%% Select data
- {selected, Fields, [{<<"a">>}]} =
+ {selected, Fields, [{BinStr}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
["FIELD"] = odbc_test_lib:to_upper(Fields),
@@ -604,8 +697,7 @@ binary_varchar_lower_limit(Config) when is_list(Config) ->
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
"'" ++ string:chars($a,
(?RDBMS:var_char_min()+1))
- ++ "')"),
- ok.
+ ++ "')").
%%-------------------------------------------------------------------------
@@ -654,8 +746,7 @@ binary_varchar_upper_limit(Config) when is_list(Config) ->
{error, _} =
odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
?RDBMS:create_var_char_table(
- (?RDBMS:var_char_max() + 1))),
- ok
+ (?RDBMS:var_char_max() + 1)))
end.
%%-------------------------------------------------------------------------
@@ -681,8 +772,7 @@ binary_varchar_no_padding(Config) when is_list(Config) ->
{selected, Fields, [{CharBin}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
true = size(CharBin) /= ?RDBMS:var_char_max(),
- ["FIELD"] = odbc_test_lib:to_upper(Fields),
- ok.
+ ["FIELD"] = odbc_test_lib:to_upper(Fields).
%%-------------------------------------------------------------------------
@@ -705,8 +795,7 @@ binary_text_lower_limit(Config) when is_list(Config) ->
{selected, Fields, [{<<"a">>}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
- ["FIELD"] = odbc_test_lib:to_upper(Fields),
- ok.
+ ["FIELD"] = odbc_test_lib:to_upper(Fields).
%%-------------------------------------------------------------------------
@@ -736,11 +825,7 @@ binary_text_upper_limit(Config) when is_list(Config) ->
%% {error, _} =
%% odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
%% "'" ++ string:chars($a, (?RDBMS:text_max()+1))
-%% ++ "')"),
-%% ok.
-
-
-%%-------------------------------------------------------------------------
+%% ++ "')").
%%-------------------------------------------------------------------------
@@ -774,8 +859,7 @@ tiny_int_lower_limit(Config) when is_list(Config) ->
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
"'" ++ integer_to_list(?RDBMS:tiny_int_min()
- 1)
- ++ "')"),
- ok
+ ++ "')")
end.
%%-------------------------------------------------------------------------
@@ -809,8 +893,7 @@ tiny_int_upper_limit(Config) when is_list(Config) ->
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
"'" ++ integer_to_list(?RDBMS:tiny_int_max()
+ 1)
- ++ "')"),
- ok
+ ++ "')")
end.
%%-------------------------------------------------------------------------
@@ -840,8 +923,7 @@ small_int_lower_limit(Config) when is_list(Config) ->
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
"'" ++ integer_to_list(?RDBMS:small_int_min()
- 1)
- ++ "')"),
- ok.
+ ++ "')").
%%-------------------------------------------------------------------------
@@ -870,8 +952,7 @@ small_int_upper_limit(Config) when is_list(Config) ->
odbc:sql_query(Ref,"INSERT INTO " ++ Table ++" VALUES(" ++
"'" ++ integer_to_list(?RDBMS:small_int_max()
+ 1)
- ++ "')"),
- ok.
+ ++ "')").
%%-------------------------------------------------------------------------
int_lower_limit(doc) ->
@@ -898,8 +979,7 @@ int_lower_limit(Config) when is_list(Config) ->
{error, _} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
"'" ++ integer_to_list(?RDBMS:int_min() - 1)
- ++ "')"),
- ok.
+ ++ "')").
%%-------------------------------------------------------------------------
@@ -927,8 +1007,7 @@ int_upper_limit(Config) when is_list(Config) ->
{error, _} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
"'" ++ integer_to_list(?RDBMS:int_max() + 1)
- ++ "')"),
- ok.
+ ++ "')").
%%-------------------------------------------------------------------------
@@ -957,8 +1036,7 @@ big_int_lower_limit(Config) when is_list(Config) ->
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
"'" ++ integer_to_list(?RDBMS:big_int_min()
- 1)
- ++ "')"),
- ok.
+ ++ "')").
%%-------------------------------------------------------------------------
@@ -987,8 +1065,7 @@ big_int_upper_limit(Config) when is_list(Config) ->
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
"'" ++ integer_to_list(?RDBMS:big_int_max()
+ 1)
- ++ "')"),
- ok.
+ ++ "')").
%%-------------------------------------------------------------------------
bit_false(doc) ->
@@ -1020,8 +1097,7 @@ bit_false(Config) when is_list(Config) ->
{error, _} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
"'" ++ integer_to_list(-1)
- ++ "')"),
- ok
+ ++ "')")
end.
%%-------------------------------------------------------------------------
@@ -1056,14 +1132,10 @@ bit_true(Config) when is_list(Config) ->
{error, _} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
"'" ++ integer_to_list(-1)
- ++ "')"),
- ok
+ ++ "')")
end.
%%-------------------------------------------------------------------------
-
-
-%%-------------------------------------------------------------------------
float_lower_limit(doc) ->
[""];
float_lower_limit(suite) ->
@@ -1073,44 +1145,45 @@ float_lower_limit(Config) when is_list(Config) ->
Ref = ?config(connection_ref, Config),
Table = ?config(tableName, Config),
- {updated, _} = % Value == 0 || -1 driver dependent!
- odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
- ?RDBMS:create_float_table()),
-
- {updated, _} =
- odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
- "'" ++ float_to_list(
- ?RDBMS:float_min())
- ++ "')"),
- {selected,[_ColName],[{MinFloat}]} =
- odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
-
- true = ?RDBMS:float_min() == MinFloat,
-
case ?RDBMS of
- oracle ->
- {updated, _} = % Value == 0 || -1 driver dependent!
- odbc:sql_query(Ref, "DROP TABLE " ++ Table),
-
+ mysql ->
+ {skip, "Not clearly defined in MYSQL"};
+ _ ->
{updated, _} = % Value == 0 || -1 driver dependent!
odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
- ?RDBMS:create_float_table()),
+ ?RDBMS:create_float_table()),
{updated, _} =
- odbc:sql_query(Ref,
- "INSERT INTO " ++ Table ++" VALUES(" ++
- ?RDBMS:float_underflow() ++ ")"),
-
- SelectResult = ?RDBMS:float_zero_selected(),
- SelectResult =
- odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table);
- _ ->
- {error, _} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
- ?RDBMS:float_underflow() ++ ")")
- end,
- ok.
+ "'" ++ float_to_list(
+ ?RDBMS:float_min())
+ ++ "')"),
+ {selected,[_ColName],[{MinFloat}]} =
+ odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
+ true = ?RDBMS:float_min() == MinFloat,
+
+ case ?RDBMS of
+ oracle ->
+ {updated, _} = % Value == 0 || -1 driver dependent!
+ odbc:sql_query(Ref, "DROP TABLE " ++ Table),
+
+ {updated, _} = % Value == 0 || -1 driver dependent!
+ odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
+ ?RDBMS:create_float_table()),
+ {updated, _} =
+ odbc:sql_query(Ref,
+ "INSERT INTO " ++ Table ++" VALUES(" ++
+ ?RDBMS:float_underflow() ++ ")"),
+ SelectResult = ?RDBMS:float_zero_selected(),
+ SelectResult =
+ odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table);
+ _ ->
+ {error, _} =
+ odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
+ ?RDBMS:float_underflow() ++ ")")
+ end
+ end.
%%-------------------------------------------------------------------------
float_upper_limit(doc) ->
@@ -1121,26 +1194,28 @@ float_upper_limit(Config) when is_list(Config) ->
Ref = ?config(connection_ref, Config),
Table = ?config(tableName, Config),
- {updated, _} = % Value == 0 || -1 driver dependent!
- odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
- ?RDBMS:create_float_table()),
-
- {updated, _} =
- odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
- "'" ++ float_to_list(
- ?RDBMS:float_max())
- ++ "')"),
-
+ case ?RDBMS of
+ mysql ->
+ {skip, "Not clearly defined in MYSQL"};
+ _->
+ {updated, _} = % Value == 0 || -1 driver dependent!
+ odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
+ ?RDBMS:create_float_table()),
- {selected,[_ColName],[{MaxFloat}]}
- = odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
+ {updated, _} =
+ odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
+ "'" ++ float_to_list(
+ ?RDBMS:float_max())
+ ++ "')"),
+ {selected,[_ColName],[{MaxFloat}]}
+ = odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
- true = ?RDBMS:float_max() == MaxFloat,
+ true = ?RDBMS:float_max() == MaxFloat,
- {error, _} =
- odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
- ?RDBMS:float_overflow() ++ ")"),
- ok.
+ {error, _} =
+ odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
+ ?RDBMS:float_overflow() ++ ")")
+ end.
%%-------------------------------------------------------------------------
float_zero(doc) ->
@@ -1160,8 +1235,7 @@ float_zero(Config) when is_list(Config) ->
SelectResult = ?RDBMS:float_zero_selected(),
SelectResult =
- odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
- ok.
+ odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table).
%%-------------------------------------------------------------------------
real_zero(doc) ->
["Test the real value zero."];
@@ -1185,10 +1259,8 @@ real_zero(Config) when is_list(Config) ->
SelectResult = ?RDBMS:real_zero_selected(),
SelectResult =
- odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
- ok
+ odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table)
end.
-%%-------------------------------------------------------------------------
%%------------------------------------------------------------------------
dec_long(doc) ->
[""];
@@ -1207,8 +1279,7 @@ dec_long(Config) when is_list(Config) ->
{selected, Fields, [{2}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
- ["FIELD"] = odbc_test_lib:to_upper(Fields),
- ok.
+ ["FIELD"] = odbc_test_lib:to_upper(Fields).
%%------------------------------------------------------------------------
dec_double(doc) ->
[""];
@@ -1255,8 +1326,7 @@ dec_double(Config) when is_list(Config) ->
{selected, Fields2, [{1.60000}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
- ["FIELD"] = odbc_test_lib:to_upper(Fields2),
- ok.
+ ["FIELD"] = odbc_test_lib:to_upper(Fields2).
%%------------------------------------------------------------------------
dec_bignum(doc) ->
@@ -1289,8 +1359,7 @@ dec_bignum(Config) when is_list(Config) ->
{selected, Fields1, [{"1.6"}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
- ["FIELD"] = odbc_test_lib:to_upper(Fields1),
- ok.
+ ["FIELD"] = odbc_test_lib:to_upper(Fields1).
%%------------------------------------------------------------------------
num_long(doc) ->
[""];
@@ -1309,8 +1378,7 @@ num_long(Config) when is_list(Config) ->
{selected, Fields, [{2}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
- ["FIELD"] = odbc_test_lib:to_upper(Fields),
- ok.
+ ["FIELD"] = odbc_test_lib:to_upper(Fields).
%%------------------------------------------------------------------------
num_double(doc) ->
[""];
@@ -1356,8 +1424,7 @@ num_double(Config) when is_list(Config) ->
{selected, Fields2, [{1.6000}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
- ["FIELD"] = odbc_test_lib:to_upper(Fields2),
- ok.
+ ["FIELD"] = odbc_test_lib:to_upper(Fields2).
%%------------------------------------------------------------------------
num_bignum(doc) ->
[""];
@@ -1389,21 +1456,19 @@ num_bignum(Config) when is_list(Config) ->
{selected, Fields1, [{"1.6"}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
- ["FIELD"] = odbc_test_lib:to_upper(Fields1),
- ok.
+ ["FIELD"] = odbc_test_lib:to_upper(Fields1).
%%------------------------------------------------------------------------
-unicode(doc) ->
+utf8(doc) ->
["Test unicode support"];
-unicode(suit) ->
+utf8(suit) ->
[];
-unicode(Config) when is_list(Config) ->
+utf8(Config) when is_list(Config) ->
Ref = ?config(connection_ref, Config),
Table = ?config(tableName, Config),
- {updated, _} = % Value == 0 || -1 driver dependent!
- odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
- ?RDBMS:create_unicode_table()),
+ odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++ "(FIELD text)"),
+
Latin1Data = ["���������",
"testasdf",
"Row 3",
@@ -1416,39 +1481,7 @@ unicode(Config) when is_list(Config) ->
"Row 10",
"Row 11",
"Row 12"],
-
- case ?RDBMS of
- sqlserver ->
- w_char_support_win(Ref, Table, Latin1Data);
- postgres ->
- direct_utf8(Ref, Table, Latin1Data);
- oracle ->
- {skip, "not currently supported"}
- end.
-
-w_char_support_win(Ref, Table, Latin1Data) ->
- UnicodeIn = lists:map(fun(S) ->
- unicode:characters_to_binary(S,latin1,{utf16,little})
- end,
- Latin1Data),
-
- test_server:format("UnicodeIn (utf 16): ~p ~n",[UnicodeIn]),
- {updated, _} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++ "(FIELD) values(?)",
- [{{sql_wvarchar,50},UnicodeIn}]),
-
- {selected,_,UnicodeOut} = odbc:sql_query(Ref,"SELECT * FROM " ++ Table),
-
- test_server:format("UnicodeOut: ~p~n", [UnicodeOut]),
-
- Result = lists:map(fun({Unicode}) ->
- unicode:characters_to_list(Unicode,{utf16,little})
- end,
- UnicodeOut),
- Latin1Data = Result.
-
-
-direct_utf8(Ref, Table, Latin1Data) ->
UnicodeIn = lists:map(fun(String) ->
unicode:characters_to_binary(String,latin1,utf8)
end,
@@ -1469,6 +1502,37 @@ direct_utf8(Ref, Table, Latin1Data) ->
test_server:format("Result: ~p ~n", [Result]),
Latin1Data = Result.
+%%------------------------------------------------------------------------
+
+nchar(doc) ->
+ ["Test unicode nchar support in sqlserver"];
+nchar(suit) ->
+ [];
+nchar(Config) when is_list(Config) ->
+ Ref = ?config(connection_ref, Config),
+ Table = ?config(tableName, Config),
+
+ {updated, _} = % Value == 0 || -1 driver dependent!
+ odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
+ "(FIELD nchar(50))"),
+
+ w_char_support(Ref, Table, sql_wvarchar, 50).
+
+%%------------------------------------------------------------------------
+
+nvarchar(doc) ->
+ ["Test 'unicode' nvarchar support"];
+nvarchar(suit) ->
+ [];
+nvarchar(Config) when is_list(Config) ->
+ Ref = ?config(connection_ref, Config),
+ Table = ?config(tableName, Config),
+
+ {updated, _} = % Value == 0 || -1 driver dependent!
+ odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
+ "(FIELD nvarchar(50))"),
+
+ w_char_support(Ref, Table, sql_wlongvarchar, 50).
%%------------------------------------------------------------------------
timestamp(doc) ->
@@ -1497,3 +1561,43 @@ timestamp(Config) when is_list(Config) ->
TimeStamps = lists:map(fun(Value) -> {Value} end, Data),
{selected,_, TimeStamps} = odbc:sql_query(Ref, "SELECT * FROM " ++ Table).
+%%------------------------------------------------------------------------
+
+w_char_support(Ref, Table, CharType, Size) ->
+ Latin1Data = ["���������",
+ "testasdf",
+ "Row 3",
+ "Row 4",
+ "Row 5",
+ "Row 6",
+ "Row 7",
+ "Row 8",
+ "Row 9",
+ "Row 10",
+ "Row 11",
+ "Row 12"],
+
+ UnicodeIn = lists:map(fun(S) ->
+ unicode:characters_to_binary(S,latin1,{utf16,little})
+ end,
+ Latin1Data),
+
+ test_server:format("UnicodeIn (utf 16): ~p ~n",[UnicodeIn]),
+
+ {updated, _} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++ "(FIELD) values(?)",
+ [{{CharType, Size},UnicodeIn}]),
+
+ {selected,_,UnicodeOut} = odbc:sql_query(Ref,"SELECT * FROM " ++ Table),
+
+ test_server:format("UnicodeOut: ~p~n", [UnicodeOut]),
+
+ PadResult = lists:map(fun({Unicode}) ->
+ unicode:characters_to_list(Unicode,{utf16,little})
+ end,
+ UnicodeOut),
+
+ test_server:format("Result: ~p~n", [PadResult]),
+
+ Result = lists:map(fun(Str) -> string:strip(Str) end, PadResult),
+
+ Latin1Data = Result.
diff --git a/lib/odbc/test/odbc_query_SUITE.erl b/lib/odbc/test/odbc_query_SUITE.erl
index 8b8d1e7a40..1852678b4b 100644
--- a/lib/odbc/test/odbc_query_SUITE.erl
+++ b/lib/odbc/test/odbc_query_SUITE.erl
@@ -43,19 +43,22 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
case odbc_test_lib:odbc_check() of
ok ->
- [sql_query, first, last, next, prev, select_count,
+ [sql_query, next, {group, scrollable_cursors}, select_count,
select_next, select_relative, select_absolute,
create_table_twice, delete_table_twice, duplicate_key,
not_connection_owner, no_result_set, query_error,
- multiple_select_result_sets, multiple_mix_result_sets,
- multiple_result_sets_error,
+ {group, multiple_result_sets},
{group, parameterized_queries}, {group, describe_table},
delete_nonexisting_row];
Other -> {skip, Other}
end.
groups() ->
- [{parameterized_queries, [],
+ [{multiple_result_sets, [], [multiple_select_result_sets,
+ multiple_mix_result_sets,
+ multiple_result_sets_error]},
+ {scrollable_cursors, [], [first, last, prev]},
+ {parameterized_queries, [],
[{group, param_integers}, param_insert_decimal,
param_insert_numeric, {group, param_insert_string},
param_insert_float, param_insert_real,
@@ -72,15 +75,27 @@ groups() ->
[describe_integer, describe_string, describe_floating,
describe_dec_num, describe_no_such_table]}].
-init_per_group(_GroupName, Config) ->
+init_per_group(multiple_result_sets, Config) ->
+ case is_supported_multiple_resultsets(?RDBMS) of
+ true ->
+ Config;
+ false ->
+ {skip, "Not supported by " ++ atom_to_list(?RDBMS) ++ "driver"}
+ end;
+init_per_group(scrollable_cursors, Config) ->
+ case proplists:get_value(scrollable_cursors, odbc_test_lib:platform_options()) of
+ off ->
+ {skip, "Not supported by driver"};
+ _ ->
+ Config
+ end;
+
+init_per_group(_,Config) ->
Config.
end_per_group(_GroupName, Config) ->
Config.
-
-
-
%%--------------------------------------------------------------------
%% Function: init_per_suite(Config) -> Config
%% Config - [tuple()]
@@ -91,8 +106,17 @@ end_per_group(_GroupName, Config) ->
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
init_per_suite(Config) when is_list(Config) ->
- application:start(odbc),
- [{tableName, odbc_test_lib:unique_table_name()}| Config].
+ case odbc_test_lib:skip() of
+ true ->
+ {skip, "ODBC not supported"};
+ false ->
+ case (catch odbc:start()) of
+ ok ->
+ [{tableName, odbc_test_lib:unique_table_name()}| Config];
+ _ ->
+ {skip, "ODBC not startable"}
+ end
+ end.
%%--------------------------------------------------------------------
%% Function: end_per_suite(Config) -> _
@@ -117,7 +141,8 @@ end_per_suite(_Config) ->
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
init_per_testcase(_Case, Config) ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
+ odbc_test_lib:strict(Ref, ?RDBMS),
Dog = test_server:timetrap(?default_timeout),
Temp = lists:keydelete(connection_ref, 1, Config),
NewConfig = lists:keydelete(watchdog, 1, Temp),
@@ -136,7 +161,7 @@ end_per_testcase(_Case, Config) ->
ok = odbc:disconnect(Ref),
%% Clean up if needed
Table = ?config(tableName, Config),
- {ok, NewRef} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, NewRef} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
odbc:sql_query(NewRef, "DROP TABLE " ++ Table),
odbc:disconnect(NewRef),
Dog = ?config(watchdog, Config),
@@ -663,9 +688,6 @@ multiple_result_sets_error(Config) when is_list(Config) ->
end.
%%-------------------------------------------------------------------------
-
-%%-------------------------------------------------------------------------
-%%-------------------------------------------------------------------------
param_insert_tiny_int(doc)->
["Test insertion of tiny ints by parameterized queries."];
param_insert_tiny_int(suite) ->
@@ -901,8 +923,6 @@ param_insert_numeric(Config) when is_list(Config) ->
ok.
%%-------------------------------------------------------------------------
-
-%%-------------------------------------------------------------------------
param_insert_char(doc)->
["Test insertion of fixed length string by parameterized queries."];
param_insert_char(suite) ->
@@ -1325,8 +1345,6 @@ param_select(Config) when is_list(Config) ->
ok.
%%-------------------------------------------------------------------------
-
-%%-------------------------------------------------------------------------
describe_integer(doc) ->
["Test describe_table/[2,3] for integer columns."];
describe_integer(suite) ->
@@ -1338,7 +1356,7 @@ describe_integer(Config) when is_list(Config) ->
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
- " (int1 SMALLINT, int2 INT, int3 INTEGER)"),
+ " (myint1 SMALLINT, myint2 INT, myint3 INTEGER)"),
Decs = ?RDBMS:describe_integer(),
%% Make sure to test timeout clause
@@ -1399,7 +1417,7 @@ describe_dec_num(Config) when is_list(Config) ->
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
- " (dec DECIMAL(9,3), num NUMERIC(9,2))"),
+ " (mydec DECIMAL(9,3), mynum NUMERIC(9,2))"),
Decs = ?RDBMS:describe_dec_num(),
@@ -1451,3 +1469,7 @@ is_driver_error(Error) ->
false ->
test_server:fail(Error)
end.
+is_supported_multiple_resultsets(sqlserver) ->
+ true;
+is_supported_multiple_resultsets(_) ->
+ false.
diff --git a/lib/odbc/test/odbc_start_SUITE.erl b/lib/odbc/test/odbc_start_SUITE.erl
index 65b990133f..e3a3440559 100644
--- a/lib/odbc/test/odbc_start_SUITE.erl
+++ b/lib/odbc/test/odbc_start_SUITE.erl
@@ -39,11 +39,18 @@
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- case code:which(odbc) of
- non_existing ->
- {skip, "No ODBC built"};
- _ ->
- [{tableName, odbc_test_lib:unique_table_name()} | Config]
+ case odbc_test_lib:skip() of
+ true ->
+ {skip, "ODBC not supported"};
+ false ->
+ case code:which(odbc) of
+ non_existing ->
+ {skip, "No ODBC built"};
+ _ ->
+ %% Make sure odbc is not already started
+ odbc:stop(),
+ [{tableName, odbc_test_lib:unique_table_name()} | Config]
+ end
end.
%%--------------------------------------------------------------------
@@ -125,14 +132,16 @@ start(doc) ->
start(suite) ->
[];
start(Config) when is_list(Config) ->
- {error,odbc_not_started} = odbc:connect(?RDBMS:connection_string(), []),
+ PlatformOptions = odbc_test_lib:platform_options(),
+ {error,odbc_not_started} = odbc:connect(?RDBMS:connection_string(),
+ PlatformOptions),
odbc:start(),
- case odbc:connect(?RDBMS:connection_string(), []) of
+ case odbc:connect(?RDBMS:connection_string(), PlatformOptions) of
{ok, Ref0} ->
ok = odbc:disconnect(Ref0),
odbc:stop(),
{error,odbc_not_started} =
- odbc:connect(?RDBMS:connection_string(), []),
+ odbc:connect(?RDBMS:connection_string(), PlatformOptions),
start_odbc(transient),
start_odbc(permanent);
{error, odbc_not_started} ->
@@ -144,7 +153,7 @@ start(Config) when is_list(Config) ->
start_odbc(Type) ->
ok = odbc:start(Type),
- case odbc:connect(?RDBMS:connection_string(), []) of
+ case odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()) of
{ok, Ref} ->
ok = odbc:disconnect(Ref),
odbc:stop();
diff --git a/lib/odbc/test/odbc_test.hrl b/lib/odbc/test/odbc_test.hrl
index 87f50043db..f7bb338a7f 100644
--- a/lib/odbc/test/odbc_test.hrl
+++ b/lib/odbc/test/odbc_test.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -25,9 +25,16 @@
-define(RDBMS, case os:type() of
{unix, sunos} ->
- postgres;
+ mysql;
{unix,linux} ->
- postgres;
+ case erlang:system_info({wordsize, external}) of
+ 4 ->
+ mysql;
+ _ ->
+ postgres
+ end;
+ {unix, darwin} ->
+ mysql;
{win32, _} ->
sqlserver
end).
diff --git a/lib/odbc/test/odbc_test_lib.erl b/lib/odbc/test/odbc_test_lib.erl
index 012eb96e43..a8439d5fb6 100644
--- a/lib/odbc/test/odbc_test_lib.erl
+++ b/lib/odbc/test/odbc_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -36,29 +36,25 @@ match_float(Float, Match, Delta) ->
(Float < Match + Delta) and (Float > Match - Delta).
odbc_check() ->
- case erlang:system_info(wordsize) of
- 4 ->
- case test_server:os_type() of
- {unix, sunos} ->
- ok;
- {unix, linux} ->
- ok;
- {win32, _} ->
+ case os:type() of
+ {unix,darwin} ->
+ lists:flatten(
+ io_lib:format("Currently we have no working drivers for MAC",
+ []));
+ _ ->
+ case erlang:system_info({wordsize, external}) of
+ 4 ->
ok;
Other ->
- lists:flatten(
- io_lib:format("Platform not supported: ~w",
- [Other]))
- end;
- Other ->
- case os:type() of
- {unix, linux} ->
- ok;
- Platform ->
- lists:flatten(
- io_lib:format("Word on platform ~w size"
- " ~w not supported", [Other,
- Platform]))
+ case os:type() of
+ {unix, linux} ->
+ ok;
+ Platform ->
+ lists:flatten(
+ io_lib:format("Word on platform ~w size"
+ " ~w not supported", [Other,
+ Platform]))
+ end
end
end.
@@ -75,3 +71,46 @@ check_row_count(Expected, Count) ->
to_upper(List) ->
lists:map(fun(Str) -> string:to_upper(Str) end, List).
+
+strict(Ref, mysql) ->
+ odbc:sql_query(Ref, "SET sql_mode='STRICT_ALL_TABLES,STRICT_TRANS_TABLES';");
+strict(_,_) ->
+ ok.
+
+platform_options() ->
+ [].
+
+skip() ->
+ case os:type() of
+ {unix, linux} ->
+ Issue = linux_issue(),
+ is_sles9(Issue);
+ {unix, sunos} ->
+ not supported_solaris();
+ _ ->
+ false
+ end.
+
+supported_solaris() ->
+ case os:version() of
+ {_,10,_} ->
+ true;
+ _ ->
+ false
+ end.
+
+linux_issue() ->
+ {ok, Binary} = file:read_file("/etc/issue"),
+ string:tokens(binary_to_list(Binary), " ").
+
+is_sles11(IssueTokens) ->
+ lists:member("11", IssueTokens).
+
+is_sles10(IssueTokens) ->
+ lists:member("10", IssueTokens).
+
+is_sles9(IssueTokens) ->
+ lists:member("9", IssueTokens).
+
+is_ubuntu(IssueTokens) ->
+ lists:member("Ubuntu", IssueTokens).
diff --git a/lib/odbc/test/oracle.erl b/lib/odbc/test/oracle.erl
index ebf6dbb6bf..d74863d8c1 100644
--- a/lib/odbc/test/oracle.erl
+++ b/lib/odbc/test/oracle.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -108,10 +108,6 @@ create_text_table() ->
" (FIELD long)". %Oracle long is variable length char data
%-------------------------------------------------------------------------
-create_unicode_table() ->
- " (FIELD nvarchar(50))".
-
-%-------------------------------------------------------------------------
create_timestamp_table() ->
" (FIELD DATETIME)".
@@ -231,8 +227,8 @@ param_select() ->
%-------------------------------------------------------------------------
describe_integer() ->
- {ok,[{"INT1",{sql_decimal,38,0}},{"INT2",{sql_decimal,38,0}},
- {"INT3",{sql_decimal,38,0}}]}.
+ {ok,[{"MYINT1",{sql_decimal,38,0}},{"MYINT2",{sql_decimal,38,0}},
+ {"MYINT3",{sql_decimal,38,0}}]}.
describe_string() ->
{ok,[{"STR1",{sql_char,10}},
@@ -243,4 +239,4 @@ describe_string() ->
describe_floating() ->
{ok,[{"F",sql_double},{"R",sql_double},{"D",sql_double}]}.
describe_dec_num() ->
- {ok,[{"DEC",{sql_decimal,9,3}},{"NUM",{sql_decimal,9,2}}]}.
+ {ok,[{"MYDEC",{sql_decimal,9,3}},{"MYNUM",{sql_decimal,9,2}}]}.
diff --git a/lib/odbc/test/postgres.erl b/lib/odbc/test/postgres.erl
index 169ca26e43..d564dbd5ff 100644
--- a/lib/odbc/test/postgres.erl
+++ b/lib/odbc/test/postgres.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -30,7 +30,7 @@ connection_string() ->
{unix, sunos} ->
"DSN=Postgres;UID=odbctest";
{unix, linux} ->
- Size = erlang:system_info(wordsize),
+ Size = erlang:system_info({wordsize, external}),
linux_dist_connection_string(Size)
end.
@@ -43,7 +43,12 @@ linux_dist_connection_string(4) ->
end;
linux_dist_connection_string(_) ->
- "DSN=PostgresLinux64;UID=odbctest".
+ case linux_dist() of
+ "ubuntu" ->
+ "DSN=PostgresLinux64Ubuntu;UID=odbctest";
+ _ ->
+ "DSN=PostgresLinux64;UID=odbctest"
+ end.
linux_dist() ->
case file:read_file("/etc/issue") of
@@ -135,10 +140,6 @@ create_text_table() ->
" (FIELD text)".
%-------------------------------------------------------------------------
-create_unicode_table() ->
- " (FIELD text)".
-
-%-------------------------------------------------------------------------
create_timestamp_table() ->
" (FIELD TIMESTAMP)".
@@ -275,9 +276,9 @@ param_select() ->
%-------------------------------------------------------------------------
describe_integer() ->
- {ok,[{"int1",sql_smallint},
- {"int2",sql_integer},
- {"int3",sql_integer}]}.
+ {ok,[{"myint1",sql_smallint},
+ {"myint2",sql_integer},
+ {"myint3",sql_integer}]}.
describe_string() ->
{ok,[{"str1",{sql_char,10}},
@@ -288,7 +289,7 @@ describe_string() ->
describe_floating() ->
{ok,[{"f",sql_real},{"r",sql_real},{"d",{sql_float,15}}]}.
describe_dec_num() ->
- {ok,[{"dec",{sql_numeric,9,3}},{"num",{sql_numeric,9,2}}]}.
+ {ok,[{"mydec",{sql_numeric,9,3}},{"mynum",{sql_numeric,9,2}}]}.
describe_timestamp() ->
{ok, [{"field", sql_timestamp}]}.
diff --git a/lib/odbc/test/sqlserver.erl b/lib/odbc/test/sqlserver.erl
index e3fe30e0bc..59252d4276 100644
--- a/lib/odbc/test/sqlserver.erl
+++ b/lib/odbc/test/sqlserver.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -123,10 +123,6 @@ create_text_table() ->
" (FIELD text)".
%-------------------------------------------------------------------------
-create_unicode_table() ->
- " (FIELD nvarchar(50))".
-
-%-------------------------------------------------------------------------
create_timestamp_table() ->
" (FIELD DATETIME)".
@@ -279,8 +275,8 @@ param_select() ->
%-------------------------------------------------------------------------
describe_integer() ->
- {ok,[{"int1", sql_smallint},{"int2", sql_integer},
- {"int3", sql_integer}]}.
+ {ok,[{"myint1", sql_smallint},{"myint2", sql_integer},
+ {"myint3", sql_integer}]}.
describe_string() ->
{ok,[{"str1",{sql_char,10}},
@@ -292,7 +288,7 @@ describe_floating() ->
{ok,[{"f", sql_real},{"r", sql_real}, {"d", {sql_float, 53}}]}.
describe_dec_num() ->
- {ok,[{"dec",{sql_decimal,9,3}},{"num",{sql_numeric,9,2}}]}.
+ {ok,[{"mydec",{sql_decimal,9,3}},{"mynum",{sql_numeric,9,2}}]}.
describe_timestamp() ->
{ok, [{"field", sql_timestamp}]}.
diff --git a/lib/odbc/vsn.mk b/lib/odbc/vsn.mk
index 42a51be33e..120ed9ee3d 100644
--- a/lib/odbc/vsn.mk
+++ b/lib/odbc/vsn.mk
@@ -1 +1 @@
-ODBC_VSN = 2.10.10
+ODBC_VSN = 2.10.11
diff --git a/lib/orber/COSS/CosNaming/Makefile b/lib/orber/COSS/CosNaming/Makefile
index d3deec7600..d4b2079036 100644
--- a/lib/orber/COSS/CosNaming/Makefile
+++ b/lib/orber/COSS/CosNaming/Makefile
@@ -113,7 +113,7 @@ debug:
@${MAKE} TYPE=debug
clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET)
+ rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) IDL-GENERATED
rm -f errs core *~
$(APP_TARGET): $(APP_SRC)
@@ -124,13 +124,15 @@ docs:
# ----------------------------------------------------
# Special Build Targets
# ----------------------------------------------------
-$(GEN_FILES): cos_naming_ext.idl cos_naming.idl
+IDL-GENERATED: cos_naming_ext.idl cos_naming.idl
erlc $(ERL_IDL_FLAGS) +'{this,"CosNaming::NamingContext"}' \
+'{this,"CosNaming::NamingContextExt"}' cos_naming_ext.idl
erlc $(ERL_IDL_FLAGS) +'{this,"CosNaming::NamingContext"}' cos_naming.idl
+ >IDL-GENERATED
-# echo "ic:gen(cos_naming, [{this, \"CosNaming::NamingContext\"}]), halt()."| $(ERL) $(ERL_IDL_FLAGS)
+$(GEN_FILES): IDL-GENERATED
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Target
diff --git a/lib/orber/doc/src/Makefile b/lib/orber/doc/src/Makefile
index b8e26d5ba3..8a555cb408 100644
--- a/lib/orber/doc/src/Makefile
+++ b/lib/orber/doc/src/Makefile
@@ -28,14 +28,6 @@ VSN=$(ORBER_VSN)
APPLICATION=orber
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -128,32 +120,10 @@ EXTRA_FILES = summary.html.src \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -167,8 +137,6 @@ $(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -184,35 +152,6 @@ clean clean_docs:
rm -f errs core *~
rm -f $(JD_HTML) $(JD_PACK)
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES) $(INTERNAL_HTML_FILES)
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTMLDIR)/*
- rm -f $(MAN3DIR)/*
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ *xmls_output *xmls_errs $(LATEX_CLEAN)
- rm -f $(JD_HTML) $(JD_PACK)
-
-endif
-
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -224,9 +163,6 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-
-ifdef DOCSUPPORT
-
release_docs_spec: docs
$(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
$(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
@@ -236,30 +172,5 @@ release_docs_spec: docs
$(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
$(INSTALL_DIR) $(RELEASE_PATH)/man/man3
$(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-
-endif
-endif
-
-endif
release_spec:
-
diff --git a/lib/orber/doc/src/Orber/ignore_config_record.inf b/lib/orber/doc/src/Orber/ignore_config_record.inf
deleted file mode 100644
index 0a5053eba3..0000000000
--- a/lib/orber/doc/src/Orber/ignore_config_record.inf
+++ /dev/null
@@ -1 +0,0 @@
-This file makes clearmake use the -T switch for this subdirectory
diff --git a/lib/orber/doc/src/make.dep b/lib/orber/doc/src/make.dep
deleted file mode 100644
index cf5aad747d..0000000000
--- a/lib/orber/doc/src/make.dep
+++ /dev/null
@@ -1,62 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: CosNaming.tex CosNaming_BindingIterator.tex \
- CosNaming_NamingContext.tex CosNaming_NamingContextExt.tex \
- Module_Interface.tex any.tex book.tex ch_contents.tex \
- ch_debugging.tex ch_exceptions.tex \
- ch_idl_to_erlang_mapping.tex ch_ifr.tex ch_install.tex \
- ch_interceptors.tex ch_introduction.tex ch_naming_service.tex \
- ch_orber_kernel.tex ch_orberweb.tex ch_security.tex \
- ch_stubs.tex corba.tex corba_object.tex example_part.tex \
- fixed.tex interceptors.tex intro_part.tex \
- lname.tex lname_component.tex orber.tex orber_acl.tex \
- orber_diagnostics.tex orber_ifr.tex orber_tc.tex \
- ref_man.tex tools_debugging_part.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-ch_contents.tex: ../../../../system/doc/definitions/term.defs
-
-ch_idl_to_erlang_mapping.tex: ../../../../system/doc/definitions/term.defs
-
-ch_install.tex: ../../../../system/doc/definitions/term.defs
-
-ch_introduction.tex: ../../../../system/doc/definitions/term.defs
-
-ch_naming_service.tex: ../../../../system/doc/definitions/term.defs
-
-ch_orber_kernel.tex: ../../../../system/doc/definitions/term.defs
-
-orber_ifr.tex: ../../../../system/doc/definitions/term.defs
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: firewall_nat.ps
-
-book.dvi: interceptor_operations.ps
-
-book.dvi: dependent.ps orbs.ps
-
-book.dvi: name.ps
-
-book.dvi: iiop.ps theORB.ps
-
-book.dvi: dataframe1.ps dataframe2.ps dataframe3.ps \
- dataframe4.ps dataframe5.ps dataframe6.ps \
- dataframe7.ps dataframe8.ps menuframe.ps
-
diff --git a/lib/orber/doc/src/notes.xml b/lib/orber/doc/src/notes.xml
index 231872f958..c8477d9252 100644
--- a/lib/orber/doc/src/notes.xml
+++ b/lib/orber/doc/src/notes.xml
@@ -32,7 +32,21 @@
<file>notes.xml</file>
</header>
- <section>
+ <section><title>Orber 3.6.22</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> XML files have been corrected. </p>
+ <p>
+ Own Id: OTP-9550 Aux Id: OTP-9541 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section>
<title>Orber 3.6.21</title>
<section>
diff --git a/lib/orber/doc/src/orber_ifr.xml b/lib/orber/doc/src/orber_ifr.xml
index 021082e101..2d47d57476 100644
--- a/lib/orber/doc/src/orber_ifr.xml
+++ b/lib/orber/doc/src/orber_ifr.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2009</year>
+ <year>1997</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -297,7 +297,7 @@
</desc>
</func>
<func>
- <name>describe_contents(Objref,Limit_type,Exclude_inherited,Max_returned_objs) -> Return</name>
+ <name>describe_contents(Objref, Limit_type, Exclude_inherited, Max_returned_objs) -> Return</name>
<fsummary>Return a list of descriptions of the IFR objects contained by the target Container object</fsummary>
<type>
<v>Objref = #IFR_objref</v>
diff --git a/lib/orber/examples/Stack/Makefile b/lib/orber/examples/Stack/Makefile
index 6e7f292a04..215e57fcbe 100644
--- a/lib/orber/examples/Stack/Makefile
+++ b/lib/orber/examples/Stack/Makefile
@@ -64,6 +64,8 @@ HRL_FILES=
ERL_FILES= $(MODULES:%=%.erl)
+GEN_FILES = $(GEN_ERL_MODULES:%=%.erl) $(GEN_HRL_FILES)
+
JAVA_CLASSES = \
StackClient
@@ -94,16 +96,20 @@ ERL_COMPILE_FLAGS += \
debug opt: $(TARGET_FILES)
clean:
- rm -f $(TARGET_FILES) $(GEN_ERL_MODULES:%=%.erl) $(GEN_HRL_FILES) $(CLASS_FILES)
+ rm -f $(TARGET_FILES) $(GEN_ERL_MODULES:%=%.erl) $(GEN_HRL_FILES) $(CLASS_FILES) IDL-GENERATED
rm -f errs core *~
docs:
test: $(TEST_TARGET_FILES)
-
-$(GEN_ERL_MODULES:%=%.erl) $(GEN_HRL_FILES): stack.idl
+IDL-GENERATED: stack.idl
erlc $(ERL_IDL_FLAGS) stack.idl
+ >IDL-GENERATED
+
+$(GEN_FILES): IDL-GENERATED
+
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Target
diff --git a/lib/orber/include/Makefile b/lib/orber/include/Makefile
deleted file mode 100644
index 219b7085e6..0000000000
--- a/lib/orber/include/Makefile
+++ /dev/null
@@ -1,66 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1998-2009. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(ORBER_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/orber-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-EXTERNAL_HRL_FILES= ../include/corba.hrl \
- ../include/ifr_types.hrl \
- ../include/orber_pi.hrl
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-debug opt clean docs:
-
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-
-release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(EXTERNAL_HRL_FILES) $(RELSYSDIR)/include
-
-
-release_docs_spec:
-
-
diff --git a/lib/orber/priv/Makefile b/lib/orber/priv/Makefile
index 2847727035..2847727035 100755..100644
--- a/lib/orber/priv/Makefile
+++ b/lib/orber/priv/Makefile
diff --git a/lib/orber/priv/blank.html b/lib/orber/priv/blank.html
index 44e86908a0..44e86908a0 100755..100644
--- a/lib/orber/priv/blank.html
+++ b/lib/orber/priv/blank.html
diff --git a/lib/orber/priv/info_frames.html b/lib/orber/priv/info_frames.html
index 75456a67a4..75456a67a4 100755..100644
--- a/lib/orber/priv/info_frames.html
+++ b/lib/orber/priv/info_frames.html
diff --git a/lib/orber/priv/main_frame.html b/lib/orber/priv/main_frame.html
index 056a92812e..056a92812e 100755..100644
--- a/lib/orber/priv/main_frame.html
+++ b/lib/orber/priv/main_frame.html
diff --git a/lib/orber/priv/orber.tool b/lib/orber/priv/orber.tool
index 910a7d7e45..910a7d7e45 100755..100644
--- a/lib/orber/priv/orber.tool
+++ b/lib/orber/priv/orber.tool
diff --git a/lib/orber/priv/orber_help.txt b/lib/orber/priv/orber_help.txt
index a6580dc30a..a6580dc30a 100755..100644
--- a/lib/orber/priv/orber_help.txt
+++ b/lib/orber/priv/orber_help.txt
diff --git a/lib/orber/priv/start_info.html b/lib/orber/priv/start_info.html
index 0ad521c90a..0ad521c90a 100755..100644
--- a/lib/orber/priv/start_info.html
+++ b/lib/orber/priv/start_info.html
diff --git a/lib/orber/src/Makefile b/lib/orber/src/Makefile
index ccc449333c..e812e22b46 100644
--- a/lib/orber/src/Makefile
+++ b/lib/orber/src/Makefile
@@ -212,7 +212,7 @@ debug:
opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET)
+ rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET) IDL-GENERATED
rm -f errs core *~
$(APP_TARGET): $(APP_SRC) ../vsn.mk
@@ -227,15 +227,14 @@ docs:
# Special Build Targets
# ----------------------------------------------------
-$(GEN_ERL_FILES1) $(GEN_HRL_FILES1): $(ERL_TOP)/lib/ic/include/erlang.idl
+IDL-GENERATED: $(ERL_TOP)/lib/ic/include/erlang.idl CORBA.idl OrberIFR.idl
erlc $(ERL_IDL_FLAGS) $(ERL_TOP)/lib/ic/include/erlang.idl
-
-$(GEN_ERL_FILES2) $(GEN_HRL_FILES2): CORBA.idl
erlc $(ERL_IDL_FLAGS) CORBA.idl
+ erlc $(ERL_IDL_FLAGS) +'{this,"Orber::IFR"}' OrberIFR.idl
+ >IDL-GENERATED
-$(GEN_ERL_FILES3) $(GEN_HRL_FILES3): OrberIFR.idl
- erlc $(ERL_IDL_FLAGS) +'{this,"Orber::IFR"}' \
- OrberIFR.idl
+$(GEN_ERL_FILES): IDL-GENERATED
+$(TARGET_FILES): IDL-GENERATED
$(GEN_ASN_ERL) $(GEN_ASN_HRL): OrberCSIv2.asn1 OrberCSIv2.set.asn
erlc $(ERL_COMPILE_FLAGS) $(ASN_FLAGS) +'{inline,"OrberCSIv2"}' OrberCSIv2.set.asn
diff --git a/lib/orber/src/corba.erl b/lib/orber/src/corba.erl
index ecec768544..989e84f581 100644
--- a/lib/orber/src/corba.erl
+++ b/lib/orber/src/corba.erl
@@ -947,7 +947,7 @@ handle_cast2(M, F, A, InternalState, State, Ctx) ->
{noreply, {InternalState, NewState}}
end.
-handle_exit(InternalState, State, {undef, [{M, F, _}|_]} = Reason,
+handle_exit(InternalState, State, {undef, [{M, F, _, _}|_]} = Reason,
OnewayOp, {M, F}, A) ->
case catch check_exports(M:module_info(exports), F) of
{'EXIT',{undef,_}} ->
@@ -979,7 +979,7 @@ handle_exit(InternalState, State, {undef, [{M, F, _}|_]} = Reason,
#'OBJ_ADAPTER'{minor=(?ORBER_VMCID bor 4),
completion_status=?COMPLETED_MAYBE})
end;
-handle_exit(InternalState, State, {undef, [{M2, F2, A2}|_]} = Reason,
+handle_exit(InternalState, State, {undef, [{M2, F2, A2, _}|_]} = Reason,
OnewayOp, {M, F}, A) ->
case catch check_exports(M2:module_info(exports), F2) of
{'EXIT',{undef,_}} ->
diff --git a/lib/orber/src/orber_diagnostics.erl b/lib/orber/src/orber_diagnostics.erl
index c12dbfa896..c115d79524 100644
--- a/lib/orber/src/orber_diagnostics.erl
+++ b/lib/orber/src/orber_diagnostics.erl
@@ -130,10 +130,10 @@ missing_modules_helper([[Mod, Type]|T], ErrorsFound) when Type == ?IFR_StructDef
end;
missing_modules_helper([[Mod, Type]|T], ErrorsFound) when Type == ?IFR_InterfaceDef ->
case catch Mod:oe_get_interface() of
- {'EXIT', {undef,[{Mod, _, _}|_]}} ->
+ {'EXIT', {undef,[{Mod, _, _, _}|_]}} ->
io:format("Missing (Interface): ~p~n", [Mod]),
missing_modules_helper(T, ErrorsFound + 1);
- {'EXIT', {undef,[{OtherMod, _, _}|_]}} ->
+ {'EXIT', {undef,[{OtherMod, _, _, _}|_]}} ->
io:format("Missing (Inherited by the ~p Interface): ~p~n",
[Mod, OtherMod]),
missing_modules_helper(T, ErrorsFound + 1);
diff --git a/lib/orber/src/orber_ifr.erl b/lib/orber/src/orber_ifr.erl
index e56672be93..9631a268e4 100644
--- a/lib/orber/src/orber_ifr.erl
+++ b/lib/orber/src/orber_ifr.erl
@@ -500,7 +500,7 @@ get_tc(Id, Type) ->
case catch Module:tc() of
{'EXIT', Reason} ->
case Reason of
- {undef,[{Module, tc,[]}|_]} ->
+ {undef,[{Module, tc,[],_}|_]} ->
orber:dbg("[~p] ~p:get_tc(~p);~nMissing ~p:tc()~n",
[?LINE, ?MODULE, Id, Module], ?DEBUG_LEVEL),
corba:raise(#'UNKNOWN'{minor=(?ORBER_VMCID bor 1),
diff --git a/lib/orber/test/Makefile b/lib/orber/test/Makefile
index b682bcf24b..996d0d1874 100644
--- a/lib/orber/test/Makefile
+++ b/lib/orber/test/Makefile
@@ -184,31 +184,17 @@ docs:
# Special Targets
# ----------------------------------------------------
-#
-# Each IDL file produces many target files so no pattern
-# rule can be used.
-#
-TGT_ORBER = \
- $(GEN_HRL_ORBER:%=$(IDLOUTDIR)/%) \
- $(GEN_MOD_ORBER:%=$(IDLOUTDIR)/%.erl)
-TGT_IIOP = \
- $(GEN_HRL_IIOP:%=$(IDLOUTDIR)/%) \
- $(GEN_MOD_IIOP:%=$(IDLOUTDIR)/%.erl)
-
-TGT_TEST_SERVER = \
- $(GEN_HRL_TEST_SERVER:%=$(IDLOUTDIR)/%) \
- $(GEN_MOD_TEST_SERVER:%=$(IDLOUTDIR)/%.erl)
-
-$(TGT_ORBER): orber_test.idl
+IDL-GENERATED: orber_test.idl iiop_test.idl orber_test_server.idl
erlc $(ERL_IDL_FLAGS) -o$(IDLOUTDIR) orber_test.idl
-
-$(TGT_IIOP): iiop_test.idl
erlc $(ERL_IDL_FLAGS) -o$(IDLOUTDIR) \
+'{preproc_flags,"-I../COSS/CosNaming"}' iiop_test.idl
-
-$(TGT_TEST_SERVER): orber_test_server.idl
erlc $(ERL_IDL_FLAGS) -o$(IDLOUTDIR) \
+'{cfgfile,"orber_test_server.cfg"}' orber_test_server.idl
+ >IDL-GENERATED
+
+$(GEN_FILES): IDL-GENERATED
+
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Targets
diff --git a/lib/orber/vsn.mk b/lib/orber/vsn.mk
index 35aabd51cd..29b21e8e01 100644
--- a/lib/orber/vsn.mk
+++ b/lib/orber/vsn.mk
@@ -1,3 +1,3 @@
-ORBER_VSN = 3.6.21
+ORBER_VSN = 3.6.22
diff --git a/lib/os_mon/c_src/Makefile.in b/lib/os_mon/c_src/Makefile.in
index 1a371eb380..b81d3f564b 100644
--- a/lib/os_mon/c_src/Makefile.in
+++ b/lib/os_mon/c_src/Makefile.in
@@ -82,13 +82,9 @@ ALL_CFLAGS = @CFLAGS@ @DEFS@ $(CFLAGS)
# Targets
# ----------------------------------------------------
-debug opt: $(OBJDIR) $(BINDIR) $(TARGET_FILES)
+_create_dirs := $(shell mkdir -p $(OBJDIR) $(BINDIR))
-$(OBJDIR):
- -@mkdir -p $(OBJDIR)
-
-$(BINDIR):
- -@mkdir -p $(BINDIR)
+debug opt: $(TARGET_FILES)
clean:
rm -f $(TARGET_FILES)
diff --git a/lib/os_mon/c_src/cpu_sup.c b/lib/os_mon/c_src/cpu_sup.c
index fbf318c614..9c5f9a6aa5 100644
--- a/lib/os_mon/c_src/cpu_sup.c
+++ b/lib/os_mon/c_src/cpu_sup.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1997-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1997-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -191,7 +191,10 @@ int main(int argc, char** argv) {
static cpu_t *read_procstat(FILE *fp, cpu_t *cpu) {
char buffer[BUFFERSIZE];
- fgets(buffer, BUFFERSIZE, fp);
+ if (fgets(buffer, BUFFERSIZE, fp) == NULL) {
+ memset(cpu, 0, sizeof(cpu_t));
+ return cpu;
+ }
sscanf(buffer, "cpu%u %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu",
&(cpu->id),
&(cpu->user),
@@ -223,7 +226,11 @@ static void util_measure(unsigned int **result_vec, int *result_sz) {
return;
}
- fgets(buffer, BUFFERSIZE, fp); /*ignore read*/
+ /*ignore read*/
+ if (fgets(buffer, BUFFERSIZE, fp) == NULL) {
+ *result_sz = 0;
+ return;
+ }
rv = *result_vec;
rv[0] = no_of_cpus;
rv[1] = CU_VALUES;
@@ -447,8 +454,12 @@ static void sendv(unsigned int data[], int ints) {
}
static void error(char* err_msg) {
- write(FD_ERR, err_msg, strlen(err_msg));
- write(FD_ERR, "\n", 1);
+ /*
+ * if we get error here we have trouble,
+ * silence unnecessary warnings
+ */
+ if(write(FD_ERR, err_msg, strlen(err_msg)));
+ if(write(FD_ERR, "\n", 1));
exit(-1);
}
diff --git a/lib/os_mon/doc/src/make.dep b/lib/os_mon/doc/src/make.dep
deleted file mode 100644
index b657f2e036..0000000000
--- a/lib/os_mon/doc/src/make.dep
+++ /dev/null
@@ -1,21 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex cpu_sup.tex disksup.tex memsup.tex \
- nteventlog.tex os_mon.tex os_mon_mib.tex os_sup.tex \
- ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/os_mon/doc/src/notes.xml b/lib/os_mon/doc/src/notes.xml
index 3b5dbe3146..f641bbd828 100644
--- a/lib/os_mon/doc/src/notes.xml
+++ b/lib/os_mon/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -30,6 +30,20 @@
</header>
<p>This document describes the changes made to the OS_Mon application.</p>
+<section><title>Os_Mon 2.2.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Remove misc. compiler warnings</p>
+ <p>
+ Own Id: OTP-9542</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Os_Mon 2.2.6</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/os_mon/mibs/Makefile b/lib/os_mon/mibs/Makefile
index cbbc337491..a361fef378 100644
--- a/lib/os_mon/mibs/Makefile
+++ b/lib/os_mon/mibs/Makefile
@@ -78,6 +78,9 @@ $(SNMP_BIN_TARGET_DIR)/OTP-MIB.bin: $(ERL_TOP)/lib/$(OTP_MIBDIR)/mibs/OTP-MI
v1/%.mib.v1: %.mib
$(ERL_TOP)/lib/snmp/bin/snmp-v2tov1 -o $@ $<
+$(SNMP_BIN_TARGET_DIR)/OTP-OS-MON-MIB.bin: \
+ $(SNMP_BIN_TARGET_DIR)/OTP-REG.bin \
+ $(SNMP_BIN_TARGET_DIR)/OTP-MIB.bin \
# ----------------------------------------------------
# Release Target
diff --git a/lib/os_mon/vsn.mk b/lib/os_mon/vsn.mk
index 2d583a398b..f000e24a8f 100644
--- a/lib/os_mon/vsn.mk
+++ b/lib/os_mon/vsn.mk
@@ -1 +1 @@
-OS_MON_VSN = 2.2.6
+OS_MON_VSN = 2.2.7
diff --git a/lib/otp_mibs/doc/src/make.dep b/lib/otp_mibs/doc/src/make.dep
deleted file mode 100644
index 2885155315..0000000000
--- a/lib/otp_mibs/doc/src/make.dep
+++ /dev/null
@@ -1,20 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex introduction.tex mibs.tex otp_mib.tex \
- part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/parsetools/doc/src/leex.xml b/lib/parsetools/doc/src/leex.xml
index 12abfd244f..d5c24c303d 100644
--- a/lib/parsetools/doc/src/leex.xml
+++ b/lib/parsetools/doc/src/leex.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2009</year><year>2009</year>
+ <year>2009</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -79,6 +79,10 @@ Token = tuple()</code>
<item><p>Causes warnings to be printed as they occur. Default is
<c>true</c>.</p>
</item>
+ <tag><c>warnings_as_errors</c></tag>
+ <item>
+ <p>Causes warnings to be treated as errors.</p>
+ </item>
<tag><c>{report, bool()}</c></tag>
<item><p>This is a short form for both <c>report_errors</c> and
<c>report_warnings</c>.</p>
diff --git a/lib/parsetools/doc/src/make.dep b/lib/parsetools/doc/src/make.dep
deleted file mode 100644
index 3a09ecdedd..0000000000
--- a/lib/parsetools/doc/src/make.dep
+++ /dev/null
@@ -1,21 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex leex.tex ref_man.tex yecc.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-ref_man.tex: ../../../../system/doc/definitions/term.defs
-
diff --git a/lib/parsetools/doc/src/notes.xml b/lib/parsetools/doc/src/notes.xml
index 77b3a1a657..0c611db1ec 100644
--- a/lib/parsetools/doc/src/notes.xml
+++ b/lib/parsetools/doc/src/notes.xml
@@ -30,6 +30,52 @@
</header>
<p>This document describes the changes made to the Parsetools application.</p>
+<section><title>Parsetools 2.0.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Dialyzer warnings have been removed. </p>
+ <p>
+ Own Id: OTP-8318</p>
+ </item>
+ <item>
+ <p>
+ yecc: add warnings_as_errors option(Thanks to Tuncer
+ ayaz)</p>
+ <p>
+ Own Id: OTP-9376</p>
+ </item>
+ <item>
+ <p>
+ Fix incorrect order of pseudo variables in yecc example</p>
+ <p>
+ The example is for converting from infix to prefix. This
+ change uses to correct ordering of the triplet. (Thanks
+ to Garret Smith)</p>
+ <p>
+ Own Id: OTP-9484</p>
+ </item>
+ <item>
+ <p>
+ Implement or fix -Werror option</p>
+ <p>
+ If -Werror is enabled and there are warnings no output
+ file is written. Also make sure that error/warning
+ reporting is consistent. (Thanks to Tuncer Ayaz)</p>
+ <p>
+ Own Id: OTP-9536</p>
+ </item>
+ <item>
+ <p> XML files have been corrected. </p>
+ <p>
+ Own Id: OTP-9550 Aux Id: OTP-9541 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Parsetools 2.0.5</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/parsetools/doc/src/yecc.xml b/lib/parsetools/doc/src/yecc.xml
index 81f1550b0a..66bc6f4795 100644
--- a/lib/parsetools/doc/src/yecc.xml
+++ b/lib/parsetools/doc/src/yecc.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -95,6 +95,10 @@
<item>This is a short form for both <c>report_errors</c> and
<c>report_warnings</c>.
</item>
+ <tag><c>warnings_as_errors</c></tag>
+ <item>
+ <p>Causes warnings to be treated as errors.</p>
+ </item>
<tag><c>{return_errors, bool()}</c>.</tag>
<item>If this flag is set, <c>{error, Errors, Warnings}</c>
is returned when there are errors. Default is
@@ -332,7 +336,7 @@ element -> list : '$1'. </code>
<code type="none">
{cons, {atom, 1, a,} {cons, {atom, 1, b},
{cons, {atom, 1, c}, nil}}} </code>
- <p>The associated code contains <c>pseudo variables</c><c>'$1'</c>, <c>'$2'</c>, <c>'$3'</c>, etc. which refer to (are
+ <p>The associated code contains <c>pseudo variables</c> <c>'$1'</c>, <c>'$2'</c>, <c>'$3'</c>, etc. which refer to (are
bound to) the values associated previously by the parser with
the symbols of the right hand side of the rule. When these
symbols are terminal categories, the values are token tuples of
@@ -421,9 +425,9 @@ myparser:parse_and_scan({Mod, Tokenizer, Args}) </code>
Nonterminals E T F.
Terminals '+' '*' '(' ')' number.
Rootsymbol E.
-E -> E '+' T: ['$1', '$2', '$3'].
+E -> E '+' T: ['$2', '$1', '$3'].
E -> T : '$1'.
-T -> T '*' F: ['$1', '$2', '$3'].
+T -> T '*' F: ['$2', '$1', '$3'].
T -> F : '$1'.
F -> '(' E ')' : '$2'.
F -> number : '$1'. </code>
@@ -434,8 +438,8 @@ Terminals '+' '*' '(' ')' number.
Rootsymbol E.
Left 100 '+'.
Left 200 '*'.
-E -> E '+' E : ['$1', '$2', '$3'].
-E -> E '*' E : ['$1', '$2', '$3'].
+E -> E '+' E : ['$2', '$1', '$3'].
+E -> E '*' E : ['$2', '$1', '$3'].
E -> '(' E ')' : '$2'.
E -> number : '$1'. </code>
<p>3. An overloaded minus operator:</p>
diff --git a/lib/parsetools/include/yeccpre.hrl b/lib/parsetools/include/yeccpre.hrl
index 80a3afbdb6..f638529aa4 100644
--- a/lib/parsetools/include/yeccpre.hrl
+++ b/lib/parsetools/include/yeccpre.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -67,7 +67,7 @@ yeccpars0(Tokens, Tzr, State, States, Vstack) ->
Error
end.
-yecc_error_type(function_clause, [{?MODULE,F,ArityOrArgs} | _]) ->
+yecc_error_type(function_clause, [{?MODULE,F,ArityOrArgs,_} | _]) ->
case atom_to_list(F) of
"yeccgoto_" ++ SymbolL ->
{ok,[{atom,_,Symbol}],_} = erl_scan:string(SymbolL),
diff --git a/lib/parsetools/src/leex.erl b/lib/parsetools/src/leex.erl
index d0b4b9efe7..cdf20461d9 100644
--- a/lib/parsetools/src/leex.erl
+++ b/lib/parsetools/src/leex.erl
@@ -35,7 +35,7 @@
-export([compile/3,file/1,file/2,format_error/1]).
-import(lists, [member/2,reverse/1,sort/1,delete/2,
- keysort/2,keydelete/3,keyfind/3,
+ keysort/2,keydelete/3,
map/2,foldl/3,foreach/2,flatmap/2]).
-import(string, [substr/2,substr/3,span/2]).
-import(ordsets, [is_element/2,add_element/2,union/2]).
@@ -58,7 +58,7 @@
gfile=[], % Graph file
module, % Module name
opts=[], % Options
- posix=false, % POSIX regular expressions
+ % posix=false, % POSIX regular expressions
errors=[],
warnings=[]
}).
@@ -73,12 +73,15 @@
%%% Interface to erl_compile.
compile(Input0, Output0,
- #options{warning = WarnLevel, verbose=Verbose, includes=Includes}) ->
+ #options{warning = WarnLevel, verbose=Verbose, includes=Includes,
+ specific=Specific}) ->
Input = assure_extension(shorten_filename(Input0), ".xrl"),
Output = assure_extension(shorten_filename(Output0), ".erl"),
Includefile = lists:sublist(Includes, 1),
+ Werror = proplists:get_bool(warnings_as_errors, Specific),
Opts = [{scannerfile,Output},{includefile,Includefile},{verbose,Verbose},
- {report_errors,true},{report_warnings,WarnLevel > 0}],
+ {report_errors,true},{report_warnings,WarnLevel > 0},
+ {warnings_as_errors, Werror}],
case file(Input, Opts) of
{ok, _} ->
ok;
@@ -107,10 +110,15 @@ file(File, Opts0) ->
St = try
{ok,REAs,Actions,Code,St2} = parse_file(St1),
{DFA,DF} = make_dfa(REAs, St2),
- St3 = out_file(St2, DFA, DF, Actions, Code),
- case lists:member(dfa_graph, St3#leex.opts) of
- true -> out_dfa_graph(St3, DFA, DF);
- false -> St3
+ case werror(St2) of
+ false ->
+ St3 = out_file(St2, DFA, DF, Actions, Code),
+ case lists:member(dfa_graph, St3#leex.opts) of
+ true -> out_dfa_graph(St3, DFA, DF);
+ false -> St3
+ end;
+ true ->
+ St2
end
catch #leex{}=St4 ->
St4
@@ -131,8 +139,8 @@ format_error({regexp,E})->
"unterminated " ++ Cs;
{illegal_char,Cs} ->
"illegal character " ++ Cs;
- {posix_cc,What} ->
- ["illegal POSIX character class ",io_lib:write_string(What)];
+%% {posix_cc,What} ->
+%% ["illegal POSIX character class ",io_lib:write_string(What)];
{char_class,What} ->
["illegal character class ",io_lib:write_string(What)]
end,
@@ -163,7 +171,8 @@ options(Options0) when is_list(Options0) ->
(T) -> [T]
end, Options0),
options(Options, [scannerfile,includefile,report_errors,
- report_warnings,return_errors,return_warnings,
+ report_warnings,warnings_as_errors,
+ return_errors,return_warnings,
verbose,dfa_graph], [])
catch error: _ -> badarg
end;
@@ -217,6 +226,7 @@ default_option(dfa_graph) -> false;
default_option(includefile) -> [];
default_option(report_errors) -> true;
default_option(report_warnings) -> true;
+default_option(warnings_as_errors) -> false;
default_option(return_errors) -> false;
default_option(return_warnings) -> false;
default_option(scannerfile) -> [];
@@ -225,6 +235,7 @@ default_option(verbose) -> false.
atom_option(dfa_graph) -> {dfa_graph,true};
atom_option(report_errors) -> {report_errors,true};
atom_option(report_warnings) -> {report_warnings,true};
+atom_option(warnings_as_errors) -> {warnings_as_errors,true};
atom_option(return_errors) -> {return_errors,true};
atom_option(return_warnings) -> {return_warnings,true};
atom_option(verbose) -> {verbose,true};
@@ -251,19 +262,29 @@ leex_ret(St) ->
report_warnings(St),
Es = pack_errors(St#leex.errors),
Ws = pack_warnings(St#leex.warnings),
+ Werror = werror(St),
if
+ Werror ->
+ do_error_return(St, Es, Ws);
Es =:= [] ->
case member(return_warnings, St#leex.opts) of
true -> {ok, St#leex.efile, Ws};
false -> {ok, St#leex.efile}
end;
- true ->
- case member(return_errors, St#leex.opts) of
- true -> {error, Es, Ws};
- false -> error
- end
+ true ->
+ do_error_return(St, Es, Ws)
+ end.
+
+do_error_return(St, Es, Ws) ->
+ case member(return_errors, St#leex.opts) of
+ true -> {error, Es, Ws};
+ false -> error
end.
+werror(St) ->
+ St#leex.warnings =/= []
+ andalso member(warnings_as_errors, St#leex.opts).
+
pack_errors([{File,_} | _] = Es) ->
[{File, flatmap(fun({_,E}) -> [E] end, sort(Es))}];
pack_errors([]) ->
@@ -286,16 +307,26 @@ report_errors(St) ->
end, report_errors, St#leex.opts).
report_warnings(St) ->
- when_opt(fun () ->
- foreach(fun({File,{none,Mod,W}}) ->
- io:fwrite("~s: Warning: ~s\n",
- [File,Mod:format_error(W)]);
- ({File,{Line,Mod,W}}) ->
- io:fwrite("~s:~w: Warning: ~s\n",
- [File,Line,Mod:format_error(W)])
- end, sort(St#leex.warnings))
- end, report_warnings, St#leex.opts).
-
+ Werror = member(warnings_as_errors, St#leex.opts),
+ Prefix = case Werror of
+ true -> "";
+ false -> "Warning: "
+ end,
+ ReportWerror = Werror andalso member(report_errors, St#leex.opts),
+ ShouldReport = member(report_warnings, St#leex.opts) orelse ReportWerror,
+ when_bool(fun () ->
+ foreach(fun({File,{none,Mod,W}}) ->
+ io:fwrite("~s: ~s~s\n",
+ [File,Prefix,
+ Mod:format_error(W)]);
+ ({File,{Line,Mod,W}}) ->
+ io:fwrite("~s:~w: ~s~s\n",
+ [File,Line,Prefix,
+ Mod:format_error(W)])
+ end, sort(St#leex.warnings))
+ end, ShouldReport).
+
+-spec add_error(_, #leex{}) -> no_return().
add_error(E, St) ->
add_error(St#leex.xfile, E, St).
@@ -341,6 +372,12 @@ when_opt(Do, Opt, Opts) ->
false -> ok
end.
+when_bool(Do, Bool) ->
+ case Bool of
+ true -> Do();
+ false -> ok
+ end.
+
verbose_print(St, Format, Args) ->
when_opt(fun () -> io:fwrite(Format, Args) end, verbose, St#leex.opts).
@@ -644,14 +681,14 @@ re_repeat1([$*|Cs], Sn, S, St) -> re_repeat1(Cs, Sn, {kclosure,S}, St);
re_repeat1([$+|Cs], Sn, S, St) -> re_repeat1(Cs, Sn, {pclosure,S}, St);
re_repeat1([$?|Cs], Sn, S, St) -> re_repeat1(Cs, Sn, {optional,S}, St);
%% { only starts interval when ere is true, otherwise normal character.
-re_repeat1([${|Cs0], Sn, S, #leex{posix=true}=St) -> % $}
- case re_interval_range(Cs0) of
- {Min,Max,[$}|Cs1]} when is_integer(Min), is_integer(Max), Min =< Max ->
- re_repeat1(Cs1, Sn, {interval,S,Min,Max}, St);
- {Min,Max,[$}|Cs1]} when is_integer(Min), is_atom(Max) ->
- re_repeat1(Cs1, Sn, {interval,S,Min,Max}, St);
- {_,_,Cs1} -> parse_error({interval_range,string_between([${|Cs0], Cs1)})
- end;
+%% re_repeat1([${|Cs0], Sn, S, #leex{posix=true}=St) -> % $}
+%% case re_interval_range(Cs0) of
+%% {Min,Max,[$}|Cs1]} when is_integer(Min), is_integer(Max), Min =< Max ->
+%% re_repeat1(Cs1, Sn, {interval,S,Min,Max}, St);
+%% {Min,Max,[$}|Cs1]} when is_integer(Min), is_atom(Max) ->
+%% re_repeat1(Cs1, Sn, {interval,S,Min,Max}, St);
+%% {_,_,Cs1} -> parse_error({interval_range,string_between([${|Cs0], Cs1)})
+%% end;
re_repeat1(Cs, Sn, S, _) -> {S,Sn,Cs}.
%% re_single(Chars, SubNumber, State) -> {RegExp,SubNumber,Chars}.
@@ -733,7 +770,7 @@ special_char($|, _) -> true;
special_char($*, _) -> true;
special_char($+, _) -> true;
special_char($?, _) -> true;
-special_char(${, #leex{posix=true}) -> true; % Only when POSIX set
+%% special_char(${, #leex{posix=true}) -> true; % Only when POSIX set
special_char($\\, _) -> true;
special_char(_, _) -> false.
@@ -744,12 +781,12 @@ re_char_class([$]|Cs], St) -> % Must special case this.
re_char_class(Cs, [$]], St);
re_char_class(Cs, St) -> re_char_class(Cs, [], St).
-re_char_class("[:" ++ Cs0, Cc, #leex{posix=true}=St) ->
- %% POSIX char class only.
- case posix_cc(Cs0) of
- {Pcl,":]" ++ Cs1} -> re_char_class(Cs1, [{posix,Pcl}|Cc], St);
- {_,Cs1} -> parse_error({posix_cc,string_between(Cs0, Cs1)})
- end;
+%% re_char_class("[:" ++ Cs0, Cc, #leex{posix=true}=St) ->
+%% %% POSIX char class only.
+%% case posix_cc(Cs0) of
+%% {Pcl,":]" ++ Cs1} -> re_char_class(Cs1, [{posix,Pcl}|Cc], St);
+%% {_,Cs1} -> parse_error({posix_cc,string_between(Cs0, Cs1)})
+%% end;
re_char_class([C1|Cs0], Cc, St) when C1 =/= $] ->
case re_char(C1, Cs0) of
{Cf,[$-,C2|Cs1]} when C2 =/= $] ->
@@ -766,19 +803,19 @@ re_char_class(Cs, Cc, _) -> {reverse(Cc),Cs}. % Preserve order
%% posix_cc(String) -> {PosixClass,RestString}.
%% Handle POSIX character classes.
-posix_cc("alnum" ++ Cs) -> {alnum,Cs};
-posix_cc("alpha" ++ Cs) -> {alpha,Cs};
-posix_cc("blank" ++ Cs) -> {blank,Cs};
-posix_cc("cntrl" ++ Cs) -> {cntrl,Cs};
-posix_cc("digit" ++ Cs) -> {digit,Cs};
-posix_cc("graph" ++ Cs) -> {graph,Cs};
-posix_cc("lower" ++ Cs) -> {lower,Cs};
-posix_cc("print" ++ Cs) -> {print,Cs};
-posix_cc("punct" ++ Cs) -> {punct,Cs};
-posix_cc("space" ++ Cs) -> {space,Cs};
-posix_cc("upper" ++ Cs) -> {upper,Cs};
-posix_cc("xdigit" ++ Cs) -> {xdigit,Cs};
-posix_cc(Cs) -> parse_error({posix_cc,substr(Cs, 1, 5)}).
+%% posix_cc("alnum" ++ Cs) -> {alnum,Cs};
+%% posix_cc("alpha" ++ Cs) -> {alpha,Cs};
+%% posix_cc("blank" ++ Cs) -> {blank,Cs};
+%% posix_cc("cntrl" ++ Cs) -> {cntrl,Cs};
+%% posix_cc("digit" ++ Cs) -> {digit,Cs};
+%% posix_cc("graph" ++ Cs) -> {graph,Cs};
+%% posix_cc("lower" ++ Cs) -> {lower,Cs};
+%% posix_cc("print" ++ Cs) -> {print,Cs};
+%% posix_cc("punct" ++ Cs) -> {punct,Cs};
+%% posix_cc("space" ++ Cs) -> {space,Cs};
+%% posix_cc("upper" ++ Cs) -> {upper,Cs};
+%% posix_cc("xdigit" ++ Cs) -> {xdigit,Cs};
+%% posix_cc(Cs) -> parse_error({posix_cc,substr(Cs, 1, 5)}).
escape_char($n) -> $\n; % \n = LF
escape_char($r) -> $\r; % \r = CR
@@ -797,24 +834,24 @@ escape_char(C) -> C. % Pass it straight through
%% Int, -> Int,any
%% Int1,Int2 -> Int1,Int2
-re_interval_range(Cs0) ->
- case re_number(Cs0) of
- {none,Cs1} -> {none,none,Cs1};
- {N,[$,|Cs1]} ->
- case re_number(Cs1) of
- {none,Cs2} -> {N,any,Cs2};
- {M,Cs2} -> {N,M,Cs2}
- end;
- {N,Cs1} -> {N,none,Cs1}
- end.
+%% re_interval_range(Cs0) ->
+%% case re_number(Cs0) of
+%% {none,Cs1} -> {none,none,Cs1};
+%% {N,[$,|Cs1]} ->
+%% case re_number(Cs1) of
+%% {none,Cs2} -> {N,any,Cs2};
+%% {M,Cs2} -> {N,M,Cs2}
+%% end;
+%% {N,Cs1} -> {N,none,Cs1}
+%% end.
-re_number([C|Cs]) when C >= $0, C =< $9 ->
- re_number(Cs, C - $0);
-re_number(Cs) -> {none,Cs}.
+%% re_number([C|Cs]) when C >= $0, C =< $9 ->
+%% re_number(Cs, C - $0);
+%% re_number(Cs) -> {none,Cs}.
-re_number([C|Cs], Acc) when C >= $0, C =< $9 ->
- re_number(Cs, 10*Acc + (C - $0));
-re_number(Cs, Acc) -> {Acc,Cs}.
+%% re_number([C|Cs], Acc) when C >= $0, C =< $9 ->
+%% re_number(Cs, 10*Acc + (C - $0));
+%% re_number(Cs, Acc) -> {Acc,Cs}.
string_between(Cs1, Cs2) ->
substr(Cs1, 1, length(Cs1)-length(Cs2)).
diff --git a/lib/parsetools/src/yecc.erl b/lib/parsetools/src/yecc.erl
index 4119e2631b..b0792a6ed8 100644
--- a/lib/parsetools/src/yecc.erl
+++ b/lib/parsetools/src/yecc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -133,12 +133,15 @@
%%% Interface to erl_compile.
compile(Input0, Output0,
- #options{warning = WarnLevel, verbose=Verbose, includes=Includes}) ->
+ #options{warning = WarnLevel, verbose=Verbose, includes=Includes,
+ specific=Specific}) ->
Input = shorten_filename(Input0),
Output = shorten_filename(Output0),
Includefile = lists:sublist(Includes, 1),
+ Werror = proplists:get_bool(warnings_as_errors, Specific),
Opts = [{parserfile,Output}, {includefile,Includefile}, {verbose,Verbose},
- {report_errors, true}, {report_warnings, WarnLevel > 0}],
+ {report_errors, true}, {report_warnings, WarnLevel > 0},
+ {warnings_as_errors, Werror}],
case file(Input, Opts) of
{ok, _OutFile} ->
ok;
@@ -278,8 +281,8 @@ options(Options0) when is_list(Options0) ->
(T) -> [T]
end, Options0),
options(Options, [file_attributes, includefile, parserfile,
- report_errors, report_warnings, return_errors,
- return_warnings, time, verbose], [])
+ report_errors, report_warnings, warnings_as_errors,
+ return_errors, return_warnings, time, verbose], [])
catch error: _ -> badarg
end;
options(Option) ->
@@ -333,6 +336,7 @@ default_option(includefile) -> [];
default_option(parserfile) -> [];
default_option(report_errors) -> true;
default_option(report_warnings) -> true;
+default_option(warnings_as_errors) -> false;
default_option(return_errors) -> false;
default_option(return_warnings) -> false;
default_option(time) -> false;
@@ -341,6 +345,7 @@ default_option(verbose) -> false.
atom_option(file_attributes) -> {file_attributes, true};
atom_option(report_errors) -> {report_errors, true};
atom_option(report_warnings) -> {report_warnings, true};
+atom_option(warnings_as_errors) -> {warnings_as_errors,true};
atom_option(return_errors) -> {return_errors, true};
atom_option(return_warnings) -> {return_warnings, true};
atom_option(time) -> {time, true};
@@ -409,12 +414,16 @@ infile(Parent, Infilex, Options) ->
{error, Reason} ->
add_error(St0#yecc.infile, none, {file_error, Reason}, St0)
end,
- case St#yecc.errors of
- [] -> ok;
+ case {St#yecc.errors, werror(St)} of
+ {[], false} -> ok;
_ -> _ = file:delete(St#yecc.outfile)
end,
Parent ! {self(), yecc_ret(St)}.
+werror(St) ->
+ St#yecc.warnings =/= []
+ andalso member(warnings_as_errors, St#yecc.options).
+
outfile(St0) ->
case file:open(St0#yecc.outfile, [write, delayed_write]) of
{ok, Outport} ->
@@ -777,17 +786,23 @@ yecc_ret(St0) ->
report_warnings(St),
Es = pack_errors(St#yecc.errors),
Ws = pack_warnings(St#yecc.warnings),
+ Werror = werror(St),
if
+ Werror ->
+ do_error_return(St, Es, Ws);
Es =:= [] ->
case member(return_warnings, St#yecc.options) of
true -> {ok, St#yecc.outfile, Ws};
false -> {ok, St#yecc.outfile}
end;
true ->
- case member(return_errors, St#yecc.options) of
- true -> {error, Es, Ws};
- false -> error
- end
+ do_error_return(St, Es, Ws)
+ end.
+
+do_error_return(St, Es, Ws) ->
+ case member(return_errors, St#yecc.options) of
+ true -> {error, Es, Ws};
+ false -> error
end.
check_expected(St0) ->
@@ -837,14 +852,22 @@ report_errors(St) ->
end.
report_warnings(St) ->
- case member(report_warnings, St#yecc.options) of
+ Werror = member(warnings_as_errors, St#yecc.options),
+ Prefix = case Werror of
+ true -> "";
+ false -> "Warning: "
+ end,
+ ReportWerror = Werror andalso member(report_errors, St#yecc.options),
+ case member(report_warnings, St#yecc.options) orelse ReportWerror of
true ->
foreach(fun({File,{none,Mod,W}}) ->
- io:fwrite(<<"~s: Warning: ~s\n">>,
- [File,Mod:format_error(W)]);
+ io:fwrite(<<"~s: ~s~s\n">>,
+ [File,Prefix,
+ Mod:format_error(W)]);
({File,{Line,Mod,W}}) ->
- io:fwrite(<<"~s:~w: Warning: ~s\n">>,
- [File,Line,Mod:format_error(W)])
+ io:fwrite(<<"~s:~w: ~s~s\n">>,
+ [File,Line,Prefix,
+ Mod:format_error(W)])
end, sort(St#yecc.warnings));
false ->
ok
diff --git a/lib/parsetools/src/yeccparser.erl b/lib/parsetools/src/yeccparser.erl
index 63127802ee..e4b8b06db5 100644
--- a/lib/parsetools/src/yeccparser.erl
+++ b/lib/parsetools/src/yeccparser.erl
@@ -17,7 +17,7 @@ line_of(Token) ->
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -83,7 +83,7 @@ yeccpars0(Tokens, Tzr, State, States, Vstack) ->
Error
end.
-yecc_error_type(function_clause, [{?MODULE,F,ArityOrArgs} | _]) ->
+yecc_error_type(function_clause, [{?MODULE,F,ArityOrArgs,_} | _]) ->
case atom_to_list(F) of
"yeccgoto_" ++ SymbolL ->
{ok,[{atom,_,Symbol}],_} = erl_scan:string(SymbolL),
diff --git a/lib/parsetools/test/leex_SUITE.erl b/lib/parsetools/test/leex_SUITE.erl
index 23ad16f98d..1e50aedf07 100644
--- a/lib/parsetools/test/leex_SUITE.erl
+++ b/lib/parsetools/test/leex_SUITE.erl
@@ -152,6 +152,24 @@ file(Config) when is_list(Config) ->
?line writable(Dotfile),
file:delete(Dotfile),
+ ok = file:delete(Scannerfile),
+ Warn = <<"Definitions.1998\n"
+ "D = [0-9]\n"
+ "Rules.\n"
+ "{L}+ : {token,{word,TokenLine,TokenChars}}.\n"
+ "Erlang code.\n">>,
+ ok = file:write_file(Filename, Warn),
+ error = leex:file(Filename, [warnings_as_errors]),
+ false = filelib:is_regular(Scannerfile),
+ error = leex:file(Filename, [return_warnings,warnings_as_errors]),
+ false = filelib:is_regular(Scannerfile),
+ {error,_,[{Filename,[{1,leex,ignored_characters}]}]} =
+ leex:file(Filename, [return_errors,warnings_as_errors]),
+ false = filelib:is_regular(Scannerfile),
+ {ok,Scannerfile,[{Filename,[{1,leex,ignored_characters}]}]} =
+ leex:file(Filename, [return_warnings]),
+ true = filelib:is_regular(Scannerfile),
+
file:delete(Filename),
ok.
@@ -551,7 +569,7 @@ ex2(Config) when is_list(Config) ->
<<"
%%% File : erlang_scan.xrl
%%% Author : Robert Virding
-%%% Purpose : Tkoen definitions for Erlang.
+%%% Purpose : Token definitions for Erlang.
Definitions.
O = [0-7]
diff --git a/lib/parsetools/test/yecc_SUITE.erl b/lib/parsetools/test/yecc_SUITE.erl
index 1de87b3bff..a5f66b48e9 100644
--- a/lib/parsetools/test/yecc_SUITE.erl
+++ b/lib/parsetools/test/yecc_SUITE.erl
@@ -173,6 +173,7 @@ syntax(Config) when is_list(Config) ->
%% Report errors. Very simple test of format_error/1.
Ret = [return, {report, true}],
Filename = filename:join(Dir, "file.yrl"),
+ Parserfile = filename:join(Dir, "file.erl"),
Parserfile1 = filename:join(Dir, "a file"),
?line ok = file:write_file(Filename, <<"">>),
@@ -247,6 +248,19 @@ syntax(Config) when is_list(Config) ->
?line {ok,_,[{_,[{2,yecc,bad_declaration}]}]} =
yecc:file(Filename, Ret),
+ %% Bad declaration with warnings_as_errors.
+ ok = file:delete(Parserfile),
+ error = yecc:file(Filename, [warnings_as_errors]),
+ false = filelib:is_regular(Parserfile),
+ error = yecc:file(Filename, [return_warnings,warnings_as_errors]),
+ false = filelib:is_regular(Parserfile),
+ {error,_,[{_,[{2,yecc,bad_declaration}]}]} =
+ yecc:file(Filename, [return_errors,warnings_as_errors]),
+ false = filelib:is_regular(Parserfile),
+ {ok,_,[{_,[{2,yecc,bad_declaration}]}]} =
+ yecc:file(Filename, [return_warnings]),
+ true = filelib:is_regular(Parserfile),
+
%% Bad declaration.
?line ok = file:write_file(Filename,
<<"Nonterminals nt. Terminals t.
diff --git a/lib/parsetools/vsn.mk b/lib/parsetools/vsn.mk
index 812bf21f03..093523f0e7 100644
--- a/lib/parsetools/vsn.mk
+++ b/lib/parsetools/vsn.mk
@@ -1 +1 @@
-PARSETOOLS_VSN = 2.0.5
+PARSETOOLS_VSN = 2.0.6
diff --git a/lib/percept/doc/src/make.dep b/lib/percept/doc/src/make.dep
deleted file mode 100644
index df16cffd4f..0000000000
--- a/lib/percept/doc/src/make.dep
+++ /dev/null
@@ -1,34 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex egd.tex egd_ug.tex part.tex percept.tex \
- percept_profile.tex percept_ug.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-egd_ug.tex: img.erl img_esi.erl
-
-percept_ug.tex: sorter.erl
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: img_esi_result.ps test1.ps test2.ps test3.ps \
- test4.ps
-
-book.dvi: percept_compare.ps percept_overview.ps percept_processes.ps \
- percept_processinfo.ps
-
diff --git a/lib/percept/doc/src/notes.xml b/lib/percept/doc/src/notes.xml
index 33bfa7baab..95c2bbda56 100644
--- a/lib/percept/doc/src/notes.xml
+++ b/lib/percept/doc/src/notes.xml
@@ -32,6 +32,32 @@
</header>
<p>This document describes the changes made to the Percept application.</p>
+<section><title>Percept 0.8.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix message handling in select requests</p>
+ <p>
+ percept_db used to send results in untagged messages, and
+ use a non selective receive to extract them. When percept
+ is used from the shell process, this can confuse other
+ messages with the actual result.</p>
+ <p>
+ Add a tag to the message to be {result, Result}. Add
+ demonitor to avoid keeping DOWN message in the queue fix
+ one spec in do_start/0</p>
+ <p>
+ (Thanks to Ahmed Omar)</p>
+ <p>
+ Own Id: OTP-9490</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Percept 0.8.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/percept/doc/src/part_notes.xml b/lib/percept/doc/src/part_notes.xml
index 4965e67640..4965e67640 100755..100644
--- a/lib/percept/doc/src/part_notes.xml
+++ b/lib/percept/doc/src/part_notes.xml
diff --git a/lib/percept/src/percept_db.erl b/lib/percept/src/percept_db.erl
index 52e9afb78f..68eb38d298 100644
--- a/lib/percept/src/percept_db.erl
+++ b/lib/percept/src/percept_db.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -92,7 +92,7 @@ restart(PerceptDB)->
stop_sync(PerceptDB),
do_start().
-%% @spec do_start(pid()) -> pid()
+%% @spec do_start() -> pid()
%% @private
%% @doc starts the percept database.
@@ -131,6 +131,7 @@ stop_sync(Pid)->
{'DOWN', MonitorRef, _Type, Pid, _Info}->
true
after ?STOP_TIMEOUT->
+ erlang:demonitor(MonitorRef, [flush]),
exit(Pid, kill)
end.
@@ -166,14 +167,14 @@ insert(Trace) ->
select(Query) ->
percept_db ! {select, self(), Query},
- receive Match -> Match end.
+ receive {result, Match} -> Match end.
%% @spec select(atom(), list()) -> Result
%% @equiv select({Table,Options})
select(Table, Options) ->
percept_db ! {select, self(), {Table, Options}},
- receive Match -> Match end.
+ receive {result, Match} -> Match end.
%% @spec consolidate() -> Result
%% @doc Checks timestamp and state-flow inconsistencies in the
@@ -213,7 +214,7 @@ loop_percept_db() ->
insert_trace(clean_trace(Trace)),
loop_percept_db();
{select, Pid, Query} ->
- Pid ! select_query(Query),
+ Pid ! {result, select_query(Query)},
loop_percept_db();
{action, stop} ->
stopped;
@@ -222,7 +223,7 @@ loop_percept_db() ->
loop_percept_db();
{operate, Pid, {Table, {Fun, Start}}} ->
Result = ets:foldl(Fun, Start, Table),
- Pid ! Result,
+ Pid ! {result, Result},
loop_percept_db();
Unhandled ->
io:format("loop_percept_db, unhandled query: ~p~n", [Unhandled]),
diff --git a/lib/percept/test/percept_SUITE_data/ipc-dist.dat b/lib/percept/test/percept_SUITE_data/ipc-dist.dat
index 14ab6c0c5d..14ab6c0c5d 100755..100644
--- a/lib/percept/test/percept_SUITE_data/ipc-dist.dat
+++ b/lib/percept/test/percept_SUITE_data/ipc-dist.dat
Binary files differ
diff --git a/lib/percept/vsn.mk b/lib/percept/vsn.mk
index 2a302991aa..3b4d9bbb64 100644
--- a/lib/percept/vsn.mk
+++ b/lib/percept/vsn.mk
@@ -1 +1 @@
-PERCEPT_VSN = 0.8.5
+PERCEPT_VSN = 0.8.6
diff --git a/lib/pman/doc/src/make.dep b/lib/pman/doc/src/make.dep
deleted file mode 100644
index 2f6a8a06cd..0000000000
--- a/lib/pman/doc/src/make.dep
+++ /dev/null
@@ -1,26 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex part.tex pman.tex pman_chapter.tex \
- ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: main_window.ps options.ps trace.ps
-
diff --git a/lib/public_key/asn1/DSS.asn1 b/lib/public_key/asn1/DSS.asn1
index 77aca3808b..77aca3808b 100755..100644
--- a/lib/public_key/asn1/DSS.asn1
+++ b/lib/public_key/asn1/DSS.asn1
diff --git a/lib/public_key/asn1/InformationFramework.asn1 b/lib/public_key/asn1/InformationFramework.asn1
new file mode 100644
index 0000000000..40fbd11a2a
--- /dev/null
+++ b/lib/public_key/asn1/InformationFramework.asn1
@@ -0,0 +1,682 @@
+InformationFramework {joint-iso-itu-t ds(5) module(1) informationFramework(1)
+ 6} DEFINITIONS ::=
+BEGIN
+
+-- EXPORTS All
+-- The types and values defined in this module are exported for use in the other ASN.1 modules contained
+-- within the Directory Specifications, and for the use of other applications which will use them to access
+-- Directory services. Other applications may use them for their own purposes, but this will not constrain
+-- extensions and modifications needed to maintain or improve the Directory service.
+IMPORTS
+ -- from ITU-T Rec. X.501 | ISO/IEC 9594-2
+ directoryAbstractService, id-ar, id-at, id-mr, id-nf, id-oa, id-oc,
+ id-sc, selectedAttributeTypes, serviceAdministration
+ FROM UsefulDefinitions {joint-iso-itu-t ds(5) module(1)
+ usefulDefinitions(0) 6}
+ SearchRule
+ FROM ServiceAdministration serviceAdministration
+ -- from ITU-T Rec. X.511 | ISO/IEC 9594-3
+ TypeAndContextAssertion
+ FROM DirectoryAbstractService directoryAbstractService
+ -- from ITU-T Rec. X.520 | ISO/IEC 9594-6
+ booleanMatch, commonName, generalizedTimeMatch, generalizedTimeOrderingMatch,
+ integerFirstComponentMatch, integerMatch, integerOrderingMatch,
+ objectIdentifierFirstComponentMatch, UnboundedDirectoryString
+ FROM SelectedAttributeTypes selectedAttributeTypes;
+
+-- attribute data types
+Attribute{ATTRIBUTE:SupportedAttributes} ::= SEQUENCE {
+ type ATTRIBUTE.&id({SupportedAttributes}),
+ values
+ SET SIZE (0..MAX) OF ATTRIBUTE.&Type({SupportedAttributes}{@type}),
+ valuesWithContext
+ SET SIZE (1..MAX) OF
+ SEQUENCE {value ATTRIBUTE.&Type({SupportedAttributes}{@type}),
+ contextList SET SIZE (1..MAX) OF Context} OPTIONAL
+}
+
+AttributeType ::= ATTRIBUTE.&id
+
+AttributeValue ::= ATTRIBUTE.&Type
+
+Context ::= SEQUENCE {
+ contextType CONTEXT.&id({SupportedContexts}),
+ contextValues
+ SET SIZE (1..MAX) OF CONTEXT.&Type({SupportedContexts}{@contextType}),
+ fallback BOOLEAN DEFAULT FALSE
+}
+
+AttributeValueAssertion ::= SEQUENCE {
+ type ATTRIBUTE.&id({SupportedAttributes}),
+ assertion
+ ATTRIBUTE.&equality-match.&AssertionType
+ ({SupportedAttributes}{@type}),
+ assertedContexts
+ CHOICE {allContexts [0] NULL,
+ selectedContexts [1] SET SIZE (1..MAX) OF ContextAssertion
+ } OPTIONAL
+}
+
+ContextAssertion ::= SEQUENCE {
+ contextType CONTEXT.&id({SupportedContexts}),
+ contextValues
+ SET SIZE (1..MAX) OF
+ CONTEXT.&Assertion({SupportedContexts}{@contextType})
+}
+
+AttributeTypeAssertion ::= SEQUENCE {
+ type ATTRIBUTE.&id({SupportedAttributes}),
+ assertedContexts SEQUENCE SIZE (1..MAX) OF ContextAssertion OPTIONAL
+}
+
+-- Definition of the following information object set is deferred, perhaps to standardized
+-- profiles or to protocol implementation conformance statements. The set is required to
+-- specify a table constraint on the values component of Attribute, the value component
+-- of AttributeTypeAndValue, and the assertion component of AttributeValueAssertion.
+SupportedAttributes ATTRIBUTE ::=
+ {objectClass | aliasedEntryName, ...}
+
+-- Definition of the following information object set is deferred, perhaps to standardized
+-- profiles or to protocol implementation conformance statements. The set is required to
+-- specify a table constraint on the context specifications
+SupportedContexts CONTEXT ::=
+ {...}
+
+-- naming data types
+Name ::= CHOICE { -- only one possibility for now --rdnSequence RDNSequence
+}
+
+RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+
+DistinguishedName ::= RDNSequence
+
+RelativeDistinguishedName ::=
+ SET SIZE (1..MAX) OF AttributeTypeAndDistinguishedValue
+
+AttributeTypeAndDistinguishedValue ::= SEQUENCE {
+ type ATTRIBUTE.&id({SupportedAttributes}),
+ value ATTRIBUTE.&Type({SupportedAttributes}{@type}),
+ primaryDistinguished BOOLEAN DEFAULT TRUE,
+ valuesWithContext
+ SET SIZE (1..MAX) OF
+ SEQUENCE {distingAttrValue
+ [0] ATTRIBUTE.&Type({SupportedAttributes}{@type})
+ OPTIONAL,
+ contextList SET SIZE (1..MAX) OF Context} OPTIONAL
+}
+
+-- subtree data types
+SubtreeSpecification ::= SEQUENCE {
+ base [0] LocalName DEFAULT {},
+ COMPONENTS OF ChopSpecification,
+ specificationFilter [4] Refinement OPTIONAL
+}
+
+-- empty sequence specifies whole administrative area
+LocalName ::= RDNSequence
+
+ChopSpecification ::= SEQUENCE {
+ specificExclusions
+ [1] SET SIZE (1..MAX) OF
+ CHOICE {chopBefore [0] LocalName,
+ chopAfter [1] LocalName} OPTIONAL,
+ minimum [2] BaseDistance DEFAULT 0,
+ maximum [3] BaseDistance OPTIONAL
+}
+
+BaseDistance ::= INTEGER(0..MAX)
+
+Refinement ::= CHOICE {
+ item [0] OBJECT-CLASS.&id,
+ and [1] SET SIZE (1..MAX) OF Refinement,
+ or [2] SET SIZE (1..MAX) OF Refinement,
+ not [3] Refinement
+}
+
+-- OBJECT-CLASS information object class specification
+OBJECT-CLASS ::= CLASS {
+ &Superclasses OBJECT-CLASS OPTIONAL,
+ &kind ObjectClassKind DEFAULT structural,
+ &MandatoryAttributes ATTRIBUTE OPTIONAL,
+ &OptionalAttributes ATTRIBUTE OPTIONAL,
+ &id OBJECT IDENTIFIER UNIQUE
+}
+WITH SYNTAX {
+ [SUBCLASS OF &Superclasses]
+ [KIND &kind]
+ [MUST CONTAIN &MandatoryAttributes]
+ [MAY CONTAIN &OptionalAttributes]
+ ID &id
+}
+
+ObjectClassKind ::= ENUMERATED {abstract(0), structural(1), auxiliary(2)}
+
+-- object classes
+top OBJECT-CLASS ::= {
+ KIND abstract
+ MUST CONTAIN {objectClass}
+ ID id-oc-top
+}
+
+alias OBJECT-CLASS ::= {
+ SUBCLASS OF {top}
+ MUST CONTAIN {aliasedEntryName}
+ ID id-oc-alias
+}
+
+parent OBJECT-CLASS ::= {KIND abstract
+ ID id-oc-parent
+}
+
+child OBJECT-CLASS ::= {KIND auxiliary
+ ID id-oc-child
+}
+
+-- ATTRIBUTE information object class specification
+ATTRIBUTE ::= CLASS {
+ &derivation ATTRIBUTE OPTIONAL,
+ &Type OPTIONAL, -- either &Type or &derivation required
+ &equality-match MATCHING-RULE OPTIONAL,
+ &ordering-match MATCHING-RULE OPTIONAL,
+ &substrings-match MATCHING-RULE OPTIONAL,
+ &single-valued BOOLEAN DEFAULT FALSE,
+ &collective BOOLEAN DEFAULT FALSE,
+ &dummy BOOLEAN DEFAULT FALSE,
+ -- operational extensions
+ &no-user-modification BOOLEAN DEFAULT FALSE,
+ &usage AttributeUsage DEFAULT userApplications,
+ &id OBJECT IDENTIFIER UNIQUE
+}
+WITH SYNTAX {
+ [SUBTYPE OF &derivation]
+ [WITH SYNTAX &Type]
+ [EQUALITY MATCHING RULE &equality-match]
+ [ORDERING MATCHING RULE &ordering-match]
+ [SUBSTRINGS MATCHING RULE &substrings-match]
+ [SINGLE VALUE &single-valued]
+ [COLLECTIVE &collective]
+ [DUMMY &dummy]
+ [NO USER MODIFICATION &no-user-modification]
+ [USAGE &usage]
+ ID &id
+}
+
+AttributeUsage ::= ENUMERATED {
+ userApplications(0), directoryOperation(1), distributedOperation(2),
+ dSAOperation(3)}
+
+-- attributes
+objectClass ATTRIBUTE ::= {
+ WITH SYNTAX OBJECT IDENTIFIER
+ EQUALITY MATCHING RULE objectIdentifierMatch
+ ID id-at-objectClass
+}
+
+aliasedEntryName ATTRIBUTE ::= {
+ WITH SYNTAX DistinguishedName
+ EQUALITY MATCHING RULE distinguishedNameMatch
+ SINGLE VALUE TRUE
+ ID id-at-aliasedEntryName
+}
+
+-- MATCHING-RULE information object class specification
+MATCHING-RULE ::= CLASS {
+ &ParentMatchingRules MATCHING-RULE OPTIONAL,
+ &AssertionType OPTIONAL,
+ &uniqueMatchIndicator ATTRIBUTE OPTIONAL,
+ &id OBJECT IDENTIFIER UNIQUE
+}
+WITH SYNTAX {
+ [PARENT &ParentMatchingRules]
+ [SYNTAX &AssertionType]
+ [UNIQUE-MATCH-INDICATOR &uniqueMatchIndicator]
+ ID &id
+}
+
+-- matching rules
+objectIdentifierMatch MATCHING-RULE ::= {
+ SYNTAX OBJECT IDENTIFIER
+ ID id-mr-objectIdentifierMatch
+}
+
+distinguishedNameMatch MATCHING-RULE ::= {
+ SYNTAX DistinguishedName
+ ID id-mr-distinguishedNameMatch
+}
+
+MAPPING-BASED-MATCHING{SelectedBy, BOOLEAN:combinable, MappingResult,
+ OBJECT IDENTIFIER:matchingRule} ::= CLASS {
+ &selectBy SelectedBy OPTIONAL,
+ &ApplicableTo ATTRIBUTE,
+ &subtypesIncluded BOOLEAN DEFAULT TRUE,
+ &combinable BOOLEAN(combinable),
+ &mappingResults MappingResult OPTIONAL,
+ &userControl BOOLEAN DEFAULT FALSE,
+ &exclusive BOOLEAN DEFAULT TRUE,
+ &matching-rule MATCHING-RULE.&id(matchingRule),
+ &id OBJECT IDENTIFIER UNIQUE
+}
+WITH SYNTAX {
+ [SELECT BY &selectBy]
+ APPLICABLE TO &ApplicableTo
+ [SUBTYPES INCLUDED &subtypesIncluded]
+ COMBINABLE &combinable
+ [MAPPING RESULTS &mappingResults]
+ [USER CONTROL &userControl]
+ [EXCLUSIVE &exclusive]
+ MATCHING RULE &matching-rule
+ ID &id
+}
+
+-- NAME-FORM information object class specification
+NAME-FORM ::= CLASS {
+ &namedObjectClass OBJECT-CLASS,
+ &MandatoryAttributes ATTRIBUTE,
+ &OptionalAttributes ATTRIBUTE OPTIONAL,
+ &id OBJECT IDENTIFIER UNIQUE
+}
+WITH SYNTAX {
+ NAMES &namedObjectClass
+ WITH ATTRIBUTES &MandatoryAttributes
+ [AND OPTIONALLY &OptionalAttributes]
+ ID &id
+}
+
+-- STRUCTURE-RULE class and DIT structure rule data types
+DITStructureRule ::= SEQUENCE {
+ ruleIdentifier RuleIdentifier,
+ -- shall be unique within the scope of the subschema
+ nameForm NAME-FORM.&id,
+ superiorStructureRules SET SIZE (1..MAX) OF RuleIdentifier OPTIONAL
+}
+
+RuleIdentifier ::= INTEGER
+
+STRUCTURE-RULE ::= CLASS {
+ &nameForm NAME-FORM,
+ &SuperiorStructureRules STRUCTURE-RULE OPTIONAL,
+ &id RuleIdentifier
+}
+WITH SYNTAX {
+ NAME FORM &nameForm
+ [SUPERIOR RULES &SuperiorStructureRules]
+ ID &id
+}
+
+-- DIT content rule data type and CONTENT-RULE class
+DITContentRule ::= SEQUENCE {
+ structuralObjectClass OBJECT-CLASS.&id,
+ auxiliaries SET SIZE (1..MAX) OF OBJECT-CLASS.&id OPTIONAL,
+ mandatory [1] SET SIZE (1..MAX) OF ATTRIBUTE.&id OPTIONAL,
+ optional [2] SET SIZE (1..MAX) OF ATTRIBUTE.&id OPTIONAL,
+ precluded [3] SET SIZE (1..MAX) OF ATTRIBUTE.&id OPTIONAL
+}
+
+CONTENT-RULE ::= CLASS {
+ &structuralClass OBJECT-CLASS.&id UNIQUE,
+ &Auxiliaries OBJECT-CLASS OPTIONAL,
+ &Mandatory ATTRIBUTE OPTIONAL,
+ &Optional ATTRIBUTE OPTIONAL,
+ &Precluded ATTRIBUTE OPTIONAL
+}
+WITH SYNTAX {
+ STRUCTURAL OBJECT-CLASS &structuralClass
+ [AUXILIARY OBJECT-CLASSES &Auxiliaries]
+ [MUST CONTAIN &Mandatory]
+ [MAY CONTAIN &Optional]
+ [MUST-NOT CONTAIN &Precluded]
+}
+
+CONTEXT ::= CLASS {
+ &Type ,
+ &DefaultValue OPTIONAL,
+ &Assertion OPTIONAL,
+ &absentMatch BOOLEAN DEFAULT TRUE,
+ &id OBJECT IDENTIFIER UNIQUE
+}
+WITH SYNTAX {
+ WITH SYNTAX &Type
+ [DEFAULT-VALUE &DefaultValue]
+ [ASSERTED AS &Assertion]
+ [ABSENT-MATCH &absentMatch]
+ ID &id
+}
+
+DITContextUse ::= SEQUENCE {
+ attributeType ATTRIBUTE.&id,
+ mandatoryContexts [1] SET SIZE (1..MAX) OF CONTEXT.&id OPTIONAL,
+ optionalContexts [2] SET SIZE (1..MAX) OF CONTEXT.&id OPTIONAL
+}
+
+DIT-CONTEXT-USE-RULE ::= CLASS {
+ &attributeType ATTRIBUTE.&id UNIQUE,
+ &Mandatory CONTEXT OPTIONAL,
+ &Optional CONTEXT OPTIONAL
+}
+WITH SYNTAX {
+ ATTRIBUTE TYPE &attributeType
+ [MANDATORY CONTEXTS &Mandatory]
+ [OPTIONAL CONTEXTS &Optional]
+}
+
+FRIENDS ::= CLASS {
+ &anchor ATTRIBUTE.&id UNIQUE,
+ &Friends ATTRIBUTE
+}WITH SYNTAX {ANCHOR &anchor
+ FRIENDS &Friends
+}
+
+-- system schema information objects
+-- object classes
+subentry OBJECT-CLASS ::= {
+ SUBCLASS OF {top}
+ KIND structural
+ MUST CONTAIN {commonName | subtreeSpecification}
+ ID id-sc-subentry
+}
+
+subentryNameForm NAME-FORM ::= {
+ NAMES subentry
+ WITH ATTRIBUTES {commonName}
+ ID id-nf-subentryNameForm
+}
+
+subtreeSpecification ATTRIBUTE ::= {
+ WITH SYNTAX SubtreeSpecification
+ USAGE directoryOperation
+ ID id-oa-subtreeSpecification
+}
+
+administrativeRole ATTRIBUTE ::= {
+ WITH SYNTAX OBJECT-CLASS.&id
+ EQUALITY MATCHING RULE objectIdentifierMatch
+ USAGE directoryOperation
+ ID id-oa-administrativeRole
+}
+
+createTimestamp ATTRIBUTE ::= {
+ WITH SYNTAX GeneralizedTime
+ -- as per 46.3 b) or c) of ITU-T Rec. X.680 | ISO/IEC 8824-1
+ EQUALITY MATCHING RULE generalizedTimeMatch
+ ORDERING MATCHING RULE generalizedTimeOrderingMatch
+ SINGLE VALUE TRUE
+ NO USER MODIFICATION TRUE
+ USAGE directoryOperation
+ ID id-oa-createTimestamp
+}
+
+modifyTimestamp ATTRIBUTE ::= {
+ WITH SYNTAX GeneralizedTime
+ -- as per 46.3 b) or c) of ITU-T Rec. X.680 | ISO/IEC 8824-1
+ EQUALITY MATCHING RULE generalizedTimeMatch
+ ORDERING MATCHING RULE generalizedTimeOrderingMatch
+ SINGLE VALUE TRUE
+ NO USER MODIFICATION TRUE
+ USAGE directoryOperation
+ ID id-oa-modifyTimestamp
+}
+
+subschemaTimestamp ATTRIBUTE ::= {
+ WITH SYNTAX GeneralizedTime
+ -- as per 46.3 b) or c) of ITU-T Rec. X.680 | ISO/IEC 8824-1
+ EQUALITY MATCHING RULE generalizedTimeMatch
+ ORDERING MATCHING RULE generalizedTimeOrderingMatch
+ SINGLE VALUE TRUE
+ NO USER MODIFICATION TRUE
+ USAGE directoryOperation
+ ID id-oa-subschemaTimestamp
+}
+
+creatorsName ATTRIBUTE ::= {
+ WITH SYNTAX DistinguishedName
+ EQUALITY MATCHING RULE distinguishedNameMatch
+ SINGLE VALUE TRUE
+ NO USER MODIFICATION TRUE
+ USAGE directoryOperation
+ ID id-oa-creatorsName
+}
+
+modifiersName ATTRIBUTE ::= {
+ WITH SYNTAX DistinguishedName
+ EQUALITY MATCHING RULE distinguishedNameMatch
+ SINGLE VALUE TRUE
+ NO USER MODIFICATION TRUE
+ USAGE directoryOperation
+ ID id-oa-modifiersName
+}
+
+subschemaSubentryList ATTRIBUTE ::= {
+ WITH SYNTAX DistinguishedName
+ EQUALITY MATCHING RULE distinguishedNameMatch
+ SINGLE VALUE TRUE
+ NO USER MODIFICATION TRUE
+ USAGE directoryOperation
+ ID id-oa-subschemaSubentryList
+}
+
+accessControlSubentryList ATTRIBUTE ::= {
+ WITH SYNTAX DistinguishedName
+ EQUALITY MATCHING RULE distinguishedNameMatch
+ NO USER MODIFICATION TRUE
+ USAGE directoryOperation
+ ID id-oa-accessControlSubentryList
+}
+
+collectiveAttributeSubentryList ATTRIBUTE ::= {
+ WITH SYNTAX DistinguishedName
+ EQUALITY MATCHING RULE distinguishedNameMatch
+ NO USER MODIFICATION TRUE
+ USAGE directoryOperation
+ ID id-oa-collectiveAttributeSubentryList
+}
+
+contextDefaultSubentryList ATTRIBUTE ::= {
+ WITH SYNTAX DistinguishedName
+ EQUALITY MATCHING RULE distinguishedNameMatch
+ NO USER MODIFICATION TRUE
+ USAGE directoryOperation
+ ID id-oa-contextDefaultSubentryList
+}
+
+serviceAdminSubentryList ATTRIBUTE ::= {
+ WITH SYNTAX DistinguishedName
+ EQUALITY MATCHING RULE distinguishedNameMatch
+ NO USER MODIFICATION TRUE
+ USAGE directoryOperation
+ ID id-oa-serviceAdminSubentryList
+}
+
+hasSubordinates ATTRIBUTE ::= {
+ WITH SYNTAX BOOLEAN
+ EQUALITY MATCHING RULE booleanMatch
+ SINGLE VALUE TRUE
+ NO USER MODIFICATION TRUE
+ USAGE directoryOperation
+ ID id-oa-hasSubordinates
+}
+
+accessControlSubentry OBJECT-CLASS ::= {
+ KIND auxiliary
+ ID id-sc-accessControlSubentry
+}
+
+collectiveAttributeSubentry OBJECT-CLASS ::= {
+ KIND auxiliary
+ ID id-sc-collectiveAttributeSubentry
+}
+
+collectiveExclusions ATTRIBUTE ::= {
+ WITH SYNTAX OBJECT IDENTIFIER
+ EQUALITY MATCHING RULE objectIdentifierMatch
+ USAGE directoryOperation
+ ID id-oa-collectiveExclusions
+}
+
+contextAssertionSubentry OBJECT-CLASS ::= {
+ KIND auxiliary
+ MUST CONTAIN {contextAssertionDefaults}
+ ID id-sc-contextAssertionSubentry
+}
+
+contextAssertionDefaults ATTRIBUTE ::= {
+ WITH SYNTAX TypeAndContextAssertion
+ EQUALITY MATCHING RULE objectIdentifierFirstComponentMatch
+ USAGE directoryOperation
+ ID id-oa-contextAssertionDefault
+}
+
+serviceAdminSubentry OBJECT-CLASS ::= {
+ KIND auxiliary
+ MUST CONTAIN {searchRules}
+ ID id-sc-serviceAdminSubentry
+}
+
+searchRules ATTRIBUTE ::= {
+ WITH SYNTAX SearchRuleDescription
+ EQUALITY MATCHING RULE integerFirstComponentMatch
+ USAGE directoryOperation
+ ID id-oa-searchRules
+}
+
+SearchRuleDescription ::= SEQUENCE {
+ COMPONENTS OF SearchRule,
+ name [28] SET SIZE (1..MAX) OF UnboundedDirectoryString OPTIONAL,
+ description [29] UnboundedDirectoryString OPTIONAL
+}
+
+hierarchyLevel ATTRIBUTE ::= {
+ WITH SYNTAX HierarchyLevel
+ EQUALITY MATCHING RULE integerMatch
+ ORDERING MATCHING RULE integerOrderingMatch
+ SINGLE VALUE TRUE
+ NO USER MODIFICATION TRUE
+ USAGE directoryOperation
+ ID id-oa-hierarchyLevel
+}
+
+HierarchyLevel ::= INTEGER
+
+hierarchyBelow ATTRIBUTE ::= {
+ WITH SYNTAX HierarchyBelow
+ EQUALITY MATCHING RULE booleanMatch
+ SINGLE VALUE TRUE
+ NO USER MODIFICATION TRUE
+ USAGE directoryOperation
+ ID id-oa-hierarchyBelow
+}
+
+HierarchyBelow ::= BOOLEAN
+
+hierarchyParent ATTRIBUTE ::= {
+ WITH SYNTAX DistinguishedName
+ EQUALITY MATCHING RULE distinguishedNameMatch
+ SINGLE VALUE TRUE
+ USAGE directoryOperation
+ ID id-oa-hierarchyParent
+}
+
+hierarchyTop ATTRIBUTE ::= {
+ WITH SYNTAX DistinguishedName
+ EQUALITY MATCHING RULE distinguishedNameMatch
+ SINGLE VALUE TRUE
+ USAGE directoryOperation
+ ID id-oa-hierarchyTop
+}
+
+-- object identifier assignments
+-- object classes
+id-oc-top OBJECT IDENTIFIER ::=
+ {id-oc 0}
+
+id-oc-alias OBJECT IDENTIFIER ::= {id-oc 1}
+
+id-oc-parent OBJECT IDENTIFIER ::= {id-oc 28}
+
+id-oc-child OBJECT IDENTIFIER ::= {id-oc 29}
+
+-- attributes
+id-at-objectClass OBJECT IDENTIFIER ::= {id-at 0}
+
+id-at-aliasedEntryName OBJECT IDENTIFIER ::= {id-at 1}
+
+-- matching rules
+id-mr-objectIdentifierMatch OBJECT IDENTIFIER ::= {id-mr 0}
+
+id-mr-distinguishedNameMatch OBJECT IDENTIFIER ::= {id-mr 1}
+
+-- operational attributes
+id-oa-excludeAllCollectiveAttributes OBJECT IDENTIFIER ::=
+ {id-oa 0}
+
+id-oa-createTimestamp OBJECT IDENTIFIER ::= {id-oa 1}
+
+id-oa-modifyTimestamp OBJECT IDENTIFIER ::= {id-oa 2}
+
+id-oa-creatorsName OBJECT IDENTIFIER ::= {id-oa 3}
+
+id-oa-modifiersName OBJECT IDENTIFIER ::= {id-oa 4}
+
+id-oa-administrativeRole OBJECT IDENTIFIER ::= {id-oa 5}
+
+id-oa-subtreeSpecification OBJECT IDENTIFIER ::= {id-oa 6}
+
+id-oa-collectiveExclusions OBJECT IDENTIFIER ::= {id-oa 7}
+
+id-oa-subschemaTimestamp OBJECT IDENTIFIER ::= {id-oa 8}
+
+id-oa-hasSubordinates OBJECT IDENTIFIER ::= {id-oa 9}
+
+id-oa-subschemaSubentryList OBJECT IDENTIFIER ::= {id-oa 10}
+
+id-oa-accessControlSubentryList OBJECT IDENTIFIER ::= {id-oa 11}
+
+id-oa-collectiveAttributeSubentryList OBJECT IDENTIFIER ::= {id-oa 12}
+
+id-oa-contextDefaultSubentryList OBJECT IDENTIFIER ::= {id-oa 13}
+
+id-oa-contextAssertionDefault OBJECT IDENTIFIER ::= {id-oa 14}
+
+id-oa-serviceAdminSubentryList OBJECT IDENTIFIER ::= {id-oa 15}
+
+id-oa-searchRules OBJECT IDENTIFIER ::= {id-oa 16}
+
+id-oa-hierarchyLevel OBJECT IDENTIFIER ::= {id-oa 17}
+
+id-oa-hierarchyBelow OBJECT IDENTIFIER ::= {id-oa 18}
+
+id-oa-hierarchyParent OBJECT IDENTIFIER ::= {id-oa 19}
+
+id-oa-hierarchyTop OBJECT IDENTIFIER ::= {id-oa 20}
+
+-- subentry classes
+id-sc-subentry OBJECT IDENTIFIER ::= {id-sc 0}
+
+id-sc-accessControlSubentry OBJECT IDENTIFIER ::= {id-sc 1}
+
+id-sc-collectiveAttributeSubentry OBJECT IDENTIFIER ::= {id-sc 2}
+
+id-sc-contextAssertionSubentry OBJECT IDENTIFIER ::= {id-sc 3}
+
+id-sc-serviceAdminSubentry OBJECT IDENTIFIER ::= {id-sc 4}
+
+-- Name forms
+id-nf-subentryNameForm OBJECT IDENTIFIER ::= {id-nf 16}
+
+-- administrative roles
+id-ar-autonomousArea OBJECT IDENTIFIER ::= {id-ar 1}
+
+id-ar-accessControlSpecificArea OBJECT IDENTIFIER ::= {id-ar 2}
+
+id-ar-accessControlInnerArea OBJECT IDENTIFIER ::= {id-ar 3}
+
+id-ar-subschemaAdminSpecificArea OBJECT IDENTIFIER ::= {id-ar 4}
+
+id-ar-collectiveAttributeSpecificArea OBJECT IDENTIFIER ::= {id-ar 5}
+
+id-ar-collectiveAttributeInnerArea OBJECT IDENTIFIER ::= {id-ar 6}
+
+id-ar-contextDefaultSpecificArea OBJECT IDENTIFIER ::= {id-ar 7}
+
+id-ar-serviceSpecificArea OBJECT IDENTIFIER ::= {id-ar 8}
+
+END -- InformationFramework
diff --git a/lib/public_key/asn1/Makefile b/lib/public_key/asn1/Makefile
index 94abec083c..2ce1168349 100644
--- a/lib/public_key/asn1/Makefile
+++ b/lib/public_key/asn1/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2010. All Rights Reserved.
+# Copyright Ericsson AB 2008-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -38,12 +38,12 @@ RELSYSDIR = $(RELEASE_PATH)/lib/public_key-$(VSN)
.SUFFIXES: .asn1
.PRECIOUS: %.erl
-ASN_TOP = OTP-PUB-KEY
+ASN_TOP = OTP-PUB-KEY PKCS-FRAME
ASN_MODULES = PKIX1Explicit88 PKIX1Implicit88 PKIX1Algorithms88 \
- PKIXAttributeCertificate PKCS-1 PKCS-3 OTP-PKIX
+ PKIXAttributeCertificate PKCS-1 PKCS-3 PKCS-8 InformationFramework PKCS5v2-0 OTP-PKIX
ASN_ASNS = $(ASN_MODULES:%=%.asn1)
-ASN_ERLS = $(ASN_TOP).erl
-ASN_HRLS = $(ASN_TOP).hrl
+ASN_ERLS = $(ASN_TOP:%=%.erl)
+ASN_HRLS = $(ASN_TOP:%=%.hrl)
ASN_CONFIGS = OTP-PUB-KEY.asn1config
ASN_DBS = $(ASN_MODULES:%=%.asn1db) OTP-PUB-KEY.asn1db
ASN_TABLES = $(ASN_MODULES:%=%.table)
@@ -65,7 +65,7 @@ EBIN = ../ebin
EXTRA_ERLC_FLAGS =
ERL_COMPILE_FLAGS += $(EXTRA_ERLC_FLAGS)
-ASN_FLAGS = -bber_bin +der +compact_bit_string +optimize +noobj +asn1config +inline
+ASN_FLAGS = -bber_bin +der +compact_bit_string +optimize +noobj +asn1config +inline +nif
# ----------------------------------------------------
# Targets
@@ -79,11 +79,11 @@ clean:
docs:
-%.erl: %.set.asn
+%.erl %.hrl: %.set.asn
erlc $(ASN_FLAGS) $<
-$(HRL_FILES): $(ASN_HRLS)
- cp -p $(ASN_HRLS) $(INCLUDE)
+$(INCLUDE)/%.hrl: %.hrl
+ cp -p $< $@
# ----------------------------------------------------
# Release Target
@@ -113,3 +113,9 @@ OTP-PUB-KEY.asn1db: PKIX1Algorithms88.asn1 \
PKCS-1.asn1\
PKCS-3.asn1\
OTP-PKIX.asn1
+
+$(EBIN)/PKCS-FRAME.beam: PKCS-FRAME.erl PKCS-FRAME.hrl
+PKCS-FRAME.erl PKCS-FRAME.hrl: PKCS-FRAME.asn1db
+PKCS-FRAME.asn1db: PKCS-8.asn1\
+ InformationFramework.asn1\
+ PKCS5v2-0.asn1 \ No newline at end of file
diff --git a/lib/public_key/asn1/PKCS-1.asn1 b/lib/public_key/asn1/PKCS-1.asn1
index b06f5efa9d..b06f5efa9d 100755..100644
--- a/lib/public_key/asn1/PKCS-1.asn1
+++ b/lib/public_key/asn1/PKCS-1.asn1
diff --git a/lib/public_key/asn1/PKCS-8.asn1 b/lib/public_key/asn1/PKCS-8.asn1
new file mode 100644
index 0000000000..7413519b57
--- /dev/null
+++ b/lib/public_key/asn1/PKCS-8.asn1
@@ -0,0 +1,83 @@
+PKCS-8 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-8(8)
+ modules(1) pkcs-8(1)}
+
+-- $Revision: 1.5 $
+
+-- This module has been checked for conformance with the ASN.1
+-- standard by the OSS ASN.1 Tools
+
+DEFINITIONS IMPLICIT TAGS ::=
+
+BEGIN
+
+-- EXPORTS All --
+-- All types and values defined in this module is exported for use in other
+-- ASN.1 modules.
+
+IMPORTS
+
+-- informationFramework
+-- FROM UsefulDefinitions {joint-iso-itu-t(2) ds(5) module(1)
+-- usefulDefinitions(0) 3}
+
+Attribute
+-- FROM InformationFramework informationFramework
+ FROM InformationFramework;
+
+-- This import is really unnecessary since ALGORITHM-IDENTIFIER is defined as a
+-- TYPE-IDENTIFIER
+-- Renome this import and replace all occurences of ALGORITHM-IDENTIFIER with
+-- TYPE-IDENTIFIER as a workaround for weaknesses in the ASN.1 compiler
+--AlgorithmIdentifier, ALGORITHM-IDENTIFIER
+-- FROM PKCS5v2-0 {iso(1) member-body(2) us(840) rsadsi(113549)
+-- pkcs(1) pkcs-5(5) modules(16) pkcs-5(1)};
+
+-- Inlined from PKCS5v2-0 since it is the only thing imported from that module
+-- AlgorithmIdentifier { ALGORITHM-IDENTIFIER:InfoObjectSet } ::=
+AlgorithmIdentifier { TYPE-IDENTIFIER:InfoObjectSet } ::=
+SEQUENCE {
+-- algorithm ALGORITHM-IDENTIFIER.&id({InfoObjectSet}),
+ algorithm TYPE-IDENTIFIER.&id({InfoObjectSet}),
+-- parameters ALGORITHM-IDENTIFIER.&Type({InfoObjectSet}
+ parameters TYPE-IDENTIFIER.&Type({InfoObjectSet}
+ {@algorithm}) OPTIONAL }
+
+-- Private-key information syntax
+
+PrivateKeyInfo ::= SEQUENCE {
+ version Version,
+-- privateKeyAlgorithm AlgorithmIdentifier {{PrivateKeyAlgorithms}},
+ privateKeyAlgorithm AlgorithmIdentifier {{...}},
+ privateKey PrivateKey,
+ attributes [0] Attributes OPTIONAL }
+
+Version ::= INTEGER {v1(0)} (v1,...)
+
+PrivateKey ::= OCTET STRING
+
+-- Attributes ::= SET OF Attribute
+Attributes ::= SET OF Attribute {{...}}
+
+-- Encrypted private-key information syntax
+
+EncryptedPrivateKeyInfo ::= SEQUENCE {
+-- encryptionAlgorithm AlgorithmIdentifier {{KeyEncryptionAlgorithms}},
+ encryptionAlgorithm AlgorithmIdentifier {{...}},
+ encryptedData EncryptedData
+}
+
+EncryptedData ::= OCTET STRING
+
+-- PrivateKeyAlgorithms ALGORITHM-IDENTIFIER ::= {
+PrivateKeyAlgorithms TYPE-IDENTIFIER ::= {
+ ... -- For local profiles
+}
+
+-- KeyEncryptionAlgorithms ALGORITHM-IDENTIFIER ::= {
+KeyEncryptionAlgorithms TYPE-IDENTIFIER ::= {
+ ... -- For local profiles
+}
+
+END
+
+
diff --git a/lib/public_key/asn1/PKCS-FRAME.set.asn b/lib/public_key/asn1/PKCS-FRAME.set.asn
new file mode 100644
index 0000000000..a0777ff260
--- /dev/null
+++ b/lib/public_key/asn1/PKCS-FRAME.set.asn
@@ -0,0 +1,3 @@
+PKCS-8.asn1
+InformationFramework.asn1
+PKCS5v2-0.asn1
diff --git a/lib/public_key/asn1/PKCS5v2-0.asn1 b/lib/public_key/asn1/PKCS5v2-0.asn1
new file mode 100644
index 0000000000..fe7e16c7fa
--- /dev/null
+++ b/lib/public_key/asn1/PKCS5v2-0.asn1
@@ -0,0 +1,142 @@
+-- PKCS #5 v2.0 ASN.1 Module
+-- Revised March 25, 1999
+
+-- This module has been checked for conformance with the
+-- ASN.1 standard by the OSS ASN.1 Tools
+
+PKCS5v2-0 {iso(1) member-body(2) us(840) rsadsi(113549)
+ pkcs(1) pkcs-5(5) modules(16) pkcs5v2-0(1)}
+
+DEFINITIONS ::= BEGIN
+
+-- Basic object identifiers
+
+rsadsi OBJECT IDENTIFIER ::=
+ {iso(1) member-body(2) us(840) 113549}
+pkcs OBJECT IDENTIFIER ::= {rsadsi 1}
+pkcs-5 OBJECT IDENTIFIER ::= {pkcs 5}
+
+-- Basic types and classes
+
+AlgorithmIdentifier { TYPE-IDENTIFIER:InfoObjectSet } ::=
+SEQUENCE {
+ algorithm TYPE-IDENTIFIER.&id({InfoObjectSet}),
+ parameters TYPE-IDENTIFIER.&Type({InfoObjectSet}
+ {@algorithm}) OPTIONAL }
+
+--ALGORITHM-IDENTIFIER ::= TYPE-IDENTIFIER
+
+-- PBKDF2
+
+-- PBKDF2Algorithms ALGORITHM-IDENTIFIER ::=
+-- { {PBKDF2-params IDENTIFIED BY id-PBKDF2}, ...}
+
+id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12}
+
+-- algid-hmacWithSHA1 AlgorithmIdentifier {{PBKDF2-PRFs}} ::=
+-- {algorithm id-hmacWithSHA1, parameters NULL : NULL}
+
+PBKDF2-params ::= SEQUENCE {
+ salt CHOICE {
+ specified OCTET STRING,
+ otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}}
+ },
+ iterationCount INTEGER (1..MAX),
+ keyLength INTEGER (1..MAX) OPTIONAL,
+ prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT
+{algorithm id-hmacWithSHA1, parameters NULL : NULL}}
+-- algid-hmacWithSHA1 }
+
+PBKDF2-SaltSources TYPE-IDENTIFIER ::= { ... }
+
+PBKDF2-PRFs TYPE-IDENTIFIER ::=
+ { {NULL IDENTIFIED BY id-hmacWithSHA1}, ... }
+
+ -- PBES1
+
+PBES1Algorithms TYPE-IDENTIFIER ::=
+ { {PBEParameter IDENTIFIED BY pbeWithMD2AndDES-CBC} |
+ {PBEParameter IDENTIFIED BY pbeWithMD2AndRC2-CBC} |
+ {PBEParameter IDENTIFIED BY pbeWithMD5AndDES-CBC} |
+ {PBEParameter IDENTIFIED BY pbeWithMD5AndRC2-CBC} |
+ {PBEParameter IDENTIFIED BY pbeWithSHA1AndDES-CBC} |
+ {PBEParameter IDENTIFIED BY pbeWithSHA1AndRC2-CBC}, ...}
+
+pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1}
+pbeWithMD2AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 4}
+pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3}
+pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6}
+pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10}
+pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11}
+
+PBEParameter ::= SEQUENCE {
+ salt OCTET STRING (SIZE(8)),
+ iterationCount INTEGER }
+
+-- PBES2
+
+PBES2Algorithms TYPE-IDENTIFIER ::=
+ { {PBES2-params IDENTIFIED BY id-PBES2}, ...}
+
+id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13}
+
+PBES2-params ::= SEQUENCE {
+ keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
+ encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} }
+
+PBES2-KDFs TYPE-IDENTIFIER ::=
+ { {PBKDF2-params IDENTIFIED BY id-PBKDF2}, ... }
+
+PBES2-Encs TYPE-IDENTIFIER ::= { ... }
+
+-- PBMAC1
+
+PBMAC1Algorithms TYPE-IDENTIFIER ::=
+ { {PBMAC1-params IDENTIFIED BY id-PBMAC1}, ...}
+
+id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14}
+
+PBMAC1-params ::= SEQUENCE {
+ keyDerivationFunc AlgorithmIdentifier {{PBMAC1-KDFs}},
+ messageAuthScheme AlgorithmIdentifier {{PBMAC1-MACs}} }
+
+PBMAC1-KDFs TYPE-IDENTIFIER ::=
+ { {PBKDF2-params IDENTIFIED BY id-PBKDF2}, ... }
+
+PBMAC1-MACs TYPE-IDENTIFIER ::= { ... }
+
+-- Supporting techniques
+
+digestAlgorithm OBJECT IDENTIFIER ::= {rsadsi 2}
+encryptionAlgorithm OBJECT IDENTIFIER ::= {rsadsi 3}
+
+SupportingAlgorithms TYPE-IDENTIFIER ::=
+ { {NULL IDENTIFIED BY id-hmacWithSHA1} |
+ {OCTET STRING (SIZE(8)) IDENTIFIED BY desCBC} |
+ {OCTET STRING (SIZE(8)) IDENTIFIED BY des-EDE3-CBC} |
+ {RC2-CBC-Parameter IDENTIFIED BY rc2CBC} |
+ {RC5-CBC-Parameters IDENTIFIED BY rc5-CBC-PAD}, ... }
+
+id-hmacWithSHA1 OBJECT IDENTIFIER ::= {digestAlgorithm 7}
+
+desCBC OBJECT IDENTIFIER ::=
+ {iso(1) identified-organization(3) oiw(14) secsig(3)
+ algorithms(2) 7} -- from OIW
+
+des-EDE3-CBC OBJECT IDENTIFIER ::= {encryptionAlgorithm 7}
+
+rc2CBC OBJECT IDENTIFIER ::= {encryptionAlgorithm 2}
+
+RC2-CBC-Parameter ::= SEQUENCE {
+ rc2ParameterVersion INTEGER OPTIONAL,
+ iv OCTET STRING (SIZE(8)) }
+
+rc5-CBC-PAD OBJECT IDENTIFIER ::= {encryptionAlgorithm 9}
+
+RC5-CBC-Parameters ::= SEQUENCE {
+ version INTEGER {v1-0(16)}, -- (v1-0),
+ rounds INTEGER (8..127),
+ blockSizeInBits INTEGER (64 | 128),
+ iv OCTET STRING OPTIONAL }
+
+END
diff --git a/lib/public_key/asn1/README b/lib/public_key/asn1/README
index 5fb8cf9725..2a880e2d51 100644
--- a/lib/public_key/asn1/README
+++ b/lib/public_key/asn1/README
@@ -46,6 +46,6 @@ diff -r1.1 PKIXAttributeCertificate.asn1
---
> version AttCertVersion, -- version is v2
-4. Defenitions of publuic keys from PKCS-1.asn1 present in
+4. Definitions of public keys from PKCS-1.asn1 present in
PKIX1Algorithms88.asn1 where removed as we take them directly from
PKCS-1.asn1 \ No newline at end of file
diff --git a/lib/public_key/doc/src/Makefile b/lib/public_key/doc/src/Makefile
index afb17399da..9616a96195 100644
--- a/lib/public_key/doc/src/Makefile
+++ b/lib/public_key/doc/src/Makefile
@@ -29,14 +29,6 @@ VSN=$(PUBLIC_KEY_VSN)
APPLICATION=public_key
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -79,33 +71,10 @@ EXTRA_FILES = \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_PART_FILES:%.xml=%.tex) \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = public_key-$(VSN).pdf
-TOP_PS_FILE = public_key-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -118,8 +87,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -134,33 +101,6 @@ clean clean_docs:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES)
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ min_head.gif \
- $(LATEX_CLEAN)
-
-endif
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -173,8 +113,6 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
$(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
$(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
@@ -184,30 +122,6 @@ release_docs_spec: docs
$(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
$(INSTALL_DIR) $(RELEASE_PATH)/man/man3
$(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-endif
-endif
-
-endif
-
release_spec:
info:
diff --git a/lib/public_key/doc/src/introduction.xml b/lib/public_key/doc/src/introduction.xml
index 8cf11ee10e..a21fcf3576 100644
--- a/lib/public_key/doc/src/introduction.xml
+++ b/lib/public_key/doc/src/introduction.xml
@@ -48,5 +48,13 @@
of the concepts of using public keys.</p>
</section>
+ <section>
+ <title>Performance tips</title>
+ <p>The public_key decode and encode functions will try to use the nifs
+ which are in the asn1 compilers runtime modules if they can be found.
+ So for the best performance you want to have the asn1 application in the
+ path of your system. </p>
+ </section>
+
</chapter>
diff --git a/lib/public_key/doc/src/make.dep b/lib/public_key/doc/src/make.dep
deleted file mode 100644
index 2675556f1b..0000000000
--- a/lib/public_key/doc/src/make.dep
+++ /dev/null
@@ -1,21 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex cert_records.tex introduction.tex \
- part.tex public_key.tex public_key_records.tex \
- ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/public_key/doc/src/notes.xml b/lib/public_key/doc/src/notes.xml
index 9d77750ea2..efd4a37eb9 100644
--- a/lib/public_key/doc/src/notes.xml
+++ b/lib/public_key/doc/src/notes.xml
@@ -34,6 +34,23 @@
<file>notes.xml</file>
</header>
+<section><title>Public_Key 0.13</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ replace "a ssl" with "an ssl" reindent
+ pkix_path_validation/3 Trivial documentation fixes
+ (Thanks to Christian von Roques )</p>
+ <p>
+ Own Id: OTP-9464</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Public_Key 0.12</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml
index d60d91cd83..821e7a2300 100644
--- a/lib/public_key/doc/src/public_key.xml
+++ b/lib/public_key/doc/src/public_key.xml
@@ -61,19 +61,20 @@
<p><code>string = [bytes()]</code></p>
<p><code>pki_asn1_type() = 'Certificate' | 'RSAPrivateKey'| 'RSAPublicKey'
- 'DSAPrivateKey' | 'DSAPublicKey' | 'DHParameter' | 'SubjectPublicKeyInfo'</code></p>
-
- <p><code>pem_entry () = {pki_asn1_type(), binary() %% DER or encrypted DER
- not_encrypted | {"DES-CBC" | "DES-EDE3-CBC", crypto:rand_bytes(8)}}.</code></p>
+ 'DSAPrivateKey' | 'DSAPublicKey' | 'DHParameter' | 'SubjectPublicKeyInfo'| 'PrivateKeyInfo'</code></p>
+ <p><code>pem_entry () = {pki_asn1_type(), binary(), %% DER or encrypted DER
+ not_encrypted | cipher_info()} </code></p>
+
+ <p><code>cipher_info() = {"RC2-CBC | "DES-CBC" | "DES-EDE3-CBC", crypto:rand_bytes(8)} |
+ 'PBES2-params'} </code></p>
+
<p><code>rsa_public_key() = #'RSAPublicKey'{}</code></p>
<p><code>rsa_private_key() = #'RSAPrivateKey'{} </code></p>
<p><code>dsa_public_key() = {integer(), #'Dss-Parms'{}} </code></p>
- <p><code>rsa_private_key() = #'RSAPrivateKey'{} </code></p>
-
<p><code>dsa_private_key() = #'DSAPrivateKey'{}</code></p>
<p><code> public_crypt_options() = [{rsa_pad, rsa_padding()}]. </code></p>
@@ -120,7 +121,8 @@
<funcs>
<func>
- <name>decrypt_private(CipherText, Key [, Options]) -> binary()</name>
+ <name>decrypt_private(CipherText, Key) -> binary()</name>
+ <name>decrypt_private(CipherText, Key, Options) -> binary()</name>
<fsummary>Public key decryption.</fsummary>
<type>
<v>CipherText = binary()</v>
@@ -133,7 +135,8 @@
</func>
<func>
- <name>decrypt_public(CipherText, Key [, Options]) - > binary()</name>
+ <name>decrypt_public(CipherText, Key) - > binary()</name>
+ <name>decrypt_public(CipherText, Key, Options) - > binary()</name>
<fsummary></fsummary>
<type>
<v>CipherText = binary()</v>
@@ -149,7 +152,7 @@
<name>der_decode(Asn1type, Der) -> term()</name>
<fsummary> Decodes a public key asn1 der encoded entity.</fsummary>
<type>
- <v>Asn1Type = atom() -</v>
+ <v>Asn1Type = atom()</v>
<d> ASN.1 type present in the public_key applications
asn1 specifications.</d>
<v>Der = der_encoded()</v>
@@ -166,7 +169,8 @@
<v>Asn1Type = atom()</v>
<d> Asn1 type present in the public_key applications
ASN.1 specifications.</d>
- <v>Entity = term() - The erlang representation of <c> Asn1Type</c></v>
+ <v>Entity = term()</v>
+ <d>The erlang representation of <c>Asn1Type</c></d>
</type>
<desc>
<p> Encodes a public key entity with ASN.1 DER encoding.</p>
@@ -199,7 +203,8 @@
</func>
<func>
- <name>pem_entry_decode(PemEntry [, Password]) -> term()</name>
+ <name>pem_entry_decode(PemEntry) -> term()</name>
+ <name>pem_entry_decode(PemEntry, Password) -> term()</name>
<fsummary>Decodes a pem entry.</fsummary>
<type>
<v> PemEntry = pem_entry() </v>
@@ -214,17 +219,19 @@
</func>
<func>
- <name>pem_entry_encode(Asn1Type, Entity [,{CipherInfo, Password}]) -> pem_entry()</name>
+ <name>pem_entry_encode(Asn1Type, Entity) -> pem_entry()</name>
+ <name>pem_entry_encode(Asn1Type, Entity, {CipherInfo, Password}) -> pem_entry()</name>
<fsummary> Creates a pem entry that can be fed to pem_encode/1.</fsummary>
<type>
<v>Asn1Type = pki_asn1_type()</v>
- <v>Entity = term() - The Erlang representation of
+ <v>Entity = term()</v>
+ <d>The Erlang representation of
<c>Asn1Type</c>. If <c>Asn1Type</c> is 'SubjectPublicKeyInfo'
then <c>Entity</c> must be either an rsa_public_key() or a
dsa_public_key() and this function will create the appropriate
'SubjectPublicKeyInfo' entry.
- </v>
- <v>CipherInfo = {"DES-CBC" | "DES-EDE3-CBC", crypto:rand_bytes(8)}</v>
+ </d>
+ <v>CipherInfo = cipher_info()</v>
<v>Password = string()</v>
</type>
<desc>
@@ -281,7 +288,7 @@
<desc>
<p>Der encodes a pkix x509 certificate or part of such a
certificate. This function must be used for encoding certificates or parts of certificates
- that are decoded/created on the otp format, whereas for the plain format this
+ that are decoded/created in the otp format, whereas for the plain format this
function will directly call der_encode/2. </p>
</desc>
</func>
diff --git a/lib/public_key/include/public_key.hrl b/lib/public_key/include/public_key.hrl
index 5f97d80f7e..2475295974 100644
--- a/lib/public_key/include/public_key.hrl
+++ b/lib/public_key/include/public_key.hrl
@@ -23,6 +23,7 @@
-define(public_key, true).
-include("OTP-PUB-KEY.hrl").
+-include("PKCS-FRAME.hrl").
-record('SubjectPublicKeyInfoAlgorithm', {
algorithm,
diff --git a/lib/public_key/src/Makefile b/lib/public_key/src/Makefile
index 5a24b02d2a..062c495a65 100644
--- a/lib/public_key/src/Makefile
+++ b/lib/public_key/src/Makefile
@@ -42,10 +42,11 @@ MODULES = \
public_key \
pubkey_pem \
pubkey_ssh \
+ pubkey_pbe \
pubkey_cert \
- pubkey_cert_records
+ pubkey_cert_records
-HRL_FILES = $(INCLUDE)/public_key.hrl
+HRL_FILES = $(INCLUDE)/public_key.hrl
INTERNAL_HRL_FILES =
@@ -109,4 +110,3 @@ release_spec: opt
$(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) $(RELSYSDIR)/ebin
release_docs_spec:
-
diff --git a/lib/public_key/src/pubkey_pbe.erl b/lib/public_key/src/pubkey_pbe.erl
new file mode 100644
index 0000000000..43f6c42f10
--- /dev/null
+++ b/lib/public_key/src/pubkey_pbe.erl
@@ -0,0 +1,213 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%% Description: Implements Password Based Encryption PKCS-5, RFC-2898
+
+-module(pubkey_pbe).
+
+-include("public_key.hrl").
+
+-export([encode/4, decode/4, decrypt_parameters/1]).
+-export([pbdkdf1/4, pbdkdf2/6]).
+
+-define(DEFAULT_SHA_MAC_KEYLEN, 20).
+-define(ASN1_OCTET_STR_TAG, 4).
+-define(IV_LEN, 8).
+
+%%====================================================================
+%% Internal application API
+%%====================================================================
+
+%%--------------------------------------------------------------------
+-spec encode(binary(), string(), string(), term()) -> binary().
+%%
+%% Description: Performs password based encoding
+%%--------------------------------------------------------------------
+encode(Data, Password, "DES-CBC" = Cipher, KeyDevParams) ->
+ {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
+ crypto:des_cbc_encrypt(Key, IV, Data);
+
+encode(Data, Password, "DES-EDE3-CBC" = Cipher, KeyDevParams) ->
+ {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
+ <<Key1:8/binary, Key2:8/binary, Key3:8/binary>> = Key,
+ crypto:des_ede3_cbc_encrypt(Key1, Key2, Key3, IV, Data);
+
+encode(Data, Password, "RC2-CBC" = Cipher, KeyDevParams) ->
+ {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
+ crypto:rc2_cbc_encrypt(Key, IV, Data).
+%%--------------------------------------------------------------------
+-spec decode(binary(), string(), string(), term()) -> binary().
+%%
+%% Description: Performs password based decoding
+%%--------------------------------------------------------------------
+decode(Data, Password,"DES-CBC"= Cipher, KeyDevParams) ->
+ {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
+ crypto:des_cbc_decrypt(Key, IV, Data);
+
+decode(Data, Password,"DES-EDE3-CBC" = Cipher, KeyDevParams) ->
+ {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
+ <<Key1:8/binary, Key2:8/binary, Key3:8/binary>> = Key,
+ crypto:des_ede3_cbc_decrypt(Key1, Key2, Key3, IV, Data);
+
+decode(Data, Password,"RC2-CBC"= Cipher, KeyDevParams) ->
+ {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
+ crypto:rc2_cbc_decrypt(Key, IV, Data).
+
+%%--------------------------------------------------------------------
+-spec pbdkdf1(string(), iodata(), integer(), atom()) -> binary().
+%%
+%% Description: Implements password based decryption key derive function 1.
+%% Exported mainly for testing purposes.
+%%--------------------------------------------------------------------
+pbdkdf1(_, _, 0, Acc) ->
+ Acc;
+pbdkdf1(Password, Salt, Count, Hash) ->
+ Result = crypto:Hash([Password, Salt]),
+ do_pbdkdf1(Result, Count-1, Result, Hash).
+
+%%--------------------------------------------------------------------
+-spec pbdkdf2(string(), iodata(), integer(), integer(), fun(), integer())
+ -> binary().
+%%
+%% Description: Implements password based decryption key derive function 2.
+%% Exported mainly for testing purposes.
+%%--------------------------------------------------------------------
+pbdkdf2(Password, Salt, Count, DerivedKeyLen, Prf, PrfOutputLen)->
+ NumBlocks = ceiling(DerivedKeyLen / PrfOutputLen),
+ NumLastBlockOctets = DerivedKeyLen - (NumBlocks - 1) * PrfOutputLen ,
+ blocks(NumBlocks, NumLastBlockOctets, 1, Password, Salt,
+ Count, Prf, PrfOutputLen, <<>>).
+%%--------------------------------------------------------------------
+-spec decrypt_parameters(#'EncryptedPrivateKeyInfo_encryptionAlgorithm'{}) ->
+ {Cipher::string(), #'PBES2-params'{}}.
+%%
+%% Description: Performs ANS1-decoding of encryption parameters.
+%%--------------------------------------------------------------------
+decrypt_parameters(#'EncryptedPrivateKeyInfo_encryptionAlgorithm'{
+ algorithm = Oid, parameters = Param}) ->
+ decrypt_parameters(Oid, Param).
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+password_to_key_and_iv(Password, _, #'PBES2-params'{} = Params) ->
+ {Salt, ItrCount, KeyLen, PseudoRandomFunction, PseudoOtputLen, IV} =
+ key_derivation_params(Params),
+ <<Key:KeyLen/binary, _/binary>> =
+ pbdkdf2(Password, Salt, ItrCount, KeyLen, PseudoRandomFunction, PseudoOtputLen),
+ {Key, IV};
+password_to_key_and_iv(Password, Cipher, Salt) ->
+ KeyLen = derived_key_length(Cipher, undefined),
+ <<Key:KeyLen/binary, _/binary>> =
+ pem_encrypt(<<>>, Password, Salt, ceiling(KeyLen div 16), <<>>, md5),
+ %% Old PEM encryption does not use standard encryption method
+ %% pbdkdf1 and uses then salt as IV
+ {Key, Salt}.
+
+pem_encrypt(_, _, _, 0, Acc, _) ->
+ Acc;
+pem_encrypt(Prev, Password, Salt, Count, Acc, Hash) ->
+ Result = crypto:Hash([Prev, Password, Salt]),
+ pem_encrypt(Result, Password, Salt, Count-1 , <<Acc/binary, Result/binary>>, Hash).
+
+do_pbdkdf1(_, 0, Acc, _) ->
+ Acc;
+do_pbdkdf1(Prev, Count, Acc, Hash) ->
+ Result = crypto:Hash(Prev),
+ do_pbdkdf1(Result, Count-1 , <<Result/binary, Acc/binary>>, Hash).
+
+iv(#'PBES2-params_encryptionScheme'{algorithm = Algo,
+ parameters = ASNIV}) when (Algo == ?'desCBC') or
+ (Algo == ?'des-EDE3-CBC') ->
+ %% This is an so called open ASN1-type that in this
+ %% case will be an octet-string of length 8
+ <<?ASN1_OCTET_STR_TAG, ?IV_LEN, IV:?IV_LEN/binary>> = ASNIV,
+ IV;
+iv(#'PBES2-params_encryptionScheme'{algorithm = ?'rc2CBC',
+ parameters = ASN1IV}) ->
+ {ok, #'RC2-CBC-Parameter'{iv = IV}} = 'PKCS-FRAME':decode('RC2-CBC-Parameter', ASN1IV),
+ iolist_to_binary(IV).
+
+blocks(1, N, Index, Password, Salt, Count, Prf, PrfLen, Acc) ->
+ <<XorSum:N/binary, _/binary>> = xor_sum(Password, Salt, Count, Index, Prf, PrfLen),
+ <<Acc/binary, XorSum/binary>>;
+blocks(NumBlocks, N, Index, Password, Salt, Count, Prf, PrfLen, Acc) ->
+ XorSum = xor_sum(Password, Salt, Count, Index, Prf, PrfLen),
+ blocks(NumBlocks -1, N, Index +1, Password, Salt, Count, Prf,
+ PrfLen, <<Acc/binary, XorSum/binary>>).
+
+xor_sum(Password, Salt, Count, Index, Prf, PrfLen) ->
+ Result = Prf(Password, [Salt,<<Index:32/unsigned-big-integer>>], PrfLen),
+ do_xor_sum(Prf, PrfLen, Result, Password, Count-1, Result).
+
+do_xor_sum(_, _, _, _, 0, Acc) ->
+ Acc;
+do_xor_sum(Prf, PrfLen, Prev, Password, Count, Acc)->
+ Result = Prf(Password, Prev, PrfLen),
+ do_xor_sum(Prf, PrfLen, Result, Password, Count-1, crypto:exor(Acc, Result)).
+
+decrypt_parameters(?'id-PBES2', DekParams) ->
+ {ok, Params} = 'PKCS-FRAME':decode('PBES2-params', DekParams),
+ {cipher(Params#'PBES2-params'.encryptionScheme), Params}.
+
+key_derivation_params(#'PBES2-params'{keyDerivationFunc = KeyDerivationFunc,
+ encryptionScheme = EncScheme}) ->
+ #'PBES2-params_keyDerivationFunc'{algorithm = ?'id-PBKDF2',
+ parameters =
+ #'PBKDF2-params'{salt = {specified, OctetSalt},
+ iterationCount = Count,
+ keyLength = Length,
+ prf = Prf}} = KeyDerivationFunc,
+ #'PBES2-params_encryptionScheme'{algorithm = Algo} = EncScheme,
+ {PseudoRandomFunction, PseudoOtputLen} = pseudo_random_function(Prf),
+ KeyLen = derived_key_length(Algo, Length),
+ {OctetSalt, Count, KeyLen,
+ PseudoRandomFunction, PseudoOtputLen, iv(EncScheme)}.
+
+%% This function currently matches a tuple that ougth to be the value
+%% ?'id-hmacWithSHA1, but we need some kind of ASN1-fix for this.
+pseudo_random_function(#'PBKDF2-params_prf'{algorithm =
+ {_,_, _,'id-hmacWithSHA1'}}) ->
+ {fun crypto:sha_mac/3, pseudo_output_length(?'id-hmacWithSHA1')};
+pseudo_random_function(#'PBKDF2-params_prf'{algorithm = ?'id-hmacWithSHA1'}) ->
+ {fun crypto:sha_mac/3, pseudo_output_length(?'id-hmacWithSHA1')}.
+
+pseudo_output_length(?'id-hmacWithSHA1') ->
+ ?DEFAULT_SHA_MAC_KEYLEN.
+
+derived_key_length(_, Len) when is_integer(Len) ->
+ Len;
+derived_key_length(Cipher,_) when (Cipher == ?'desCBC') or
+ (Cipher == "DES-CBC") ->
+ 8;
+derived_key_length(Cipher,_) when (Cipher == ?'rc2CBC') or
+ (Cipher == "RC2-CBC") ->
+ 16;
+derived_key_length(Cipher,_) when (Cipher == ?'des-EDE3-CBC') or
+ (Cipher == "DES-EDE3-CBC") ->
+ 24.
+
+cipher(#'PBES2-params_encryptionScheme'{algorithm = ?'desCBC'}) ->
+ "DES-CBC";
+cipher(#'PBES2-params_encryptionScheme'{algorithm = ?'des-EDE3-CBC'}) ->
+ "DES-EDE3-CBC";
+cipher(#'PBES2-params_encryptionScheme'{algorithm = ?'rc2CBC'}) ->
+ "RC2-CBC".
+
+ceiling(Float) ->
+ erlang:round(Float + 0.5).
diff --git a/lib/public_key/src/pubkey_pem.erl b/lib/public_key/src/pubkey_pem.erl
index c26815bc04..910473d629 100644
--- a/lib/public_key/src/pubkey_pem.erl
+++ b/lib/public_key/src/pubkey_pem.erl
@@ -43,8 +43,6 @@
-include("public_key.hrl").
-export([encode/1, decode/1, decipher/2, cipher/3]).
-%% Backwards compatibility
--export([decode_key/2]).
-define(ENCODED_LINE_LENGTH, 64).
@@ -69,23 +67,23 @@ encode(PemEntries) ->
encode_pem_entries(PemEntries).
%%--------------------------------------------------------------------
--spec decipher({pki_asn1_type(), DerEncrypted::binary(),{Cipher :: string(),
- Salt :: binary()}},
+-spec decipher({pki_asn1_type(), DerEncrypted::binary(),
+ {Cipher :: string(), Salt :: iodata() | #'PBES2-params'{}}},
string()) -> Der::binary().
%%
%% Description: Deciphers a decrypted pem entry.
%%--------------------------------------------------------------------
-decipher({_, DecryptDer, {Cipher,Salt}}, Password) ->
- decode_key(DecryptDer, Password, Cipher, Salt).
+decipher({_, DecryptDer, {Cipher, KeyDevParams}}, Password) ->
+ pubkey_pbe:decode(DecryptDer, Password, Cipher, KeyDevParams).
%%--------------------------------------------------------------------
--spec cipher(Der::binary(),{Cipher :: string(), Salt :: binary()} ,
+-spec cipher(Der::binary(), {Cipher :: string(), Salt :: iodata() | #'PBES2-params'{}} ,
string()) -> binary().
%%
%% Description: Ciphers a PEM entry
%%--------------------------------------------------------------------
-cipher(Der, {Cipher,Salt}, Password)->
- encode_key(Der, Password, Cipher, Salt).
+cipher(Der, {Cipher, KeyDevParams}, Password)->
+ pubkey_pbe:encode(Der, Password, Cipher, KeyDevParams).
%%--------------------------------------------------------------------
%%% Internal functions
@@ -127,8 +125,20 @@ decode_pem_entry(Start, Lines) ->
Type = asn1_type(Start),
Cs = erlang:iolist_to_binary(Lines),
Decoded = base64:mime_decode(Cs),
- {Type, Decoded, not_encrypted}.
-
+ case Type of
+ 'EncryptedPrivateKeyInfo'->
+ decode_encrypted_private_keyinfo(Decoded);
+ _ ->
+ {Type, Decoded, not_encrypted}
+ end.
+
+decode_encrypted_private_keyinfo(Der) ->
+ #'EncryptedPrivateKeyInfo'{encryptionAlgorithm = AlgorithmInfo,
+ encryptedData = Data} =
+ public_key:der_decode('EncryptedPrivateKeyInfo', Der),
+ DecryptParams = pubkey_pbe:decrypt_parameters(AlgorithmInfo),
+ {'PrivateKeyInfo', iolist_to_binary(Data), DecryptParams}.
+
split_bin(Bin) ->
split_bin(0, Bin).
@@ -160,37 +170,6 @@ join_entry([<<"-----END ", _/binary>>| Lines], Entry) ->
join_entry([Line | Lines], Entry) ->
join_entry(Lines, [Line | Entry]).
-decode_key(Data, Password, "DES-CBC", Salt) ->
- Key = password_to_key(Password, Salt, 8),
- IV = Salt,
- crypto:des_cbc_decrypt(Key, IV, Data);
-decode_key(Data, Password, "DES-EDE3-CBC", Salt) ->
- Key = password_to_key(Password, Salt, 24),
- IV = Salt,
- <<Key1:8/binary, Key2:8/binary, Key3:8/binary>> = Key,
- crypto:des_ede3_cbc_decrypt(Key1, Key2, Key3, IV, Data).
-
-encode_key(Data, Password, "DES-CBC", Salt) ->
- Key = password_to_key(Password, Salt, 8),
- IV = Salt,
- crypto:des_cbc_encrypt(Key, IV, Data);
-encode_key(Data, Password, "DES-EDE3-CBC", Salt) ->
- Key = password_to_key(Password, Salt, 24),
- IV = Salt,
- <<Key1:8/binary, Key2:8/binary, Key3:8/binary>> = Key,
- crypto:des_ede3_cbc_encrypt(Key1, Key2, Key3, IV, Data).
-
-password_to_key(Data, Salt, KeyLen) ->
- <<Key:KeyLen/binary, _/binary>> =
- password_to_key(<<>>, Data, Salt, KeyLen, <<>>),
- Key.
-
-password_to_key(_, _, _, Len, Acc) when Len =< 0 ->
- Acc;
-password_to_key(Prev, Data, Salt, Len, Acc) ->
- M = crypto:md5([Prev, Data, Salt]),
- password_to_key(M, Data, Salt, Len - size(M), <<Acc/binary, M/binary>>).
-
unhex(S) ->
unhex(S, []).
@@ -228,6 +207,10 @@ pem_end(<<"-----BEGIN DSA PRIVATE KEY-----">>) ->
<<"-----END DSA PRIVATE KEY-----">>;
pem_end(<<"-----BEGIN DH PARAMETERS-----">>) ->
<<"-----END DH PARAMETERS-----">>;
+pem_end(<<"-----BEGIN PRIVATE KEY-----">>) ->
+ <<"-----END PRIVATE KEY-----">>;
+pem_end(<<"-----BEGIN ENCRYPTED PRIVATE KEY-----">>) ->
+ <<"-----END ENCRYPTED PRIVATE KEY-----">>;
pem_end(_) ->
undefined.
@@ -242,18 +225,14 @@ asn1_type(<<"-----BEGIN PUBLIC KEY-----">>) ->
asn1_type(<<"-----BEGIN DSA PRIVATE KEY-----">>) ->
'DSAPrivateKey';
asn1_type(<<"-----BEGIN DH PARAMETERS-----">>) ->
- 'DHParameter'.
+ 'DHParameter';
+asn1_type(<<"-----BEGIN PRIVATE KEY-----">>) ->
+ 'PrivateKeyInfo';
+asn1_type(<<"-----BEGIN ENCRYPTED PRIVATE KEY-----">>) ->
+ 'EncryptedPrivateKeyInfo'.
pem_decrypt() ->
<<"Proc-Type: 4,ENCRYPTED">>.
pem_decrypt_info(Cipher, Salt) ->
io_lib:format("DEK-Info: ~s,~s", [Cipher, lists:flatten(hexify(Salt))]).
-
-%%--------------------------------------------------------------------
-%%% Deprecated
-%%--------------------------------------------------------------------
-decode_key({_Type, Bin, not_encrypted}, _) ->
- Bin;
-decode_key({_Type, Bin, {Chipher,Salt}}, Password) ->
- decode_key(Bin, Password, Chipher, Salt).
diff --git a/lib/public_key/src/public_key.app.src b/lib/public_key/src/public_key.app.src
index 1963bd05d4..4cc81ea573 100644
--- a/lib/public_key/src/public_key.app.src
+++ b/lib/public_key/src/public_key.app.src
@@ -3,10 +3,12 @@
{vsn, "%VSN%"},
{modules, [ public_key,
pubkey_pem,
+ pubkey_pbe,
pubkey_ssh,
pubkey_cert,
pubkey_cert_records,
- 'OTP-PUB-KEY'
+ 'OTP-PUB-KEY',
+ 'PKCS-FRAME'
]},
{applications, [crypto, kernel, stdlib]},
{registered, []},
diff --git a/lib/public_key/src/public_key.appup.src b/lib/public_key/src/public_key.appup.src
index 4986801dad..2945fb1213 100644
--- a/lib/public_key/src/public_key.appup.src
+++ b/lib/public_key/src/public_key.appup.src
@@ -1,70 +1,16 @@
%% -*- erlang -*-
{"%VSN%",
[
- {"0.11",
- [
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {add_module, pubkey_ssh, soft, soft_purge, soft_purge},
- {update, pubkey_cert, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []}
- ]
- },
-
- {"0.10",
- [
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []}
- ]
- },
- {"0.9",
- [
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert, soft, soft_purge, soft_purge, []}
- ]
- },
- {"0.8",
- [
- {update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []},
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert, soft, soft_purge, soft_purge, []}
- ]
- }
+ {"0.13", [{restart_application, public_key}]},
+ {"0.11", [{restart_application, public_key}]},
+ {"0.10", [{restart_application, public_key}]},
+ {"0.9", [{restart_application, public_key}]},
+ {"0.8", [{restart_application, public_key}]}
],
[
- {"0.11",
- [
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {delete_module, pubkey_ssh, soft, soft_purge, soft_purge},
- {update, pubkey_cert, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []}
- ]
- },
-
- {"0.10",
- [
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []}
- ]
- },
- {"0.9",
- [
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert, soft, soft_purge, soft_purge, []}
- ]
- },
- {"0.8",
- [
- {update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []},
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert, soft, soft_purge, soft_purge, []}
- ]
- }
+ {"0.13", [{restart_application, public_key}]},
+ {"0.11", [{restart_application, public_key}]},
+ {"0.10", [{restart_application, public_key}]},
+ {"0.9", [{restart_application, public_key}]},
+ {"0.8", [{restart_application, public_key}]}
]}.
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index 2901020e83..753322b46d 100644
--- a/lib/public_key/src/public_key.erl
+++ b/lib/public_key/src/public_key.erl
@@ -45,13 +45,6 @@
ssh_decode/2, ssh_encode/2
]).
-%% Deprecated
--export([decode_private_key/1, decode_private_key/2, pem_to_der/1]).
-
--deprecated({pem_to_der, 1, next_major_release}).
--deprecated({decode_private_key, 1, next_major_release}).
--deprecated({decode_private_key, 2, next_major_release}).
-
-type rsa_padding() :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding'
| 'rsa_no_padding'.
-type public_crypt_options() :: [{rsa_pad, rsa_padding()}].
@@ -104,22 +97,23 @@ pem_entry_decode({Asn1Type, Der, not_encrypted}) when is_atom(Asn1Type),
pem_entry_decode({Asn1Type, Der, not_encrypted}, _) when is_atom(Asn1Type),
is_binary(Der) ->
der_decode(Asn1Type, Der);
+pem_entry_decode({Asn1Type, CryptDer, {Cipher, #'PBES2-params'{}}} = PemEntry,
+ Password) when is_atom(Asn1Type) andalso
+ is_binary(CryptDer) andalso
+ is_list(Cipher) ->
+ do_pem_entry_decode(PemEntry, Password);
pem_entry_decode({Asn1Type, CryptDer, {Cipher, Salt}} = PemEntry,
- Password) when is_atom(Asn1Type),
- is_binary(CryptDer),
- is_list(Cipher),
- is_binary(Salt),
- erlang:byte_size(Salt) == 8
- ->
- Der = pubkey_pem:decipher(PemEntry, Password),
- der_decode(Asn1Type, Der).
+ Password) when is_atom(Asn1Type) andalso
+ is_binary(CryptDer) andalso
+ is_list(Cipher) andalso
+ is_binary(Salt) andalso
+ erlang:byte_size(Salt) == 8 ->
+ do_pem_entry_decode(PemEntry, Password).
%%--------------------------------------------------------------------
-spec pem_entry_encode(pki_asn1_type(), term()) -> pem_entry().
--spec pem_entry_encode(pki_asn1_type(), term(),
- {{Cipher :: string(), Salt :: binary()}, string()}) ->
- pem_entry().
-%
+-spec pem_entry_encode(pki_asn1_type(), term(), term()) -> pem_entry().
+%%
%% Description: Creates a pem entry that can be feed to pem_encode/1.
%%--------------------------------------------------------------------
pem_entry_encode('SubjectPublicKeyInfo', Entity=#'RSAPublicKey'{}) ->
@@ -137,21 +131,36 @@ pem_entry_encode('SubjectPublicKeyInfo',
pem_entry_encode(Asn1Type, Entity) when is_atom(Asn1Type) ->
Der = der_encode(Asn1Type, Entity),
{Asn1Type, Der, not_encrypted}.
-pem_entry_encode(Asn1Type, Entity,
- {{Cipher, Salt}= CipherInfo, Password}) when is_atom(Asn1Type),
- is_list(Cipher),
- is_binary(Salt),
- erlang:byte_size(Salt) == 8,
- is_list(Password)->
- Der = der_encode(Asn1Type, Entity),
- DecryptDer = pubkey_pem:cipher(Der, CipherInfo, Password),
- {Asn1Type, DecryptDer, CipherInfo}.
-
+pem_entry_encode(Asn1Type, Entity, {{Cipher, #'PBES2-params'{}} = CipherInfo,
+ Password}) when is_atom(Asn1Type) andalso
+ is_list(Password) andalso
+ is_list(Cipher) ->
+ do_pem_entry_encode(Asn1Type, Entity, CipherInfo, Password);
+
+pem_entry_encode(Asn1Type, Entity, {{Cipher, Salt} = CipherInfo,
+ Password}) when is_atom(Asn1Type) andalso
+ is_list(Password) andalso
+ is_list(Cipher) andalso
+ is_binary(Salt) andalso
+ erlang:byte_size(Salt) == 8 ->
+ do_pem_entry_encode(Asn1Type, Entity, CipherInfo, Password).
+
%%--------------------------------------------------------------------
-spec der_decode(asn1_type(), Der::binary()) -> term().
%%
%% Description: Decodes a public key asn1 der encoded entity.
%%--------------------------------------------------------------------
+der_decode(Asn1Type, Der) when (Asn1Type == 'PrivateKeyInfo') or
+ (Asn1Type == 'EncryptedPrivateKeyInfo')
+ andalso is_binary(Der) ->
+ try
+ {ok, Decoded} = 'PKCS-FRAME':decode(Asn1Type, Der),
+ Decoded
+ catch
+ error:{badmatch, {error, _}} = Error ->
+ erlang:error(Error)
+ end;
+
der_decode(Asn1Type, Der) when is_atom(Asn1Type), is_binary(Der) ->
try
{ok, Decoded} = 'OTP-PUB-KEY':decode(Asn1Type, Der),
@@ -166,6 +175,16 @@ der_decode(Asn1Type, Der) when is_atom(Asn1Type), is_binary(Der) ->
%%
%% Description: Encodes a public key entity with asn1 DER encoding.
%%--------------------------------------------------------------------
+der_encode(Asn1Type, Entity) when (Asn1Type == 'PrivateKeyInfo') or
+ (Asn1Type == 'EncryptedPrivateKeyInfo') ->
+ try
+ {ok, Encoded} = 'PKCS-FRAME':encode(Asn1Type, Entity),
+ iolist_to_binary(Encoded)
+ catch
+ error:{badmatch, {error, _}} = Error ->
+ erlang:error(Error)
+ end;
+
der_encode(Asn1Type, Entity) when is_atom(Asn1Type) ->
try
{ok, Encoded} = 'OTP-PUB-KEY':encode(Asn1Type, Entity),
@@ -488,9 +507,10 @@ pkix_path_validation(PathErr, [Cert | Chain], Options0) when is_atom(PathErr)->
_:_ ->
{error, Reason}
end;
-pkix_path_validation(TrustedCert, CertChain, Options) when
- is_binary(TrustedCert) -> OtpCert = pkix_decode_cert(TrustedCert,
- otp), pkix_path_validation(OtpCert, CertChain, Options);
+pkix_path_validation(TrustedCert, CertChain, Options)
+ when is_binary(TrustedCert) ->
+ OtpCert = pkix_decode_cert(TrustedCert, otp),
+ pkix_path_validation(OtpCert, CertChain, Options);
pkix_path_validation(#'OTPCertificate'{} = TrustedCert, CertChain, Options)
when is_list(CertChain), is_list(Options) ->
@@ -534,6 +554,14 @@ ssh_encode(Entries, Type) when is_list(Entries),
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
+do_pem_entry_encode(Asn1Type, Entity, CipherInfo, Password) ->
+ Der = der_encode(Asn1Type, Entity),
+ DecryptDer = pubkey_pem:cipher(Der, CipherInfo, Password),
+ {Asn1Type, DecryptDer, CipherInfo}.
+
+do_pem_entry_decode({Asn1Type,_, _} = PemEntry, Password) ->
+ Der = pubkey_pem:decipher(PemEntry, Password),
+ der_decode(Asn1Type, Der).
encrypt_public(PlainText, N, E, Options)->
Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
@@ -631,20 +659,3 @@ validate(DerCert, #path_validation_state{working_issuer_name = Issuer,
sized_binary(Binary) ->
Size = size(Binary),
<<?UINT32(Size), Binary/binary>>.
-
-%%--------------------------------------------------------------------
-%%% Deprecated functions
-%%--------------------------------------------------------------------
-pem_to_der(CertSource) ->
- {ok, Bin} = file:read_file(CertSource),
- {ok, pubkey_pem:decode(Bin)}.
-
-decode_private_key(KeyInfo) ->
- decode_private_key(KeyInfo, no_passwd).
-
-decode_private_key(KeyInfo = {'RSAPrivateKey', _, _}, Password) ->
- DerEncoded = pubkey_pem:decode_key(KeyInfo, Password),
- 'OTP-PUB-KEY':decode('RSAPrivateKey', DerEncoded);
-decode_private_key(KeyInfo = {'DSAPrivateKey', _, _}, Password) ->
- DerEncoded = pubkey_pem:decode_key(KeyInfo, Password),
- 'OTP-PUB-KEY':decode('DSAPrivateKey', DerEncoded).
diff --git a/lib/public_key/test/Makefile b/lib/public_key/test/Makefile
index 6889ae9a8a..b7f91981a5 100644
--- a/lib/public_key/test/Makefile
+++ b/lib/public_key/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2010. All Rights Reserved.
+# Copyright Ericsson AB 2008-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -30,6 +30,7 @@ INCLUDES= -I. -I ../include
MODULES= \
erl_make_certs \
public_key_SUITE \
+ pbe_SUITE \
pkits_SUITE
ERL_FILES= $(MODULES:%=%.erl)
diff --git a/lib/public_key/test/pbe_SUITE.erl b/lib/public_key/test/pbe_SUITE.erl
new file mode 100644
index 0000000000..380a67db7b
--- /dev/null
+++ b/lib/public_key/test/pbe_SUITE.erl
@@ -0,0 +1,259 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(pbe_SUITE).
+
+-include_lib("test_server/include/test_server.hrl").
+-include_lib("public_key/include/public_key.hrl").
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+%% Test server callback functions
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config) -> Config
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Description: Initialization before the whole suite
+%%
+%% Note: This function is free to add any key/value pairs to the Config
+%% variable, but should NOT alter/remove any existing entries.
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ try crypto:start() of
+ ok ->
+ Config
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config) -> _
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Description: Cleanup after the whole suite
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ application:stop(crypto).
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config) -> Config
+%% Case - atom()
+%% Name of the test case that is about to be run.
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%%
+%% Description: Initialization before each test case
+%%
+%% Note: This function is free to add any key/value pairs to the Config
+%% variable, but should NOT alter/remove any existing entries.
+%% Description: Initialization before each test case
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config) -> _
+%% Case - atom()
+%% Name of the test case that is about to be run.
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Description: Cleanup after each test case
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: all(Clause) -> TestCases
+%% Clause - atom() - suite | doc
+%% TestCases - [Case]
+%% Case - atom()
+%% Name of a test case.
+%% Description: Returns a list of all test cases in this test suite
+%%--------------------------------------------------------------------
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [
+ pbdkdf1,
+ pbdkdf2,
+ encrypted_private_key_info].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+%% Test cases starts here.
+%%--------------------------------------------------------------------
+pbdkdf1(doc) ->
+ ["Test with PKCS #5 PBKDF1 Test Vectors"];
+pbdkdf1(Config) when is_list(Config) ->
+ %%Password = "password"
+ %% = (0x)70617373776F7264
+ %%Salt = (0x)78578E5A5D63CB06
+ %%Count = 1000
+ %%kLen = 16
+ %%Key = PBKDF1(Password, Salt, Count, kLen)
+ %%= (0x)DC19847E05C64D2FAF10EBFB4A3D2A20
+
+ Password = "password",
+ Salt = <<16#78,16#57,16#8E,16#5A,16#5D,16#63,16#CB,16#06>>,
+ Count = 1000,
+
+ <<16#DC, 16#19, 16#84, 16#7E,
+ 16#05, 16#C6, 16#4D, 16#2F,
+ 16#AF, 16#10, 16#EB, 16#FB,
+ 16#4A, 16#3D, 16#2A, 16#20, _/binary>> =
+ pubkey_pbe:pbdkdf1(Password, Salt, Count, sha).
+
+pbdkdf2(doc) ->
+ ["Test with PKCS #5 PBKDF2 Test Vectors"];
+pbdkdf2(Config) when is_list(Config) ->
+ %% Input:
+ %% P = "password" (8 octets)
+ %% S = "salt" (4 octets)
+ %% c = 1
+ %% dkLen = 20
+
+ %% Output:
+ %% DK = 0c 60 c8 0f 96 1f 0e 71
+ %% f3 a9 b5 24 af 60 12 06
+ %% 2f e0 37 a6 (20 octets)
+
+ <<16#0c, 16#60, 16#c8, 16#0f, 16#96, 16#1f, 16#0e, 16#71,
+ 16#f3, 16#a9, 16#b5, 16#24, 16#af, 16#60, 16#12, 16#06,
+ 16#2f, 16#e0, 16#37, 16#a6>> = pubkey_pbe:pbdkdf2("password", "salt", 1, 20, fun crypto:sha_mac/3, 20),
+
+ %% Input:
+ %% P = "password" (8 octets)
+ %% S = "salt" (4 octets)
+ %% c = 2
+ %% dkLen = 20
+
+ %% Output:
+ %% DK = ea 6c 01 4d c7 2d 6f 8c
+ %% cd 1e d9 2a ce 1d 41 f0
+ %% d8 de 89 57 (20 octets)
+
+ <<16#ea, 16#6c, 16#01, 16#4d, 16#c7, 16#2d, 16#6f, 16#8c,
+ 16#cd, 16#1e, 16#d9, 16#2a, 16#ce, 16#1d, 16#41, 16#f0,
+ 16#d8, 16#de, 16#89, 16#57>> =
+ pubkey_pbe:pbdkdf2("password", "salt", 2, 20, fun crypto:sha_mac/3, 20),
+
+ %% Input:
+ %% P = "password" (8 octets)
+ %% S = "salt" (4 octets)
+ %% c = 4096
+ %% dkLen = 20
+
+ %% Output:
+ %% DK = 4b 00 79 01 b7 65 48 9a
+ %% be ad 49 d9 26 f7 21 d0
+ %% 65 a4 29 c1 (20 octets)
+
+ <<16#4b, 16#00, 16#79, 16#01, 16#b7, 16#65, 16#48, 16#9a,
+ 16#be, 16#ad, 16#49, 16#d9, 16#26, 16#f7, 16#21, 16#d0,
+ 16#65, 16#a4, 16#29, 16#c1>> = pubkey_pbe:pbdkdf2("password", "salt", 4096, 20, fun crypto:sha_mac/3, 20),
+
+ %% Input:
+ %% P = "password" (8 octets)
+ %% S = "salt" (4 octets)
+ %% c = 16777216
+ %% dkLen = 20
+
+ %% Output:
+ %% DK = ee fe 3d 61 cd 4d a4 e4
+ %% e9 94 5b 3d 6b a2 15 8c
+ %% 26 34 e9 84 (20 octets)
+
+
+ <<16#ee, 16#fe, 16#3d, 16#61, 16#cd, 16#4d, 16#a4, 16#e4,
+ 16#e9, 16#94, 16#5b, 16#3d, 16#6b, 16#a2, 16#15, 16#8c,
+ 16#26, 16#34, 16#e9, 16#84>> = pubkey_pbe:pbdkdf2("password", "salt", 16777216, 20, fun crypto:sha_mac/3, 20),
+
+ %% Input:
+ %% P = "passwordPASSWORDpassword" (24 octets)
+ %% S = "saltSALTsaltSALTsaltSALTsaltSALTsalt" (36 octets)
+ %% c = 4096
+ %% dkLen = 25
+
+ %% Output:
+ %% DK = 3d 2e ec 4f e4 1c 84 9b
+ %% 80 c8 d8 36 62 c0 e4 4a
+ %% 8b 29 1a 96 4c f2 f0 70
+ %% 38 (25 octets)
+
+ <<16#3d, 16#2e, 16#ec, 16#4f, 16#e4, 16#1c, 16#84, 16#9b,
+ 16#80, 16#c8, 16#d8, 16#36, 16#62, 16#c0, 16#e4, 16#4a,
+ 16#8b, 16#29, 16#1a, 16#96, 16#4c, 16#f2, 16#f0, 16#70,
+ 16#38>>
+ = pubkey_pbe:pbdkdf2("passwordPASSWORDpassword",
+ "saltSALTsaltSALTsaltSALTsaltSALTsalt", 4096, 25, fun crypto:sha_mac/3, 20),
+
+ %% Input:
+ %% P = "pass\0word" (9 octets)
+ %% S = "sa\0lt" (5 octets)
+ %% c = 4096
+ %% dkLen = 16
+
+ %% Output:
+ %% DK = 56 fa 6a a7 55 48 09 9d
+ %% cc 37 d7 f0 34 25 e0 c3 (16 octets)
+
+ <<16#56, 16#fa, 16#6a, 16#a7, 16#55, 16#48, 16#09, 16#9d,
+ 16#cc, 16#37, 16#d7, 16#f0, 16#34, 16#25, 16#e0, 16#c3>>
+ = pubkey_pbe:pbdkdf2("pass\0word",
+ "sa\0lt", 4096, 16, fun crypto:sha_mac/3, 20).
+
+encrypted_private_key_info(doc) ->
+ ["Tests reading a EncryptedPrivateKeyInfo file encrypted with different ciphers"];
+encrypted_private_key_info(Config) when is_list(Config) ->
+ Datadir = ?config(data_dir, Config),
+ {ok, PemDes} = file:read_file(filename:join(Datadir, "des_cbc_enc_key.pem")),
+
+ PemDesEntry = public_key:pem_decode(PemDes),
+ test_server:format("Pem entry: ~p" , [PemDesEntry]),
+ [{'PrivateKeyInfo', _, {"DES-CBC",_}} = PubEntry0] = PemDesEntry,
+ KeyInfo = public_key:pem_entry_decode(PubEntry0, "password"),
+
+ {ok, Pem3Des} = file:read_file(filename:join(Datadir, "des_ede3_cbc_enc_key.pem")),
+
+ Pem3DesEntry = public_key:pem_decode(Pem3Des),
+ test_server:format("Pem entry: ~p" , [Pem3DesEntry]),
+ [{'PrivateKeyInfo', _, {"DES-EDE3-CBC",_}} = PubEntry1] = Pem3DesEntry,
+ KeyInfo = public_key:pem_entry_decode(PubEntry1, "password"),
+
+ {ok, PemRc2} = file:read_file(filename:join(Datadir, "rc2_cbc_enc_key.pem")),
+
+ PemRc2Entry = public_key:pem_decode(PemRc2),
+ test_server:format("Pem entry: ~p" , [PemRc2Entry]),
+ [{'PrivateKeyInfo', _, {"RC2-CBC",_}} = PubEntry2] = PemRc2Entry,
+ KeyInfo = public_key:pem_entry_decode(PubEntry2, "password"),
+
+ check_key_info(KeyInfo).
+
+
+check_key_info(#'PrivateKeyInfo'{privateKeyAlgorithm =
+ #'PrivateKeyInfo_privateKeyAlgorithm'{algorithm = ?rsaEncryption},
+ privateKey = Key}) ->
+ #'RSAPrivateKey'{} = public_key:der_decode('RSAPrivateKey', iolist_to_binary(Key)).
diff --git a/lib/public_key/test/pbe_SUITE_data/des_cbc_enc_key.pem b/lib/public_key/test/pbe_SUITE_data/des_cbc_enc_key.pem
new file mode 100644
index 0000000000..eaa06145aa
--- /dev/null
+++ b/lib/public_key/test/pbe_SUITE_data/des_cbc_enc_key.pem
@@ -0,0 +1,11 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBozA9BgkqhkiG9w0BBQ0wMDAbBgkqhkiG9w0BBQwwDgQIfWBDXwLp4K4CAggA
+MBEGBSsOAwIHBAiaCF/AvOgQ6QSCAWDWX4BdAzCRNSQSANSuNsT5X8mWYO27mr3Y
+9c9LoBVXGNmYWKA77MI4967f7SmjNcgXj3xNE/jmnVz6hhsjS8E5VPT3kfyVkpdZ
+0lr5e9Yk2m3JWpPU7++v5zBkZmC4V/MwV/XuIs6U+vykgzMgpxQg0oZKS9zgmiZo
+f/4dOCL0UtCDnyOSvqT7mCVIcMDIEKu8QbVlgZYBop08l60EuEU3gARUo8WsYQmO
+Dz/ldx0Z+znIT0SXVuOwc+RVItC5T/Qx+aijmmpt+9l14nmaGBrEkmuhmtdvU/4v
+aptewGRgmjOfD6cqK+zs0O5NrrJ3P/6ZSxXj91CQgrThGfOv72bUncXEMNtc8pks
+2jpHFjGMdKufnadAD7XuMgzkkaklEXZ4f5tU6heIIwr51g0GBEGF96gYPFnjnSQM
+75JE02Clo+DfcfXpcybPTwwFg2jd6JTTOfkdf6OdSlA/1XNK43FA
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/lib/public_key/test/pbe_SUITE_data/des_ede3_cbc_enc_key.pem b/lib/public_key/test/pbe_SUITE_data/des_ede3_cbc_enc_key.pem
new file mode 100644
index 0000000000..22ea46d56f
--- /dev/null
+++ b/lib/public_key/test/pbe_SUITE_data/des_ede3_cbc_enc_key.pem
@@ -0,0 +1,11 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBpjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIeFeOWl1jywYCAggA
+MBQGCCqGSIb3DQMHBAjUJ5eGBhQGtQSCAWBrHrRgqO8UUMLcWzZEtpk1l3mjxiF/
+koCMkHsFwowgyWhEbgIkTgbSViK54LVK8PskekcGNLph+rB6bGZ7pPbL5pbXASJ8
++MkQcG3FZdlS4Ek9tTJDApj3O1UubZGFG4uvTlJJFbF1BOJ3MkY3XQ9Gl1qwv7j5
+6e103Da7Cq9+oIDKmznza78XXQYrUsPo8mJGjUxPskEYlzwvHjKubRnYm/K6RKhi
+5f4zX4BQ/Dt3H812ZjRXrsjAJP0KrD/jyD/jCT7zNBVPH1izBds+RwizyQAHwfNJ
+BFR78TH4cgzB619X47FDVOnT0LqQNVd0O3cSwnPrXE9XR3tPayE+iOB15llFSmi8
+z0ByOXldEpkezCn92Umk++suzIVj1qfsK+bv2phZWJPbLEIWPDRHUbYf76q5ArAr
+u4xtxT/hoK3krEs/IN3d70qjlUJ36SEw1UaZ82PWhakQbdtu39ZraMJB
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/lib/public_key/test/pbe_SUITE_data/rc2_cbc_enc_key.pem b/lib/public_key/test/pbe_SUITE_data/rc2_cbc_enc_key.pem
new file mode 100644
index 0000000000..618cddcfd7
--- /dev/null
+++ b/lib/public_key/test/pbe_SUITE_data/rc2_cbc_enc_key.pem
@@ -0,0 +1,12 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBrjBIBgkqhkiG9w0BBQ0wOzAeBgkqhkiG9w0BBQwwEQQIrHyQPBZqWLUCAggA
+AgEQMBkGCCqGSIb3DQMCMA0CAToECEhbh7YZKiPSBIIBYCT1zp6o5jpFlIkgwPop
+7bW1+8ACr4exqzkeb3WflQ8cWJ4cURxzVdvxUnXeW1VJdaQZtjS/QHs5GhPTG/0f
+wtvnaPfwrIJ3FeGaZfcg2CrYhalOFmEb4xrE4KyoEQmUN8tb/Cg94uzd16BOPw21
+RDnE8bnPdIGY7TyL95kbkqH23mK53pi7h+xWIgduW+atIqDyyt55f7WMZcvDvlj6
+VpN/V0h+qxBHL274WA4dj6GYgeyUFpi60HdGCK7By2TBy8h1ZvKGjmB9h8jZvkx1
+MkbRumXxyFsowTZawyYvO8Um6lbfEDP9zIEUq0IV8RqH2MRyblsPNSikyYhxX/cz
+tdDxRKhilySbSBg5Kr8OfcwKp9bpinN96nmG4xr3Tch1bnVvqJzOQ5+Vva2WwVvH
+2JkWvYm5WaANg4Q6bRxu9vz7DuhbJjQdZbxFezIAgrJdSe92B00jO/0Kny1WjiVO
+6DA=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl
index b11e4d092a..a91dcfa029 100644
--- a/lib/public_key/test/public_key_SUITE.erl
+++ b/lib/public_key/test/public_key_SUITE.erl
@@ -23,8 +23,8 @@
%% Note: This directive should only be used in test suites.
-compile(export_all).
--include_lib("common_test/include/ct.hrl").
--include_lib("test_server/include/test_server_line.hrl").
+%%-include_lib("common_test/include/ct.hrl").
+-include_lib("test_server/include/test_server.hrl").
-include_lib("public_key/include/public_key.hrl").
@@ -107,7 +107,7 @@ all() ->
{group, ssh_public_key_decode_encode},
encrypt_decrypt,
{group, sign_verify},
- pkix, pkix_path_validation, deprecated].
+ pkix, pkix_path_validation].
groups() ->
[{pem_decode_encode, [], [dsa_pem, rsa_pem, encrypted_pem,
@@ -699,27 +699,6 @@ pkix_path_validation(Config) when is_list(Config) ->
VerifyFunAndState1}]),
ok.
-%%--------------------------------------------------------------------
-deprecated(doc) ->
- ["Check deprecated functions."];
-deprecated(suite) ->
- [];
-deprecated(Config) when is_list(Config) ->
- Datadir = ?config(data_dir, Config),
- {ok, [DsaKey = {'DSAPrivateKey', _DsaKey, _}]} =
- public_key:pem_to_der(filename:join(Datadir, "dsa.pem")),
- {ok, [RsaKey = {'RSAPrivateKey', _RsaKey,_}]} =
- public_key:pem_to_der(filename:join(Datadir, "client_key.pem")),
- {ok, [ProtectedRsaKey = {'RSAPrivateKey', _ProtectedRsaKey,_}]} =
- public_key:pem_to_der(filename:join(Datadir, "rsa.pem")),
-
- {ok, #'DSAPrivateKey'{}} = public_key:decode_private_key(DsaKey),
- {ok, #'RSAPrivateKey'{}} = public_key:decode_private_key(RsaKey),
- {ok, #'RSAPrivateKey'{}} = public_key:decode_private_key(ProtectedRsaKey, "abcd1234"),
- ok.
-
-%%--------------------------------------------------------------------
-
check_entry_type(#'DSAPrivateKey'{}, 'DSAPrivateKey') ->
true;
check_entry_type(#'RSAPrivateKey'{}, 'RSAPrivateKey') ->
diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk
index 3c6b012152..d8f811bf25 100644
--- a/lib/public_key/vsn.mk
+++ b/lib/public_key/vsn.mk
@@ -1 +1 @@
-PUBLIC_KEY_VSN = 0.12
+PUBLIC_KEY_VSN = 0.14
diff --git a/lib/reltool/doc/src/make.dep b/lib/reltool/doc/src/make.dep
deleted file mode 100644
index 59e77e8162..0000000000
--- a/lib/reltool/doc/src/make.dep
+++ /dev/null
@@ -1,20 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex part.tex ref_man.tex reltool.tex \
- reltool_examples.tex reltool_intro.tex reltool_usage.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/reltool/doc/src/notes.xml b/lib/reltool/doc/src/notes.xml
index 324d69675e..5304b996a4 100644
--- a/lib/reltool/doc/src/notes.xml
+++ b/lib/reltool/doc/src/notes.xml
@@ -37,7 +37,35 @@
thus constitutes one section in this document. The title of each
section is the version number of Reltool.</p>
- <section><title>Reltool 0.5.6</title>
+ <section><title>Reltool 0.5.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ If a module was duplicated in the library directories
+ visible to reltool, and the configuration did not point
+ out which file to use, then reltool:start would always
+ fail. A pop-up is added which asks if you want to
+ continue with a safe and minimal configuration.</p>
+ <p>
+ Own Id: OTP-9383</p>
+ </item>
+ <item>
+ <p>
+ wx would sometimes crash due to an empty radiobox on the
+ 'releases' tab of the system window. This radiobox is
+ removed, and replaced by a listbox which will always
+ contain at least kernel and stdlib applications.</p>
+ <p>
+ Own Id: OTP-9384</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Reltool 0.5.6</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/reltool/src/reltool_sys_win.erl b/lib/reltool/src/reltool_sys_win.erl
index 76c064f1e7..8b0f64eb45 100644
--- a/lib/reltool/src/reltool_sys_win.erl
+++ b/lib/reltool/src/reltool_sys_win.erl
@@ -54,7 +54,9 @@
whitelist,
blacklist,
derived,
- fgraph_wins
+ fgraph_wins,
+ app_box,
+ mod_box
}).
-define(WIN_WIDTH, 800).
@@ -86,6 +88,11 @@
-define(blacklist, "Excluded").
-define(derived, "Derived").
+-define(safe_config,{sys,[{incl_cond,exclude},
+ {app,kernel,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]}]}).
+
-record(root_data, {dir}).
-record(lib_data, {dir, tree, item}).
-record(escript_data, {file, tree, item}).
@@ -102,7 +109,7 @@
start_link(Opts) ->
proc_lib:start_link(?MODULE,
init,
- [[{parent, self()} | Opts]],
+ [[{safe_config, false}, {parent, self()} | Opts]],
infinity,
[]).
@@ -126,53 +133,73 @@ init(Options) ->
exit({Reason, erlang:get_stacktrace()})
end.
-do_init([{parent, Parent} | Options]) ->
+do_init([{safe_config, Safe}, {parent, Parent} | Options]) ->
case reltool_server:start_link(Options) of
{ok, ServerPid, C, Sys} ->
process_flag(trap_exit, C#common.trap_exit),
- S = #state{parent_pid = Parent,
- server_pid = ServerPid,
- common = C,
- config_file = filename:absname("config.reltool"),
- target_dir = filename:absname("reltool_target_dir"),
- app_wins = [],
- sys = Sys,
- fgraph_wins = []},
wx:new(),
wx:debug(C#common.wx_debug),
- S2 = create_window(S),
%% wx_misc:beginBusyCursor(),
case reltool_server:get_status(ServerPid) of
{ok, Warnings} ->
exit_dialog(Warnings),
- {ok, Sys2} = reltool_server:get_sys(ServerPid),
- S3 = S2#state{sys = Sys2},
+ {ok, Sys} = reltool_server:get_sys(ServerPid),
+ S = #state{parent_pid = Parent,
+ server_pid = ServerPid,
+ common = C,
+ config_file = filename:absname("config.reltool"),
+ target_dir = filename:absname("reltool_target_dir"),
+ app_wins = [],
+ sys = Sys,
+ fgraph_wins = []},
+ S2 = create_window(S),
S5 = wx:batch(fun() ->
Title = atom_to_list(?APPLICATION),
- wxFrame:setTitle(S3#state.frame,
+ wxFrame:setTitle(S2#state.frame,
Title),
%% wxFrame:setMinSize(Frame,
%% {?WIN_WIDTH, ?WIN_HEIGHT}),
wxStatusBar:setStatusText(
- S3#state.status_bar,
+ S2#state.status_bar,
"Done."),
- S4 = redraw_apps(S3),
- redraw_libs(S4)
+ S3 = redraw_apps(S2),
+ S4 = redraw_libs(S3),
+ redraw_config_page(S4)
end),
%% wx_misc:endBusyCursor(),
%% wxFrame:destroy(Frame),
proc_lib:init_ack(S#state.parent_pid, {ok, self()}),
loop(S5);
{error, Reason} ->
- io:format("~p(~p): <ERROR> ~p\n", [?MODULE, ?LINE, Reason]),
- exit(Reason)
+ restart_server_safe_config(Safe,Parent,Reason)
end;
{error, Reason} ->
io:format("~p(~p): <ERROR> ~p\n", [?MODULE, ?LINE, Reason]),
exit(Reason)
end.
+restart_server_safe_config(true,_Parent,Reason) ->
+ io:format("~p(~p): <ERROR> ~p\n", [?MODULE, ?LINE, Reason]),
+ exit(Reason);
+restart_server_safe_config(false,Parent,Reason) ->
+ Strings =
+ [{?wxBLACK,"Could not start reltool server:\n\n"},
+ {?wxRED,Reason++"\n\n"},
+ {?wxBLACK,
+ io_lib:format(
+ "Resetting the configuration to:~n~n ~p~n~n"
+ "Do you want to continue with this configuration?",
+ [?safe_config])}],
+
+ case question_dialog_2("Reltool server start error", Strings) of
+ ?wxID_OK ->
+ do_init([{safe_config,true},{parent,Parent},?safe_config]);
+ ?wxID_CANCEL ->
+ io:format("~p(~p): <ERROR> ~p\n", [?MODULE, ?LINE, Reason]),
+ exit(Reason)
+ end.
+
exit_dialog([]) ->
ok;
exit_dialog(Warnings) ->
@@ -606,6 +633,13 @@ create_config_page(#state{sys = Sys, book = Book} = S) ->
{proportion, 1}]),
wxPanel:setSizer(Panel, Sizer),
wxNotebook:addPage(Book, Panel, ?SYS_PAGE, []),
+ S#state{app_box = AppBox, mod_box = ModBox}.
+
+redraw_config_page(#state{sys = Sys, app_box = AppBox, mod_box = ModBox} = S) ->
+ AppChoice = reltool_utils:incl_cond_to_index(Sys#sys.incl_cond),
+ wxRadioBox:setSelection(AppBox, AppChoice),
+ ModChoice = reltool_utils:mod_cond_to_index(Sys#sys.mod_cond),
+ wxRadioBox:setSelection(ModBox, ModChoice),
S.
create_main_release_page(#state{book = Book} = S) ->
@@ -640,15 +674,15 @@ create_main_release_page(#state{book = Book} = S) ->
add_release_page(Book, #rel{name = RelName, rel_apps = RelApps}) ->
Panel = wxPanel:new(Book, []),
Sizer = wxBoxSizer:new(?wxHORIZONTAL),
- RelBox = wxRadioBox:new(Panel,
- ?wxID_ANY,
- "Applications included in the release " ++ RelName,
- ?wxDefaultPosition,
- ?wxDefaultSize,
- [atom_to_list(RA#rel_app.name) || RA <- RelApps],
- []),
- %% wxRadioBox:setSelection(RelBox, 2), % mandatory
- wxEvtHandler:connect(RelBox, command_radiobox_selected,
+ AppNames = [kernel, stdlib |
+ [RA#rel_app.name || RA <- RelApps] -- [kernel, stdlib]],
+ RelBox = wxListBox:new(
+ Panel,?wxID_ANY,
+ [{pos,?wxDefaultPosition},
+ {size,?wxDefaultSize},
+ {choices,[[atom_to_list(AppName)] || AppName <- AppNames]},
+ {style,?wxLB_EXTENDED}]),
+ wxEvtHandler:connect(RelBox, command_listbox_selected,
[{userData, {config_rel_cond, RelName}}]),
RelToolTip = "Choose which applications that shall "
"be included in the release resource file.",
@@ -1363,7 +1397,8 @@ refresh(S) ->
[ok = reltool_app_win:refresh(AW#app_win.pid) || AW <- S#state.app_wins],
S2 = S#state{sys = Sys},
S3 = redraw_libs(S2),
- redraw_apps(S3).
+ S4 = redraw_apps(S3),
+ redraw_config_page(S4).
question_dialog(Question, Details) ->
%% Parent = S#state.frame,
@@ -1420,6 +1455,44 @@ display_message(Message, Icon) ->
wxMessageDialog:showModal(Dialog),
wxMessageDialog:destroy(Dialog).
+%% Strings = [{Color,String}]
+question_dialog_2(DialogLabel, Strings) ->
+ %% Parent = S#state.frame,
+ Parent = wx:typeCast(wx:null(), wxWindow),
+ %% [{style, ?wxYES_NO bor ?wxICON_ERROR bor ?wx}]),
+ DialogStyle = ?wxRESIZE_BORDER bor ?wxCAPTION bor ?wxSYSTEM_MENU bor
+ ?wxMINIMIZE_BOX bor ?wxMAXIMIZE_BOX bor ?wxCLOSE_BOX,
+ Dialog = wxDialog:new(Parent, ?wxID_ANY, DialogLabel,
+ [{style, DialogStyle}]),
+ Color = wxWindow:getBackgroundColour(Dialog),
+ TextStyle = ?wxTE_READONLY bor ?wxTE_MULTILINE bor ?wxHSCROLL,
+ Text = wxTextCtrl:new(Dialog, ?wxID_ANY,
+ [{size, {600, 400}}, {style, TextStyle}]),
+ wxWindow:setBackgroundColour(Text, Color),
+ TextAttr = wxTextAttr:new(),
+ add_text(Text,TextAttr,Strings),
+ Sizer = wxBoxSizer:new(?wxVERTICAL),
+ wxSizer:add(Sizer, Text, [{border, 2}, {flag, ?wxEXPAND}, {proportion, 1}]),
+ ButtSizer = wxDialog:createStdDialogButtonSizer(Dialog, ?wxOK bor ?wxCANCEL),
+ wxSizer:add(Sizer, ButtSizer, [{border, 2}, {flag, ?wxEXPAND}]),
+ wxPanel:setSizer(Dialog, Sizer),
+ wxSizer:fit(Sizer, Dialog),
+ wxSizer:setSizeHints(Sizer, Dialog),
+ Answer = wxDialog:showModal(Dialog),
+ wxDialog:destroy(Dialog),
+ Answer.
+
+add_text(Text,Attr,[{Color,String}|Strings]) ->
+ wxTextAttr:setTextColour(Attr, Color),
+ wxTextCtrl:setDefaultStyle(Text, Attr),
+ wxTextCtrl:appendText(Text, String),
+ add_text(Text,Attr,Strings);
+add_text(_,_,[]) ->
+ ok.
+
+
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% sys callbacks
diff --git a/lib/reltool/vsn.mk b/lib/reltool/vsn.mk
index 227b1c80a2..751f9bb6db 100644
--- a/lib/reltool/vsn.mk
+++ b/lib/reltool/vsn.mk
@@ -1 +1 @@
-RELTOOL_VSN = 0.5.6
+RELTOOL_VSN = 0.5.7
diff --git a/lib/runtime_tools/c_src/Makefile.in b/lib/runtime_tools/c_src/Makefile.in
index 840de39f07..73ab6cdc11 100644
--- a/lib/runtime_tools/c_src/Makefile.in
+++ b/lib/runtime_tools/c_src/Makefile.in
@@ -89,42 +89,31 @@ endif
# Targets
# ----------------------------------------------------
-debug opt: $(OBJDIR) $(BINDIR) $(SOLIBS)
+_create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR))
-$(OBJDIR):
- -@mkdir -p $(OBJDIR)
-
-$(BINDIR):
- -@mkdir -p $(BINDIR)
+debug opt: $(SOLIBS)
$(OBJDIR)/%.o: %.c
- $(INSTALL_DIR) $(OBJDIR)
$(CC) -c -o $@ $(ALL_CFLAGS) $<
$(LIBDIR)/trace_ip_drv.so: $(TRACE_IP_DRV_OBJS)
- $(INSTALL_DIR) $(LIBDIR)
$(LD) $(LDFLAGS) -o $@ $^ -lc $(LIBS)
$(LIBDIR)/trace_file_drv.so: $(TRACE_FILE_DRV_OBJS)
- $(INSTALL_DIR) $(LIBDIR)
$(LD) $(LDFLAGS) -o $@ $^ -lc $(LIBS)
$(LIBDIR)/trace_ip_drv.dll: $(TRACE_IP_DRV_OBJS)
- $(INSTALL_DIR) $(LIBDIR)
$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
$(LIBDIR)/trace_file_drv.dll: $(TRACE_FILE_DRV_OBJS)
- $(INSTALL_DIR) $(LIBDIR)
$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
#
# VxWorks is simply to different from Unix in this sense.
# Here are the inference rules for VxWorks
#
$(LIBDIR)/trace_ip_drv.eld: $(TRACE_IP_DRV_OBJS)
- $(INSTALL_DIR) $(LIBDIR)
$(LD) $(LDFLAGS) -o $@ $^
$(LIBDIR)/trace_file_drv.eld: $(TRACE_FILE_DRV_OBJS)
- $(INSTALL_DIR) $(LIBDIR)
$(LD) $(LDFLAGS) -o $@ $^
clean:
diff --git a/lib/runtime_tools/doc/src/dbg.xml b/lib/runtime_tools/doc/src/dbg.xml
index 0e63649c09..c7c5cd4ff0 100644
--- a/lib/runtime_tools/doc/src/dbg.xml
+++ b/lib/runtime_tools/doc/src/dbg.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -316,7 +316,8 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c
<v>Module = atom() | '_'</v>
<v>Function = atom() | '_'</v>
<v>Arity = integer() |'_'</v>
- <v>MatchSpec = integer() | atom() | [] | match_spec()</v>
+ <v>MatchSpec = integer() | Built-inAlias | [] | match_spec()</v>
+ <v>Built-inAlias = x | c | cx</v>
<v>MatchDesc = [MatchInfo]</v>
<v>MatchInfo = {saved, integer()} | MatchNum</v>
<v>MatchNum = {matched, node(), integer()} | {matched, node(), 0, RPCError}</v>
@@ -349,8 +350,9 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c
if the MatchSpec is other
than []. The integer <c>N</c> may then be used in
subsequent calls to this function and will stand as an
- "alias" for the given expression. There are also built-in
- aliases named with atoms (see also <c>ltp/0</c> below).</p>
+ "alias" for the given expression. There are also a couple of
+ built-in aliases for common expressions, see <c>ltp/0</c> below
+ for details.</p>
<p>If an error is returned, it can be due to errors in
compilation of the match specification. Such errors are
presented as a list of tuples <c>{error, string()}</c> where
@@ -528,6 +530,21 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c
<p>Match specifications used can be saved in a file (if a
read-write file system is present) for use in later
debugging sessions, see <c>wtp/1</c> and <c>rtp/1</c></p>
+ <p>There are three built-in trace patterns:
+ <c>exception_trace</c>, <c>caller_trace</c>
+ and <c>caller_exception_trace</c> (or <c>x</c>, <c>c</c> and
+ <c>cx</c> respectively).
+ Exception trace sets a trace which will show function names,
+ parameters, return values and exceptions thrown from functions.
+ Caller traces display function names, parameters and information
+ about which function called it. An example using a built-in alias:</p>
+ <pre>
+(x@y)4> <input>dbg:tp(lists,sort,cx).</input>
+{ok,[{matched,nonode@nohost,2},{saved,cx}]}
+(x@y)4> <input>lists:sort([2,1]).</input>
+(&lt;0.32.0&gt;) call lists:sort([2,1]) ({erl_eval,do_apply,5})
+(&lt;0.32.0&gt;) returned from lists:sort/1 -> [1,2]
+[1,2]</pre>
</desc>
</func>
<func>
@@ -706,7 +723,7 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c
value from the last invocation of the fun. The initial value
of the second parameter is specified in the <c>InitialData</c>
part of the <c>HandlerSpec</c>. The <c>HandlerFun</c> may
- chose any appropriate action to take when invoked, and can
+ choose any appropriate action to take when invoked, and can
save a state for the next invocation by returning it.
</p>
<p>If <c>Type</c> is a port, then the second parameter should
@@ -766,7 +783,7 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c
<p>This function creates a trace port generating <em>fun</em>.
The <em>fun</em> takes no arguments and returns a newly opened
trace port. The return value from this function is suitable as
- a second parameter to tracer/2, i. e. <c>dbg:tracer(port, dbg:trace_port(ip, 4711))</c>. </p>
+ a second parameter to tracer/2, i.e. <c>dbg:tracer(port, dbg:trace_port(ip, 4711))</c>. </p>
<p>A trace port is an
Erlang port to a dynamically linked in driver that handles
trace messages directly, without the overhead of sending them
@@ -852,9 +869,9 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c
<desc>
<p>This function is used to do a control operation on the
active trace port driver on the given node
- (<c>Nodename</c>). Which operations that are allowed as well
- as their return values are depending on which trace driver
- that is used.</p>
+ (<c>Nodename</c>). Which operations are allowed as well
+ as their return values depend on which trace driver
+ is used.</p>
<p>Returns either <c>ok</c> or <c>{ok, Result}</c>
if the operation was successful, or <c>{error, Reason}</c>
if the current tracer is a process
diff --git a/lib/runtime_tools/doc/src/make.dep b/lib/runtime_tools/doc/src/make.dep
deleted file mode 100644
index 85eae88adf..0000000000
--- a/lib/runtime_tools/doc/src/make.dep
+++ /dev/null
@@ -1,20 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex dbg.tex erts_alloc_config.tex refman.tex \
- runtime_tools_app.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: refman.xml
-
diff --git a/lib/runtime_tools/doc/src/notes.xml b/lib/runtime_tools/doc/src/notes.xml
index 599be62241..0bb76e1ea4 100644
--- a/lib/runtime_tools/doc/src/notes.xml
+++ b/lib/runtime_tools/doc/src/notes.xml
@@ -31,6 +31,23 @@
<p>This document describes the changes made to the Runtime_Tools
application.</p>
+<section><title>Runtime_Tools 1.8.6</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Two new built-in trace pattern aliases have been added:
+ caller_trace (c) and caller_exception_trace (cx). See the
+ dbg:ltp/0 documentation for more info.</p>
+ <p>
+ Own Id: OTP-9458</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Runtime_Tools 1.8.5</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/runtime_tools/src/Makefile b/lib/runtime_tools/src/Makefile
index 4f831f3dd8..46b570210a 100644
--- a/lib/runtime_tools/src/Makefile
+++ b/lib/runtime_tools/src/Makefile
@@ -46,7 +46,8 @@ MODULES= \
runtime_tools_sup \
dbg \
percept_profile \
- observer_backend
+ observer_backend \
+ ttb_autostart
HRL_FILES= ../include/observer_backend.hrl
ERL_FILES= $(MODULES:%=%.erl)
diff --git a/lib/runtime_tools/src/dbg.erl b/lib/runtime_tools/src/dbg.erl
index 56283f4d3d..385047ee73 100644
--- a/lib/runtime_tools/src/dbg.erl
+++ b/lib/runtime_tools/src/dbg.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -32,7 +32,7 @@
-export([fun2ms/1]).
%% Local exports
--export([erlang_trace/3,get_info/0]).
+-export([erlang_trace/3,get_info/0,deliver_and_flush/1]).
%% Debug exports
-export([wrap_presort/2, wrap_sort/2, wrap_postsort/1, wrap_sortfix/2,
@@ -348,17 +348,16 @@ trace_port_control(Operation) ->
trace_port_control(node(), Operation).
trace_port_control(Node, flush) ->
- Ref = erlang:trace_delivered(all),
- receive
- {trace_delivered,all,Ref} -> ok
- end,
- case trace_port_control(Node, $f, "") of
- {ok, [0]} ->
- ok;
- {ok, _} ->
- {error, not_supported_by_trace_driver};
- Other ->
- Other
+ case get_tracer(Node) of
+ {ok, Port} when is_port(Port) ->
+ case catch rpc:call(Node,?MODULE,deliver_and_flush,[Port]) of
+ [0] ->
+ ok;
+ _ ->
+ {error, not_supported_by_trace_driver}
+ end;
+ _ ->
+ {error, no_trace_driver}
end;
trace_port_control(Node,get_listen_port) ->
case trace_port_control(Node,$p, "") of
@@ -378,7 +377,14 @@ trace_port_control(Node, Command, Arg) ->
{error, no_trace_driver}
end.
-
+%% A bit more than just flush - it also makes sure all trace messages
+%% are delivered first, before flushing the driver.
+deliver_and_flush(Port) ->
+ Ref = erlang:trace_delivered(all),
+ receive
+ {trace_delivered,all,Ref} -> ok
+ end,
+ erlang:port_control(Port, $f, "").
trace_port(file, {Filename, wrap, Tail}) ->
@@ -684,18 +690,12 @@ loop({C,T}=SurviveLinks, Table) ->
%% tracing on the node it removes from the list of active trace nodes,
%% we will call erlang:trace_delivered/1 on ALL nodes that we have
%% connections to.
- Delivered = fun() ->
- Ref = erlang:trace_delivered(all),
- receive
- {trace_delivered,all,Ref} -> ok
- end
- end,
- catch rpc:multicall(nodes(), erlang, apply, [Delivered,[]]),
- Ref = erlang:trace_delivered(all),
- receive
- {trace_delivered,all,Ref} ->
- exit(done)
- end;
+ %% If it is a file trace driver, we will also flush the port.
+ lists:foreach(fun({Node,{_Relay,Port}}) ->
+ rpc:call(Node,?MODULE,deliver_and_flush,[Port])
+ end,
+ get()),
+ exit(done);
{From, {link_to, Pid}} ->
case (catch link(Pid)) of
{'EXIT', Reason} ->
@@ -1449,6 +1449,19 @@ new_pattern_table() ->
ets:insert(PT,
{exception_trace,
term_to_binary(x)}),
+ ets:insert(PT,
+ {c,
+ term_to_binary([{'_',[],[{message,{caller}}]}])}),
+ ets:insert(PT,
+ {caller_trace,
+ term_to_binary(c)}),
+ ets:insert(PT,
+ {cx,
+ term_to_binary([{'_',[],[{exception_trace},
+ {message,{caller}}]}])}),
+ ets:insert(PT,
+ {caller_exception_trace,
+ term_to_binary(cx)}),
PT.
diff --git a/lib/runtime_tools/src/erts_alloc_config.erl b/lib/runtime_tools/src/erts_alloc_config.erl
index 0bcb202fd8..1a57c94443 100644
--- a/lib/runtime_tools/src/erts_alloc_config.erl
+++ b/lib/runtime_tools/src/erts_alloc_config.erl
@@ -1,6 +1,7 @@
+%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -16,6 +17,7 @@
%% The Initial Developer of the Original Code is Ericsson AB.
%%
%% %CopyrightEnd%
+%%
%%%-------------------------------------------------------------------
%%% File : erts_alloc_config.erl
@@ -71,6 +73,7 @@
A == binary_alloc;
A == std_alloc;
A == ets_alloc;
+ A == fix_alloc;
A == eheap_alloc;
A == ll_alloc;
A == sl_alloc;
@@ -94,6 +97,7 @@
[{binary_alloc, 131072},
{std_alloc, 131072},
{ets_alloc, 131072},
+ {fix_alloc, 131072},
{eheap_alloc, 524288},
{ll_alloc, 2097152},
{sl_alloc, 131072},
@@ -104,6 +108,7 @@
[{binary_alloc, 10},
{std_alloc, 10},
{ets_alloc, 10},
+ {fix_alloc, 10},
{eheap_alloc, 10},
{ll_alloc, 0},
{sl_alloc, 10},
@@ -438,9 +443,6 @@ conf_alloc(#conf{format_to = FTO} = Conf, #alloc{name = A} = Alc) ->
chk_xnote(Conf, Alc).
chk_xnote(#conf{format_to = FTO},
- #alloc{name = fix_alloc}) ->
- fcp(FTO, "Cannot be configured.");
-chk_xnote(#conf{format_to = FTO},
#alloc{name = sys_alloc}) ->
fcp(FTO, "Cannot be configured. Default malloc implementation used.");
chk_xnote(#conf{format_to = FTO},
diff --git a/lib/runtime_tools/src/inviso_rt.erl b/lib/runtime_tools/src/inviso_rt.erl
index ac7ac2a584..b162f5b045 100644
--- a/lib/runtime_tools/src/inviso_rt.erl
+++ b/lib/runtime_tools/src/inviso_rt.erl
@@ -2359,8 +2359,8 @@ list_wrapset(Prefix,Suffix) ->
list_wrapset_2([File|Rest],RegExp) ->
Length=length(File),
- case regexp:first_match(File,RegExp) of
- {match,1,Length} -> % This is a member of the set.
+ case re:run(File,RegExp) of
+ {match,[{0,Length}]} -> % This is a member of the set.
[File|list_wrapset_2(Rest,RegExp)];
_ ->
list_wrapset_2(Rest,RegExp)
diff --git a/lib/runtime_tools/src/inviso_rt_lib.erl b/lib/runtime_tools/src/inviso_rt_lib.erl
index 2c6964e53e..ee6a72ae0c 100644
--- a/lib/runtime_tools/src/inviso_rt_lib.erl
+++ b/lib/runtime_tools/src/inviso_rt_lib.erl
@@ -197,15 +197,15 @@ match_modules(RegExpDir,RegExpMod,Actions) ->
handle_expand_regexp_2([{Mod,Path}|Rest],RegExpDir,RegExpMod,Result) ->
ModStr=atom_to_list(Mod),
ModLen=length(ModStr),
- case regexp:first_match(ModStr,RegExpMod) of
- {match,1,ModLen} -> % Ok, The regexp matches the module.
+ case re:run(ModStr,RegExpMod) of
+ {match,[{0,ModLen}]} -> % Ok, The regexp matches the module.
if
is_list(RegExpDir),is_atom(Path) -> % Preloaded or covercompiled...
handle_expand_regexp_2(Rest,RegExpDir,RegExpMod,Result);
is_list(RegExpDir),is_list(Path) -> % Dir reg-exp is used!
PathOnly=filename:dirname(Path), % Must remove beam-file name.
- case regexp:first_match(PathOnly,RegExpDir) of
- {match,_,_} -> % Did find a match, that is enough!
+ case re:run(PathOnly,RegExpDir,[{capture,none}]) of
+ match -> % Did find a match, that is enough!
handle_expand_regexp_2(Rest,RegExpDir,RegExpMod,[Mod|Result]);
_ -> % Either error or nomatch.
handle_expand_regexp_2(Rest,RegExpDir,RegExpMod,Result)
@@ -233,8 +233,8 @@ handle_expand_regexp_3([Path|Rest],RegExpDir,RegExpMod,AllLoaded,Result) ->
volumerelative -> % Only on Windows!?
filename:absname(Path)
end,
- case regexp:first_match(AbsPath,RegExpDir) of
- {match,_,_} -> % Ok, the directory is allowed.
+ case re:run(AbsPath,RegExpDir,[{capture,none}]) of
+ match -> % Ok, the directory is allowed.
NewResult=handle_expand_regexp_3_1(Path,RegExpMod,AllLoaded,Result),
handle_expand_regexp_3(Rest,RegExpDir,RegExpMod,AllLoaded,NewResult);
_ -> % This directory does not qualify.
@@ -262,8 +262,8 @@ handle_expand_regexp_3_2([File|Rest],RegExpMod,AllLoaded,Result) ->
case {lists:keysearch(Mod,1,AllLoaded),lists:member(Mod,Result)} of
{false,false} -> % This module is not tried before.
ModLen=length(ModStr),
- case regexp:first_match(ModStr,RegExpMod) of
- {match,1,ModLen} -> % This module satisfies the regexp.
+ case re:run(ModStr,RegExpMod) of
+ {match,[{0,ModLen}]} -> % This module satisfies the regexp.
handle_expand_regexp_3_2(Rest,RegExpMod,AllLoaded,[Mod|Result]);
_ -> % Error or not perfect match.
handle_expand_regexp_3_2(Rest,RegExpMod,AllLoaded,Result)
diff --git a/lib/runtime_tools/src/observer_backend.erl b/lib/runtime_tools/src/observer_backend.erl
index 0f428de07a..9c1f9da5b1 100644
--- a/lib/runtime_tools/src/observer_backend.erl
+++ b/lib/runtime_tools/src/observer_backend.erl
@@ -31,6 +31,7 @@
ttb_write_binary/2,
ttb_stop/1,
ttb_fetch/2,
+ ttb_resume_trace/0,
ttb_get_filenames/1]).
-define(CHUNKSIZE,8191). % 8 kbytes - 1 byte
@@ -92,16 +93,22 @@ etop_collect([], Acc) -> Acc.
%%
%% ttb backend
%%
-ttb_init_node(MetaFile,PI,Traci) ->
+ttb_init_node(MetaFile_0,PI,Traci) ->
if
- is_list(MetaFile);
- is_atom(MetaFile) ->
+ is_list(MetaFile_0);
+ is_atom(MetaFile_0) ->
+ {ok, Cwd} = file:get_cwd(),
+ MetaFile = filename:join(Cwd, MetaFile_0),
file:delete(MetaFile);
true -> % {local,_,_}
- ok
+ MetaFile = MetaFile_0
+ end,
+ case proplists:get_value(resume, Traci) of
+ {true, _} -> (autostart_module()):write_config(Traci);
+ _ -> ok
end,
Self = self(),
- MetaPid = spawn(fun() -> ttb_meta_tracer(MetaFile,PI,Self) end),
+ MetaPid = spawn(fun() -> ttb_meta_tracer(MetaFile,PI,Self,Traci) end),
receive {MetaPid,started} -> ok end,
MetaPid ! {metadata,Traci},
case PI of
@@ -111,13 +118,14 @@ ttb_init_node(MetaFile,PI,Traci) ->
false ->
ok
end,
- {ok,MetaPid}.
+ {ok,MetaFile,MetaPid}.
ttb_write_trace_info(MetaPid,Key,What) ->
MetaPid ! {metadata,Key,What},
ok.
-ttb_meta_tracer(MetaFile,PI,Parent) ->
+ttb_meta_tracer(MetaFile,PI,Parent,SessionData) ->
+ erlang:monitor(process, proplists:get_value(ttb_control, SessionData)),
case PI of
true ->
ReturnMS = [{'_',[],[{return_trace}]}],
@@ -130,22 +138,29 @@ ttb_meta_tracer(MetaFile,PI,Parent) ->
ok
end,
Parent ! {self(),started},
- ttb_meta_tracer_loop(MetaFile,PI,dict:new()).
+ case proplists:get_value(overload_check, SessionData) of
+ {Ms, M, F} ->
+ catch M:F(init),
+ erlang:send_after(Ms, self(), overload_check);
+ _ ->
+ ok
+ end,
+ ttb_meta_tracer_loop(MetaFile,PI,dict:new(),SessionData).
-ttb_meta_tracer_loop(MetaFile,PI,Acc) ->
+ttb_meta_tracer_loop(MetaFile,PI,Acc,State) ->
receive
{trace_ts,_,call,{erlang,register,[Name,Pid]},_} ->
ttb_store_meta({pid,{Pid,Name}},MetaFile),
- ttb_meta_tracer_loop(MetaFile,PI,Acc);
+ ttb_meta_tracer_loop(MetaFile,PI,Acc,State);
{trace_ts,_,call,{global,register_name,[Name,Pid]},_} ->
ttb_store_meta({pid,{Pid,{global,Name}}},MetaFile),
- ttb_meta_tracer_loop(MetaFile,PI,Acc);
+ ttb_meta_tracer_loop(MetaFile,PI,Acc,State);
{trace_ts,CallingPid,call,{erlang,spawn_opt,[{M,F,Args,_}]},_} ->
MFA = {M,F,length(Args)},
NewAcc = dict:update(CallingPid,
fun(Old) -> [MFA|Old] end, [MFA],
Acc),
- ttb_meta_tracer_loop(MetaFile,PI,NewAcc);
+ ttb_meta_tracer_loop(MetaFile,PI,NewAcc,State);
{trace_ts,CallingPid,return_from,{erlang,spawn_opt,_Arity},Ret,_} ->
case Ret of
{NewPid,_Mref} when is_pid(NewPid) -> ok;
@@ -158,14 +173,14 @@ ttb_meta_tracer_loop(MetaFile,PI,Acc) ->
T
end,
Acc),
- ttb_meta_tracer_loop(MetaFile,PI,NewAcc);
+ ttb_meta_tracer_loop(MetaFile,PI,NewAcc,State);
{trace_ts,CallingPid,call,{erlang,Spawn,[M,F,Args]},_}
when Spawn==spawn;Spawn==spawn_link ->
MFA = {M,F,length(Args)},
NewAcc = dict:update(CallingPid,
fun(Old) -> [MFA|Old] end, [MFA],
Acc),
- ttb_meta_tracer_loop(MetaFile,PI,NewAcc);
+ ttb_meta_tracer_loop(MetaFile,PI,NewAcc,State);
{trace_ts,CallingPid,return_from,{erlang,Spawn,_Arity},NewPid,_}
when Spawn==spawn;Spawn==spawn_link ->
@@ -176,28 +191,53 @@ ttb_meta_tracer_loop(MetaFile,PI,Acc) ->
T
end,
Acc),
- ttb_meta_tracer_loop(MetaFile,PI,NewAcc);
+ ttb_meta_tracer_loop(MetaFile,PI,NewAcc,State);
{metadata,Data} when is_list(Data) ->
ttb_store_meta(Data,MetaFile),
- ttb_meta_tracer_loop(MetaFile,PI,Acc);
+ ttb_meta_tracer_loop(MetaFile,PI,Acc,State);
{metadata,Key,Fun} when is_function(Fun) ->
ttb_store_meta([{Key,Fun()}],MetaFile),
- ttb_meta_tracer_loop(MetaFile,PI,Acc);
+ ttb_meta_tracer_loop(MetaFile,PI,Acc,State);
{metadata,Key,What} ->
ttb_store_meta([{Key,What}],MetaFile),
- ttb_meta_tracer_loop(MetaFile,PI,Acc);
-
- stop when PI=:=true ->
- erlang:trace_pattern({erlang,spawn,3},false,[meta]),
+ ttb_meta_tracer_loop(MetaFile,PI,Acc,State);
+ overload_check ->
+ {Ms, M, F} = proplists:get_value(overload_check, State),
+ case catch M:F(check) of
+ true ->
+ erlang:trace(all, false, [all]),
+ ControlPid = proplists:get_value(ttb_control, State),
+ ControlPid ! {node_overloaded, node()},
+ catch M:F(stop),
+ ttb_meta_tracer_loop(MetaFile,PI,Acc,lists:keydelete(overload_check, 1, State));
+ _ ->
+ erlang:send_after(Ms, self(), overload_check),
+ ttb_meta_tracer_loop(MetaFile,PI,Acc, State)
+ end;
+ {'DOWN', _, _, _, _} ->
+ stop_seq_trace(),
+ self() ! stop,
+ ttb_meta_tracer_loop(MetaFile,PI,Acc, State);
+ stop when PI=:=true ->
+ try_stop_resume(State),
+ try_stop_overload_check(State),
+ erlang:trace_pattern({erlang,spawn,3},false,[meta]),
erlang:trace_pattern({erlang,spawn_link,3},false,[meta]),
erlang:trace_pattern({erlang,spawn_opt,1},false,[meta]),
erlang:trace_pattern({erlang,register,2},false,[meta]),
erlang:trace_pattern({global,register_name,2},false,[meta]);
stop ->
- ok
+ try_stop_resume(State),
+ try_stop_overload_check(State)
+ end.
+
+try_stop_overload_check(State) ->
+ case proplists:get_value(overload, State) of
+ undefined -> ok;
+ {_, M, F} -> catch M:F(stop)
end.
pnames() ->
@@ -222,6 +262,40 @@ pinfo(P,Globals) ->
undefined -> [] % the process has terminated
end.
+autostart_module() ->
+ element(2, application:get_env(runtime_tools, ttb_autostart_module)).
+
+try_stop_resume(State) ->
+ case proplists:get_value(resume, State) of
+ true -> (autostart_module()):delete_config();
+ _ -> ok
+ end.
+
+ttb_resume_trace() ->
+ case (autostart_module()):read_config() of
+ {error, _} ->
+ ok;
+ {ok, Data} ->
+ Pid = proplists:get_value(ttb_control, Data),
+ {_, Timeout} = proplists:get_value(resume, Data),
+ case rpc:call(node(Pid), erlang, whereis, [ttb]) of
+ Pid ->
+ Pid ! {noderesumed, node(), self()},
+ wait_for_fetch_ready(Timeout);
+ _ ->
+ ok
+ end,
+ (autostart_module()):delete_config(),
+ ok
+ end.
+
+wait_for_fetch_ready(Timeout) ->
+ receive
+ trace_resumed ->
+ ok
+ after Timeout ->
+ ok
+ end.
ttb_store_meta(Data,{local,MetaFile,Port}) when is_list(Data) ->
ttb_send_to_port(Port,MetaFile,Data);
@@ -273,6 +347,9 @@ ttb_stop(MetaPid) ->
%% returns, and then the Port (in {local,MetaFile,Port})
%% cannot be accessed any more.
receive {'DOWN', Ref, process, MetaPid, _Info} -> ok end,
+ stop_seq_trace().
+
+stop_seq_trace() ->
seq_trace:reset_trace(),
seq_trace:set_system_tracer(false).
@@ -287,7 +364,7 @@ ttb_fetch(MetaFile,{Port,Host}) ->
send_files({Sock,Host},[File|Files]) ->
{ok,Fd} = file:open(File,[raw,read,binary]),
- gen_tcp:send(Sock,<<1,(list_to_binary(File))/binary>>),
+ gen_tcp:send(Sock,<<1,(list_to_binary(filename:basename(File)))/binary>>),
send_chunks(Sock,Fd),
file:delete(File),
send_files({Sock,Host},Files);
diff --git a/lib/runtime_tools/src/runtime_tools.app.src b/lib/runtime_tools/src/runtime_tools.app.src
index e6dc7a21d4..095567b165 100644
--- a/lib/runtime_tools/src/runtime_tools.app.src
+++ b/lib/runtime_tools/src/runtime_tools.app.src
@@ -22,7 +22,8 @@
{modules, [dbg,observer_backend,percept_profile,
inviso_rt,inviso_rt_lib,inviso_rt_meta,
inviso_as_lib,inviso_autostart,inviso_autostart_server,
- runtime_tools,runtime_tools_sup,erts_alloc_config]},
+ runtime_tools,runtime_tools_sup,erts_alloc_config,
+ ttb_autostart]},
{registered, [runtime_tools_sup,inviso_rt,inviso_rt_meta]},
{applications, [kernel, stdlib]},
% {env, [{inviso_autostart_mod,your_own_autostart_module}]},
diff --git a/lib/runtime_tools/src/runtime_tools_sup.erl b/lib/runtime_tools/src/runtime_tools_sup.erl
index 1a872c355d..4fcb2292d0 100644
--- a/lib/runtime_tools/src/runtime_tools_sup.erl
+++ b/lib/runtime_tools/src/runtime_tools_sup.erl
@@ -38,6 +38,8 @@
init(AutoModArgs) ->
Flags = {one_for_one, 0, 3600},
Children = [{inviso_rt, {inviso_rt, start_link_auto, [AutoModArgs]},
- temporary, 3000, worker, [inviso_rt]}],
+ temporary, 3000, worker, [inviso_rt]},
+ {ttb_autostart, {ttb_autostart, start_link, []},
+ temporary, 3000, worker, [ttb_autostart]}],
{ok, {Flags, Children}}.
%% -----------------------------------------------------------------------------
diff --git a/lib/runtime_tools/src/ttb_autostart.erl b/lib/runtime_tools/src/ttb_autostart.erl
new file mode 100644
index 0000000000..4c6971c119
--- /dev/null
+++ b/lib/runtime_tools/src/ttb_autostart.erl
@@ -0,0 +1,55 @@
+%%%-------------------------------------------------------------------
+%%% File : ttb_autostart.erl
+%%% Author : BartÅ‚omiej PuzoÅ„ <[email protected]>
+%%% Description : This supervisor is used to resume ttb tracing
+%%% Users are able to provide custom restart modules for *_config, as
+%%% file:write/read/delete may not be possible on diskless nodes.
+%%%
+%%% Created : 31 Jul 2010 by <[email protected]>
+%%%-------------------------------------------------------------------
+-module(ttb_autostart).
+
+-behaviour(gen_server).
+
+%% API
+-export([start_link/0,
+ read_config/0,
+ write_config/1,
+ delete_config/0]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+-define(DEF_AUTOSTART_MODULE, ?MODULE).
+-define(AUTOSTART_FILENAME, "ttb_autostart.bin").
+
+start_link() ->
+ gen_server:start_link(?MODULE, no_args, []).
+
+delete_config() ->
+ file:delete(?AUTOSTART_FILENAME).
+
+read_config() ->
+ case file:read_file(?AUTOSTART_FILENAME) of
+ {ok, Data} -> {ok, binary_to_term(Data)};
+ Error -> Error
+ end.
+
+write_config(Data) ->
+ file:write_file(?AUTOSTART_FILENAME, term_to_binary(Data)).
+
+init(no_args) ->
+ case application:get_env(runtime_tools, ttb_autostart_module) of
+ {ok, _} -> ok;
+ undefined -> application:set_env(runtime_tools, ttb_autostart_module, ?DEF_AUTOSTART_MODULE)
+ end,
+ observer_backend:ttb_resume_trace(),
+ %%As the process is not needed any more, it will shut itself down
+ {ok, no_args, 10000}.
+
+handle_call(_,_,_) -> {noreply, no_args}.
+handle_cast(_,_) -> {noreply, no_args}.
+handle_info(timeout,_) -> {stop, normal, no_args}.
+terminate(_,_) -> ok.
+code_change(_,_,_) -> {ok, no_args}.
diff --git a/lib/runtime_tools/test/inviso_SUITE.erl b/lib/runtime_tools/test/inviso_SUITE.erl
index 3ae8d34dd6..758867cf45 100644
--- a/lib/runtime_tools/test/inviso_SUITE.erl
+++ b/lib/runtime_tools/test/inviso_SUITE.erl
@@ -1380,9 +1380,10 @@ fetch_log_dist_trace_2(Config) ->
io:format("~p~n",[NodeResults]),
CheckFun=fun({N,{complete,[{trace_log,FileResults1},{ti_log,[{ok,TiFile}]}]}}) ->
Fun2=fun({ok,File}) ->
- {match,1,_}=
- regexp:first_match(File,
- "^"++"p1"++Name++atom_to_list(N)),
+ match=
+ re:run(File,
+ "^"++"p1"++Name++atom_to_list(N),
+ [{capture,none}]),
true;
(_) ->
false
@@ -1425,8 +1426,8 @@ fetch_log_dist_trace_3(Config) ->
CheckFun=fun({N,{ok,[{trace_log,PrivDir2,[F1,F2]},{ti_log,PrivDir2,[F3]}]}})->
PrivDir2=PrivDir,
RegExp="^"++Name++atom_to_list(N)++"[0-9]+"++"\.log",
- {match,1,_}=regexp:first_match(F1,RegExp),
- {match,1,_}=regexp:first_match(F2,RegExp),
+ match=re:run(F1,RegExp,[{capture,none}]),
+ match=re:run(F2,RegExp,[{capture,none}]),
F3=Name++"_ti_"++atom_to_list(N)++".ti",
true;
(_) ->
@@ -1439,9 +1440,10 @@ fetch_log_dist_trace_3(Config) ->
io:format("~p~n",[NodeResults2]),
CheckFun2=fun({N,{complete,[{trace_log,FileResults1},{ti_log,[{ok,TiFile}]}]}}) ->
Fun2=fun({ok,File}) ->
- {match,1,_}=
- regexp:first_match(File,
- "^"++"p1"++Name++atom_to_list(N)),
+ match=
+ re:run(File,
+ "^"++"p1"++Name++atom_to_list(N),
+ [{capture,none}]),
true;
(_) ->
false
@@ -2649,8 +2651,8 @@ check_on_nodes([],_,_,_,_) ->
how_many_files_regexp([],_,N) ->
{ok,N};
how_many_files_regexp([FName|Rest],RegExp,N) ->
- case regexp:first_match(FName,RegExp) of
- {match,1,_} ->
+ case re:run(FName,RegExp,[{capture,none}]) of
+ match ->
how_many_files_regexp(Rest,RegExp,N+1);
nomatch ->
how_many_files_regexp(Rest,RegExp,N);
diff --git a/lib/runtime_tools/vsn.mk b/lib/runtime_tools/vsn.mk
index 6ed98f697e..0bcd261861 100644
--- a/lib/runtime_tools/vsn.mk
+++ b/lib/runtime_tools/vsn.mk
@@ -1 +1 @@
-RUNTIME_TOOLS_VSN = 1.8.5
+RUNTIME_TOOLS_VSN = 1.8.6
diff --git a/lib/sasl/doc/src/make.dep b/lib/sasl/doc/src/make.dep
deleted file mode 100644
index 4843b7934a..0000000000
--- a/lib/sasl/doc/src/make.dep
+++ /dev/null
@@ -1,22 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: alarm_handler.tex appup.tex book.tex error_logging.tex \
- overload.tex part.tex rb.tex ref_man.tex rel.tex \
- release_handler.tex relup.tex sasl_app.tex \
- sasl_intro.tex script.tex systools.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/sasl/doc/src/notes.xml b/lib/sasl/doc/src/notes.xml
index d4460d47b4..01cdc4b29e 100644
--- a/lib/sasl/doc/src/notes.xml
+++ b/lib/sasl/doc/src/notes.xml
@@ -30,6 +30,104 @@
</header>
<p>This document describes the changes made to the SASL application.</p>
+<section><title>SASL 2.1.10</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The release_handler functionality on windows services was
+ broken. This has been corrected.</p>
+ <p>
+ Own Id: OTP-9306</p>
+ </item>
+ <item>
+ <p>
+ If a new version of an application did not include any
+ erlang module changes, the code path of the application
+ was not updated by the release_handler unless a
+ 'load_object_code' instruction was added for the
+ application. This would be a problem if e.g. only some
+ files in the priv dir were changed since calls to
+ code:lib_dir or code:priv_dir would then point to the old
+ location of the application. This has been corrected -
+ now code:replace_path/2 will be called for all
+ applications that are changed (i.e. when the
+ application's vsn is changed in the .rel file).</p>
+ <p>
+ Own Id: OTP-9402</p>
+ </item>
+ <item>
+ <p>
+ The appup instruction 'delete_module' would cause a crash
+ during upgrade if the module to be deleted was not
+ loaded. This has been corrected.</p>
+ <p>
+ Own Id: OTP-9417</p>
+ </item>
+ <item>
+ <p>
+ If a path was given as ONLY 'ebin' and not for example
+ './ebin', then systools:make_tar would fail with a
+ <c>function_clause</c> exception in filename:join/1. This
+ has been corrected. (Thanks to Nikola Skoric for
+ reporting).</p>
+ <p>
+ Own Id: OTP-9507</p>
+ </item>
+ <item>
+ <p>
+ Implement or fix -Werror option</p>
+ <p>
+ If -Werror is enabled and there are warnings no output
+ file is written. Also make sure that error/warning
+ reporting is consistent. (Thanks to Tuncer Ayaz)</p>
+ <p>
+ Own Id: OTP-9536</p>
+ </item>
+ <item>
+ <p>
+ Improved error information for timeouts during
+ release_handler:install_release.</p>
+ <p>
+ This patch addresses two cases where a timeout will occur
+ during upgrade. 1) if a supervisor is suspended (call to
+ get children from supervisor will hang) 2) if the child
+ spec for a supervisor incorrectly states that it is a
+ worker with a dynamic set of modules (call to get modules
+ from gen_event will hang)</p>
+ <p>
+ An error report will now be printed, and the return value
+ of release_handler:install_release will indicate what
+ happened. (Thanks to joe williams)</p>
+ <p>
+ Own Id: OTP-9546</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ <c>release_handler:install_release</c> could be very slow
+ when there are many processes in the system. Some
+ optimization work has been done both in erts and in the
+ release handler in order to improve this. </p>
+ <p>
+ A new option, <c>purge</c>, is added to
+ <c>release_handler:check_install_release</c> which can be
+ called first in order to speed up the execution of
+ <c>release_handler:install_release</c>.</p>
+ <p>
+ Own Id: OTP-9395</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SASL 2.1.9.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/sasl/doc/src/release_handler.xml b/lib/sasl/doc/src/release_handler.xml
index 4a973bc5ed..5ac0dc1acc 100644
--- a/lib/sasl/doc/src/release_handler.xml
+++ b/lib/sasl/doc/src/release_handler.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -159,9 +159,12 @@ old reboot_old permanent
<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>
<type>
<v>Vsn = OtherVsn = string()</v>
+ <v>Opts = [Opt]</v>
+ <v>Opt = purge</v>
<v>Descr = term()</v>
<v>Reason = term()</v>
</type>
@@ -179,6 +182,11 @@ old reboot_old permanent
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
+ reduce the time needed by <seealso
+ marker="#install_release/1">install_release</seealso>.</p>
</desc>
</func>
<func>
@@ -299,6 +307,24 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
<c>{update_paths,true}</c>, afterwards
<c>code:lib_dir(myapp)</c> will return
<c>/home/user/myapp-1.0</c>.</p>
+ <note>
+ <p>Installing a new release might be quite 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
+ 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
+ checks.</p>
+ <p>Obviously, this will not reduce the overall time for the
+ upgrade, but it will allow checks and purge to be executed
+ in the background before the real upgrade is started.</p>
+ </note>
</desc>
</func>
<func>
diff --git a/lib/sasl/doc/src/systools.xml b/lib/sasl/doc/src/systools.xml
index 883c9c372b..8c1c327d74 100644
--- a/lib/sasl/doc/src/systools.xml
+++ b/lib/sasl/doc/src/systools.xml
@@ -45,7 +45,8 @@
<v>Name = string()</v>
<v>UpFrom = DownTo = [Name | {Name,Descr}]</v>
<v>&nbsp;Descr = term()</v>
- <v>Opt = {path,[Dir]} | restart_emulator | silent | noexec | {outdir,Dir}</v>
+ <v>Opt = {path,[Dir]} | restart_emulator | silent | noexec | {outdir,Dir}
+ | 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>
@@ -122,6 +123,8 @@
<p>If the option <c>noexec</c> is provided, 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>
</desc>
</func>
<func>
@@ -130,7 +133,8 @@
<fsummary>Generate a boot script <c>.script/.boot</c>.</fsummary>
<type>
<v>Name = string()</v>
- <v>Opt = src_tests | {path,[Dir]} | local | {variables,[Var]} | exref | {exref,[App]}] | silent | {outdir,Dir}</v>
+ <v>Opt = src_tests | {path,[Dir]} | local | {variables,[Var]} | exref | {exref,[App]}]
+ | silent | {outdir,Dir} | warnings_as_errors</v>
<v>&nbsp;Dir = string()</v>
<v>&nbsp;Var = {VarName,Prefix}</v>
<v>&nbsp;&nbsp;VarName = Prefix = string()</v>
@@ -232,6 +236,8 @@
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>
</desc>
</func>
<func>
diff --git a/lib/sasl/examples/src/Makefile b/lib/sasl/examples/src/Makefile
index 4a4e04a536..9cf0d4c25d 100644
--- a/lib/sasl/examples/src/Makefile
+++ b/lib/sasl/examples/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010. All Rights Reserved.
+# Copyright Ericsson AB 2010-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -66,7 +66,7 @@ release_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)/examples/src
$(INSTALL_DIR) $(RELSYSDIR)/examples/ebin
(cd ..; tar cf - src ebin | (cd $(RELSYSDIR)/examples; tar xf -))
- chmod -f -R ug+w $(RELSYSDIR)/examples
+ chmod -R ug+w $(RELSYSDIR)/examples
release_docs_spec:
diff --git a/lib/sasl/src/erlsrv.erl b/lib/sasl/src/erlsrv.erl
index f9804c41dc..086dc7c651 100644
--- a/lib/sasl/src/erlsrv.erl
+++ b/lib/sasl/src/erlsrv.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -75,14 +75,21 @@ write_all_data(Port,[H|T]) ->
write_all_data(Port,T).
read_all_data(Port) ->
+ lists:reverse(read_all_data(Port,[],[])).
+read_all_data(Port,Line,Lines) ->
receive
+ {Port, {data, {noeol,Data}}} ->
+ read_all_data(Port,Line++Data,Lines);
{Port, {data, {eol,Data}}} ->
- [ Data | read_all_data(Port)];
- _ ->
+ read_all_data(Port,[],[Line++Data|Lines]);
+ {Port,_Other} ->
Port ! {self(), close},
receive
{Port, closed} ->
- []
+ case Line of
+ [] -> Lines;
+ _ -> [Line|Lines]
+ end
end
end.
@@ -208,7 +215,7 @@ store_service(EmulatorVersion,Service) ->
false ->
{error, no_servicename};
{value, {_,Name}} ->
- {Action,Service1} = case get_service(Name) of
+ {Action,Service1} = case get_service(EmulatorVersion,Name) of
{error, no_such_service} ->
{"add",Service};
_ ->
@@ -377,8 +384,14 @@ pick_argument(_,[],Acc) ->
{Acc, ""};
pick_argument(normal,[$ |T],Acc) ->
{Acc,T};
+pick_argument(normal,[$\\|T],Acc) ->
+ pick_argument(normal_escaped,T,[$\\|Acc]);
pick_argument(normal,[$"|T],Acc) ->
pick_argument(quoted,T,[$"|Acc]);
+pick_argument(normal_escaped,[$"|T],Acc) ->
+ pick_argument(bquoted,T,[$"|Acc]);
+pick_argument(normal_escaped,[A|T],Acc) ->
+ pick_argument(normal,T,[A|Acc]);
pick_argument(quoted_escaped,[H|T],Acc) ->
pick_argument(quoted,T,[H|Acc]);
pick_argument(quoted,[$"|T],Acc) ->
@@ -387,6 +400,14 @@ pick_argument(quoted,[$\\|T],Acc) ->
pick_argument(quoted_escaped,T,[$\\|Acc]);
pick_argument(quoted,[H|T],Acc) ->
pick_argument(quoted,T,[H|Acc]);
+pick_argument(bquoted_escaped,[$"|T],Acc) ->
+ pick_argument(normal,T,[$"|Acc]);
+pick_argument(bquoted_escaped,[H|T],Acc) ->
+ pick_argument(bquoted,T,[H|Acc]);
+pick_argument(bquoted,[$\\|T],Acc) ->
+ pick_argument(bquoted_escaped,T,[$\\|Acc]);
+pick_argument(bquoted,[H|T],Acc) ->
+ pick_argument(bquoted,T,[H|Acc]);
pick_argument(normal,[H|T],Acc) ->
pick_argument(normal,T,[H|Acc]).
diff --git a/lib/sasl/src/release_handler.erl b/lib/sasl/src/release_handler.erl
index b60aa847df..bc08f94dff 100644
--- a/lib/sasl/src/release_handler.erl
+++ b/lib/sasl/src/release_handler.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -25,8 +25,8 @@
-export([start_link/0,
create_RELEASES/1, create_RELEASES/2, create_RELEASES/4,
unpack_release/1,
- check_install_release/1, install_release/1, install_release/2,
- remove_release/1,
+ check_install_release/1, check_install_release/2,
+ install_release/1, install_release/2, remove_release/1,
which_releases/0, make_permanent/1, reboot_old_release/1,
set_unpacked/2, set_removed/1, install_file/2]).
-export([upgrade_app/2, downgrade_app/2, downgrade_app/3,
@@ -149,15 +149,35 @@ unpack_release(ReleaseName) ->
%%-----------------------------------------------------------------
%% Purpose: Checks the relup script for the specified version.
%% The release must be unpacked.
+%% Options = [purge] - all old code that can be soft purged
+%% will be purged if all checks succeeds. This can be usefull
+%% in order to reduce time needed in the following call to
+%% install_release.
%% Returns: {ok, FromVsn, Descr} | {error, Reason}
-%% Reason = {already_installed, Vsn} |
+%% Reason = {illegal_option, IllegalOpt} |
+%% {already_installed, Vsn} |
%% {bad_relup_file, RelFile} |
%% {no_such_release, Vsn} |
%% {no_such_from_vsn, Vsn} |
%% exit_reason()
%%-----------------------------------------------------------------
check_install_release(Vsn) ->
- call({check_install_release, Vsn}).
+ check_install_release(Vsn, []).
+
+check_install_release(Vsn, Opts) ->
+ case check_check_install_options(Opts, false) of
+ {ok,Purge} ->
+ call({check_install_release, Vsn, Purge});
+ Error ->
+ Error
+ end.
+
+check_check_install_options([purge|Opts], _) ->
+ check_check_install_options(Opts, true);
+check_check_install_options([Illegal|_],_Purge) ->
+ {error,{illegal_option,Illegal}};
+check_check_install_options([],Purge) ->
+ {ok,Purge}.
%%-----------------------------------------------------------------
@@ -291,7 +311,8 @@ check_script(Script, LibDirs) ->
release_handler_1:check_script(Script, LibDirs).
%%-----------------------------------------------------------------
-%% eval_script(Script, Apps, LibDirs, Opts) -> {ok, UnPurged} |
+%% eval_script(Script, Apps, LibDirs, NewLibs, Opts) ->
+%% {ok, UnPurged} |
%% restart_new_emulator |
%% {error, Error}
%% {'EXIT', Reason}
@@ -299,9 +320,13 @@ check_script(Script, LibDirs) ->
%% net_kernel:monitor_nodes(true) before calling this function.
%% No! No other process than the release_handler can ever call this
%% function, if sync_nodes is used.
-%%-----------------------------------------------------------------
-eval_script(Script, Apps, LibDirs, Opts) ->
- catch release_handler_1:eval_script(Script, Apps, LibDirs, Opts).
+%%
+%% LibDirs is a list of all applications, while NewLibs is a list of
+%% applications that have changed version between the current and the
+%% new release.
+%% -----------------------------------------------------------------
+eval_script(Script, Apps, LibDirs, NewLibs, Opts) ->
+ catch release_handler_1:eval_script(Script, Apps, LibDirs, NewLibs, Opts).
%%-----------------------------------------------------------------
%% Func: create_RELEASES(Root, RelFile, LibDirs) -> ok | {error, Reason}
@@ -405,6 +430,7 @@ eval_appup_script(App, ToVsn, ToDir, Script) ->
Res = release_handler_1:eval_script(Script,
[], % [AppSpec]
[{App, ToVsn, ToDir}],
+ [{App, ToVsn, ToDir}],
[]), % [Opt]
case Res of
{ok, _Unpurged} ->
@@ -535,11 +561,12 @@ handle_call({unpack_release, ReleaseName}, _From, S)
handle_call({unpack_release, _ReleaseName}, _From, S) ->
{reply, {error, client_node}, S};
-handle_call({check_install_release, Vsn}, _From, S) ->
+handle_call({check_install_release, Vsn, Purge}, _From, S) ->
case catch do_check_install_release(S#state.rel_dir,
Vsn,
S#state.releases,
- S#state.masters) of
+ S#state.masters,
+ Purge) of
{ok, CurrentVsn, Descr} ->
{reply, {ok, CurrentVsn, Descr}, S};
{error, Reason} ->
@@ -849,7 +876,7 @@ check_path_response(Path, {ok, _Info}) ->
check_path_response(Path, {error, _Reason}) ->
throw({error, {no_such_directory, Path}}).
-do_check_install_release(RelDir, Vsn, Releases, Masters) ->
+do_check_install_release(RelDir, Vsn, Releases, Masters, Purge) ->
case lists:keysearch(Vsn, #release.vsn, Releases) of
{value, #release{status = current}} ->
{error, {already_installed, Vsn}};
@@ -874,7 +901,20 @@ do_check_install_release(RelDir, Vsn, Releases, Masters) ->
case get_rh_script(LatestRelease, Release, RelDir, Masters) of
{ok, {CurrentVsn, Descr, Script}} ->
case catch check_script(Script, Libs) of
- ok ->
+ {ok,SoftPurgeMods} when Purge=:=true ->
+ %% Get modules with brutal_purge
+ %% instructions, but that can be
+ %% soft purged
+ {ok,BrutalPurgeMods} =
+ release_handler_1:check_old_processes(
+ Script,brutal_purge),
+ lists:foreach(
+ fun(Mod) ->
+ catch erlang:purge_module(Mod)
+ end,
+ SoftPurgeMods ++ BrutalPurgeMods),
+ {ok, CurrentVsn, Descr};
+ {ok,_} ->
{ok, CurrentVsn, Descr};
Else ->
Else
@@ -890,6 +930,7 @@ do_check_install_release(RelDir, Vsn, Releases, Masters) ->
end.
do_install_release(#state{start_prg = StartPrg,
+ root = RootDir,
rel_dir = RelDir, releases = Releases,
masters = Masters,
static_emulator = Static},
@@ -905,7 +946,9 @@ do_install_release(#state{start_prg = StartPrg,
EnvBefore = application_controller:prep_config_change(),
Apps = change_appl_data(RelDir, Release, Masters),
LibDirs = Release#release.libs,
- case eval_script(Script, Apps, LibDirs, Opts) of
+ NewLibs = get_new_libs(LatestRelease#release.libs,
+ Release#release.libs),
+ case eval_script(Script, Apps, LibDirs, NewLibs, Opts) of
{ok, []} ->
application_controller:config_change(EnvBefore),
mon_nodes(false),
@@ -926,8 +969,8 @@ do_install_release(#state{start_prg = StartPrg,
NReleases = set_status(Vsn, current, Releases),
NReleases2 = set_status(Vsn,tmp_current,NReleases),
write_releases(RelDir, NReleases2, Masters),
- prepare_restart_new_emulator(StartPrg, RelDir,
- Release,
+ prepare_restart_new_emulator(StartPrg, RootDir,
+ RelDir, Release,
PermanentRelease,
Masters),
{restart_new_emulator, CurrentVsn, Descr};
@@ -997,7 +1040,7 @@ do_make_services_permanent(PermanentVsn,Vsn, PermanentEVsn, EVsn) ->
throw(Error4)
end
end.
-
+
do_make_permanent(#state{releases = Releases,
rel_dir = RelDir, unpurged = Unpurged,
masters = Masters,
@@ -1409,8 +1452,8 @@ prepare_restart_nt(#release{erts_vsn = EVsn, vsn = Vsn},
FutureServiceName = hd(string:tokens(atom_to_list(node()),"@"))
++ "_" ++ Vsn,
CurrentService = case erlsrv:get_service(PermEVsn,CurrentServiceName) of
- {error, Reason} ->
- throw({error, Reason});
+ {error, _} = Error1 ->
+ throw(Error1);
CS ->
CS
end,
@@ -1425,37 +1468,33 @@ prepare_restart_nt(#release{erts_vsn = EVsn, vsn = Vsn},
CurrentServiceName),
case erlsrv:store_service(EVsn, FutureService) of
- {error, Rison} ->
- throw({error,Rison});
- _ ->
+ {error, _} = Error2 ->
+ throw(Error2);
+ _X ->
erlsrv:disable_service(EVsn, FutureServiceName),
ErlSrv = filename:nativename(erlsrv:erlsrv(EVsn)),
- case heart:set_cmd(ErlSrv ++ " enable " ++ FutureServiceName ++
- " & " ++ ErlSrv ++ " start " ++
- FutureServiceName ++
- " & " ++ ErlSrv ++ " disable " ++
- FutureServiceName) of
+ StartDisabled = ErlSrv ++ " start_disabled " ++ FutureServiceName,
+ case heart:set_cmd(StartDisabled) of
ok ->
ok;
- Error ->
- throw({error, {'heart:set_cmd() error', Error}})
+ Error3 ->
+ throw({error, {'heart:set_cmd() error', Error3}})
end
end.
-
%%-----------------------------------------------------------------
%% Set things up for restarting the new emulator. The actual
%% restart is performed by calling init:reboot() higher up.
%%-----------------------------------------------------------------
-prepare_restart_new_emulator(StartPrg, RelDir,
- Release, PRelease,
- Masters) ->
+prepare_restart_new_emulator(StartPrg, RootDir, RelDir,
+ Release, PRelease, Masters) ->
#release{erts_vsn = EVsn, vsn = Vsn} = Release,
Data = EVsn ++ " " ++ Vsn,
DataFile = write_new_start_erl(Data, RelDir, Masters),
%% Tell heart to use DataFile instead of start_erl.data
case os:type() of
{win32,nt} ->
+ write_ini_file(RootDir,EVsn,Masters),
prepare_restart_nt(Release,PRelease,DataFile);
{unix,_} ->
StartP = check_start_prg(StartPrg, Masters),
@@ -1832,50 +1871,10 @@ write_start(File, Data, false) ->
end;
write_start(File, Data, Masters) ->
all_masters(Masters),
- write_start_m(File, Data, Masters).
+ safe_write_file_m(File, Data, Masters).
%%-----------------------------------------------------------------
-%% Write the "start_erl.data" file at all master nodes.
-%% 1. Save "start_erl.backup" at all nodes.
-%% 2. Write the "start_erl.change" file at all nodes.
-%% 3. Move "start_erl.change" to "start_erl.data".
-%% 4. Remove "start_erl.backup" at all nodes.
-%%
-%% If one of the steps above fails, all steps is recovered from
-%% (as long as possible), except for 4 which is allowed to fail.
-%%-----------------------------------------------------------------
-write_start_m(File, Data, Masters) ->
- Dir = filename:dirname(File),
- Backup = filename:join(Dir, "start_erl.backup"),
- Change = filename:join(Dir, "start_erl.change"),
- case at_all_masters(Masters, ?MODULE, do_copy_files,
- [File, [Backup]]) of
- ok ->
- case at_all_masters(Masters, ?MODULE, do_write_file,
- [Change, Data]) of
- ok ->
- case at_all_masters(Masters, file, rename,
- [Change, File]) of
- ok ->
- remove_files(all, [Backup, Change], Masters),
- ok;
- {error, {Master, R}} ->
- takewhile(Master, Masters, file, rename,
- [Backup, File]),
- remove_files(all, [Backup, Change], Masters),
- throw({error, {Master, R, move_start_erl}})
- end;
- {error, {Master, R}} ->
- remove_files(all, [Backup, Change], Masters),
- throw({error, {Master, R, write_start_erl}})
- end;
- {error, {Master, R}} ->
- remove_files(Master, [Backup], Masters),
- throw({error, {Master, R, backup_start_erl}})
- end.
-
-%%-----------------------------------------------------------------
%% Copy the "start.boot" and "sys.config" from SrcDir to DestDir at all
%% master nodes.
%% 1. Save DestDir/"start.backup" and DestDir/"sys.backup" at all nodes.
@@ -1917,3 +1916,97 @@ set_static_files(SrcDir, DestDir, Masters) ->
remove_files(Master, [BackupBoot, BackupConf], Masters),
throw({error, {Master, R, backup_start_config}})
end.
+
+%%-----------------------------------------------------------------
+%% Write erl.ini
+%% Writes the erl.ini file used by erl.exe when (re)starting the erlang node.
+%% At first installation, this is done by Install.exe, which means that if
+%% the format of this file for some reason is changed, then Install.c must
+%% also be updated (and probably some other c-files which read erl.ini)
+%%-----------------------------------------------------------------
+write_ini_file(RootDir,EVsn,Masters) ->
+ BinDir = filename:join([RootDir,"erts-"++EVsn,"bin"]),
+ Str0 = io_lib:format("[erlang]~n"
+ "Bindir=~s~n"
+ "Progname=erl~n"
+ "Rootdir=~s~n",
+ [filename:nativename(BinDir),
+ filename:nativename(RootDir)]),
+ Str = re:replace(Str0,"\\\\","\\\\\\\\",[{return,list},global]),
+ IniFile = filename:join(BinDir,"erl.ini"),
+ do_write_ini_file(IniFile,Str,Masters).
+
+do_write_ini_file(File,Data,false) ->
+ case do_write_file(File, Data) of
+ ok -> ok;
+ Error -> throw(Error)
+ end;
+do_write_ini_file(File,Data,Masters) ->
+ all_masters(Masters),
+ safe_write_file_m(File, Data, Masters).
+
+
+%%-----------------------------------------------------------------
+%% Write the given file at all master nodes.
+%% 1. Save <File>.backup at all nodes.
+%% 2. Write <File>.change at all nodes.
+%% 3. Move <File>.change to <File>
+%% 4. Remove <File>.backup at all nodes.
+%%
+%% If one of the steps above fails, all steps are recovered from
+%% (as long as possible), except for 4 which is allowed to fail.
+%%-----------------------------------------------------------------
+safe_write_file_m(File, Data, Masters) ->
+ Backup = File ++ ".backup",
+ Change = File ++ ".change",
+ case at_all_masters(Masters, ?MODULE, do_copy_files,
+ [File, [Backup]]) of
+ ok ->
+ case at_all_masters(Masters, ?MODULE, do_write_file,
+ [Change, Data]) of
+ ok ->
+ case at_all_masters(Masters, file, rename,
+ [Change, File]) of
+ ok ->
+ remove_files(all, [Backup, Change], Masters),
+ ok;
+ {error, {Master, R}} ->
+ takewhile(Master, Masters, file, rename,
+ [Backup, File]),
+ remove_files(all, [Backup, Change], Masters),
+ throw({error, {Master, R, rename,
+ filename:basename(Change),
+ filename:basename(File)}})
+ end;
+ {error, {Master, R}} ->
+ remove_files(all, [Backup, Change], Masters),
+ throw({error, {Master, R, write, filename:basename(Change)}})
+ end;
+ {error, {Master, R}} ->
+ remove_files(Master, [Backup], Masters),
+ throw({error, {Master, R, backup,
+ filename:basename(File),
+ filename:basename(Backup)}})
+ end.
+
+%%-----------------------------------------------------------------
+%% Figure out which applications that have changed version between the
+%% two releases. The paths for these applications must always be
+%% updated, even if the relup script does not load any modules. See
+%% OTP-9402.
+%%
+%% A different situation is when the same application version is used
+%% in old and new release, but the path has changed. This is not
+%% handled here - instead it must be explicitely indicated by the
+%% 'update_paths' option to release_handler:install_release/2 if the
+%% code path shall be updated then.
+%% -----------------------------------------------------------------
+get_new_libs([{App,Vsn,_LibDir}|CurrentLibs], NewLibs) ->
+ case lists:keyfind(App,1,NewLibs) of
+ {App,NewVsn,_} = LibInfo when NewVsn =/= Vsn ->
+ [LibInfo | get_new_libs(CurrentLibs,NewLibs)];
+ _ ->
+ get_new_libs(CurrentLibs,NewLibs)
+ end;
+get_new_libs([],_) ->
+ [].
diff --git a/lib/sasl/src/release_handler_1.erl b/lib/sasl/src/release_handler_1.erl
index 8d050fb7b0..8d0baf3ab1 100644
--- a/lib/sasl/src/release_handler_1.erl
+++ b/lib/sasl/src/release_handler_1.erl
@@ -19,8 +19,9 @@
-module(release_handler_1).
%% External exports
--export([eval_script/3, eval_script/4, check_script/2]).
--export([get_current_vsn/1]). %% exported because used in a test case
+-export([eval_script/1, eval_script/5,
+ check_script/2, check_old_processes/2]).
+-export([get_current_vsn/1, get_supervised_procs/0]). %% exported because used in a test case
-record(eval_state, {bins = [], stopped = [], suspended = [], apps = [],
libdirs, unpurged = [], vsns = [], newlibs = [],
@@ -33,11 +34,11 @@
%% libdirs = [{Lib, LibVsn, LibDir}] - Maps Lib to Vsn and Directory
%% unpurged = [{Mod, soft_purge | brutal_purge}]
%% vsns = [{Mod, OldVsn, NewVsn}] - remember the old vsn of a mod
-%% before it is removed/a new vsn is loaded; the new vsn
+%% before a new vsn is loaded; the new vsn
%% is kept in case of a downgrade, where the code_change
%% function receives the vsn of the module to downgrade
%% *to*.
-%% newlibs = [{Lib, Dir}] - list of all new libs; used to change
+%% newlibs = [{Lib, LibVsn, LibDir}] - list of all new libs; used to change
%% the code path
%% opts = [{Tag, Value}] - list of options
%%-----------------------------------------------------------------
@@ -47,34 +48,39 @@
%%% This is a low-level release handler.
%%%-----------------------------------------------------------------
check_script(Script, LibDirs) ->
- case catch check_old_processes(Script) of
- ok ->
+ case catch check_old_processes(Script,soft_purge) of
+ {ok, PurgeMods} ->
{Before, _After} = split_instructions(Script),
case catch lists:foldl(fun(Instruction, EvalState1) ->
eval(Instruction, EvalState1)
end,
#eval_state{libdirs = LibDirs},
Before) of
- EvalState2 when is_record(EvalState2, eval_state) -> ok;
- {error, Error} -> {error, Error};
- Other -> {error, Other}
+ EvalState2 when is_record(EvalState2, eval_state) ->
+ {ok,PurgeMods};
+ {error, Error} ->
+ {error, Error};
+ Other ->
+ {error, Other}
end;
{error, Mod} ->
{error, {old_processes, Mod}}
end.
-eval_script(Script, Apps, LibDirs) ->
- eval_script(Script, Apps, LibDirs, []).
+%% eval_script/1 - For testing only - no apps added, just testing instructions
+eval_script(Script) ->
+ eval_script(Script, [], [], [], []).
-eval_script(Script, Apps, LibDirs, Opts) ->
- case catch check_old_processes(Script) of
- ok ->
+eval_script(Script, Apps, LibDirs, NewLibs, Opts) ->
+ case catch check_old_processes(Script,soft_purge) of
+ {ok,_} ->
{Before, After} = split_instructions(Script),
case catch lists:foldl(fun(Instruction, EvalState1) ->
eval(Instruction, EvalState1)
end,
#eval_state{apps = Apps,
libdirs = LibDirs,
+ newlibs = NewLibs,
opts = Opts},
Before) of
EvalState2 when is_record(EvalState2, eval_state) ->
@@ -110,32 +116,63 @@ split_instructions([], Before) ->
{[], lists:reverse(Before)}.
%%-----------------------------------------------------------------
-%% Func: check_old_processes/1
+%% Func: check_old_processes/2
%% Args: Script = [instruction()]
+%% PrePurgeMethod = soft_purge | brutal_purge
%% Purpose: Check if there is any process that runs an old version
-%% of a module that should be soft_purged, (i.e. not purged
-%% at all if there is any such process). Returns {error, Mod}
-%% if so, ok otherwise.
-%% Returns: ok | {error, Mod}
+%% of a module that should be purged according to PrePurgeMethod.
+%% Returns a list of modules that can be soft_purged.
+%%
+%% If PrePurgeMethod == soft_purge, the function will succeed
+%% only if there is no process running old code of any of the
+%% modules. Else it will throw {error,Mod}, where Mod is the
+%% first module found that can not be soft_purged.
+%%
+%% If PrePurgeMethod == brutal_purge, the function will
+%% always succeed and return a list of all modules that are
+%% specified in the script with PrePurgeMethod brutal_purge,
+%% but that can be soft_purged.
+%%
+%% Returns: {ok,PurgeMods} | {error, Mod}
+%% PurgeMods = [Mod]
%% Mod = atom()
%%-----------------------------------------------------------------
-check_old_processes(Script) ->
- lists:foreach(fun({load, {Mod, soft_purge, _PostPurgeMethod}}) ->
- check_old_code(Mod);
- ({remove, {Mod, soft_purge, _PostPurgeMethod}}) ->
- check_old_code(Mod);
- (_) -> ok
- end,
- Script).
+check_old_processes(Script,PrePurgeMethod) ->
+ Procs = erlang:processes(),
+ {ok,lists:flatmap(
+ fun({load, {Mod, PPM, _PostPurgeMethod}}) when PPM==PrePurgeMethod ->
+ check_old_code(Mod,Procs,PrePurgeMethod);
+ ({remove, {Mod, PPM, _PostPurgeMethod}}) when PPM==PrePurgeMethod ->
+ check_old_code(Mod,Procs,PrePurgeMethod);
+ (_) -> []
+ end,
+ Script)}.
+
+check_old_code(Mod,Procs,PrePurgeMethod) ->
+ case erlang:check_old_code(Mod) of
+ true when PrePurgeMethod==soft_purge ->
+ do_check_old_code(Mod,Procs);
+ true when PrePurgeMethod==brutal_purge ->
+ case catch do_check_old_code(Mod,Procs) of
+ {error,Mod} -> [];
+ R -> R
+ end;
+ false ->
+ []
+ end.
+
+
+do_check_old_code(Mod,Procs) ->
+ lists:foreach(
+ fun(Pid) ->
+ case erlang:check_process_code(Pid, Mod) of
+ false -> ok;
+ true -> throw({error, Mod})
+ end
+ end,
+ Procs),
+ [Mod].
-check_old_code(Mod) ->
- lists:foreach(fun(Pid) ->
- case erlang:check_process_code(Pid, Mod) of
- false -> ok;
- true -> throw({error, Mod})
- end
- end,
- erlang:processes()).
%%-----------------------------------------------------------------
%% An unpurged module is a module for which there exist an old
@@ -214,16 +251,15 @@ check_old_code(Mod) ->
%%-----------------------------------------------------------------
eval({load_object_code, {Lib, LibVsn, Modules}}, EvalState) ->
case lists:keysearch(Lib, 1, EvalState#eval_state.libdirs) of
- {value, {Lib, LibVsn, LibDir}} ->
- Ebin = filename:join(LibDir, "ebin"),
+ {value, {Lib, LibVsn, LibDir} = LibInfo} ->
Ext = code:objfile_extension(),
{NewBins, NewVsns} =
lists:foldl(fun(Mod, {Bins, Vsns}) ->
File = lists:concat([Mod, Ext]),
- FName = filename:join(Ebin, File),
+ FName = filename:join([LibDir, "ebin", File]),
case erl_prim_loader:get_file(FName) of
{ok, Bin, FName2} ->
- NVsns = add_new_vsn(Mod, Bin, Vsns),
+ NVsns = add_vsns(Mod, Bin, Vsns),
{[{Mod, Bin, FName2} | Bins],NVsns};
error ->
throw({error, {no_such_file,FName}})
@@ -232,7 +268,7 @@ eval({load_object_code, {Lib, LibVsn, Modules}}, EvalState) ->
{EvalState#eval_state.bins,
EvalState#eval_state.vsns},
Modules),
- NewLibs = [{Lib, Ebin} | EvalState#eval_state.newlibs],
+ NewLibs = lists:keystore(Lib,1,EvalState#eval_state.newlibs,LibInfo),
EvalState#eval_state{bins = NewBins,
newlibs = NewLibs,
vsns = NewVsns};
@@ -242,15 +278,14 @@ eval({load_object_code, {Lib, LibVsn, Modules}}, EvalState) ->
eval(point_of_no_return, EvalState) ->
Libs = case get_opt(update_paths, EvalState, false) of
false ->
- EvalState#eval_state.newlibs; % [{Lib, Path}]
+ EvalState#eval_state.newlibs;
true ->
- lists:map(fun({Lib, _LibVsn, LibDir}) ->
- Ebin= filename:join(LibDir,"ebin"),
- {Lib, Ebin}
- end,
- EvalState#eval_state.libdirs)
+ EvalState#eval_state.libdirs
end,
- lists:foreach(fun({Lib, Path}) -> code:replace_path(Lib, Path) end,
+ lists:foreach(fun({Lib, _LibVsn, LibDir}) ->
+ Ebin = filename:join(LibDir,"ebin"),
+ code:replace_path(Lib, Ebin)
+ end,
Libs),
EvalState;
eval({load, {Mod, _PrePurgeMethod, PostPurgeMethod}}, EvalState) ->
@@ -258,32 +293,21 @@ eval({load, {Mod, _PrePurgeMethod, PostPurgeMethod}}, EvalState) ->
{value, {_Mod, Bin, File}} = lists:keysearch(Mod, 1, Bins),
% load_binary kills all procs running old code
% if soft_purge, we know that there are no such procs now
- Vsns = EvalState#eval_state.vsns,
- NewVsns = add_old_vsn(Mod, Vsns),
code:load_binary(Mod, File, Bin),
% Now, the prev current is old. There might be procs
% running it. Find them.
Unpurged = do_soft_purge(Mod,PostPurgeMethod,EvalState#eval_state.unpurged),
EvalState#eval_state{bins = lists:keydelete(Mod, 1, Bins),
- unpurged = Unpurged,
- vsns = NewVsns};
+ unpurged = Unpurged};
eval({remove, {Mod, _PrePurgeMethod, PostPurgeMethod}}, EvalState) ->
- % purge kills all procs running old code
- % if soft_purge, we know that there are no such procs now
- Vsns = EvalState#eval_state.vsns,
- NewVsns = add_old_vsn(Mod, Vsns),
+ %% purge kills all procs running old code
+ %% if soft_purge, we know that there are no such procs now
code:purge(Mod),
code:delete(Mod),
- % Now, the prev current is old. There might be procs
- % running it. Find them.
- Unpurged =
- case code:soft_purge(Mod) of
- true -> EvalState#eval_state.unpurged;
- false -> [{Mod, PostPurgeMethod} | EvalState#eval_state.unpurged]
- end,
-%% Bins = EvalState#eval_state.bins,
-%% EvalState#eval_state{bins = lists:keydelete(Mod, 1, Bins),
- EvalState#eval_state{unpurged = Unpurged, vsns = NewVsns};
+ %% Now, the prev current is old. There might be procs
+ %% running it. Find them.
+ Unpurged = do_soft_purge(Mod,PostPurgeMethod,EvalState#eval_state.unpurged),
+ EvalState#eval_state{unpurged = Unpurged};
eval({purge, Modules}, EvalState) ->
% Now, if there are any processes still executing old code, OR
% if some new processes started after suspend but before load,
@@ -469,6 +493,19 @@ start(Procs) ->
%% supervisor module, we should load the new version, and then
%% delete the old. Then we should perform the start changes
%% manually, by adding/deleting children.
+%%
+%% Recent changes to this code cause the upgrade error out and
+%% log the case where a suspended supervisor has which_children
+%% called against it. This retains the behavior of causing a VM
+%% restart to the *old* version of a release but has the
+%% advantage of logging the pid and supervisor that had the
+%% issue.
+%%
+%% A second case where this can occur is if a child spec is
+%% incorrect and get_modules is called against a process that
+%% can't respond to the gen:call. Again an error is logged,
+%% an error returned and a VM restart is issued.
+%%
%% Returns: [{SuperPid, ChildName, ChildPid, Mods}]
%%-----------------------------------------------------------------
%% OTP-3452. For each application the first item contains the pid
@@ -478,49 +515,81 @@ start(Procs) ->
get_supervised_procs() ->
lists:foldl(
fun(Application, Procs) ->
- case application_controller:get_master(Application) of
- Pid when is_pid(Pid) ->
- {Root, _AppMod} = application_master:get_child(Pid),
- case get_supervisor_module(Root) of
- {ok, SupMod} ->
- get_procs(supervisor:which_children(Root),
- Root) ++
- [{undefined, undefined, Root, [SupMod]} |
- Procs];
- {error, _} ->
- error_logger:error_msg("release_handler: "
- "cannot find top "
- "supervisor for "
- "application ~w~n",
- [Application]),
- get_procs(supervisor:which_children(Root),
- Root) ++ Procs
- end;
- _ -> Procs
- end
+ get_master_procs(Application,
+ Procs,
+ application_controller:get_master(Application))
end,
[],
- lists:map(fun({Application, _Name, _Vsn}) ->
- Application
- end,
- application:which_applications())).
+ get_application_names()).
+
+get_supervised_procs(_, Root, Procs, {ok, SupMod}) ->
+ get_procs(maybe_supervisor_which_children(get_proc_state(Root), SupMod, Root), Root) ++
+ [{undefined, undefined, Root, [SupMod]} | Procs];
+get_supervised_procs(Application, Root, Procs, {error, _}) ->
+ error_logger:error_msg("release_handler: cannot find top supervisor for "
+ "application ~w~n", [Application]),
+ get_procs(maybe_supervisor_which_children(get_proc_state(Root), Application, Root), Root) ++ Procs.
+
+get_application_names() ->
+ lists:map(fun({Application, _Name, _Vsn}) ->
+ Application
+ end,
+ application:which_applications()).
+
+get_master_procs(Application, Procs, Pid) when is_pid(Pid) ->
+ {Root, _AppMod} = application_master:get_child(Pid),
+ get_supervised_procs(Application, Root, Procs, get_supervisor_module(Root));
+get_master_procs(_, Procs, _) ->
+ Procs.
get_procs([{Name, Pid, worker, dynamic} | T], Sup) when is_pid(Pid) ->
- Mods = get_dynamic_mods(Pid),
+ Mods = maybe_get_dynamic_mods(Name, Pid),
[{Sup, Name, Pid, Mods} | get_procs(T, Sup)];
get_procs([{Name, Pid, worker, Mods} | T], Sup) when is_pid(Pid), is_list(Mods) ->
[{Sup, Name, Pid, Mods} | get_procs(T, Sup)];
get_procs([{Name, Pid, supervisor, Mods} | T], Sup) when is_pid(Pid) ->
- [{Sup, Name, Pid, Mods} | get_procs(T, Sup)] ++
- get_procs(supervisor:which_children(Pid), Pid);
+ [{Sup, Name, Pid, Mods} | get_procs(T, Sup)] ++
+ get_procs(maybe_supervisor_which_children(get_proc_state(Pid), Name, Pid), Pid);
get_procs([_H | T], Sup) ->
get_procs(T, Sup);
get_procs(_, _Sup) ->
[].
-get_dynamic_mods(Pid) ->
- {ok,Res} = gen:call(Pid, self(), get_modules),
- Res.
+get_proc_state(Proc) ->
+ {status, _, {module, _}, [_, State, _, _, _]} = sys:get_status(Proc),
+ State.
+
+maybe_supervisor_which_children(suspended, Name, Pid) ->
+ error_logger:error_msg("release_handler: a which_children call"
+ " to ~p (~p) was avoided. This supervisor"
+ " is suspended and should likely be upgraded"
+ " differently. Exiting ...~n", [Name, Pid]),
+ error(suspended_supervisor);
+
+maybe_supervisor_which_children(State, Name, Pid) ->
+ case catch supervisor:which_children(Pid) of
+ Res when is_list(Res) ->
+ Res;
+ Other ->
+ error_logger:error_msg("release_handler: ~p~nerror during"
+ " a which_children call to ~p (~p)."
+ " [State: ~p] Exiting ... ~n",
+ [Other, Name, Pid, State]),
+ error(which_children_failed)
+ end.
+
+maybe_get_dynamic_mods(Name, Pid) ->
+ case catch gen:call(Pid, self(), get_modules) of
+ {ok, Res} ->
+ Res;
+ Other ->
+ error_logger:error_msg("release_handler: ~p~nerror during a"
+ " get_modules call to ~p (~p),"
+ " there may be an error in it's"
+ " childspec. Exiting ...~n",
+ [Other, Name, Pid]),
+ error(get_modules_failed)
+ end.
%% XXXX
%% Note: The following is a terrible hack done in order to resolve the
@@ -606,26 +675,20 @@ sync_nodes(Id, Nodes) ->
end,
NNodes).
-add_old_vsn(Mod, Vsns) ->
+add_vsns(Mod, NewBin, Vsns) ->
+ OldVsn = get_current_vsn(Mod),
+ NewVsn = get_vsn(NewBin),
case lists:keysearch(Mod, 1, Vsns) of
- {value, {Mod, undefined, NewVsn}} ->
- OldVsn = get_current_vsn(Mod),
- lists:keyreplace(Mod, 1, Vsns, {Mod, OldVsn, NewVsn});
- {value, {Mod, _OldVsn, _NewVsn}} ->
- Vsns;
+ {value, {Mod, OldVsn0, NewVsn0}} ->
+ lists:keyreplace(Mod, 1, Vsns, {Mod,
+ replace_undefined(OldVsn0,OldVsn),
+ replace_undefined(NewVsn0,NewVsn)});
false ->
- OldVsn = get_current_vsn(Mod),
- [{Mod, OldVsn, undefined} | Vsns]
+ [{Mod, OldVsn, NewVsn} | Vsns]
end.
-add_new_vsn(Mod, Bin, Vsns) ->
- NewVsn = get_vsn(Bin),
- case lists:keysearch(Mod, 1, Vsns) of
- {value, {Mod, OldVsn, undefined}} ->
- lists:keyreplace(Mod, 1, Vsns, {Mod, OldVsn, NewVsn});
- false ->
- [{Mod, undefined, NewVsn} | Vsns]
- end.
+replace_undefined(undefined,Vsn) -> Vsn;
+replace_undefined(Vsn,_) -> Vsn.
%%-----------------------------------------------------------------
%% Func: get_current_vsn/1
@@ -645,7 +708,9 @@ get_current_vsn(Mod) ->
{ok, Bin, _File2} ->
get_vsn(Bin);
error ->
- throw({error, {no_such_file, File}})
+ %% This is the case when a new module is added, there will
+ %% be no current version of it at the time of this call.
+ undefined
end.
%%-----------------------------------------------------------------
diff --git a/lib/sasl/src/systools_lib.erl b/lib/sasl/src/systools_lib.erl
index b652c109fe..1b6ea125d9 100644
--- a/lib/sasl/src/systools_lib.erl
+++ b/lib/sasl/src/systools_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -24,7 +24,7 @@
%%
-export([file_term2binary/2, read_term/1, read_term_from_stream/2,
- get_dirs/1, get_path/1]).
+ get_dirs/1, get_path/1, werror/2]).
-include_lib("kernel/include/file.hrl").
@@ -176,21 +176,26 @@ add_dirs(RegName, Dirs, Root) ->
regexp_match(RegName, D0, Root) ->
case file:list_dir(D0) of
{ok, Files} when length(Files) > 0 ->
- FR = fun(F) ->
- case regexp:match(F, RegName) of
- {match,1,N} when N == length(F) ->
- DirF = join(D0, F, Root),
- case dir_p(DirF) of
- true ->
- {true, DirF};
+ case re:compile(RegName) of
+ {ok, MP} ->
+ FR = fun(F) ->
+ case re:run(F, MP) of
+ {match,[{0,N}]} when N == length(F) ->
+ DirF = join(D0, F, Root),
+ case dir_p(DirF) of
+ true ->
+ {true, DirF};
+ _ ->
+ false
+ end;
_ ->
false
- end;
- _ ->
- false
- end
- end,
- {true,lists:zf(FR, Files)};
+ end
+ end,
+ {true,lists:zf(FR, Files)};
+ _ ->
+ false
+ end;
_ ->
false
end.
@@ -214,6 +219,7 @@ flat([H|T], Ack) ->
flat(T, [H|Ack]);
flat([], Ack) ->
lists:reverse(Ack).
-
-
+
+werror(Options, Warnings) ->
+ lists:member(warnings_as_errors, Options) andalso Warnings =/= [].
diff --git a/lib/sasl/src/systools_make.erl b/lib/sasl/src/systools_make.erl
index 7489ee58d2..7f400f5cce 100644
--- a/lib/sasl/src/systools_make.erl
+++ b/lib/sasl/src/systools_make.erl
@@ -44,10 +44,12 @@
%%-----------------------------------------------------------------
%% Create a boot script from a release file.
-%% Options is a list of {path, Path} | silent | local where path sets
-%% the search path, silent supresses error message printing on console,
-%% local generates a script with references to the directories there
-%% the applications are found.
+%% Options is a list of {path, Path} | silent | local
+%% | warnings_as_errors
+%% where path sets the search path, silent supresses error message
+%% printing on console, local generates a script with references
+%% to the directories there the applications are found,
+%% and warnings_as_errors treats warnings as errors.
%%
%% New options: {path,Path} can contain wildcards
%% src_tests
@@ -85,11 +87,16 @@ make_script(RelName, Output, Flags) when is_list(RelName),
ModTestP = {member(src_tests, Flags),xref_p(Flags)},
case get_release(RelName, Path, ModTestP, machine(Flags)) of
{ok, Release, Appls, Warnings} ->
- case generate_script(Output,Release,Appls,Flags) of
- ok ->
+ case systools_lib:werror(Flags, Warnings) of
+ true ->
return(ok,Warnings,Flags);
- Error ->
- return(Error,Warnings,Flags)
+ false ->
+ case generate_script(Output,Release,Appls,Flags) of
+ ok ->
+ return(ok,Warnings,Flags);
+ Error ->
+ return(Error,Warnings,Flags)
+ end
end;
Error ->
return(Error,[],Flags)
@@ -130,10 +137,21 @@ get_outdir(Flags) ->
return(ok,Warnings,Flags) ->
case member(silent,Flags) of
true ->
- {ok,?MODULE,Warnings};
+ case systools_lib:werror(Flags, Warnings) of
+ true ->
+ error;
+ false ->
+ {ok,?MODULE,Warnings}
+ end;
_ ->
- io:format("~s",[format_warning(Warnings)]),
- ok
+ case member(warnings_as_errors,Flags) of
+ true ->
+ io:format("~s",[format_warning(Warnings, true)]),
+ error;
+ false ->
+ io:format("~s",[format_warning(Warnings)]),
+ ok
+ end
end;
return({error,Mod,Error},_,Flags) ->
case member(silent,Flags) of
@@ -1612,9 +1630,9 @@ var_dir(_Dir, _, _, []) ->
false.
appDir(AppDir) ->
- case reverse(filename:split(AppDir)) of
- ["ebin"|Dir] -> filename:join(reverse(Dir));
- _ -> AppDir
+ case filename:basename(AppDir) of
+ "ebin" -> filename:dirname(AppDir);
+ _ -> AppDir
end.
add_modules(Modules, Tar, AppDir, ToDir, Ext) ->
@@ -1833,78 +1851,89 @@ get_flag(_,_) -> false.
%% Check Options for make_script
check_args_script(Args) ->
cas(Args,
- {undef, undef, undef, undef, undef, undef, undef, undef, []}).
+ {undef, undef, undef, undef, undef, undef, undef, undef,
+ undef, []}).
-cas([], {_Path,_Sil,_Loc,_Test,_Var,_Mach,_Xref,_XrefApps, X}) ->
+cas([], {_Path,_Sil,_Loc,_Test,_Var,_Mach,_Xref,_XrefApps,_Werror, X}) ->
X;
%%% path ---------------------------------------------------------------
-cas([{path, P} | Args], {Path, Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X}) when is_list(P) ->
+cas([{path, P} | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) when is_list(P) ->
case check_path(P) of
ok ->
- cas(Args, {P, Sil, Loc, Test, Var, Mach, Xref, XrefApps,X});
+ cas(Args, {P, Sil, Loc, Test, Var, Mach, Xref, XrefApps,
+ Werror, X});
error ->
cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps,
- X++[{path,P}]})
+ Werror, X++[{path,P}]})
end;
%%% silent -------------------------------------------------------------
-cas([silent | Args], {Path, _Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X}) ->
- cas(Args, {Path, silent, Loc, Test, Var, Mach, Xref, XrefApps, X});
+cas([silent | Args], {Path, _Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) ->
+ cas(Args, {Path, silent, Loc, Test, Var, Mach, Xref, XrefApps,
+ Werror, X});
%%% local --------------------------------------------------------------
-cas([local | Args], {Path, Sil, _Loc, Test, Var, Mach,
- Xref, XrefApps, X}) ->
- cas(Args, {Path, Sil, local, Test, Var, Mach, Xref, XrefApps, X});
+cas([local | Args], {Path, Sil, _Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) ->
+ cas(Args, {Path, Sil, local, Test, Var, Mach, Xref, XrefApps,
+ Werror, X});
%%% src_tests -------------------------------------------------------
-cas([src_tests | Args], {Path, Sil, Loc, _Test, Var, Mach,
- Xref, XrefApps, X}) ->
+cas([src_tests | Args], {Path, Sil, Loc, _Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) ->
cas(Args,
- {Path, Sil, Loc, src_tests, Var, Mach, Xref, XrefApps,X});
+ {Path, Sil, Loc, src_tests, Var, Mach, Xref, Werror, XrefApps,X});
%%% variables ----------------------------------------------------------
-cas([{variables, V} | Args], {Path, Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X}) when is_list(V) ->
+cas([{variables, V} | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) when is_list(V) ->
case check_vars(V) of
ok ->
cas(Args,
- {Path, Sil, Loc, Test, V, Mach, Xref, XrefApps, X});
+ {Path, Sil, Loc, Test, V, Mach, Xref, XrefApps, Werror, X});
error ->
cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps,
- X++[{variables, V}]})
+ Werror, X++[{variables, V}]})
end;
%%% machine ------------------------------------------------------------
-cas([{machine, M} | Args], {Path, Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X}) when is_atom(M) ->
- cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, X});
+cas([{machine, M} | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) when is_atom(M) ->
+ cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, Werror, X});
%%% exref --------------------------------------------------------------
-cas([exref | Args], {Path, Sil, Loc, Test, Var, Mach,
- _Xref, XrefApps, X}) ->
- cas(Args, {Path, Sil, Loc, Test, Var, Mach, exref, XrefApps, X});
+cas([exref | Args], {Path, Sil, Loc, Test, Var, Mach, _Xref,
+ XrefApps, Werror, X}) ->
+ cas(Args, {Path, Sil, Loc, Test, Var, Mach, exref, XrefApps, Werror, X});
%%% exref Apps ---------------------------------------------------------
-cas([{exref, Apps} | Args], {Path, Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X}) when is_list(Apps) ->
+cas([{exref, Apps} | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) when is_list(Apps) ->
case check_apps(Apps) of
ok ->
cas(Args, {Path, Sil, Loc, Test, Var, Mach,
- Xref, Apps, X});
+ Xref, Apps, Werror, X});
error ->
cas(Args, {Path, Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X++[{exref, Apps}]})
+ Xref, XrefApps, Werror, X++[{exref, Apps}]})
end;
%%% outdir Dir ---------------------------------------------------------
-cas([{outdir, Dir} | Args], {Path, Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X}) when is_list(Dir) ->
- cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, X});
+cas([{outdir, Dir} | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) when is_list(Dir) ->
+ cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, Werror, X});
%%% otp_build (secret, not documented) ---------------------------------
-cas([otp_build | Args], {Path, Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X}) ->
- cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, X});
+cas([otp_build | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) ->
+ cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, Werror, X});
%%% no_module_tests (kept for backwards compatibility, but ignored) ----
-cas([no_module_tests | Args], {Path, Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X}) ->
- cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps,X});
+cas([no_module_tests | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) ->
+ cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, Werror, X});
+%%% warnings_as_errors (kept for backwards compatibility, but ignored) ----
+cas([warnings_as_errors | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, _Werror, X}) ->
+ cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps,
+ warnings_as_errors, X});
%%% ERROR --------------------------------------------------------------
-cas([Y | Args], {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, X}) ->
- cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps,X++[Y]}).
+cas([Y | Args], {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps,
+ Werror, X}) ->
+ cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, Werror,
+ X++[Y]}).
@@ -2030,7 +2059,6 @@ check_apps([H|T]) when is_atom(H) ->
check_apps(_) ->
error.
-
%% Format error
format_error(badly_formatted_release) ->
@@ -2144,21 +2172,31 @@ form_tar_err({add, File, Error}) ->
%% Format warning
format_warning(Warnings) ->
- map(fun({warning,W}) -> form_warn(W) end, Warnings).
-
-form_warn({source_not_found,{Mod,_,App,_,_}}) ->
- io_lib:format("*WARNING* ~p: Source code not found: ~p.erl~n",
- [App,Mod]);
-form_warn({{parse_error, File},{_,_,App,_,_}}) ->
- io_lib:format("*WARNING* ~p: Parse error: ~p~n",
- [App,File]);
-form_warn({obj_out_of_date,{Mod,_,App,_,_}}) ->
- io_lib:format("*WARNING* ~p: Object code (~p) out of date~n",[App,Mod]);
-form_warn({exref_undef, Undef}) ->
- F = fun({M,F,A}) ->
- io_lib:format("*WARNING* Undefined function ~p:~p/~p~n",
- [M,F,A])
+ format_warning(Warnings, false).
+
+format_warning(Warnings, Werror) ->
+ Prefix = case Werror of
+ true ->
+ "";
+ false ->
+ "*WARNING* "
+ end,
+ map(fun({warning,W}) -> form_warn(Prefix, W) end, Warnings).
+
+form_warn(Prefix, {source_not_found,{Mod,_,App,_,_}}) ->
+ io_lib:format("~s~p: Source code not found: ~p.erl~n",
+ [Prefix,App,Mod]);
+form_warn(Prefix, {{parse_error, File},{_,_,App,_,_}}) ->
+ io_lib:format("~s~p: Parse error: ~p~n",
+ [Prefix,App,File]);
+form_warn(Prefix, {obj_out_of_date,{Mod,_,App,_,_}}) ->
+ io_lib:format("~s~p: Object code (~p) out of date~n",
+ [Prefix,App,Mod]);
+form_warn(Prefix, {exref_undef, Undef}) ->
+ F = fun({M,F,A}) ->
+ io_lib:format("~sUndefined function ~p:~p/~p~n",
+ [Prefix,M,F,A])
end,
map(F, Undef);
-form_warn(What) ->
- io_lib:format("*WARNING* ~p~n", [What]).
+form_warn(Prefix, What) ->
+ io_lib:format("~s ~p~n", [Prefix,What]).
diff --git a/lib/sasl/src/systools_relup.erl b/lib/sasl/src/systools_relup.erl
index ec5486226c..6d9e922900 100644
--- a/lib/sasl/src/systools_relup.erl
+++ b/lib/sasl/src/systools_relup.erl
@@ -122,7 +122,7 @@
%% rel_filename() = description() = string()
%% Opts = [opt()]
%% opt() = {path, [path()]} | silent | noexec | restart_emulator
-%% | {outdir, string()}
+%% | {outdir, string()} | warnings_as_errors
%% path() = [string()]
%% Ret = ok | error | {ok, Relup, Module, Warnings} | {error, Module, Error}
%%
@@ -139,8 +139,9 @@
%%
%% The option `path' sets search path, `silent' suppresses printing of
%% error messages to the console, `noexec' inhibits the creation of
-%% the output "relup" file, and restart_emulator ensures that the new
-%% emulator is restarted (as the final step).
+%% the output "relup" file, restart_emulator ensures that the new
+%% emulator is restarted (as the final step), and `warnings_as_errors'
+%% treats warnings as errors.
%% ----------------------------------------------------------------
mk_relup(TopRelFile, BaseUpRelDcs, BaseDnRelDcs) ->
mk_relup(TopRelFile, BaseUpRelDcs, BaseDnRelDcs, []).
@@ -153,14 +154,29 @@ mk_relup(TopRelFile, BaseUpRelDcs, BaseDnRelDcs, Opts) ->
{false, false} ->
case R of
{ok, _Res, _Mod, Ws} ->
- print_warnings(Ws),
- ok;
+ print_warnings(Ws, Opts),
+ case systools_lib:werror(Opts, Ws) of
+ true ->
+ error;
+ false ->
+ ok
+ end;
Other ->
print_error(Other),
error
end;
- _ ->
- R
+ _ ->
+ case R of
+ {ok, _Res, _Mod, Ws} ->
+ case systools_lib:werror(Opts, Ws) of
+ true ->
+ error;
+ false ->
+ R
+ end;
+ R ->
+ R
+ end
end;
BadArg ->
erlang:error({badarg, BadArg})
@@ -195,7 +211,12 @@ do_mk_relup(TopRelFile, BaseUpRelDcs, BaseDnRelDcs, Path, Opts) ->
{Dn, Ws2} = foreach_baserel_dn(TopRel, TopApps, BaseDnRelDcs,
Path, Opts, Ws1),
Relup = {TopRel#release.vsn, Up, Dn},
- write_relup_file(Relup, Opts),
+ case systools_lib:werror(Opts, Ws2) of
+ true ->
+ ok;
+ false ->
+ write_relup_file(Relup, Opts)
+ end,
{ok, Relup, ?MODULE, Ws2};
Other ->
throw(Other)
@@ -527,20 +548,29 @@ format_error(Error) ->
io:format("~p~n", [Error]).
-print_warnings(Ws) when is_list(Ws) ->
- lists:foreach(fun(W) -> print_warning(W) end, Ws);
-print_warnings(W) ->
- print_warning(W).
+print_warnings(Ws, Opts) when is_list(Ws) ->
+ lists:foreach(fun(W) -> print_warning(W, Opts) end, Ws);
+print_warnings(W, Opts) ->
+ print_warning(W, Opts).
-print_warning(W) ->
- S = format_warning(W),
+print_warning(W, Opts) ->
+ Prefix = case lists:member(warnings_as_errors, Opts) of
+ true ->
+ "";
+ false ->
+ "*WARNING* "
+ end,
+ S = format_warning(Prefix, W),
io:format("~s", [S]).
-format_warning({erts_vsn_changed, {Rel1, Rel2}}) ->
- io_lib:format("*WARNING* The ERTS version changed between ~p and ~p~n",
- [Rel1, Rel2]);
-format_warning(What) ->
- io_lib:format("*WARNING* ~p~n",[What]).
+format_warning(W) ->
+ format_warning("*WARNING* ", W).
+
+format_warning(Prefix, {erts_vsn_changed, {Rel1, Rel2}}) ->
+ io_lib:format("~sThe ERTS version changed between ~p and ~p~n",
+ [Prefix, Rel1, Rel2]);
+format_warning(Prefix, What) ->
+ io_lib:format("~s~p~n",[Prefix, What]).
get_reason({error, {open, _, _}}) -> open;
diff --git a/lib/sasl/test/Makefile b/lib/sasl/test/Makefile
index ad08c8136b..65be134462 100644
--- a/lib/sasl/test/Makefile
+++ b/lib/sasl/test/Makefile
@@ -31,7 +31,8 @@ MODULES= \
systools_SUITE \
systools_rc_SUITE \
overload_SUITE \
- rb_SUITE
+ rb_SUITE \
+ rh_test_lib
ERL_FILES= $(MODULES:%=%.erl)
@@ -85,7 +86,7 @@ release_tests_spec: make_emakefile
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR)
$(INSTALL_DATA) sasl.spec sasl.cover $(EMAKEFILE) $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
@tar cfh - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
release_docs_spec:
diff --git a/lib/sasl/test/installer.erl b/lib/sasl/test/installer.erl
index a114c4b5c9..f5ceab0dc4 100644
--- a/lib/sasl/test/installer.erl
+++ b/lib/sasl/test/installer.erl
@@ -119,6 +119,7 @@ install_3(TestNode,PrivDir) ->
?print(["install_3 unpack_release P2A ok"]),
?check_release("P2A",unpacked,["a-1.1"]),
{ok, "P1I", [new_emu]} = release_handler:check_install_release("P2A"),
+ ?print(["install_3 check_install_release P2A ok"]),
ok = release_handler:make_permanent("P1I"),
?print(["install_3 make_permanent P1I ok"]),
?check_release("P1I",permanent,["a-1.1"]),
@@ -268,23 +269,30 @@ client1_1(TestNode,PrivDir,MasterDir,ClientSname) ->
erl_boot_server:start([IP]),
ok = net_kernel:monitor_nodes(true),
- Node = start_client(TestNode,ClientSname),
+ Node = start_client(TestNode,client1,ClientSname),
trace_disallowed_calls(Node),
%% Check env var for SASL on client node
SaslEnv = rpc:call(Node, application, get_all_env, [sasl]),
+ ?print([{client1_1,sasl_env},SaslEnv]),
{_,CliDir} = lists:keyfind(client_directory,1,SaslEnv),
{_,[Master]} = lists:keyfind(masters,1,SaslEnv),
{_,StartCli} = lists:keyfind(start_prg,1,SaslEnv),
- Root = code:root_dir(),
- true = (CliDir =:= filename:join([Root,"clients","type1",Node])),
- true = (StartCli =:= filename:join([CliDir,"bin","start"])),
+ NodeStr = atom_to_list(Node),
+ [NodeStr,"type1","clients"|_] = lists:reverse(filename:split(CliDir)),
true = (Master =:= node()),
+ case os:type() of
+ {unix,_} ->
+ true = (StartCli =:= filename:join([CliDir,"bin","start"]));
+ _ ->
+ ok
+ end,
%% Unpack P1H on master
{ok, "P1H"} = unpack_release(PrivDir,"rel1"),
%% Unpack and install P1H on client
+ Root = code:root_dir(),
P1HDir = filename:join([Root, "releases", "P1H"]),
%% The AppDirs argument (last arg to set_unpacked) below is really
@@ -339,6 +347,7 @@ client1_2(TestNode,PrivDir,Node) ->
?check_running_app_client(Node,a,"1.0"),
ok = rpc:call(Node, release_handler, make_permanent, ["P1H"]),
+ ?check_release_client(Node,"P1H",permanent,["a-1.0"]),
check_disallowed_calls(),
reboot(TestNode,Node),
@@ -584,7 +593,7 @@ trace_disallowed_calls(Node) ->
MasterProc = self(),
rpc:call(Node,dbg,tracer,[process,{fun(T,_) -> MasterProc ! T end,[]}]),
rpc:call(Node,dbg,p,[all,call]),
- rpc:call(Node,dbg,tp,[file,[]]).
+ rpc:call(Node,dbg,tp,[file,[{'_',[],[{message,{caller}}]}]]).
check_disallowed_calls() ->
receive
@@ -594,13 +603,12 @@ check_disallowed_calls() ->
ok
end.
-start_client(TestNode,Client) ->
- {Start, Node} = do_start_client(Client,test_host()),
- Cmd = lists:concat(["env NODENAME=",Client," ",
- filename:join(code:root_dir(), Start)]),
- ?print([{start_client,Client},Cmd]),
- Res = os:cmd(Cmd),
- ?print([{start_client,result},Res]),
+start_client(TestNode,Client,Sname) ->
+ Node = list_to_atom(lists:concat([Sname,"@",test_host()])),
+ case os:type() of
+ {unix,_} -> start_client_unix(TestNode,Sname,Node);
+ {win32,_} -> start_client_win32(TestNode,Client,Sname)
+ end,
receive
{nodeup, Node} ->
wait_started(TestNode,Node)
@@ -609,10 +617,34 @@ start_client(TestNode,Client) ->
?fail({"can not start", Node})
end.
-do_start_client(Client, Host) ->
- Node = list_to_atom(lists:concat([Client,"@",Host])),
+start_client_unix(TestNode,Sname,Node) ->
Start = filename:join(["clients", "type1", Node, "bin", "start"]),
- {Start, Node}.
+ Cmd = lists:concat(["env NODENAME=",Sname," ",
+ filename:join(code:root_dir(), Start)]),
+ ?print([{start_client,Sname},Cmd]),
+ Res = os:cmd(Cmd),
+ ?print([{start_client,result},Res]).
+
+start_client_win32(TestNode,Client,ClientSname) ->
+ Name = atom_to_list(ClientSname) ++ "_P1G",
+ RootDir = code:root_dir(),
+ ErtsBinDir = filename:join(RootDir,"erts-4.4/bin"),
+
+ {ClientArgs,RelClientDir} = rh_test_lib:get_client_args(Client,ClientSname,
+ RootDir),
+ StartErlArgs = rh_test_lib:get_start_erl_args(RootDir,RelClientDir,
+ ClientArgs),
+ ServiceArgs = rh_test_lib:get_service_args(RootDir, RelClientDir,
+ ClientSname, StartErlArgs),
+
+ ?print([{start_client,ClientSname},ServiceArgs]),
+ Erlsrv = filename:nativename(filename:join(ErtsBinDir,"erlsrv")),
+ rh_test_lib:erlsrv(Erlsrv,stop,Name),
+ rh_test_lib:erlsrv(Erlsrv,remove,Name),
+ ok = rh_test_lib:erlsrv(Erlsrv,add,Name,ServiceArgs),
+ ok = rh_test_lib:erlsrv(Erlsrv,start,Name),
+ ?print([{start_client,result},ok]),
+ ok.
reboot(TestNode,Node) ->
cover_client(TestNode,Node,stop_cover),
@@ -628,7 +660,7 @@ check_reboot(TestNode,Node) ->
receive
{nodeup, Node} -> wait_started(TestNode,Node)
after 30000 ->
- ?fail({Node, "not rebooted",net_adm:ping(Node)})
+ ?fail({Node, "not rebooted",net_adm:ping(Node)})
end
after 30000 ->
?fail({Node, "not closing down",net_adm:ping(Node)})
@@ -678,22 +710,28 @@ client2(TestNode,PrivDir,ClientSname) ->
release_handler:remove_release("P1H"),
ok = net_kernel:monitor_nodes(true),
- Node = start_client(TestNode,ClientSname),
+ Node = start_client(TestNode,client2,ClientSname),
%% Check env var for SASL on client node
- ?print([{sasl_env, Node}, rpc:call(Node, application, get_all_env, [sasl])]),
SaslEnv = rpc:call(Node, application, get_all_env, [sasl]),
+ ?print([{client1_1,sasl_env},SaslEnv]),
{_,CliDir} = lists:keyfind(client_directory,1,SaslEnv),
{_,[Master,Master2]} = lists:keyfind(masters,1,SaslEnv),
{_,StartCli} = lists:keyfind(start_prg,1,SaslEnv),
- Root = code:root_dir(),
- true = (CliDir =:= filename:join([Root,"clients","type1",Node])),
- true = (StartCli =:= filename:join([CliDir,"bin","start"])),
+ NodeStr = atom_to_list(Node),
+ [NodeStr,"type1","clients"|_] = lists:reverse(filename:split(CliDir)),
true = (Master =:= node()),
true = (Master2 =:= list_to_atom("master2@"++TestHost)),
+ case os:type() of
+ {unix,_} ->
+ true = (StartCli =:= filename:join([CliDir,"bin","start"]));
+ _ ->
+ ok
+ end,
{ok, "P1H"} = unpack_release(PrivDir,"rel1"),
+ Root = code:root_dir(),
{error,{bad_masters,[Master2]}} =
rpc:call(Node, release_handler, set_unpacked,
[filename:join([Root, "releases", "P1H", "rel1.rel"]),[]]),
diff --git a/lib/sasl/test/release_handler_SUITE.erl b/lib/sasl/test/release_handler_SUITE.erl
index efa775f344..af2183bfff 100644
--- a/lib/sasl/test/release_handler_SUITE.erl
+++ b/lib/sasl/test/release_handler_SUITE.erl
@@ -51,11 +51,14 @@ unix_cases() ->
[target_system] ++ RunErlCases ++ cases().
win32_cases() ->
- cases().
+ [{group,release} | cases()].
%% Cases that can be run on all platforms
cases() ->
- [otp_2740, otp_2760, otp_5761, instructions, eval_appup].
+ [otp_2740, otp_2760, otp_5761, otp_9402, otp_9417,
+ otp_9395_check_old_code, otp_9395_check_and_purge,
+ otp_9395_update_many_mods, otp_9395_rm_many_mods,
+ instructions, eval_appup, supervisor_which_children_timeout].
groups() ->
[{release,[],
@@ -148,6 +151,10 @@ init_per_group(release_gg, Config0) ->
end_per_group(release, Config) ->
Dog = ?t:timetrap(?default_timeout),
stop_print_proc(),
+ case os:type() of
+ {win32,_} -> delete_all_services();
+ _ -> ok
+ end,
delete_release(Config),
?t:timetrap_cancel(Dog),
Config;
@@ -169,6 +176,10 @@ end_per_testcase(Case, Config) ->
Dog=?config(watchdog, Config),
test_server:timetrap_cancel(Dog),
+ try apply(?MODULE,Case,[cleanup,Config])
+ catch error:undef -> ok
+ end,
+
%% DEBUG
case ?config(tc_status,Config) of
ok ->
@@ -206,10 +217,6 @@ end_per_testcase(Case, Config) ->
%% immediately restarted by heart and the test cases wait until
%% the node is actually up and running -- see wait_nodes_up/2)
file:delete("sasl_erl_crash.dump"),
-
- try apply(?MODULE,Case,[cleanup,Config])
- catch error:undef -> ok
- end,
ok.
gg_node_snames(Config) ->
@@ -224,7 +231,10 @@ gg_node_snames(Config) ->
no_run_erl(Config) when is_list(Config) ->
{comment, "No run_erl program"}.
-
+break(Config) ->
+ erlang:display(test_break),
+ ?t:break(priv_dir(Config)),
+ ok.
%% Test upgrade and downgrade of erts
upgrade(Conf) when is_list(Conf) ->
@@ -323,7 +333,7 @@ client1(Conf) when is_list(Conf) ->
%% Copy the P1G release to a directory for use in this testcase
ok = copy_installed(Conf,p1g_install,[Master]),
- ok = copy_client(Conf,Master,Client,"start_cli1"),
+ ok = copy_client(Conf,Master,Client,client1),
%% start the master node
[TestNode] = start_nodes(Conf,[Master],"client1"),
@@ -348,7 +358,7 @@ client2(Conf) when is_list(Conf) ->
%% Copy the P1G release to a directory for use in this testcase
ok = copy_installed(Conf,p1g_install,[Master]),
- ok = copy_client(Conf,Master,Client,"start_cli2"),
+ ok = copy_client(Conf,Master,Client,client2),
%% start the master node
[TestNode] = start_nodes(Conf,[Master],"client2"),
@@ -386,7 +396,7 @@ instructions(Conf) when is_list(Conf) ->
{stop, [aa]},
{apply, {?MODULE, no_cc, []}},
{start, [aa]}],
- {ok, _} = release_handler_1:eval_script(S1, [], []),
+ {ok, _} = release_handler_1:eval_script(S1),
case whereis(cc) of
Pid2 when is_pid(Pid2) -> ok;
@@ -396,17 +406,17 @@ instructions(Conf) when is_list(Conf) ->
%% Make bb run old version of b.
S2 = [point_of_no_return,
{remove, {b, soft_purge, soft_purge}}],
- {ok, [{b, soft_purge}]} = release_handler_1:eval_script(S2, [], []),
+ {ok, [{b, soft_purge}]} = release_handler_1:eval_script(S2),
check_bstate("first", [FirstBB]),
false = code:is_loaded(b),
- {error,{old_processes,b}} = release_handler_1:eval_script(S2,[],[]),
+ {error,{old_processes,b}} = release_handler_1:eval_script(S2),
check_bstate("first", [FirstBB]),
%% Let supervisor restart bb with new code
S3 = [point_of_no_return,
{purge, [b]}],
- {ok, []} = release_handler_1:eval_script(S3, [], []),
+ {ok, []} = release_handler_1:eval_script(S3),
ok = wait_for(bb),
check_bstate("second", []),
SecondBB = whereis(bb),
@@ -439,7 +449,7 @@ instructions(Conf) when is_list(Conf) ->
%% Let supervisor restart bb yet another time
S4 = [point_of_no_return,
{remove, {b, brutal_purge, soft_purge}}],
- {ok, HopefullyEmpty} = release_handler_1:eval_script(S4, [], []),
+ {ok, HopefullyEmpty} = release_handler_1:eval_script(S4),
ok = wait_for(bb),
FourthBB = whereis(bb),
@@ -513,6 +523,29 @@ no_cc() ->
%%%-----------------------------------------------------------------
%%-----------------------------------------------------------------
+%% release_handler_1:get_supervised_procs/0 test
+%%-----------------------------------------------------------------
+supervisor_which_children_timeout(Conf) ->
+ PrivDir = priv_dir(Conf),
+ Dir = filename:join(PrivDir,"supervisor_which_children_timeout"),
+ DataDir = ?config(data_dir,Conf),
+ LibDir = filename:join([DataDir,release_handler_timeouts]),
+
+ Rel1 = create_and_install_fake_first_release(Dir,[{dummy,"0.1",LibDir}]),
+
+ {ok, Node} = t_start_node(supervisor_which_children_timeout, Rel1, []),
+ Proc = rpc:call(Node, erlang, whereis, [dummy_sup_2]),
+ ok = rpc:call(Node, sys, suspend, [Proc]),
+ Result = {badrpc, {'EXIT', {suspended_supervisor, _}}} =
+ rpc:call(Node, release_handler_1, get_supervised_procs, []),
+ ?t:format("release_handler_1:get_supervised_procs/0: ~p~n", [Result]),
+
+ ok.
+
+supervisor_which_children_timeout(cleanup, Conf) ->
+ stop_node(node_name(supervisor_which_children_timeout)).
+
+%%-----------------------------------------------------------------
%% Ticket: OTP-2740
%% Slogan: vsn not numeric doesn't work so good in release_handling
%%-----------------------------------------------------------------
@@ -549,7 +582,7 @@ otp_2760(Conf) ->
LibDir = filename:join([DataDir,app1_app2,lib1]),
Rel1 = create_and_install_fake_first_release(Dir,[{app1,"1.0",LibDir}]),
- Rel2 = create_fake_upgrade_release(Dir,"after",[],{Rel1,Rel1,[LibDir]}),
+ Rel2 = create_fake_upgrade_release(Dir,"after",[],{[Rel1],[Rel1],[LibDir]}),
Rel2Dir = filename:dirname(Rel2),
%% Start a node with Rel1.boot and check that the app1 module is loaded
@@ -559,13 +592,15 @@ otp_2760(Conf) ->
%% Execute the relup script and check that app1 is unloaded
{ok, [{"after", [{_Rel1Vsn, _Descr, Script}], _}]} =
file:consult(filename:join(Rel2Dir, "relup")),
- {ok, []} = rpc:call(Node, release_handler_1, eval_script,
- [Script, [], []]),
+ {ok, []} = rpc:call(Node, release_handler_1, eval_script, [Script]),
false = rpc:call(Node, code, is_loaded, [app1]),
- true = stop_node(Node),
ok.
+otp_2760(cleanup,_Conf) ->
+ stop_node(node_name(otp_2760)).
+
+
%% Test upgrade using other filesystem than the defined in OTP and
%% option {update_paths, true}
otp_5761(Conf) when is_list(Conf) ->
@@ -591,7 +626,7 @@ otp_5761(Conf) when is_list(Conf) ->
"2",
[{app1,"2.0",LibDir2},
{app2,"1.0",LibDir2}],
- {Rel1,Rel1,[LibDir1]}),
+ {[Rel1],[Rel1],[LibDir1]}),
Rel1Dir = filename:dirname(Rel1),
Rel2Dir = filename:dirname(Rel2),
@@ -647,10 +682,410 @@ otp_5761(Conf) when is_list(Conf) ->
App11Dir = rpc:call(Node, code, lib_dir, [app1]),
App2aDir = rpc:call(Node, code, lib_dir, [app2]),
- %% Stop the slave node
- true = stop_node(Node),
ok.
+otp_5761(cleanup,_Conf) ->
+ stop_node(node_name(otp_5761)).
+
+
+%% When a new version of an application is added, but no module is
+%% changed - the path was not updated - i.e. code:priv_dir would point
+%% to the old location.
+otp_9402(Conf) when is_list(Conf) ->
+ %% Set some paths
+ PrivDir = priv_dir(Conf),
+ Dir = filename:join(PrivDir,"otp_9402"),
+ LibDir = filename:join(?config(data_dir, Conf), "lib"),
+
+ %% Create the releases
+ Rel1 = create_and_install_fake_first_release(Dir,
+ [{a,"1.1",LibDir}]),
+ Rel2 = create_fake_upgrade_release(Dir,
+ "2",
+ [{a,"1.2",LibDir}],
+ {[Rel1],[Rel1],[LibDir]}),
+ Rel1Dir = filename:dirname(Rel1),
+ Rel2Dir = filename:dirname(Rel2),
+
+ %% Start a slave node
+ {ok, Node} = t_start_node(otp_9402, Rel1, filename:join(Rel1Dir,"sys.config")),
+
+ %% Check path
+ Dir1 = filename:join([LibDir, "a-1.1"]),
+ Dir1 = rpc:call(Node, code, lib_dir, [a]),
+ ABeam = rpc:call(Node, code, which, [a]),
+
+ %% Install second release, with no changed modules
+ {ok, RelVsn2} =
+ rpc:call(Node, release_handler, set_unpacked,
+ [Rel2++".rel", [{a,"1.2",LibDir}]]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "relup")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "start.boot")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "sys.config")]),
+
+ {ok, RelVsn1, []} =
+ rpc:call(Node, release_handler, install_release, [RelVsn2]),
+
+ %% Check path
+ Dir2 = filename:join([LibDir, "a-1.2"]),
+ Dir2 = rpc:call(Node, code, lib_dir, [a]),
+ APrivDir2 = rpc:call(Node, code, priv_dir, [a]),
+ true = filelib:is_regular(filename:join(APrivDir2,"file")),
+
+ %% Just to make sure no modules have been re-loaded
+ ABeam = rpc:call(Node, code, which, [a]),
+
+ %% Install RelVsn1 again
+ {ok, _OtherVsn, []} =
+ rpc:call(Node, release_handler, install_release, [RelVsn1]),
+
+ %% Check path
+ Dir1 = rpc:call(Node, code, lib_dir, [a]),
+ APrivDir1 = rpc:call(Node, code, priv_dir, [a]),
+ false = filelib:is_regular(filename:join(APrivDir1,"file")),
+
+ %% Just to make sure no modules have been re-loaded
+ ABeam = rpc:call(Node, code, which, [a]),
+
+ ok.
+
+otp_9402(cleanup,_Conf) ->
+ stop_node(node_name(otp_9402)).
+
+
+%% When a module is deleted in an appup instruction, the upgrade
+%% failed if the module was not loaded.
+otp_9417(Conf) when is_list(Conf) ->
+ %% Set some paths
+ PrivDir = priv_dir(Conf),
+ Dir = filename:join(PrivDir,"otp_9417"),
+ LibDir = filename:join(?config(data_dir, Conf), "lib"),
+
+ %% Create the releases
+ Rel1 = create_and_install_fake_first_release(Dir,
+ [{b,"1.0",LibDir}]),
+ Rel2 = create_fake_upgrade_release(Dir,
+ "2",
+ [{b,"2.0",LibDir}],
+ {[Rel1],[Rel1],[LibDir]}),
+ Rel1Dir = filename:dirname(Rel1),
+ Rel2Dir = filename:dirname(Rel2),
+
+ %% Start a slave node
+ {ok, Node} = t_start_node(otp_9417, Rel1, filename:join(Rel1Dir,"sys.config")),
+
+ %% Check paths
+ Dir1 = filename:join([LibDir, "b-1.0"]),
+ Dir1 = rpc:call(Node, code, lib_dir, [b]),
+ BLibBeam = filename:join([Dir1,"ebin","b_lib.beam"]),
+ BLibBeam = rpc:call(Node,code,which,[b_lib]),
+ false = rpc:call(Node,code,is_loaded,[b_lib]),
+ false = rpc:call(Node,code,is_loaded,[b_server]),
+
+ %% Install second release, which removes b_lib module
+ {ok, RelVsn2} =
+ rpc:call(Node, release_handler, set_unpacked,
+ [Rel2++".rel", [{b,"2.0",LibDir}]]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "relup")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "start.boot")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "sys.config")]),
+
+ {ok, _RelVsn1, []} =
+ rpc:call(Node, release_handler, install_release, [RelVsn2]),
+
+ %% Check that the module does no longer exist
+ false = rpc:call(Node, code, is_loaded, [b_lib]),
+ non_existing = rpc:call(Node, code, which, [b_lib]),
+
+ %% And check some paths
+ Dir2 = filename:join([LibDir, "b-2.0"]),
+ Dir2 = rpc:call(Node, code, lib_dir, [b]),
+ BServerBeam = filename:join([Dir2,"ebin","b_server.beam"]),
+ {file,BServerBeam} = rpc:call(Node,code,is_loaded,[b_server]),
+ ok.
+
+otp_9417(cleanup,_Conf) ->
+ stop_node(node_name(otp_9417)).
+
+
+%% OTP-9395 - performance problems when there are MANY processes
+%% Test that the procedure of checking for old code before an upgrade
+%% can be started is "very much faster" when there is no old code in
+%% the system.
+otp_9395_check_old_code(Conf) when is_list(Conf) ->
+
+ NProcs = 1000,
+ MPath = filename:join([?config(data_dir,Conf),"lib","many_mods-1.0","ebin"]),
+ code:add_path(MPath),
+
+ %% Start NProc processes, each referencing each module
+ {Modules,Pids} = m:start(NProcs),
+
+ %% Load each module again in order to get old code
+ [code:load_file(Mod) || Mod <- Modules],
+ true = erlang:check_old_code(m10),
+
+ S = [point_of_no_return |
+ [{remove,{M,soft_purge,soft_purge}} || M <- Modules]],
+
+ %% Do the old code check, then purge, and redo
+ {T1,{ok,PurgeMods}} = timer:tc(release_handler_1,check_script,[S,[]]),
+ true = (lists:sort(PurgeMods) == lists:sort(Modules)),
+ [code:purge(M) || M <- PurgeMods],
+ {T2,{ok,[]}} = timer:tc(release_handler_1,check_script,[S,[]]),
+
+ %% Cleanup
+ lists:foreach(fun(Pid) -> Pid ! stop end, Pids),
+ lists:foreach(fun(Mod) -> code:purge(Mod),
+ code:delete(Mod),
+ code:purge(Mod)
+ end, Modules),
+ code:del_path(MPath),
+
+ %% Test that second run was much faster than the first
+ if T2 > 0 ->
+ X = T1/T2,
+ ct:log("~p procs, ~p mods -> ~n"
+ "\tWith old code: ~.2f sec~n"
+ "\tAfter purge: ~.2f sec~n"
+ "\tT1/T2: ~.2f",
+ [NProcs,length(Modules),T1/1000000,T2/1000000,X]),
+ if X < 1000 ->
+ ct:fail({not_enough_improvement_after_purge,round(X)});
+ true ->
+ ok
+ end;
+ T1 > 0 -> %% Means T1/T2 = infinite
+ ok;
+ true ->
+ ct:fail({unexpected_values,T1,T2})
+ end,
+ ok.
+
+
+%% OTP-9395 - performance problems when there are MANY processes
+%% Added option 'purge' to check_install_release
+otp_9395_check_and_purge(Conf) when is_list(Conf) ->
+ %% Set some paths
+ PrivDir = priv_dir(Conf),
+ Dir = filename:join(PrivDir,"otp_9395_check_and_purge"),
+ LibDir = filename:join(?config(data_dir, Conf), "lib"),
+
+ %% Create the releases
+ Rel1 = create_and_install_fake_first_release(Dir,
+ [{b,"1.0",LibDir}]),
+ Rel2 = create_fake_upgrade_release(Dir,
+ "2",
+ [{b,"2.0",LibDir}],
+ {[Rel1],[Rel1],[LibDir]}),
+ Rel1Dir = filename:dirname(Rel1),
+ Rel2Dir = filename:dirname(Rel2),
+
+ %% Start a slave node
+ {ok, Node} = t_start_node(otp_9395_check_and_purge, Rel1,
+ filename:join(Rel1Dir,"sys.config")),
+
+ %% Make sure there is old code for b_lib and b_server
+ rpc:call(Node,code,load_file,[b_lib]),
+ rpc:call(Node,code,load_file,[b_lib]),
+ rpc:call(Node,code,load_file,[b_server]),
+ rpc:call(Node,code,load_file,[b_server]),
+ true = rpc:call(Node,erlang,check_old_code,[b_lib]),
+ true = rpc:call(Node,erlang,check_old_code,[b_server]),
+
+ %% Unpack second release, which removes b_lib module and loads b_server
+ {ok, RelVsn2} =
+ rpc:call(Node, release_handler, set_unpacked,
+ [Rel2++".rel", [{b,"2.0",LibDir}]]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "relup")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "start.boot")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "sys.config")]),
+
+ %% Do check_install_release, and check that old code still exists
+ {ok, _RelVsn1, []} =
+ rpc:call(Node, release_handler, check_install_release, [RelVsn2]),
+ true = rpc:call(Node,erlang,check_old_code,[b_lib]),
+ true = rpc:call(Node,erlang,check_old_code,[b_server]),
+
+ %% Do check_install_release with option 'purge' and check that old
+ %% code is gone
+ {ok, _RelVsn1, []} =
+ rpc:call(Node, release_handler, check_install_release, [RelVsn2,[purge]]),
+ false = rpc:call(Node,erlang,check_old_code,[b_lib]),
+ false = rpc:call(Node,erlang,check_old_code,[b_server]),
+
+ ok.
+
+otp_9395_check_and_purge(cleanup,_Conf) ->
+ stop_node(node_name(otp_9395_check_and_purge)).
+
+
+%% OTP-9395 - performance problems when there are MANY processes
+%% Upgrade which updates many modules (brutal_purge)
+otp_9395_update_many_mods(Conf) when is_list(Conf) ->
+ %% Set some paths
+ PrivDir = priv_dir(Conf),
+ Dir = filename:join(PrivDir,"otp_9395_update_many_mods"),
+ LibDir = filename:join(?config(data_dir, Conf), "lib"),
+
+ %% Create the releases
+ Rel1 = create_and_install_fake_first_release(Dir,
+ [{many_mods,"1.0",LibDir}]),
+ Rel2 = create_fake_upgrade_release(Dir,
+ "2",
+ [{many_mods,"1.1",LibDir}],
+ {[Rel1],[Rel1],[LibDir]}),
+ Rel1Dir = filename:dirname(Rel1),
+ Rel2Dir = filename:dirname(Rel2),
+
+ %% Start a slave node
+ {ok, Node} = t_start_node(otp_9395_update_many_mods, Rel1,
+ filename:join(Rel1Dir,"sys.config")),
+
+ %% Start a lot of processes on the new node, all with refs to each
+ %% module that will be updated
+ NProcs = 1000,
+ {Modules,Pids1} = rpc:call(Node,m,start,[NProcs]),
+
+ %% Then load modules in order to get old code
+ [rpc:call(Node,code,load_file,[Mod]) || Mod <- Modules],
+ true = rpc:call(Node,erlang,check_old_code,[m10]),
+
+ %% Unpack second release, which updates all mX modules
+ {ok, RelVsn2} =
+ rpc:call(Node, release_handler, set_unpacked,
+ [Rel2++".rel", [{many_mods,"1.1",LibDir}]]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "relup")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "start.boot")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "sys.config")]),
+
+ %% First, install release directly and check how much time it takes
+ {TInst0,{ok, _, []}} =
+ timer:tc(rpc,call,[Node, release_handler, install_release, [RelVsn2]]),
+ ct:log("install_release: ~.2f",[TInst0/1000000]),
+
+ %% Restore to old release, spawn processes again and load to get old code
+ {_,RelVsn1} = init:script_id(),
+ {_TInst1,{ok, _, []}} =
+ timer:tc(rpc,call,[Node, release_handler, install_release, [RelVsn1]]),
+% ct:log("install_release: ~.2f",[_TInst1/1000000]),
+
+ [exit(Pid,kill) || Pid <- Pids1],
+ {Modules,_Pids2} = rpc:call(Node,m,start,[NProcs]),
+ [rpc:call(Node,code,load_file,[Mod]) || Mod <- Modules],
+ true = rpc:call(Node,erlang,check_old_code,[m10]),
+
+ %% Run check_install_release with purge before install this time
+ {TCheck,{ok, _RelVsn1, []}} =
+ timer:tc(rpc,call,[Node, release_handler, check_install_release,
+ [RelVsn2,[purge]]]),
+ ct:log("check_install_release with purge: ~.2f",[TCheck/1000000]),
+
+ %% Finally install release after check and purge, and check that
+ %% this install was faster than the first.
+ {TInst2,{ok, _RelVsn1, []}} =
+ timer:tc(rpc,call,[Node, release_handler, install_release, [RelVsn2]]),
+ ct:log("install_release: ~.2f",[TInst2/1000000]),
+
+ true = (TInst2 < TInst0),
+
+ ok.
+
+otp_9395_update_many_mods(cleanup,_Conf) ->
+ stop_node(node_name(otp_9395_update_many_mods)).
+
+
+%% OTP-9395 - performance problems when there are MANY processes
+%% Upgrade which removes many modules (brutal_purge)
+otp_9395_rm_many_mods(Conf) when is_list(Conf) ->
+ %% Set some paths
+ PrivDir = priv_dir(Conf),
+ Dir = filename:join(PrivDir,"otp_9395_rm_many_mods"),
+ LibDir = filename:join(?config(data_dir, Conf), "lib"),
+
+ %% Create the releases
+ Rel1 = create_and_install_fake_first_release(Dir,
+ [{many_mods,"1.0",LibDir}]),
+ Rel2 = create_fake_upgrade_release(Dir,
+ "2",
+ [{many_mods,"2.0",LibDir}],
+ {[Rel1],[Rel1],[LibDir]}),
+ Rel1Dir = filename:dirname(Rel1),
+ Rel2Dir = filename:dirname(Rel2),
+
+ %% Start a slave node
+ {ok, Node} = t_start_node(otp_9395_rm_many_mods, Rel1,
+ filename:join(Rel1Dir,"sys.config")),
+
+ %% Start a lot of processes on the new node, all with refs to each
+ %% module that will be updated
+ NProcs = 1000,
+ {Modules,Pids1} = rpc:call(Node,m,start,[NProcs]),
+
+ %% Then load modules in order to get old code
+ [rpc:call(Node,code,load_file,[Mod]) || Mod <- Modules],
+ true = rpc:call(Node,erlang,check_old_code,[m10]),
+
+ %% Unpack second release, which removes all mX modules
+ {ok, RelVsn2} =
+ rpc:call(Node, release_handler, set_unpacked,
+ [Rel2++".rel", [{many_mods,"2.0",LibDir}]]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "relup")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "start.boot")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "sys.config")]),
+
+ %% First, install release directly and check how much time it takes
+ {TInst0,{ok, _, []}} =
+ timer:tc(rpc,call,[Node, release_handler, install_release, [RelVsn2]]),
+ ct:log("install_release: ~.2f",[TInst0/1000000]),
+
+ %% Restore to old release, spawn processes again and load to get old code
+ {_,RelVsn1} = init:script_id(),
+ {_TInst1,{ok, _, []}} =
+ timer:tc(rpc,call,[Node, release_handler, install_release, [RelVsn1]]),
+% ct:log("install_release: ~.2f",[_TInst1/1000000]),
+
+ [exit(Pid,kill) || Pid <- Pids1],
+ {Modules,_Pids2} = rpc:call(Node,m,start,[NProcs]),
+ [rpc:call(Node,code,load_file,[Mod]) || Mod <- Modules],
+ true = rpc:call(Node,erlang,check_old_code,[m10]),
+
+ %% Run check_install_release with purge before install this time
+ {TCheck,{ok, _RelVsn1, []}} =
+ timer:tc(rpc,call,[Node, release_handler, check_install_release,
+ [RelVsn2,[purge]]]),
+ ct:log("check_install_release with purge: ~.2f",[TCheck/1000000]),
+
+ %% Finally install release after check and purge, and check that
+ %% this install was faster than the first.
+ {TInst2,{ok, _RelVsn1, []}} =
+ timer:tc(rpc,call,[Node, release_handler, install_release, [RelVsn2]]),
+ ct:log("install_release: ~.2f",[TInst2/1000000]),
+
+ true = (TInst2 =< TInst0),
+
+ ok.
+
+otp_9395_rm_many_mods(cleanup,_Conf) ->
+ stop_node(node_name(otp_9395_rm_many_mods)).
+
+
+
%% Test upgrade and downgrade of applications
eval_appup(Conf) when is_list(Conf) ->
@@ -983,19 +1418,16 @@ stop_node(Node) ->
?t:stop_node(Node).
-copy_client(Conf,Master,Sname,StartScript) ->
+copy_client(Conf,Master,Sname,Client) ->
io:format("copy_client(Conf)"),
DataDir = ?config(data_dir, Conf),
MasterDir = filename:join(priv_dir(Conf),Master),
- {ok,Host} = inet:gethostname(),
- {ok,IpTuple} = inet:getaddr(Host,inet),
- IpAddr = inet_parse:ntoa(IpTuple),
-
- CliNode = node_name(Sname),
+ {ClientArgs,RelCliDir} = rh_test_lib:get_client_args(Client,Sname,MasterDir,
+ node_name(Master)),
- Cli = filename:join([MasterDir, "clients", "type1", CliNode]),
+ Cli = filename:join([MasterDir, RelCliDir]),
ok = filelib:ensure_dir(filename:join([Cli,"bin","."])),
ok = filelib:ensure_dir(filename:join([Cli,"releases","."])),
ok = filelib:ensure_dir(filename:join([Cli,"log","."])),
@@ -1003,12 +1435,16 @@ copy_client(Conf,Master,Sname,StartScript) ->
P1GOrig = filename:join([MasterDir, "releases", "P1G"]),
ok = copy_tree(Conf,P1GOrig,filename:join(Cli,"releases")),
- ok = subst_file(filename:join([DataDir, "clients", StartScript]),
- filename:join([Cli,"bin","start"]),
- [{"ROOT",MasterDir},
- {"MASTER",atom_to_list(Master)},
- {"IPADDR",IpAddr}],
- [{chmod,8#0755}]),
+ case os:type() of
+ {unix,_} ->
+ ok = subst_file(filename:join([DataDir, "start_client"]),
+ filename:join([Cli,"bin","start"]),
+ [{"ROOT",MasterDir},
+ {"CLIENTARGS",ClientArgs}],
+ [{chmod,8#0755}]);
+ _ ->
+ ok
+ end,
StartErlData = filename:join([MasterDir, "releases", "start_erl.data"]),
CliRelDir = filename:join([Cli, "releases"]),
@@ -1030,21 +1466,32 @@ delete_release(Conf) ->
{ok, Dirs} = file:list_dir(PrivDir),
?t:format("======== deleting ~p~n",[Dirs]),
- ok = delete_release_os(Dirs),
- ?t:format("======== remaining ~p~n",[file:list_dir(PrivDir)]),
+ ok = delete_release_os(Dirs--["save"]),
+ {ok,Remaining} = file:list_dir(PrivDir),
+ ?t:format("======== remaining ~p~n",[Remaining]),
+
+ case Remaining of
+ [] ->
+ ok;
+ _ ->
+ delete_release_os(Remaining),
+ Remaining2 = file:list_dir(PrivDir),
+ ?t:format("======== remaining after second try ~p~n",[Remaining2])
+ end,
+
ok = file:set_cwd(OrigWd),
ok.
delete_release_os(Dirs) ->
case os:type() of
- {unix, _} ->
- delete_release_unix(Dirs);
- {win32, _} ->
- delete_release_win32(Dirs);
- Os ->
- test_server:fail({error, {not_yet_implemented_os, Os}})
- end.
+ {unix, _} ->
+ delete_release_unix(Dirs);
+ {win32, _} ->
+ delete_release_win32(Dirs);
+ Os ->
+ test_server:fail({error, {not_yet_implemented_os, Os}})
+ end.
delete_release_unix([]) ->
@@ -1075,7 +1522,14 @@ delete_release_win32([]) ->
delete_release_win32(["save"|Dirs]) ->
delete_release_win32(Dirs);
delete_release_win32([Dir|Dirs]) ->
- Rm = string:concat("rmdir /s ", Dir),
+ Rm =
+ case filelib:is_dir(Dir) of
+ true ->
+ string:concat("rmdir /s /q ", Dir);
+ false ->
+ string:concat("del /q ", Dir)
+ end,
+ ?t:format("============== COMMAND ~p~n",[Rm]),
[] = os:cmd(Rm),
delete_release_win32(Dirs).
@@ -1200,7 +1654,12 @@ subst_var([], Vars, Result, VarAcc) ->
priv_dir(Conf) ->
- filename:absname(?config(priv_dir, Conf)). % Get rid of trailing slash
+%% filename:absname(?config(priv_dir, Conf)). % Get rid of trailing slash
+ %% Due to problem with long paths on windows => creating a new
+ %% priv_dir under data_dir
+ Dir = filename:absname(filename:join(?config(data_dir, Conf),priv_dir)),
+ filelib:ensure_dir(filename:join(Dir,"*")),
+ Dir.
latest_version(Dir) ->
List = filelib:wildcard(Dir ++ "*"),
@@ -1256,12 +1715,28 @@ do_create_p1g(Conf,TargetDir) ->
ErtsLatest = latest_version(filename:join(code:root_dir(),"erts")),
ok = copy_tree(Conf, ErtsLatest, ErtsDir, TargetDir),
ErtsBinDir = filename:join([TargetDir,ErtsDir,bin]),
- copy_file(filename:join([ErtsBinDir, "epmd"]), BinDir, [preserve]),
- copy_file(filename:join([ErtsBinDir, "run_erl"]), BinDir, [preserve]),
- copy_file(filename:join([ErtsBinDir, "to_erl"]), BinDir, [preserve]),
+
+ case os:type() of
+ {unix, _} ->
+ copy_file(filename:join([ErtsBinDir, "epmd"]), BinDir, [preserve]),
+ copy_file(filename:join([ErtsBinDir, "run_erl"]), BinDir, [preserve]),
+ copy_file(filename:join([ErtsBinDir, "to_erl"]), BinDir, [preserve]),
+
+ %% Create the start_erl shell script
+ ok = subst_file(filename:join([ErtsBinDir,"start_erl.src"]),
+ filename:join([BinDir,"start_erl"]),
+ [{"EMU","beam"}],
+ [{chmod,8#0755}]);
+ {win32,_} ->
+ %% Add a batch file to use as HEART_COMMAND
+ ok = copy_file(filename:join(DataDir, "heart_restart.bat"),
+ ErtsBinDir,[preserve])
+ end,
copy_file(filename:join(DataDir, "../installer.beam"),
filename:join([DataDir,lib,"installer-1.0",ebin])),
+ copy_file(filename:join(DataDir, "../rh_test_lib.beam"),
+ filename:join([DataDir,lib,"installer-1.0",ebin])),
%% Create .rel, .script and .boot files
RelName = "rel0",
@@ -1272,7 +1747,7 @@ do_create_p1g(Conf,TargetDir) ->
ok = filelib:ensure_dir(RelFile),
LibPath = filename:join([DataDir,lib,"*",ebin]),
- TarFile = create_basic_release(RelFile, RelVsn, {ErtsVsn,false},
+ TarFile = create_basic_release(Conf, RelFile, RelVsn, {ErtsVsn,false},
LibPath, [], [], [], []),
%% Extract tar file in target directory (i.e. same directory as erts etc.)
@@ -1286,20 +1761,6 @@ do_create_p1g(Conf,TargetDir) ->
%% Create RELEASES
ok = release_handler:create_RELEASES(TargetDir,ReleasesDir,RelFile,[]),
- %% Create start_erl
- ok = subst_file(filename:join([ErtsBinDir,"start_erl.src"]),
- filename:join([BinDir,"start_erl"]),
- [{"EMU","beam"}],
- [{chmod,8#0755}]),
-
- %% Create start script
- %% Using a customized start script from DataDir where some options
- %% (heart and nodename) are added compared to the start.src in the
- %% erlang distribution.
- ok = subst_file(filename:join(DataDir, "start"),
- filename:join([BinDir, "start"]),
- [{"ROOT",TargetDir}],
- [preserve]),
ok.
%% Create version P1H - which is P1G + a-1.0
@@ -1336,12 +1797,12 @@ create_upgrade_release(Conf,RelName,RelVsn,Erts,Apps,Config,{UpFromName,Descr})
UpFrom = [{filename:join([PrivDir,UpFromName,UpFromName]),Descr}],
- create_basic_release(RelFile, RelVsn, Erts, LibPath,
+ create_basic_release(Conf, RelFile, RelVsn, Erts, LibPath,
Apps, Config, UpFrom, []),
ok.
%% Create .rel, .script, .boot, sys.config and tar
-create_basic_release(RelFile,RelVsn,{ErtsVsn,ErtsDir},LibPath,ExtraApps,Config,UpFrom,DownTo) ->
+create_basic_release(Conf, RelFile,RelVsn,{ErtsVsn,ErtsDir},LibPath,ExtraApps,Config,UpFrom,DownTo) ->
RelDir = filename:dirname(RelFile),
RelFileName = filename:rootname(RelFile),
@@ -1370,7 +1831,14 @@ create_basic_release(RelFile,RelVsn,{ErtsVsn,ErtsDir},LibPath,ExtraApps,Config,U
_ -> [{erts,ErtsDir}]
end]),
- RelFileName ++ ".tar.gz".
+ TarFileName = RelFileName ++ ".tar.gz",
+
+ case os:type() of
+ {win32,_} when ErtsDir=/=false -> modify_tar_win32(Conf, TarFileName);
+ _ -> ok
+ end,
+
+ TarFileName.
%% Create a .rel file
create_installer_rel_file(RelFile,RelVsn,ErtsVsn,ExtraApps) ->
@@ -1470,21 +1938,70 @@ permanent_p1h(Node) ->
copy_installed(Conf,FromNode,ToNodes) ->
PrivDir = priv_dir(Conf),
DataDir = ?config(data_dir,Conf),
+
+ %% Instead of using copy_tree on the complete node directory, I'm
+ %% splitting this in separate tar files per subdirectory so the
+ %% log directory can be completely skipped. The reason for this is
+ %% that the tar file might become faulty if the node is alive and
+ %% writing to the log while the tar is created.
+ FromDir = filename:join(PrivDir,FromNode),
+ {ok,FromDirNames} = file:list_dir(FromDir),
+ TempTarFiles =
+ [begin
+ TempTarFile = filename:join(PrivDir,"temp_" ++ FDN ++ ".tar"),
+ {ok,Tar} = erl_tar:open(TempTarFile,[write]),
+ ok = erl_tar:add(Tar,filename:join(FromDir,FDN),FDN,[]),
+ ok = erl_tar:close(Tar),
+ TempTarFile
+ end || FDN <- FromDirNames, FDN=/="log"],
lists:foreach(
fun(Node) ->
- ok = copy_tree(Conf,filename:join(PrivDir,FromNode),Node,PrivDir),
NodeDir = filename:join(PrivDir,Node),
- ok = subst_file(filename:join(DataDir, "start"),
- filename:join([NodeDir, "bin", "start"]),
- [{"ROOT",NodeDir}]),
- LogDir = filename:join(NodeDir,log),
- {ok,Logs} = file:list_dir(LogDir),
- lists:foreach(fun(Log) ->
- file:delete(filename:join(LogDir,Log))
- end,
- Logs)
+ ok = filelib:ensure_dir(filename:join([NodeDir,"log","*"])),
+ lists:foreach(
+ fun(TempTarFile) ->
+ ok = erl_tar:extract(TempTarFile,[{cwd,NodeDir}])
+ end, TempTarFiles),
+ case os:type() of
+ {unix,_} ->
+ %% Create start script
+ %% Using a customized start script from DataDir
+ %% where some options (heart and nodename) are
+ %% added compared to the start.src in the erlang
+ %% distribution.
+ ok = subst_file(filename:join(DataDir, "start"),
+ filename:join([NodeDir, "bin", "start"]),
+ [{"ROOT",NodeDir}],
+ [preserve]);
+ {win32,_} ->
+ %% Write erl.ini
+ ErtsDirs =
+ filelib:wildcard(filename:join(NodeDir,"erts-*")),
+ lists:foreach(
+ fun(ErtsDir) ->
+ ok = subst_file(
+ filename:join(DataDir, "erl.ini.src"),
+ filename:join([ErtsDir, "bin", "erl.ini"]),
+ [{"ROOTDIR",NodeDir},
+ {"BINDIR",filename:join(ErtsDir,"bin")}])
+ end,
+ ErtsDirs),
+
+ %% The service on windows runs as local
+ %% administrator (not otptest user), so we need
+ %% to chmod the release in order to allow the
+ %% executing node to install releases, write
+ %% logs etc.
+ chmod_release_win32(NodeDir)
+ end
end,
- ToNodes).
+ ToNodes),
+
+ lists:foreach(fun(TempTarFile) -> file:delete(TempTarFile) end, TempTarFiles),
+ ok.
+
+chmod_release_win32(Dir) ->
+ os:cmd("echo y|cacls " ++ Dir ++ " /T /E /G Administrators:F").
start_nodes(Conf,Snames,Tag) ->
PrivDir = priv_dir(Conf),
@@ -1493,19 +2010,42 @@ start_nodes(Conf,Snames,Tag) ->
fun(Sname) ->
NodeDir = filename:join(PrivDir,Sname),
Node = node_name(Sname),
-
- Script = filename:join([NodeDir,"bin","start"]),
- Cmd = "env NODENAME="++atom_to_list(Sname) ++ " " ++ Script,
- %% {ok,StartFile} = file:read_file(Cmd),
- %% io:format("~s:\n~s~n~n",[Start,binary_to_list(StartFile)]),
- Res = os:cmd(Cmd),
- io:format("Start ~p: ~p~n=>\t~p~n", [Sname,Cmd,Res]),
+
+ case os:type() of
+ {unix,_} ->
+ start_node_unix(Sname,NodeDir);
+ {win32,_} ->
+ start_node_win32(Sname,NodeDir)
+ end,
Node
end,
Snames),
wait_nodes_up(Nodes,Tag),
Nodes.
+start_node_unix(Sname,NodeDir) ->
+ Script = filename:join([NodeDir,"bin","start"]),
+ Cmd = "env NODENAME="++atom_to_list(Sname) ++ " " ++ Script,
+ %% {ok,StartFile} = file:read_file(Cmd),
+ %% io:format("~s:\n~s~n~n",[Start,binary_to_list(StartFile)]),
+ Res = os:cmd(Cmd),
+ io:format("Start ~p: ~p~n=>\t~p~n", [Sname,Cmd,Res]).
+
+start_node_win32(Sname,NodeDir) ->
+ Name = atom_to_list(Sname) ++ "_P1G",
+ ErtsBinDir = filename:join(NodeDir,"erts-4.4/bin"),
+
+ StartErlArgs = rh_test_lib:get_start_erl_args(NodeDir),
+ ServiceArgs = rh_test_lib:get_service_args(NodeDir, Sname, StartErlArgs),
+
+ Erlsrv = filename:nativename(filename:join(ErtsBinDir,"erlsrv")),
+ rh_test_lib:erlsrv(Erlsrv,stop,Name),
+ rh_test_lib:erlsrv(Erlsrv,remove,Name),
+ ok = rh_test_lib:erlsrv(Erlsrv,add,Name,ServiceArgs),
+ ok = rh_test_lib:erlsrv(Erlsrv,start,Name),
+ ok.
+
+%% Create a unique node name for each test case
tc_sname(Config) ->
tc_sname(Config,"").
tc_sname(Config,Fix) when is_atom(Fix) ->
@@ -1607,9 +2147,8 @@ create_fake_upgrade_release(Dir,RelVsn,AppDirs,{UpFrom,DownTo,ExtraLibs}) ->
%% And a relup file so it can be upgraded to
RelupPath = Paths ++ [filename:join([Lib,"*","ebin"]) || Lib <- ExtraLibs],
- ok = systools:make_relup(Rel,[UpFrom],[DownTo],
- [{path,RelupPath},
- {outdir,RelDir}]),
+ ok = systools:make_relup(Rel,UpFrom,DownTo,[{path,RelupPath},
+ {outdir,RelDir}]),
Rel.
@@ -1649,3 +2188,32 @@ create_fake_release(Dir,RelName,RelVsn,AppDirs) ->
rpc_inst(Node,Func,Args) ->
rpc:call(Node,installer,Func,[node()|Args]).
+
+delete_all_services() ->
+ ErlSrv = erlsrv:erlsrv(erlang:system_info(version)),
+ [_|Serviceinfo] = string:tokens(os:cmd(ErlSrv ++ " list"),"\n"),
+ Services =
+ [lists:takewhile(fun($\t) -> false; (_) -> true end,S)
+ || S <- Serviceinfo],
+ ?t:format("Services to remove: ~p~n",[Services]),
+ lists:foreach(fun(S) ->
+ rh_test_lib:erlsrv(ErlSrv,stop,S),
+ rh_test_lib:erlsrv(ErlSrv,remove,S)
+ end,
+ Services).
+
+modify_tar_win32(Conf, TarFileName) ->
+ DataDir = ?config(data_dir,Conf),
+ PrivDir = priv_dir(Conf),
+ TmpDir = filename:join(PrivDir,"tmp_modify_tar_win32"),
+ ok = erl_tar:extract(TarFileName,[{cwd,TmpDir},compressed]),
+
+ ErtsBinDir = filelib:wildcard(filename:join([TmpDir,"erts-*","bin"])),
+ ok = copy_file(filename:join(DataDir, "heart_restart.bat"),
+ ErtsBinDir,[preserve]),
+
+ {ok,Fs} = file:list_dir(TmpDir),
+ {ok,T} = erl_tar:open(TarFileName,[write,compressed]),
+ [ok = erl_tar:add(T,filename:join(TmpDir,F),F,[]) || F <- Fs],
+ ok = erl_tar:close(T),
+ ok.
diff --git a/lib/sasl/test/release_handler_SUITE_data/Makefile.src b/lib/sasl/test/release_handler_SUITE_data/Makefile.src
index 85e25fdc2f..edb446413d 100644
--- a/lib/sasl/test/release_handler_SUITE_data/Makefile.src
+++ b/lib/sasl/test/release_handler_SUITE_data/Makefile.src
@@ -1,14 +1,42 @@
EFLAGS=+debug_info
P2B= \
- P2B/a-2.0/ebin/a.beam \
- P2B/a-2.0/ebin/a_sup.beam
+ P2B/a-2.0/ebin/a.@EMULATOR@ \
+ P2B/a-2.0/ebin/a_sup.@EMULATOR@
LIB= \
- lib/a-1.1/ebin/a.beam \
- lib/a-1.1/ebin/a_sup.beam \
- lib/a-1.0/ebin/a.beam \
- lib/a-1.0/ebin/a_sup.beam \
+ lib/a-1.2/ebin/a.@EMULATOR@ \
+ lib/a-1.2/ebin/a_sup.@EMULATOR@ \
+ lib/a-1.1/ebin/a.@EMULATOR@ \
+ lib/a-1.1/ebin/a_sup.@EMULATOR@ \
+ lib/a-1.0/ebin/a.@EMULATOR@ \
+ lib/a-1.0/ebin/a_sup.@EMULATOR@ \
+ lib/b-1.0/ebin/b_server.@EMULATOR@ \
+ lib/b-1.0/ebin/b_lib.@EMULATOR@ \
+ lib/b-2.0/ebin/b_server.@EMULATOR@ \
+ lib/many_mods-1.0/ebin/m.@EMULATOR@ \
+ lib/many_mods-1.0/ebin/m1.@EMULATOR@ \
+ lib/many_mods-1.0/ebin/m2.@EMULATOR@ \
+ lib/many_mods-1.0/ebin/m3.@EMULATOR@ \
+ lib/many_mods-1.0/ebin/m4.@EMULATOR@ \
+ lib/many_mods-1.0/ebin/m5.@EMULATOR@ \
+ lib/many_mods-1.0/ebin/m6.@EMULATOR@ \
+ lib/many_mods-1.0/ebin/m7.@EMULATOR@ \
+ lib/many_mods-1.0/ebin/m8.@EMULATOR@ \
+ lib/many_mods-1.0/ebin/m9.@EMULATOR@ \
+ lib/many_mods-1.0/ebin/m10.@EMULATOR@ \
+ lib/many_mods-1.1/ebin/m.@EMULATOR@ \
+ lib/many_mods-1.1/ebin/m1.@EMULATOR@ \
+ lib/many_mods-1.1/ebin/m2.@EMULATOR@ \
+ lib/many_mods-1.1/ebin/m3.@EMULATOR@ \
+ lib/many_mods-1.1/ebin/m4.@EMULATOR@ \
+ lib/many_mods-1.1/ebin/m5.@EMULATOR@ \
+ lib/many_mods-1.1/ebin/m6.@EMULATOR@ \
+ lib/many_mods-1.1/ebin/m7.@EMULATOR@ \
+ lib/many_mods-1.1/ebin/m8.@EMULATOR@ \
+ lib/many_mods-1.1/ebin/m9.@EMULATOR@ \
+ lib/many_mods-1.1/ebin/m10.@EMULATOR@ \
+ lib/many_mods-2.0/ebin/m.@EMULATOR@
APP= \
app1_app2/lib1/app1-1.0/ebin/app1_sup.@EMULATOR@ \
@@ -36,8 +64,13 @@ C= \
c/b.@EMULATOR@ \
c/c_sup.@EMULATOR@
+SUP= \
+ release_handler_timeouts/dummy-0.1/ebin/dummy_app.@EMULATOR@ \
+ release_handler_timeouts/dummy-0.1/ebin/dummy_server.@EMULATOR@ \
+ release_handler_timeouts/dummy-0.1/ebin/dummy_sup.@EMULATOR@ \
+ release_handler_timeouts/dummy-0.1/ebin/dummy_sup_2.@EMULATOR@
-all: $(P2B) $(LIB) $(APP) $(OTP2740) $(C)
+all: $(P2B) $(LIB) $(APP) $(OTP2740) $(C) $(SUP)
P2B/a-2.0/ebin/a.@EMULATOR@: P2B/a-2.0/src/a.erl
erlc $(EFLAGS) -oP2B/a-2.0/ebin P2B/a-2.0/src/a.erl
@@ -57,6 +90,67 @@ lib/a-1.1/ebin/a_sup.@EMULATOR@: lib/a-1.1/src/a_sup.erl
erlc $(EFLAGS) -olib/a-1.1/ebin lib/a-1.1/src/a_sup.erl
+lib/a-1.2/ebin/a.@EMULATOR@: lib/a-1.2/src/a.erl
+ erlc $(EFLAGS) -olib/a-1.2/ebin lib/a-1.2/src/a.erl
+lib/a-1.2/ebin/a_sup.@EMULATOR@: lib/a-1.2/src/a_sup.erl
+ erlc $(EFLAGS) -olib/a-1.2/ebin lib/a-1.2/src/a_sup.erl
+
+lib/b-1.0/ebin/b_server.@EMULATOR@: lib/b-1.0/src/b_server.erl
+ erlc $(EFLAGS) -olib/b-1.0/ebin lib/b-1.0/src/b_server.erl
+lib/b-1.0/ebin/b_lib.@EMULATOR@: lib/b-1.0/src/b_lib.erl
+ erlc $(EFLAGS) -olib/b-1.0/ebin lib/b-1.0/src/b_lib.erl
+
+lib/b-2.0/ebin/b_server.@EMULATOR@: lib/b-2.0/src/b_server.erl
+ erlc $(EFLAGS) -olib/b-2.0/ebin lib/b-2.0/src/b_server.erl
+
+lib/many_mods-1.0/ebin/m.@EMULATOR@: lib/many_mods-1.0/src/m.erl
+ erlc $(EFLAGS) -olib/many_mods-1.0/ebin lib/many_mods-1.0/src/m.erl
+lib/many_mods-1.0/ebin/m1.@EMULATOR@: lib/many_mods-1.0/src/m1.erl
+ erlc $(EFLAGS) -olib/many_mods-1.0/ebin lib/many_mods-1.0/src/m1.erl
+lib/many_mods-1.0/ebin/m2.@EMULATOR@: lib/many_mods-1.0/src/m2.erl
+ erlc $(EFLAGS) -olib/many_mods-1.0/ebin lib/many_mods-1.0/src/m2.erl
+lib/many_mods-1.0/ebin/m3.@EMULATOR@: lib/many_mods-1.0/src/m3.erl
+ erlc $(EFLAGS) -olib/many_mods-1.0/ebin lib/many_mods-1.0/src/m3.erl
+lib/many_mods-1.0/ebin/m4.@EMULATOR@: lib/many_mods-1.0/src/m4.erl
+ erlc $(EFLAGS) -olib/many_mods-1.0/ebin lib/many_mods-1.0/src/m4.erl
+lib/many_mods-1.0/ebin/m5.@EMULATOR@: lib/many_mods-1.0/src/m5.erl
+ erlc $(EFLAGS) -olib/many_mods-1.0/ebin lib/many_mods-1.0/src/m5.erl
+lib/many_mods-1.0/ebin/m6.@EMULATOR@: lib/many_mods-1.0/src/m6.erl
+ erlc $(EFLAGS) -olib/many_mods-1.0/ebin lib/many_mods-1.0/src/m6.erl
+lib/many_mods-1.0/ebin/m7.@EMULATOR@: lib/many_mods-1.0/src/m7.erl
+ erlc $(EFLAGS) -olib/many_mods-1.0/ebin lib/many_mods-1.0/src/m7.erl
+lib/many_mods-1.0/ebin/m8.@EMULATOR@: lib/many_mods-1.0/src/m8.erl
+ erlc $(EFLAGS) -olib/many_mods-1.0/ebin lib/many_mods-1.0/src/m8.erl
+lib/many_mods-1.0/ebin/m9.@EMULATOR@: lib/many_mods-1.0/src/m9.erl
+ erlc $(EFLAGS) -olib/many_mods-1.0/ebin lib/many_mods-1.0/src/m9.erl
+lib/many_mods-1.0/ebin/m10.@EMULATOR@: lib/many_mods-1.0/src/m10.erl
+ erlc $(EFLAGS) -olib/many_mods-1.0/ebin lib/many_mods-1.0/src/m10.erl
+lib/many_mods-1.1/ebin/m.@EMULATOR@: lib/many_mods-1.1/src/m.erl
+ erlc $(EFLAGS) -olib/many_mods-1.1/ebin lib/many_mods-1.1/src/m.erl
+lib/many_mods-1.1/ebin/m1.@EMULATOR@: lib/many_mods-1.1/src/m1.erl
+ erlc $(EFLAGS) -olib/many_mods-1.1/ebin lib/many_mods-1.1/src/m1.erl
+lib/many_mods-1.1/ebin/m2.@EMULATOR@: lib/many_mods-1.1/src/m2.erl
+ erlc $(EFLAGS) -olib/many_mods-1.1/ebin lib/many_mods-1.1/src/m2.erl
+lib/many_mods-1.1/ebin/m3.@EMULATOR@: lib/many_mods-1.1/src/m3.erl
+ erlc $(EFLAGS) -olib/many_mods-1.1/ebin lib/many_mods-1.1/src/m3.erl
+lib/many_mods-1.1/ebin/m4.@EMULATOR@: lib/many_mods-1.1/src/m4.erl
+ erlc $(EFLAGS) -olib/many_mods-1.1/ebin lib/many_mods-1.1/src/m4.erl
+lib/many_mods-1.1/ebin/m5.@EMULATOR@: lib/many_mods-1.1/src/m5.erl
+ erlc $(EFLAGS) -olib/many_mods-1.1/ebin lib/many_mods-1.1/src/m5.erl
+lib/many_mods-1.1/ebin/m6.@EMULATOR@: lib/many_mods-1.1/src/m6.erl
+ erlc $(EFLAGS) -olib/many_mods-1.1/ebin lib/many_mods-1.1/src/m6.erl
+lib/many_mods-1.1/ebin/m7.@EMULATOR@: lib/many_mods-1.1/src/m7.erl
+ erlc $(EFLAGS) -olib/many_mods-1.1/ebin lib/many_mods-1.1/src/m7.erl
+lib/many_mods-1.1/ebin/m8.@EMULATOR@: lib/many_mods-1.1/src/m8.erl
+ erlc $(EFLAGS) -olib/many_mods-1.1/ebin lib/many_mods-1.1/src/m8.erl
+lib/many_mods-1.1/ebin/m9.@EMULATOR@: lib/many_mods-1.1/src/m9.erl
+ erlc $(EFLAGS) -olib/many_mods-1.1/ebin lib/many_mods-1.1/src/m9.erl
+lib/many_mods-1.1/ebin/m10.@EMULATOR@: lib/many_mods-1.1/src/m10.erl
+ erlc $(EFLAGS) -olib/many_mods-1.1/ebin lib/many_mods-1.1/src/m10.erl
+lib/many_mods-2.0/ebin/m.@EMULATOR@: lib/many_mods-2.0/src/m.erl
+ erlc $(EFLAGS) -olib/many_mods-2.0/ebin lib/many_mods-2.0/src/m.erl
+
+
app1_app2/lib1/app1-1.0/ebin/app1_sup.@EMULATOR@: app1_app2/lib1/app1-1.0/src/app1_sup.erl
erlc $(EFLAGS) -oapp1_app2/lib1/app1-1.0/ebin app1_app2/lib1/app1-1.0/src/app1_sup.erl
app1_app2/lib1/app1-1.0/ebin/app1_server.@EMULATOR@: app1_app2/lib1/app1-1.0/src/app1_server.erl
@@ -106,3 +200,12 @@ c/b.@EMULATOR@: c/b.erl
erlc $(EFLAGS) -oc c/b.erl
c/c_sup.@EMULATOR@: c/c_sup.erl
erlc $(EFLAGS) -oc c/c_sup.erl
+
+release_handler_timeouts/dummy-0.1/ebin/dummy_app.@EMULATOR@: release_handler_timeouts/dummy-0.1/src/dummy_app.erl
+ erlc $(EFLAGS) -orelease_handler_timeouts/dummy-0.1/ebin release_handler_timeouts/dummy-0.1/src/dummy_app.erl
+release_handler_timeouts/dummy-0.1/ebin/dummy_server.@EMULATOR@: release_handler_timeouts/dummy-0.1/src/dummy_server.erl
+ erlc $(EFLAGS) -orelease_handler_timeouts/dummy-0.1/ebin release_handler_timeouts/dummy-0.1/src/dummy_server.erl
+release_handler_timeouts/dummy-0.1/ebin/dummy_sup.@EMULATOR@: release_handler_timeouts/dummy-0.1/src/dummy_sup.erl
+ erlc $(EFLAGS) -orelease_handler_timeouts/dummy-0.1/ebin release_handler_timeouts/dummy-0.1/src/dummy_sup.erl
+release_handler_timeouts/dummy-0.1/ebin/dummy_sup_2.@EMULATOR@: release_handler_timeouts/dummy-0.1/src/dummy_sup_2.erl
+ erlc $(EFLAGS) -orelease_handler_timeouts/dummy-0.1/ebin release_handler_timeouts/dummy-0.1/src/dummy_sup_2.erl
diff --git a/lib/sasl/test/release_handler_SUITE_data/clients/start_cli1 b/lib/sasl/test/release_handler_SUITE_data/clients/start_cli1
deleted file mode 100755
index ee3d8c97cf..0000000000
--- a/lib/sasl/test/release_handler_SUITE_data/clients/start_cli1
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/sh
-#
-# This program invokes the erlang emulator by calling run_erl.
-# It should only be used at an embedded target system.
-# It should be modified to give the correct flags to erl (via start_erl),
-# e.g -mode embedded -sname XXX
-#
-# Usage: start [Data]
-#
-
-if [ "x${NODENAME}" = "x" ]
-then
- echo "ERROR: Variable \$NODENAME is not set!!"
- exit 1
-fi
-
-TESTHOST=`hostname | sed 's/[.].*//'`
-IPADDR=%IPADDR%
-
-ROOTDIR=%ROOT%
-CLIENTDIR=$ROOTDIR/clients/type1/$NODENAME@$TESTHOST
-
-RELDIR=$CLIENTDIR/releases
-
-# Note that this scripts is modified an copied to $CLIENTDIR/bin/start
-# in release_handler_SUITE:copy_client - therefore HEART_COMMAND is as follows:
-HEART_COMMAND=$CLIENTDIR/bin/start
-HW_WD_DISABLE=true
-export HW_WD_DISABLE HEART_COMMAND
-
-START_ERL_DATA=${1:-$RELDIR/start_erl.data}
-
-if [ ! -d /tmp/$NODENAME@$TESTHOST ]
-then
- mkdir /tmp/$NODENAME@$TESTHOST
-fi
-
-$ROOTDIR/bin/run_erl /tmp/$NODENAME@$TESTHOST/ $CLIENTDIR/log "exec $ROOTDIR/bin/start_erl $ROOTDIR $RELDIR $START_ERL_DATA -heart -sname $NODENAME -sasl start_prg \\\"$CLIENTDIR/bin/start\\\" masters \[\\'%MASTER%@$TESTHOST\\'\] client_directory \\\"$CLIENTDIR\\\" -loader inet -id $NODENAME -hosts $IPADDR" > $CLIENTDIR/log/run_erl.out 2>&1 &
diff --git a/lib/sasl/test/release_handler_SUITE_data/erl.ini.src b/lib/sasl/test/release_handler_SUITE_data/erl.ini.src
new file mode 100644
index 0000000000..b8791e75a5
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/erl.ini.src
@@ -0,0 +1,4 @@
+[erlang]
+Bindir=%BINDIR%
+Progname=erl
+Rootdir=%ROOTDIR%
diff --git a/lib/sasl/test/release_handler_SUITE_data/heart_restart.bat b/lib/sasl/test/release_handler_SUITE_data/heart_restart.bat
new file mode 100644
index 0000000000..ede1ad4ff3
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/heart_restart.bat
@@ -0,0 +1,3 @@
+@echo off
+%ERLSRV_EXECUTABLE% stop %ERLSRV_SERVICE_NAME%
+%ERLSRV_EXECUTABLE% start %ERLSRV_SERVICE_NAME% \ No newline at end of file
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/README b/lib/sasl/test/release_handler_SUITE_data/lib/README
new file mode 100644
index 0000000000..639a4ca0fb
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/README
@@ -0,0 +1,33 @@
+a-1.0:
+start version
+
+a-1.1:
+can be upgraded to from a-1.0. Module a has changed
+
+a-1.2:
+can be upgraded to from a-1.1.
+No module have changed, but priv dir is added including one 'file'
+
+b-1.0:
+start version, includes b_lib and b_server
+
+b-2.0:
+can be upgraded to from b-1.0.
+Removes b_lib (soft_purge) and updates b_server (brutal_purge)
+* The diff in purge method is important for test "check_and_purge", in
+ order to check that the purge option to check_install_release works
+ for both methods.
+
+many_mods-1.0:
+start version.
+m:start/1 starts N procs, each calling Mod:bar() in all other modules (m1-m10).
+m1-m10: implements bar() which returns a big constant.
+The point is to get many processes with references to many modules,
+and then load the modules again so that old code exists. See tests
+otp_9395_update_many_mods and otp_9395_rm_many_mods.
+
+many_mods-1.1:
+can be upgraded to from many_mods-1.0. Updates modules m1-m10.
+
+many_mods-2.0:
+can be upgraded to from many_mods-1.0. Removes modules m1-m10. \ No newline at end of file
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/a-1.0/src/a.app b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/ebin/a.app
index e938137f67..b38722f06d 100644
--- a/lib/sasl/test/release_handler_SUITE_data/lib/a-1.0/src/a.app
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/ebin/a.app
@@ -1,7 +1,7 @@
{application, a,
[{description, "A CXC 138 11"},
- {vsn, "1.0"},
- {modules, [{a, 1}, {a_sup,1}]},
+ {vsn, "1.2"},
+ {modules, [{a, 2}, {a_sup,1}]},
{registered, [a_sup]},
{applications, [kernel, stdlib]},
{env, [{key1, val1}]},
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/ebin/a.appup b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/ebin/a.appup
new file mode 100644
index 0000000000..3df0546316
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/ebin/a.appup
@@ -0,0 +1,3 @@
+{"1.2",
+ [{"1.1",[]}],
+ [{"1.1",[]}]}.
diff --git a/bootstrap/lib/kernel/egen/.gitignore b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/priv/file
index e69de29bb2..e69de29bb2 100644
--- a/bootstrap/lib/kernel/egen/.gitignore
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/priv/file
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/src/a.erl b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/src/a.erl
new file mode 100644
index 0000000000..c082ad5339
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/src/a.erl
@@ -0,0 +1,54 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved via the world wide web at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
+%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
+%% AB. All Rights Reserved.''
+%%
+%% $Id$
+%%
+-module(a).
+
+
+-behaviour(gen_server).
+
+%% External exports
+-export([start_link/0, a/0, b/0]).
+%% Internal exports
+-export([init/1, handle_call/3, handle_info/2, terminate/2, code_change/3]).
+
+start_link() -> gen_server:start_link({local, aa}, a, [], []).
+
+a() -> gen_server:call(aa, a).
+b() -> gen_server:call(aa, b).
+
+%%-----------------------------------------------------------------
+%% Callback functions from gen_server
+%%-----------------------------------------------------------------
+init([]) ->
+ process_flag(trap_exit, true),
+ {ok, {state, bval}}.
+
+handle_call(a, _From, State) ->
+ X = application:get_all_env(a),
+ {reply, X, State};
+
+handle_call(b, _From, State) ->
+ {reply, {ok, element(2, State)}, State}.
+
+handle_info(_, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(1, Extra, State) ->
+ {ok, {state, bval}}.
diff --git a/lib/asn1/src/asn1_sup.erl b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/src/a_sup.erl
index a241dec6f4..a141c1767b 100644
--- a/lib/asn1/src/asn1_sup.erl
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/src/a_sup.erl
@@ -3,35 +3,35 @@
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved via the world wide web at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
%% AB. All Rights Reserved.''
-%%
+%%
%% $Id$
%%
+-module(a_sup).
-%% Purpose: Main supervisor in asn1 application.
-
--module(asn1_sup).
-behaviour(supervisor).
--export([start_link/0, init/1]).
+%% External exports
+-export([start/2]).
-start_link() ->
- supervisor:start_link({local, asn1_sup}, asn1_sup, []).
+%% Internal exports
+-export([init/1]).
+start(_, _) ->
+ supervisor:start_link({local, a_sup}, a_sup, []).
-%% init([])
-%% Returns: {ok, {SupFlags, [ChildSpec]}}
-%%
init([]) ->
- Child = {asn1_server, {asn1_server, start_link, []},
- permanent, 2000, worker, [asn1_server]},
- {ok, {{one_for_all, 10, 3600}, [Child]}}.
+ SupFlags = {one_for_one, 4, 3600},
+ Config = {a,
+ {a, start_link, []},
+ permanent, 2000, worker, [a]},
+ {ok, {SupFlags, [Config]}}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/b-1.0/ebin/b.app b/lib/sasl/test/release_handler_SUITE_data/lib/b-1.0/ebin/b.app
new file mode 100644
index 0000000000..00347b2754
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/b-1.0/ebin/b.app
@@ -0,0 +1,7 @@
+%% -*- erlang -*-
+{application, b,
+ [{description, "B CXC 138 12"},
+ {vsn, "1.0"},
+ {modules, [{b_server, 1},{b_lib, 1}]},
+ {registered, [b_server]},
+ {applications, [kernel, stdlib]}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/b-1.0/src/b_lib.erl b/lib/sasl/test/release_handler_SUITE_data/lib/b-1.0/src/b_lib.erl
new file mode 100644
index 0000000000..7e8a308a5e
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/b-1.0/src/b_lib.erl
@@ -0,0 +1,3 @@
+-module(b_lib).
+-compile(export_all).
+foo() -> ok.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/b-1.0/src/b_server.erl b/lib/sasl/test/release_handler_SUITE_data/lib/b-1.0/src/b_server.erl
new file mode 100644
index 0000000000..e1a80a076f
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/b-1.0/src/b_server.erl
@@ -0,0 +1,37 @@
+-module(b_server).
+
+-behaviour(gen_server).
+
+%% API
+-export([start_link/0]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+-define(SERVER, ?MODULE).
+
+-record(state, {}).
+
+start_link() ->
+ gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
+
+init([]) ->
+ {ok, #state{}}.
+
+handle_call(_Request, _From, State) ->
+ Reply = ok,
+ {reply, Reply, State}.
+
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(OldVsn, State, Extra) ->
+ file:write_file("/tmp/b_server",io_lib:format("~p~n",[{"1.0",OldVsn,Extra}])),
+ {ok, State}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/ebin/b.app b/lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/ebin/b.app
new file mode 100644
index 0000000000..73c8e42b32
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/ebin/b.app
@@ -0,0 +1,7 @@
+%% -*- erlang -*-
+{application, b,
+ [{description, "B CXC 138 12"},
+ {vsn, "2.0"},
+ {modules, [{b_server, 1}]},
+ {registered, [b_server]},
+ {applications, [kernel, stdlib]}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/ebin/b.appup b/lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/ebin/b.appup
new file mode 100644
index 0000000000..001255a88c
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/ebin/b.appup
@@ -0,0 +1,6 @@
+%% -*- erlang -*-
+{"2.0",
+ [{"1.0",[{remove_module,b_lib,soft_purge,soft_purge,[]},
+ {update,b_server,{advanced,[]}}]}],
+ [{"1.0",[{add_module,b_lib},
+ {update,b_server,{advanced,[]}}]}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/src/b_lib.erl b/lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/src/b_lib.erl
new file mode 100644
index 0000000000..7e8a308a5e
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/src/b_lib.erl
@@ -0,0 +1,3 @@
+-module(b_lib).
+-compile(export_all).
+foo() -> ok.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/src/b_server.erl b/lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/src/b_server.erl
new file mode 100644
index 0000000000..f8bfbdaff7
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/src/b_server.erl
@@ -0,0 +1,37 @@
+-module(b_server).
+
+-behaviour(gen_server).
+
+%% API
+-export([start_link/0]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+-define(SERVER, ?MODULE).
+
+-record(state, {}).
+
+start_link() ->
+ gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
+
+init([]) ->
+ {ok, #state{}}.
+
+handle_call(_Request, _From, State) ->
+ Reply = ok,
+ {reply, Reply, State}.
+
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(OldVsn, State, Extra) ->
+ file:write_file("/tmp/b_server",io_lib:format("~p~n",[{"2.0",OldVsn,Extra}])),
+ {ok, State}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/installer-1.0/ebin/installer.app b/lib/sasl/test/release_handler_SUITE_data/lib/installer-1.0/ebin/installer.app
index 6f77317f6a..e1391c0605 100644
--- a/lib/sasl/test/release_handler_SUITE_data/lib/installer-1.0/ebin/installer.app
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/installer-1.0/ebin/installer.app
@@ -1,6 +1,6 @@
{application, installer,
[{description, "Installer application"},
{vsn, "1.0"},
- {modules, [{installer, 1}]},
+ {modules, [installer,rh_test_lib]},
{registered, []},
{applications, [kernel, stdlib, sasl]}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/ebin/many_mods.app b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/ebin/many_mods.app
new file mode 100644
index 0000000000..aa39adfffa
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/ebin/many_mods.app
@@ -0,0 +1,17 @@
+%% -*- erlang -*-
+{application, many_mods,
+ [{description, "Application with many modules CXC 138 11"},
+ {vsn, "1.0"},
+ {modules, [{m, 1},
+ {m1,1},
+ {m2,1},
+ {m3,1},
+ {m4,1},
+ {m5,1},
+ {m6,1},
+ {m7,1},
+ {m8,1},
+ {m9,1},
+ {m10,1}]},
+ {registered, []},
+ {applications, [kernel, stdlib]}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m.erl
new file mode 100644
index 0000000000..418102bebb
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m.erl
@@ -0,0 +1,11 @@
+-module(m).
+-compile(export_all).
+
+start(NProcs) ->
+ Modules = [m1,m2,m3,m4,m5,m6,m7,m8,m9,m10],
+ Pids = [spawn_link(fun() ->
+ Cs = [M:bar() || M <- Modules],
+ receive stop -> Cs end
+ end) ||
+ _ <- lists:seq(1,NProcs)],
+ {Modules,Pids}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m1.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m1.erl
new file mode 100644
index 0000000000..cacc13f5d7
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m1.erl
@@ -0,0 +1,4 @@
+-module(m1).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m10.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m10.erl
new file mode 100644
index 0000000000..81e120b891
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m10.erl
@@ -0,0 +1,4 @@
+-module(m10).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m2.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m2.erl
new file mode 100644
index 0000000000..481276ba7b
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m2.erl
@@ -0,0 +1,4 @@
+-module(m2).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m3.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m3.erl
new file mode 100644
index 0000000000..9a04ed5fc9
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m3.erl
@@ -0,0 +1,4 @@
+-module(m3).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m4.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m4.erl
new file mode 100644
index 0000000000..90de9a30c9
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m4.erl
@@ -0,0 +1,4 @@
+-module(m4).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m5.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m5.erl
new file mode 100644
index 0000000000..8a9b690dfa
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m5.erl
@@ -0,0 +1,4 @@
+-module(m5).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m6.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m6.erl
new file mode 100644
index 0000000000..cd0d3977ed
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m6.erl
@@ -0,0 +1,4 @@
+-module(m6).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m7.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m7.erl
new file mode 100644
index 0000000000..1f79918d6e
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m7.erl
@@ -0,0 +1,4 @@
+-module(m7).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m8.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m8.erl
new file mode 100644
index 0000000000..2ce03a0b7e
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m8.erl
@@ -0,0 +1,4 @@
+-module(m8).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m9.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m9.erl
new file mode 100644
index 0000000000..1c5f72e628
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m9.erl
@@ -0,0 +1,4 @@
+-module(m9).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/ebin/many_mods.app b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/ebin/many_mods.app
new file mode 100644
index 0000000000..36c50caf2f
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/ebin/many_mods.app
@@ -0,0 +1,17 @@
+%% -*- erlang -*-
+{application, many_mods,
+ [{description, "Application with many modules CXC 138 11"},
+ {vsn, "1.1"},
+ {modules, [{m, 1},
+ {m1,1},
+ {m2,1},
+ {m3,1},
+ {m4,1},
+ {m5,1},
+ {m6,1},
+ {m7,1},
+ {m8,1},
+ {m9,1},
+ {m10,1}]},
+ {registered, []},
+ {applications, [kernel, stdlib]}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/ebin/many_mods.appup b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/ebin/many_mods.appup
new file mode 100644
index 0000000000..696435e06f
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/ebin/many_mods.appup
@@ -0,0 +1,22 @@
+%% -*- erlang -*-
+{"1.1",
+ [{"1.0",[{update,m1},
+ {update,m2},
+ {update,m3},
+ {update,m4},
+ {update,m5},
+ {update,m6},
+ {update,m7},
+ {update,m8},
+ {update,m9},
+ {update,m10}]}],
+ [{"1.0",[{update,m1},
+ {update,m2},
+ {update,m3},
+ {update,m4},
+ {update,m5},
+ {update,m6},
+ {update,m7},
+ {update,m8},
+ {update,m9},
+ {update,m10}]}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m.erl
new file mode 100644
index 0000000000..418102bebb
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m.erl
@@ -0,0 +1,11 @@
+-module(m).
+-compile(export_all).
+
+start(NProcs) ->
+ Modules = [m1,m2,m3,m4,m5,m6,m7,m8,m9,m10],
+ Pids = [spawn_link(fun() ->
+ Cs = [M:bar() || M <- Modules],
+ receive stop -> Cs end
+ end) ||
+ _ <- lists:seq(1,NProcs)],
+ {Modules,Pids}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m1.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m1.erl
new file mode 100644
index 0000000000..cacc13f5d7
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m1.erl
@@ -0,0 +1,4 @@
+-module(m1).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m10.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m10.erl
new file mode 100644
index 0000000000..81e120b891
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m10.erl
@@ -0,0 +1,4 @@
+-module(m10).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m2.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m2.erl
new file mode 100644
index 0000000000..481276ba7b
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m2.erl
@@ -0,0 +1,4 @@
+-module(m2).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m3.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m3.erl
new file mode 100644
index 0000000000..9a04ed5fc9
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m3.erl
@@ -0,0 +1,4 @@
+-module(m3).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m4.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m4.erl
new file mode 100644
index 0000000000..90de9a30c9
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m4.erl
@@ -0,0 +1,4 @@
+-module(m4).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m5.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m5.erl
new file mode 100644
index 0000000000..8a9b690dfa
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m5.erl
@@ -0,0 +1,4 @@
+-module(m5).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m6.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m6.erl
new file mode 100644
index 0000000000..cd0d3977ed
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m6.erl
@@ -0,0 +1,4 @@
+-module(m6).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m7.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m7.erl
new file mode 100644
index 0000000000..1f79918d6e
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m7.erl
@@ -0,0 +1,4 @@
+-module(m7).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m8.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m8.erl
new file mode 100644
index 0000000000..2ce03a0b7e
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m8.erl
@@ -0,0 +1,4 @@
+-module(m8).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m9.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m9.erl
new file mode 100644
index 0000000000..1c5f72e628
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m9.erl
@@ -0,0 +1,4 @@
+-module(m9).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-2.0/ebin/many_mods.app b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-2.0/ebin/many_mods.app
new file mode 100644
index 0000000000..98f6527750
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-2.0/ebin/many_mods.app
@@ -0,0 +1,7 @@
+%% -*- erlang -*-
+{application, many_mods,
+ [{description, "Application with many modules CXC 138 11"},
+ {vsn, "2.0"},
+ {modules, [{m, 1}]},
+ {registered, []},
+ {applications, [kernel, stdlib]}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-2.0/ebin/many_mods.appup b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-2.0/ebin/many_mods.appup
new file mode 100644
index 0000000000..3a34db78c1
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-2.0/ebin/many_mods.appup
@@ -0,0 +1,24 @@
+%% -*- erlang -*-
+{"2.0",
+ [{"1.0",[{update,m},
+ {delete_module,m1},
+ {delete_module,m2},
+ {delete_module,m3},
+ {delete_module,m4},
+ {delete_module,m5},
+ {delete_module,m6},
+ {delete_module,m7},
+ {delete_module,m8},
+ {delete_module,m9},
+ {delete_module,m10}]}],
+ [{"1.0",[{update,m},
+ {add_module,m1},
+ {add_module,m2},
+ {add_module,m3},
+ {add_module,m4},
+ {add_module,m5},
+ {add_module,m6},
+ {add_module,m7},
+ {add_module,m8},
+ {add_module,m9},
+ {add_module,m10}]}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-2.0/src/m.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-2.0/src/m.erl
new file mode 100644
index 0000000000..2edc1e6be4
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-2.0/src/m.erl
@@ -0,0 +1,11 @@
+-module(m).
+-compile(export_all).
+
+start(NProcs) ->
+ Modules = [],
+ Pids = [spawn_link(fun() ->
+ Cs = [M:bar() || M <- Modules],
+ receive stop -> Cs end
+ end) ||
+ _ <- lists:seq(1,NProcs)],
+ {Modules,Pids}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/ebin/dummy.app b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/ebin/dummy.app
new file mode 100644
index 0000000000..9efdc2e5da
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/ebin/dummy.app
@@ -0,0 +1,7 @@
+{application,dummy,
+ [{description,"a dummy app"},
+ {vsn,"0.1"},
+ {registered,[dummy_app]},
+ {mod,{dummy_app,[]}},
+ {applications,[kernel,stdlib,sasl]},
+ {modules,[dummy_app,dummy_server,dummy_sup,dummy_sup_2]}]}. \ No newline at end of file
diff --git a/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_app.erl b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_app.erl
new file mode 100644
index 0000000000..51363b3630
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_app.erl
@@ -0,0 +1,9 @@
+-module(dummy_app).
+-behaviour(application).
+
+-export([start/2, stop/1]).
+
+start(_,_) ->
+ dummy_sup:start_link().
+
+stop(_) -> ok.
diff --git a/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_server.erl b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_server.erl
new file mode 100644
index 0000000000..382251eba7
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_server.erl
@@ -0,0 +1,56 @@
+-module(dummy_server).
+-behaviour(gen_server).
+
+-export([start_link/0, set_state/1, get_state/0]).
+
+-export([init/1,
+ handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ terminate/2,
+ code_change/3]).
+
+%%
+
+start_link() ->
+ gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
+
+set_state(What) ->
+ gen_server:call(?MODULE, {set_state, What}).
+
+get_state() ->
+ gen_server:call(?MODULE, get_state).
+
+
+%%
+
+init([]) ->
+ say("init, setting state to 0", []),
+ {ok, 0}.
+
+
+handle_call({set_state, NewState}, _From, _State) ->
+ {reply, {ok, NewState}, NewState};
+
+handle_call(get_state, _From, State) ->
+ {reply, State, State}.
+
+handle_cast('__not_implemented', State) ->
+ {noreply, State}.
+
+handle_info(_Info, State) ->
+ say("info ~p, ~p.", [_Info, State]),
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ say("terminate ~p, ~p", [_Reason, _State]),
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ say("code_change ~p, ~p, ~p", [_OldVsn, State, _Extra]),
+ {ok, State}.
+
+%% Internal
+
+say(Format, Data) ->
+ io:format("~p:~p: ~s~n", [?MODULE, self(), io_lib:format(Format, Data)]).
diff --git a/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_sup.erl b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_sup.erl
new file mode 100644
index 0000000000..3d7b5060df
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_sup.erl
@@ -0,0 +1,15 @@
+-module(dummy_sup).
+-behaviour(supervisor).
+
+-export([start_link/0]).
+-export([init/1]).
+
+start_link() ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+init([]) ->
+ DummySup2 = {dummy_sup_2,
+ {dummy_sup_2, start_link, []},
+ permanent, 5000, supervisor, [dummy_sup_2]},
+
+ {ok, {{one_for_one, 10, 10}, [DummySup2]}}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_sup_2.erl b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_sup_2.erl
new file mode 100644
index 0000000000..d936cbcbd6
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_sup_2.erl
@@ -0,0 +1,15 @@
+-module(dummy_sup_2).
+-behaviour(supervisor).
+
+-export([start_link/0]).
+-export([init/1]).
+
+start_link() ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+init([]) ->
+ Dummy = {dummy_server,
+ {dummy_server, start_link, []},
+ permanent, 5000, worker, [dummy_server]},
+
+ {ok, {{one_for_one, 10, 10}, [Dummy]}}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/clients/start_cli2 b/lib/sasl/test/release_handler_SUITE_data/start_client
index 88912cf884..5ea94d6f7c 100755
--- a/lib/sasl/test/release_handler_SUITE_data/clients/start_cli2
+++ b/lib/sasl/test/release_handler_SUITE_data/start_client
@@ -34,4 +34,4 @@ then
mkdir /tmp/$NODENAME@$TESTHOST
fi
-$ROOTDIR/bin/run_erl /tmp/$NODENAME@$TESTHOST/ $CLIENTDIR/log "exec $ROOTDIR/bin/start_erl $ROOTDIR $RELDIR $START_ERL_DATA -heart -sname $NODENAME -sasl start_prg \\\"$CLIENTDIR/bin/start\\\" masters \[\\'%MASTER%@$TESTHOST\\',\\'master2@$TESTHOST\\'\] client_directory \\\"$CLIENTDIR\\\"" > /dev/null 2>&1 &
+$ROOTDIR/bin/run_erl /tmp/$NODENAME@$TESTHOST/ $CLIENTDIR/log "exec $ROOTDIR/bin/start_erl $ROOTDIR $RELDIR $START_ERL_DATA -heart -sname $NODENAME %CLIENTARGS%" > $CLIENTDIR/log/run_erl.out 2>&1 &
diff --git a/lib/sasl/test/rh_test_lib.erl b/lib/sasl/test/rh_test_lib.erl
new file mode 100644
index 0000000000..99a7f919a7
--- /dev/null
+++ b/lib/sasl/test/rh_test_lib.erl
@@ -0,0 +1,100 @@
+-module(rh_test_lib).
+
+-export([erlsrv/3,
+ erlsrv/4]).
+-export([get_service_args/3,
+ get_service_args/4,
+ get_start_erl_args/1,
+ get_start_erl_args/3,
+ get_client_args/3,
+ get_client_args/4]).
+
+
+erlsrv(Erlsrv,Action,Name) ->
+ erlsrv(Erlsrv,Action,Name,"").
+erlsrv(Erlsrv,Action,Name,Rest) ->
+ Cmd = Erlsrv ++ " " ++ atom_to_list(Action) ++ " " ++ Name ++ " " ++ Rest,
+ io:format("erlsrv cmd: ~p~n",[Cmd]),
+ Port = open_port({spawn, Cmd}, [stream, {line, 100}, eof, in]),
+ Res = recv_prog_output(Port),
+ case Res of
+ [] ->
+ failed;
+ _Y ->
+ io:format("erlsrv res: ~p~n",[_Y]),
+ ok
+ end.
+
+recv_prog_output(Port) ->
+ receive
+ {Port, {data, {eol,Data}}} ->
+ %%io:format("Got data: ~s~n", [Data]),
+ [ Data, "\n" | recv_prog_output(Port)];
+ {Port, {data, {noeol,Data}}} ->
+ %%io:format("Got data: ~s~n", [Data]),
+ [ Data | recv_prog_output(Port)];
+ {Port, _Other} ->
+ %%io:format("Got ~p from port~n", [_Other]),
+ Port ! {self(), close},
+ receive
+ {Port,closed} ->
+ []
+ end
+ end.
+
+get_service_args(RootDir, Sname, StartErlArgs) ->
+ get_service_args(RootDir, "", Sname, StartErlArgs).
+get_service_args(RootDir, RelClientDir, Sname, StartErlArgs) ->
+ LogDir = filename:nativename(filename:join([RootDir,RelClientDir,"log"])),
+ %% start_erl.exe will be found since it is in the same directory as erlsrv.exe
+ %% And heart_restart.bat will be found since the erts bin dir is
+ %% always in the path for the erlang virtual machine.
+ " -machine start_erl.exe -workdir " ++ LogDir ++
+ " -debugtype new -sname " ++ atom_to_list(Sname) ++
+ " -env HEART_COMMAND=heart_restart.bat -args \"" ++ StartErlArgs ++ "\"".
+
+get_start_erl_args(RootDir) ->
+ get_start_erl_args(RootDir,"","").
+get_start_erl_args(RootDir,RelClientDir,ExtraArgs) ->
+ Cookie = atom_to_list(erlang:get_cookie()),
+ RelDir = filename:join([RootDir,RelClientDir,"releases"]),
+ ExtraArgs ++ " -setcookie " ++ Cookie ++
+ " -heart ++ -rootdir " ++ filename:nativename(RootDir) ++
+ " -reldir " ++ filename:nativename(RelDir).
+
+%% Must be called on the master node
+get_client_args(Client,Sname,RootDir) ->
+ get_client_args(Client,Sname,RootDir,node()).
+get_client_args(Client,Sname,RootDir,Master) ->
+ {ok,Host} = inet:gethostname(),
+ Node = atom_to_list(Sname) ++ "@" ++ Host,
+ RelClientDir = filename:join(["clients","type1",Node]),
+ ClientDir = filename:join([RootDir,RelClientDir]),
+ StartPrg = filename:join([ClientDir,"bin","start"]),
+ {" -sasl start_prg \\\\\\\"" ++ StartPrg ++ "\\\\\\\" masters \[" ++
+ single_quote() ++ atom_to_list(Master) ++ single_quote() ++
+ get_client_extra_master(Client,Host) ++
+ "\] client_directory \\\\\\\"" ++ ClientDir ++ "\\\\\\\"" ++
+ get_client_loader_args(Client,Sname,Host),
+ RelClientDir}.
+
+get_client_loader_args(client1,Sname,Host) ->
+ {ok,IpTuple} = inet:getaddr(Host,inet),
+ IpAddr = inet_parse:ntoa(IpTuple),
+ " -loader inet -id " ++
+ atom_to_list(Sname) ++ " -hosts " ++ IpAddr;
+get_client_loader_args(_,_,_) ->
+ "".
+
+get_client_extra_master(client2,Host) ->
+ "," ++ single_quote() ++ "master2@" ++ Host ++ single_quote();
+get_client_extra_master(_,_) ->
+ "".
+
+single_quote() ->
+ case os:type() of
+ {win32,_} ->
+ "\'";
+ _ ->
+ "\\'"
+ end.
diff --git a/lib/sasl/test/systools_SUITE.erl b/lib/sasl/test/systools_SUITE.erl
index 9190b111ef..e352247d44 100644
--- a/lib/sasl/test/systools_SUITE.erl
+++ b/lib/sasl/test/systools_SUITE.erl
@@ -48,7 +48,7 @@
included_fail_script/1, included_bug_script/1, exref_script/1]).
-export([ tar_options/1, normal_tar/1, no_mod_vsn_tar/1, variable_tar/1,
src_tests_tar/1, shadow_tar/1, var_tar/1,
- exref_tar/1, link_tar/1]).
+ exref_tar/1, link_tar/1, otp_9507/1]).
-export([ normal_relup/1, abnormal_relup/1, no_appup_relup/1,
bad_appup_relup/1, app_start_type_relup/1, otp_3065/1]).
-export([
@@ -81,7 +81,7 @@ groups() ->
{tar, [],
[tar_options, normal_tar, no_mod_vsn_tar, variable_tar,
src_tests_tar, shadow_tar, var_tar,
- exref_tar, link_tar]},
+ exref_tar, link_tar, otp_9507]},
{relup, [],
[normal_relup, abnormal_relup, no_appup_relup,
bad_appup_relup, app_start_type_relup]},
@@ -396,6 +396,7 @@ src_tests_script(Config) when is_list(Config) ->
?line PSAVE = code:get_path(), % Save path
?line {LatestDir, LatestName} = create_script(latest,Config),
+ ?line BootFile = LatestName ++ ".boot",
?line DataDir = filename:absname(?copydir),
?line LibDir = fname([DataDir, d_missing_src, lib]),
@@ -416,14 +417,32 @@ src_tests_script(Config) when is_list(Config) ->
?line Erl2 = filename:join([P1,"..","src","db2.erl"]),
?line file:delete(Erl2),
- %% Then make script - two warnings should be issued when
- %% src_tests is given
+ %% Then make script
+
+ %% .boot file should not exist
+ ?line ok = file:delete(BootFile),
+ ?line false = filelib:is_regular(BootFile),
+ %% With warnings_as_errors and src_tests option, an error should be issued
+ ?line error =
+ systools:make_script(LatestName, [silent, {path, N}, src_tests,
+ warnings_as_errors]),
+ ?line error =
+ systools:make_script(LatestName, [{path, N}, src_tests,
+ warnings_as_errors]),
+
+ %% due to warnings_as_errors .boot file should still not exist
+ ?line false = filelib:is_regular(BootFile),
+
+ %% Two warnings should be issued when src_tests is given
%% 1. old object code for db1.beam
%% 2. missing source code for db2.beam
?line {ok, _, [{warning,{obj_out_of_date,_}},
{warning,{source_not_found,_}}]} =
systools:make_script(LatestName, [silent, {path, N}, src_tests]),
+ %% .boot file should exist now
+ ?line true = filelib:is_regular(BootFile),
+
%% Without the src_tests option, no warning should be issued
?line {ok, _, []} =
systools:make_script(LatestName, [silent, {path, N}]),
@@ -1066,6 +1085,48 @@ exref_tar(Config) when is_list(Config) ->
?line ok = file:set_cwd(OldDir),
ok.
+
+
+%% otp_9507
+%%
+otp_9507(suite) -> [];
+otp_9507(doc) ->
+ ["make_tar failed when path given as just 'ebin'."];
+otp_9507(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+
+ ?line {LatestDir, LatestName} = create_script(latest_small,Config),
+
+ ?line DataDir = filename:absname(?copydir),
+ ?line LibDir = fname([DataDir, d_normal, lib]),
+ ?line FeDir = fname([LibDir, 'fe-3.1']),
+
+ ?line ok = file:set_cwd(FeDir),
+
+ RelName = fname([LatestDir,LatestName]),
+
+ ?line P1 = ["./ebin",
+ fname([DataDir, lib, kernel, ebin]),
+ fname([DataDir, lib, stdlib, ebin])],
+ ?line {ok, _, _} = systools:make_script(RelName, [silent, {path, P1}]),
+ ?line ok = systools:make_tar(RelName, [{path, P1}]),
+ ?line Content1 = tar_contents(RelName),
+
+ ?line P2 = ["ebin",
+ fname([DataDir, lib, kernel, ebin]),
+ fname([DataDir, lib, stdlib, ebin])],
+
+ %% Tickets solves the following line - it used to fail with
+ %% {function_clause,[{filename,join,[[]]},...}
+ ?line ok = systools:make_tar(RelName, [{path, P2}]),
+ ?line Content2 = tar_contents(RelName),
+ true = (Content1 == Content2),
+
+ ?line ok = file:set_cwd(OldDir),
+
+ ok.
+
+
%% The relup stuff.
%%
%%
@@ -1108,6 +1169,21 @@ normal_relup(Config) when is_list(Config) ->
[{path, P}, silent]),
?line ok = check_relup([{db, "2.1"}], [{db, "1.0"}]),
+ %% file should not be written if warnings_as_errors is enabled.
+ %% delete before running tests.
+ ?line ok = file:delete("relup"),
+
+ %% Check that warnings are treated as errors
+ ?line error =
+ systools:make_relup(LatestName, [LatestName2], [LatestName1],
+ [{path, P}, warnings_as_errors]),
+ ?line error =
+ systools:make_relup(LatestName, [LatestName2], [LatestName1],
+ [{path, P}, silent, warnings_as_errors]),
+
+ %% relup file should not exist
+ ?line false = filelib:is_regular("relup"),
+
%% Check that warnings get through
?line ok = systools:make_relup(LatestName, [LatestName2], [LatestName1],
[{path, P}]),
@@ -1117,6 +1193,9 @@ normal_relup(Config) when is_list(Config) ->
[{path, P}, silent]),
?line ok = check_relup([{fe, "3.1"}, {db, "2.1"}], [{db, "1.0"}]),
+ %% relup file should exist now
+ ?line true = filelib:is_regular("relup"),
+
?line ok = file:set_cwd(OldDir),
ok.
diff --git a/lib/sasl/vsn.mk b/lib/sasl/vsn.mk
index 26dc2c1448..2db134af48 100644
--- a/lib/sasl/vsn.mk
+++ b/lib/sasl/vsn.mk
@@ -1 +1 @@
-SASL_VSN = 2.1.9.4
+SASL_VSN = 2.1.10
diff --git a/lib/snmp/Makefile b/lib/snmp/Makefile
index 20e3d4692a..4264531112 100644
--- a/lib/snmp/Makefile
+++ b/lib/snmp/Makefile
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2009. All Rights Reserved.
+# Copyright Ericsson AB 1996-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -67,7 +67,7 @@ do_configure: configure
configure: configure.in
autoconf
-.PHONY: info
+.PHONY: info gclean
info:
@echo "OS: $(OS)"
@@ -76,6 +76,9 @@ info:
@echo "SNMP_VSN: $(SNMP_VSN)"
@echo "APP_VSN: $(APP_VSN)"
+gclean:
+ git clean -fXd
+
# ----------------------------------------------------
# Application (source) release targets
diff --git a/lib/snmp/doc/src/Makefile b/lib/snmp/doc/src/Makefile
index 35ed63e103..df597c8ba7 100644
--- a/lib/snmp/doc/src/Makefile
+++ b/lib/snmp/doc/src/Makefile
@@ -28,14 +28,6 @@ VSN = $(SNMP_VSN)
APPLICATION=snmp
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -88,40 +80,10 @@ MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
MAN6_FILES = $(XML_REF6_FILES:%_app.xml=$(MAN6DIR)/%.6)
MAN7_FILES = $(MIB_FILES:$(MIBSDIR)/%.mib=$(MAN7DIR)/%.7)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = \
- $(XML_REF1_FILES:%.xml=%.tex) \
- $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_REF6_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_PART_FILES = $(XML_PART_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = snmp-$(VSN).pdf
-TOP_PS_FILE = snmp-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- @echo "building $(TOP_PDF_FILE)"
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- @echo "building $(TOP_PS_FILE)"
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-TOP_HTML_FILES = $(INDEX_TARGET)
-
-endif
-
INDEX_FILE = index.html
INDEX_SRC = $(INDEX_FILE).src
INDEX_TARGET = $(DOCDIR)/$(INDEX_FILE)
@@ -141,8 +103,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif # Copy them to ../html
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
ldocs: local_docs $(INDEX_TARGET)
@@ -152,51 +112,11 @@ $(TOP_PDF_FILE): $(XML_FILES)
pdf: $(TOP_PDF_FILE)
html: gifs $(HTML_REF_MAN_FILE)
+html2: html $(INDEX_TARGET)
clean clean_docs: clean_html clean_man clean_pdf
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES) $(TOP_HTML_FILES) gifs
-
-html2: gifs $(TOP_HTML_FILES) $(HTML_FILES) $(HTML_REF1_FILES) $(HTML_REF3_FILES) $(HTML_REF6_FILES) $(HTML_CHAP_FILES)
-
-clean: clean_tex clean_html clean_man clean_docs
-
-
-clean_tex:
- @echo "cleaning tex:"
- rm -f $(TEX_FILES_USERS_GUIDE)
- rm -f $(TEX_FILES_REF_MAN)
- rm -f $(TEX_PART_FILES)
- rm -f $(TEX_FILES_BOOK)
-
-clean_docs:
- @echo "cleaning docs:"
- rm -f $(TOP_PDF_FILE)
- rm -f $(TOP_PS_FILE)
- rm -f core $(LATEX_CLEAN)
-
-
-$(HTML_PART_FILES): notes.xml
-
-endif
-
$(INDEX_TARGET): $(INDEX_SRC) ../../vsn.mk # Create top make file
sed -e 's;%VSN%;$(VSN);' $< > $@ # inserting version number
@@ -228,6 +148,7 @@ clean_man:
clean_html:
@echo "cleaning html:"
rm -rf $(HTMLDIR)/*
+ rm -f $(INDEX_TARGET)
$(MAN7DIR)/%.7: $(MIBSDIR)/%.mib
@echo "processing $*"
@@ -248,8 +169,6 @@ $(MAN1DIR)/snmpc.1: snmpc_cmd.xml
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
$(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
$(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
@@ -266,55 +185,13 @@ release_docs_spec: docs
$(INSTALL_DIR) $(RELEASE_PATH)/man/man7
$(INSTALL_DATA) $(MAN7DIR)/* $(RELEASE_PATH)/man/man7
-else
-
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man1
- $(INSTALL_DATA) $(MAN1_FILES) $(RELEASE_PATH)/man/man1
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man6
- $(INSTALL_DATA) $(MAN6_FILES) $(RELEASE_PATH)/man/man6
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man7
- $(INSTALL_DATA) $(MAN7_FILES) $(RELEASE_PATH)/man/man7
- $(INSTALL_DATA) $(TOP_HTML_FILES) \
- $(RELSYSDIR)/doc
-endif
-endif
-
-endif
-
release_spec:
-ifdef DOCSUPPORT
info: info_xml info_man info_html
@echo "MAN1DIR: $(MAN1DIR)"
@echo "MAN3DIR: $(MAN3DIR)"
@echo "MAN6DIR: $(MAN6DIR)"
@echo "MAN7DIR: $(MAN7DIR)"
-else
-info: info_xml info_man info_html info_tex
- @echo "DVI2PS = $(DVI2PS)"
- @echo "DVIPS_FLAGS = $(DVIPS_FLAGS)"
- @echo ""
- @echo "DISTILL = $(DISTILL)"
- @echo "DISTILL_FLAGS = $(DISTILL_FLAGS)"
-endif
info_man:
@echo "man files:"
@@ -360,14 +237,3 @@ info_html:
@echo "HTML_REF3_FILES = $(HTML_REF3_FILES)"
@echo "HTML_REF6_FILES = $(HTML_REF6_FILES)"
@echo "HTML_CHAP_FILES = $(HTML_CHAP_FILES)"
-
-info_tex:
- @echo "tex files:"
- @echo "TEX_FILES_USERS_GUIDE = $(TEX_FILES_USERS_GUIDE)"
- @echo "TEX_FILES_REF_MAN = $(TEX_FILES_REF_MAN)"
- @echo "TEX_PART_FILES = $(TEX_PART_FILES)"
- @echo "TEX_FILES_BOOK = $(TEX_FILES_BOOK)"
-
-ifndef DOCSUPPORT
-include depend.mk
-endif
diff --git a/lib/snmp/doc/src/depend.mk b/lib/snmp/doc/src/depend.mk
deleted file mode 100644
index 20a523dd8c..0000000000
--- a/lib/snmp/doc/src/depend.mk
+++ /dev/null
@@ -1,83 +0,0 @@
-#-*-makefile-*- ; force emacs to enter makefile-mode
-
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2004-2011. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-
-$(HTMLDIR)/part_notes.html: \
- part_notes_history.xml \
- part_notes.xml \
- notes_history.xml \
- notes.xml
-
-$(HTMLDIR)/part.html: \
- part.xml \
- snmp_intro.xml \
- snmp_agent_funct_descr.xml \
- snmp_manager_funct_descr.xml \
- snmp_mib_compiler.xml \
- snmp_config.xml \
- snmp_agent_config_files.xml \
- snmp_manager_config_files.xml \
- snmp_impl_example_agent.xml \
- snmp_impl_example_manager.xml \
- snmp_instr_functions.xml \
- snmp_def_instr_functions.xml \
- snmp_agent_netif.xml \
- snmp_manager_netif.xml \
- snmp_audit_trail_log.xml \
- snmp_advanced_agent.xml \
- snmp_app_a.xml \
- snmp_app_b.xml
-
-$(HTMLDIR)/ref_man.html: \
- ref_man.xml \
- snmp_app.xml \
- snmp.xml \
- snmpc.xml \
- snmpc_cmd.xml \
- snmpa.xml \
- snmpa_conf.xml \
- snmpa_discovery_handler.xml \
- snmpa_error_report.xml \
- snmpa_error.xml \
- snmpa_error_io.xml \
- snmpa_error_logger.xml \
- snmpa_local_db.xml \
- snmpa_mpd.xml \
- snmpa_network_interface.xml \
- snmpa_network_interface_filter.xml \
- snmpa_notification_delivery_info_receiver.xml \
- snmpa_notification_filter.xml \
- snmpa_supervisor.xml \
- snmp_community_mib.xml \
- snmp_framework_mib.xml \
- snmp_generic.xml \
- snmp_index.xml \
- snmp_notification_mib.xml \
- snmp_pdus.xml \
- snmp_standard_mib.xml \
- snmp_target_mib.xml \
- snmp_user_based_sm_mib.xml \
- snmp_view_based_acm_mib.xml \
- snmpm.xml \
- snmpm_conf.xml \
- snmpm_mpd.xml \
- snmpm_network_interface.xml \
- snmpm_network_interface_filter.xml \
- snmpm_user.xml
-
-
diff --git a/lib/snmp/doc/src/make.dep b/lib/snmp/doc/src/make.dep
deleted file mode 100644
index 223e197f25..0000000000
--- a/lib/snmp/doc/src/make.dep
+++ /dev/null
@@ -1,77 +0,0 @@
-#-*-makefile-*- ; force emacs to enter makefile-mode
-
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2011. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex part.tex ref_man.tex snmp.tex snmp_advanced_agent.tex \
- snmp_agent_config_files.tex snmp_agent_funct_descr.tex \
- snmp_agent_netif.tex snmp_app.tex snmp_app_a.tex \
- snmp_app_b.tex snmp_audit_trail_log.tex \
- snmp_community_mib.tex \
- snmp_config.tex snmp_def_instr_functions.tex \
- snmp_framework_mib.tex snmp_generic.tex \
- snmp_impl_example_agent.tex \
- snmp_impl_example_manager.tex snmp_index.tex \
- snmp_instr_functions.tex snmp_intro.tex \
- snmp_manager_config_files.tex \
- snmp_manager_funct_descr.tex snmp_manager_netif.tex \
- snmp_mib_compiler.tex snmp_notification_mib.tex \
- snmp_pdus.tex snmp_standard_mib.tex snmp_target_mib.tex \
- snmp_user_based_sm_mib.tex snmp_view_based_acm_mib.tex \
- snmpa.tex snmpa_conf.tex snmpa_error.tex snmpa_error_io.tex \
- snmpa_error_logger.tex snmpa_error_report.tex \
- snmpa_local_db.tex snmpa_mpd.tex \
- snmpa_discovery_handler.tex \
- snmpa_network_interface.tex \
- snmpa_network_interface_filter.tex \
- snmpa_notification_delivery_info_receiver.tex \
- snmpa_notification_filter.tex \
- snmpa_supervisor.tex \
- snmpc.tex snmpc_cmd.tex snmpm.tex snmpm_conf.tex snmpm_mpd.tex \
- snmpm_network_interface.tex snmpm_network_interface_filter.tex \
- snmpm_user.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: MIB_mechanism.ps snmp-um-1-image-1.ps snmp-um-1-image-2.ps \
- snmp-um-1-image-3.ps
-
-book.dvi: snmp_agent_netif_1.ps
-
-book.dvi: getnext1.ps getnext2.ps getnext3.ps getnext4.ps
-
-book.dvi: snmp_manager_netif_1.ps
-
diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml
index 6a20d8ee3a..fd5a548b16 100644
--- a/lib/snmp/doc/src/notes.xml
+++ b/lib/snmp/doc/src/notes.xml
@@ -32,6 +32,306 @@
<file>notes.xml</file>
</header>
+
+ <section>
+ <title>SNMP Development Toolkit 4.21.3</title>
+ <p>Version 4.21.3 supports code replacement in runtime from/to
+ version 4.21.2, 4.21.1, 4.21 and 4.20.1. </p>
+
+ <section>
+ <title>Improvements and new features</title>
+<!--
+ <p>-</p>
+-->
+
+ <list type="bulleted">
+ <item>
+ <p>[compiler] Improved version info printout. </p>
+ <p>Own Id: OTP-9618</p>
+ </item>
+
+ </list>
+ </section>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+<!--
+ <p>-</p>
+-->
+
+ <list type="bulleted">
+ <item>
+ <p>[compiler] Fix the <c>--warnings/--W</c> option parsing in the
+ <seealso marker="snmpc(command)#option_warnings">snmpc</seealso>
+ wrapper (e)script.
+ The short warning option was incorrectly <c>--w</c>, instead
+ of as documented <c>--W</c>. This has now been corrected. </p>
+ <p>*** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>Tuncer Ayaz</p>
+ <p>Own Id: OTP-9718</p>
+ </item>
+
+ </list>
+
+ </section>
+
+
+ <section>
+ <title>Incompatibilities</title>
+<!--
+ <p>-</p>
+-->
+
+ <list type="bulleted">
+ <item>
+ <p>[compiler] The short warning option has been changed from
+ <c>--w</c> to <c>--W</c> to comply with the documentation. </p>
+ <p>Tuncer Ayaz</p>
+ <p>Own Id: OTP-9718</p>
+ </item>
+
+
+ </list>
+ </section>
+
+ </section> <!-- 4.21.3 -->
+
+
+ <section>
+ <title>SNMP Development Toolkit 4.21.2</title>
+ <p>Version 4.21.2 supports code replacement in runtime from/to
+ version 4.21.1, 4.21, 4.20.1, 4.20 and 4.19. </p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <p>-</p>
+
+<!--
+ <list type="bulleted">
+ <item>
+ <p>Bad note store GC timer deactivation.
+ Wrong field in the state record was set (timeout instead active). </p>
+ <p>Stefan Grundmann</p>
+ <p>Own Id: OTP-9690</p>
+ </item>
+
+ </list>
+-->
+
+ </section>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+<!--
+ <p>-</p>
+-->
+
+ <list type="bulleted">
+ <item>
+ <p>Bad note store GC timer deactivation.
+ Wrong field in the state record was set (timeout instead active). </p>
+ <p>Stefan Grundmann</p>
+ <p>Own Id: OTP-9690</p>
+ </item>
+
+ </list>
+ </section>
+
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+
+ </section> <!-- 4.21.2 -->
+
+
+ <section>
+ <title>SNMP Development Toolkit 4.21.1</title>
+ <p>Version 4.21.1 supports code replacement in runtime from/to
+ version 4.20.1, 4.20 and 4.19. </p>
+
+ <section>
+ <title>Improvements and new features</title>
+<!--
+ <p>-</p>
+-->
+ <list type="bulleted">
+ <item>
+ <p>[compiler] Used wrong variable name (for
+ warnings-as-errors variable), which caused the
+ compiler to crash when using the snmpc (e)script. </p>
+ <p>Also added the option
+ <seealso marker="snmpc(command)#option_werror">--Werror</seealso>
+ for the SNMP MIB compiler (escript) frontend (to mimic
+ <seealso marker="erts:erlc">erlc</seealso>),
+ which specifies whether warnings should be treated as errors. </p>
+ <p>Own Id: OTP-9447</p>
+ </item>
+
+ <item>
+ <p>[agent] Some very minor debugging improvements. </p>
+ <p>Own Id: OTP-9446</p>
+ </item>
+ </list>
+
+ </section>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+ <p>-</p>
+
+<!--
+ <list type="bulleted">
+ <item>
+ <p>The snmp config tool could not handle (manager) audit trail config
+ because the option seqno was not handled. </p>
+ <p>Own Id: OTP-9354</p>
+ </item>
+
+ </list>
+-->
+ </section>
+
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+
+ </section> <!-- 4.21.1 -->
+
+
+ <section>
+ <title>SNMP Development Toolkit 4.21</title>
+ <p>Version 4.21 supports code replacement in runtime from/to
+ version 4.20.1, 4.20 and 4.19. </p>
+
+ <section>
+ <title>Improvements and new features</title>
+<!--
+ <p>-</p>
+-->
+ <list type="bulleted">
+ <item>
+ <p>[manager] There was no way to specify transport domain.
+ The transport domains was assumed to be IPv4 (transportDomainUdpIpv4).
+ This has now been changed so that it can also be IPv6
+ (transportDomainUdpIpv6).
+ To facilitate this, the transport domain, <c>tdomain</c>,
+ is now a (new) valid option when
+ <seealso marker="snmpm#register_agent">registering</seealso>
+ a new agent (and
+ <seealso marker="snmpm#update_agent_info">updating</seealso>
+ agent info). </p>
+ <p>This also mean that the transport behaviour has changed. </p>
+ <p>Own Id: OTP-9305</p>
+ <p>Aux Id: Seq 11847</p>
+ </item>
+
+ <item>
+ <p>[compiler] Added the option
+ <seealso marker="snmpc#compile">warnings_as_errors</seealso>
+ (for the SNMP MIB compiler (escript) frontend, the option
+ <seealso marker="snmpc(command)#option_wae">--wae</seealso> is used)
+ which specifies whether warnings should be treated as errors. </p>
+ <p>Tuncer Ayaz</p>
+ <p>Own Id: OTP-9437</p>
+ </item>
+ </list>
+
+ </section>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+<!--
+ <p>-</p>
+-->
+
+ <list type="bulleted">
+ <item>
+ <p>The snmp config tool could not handle (manager) audit trail config
+ because the option seqno was not handled. </p>
+ <p>Own Id: OTP-9354</p>
+ </item>
+
+ <item>
+ <p>[agent] The SNMP ACM cache was not properly updated when
+ changes where made to the VACM security-to-group, access and
+ view-tree-family tables. </p>
+ <p>Own Id: OTP-9367</p>
+ <p>Aux Id: Seq 11858</p>
+ </item>
+
+ <item>
+ <p>Fixed install directory typo for man3. </p>
+ <p>Peter Lemenkov</p>
+ <p>Hans Ulrich Niedermann</p>
+ <p>Own Id: OTP-9442</p>
+ </item>
+
+ </list>
+ </section>
+
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+
+ </section> <!-- 4.21 -->
+
+
+ <section>
+ <title>SNMP Development Toolkit 4.20.1</title>
+ <p>Version 4.20.1 supports code replacement in runtime from/to
+ version 4.20, 4.19 and 4.18.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <p>-</p>
+<!--
+ <list type="bulleted">
+ <item>
+ <p>Added type specs for functions that do not return. </p>
+ <p>Kostis Sagonas</p>
+ <p>Own Id: OTP-9208</p>
+ </item>
+ </list>
+-->
+ </section>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+<!--
+ <p>-</p>
+-->
+ <list type="bulleted">
+ <item>
+ <p>[agent] Did not handle transport domains properly in some cases,
+ for instance trap sending. </p>
+ <p>Own Id: OTP-9400</p>
+ </item>
+
+ <item>
+ <p>[agent] Wrong default transport domain, snmpUDPDomain, instead
+ of transportDomainUdpIpv4. </p>
+ <p>Own Id: OTP-9425</p>
+ <p>Aux Id: Seq 11874</p>
+ </item>
+
+ </list>
+ </section>
+
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+
+ </section> <!-- 4.20.1 -->
+
+
<section>
<title>SNMP Development Toolkit 4.20</title>
<p>Version 4.20 supports code replacement in runtime from/to
@@ -620,927 +920,6 @@ snmp_view_basec_acm_mib:vacmAccessTable(set, RowIndex, Cols).
</section> <!-- 4.15 -->
- <section>
- <title>SNMP Development Toolkit 4.14</title>
-
- <p>Version 4.14 supports code replacement in runtime from/to
- version 4.13.5, 4.13.4, 4.13.3, 4.13.2, 4.13.1 and 4.13.</p>
-
- <section>
- <title>Improvements and new features</title>
- <!--
- <p>-</p>
- -->
-
- <list type="bulleted">
- <item>
- <p>[compiler] Include object- and notification groups in the
- compiled mib.
- This will make it possible to import groups from other mibs. </p>
- <p>Also the SNMPv2-MIB-file has been updated to a more
- up-to-date version. </p>
- <p>Own Id: OTP-8223</p>
- <!-- <p>Aux Id: Seq 11383</p> -->
- </item>
-
- <item>
- <p>[manager] Added support for message filtering in the
- network interface module provided with the application.
- The component that actually make the filter decisions
- is the network interface filter module. This module
- must implement the
- <seealso marker="snmpm_network_interface_filter">network interface filter behaviour</seealso>
- for message filtering.
- See also the Configuring chapter of
- the User's Guide to see how to configure this feature. </p>
- <p>See the
- <seealso marker="snmp_app#configuration_params">configuration</seealso>
- chapter for more info about the filter options.</p>
- <p>Own Id: OTP-8228</p>
- <p>Aux Id: Seq 11411</p>
- </item>
-
- <item>
- <p>The MIBs delivered as part of the application is now
- also available as man pages, section 7. </p>
- <p>Own Id: OTP-8237</p>
- <!-- <p>Aux Id: Seq 11383</p> -->
- </item>
-
- </list>
-
- </section>
-
- <section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <p>-</p>
-
- <!--
- <list type="bulleted">
- <item>
- <p>[agent] The main agent type header file contained some miss-information
- regarding the type of the entrytype field of the me-record, causing
- unneccessary confusion.</p>
- <p>Own Id: OTP-8116</p>
- <p>Aux Id: Seq 11312</p>
- </item>
-
- </list>
- -->
-
- </section>
-
- <section>
- <title>Incompatibilities</title>
- <p>-</p>
- </section>
- </section> <!-- 4.14 -->
-
-
- <section>
- <title>SNMP Development Toolkit 4.13.5</title>
-
- <p>Version 4.13.5 supports code replacement in runtime from/to
- version 4.13.4, 4.13.3, 4.13.2, 4.13.1 and 4.13.</p>
-
- <section>
- <title>Improvements and new features</title>
- <!--
- <p>-</p>
- -->
-
- <list type="bulleted">
- <item>
- <p>[agent] Improved the cache handling of the mib server. </p>
- <p>A number of new functions and config options for the mib server
- cache has been added. </p>
- <p>See
- <seealso marker="snmpa#invalidate_mibs_cache">invalidate_mibs_cache/0,1</seealso>,
- <seealso marker="snmpa#enable_mibs_cache">enable_mibs_cache/0,1</seealso>,
- <seealso marker="snmpa#disable_mibs_cache">disable_mibs_cache/0,1</seealso>,
- <seealso marker="snmpa#gc_mibs_cache">gc_mibs_cache/0,1,2,3</seealso>,
- <seealso marker="snmpa#enable_mibs_cache_autogc">enable_mibs_cache_autogc/0,1</seealso>,
- <seealso marker="snmpa#disable_mibs_cache_autogc">disable_mibs_cache_autogc/0,1</seealso>,
- <seealso marker="snmpa#update_mibs_cache_age">update_mibs_cache_age/1,2</seealso> and
- <seealso marker="snmpa#update_mibs_cache_gclimit">update_mibs_cache_gclimit/1,2</seealso> for more info. </p>
- <p>See also the
- <seealso marker="snmp_app#configuration_params">configuration</seealso>
- chapter for more info about the mib server cache options.</p>
- <p>Own Id: OTP-8182</p>
- <p>Aux Id: Seq 11383</p>
- </item>
-
- <item>
- <p>[agent] A manager could no longer use the SNMPv3 user "initial"
- as this was interpretated as the first step of the discovery. </p>
- <p>Introduced a new terminating option, <c>trigger_username</c> to
- make it possible to configure the username the agent reacts to.
- Default is <c>""</c>. </p>
- <p>See the
- <seealso marker="snmp_app#configuration_params">configuration</seealso>
- chapter for more info about the discovery options.</p>
- <p>Own Id: OTP-8120</p>
- <p>Aux Id: Seq 11361</p>
- </item>
-
- </list>
-
- </section>
-
- <section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <!--
- <p>-</p>
- -->
- <list type="bulleted">
- <item>
- <p>[agent] The main agent type header file contained some miss-information
- regarding the type of the entrytype field of the me-record, causing
- unneccessary confusion.</p>
- <p>Own Id: OTP-8116</p>
- <p>Aux Id: Seq 11312</p>
- </item>
-
- </list>
-
- </section>
-
- <section>
- <title>Incompatibilities</title>
- <p>-</p>
- </section>
- </section> <!-- 4.13.5 -->
-
-
- <section>
- <title>SNMP Development Toolkit 4.13.4</title>
-
- <p>Version 4.13.4 supports code replacement in runtime from/to
- version 4.13.3, 4.13.2, 4.13.1 and 4.13.</p>
-
- <section>
- <title>Improvements and new features</title>
- <p>-</p>
-
- <!--
- <list type="bulleted">
- <item>
- <p>[agent] Support for the discovery process. </p>
- <p>The agent can both initiate discovery itself (see the
- <seealso marker="snmp_agent_funct_descr#discovery">discovery</seealso> chapter
- for more info) and respond to discovery initiated by a manager.</p>
- <p>Own Id: OTP-7571</p>
- <p>Aux Id: Seq 11053</p>
- </item>
-
- </list>
- -->
-
- </section>
-
- <section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <!--
- <p>-</p>
- -->
- <list type="bulleted">
- <item>
- <p>[agent] Originating discovery problems. </p>
- <p>Invalid state variable update during second stage of
- discovery causes master agent crash. </p>
- <p>Also the net_if process failed to activate socket
- ({active, once}) after first discovery response was sent. </p>
- <p>Own Id: OTP-8044</p>
- <p>Aux Id: Seq 11295</p>
- </item>
-
- <item>
- <p>[agent] Terminating discovery problem. </p>
- <p>The reply to the second stage request should include a
- varbind with <c>usmStatsNotInTimeWindows</c>.</p>
- <p>Own Id: OTP-8062</p>
- <p>Aux Id: Seq 11318</p>
- </item>
-
- <item>
- <p>[agent] Originating discovery improvement. </p>
- <p>Added the ExtraInfo argument to the
- <seealso marker="snmpa#discovery">discovery</seealso> function.
- This argument will be passed on to the stage1_finish callback
- function. Also, the
- <seealso marker="snmpa#discovery">discovery</seealso> function
- will now always return <c>{ok, ManagerEngineID}</c> on successful
- discovery. </p>
- <p>The <seealso marker="snmpa_discovery_handler">discovery handler</seealso>
- behaviour updated accordingly. </p>
- <p>Own Id: OTP-8098</p>
- <p>Aux Id: Seq 11346</p>
- </item>
-
- </list>
-
- </section>
-
- <section>
- <title>Incompatibilities</title>
- <p>-</p>
- </section>
- </section> <!-- 4.13.4 -->
-
-
- <section>
- <title>SNMP Development Toolkit 4.13.3</title>
-
- <p>Version 4.13.3 supports code replacement in runtime from/to
- version 4.13.2, 4.13.1 and 4.13.</p>
-
- <section>
- <title>Improvements and new features</title>
- <p>-</p>
-
- <!--
- <list type="bulleted">
- <item>
- <p>[agent] Support for the discovery process. </p>
- <p>The agent can both initiate discovery itself (see the
- <seealso marker="snmp_agent_funct_descr#discovery">discovery</seealso> chapter
- for more info) and respond to discovery initiated by a manager.</p>
- <p>Own Id: OTP-7571</p>
- <p>Aux Id: Seq 11053</p>
- </item>
-
- </list>
- -->
-
- </section>
-
- <section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <!--
- <p>-</p>
- -->
- <list type="bulleted">
- <item>
- <p>[manager] A request for an oid of type BITS was actually
- returned as OCTET STRING. </p>
- <p>Values of type BITS are encoded as OCTET STRING,
- which makes it impossible for the decoder to know that
- they should really be of type BITS.
- Instead, this has to be done higher up in the stack, where
- there is knowledge of the MIB (assuming that the mib has
- been loaded, there is info about the type of the mibentry). </p>
- <p>This problem has now been fixed, but requires that the MIB
- defining this mib-entry is loaded! </p>
- <p>The utility function
- <seealso marker="snmpm#oid_to_type">oid_to_type</seealso>
- has been added, for debug purpose. </p>
- <p>The utility function(s)
- <seealso marker="snmp#octet_string_to_bits">octet_string_to_bits</seealso>
- and
- <seealso marker="snmp#bits_to_octet_string">bits_to_octet_string</seealso>
- has also been added. These can be used if the user prefers to
- handle the conversion on their own. </p>
- <p>Own Id: OTP-8015</p>
- <p>Aux Id: Seq 11285</p>
- </item>
-
- <item>
- <p>[agent] Fixed some issues with the discovery handling. </p>
- <p>Changed the API of the
- <seealso marker="snmpa#discovery">discovery</seealso>
- function to solve some
- of these problems. </p>
- <p>Introduced various options for controlling the discovery
- process. See the
- <seealso marker="snmp_app#configuration_params">configuration</seealso>
- chapter for more info about the discovery options.</p>
- <p>Own Id: OTP-8020</p>
- <p>Aux Id: Seq 11295</p>
- </item>
-
- </list>
-
- </section>
-
- <section>
- <title>Incompatibilities</title>
- <p>-</p>
- </section>
- </section> <!-- 4.13.3 -->
-
-
- <section>
- <title>SNMP Development Toolkit 4.13.2</title>
-
- <p>Version 4.13.2 supports code replacement in runtime from/to
- version 4.13.1 and 4.13.</p>
-
- <section>
- <title>Improvements and new features</title>
- <p>-</p>
-
- <!--
- <list type="bulleted">
- <item>
- <p>[agent] Support for the discovery process. </p>
- <p>The agent can both initiate discovery itself (see the
- <seealso marker="snmp_agent_funct_descr#discovery">discovery</seealso> chapter
- for more info) and respond to discovery initiated by a manager.</p>
- <p>Own Id: OTP-7571</p>
- <p>Aux Id: Seq 11053</p>
- </item>
-
- </list>
- -->
-
- </section>
-
- <section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <!--
- <p>-</p>
- -->
- <list type="bulleted">
- <item>
- <p>[manager] Failure during downed user cleanup.
- As part of the cleanup after a crashed user,
- the manager attempts to unregister the agents
- registered by this user. This however failed,
- causing a server crash. </p>
- <p>Own Id: OTP-7961</p>
- <p>Aux Id: Seq 11275</p>
- </item>
-
- <item>
- <p>[manager] Incorrectly documented value type for
- IpAddress (ip). The value type for IpAddress is
- documented as ip but is actually ia. The value type
- ip has been added. The old (not documented) value
- type ia still works. </p>
- <p>Own Id: OTP-7977</p>
- <p>Aux Id: Seq 11279</p>
- </item>
-
- <item>
- <p>[manager] EngineId lookup fails when using version-3. </p>
- <p>Own Id: OTP-7983</p>
- <p>Aux Id: Seq 11275</p>
- </item>
-
- <item>
- <p>[agent] As of version 4.13 the possible return values
- of the function
- <seealso marker="snmpa_mpd#process_packet">snmpa_mpd:process_packet/4</seealso>
- changed, but this was not documented. </p>
- <p>Own Id: OTP-7989</p>
- <p>Aux Id: Seq 11275</p>
- </item>
-
- </list>
-
- </section>
-
- <section>
- <title>Incompatibilities</title>
- <p>-</p>
- </section>
- </section> <!-- 4.13.2 -->
-
- <section>
- <title>SNMP Development Toolkit 4.13.1</title>
-
- <p>Version 4.13.1 supports code replacement in runtime from/to
- version 4.13.</p>
-
- <section>
- <title>Improvements and new features</title>
- <p>-</p>
-
- <!--
- <list type="bulleted">
- <item>
- <p>[agent] Support for the discovery process. </p>
- <p>The agent can both initiate discovery itself (see the
- <seealso marker="snmp_agent_funct_descr#discovery">discovery</seealso> chapter
- for more info) and respond to discovery initiated by a manager.</p>
- <p>Own Id: OTP-7571</p>
- <p>Aux Id: Seq 11053</p>
- </item>
-
- </list>
- -->
-
- </section>
-
- <section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <!--
- <p>-</p>
- -->
- <list type="bulleted">
- <item>
- <p>[manager] Registration of users had some issues. </p>
- <p>Not all of the registration functions where actually exported
- (<seealso marker="snmpm#register_user">register_user/4</seealso>
- and
- <seealso marker="snmpm#register_user_monitor">register_user_monitor/4</seealso>).
- This has now been fixed. </p>
- <p>Also, the registration did not succeed unless
- user implemented the *new* behaviour. This has now
- also been fixed (registration succeeds if the user
- implements either the new (i.e. updated
- <seealso marker="snmpm_user">snmpm_user</seealso>)
- or the old user behaviour (<c>snmpm_user_old</c>)). </p>
- <p>Own Id: OTP-7902</p>
- <p>Aux Id: Seq 11240</p>
- </item>
-
- </list>
-
- </section>
-
- <section>
- <title>Incompatibilities</title>
- <p>-</p>
- </section>
- </section> <!-- 4.13.1 -->
-
- <section>
- <title>SNMP Development Toolkit 4.13</title>
-<!--
- <p>Version 4.13 supports code replacement in runtime from/to
- version 4.12.1.</p>
--->
-
- <section>
- <title>Improvements and new features</title>
- <!--
- <p>-</p>
- -->
- <list type="bulleted">
- <item>
- <p>[agent] Support for the discovery process. </p>
- <p>The agent can both initiate discovery itself (see the
- <seealso marker="snmp_agent_funct_descr#discovery">discovery</seealso> chapter
- for more info) and respond to discovery initiated by a manager.</p>
- <p>Own Id: OTP-7571</p>
- <p>Aux Id: Seq 11053</p>
- </item>
-
- </list>
-
- </section>
-
- <section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <!--
- <p>-</p>
- -->
- <list type="bulleted">
- <item>
- <p>[agent] Unnecessary use of math:pow/2 could cause problems
- on systems without floating point support. </p>
- <p>Per Hedeland</p>
- <p>Own Id: OTP-7735</p>
- <!-- <p>Aux Id: Seq 10966</p> -->
- </item>
-
- <item>
- <p>[manager] A major flaw was discovered with the agent handling. </p>
- <p>First, <c>TargetName</c> was never used as intended, as a unique
- identifier for the target (agent in this case). </p>
- <p>Second, <c>TargetName</c> had a <em>default value</em>, which meant
- that several agents could have the same <c>TargetName</c>, causing
- unpredictable behaviour in the manager. </p>
- <p>Third, <c>EngineID</c> was not a mandatory config option and had
- furthermore also a <em>default value</em>. </p>
-
- <p>These problems has been solved in the following way: </p>
- <p>First, a new set of api functions has been introduced (and documented):
- <seealso marker="snmpm#register_user">register_user/4</seealso>,
- <seealso marker="snmpm#register_user_monitor">register_user_monitor/4</seealso>,
- <seealso marker="snmpm#register_agent">register_agent/3</seealso>,
- <seealso marker="snmpm#unregister_agent">unregister_agent/2</seealso>,
- <seealso marker="snmpm#agent_info">agent_info/2</seealso>,
- <seealso marker="snmpm#update_agent_info">update_agent_info/4</seealso>,
- <seealso marker="snmpm#sync_get">sync_get/3,4,5,6</seealso>,
- <seealso marker="snmpm#async_get">async_get/3,4,5,6</seealso>,
- <seealso marker="snmpm#sync_get_next">sync_get_next/3,4,5,6</seealso>,
- <seealso marker="snmpm#async_get_next">async_get_next/3,4,5,6</seealso>,
- <seealso marker="snmpm#sync_set">sync_set/3,4,5,6</seealso>,
- <seealso marker="snmpm#async_set">async_set/3,4,5,6</seealso>,
- <seealso marker="snmpm#sync_get_bulk">sync_get_bulk/5,6,7,8</seealso> and
- <seealso marker="snmpm#async_get_bulk">async_get_bulk/5,6,7,8</seealso>
- that all use <c>TargetName</c> (and not, as previously, <c>Addr</c>
- and <c>Port</c>) to identify the agent (also the return value of
- <seealso marker="snmpm#which_agents">which_agents</seealso> has
- been changed). </p>
- <p>Second, for backward compatibility, the old functions still
- exist, but are no longer documented and are now wrappers for the
- new functions, including erroneous default value for EngineID and
- all. The TargetName is however generated from the provided
- <c>Addr</c>, <c>Port</c> and <c>Version</c> config options. </p>
- <p>Third, the behaviour of the
- <seealso marker="snmpm_user">SNMP manager user</seealso> has
- been changed to reflect this, i.e.
- <seealso marker="snmpm_user#handle_pdu">handle_pdu/4</seealso>,
- <seealso marker="snmpm_user#handle_trap">handle_trap/3</seealso>,
- <seealso marker="snmpm_user#handle_inform">handle_inform/3</seealso>,
- <seealso marker="snmpm_user#handle_report">handle_report/3</seealso>
- and the return-value of
- <seealso marker="snmpm_user#handle_agent">handle_agent/4</seealso>.
- The old (non-documented) callback-functions (using Addr and Port)
- will still be called if the agent was registered using the old
- registration functions. </p>
-
- <p>Own Id: OTP-7836</p>
- <!-- <p>Aux Id: Seq 10966</p> -->
- </item>
-
- </list>
-
- </section>
-
- <section>
- <title>Incompatibilities</title>
- <p>-</p>
- </section>
- </section> <!-- 4.13 -->
-
- <section>
- <title>SNMP Development Toolkit 4.12.2</title>
- <p>Version 4.12.2 supports code replacement in runtime from/to
- version 4.12.1, 4.12, 4.11.2, 4.11.1 and 4.11.</p>
-
- <section>
- <title>Improvements and new features</title>
- <p>-</p>
- <!--
- <list type="bulleted">
- <item>
- <item>
- <p>[agent] Improvement of the inform reporting.
- It was previously not certain how many acks an
- application received, 0, 1 or 2. This has now been
- fixed, so that only 1 (one) ack is issued. </p>
- <p>Per Hedeland</p>
- <p>Own Id: OTP-7525</p>
- </item>
-
- </list>
- -->
-
- </section>
-
- <section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <!--
- <p>-</p>
- -->
- <list type="bulleted">
- <item>
- <p>[agent] Bad session cache (usm+camv-info) invalidation
- could cause user crash, through call(s) to (a number of)
- MIB API function(s) (undefined function). </p>
- <p>Own Id: OTP-7868</p>
- <!-- <p>Aux Id: Seq 11124</p> -->
- </item>
-
- </list>
-
- </section>
-
- <section>
- <title>Incompatibilities</title>
- <p>-</p>
- </section>
- </section> <!-- 4.12.2 -->
-
- <section>
- <title>SNMP Development Toolkit 4.12.1</title>
- <p>Version 4.12.1 supports code replacement in runtime from/to
- version 4.12, 4.11.2, 4.11.1 and 4.11.</p>
-
- <section>
- <title>Improvements and new features</title>
- <p>-</p>
- <!--
- <list type="bulleted">
- <item>
- <item>
- <p>[agent] Improvement of the inform reporting.
- It was previously not certain how many acks an
- application received, 0, 1 or 2. This has now been
- fixed, so that only 1 (one) ack is issued. </p>
- <p>Per Hedeland</p>
- <p>Own Id: OTP-7525</p>
- </item>
-
- </list>
- -->
-
- </section>
-
- <section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <!--
- <p>-</p>
- -->
- <list type="bulleted">
- <item>
- <p>Logging of messages with the GetBulk-request PDU
- incorrectly produced an erroneous entry in the
- log: "An error occurred". </p>
- <p>The reason for this was that the PDU-fields
- error_status and error_index is re-used for
- Non-repeaters and Max-repetitions for
- GetBulk-request PDUs, but this was not handled
- by the logging code. </p>
- <p>Own Id: OTP-7695</p>
- <p>Aux Id: Seq 11124</p>
- </item>
-
- <item>
- <p>[agent] An attempt to set the row status to active for an
- notReady table row, could result in an "inconsistentValue"
- error. </p>
- <p>The same problem existed when attempting to set row status
- to notInService for a row in notReady. </p>
- <p>Serge Aleynikov</p>
- <p>Own Id: OTP-7698</p>
- <!-- <p>Aux Id: Seq 10966</p> -->
- </item>
-
- </list>
-
- </section>
-
- <section>
- <title>Incompatibilities</title>
- <p>-</p>
- </section>
- </section> <!-- 4.12.1 -->
-
- <section>
- <title>SNMP Development Toolkit 4.12</title>
- <p>Version 4.12 supports code replacement in runtime from/to
- version 4.11.2, 4.11.1 and 4.11.</p>
-
- <section>
- <title>Improvements and new features</title>
- <!--
- <p>-</p>
- -->
- <list type="bulleted">
- <item>
- <p>[agent] A simple lookup cache has been added to improve
- the mib server lookup performance. </p>
- <p>This can be disabled with the mib_server
- <seealso marker="snmp_app">cache</seealso> option. </p>
- <p>Own Id: OTP-7346</p>
- </item>
-
- <item>
- <p>[agent] Improvement of the inform reporting.
- It was previously not certain how many acks an
- application received, 0, 1 or 2. This has now been
- fixed, so that only 1 (one) ack is issued. </p>
- <p>Per Hedeland</p>
- <p>Own Id: OTP-7525</p>
- </item>
-
- </list>
-
- </section>
-
- <section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <p>-</p>
- <!--
- <list type="bulleted">
- <item>
- <p>[manager] Encryption error when attempting to send
- version 3 inform-requests. </p>
- <p>Own Id: OTP-7432</p>
- <p>Aux Id: Seq 10966</p>
- </item>
-
- </list>
- -->
-
- </section>
-
- <section>
- <title>Incompatibilities</title>
- <p>-</p>
- </section>
- </section> <!-- 4.12 -->
-
- <section>
- <title>SNMP Development Toolkit 4.11.2</title>
- <p>Version 4.11.2 supports code replacement in runtime from/to
- version 4.11.1 and 4.11. </p>
-
- <section>
- <title>Improvements and new features</title>
- <p>-</p>
- <!--
- <list type="bulleted">
- <item>
- <p>Added utility functions for transforming DateAndTime
- as [int()] to strings;
- <seealso marker="snmp#dat2s">date_and_time_to_string/2</seealso>
- and
- <seealso marker="snmp#dat2s2">date_and_time_to_string2/1</seealso>. </p>
- <p>Also added new validation function
- <seealso marker="snmp#vdat">validate_date_and_time/2</seealso>. </p>
- <p>Own Id: OTP-7412</p>
- <p>Aux Id: Seq 10987</p>
- </item>
- </list>
- -->
- </section>
-
- <section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <!--
- <p>-</p>
- -->
- <list type="bulleted">
- <item>
- <p>[manager] Erroneous engine-id check when receiving version 3
- informs. </p>
- <p>Own Id: OTP-7570</p>
- <p>Aux Id: Seq 11060</p>
- </item>
-
- <item>
- <p>Receiving an snmp message with a very large version
- number could cause the erlang node to run out of
- memory and consequently crash. </p>
- <p>The standard specifies the snmp version as an
- (unlimited) INTEGER, but today only
- 0 (version 1), 1 (version 2) and 3 (version 3) is
- actually used. So, when decoding a message, a limit
- has been put on the snmp version integer in order
- to not allow this kind of a problem. </p>
- <p>Own Id: OTP-7575</p>
- <p>Aux Id: Seq 11064</p>
- </item>
-
- </list>
- </section>
-
- <section>
- <title>Incompatibilities</title>
- <p>-</p>
- </section>
- </section> <!-- 4.11.2 -->
-
-
- <section>
- <title>SNMP Development Toolkit 4.11.1</title>
- <p>Version 4.11.1 supports code replacement in runtime from/to
- version 4.11.</p>
-
- <section>
- <title>Improvements and new features</title>
- <!--
- <p>-</p>
- -->
- <list type="bulleted">
- <item>
- <p>[compiler] The MIB compiler did not retrieve the REFERENCE part
- of a SNMP MIB definition. </p>
- <p>This problem has been partly solved. For SNMP tables,
- the assocList field of the tables mib-entry record now contains
- this info (as <c>{reference, string()}</c>), <em>if</em> the
- MIB was compiled with the compiler option <em>+reference</em>. </p>
- <p>This solution is temporary, until such time as a permanent
- solution (and probably not backward compatible) is devised, which
- retrieves and stores all REFERENCE part(s) of a MIB. </p>
- <p>See the
- <seealso marker="snmpc#compiler_opts">compiler options</seealso>
- for more info. </p>
-
- <p>Serge Aleynikov</p>
- <p>Own Id: OTP-7426</p>
- </item>
-
- <item>
- <p>Added utility functions for transforming DateAndTime
- as [int()] to strings;
- <seealso marker="snmp#dat2s">date_and_time_to_string/2</seealso>
- and
- <seealso marker="snmp#dat2s2">date_and_time_to_string2/1</seealso>. </p>
- <p>Also added new validation function
- <seealso marker="snmp#vdat">validate_date_and_time/2</seealso>. </p>
- <p>Own Id: OTP-7412</p>
- <p>Aux Id: Seq 10987</p>
- </item>
-
- </list>
-
- </section>
-
- <section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <!--
- <p>-</p>
- -->
- <list type="bulleted">
- <item>
- <p>[manager] Encryption error when attempting to send
- version 3 inform-requests. </p>
- <p>Own Id: OTP-7432</p>
- <p>Aux Id: Seq 10966</p>
- </item>
-
- </list>
- </section>
-
- <section>
- <title>Incompatibilities</title>
- <p>-</p>
- </section>
- </section> <!-- 4.11.1 -->
-
- <section>
- <title>SNMP Development Toolkit 4.11</title>
- <p>Version 4.11 supports code replacement in runtime from/to
- version 4.10.3, 4.10.2, 4.10.1 and 4.10.</p>
-
- <section>
- <title>Improvements and new features</title>
- <!--
- <p>-</p>
- -->
- <list type="bulleted">
- <item>
- <p>[agent] Performance improvements in the case when an SNMP
- manager performs an snmpwalk. </p>
- <p>Martin Bj&ouml;rklund</p>
- <p>Own Id: OTP-7201</p>
- </item>
-
- <item>
- <p>The API for sending inform(s) has been improved. Also
- the documentation has been corrected and updated. See
- <seealso marker="snmpa#send_notification">snmpa:send_notification</seealso> and
- <seealso marker="snmpa_notification_delivery_info_receiver">snmpa_notification_delivery_info_receiver</seealso>
- for more info.</p>
- <p>Own Id: OTP-7287</p>
- <p>Aux Id: Seq 10926</p>
- </item>
-
- <item>
- <p>[agent] Performance of the internal database (local-db)
- has been improved.</p>
- <p>Own Id: OTP-7319</p>
- <p>Aux Id: Seq 10942</p>
- </item>
-
- <item>
- <p>[agent] Added utility functions,
- <seealso marker="snmpa#restart_worker">snmpa:restart_worker/0,1</seealso> and
- <seealso marker="snmpa#restart_set_worker">snmpa:restart_set_worker/0,1</seealso>,
- for restarting the agent worker processes (in case the agent is
- multi-threaded).</p>
- <p>Own Id: OTP-7369</p>
- </item>
-
- <item>
- <p>Add utility function to
- <seealso marker="snmp#read_mib">read</seealso>
- a compiled mib. </p>
- <p>Own Id: OTP-7371</p>
- </item>
-
- </list>
- </section>
-
- <section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <!--
- <p>-</p>
- -->
- <list type="bulleted">
- <item>
- <p>[manager] Encryption error when attempting to send
- version 3 inform-requests. </p>
- <p>Own Id: OTP-7377</p>
- <p>Aux Id: Seq 10966</p>
- </item>
-
- </list>
- </section>
-
- <section>
- <title>Incompatibilities</title>
- <p>-</p>
- </section>
- </section> <!-- 4.11 -->
-
<!-- section>
<title>Release notes history</title>
<p>For information about older versions see
diff --git a/lib/snmp/doc/src/notes_history.xml b/lib/snmp/doc/src/notes_history.xml
index 934df87866..722d02afbd 100644
--- a/lib/snmp/doc/src/notes_history.xml
+++ b/lib/snmp/doc/src/notes_history.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE chapter SYSTEM "chapter.dtd">
<chapter>
@@ -33,6 +33,928 @@
</header>
<section>
+ <title>SNMP Development Toolkit 4.14</title>
+
+ <p>Version 4.14 supports code replacement in runtime from/to
+ version 4.13.5, 4.13.4, 4.13.3, 4.13.2, 4.13.1 and 4.13.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <!--
+ <p>-</p>
+ -->
+
+ <list type="bulleted">
+ <item>
+ <p>[compiler] Include object- and notification groups in the
+ compiled mib.
+ This will make it possible to import groups from other mibs. </p>
+ <p>Also the SNMPv2-MIB-file has been updated to a more
+ up-to-date version. </p>
+ <p>Own Id: OTP-8223</p>
+ <!-- <p>Aux Id: Seq 11383</p> -->
+ </item>
+
+ <item>
+ <p>[manager] Added support for message filtering in the
+ network interface module provided with the application.
+ The component that actually make the filter decisions
+ is the network interface filter module. This module
+ must implement the
+ <seealso marker="snmpm_network_interface_filter">network interface filter behaviour</seealso>
+ for message filtering.
+ See also the Configuring chapter of
+ the User's Guide to see how to configure this feature. </p>
+ <p>See the
+ <seealso marker="snmp_app#configuration_params">configuration</seealso>
+ chapter for more info about the filter options.</p>
+ <p>Own Id: OTP-8228</p>
+ <p>Aux Id: Seq 11411</p>
+ </item>
+
+ <item>
+ <p>The MIBs delivered as part of the application is now
+ also available as man pages, section 7. </p>
+ <p>Own Id: OTP-8237</p>
+ <!-- <p>Aux Id: Seq 11383</p> -->
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <p>-</p>
+
+ <!--
+ <list type="bulleted">
+ <item>
+ <p>[agent] The main agent type header file contained some miss-information
+ regarding the type of the entrytype field of the me-record, causing
+ unneccessary confusion.</p>
+ <p>Own Id: OTP-8116</p>
+ <p>Aux Id: Seq 11312</p>
+ </item>
+
+ </list>
+ -->
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.14 -->
+
+
+ <section>
+ <title>SNMP Development Toolkit 4.13.5</title>
+
+ <p>Version 4.13.5 supports code replacement in runtime from/to
+ version 4.13.4, 4.13.3, 4.13.2, 4.13.1 and 4.13.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <!--
+ <p>-</p>
+ -->
+
+ <list type="bulleted">
+ <item>
+ <p>[agent] Improved the cache handling of the mib server. </p>
+ <p>A number of new functions and config options for the mib server
+ cache has been added. </p>
+ <p>See
+ <seealso marker="snmpa#invalidate_mibs_cache">invalidate_mibs_cache/0,1</seealso>,
+ <seealso marker="snmpa#enable_mibs_cache">enable_mibs_cache/0,1</seealso>,
+ <seealso marker="snmpa#disable_mibs_cache">disable_mibs_cache/0,1</seealso>,
+ <seealso marker="snmpa#gc_mibs_cache">gc_mibs_cache/0,1,2,3</seealso>,
+ <seealso marker="snmpa#enable_mibs_cache_autogc">enable_mibs_cache_autogc/0,1</seealso>,
+ <seealso marker="snmpa#disable_mibs_cache_autogc">disable_mibs_cache_autogc/0,1</seealso>,
+ <seealso marker="snmpa#update_mibs_cache_age">update_mibs_cache_age/1,2</seealso> and
+ <seealso marker="snmpa#update_mibs_cache_gclimit">update_mibs_cache_gclimit/1,2</seealso> for more info. </p>
+ <p>See also the
+ <seealso marker="snmp_app#configuration_params">configuration</seealso>
+ chapter for more info about the mib server cache options.</p>
+ <p>Own Id: OTP-8182</p>
+ <p>Aux Id: Seq 11383</p>
+ </item>
+
+ <item>
+ <p>[agent] A manager could no longer use the SNMPv3 user "initial"
+ as this was interpretated as the first step of the discovery. </p>
+ <p>Introduced a new terminating option, <c>trigger_username</c> to
+ make it possible to configure the username the agent reacts to.
+ Default is <c>""</c>. </p>
+ <p>See the
+ <seealso marker="snmp_app#configuration_params">configuration</seealso>
+ chapter for more info about the discovery options.</p>
+ <p>Own Id: OTP-8120</p>
+ <p>Aux Id: Seq 11361</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[agent] The main agent type header file contained some miss-information
+ regarding the type of the entrytype field of the me-record, causing
+ unneccessary confusion.</p>
+ <p>Own Id: OTP-8116</p>
+ <p>Aux Id: Seq 11312</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.13.5 -->
+
+
+ <section>
+ <title>SNMP Development Toolkit 4.13.4</title>
+
+ <p>Version 4.13.4 supports code replacement in runtime from/to
+ version 4.13.3, 4.13.2, 4.13.1 and 4.13.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <p>-</p>
+
+ <!--
+ <list type="bulleted">
+ <item>
+ <p>[agent] Support for the discovery process. </p>
+ <p>The agent can both initiate discovery itself (see the
+ <seealso marker="snmp_agent_funct_descr#discovery">discovery</seealso> chapter
+ for more info) and respond to discovery initiated by a manager.</p>
+ <p>Own Id: OTP-7571</p>
+ <p>Aux Id: Seq 11053</p>
+ </item>
+
+ </list>
+ -->
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[agent] Originating discovery problems. </p>
+ <p>Invalid state variable update during second stage of
+ discovery causes master agent crash. </p>
+ <p>Also the net_if process failed to activate socket
+ ({active, once}) after first discovery response was sent. </p>
+ <p>Own Id: OTP-8044</p>
+ <p>Aux Id: Seq 11295</p>
+ </item>
+
+ <item>
+ <p>[agent] Terminating discovery problem. </p>
+ <p>The reply to the second stage request should include a
+ varbind with <c>usmStatsNotInTimeWindows</c>.</p>
+ <p>Own Id: OTP-8062</p>
+ <p>Aux Id: Seq 11318</p>
+ </item>
+
+ <item>
+ <p>[agent] Originating discovery improvement. </p>
+ <p>Added the ExtraInfo argument to the
+ <seealso marker="snmpa#discovery">discovery</seealso> function.
+ This argument will be passed on to the stage1_finish callback
+ function. Also, the
+ <seealso marker="snmpa#discovery">discovery</seealso> function
+ will now always return <c>{ok, ManagerEngineID}</c> on successful
+ discovery. </p>
+ <p>The <seealso marker="snmpa_discovery_handler">discovery handler</seealso>
+ behaviour updated accordingly. </p>
+ <p>Own Id: OTP-8098</p>
+ <p>Aux Id: Seq 11346</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.13.4 -->
+
+
+ <section>
+ <title>SNMP Development Toolkit 4.13.3</title>
+
+ <p>Version 4.13.3 supports code replacement in runtime from/to
+ version 4.13.2, 4.13.1 and 4.13.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <p>-</p>
+
+ <!--
+ <list type="bulleted">
+ <item>
+ <p>[agent] Support for the discovery process. </p>
+ <p>The agent can both initiate discovery itself (see the
+ <seealso marker="snmp_agent_funct_descr#discovery">discovery</seealso> chapter
+ for more info) and respond to discovery initiated by a manager.</p>
+ <p>Own Id: OTP-7571</p>
+ <p>Aux Id: Seq 11053</p>
+ </item>
+
+ </list>
+ -->
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[manager] A request for an oid of type BITS was actually
+ returned as OCTET STRING. </p>
+ <p>Values of type BITS are encoded as OCTET STRING,
+ which makes it impossible for the decoder to know that
+ they should really be of type BITS.
+ Instead, this has to be done higher up in the stack, where
+ there is knowledge of the MIB (assuming that the mib has
+ been loaded, there is info about the type of the mibentry). </p>
+ <p>This problem has now been fixed, but requires that the MIB
+ defining this mib-entry is loaded! </p>
+ <p>The utility function
+ <seealso marker="snmpm#oid_to_type">oid_to_type</seealso>
+ has been added, for debug purpose. </p>
+ <p>The utility function(s)
+ <seealso marker="snmp#octet_string_to_bits">octet_string_to_bits</seealso>
+ and
+ <seealso marker="snmp#bits_to_octet_string">bits_to_octet_string</seealso>
+ has also been added. These can be used if the user prefers to
+ handle the conversion on their own. </p>
+ <p>Own Id: OTP-8015</p>
+ <p>Aux Id: Seq 11285</p>
+ </item>
+
+ <item>
+ <p>[agent] Fixed some issues with the discovery handling. </p>
+ <p>Changed the API of the
+ <seealso marker="snmpa#discovery">discovery</seealso>
+ function to solve some
+ of these problems. </p>
+ <p>Introduced various options for controlling the discovery
+ process. See the
+ <seealso marker="snmp_app#configuration_params">configuration</seealso>
+ chapter for more info about the discovery options.</p>
+ <p>Own Id: OTP-8020</p>
+ <p>Aux Id: Seq 11295</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.13.3 -->
+
+
+ <section>
+ <title>SNMP Development Toolkit 4.13.2</title>
+
+ <p>Version 4.13.2 supports code replacement in runtime from/to
+ version 4.13.1 and 4.13.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <p>-</p>
+
+ <!--
+ <list type="bulleted">
+ <item>
+ <p>[agent] Support for the discovery process. </p>
+ <p>The agent can both initiate discovery itself (see the
+ <seealso marker="snmp_agent_funct_descr#discovery">discovery</seealso> chapter
+ for more info) and respond to discovery initiated by a manager.</p>
+ <p>Own Id: OTP-7571</p>
+ <p>Aux Id: Seq 11053</p>
+ </item>
+
+ </list>
+ -->
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[manager] Failure during downed user cleanup.
+ As part of the cleanup after a crashed user,
+ the manager attempts to unregister the agents
+ registered by this user. This however failed,
+ causing a server crash. </p>
+ <p>Own Id: OTP-7961</p>
+ <p>Aux Id: Seq 11275</p>
+ </item>
+
+ <item>
+ <p>[manager] Incorrectly documented value type for
+ IpAddress (ip). The value type for IpAddress is
+ documented as ip but is actually ia. The value type
+ ip has been added. The old (not documented) value
+ type ia still works. </p>
+ <p>Own Id: OTP-7977</p>
+ <p>Aux Id: Seq 11279</p>
+ </item>
+
+ <item>
+ <p>[manager] EngineId lookup fails when using version-3. </p>
+ <p>Own Id: OTP-7983</p>
+ <p>Aux Id: Seq 11275</p>
+ </item>
+
+ <item>
+ <p>[agent] As of version 4.13 the possible return values
+ of the function
+ <seealso marker="snmpa_mpd#process_packet">snmpa_mpd:process_packet/4</seealso>
+ changed, but this was not documented. </p>
+ <p>Own Id: OTP-7989</p>
+ <p>Aux Id: Seq 11275</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.13.2 -->
+
+ <section>
+ <title>SNMP Development Toolkit 4.13.1</title>
+
+ <p>Version 4.13.1 supports code replacement in runtime from/to
+ version 4.13.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <p>-</p>
+
+ <!--
+ <list type="bulleted">
+ <item>
+ <p>[agent] Support for the discovery process. </p>
+ <p>The agent can both initiate discovery itself (see the
+ <seealso marker="snmp_agent_funct_descr#discovery">discovery</seealso> chapter
+ for more info) and respond to discovery initiated by a manager.</p>
+ <p>Own Id: OTP-7571</p>
+ <p>Aux Id: Seq 11053</p>
+ </item>
+
+ </list>
+ -->
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[manager] Registration of users had some issues. </p>
+ <p>Not all of the registration functions where actually exported
+ (<seealso marker="snmpm#register_user">register_user/4</seealso>
+ and
+ <seealso marker="snmpm#register_user_monitor">register_user_monitor/4</seealso>).
+ This has now been fixed. </p>
+ <p>Also, the registration did not succeed unless
+ user implemented the *new* behaviour. This has now
+ also been fixed (registration succeeds if the user
+ implements either the new (i.e. updated
+ <seealso marker="snmpm_user">snmpm_user</seealso>)
+ or the old user behaviour (<c>snmpm_user_old</c>)). </p>
+ <p>Own Id: OTP-7902</p>
+ <p>Aux Id: Seq 11240</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.13.1 -->
+
+ <section>
+ <title>SNMP Development Toolkit 4.13</title>
+<!--
+ <p>Version 4.13 supports code replacement in runtime from/to
+ version 4.12.1.</p>
+-->
+
+ <section>
+ <title>Improvements and new features</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[agent] Support for the discovery process. </p>
+ <p>The agent can both initiate discovery itself (see the
+ <seealso marker="snmp_agent_funct_descr#discovery">discovery</seealso> chapter
+ for more info) and respond to discovery initiated by a manager.</p>
+ <p>Own Id: OTP-7571</p>
+ <p>Aux Id: Seq 11053</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[agent] Unnecessary use of math:pow/2 could cause problems
+ on systems without floating point support. </p>
+ <p>Per Hedeland</p>
+ <p>Own Id: OTP-7735</p>
+ <!-- <p>Aux Id: Seq 10966</p> -->
+ </item>
+
+ <item>
+ <p>[manager] A major flaw was discovered with the agent handling. </p>
+ <p>First, <c>TargetName</c> was never used as intended, as a unique
+ identifier for the target (agent in this case). </p>
+ <p>Second, <c>TargetName</c> had a <em>default value</em>, which meant
+ that several agents could have the same <c>TargetName</c>, causing
+ unpredictable behaviour in the manager. </p>
+ <p>Third, <c>EngineID</c> was not a mandatory config option and had
+ furthermore also a <em>default value</em>. </p>
+
+ <p>These problems has been solved in the following way: </p>
+ <p>First, a new set of api functions has been introduced (and documented):
+ <seealso marker="snmpm#register_user">register_user/4</seealso>,
+ <seealso marker="snmpm#register_user_monitor">register_user_monitor/4</seealso>,
+ <seealso marker="snmpm#register_agent">register_agent/3</seealso>,
+ <seealso marker="snmpm#unregister_agent">unregister_agent/2</seealso>,
+ <seealso marker="snmpm#agent_info">agent_info/2</seealso>,
+ <seealso marker="snmpm#update_agent_info">update_agent_info/4</seealso>,
+ <seealso marker="snmpm#sync_get">sync_get/3,4,5,6</seealso>,
+ <seealso marker="snmpm#async_get">async_get/3,4,5,6</seealso>,
+ <seealso marker="snmpm#sync_get_next">sync_get_next/3,4,5,6</seealso>,
+ <seealso marker="snmpm#async_get_next">async_get_next/3,4,5,6</seealso>,
+ <seealso marker="snmpm#sync_set">sync_set/3,4,5,6</seealso>,
+ <seealso marker="snmpm#async_set">async_set/3,4,5,6</seealso>,
+ <seealso marker="snmpm#sync_get_bulk">sync_get_bulk/5,6,7,8</seealso> and
+ <seealso marker="snmpm#async_get_bulk">async_get_bulk/5,6,7,8</seealso>
+ that all use <c>TargetName</c> (and not, as previously, <c>Addr</c>
+ and <c>Port</c>) to identify the agent (also the return value of
+ <seealso marker="snmpm#which_agents">which_agents</seealso> has
+ been changed). </p>
+ <p>Second, for backward compatibility, the old functions still
+ exist, but are no longer documented and are now wrappers for the
+ new functions, including erroneous default value for EngineID and
+ all. The TargetName is however generated from the provided
+ <c>Addr</c>, <c>Port</c> and <c>Version</c> config options. </p>
+ <p>Third, the behaviour of the
+ <seealso marker="snmpm_user">SNMP manager user</seealso> has
+ been changed to reflect this, i.e.
+ <seealso marker="snmpm_user#handle_pdu">handle_pdu/4</seealso>,
+ <seealso marker="snmpm_user#handle_trap">handle_trap/3</seealso>,
+ <seealso marker="snmpm_user#handle_inform">handle_inform/3</seealso>,
+ <seealso marker="snmpm_user#handle_report">handle_report/3</seealso>
+ and the return-value of
+ <seealso marker="snmpm_user#handle_agent">handle_agent/4</seealso>.
+ The old (non-documented) callback-functions (using Addr and Port)
+ will still be called if the agent was registered using the old
+ registration functions. </p>
+
+ <p>Own Id: OTP-7836</p>
+ <!-- <p>Aux Id: Seq 10966</p> -->
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.13 -->
+
+ <section>
+ <title>SNMP Development Toolkit 4.12.2</title>
+ <p>Version 4.12.2 supports code replacement in runtime from/to
+ version 4.12.1, 4.12, 4.11.2, 4.11.1 and 4.11.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <p>-</p>
+ <!--
+ <list type="bulleted">
+ <item>
+ <item>
+ <p>[agent] Improvement of the inform reporting.
+ It was previously not certain how many acks an
+ application received, 0, 1 or 2. This has now been
+ fixed, so that only 1 (one) ack is issued. </p>
+ <p>Per Hedeland</p>
+ <p>Own Id: OTP-7525</p>
+ </item>
+
+ </list>
+ -->
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[agent] Bad session cache (usm+camv-info) invalidation
+ could cause user crash, through call(s) to (a number of)
+ MIB API function(s) (undefined function). </p>
+ <p>Own Id: OTP-7868</p>
+ <!-- <p>Aux Id: Seq 11124</p> -->
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.12.2 -->
+
+ <section>
+ <title>SNMP Development Toolkit 4.12.1</title>
+ <p>Version 4.12.1 supports code replacement in runtime from/to
+ version 4.12, 4.11.2, 4.11.1 and 4.11.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <p>-</p>
+ <!--
+ <list type="bulleted">
+ <item>
+ <item>
+ <p>[agent] Improvement of the inform reporting.
+ It was previously not certain how many acks an
+ application received, 0, 1 or 2. This has now been
+ fixed, so that only 1 (one) ack is issued. </p>
+ <p>Per Hedeland</p>
+ <p>Own Id: OTP-7525</p>
+ </item>
+
+ </list>
+ -->
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>Logging of messages with the GetBulk-request PDU
+ incorrectly produced an erroneous entry in the
+ log: "An error occurred". </p>
+ <p>The reason for this was that the PDU-fields
+ error_status and error_index is re-used for
+ Non-repeaters and Max-repetitions for
+ GetBulk-request PDUs, but this was not handled
+ by the logging code. </p>
+ <p>Own Id: OTP-7695</p>
+ <p>Aux Id: Seq 11124</p>
+ </item>
+
+ <item>
+ <p>[agent] An attempt to set the row status to active for an
+ notReady table row, could result in an "inconsistentValue"
+ error. </p>
+ <p>The same problem existed when attempting to set row status
+ to notInService for a row in notReady. </p>
+ <p>Serge Aleynikov</p>
+ <p>Own Id: OTP-7698</p>
+ <!-- <p>Aux Id: Seq 10966</p> -->
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.12.1 -->
+
+ <section>
+ <title>SNMP Development Toolkit 4.12</title>
+ <p>Version 4.12 supports code replacement in runtime from/to
+ version 4.11.2, 4.11.1 and 4.11.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[agent] A simple lookup cache has been added to improve
+ the mib server lookup performance. </p>
+ <p>This can be disabled with the mib_server
+ <seealso marker="snmp_app">cache</seealso> option. </p>
+ <p>Own Id: OTP-7346</p>
+ </item>
+
+ <item>
+ <p>[agent] Improvement of the inform reporting.
+ It was previously not certain how many acks an
+ application received, 0, 1 or 2. This has now been
+ fixed, so that only 1 (one) ack is issued. </p>
+ <p>Per Hedeland</p>
+ <p>Own Id: OTP-7525</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <p>-</p>
+ <!--
+ <list type="bulleted">
+ <item>
+ <p>[manager] Encryption error when attempting to send
+ version 3 inform-requests. </p>
+ <p>Own Id: OTP-7432</p>
+ <p>Aux Id: Seq 10966</p>
+ </item>
+
+ </list>
+ -->
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.12 -->
+
+ <section>
+ <title>SNMP Development Toolkit 4.11.2</title>
+ <p>Version 4.11.2 supports code replacement in runtime from/to
+ version 4.11.1 and 4.11. </p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <p>-</p>
+ <!--
+ <list type="bulleted">
+ <item>
+ <p>Added utility functions for transforming DateAndTime
+ as [int()] to strings;
+ <seealso marker="snmp#dat2s">date_and_time_to_string/2</seealso>
+ and
+ <seealso marker="snmp#dat2s2">date_and_time_to_string2/1</seealso>. </p>
+ <p>Also added new validation function
+ <seealso marker="snmp#vdat">validate_date_and_time/2</seealso>. </p>
+ <p>Own Id: OTP-7412</p>
+ <p>Aux Id: Seq 10987</p>
+ </item>
+ </list>
+ -->
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[manager] Erroneous engine-id check when receiving version 3
+ informs. </p>
+ <p>Own Id: OTP-7570</p>
+ <p>Aux Id: Seq 11060</p>
+ </item>
+
+ <item>
+ <p>Receiving an snmp message with a very large version
+ number could cause the erlang node to run out of
+ memory and consequently crash. </p>
+ <p>The standard specifies the snmp version as an
+ (unlimited) INTEGER, but today only
+ 0 (version 1), 1 (version 2) and 3 (version 3) is
+ actually used. So, when decoding a message, a limit
+ has been put on the snmp version integer in order
+ to not allow this kind of a problem. </p>
+ <p>Own Id: OTP-7575</p>
+ <p>Aux Id: Seq 11064</p>
+ </item>
+
+ </list>
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.11.2 -->
+
+
+ <section>
+ <title>SNMP Development Toolkit 4.11.1</title>
+ <p>Version 4.11.1 supports code replacement in runtime from/to
+ version 4.11.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[compiler] The MIB compiler did not retrieve the REFERENCE part
+ of a SNMP MIB definition. </p>
+ <p>This problem has been partly solved. For SNMP tables,
+ the assocList field of the tables mib-entry record now contains
+ this info (as <c>{reference, string()}</c>), <em>if</em> the
+ MIB was compiled with the compiler option <em>+reference</em>. </p>
+ <p>This solution is temporary, until such time as a permanent
+ solution (and probably not backward compatible) is devised, which
+ retrieves and stores all REFERENCE part(s) of a MIB. </p>
+ <p>See the
+ <seealso marker="snmpc#compiler_opts">compiler options</seealso>
+ for more info. </p>
+
+ <p>Serge Aleynikov</p>
+ <p>Own Id: OTP-7426</p>
+ </item>
+
+ <item>
+ <p>Added utility functions for transforming DateAndTime
+ as [int()] to strings;
+ <seealso marker="snmp#dat2s">date_and_time_to_string/2</seealso>
+ and
+ <seealso marker="snmp#dat2s2">date_and_time_to_string2/1</seealso>. </p>
+ <p>Also added new validation function
+ <seealso marker="snmp#vdat">validate_date_and_time/2</seealso>. </p>
+ <p>Own Id: OTP-7412</p>
+ <p>Aux Id: Seq 10987</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[manager] Encryption error when attempting to send
+ version 3 inform-requests. </p>
+ <p>Own Id: OTP-7432</p>
+ <p>Aux Id: Seq 10966</p>
+ </item>
+
+ </list>
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.11.1 -->
+
+ <section>
+ <title>SNMP Development Toolkit 4.11</title>
+ <p>Version 4.11 supports code replacement in runtime from/to
+ version 4.10.3, 4.10.2, 4.10.1 and 4.10.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[agent] Performance improvements in the case when an SNMP
+ manager performs an snmpwalk. </p>
+ <p>Martin Bj&ouml;rklund</p>
+ <p>Own Id: OTP-7201</p>
+ </item>
+
+ <item>
+ <p>The API for sending inform(s) has been improved. Also
+ the documentation has been corrected and updated. See
+ <seealso marker="snmpa#send_notification">snmpa:send_notification</seealso> and
+ <seealso marker="snmpa_notification_delivery_info_receiver">snmpa_notification_delivery_info_receiver</seealso>
+ for more info.</p>
+ <p>Own Id: OTP-7287</p>
+ <p>Aux Id: Seq 10926</p>
+ </item>
+
+ <item>
+ <p>[agent] Performance of the internal database (local-db)
+ has been improved.</p>
+ <p>Own Id: OTP-7319</p>
+ <p>Aux Id: Seq 10942</p>
+ </item>
+
+ <item>
+ <p>[agent] Added utility functions,
+ <seealso marker="snmpa#restart_worker">snmpa:restart_worker/0,1</seealso> and
+ <seealso marker="snmpa#restart_set_worker">snmpa:restart_set_worker/0,1</seealso>,
+ for restarting the agent worker processes (in case the agent is
+ multi-threaded).</p>
+ <p>Own Id: OTP-7369</p>
+ </item>
+
+ <item>
+ <p>Add utility function to
+ <seealso marker="snmp#read_mib">read</seealso>
+ a compiled mib. </p>
+ <p>Own Id: OTP-7371</p>
+ </item>
+
+ </list>
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[manager] Encryption error when attempting to send
+ version 3 inform-requests. </p>
+ <p>Own Id: OTP-7377</p>
+ <p>Aux Id: Seq 10966</p>
+ </item>
+
+ </list>
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.11 -->
+
+
+ <section>
<title>SNMP Development Toolkit 4.10.3</title>
<p>Version 4.10.3 supports code replacement in runtime from/to
version 4.10.2, 4.10.1 and 4.10.</p>
diff --git a/lib/snmp/doc/src/snmpc.xml b/lib/snmp/doc/src/snmpc.xml
index 771629492d..61d19251c5 100644
--- a/lib/snmp/doc/src/snmpc.xml
+++ b/lib/snmp/doc/src/snmpc.xml
@@ -48,7 +48,11 @@
<type>
<v>File = string()</v>
<v>Options = [opt()]</v>
- <v>opt() = db() | relaxed_row_name_assign_check() | deprecated() | description() | reference() | group_check() | i() | il() | imports() | module() | module_identity() | module_compliance() | agent_capabilities() | outdir() | no_defs() | verbosity() | warnings()</v>
+ <v>opt() = db() | relaxed_row_name_assign_check() | deprecated() |
+ description() | reference() | group_check() | i() | il() |
+ imports() | module() | module_identity() | module_compliance() |
+ agent_capabilities() | outdir() | no_defs() | verbosity() |
+ warnings() | warnings_as_errors()</v>
<v>db() = {db, volatile|persistent|mnesia}</v>
<v>deprecated() = {deprecated, bool()}</v>
<v>relaxed_row_name_assign_check() = relaxed_row_name_assign_check</v>
@@ -66,6 +70,7 @@
<v>outdir() = {outdir, dir()}</v>
<v>verbosity() = {verbosity, silence|warning|info|log|debug|trace}</v>
<v>warnings() = {warnings, bool()}</v>
+ <v>warnings_as_errors() = warnings_as_errors</v>
<v>dir() = string()</v>
<v>BinFileName = string()</v>
</type>
@@ -200,11 +205,17 @@
<item>
<p>The option <c>warnings</c> specifies whether warning
- messages should be shown. </p>
+ messages should be shown. </p>
<p>Default is <c>true</c>. </p>
</item>
+ <item>
+ <p>The option <c>warnings_as_errors</c>, if present, specifies
+ whether warnings should be treated as errors.</p>
+ </item>
+
</list>
+
<p>The MIB compiler understands both SMIv1 and SMIv2 MIBs. It
uses the <c>MODULE-IDENTITY</c> statement to determine if the MIB is
version 1 or 2.
diff --git a/lib/snmp/doc/src/snmpc_cmd.xml b/lib/snmp/doc/src/snmpc_cmd.xml
index 9358382a10..971f8a3cff 100644
--- a/lib/snmp/doc/src/snmpc_cmd.xml
+++ b/lib/snmp/doc/src/snmpc_cmd.xml
@@ -50,6 +50,8 @@
with definitions of Erlang constants for the objects in
the MIB, see
<seealso marker="snmpc#mib_to_hrl">mib_to_hrl/1</seealso>. </p>
+
+ <marker id="options"></marker>
</desc>
</func>
</funcs>
@@ -58,15 +60,18 @@
<title>Compiler options</title>
<p>The following options are supported (note that most of these relate
to the compilation of the MIB file):</p>
+ <marker id="option_help"></marker>
<taglist>
<tag>--help</tag>
<item>
<p>Prints help info.</p>
+ <marker id="option_version"></marker>
</item>
<tag>--version</tag>
<item>
<p>Prints application and mib format version.</p>
+ <marker id="option_verbosity"></marker>
</item>
<tag>--verbosity <em>verbosity</em></tag>
@@ -74,11 +79,22 @@
<p>Print debug info. </p>
<p><c>verbosity</c> = <c>trace</c> | <c>debug</c> | <c>log</c> | <c>info</c> | <c>silence</c></p>
<p>Defaults to <c>silence</c>.</p>
+ <marker id="option_w"></marker>
+ <marker id="option_warnings"></marker>
</item>
- <tag>--warnings</tag>
+ <tag>--warnings | --W</tag>
<item>
<p>Print warning messages. </p>
+ <marker id="option_wae"></marker>
+ <marker id="option_werror"></marker>
+ </item>
+
+ <tag>--wae | --Werror</tag>
+ <item>
+ <p>Warnings as errors.
+ Indicates that warnings shall be treated as errors. </p>
+ <marker id="option_odir"></marker>
</item>
<tag>--o <em>directory</em></tag>
@@ -86,6 +102,7 @@
<p>The directory where the compiler should place the output files.
If not specified, output files will be placed in the current working
directory.</p>
+ <marker id="option_idir"></marker>
</item>
<tag>--i <em>Directory</em></tag>
@@ -94,6 +111,7 @@
By default, the current working directory is always included. </p>
<p>This option can be present several times, each time specifying
<em>one</em> path. </p>
+ <marker id="option_ildir"></marker>
</item>
<tag>--il <em>Directory</em></tag>
@@ -106,6 +124,7 @@
the current version may be in the system). The current directory
and the "snmp-home"/priv/mibs/ are always listed last in the
include path. </p>
+ <marker id="option_sgc"></marker>
</item>
<tag>--sgc</tag>
@@ -114,42 +133,50 @@
group check of the mib compiler.
That is, should the OBJECT-GROUP and the NOTIFICATION-GROUP
macro(s) be checked for correctness or not. </p>
+ <marker id="option_dep"></marker>
</item>
<tag>--dep</tag>
<item>
<p>Keep deprecated definition(s).
If not specified the compiler will ignore deprecated definitions. </p>
+ <marker id="option_desc"></marker>
</item>
<tag>--desc</tag>
<item>
<p>The DESCRIPTION field will be included. </p>
+ <marker id="option_ref"></marker>
</item>
<tag>--ref</tag>
<item>
<p>The REFERENCE field will be included. </p>
+ <marker id="option_imp"></marker>
</item>
<tag>--imp</tag>
<item>
<p>The IMPORTS field will be included. </p>
+ <marker id="option_mi"></marker>
</item>
<tag>--mi</tag>
<item>
<p>The MODULE-IDENTITY field will be included. </p>
+ <marker id="option_mc"></marker>
</item>
<tag>--mc</tag>
<item>
<p>The MODULE-COMPLIANCE field will be included. </p>
+ <marker id="option_ac"></marker>
</item>
<tag>--ac</tag>
<item>
<p>The AGENT-CAPABILITIES field will be included. </p>
+ <marker id="option_mod"></marker>
</item>
<tag>--mod <em>module</em></tag>
@@ -157,6 +184,7 @@
<p>The module which implements all the instrumentation functions. </p>
<p>The name of all instrumentation functions must be the
same as the corresponding managed object it implements. </p>
+ <marker id="option_nd"></marker>
</item>
<tag>--nd</tag>
@@ -165,6 +193,7 @@
used if a managed object have no instrumentation function.
Instead this will be reported as an error, and the compilation
aborts. </p>
+ <marker id="option_rrnac"></marker>
</item>
<tag>--rrnac</tag>
@@ -176,6 +205,7 @@
This means that the error will be converted to a warning. </p>
<p>By default it is not included, but if this option is present
it will be. </p>
+ <marker id="see_also"></marker>
</item>
</taglist>
@@ -183,7 +213,7 @@
<section>
<title>SEE ALSO</title>
- <p><seealso marker="erlc">erlc(1)</seealso>,
+ <p><seealso marker="erts:erlc">erlc(1)</seealso>,
<seealso marker="compiler:compile">compile(3)</seealso>,
<seealso marker="snmp:snmpc">snmpc(3)</seealso></p>
</section>
diff --git a/lib/snmp/doc/src/snmpm.xml b/lib/snmp/doc/src/snmpm.xml
index b527d171b0..c36a1b2a24 100644
--- a/lib/snmp/doc/src/snmpm.xml
+++ b/lib/snmp/doc/src/snmpm.xml
@@ -283,27 +283,27 @@ sec_level = noAuthNoPriv | authNoPriv | authPriv
<v>TargetName = target_name()</v>
<v>Config = [agent_config()]</v>
<v>agent_config() = {Item, Val}</v>
- <v>Item = engine_id | address | port | community | timeout | max_message_size | version | sec_model | sec_name | sec_level</v>
+ <v>Item = engine_id | address | port | community | timeout | max_message_size | version | sec_model | sec_name | sec_level | tdomain</v>
<v>Val = term()</v>
<v>Reason = term()</v>
</type>
<desc>
<p>Explicitly instruct the manager to handle this agent, with
- <c>UserId</c> as the responsible user. </p>
- <p>Called to instruct the manager that this agent
- shall be handled. This function is used when
- the user knows in advance which agents the
- manager shall handle.
- Note that there is an alternate way to do the same thing:
- Add the agent to the manager config files (see
- <seealso marker="snmp_manager_config_files#agents">agents.conf</seealso>).</p>
+ <c>UserId</c> as the responsible user. </p>
+ <p>Called to instruct the manager that this agent shall be handled.
+ This function is used when the user knows in advance which agents
+ the manager shall handle.
+ Note that there is an alternate way to do the same thing:
+ Add the agent to the manager config files (see
+ <seealso marker="snmp_manager_config_files#agents">agents.conf</seealso>).</p>
<p><c>TargetName</c> is a non-empty string,
- uniquely identifying the agent. </p>
- <p>The type of <c>Val</c> depends on <c>Item</c>: </p>
+ uniquely identifying the agent. </p>
+ <p>The type of <c>Val</c> depends on <c>Item</c>: </p>
<code type="none"><![CDATA[
[mandatory] engine_id = string()
[mandatory] address = ip_address()
[optional] port = integer()
+[optional] tdomain = transportDomainUdpIpv4 | transportDomainUdpIpv6
[optional] community = string()
[optional] timeout = integer() | snmp_timer()
[optional] max_message_size = integer()
@@ -312,7 +312,9 @@ sec_level = noAuthNoPriv | authNoPriv | authPriv
[optional] sec_name = string()
[optional] sec_level = noAuthNoPriv | authNoPriv | authPriv
]]></code>
- <p>Note that if no <c>Port</c> is given, the default value is used.</p>
+ <p>Note that if no <c>tdomain</c> is given, the default value,
+ <c>transportDomainUdpIpv4</c>, is used.</p>
+ <p>Note that if no <c>port</c> is given, the default value is used.</p>
<marker id="unregister_agent"></marker>
</desc>
@@ -348,17 +350,25 @@ sec_level = noAuthNoPriv | authNoPriv | authPriv
</func>
<func>
+ <name>update_agent_info(UserId, TargetName, Info) -> ok | {error, Reason}</name>
<name>update_agent_info(UserId, TargetName, Item, Val) -> ok | {error, Reason}</name>
<fsummary>Update agent config</fsummary>
<type>
<v>UserId = term()</v>
<v>TargetName = target_name()</v>
- <v>Item = atom()</v>
- <v>Val = term()</v>
+ <v>Info = [{item(), item_value()}]</v>
+ <v>Item = item()</v>
+ <v>item() = atom()</v>
+ <v>Val = item_value()</v>
+ <v>item_value() = term()</v>
<v>Reason = term()</v>
</type>
<desc>
- <p>Update agent config.</p>
+ <p>Update agent config. The function <c>update_agent_info/3</c>
+ should be used when several values needs to be updated atomically. </p>
+ <p>See function
+ <seealso marker="#register_agent">register_agent</seealso>)
+ for more info about what kind of items are allowed. </p>
<marker id="which_agents"></marker>
</desc>
diff --git a/lib/snmp/mibs/Makefile.in b/lib/snmp/mibs/Makefile.in
index 3af74eca75..993a67c6f2 100644
--- a/lib/snmp/mibs/Makefile.in
+++ b/lib/snmp/mibs/Makefile.in
@@ -41,8 +41,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/snmp-$(VSN)
# ----------------------------------------------------
# NOTE:
-# 1) Order is important; some MIBs include others
-# 2) The OTP-REG mib actually belongs to another
+# The OTP-REG mib actually belongs to another
# application (otp_mibs), and is exported by this
# app. But since that app is built later, we have
# to built it here in order to be able to build
@@ -148,6 +147,35 @@ $(ERL_TOP)/lib/snmp/bin/snmp-v2tov1: $(ERL_TOP)/lib/snmp/bin/snmp-v2tov1.src
$(SNMP_BIN_TARGET_DIR)/OTP-REG.bin: $(ERL_TOP)/lib/$(OTP_MIBDIR)/mibs/OTP-REG.mib
$(ERLC) -pa $(SNMP_TOOLKIT)/ebin -I $(SNMP_TOOLKIT)/priv/mibs $(SNMP_FLAGS) -o $(SNMP_BIN_TARGET_DIR) $<
+# To support parallel make, we'll need explicit dependencies
+# to ensure that an imported MIB has been compiled when it's needed.
+
+$(SNMP_BIN_TARGET_DIR)/STANDARD-MIB.bin: \
+ $(SNMP_BIN_TARGET_DIR)/RFC1213-MIB.bin
+
+$(SNMP_BIN_TARGET_DIR)/SNMP-TARGET-MIB.bin: \
+ $(SNMP_BIN_TARGET_DIR)/SNMP-FRAMEWORK-MIB.bin
+
+$(SNMP_BIN_TARGET_DIR)/SNMP-NOTIFICATION-MIB.bin: \
+ $(SNMP_BIN_TARGET_DIR)/SNMP-FRAMEWORK-MIB.bin \
+ $(SNMP_BIN_TARGET_DIR)/SNMP-TARGET-MIB.bin
+
+$(SNMP_BIN_TARGET_DIR)/SNMP-COMMUNITY-MIB.bin: \
+ $(SNMP_BIN_TARGET_DIR)/SNMP-FRAMEWORK-MIB.bin \
+ $(SNMP_BIN_TARGET_DIR)/SNMP-TARGET-MIB.bin
+
+$(SNMP_BIN_TARGET_DIR)/SNMP-USER-BASED-SM-MIB.bin: \
+ $(SNMP_BIN_TARGET_DIR)/SNMP-FRAMEWORK-MIB.bin
+
+$(SNMP_BIN_TARGET_DIR)/SNMP-VIEW-BASED-ACM-MIB.bin: \
+ $(SNMP_BIN_TARGET_DIR)/SNMP-FRAMEWORK-MIB.bin
+
+$(SNMP_BIN_TARGET_DIR)/SNMP-USM-AES-MIB.bin: \
+ $(SNMP_BIN_TARGET_DIR)/SNMP-FRAMEWORK-MIB.bin
+
+$(SNMP_BIN_TARGET_DIR)/OTP-SNMPEA-MIB.bin: \
+ $(SNMP_BIN_TARGET_DIR)/OTP-REG.bin
+
clean:
rm -f $(TARGET_FILES)
@@ -185,7 +213,7 @@ info:
@echo "VSN = $(VSN)"
@echo "RELSYSDIR = $(RELSYSDIR)"
-v1/%.mib.v1: %.mib
+v1/%.mib.v1: %.mib $(ERL_TOP)/lib/snmp/bin/snmp-v2tov1
$(ERL_TOP)/lib/snmp/bin/snmp-v2tov1 -o $@ $<
diff --git a/lib/snmp/src/agent/snmp_target_mib.erl b/lib/snmp/src/agent/snmp_target_mib.erl
index 77910541a2..60bd3e0912 100644
--- a/lib/snmp/src/agent/snmp_target_mib.erl
+++ b/lib/snmp/src/agent/snmp_target_mib.erl
@@ -383,10 +383,18 @@ is_valid_tag(Tag, TDomain, TAddress) ->
is_valid_tag(TDomain, TAddress, Tag, []).
is_valid_tag(TDomain, TAddress, Tag, Key) ->
+ ?vtrace("is_valid_tag -> entry with"
+ "~n TDomain: ~p"
+ "~n TAddress: ~p"
+ "~n Tag: ~p"
+ "~n Key: ~p", [TDomain, TAddress, Tag, Key]),
case table_next(snmpTargetAddrTable, Key) of
endOfTable ->
+ ?vtrace("is_valid_tag -> endOfTable", []),
false;
NextKey ->
+ ?vtrace("is_valid_tag -> next key found"
+ "~n NextKey: ~p", [NextKey]),
case get(snmpTargetAddrTable, NextKey, [?snmpTargetAddrTDomain,
?snmpTargetAddrTAddress,
?snmpTargetAddrTagList,
@@ -395,6 +403,8 @@ is_valid_tag(TDomain, TAddress, Tag, Key) ->
{value, TAddress}, % RFC2576: chapters 5.2.1 & 5.3
{value, TagList},
{value, []}] ->
+ ?vtrace("is_valid_tag -> found with exact match"
+ "~n TagList: ~p", [TagList]),
case snmp_misc:is_tag_member(Tag, TagList) of
true ->
?vtrace("is_valid_tag -> exact: "
@@ -410,9 +420,14 @@ is_valid_tag(TDomain, TAddress, Tag, Key) ->
{value, TAddress2},
{value, TagList},
{value, TMask}] when TMask =/= [] ->
+ ?vtrace("is_valid_tag -> found with exact match"
+ "~n TagList: ~p"
+ "~n TMask: ~p", [TagList, TMask]),
case snmp_misc:is_tmask_match(TAddress, TAddress2,
TMask) of
true ->
+ ?vtrace("is_valid_tag -> "
+ "tmask match - now check tag member", []),
case snmp_misc:is_tag_member(Tag, TagList) of
true ->
?vtrace("is_valid_tag -> masked: "
@@ -425,10 +440,12 @@ is_valid_tag(TDomain, TAddress, Tag, Key) ->
Tag, NextKey)
end;
false ->
+ ?vtrace("is_valid_tag -> tmask NO match", []),
is_valid_tag(TDomain, TAddress,
Tag, NextKey)
end;
_ ->
+ ?vtrace("is_valid_tag -> not found - try next", []),
is_valid_tag(TDomain, TAddress, Tag, NextKey)
end
end.
@@ -591,9 +608,9 @@ snmpTargetAddrTable(print) ->
[Prefix, element(?snmpTargetAddrName, Row),
Prefix, element(?snmpTargetAddrTDomain, Row),
case element(?snmpTargetAddrTDomain, Row) of
- ?snmpUDPDomain -> udp;
- ?transportDomainUdpIpv4 -> udpIpv4;
- ?transportDomainUdpIpv6 -> udpIpv6;
+ ?snmpUDPDomain -> snmpUDPDomain;
+ ?transportDomainUdpIpv4 -> transportDomainUdpIpv4;
+ ?transportDomainUdpIpv6 -> transportDomainUdpIpv6;
_ -> undefined
end,
Prefix, element(?snmpTargetAddrTAddress, Row),
diff --git a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl
index 28469a7b4e..37f6dd3f26 100644
--- a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl
+++ b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl
@@ -247,6 +247,7 @@ add_sec2group(SecModel, SecName, GroupName) ->
Key = [Key1, length(Key2) | Key2],
case table_cre_row(vacmSecurityToGroupTable, Key, Row) of
true ->
+ snmpa_agent:invalidate_ca_cache(),
{ok, Key};
false ->
{error, create_failed}
@@ -260,6 +261,7 @@ add_sec2group(SecModel, SecName, GroupName) ->
delete_sec2group(Key) ->
case table_del_row(vacmSecurityToGroupTable, Key) of
true ->
+ snmpa_agent:invalidate_ca_cache(),
ok;
false ->
{error, delete_failed}
@@ -279,6 +281,7 @@ add_access(GroupName, Prefix, SecModel, SecLevel, Match, RV, WV, NV) ->
Key3 = [SM, SL],
Key = Key1 ++ Key2 ++ Key3,
snmpa_vacm:insert([{Key, Row}], false),
+ snmpa_agent:invalidate_ca_cache(),
{ok, Key};
{error, Reason} ->
{error, Reason};
@@ -287,6 +290,7 @@ add_access(GroupName, Prefix, SecModel, SecLevel, Match, RV, WV, NV) ->
end.
delete_access(Key) ->
+ snmpa_agent:invalidate_ca_cache(),
snmpa_vacm:delete(Key).
@@ -299,6 +303,7 @@ add_view_tree_fam(ViewIndex, SubTree, Status, Mask) ->
Key = [length(Key1) | Key1] ++ [length(Key2) | Key2],
case table_cre_row(vacmViewTreeFamilyTable, Key, Row) of
true ->
+ snmpa_agent:invalidate_ca_cache(),
{ok, Key};
false ->
{error, create_failed}
@@ -312,6 +317,7 @@ add_view_tree_fam(ViewIndex, SubTree, Status, Mask) ->
delete_view_tree_fam(Key) ->
case table_del_row(vacmViewTreeFamilyTable, Key) of
true ->
+ snmpa_agent:invalidate_ca_cache(),
ok;
false ->
{error, delete_failed}
diff --git a/lib/snmp/src/agent/snmpa_agent.erl b/lib/snmp/src/agent/snmpa_agent.erl
index 82a7ec647b..6322f0f21d 100644
--- a/lib/snmp/src/agent/snmpa_agent.erl
+++ b/lib/snmp/src/agent/snmpa_agent.erl
@@ -1626,7 +1626,7 @@ invalidate_ca_cache() ->
MasterAgent ! invalidate_ca_cache;
false ->
%% This is running on a sub-agent node,
- %% so sent skip it
+ %% so skip it
ok
end;
_ -> % Not on this node
diff --git a/lib/snmp/src/agent/snmpa_conf.erl b/lib/snmp/src/agent/snmpa_conf.erl
index 4b88eb69f7..c17a6abbd7 100644
--- a/lib/snmp/src/agent/snmpa_conf.erl
+++ b/lib/snmp/src/agent/snmpa_conf.erl
@@ -424,7 +424,8 @@ target_addr_entry(Name,
EngineId,
TMask) ->
target_addr_entry(Name, Ip, 162, TagList,
- ParamsName, EngineId, TMask, 2048).
+ ParamsName, EngineId,
+ TMask, 2048).
target_addr_entry(Name,
Ip,
@@ -435,7 +436,8 @@ target_addr_entry(Name,
TMask,
MaxMessageSize) ->
target_addr_entry(Name, Ip, Udp, 1500, 3, TagList,
- ParamsName, EngineId, TMask, MaxMessageSize).
+ ParamsName, EngineId,
+ TMask, MaxMessageSize).
target_addr_entry(Name,
Ip,
@@ -448,7 +450,8 @@ target_addr_entry(Name,
TMask,
MaxMessageSize) ->
target_addr_entry(Name, snmp_target_mib:default_domain(), Ip, Udp,
- Timeout, RetryCount, TagList, ParamsName,
+ Timeout, RetryCount, TagList,
+ ParamsName, EngineId,
TMask, MaxMessageSize).
target_addr_entry(Name,
diff --git a/lib/snmp/src/agent/snmpa_mpd.erl b/lib/snmp/src/agent/snmpa_mpd.erl
index 14f62b12f3..4f50b1a674 100644
--- a/lib/snmp/src/agent/snmpa_mpd.erl
+++ b/lib/snmp/src/agent/snmpa_mpd.erl
@@ -32,6 +32,7 @@
-include("SNMP-MPD-MIB.hrl").
-include("SNMPv2-TM.hrl").
-include("SNMP-FRAMEWORK-MIB.hrl").
+-include("TRANSPORT-ADDRESS-MIB.hrl").
-define(VMODULE,"MPD").
-include("snmp_verbosity.hrl").
@@ -981,12 +982,15 @@ generate_discovery_msg2(NoteStore, Pdu,
discovery_note_timeout(Timeout) ->
(Timeout div 100) + 1.
-generate_discovery_msg(NoteStore, {?snmpUDPDomain, [A,B,C,D,U1,U2]},
+generate_discovery_msg(NoteStore, {TDomain, TAddress},
Pdu, ScopedPduBytes,
ContextEngineID, ManagerEngineID,
SecModel, SecName, SecLevelFlag,
InitialUserName,
ContextName, Timeout) ->
+
+ {ok, {_Domain, Address}} = transform_taddr(TDomain, TAddress),
+
%% 7.1.7
?vdebug("generate_discovery_msg -> 7.1.7 (~w)", [ManagerEngineID]),
MsgID = generate_msg_id(),
@@ -1027,7 +1031,7 @@ generate_discovery_msg(NoteStore, {?snmpUDPDomain, [A,B,C,D,U1,U2]},
%% Log(Packet),
inc_snmp_out_vars(Pdu),
?vdebug("generate_discovery_msg -> done", []),
- {Packet, {{A,B,C,D}, U1 bsl 8 + U2}};
+ {Packet, Address};
Error ->
throw(Error)
@@ -1057,6 +1061,34 @@ generate_sec_discovery_msg(Message, SecModule,
end.
+transform_taddr(?snmpUDPDomain, TAddress) ->
+ transform_taddr(?transportDomainUdpIpv4, TAddress);
+transform_taddr(?transportDomainUdpIpv4, [A, B, C, D, P1, P2]) ->
+ Domain = transportDomainUdpIpv4,
+ Addr = {A,B,C,D},
+ Port = P1 bsl 8 + P2,
+ Address = {Addr, Port},
+ {ok, {Domain, Address}};
+transform_taddr(?transportDomainUdpIpv4, BadAddr) ->
+ {error, {bad_transportDomainUdpIpv4_address, BadAddr}};
+transform_taddr(?transportDomainUdpIpv6,
+ [A1, A2, A3, A4, A5, A6, A7, A8, P1, P2]) ->
+ Domain = transportDomainUdpIpv6,
+ Addr = {A1, A2, A3, A4, A5, A6, A7, A8},
+ Port = P1 bsl 8 + P2,
+ Address = {Addr, Port},
+ {ok, {Domain, Address}};
+transform_taddr(?transportDomainUdpIpv6, BadAddr) ->
+ {error, {bad_transportDomainUdpIpv6_address, BadAddr}};
+transform_taddr(BadTDomain, TAddress) ->
+ case lists:member(BadTDomain, snmp_conf:all_tdomains()) of
+ true ->
+ {error, {unsupported_tdomain, BadTDomain, TAddress}};
+ false ->
+ {error, {unknown_tdomain, BadTDomain, TAddress}}
+ end.
+
+
process_taddrs(Dests) ->
?vtrace("process_taddrs -> entry with"
"~n Dests: ~p", [Dests]),
@@ -1066,46 +1098,44 @@ process_taddrs([], Acc) ->
?vtrace("process_taddrs -> entry when done with"
"~n Acc: ~p", [Acc]),
lists:reverse(Acc);
-
+
%% v3
-process_taddrs([{{?snmpUDPDomain, [A,B,C,D,U1,U2]}, SecData} | T], Acc) ->
+process_taddrs([{{TDomain, TAddress}, SecData} | T], Acc) ->
?vtrace("process_taddrs -> entry when v3 with"
- "~n A: ~p"
- "~n B: ~p"
- "~n C: ~p"
- "~n D: ~p"
- "~n U1: ~p"
- "~n U2: ~p"
- "~n SecData: ~p", [A, B, C, D, U1, U2, SecData]),
- Entry = {{snmpUDPDomain, {{A,B,C,D}, U1 bsl 8 + U2}}, SecData},
- process_taddrs(T, [Entry | Acc]);
-%% Bad v3
-process_taddrs([{{TDomain, TAddr}, _SecData} | T], Acc) ->
- ?vtrace("process_taddrs -> entry when bad v3 with"
- "~n TDomain: ~p"
- "~n TAddr: ~p", [TDomain, TAddr]),
- user_err("Bad TDomain/TAddr: ~w/~w", [TDomain, TAddr]),
- process_taddrs(T, Acc);
+ "~n TDomain: ~p"
+ "~n TAddress: ~p"
+ "~n SecData: ~p", [TDomain, TAddress, SecData]),
+ case transform_taddr(TDomain, TAddress) of
+ {ok, DestAddr} ->
+ ?vtrace("process_taddrs -> transformed: "
+ "~n DestAddr: ~p", [DestAddr]),
+ Entry = {DestAddr, SecData},
+ process_taddrs(T, [Entry | Acc]);
+ {error, Reason} ->
+ ?vinfo("Failed transforming v3 domain and address"
+ "~n Reason: ~p", [Reason]),
+ user_err("Bad TDomain/TAddress: ~w/~w", [TDomain, TAddress]),
+ process_taddrs(T, Acc)
+ end;
%% v1 & v2
-process_taddrs([{?snmpUDPDomain, [A,B,C,D,U1,U2]} | T], Acc) ->
+process_taddrs([{TDomain, TAddress} | T], Acc) ->
?vtrace("process_taddrs -> entry when v1/v2 with"
- "~n A: ~p"
- "~n B: ~p"
- "~n C: ~p"
- "~n D: ~p"
- "~n U1: ~p"
- "~n U2: ~p", [A, B, C, D, U1, U2]),
- Entry = {snmpUDPDomain, {{A,B,C,D}, U1 bsl 8 + U2}},
- process_taddrs(T, [Entry | Acc]);
-%% Bad v1 or v2
-process_taddrs([{TDomain, TAddr} | T], Acc) ->
- ?vtrace("process_taddrs -> entry when bad v1/v2 with"
- "~n TDomain: ~p"
- "~n TAddr: ~p", [TDomain, TAddr]),
- user_err("Bad TDomain/TAddr: ~w/~w", [TDomain, TAddr]),
- process_taddrs(T, Acc);
+ "~n TDomain: ~p"
+ "~n TAddress: ~p", [TDomain, TAddress]),
+ case transform_taddr(TDomain, TAddress) of
+ {ok, DestAddr} ->
+ ?vtrace("process_taddrs -> transformed: "
+ "~n DestAddr: ~p", [DestAddr]),
+ Entry = DestAddr,
+ process_taddrs(T, [Entry | Acc]);
+ {error, Reason} ->
+ ?vinfo("Failed transforming v1/v2 domain and address: "
+ "~n Reason: ~p", [Reason]),
+ user_err("Bad TDomain/TAddress: ~w/~w", [TDomain, TAddress]),
+ process_taddrs(T, Acc)
+ end;
process_taddrs(Crap, Acc) ->
- throw({error, {taddrs_crap, Crap, Acc}}).
+ throw({error, {bad_taddrs, Crap, Acc}}).
mk_v1_v2_packet_list(To, Packet, Len, Pdu) ->
diff --git a/lib/snmp/src/agent/snmpa_set_lib.erl b/lib/snmp/src/agent/snmpa_set_lib.erl
index 191029f6db..00c77a0cdb 100644
--- a/lib/snmp/src/agent/snmpa_set_lib.erl
+++ b/lib/snmp/src/agent/snmpa_set_lib.erl
@@ -378,15 +378,15 @@ dbg_apply(M,F,A) ->
Res
end,
case Result of
- {'EXIT', {undef, [{M, F, A} | _]}} ->
+ {'EXIT', {undef, [{M, F, A, _} | _]}} ->
{'EXIT', {hook_undef, {M, F, A}}};
- {'EXIT', {function_clause, [{M, F, A} | _]}} ->
+ {'EXIT', {function_clause, [{M, F, A, _} | _]}} ->
{'EXIT', {hook_function_clause, {M, F, A}}};
% XXX: Old format for compatibility
- {'EXIT', {undef, {M, F, A}}} ->
+ {'EXIT', {undef, {M, F, A, _}}} ->
{'EXIT', {hook_undef, {M, F, A}}};
- {'EXIT', {function_clause, {M, F, A}}} ->
+ {'EXIT', {function_clause, {M, F, A, _}}} ->
{'EXIT', {hook_function_clause, {M, F, A}}};
Result ->
diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src
index 5deb40be0f..af988fda26 100644
--- a/lib/snmp/src/app/snmp.appup.src
+++ b/lib/snmp/src/app/snmp.appup.src
@@ -22,175 +22,83 @@
%% ----- U p g r a d e -------------------------------------------------------
[
- {"4.19",
+ {"4.21.2",
[
- {load_module, snmpa, soft_purge, soft_purge, []},
- {load_module, snmpm, soft_purge, soft_purge, [snmpm_server]},
- {load_module, snmpa_usm, soft_purge, soft_purge, []},
- {load_module, snmpm_usm, soft_purge, soft_purge, []},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
- {load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmpa_conf, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_misc, soft_purge, soft_purge, []},
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmpa_mpd, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmpa_trap, soft_purge, soft_purge,
- [snmpa_mpd, snmp_notification_mib, snmp_target_mib, snmpa_net_if]},
- {load_module, snmpa_acm, soft_purge, soft_purge,
- [snmp_conf, snmpa_mpd, snmp_target_mib]},
- {load_module, snmpa_conf, soft_purge, soft_purge,
- [snmp_notification_mib]},
- {load_module, snmp_notification_mib, soft_purge, soft_purge,
- [snmp_conf, snmp_target_mib]},
- {load_module, snmp_community_mib, soft_purge, soft_purge, []},
- {load_module, snmp_target_mib, soft_purge, soft_purge,
- [snmp_conf]},
- {update, snmpm_net_if, soft, soft_purge, soft_purge, []},
- {update, snmpm_server, soft, soft_purge, soft_purge, [snmpm_net_if]},
- {update, snmpa_net_if, soft, soft_purge, soft_purge,
- [snmp_conf, snmpa_mpd]},
- {update, snmpa_agent, soft, soft_purge, soft_purge,
- [snmpa_acm, snmpa_mpd, snmpa_trap]}
]
},
- {"4.18",
+ {"4.21.1",
+ [
+ {update, snmp_note_store, soft, soft_purge, soft_purge, []}
+ ]
+ },
+ {"4.21",
+ [
+ {update, snmp_note_store, soft, soft_purge, soft_purge, []},
+ {load_module, snmp_target_mib, soft_purge, soft_purge, []}
+ ]
+ },
+ {"4.20.1",
[
- {load_module, snmpa, soft_purge, soft_purge, []},
- {load_module, snmpm, soft_purge, soft_purge, [snmpm_server]},
- {load_module, snmpa_usm, soft_purge, soft_purge, []},
- {load_module, snmpm_usm, soft_purge, soft_purge, []},
- {load_module, snmp_misc, soft_purge, soft_purge, []},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
+ {load_module, snmp_target_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []},
+ {load_module, snmpm, soft_purge, soft_purge,
+ [snmpm_server, snmpm_config, snmp_config]},
{load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmp_config, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmpa_conf, soft_purge, soft_purge, []},
- {load_module, snmpa_mpd, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmpa_vacm, soft_purge, soft_purge, []},
- {load_module, snmpa_trap, soft_purge, soft_purge,
- [snmpa_mpd, snmp_notification_mib, snmp_target_mib, snmpa_net_if]},
- {load_module, snmpa_acm, soft_purge, soft_purge,
- [snmp_conf, snmpa_mpd, snmp_target_mib]},
- {load_module, snmpa, soft_purge, soft_purge,
- [snmp_community_mib,
- snmp_framework_mib,
- snmp_standard_mib,
- snmp_target_mib,
- snmp_user_based_sm_mib,
- snmp_view_based_acm_mib]},
- {load_module, snmp_notification_mib, soft_purge, soft_purge,
- [snmp_conf, snmp_target_mib, snmpa_mib_lib]},
- {load_module, snmp_community_mib, soft_purge, soft_purge,
- [snmpa_mib_lib]},
- {load_module, snmp_framework_mib, soft_purge, soft_purge,
- [snmpa_mib_lib]},
- {load_module, snmp_standard_mib, soft_purge, soft_purge,
- [snmpa_mib_lib]},
- {load_module, snmp_target_mib, soft_purge, soft_purge,
- [snmpa_mib_lib]},
- {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge,
- [snmpa_mib_lib]},
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
- [snmpa_mib_lib, snmpa_vacm]},
- {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
-
- {update, snmpm_net_if, soft, soft_purge, soft_purge, []},
- {update, snmpm_server, soft, soft_purge, soft_purge, [snmpm_net_if]},
-
- {update, snmpa_net_if, soft, soft_purge, soft_purge,
- [snmp_conf, snmpa_mpd]},
- {update, snmpa_agent, soft, soft_purge, soft_purge,
- [snmpa_acm, snmpa_mpd, snmpa_trap]}
+ {load_module, snmp_config, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge,
+ [snmp_conf, snmp_config, snmpm_config]},
+ {load_module, snmpa_mpd, soft_purge, soft_purge,
+ [snmp_conf, snmp_config]},
+ {load_module, snmpa_conf, soft_purge, soft_purge, [snmp_config]},
+ {update, snmp_note_store, soft, soft_purge, soft_purge, []},
+ {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mpd]},
+ {update, snmpm_config, soft, soft_purge, soft_purge, [snmp_conf]},
+ {update, snmpm_server, soft, soft_purge, soft_purge,
+ [snmpm_net_if, snmpm_mpd, snmpm_config]},
+ {update, snmpm_net_if, soft, soft_purge, soft_purge,
+ [snmp_conf, snmpm_mpd, snmpm_config]}
]
- }
+ }
],
%% ------D o w n g r a d e ---------------------------------------------------
[
- {"4.19",
+ {"4.21.2",
[
- {load_module, snmpa, soft_purge, soft_purge, []},
- {load_module, snmpm, soft_purge, soft_purge, [snmpm_server]},
- {load_module, snmpa_usm, soft_purge, soft_purge, []},
- {load_module, snmpm_usm, soft_purge, soft_purge, []},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
- {load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmpa_conf, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmp_misc, soft_purge, soft_purge, []},
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmpa_mpd, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmpa_trap, soft_purge, soft_purge,
- [snmpa_mpd, snmp_notification_mib, snmp_target_mib, snmpa_net_if]},
- {load_module, snmpa_acm, soft_purge, soft_purge,
- [snmp_conf, snmpa_mpd, snmp_target_mib]},
- {load_module, snmpa_conf, soft_purge, soft_purge,
- [snmp_notification_mib]},
- {load_module, snmp_notification_mib, soft_purge, soft_purge,
- [snmp_conf, snmp_target_mib]},
- {load_module, snmp_community_mib, soft_purge, soft_purge, []},
- {load_module, snmp_target_mib, soft_purge, soft_purge,
- [snmp_conf]},
-
- {update, snmpm_net_if, soft, soft_purge, soft_purge, []},
- {update, snmpm_server, soft, soft_purge, soft_purge, [snmpm_net_if]},
-
- {update, snmpa_net_if, soft, soft_purge, soft_purge,
- [snmp_conf, snmpa_mpd]},
- {update, snmpa_agent, soft, soft_purge, soft_purge,
- [snmpa_acm, snmpa_mpd, snmpa_trap]}
]
},
- {"4.18",
+ {"4.21.1",
+ [
+ {update, snmp_note_store, soft, soft_purge, soft_purge, []}
+ ]
+ },
+ {"4.21",
+ [
+ {update, snmp_note_store, soft, soft_purge, soft_purge, []},
+ {load_module, snmp_target_mib, soft_purge, soft_purge, []}
+ ]
+ },
+ {"4.20.1",
[
- {load_module, snmpa, soft_purge, soft_purge, []},
- {load_module, snmpm, soft_purge, soft_purge, [snmpm_server]},
- {load_module, snmpa_usm, soft_purge, soft_purge, []},
- {load_module, snmpm_usm, soft_purge, soft_purge, []},
- {load_module, snmp_misc, soft_purge, soft_purge, []},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
+ {load_module, snmp_target_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []},
+ {load_module, snmpm, soft_purge, soft_purge,
+ [snmpm_server, snmpm_config, snmp_config]},
{load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmpa_conf, soft_purge, soft_purge, [snmp_conf]},
{load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmpa_mpd, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmpa_vacm, soft_purge, soft_purge, []},
- {load_module, snmpa_trap, soft_purge, soft_purge,
- [snmpa_mpd, snmp_notification_mib, snmp_target_mib, snmpa_net_if]},
- {load_module, snmpa_acm, soft_purge, soft_purge,
- [snmp_conf, snmpa_mpd, snmp_target_mib]},
- {load_module, snmpa, soft_purge, soft_purge,
- [snmp_community_mib,
- snmp_framework_mib,
- snmp_standard_mib,
- snmp_target_mib,
- snmp_user_based_sm_mib,
- snmp_view_based_acm_mib]},
- {load_module, snmp_notification_mib, soft_purge, soft_purge,
- [snmp_conf, snmp_target_mib, snmpa_mib_lib]},
- {load_module, snmp_community_mib, soft_purge, soft_purge,
- [snmpa_mib_lib]},
- {load_module, snmp_framework_mib, soft_purge, soft_purge,
- [snmpa_mib_lib]},
- {load_module, snmp_standard_mib, soft_purge, soft_purge,
- [snmpa_mib_lib]},
- {load_module, snmp_target_mib, soft_purge, soft_purge,
- [snmpa_mib_lib]},
- {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge,
- [snmpa_mib_lib]},
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
- [snmpa_mib_lib, snmpa_vacm]},
- {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
-
- {update, snmpm_net_if, soft, soft_purge, soft_purge, []},
- {update, snmpm_server, soft, soft_purge, soft_purge, [snmpm_net_if]},
-
- {update, snmpa_net_if, soft, soft_purge, soft_purge,
- [snmp_conf, snmpa_mpd]},
- {update, snmpa_agent, soft, soft_purge, soft_purge,
- [snmpa_acm, snmpa_mpd, snmpa_trap]}
+ {load_module, snmpm_mpd, soft_purge, soft_purge,
+ [snmp_conf, snmp_config, snmpm_config]},
+ {load_module, snmpa_mpd, soft_purge, soft_purge,
+ [snmp_conf, snmp_config]},
+ {load_module, snmpa_conf, soft_purge, soft_purge, [snmp_config]},
+ {update, snmp_note_store, soft, soft_purge, soft_purge, []},
+ {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mpd]},
+ {update, snmpm_config, soft, soft_purge, soft_purge, [snmp_conf]},
+ {update, snmpm_server, soft, soft_purge, soft_purge,
+ [snmpm_net_if, snmpm_mpd, snmpm_config]},
+ {update, snmpm_net_if, soft, soft_purge, soft_purge,
+ [snmp_conf, snmpm_mpd, snmpm_config]}
]
}
]
diff --git a/lib/snmp/src/compile/Makefile b/lib/snmp/src/compile/Makefile
index 0ceaf276a6..627af6f185 100644
--- a/lib/snmp/src/compile/Makefile
+++ b/lib/snmp/src/compile/Makefile
@@ -45,11 +45,10 @@ RELSYSDIR = $(RELEASE_PATH)/lib/snmp-$(VSN)
include modules.mk
-ESCRIPT_BIN = $(ESCRIPT_SRC:%.src=$(BIN)/%)
-
-ERL_FILES = $(MODULES:%=%.erl)
-
-TARGET_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(ESCRIPT_BIN)
+ESCRIPT_BIN = $(ESCRIPT_SRC:%.src=$(BIN)/%)
+ERL_FILES = $(MODULES:%=%.erl)
+EBIN_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+TARGET_FILES = $(EBIN_FILES) $(ESCRIPT_BIN)
GENERATED_PARSER = $(PARSER_MODULE:%=%.erl)
@@ -125,7 +124,7 @@ release_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)/src/compiler
$(INSTALL_DATA) $(ESCRIPT_SRC) $(PARSER_SRC) $(ERL_FILES) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src/compiler
$(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DATA) $(EBIN_FILES) $(RELSYSDIR)/ebin
$(INSTALL_DIR) $(RELSYSDIR)/bin
$(INSTALL_SCRIPT) $(ESCRIPT_BIN) $(RELSYSDIR)/bin
diff --git a/lib/snmp/src/compile/depend.mk b/lib/snmp/src/compile/depend.mk
index f7084f8bcd..3ee8dc4bec 100644
--- a/lib/snmp/src/compile/depend.mk
+++ b/lib/snmp/src/compile/depend.mk
@@ -44,6 +44,6 @@ $(EBIN)/snmpc_mib_gram.$(EMULATOR): \
../../include/snmp_types.hrl \
snmpc_mib_gram.erl
-$(BIN)/snmpc: snmpc.src
+$(BIN)/snmpc: snmpc.src ../../vsn.mk
$(PERL) -p -e 's?%VSN%?$(VSN)? ' < $< > $@
chmod 755 $@
diff --git a/lib/snmp/src/compile/snmpc.erl b/lib/snmp/src/compile/snmpc.erl
index 195c238184..5e6b81f1ec 100644
--- a/lib/snmp/src/compile/snmpc.erl
+++ b/lib/snmp/src/compile/snmpc.erl
@@ -108,6 +108,7 @@ compile(FileName) ->
%% {i, [import_dir_string()]} ["./"]
%% {il, [import_lib_dir_string()]} []
%% {warnings, bool()} true
+%% warnings_as_errors
%% {outdir, string()} "./"
%% description
%% reference
@@ -199,6 +200,8 @@ get_options([reference|Opts], Formats, Args) ->
get_options(Opts, ["~n reference"|Formats], Args);
get_options([{warnings, Val}|Opts], Formats, Args) ->
get_options(Opts, ["~n warnings: ~w"|Formats], [Val|Args]);
+get_options([warnings_as_errors|Opts], Formats, Args) ->
+ get_options(Opts, ["~n warnings_as_errors"|Formats], Args);
get_options([{verbosity, Val}|Opts], Formats, Args) ->
get_options(Opts, ["~n verbosity: ~w"|Formats], [Val|Args]);
get_options([imports|Opts], Formats, Args) ->
@@ -261,6 +264,8 @@ check_options([{group_check, Atom} | T]) when is_atom(Atom) ->
check_options([{warnings, Bool} | T]) ->
check_bool(warnings, Bool),
check_options(T);
+check_options([warnings_as_errors | T]) ->
+ check_options(T);
check_options([{db, volatile} | T]) ->
check_options(T);
check_options([{db, persistent} | T]) ->
@@ -331,6 +336,9 @@ get_agent_capabilities(Options) ->
get_module_compliance(Options) ->
get_bool_option(module_compliance, Options).
+get_warnings_as_errors(Options) ->
+ lists:member(warnings_as_errors, Options).
+
get_relaxed_row_name_assign_check(Options) ->
lists:member(relaxed_row_name_assign_check, Options).
@@ -409,6 +417,7 @@ init(From, MibFileName, Options) ->
put(reference, get_reference(Options)),
put(agent_capabilities, get_agent_capabilities(Options)),
put(module_compliance, get_module_compliance(Options)),
+ put(warnings_as_errors, get_warnings_as_errors(Options)),
File = filename:rootname(MibFileName, ".mib"),
put(filename, filename:basename(File ++ ".mib")),
R = case catch c_impl(File) of
diff --git a/lib/snmp/src/compile/snmpc.src b/lib/snmp/src/compile/snmpc.src
index 5f9b154bfa..868e0929b4 100644
--- a/lib/snmp/src/compile/snmpc.src
+++ b/lib/snmp/src/compile/snmpc.src
@@ -46,11 +46,12 @@
agent_capabilities = false,
module,
no_defaults = false,
- relaxed_row_name_assigne_check = false,
+ relaxed_row_name_assign_check = false,
%% The default verbosity (silence) will be filled in
%% during argument processing.
verbosity,
- warnings = false
+ warnings = false,
+ warnings_as_errors = false
}).
@@ -73,7 +74,8 @@
%% --rrnac
%% --version
%% --verbosity V
-%% --warnings
+%% --warnings | --W
+%% --Werror | --wae | --warnings_as_errors
main(Args) when is_list(Args) ->
case (catch process_args(Args)) of
ok ->
@@ -152,11 +154,12 @@ mk_mib_options(#state{outdir = OutDir,
agent_capabilities = AC,
module = Mod,
no_defaults = ND,
- relaxed_row_name_assigne_check = RRNAC,
+ relaxed_row_name_assign_check = RRNAC,
%% The default verbosity (silence) will be filled in
%% during argument processing.
verbosity = V,
- warnings = W}) ->
+ warnings = W,
+ warnings_as_errors = WAE}) ->
[{outdir, OutDir},
{db, DB},
{i, IDs},
@@ -178,7 +181,8 @@ mk_mib_options(#state{outdir = OutDir,
maybe_option(Imp, imports) ++
maybe_option(MI, module_identity) ++
maybe_option(MC, module_compliance) ++
- maybe_option(AC, agent_capabilities).
+ maybe_option(AC, agent_capabilities) ++
+ maybe_option(WAE, warnings_as_errors).
maybe_option(true, Opt) -> [Opt];
maybe_option(_, _) -> [].
@@ -217,7 +221,10 @@ process_args([], #state{verbosity = Verbosity0, file = MIB} = State) ->
process_args(["--help"|_Args], _State) ->
ok;
process_args(["--version"|_Args], #state{version = Version, mfv = MFV} = _State) ->
- {ok, lists:flatten(io_lib:format("snmpc ~s (~s)", [Version, MFV]))};
+ OtpVersion = otp_release(),
+ {ok, lists:flatten(
+ io_lib:format("snmpc ~s [Mib format version ~s] (OTP ~s)",
+ [Version, MFV, OtpVersion]))};
process_args(["--verbosity", Verbosity0|Args], #state{verbosity = V} = State)
when (V =:= undefined) ->
Verbosity = list_to_atom(Verbosity0),
@@ -230,6 +237,8 @@ process_args(["--verbosity", Verbosity0|Args], #state{verbosity = V} = State)
process_args(["--verbosity"|_Args], #state{verbosity = V})
when (V =/= undefined) ->
e(lists:flatten(io_lib:format("Verbosity already set to ~w", [V])));
+process_args(["--W"|Args], State) ->
+ process_args(Args, State#state{warnings = true});
process_args(["--warnings"|Args], State) ->
process_args(Args, State#state{warnings = true});
process_args(["--o", Dir|Args], State) ->
@@ -291,7 +300,13 @@ process_args(["--mod"|_Args], #state{module = M})
process_args(["--nd"|Args], State) ->
process_args(Args, State#state{no_defaults = true});
process_args(["--rrnac"|Args], State) ->
- process_args(Args, State#state{relaxed_row_name_assigne_check = true});
+ process_args(Args, State#state{relaxed_row_name_assign_check = true});
+process_args(["--Werror"|Args], State) ->
+ process_args(Args, State#state{warnings_as_errors = true});
+process_args(["--wae"|Args], State) ->
+ process_args(Args, State#state{warnings_as_errors = true});
+process_args(["--warnings_as_errors"|Args], State) ->
+ process_args(Args, State#state{warnings_as_errors = true});
process_args([MIB], State) ->
Ext = filename:extension(MIB),
if
@@ -326,7 +341,7 @@ usage() ->
"~n --verbosity <verbosity> - Print debug info."
"~n verbosity = trace | debug | log | info | silence"
"~n Defaults to silence."
- "~n --warnings - Print warning messages."
+ "~n --warnings | --W - Print warning messages."
"~n --o <output dir> - The output dir."
"~n Defaults to current working dir."
"~n --i <include dir> - Add this dir to the list of dirs that will be"
@@ -334,16 +349,19 @@ usage() ->
"~n The current workin dir will always be included. "
"~n --il <include_lib dir> - Add this dir to the list of dirs that will be"
"~n searched for imported (compiled) MIB files."
- "~n It assumes that the first element in the dir name"
- "~n correspond to an OTP application. For example snmp/mibs/"
- "~n The current workin dir and the <snmp-home>/priv/mibs "
+ "~n It assumes that the first element in the dir "
+ "~n name correspond to an OTP application. "
+ "~n For example snmp/mibs/ "
+ "~n The current workin dir and the "
+ "~n <snmp-home>/priv/mibs "
"~n are always listed last the includ path. "
"~n --db <DB> - Database to used for the default instrumentation."
"~n Defaults to volatile."
- "~n --sgc - This option (skip group check), if present, disables "
- "~n the \"group check\" of the mib compiler. "
- "~n That is, should the OBJECT-GROUP and the NOTIFICATION-GROUP "
- "~n macro(s) be checked for correctness or not. "
+ "~n --sgc - This option (skip group check), if present, "
+ "~n disables the \"group check\" of the mib compiler. "
+ "~n That is, should the OBJECT-GROUP and the "
+ "~n NOTIFICATION-GROUP macro(s) be checked for "
+ "~n correctness or not. "
"~n By default the check is done. "
"~n --dep - Keep deprecated definition(s)."
"~n If not specified the compiler will ignore"
@@ -354,23 +372,27 @@ usage() ->
"~n --mi - The MODULE-IDENTITY field will be included."
"~n --mc - The MODULE-COMPLIANCE field will be included."
"~n --ac - The AGENT-CAPABILITIES field will be included."
- "~n --mod <module> - The module which implements all the instrumentation"
- "~n functions. "
+ "~n --mod <module> - The module which implements all the "
+ "~n instrumentation functions. "
"~n The name of all instrumentation functions must"
"~n be the same as the corresponding managed object"
"~n it implements."
- "~n --nd - The default instrumentation functions will *not* be used"
- "~n if a managed object have no instrumentation function. "
- "~n Instead this will be reported as an error, and the "
- "~n compilation aborts. "
- "~n --rrnac - This option, if present, specifies that the row name "
- "~n assign check shall not be done strictly according to"
- "~n the SMI (which allows only the value 1). "
- "~n With this option, all values greater than zero is allowed"
- "~n (>= 1). This means that the error will be converted to "
+ "~n --nd - The default instrumentation functions will *not* "
+ "~n be used if a managed object have no "
+ "~n instrumentation function. Instead this will be "
+ "~n reported as an error, and the compilation aborts. "
+ "~n --rrnac - This option, if present, specifies that the row "
+ "~n name assign check shall not be done strictly "
+ "~n according to the SMI (which allows only the "
+ "~n value 1). With this option, all values greater "
+ "~n than zero is allowed (>= 1). "
+ "~n This means that the error will be converted to "
"~n a warning. "
- "~n By default it is not included, but if this option is "
- "~n present it will be. "
+ "~n By default it is not included, but if this "
+ "~n option is present it will be. "
+ "~n --wae | --Werror - Warnings as errors. "
+ "~n Indicates that warnings shall be treated as "
+ "~n errors. "
"~n "
"~n", []),
halt(1).
@@ -379,3 +401,17 @@ usage() ->
e(Reason) ->
throw({error, Reason}).
+
+otp_release() ->
+ system_info(otp_release, string).
+
+system_info(Tag, Type) ->
+ case (catch erlang:system_info(Tag)) of
+ {'EXIT', _} ->
+ "-";
+ Info when is_list(Info) andalso (Type =:= string) ->
+ Info;
+ Info ->
+ lists:flatten(io_lib:format("~w", [Info]))
+ end.
+
diff --git a/lib/snmp/src/compile/snmpc_lib.erl b/lib/snmp/src/compile/snmpc_lib.erl
index 4f71c47bfa..38bb8f3ac6 100644
--- a/lib/snmp/src/compile/snmpc_lib.erl
+++ b/lib/snmp/src/compile/snmpc_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1754,12 +1754,12 @@ error(FormatStr, Data, Line) when is_list(FormatStr) ->
exit(error).
print_error(FormatStr, Data) when is_list(FormatStr) ->
- ok = io:format("~s: Error: " ++ FormatStr,[get(filename)|Data]),
+ ok = io:format("~s: " ++ FormatStr,[get(filename)|Data]),
put(errors,yes),
io:format("~n").
print_error(FormatStr, Data,Line) when is_list(FormatStr) ->
- ok = io:format("~s: ~w: Error: " ++ FormatStr,[get(filename), Line |Data]),
+ ok = io:format("~s: ~w: " ++ FormatStr,[get(filename), Line |Data]),
put(errors,yes),
io:format("~n").
diff --git a/lib/snmp/src/compile/snmpc_lib.hrl b/lib/snmp/src/compile/snmpc_lib.hrl
index 000486e728..35ec9abd03 100644
--- a/lib/snmp/src/compile/snmpc_lib.hrl
+++ b/lib/snmp/src/compile/snmpc_lib.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -20,8 +20,17 @@
-ifndef(snmpc_lib).
-define(snmpc_lib, true).
--define(vwarning(F, A), ?verbosity(warning, F, A, ignore)).
--define(vwarning2(F, A, MibLine), ?verbosity(warning, F, A, MibLine)).
+-define(vwarning(F, A),
+ case get(warnings_as_errors) of
+ true -> snmpc_lib:error(F, A);
+ _ -> ?verbosity(warning, F, A, ignore)
+ end).
+
+-define(vwarning2(F, A, MibLine),
+ case get(warnings_as_errors) of
+ true -> snmpc_lib:error(F, A, MibLine);
+ _ -> ?verbosity(warning, F, A, MibLine)
+ end).
-define(vinfo(F, A), ?verbosity(info, F, A, ignore)).
-define(vinfo2(F, A, MibLine), ?verbosity(info, F, A, MibLine)).
-define(vlog(F, A), ?verbosity(log, F, A, ignore)).
diff --git a/lib/snmp/src/manager/snmpm.erl b/lib/snmp/src/manager/snmpm.erl
index 0d084332de..6d2ac8d747 100644
--- a/lib/snmp/src/manager/snmpm.erl
+++ b/lib/snmp/src/manager/snmpm.erl
@@ -50,7 +50,7 @@
register_agent/2, register_agent/3, register_agent/4,
unregister_agent/2, unregister_agent/3,
which_agents/0, which_agents/1,
- agent_info/2, update_agent_info/4,
+ agent_info/2, update_agent_info/3, update_agent_info/4,
register_usm_user/3, unregister_usm_user/2,
which_usm_users/0, which_usm_users/1,
@@ -167,6 +167,7 @@
-include_lib("snmp/include/snmp_types.hrl").
-include("snmpm_atl.hrl").
-include("snmpm_internal.hrl").
+-include("snmp_verbosity.hrl").
-define(DEFAULT_AGENT_PORT, 161).
@@ -447,8 +448,11 @@ agent_info(Addr, Port, Item) ->
Error
end.
+update_agent_info(UserId, TargetName, Info) when is_list(Info) ->
+ snmpm_config:update_agent_info(UserId, TargetName, Info).
+
update_agent_info(UserId, TargetName, Item, Val) ->
- snmpm_config:update_agent_info(UserId, TargetName, Item, Val).
+ update_agent_info(UserId, TargetName, [{Item, Val}]).
%% Backward compatibility functions
update_agent_info(UserId, Addr, Port, Item, Val) ->
diff --git a/lib/snmp/src/manager/snmpm_config.erl b/lib/snmp/src/manager/snmpm_config.erl
index fd6da3e71a..c2e57abddb 100644
--- a/lib/snmp/src/manager/snmpm_config.erl
+++ b/lib/snmp/src/manager/snmpm_config.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -36,7 +36,8 @@
user_info/0, user_info/1, user_info/2,
register_agent/3, unregister_agent/2,
- agent_info/0, agent_info/2, agent_info/3, update_agent_info/4,
+ agent_info/0, agent_info/2, agent_info/3,
+ update_agent_info/3, update_agent_info/4,
which_agents/0, which_agents/1,
is_known_engine_id/2,
@@ -84,7 +85,9 @@
backup/1,
- mk_target_name/3
+ mk_target_name/3,
+
+ default_transport_domain/0
]).
@@ -127,23 +130,24 @@
%% Macros and Constants:
--define(SERVER, ?MODULE).
--define(BACKUP_DB, snmpm_config_backup).
--define(CONFIG_DB, snmpm_config_db).
+-define(SERVER, ?MODULE).
+-define(BACKUP_DB, snmpm_config_backup).
+-define(CONFIG_DB, snmpm_config_db).
-define(DEFAULT_USER, default_user).
-define(DEFAULT_AGENT_PORT, 161).
--define(IRB_DEFAULT, auto).
-%% -define(IRB_DEFAULT, {user, timer:seconds(15)}).
+-define(IRB_DEFAULT, auto).
+%% -define(IRB_DEFAULT, {user, timer:seconds(15)}).
--define(USER_MOD_DEFAULT, snmpm_user_default).
--define(USER_DATA_DEFAULT, undefined).
+-define(USER_MOD_DEFAULT, snmpm_user_default).
+-define(USER_DATA_DEFAULT, undefined).
%% -define(DEF_ADDR_TAG, default_addr_tag).
-define(DEFAULT_TARGETNAME, default_agent).
--define(DEF_PORT_TAG, default_port_tag).
+-define(DEF_PORT_TAG, default_port_tag).
+-define(SUPPORTED_DOMAINS, [transportDomainUdpIpv4, transportDomainUdpIpv6]).
-ifdef(snmp_debug).
-define(GS_START_LINK(Opts),
@@ -159,6 +163,11 @@
%%%-------------------------------------------------------------------
%%% API
%%%-------------------------------------------------------------------
+
+default_transport_domain() ->
+ transportDomainUdpIpv4.
+
+
start_link(Opts) ->
?d("start_link -> entry with"
"~n Opts: ~p", [Opts]),
@@ -269,9 +278,10 @@ do_user_info(_UserId, BadItem) ->
error({not_found, BadItem}).
-%% A target-name constructed in this way is a string with the following
+%% A target-name constructed in this way is a string with the following:
%% <IP-address>:<Port>-<Version>
-%%
+%% This is intended for backward compatibility and therefor has
+%% only support for IPv4 addresses and *no* other transport domain.
mk_target_name(Addr0, Port, Config) when is_list(Config) ->
Version =
case lists:keysearch(version, 1, Config) of
@@ -280,7 +290,6 @@ mk_target_name(Addr0, Port, Config) when is_list(Config) ->
false ->
select_lowest_supported_version()
end,
-%% p("mk_target_name -> Version: ~p", [Version]),
case normalize_address(Addr0) of
{A, B, C, D} ->
lists:flatten(
@@ -308,57 +317,99 @@ select_lowest_supported_version([H|T], Versions) ->
end.
-register_agent(UserId, _TargetName, _Config) when (UserId =:= user_id) ->
+register_agent(UserId, _TargetName, _Config0) when (UserId =:= user_id) ->
{error, {bad_user_id, UserId}};
-register_agent(UserId, TargetName, Config)
+register_agent(UserId, TargetName, Config0)
when (is_list(TargetName) andalso
(length(TargetName) > 0) andalso
- is_list(Config)) ->
+ is_list(Config0)) ->
-%% p("register_agent -> entry with"
-%% "~n UserId: ~p"
-%% "~n TargetName: ~p"
-%% "~n Config: ~p", [UserId, TargetName, Config]),
+ ?vtrace("register_agent -> entry with"
+ "~n UserId: ~p"
+ "~n TargetName: ~p"
+ "~n Config0: ~p", [UserId, TargetName, Config0]),
%% Check:
%% 1) That the mandatory configs are present
- %% 2) That the illegal config user_id (used internally) is
- %% not present
+ %% 2) That no illegal config, e.g. user_id (used internally),
+ %% is not present
%% 3) Check that there are no invalid or erroneous configs
- %% 4) Chack that the manager is capable to use the selected version
- case verify_agent_config(Config) of
- ok ->
+ %% 4) Check that the manager is capable of using the selected version
+ case verify_agent_config(Config0) of
+ {ok, Config} ->
call({register_agent, UserId, TargetName, Config});
Error ->
Error
end.
-verify_agent_config(Conf) ->
- ok = verify_mandatory(Conf, [engine_id, address, reg_type]),
- case verify_invalid(Conf, [user_id]) of
- ok ->
- case verify_agent_config2(Conf) of
- ok ->
- {ok, Vsns} = system_info(versions),
- Vsn =
- case lists:keysearch(version, 1, Conf) of
- {value, {version, V}} ->
- V;
- false ->
- v1
- end,
- case lists:member(Vsn, Vsns) of
- true ->
- ok;
- false ->
- {error, {version_not_supported_by_manager, Vsn, Vsns}}
- end
- end;
- Error ->
+verify_agent_config(Conf0) ->
+ try
+ begin
+ verify_mandatory(Conf0, [engine_id, address, reg_type]),
+ verify_invalid(Conf0, [user_id]),
+ Conf = verify_agent_config3(Conf0),
+ Vsns = versions(),
+ Vsn = which_version(Conf),
+ verify_version(Vsn, Vsns),
+ {ok, Conf}
+ end
+ catch
+ throw:Error ->
Error
end.
+versions() ->
+ case system_info(versions) of
+ {ok, Vsns} ->
+ Vsns;
+ {error, _} = ERROR ->
+ throw(ERROR)
+ end.
+
+which_version(Conf) ->
+ case lists:keysearch(version, 1, Conf) of
+ {value, {version, V}} ->
+ V;
+ false ->
+ v1
+ end.
+
+verify_version(Vsn, Vsns) ->
+ case lists:member(Vsn, Vsns) of
+ true ->
+ ok;
+ false ->
+ Reason = {version_not_supported_by_manager, Vsn, Vsns},
+ throw({error, Reason})
+ end.
+
+verify_agent_config3(Conf0) ->
+ %% Fix (transport) address and domain
+ {TDomain, Conf1} =
+ case lists:keysearch(tdomain, 1, Conf0) of
+ {value, {tdomain, Dom}} ->
+ {Dom, Conf0};
+ false ->
+ Dom = default_transport_domain(),
+ {Dom, [{tdomain, Dom} | Conf0]}
+ end,
+ Conf2 = case lists:keysearch(address, 1, Conf1) of
+ {value, {address, Address}} ->
+ lists:keyreplace(address, 1, Conf1,
+ {address, {TDomain, Address}});
+ false ->
+ %% This is a mandatory config option,
+ %% a later test will detect this
+ Conf1
+ end,
+ case verify_agent2(Conf2) of
+ {ok, Conf} ->
+ Conf;
+ {error, _} = ERROR ->
+ throw(ERROR)
+ end.
+
verify_agent_config2(Conf) ->
verify_agent2(Conf).
@@ -366,6 +417,7 @@ verify_agent_config2(Conf) ->
unregister_agent(UserId, TargetName) ->
call({unregister_agent, UserId, TargetName}).
+%% This is the old style agent unregistration (using Addr and Port).
unregister_agent(UserId, Addr0, Port) ->
Addr = normalize_address(Addr0),
case do_agent_info(Addr, Port, target_name) of
@@ -421,17 +473,51 @@ which_agents(UserId) ->
Agents = ets:match(snmpm_agent_table, Pat),
[TargetName || [TargetName] <- Agents].
-
-update_agent_info(UserId, TargetName, Item, Val0)
- when (Item =/= user_id) ->
- case (catch verify_val(Item, Val0)) of
- {ok, Val} ->
- call({update_agent_info, UserId, TargetName, Item, Val});
- Error ->
+
+verify_agent_info(TargetName, Info0) ->
+ try
+ begin
+ verify_invalid(Info0, [user_id]),
+ %% Check if address is part of the list and
+ %% if so update it with the domain info.
+ Info =
+ case lists:keysearch(address, 1, Info0) of
+ {value, {address, Addr}} ->
+ %% If domain is part of the info, then use it.
+ %% If not, lookup what is already stored for
+ %% this agent and use that.
+ Domain =
+ case lists:keysearch(tdomain, 1, Info0) of
+ {value, {tdomain, Dom}} ->
+ Dom;
+ false ->
+ {ok, Dom} =
+ agent_info(TargetName, tdomain),
+ Dom
+ end,
+ Addr2 = {Domain, Addr},
+ lists:keyreplace(address, 1, Info0, {address, Addr2});
+ false ->
+ Info0
+ end,
+ verify_agent2(Info)
+ end
+ catch
+ throw:Error ->
Error
end.
-%% Backward compatibillity
+update_agent_info(UserId, TargetName, Info) ->
+ call({update_agent_info, UserId, TargetName, Info}).
+
+%% <BACKWARD-COMPAT-2>
+%% This is wrapped in the interface module, so this function is
+%% only here to catch code-upgrade problems.
+update_agent_info(UserId, TargetName, Item, Val) ->
+ update_agent_info(UserId, TargetName, [{Item, Val}]).
+%% </BACKWARD-COMPAT-2>
+
+%% <BACKWARD-COMPAT-1>
update_agent_info(UserId, Addr, Port, Item, Val) ->
case agent_info(Addr, Port, target_name) of
{ok, TargetName} ->
@@ -439,6 +525,7 @@ update_agent_info(UserId, Addr, Port, Item, Val) ->
Error ->
Error
end.
+%% </BACKWARD-COMPAT-1>
is_known_engine_id(EngineID, TargetName) ->
case agent_info(TargetName, engine_id) of
@@ -650,22 +737,14 @@ unregister_usm_user(EngineID, Name)
call({unregister_usm_user, EngineID, Name}).
verify_usm_user_config(EngineID, Name, Config) ->
- %% case verify_mandatory(Config, []) of
- %% ok ->
- %% case verify_invalid(Config, [engine_id, name]) of
- %% ok ->
- %% verify_usm_user_config2(EngineID, Name, Config);
- %% Error ->
- %% Error
- %% end;
- %% Error ->
- %% Error
- %% end.
- ok = verify_mandatory(Config, []),
- case verify_invalid(Config, [engine_id, name]) of
- ok ->
- verify_usm_user_config2(EngineID, Name, Config);
- Error ->
+ try
+ begin
+ verify_mandatory(Config, []),
+ verify_invalid(Config, [engine_id, name]),
+ verify_usm_user_config2(EngineID, Name, Config)
+ end
+ catch
+ throw:Error ->
Error
end.
@@ -1590,6 +1669,7 @@ check_agent_config2(Agent) ->
throw(Err)
end.
+%% For backward compatibility
check_agent_config({UserId,
TargetName,
Community,
@@ -1597,10 +1677,27 @@ check_agent_config({UserId,
EngineId,
Timeout, MaxMessageSize,
Version, SecModel, SecName, SecLevel}) ->
+ TDomain = default_transport_domain(),
+ check_agent_config({UserId,
+ TargetName,
+ Community,
+ TDomain, Ip, Port,
+ EngineId,
+ Timeout, MaxMessageSize,
+ Version, SecModel, SecName, SecLevel});
+
+check_agent_config({UserId,
+ TargetName,
+ Community,
+ TDomain, Ip, Port,
+ EngineId,
+ Timeout, MaxMessageSize,
+ Version, SecModel, SecName, SecLevel}) ->
?vtrace("check_agent_config -> entry with"
"~n UserId: ~p"
"~n TargetName: ~p"
"~n Community: ~p"
+ "~n TDomain: ~p"
"~n Ip: ~p"
"~n Port: ~p"
"~n EngineId: ~p"
@@ -1610,15 +1707,16 @@ check_agent_config({UserId,
"~n SecModel: ~p"
"~n SecName: ~p"
"~n SecLevel: ~p",
- [UserId, TargetName, Community, Ip, Port,
+ [UserId, TargetName, Community,
+ TDomain, Ip, Port,
EngineId, Timeout, MaxMessageSize,
Version, SecModel, SecName, SecLevel]),
- Addr = normalize_address(Ip),
+ Addr = normalize_address(TDomain, Ip),
?vtrace("check_agent_config -> Addr: ~p", [Addr]),
Agent = {UserId,
TargetName,
Community,
- Addr, Port,
+ TDomain, Addr, Port,
EngineId,
Timeout, MaxMessageSize,
Version, SecModel, SecName, SecLevel},
@@ -1644,6 +1742,7 @@ init_agent_config({UserId, TargetName, Config}) ->
end.
+%% For backward compatibility
verify_agent({UserId,
TargetName,
Comm,
@@ -1651,48 +1750,68 @@ verify_agent({UserId,
EngineId,
Timeout, MMS,
Version, SecModel, SecName, SecLevel}) ->
- ?vtrace("verify_agent -> entry with"
+ TDomain = default_transport_domain(),
+ verify_agent({UserId,
+ TargetName,
+ Comm,
+ TDomain, Ip, Port,
+ EngineId,
+ Timeout, MMS,
+ Version, SecModel, SecName, SecLevel});
+
+verify_agent({UserId,
+ TargetName,
+ Comm,
+ TDomain, Ip, Port,
+ EngineId,
+ Timeout, MMS,
+ Version, SecModel, SecName, SecLevel}) ->
+ ?vdebug("verify_agent -> entry with"
"~n UserId: ~p"
"~n TargetName: ~p", [UserId, TargetName]),
snmp_conf:check_string(TargetName, {gt, 0}),
- case verify_val(address, Ip) of
- {ok, Addr} ->
- snmp_conf:check_integer(Port, {gt, 0}),
- Conf =
- [{reg_type, target_name},
- {address, Addr},
- {port, Port},
- {community, Comm},
- {engine_id, EngineId},
- {timeout, Timeout},
- {max_message_size, MMS},
- {version, Version},
- {sec_model, SecModel},
- {sec_name, SecName},
- {sec_level, SecLevel}
- ],
- case verify_agent2(Conf) of
- ok ->
- {UserId, TargetName, Conf, Version};
- Err ->
- throw(Err)
- end;
-
- Error ->
- ?vlog("verify_agent -> failed: ~n ~p", [Error]),
- throw(Error)
+ snmp_conf:check_integer(Port, {gt, 0}),
+ %% Note that the order of Conf *is* important.
+ %% Some properties may depend on others, so that
+ %% in order to verify one property, another must
+ %% be already verified (and present). An example
+ %% of this is the property 'address', for which
+ %% the property tdomain is needed.
+ Conf0 =
+ [{reg_type, target_name},
+ {tdomain, TDomain},
+ %% This should be taddress, but what the*...
+ {address, {TDomain, Ip}},
+ {port, Port},
+ {community, Comm},
+ {engine_id, EngineId},
+ {timeout, Timeout},
+ {max_message_size, MMS},
+ {version, Version},
+ {sec_model, SecModel},
+ {sec_name, SecName},
+ {sec_level, SecLevel}
+ ],
+ case verify_agent2(Conf0) of
+ {ok, Conf} ->
+ {UserId, TargetName, Conf, Version};
+ Err ->
+ throw(Err)
end.
-verify_agent2([]) ->
- ok;
-verify_agent2([{Item, Val}|Items]) ->
- case verify_val(Item, Val) of
- {ok, _Val} ->
- verify_agent2(Items);
+verify_agent2(Conf) ->
+ verify_agent2(Conf, []).
+
+verify_agent2([], VerifiedConf) ->
+ {ok, VerifiedConf};
+verify_agent2([{Item, Val0}|Items], VerifiedConf) ->
+ case verify_val(Item, Val0) of
+ {ok, Val} ->
+ verify_agent2(Items, [{Item, Val} | VerifiedConf]);
Err ->
Err
end;
-verify_agent2([Bad|_]) ->
+verify_agent2([Bad|_], _VerifiedConf) ->
{error, {bad_agent_config, Bad}}.
@@ -1708,14 +1827,28 @@ read_users_config_file(Dir) ->
check_user_config({Id, Mod, Data}) ->
+ ?vtrace("check_user_config -> entry with"
+ "~n Id: ~p"
+ "~n Mod: ~p"
+ "~n Data: ~p", [Id, Mod, Data]),
check_user_config({Id, Mod, Data, []});
-check_user_config({Id, Mod, _Data, DefaultAgentConfig} = User)
+check_user_config({Id, Mod, Data, DefaultAgentConfig} = _User)
when (Id =/= ?DEFAULT_USER) andalso is_list(DefaultAgentConfig) ->
+ ?vtrace("check_user_config -> entry with"
+ "~n Id: ~p"
+ "~n Mod: ~p"
+ "~n Data: ~p"
+ "~n DefaultAgentConfig: ~p",
+ [Id, Mod, Data, DefaultAgentConfig]),
case (catch verify_user_behaviour(Mod)) of
ok ->
+ ?vtrace("check_user_config -> user behaviour verified", []),
case verify_user_agent_config(DefaultAgentConfig) of
- ok ->
- {ok, User};
+ {ok, DefAgentConf} ->
+ ?vtrace("check_user_config -> "
+ "user agent (default) config verified", []),
+ User2 = {Id, Mod, Data, DefAgentConf},
+ {ok, User2};
{error, Reason} ->
error({bad_default_agent_config, Reason})
end;
@@ -1756,16 +1889,16 @@ verify_user({Id, UserMod, UserData}) ->
verify_user({Id, UserMod, UserData, DefaultAgentConfig})
when (Id =/= ?DEFAULT_USER) andalso is_list(DefaultAgentConfig) ->
?d("verify_user -> entry with"
- "~n Id: ~p"
- "~n UserMod: ~p"
- "~n UserData: ~p"
+ "~n Id: ~p"
+ "~n UserMod: ~p"
+ "~n UserData: ~p"
"~n DefaultAgentConfig: ~p",
[Id, UserMod, UserData, DefaultAgentConfig]),
case (catch verify_user_behaviour(UserMod)) of
ok ->
case verify_user_agent_config(DefaultAgentConfig) of
- ok ->
- Config = default_agent_config(DefaultAgentConfig),
+ {ok, DefAgentConf} ->
+ Config = default_agent_config(DefAgentConf),
{ok, #user{id = Id,
mod = UserMod,
data = UserData,
@@ -1783,10 +1916,15 @@ verify_user({Id, _, _, _}) ->
{error, {bad_user_id, Id}}.
verify_user_agent_config(Conf) ->
- case verify_invalid(Conf, [user_id, engine_id, address]) of
- ok ->
- verify_agent_config2(Conf);
- Error ->
+ try
+ begin
+ verify_invalid(Conf, [user_id, engine_id, address]),
+ verify_agent_config2(Conf)
+ end
+ catch
+ throw:Error ->
+ ?vdebug("verify_user_agent_config -> throw"
+ "~n Error: ~p", [Error]),
Error
end.
@@ -2147,6 +2285,16 @@ handle_call({unregister_agent, UserId, TargetName}, _From, State) ->
Reply = handle_unregister_agent(UserId, TargetName),
{reply, Reply, State};
+handle_call({update_agent_info, UserId, TargetName, Info},
+ _From, State) ->
+ ?vlog("received update_agent_info request: "
+ "~n UserId: ~p"
+ "~n TargetName: ~p"
+ "~n Info: ~p", [UserId, TargetName, Info]),
+ Reply = handle_update_agent_info(UserId, TargetName, Info),
+ {reply, Reply, State};
+
+%% <BACKWARD-COMPAT>
handle_call({update_agent_info, UserId, TargetName, Item, Val},
_From, State) ->
?vlog("received update_agent_info request: "
@@ -2156,6 +2304,7 @@ handle_call({update_agent_info, UserId, TargetName, Item, Val},
"~n Val: ~p", [UserId, TargetName, Item, Val]),
Reply = handle_update_agent_info(UserId, TargetName, Item, Val),
{reply, Reply, State};
+%% </BACKWARD-COMPAT>
handle_call({register_usm_user, User}, _From, State) ->
?vlog("received register_usm_user request: "
@@ -2517,16 +2666,27 @@ handle_register_agent(UserId, TargetName, Config) ->
"~n Config: ~p", [UserId, TargetName, Config]),
case (catch agent_info(TargetName, user_id)) of
{error, _} ->
+ ?vtrace("handle_register_agent -> user_id not found in config", []),
case ets:lookup(snmpm_user_table, UserId) of
[#user{default_agent_config = DefConfig}] ->
+ ?vtrace("handle_register_agent -> "
+ "~n DefConfig: ~p", [DefConfig]),
+ %% First, insert this users default config
+ ?vtrace("handle_register_agent -> store default config", []),
do_handle_register_agent(TargetName, DefConfig),
+ %% Second, insert the config for this agent
+ ?vtrace("handle_register_agent -> store config", []),
do_handle_register_agent(TargetName,
[{user_id, UserId}|Config]),
%% <DIRTY-BACKWARD-COMPATIBILLITY>
%% And now for some (backward compatibillity)
%% dirty crossref stuff
+ ?vtrace("handle_register_agent -> lookup address", []),
{ok, Addr} = agent_info(TargetName, address),
+ ?vtrace("handle_register_agent -> Addr: ~p, lookup Port",
+ [Addr]),
{ok, Port} = agent_info(TargetName, port),
+ ?vtrace("handle_register_agent -> register cross-ref fix", []),
ets:insert(snmpm_agent_table,
{{Addr, Port, target_name}, TargetName}),
%% </DIRTY-BACKWARD-COMPATIBILLITY>
@@ -2551,10 +2711,18 @@ handle_register_agent(UserId, TargetName, Config) ->
do_handle_register_agent(_TargetName, []) ->
ok;
do_handle_register_agent(TargetName, [{Item, Val}|Rest]) ->
+ ?vtrace("handle_register_agent -> entry with"
+ "~n TargetName: ~p"
+ "~n Item: ~p"
+ "~n Val: ~p"
+ "~n Rest: ~p", [TargetName, Item, Val, Rest]),
case (catch do_update_agent_info(TargetName, Item, Val)) of
ok ->
do_handle_register_agent(TargetName, Rest);
{error, Reason} ->
+ ?vtrace("handle_register_agent -> failed updating ~p"
+ "~n Item: ~p"
+ "~n Reason: ~p", [Item, Reason]),
ets:match_delete(snmpm_agent_table, {TargetName, '_'}),
{error, Reason}
end;
@@ -2589,41 +2757,61 @@ handle_unregister_agent(UserId, TargetName) ->
end.
-handle_update_agent_info(UserId, TargetName, Item, Val) ->
+handle_update_agent_info(UserId, TargetName, Info) ->
?vdebug("handle_update_agent_info -> entry with"
"~n UserId: ~p"
"~n TargetName: ~p"
- "~n Item: ~p"
- "~n Val: ~p", [UserId, TargetName, Item, Val]),
+ "~n Info: ~p", [UserId, TargetName, Info]),
+ %% Verify ownership
case (catch agent_info(TargetName, user_id)) of
- {ok, UserId} ->
- do_update_agent_info(TargetName, Item, Val);
+ {ok, UserId} ->
+ handle_update_agent_info(TargetName, Info);
{ok, OtherUserId} ->
{error, {not_owner, OtherUserId}};
Error ->
Error
end.
-do_update_agent_info(TargetName, Item, Val0) ->
-%% p("do_update_agent_info -> entry with"
-%% "~n TargetName: ~p"
-%% "~n Item: ~p"
-%% "~n Val0: ~p", [TargetName, Item, Val0]),
- case verify_val(Item, Val0) of
- {ok, Val} ->
-%% p("do_update_agent_info -> verified value"
-%% "~n Val: ~p", [Val]),
- ets:insert(snmpm_agent_table, {{TargetName, Item}, Val}),
- ok;
+handle_update_agent_info(TargetName, Info0) ->
+ ?vtrace("handle_update_agent_info -> entry with"
+ "~n TargetName: ~p"
+ "~n Info0: ~p", [TargetName, Info0]),
+ %% Verify info
+ try verify_agent_info(TargetName, Info0) of
+ {ok, Info} ->
+ do_update_agent_info(TargetName, Info);
Error ->
- ?vlog("do_update_agent_info -> verify value failed: "
- "~n TargetName: ~p"
- "~n Item: ~p"
- "~n Val0: ~p"
- "~n Error: ~p", [TargetName, Item, Val0, Error]),
- {error, {bad_agent_val, TargetName, Item, Val0}}
+ Error
+ catch
+ throw:Error ->
+ Error;
+ T:E ->
+ {error, {failed_info_verification, Info0, T, E}}
end.
+handle_update_agent_info(UserId, TargetName, Item, Val) ->
+ ?vdebug("handle_update_agent_info -> entry with"
+ "~n UserId: ~p"
+ "~n TargetName: ~p"
+ "~n Item: ~p"
+ "~n Val: ~p", [UserId, TargetName, Item, Val]),
+ handle_update_agent_info(TargetName, [{Item, Val}]).
+
+do_update_agent_info(TargetName, Info) ->
+ InsertItem =
+ fun({Item, Val}) ->
+ ets:insert(snmpm_agent_table, {{TargetName, Item}, Val})
+ end,
+ lists:foreach(InsertItem, Info).
+
+do_update_agent_info(TargetName, Item, Val) ->
+ ?vtrace("do_update_agent_info -> entry with"
+ "~n TargetName: ~p"
+ "~n Item: ~p"
+ "~n Val: ~p", [TargetName, Item, Val]),
+ ets:insert(snmpm_agent_table, {{TargetName, Item}, Val}),
+ ok.
+
handle_register_usm_user(#usm_user{engine_id = EngineID,
name = Name} = User) ->
@@ -2791,7 +2979,7 @@ verify_mandatory(Conf, [Mand|Mands]) ->
true ->
verify_mandatory(Conf, Mands);
false ->
- {error, {missing_mandatory_config, Mand}}
+ throw({error, {missing_mandatory_config, Mand}})
end.
verify_invalid(_, []) ->
@@ -2801,7 +2989,7 @@ verify_invalid(Conf, [Inv|Invs]) ->
false ->
verify_invalid(Conf, Invs);
true ->
- {error, {illegal_config, Inv}}
+ throw({error, {illegal_config, Inv}})
end.
@@ -2810,10 +2998,26 @@ verify_val(user_id, UserId) ->
verify_val(reg_type, RegType)
when (RegType =:= addr_port) orelse (RegType =:= target_name) ->
{ok, RegType};
-verify_val(address, Addr0) ->
- case normalize_address(Addr0) of
+verify_val(tdomain = Item, snmpUDPDomain = _Domain) ->
+ verify_val(Item, transportDomainUdpIpv4);
+verify_val(tdomain, Domain) ->
+ case lists:member(Domain, ?SUPPORTED_DOMAINS) of
+ true ->
+ {ok, Domain};
+ false ->
+ case lists:member(Domain, snmp_conf:all_domains()) of
+ true ->
+ error({unsupported_domain, Domain});
+ false ->
+ error({unknown_domain, Domain})
+ end
+ end;
+verify_val(address, {Domain, Addr0}) ->
+ case normalize_address(Domain, Addr0) of
{_A1, _A2, _A3, _A4} = Addr ->
{ok, Addr};
+ {_A1, _A2, _A3, _A4, _A5, _A6, _A7, _A8} = Addr ->
+ {ok, Addr};
_ when is_list(Addr0) ->
case (catch snmp_conf:check_ip(Addr0)) of
ok ->
@@ -2824,6 +3028,8 @@ verify_val(address, Addr0) ->
_ ->
error({bad_address, Addr0})
end;
+verify_val(address, BadAddress) ->
+ error({bad_address, BadAddress});
verify_val(port, Port) ->
case (catch snmp_conf:check_integer(Port, {gt, 0})) of
ok ->
@@ -2875,7 +3081,7 @@ verify_val(sec_name, BadName) ->
verify_val(sec_level, Level) ->
(catch snmp_conf:check_sec_level(Level));
verify_val(Item, _) ->
- {error, {no_such_item, Item}}.
+ {error, {unknown_item, Item}}.
%%%-------------------------------------------------------------------
@@ -3034,11 +3240,17 @@ init_mini_mib_elems(MibName, [_|T], Res) ->
%%----------------------------------------------------------------------
normalize_address(Addr) ->
- case inet:getaddr(Addr, inet) of
+ normalize_address(snmpUDPDomain, Addr).
+
+normalize_address(snmpUDPDomain, Addr) ->
+ normalize_address(transportDomainUdpIpv4, Addr);
+
+normalize_address(Domain, Addr) ->
+ case inet:getaddr(Addr, td2fam(Domain)) of
{ok, Addr2} ->
Addr2;
_ when is_list(Addr) ->
- case (catch snmp_conf:check_ip(Addr)) of
+ case (catch snmp_conf:check_ip(Domain, Addr)) of
ok ->
list_to_tuple(Addr);
_ ->
@@ -3048,6 +3260,9 @@ normalize_address(Addr) ->
Addr
end.
+td2fam(transportDomainUdpIpv4) -> inet;
+td2fam(transportDomainUdpIpv6) -> inet6.
+
%%----------------------------------------------------------------------
diff --git a/lib/snmp/src/manager/snmpm_mpd.erl b/lib/snmp/src/manager/snmpm_mpd.erl
index 7712370d28..103c87d32b 100644
--- a/lib/snmp/src/manager/snmpm_mpd.erl
+++ b/lib/snmp/src/manager/snmpm_mpd.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -92,7 +92,7 @@ reset(#state{v3 = V3}) ->
%% Purpose: This is the main Message Dispatching function. (see
%% section 4.2.1 in rfc2272)
%%-----------------------------------------------------------------
-process_msg(Msg, TDomain, Addr, Port, State, NoteStore, Logger) ->
+process_msg(Msg, Domain, Addr, Port, State, NoteStore, Logger) ->
inc(snmpInPkts),
@@ -102,18 +102,18 @@ process_msg(Msg, TDomain, Addr, Port, State, NoteStore, Logger) ->
#message{version = 'version-1', vsn_hdr = Community, data = Data}
when State#state.v1 =:= true ->
HS = ?empty_msg_size + length(Community),
- process_v1_v2c_msg('version-1', NoteStore, Msg, TDomain,
- Addr, Port,
+ process_v1_v2c_msg('version-1', NoteStore, Msg,
+ Domain, Addr, Port,
Community, Data, HS, Logger);
%% Version 2
#message{version = 'version-2', vsn_hdr = Community, data = Data}
when State#state.v2c =:= true ->
HS = ?empty_msg_size + length(Community),
- process_v1_v2c_msg('version-2', NoteStore, Msg, TDomain,
- Addr, Port,
- Community, Data, HS, Logger);
-
+ (catch process_v1_v2c_msg('version-2', NoteStore, Msg,
+ Domain, Addr, Port,
+ Community, Data, HS, Logger));
+
%% Version 3
#message{version = 'version-3', vsn_hdr = H, data = Data}
when State#state.v3 =:= true ->
@@ -148,17 +148,30 @@ process_msg(Msg, TDomain, Addr, Port, State, NoteStore, Logger) ->
%%-----------------------------------------------------------------
%% Handles a Community based message (v1 or v2c).
%%-----------------------------------------------------------------
-process_v1_v2c_msg(Vsn, _NoteStore, Msg, snmpUDPDomain,
+process_v1_v2c_msg(Vsn, _NoteStore, Msg, Domain,
Addr, Port,
Community, Data, HS, Log) ->
?vdebug("process_v1_v2c_msg -> entry with"
"~n Vsn: ~p"
+ "~n Domain: ~p"
"~n Addr: ~p"
"~n Port: ~p"
"~n Community: ~p"
- "~n HS: ~p", [Vsn, Addr, Port, Community, HS]),
+ "~n HS: ~p", [Vsn, Domain, Addr, Port, Community, HS]),
+ {TDomain, TAddress} =
+ try
+ begin
+ TD = snmp_conf:mk_tdomain(Domain),
+ TA = snmp_conf:mk_taddress(Domain, Addr, Port),
+ {TD, TA}
+ end
+ catch
+ throw:{error, TReason} ->
+ throw({discarded, {badarg, Domain, TReason}})
+ end,
+
Max = get_max_message_size(),
AgentMax = get_agent_max_message_size(Addr, Port),
PduMS = pdu_ms(Max, AgentMax, HS),
@@ -170,14 +183,14 @@ process_v1_v2c_msg(Vsn, _NoteStore, Msg, snmpUDPDomain,
?vtrace("process_v1_v2c_msg -> was a pdu", []),
Log(Msg),
inc_snmp_in(Pdu),
- MsgData = {Community, sec_model(Vsn)},
+ MsgData = {Community, sec_model(Vsn), TDomain, TAddress},
{ok, Vsn, Pdu, PduMS, MsgData};
Trap when is_record(Trap, trappdu) ->
?vtrace("process_v1_v2c_msg -> was a trap", []),
Log(Msg),
inc_snmp_in(Trap),
- MsgData = {Community, sec_model(Vsn)},
+ MsgData = {Community, sec_model(Vsn), TDomain, TAddress},
{ok, Vsn, Trap, PduMS, MsgData};
{'EXIT', Reason} ->
@@ -185,11 +198,7 @@ process_v1_v2c_msg(Vsn, _NoteStore, Msg, snmpUDPDomain,
"~n Reason: ~p", [Reason]),
inc(snmpInASNParseErrs),
{discarded, Reason}
- end;
-process_v1_v2c_msg(_Vsn, _NoteStore, _Msg, TDomain,
- _Addr, _Port,
- _Comm, _HS, _Data, _Log) ->
- {discarded, {badarg, TDomain}}.
+ end.
pdu_ms(MgrMMS, AgentMMS, HS) when AgentMMS < MgrMMS ->
AgentMMS - HS;
@@ -482,8 +491,8 @@ generate_msg('version-3', NoteStore, Pdu,
generate_v3_msg(NoteStore, Pdu,
SecModel, SecName, SecLevel, CtxEngineID, CtxName,
TargetName, Log);
-generate_msg(Vsn, _NoteStore, Pdu, {Community, _SecModel}, Log) ->
- generate_v1_v2c_msg(Vsn, Pdu, Community, Log).
+generate_msg(Vsn, _NoteStore, Pdu, {Comm, _SecModel}, Log) ->
+ generate_v1_v2c_msg(Vsn, Pdu, Comm, Log).
generate_v3_msg(NoteStore, Pdu,
@@ -627,6 +636,8 @@ generate_response_msg('version-3', Pdu,
generate_v3_response_msg(Pdu, MsgID, SecModel, SecName, SecLevel,
CtxEngineID, CtxName, SecData, Log);
generate_response_msg(Vsn, Pdu, {Comm, _SecModel}, Log) ->
+ generate_v1_v2c_response_msg(Vsn, Pdu, Comm, Log);
+generate_response_msg(Vsn, Pdu, {Comm, _SecModel, _TDomain, _TAddress}, Log) ->
generate_v1_v2c_response_msg(Vsn, Pdu, Comm, Log).
diff --git a/lib/snmp/src/manager/snmpm_net_if.erl b/lib/snmp/src/manager/snmpm_net_if.erl
index a116c9f26b..4d6bd9aa33 100644
--- a/lib/snmp/src/manager/snmpm_net_if.erl
+++ b/lib/snmp/src/manager/snmpm_net_if.erl
@@ -28,7 +28,8 @@
start_link/2,
stop/1,
send_pdu/6, % Backward compatibillity
- send_pdu/7,
+ send_pdu/7, % Backward compatibillity
+ send_pdu/8,
inform_response/4,
@@ -101,16 +102,21 @@ stop(Pid) ->
send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port) ->
send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port, ?DEFAULT_EXTRA_INFO).
-send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port, ExtraInfo)
+send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port, ExtraInfo) ->
+ Domain = snmpm_config:default_transport_domain(),
+ send_pdu(Pid, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo).
+
+send_pdu(Pid, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo)
when is_record(Pdu, pdu) ->
?d("send_pdu -> entry with"
"~n Pid: ~p"
"~n Pdu: ~p"
"~n Vsn: ~p"
"~n MsgData: ~p"
+ "~n Domain: ~p"
"~n Addr: ~p"
- "~n Port: ~p", [Pid, Pdu, Vsn, MsgData, Addr, Port]),
- cast(Pid, {send_pdu, Pdu, Vsn, MsgData, Addr, Port, ExtraInfo}).
+ "~n Port: ~p", [Pid, Pdu, Vsn, MsgData, Domain, Addr, Port]),
+ cast(Pid, {send_pdu, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo}).
note_store(Pid, NoteStore) ->
call(Pid, {note_store, NoteStore}).
@@ -380,15 +386,17 @@ handle_call(Req, From, State) ->
%% {noreply, State, Timeout} |
%% {stop, Reason, State} (terminate/2 is called)
%%--------------------------------------------------------------------
-handle_cast({send_pdu, Pdu, Vsn, MsgData, Addr, Port, ExtraInfo}, State) ->
+handle_cast({send_pdu, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo},
+ State) ->
?vlog("received send_pdu message with"
"~n Pdu: ~p"
"~n Vsn: ~p"
"~n MsgData: ~p"
+ "~n Domain: ~p"
"~n Addr: ~p"
- "~n Port: ~p", [Pdu, Vsn, MsgData, Addr, Port]),
+ "~n Port: ~p", [Pdu, Vsn, MsgData, Domain, Addr, Port]),
maybe_process_extra_info(ExtraInfo),
- maybe_handle_send_pdu(Pdu, Vsn, MsgData, Addr, Port, State),
+ maybe_handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, Port, State),
{noreply, State};
handle_cast({inform_response, Ref, Addr, Port}, State) ->
@@ -545,8 +553,9 @@ handle_recv_msg(Addr, Port, Bytes,
mpd_state = MpdState,
sock = Sock,
log = Log} = State) ->
+ Domain = snmp_conf:which_domain(Addr), % What the ****...
Logger = logger(Log, read, Addr, Port),
- case (catch snmpm_mpd:process_msg(Bytes, snmpUDPDomain, Addr, Port,
+ case (catch snmpm_mpd:process_msg(Bytes, Domain, Addr, Port,
MpdState, NoteStore, Logger)) of
{ok, Vsn, Pdu, MS, ACM} ->
@@ -734,17 +743,17 @@ irgc_stop(Ref) ->
(catch erlang:cancel_timer(Ref)).
-maybe_handle_send_pdu(Pdu, Vsn, MsgData, Addr, Port,
+maybe_handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, Port,
#state{filter = FilterMod} = State) ->
case (catch FilterMod:accept_send_pdu(Addr, Port, pdu_type_of(Pdu))) of
false ->
inc(netIfPduOutDrops),
ok;
_ ->
- handle_send_pdu(Pdu, Vsn, MsgData, Addr, Port, State)
+ handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, Port, State)
end.
-handle_send_pdu(Pdu, Vsn, MsgData, Addr, Port,
+handle_send_pdu(Pdu, Vsn, MsgData, _Domain, Addr, Port,
#state{server = Pid,
note_store = NoteStore,
sock = Sock,
diff --git a/lib/snmp/src/manager/snmpm_server.erl b/lib/snmp/src/manager/snmpm_server.erl
index 58a58507d6..484954addb 100644
--- a/lib/snmp/src/manager/snmpm_server.erl
+++ b/lib/snmp/src/manager/snmpm_server.erl
@@ -161,7 +161,8 @@
{id,
user_id,
reg_type,
- target,
+ target,
+ domain,
addr,
port,
type,
@@ -1175,11 +1176,12 @@ handle_sync_get(Pid, UserId, TargetName, Oids, SendOpts, From, State) ->
"~n From: ~p",
[Pid, UserId, TargetName, Oids, SendOpts, From]),
case agent_data(TargetName, SendOpts) of
- {ok, RegType, Addr, Port, Vsn, MsgData} ->
+ {ok, RegType, Domain, Addr, Port, Vsn, MsgData} ->
?vtrace("handle_sync_get -> send a ~p message", [Vsn]),
Extra = ?GET_EXTRA(SendOpts),
ReqId = send_get_request(Oids, Vsn, MsgData,
- Addr, Port, Extra, State),
+ Domain, Addr, Port,
+ Extra, State),
?vdebug("handle_sync_get -> ReqId: ~p", [ReqId]),
Msg = {sync_timeout, ReqId, From},
Timeout = ?SYNC_GET_TIMEOUT(SendOpts),
@@ -1190,6 +1192,7 @@ handle_sync_get(Pid, UserId, TargetName, Oids, SendOpts, From, State) ->
user_id = UserId,
reg_type = RegType,
target = TargetName,
+ domain = Domain,
addr = Addr,
port = Port,
type = get,
@@ -1227,11 +1230,12 @@ handle_sync_get_next(Pid, UserId, TargetName, Oids, SendOpts,
"~n From: ~p",
[Pid, UserId, TargetName, Oids, SendOpts, From]),
case agent_data(TargetName, SendOpts) of
- {ok, RegType, Addr, Port, Vsn, MsgData} ->
+ {ok, RegType, Domain, Addr, Port, Vsn, MsgData} ->
?vtrace("handle_sync_get_next -> send a ~p message", [Vsn]),
Extra = ?GET_EXTRA(SendOpts),
ReqId = send_get_next_request(Oids, Vsn, MsgData,
- Addr, Port, Extra, State),
+ Domain, Addr, Port,
+ Extra, State),
?vdebug("handle_sync_get_next -> ReqId: ~p", [ReqId]),
Msg = {sync_timeout, ReqId, From},
Timeout = ?SYNC_GET_NEXT_TIMEOUT(SendOpts),
@@ -1242,6 +1246,7 @@ handle_sync_get_next(Pid, UserId, TargetName, Oids, SendOpts,
user_id = UserId,
reg_type = RegType,
target = TargetName,
+ domain = Domain,
addr = Addr,
port = Port,
type = get_next,
@@ -1285,10 +1290,11 @@ handle_sync_get_bulk(Pid, UserId, TargetName, NonRep, MaxRep, Oids, SendOpts,
"~n From: ~p",
[Pid, UserId, TargetName, NonRep, MaxRep, Oids, SendOpts, From]),
case agent_data(TargetName, SendOpts) of
- {ok, RegType, Addr, Port, Vsn, MsgData} ->
+ {ok, RegType, Domain, Addr, Port, Vsn, MsgData} ->
?vtrace("handle_sync_get_bulk -> send a ~p message", [Vsn]),
Extra = ?GET_EXTRA(SendOpts),
- ReqId = send_get_bulk_request(Oids, Vsn, MsgData, Addr, Port,
+ ReqId = send_get_bulk_request(Oids, Vsn, MsgData,
+ Domain, Addr, Port,
NonRep, MaxRep, Extra, State),
?vdebug("handle_sync_get_bulk -> ReqId: ~p", [ReqId]),
Msg = {sync_timeout, ReqId, From},
@@ -1300,6 +1306,7 @@ handle_sync_get_bulk(Pid, UserId, TargetName, NonRep, MaxRep, Oids, SendOpts,
user_id = UserId,
reg_type = RegType,
target = TargetName,
+ domain = Domain,
addr = Addr,
port = Port,
type = get_bulk,
@@ -1339,11 +1346,12 @@ handle_sync_set(Pid, UserId, TargetName, VarsAndVals, SendOpts, From, State) ->
"~n From: ~p",
[Pid, UserId, TargetName, VarsAndVals, From]),
case agent_data(TargetName, SendOpts) of
- {ok, RegType, Addr, Port, Vsn, MsgData} ->
+ {ok, RegType, Domain, Addr, Port, Vsn, MsgData} ->
?vtrace("handle_sync_set -> send a ~p message", [Vsn]),
Extra = ?GET_EXTRA(SendOpts),
ReqId = send_set_request(VarsAndVals, Vsn, MsgData,
- Addr, Port, Extra, State),
+ Domain, Addr, Port,
+ Extra, State),
?vdebug("handle_sync_set -> ReqId: ~p", [ReqId]),
Msg = {sync_timeout, ReqId, From},
Timeout = ?SYNC_SET_TIMEOUT(SendOpts),
@@ -1354,6 +1362,7 @@ handle_sync_set(Pid, UserId, TargetName, VarsAndVals, SendOpts, From, State) ->
user_id = UserId,
reg_type = RegType,
target = TargetName,
+ domain = Domain,
addr = Addr,
port = Port,
type = set,
@@ -1391,10 +1400,11 @@ handle_async_get(Pid, UserId, TargetName, Oids, SendOpts, State) ->
"~n SendOpts: ~p",
[Pid, UserId, TargetName, Oids, SendOpts]),
case agent_data(TargetName, SendOpts) of
- {ok, RegType, Addr, Port, Vsn, MsgData} ->
+ {ok, RegType, Domain, Addr, Port, Vsn, MsgData} ->
?vtrace("handle_async_get -> send a ~p message", [Vsn]),
Extra = ?GET_EXTRA(SendOpts),
- ReqId = send_get_request(Oids, Vsn, MsgData, Addr, Port,
+ ReqId = send_get_request(Oids, Vsn, MsgData,
+ Domain, Addr, Port,
Extra, State),
?vdebug("handle_async_get -> ReqId: ~p", [ReqId]),
Expire = ?ASYNC_GET_TIMEOUT(SendOpts),
@@ -1402,6 +1412,7 @@ handle_async_get(Pid, UserId, TargetName, Oids, SendOpts, State) ->
user_id = UserId,
reg_type = RegType,
target = TargetName,
+ domain = Domain,
addr = Addr,
port = Port,
type = get,
@@ -1439,17 +1450,19 @@ handle_async_get_next(Pid, UserId, TargetName, Oids, SendOpts, State) ->
"~n SendOpts: ~p",
[Pid, UserId, TargetName, Oids, SendOpts]),
case agent_data(TargetName, SendOpts) of
- {ok, RegType, Addr, Port, Vsn, MsgData} ->
+ {ok, RegType, Domain, Addr, Port, Vsn, MsgData} ->
?vtrace("handle_async_get_next -> send a ~p message", [Vsn]),
Extra = ?GET_EXTRA(SendOpts),
ReqId = send_get_next_request(Oids, Vsn, MsgData,
- Addr, Port, Extra, State),
+ Domain, Addr, Port,
+ Extra, State),
?vdebug("handle_async_get_next -> ReqId: ~p", [ReqId]),
Expire = ?ASYNC_GET_NEXT_TIMEOUT(SendOpts),
Req = #request{id = ReqId,
user_id = UserId,
reg_type = RegType,
target = TargetName,
+ domain = Domain,
addr = Addr,
port = Port,
type = get_next,
@@ -1494,10 +1507,11 @@ handle_async_get_bulk(Pid,
"~n SendOpts: ~p",
[Pid, UserId, TargetName, NonRep, MaxRep, Oids, SendOpts]),
case agent_data(TargetName, SendOpts) of
- {ok, RegType, Addr, Port, Vsn, MsgData} ->
+ {ok, RegType, Domain, Addr, Port, Vsn, MsgData} ->
?vtrace("handle_async_get_bulk -> send a ~p message", [Vsn]),
Extra = ?GET_EXTRA(SendOpts),
- ReqId = send_get_bulk_request(Oids, Vsn, MsgData, Addr, Port,
+ ReqId = send_get_bulk_request(Oids, Vsn, MsgData,
+ Domain, Addr, Port,
NonRep, MaxRep, Extra, State),
?vdebug("handle_async_get_bulk -> ReqId: ~p", [ReqId]),
Expire = ?ASYNC_GET_BULK_TIMEOUT(SendOpts),
@@ -1505,6 +1519,7 @@ handle_async_get_bulk(Pid,
user_id = UserId,
reg_type = RegType,
target = TargetName,
+ domain = Domain,
addr = Addr,
port = Port,
type = get_bulk,
@@ -1541,17 +1556,19 @@ handle_async_set(Pid, UserId, TargetName, VarsAndVals, SendOpts, State) ->
"~n SendOpts: ~p",
[Pid, UserId, TargetName, VarsAndVals, SendOpts]),
case agent_data(TargetName, SendOpts) of
- {ok, RegType, Addr, Port, Vsn, MsgData} ->
+ {ok, RegType, Domain, Addr, Port, Vsn, MsgData} ->
?vtrace("handle_async_set -> send a ~p message", [Vsn]),
Extra = ?GET_EXTRA(SendOpts),
ReqId = send_set_request(VarsAndVals, Vsn, MsgData,
- Addr, Port, Extra, State),
+ Domain, Addr, Port,
+ Extra, State),
?vdebug("handle_async_set -> ReqId: ~p", [ReqId]),
Expire = ?ASYNC_SET_TIMEOUT(SendOpts),
Req = #request{id = ReqId,
user_id = UserId,
reg_type = RegType,
target = TargetName,
+ domain = Domain,
addr = Addr,
port = Port,
type = set,
@@ -2907,7 +2924,7 @@ do_gc(Key, Now) ->
%%
%%----------------------------------------------------------------------
-send_get_request(Oids, Vsn, MsgData, Addr, Port, ExtraInfo,
+send_get_request(Oids, Vsn, MsgData, Domain, Addr, Port, ExtraInfo,
#state{net_if = NetIf,
net_if_mod = Mod,
mini_mib = MiniMIB}) ->
@@ -2918,34 +2935,39 @@ send_get_request(Oids, Vsn, MsgData, Addr, Port, ExtraInfo,
"~n Pdu: ~p"
"~n Vsn: ~p"
"~n MsgData: ~p"
+ "~n Domain: ~p"
"~n Addr: ~p"
- "~n Port: ~p", [Mod, NetIf, Pdu, Vsn, MsgData, Addr, Port]),
- (catch Mod:send_pdu(NetIf, Pdu, Vsn, MsgData, Addr, Port, ExtraInfo)),
+ "~n Port: ~p",
+ [Mod, NetIf, Pdu, Vsn, MsgData, Domain, Addr, Port]),
+ Res = (catch Mod:send_pdu(NetIf, Pdu, Vsn, MsgData,
+ Domain, Addr, Port, ExtraInfo)),
+ ?vtrace("send_get_request -> send result:"
+ "~n ~p", [Res]),
Pdu#pdu.request_id.
-send_get_next_request(Oids, Vsn, MsgData, Addr, Port, ExtraInfo,
+send_get_next_request(Oids, Vsn, MsgData, Domain, Addr, Port, ExtraInfo,
#state{mini_mib = MiniMIB,
net_if = NetIf,
net_if_mod = Mod}) ->
Pdu = make_pdu(get_next, Oids, MiniMIB),
- Mod:send_pdu(NetIf, Pdu, Vsn, MsgData, Addr, Port, ExtraInfo),
+ Mod:send_pdu(NetIf, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo),
Pdu#pdu.request_id.
-send_get_bulk_request(Oids, Vsn, MsgData, Addr, Port,
+send_get_bulk_request(Oids, Vsn, MsgData, Domain, Addr, Port,
NonRep, MaxRep, ExtraInfo,
#state{mini_mib = MiniMIB,
net_if = NetIf,
net_if_mod = Mod}) ->
Pdu = make_pdu(bulk, {NonRep, MaxRep, Oids}, MiniMIB),
- Mod:send_pdu(NetIf, Pdu, Vsn, MsgData, Addr, Port, ExtraInfo),
+ Mod:send_pdu(NetIf, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo),
Pdu#pdu.request_id.
-send_set_request(VarsAndVals, Vsn, MsgData, Addr, Port, ExtraInfo,
+send_set_request(VarsAndVals, Vsn, MsgData, Domain, Addr, Port, ExtraInfo,
#state{mini_mib = MiniMIB,
net_if = NetIf,
net_if_mod = Mod}) ->
Pdu = make_pdu(set, VarsAndVals, MiniMIB),
- Mod:send_pdu(NetIf, Pdu, Vsn, MsgData, Addr, Port, ExtraInfo),
+ Mod:send_pdu(NetIf, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo),
Pdu#pdu.request_id.
%% send_discovery(Vsn, MsgData, Addr, Port, ExtraInfo,
@@ -3181,10 +3203,11 @@ agent_data(TargetName, SendOpts) ->
{Comm, SecModel}
end,
+ Domain = agent_data_item(tdomain, Info),
Addr = agent_data_item(address, Info),
Port = agent_data_item(port, Info),
RegType = agent_data_item(reg_type, Info),
- {ok, RegType, Addr, Port, version(Version), MsgData};
+ {ok, RegType, Domain, Addr, Port, version(Version), MsgData};
Error ->
Error
end.
diff --git a/lib/snmp/src/misc/snmp_conf.erl b/lib/snmp/src/misc/snmp_conf.erl
index 20f4455d10..7249def24e 100644
--- a/lib/snmp/src/misc/snmp_conf.erl
+++ b/lib/snmp/src/misc/snmp_conf.erl
@@ -37,7 +37,9 @@
check_timer/1,
+ all_domains/0,
check_domain/1,
+ all_tdomains/0,
check_tdomain/1,
mk_tdomain/1,
which_domain/1,
@@ -345,6 +347,25 @@ check_sec_level(BadSecLevel) ->
%% ---------
+all_tdomains() ->
+ [
+ ?transportDomainUdpIpv4,
+ ?transportDomainUdpIpv6,
+ ?transportDomainUdpIpv4z,
+ ?transportDomainUdpIpv6z,
+ ?transportDomainTcpIpv4,
+ ?transportDomainTcpIpv6,
+ ?transportDomainTcpIpv4z,
+ ?transportDomainTcpIpv6z,
+ ?transportDomainSctpIpv4,
+ ?transportDomainSctpIpv6,
+ ?transportDomainSctpIpv4z,
+ ?transportDomainSctpIpv6z,
+ ?transportDomainLocal,
+ ?transportDomainUdpDns,
+ ?transportDomainTcpDns,
+ ?transportDomainSctpDns
+ ].
check_tdomain(TDomain) ->
SupportedTDomains =
@@ -353,25 +374,7 @@ check_tdomain(TDomain) ->
?transportDomainUdpIpv4,
?transportDomainUdpIpv6
],
- AllTDomains =
- [
- ?transportDomainUdpIpv4,
- ?transportDomainUdpIpv6,
- ?transportDomainUdpIpv4z,
- ?transportDomainUdpIpv6z,
- ?transportDomainTcpIpv4,
- ?transportDomainTcpIpv6,
- ?transportDomainTcpIpv4z,
- ?transportDomainTcpIpv6z,
- ?transportDomainSctpIpv4,
- ?transportDomainSctpIpv6,
- ?transportDomainSctpIpv4z,
- ?transportDomainSctpIpv6z,
- ?transportDomainLocal,
- ?transportDomainUdpDns,
- ?transportDomainTcpDns,
- ?transportDomainSctpDns
- ],
+ AllTDomains = all_tdomains(),
case lists:member(TDomain, SupportedTDomains) of
true ->
ok;
@@ -388,7 +391,7 @@ check_tdomain(TDomain) ->
%% ---------
mk_tdomain(snmpUDPDomain) ->
- ?snmpUDPDomain;
+ mk_tdomain(transportDomainUdpIpv4);
mk_tdomain(transportDomainUdpIpv4) ->
?transportDomainUdpIpv4;
mk_tdomain(transportDomainUdpIpv6) ->
@@ -474,6 +477,26 @@ do_check_timer(WaitFor, Factor, Incr, Retry) ->
%% ---------
+all_domains() ->
+ [
+ transportDomainUdpIpv4,
+ transportDomainUdpIpv6,
+ transportDomainUdpIpv4z,
+ transportDomainUdpIpv6z,
+ transportDomainTcpIpv4,
+ transportDomainTcpIpv6,
+ transportDomainTcpIpv4z,
+ transportDomainTcpIpv6z,
+ transportDomainSctpIpv4,
+ transportDomainSctpIpv6,
+ transportDomainSctpIpv4z,
+ transportDomainSctpIpv6z,
+ transportDomainLocal,
+ transportDomainUdpDns,
+ transportDomainTcpDns,
+ transportDomainSctpDns
+ ].
+
check_domain(Domain) ->
SupportedDomains =
[
@@ -481,25 +504,7 @@ check_domain(Domain) ->
transportDomainUdpIpv4,
transportDomainUdpIpv6
],
- AllDomains =
- [
- transportDomainUdpIpv4,
- transportDomainUdpIpv6,
- transportDomainUdpIpv4z,
- transportDomainUdpIpv6z,
- transportDomainTcpIpv4,
- transportDomainTcpIpv6,
- transportDomainTcpIpv4z,
- transportDomainTcpIpv6z,
- transportDomainSctpIpv4,
- transportDomainSctpIpv6,
- transportDomainSctpIpv4z,
- transportDomainSctpIpv6z,
- transportDomainLocal,
- transportDomainUdpDns,
- transportDomainTcpDns,
- transportDomainSctpDns
- ],
+ AllDomains = all_domains(),
case lists:member(Domain, SupportedDomains) of
true ->
ok;
diff --git a/lib/snmp/src/misc/snmp_config.erl b/lib/snmp/src/misc/snmp_config.erl
index fcbc6a88c9..6ab20e3e48 100644
--- a/lib/snmp/src/misc/snmp_config.erl
+++ b/lib/snmp/src/misc/snmp_config.erl
@@ -337,7 +337,7 @@ config_agent_sys() ->
{dir, ATLDir},
{size, ATLSize},
{repair, ATLRepair},
- {seqno, ATLSeqNo}]}];
+ {seqno, ATLSeqNo}]}];
no ->
[]
end,
@@ -568,7 +568,7 @@ config_agent_snmp(Dir, Vsns) ->
false ->
ok
end,
- i("The following agent files were written: agent.conf, "
+ i("The following agent files where written: agent.conf, "
"community.conf,~n"
"standard.conf, target_addr.conf, "
"target_params.conf, ~n"
@@ -776,7 +776,7 @@ config_manager_snmp(Dir, Vsns) ->
Users, Agents, Usms)) of
ok ->
i("~n- - - - - - - - - - - - -"),
- i("The following manager files were written: "
+ i("The following manager files where written: "
"manager.conf, agents.conf " ++
case lists:member(v3, Vsns) of
true ->
@@ -2350,7 +2350,9 @@ write_sys_config_file_manager_atl_opt(Fid, {type, Type}) ->
write_sys_config_file_manager_atl_opt(Fid, {size, Size}) ->
ok = io:format(Fid, "{size, ~w}", [Size]);
write_sys_config_file_manager_atl_opt(Fid, {repair, Rep}) ->
- ok = io:format(Fid, "{repair, ~w}", [Rep]).
+ ok = io:format(Fid, "{repair, ~w}", [Rep]);
+write_sys_config_file_manager_atl_opt(Fid, {seqno, SeqNo}) ->
+ ok = io:format(Fid, "{seqno, ~w}", [SeqNo]).
header() ->
diff --git a/lib/snmp/src/misc/snmp_note_store.erl b/lib/snmp/src/misc/snmp_note_store.erl
index a21a6209f1..23fccf8a5f 100644
--- a/lib/snmp/src/misc/snmp_note_store.erl
+++ b/lib/snmp/src/misc/snmp_note_store.erl
@@ -258,10 +258,17 @@ code_change({down, _Vsn}, State, _Extra) ->
{ok, NState};
% upgrade
-code_change(_Vsn, State, _Extra) ->
+code_change(_Vsn, State0, _Extra) ->
process_flag(trap_exit, true),
- NState = restart_timer(State),
- {ok, NState}.
+ State1 =
+ case State0 of
+ #state{timeout = false} ->
+ State0#state{timeout = ?timeout};
+ _ ->
+ State0
+ end,
+ State2 = restart_timer(State1),
+ {ok, State2}.
%%----------------------------------------------------------
@@ -282,7 +289,7 @@ deactivate_timer(#state{timer = Pid, active = true} = State) ->
receive
deactivated -> ok
end,
- State#state{timeout = false};
+ State#state{active = false};
deactivate_timer(State) ->
State.
diff --git a/lib/snmp/test/Makefile b/lib/snmp/test/Makefile
index 5530805bc1..78ffb1c255 100644
--- a/lib/snmp/test/Makefile
+++ b/lib/snmp/test/Makefile
@@ -220,6 +220,10 @@ appup: make
$(MAYBE_ESTOP)
+$(SNMP_BIN_TARGET_DIR)/Klas4.bin: $(SNMP_BIN_TARGET_DIR)/Klas3.bin
+
+$(SNMP_BIN_TARGET_DIR)/SA-MIB.bin: $(SNMP_BIN_TARGET_DIR)/OLD-SNMPEA-MIB.bin
+
# ----------------------------------------------------
# Release Target
# ----------------------------------------------------
diff --git a/lib/snmp/test/snmp_compiler_test.erl b/lib/snmp/test/snmp_compiler_test.erl
index 2e6020ae7a..c964b08168 100644
--- a/lib/snmp/test/snmp_compiler_test.erl
+++ b/lib/snmp/test/snmp_compiler_test.erl
@@ -47,6 +47,7 @@
module_identity/1,
agent_capabilities/1,
module_compliance/1,
+ warnings_as_errors/1,
otp_6150/1,
otp_8574/1,
@@ -97,9 +98,10 @@ all() ->
description,
oid_conflicts,
imports,
- module_identity,
- agent_capabilities,
- module_compliance,
+ module_identity,
+ agent_capabilities,
+ module_compliance,
+ warnings_as_errors,
{group, tickets}
].
@@ -152,6 +154,8 @@ description(Config) when is_list(Config) ->
ok.
+%%======================================================================
+
oid_conflicts(suite) -> [];
oid_conflicts(Config) when is_list(Config) ->
put(tname,oid_conflicts),
@@ -165,18 +169,24 @@ oid_conflicts(Config) when is_list(Config) ->
ok.
+%%======================================================================
+
imports(suite) ->
[];
imports(Config) when is_list(Config) ->
?SKIP(not_yet_implemented).
+%%======================================================================
+
module_identity(suite) ->
[];
module_identity(Config) when is_list(Config) ->
?SKIP(not_yet_implemented).
+%%======================================================================
+
agent_capabilities(suite) ->
[];
agent_capabilities(Config) when is_list(Config) ->
@@ -218,6 +228,8 @@ agent_capabilities(Config) when is_list(Config) ->
ok.
+%%======================================================================
+
module_compliance(suite) ->
[];
module_compliance(Config) when is_list(Config) ->
@@ -259,6 +271,32 @@ module_compliance(Config) when is_list(Config) ->
ok.
+%%======================================================================
+
+warnings_as_errors(suite) ->
+ ["OTP-9437"];
+warnings_as_errors(Config) when is_list(Config) ->
+ put(tname,warnings_as_errors),
+ p("starting with Config: ~p~n", [Config]),
+ Dir = ?config(comp_dir, Config),
+ MibDir = ?config(mib_dir, Config),
+ MibFile = join(MibDir, "OTP8574-MIB.mib"),
+ OutFile = join(Dir, "OTP8574-MIB.bin"),
+ Opts = [{group_check, false},
+ {outdir, Dir},
+ {verbosity, trace},
+ relaxed_row_name_assign_check],
+ {error, compilation_failed} =
+ snmpc:compile(MibFile, [warnings_as_errors|Opts]),
+ false = filelib:is_regular(OutFile),
+ {ok, _} = snmpc:compile(MibFile, Opts),
+ true = filelib:is_regular(OutFile),
+ ok = file:delete(OutFile),
+ ok.
+
+
+%%======================================================================
+
otp_6150(suite) ->
[];
otp_6150(Config) when is_list(Config) ->
@@ -273,6 +311,8 @@ otp_6150(Config) when is_list(Config) ->
ok.
+%%======================================================================
+
otp_8574(suite) ->
[];
otp_8574(Config) when is_list(Config) ->
@@ -304,6 +344,8 @@ otp_8574(Config) when is_list(Config) ->
end.
+%%======================================================================
+
otp_8595(suite) ->
[];
otp_8595(Config) when is_list(Config) ->
diff --git a/lib/snmp/test/snmp_manager_test.erl b/lib/snmp/test/snmp_manager_test.erl
index 0b536748fb..d18f20d359 100644
--- a/lib/snmp/test/snmp_manager_test.erl
+++ b/lib/snmp/test/snmp_manager_test.erl
@@ -61,6 +61,7 @@
register_agent1/1,
register_agent2/1,
+ register_agent3/1,
info/1,
@@ -383,12 +384,12 @@ end_per_testcase2(Case, Config) ->
all() ->
[
{group, start_and_stop_tests},
- {group, misc_tests},
+ {group, misc_tests},
{group, user_tests},
- {group, agent_tests},
+ {group, agent_tests},
{group, request_tests},
{group, event_tests},
- discovery,
+ discovery,
{group, tickets}
].
@@ -417,7 +418,8 @@ groups() ->
{agent_tests, [],
[
register_agent1,
- register_agent2
+ register_agent2,
+ register_agent3
]
},
{request_tests, [],
@@ -477,14 +479,14 @@ groups() ->
},
{event_tests, [],
[
- trap1,
- trap2,
- inform1,
- inform2,
- inform3,
- inform4,
- inform_swarm,
- report
+ trap1%% ,
+ %% trap2,
+ %% inform1,
+ %% inform2,
+ %% inform3,
+ %% inform4,
+ %% inform_swarm,
+ %% report
]
},
{tickets, [],
@@ -1134,6 +1136,7 @@ register_agent1(suite) ->
register_agent1(Config) when is_list(Config) ->
process_flag(trap_exit, true),
put(tname,ra1),
+
p("starting with Config: ~p~n", [Config]),
ManagerNode = start_manager_node(),
@@ -1164,7 +1167,7 @@ register_agent1(Config) when is_list(Config) ->
p("manager info: ~p~n", [mgr_info(ManagerNode)]),
- p("register user(s) calvin & hobbe"),
+ p("register user(s) user_alfa & user_beta"),
?line ok = mgr_register_user(ManagerNode, user_alfa, snmpm_user_default, []),
?line ok = mgr_register_user(ManagerNode, user_beta, snmpm_user_default, []),
p("manager info: ~p~n", [mgr_info(ManagerNode)]),
@@ -1293,7 +1296,7 @@ register_agent2(Config) when is_list(Config) ->
p("manager info: ~p~n", [mgr_info(ManagerNode)]),
- p("register user(s) calvin & hobbe"),
+ p("register user(s) user_alfa & user_beta"),
?line ok = mgr_register_user(ManagerNode, user_alfa, snmpm_user_default, []),
?line ok = mgr_register_user(ManagerNode, user_beta, snmpm_user_default, []),
p("manager info: ~p~n", [mgr_info(ManagerNode)]),
@@ -1348,7 +1351,7 @@ register_agent2(Config) when is_list(Config) ->
end,
p("manager info: ~p~n", [mgr_info(ManagerNode)]),
-
+
p("unregister user user_alfa"),
?line ok = mgr_unregister_user(ManagerNode, user_alfa),
@@ -1377,7 +1380,157 @@ register_agent2(Config) when is_list(Config) ->
p("manager info: ~p~n", [mgr_info(ManagerNode)]),
- p("unregister user hobbe"),
+ p("unregister user user_beta"),
+ ?line ok = mgr_unregister_user(ManagerNode, user_beta),
+
+ p("manager info: ~p~n", [mgr_info(ManagerNode)]),
+
+ ?SLEEP(1000),
+
+ p("stop snmp application (with only manager)"),
+ ?line ok = stop_snmp(ManagerNode),
+
+ ?SLEEP(1000),
+
+ stop_node(ManagerNode),
+
+ ?SLEEP(1000),
+
+ p("end"),
+ ok.
+
+
+%%======================================================================
+
+register_agent3(doc) ->
+ ["Test registration of agents with the NEW interface functions "
+ "and specifying transport domain"];
+register_agent3(suite) ->
+ [];
+register_agent3(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ put(tname, ra3),
+ p("starting with Config: ~p~n", [Config]),
+
+ ManagerNode = start_manager_node(),
+
+ ConfDir = ?config(manager_conf_dir, Config),
+ DbDir = ?config(manager_db_dir, Config),
+ LocalHost = snmp_test_lib:localhost(),
+
+
+ write_manager_conf(ConfDir),
+
+ Opts = [{server, [{verbosity, trace}]},
+ {net_if, [{verbosity, trace}]},
+ {note_store, [{verbosity, trace}]},
+ {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}],
+
+
+ p("load snmp application"),
+ ?line ok = load_snmp(ManagerNode),
+
+ p("set manager env for the snmp application"),
+ ?line ok = set_mgr_env(ManagerNode, Opts),
+
+ p("starting snmp application (with only manager)"),
+ ?line ok = start_snmp(ManagerNode),
+
+ p("started"),
+
+ ?SLEEP(1000),
+
+ p("manager info: ~p~n", [mgr_info(ManagerNode)]),
+
+ p("register user(s) user_alfa & user_beta"),
+ ?line ok = mgr_register_user(ManagerNode, user_alfa, snmpm_user_default, []),
+ ?line ok = mgr_register_user(ManagerNode, user_beta, snmpm_user_default, []),
+ p("manager info: ~p~n", [mgr_info(ManagerNode)]),
+
+ p("register agent(s)"),
+ TargetName1 = "agent2",
+ ?line ok = mgr_register_agent(ManagerNode, user_alfa, TargetName1,
+ [{tdomain, transportDomainUdpIpv4},
+ {address, LocalHost},
+ {port, 5001},
+ {engine_id, "agentEngineId-1"}]),
+ TargetName2 = "agent3",
+ ?line ok = mgr_register_agent(ManagerNode, user_alfa, TargetName2,
+ [{tdomain, transportDomainUdpIpv6},
+ {address, LocalHost},
+ {port, 5002},
+ {engine_id, "agentEngineId-2"}]),
+ TargetName3 = "agent4",
+ ?line {error, {unsupported_domain, _} = Reason4} =
+ mgr_register_agent(ManagerNode, user_beta, TargetName3,
+ [{tdomain, transportDomainTcpIpv4},
+ {address, LocalHost},
+ {port, 5003},
+ {engine_id, "agentEngineId-3"}]),
+ p("Expected registration failure: ~p", [Reason4]),
+ TargetName4 = "agent5",
+ ?line {error, {unknown_domain, _} = Reason5} =
+ mgr_register_agent(ManagerNode, user_beta, TargetName4,
+ [{tdomain, transportDomainUdpIpv4_bad},
+ {address, LocalHost},
+ {port, 5004},
+ {engine_id, "agentEngineId-4"}]),
+ p("Expected registration failure: ~p", [Reason5]),
+
+ p("verify all agent(s): expect 2"),
+ case mgr_which_agents(ManagerNode) of
+ Agents1 when length(Agents1) =:= 2 ->
+ p("all agents: ~p~n", [Agents1]),
+ ok;
+ Agents1 ->
+ ?FAIL({agent_registration_failure, Agents1})
+ end,
+
+ p("verify user_alfa agent(s)"),
+ case mgr_which_agents(ManagerNode, user_alfa) of
+ Agents2 when length(Agents2) =:= 2 ->
+ p("calvin agents: ~p~n", [Agents2]),
+ ok;
+ Agents2 ->
+ ?FAIL({agent_registration_failure, Agents2})
+ end,
+
+ p("verify user_beta agent(s)"),
+ case mgr_which_agents(ManagerNode, user_beta) of
+ Agents3 when length(Agents3) =:= 0 ->
+ p("hobbe agents: ~p~n", [Agents3]),
+ ok;
+ Agents3 ->
+ ?FAIL({agent_registration_failure, Agents3})
+ end,
+
+ p("manager info: ~p~n", [mgr_info(ManagerNode)]),
+
+ p("unregister user user_alfa"),
+ ?line ok = mgr_unregister_user(ManagerNode, user_alfa),
+
+ p("verify all agent(s): expect 0"),
+ case mgr_which_agents(ManagerNode) of
+ Agents4 when length(Agents4) =:= 0 ->
+ p("all agents: ~p~n", [Agents4]),
+ ok;
+ Agents4 ->
+ ?FAIL({agent_unregistration_failure, Agents4})
+ end,
+ p("manager info: ~p~n", [mgr_info(ManagerNode)]),
+
+ p("verify all agent(s): expect 0"),
+ case mgr_which_agents(ManagerNode) of
+ [] ->
+ ok;
+ Agents5 ->
+ p("all agents: ~p~n", [Agents5]),
+ ?FAIL({agent_unregistration_failure, Agents5})
+ end,
+
+ p("manager info: ~p~n", [mgr_info(ManagerNode)]),
+
+ p("unregister user user_beta"),
?line ok = mgr_unregister_user(ManagerNode, user_beta),
p("manager info: ~p~n", [mgr_info(ManagerNode)]),
diff --git a/lib/snmp/test/snmp_manager_user_old.erl b/lib/snmp/test/snmp_manager_user_old.erl
index edffc80dd4..edffc80dd4 100755..100644
--- a/lib/snmp/test/snmp_manager_user_old.erl
+++ b/lib/snmp/test/snmp_manager_user_old.erl
diff --git a/lib/snmp/test/test_config/Makefile b/lib/snmp/test/test_config/Makefile
index d7bebbc431..d65bb8abe2 100644
--- a/lib/snmp/test/test_config/Makefile
+++ b/lib/snmp/test/test_config/Makefile
@@ -155,23 +155,23 @@ release_spec:
release_tests_spec: clean opt
$(INSTALL_DIR) $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
$(INSTALL_DIR) $(RELSYSDIR)/agent
- chmod -f -R u+w $(RELSYSDIR)/agent
+ chmod -R u+w $(RELSYSDIR)/agent
$(INSTALL_DIR) $(RELSYSDIR)/agent/conf
- chmod -f -R u+w $(RELSYSDIR)/agent/conf
+ chmod -R u+w $(RELSYSDIR)/agent/conf
$(INSTALL_DIR) $(RELSYSDIR)/agent/db
- chmod -f -R u+w $(RELSYSDIR)/agent/db
+ chmod -R u+w $(RELSYSDIR)/agent/db
$(INSTALL_DIR) $(RELSYSDIR)/agent/log
- chmod -f -R u+w $(RELSYSDIR)/agent/log
+ chmod -R u+w $(RELSYSDIR)/agent/log
$(INSTALL_DIR) $(RELSYSDIR)/manager
- chmod -f -R u+w $(RELSYSDIR)/manager
+ chmod -R u+w $(RELSYSDIR)/manager
$(INSTALL_DIR) $(RELSYSDIR)/manager/conf
- chmod -f -R u+w $(RELSYSDIR)/manager/conf
+ chmod -R u+w $(RELSYSDIR)/manager/conf
$(INSTALL_DIR) $(RELSYSDIR)/manager/db
- chmod -f -R u+w $(RELSYSDIR)/manager/db
+ chmod -R u+w $(RELSYSDIR)/manager/db
$(INSTALL_DIR) $(RELSYSDIR)/manager/log
- chmod -f -R u+w $(RELSYSDIR)/manager/log
+ chmod -R u+w $(RELSYSDIR)/manager/log
$(INSTALL_DATA) $(SYS_CONFIG_FILES) $(RELSYSDIR)
$(INSTALL_DATA) $(AGENT_CONFIG_FILES) $(RELSYSDIR)/agent/conf
$(INSTALL_DATA) $(MANAGER_CONFIG_FILES) $(RELSYSDIR)/manager/conf
diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk
index 29228fc59b..25e3a9470b 100644
--- a/lib/snmp/vsn.mk
+++ b/lib/snmp/vsn.mk
@@ -17,6 +17,6 @@
#
# %CopyrightEnd%
-SNMP_VSN = 4.20
+SNMP_VSN = 4.21.3
PRE_VSN =
APP_VSN = "snmp-$(SNMP_VSN)$(PRE_VSN)"
diff --git a/lib/ssh/doc/src/Makefile b/lib/ssh/doc/src/Makefile
index c4d8d9901c..c97c99cf52 100644
--- a/lib/ssh/doc/src/Makefile
+++ b/lib/ssh/doc/src/Makefile
@@ -29,15 +29,6 @@ VSN=$(SSH_VSN)
APPLICATION=ssh
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -76,33 +67,10 @@ EXTRA_FILES = \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -115,8 +83,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -131,32 +97,6 @@ clean clean_docs:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES)
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ *xmls_output *xmls_errs $(LATEX_CLEAN)
-
-endif
-
man: $(MAN3_FILES)
@@ -168,8 +108,6 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
$(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
$(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
@@ -179,28 +117,5 @@ release_docs_spec: docs
$(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
$(INSTALL_DIR) $(RELEASE_PATH)/man/man3
$(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-endif
-endif
-
-endif
release_spec:
diff --git a/lib/ssh/doc/src/make.dep b/lib/ssh/doc/src/make.dep
deleted file mode 100644
index cfe2f9617b..0000000000
--- a/lib/ssh/doc/src/make.dep
+++ /dev/null
@@ -1,19 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex ref_man.tex ssh.tex ssh_channel.tex \
- ssh_connection.tex ssh_sftp.tex ssh_sftpd.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml
index 71f3941577..6fc4fdc43d 100644
--- a/lib/ssh/doc/src/notes.xml
+++ b/lib/ssh/doc/src/notes.xml
@@ -29,6 +29,20 @@
<file>notes.xml</file>
</header>
+<section><title>Ssh 2.0.8</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Calling ssh_sftp:stop_channel/1 resulted in that the trap_exit flag was
+ set to true for the invoking process.</p>
+ <p>
+ Own Id: OTP-9386 Aux Id: seq11865</p>
+ </item>
+ </list>
+ </section>
+</section>
+
<section><title>Ssh 2.0.7</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/ssh/src/DSS.asn1 b/lib/ssh/src/DSS.asn1
index 77aca3808b..77aca3808b 100755..100644
--- a/lib/ssh/src/DSS.asn1
+++ b/lib/ssh/src/DSS.asn1
diff --git a/lib/ssh/src/Makefile b/lib/ssh/src/Makefile
index 42880fa80b..e7cf2c6723 100644
--- a/lib/ssh/src/Makefile
+++ b/lib/ssh/src/Makefile
@@ -127,13 +127,10 @@ $(APP_TARGET): $(APP_SRC) ../vsn.mk
$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
sed -e 's;%VSN%;$(VSN);' $< > $@
-%.hrl: %.asn1
- erlc $(ASN_FLAGS) $<
+%.erl %.hrl: %.asn1
+ $(ERLC) $(ASN_FLAGS) $<
-DSS.hrl DSS.erl: DSS.asn1
-PKCS-1.hrl PKCS-1.erl: PKCS-1.asn1
-
-$(EBIN)/ssh_file.$(EMULATOR): $(ASN_HRLS)
+$(EBIN)/ssh_file.$(EMULATOR) $(EBIN)/ssh_rsa.$(EMULATOR): $(ASN_HRLS)
docs:
diff --git a/lib/ssh/src/PKCS-1.asn1 b/lib/ssh/src/PKCS-1.asn1
index e7d6b18c63..e7d6b18c63 100755..100644
--- a/lib/ssh/src/PKCS-1.asn1
+++ b/lib/ssh/src/PKCS-1.asn1
diff --git a/lib/ssh/src/ssh.appup.src b/lib/ssh/src/ssh.appup.src
index 974145836c..150b7d86dd 100644
--- a/lib/ssh/src/ssh.appup.src
+++ b/lib/ssh/src/ssh.appup.src
@@ -19,13 +19,19 @@
{"%VSN%",
[
- {"2.0.6", [{load_module, ssh_userreg, soft_purge, soft_purge, []}]},
+ {"2.0.7", [{load_module, ssh_sftp, soft_purge, soft_purge, []}]},
+ {"2.0.6", [{load_module, ssh_userreg, soft_purge, soft_purge, []},
+ {load_module, ssh_sftp, soft_purge, soft_purge, []}]},
{"2.0.5", [{load_module, ssh_userreg, soft_purge, soft_purge, []},
+ {load_module, ssh_sftp, soft_purge, soft_purge, []},
{load_module, ssh_connection_handler, soft_purge, soft_purge, [ssh_userreg]}]}
],
[
- {"2.0.6", [{load_module, ssh_userreg, soft_purge, soft_purge, []}]},
+ {"2.0.7", [{load_module, ssh_sftp, soft_purge, soft_purge, []}]},
+ {"2.0.6", [{load_module, ssh_userreg, soft_purge, soft_purge, []},
+ {load_module, ssh_sftp, soft_purge, soft_purge, []}]},
{"2.0.5", [{load_module, ssh_userreg, soft_purge, soft_purge, []},
+ {load_module, ssh_sftp, soft_purge, soft_purge, []},
{load_module, ssh_connection_handler, soft_purge, soft_purge, [ssh_userreg]}]}
]
}.
diff --git a/lib/ssh/src/ssh_bits.erl b/lib/ssh/src/ssh_bits.erl
index 3f0a06575c..3f0a06575c 100755..100644
--- a/lib/ssh/src/ssh_bits.erl
+++ b/lib/ssh/src/ssh_bits.erl
diff --git a/lib/ssh/src/ssh_connect.hrl b/lib/ssh/src/ssh_connect.hrl
index 34d4ff8fc1..34d4ff8fc1 100755..100644
--- a/lib/ssh/src/ssh_connect.hrl
+++ b/lib/ssh/src/ssh_connect.hrl
diff --git a/lib/ssh/src/ssh_dsa.erl b/lib/ssh/src/ssh_dsa.erl
index 1b9a396f0c..1b9a396f0c 100755..100644
--- a/lib/ssh/src/ssh_dsa.erl
+++ b/lib/ssh/src/ssh_dsa.erl
diff --git a/lib/ssh/src/ssh_file.erl b/lib/ssh/src/ssh_file.erl
index 12180f56bb..12180f56bb 100755..100644
--- a/lib/ssh/src/ssh_file.erl
+++ b/lib/ssh/src/ssh_file.erl
diff --git a/lib/ssh/src/ssh_io.erl b/lib/ssh/src/ssh_io.erl
index 915fd63e4f..915fd63e4f 100755..100644
--- a/lib/ssh/src/ssh_io.erl
+++ b/lib/ssh/src/ssh_io.erl
diff --git a/lib/ssh/src/ssh_math.erl b/lib/ssh/src/ssh_math.erl
index 510eb16aa6..510eb16aa6 100755..100644
--- a/lib/ssh/src/ssh_math.erl
+++ b/lib/ssh/src/ssh_math.erl
diff --git a/lib/ssh/src/ssh_rsa.erl b/lib/ssh/src/ssh_rsa.erl
index 91b8285b2e..91b8285b2e 100755..100644
--- a/lib/ssh/src/ssh_rsa.erl
+++ b/lib/ssh/src/ssh_rsa.erl
diff --git a/lib/ssh/src/ssh_sftp.erl b/lib/ssh/src/ssh_sftp.erl
index 59e09fdd0f..f000558100 100755..100644
--- a/lib/ssh/src/ssh_sftp.erl
+++ b/lib/ssh/src/ssh_sftp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -130,9 +130,9 @@ start_channel(Host, Port, Opts) ->
end.
stop_channel(Pid) ->
- case process_info(Pid, [trap_exit]) of
- [{trap_exit, Bool}] ->
- process_flag(trap_exit, true),
+ case is_process_alive(Pid) of
+ true ->
+ OldValue = process_flag(trap_exit, true),
link(Pid),
exit(Pid, ssh_sftp_stop_channel),
receive
@@ -145,9 +145,9 @@ stop_channel(Pid) ->
ok
end
end,
- process_flag(trap_exit, Bool),
+ process_flag(trap_exit, OldValue),
ok;
- undefined ->
+ false ->
ok
end.
diff --git a/lib/ssh/src/ssh_userauth.hrl b/lib/ssh/src/ssh_userauth.hrl
index 8eb2d46ed1..8eb2d46ed1 100755..100644
--- a/lib/ssh/src/ssh_userauth.hrl
+++ b/lib/ssh/src/ssh_userauth.hrl
diff --git a/lib/ssh/src/ssh_xfer.hrl b/lib/ssh/src/ssh_xfer.hrl
index 4a4f1a4291..4a4f1a4291 100755..100644
--- a/lib/ssh/src/ssh_xfer.hrl
+++ b/lib/ssh/src/ssh_xfer.hrl
diff --git a/lib/ssh/test/Makefile b/lib/ssh/test/Makefile
index 5a2a6de24a..1820924ed6 100644
--- a/lib/ssh/test/Makefile
+++ b/lib/ssh/test/Makefile
@@ -115,7 +115,7 @@ release_tests_spec: opt
$(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR)
$(INSTALL_DATA) ssh.spec ssh.cover $(RELSYSDIR)
$(INSTALL_DATA) $(HRL_FILES_NEEDED_IN_TEST) $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
@tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
release_docs_spec:
diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk
index d79038df29..fe2b915d17 100644
--- a/lib/ssh/vsn.mk
+++ b/lib/ssh/vsn.mk
@@ -1,5 +1,5 @@
#-*-makefile-*- ; force emacs to enter makefile-mode
-SSH_VSN = 2.0.7
+SSH_VSN = 2.0.8
APP_VSN = "ssh-$(SSH_VSN)"
diff --git a/lib/ssl/Makefile b/lib/ssl/Makefile
index daad7dc3e6..a7a95004a6 100644
--- a/lib/ssl/Makefile
+++ b/lib/ssl/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2010. All Rights Reserved.
+# Copyright Ericsson AB 1999-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -25,7 +25,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
# Macros
#
-SUB_DIRECTORIES = src c_src doc/src examples/certs examples/src
+SUB_DIRECTORIES = src doc/src examples/certs examples/src
include vsn.mk
VSN = $(SSL_VSN)
diff --git a/lib/ssl/c_src/Makefile.dist b/lib/ssl/c_src/Makefile.dist
deleted file mode 100644
index 2468468921..0000000000
--- a/lib/ssl/c_src/Makefile.dist
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2009. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-
-# Makefile for SSL on Unix
-#
-# Placed in obj directory.
-#
-CC = gcc
-
-BINDIR = %BINDIR%
-LIBS = %LIBS%
-SSL_LIBDIR = %SSL_LIBDIR%
-OBJS = %OBJS%
-
-$(BINDIR)/ssl_esock: $(OBJS)
- $(CC) -L$(SSL_LIBDIR) -Wl,-R$(SSL_LIBDIR) -o $@ $^ \
- $(LIBS) -lssl -lcrypto
diff --git a/lib/ssl/c_src/Makefile.in b/lib/ssl/c_src/Makefile.in
deleted file mode 100644
index 6e413e7e8e..0000000000
--- a/lib/ssl/c_src/Makefile.in
+++ /dev/null
@@ -1,215 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2011. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-
-#
-# Makefile only for Unix and Win32/Cygwin.
-#
-
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-# ----------------------------------------------------
-# SSL locations and include options from configure
-# ----------------------------------------------------
-SSL_LIBDIR = @SSL_LIBDIR@
-SSL_INCLUDE = @SSL_INCLUDE@
-SSL_CRYPTO_LIBNAME = @SSL_CRYPTO_LIBNAME@
-SSL_SSL_LIBNAME = @SSL_SSL_LIBNAME@
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(SSL_VSN)
-
-# ----------------------------------------------------
-# Commands
-# ----------------------------------------------------
-CC = @CC@
-LD = @LD@
-SHELL = /bin/sh
-LIBS = @LIBS@
-PLAIN_CFLAGS = @CFLAGS@
-
-# ----------------------------------------------------
-# Includes and libs
-# ----------------------------------------------------
-
-ALL_CFLAGS = @WFLAGS@ @CFLAGS@ @DEFS@ $(TYPE_FLAGS)
-TARGET = @host@
-
-ifeq ($(TYPE),debug)
-TYPEMARKER = .debug
-TYPE_FLAGS = -g -DDEBUG @DEBUG_FLAGS@
-else
-TYPEMARKER =
-TYPE_FLAGS = -O2
-endif
-
-PRIVDIR = ../priv
-BINDIR = $(PRIVDIR)/bin/$(TARGET)
-OBJDIR = $(PRIVDIR)/obj/$(TARGET)
-
-# ----------------------------------------------------
-# File suffixes
-# ----------------------------------------------------
-exe = @EXEEXT@
-obj = .@OBJEXT@
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/ssl-$(VSN)
-
-# ----------------------------------------------------
-# Common Macros
-# ----------------------------------------------------
-OBJS = $(OBJDIR)/esock$(obj) \
- $(OBJDIR)/debuglog$(obj) \
- $(OBJDIR)/esock_poll$(obj) \
- $(OBJDIR)/esock_osio$(obj) \
- $(OBJDIR)/esock_utils$(obj) \
- $(OBJDIR)/esock_posix_str$(obj) \
- $(OBJDIR)/esock_openssl$(obj)
-
-PORT_PROGRAM = $(BINDIR)/ssl_esock$(exe)
-
-SKIP_BUILDING_BINARIES := false
-
-# Try to be BC for R10
-ifeq ($(findstring @SSL_,@SSL_DYNAMIC_ONLY@),@SSL_)
-DYNAMIC_CRYPTO_LIB=yes
-else
-DYNAMIC_CRYPTO_LIB=@SSL_DYNAMIC_ONLY@
-endif
-
-
-ifeq ($(DYNAMIC_CRYPTO_LIB),yes)
-
-ifneq ($(findstring win32,$(TARGET)),win32)
-SSL_MAKEFILE = $(OBJDIR)/Makefile
-else
-SSL_MAKEFILE =
-endif
-
-CC_R_FLAG=@CFLAG_RUNTIME_LIBRARY_PATH@
-
-ifeq ($(findstring @,$(CC_R_FLAG)),@)
-# Old erts configure used which hasn't replaced @CFLAG_RUNTIME_LIBRARY_PATH@;
-# we try our best here instead...
-
-ifeq ($(findstring darwin,$(TARGET)),darwin) # darwin: no flag
-CC_R_FLAG =
-else
-ifeq ($(findstring osf,$(TARGET)),osf) # osf1: -Wl,-rpath,
-CC_R_FLAG = -Wl,-rpath,
-else # Default: -Wl,-R
-CC_R_FLAG = -Wl,-R
-endif
-endif
-endif
-
-ifeq ($(strip $(CC_R_FLAG)),)
-CC_R_OPT =
-else
-CC_R_OPT = $(CC_R_FLAG)$(SSL_LIBDIR)
-endif
-
-SSL_CC_RUNTIME_LIBRARY_PATH=@SSL_CC_RUNTIME_LIBRARY_PATH@
-# Sigh...
-ifeq ($(findstring @,$(SSL_CC_RUNTIME_LIBRARY_PATH)),@)
-SSL_CC_RUNTIME_LIBRARY_PATH = $(CC_R_OPT)
-endif
-
-SSL_LINK_LIB=-L$(SSL_LIBDIR) -l$(SSL_SSL_LIBNAME) -l$(SSL_CRYPTO_LIBNAME)
-else
-# not dynamic crypto lib (default from R11B-5)
-NEED_KERBEROS=@SSL_LINK_WITH_KERBEROS@
-NEED_ZLIB=@SSL_LINK_WITH_ZLIB@
-SSL_MAKEFILE =
-CC_R_OPT =
-SSL_CC_RUNTIME_LIBRARY_PATH=
-SSL_LINK_LIB = $(SSL_LIBDIR)/lib$(SSL_SSL_LIBNAME).a $(SSL_LIBDIR)/lib$(SSL_CRYPTO_LIBNAME).a
-ifeq ($(NEED_KERBEROS),yes)
-SSL_LINK_LIB += @STATIC_KERBEROS_LIBS@
-endif
-ifeq ($(NEED_ZLIB),yes)
-SSL_LINK_LIB += @STATIC_ZLIB_LIBS@
-endif
-endif
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-debug opt: $(OBJDIR) $(BINDIR) $(OBJS) $(PORT_PROGRAM) $(SSL_MAKEFILE)
-
-$(OBJDIR):
- -@mkdir -p $(OBJDIR)
-
-$(BINDIR):
- -@mkdir -p $(BINDIR)
-
-$(OBJDIR)/esock_openssl$(obj): esock_openssl.c
- $(CC) -c -o $@ $(ALL_CFLAGS) $(SSL_INCLUDE) $<
-
-$(OBJDIR)/%$(obj): %.c
- $(CC) -c -o $@ $(ALL_CFLAGS) $<
-
-# Unix
-$(BINDIR)/ssl_esock: $(OBJS)
- $(CC) $(PLAIN_CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) $(SSL_CC_RUNTIME_LIBRARY_PATH) $(SSL_LINK_LIB)
-
-# Win32/Cygwin
-$(BINDIR)/ssl_esock.exe: $(OBJS)
- $(LD) $(SSL_CC_RUNTIME_LIBRARY_PATH) -L$(SSL_LIBDIR) -o $@ $^ -lwsock32 -l$(SSL_CRYPTO_LIBNAME) -l$(SSL_SSL_LIBNAME)
-
-# Unix only, and only when linking statically
-$(SSL_MAKEFILE):
- sed -e "s;%BINDIR%;../../bin/$(TARGET);" \
- -e "s;%SSL_LIBDIR%;$(SSL_LIBDIR);" \
- -e "s;%OBJS;$(OBJS);" \
- -e "s;%LIBS%;$(LIBS);" ./Makefile.dist \
- > $(OBJDIR)/Makefile
-
-
-clean:
- rm -f $(PORT_PROGRAM) $(OBJS) core *~ $(SSL_MAKEFILE)
-
-docs:
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv/bin
- $(INSTALL_PROGRAM) $(PORT_PROGRAM) $(RELSYSDIR)/priv/bin
-ifneq ($(SSL_MAKEFILE),)
- $(INSTALL_DIR) $(RELSYSDIR)/priv/obj
- $(INSTALL_DATA) $(OBJS) $(RELSYSDIR)/priv/obj
- sed -e "s;%BINDIR%;../bin;" \
- -e "s;%SSL_LIBDIR%;$(SSL_LIBDIR);" \
- -e "s;%OBJS;$(OBJS);" \
- -e "s;%LIBS%;$(LIBS);" ./Makefile.dist \
- > $(RELSYSDIR)/priv/obj/Makefile
-endif
-
-release_docs_spec:
-
diff --git a/lib/ssl/c_src/Makefile.win32 b/lib/ssl/c_src/Makefile.win32
deleted file mode 100644
index 668cd2a28d..0000000000
--- a/lib/ssl/c_src/Makefile.win32
+++ /dev/null
@@ -1,147 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2009. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-
-#
-# SSL - Makefile for Windows NT
-#
-# It is assumed that the following environment variables have been set:
-#
-# INCLUDE X:\MSDEV\INCLUDE
-# LIB X:\MSDEV\LIB
-#
-# so that standard include files, and the socket library can be found.
-#
-# When ssl_esock.exe is run, the PATH environment variable must contain
-# the name of a directory that contains ssleay32.dll and libeay32.dll,
-# and windows socket dll.
-#
-
-# Roots
-!ifndef OPENSSL_ROOT
-! error "Makefile.win32: ssl: OPENSSL_ROOT not set"
-!endif
-
-TARGET = win32
-
-BINDIR = ..\priv\bin\$(TARGET)
-OBJDIR = ..\priv\obj\$(TARGET)
-
-!if !exist($(BINDIR))
-! if [mkdir $(BINDIR)]
-! error "SSL: cannot create BINDIR"
-! endif
-!endif
-
-!if !exist($(OBJDIR))
-! if [mkdir $(OBJDIR)]
-! error "SSL: cannot create OBJDIR"
-! endif
-!endif
-
-# Includes
-#
-OPENSSL_INCLUDE = $(OPENSSL_ROOT)\inc32
-
-INCLUDES = /I. /I$(OPENSSL_INCLUDE)
-
-# Libraries
-#
-OPENSSL_LIBDIR = $(OPENSSL_ROOT)\out32dll
-OPENSSL_LIBS = \
- $(OPENSSL_LIBDIR)\ssleay32.lib \
- $(OPENSSL_LIBDIR)\libeay32.lib
-
-!ifdef ESOCK_WINSOCK2
-WINSOCK_LIB = ws2_32.lib
-DEFS = -DESOCK_WINSOCK2
-!else
-WINSOCK_LIB = wsock32.lib
-!endif
-
-# Compiler options
-#
-# NOTE: Size of fd_set is set in esock_winsock.h but can be overridden
-# with a -D option here.
-#
-OPTS = /MDd /G5 /Ox /O2 /Ob2 /Z7
-DEFS = -D__WIN32__ -DWIN32 $(DEFS)
-CFLAGS = $(INCLUDES) /nologo $(OPTS) $(DEFS)
-
-# Object files
-#
-SSL_BASE_OBJS = \
- $(OBJDIR)\esock.obj \
- $(OBJDIR)\debuglog.obj \
- $(OBJDIR)\esock_poll$(obj) \
- $(OBJDIR)\esock_osio.obj \
- $(OBJDIR)\esock_utils.obj \
- $(OBJDIR)\esock_posix_str.obj
-
-OPENSSL_OBJS = \
- $(OBJDIR)\esock_openssl.obj
-
-#
-# Targets
-#
-
-all: $(SSL_BASE_OBJS) $(OPENSSL_OBJS) $(BINDIR)\ssl_esock.exe
-
-clean:
- del $(BINDIR)\*.exe
- del $(OBJDIR)\*.obj
-
-# Inference rule .c.obj:
-#
-{.}.c{$(OBJDIR)}.obj:
- $(CC) $(CFLAGS) /c /Fo$@ $(*B).c
-
-# Binary
-#
-$(BINDIR)\ssl_esock.exe: $(SSL_BASE_OBJS) $(OPENSSL_OBJS)
- $(CC) /nologo $(SSL_BASE_OBJS) $(OPENSSL_OBJS) $(OPENSSL_LIBS) \
- $(WINSOCK_LIB) /Fe$(BINDIR)\ssl_esock.exe
-
-
-
-# Dependencies
-#
-$(OBJDIR)\esock.o: esock.h debuglog.h esock_ssl.h esock_osio.h \
- esock_utils.h esock_winsock.h
-$(OBJDIR)\debuglog.o: debuglog.h esock_ssl.h esock_utils.h
-$(OBJDIR)\esock_osio.o: esock_osio.h esock.h debuglog.h esock_utils.h \
- esock_winsock.h
-$(OBJDIR)\esock_utils.o: esock_utils.h
-$(OBJDIR)\esock_posix_str.o: esock_posix_str.h esock_winsock.h
-
-$(OBJDIR)\esock_openssl.o: esock.h esock_ssl.h debuglog.h esock_utils.h \
- $(OPENSSL_INCLUDE)\crypto.h \
- $(OPENSSL_INCLUDE)\ssl.h \
- $(OPENSSL_INCLUDE)\err.h
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/ssl/c_src/Makefile.win32.dist b/lib/ssl/c_src/Makefile.win32.dist
deleted file mode 100644
index 8510c44e08..0000000000
--- a/lib/ssl/c_src/Makefile.win32.dist
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2009. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-
-# Makefile.win32.dist for SSL
-#
-# To be placed in obj directory.
-#
-
-CC = cl
-
-BINDIR = %BINDIR%
-
-OPENSSL_LIBS = \
- $(BINDIR)\ssleay32.lib \
- $(BINDIR)\libeay32.lib
-
-WINSOCK_LIB = ws2_32.lib
-
-SSL_BASE_OBJS = esock.obj debuglog.obj esock_osio.obj esock_utils.obj \
- esock_posix_str.obj
-
-OPENSSL_OBJS = esock_openssl.obj
-
-$(BINDIR)\ssl_esock.exe: $(SSL_BASE_OBJS) $(OPENSSL_OBJS)
- $(CC) /nologo $(SSL_BASE_OBJS) $(OPENSSL_OBJS) $(OPENSSL_LIBS) \
- $(WINSOCK_LIB) /Fe$(BINDIR)\ssl_esock.exe
-
-
-
diff --git a/lib/ssl/c_src/debuglog.c b/lib/ssl/c_src/debuglog.c
deleted file mode 100644
index e2e55df4b2..0000000000
--- a/lib/ssl/c_src/debuglog.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/*<copyright>
- * <year>1999-2008</year>
- * <holder>Ericsson AB, All Rights Reserved</holder>
- *</copyright>
- *<legalnotice>
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * The Initial Developer of the Original Code is Ericsson AB.
- *</legalnotice>
- */
-/*
- * Purpose: Various routines for debug printouts and logs.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <ctype.h>
-#include <time.h>
-#include "debuglog.h"
-#include "esock_utils.h"
-
-#ifndef __WIN32__
-static char tr_format_buf[256];
-static char *tr_format(const char *format);
-static int vfprintclistf(FILE *fp, const char *format, va_list args);
-#endif
-
-int debug = 0;
-int debugmsg = 0;
-FILE *ssllogfp = NULL;
-FILE *__locallogfp = NULL;
-
-void open_ssllog(char *path)
-{
- ssllogfp = openlog(path);
-}
-
-void close_ssllog(void)
-{
- if (ssllogfp)
- closelog(ssllogfp);
-}
-
-FILE *openlog(char *s)
-{
- FILE *fp;
- time_t t = time(NULL);
-
- if ((fp = fopen(s, "a"))) {
- setbuf(fp, NULL);
- fprintf(fp, "===== Opened [%s] %s", s, ctime(&t));
- }
- return fp;
-}
-
-void closelog(FILE *fp)
-{
- time_t t = time(NULL);
-
- if (fp) {
- fprintf(fp, "Closed %s", ctime(&t));
- fclose(fp);
- }
-}
-
-int __debugprintf(const char *format, ...)
-{
- va_list args;
- int ret;
-#ifndef __WIN32__
- char *newformat;
-
- va_start(args, format);
- newformat = tr_format(format);
- ret = vfprintf(stderr, newformat, args);
- if (newformat != format && newformat != tr_format_buf)
- esock_free(newformat);
-#else
- va_start(args, format);
- ret = vfprintf(stderr, format, args);
-#endif
- va_end(args);
- if (ssllogfp) {
- va_start(args, format);
- vfprintf(ssllogfp, format, args);
- va_end(args);
- }
- return ret;
-}
-
-int __debugprintclistf(const char *format, ...)
-{
- va_list args;
- int ret;
-#ifndef __WIN32__
- char *newformat;
-
- va_start(args, format);
- newformat = tr_format(format);
- ret = vfprintclistf(stderr, newformat, args);
- if (newformat != format && newformat != tr_format_buf)
- esock_free(newformat);
-#else
- va_start(args, format);
- ret = vfprintclistf(stderr, format, args);
-#endif
- if (ssllogfp)
- vfprintclistf(ssllogfp, format, args);
- va_end(args);
- return ret;
-}
-
-int __debuglogf(const char *format, ...)
-{
- va_list args;
- int ret;
-
- va_start(args, format);
- ret = vfprintf(__locallogfp, format, args);
- va_end(args);
- return ret;
-}
-
-#ifndef __WIN32__
-
-/* Insert `\r' before each `\n' i format */
-static char *tr_format(const char *format)
-{
- char *newformat, *s, *t;
- int len;
-
- len = strlen(format);
- if ((newformat = (len > 127) ? esock_malloc(len) : tr_format_buf)) {
- for (s = (char *)format, t = newformat; *s; *t++ = *s++)
- if (*s == '\n')
- *t++ = '\r';
- *t = '\0';
- } else
- newformat = (char *)format;
- return newformat;
-}
-
-#endif
-
-/* This function is for printing arrays of characters with formats
- * %FPa or %FPb, where F and P are the ordinary specifiers for
- * field width and precision, respectively.
- *
- * The conversion specifier `a' implies hex-string output, while
- * the `b' specifier provides character output (for non-printable
- * characters a `.' is written.
- *
- * The F specifier contains the width for each character. The
- * P specifier tells how many characters to print.
- *
- * Example: Suppose we have a function myprintf(char *format, ...)
- * that calls our vfprintclistf(), and that
- *
- * char buf[] = "h\r\n";
- * len = 3;
- *
- * Then
- *
- * myprintf("%.2b", buf) prints "h."
- * myprintf("%2.3b", buf) prints "h . . "
- * myprintf("%3.*a", len, buf) prints "68 0d 0a"
- *
- */
-
-static int vfprintclistf(FILE *fp, const char *format, va_list args)
-{
-
- int i, len, width, prec, written = 0;
- char *s, *prevs, *fstart;
- unsigned char *buf;
-
- if (!format || !*format)
- return 0;
-
- /* %{[0-9]*|\*}{.{[0-9]*|\*}{a|b} */
-
- prevs = (char *)format; /* format is const */
- s = strchr(format, '%');
- while (s && *s) {
- if (s - prevs > 0)
- written += fprintf(fp, "%.*s", s - prevs, prevs);
- width = prec = 0;
- fstart = s;
- s++;
- if (*s != '%') { /* otherwise it is not a format */
- if (*s == '*') { /* width in arg */
- s++;
- width = va_arg(args, int);
- } else if ((len = strspn(s, "0123456789"))) { /* const width */
- width = atoi(s);
- s += len;
- } else
- width = 0;
- if (*s == '.') { /* precision specified */
- s++;
- if (*s == '*') { /* precision in arg */
- s++;
- prec = va_arg(args, int);
- } else if ((len = strspn(s, "0123456789"))) { /* const prec */
- prec = atoi(s);
- s += len;
- } else /* no precision value, defaults to zero */
- prec = 0;
- } else
- prec = 0; /* no precision defaults to zero */
- if (*s == 'a' || *s == 'b') { /* only valid specifiers */
- buf = va_arg(args, unsigned char *);
- if (*s == 'a') {
- for (i = 0; i < prec; i++)
- written += fprintf(fp, "%*.2x", width, buf[i]);
- }else if (*s == 'b') {
- for (i = 0; i < prec; i++) {
- if (isprint(buf[i]))
- written += fprintf(fp, "%*c", width, buf[i]);
- else
- written += fprintf(fp, "%*c", width, '.');
- }
- }
- } else {
- fprintf(stderr, "fprintclistf: format \"%s\" invalid.\n",
- format);
- va_end(args);
- return written;
- }
- }
- s++;
- /* Now s points to the next character after the format */
- prevs = s;
- s = strchr(s, '%');
- }
- if (format + strlen(format) + 1 - prevs > 0)
- written += fprintf(fp, "%s", prevs);
- return written;
-}
-
diff --git a/lib/ssl/c_src/debuglog.h b/lib/ssl/c_src/debuglog.h
deleted file mode 100644
index 5699e6b495..0000000000
--- a/lib/ssl/c_src/debuglog.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*<copyright>
- * <year>1998-2008</year>
- * <holder>Ericsson AB, All Rights Reserved</holder>
- *</copyright>
- *<legalnotice>
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * The Initial Developer of the Original Code is Ericsson AB.
- *</legalnotice>
- */
-/*
- * Purpose: Debug functions and macros.
- *
- */
-
-#ifndef __DEBUGLOG_H_
-#define __DEBUGLOG_H_
-
-#include <stdio.h>
-#include "esock_ssl.h"
-
-#define DEBUGF(x) if (debug) __debugprintf x;
-#define DEBUGMSGF(x) if (debugmsg) __debugprintclistf x;
-#define LOGF(fp, x) if (fp) { __locallogfp = fp; __debuglogf x; }
-#define SSLDEBUGF() if (debug) { esock_ssl_print_errors_fp(stderr); \
- if (ssllogfp) esock_ssl_print_errors_fp(ssllogfp); }
-
-int debug;
-int debugmsg;
-FILE *ssllogfp;
-FILE *__locallogfp;
-
-void open_ssllog(char *path);
-void close_ssllog(void);
-FILE *openlog(char *);
-void closelog(FILE *);
-int __debugprintf(const char *, ...);
-int __debugprintclistf(const char *, ...);
-int __debuglogf(const char *, ...);
-
-#endif
diff --git a/lib/ssl/c_src/esock.c b/lib/ssl/c_src/esock.c
deleted file mode 100644
index 78d08f7c29..0000000000
--- a/lib/ssl/c_src/esock.c
+++ /dev/null
@@ -1,1904 +0,0 @@
-/*<copyright>
- * <year>1999-2008</year>
- * <holder>Ericsson AB, All Rights Reserved</holder>
- *</copyright>
- *<legalnotice>
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * The Initial Developer of the Original Code is Ericsson AB.
- *</legalnotice>
- */
-
-/*
- * Purpose: Implementation of Secure Socket Layer (SSL).
- *
- * This is an "SSL proxy" for Erlang in the form of a port
- * program.
- *
- * The implementation has borrowed somewhat from the original
- * implementation of `socket' by Claes Wikstr�m, and the former
- * implementation of `ssl_socket' by Helen Ariyan.
- *
- * All I/O is now non-blocking.
- *
- * When a connection (cp) is in the state JOINED we have the following
- * picture:
- *
- * proxy->fd fd
- * | |
- * proxy->eof | --------> wq -----------> | bp
- * | |
- * Erlang | | SSL
- * | |
- * proxy->bp | <------ proxy->wq --------- | eof
- * | |
- *
- * We read from Erlang (proxy->fd) and write to SSL (fd); and read from
- * SSL (fd) and write to Erlang (proxy->fd).
- *
- * The variables bp (broken pipe) and eof (end of file) take the
- * values 0 and 1.
- *
- * What has been read and cannot be immediately written is put in a
- * write queue (wq). A wq is emptied before reads are continued, which
- * means that at most one chunk that is read can be in a wq.
- *
- * The proxy-to-ssl part of a cp is valid iff
- *
- * !bp && (wq.len > 0 || !proxy->eof).
- *
- * The ssl-to-proxy part of a cp is valid iff
- *
- * !proxy->bp && (proxy->wq.len > 0 || !eof).
- *
- * The connection is valid if any of the above parts are valid, i.e.
- * invalid if both parts are invalid.
- *
- * Every SELECT_TIMEOUT second we try to write to those file
- * descriptors that have non-empty wq's (the only way to detect that a
- * far end has gone away is to write to it).
- *
- * STATE TRANSITIONS
- *
- * Below (*) means that the corresponding file descriptor is published
- * (i.e. kwown outside this port program) when the state is entered,
- * and thus cannot be closed without synchronization with the
- * ssl_server.
- *
- * Listen:
- *
- * STATE_NONE ---> (*) PASSIVE_LISTENING <---> ACTIVE_LISTENING
- *
- * Accept:
- *
- * STATE_NONE ---> SSL_ACCEPT ---> (*) CONNECTED ---> JOINED --->
- * ---> SSL_SHUTDOWN ---> DEFUNCT
- *
- * Connect:
- *
- * STATE_NONE ---> (*) WAIT_CONNECT ---> SSL_CONNECT ---> CONNECTED --->
- * ---> JOINED ---> SSL_SHUTDOWN ---> DEFUNCT
- *
- * In states where file descriptors has been published, and where
- * something goes wrong, the state of the connection is set to
- * DEFUNCT. A connection in such a state can only be closed by a CLOSE
- * message from Erlang (a reception of such a message is registered in
- * cp->closed). The possible states are: WAIT_CONNECT, SSL_CONNECT,
- * CONNECTED, JOINED, and SSL_SHUTDOWN.
- *
- * A connection in state SSL_ACCEPT can be closed and removed without
- * synchronization.
- *
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#ifdef __WIN32__
-#include "esock_winsock.h"
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <time.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <errno.h>
-
-#ifdef __WIN32__
-#include <process.h>
-#else
-#include <unistd.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <sys/time.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-#endif
-
-#ifndef INADDR_NONE
-#define INADDR_NONE 0xffffffff /* Should be in <netinet/in.h>. */
-#endif
-
-#include "esock.h"
-#include "debuglog.h"
-#include "esock_utils.h"
-#include "esock_ssl.h"
-#include "esock_osio.h"
-#include "esock_posix_str.h"
-#include "esock_poll.h"
-
-#define MAJOR_VERSION 2
-#define MINOR_VERSION 0
-#define MAXREPLYBUF 256
-#define RWBUFLEN (32*1024)
-#define IS_CLIENT 0
-#define IS_SERVER 1
-#define SELECT_TIMEOUT 2 /* seconds */
-
-#define psx_errstr() esock_posix_str(sock_errno())
-#define ssl_errstr() esock_ssl_errstr
-
-#define PROXY_TO_SSL_VALID(cp) (!(cp)->bp && \
- ((cp)->wq.len > 0 || !(cp)->proxy->eof))
-
-#define SSL_TO_PROXY_VALID(cp) (!(cp)->proxy->bp && \
- ((cp)->proxy->wq.len > 0 || !(cp)->eof))
-
-#define JOINED_STATE_INVALID(cp) (!(PROXY_TO_SSL_VALID(cp)) && \
- !(SSL_TO_PROXY_VALID(cp)))
-static int loop(void);
-static int set_poll_conns(Connection *cp, EsockPoll *ep, int verbose);
-static Connection *next_polled_conn(Connection *cp, Connection **cpnext,
- EsockPoll *ep, int set_wq_fds);
-
-static void leave_joined_state(Connection *cp);
-static void do_shutdown(Connection *cp);
-static void close_and_remove_connection(Connection *cp);
-static int reply(int cmd, char *fmt, ...);
-static int input(char *fmt, ...);
-static int put_pars(unsigned char *buf, char *fmt, va_list args);
-static int get_pars(unsigned char *buf, char *fmt, va_list args);
-static FD do_connect(char *lipstring, int lport, char *fipstring, int fport);
-static FD do_listen(char *ipstring, int lport, int backlog, int *aport);
-static FD do_accept(FD listensock, struct sockaddr *saddr, int *len);
-static void print_connections(void);
-static void dump_connections(void);
-static int check_num_sock_fds(FD fd);
-static void safe_close(FD fd);
-static Connection *new_connection(int state, FD fd);
-static Connection *get_connection(FD fd);
-static void remove_connection(Connection *conn);
-static Proxy *get_proxy_by_peerport(int port);
-static Proxy *new_proxy(FD fd);
-static void remove_proxy(Proxy *proxy);
-static void ensure_write_queue(WriteQueue *wq, int size);
-static void clean_up(void);
-
-static Connection *connections = NULL;
-static int num_sock_fds; /* On UNIX all file descriptors */
-static Proxy *proxies = NULL;
-static int proxy_listensock = INVALID_FD;
-static int proxy_listenport = 0;
-static int proxy_backlog = 128;
-static int proxysock_last_err = 0;
-static int proxysock_err_cnt = 0;
-static char rwbuf[RWBUFLEN];
-static unsigned char *ebuf = NULL; /* Set by read_ctrl() */
-
-static char *connstr[] = {
- "STATE_NONE",
- "ACTIVE_LISTENING",
- "PASSIVE_LISTENING",
- "CONNECTED",
- "WAIT_CONNECT",
- "SSL_CONNECT",
- "SSL_ACCEPT",
- "TRANSPORT_ACCEPT",
- "JOINED",
- "SSL_SHUTDOWN",
- "DEFUNCT"
-};
-
-static char *originstr[] = {
- "listen",
- "accept",
- "connect"
-};
-
-int main(int argc, char **argv)
-{
- char *logfile = NULL;
- int i;
- esock_version *vsn;
- char *ciphers;
-#ifdef __WIN32__
- int pid;
- WORD version;
- WSADATA wsa_data;
-
- set_binary_mode();
- setvbuf(stderr, NULL, _IONBF, 0);
- /* Two sockets for the stdin socket pipe (local thread). */
- num_sock_fds = 2;
-#else
- pid_t pid;
- num_sock_fds = 3; /* 0, 1, 2 */
-#endif
-
- pid = getpid();
- i = 1;
- while (i < argc) {
- if (strcmp(argv[i], "-d") == 0) {
- debug = 1;
- i++;
- } else if (strcmp(argv[i], "-dm") == 0) {
- debugmsg = 1;
- i++;
- } else if (strcmp(argv[i], "-pp") == 0) {
- i++;
- proxy_listenport = atoi(argv[i]);
- i++;
- } else if (strcmp(argv[i], "-pb") == 0) {
- i++;
- proxy_backlog = atoi(argv[i]);
- i++;
- } else if (strcmp(argv[i], "-pv") == 0) {
- i++;
- protocol_version = atoi(argv[i]);
- i++;
- } else if (strcmp(argv[i], "-dd") == 0) {
- i++;
- logfile = esock_malloc(strlen(argv[i]) + 64);
- sprintf(logfile, "%s/ssl_esock.%d.log", argv[i], (int)pid);
- i++;
- } else if (strcmp(argv[i], "-ersa") == 0) {
- ephemeral_rsa = 1;
- i++;
- } else if (strcmp(argv[i], "-edh") == 0) {
- ephemeral_dh = 1;
- i++;
- }
- }
- if (debug || debugmsg) {
- DEBUGF(("Starting ssl_esock\n"));
- if (logfile) {
- open_ssllog(logfile);
-#ifndef __WIN32__
- num_sock_fds++;
-#endif
- }
- atexit(close_ssllog);
- DEBUGF(("pid = %d\n", getpid()));
- }
- if (esock_ssl_init() < 0) {
- fprintf(stderr, "esock: Could not do esock_ssl_init\n");
- exit(EXIT_FAILURE);
- }
-
- atexit(esock_ssl_finish);
-
-#ifdef __WIN32__
- /* Start Windows' sockets */
- version = MAKEWORD(MAJOR_VERSION, MINOR_VERSION);
- if (WSAStartup(version, &wsa_data) != 0) {
- fprintf(stderr, "esock: Could not start up Windows' sockets\n");
- exit(EXIT_FAILURE);
- }
- atexit((void (*)(void))WSACleanup);
- if (LOBYTE(wsa_data.wVersion) < MAJOR_VERSION ||
- (LOBYTE(wsa_data.wVersion) == MAJOR_VERSION &&
- HIBYTE(wsa_data.wVersion) < MINOR_VERSION)) {
- fprintf(stderr, "esock: Windows socket version error. "
- "Requested version:"
- "%d.%d, version found: %d.%d\n", MAJOR_VERSION,
- MINOR_VERSION, LOBYTE(wsa_data.wVersion),
- HIBYTE(wsa_data.wVersion));
- exit(EXIT_FAILURE);
- }
- DEBUGF(("Using Windows socket version: %d.%d\n",
- LOBYTE(wsa_data.wVersion), HIBYTE(wsa_data.wVersion)));
- DEBUGF(("Maximum number of sockets available: %d\n",
- wsa_data.iMaxSockets));
-
- if (esock_osio_init() < 0) {
- fprintf(stderr, "esock: Could not init osio\n");
- exit(EXIT_FAILURE);
- }
- atexit(esock_osio_finish);
-#endif
-
- /* Create the local proxy listen socket and set it to non-blocking */
- proxy_listensock = do_listen("127.0.0.1", proxy_listenport,
- proxy_backlog, &proxy_listenport);
- if (proxy_listensock == INVALID_FD) {
- fprintf(stderr, "esock: Cannot create local listen socket\n");
- exit(EXIT_FAILURE);
- }
- SET_NONBLOCKING(proxy_listensock);
- DEBUGF(("Local proxy listen socket: fd = %d, port = %d\n",
- proxy_listensock, proxy_listenport));
-
- vsn = esock_ssl_version();
- ciphers = esock_ssl_ciphers();
-
- /* Report: port number of the local proxy listen socket, the native
- * os pid, the compile and lib versions of the ssl library, and
- * the list of available ciphers. */
- reply(ESOCK_PROXY_PORT_REP, "24sss", proxy_listenport, (int)pid,
- vsn->compile_version, vsn->lib_version, ciphers);
-
- atexit(clean_up);
-
- loop();
-
- if (logfile)
- esock_free(logfile);
- exit(EXIT_SUCCESS);
-}
-
-
-/*
- * Local functions
- *
- */
-
-static int loop(void)
-{
- EsockPoll pollfd;
- FD fd, msgsock, listensock, connectsock, proxysock;
- int cc, wc, fport, lport, pport, length, backlog, intref, op;
- int value;
- char *lipstring, *fipstring;
- char *flags;
- char *protocol_vsn, *cipher;
- unsigned char *cert, *bin;
- int certlen, binlen;
- struct sockaddr_in iserv_addr;
- int sret = 1;
- Connection *cp, *cpnext, *newcp;
- Proxy *pp;
- time_t last_time = 0, now = 0;
- int set_wq_fds;
-
- esock_poll_init(&pollfd);
-
- while(1) {
- esock_poll_zero(&pollfd);
- esock_poll_fd_set_read(&pollfd, proxy_listensock);
- esock_poll_fd_set_read(&pollfd, local_read_fd);
-
- set_wq_fds = 0;
-
- if (sret) /* sret == 1 the first time. */
- DEBUGF(("==========LOOP=============\n"));
-
- cc = set_poll_conns(connections, &pollfd, sret) + 1;
-
- if (sret) {
- print_connections();
- DEBUGF(("Before poll/select: %d descriptor%s (total %d)\n",
- cc, (cc == 1) ? "" : "s", num_sock_fds));
- }
-
- sret = esock_poll(&pollfd, SELECT_TIMEOUT);
- if (sret < 0) {
- DEBUGF(("select/poll error: %s\n", psx_errstr()));
- continue;
- }
-
- time(&now);
- if (now >= last_time + SELECT_TIMEOUT) {
- set_wq_fds = 1;
- last_time = now;
- }
- /*
- * First accept as many connections as possible on the
- * proxy listen socket. We record the peer port, which
- * is later used as a reference for joining a proxy
- * connection with a network connection.
- */
-
- if (esock_poll_fd_isset_read(&pollfd, proxy_listensock)) {
- while (1) {
- length = sizeof(iserv_addr);
- proxysock = do_accept(proxy_listensock,
- (struct sockaddr *)&iserv_addr,
- (int*)&length);
- if(proxysock == INVALID_FD) {
- if (sock_errno() != ERRNO_BLOCK) {
- /* We can here for example get the error
- * EMFILE, i.e. no more file descriptors
- * available, but we do not have any specific
- * connection to report the error to. We
- * increment the error counter and saves the
- * last err.
- */
- proxysock_err_cnt++;
- proxysock_last_err = sock_errno();
- DEBUGF(("accept error (proxy_listensock): %s\n",
- psx_errstr()));
- }
- break;
- } else {
- /* Get peer port number */
-/* length = sizeof(iserv_addr); */
-/* if (getpeername(proxysock, (struct sockaddr *)&iserv_addr, */
-/* &length) < 0) { */
-/* DEBUGF(("Can't get peername of proxy socket")); */
-/* safe_close(proxysock); */
-/* } else { */
- /* Add to pending proxy connections */
- SET_NONBLOCKING(proxysock);
- pp = new_proxy(proxysock);
- pp->peer_port = ntohs(iserv_addr.sin_port);
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("[PROXY_LISTEN_SOCK] conn accepted: "
- "proxyfd = %d, "
- "peer port = %d\n", proxysock, pp->peer_port));
-/* } */
- }
- }
- }
-
- /*
- * Read control messages from Erlang
- */
- if (esock_poll_fd_isset_read(&pollfd, local_read_fd)) {
- cc = read_ctrl(&ebuf);
- if ( cc < 0 ) {
- DEBUGF(("Read loop -1 or 0\n"));
- return -1;
- } else if (cc == 0) { /* not eof */
- DEBUGF(("GOT empty string \n"));
-
- } else {
-
- switch((int)*ebuf) {
-
- case ESOCK_SET_SEED_CMD:
- /*
- * ebuf = {cmd(1), binary(N) }
- */
- input("b", &binlen, &bin);
- DEBUGF(("[SET_SEED_CMD]\n"));
- esock_ssl_seed(bin, binlen);
- /* no reply */
- break;
-
- case ESOCK_GETPEERNAME_CMD:
- /*
- * ebuf = {cmd(1), fd(4)}
- */
- input("4", &fd);
- DEBUGF(("[GETPEERNAME_CMD] fd = %d\n", fd));
- cp = get_connection(fd);
- length = sizeof(iserv_addr);
- if (!cp) {
- sock_set_errno(ERRNO_NOTSOCK);
- reply(ESOCK_GETPEERNAME_ERR, "4s", fd, psx_errstr());
- } else if (getpeername(fd,
- (struct sockaddr *) &iserv_addr,
- &length) < 0) {
- reply(ESOCK_GETPEERNAME_ERR, "4s", fd, psx_errstr());
- } else {
- /*
- * reply = {cmd(1), fd(4), port(2),
- * ipstring(N), 0(1)}
- */
- reply(ESOCK_GETPEERNAME_REP, "42s", fd,
- ntohs(iserv_addr.sin_port),
- inet_ntoa(iserv_addr.sin_addr));
- }
- break;
-
- case ESOCK_GETSOCKNAME_CMD:
- /*
- * ebuf = {cmd(1), fd(4)}
- */
- input("4", &fd);
- DEBUGF(("[GETSOCKNAME_CMD] fd = %d\n", fd));
- cp = get_connection(fd);
- length = sizeof(iserv_addr);
- if (!cp) {
- sock_set_errno(ERRNO_NOTSOCK);
- reply(ESOCK_GETSOCKNAME_ERR, "4s", fd, psx_errstr());
- } else if (getsockname(fd,
- (struct sockaddr *)&iserv_addr,
- &length) < 0) {
- reply(ESOCK_GETSOCKNAME_ERR, "4s", fd, psx_errstr());
- } else {
- /*
- * reply = {cmd(1), fd(4), port(2),
- * ipstring(N), 0(1)}
- */
- reply(ESOCK_GETSOCKNAME_REP, "42s", fd,
- ntohs(iserv_addr.sin_port),
- inet_ntoa(iserv_addr.sin_addr));
- }
- break;
-
- case ESOCK_GETCONNINFO_CMD:
- /*
- * ebuf = {cmd(1), fd(4)}
- */
- input("4", &fd);
- DEBUGF(("[GETCONNINFO_CMD] fd = %d\n", fd));
- cp = get_connection(fd);
- if (!cp) {
- sock_set_errno(ERRNO_NOTSOCK);
- reply(ESOCK_GETCONNINFO_ERR, "4s", fd, psx_errstr());
- } else {
- if (esock_ssl_getprotocol_version(cp,
- &protocol_vsn) < 0)
- reply(ESOCK_GETCONNINFO_ERR, "4s", fd, psx_errstr());
- else if (esock_ssl_getcipher(cp, &cipher) < 0)
- reply(ESOCK_GETCONNINFO_ERR, "4s", fd, psx_errstr());
- else
- /*
- * reply = {cmd(1), fd(4), protocol(N), 0(1),
- * cipher(N), 0(1)}
- */
- reply(ESOCK_GETCONNINFO_REP, "4ss", fd,
- protocol_vsn, cipher);
- }
- break;
-
- case ESOCK_GETPEERCERT_CMD:
- /*
- * ebuf = {cmd(1), fd(4)}
- */
- input("4", &fd);
- DEBUGF(("[GETPEERCERT_CMD] fd = %d\n", fd));
- cp = get_connection(fd);
- if (!cp) {
- sock_set_errno(ERRNO_NOTSOCK);
- reply(ESOCK_GETPEERCERT_ERR, "4s", fd, psx_errstr());
- } else {
- if ((certlen = esock_ssl_getpeercert(cp, &cert)) < 0)
- reply(ESOCK_GETPEERCERT_ERR, "4s", fd, psx_errstr());
- else {
- /*
- * reply = {cmd(1), fd(4), certlen(4), cert(N)}
- */
- reply(ESOCK_GETPEERCERT_REP, "4b", fd,
- certlen, cert);
- esock_free(cert);
- }
- }
- break;
-
- case ESOCK_CONNECT_CMD:
- /*
- * ebuf = {cmd(1), intref(4),
- * lport(2), lipstring(N), 0(1), -- local
- * fport(2), fipstring(N), 0(1), -- foreign
- * flags(N), 0(1)}
- */
- input("42s2ss", &intref, &lport, &lipstring,
- &fport, &fipstring, &flags);
- DEBUGF(("[CONNECT_CMD] intref = %d, "
- "lipstring = %s lport = %d, "
- "fipstring = %s fport = %d, "
- "flags = %s\n", intref, lipstring, lport,
- fipstring, fport, flags));
- connectsock = do_connect(lipstring, lport,
- fipstring, fport);
- if(connectsock == INVALID_FD) {
- reply(ESOCK_CONNECT_SYNC_ERR, "4s", intref, psx_errstr());
- break;
- }
- DEBUGF((" fd = %d\n", connectsock));
- cp = new_connection(ESOCK_WAIT_CONNECT, connectsock);
- cp->origin = ORIG_CONNECT;
- length = strlen(flags);
- cp->flags = esock_malloc(length + 1);
- strcpy(cp->flags, flags);
- DEBUGF(("-> WAIT_CONNECT fd = %d\n", connectsock));
- /* Publish connectsock */
- reply(ESOCK_CONNECT_WAIT_REP, "44", intref, connectsock);
- break;
-
- case ESOCK_TERMINATE_CMD:
- /*
- * ebuf = {cmd(1)}
- */
- exit(EXIT_SUCCESS);
- break;
-
- case ESOCK_CLOSE_CMD:
- /*
- * ebuf = {cmd(1), fd(4)}
- */
- input("4", &fd);
- if ((cp = get_connection(fd))) {
- DEBUGF(("%s[CLOSE_CMD]: fd = %d\n",
- connstr[cp->state], fd));
- if (cp->proxy)
- cp->proxy->bp = 1;
- switch (cp->state) {
- case ESOCK_JOINED:
- cp->close = 1;
- if (JOINED_STATE_INVALID(cp))
- leave_joined_state(cp);
- break;
- case ESOCK_SSL_SHUTDOWN:
- cp->close = 1;
- DEBUGF((" close flag set\n"));
- break;
- default:
- DEBUGF(("-> (removal)\n"));
- close_and_remove_connection(cp);
- }
- } else
- DEBUGF(("[CLOSE_CMD]: ERROR: fd = %d not found\n", fd));
- break;
-
- case ESOCK_SET_SOCKOPT_CMD:
- /*
- * ebuf = {cmd(1), fd(4), op(1), on(1)}
- */
- input("411", &fd, &op, &value);
- switch(op) {
- case ESOCK_SET_TCP_NODELAY:
- if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
- (void *)&value, sizeof(value)) < 0) {
- DEBUGF(("Error: setsockopt TCP_NODELAY\n"));
- reply(ESOCK_IOCTL_ERR, "4s", fd, psx_errstr());
- } else {
- reply(ESOCK_IOCTL_OK, "4", fd);
- }
- break;
- default:
- DEBUGF(("Error: set_sock_opt - Not implemented\n"));
- sock_set_errno(ERRNO_OPNOTSUPP);
- reply(ESOCK_IOCTL_ERR, "4", fd, psx_errstr());
- break;
- }
- break;
-
- case ESOCK_LISTEN_CMD:
- /*
- * ebuf = {cmd(1), intref(4), lport(2), ipstring(N), 0(1),
- * backlog(2), flags(N), 0(1)}
- */
- input("42s2s", &intref, &lport, &lipstring, &backlog,
- &flags);
- DEBUGF(("[LISTEN_CMD] intref = %d, port = %d, "
- "ipstring = %s, backlog = %d, flags = %s\n",
- intref, lport, lipstring, backlog, flags));
-
- listensock = do_listen(lipstring, lport, backlog, &lport);
- if(listensock == INVALID_FD) {
- reply(ESOCK_LISTEN_SYNC_ERR, "4s", intref, psx_errstr());
- break;
- }
- cp = new_connection(ESOCK_PASSIVE_LISTENING, listensock);
- /* Flags may be an empty string */
- length = strlen(flags);
- cp->flags = esock_malloc(length + 1);
- strcpy(cp->flags, flags);
-
- cp->origin = ORIG_LISTEN;
- if (esock_ssl_listen_init(cp) < 0) {
- DEBUGF(("esock_ssl_listen_init() failed.\n"));
- reply(ESOCK_LISTEN_SYNC_ERR, "4s", intref,
- ssl_errstr());
- close_and_remove_connection(cp);
- break;
- }
- DEBUGF(("-> PASSIVE_LISTENING (fd = %d)\n", listensock));
- /* Publish listensock */
- reply(ESOCK_LISTEN_REP, "442", intref, listensock,
- ntohs(iserv_addr.sin_port));
- break;
-
- case ESOCK_TRANSPORT_ACCEPT_CMD:
- /*
- * ebuf = { op(1), fd(4), flags(N), 0(1)}
- */
- input("4s", &fd, &flags);
- DEBUGF(("[TRANSPORT_ACCEPT_CMD] listenfd = %d, flags = %s\n", fd,
- flags));
- cp = get_connection(fd);
- if (cp) {
- /* We store the flags in the listen socket's
- * connection, and overwrite previous flags.
- */
- if ((length = strlen(flags)) > 0) {
- if (cp->flags)
- cp->flags = esock_realloc(cp->flags,
- length + 1);
- else
- cp->flags = esock_malloc(length + 1);
- strcpy(cp->flags, flags);
- }
- if (cp->flags && cp->flags[0] != '\0') {
- cp->acceptors++;
- cp->state = ESOCK_ACTIVE_LISTENING;
- DEBUGF(("-> ACTIVE_LISTENING\n"));
- break;
- }
- DEBUGF(("ERROR: flags empty\n"));
- }
- reply(ESOCK_TRANSPORT_ACCEPT_ERR, "4s", fd, "ebadf");
- break;
-
- case ESOCK_SSL_ACCEPT_CMD:
- input("4s", &fd, &flags);
- DEBUGF(("[SSL_ACCEPT_CMD] fd = %d, flags = %s\n", fd, flags));
- cp = get_connection(fd);
- if (cp)
- cp->state = ESOCK_SSL_ACCEPT;
- //reply(ESOCK_SSL_ACCEPT_REP, "4", fd);
- break;
-
- case ESOCK_NOACCEPT_CMD:
- /*
- * ebuf = {cmd(1), fd(4)}
- */
- input("4", &fd);
- DEBUGF(("[NOACCEPT_CMD] listenfd = %d\n", fd));
- cp = get_connection(fd);
- if (cp && (--cp->acceptors <= 0)) {
- cp->acceptors = 0;
- cp->state = ESOCK_PASSIVE_LISTENING;
- esock_poll_clear_event(&pollfd, fd);
- DEBUGF(("-> PASSIVE_LISTENING\n"));
- }
- break;
-
- case ESOCK_PROXY_JOIN_CMD:
- /*
- * ebuf = {cmd(1), fd(4), portnum(2)}
- *
- * fd - file descriptor of a connection in state
- * CONNECTED
- * portnum - port number of the Erlang proxy peer
- */
- input("42", &fd, &pport);
- cp = get_connection(fd);
- pp = get_proxy_by_peerport(pport);
- if (cp && cp->state == ESOCK_CONNECTED && pp) {
- DEBUGF(("CONNECTED[PROXY_JOIN_CMD] fd = %d "
- "portnum = %d\n", fd, pport));
- cp->proxy = pp;
- pp->conn = cp;
- reply(ESOCK_PROXY_JOIN_REP, "4", fd);
- cp->state = ESOCK_JOINED;
- DEBUGF(("-> JOINED\n"));
- break;
- }
- if (!cp) {
- DEBUGF(("[PROXY_JOIN_CMD] ERROR: No connection "
- "having fd = %d\n", fd));
- reply(ESOCK_PROXY_JOIN_ERR, "4s", fd, "ebadsocket");
- } else if (cp->state != ESOCK_CONNECTED) {
- DEBUGF(("%s[PROXY_JOIN_CMD] ERROR: Bad state: "
- "fd = %d\n", connstr[cp->state], cp->fd));
- reply(ESOCK_PROXY_JOIN_ERR, "4s", fd, "ebadstate");
- } else {
- DEBUGF(("ERROR: No proxy: fd = %d, pport = %d\n",
- fd, pport));
- if (proxysock_err_cnt > 0) {
- proxysock_err_cnt--;
- reply(ESOCK_PROXY_JOIN_ERR, "4s", fd,
- esock_posix_str(proxysock_last_err));
- } else {
- reply(ESOCK_PROXY_JOIN_ERR, "4s", fd,
- "enoproxysocket");
- }
- cp->state = ESOCK_DEFUNCT;
- }
- break;
-
- case ESOCK_DUMP_STATE_CMD:
- dump_connections();
- break;
-
- case ESOCK_SET_DEBUG_CMD:
- /*
- * ebuf = {cmd(1), debug(1)}
- */
- input("1", &debug);
- break;
-
- case ESOCK_SET_DEBUGMSG_CMD:
- /*
- * ebuf = {cmd(1), debugmsg(1)}
- */
- input("1", &debugmsg);
- break;
-
- default:
- fprintf(stderr, "esock: default value in loop %c\n",
- *ebuf);
- exit(EXIT_FAILURE);
- break;
- }
- }
- }
-
- /* Go through all connections that have their file descriptors
- set. */
-
- /* Note: We may remove the current connection (cp). Thus we
- * must be careful not to read cp->next after cp has been
- * removed. */
- for (cp = next_polled_conn(connections, &cpnext, &pollfd, set_wq_fds);
- cp != NULL;
- cp = next_polled_conn(cpnext, &cpnext, &pollfd, set_wq_fds)
- ) {
-
- switch(cp->state) {
-
- case ESOCK_PASSIVE_LISTENING:
- DEBUGF(("-----------------------------------\n"));
- fprintf(stderr, "esock: Got connect request while PASSIVE\n");
- exit(EXIT_FAILURE);
- break;
-
- case ESOCK_ACTIVE_LISTENING:
- /* new connect from network */
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("ACTIVE_LISTENING - trying to accept on %d\n",
- cp->fd));
- length = sizeof(iserv_addr);
- msgsock = do_accept(cp->fd, (struct sockaddr*)&iserv_addr,
- (int*)&length);
- if(msgsock == INVALID_FD) {
- DEBUGF(("accept error: %s\n", psx_errstr()));
- reply(ESOCK_TRANSPORT_ACCEPT_ERR, "4s", cp->fd, psx_errstr());
- break;
- }
- SET_NONBLOCKING(msgsock);
- if (--cp->acceptors <= 0) {
- cp->acceptors = 0;
- cp->state = ESOCK_PASSIVE_LISTENING;
- DEBUGF(("-> PASSIVE_LISTENING\n"));
- }
- DEBUGF(("server accepted connection on fd %d\n", msgsock));
- newcp = new_connection(ESOCK_TRANSPORT_ACCEPT, msgsock);
- newcp->origin = ORIG_ACCEPT;
- reply(ESOCK_TRANSPORT_ACCEPT_REP, "44", cp->fd, msgsock);
- newcp->listen_fd = cp->fd; /* Needed for ESOCK_ACCEPT_ERR */
- length = strlen(cp->flags);
- /* XXX new flags are not needed */
- newcp->flags = esock_malloc(length + 1);
- strcpy(newcp->flags, cp->flags); /* XXX Why? */
- if (esock_ssl_accept_init(newcp, cp->opaque) < 0) {
- cp->errstr = ssl_errstr();
- break;
- }
- newcp->ssl_want = ESOCK_SSL_WANT_READ;
- break;
-
- case ESOCK_SSL_ACCEPT:
- /* SSL accept handshake. msgsock is *not* published yet. */
- msgsock = cp->fd;
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("SSL_ACCEPT fd = %d\n", msgsock));
- if (cp->errstr != NULL) { /* this means we got an error in ssl_accept_init */
- /* N.B.: The *listen fd* is reported. */
- reply(ESOCK_SSL_ACCEPT_ERR, "4s", msgsock, cp->errstr);
- close_and_remove_connection(cp);
- break;
- }
- if (esock_ssl_accept(cp) < 0) {
- if (sock_errno() != ERRNO_BLOCK) {
- /* Handshake failed. */
- reply(ESOCK_SSL_ACCEPT_ERR, "4s", msgsock,
- ssl_errstr());
- DEBUGF(("ERROR: handshake: %s\n", ssl_errstr()));
- close_and_remove_connection(cp);
- }
- } else {
- /* SSL handshake successful: publish */
- reply(ESOCK_SSL_ACCEPT_REP, "4", msgsock);
- DEBUGF(("-> CONNECTED\n"));
- DEBUGF((" Session was %sreused.\n",
- (esock_ssl_session_reused(cp)) ? "" : "NOT "));
- cp->state = ESOCK_CONNECTED;
- }
- break;
-
- case ESOCK_CONNECTED:
- /* Should not happen. We do not read or write until
- the connection is in state JOINED. */
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("CONNECTED: Error: should not happen. fd = %d\n",
- cp->fd));
- break;
-
- case ESOCK_JOINED:
- /*
- * Reading from Proxy, writing to SSL
- */
- if (esock_poll_fd_isset_write(&pollfd, cp->fd)) {
- /* If there is a write queue, write to ssl only */
- if (cp->wq.len > 0) {
- /* The write retry semantics of SSL_write in
- * the OpenSSL package is strange. Partial
- * writes never occur, only complete writes or
- * failures. A failure, however, still
- * consumes all data written, although not all
- * encrypted data could be written to the
- * underlying socket. To retry a write we have
- * to provide the same buf and length as in
- * the original call, in our case rwbuf and
- * the original buffer length. Hence the
- * strange memcpy(). Note that wq.offset will
- * always be zero when we use OpenSSL.
- */
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("JOINED: writing to ssl "
- "fd = %d, from write queue only, wc = %d\n",
- cp->fd, cp->wq.len - cp->wq.offset));
- memcpy(rwbuf, cp->wq.buf, cp->wq.len - cp->wq.offset);
-
- /* esock_ssl_write sets cp->eof, cp->bp when return
- * value is zero */
- wc = esock_ssl_write(cp, rwbuf,
- cp->wq.len - cp->wq.offset);
- if (wc < 0) {
- if (sock_errno() != ERRNO_BLOCK) {
- /* Assume broken SSL pipe */
- DEBUGF(("broken SSL pipe\n"));
- cp->bp = 1;
- shutdown(cp->proxy->fd, SHUTDOWN_READ);
- cp->proxy->eof = 1;
- if (JOINED_STATE_INVALID(cp)) {
- leave_joined_state(cp);
- break;
- }
- }
- } else if (wc == 0) {
- /* SSL broken pipe */
- DEBUGF(("broken SSL pipe\n"));
- cp->bp = 1;
- shutdown(cp->proxy->fd, SHUTDOWN_READ);
- cp->proxy->eof = 1;
- if (JOINED_STATE_INVALID(cp)) {
- leave_joined_state(cp);
- break;
- }
- } else {
- cp->wq.offset += wc;
- if (cp->wq.offset == cp->wq.len)
- cp->wq.len = 0;
- }
- }
- } else if (esock_poll_fd_isset_read(&pollfd, cp->proxy->fd)) {
- /* Read from proxy and write to SSL */
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("JOINED: reading from proxy, "
- "proxyfd = %d\n", cp->proxy->fd));
- cc = sock_read(cp->proxy->fd, rwbuf, RWBUFLEN);
- DEBUGF(("read from proxyfd = %d, cc = %d\n",
- cp->proxy->fd, cc));
- if (cc > 0) {
- /* esock_ssl_write sets cp->eof, cp->bp when return
- * value is zero */
- wc = esock_ssl_write(cp, rwbuf, cc);
- if (wc < 0) {
- if (sock_errno() != ERRNO_BLOCK) {
- /* Assume broken pipe */
- DEBUGF(("broken SSL pipe\n"));
- cp->bp = 1;
- shutdown(cp->proxy->fd, SHUTDOWN_READ);
- cp->proxy->eof = 1;
- if (JOINED_STATE_INVALID(cp)) {
- leave_joined_state(cp);
- break;
- }
- } else {
- /* add to write queue */
- DEBUGF(("adding all to write queue "
- "%d bytes\n", cc));
- ensure_write_queue(&cp->wq, cc);
- memcpy(cp->wq.buf, rwbuf, cc);
- cp->wq.len = cc;
- cp->wq.offset = 0;
- }
- } else if (wc == 0) {
- /* Broken SSL pipe */
- DEBUGF(("broken SSL pipe\n"));
- cp->bp = 1;
- shutdown(cp->proxy->fd, SHUTDOWN_READ);
- cp->proxy->eof = 1;
- if (JOINED_STATE_INVALID(cp)) {
- leave_joined_state(cp);
- break;
- }
- } else if (wc < cc) {
- /* add remainder to write queue */
- DEBUGF(("adding remainder to write queue "
- "%d bytes\n", cc - wc));
- ensure_write_queue(&cp->wq, cc - wc);
- memcpy(cp->wq.buf, rwbuf + wc, cc - wc);
- cp->wq.len = cc - wc;
- cp->wq.offset = 0;
- }
- } else {
- /* EOF proxy or error */
- DEBUGF(("proxy eof or error %d\n", errno));
- cp->proxy->eof = 1;
- if (cp->wq.len == 0) {
- esock_ssl_shutdown(cp);
- cp->bp = 1;
- }
- if (JOINED_STATE_INVALID(cp)) {
- leave_joined_state(cp);
- break;
- }
- }
- }
- /*
- * Reading from SSL, writing to proxy
- */
- if (esock_poll_fd_isset_write(&pollfd, cp->proxy->fd)) {
- /* If there is a write queue, write to proxy only */
- if (cp->proxy->wq.len > 0) {
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("JOINED: writing to proxyfd = %d, "
- "from write queue only, wc = %d\n",
- cp->proxy->fd, cp->proxy->wq.len -
- cp->proxy->wq.offset));
- wc = sock_write(cp->proxy->fd, cp->proxy->wq.buf +
- cp->proxy->wq.offset,
- cp->proxy->wq.len -
- cp->proxy->wq.offset);
- if (wc < 0) {
- if (sock_errno() != ERRNO_BLOCK) {
- /* Assume broken pipe */
- DEBUGF(("broken proxy pipe\n"));
- cp->proxy->bp = 1;
- /* There is no SSL shutdown for read */
- cp->eof = 1;
- if (JOINED_STATE_INVALID(cp)) {
- leave_joined_state(cp);
- break;
- }
- }
- } else {
- cp->proxy->wq.offset += wc;
- if (cp->proxy->wq.offset == cp->proxy->wq.len)
- cp->proxy->wq.len = 0;
- }
- }
- } else if (esock_poll_fd_isset_read(&pollfd, cp->fd)) {
- /* Read from SSL and write to proxy */
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("JOINED: read from ssl fd = %d\n",
- cp->fd));
- cc = esock_ssl_read(cp, rwbuf, RWBUFLEN);
- DEBUGF(("read from fd = %d, cc = %d\n", cp->fd, cc));
- if (cc > 0) {
- wc = sock_write(cp->proxy->fd, rwbuf, cc);
- if (wc < 0) {
- if (sock_errno() != ERRNO_BLOCK) {
- DEBUGF(("broken proxy pipe\n"));
- /* Assume broken pipe */
- cp->proxy->bp = 1;
- /* There is no SSL shutdown for read */
- cp->eof = 1;
- if (JOINED_STATE_INVALID(cp)) {
- leave_joined_state(cp);
- break;
- }
- } else {
- /* add all to write queue */
- DEBUGF(("adding to write queue %d bytes\n",
- cc));
- ensure_write_queue(&cp->proxy->wq, cc);
- memcpy(cp->proxy->wq.buf, rwbuf, cc);
- cp->proxy->wq.len = cc;
- cp->proxy->wq.offset = 0;
- }
- } else if (wc < cc) {
- /* add to write queue */
- DEBUGF(("adding to write queue %d bytes\n",
- cc - wc));
- ensure_write_queue(&cp->proxy->wq, cc - wc);
- memcpy(cp->proxy->wq.buf, rwbuf + wc, cc - wc);
- cp->proxy->wq.len = cc - wc;
- cp->proxy->wq.offset = 0;
- }
- } else if (cc == 0) {
- /* SSL eof */
- DEBUGF(("SSL eof\n"));
- cp->eof = 1;
- if (cp->proxy->wq.len == 0) {
- shutdown(cp->proxy->fd, SHUTDOWN_WRITE);
- cp->proxy->bp = 1;
- }
- if (JOINED_STATE_INVALID(cp)) {
- leave_joined_state(cp);
- break;
- }
- } else {
- /* This may very well happen when reading from SSL. */
- DEBUGF(("NOTE: readmask set, cc < 0, fd = %d, "
- "is ok\n", cp->fd));
- }
- }
- break;
-
- case ESOCK_SSL_SHUTDOWN:
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("SSL_SHUTDOWN: fd = %d\n", cp->fd));
- do_shutdown(cp);
- break;
-
- case ESOCK_DEFUNCT:
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("DEFUNCT: ERROR: should not happen. fd = %d\n",
- cp->fd));
- break;
-
- case ESOCK_WAIT_CONNECT:
- /* New connection shows up */
- connectsock = cp->fd;/* Is published */
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("WAIT_CONNECT fd = %d\n", connectsock));
-
- /* If the connection did succeed it's possible to
- * fetch the peer name (UNIX); or failure shows in
- * exceptmask (WIN32). Sorry for the mess below, but
- * we have to have balanced paren's in #ifdefs in
- * order not to confuse Emacs' indentation. */
- length = sizeof(iserv_addr);
- if (
-#ifdef __WIN32__
- esock_poll_fd_isset_exception(&pollfd, connectsock)
-#else
- getpeername(connectsock, (struct sockaddr *)&iserv_addr,
- &length) < 0
-#endif
- ) {
- sock_set_errno(ERRNO_CONNREFUSED);
- DEBUGF(("connect error: %s\n", psx_errstr()));
- reply(ESOCK_CONNECT_ERR, "4s", connectsock, psx_errstr());
- cp->state = ESOCK_DEFUNCT;
- break;
- }
- if (esock_ssl_connect_init(cp) < 0) {
- DEBUGF(("esock_ssl_connect_init() failed\n"));
- reply(ESOCK_CONNECT_ERR, "4s", connectsock, ssl_errstr());
- cp->state = ESOCK_DEFUNCT;
- break;
- }
- DEBUGF(("-> SSL_CONNECT\n"));
- cp->state = ESOCK_SSL_CONNECT;
- cp->ssl_want = ESOCK_SSL_WANT_WRITE;
- break;
-
- case ESOCK_SSL_CONNECT:
- /* SSL connect handshake. connectsock is published. */
- connectsock = cp->fd;
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("SSL_CONNECT fd = %d\n", connectsock));
- if (esock_ssl_connect(cp) < 0) {
- if (sock_errno() != ERRNO_BLOCK) {
- /* Handshake failed */
- DEBUGF(("ERROR: handshake: %s\n", ssl_errstr()));
- reply(ESOCK_CONNECT_ERR, "4s", connectsock,
- ssl_errstr());
- cp->state = ESOCK_DEFUNCT;
- }
- } else {
- /* SSL connect handshake successful */
- DEBUGF(("-> CONNECTED\n"));
- reply(ESOCK_CONNECT_REP, "4", connectsock);
- cp->state = ESOCK_CONNECTED;
- }
- break;
-
- default:
- DEBUGF(("ERROR: Connection in unknown state.\n"));
- }
- }
- }
-}
-
-static int set_poll_conns(Connection *cp, EsockPoll *ep, int verbose)
-{
- int i = 0;
-
- if (verbose)
- DEBUGF(("MASKS SET FOR FD: "));
- while (cp) {
- switch (cp->state) {
- case ESOCK_ACTIVE_LISTENING:
- if (verbose)
- DEBUGF(("%d (read) ", cp->fd));
- esock_poll_fd_set_read(ep, cp->fd);
- break;
- case ESOCK_WAIT_CONNECT:
- if (verbose)
- DEBUGF(("%d (write) ", cp->fd));
- esock_poll_fd_set_write(ep, cp->fd);
-#ifdef __WIN32__
- esock_poll_fd_set_exception(ep, cp->fd); /* Failure shows in exceptions */
-#endif
- break;
- case ESOCK_SSL_CONNECT:
- case ESOCK_SSL_ACCEPT:
- if (cp->ssl_want == ESOCK_SSL_WANT_READ) {
- if (verbose)
- DEBUGF(("%d (read) ", cp->fd));
- esock_poll_fd_set_read(ep, cp->fd);
- } else if (cp->ssl_want == ESOCK_SSL_WANT_WRITE) {
- if (verbose)
- DEBUGF(("%d (write) ", cp->fd));
- esock_poll_fd_set_write(ep, cp->fd);
- }
- break;
- case ESOCK_JOINED:
- if (!cp->bp) {
- if (cp->wq.len) {
- if (verbose)
- DEBUGF(("%d (write) ", cp->fd));
- esock_poll_fd_set_write(ep, cp->fd);
- } else if (!cp->proxy->eof) {
- if (verbose)
- DEBUGF(("%d (read) ", cp->proxy->fd));
- esock_poll_fd_set_read(ep, cp->proxy->fd);
- }
- }
- if (!cp->proxy->bp) {
- if (cp->proxy->wq.len) {
- if (verbose)
- DEBUGF(("%d (write) ", cp->proxy->fd));
- esock_poll_fd_set_write(ep, cp->proxy->fd);
- } else if (!cp->eof) {
- if (verbose)
- DEBUGF(("%d (read) ", cp->fd));
- esock_poll_fd_set_read(ep, cp->fd);
- }
- }
- break;
- case ESOCK_SSL_SHUTDOWN:
- if (cp->ssl_want == ESOCK_SSL_WANT_READ) {
- if (verbose)
- DEBUGF(("%d (read) ", cp->fd));
- esock_poll_fd_set_read(ep, cp->fd);
- } else if (cp->ssl_want == ESOCK_SSL_WANT_WRITE) {
- if (verbose)
- DEBUGF(("%d (write) ", cp->fd));
- esock_poll_fd_set_write(ep, cp->fd);
- }
- break;
- default:
- break;
- }
- i++;
- cp = cp->next;
- }
- if (verbose)
- DEBUGF(("\n"));
- return i;
-}
-
-
-static Connection *next_polled_conn(Connection *cp, Connection **cpnext,
- EsockPoll *ep, int set_wq_fds)
-{
- while(cp) {
- if (esock_poll_fd_isset_read(ep, cp->fd) ||
- (cp->proxy && esock_poll_fd_isset_read(ep, cp->proxy->fd)) ||
- (esock_poll_fd_isset_write(ep, cp->fd)) ||
- (cp->proxy && esock_poll_fd_isset_write(ep, cp->proxy->fd))
-#ifdef __WIN32__
- || esock_poll_fd_isset_exception(ep, cp->fd) /* Connect failure in WIN32 */
-#endif
- || (set_wq_fds && (cp->wq.len ||
- (cp->proxy && cp->proxy->wq.len)))
- || cp->errstr != NULL) {
- *cpnext = cp->next;
- return cp;
- }
- cp = cp->next;
- }
- *cpnext = NULL;
- return NULL;
-}
-
-static void leave_joined_state(Connection *cp)
-{
- shutdown(cp->proxy->fd, SHUTDOWN_ALL);
- if (((cp->bp || cp->eof) && cp->clean) ||
- (!cp->bp && !cp->eof)) {
- DEBUGF(("-> SSL_SHUTDOWN\n"));
- cp->state = ESOCK_SSL_SHUTDOWN;
- cp->ssl_want = ESOCK_SSL_WANT_WRITE;
- do_shutdown(cp);
- } else if (cp->close) {
- DEBUGF(("-> (removal)\n"));
- close_and_remove_connection(cp);
- } else {
- DEBUGF(("-> DEFUNCT\n"));
- cp->state = ESOCK_DEFUNCT;
- }
-}
-
-/* We are always in state SHUTDOWN here */
-static void do_shutdown(Connection *cp)
-{
- int ret;
-
- ret = esock_ssl_shutdown(cp);
- if (ret < 0) {
- if (sock_errno() == ERRNO_BLOCK) {
- return;
- } else {
- /* Something is wrong -- close and remove or move to DEFUNCT */
- DEBUGF(("Error in SSL shutdown\n"));
- if (cp->close) {
- DEBUGF(("-> (removal)\n"));
- close_and_remove_connection(cp);
- } else {
- DEBUGF(("-> DEFUNCT\n"));
- cp->state = ESOCK_DEFUNCT;
- }
- }
- } else if (ret == 0) {
- /* `close_notify' has been sent. Wait for reception of
- same. */
- return;
- } else if (ret == 1) {
- /* `close_notify' has been sent, and received. */
- if (cp->close) {
- DEBUGF(("-> (removal)\n"));
- close_and_remove_connection(cp);
- } else {
- DEBUGF(("-> DEFUNCT\n"));
- cp->state = ESOCK_DEFUNCT;
- }
- }
-}
-
-static void close_and_remove_connection(Connection *cp)
-{
- safe_close(cp->fd);
- remove_connection(cp);
-}
-
-static int reply(int cmd, char *fmt, ...)
-{
- static unsigned char replybuf[MAXREPLYBUF];
- unsigned char *buf = replybuf;
- va_list args;
- int len;
-
- va_start(args, fmt);
- len = put_pars(NULL, fmt, args);
- va_end(args);
- len++;
- if (len > sizeof(replybuf))
- buf = esock_malloc(len);
-
- PUT_INT8(cmd, buf);
- va_start(args, fmt);
- (void) put_pars(buf + 1, fmt, args);
- va_end(args);
- write_ctrl(buf, len);
- if (buf != replybuf)
- esock_free(buf);
- return len;
-}
-
-static int input(char *fmt, ...)
-{
- va_list args;
- int len;
-
- va_start(args, fmt);
- len = get_pars(ebuf + 1, fmt, args);
- va_end(args);
- return len + 1;
-}
-
-static int put_pars(unsigned char *buf, char *fmt, va_list args)
-{
- char *s, *str, *bin;
- int val, len, pos = 0;
-
- s = fmt;
- while (*s) {
- switch (*s) {
- case '1':
- val = va_arg(args, int);
- if (buf)
- PUT_INT8(val, buf + pos);
- pos++;
- break;
- case '2':
- val = va_arg(args, int);
- if (buf)
- PUT_INT16(val, buf + pos);
- pos += 2;
- break;
- case '4':
- val = va_arg(args, int);
- if (buf)
- PUT_INT32(val, buf + pos);
- pos += 4;
- break;
- case 's': /* string */
- str = va_arg(args, char *);
- if (buf)
- strcpy((char *)(buf + pos), str);
- pos += strlen(str) + 1;
- break;
- case 'b': /* binary */
- len = va_arg(args, int);
- if (buf)
- PUT_INT32(len, buf + pos);
- pos += 4;
- bin = va_arg(args, char *);
- if (buf)
- memcpy(buf + pos, bin, len);
- pos += len;
- break;
- default:
- fprintf(stderr, "esock: Invalid format character: %c\n", *s);
- exit(EXIT_FAILURE);
- break;
- }
- s++;
- }
- return pos;
-}
-
-
-static int get_pars(unsigned char *buf, char *fmt, va_list args)
-{
- int *ip;
- char *s, **strp, **bin;
- int pos = 0;
-
- s = fmt;
- while (*s) {
- switch (*s) {
- case '1':
- ip = va_arg(args, int *);
- *ip = GET_INT8(buf + pos);
- pos++;
- break;
- case '2':
- ip = va_arg(args, int *);
- *ip = GET_INT16(buf + pos);
- pos += 2;
- break;
- case '4':
- ip = va_arg(args, int *);
- *ip = GET_INT32(buf + pos);
- pos += 4;
- break;
- case 's':
- strp = va_arg(args, char **);
- *strp = (char *)(buf + pos);
- pos += strlen(*strp) + 1;
- break;
- case 'b':
- ip = va_arg(args, int *);
- *ip = GET_INT32(buf + pos);
- pos += 4;
- bin = va_arg(args, char **);
- *bin = (char *)(buf + pos);
- pos += *ip;
- break;
- default:
- fprintf(stderr, "esock: Invalid format character: %c\n", *s);
- exit(EXIT_FAILURE);
- break;
- }
- s++;
- }
- return pos;
-}
-
-static FD do_connect(char *lipstring, int lport, char *fipstring, int fport)
-{
- struct sockaddr_in sock_addr;
- long inaddr;
- FD fd;
-
- if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_FD) {
- DEBUGF(("Error calling socket()\n"));
- return fd;
- }
- if (check_num_sock_fds(fd) < 0)
- return INVALID_FD;
- DEBUGF((" fd = %d\n", fd));
-
- /* local */
- if ((inaddr = inet_addr(lipstring)) == INADDR_NONE) {
- DEBUGF(("Error in inet_addr(): lipstring = %s\n", lipstring));
- safe_close(fd);
- sock_set_errno(ERRNO_ADDRNOTAVAIL);
- return INVALID_FD;
- }
- memset(&sock_addr, 0, sizeof(sock_addr));
- sock_addr.sin_family = AF_INET;
- sock_addr.sin_addr.s_addr = inaddr;
- sock_addr.sin_port = htons(lport);
- if(bind(fd, (struct sockaddr*) &sock_addr, sizeof(sock_addr)) < 0) {
- DEBUGF(("Error in bind()\n"));
- safe_close(fd);
- /* XXX Set error code for bind error */
- return INVALID_FD;
- }
-
- /* foreign */
- if ((inaddr = inet_addr(fipstring)) == INADDR_NONE) {
- DEBUGF(("Error in inet_addr(): fipstring = %s\n", fipstring));
- safe_close(fd);
- sock_set_errno(ERRNO_ADDRNOTAVAIL);
- return INVALID_FD;
- }
- memset(&sock_addr, 0, sizeof(sock_addr));
- sock_addr.sin_family = AF_INET;
- sock_addr.sin_addr.s_addr = inaddr;
- sock_addr.sin_port = htons(fport);
-
- SET_NONBLOCKING(fd);
-
- if(connect(fd, (struct sockaddr*)&sock_addr, sizeof(sock_addr)) < 0) {
- if (sock_errno() != ERRNO_PROGRESS && /* UNIX */
- sock_errno() != ERRNO_BLOCK) { /* WIN32 */
- DEBUGF(("Error in connect()\n"));
- safe_close(fd);
- return INVALID_FD;
- }
- }
- return fd;
-}
-
-static FD do_listen(char *ipstring, int lport, int backlog, int *aport)
-{
- static int one = 1; /* Type must be int, not long */
- struct sockaddr_in sock_addr;
- long inaddr;
- int length;
- FD fd;
-
- if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_FD) {
- DEBUGF(("Error calling socket()\n"));
- return fd;
- }
- if (check_num_sock_fds(fd) < 0)
- return INVALID_FD;
- DEBUGF((" fd = %d\n", fd));
- if ((inaddr = inet_addr(ipstring)) == INADDR_NONE) {
- DEBUGF(("Error in inet_addr(): ipstring = %s\n", ipstring));
- safe_close(fd);
- sock_set_errno(ERRNO_ADDRNOTAVAIL);
- return INVALID_FD;
- }
- memset(&sock_addr, 0, sizeof(sock_addr));
- sock_addr.sin_family = AF_INET;
- sock_addr.sin_addr.s_addr = inaddr;
- sock_addr.sin_port = htons(lport);
-
- setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one));
-
- if(bind(fd, (struct sockaddr*) &sock_addr, sizeof(sock_addr)) < 0) {
- DEBUGF(("Error in bind()\n"));
- safe_close(fd);
- return INVALID_FD;
- }
- if (listen(fd, backlog) < 0) {
- DEBUGF(("Error in listen()\n"));
- safe_close(fd);
- return INVALID_FD;
- }
- /* find out assigned local port number */
- length = sizeof(sock_addr);
- if (getsockname(fd, (struct sockaddr *)&sock_addr, &length) < 0) {
- DEBUGF(("Error in getsockname()\n"));
- safe_close(fd);
- return INVALID_FD;
- }
- if (aport)
- *aport = ntohs(sock_addr.sin_port);
- return fd;
-}
-
-static FD do_accept(FD listensock, struct sockaddr *saddr, int *len)
-{
- FD fd;
-
- if ((fd = accept(listensock, saddr, len)) == INVALID_FD) {
- DEBUGF(("Error calling accept()\n"));
- return fd;
- }
- if (check_num_sock_fds(fd) < 0)
- return INVALID_FD;
- return fd;
-}
-
-static Connection *new_connection(int state, FD fd)
-{
- Connection *cp;
-
- if (!(cp = esock_malloc(sizeof(Connection))))
- return NULL;
- cp->state = state;
- cp->acceptors = 0;
- cp->fd = fd;
- cp->listen_fd = INVALID_FD;
- cp->proxy = NULL;
- cp->opaque = NULL;
- cp->ssl_want = 0;
- cp->eof = 0;
- cp->bp = 0;
- cp->clean = 0; /* XXX Used? */
- cp->close = 0;
- cp->origin = -1;
- cp->flags = NULL;
- cp->logfp = NULL;
- cp->wq.size = 0;
- cp->wq.buf = NULL;
- cp->wq.len = 0;
- cp->wq.offset = 0;
- cp->next = connections;
- cp->errstr = NULL;
- connections = cp;
- return cp;
-}
-
-
-static void print_connections(void)
-{
- if (debug) {
- Connection *cp = connections;
- DEBUGF(("CONNECTIONS:\n"));
- while (cp) {
- if (cp->state == ESOCK_JOINED) {
- DEBUGF((" - %s [%8p] (origin = %s)\n"
- " (fd = %d, eof = %d, wq = %d, bp = %d)\n"
- " (proxyfd = %d, eof = %d, wq = %d, bp = %d)\n",
- connstr[cp->state], cp, originstr[cp->origin],
- cp->fd, cp->eof, cp->wq.len, cp->bp,
- cp->proxy->fd, cp->proxy->eof, cp->proxy->wq.len,
- cp->proxy->bp));
- } else if (cp->state == ESOCK_ACTIVE_LISTENING) {
- DEBUGF((" - %s [%8p] (fd = %d, acceptors = %d)\n",
- connstr[cp->state], cp, cp->fd, cp->acceptors));
- } else {
- DEBUGF((" - %s [%8p] (fd = %d)\n", connstr[cp->state], cp,
- cp->fd));
- }
- cp= cp->next;
- }
- }
-}
-
-static void dump_connections(void)
-{
- Connection *cp = connections;
- Proxy *pp = proxies;
- time_t t = time(NULL);
- int length = 0;
- struct sockaddr_in iserv_addr;
-
- __debugprintf("CONNECTIONS %s", ctime(&t));
- while (cp) {
- if (cp->state == ESOCK_JOINED) {
- __debugprintf(" - %s [%8p] (origin = %s)\n"
- " (fd = %d, eof = %d, wq = %d, bp = %d), close = %d\n"
- " (proxyfd = %d, eof = %d, wq = %d, bp = %d)\n",
- connstr[cp->state], cp, originstr[cp->origin],
- cp->fd, cp->eof, cp->wq.len, cp->bp, cp->close,
- cp->proxy->fd, cp->proxy->eof, cp->proxy->wq.len,
- cp->proxy->bp);
- } else if (cp->state == ESOCK_ACTIVE_LISTENING) {
- __debugprintf(" - %s [%8p] (fd = %d, acceptors = %d)\n",
- connstr[cp->state], cp, cp->fd, cp->acceptors);
- } else {
- __debugprintf(" - %s [%8p] (fd = %d)\n", connstr[cp->state], cp,
- cp->fd);
- }
- length = sizeof(iserv_addr);
- if ((cp->state == ESOCK_ACTIVE_LISTENING) ||
- (cp->state == ESOCK_PASSIVE_LISTENING)) {
- getsockname(cp->fd, (struct sockaddr *) &iserv_addr, &length);
- __debugprintf(" (ip = %s, port = %d)\n",
- inet_ntoa(iserv_addr.sin_addr),
- ntohs(iserv_addr.sin_port));
- }
- else {
- getsockname(cp->fd, (struct sockaddr *) &iserv_addr, &length);
- __debugprintf(" (local_ip = %s, local_port = %d)\n",
- inet_ntoa(iserv_addr.sin_addr),
- ntohs(iserv_addr.sin_port));
- length = sizeof(iserv_addr);
- getpeername(cp->fd, (struct sockaddr *) &iserv_addr, &length);
- __debugprintf(" (remote_ip = %s, remote_port = %d)\n",
- inet_ntoa(iserv_addr.sin_addr),
- ntohs(iserv_addr.sin_port));
- }
- cp=cp->next;
- }
-
- __debugprintf("PROXIES\n");
- while (pp) {
- __debugprintf(" - fd = %d [%8p] (external_fd = %d, peer_port = %d,"
- " eof = %d)\n", pp->fd, pp, pp->conn->fd, pp->peer_port,
- pp->eof);
-
- pp= pp->next;
- }
-}
-
-static Connection *get_connection(FD fd)
-{
- Connection *cp = connections;
-
- while(cp) {
- if(cp->fd == fd)
- return cp;
- cp = cp->next;
- }
- return NULL;
-}
-
-/*
- * Remove a connection from the list of connection, close the proxy
- * socket and free all resources. The main socket (fd) is *not*
- * closed here, because the closing of that socket has to be synchronized
- * with the Erlang process controlling this port program.
- */
-static void remove_connection(Connection *conn)
-{
- Connection **prev = &connections;
- Connection *cp = connections;
-
- while (cp) {
- if(cp == conn) {
- DEBUGF(("remove_connection: fd = %d\n", cp->fd));
- esock_ssl_free(cp); /* frees cp->opaque only */
- esock_free(cp->flags);
- closelog(cp->logfp); /* XXX num_sock_fds */
- esock_free(cp->wq.buf);
- if (cp->proxy) {
- safe_close(cp->proxy->fd);
- remove_proxy(cp->proxy);
- }
- *prev = cp->next;
- esock_free(cp);
- return;
- }
- prev = &cp->next;
- cp = cp->next;
- }
-}
-
-static Proxy *get_proxy_by_peerport(int port)
-{
- Proxy *p = proxies;
-
- while(p) {
- if (p->peer_port == port)
- return p;
- p = p->next;
- }
- return NULL;
-}
-
-static Proxy *new_proxy(FD fd)
-{
- Proxy *p;
-
- if (!(p = esock_malloc(sizeof(Proxy))))
- return NULL;
-
- p->fd = fd;
- p->peer_port = -1;
- p->eof = 0;
- p->bp = 0;
- p->conn = NULL;
- p->wq.size = 0;
- p->wq.buf = NULL;
- p->wq.len = 0;
- p->wq.offset = 0;
- p->next = proxies;
- proxies = p;
- return p;
-}
-
-static void remove_proxy(Proxy *proxy)
-{
- Proxy *p = proxies, **pp = &proxies;
-
- while(p) {
- if (p == proxy) {
- DEBUGF(("remove_proxyfd = %d\n", p->fd));
- esock_free(p->wq.buf);
- *pp = p->next;
- esock_free(p);
- return;
- }
- pp = &p->next;
- p = p->next;
- }
-}
-
-static int check_num_sock_fds(FD fd)
-{
- num_sock_fds++; /* fd is valid */
-#ifdef USE_SELECT
- if (num_sock_fds > FD_SETSIZE) {
- num_sock_fds--;
- sock_set_errno(ERRNO_MFILE);
- safe_close(fd);
- return -1;
- }
-#endif
- return 0;
-}
-
-static void safe_close(FD fd)
-{
- int err;
-
- err = sock_errno();
- DEBUGF(("safe_close fd = %d\n", fd));
- if (sock_close(fd) < 0) {
- DEBUGF(("safe_close failed\n"));
- } else {
- num_sock_fds--;
- }
- sock_set_errno(err);
-}
-
-static void clean_up(void)
-{
- Connection *cp, *cpnext;
- Proxy *pp, *ppnext;
-
- cp = connections;
- while (cp) {
- safe_close(cp->fd);
- cpnext = cp->next;
- remove_connection(cp);
- cp = cpnext;
- }
-
- pp = proxies;
- while (pp) {
- safe_close(pp->fd);
- ppnext = pp->next;
- remove_proxy(pp);
- pp = ppnext;
- }
-}
-
-static void ensure_write_queue(WriteQueue *wq, int size)
-{
- if (wq->size < size) {
- wq->buf = esock_realloc(wq->buf, size);
- wq->size = size;
- }
-}
-
-
-
-
-
-
-
diff --git a/lib/ssl/c_src/esock.h b/lib/ssl/c_src/esock.h
deleted file mode 100644
index 16c9faa530..0000000000
--- a/lib/ssl/c_src/esock.h
+++ /dev/null
@@ -1,273 +0,0 @@
-/*<copyright>
- * <year>1999-2008</year>
- * <holder>Ericsson AB, All Rights Reserved</holder>
- *</copyright>
- *<legalnotice>
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * The Initial Developer of the Original Code is Ericsson AB.
- *</legalnotice>
- */
-/*
- * Purpose: Implementation of Secure Socket Layer (SSL).
- *
- */
-
-#ifndef ESOCK_H
-#define ESOCK_H
-
-#ifdef __WIN32__
-#include "esock_winsock.h"
-#endif
-#include <stdio.h>
-
-#ifdef __WIN32__
-#define INVALID_FD INVALID_SOCKET
-
-#define sock_read(fd, buf, len) recv((fd), (buf), (len), 0)
-#define sock_write(fd, buf, len) send((fd), (buf), (len), 0)
-#define sock_close(fd) closesocket(fd)
-#define sock_errno() WSAGetLastError()
-#define sock_set_errno(err) WSASetLastError(err)
-
-#define ERRNO_NONE 0
-#define ERRNO_BLOCK WSAEWOULDBLOCK
-#define ERRNO_CONNREFUSED WSAECONNREFUSED
-#define ERRNO_PROGRESS WSAEINPROGRESS
-#define ERRNO_PROTONOSUPPORT WSAEPROTONOSUPPORT
-#define ERRNO_INVAL WSAEINVAL
-#define ERRNO_ADDRNOTAVAIL WSAEADDRNOTAVAIL
-#define ERRNO_NOTSOCK WSAENOTSOCK
-#define ERRNO_OPNOTSUPP WSAEOPNOTSUPP
-#define ERRNO_MFILE WSAEMFILE
-#define SET_BLOCKING(fd) do { \
- unsigned long zeroval = 0; \
- ioctlsocket((fd), FIONBIO, &zeroval); \
- } while (0)
-#define SET_NONBLOCKING(fd) do { \
- unsigned long oneval = 1; \
- ioctlsocket((fd), FIONBIO, &oneval); \
- } while (0)
-#else
-#define INVALID_FD (-1)
-
-#define sock_read(fd, buf, len) read((fd), (buf), (len))
-#define sock_write(fd, buf, len) write((fd), (buf), (len))
-#define sock_close(fd) close(fd)
-#define sock_errno() errno
-#define sock_set_errno(err) do {errno = (err);} while(0)
-
-#define ERRNO_NONE 0
-#define ERRNO_BLOCK EAGAIN
-#define ERRNO_CONNREFUSED ECONNREFUSED
-#define ERRNO_PROGRESS EINPROGRESS
-#define ERRNO_PROTONOSUPPORT EPROTONOSUPPORT
-#define ERRNO_INVAL EINVAL
-#define ERRNO_ADDRNOTAVAIL EADDRNOTAVAIL
-#define ERRNO_NOTSOCK ENOTSOCK
-#define ERRNO_OPNOTSUPP EOPNOTSUPP
-#define ERRNO_MFILE EMFILE
-#define SET_BLOCKING(fd) fcntl((fd), F_SETFL, \
- fcntl((fd), F_GETFL, 0) & ~O_NONBLOCK)
-#define SET_NONBLOCKING(fd) fcntl((fd), F_SETFL, \
- fcntl((fd), F_GETFL, 0) | O_NONBLOCK)
-#endif
-
-#define GET_INT8(s) ((s)[0])
-#define GET_INT16(s) (((s)[0] << 8) | (s)[1])
-#define GET_INT32(s) (((s)[0] << 24) | ((s)[1] << 16) | \
- ((s)[2] << 8) | (s)[3])
-
-#define PUT_INT8(x, s) do { (s)[0] = x; } while(0)
-#define PUT_INT16(x, s) do { (s)[0] = ((x) >> 8) & 0xff; \
- (s)[1] = ((x) & 0xff); } while(0)
-#define PUT_INT32(x, s) do { (s)[0] = ((x) >> 24) & 0xff; \
- (s)[1] = ((x) >> 16) & 0xff; \
- (s)[2] = ((x) >> 8) & 0xff; \
- (s)[3] = (x) & 0xff; } while(0)
-
-/* type for Connections */
-#define ESOCK_STATE_NONE 0
-#define ESOCK_ACTIVE_LISTENING 1
-#define ESOCK_PASSIVE_LISTENING 2
-#define ESOCK_CONNECTED 3
-#define ESOCK_WAIT_CONNECT 4
-#define ESOCK_SSL_CONNECT 5
-#define ESOCK_SSL_ACCEPT 6
-#define ESOCK_TRANSPORT_ACCEPT 7
-#define ESOCK_JOINED 8
-#define ESOCK_SSL_SHUTDOWN 9
-#define ESOCK_DEFUNCT 10
-
-#ifdef __WIN32__
- typedef SOCKET FD;
-#else
- typedef int FD;
-#endif
-
-/* For the shutdown(fd, how) call */
-#ifdef __WIN32__
-#define SHUTDOWN_READ SD_RECEIVE
-#define SHUTDOWN_WRITE SD_SEND
-#define SHUTDOWN_ALL SD_BOTH
-#else
-#define SHUTDOWN_READ 0
-#define SHUTDOWN_WRITE 1
-#define SHUTDOWN_ALL 2
-#endif
-
-#define ORIG_LISTEN 0
-#define ORIG_ACCEPT 1
-#define ORIG_CONNECT 2
-
-typedef struct {
- int size; /* Total size of buf */
- unsigned char *buf;
- int len; /* Current number of bytes in buf */
- int offset; /* Bytes already written */
-} WriteQueue;
-
-typedef struct _proxy Proxy;
-
-typedef struct Connection {
- FD fd;
- FD listen_fd; /* Needed for async listen error */
- unsigned char state;
- int acceptors; /* Count acceptors for listen socket */
- Proxy *proxy;
- void *opaque; /* Any suitable ssl structure */
- int ssl_want; /* read/write flags */
- int eof; /* end of file (read) */
- int bp; /* broken pipe (write) */
- int clean; /* Clean SSL shutdown initiated */
- int close; /* Close if set */
- int origin; /* listen, accept or connect */
- int encrypted; /* 1 = SSL encrypted, 0 = normal, unencrypted tcp */
- char *flags; /* ssl parameters */
- FILE *logfp; /* connection log file (not used) */
- WriteQueue wq;
- struct Connection* next;
- const char* errstr; /* only used to report errors from ssl_accept_init in SSL_ACCEPT */
-} Connection;
-
-struct _proxy {
- FD fd;
- int peer_port;
- int eof; /* end of file (read) */
- int bp; /* broken pipe (write) */
- Connection *conn;
- WriteQueue wq;
- Proxy *next;
-};
-
-/* Commands, replies, and error responses */
-
-#define ESOCK_CONNECT_CMD 1
-#define ESOCK_CONNECT_WAIT_REP 2
-#define ESOCK_CONNECT_REP 3
-#define ESOCK_CONNECT_ERR 4
-
-#define ESOCK_TERMINATE_CMD 5
-#define ESOCK_CLOSE_CMD 6
-
-#define ESOCK_LISTEN_CMD 7
-#define ESOCK_LISTEN_REP 8
-#define ESOCK_LISTEN_ERR 9
-
-#define ESOCK_TRANSPORT_ACCEPT_CMD 10
-#define ESOCK_NOACCEPT_CMD 11
-#define ESOCK_TRANSPORT_ACCEPT_REP 12
-#define ESOCK_TRANSPORT_ACCEPT_ERR 13
-
-#define ESOCK_FROMNET_CLOSE_REP 14
-
-#define ESOCK_CONNECT_SYNC_ERR 15
-#define ESOCK_LISTEN_SYNC_ERR 16
-
-#define ESOCK_PROXY_PORT_REP 23
-#define ESOCK_PROXY_JOIN_CMD 24
-#define ESOCK_PROXY_JOIN_REP 25
-#define ESOCK_PROXY_JOIN_ERR 26
-
-#define ESOCK_SET_SOCKOPT_CMD 27
-#define ESOCK_IOCTL_OK 28
-#define ESOCK_IOCTL_ERR 29
-
-#define ESOCK_GETPEERNAME_CMD 30
-#define ESOCK_GETPEERNAME_REP 31
-#define ESOCK_GETPEERNAME_ERR 32
-
-#define ESOCK_GETSOCKNAME_CMD 33
-#define ESOCK_GETSOCKNAME_REP 34
-#define ESOCK_GETSOCKNAME_ERR 35
-
-#define ESOCK_GETPEERCERT_CMD 36
-#define ESOCK_GETPEERCERT_REP 37
-#define ESOCK_GETPEERCERT_ERR 38
-
-#define ESOCK_GETVERSION_CMD 39
-#define ESOCK_GETVERSION_REP 40
-
-#define ESOCK_SET_SEED_CMD 41
-
-#define ESOCK_GETCONNINFO_CMD 42
-#define ESOCK_GETCONNINFO_REP 43
-#define ESOCK_GETCONNINFO_ERR 44
-
-#define ESOCK_SSL_ACCEPT_CMD 45
-#define ESOCK_SSL_ACCEPT_REP 46
-#define ESOCK_SSL_ACCEPT_ERR 47
-
-#define ESOCK_DUMP_STATE_CMD 48
-#define ESOCK_SET_DEBUG_CMD 49
-#define ESOCK_SET_DEBUGMSG_CMD 50
-
-
-/* Option codes for ESOCK_SET_SOCKOPT_CMD */
-#define ESOCK_SET_TCP_NODELAY 1
-
-/* SSL want to read or write */
-#define ESOCK_SSL_WANT_READ 1
-#define ESOCK_SSL_WANT_WRITE 2
-
-/* Protocol version according to ssl_server */
-#define ESOCK_SSLv2 1
-#define ESOCK_SSLv3 2
-#define ESOCK_TLSv1 4
-
-
-#endif
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/ssl/c_src/esock_openssl.c b/lib/ssl/c_src/esock_openssl.c
deleted file mode 100644
index 2621c9934e..0000000000
--- a/lib/ssl/c_src/esock_openssl.c
+++ /dev/null
@@ -1,1213 +0,0 @@
-/*<copyright>
- * <year>1999-2008</year>
- * <holder>Ericsson AB, All Rights Reserved</holder>
- *</copyright>
- *<legalnotice>
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * The Initial Developer of the Original Code is Ericsson AB.
- *</legalnotice>
- */
-/*
- * Purpose: Adaptions for the OpenSSL package.
- *
- * This file implements the functions defined in esock_ssl.h for
- * the OpenSSL package.
- *
- * The following holds true for non-blockling I/O:
- *
- * Function Return values
- * -------- -------------
- * SSL_accept() success: 1, failure: =<0
- * SSL_connect() success: 1, failure: =<0
- * SSL_read() success: >0, eof: 0, failure: <0
- * SSL_write() success: > 0, failure: =<0
- * SSL_shutdown() success: 1, not finished: 0
- *
- * If the return value of any of the above functions is `ret' and the
- * ssl connection is `ssl', the call
- *
- * ssl_error = SSL_get_error(ssl, ret);
- *
- * returns one of the following eight values:
- *
- * SSL_ERROR_NONE ret > 0
- * SSL_ERROR_ZERO_RETURN ret = 0
- * SSL_ERROR_WANT_READ ret < 0 and ssl wants to read
- * SSL_ERROR_WANT_WRITE ret < 0 and ssl wants to write
- * SSL_ERROR_SYSCALL ret < 0 or ret = 0
- * SSL_ERROR_SSL if there was an ssl internal error
- * SSL_ERROR_WANT_X509_LOOKUP ret < 0 and ssl wants x509 lookup
- * SSL_ERROR_WANT_CONNECT ret < 0 and ssl wants connect
- *
- * It is the case that SSL_read() sometimes returns -1, even when the
- * underlying file descriptor is ready for reading.
- *
- * Also, sometimes we may have SSL_ERROR_SSL in SSL_accept() and SSL_connect()
- * when a retry should be done.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#ifndef __WIN32__
-# include <fcntl.h>
-# include <unistd.h>
-#endif
-
-#include "esock.h"
-#include "esock_ssl.h"
-#include "debuglog.h"
-#include "esock_utils.h"
-#include "esock_posix_str.h"
-
-#include <openssl/crypto.h>
-#include <openssl/ssl.h>
-#include <openssl/err.h>
-#include <openssl/rand.h>
-
-int ephemeral_rsa = 0;
-int ephemeral_dh = 0; /* XXX Not used yet */
-int protocol_version = 0;
-
-char *esock_ssl_errstr = "";
-
-#define FLAGSBUFSIZE 512
-#define X509BUFSIZE 256
-#define DEFAULT_VERIFY_DEPTH 1
-
-#define SET_WANT(cp, ssl_error) \
- switch((ssl_error)) { \
- case SSL_ERROR_WANT_READ: \
- (cp)->ssl_want = ESOCK_SSL_WANT_READ; \
- break; \
- case SSL_ERROR_WANT_WRITE: \
- (cp)->ssl_want = ESOCK_SSL_WANT_WRITE; \
- break; \
- default: \
- (cp)->ssl_want = 0; \
- break; \
- }
-
-#define RESET_ERRSTR() \
- esock_ssl_errstr = "";
-
-#define MAYBE_SET_ERRSTR(s) \
- if (!esock_ssl_errstr[0]) \
- esock_ssl_errstr = (s);
-
-typedef struct {
- int code;
- char *text;
-} err_entry;
-
-typedef struct {
- SSL_CTX *ctx;
- char *passwd;
- int verify_depth;
-} callback_data;
-
-static char *ssl_error_str(int error);
-static void end_ssl_call(int ret, Connection *cp, int ssl_error);
-static void check_shutdown(Connection *cp);
-static int set_ssl_parameters(Connection *cp, SSL_CTX *ctx);
-static int verify_callback(int ok, X509_STORE_CTX *ctx);
-static int passwd_callback(char *buf, int num, int rwflag, void *userdata);
-static void info_callback(const SSL *ssl, int where, int ret);
-static void callback_data_free(void *parent, void *ptr,
- CRYPTO_EX_DATA *ad,
- int idx, long arg1, void *argp);
-static RSA *tmp_rsa_callback(SSL *ssl, int is_export, int keylen);
-static void restrict_protocols(SSL_CTX *ctx);
-
-static err_entry errs[] = {
- {SSL_ERROR_NONE, "SSL_ERROR_NONE"},
- {SSL_ERROR_ZERO_RETURN, "SSL_ERROR_ZERO_RETURN"},
- {SSL_ERROR_WANT_READ, "SSL_ERROR_WANT_READ"},
- {SSL_ERROR_WANT_WRITE, "SSL_ERROR_WANT_WRITE"},
- {SSL_ERROR_SYSCALL, "SSL_ERROR_SYSCALL"},
- {SSL_ERROR_SSL, "SSL_ERROR_SSL"},
- {SSL_ERROR_WANT_X509_LOOKUP, "SSL_ERROR_WANT_X509_LOOKUP"},
- {SSL_ERROR_WANT_CONNECT, "SSL_ERROR_WANT_CONNECT"}
-};
-
-static SSL_METHOD *method; /* for listen and connect init */
-static char x509_buf[X509BUFSIZE]; /* for verify_callback */
-static int callback_data_index = -1; /* for ctx ex_data */
-static unsigned char randvec[1024]; /* XXX */
-
-#if defined(__WIN32__) || OPEN_MAX > 256
-# define FOPEN_WORKAROUND(var, expr) var = (expr)
-# define VOID_FOPEN_WORKAROUND(expr) expr
-#else
-/*
- * This is an ugly workaround. On Solaris, fopen() will return NULL if
- * it gets a file descriptor > 255. To avoid that, we'll make sure that
- * there is always one low-numbered file descriptor available when
- * fopen() is called.
- */
-static int reserved_fd; /* Reserve a low-numbered file descriptor */
-# define USE_FOPEN_WORKAROUND 1
-
-# define FOPEN_WORKAROUND(var, expr) \
-do { \
- close(reserved_fd); \
- var = (expr); \
- reserved_fd = open("/dev/null", O_RDONLY); \
-} while (0)
-
-# define VOID_FOPEN_WORKAROUND(expr) \
-do { \
- close(reserved_fd); \
- expr; \
- reserved_fd = open("/dev/null", O_RDONLY); \
-} while (0)
-#endif
-
-esock_version *esock_ssl_version(void)
-{
- static esock_version vsn;
-
- vsn.compile_version = OPENSSL_VERSION_TEXT;
- vsn.lib_version = SSLeay_version(SSLEAY_VERSION);
- return &vsn;
-}
-
-char *esock_ssl_ciphers(void)
-{
- SSL_CTX *ctx;
- SSL *ssl;
- char *ciphers;
- const char *cp;
- int i = 0, used = 0, len, incr = 1024;
-
- if (!(ctx = SSL_CTX_new(method)))
- return NULL;
- restrict_protocols(ctx);
- if (!(ssl = SSL_new(ctx))) {
- SSL_CTX_free(ctx);
- return NULL;
- }
-
- ciphers = esock_malloc(incr);
- len = incr;
- *ciphers = '\0';
-
- while (1) {
- if (!(cp = SSL_get_cipher_list(ssl, i)))
- break;
- if (i > 0) {
- if (used == len) {
- len += incr;
- ciphers = esock_realloc(ciphers, len);
- }
- strcat(ciphers, ":");
- used++;
- }
- if (strlen(cp) + used >= len) {
- len += incr;
- ciphers = esock_realloc(ciphers, len);
- }
- strcat(ciphers, cp);
- used += strlen(cp);
- i++;
- }
- SSL_free(ssl);
- SSL_CTX_free(ctx);
- return ciphers;
-}
-
-void esock_ssl_seed(void *buf, int len)
-{
- RAND_seed(buf, len);
-
- /* XXX Maybe we should call RAND_status() and check if we have got
- * enough randomness.
- */
-}
-
-int esock_ssl_init(void)
-{
- method = SSLv23_method(); /* SSLv2, SSLv3 and TLSv1, may be restricted
- in listen and connect */
- SSL_load_error_strings();
- SSL_library_init();
- esock_ssl_seed(randvec, sizeof(randvec));
- callback_data_index = SSL_CTX_get_ex_new_index(0, "callback_data",
- NULL, NULL,
- callback_data_free);
-#ifdef USE_FOPEN_WORKAROUND
- reserved_fd = open("/dev/null", O_RDONLY);
- DEBUGF(("init: reserved_fd=%d\r\n", reserved_fd));
-#endif
- return 0;
-}
-
-
-void esock_ssl_finish(void)
-{
- /* Nothing */
-}
-
-
-void esock_ssl_free(Connection *cp)
-{
- SSL *ssl = cp->opaque;
- SSL_CTX *ctx;
-
- if (ssl) {
- ctx = SSL_get_SSL_CTX(ssl);
- SSL_free(ssl);
- if (cp->origin != ORIG_ACCEPT)
- SSL_CTX_free(ctx);
- cp->opaque = NULL;
- }
-}
-
-
-/*
- * Print SSL specific errors.
- */
-void esock_ssl_print_errors_fp(FILE *fp)
-{
- ERR_print_errors_fp(fp);
-}
-
-
-int esock_ssl_accept_init(Connection *cp, void *listenssl)
-{
- SSL_CTX *listenctx;
- SSL *ssl;
-
- RESET_ERRSTR();
- MAYBE_SET_ERRSTR("esslacceptinit");
-
- if(!listenssl) {
- DEBUGF(("esock_ssl_accept_init: listenssl null\n"));
- return -1;
- }
- if (!(listenctx = SSL_get_SSL_CTX(listenssl))) {
- DEBUGF(("esock_ssl_accept_init: SSL_get_SSL_CTX\n"));
- return -1;
- }
- if (!(ssl = cp->opaque = SSL_new(listenctx))) {
- DEBUGF(("esock_ssl_accept_init: SSL_new(listenctx)\n"));
- return -1;
- }
- SSL_set_fd(ssl, cp->fd);
- return 0;
-
-}
-
-
-int esock_ssl_connect_init(Connection *cp)
-{
- SSL_CTX *ctx;
- SSL *ssl;
-
- RESET_ERRSTR();
- MAYBE_SET_ERRSTR("esslconnectinit");
-
- if (!(ctx = SSL_CTX_new(method)))
- return -1;
- if (set_ssl_parameters(cp, ctx) < 0) {
- SSL_CTX_free(ctx);
- return -1;
- }
- restrict_protocols(ctx);
- if (!(ssl = cp->opaque = SSL_new(ctx))) {
- SSL_CTX_free(ctx);
- return -1;
- }
- SSL_set_fd(ssl, cp->fd);
- return 0;
-}
-
-
-int esock_ssl_listen_init(Connection *cp)
-{
- SSL_CTX *ctx;
- SSL *ssl;
-
- RESET_ERRSTR();
- MAYBE_SET_ERRSTR("essllisteninit");
-
- if (!(ctx = SSL_CTX_new(method)))
- return -1;
- if (set_ssl_parameters(cp, ctx) < 0) {
- SSL_CTX_free(ctx);
- return -1;
- }
- restrict_protocols(ctx);
-
- /* The allocation of ctx is for setting ssl parameters, so that
- * accepts can inherit them. We allocate ssl to be able to
- * refer to it via cp->opaque, but will not be used otherwise.
- */
- if (!(ssl = cp->opaque = SSL_new(ctx))) {
- SSL_CTX_free(ctx);
- return -1;
- }
- /* Set callback for temporary ephemeral RSA key generation.
- * Note: for servers only. */
- SSL_CTX_set_tmp_rsa_callback(ctx, tmp_rsa_callback);
- return 0;
-}
-
-/*
- * esock_ssl_accept(Connection *cp)
- *
- */
-int esock_ssl_accept(Connection *cp)
-{
- int ret, ssl_error;
- SSL *ssl = cp->opaque;
-
- RESET_ERRSTR();
-
- DEBUGF(("esock_ssl_accept: calling SSL_accept fd = %d\n"
- " state before: %s\n", cp->fd, SSL_state_string(ssl)));
- ret = SSL_accept(ssl);
- DEBUGF((" sock_errno %d errno %d \n", sock_errno(), errno));
- ssl_error = SSL_get_error(ssl, ret);
- DEBUGF((" SSL_accept = %d\n"
- " ssl_error: %s\n"
- " state after: %s\n",
- ret, ssl_error_str(ssl_error), SSL_state_string(ssl)));
- DEBUGF((" ret %d os error %s\n", ret, strerror(errno)));
- if (ret > 0)
- return ret;
- else if (ret == 0) {
- const char* f; int l; unsigned int e;
- while ((e = ERR_get_error_line(&f, &l))) {
- DEBUGF((" error %s:%d %s\n", f, l, ssl_error_str(e)));
- }
- /* permanent accept error */
- sock_set_errno(ERRNO_NONE);
- MAYBE_SET_ERRSTR("esslaccept");
- return -1;
- }
- end_ssl_call(ret, cp, ssl_error);
- return ret;
-}
-
-/*
- * esock_ssl_connect(Connection *cp)
- *
- */
-int esock_ssl_connect(Connection *cp)
-{
- int ret, ssl_error;
- SSL *ssl = cp->opaque;
-
- RESET_ERRSTR();
-
- DEBUGF(("esock_ssl_connect: calling SSL_connect fd = %d\n"
- " state before: %s\n", cp->fd, SSL_state_string(ssl)));
- ret = SSL_connect(ssl);
- ssl_error = SSL_get_error(ssl, ret);
- DEBUGF((" SSL_connect() = %d\n"
- " ssl_error: %s\n"
- " state after: %s\n",
- ret, ssl_error_str(ssl_error), SSL_state_string(ssl)));
- if (ret > 0)
- return ret;
- else if (ret == 0) {
- /* permanent connect error */
- sock_set_errno(ERRNO_NONE);
- MAYBE_SET_ERRSTR("esslconnect");
- return -1;
- }
- end_ssl_call(ret, cp, ssl_error);
- return ret;
-}
-
-
-int esock_ssl_session_reused(Connection *cp)
-{
- SSL *ssl = cp->opaque;
-
- return SSL_session_reused(ssl);
-}
-
-
-/* esock_ssl_read(Connection *cp, char *buf, int len)
- *
- * Read at most `len' chars into `buf'. Returns number of chars
- * read ( > 0), or 0 at EOF, or -1 on error. Sets cp->eof, cp->bp if
- * appropriate.
- */
-
-int esock_ssl_read(Connection *cp, char *buf, int len)
-{
- int ret, ssl_error;
- SSL *ssl = cp->opaque;
-
- RESET_ERRSTR();
- DEBUGF(("esock_ssl_read: calling SSL_read fd = %d\n"
- " state before: %s\n", cp->fd, SSL_state_string(ssl)));
-
- ret = SSL_read(ssl, buf, len);
- ssl_error = SSL_get_error(ssl, ret);
-
- DEBUGF((" SSL_read = %d\n"
- " ssl_error: %s\n"
- " state after: %s\n",
- ret, ssl_error_str(ssl_error), SSL_state_string(ssl)));
-
- if (ssl_error == SSL_ERROR_NONE) {
- DEBUGMSGF(("message (hex) : [%3.*a]\n", ret, buf));
- DEBUGMSGF(("message (char): [%3.*b]\n", ret, buf));
- }
- if (ret > 0)
- return ret;
- if (ret == 0) {
- check_shutdown(cp);
- return ret;
- }
- end_ssl_call(ret, cp, ssl_error);
- return ret;
-}
-
-/*
- * esock_ssl_write(Connection *cp, char *buf, int len)
- *
- * Writes at most `len' chars from `buf'. Returns number of chars
- * written, or -1 on error.
- */
-int esock_ssl_write(Connection *cp, char *buf, int len)
-{
- int ret, ssl_error;
- SSL *ssl = cp->opaque;
-
- RESET_ERRSTR();
- DEBUGF(("esock_ssl_write: calling SSL_write fd = %d\n"
- " state before: %s\n", cp->fd, SSL_state_string(ssl)));
- ret = SSL_write(ssl, buf, len);
- ssl_error = SSL_get_error(ssl, ret);
- DEBUGF((" SSL_write = %d\n"
- " ssl_error: %s\n"
- " state after: %s\n",
- ret, ssl_error_str(ssl_error), SSL_state_string(ssl)));
- if (ssl_error == SSL_ERROR_NONE) {
- DEBUGMSGF(("message (hex) : [%3.*a]\n", ret, buf));
- DEBUGMSGF(("message (char): [%3.*b]\n", ret, buf));
- }
- if (ret > 0)
- return ret;
- if (ret == 0) {
- check_shutdown(cp);
- return ret;
- }
- end_ssl_call(ret, cp, ssl_error);
- return ret;
-}
-
-
-int esock_ssl_shutdown(Connection *cp)
-{
- int ret, ssl_error;
- SSL *ssl = cp->opaque;
-
- RESET_ERRSTR();
- DEBUGF(("esock_ssl_shutdown: calling SSL_shutdown fd = %d\n"
- " state before: %s\n", cp->fd, SSL_state_string(ssl)));
- ret = SSL_shutdown(ssl);
- ssl_error = SSL_get_error(ssl, ret);
- DEBUGF((" SSL_shutdown = %d\n"
- " ssl_error: %s\n"
- " state after: %s\n",
- ret, ssl_error_str(ssl_error), SSL_state_string(ssl)));
- if (ret >= 0) {
- check_shutdown(cp);
- return ret;
- }
- end_ssl_call(ret, cp, ssl_error);
- return ret;
-}
-
-
-/* Returns total number of bytes in DER encoded cert pointed to by
- * *buf, which is allocated by this function, unless return < 0.
- * XXX X509_free ??
- */
-int esock_ssl_getpeercert(Connection *cp, unsigned char **buf)
-{
- int len;
- SSL *ssl = cp->opaque;
- X509 *x509;
- unsigned char *tmp;
-
- RESET_ERRSTR();
- if((x509 = SSL_get_peer_certificate(ssl)) == NULL) {
- MAYBE_SET_ERRSTR("enopeercert"); /* XXX doc */
- return -1;
- }
-
- if ((len = i2d_X509(x509, NULL)) <= 0) {
- MAYBE_SET_ERRSTR("epeercert");
- return -1;
- }
-
- tmp = *buf = esock_malloc(len);
-
- /* We must use a temporary value here, since i2d_X509(X509 *x,
- * unsigned char **out) increments *out.
- */
- if (i2d_X509(x509, &tmp) < 0) {
- esock_free(tmp);
- MAYBE_SET_ERRSTR("epeercert");
- return -1;
- }
- return len;
-}
-
-/* Returns total number of bytes in chain of certs. Each cert begins
- * with a 4-bytes length. The last cert is ended with 4-bytes of
- * zeros. The result is returned in *buf, which is allocated unless
- * the return value is < 0.
- * XXX X509_free ? sk_X509_free ?
- * XXX X509_free is reference counting.
- */
-int esock_ssl_getpeercertchain(Connection *cp, unsigned char **buf)
-{
- SSL *ssl = cp->opaque;
- STACK_OF(X509) *x509_stack;
- X509 *x509;
- int num, i, totlen, pos, *der_len;
- unsigned char *vbuf;
-
- RESET_ERRSTR();
- if((x509_stack = SSL_get_peer_cert_chain(ssl)) == NULL) {
- MAYBE_SET_ERRSTR("enopeercertchain"); /* XXX doc */
- return -1;
- }
-
- num = sk_X509_num(x509_stack);
- der_len = esock_malloc(num * sizeof(int));
- totlen = 0;
-
- for (i = 0; i < num; i++) {
- x509 = sk_X509_value(x509_stack, i);
- totlen += 4;
- if ((der_len[i] = i2d_X509(x509, NULL)) < 0) {
- MAYBE_SET_ERRSTR("epeercertchain");
- esock_free(der_len);
- return -1;
- }
- totlen += der_len[i];
- }
- totlen += 4;
-
- vbuf = *buf = esock_malloc(totlen);
- pos = 0;
-
- for (i = 0; i < num; i++) {
- x509 = sk_X509_value(x509_stack, i);
- PUT_INT32(der_len[i], vbuf);
- vbuf += 4;
- /* Note: i2d_X509 increments vbuf */
- if (i2d_X509(x509, &vbuf) < 0) {
- MAYBE_SET_ERRSTR("epeercertchain");
- esock_free(*buf);
- esock_free(der_len);
- return -1;
- }
- }
- esock_free(der_len);
- return totlen;
-}
-
-
-int esock_ssl_getprotocol_version(Connection *cp, char **buf)
-{
- SSL *ssl = cp->opaque;
-
- RESET_ERRSTR();
- if (!ssl) {
- MAYBE_SET_ERRSTR("enoent");
- return -1;
- }
- *buf = (char *) SSL_get_version(ssl);
-
- return 0;
-}
-
-
-int esock_ssl_getcipher(Connection *cp, char **buf)
-{
- SSL *ssl = cp->opaque;
-
- RESET_ERRSTR();
- if (!ssl) {
- MAYBE_SET_ERRSTR("enoent");
- return -1;
- }
- *buf = (char *) SSL_get_cipher(ssl);
-
- return 0;
-}
-
-/* Local functions */
-
-static char *ssl_error_str(int ssl_error)
-{
- int i;
- static char buf[128];
-
- for (i = 0; i < sizeof(errs)/sizeof(err_entry); i ++) {
- if (ssl_error == errs[i].code)
- return errs[i].text;
- }
- sprintf(buf, "esock_openssl: SSL_error unknown: %d", ssl_error);
- return buf;
-}
-
-void end_ssl_call(int ret, Connection *cp, int ssl_error)
-{
- SET_WANT(cp, ssl_error);
- switch (ssl_error) {
- case SSL_ERROR_SYSCALL:
- /* Typically sock_errno() is equal to ERRNO_BLOCK */
- MAYBE_SET_ERRSTR(esock_posix_str(sock_errno()));
- break;
- case SSL_ERROR_SSL:
- sock_set_errno(ERRNO_NONE);
- MAYBE_SET_ERRSTR("esslerrssl");
- break;
- case SSL_ERROR_WANT_X509_LOOKUP:
- SSLDEBUGF();
- sock_set_errno(ERRNO_NONE);
- MAYBE_SET_ERRSTR("ex509lookup");
- break;
- case SSL_ERROR_WANT_CONNECT:
- SSLDEBUGF();
- sock_set_errno(ERRNO_NONE);
- MAYBE_SET_ERRSTR("ewantconnect");
- break;
- default:
- break;
- }
-}
-
-void check_shutdown(Connection *cp)
-{
- int sd_mode;
- SSL *ssl = cp->opaque;
-
- sd_mode = SSL_get_shutdown(ssl);
- if (sd_mode & SSL_RECEIVED_SHUTDOWN)
- cp->eof = 1;
- if (sd_mode & SSL_SENT_SHUTDOWN) {
- DEBUGF(("check_shutdown SSL_SENT_SHUTDOWN\n"));
- cp->bp = 1;
- }
-}
-
-/*
- * set_ssl_parameters
- *
- * Set ssl parameters from connection structure. Only called for
- * listen and connect.
- *
- * Note: The -cacertdir option is not documented.
- */
-static int set_ssl_parameters(Connection *cp, SSL_CTX *ctx)
-{
- char *cacertfile = NULL, *cacertdir = NULL, *certfile = NULL;
- char *keyfile = NULL, *ciphers = NULL, *password = NULL;
- int verify = 0, verify_depth = DEFAULT_VERIFY_DEPTH, verify_mode;
- int i, argc;
- char **argv;
- callback_data *cb_data;
-
- RESET_ERRSTR();
-
- argc = esock_build_argv(cp->flags, &argv);
-
- DEBUGF(("Argv:\n"));
- for (i = 0; i < argc; i++) {
- DEBUGF(("%d: %s\n", i, argv[i]));
- }
-
- for (i = 0; i < argc; i++) {
- if (strcmp(argv[i], "-verify") == 0) {
- verify = atoi(argv[++i]);
- } else if (strcmp(argv[i], "-depth") == 0) {
- verify_depth = atoi(argv[++i]);
- } else if (strcmp(argv[i], "-log") == 0) {
- /* XXX ignored: logging per connection not supported */
- i++;
- } else if (strcmp(argv[i], "-certfile") == 0) {
- certfile = argv[++i];
- } else if (strcmp(argv[i], "-keyfile") == 0) {
- keyfile = argv[++i];
- } else if (strcmp(argv[i], "-password") == 0) {
- password = argv[++i];
- } else if (strcmp(argv[i], "-cacertfile") == 0) {
- cacertfile = argv[++i];
- } else if (strcmp(argv[i], "-cacertdir") == 0) {
- cacertdir = argv[++i];
- } else if (strcmp(argv[i], "-d") == 0) {
- /* XXX ignored: debug per connection not supported */
- i++;
- } else if (strcmp(argv[i], "-ciphers") == 0) {
- ciphers = argv[++i];
- } else {
- /* XXX Error: now ignored */
- }
- }
- DEBUGF(("set_ssl_parameters: all arguments read\n"));
-
- if (cp->origin == ORIG_LISTEN && !certfile) {
- DEBUGF(("ERROR: Server must have certificate\n"));
- MAYBE_SET_ERRSTR("enoservercert");
- goto err_end;
- }
-
- /* Define callback data */
- /* XXX Check for NULL */
- cb_data = esock_malloc(sizeof(callback_data));
- cb_data->ctx = ctx;
- if (password) {
- cb_data->passwd = esock_malloc(strlen(password) + 1);
- strcpy(cb_data->passwd, password);
- } else
- cb_data->passwd = NULL;
- cb_data->verify_depth = verify_depth;
- SSL_CTX_set_ex_data(ctx, callback_data_index, cb_data);
-
- /* password callback */
- SSL_CTX_set_default_passwd_cb(ctx, passwd_callback);
- SSL_CTX_set_default_passwd_cb_userdata(ctx, cb_data);
-
- /* Set location for "trusted" certificates */
- if (cacertfile || cacertdir) {
- int res;
- DEBUGF(("set_ssl_parameters: SSL_CTX_load_verify_locations\n"));
- FOPEN_WORKAROUND(res, SSL_CTX_load_verify_locations(ctx, cacertfile,
- cacertdir));
- if (!res) {
- DEBUGF(("ERROR: Cannot load verify locations\n"));
- MAYBE_SET_ERRSTR("ecacertfile");
- goto err_end;
- }
- } else {
- int res;
- DEBUGF(("set_ssl_parameters: SSL_CTX_set_default_verify_paths\n"));
- FOPEN_WORKAROUND(res, SSL_CTX_set_default_verify_paths(ctx));
- if (!res) {
- DEBUGF(("ERROR: Cannot set default verify paths\n"));
- MAYBE_SET_ERRSTR("ecacertfile");
- goto err_end;
- }
- }
-
- /* For a server the following sets the list of CA distinguished
- * names that it sends to its client when it requests the
- * certificate from the client.
- * XXX The names of certs in cacertdir ignored.
- */
- if (cp->origin == ORIG_LISTEN && cacertfile) {
- DEBUGF(("set_ssl_parameters: SSL_CTX_set_client_CA_list\n"));
- VOID_FOPEN_WORKAROUND(SSL_CTX_set_client_CA_list(ctx,
- SSL_load_client_CA_file(cacertfile)));
- if (!SSL_CTX_get_client_CA_list(ctx)) {
- DEBUGF(("ERROR: Cannot set client CA list\n"));
- MAYBE_SET_ERRSTR("ecacertfile");
- goto err_end;
- }
- }
-
- /* Use certificate file if key file has not been set. */
- if (!keyfile)
- keyfile = certfile;
-
- if (certfile) {
- int res;
- DEBUGF(("set_ssl_parameters: SSL_CTX_use_certificate_file\n"));
- FOPEN_WORKAROUND(res, SSL_CTX_use_certificate_file(ctx, certfile,
- SSL_FILETYPE_PEM));
- if (res <= 0) {
- DEBUGF(("ERROR: Cannot set certificate file\n"));
- MAYBE_SET_ERRSTR("ecertfile");
- goto err_end;
- }
- }
- if (keyfile) {
- int res;
- DEBUGF(("set_ssl_parameters: SSL_CTX_use_PrivateKey_file\n"));
- FOPEN_WORKAROUND(res, SSL_CTX_use_PrivateKey_file(ctx, keyfile,
- SSL_FILETYPE_PEM));
- if (res <= 0) {
- DEBUGF(("ERROR: Cannot set private key file\n"));
- MAYBE_SET_ERRSTR("ekeyfile");
- goto err_end;
- }
- }
- if(certfile && keyfile) {
- DEBUGF(("set_ssl_parameters: SSL_CTX_check_private_key\n"));
- if (!SSL_CTX_check_private_key(ctx)) {
- DEBUGF(("ERROR: Private key does not match the certificate\n"));
- MAYBE_SET_ERRSTR("ekeymismatch");
- goto err_end;
- }
- }
-
- /* Ciphers */
- if (ciphers) {
- DEBUGF(("set_ssl_parameters: SSL_CTX_set_cipher_list\n"));
- if (!SSL_CTX_set_cipher_list(ctx, ciphers)) {
- DEBUGF(("ERROR: Cannot set cipher list\n"));
- MAYBE_SET_ERRSTR("ecipher");
- goto err_end;
- }
- }
-
- /* Verify depth */
- DEBUGF(("set_ssl_parameters: SSL_CTX_set_verify_depth (depth = %d)\n",
- verify_depth));
- SSL_CTX_set_verify_depth(ctx, verify_depth);
-
- /* Verify mode and callback */
- /* XXX Why precisely these modes? */
- switch (verify) {
- case 0:
- verify_mode = SSL_VERIFY_NONE;
- break;
- case 1:
- verify_mode = SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE;
- break;
- case 2:
- verify_mode = SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE|
- SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
- break;
- default:
- verify_mode = SSL_VERIFY_NONE;
- }
- DEBUGF(("set_ssl_parameters: SSL_CTX_set_verify (verify = %d)\n",
- verify));
- SSL_CTX_set_verify(ctx, verify_mode, verify_callback);
-
- /* Session id context. Should be an option really. */
- if (cp->origin == ORIG_LISTEN) {
- unsigned char *sid = "Erlang/OTP/ssl";
- SSL_CTX_set_session_id_context(ctx, sid, strlen(sid));
- }
-
- /* info callback */
- if (debug)
- SSL_CTX_set_info_callback(ctx, info_callback);
-
- DEBUGF(("set_ssl_parameters: done\n"));
- /* Free arg list */
- for (i = 0; argv[i]; i++)
- esock_free(argv[i]);
- esock_free(argv);
- return 0;
-
- err_end:
- DEBUGF(("set_ssl_parameters: error\n"));
- /* Free arg list */
- for (i = 0; argv[i]; i++)
- esock_free(argv[i]);
- esock_free(argv);
- return -1;
-}
-
-/* Call back functions */
-
-static int verify_callback(int ok, X509_STORE_CTX *x509_ctx)
-{
- X509 *cert;
- int cert_err, depth;
- SSL *ssl;
- SSL_CTX *ctx;
- callback_data *cb_data;
-
- cert = X509_STORE_CTX_get_current_cert(x509_ctx);
- cert_err = X509_STORE_CTX_get_error(x509_ctx);
- depth = X509_STORE_CTX_get_error_depth(x509_ctx);
-
- ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
- SSL_get_ex_data_X509_STORE_CTX_idx());
- ctx = SSL_get_SSL_CTX(ssl);
- cb_data = SSL_CTX_get_ex_data(ctx, callback_data_index);
-
- X509_NAME_oneline(X509_get_subject_name(cert), x509_buf, sizeof(x509_buf));
- DEBUGF((" +vfy: depth = %d\n", depth));
- DEBUGF((" subject = %s\n", x509_buf));
- X509_NAME_oneline(X509_get_issuer_name(cert), x509_buf, sizeof(x509_buf));
- DEBUGF((" issuer = %s\n", x509_buf));
-
- if (!ok) {
- DEBUGF((" +vfy: error = %d [%s]\n", cert_err,
- X509_verify_cert_error_string(cert_err)));
- if (depth >= cb_data->verify_depth)
- ok = 1;
- }
-
- switch (cert_err) {
- case X509_V_OK:
- case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
- ok = 1;
- break;
- case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
- case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
- MAYBE_SET_ERRSTR("enoissuercert");
- break;
- case X509_V_ERR_CERT_HAS_EXPIRED:
- MAYBE_SET_ERRSTR("epeercertexpired");
- break;
- case X509_V_ERR_CERT_NOT_YET_VALID:
- case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
- case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
- MAYBE_SET_ERRSTR("epeercertinvalid");
- break;
- case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
- MAYBE_SET_ERRSTR("eselfsignedcert");
- break;
- case X509_V_ERR_CERT_CHAIN_TOO_LONG:
- MAYBE_SET_ERRSTR("echaintoolong");
- break;
- default:
- MAYBE_SET_ERRSTR("epeercert");
- break;
- }
- DEBUGF((" +vfy: return = %d\n",ok));
- return ok;
-}
-
-static int passwd_callback(char *buf, int num, int rwflag, void *userdata)
-{
- callback_data *cb_data = userdata;
- int len;
-
- if (cb_data && cb_data->passwd) {
- DEBUGF((" +passwd: %s\n", cb_data->passwd));
- strncpy(buf, cb_data->passwd, num);
- len = strlen(cb_data->passwd);
- return len;
- }
- DEBUGF((" +passwd: ERROR: No password set.\n"));
- return 0;
-}
-
-static void info_callback(const SSL *ssl, int where, int ret)
-{
- char *str;
-
- if (where & SSL_CB_LOOP) {
- DEBUGF((" info: %s\n",SSL_state_string_long(ssl)));
- } else if (where & SSL_CB_ALERT) {
- str = (where & SSL_CB_READ) ? "read" : "write";
- DEBUGF((" info: SSL3 alert %s:%s:%s\n", str,
- SSL_alert_type_string_long(ret),
- SSL_alert_desc_string_long(ret)));
- } else if (where & SSL_CB_EXIT) {
- if (ret == 0) {
- DEBUGF((" info: failed in %s\n", SSL_state_string_long(ssl)));
- } else if (ret < 0) {
- DEBUGF((" info: error in %s\n", SSL_state_string_long(ssl)));
- }
- }
-}
-
-/* This function is called whenever a SSL_CTX *ctx structure is
- * freed.
-*/
-static void callback_data_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
- int idx, long arg1, void *argp)
-{
- callback_data *cb_data = ptr;
-
- if (cb_data) {
- if (cb_data->passwd)
- esock_free(cb_data->passwd);
- esock_free(cb_data);
- }
-}
-
-static RSA *tmp_rsa_callback(SSL *ssl, int is_export, int keylen)
-{
- static RSA *rsa512 = NULL;
- static RSA *rsa1024 = NULL;
-
- switch (keylen) {
- case 512:
- if (!rsa512)
- rsa512 = RSA_generate_key(keylen, RSA_F4, NULL, NULL);
- return rsa512;
- break;
- case 1024:
- if (!rsa1024)
- rsa1024 = RSA_generate_key(keylen, RSA_F4, NULL, NULL);
- return rsa1024;
- break;
- default:
- if (rsa1024)
- return rsa1024;
- if (rsa512)
- return rsa512;
- rsa512 = RSA_generate_key(keylen, RSA_F4, NULL, NULL);
- return rsa512;
- }
-}
-
-/* Restrict protocols (SSLv2, SSLv3, TLSv1) */
-static void restrict_protocols(SSL_CTX *ctx)
-{
- long options = 0;
-
- if (protocol_version) {
- if ((protocol_version & ESOCK_SSLv2) == 0)
- options |= SSL_OP_NO_SSLv2;
- if ((protocol_version & ESOCK_SSLv3) == 0)
- options |= SSL_OP_NO_SSLv3;
- if ((protocol_version & ESOCK_TLSv1) == 0)
- options |= SSL_OP_NO_TLSv1;
- SSL_CTX_set_options(ctx, options);
- }
-}
-
-
-static unsigned char randvec [] = {
- 181, 177, 237, 240, 107, 24, 43, 148,
- 105, 4, 248, 13, 199, 255, 23, 58,
- 71, 181, 57, 151, 156, 25, 165, 7,
- 73, 80, 80, 231, 70, 110, 96, 162,
- 24, 205, 178, 178, 67, 122, 210, 180,
- 92, 6, 156, 182, 84, 159, 85, 6,
- 175, 66, 165, 167, 137, 34, 179, 237,
- 77, 90, 87, 185, 21, 106, 92, 115,
- 137, 65, 233, 42, 164, 153, 208, 133,
- 160, 172, 129, 202, 46, 220, 98, 66,
- 115, 66, 46, 28, 226, 200, 140, 145,
- 207, 194, 58, 71, 56, 203, 113, 34,
- 221, 116, 63, 114, 188, 210, 45, 238,
- 200, 123, 35, 150, 2, 78, 160, 22,
- 226, 167, 162, 10, 182, 75, 109, 97,
- 86, 252, 93, 125, 117, 214, 220, 37,
- 105, 160, 56, 158, 97, 57, 22, 14,
- 73, 169, 111, 190, 222, 176, 14, 82,
- 111, 42, 87, 90, 136, 236, 22, 209,
- 156, 207, 40, 251, 88, 141, 51, 211,
- 31, 158, 153, 91, 119, 83, 255, 60,
- 55, 94, 5, 115, 119, 210, 224, 185,
- 163, 163, 5, 3, 197, 106, 110, 206,
- 109, 132, 50, 190, 177, 133, 175, 129,
- 225, 161, 156, 244, 77, 150, 99, 38,
- 17, 111, 46, 230, 152, 64, 50, 164,
- 19, 78, 3, 164, 169, 175, 104, 97,
- 103, 158, 91, 168, 186, 191, 73, 88,
- 118, 112, 41, 188, 219, 0, 198, 209,
- 206, 7, 5, 169, 127, 180, 80, 74,
- 124, 4, 4, 108, 197, 67, 204, 29,
- 101, 95, 174, 147, 64, 163, 89, 160,
- 10, 5, 56, 134, 209, 69, 209, 55,
- 214, 136, 45, 212, 113, 85, 159, 133,
- 141, 249, 75, 40, 175, 91, 142, 13,
- 179, 179, 51, 0, 136, 63, 148, 175,
- 103, 162, 8, 214, 4, 24, 59, 71,
- 9, 185, 48, 127, 159, 165, 8, 8,
- 135, 151, 92, 214, 132, 151, 204, 169,
- 24, 112, 229, 59, 236, 81, 238, 64,
- 150, 196, 97, 213, 140, 159, 20, 24,
- 79, 210, 191, 53, 130, 33, 157, 87,
- 16, 180, 175, 217, 56, 123, 115, 196,
- 130, 6, 155, 37, 220, 80, 232, 129,
- 240, 57, 199, 249, 196, 152, 28, 111,
- 124, 192, 59, 46, 29, 21, 178, 51,
- 156, 17, 248, 61, 254, 80, 201, 131,
- 203, 59, 227, 191, 71, 121, 134, 181,
- 55, 79, 130, 225, 246, 36, 179, 224,
- 189, 243, 200, 75, 73, 41, 251, 41,
- 71, 251, 78, 146, 99, 101, 104, 69,
- 18, 122, 65, 24, 232, 84, 246, 242,
- 209, 18, 241, 114, 3, 65, 177, 99,
- 49, 99, 215, 59, 9, 175, 195, 11,
- 25, 46, 43, 120, 109, 179, 159, 250,
- 239, 246, 135, 78, 2, 238, 214, 237,
- 64, 170, 50, 44, 68, 67, 111, 232,
- 225, 230, 224, 124, 76, 32, 52, 158,
- 151, 54, 184, 135, 122, 66, 211, 215,
- 121, 90, 124, 158, 55, 73, 116, 137,
- 240, 15, 38, 31, 183, 86, 93, 49,
- 148, 184, 125, 250, 155, 216, 84, 246,
- 27, 172, 141, 54, 80, 158, 227, 254,
- 189, 164, 238, 229, 68, 26, 231, 11,
- 198, 222, 15, 141, 98, 8, 124, 219,
- 60, 125, 170, 213, 114, 24, 189, 65,
- 80, 186, 71, 126, 223, 153, 20, 141,
- 110, 73, 173, 218, 214, 63, 205, 177,
- 132, 115, 184, 28, 122, 232, 210, 72,
- 237, 41, 93, 17, 152, 95, 242, 138,
- 79, 98, 47, 197, 36, 17, 137, 230,
- 15, 73, 193, 1, 181, 123, 0, 186,
- 185, 135, 142, 200, 139, 78, 57, 145,
- 191, 32, 98, 250, 113, 188, 71, 32,
- 205, 81, 219, 99, 60, 87, 42, 95,
- 249, 252, 121, 125, 246, 230, 74, 162,
- 73, 59, 179, 142, 178, 47, 163, 161,
- 236, 14, 123, 219, 18, 6, 102, 140,
- 215, 210, 76, 9, 119, 147, 252, 63,
- 13, 51, 161, 172, 180, 116, 212, 129,
- 116, 237, 38, 64, 213, 222, 35, 14,
- 183, 237, 78, 204, 250, 250, 5, 41,
- 142, 5, 207, 154, 65, 183, 108, 82,
- 1, 43, 149, 233, 89, 195, 25, 233,
- 4, 34, 19, 122, 16, 58, 121, 5,
- 118, 168, 22, 213, 49, 226, 163, 169,
- 21, 78, 179, 232, 125, 216, 198, 147,
- 245, 196, 199, 138, 185, 167, 179, 82,
- 175, 53, 6, 162, 5, 141, 180, 212,
- 95, 201, 234, 169, 111, 175, 138, 197,
- 177, 246, 154, 41, 185, 201, 134, 187,
- 88, 99, 231, 23, 190, 36, 72, 174,
- 244, 185, 205, 50, 230, 226, 210, 119,
- 175, 107, 109, 244, 12, 122, 84, 51,
- 146, 95, 68, 74, 76, 212, 221, 103,
- 244, 71, 63, 133, 149, 233, 48, 3,
- 176, 168, 6, 98, 88, 226, 120, 190,
- 205, 249, 38, 157, 205, 148, 250, 203,
- 147, 62, 195, 229, 219, 109, 177, 119,
- 120, 43, 165, 99, 253, 210, 180, 32,
- 227, 180, 174, 64, 156, 139, 251, 53,
- 205, 132, 210, 208, 3, 199, 115, 64,
- 59, 27, 249, 164, 224, 191, 124, 241,
- 142, 10, 19, 120, 227, 46, 174, 231,
- 48, 65, 41, 56, 51, 38, 185, 95,
- 250, 182, 100, 40, 196, 124, 173, 119,
- 162, 148, 170, 34, 51, 68, 175, 60,
- 242, 201, 225, 34, 146, 157, 159, 0,
- 144, 148, 82, 72, 149, 53, 201, 10,
- 248, 206, 154, 126, 33, 153, 56, 48,
- 5, 90, 194, 22, 251, 173, 211, 202,
- 203, 253, 112, 147, 188, 200, 142, 206,
- 206, 175, 233, 76, 93, 104, 125, 41,
- 64, 145, 202, 53, 130, 251, 23, 90,
- 28, 199, 13, 128, 185, 154, 53, 194,
- 195, 55, 80, 56, 151, 216, 195, 138,
- 7, 170, 143, 236, 74, 141, 229, 174,
- 32, 165, 131, 68, 174, 104, 35, 143,
- 183, 41, 80, 191, 120, 79, 166, 240,
- 123, 55, 60, 2, 128, 56, 4, 199,
- 122, 85, 90, 76, 246, 29, 13, 6,
- 126, 229, 14, 203, 244, 73, 121, 42,
- 169, 35, 44, 202, 18, 69, 153, 120,
- 141, 77, 124, 191, 215, 18, 115, 187,
- 108, 246, 135, 151, 225, 192, 50, 89,
- 128, 45, 39, 253, 149, 234, 203, 84,
- 51, 174, 15, 237, 17, 57, 76, 81,
- 39, 107, 40, 36, 22, 52, 92, 39};
diff --git a/lib/ssl/c_src/esock_osio.c b/lib/ssl/c_src/esock_osio.c
deleted file mode 100644
index 41c5271c16..0000000000
--- a/lib/ssl/c_src/esock_osio.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/*<copyright>
- * <year>1999-2008</year>
- * <holder>Ericsson AB, All Rights Reserved</holder>
- *</copyright>
- *<legalnotice>
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * The Initial Developer of the Original Code is Ericsson AB.
- *</legalnotice>
- */
-/*
- * Purpose: Std filedescriptors, break handler
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#ifdef __WIN32__
-#include "esock_winsock.h"
-#include <process.h>
-#include <io.h>
-#include <fcntl.h>
-#else
-#include <unistd.h>
-#include <signal.h>
-#endif
-
-#include "esock.h"
-#include "debuglog.h"
-#include "esock_utils.h"
-#include "esock_osio.h"
-
-#ifdef __WIN32__
-#define write _write
-#define read _read
-#define LOCALHOSTADDR "127.0.0.1"
-#define LOCBUFSIZE 1024
-#endif
-
-#define PACKET_SIZE 4
-#define EBUFSIZE 256
-
-FD local_read_fd = 0;
-
-static int inc_rbuf(int size);
-static void free_rbuf(void);
-static int read_fill(unsigned char *buf, int len);
-#ifdef __WIN32__
-static int create_local_thread(void);
-static DWORD WINAPI local_thread(LPVOID lpvParam);
-static BOOL WINAPI signal_handler(DWORD ctrl);
-#endif
-
-static unsigned char *rbuf = NULL;
-static int rbuf_malloced = 0;
-#ifdef __WIN32__
-static unsigned long one = 1, zero = 0;
-static int local_portno;
-static char *local_buf;
-#endif
-
-int set_break_handler(void)
-{
-#ifndef __WIN32__
- struct sigaction act;
-
- /* Ignore SIGPIPE signal */
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0;
- act.sa_handler = SIG_IGN;
- sigaction(SIGPIPE, &act, NULL);
- return 0;
-#else
- SetConsoleCtrlHandler(signal_handler, TRUE);
- return 0;
-#endif
-}
-
-
-#ifdef __WIN32__
-
-int set_binary_mode(void)
-{
- _setmode(0, _O_BINARY);
- _setmode(1, _O_BINARY);
- return 0;
-}
-
-int esock_osio_init(void)
-{
- return create_local_thread();
-}
-
-void esock_osio_finish(void)
-{
- sock_close(local_read_fd);
-}
-
-#endif
-
-int read_ctrl(unsigned char **ebufp)
-{
- int tbh, cc;
- unsigned char *mbuf;
-
- if (inc_rbuf(EBUFSIZE) < 0) {
- fprintf(stderr, "read_ctrl: cannot alloc rbuf\n");
- return -1;
- }
- cc = read_fill(rbuf, PACKET_SIZE);
- if (cc < 0) {
- free_rbuf();
- return -1;
- }
- if (cc == 0) {
- free_rbuf();
- return -1; /* XXX 0 ?? */
- }
- tbh = GET_INT32(rbuf);
-
- if (tbh > rbuf_malloced - 4) {
- if (inc_rbuf(tbh + 4) < 0)
- return -1;
- }
-
- mbuf = rbuf + PACKET_SIZE;
- cc = read_fill(mbuf, tbh);
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("read_ctrl: cc = %d\n", cc));
- if(cc > 0) {
- DEBUGMSGF(("message (hex) : [%3.*a]\n", cc, mbuf));
- DEBUGMSGF(("message (char): [%3.*b]\n", cc, mbuf));
- }
- *ebufp = mbuf;
- return cc;
-}
-
-int write_ctrl(unsigned char *buf, int len)
-{
- unsigned char lb[4];
-
- PUT_INT32(len, lb);
- DEBUGF(("write_ctrl: len = %d\n", len));
- DEBUGMSGF(("message (hex) : [%3.*a] [%3.*a]\n", PACKET_SIZE, lb,
- len, buf));
- DEBUGMSGF(("message (char): [%3.*b] [%3.*b]\n", PACKET_SIZE, lb,
- len, buf));
-
- if (write(1, lb, PACKET_SIZE) != PACKET_SIZE) { /* XXX */
- fprintf(stderr, "write_ctrl: Bad write \n");
- return -1;
- }
- if (write(1, buf, len) != len) { /* XXX */
- fprintf(stderr, "write_ctrl: Bad write \n");
- return -1;
- }
- return len;
-}
-
-
-/*
- * Local functions
- *
- */
-
-static int inc_rbuf(int size)
-{
- unsigned char *nbuf;
-
- if (rbuf_malloced >= size)
- return 0;
- if (rbuf != NULL)
- nbuf = esock_realloc(rbuf, size);
- else
- nbuf = esock_malloc(size);
- if(nbuf != NULL) {
- rbuf = nbuf;
- rbuf_malloced = size;
- return 0;
- }
- return -1;
-}
-
-static void free_rbuf(void)
-{
- if (rbuf != NULL) {
- esock_free(rbuf);
- rbuf = NULL;
- rbuf_malloced = 0;
- }
-}
-
-/* Fill buffer, return buffer length, 0 for EOF, < 0 for error. */
-
-static int read_fill(unsigned char *buf, int len)
-{
- int i, got = 0;
-
- do {
- if ((i = sock_read(local_read_fd, buf+got, len-got)) <= 0)
- return i;
- got += i;
- } while (got < len);
- return len;
-}
-
-
-#ifdef __WIN32__
-
-/*
- * This routine creates a local thread, which reads from standard input
- * and writes to a socket.
- */
-
-static int create_local_thread(void)
-{
- struct sockaddr_in iserv_addr;
- SOCKET tmpsock;
- int length;
- unsigned threadaddr;
-
- local_buf = esock_malloc(LOCBUFSIZE);
- if ((tmpsock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
- fprintf(stderr, "create_local_thread could not create socket.\n");
- return -1;
- }
- memset(&iserv_addr, 0, sizeof(iserv_addr));
- iserv_addr.sin_family = AF_INET;
- iserv_addr.sin_addr.s_addr = inet_addr(LOCALHOSTADDR);
- iserv_addr.sin_port = htons(0); /* Have any port */
-
- if (bind(tmpsock, (struct sockaddr *) &iserv_addr,
- sizeof(iserv_addr)) < 0) {
- fprintf(stderr, "create_local_thread could not bind.\n");
- closesocket(tmpsock);
- return -1;
- }
- listen(tmpsock, 1);
- length = sizeof(iserv_addr);
- if (getsockname(tmpsock, (struct sockaddr *) &iserv_addr, &length) < 0) {
- fprintf(stderr, "create_local_thread could not getsockname.\n");
- closesocket(tmpsock);
- return -1;
- }
- local_portno = ntohs(iserv_addr.sin_port);
-
- if (_beginthreadex(NULL, 0, local_thread, NULL, 0, &threadaddr) == 0) {
- fprintf(stderr, "create_local_thread could not _beginthreadex().\n");
- closesocket(tmpsock);
- return -1;
- }
- local_read_fd = accept(tmpsock, (struct sockaddr *) NULL, (int *) NULL);
- if (local_read_fd == INVALID_FD) {
- fprintf(stderr, "create_local_thread could not accept.\n");
- closesocket(tmpsock);
- return -1;
- }
- closesocket(tmpsock);
- return 0;
-}
-
-static DWORD WINAPI local_thread(LPVOID lpvParam)
-{
- SOCKET sock;
- struct hostent *host;
- char hostname[64];
- struct sockaddr_in iserv_addr;
- unsigned long addr;
- int len;
- HANDLE thread;
-
- sock = socket(AF_INET, SOCK_STREAM, 0);
- memset(&iserv_addr, 0, sizeof(struct sockaddr_in));
- iserv_addr.sin_family = AF_INET;
- iserv_addr.sin_addr.s_addr = inet_addr(LOCALHOSTADDR);
- iserv_addr.sin_port = htons(local_portno);
- if(connect(sock, (struct sockaddr*)&iserv_addr, sizeof iserv_addr) ==
- SOCKET_ERROR) {
- fprintf(stderr, "local_thread thread could not connect\n");
- closesocket(sock);
- return 0;
- }
- setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
-
- /* read from 0 and write to sock */
- while (1) {
- if ((len = read(0, local_buf, LOCBUFSIZE)) <= 0) {
- closesocket(sock);
- close(0);
- return 0;
- }
- if (send(sock, local_buf, len, 0) != len ) {
- closesocket(sock);
- close(0);
- return 0;
- }
- }
- return 0;
-}
-
-/* Signal handler */
-
-static BOOL WINAPI signal_handler(DWORD ctrl)
-{
- switch (ctrl) {
- case CTRL_C_EVENT:
- case CTRL_BREAK_EVENT:
- break;
- case CTRL_LOGOFF_EVENT:
- if (!getenv("ERLSRV_SERVICE_NAME"))
- return FALSE;
- break;
- default:
- exit(1);
- }
- return TRUE;
-}
-
-#endif
diff --git a/lib/ssl/c_src/esock_osio.h b/lib/ssl/c_src/esock_osio.h
deleted file mode 100644
index 8742c3b05b..0000000000
--- a/lib/ssl/c_src/esock_osio.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2009. All Rights Reserved.
- *
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * %CopyrightEnd%
- */
-
-#ifndef ESOCK_OSIO_H
-#define ESOCK_OSIO_H
-
-extern FD local_read_fd;
-
-#ifdef __WIN32__
-int set_binary_mode(void);
-int esock_osio_init(void);
-void esock_osio_finish(void);
-#endif
-int set_break_handler(void);
-int read_ctrl(unsigned char **ebufp);
-int write_ctrl(unsigned char *buf, int len);
-
-#endif
diff --git a/lib/ssl/c_src/esock_poll.c b/lib/ssl/c_src/esock_poll.c
deleted file mode 100644
index e982eba881..0000000000
--- a/lib/ssl/c_src/esock_poll.c
+++ /dev/null
@@ -1,222 +0,0 @@
-/*<copyright>
- * <year>2005-2008</year>
- * <holder>Ericsson AB, All Rights Reserved</holder>
- *</copyright>
- *<legalnotice>
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * The Initial Developer of the Original Code is Ericsson AB.
- *</legalnotice>
- */
-
-/*
- * Purpose: Hide poll() and select() behind an API so that we
- * can use either one.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#ifdef __WIN32__
-#include "esock_winsock.h"
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <time.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <errno.h>
-
-#ifdef __WIN32__
-#include <process.h>
-#else
-#include <unistd.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <sys/time.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-#endif
-
-#include "esock.h"
-#include "esock_ssl.h"
-#include "esock_utils.h"
-#include "esock_poll.h"
-#include "debuglog.h"
-
-#if !defined(USE_SELECT)
-
-/* At least on FreeBSD, we need POLLRDNORM for normal files, not POLLIN. */
-/* Whether this is a bug in FreeBSD, I don't know. */
-#ifdef POLLRDNORM
-#define POLL_INPUT (POLLIN | POLLRDNORM)
-#else
-#define POLL_INPUT POLLIN
-#endif
-
-static void poll_fd_set(EsockPoll *ep, FD fd, short events)
-{
- int i, j;
- int prev_num_fds = ep->num_fds;
-
- if (ep->num_fds <= fd) {
- ep->num_fds = fd + 64;
- ep->fd_to_poll = (int *) esock_realloc(ep->fd_to_poll,
- ep->num_fds*sizeof(int));
- for (j = prev_num_fds; j < ep->num_fds; j++)
- ep->fd_to_poll[j] = -1;
- }
- i = ep->fd_to_poll[fd];
- if (i > 0 && i < ep->active && ep->fds[i].fd == fd) {
- /* Already present in poll array */
- ep->fds[i].events |= events;
- } else {
- /* Append to poll array */
- if (ep->active >= ep->allocated) {
- ep->allocated *= 2;
- ep->fds = (struct pollfd *)
- esock_realloc(ep->fds, ep->allocated*sizeof(struct pollfd));
- }
- ep->fd_to_poll[fd] = ep->active;
- ep->fds[ep->active].fd = fd;
- ep->fds[ep->active].events = events;
- ep->fds[ep->active].revents = 0;
- ep->active++;
- }
-}
-
-static int poll_is_set(EsockPoll *ep, FD fd, short mask)
-{
- if (fd >= ep->num_fds) {
- return 0;
- } else {
- int i = ep->fd_to_poll[fd];
- return 0 <= i && i < ep->active && ep->fds[i].fd == fd &&
- (ep->fds[i].revents & mask) != 0;
- }
-}
-
-#endif
-
-void esock_poll_init(EsockPoll *ep)
-{
-#ifdef USE_SELECT
- /* Nothing to do here */
-#else
- ep->allocated = 2;
- ep->fds = (struct pollfd *) esock_malloc(ep->allocated*sizeof(struct pollfd));
- ep->num_fds = 1;
- ep->fd_to_poll = esock_malloc(ep->num_fds*sizeof(int));
-#endif
-}
-
-void esock_poll_zero(EsockPoll *ep)
-{
-#ifdef USE_SELECT
- FD_ZERO(&ep->readmask);
- FD_ZERO(&ep->writemask);
- FD_ZERO(&ep->exceptmask);
-#else
- int i;
-
- for (i = 0; i < ep->num_fds; i++)
- ep->fd_to_poll[i] = -1;
- ep->active = 0;
-#endif
-}
-
-void esock_poll_fd_set_read(EsockPoll *ep, FD fd)
-{
-#ifdef USE_SELECT
- FD_SET(fd, &ep->readmask);
-#else
- poll_fd_set(ep, fd, POLL_INPUT);
-#endif
-}
-
-void esock_poll_fd_set_write(EsockPoll *ep, FD fd)
-{
-#ifdef USE_SELECT
- FD_SET(fd, &ep->writemask);
-#else
- poll_fd_set(ep, fd, POLLOUT);
-#endif
-}
-
-int esock_poll_fd_isset_read(EsockPoll *ep, FD fd)
-{
-#ifdef USE_SELECT
- return FD_ISSET(fd, &ep->readmask);
-#else
- return poll_is_set(ep, fd, (POLL_INPUT|POLLHUP|POLLERR|POLLNVAL));
-#endif
-}
-
-int esock_poll_fd_isset_write(EsockPoll *ep, FD fd)
-{
-#ifdef USE_SELECT
- return FD_ISSET(fd, &ep->writemask);
-#else
- return poll_is_set(ep, fd, (POLLOUT|POLLHUP|POLLERR|POLLNVAL));
-#endif
-}
-
-#ifdef __WIN32__
-void esock_poll_fd_set_exception(EsockPoll *ep, FD fd)
-{
- FD_SET(fd, &ep->exceptmask);
-}
-
-int esock_poll_fd_isset_exception(EsockPoll *ep, FD fd)
-{
- return FD_ISSET(fd, &ep->exceptmask);
-}
-#endif
-
-int esock_poll(EsockPoll *ep, int seconds)
-{
- int sret;
-
-#ifdef USE_SELECT
- struct timeval tv;
-
- tv.tv_sec = seconds;
- tv.tv_usec = 0;
- sret = select(FD_SETSIZE, &ep->readmask, &ep->writemask, &ep->exceptmask, &tv);
- if (sret == 0) {
- FD_ZERO(&ep->readmask);
- FD_ZERO(&ep->writemask);
- FD_ZERO(&ep->exceptmask);
- }
-#else
- sret = poll(ep->fds, ep->active, 1000*seconds);
-#endif
- return sret;
-}
-
-void esock_poll_clear_event(EsockPoll* ep, FD fd)
-{
-#ifdef USE_SELECT
- FD_CLR(fd, &ep->readmask);
- FD_CLR(fd, &ep->writemask);
- FD_CLR(fd, &ep->exceptmask);
-#else
- int i = ep->fd_to_poll[fd];
- if (i > 0 && ep->fds[i].fd == fd)
- ep->fds[i].revents = 0;
-#endif
-}
diff --git a/lib/ssl/c_src/esock_poll.h b/lib/ssl/c_src/esock_poll.h
deleted file mode 100644
index 639976dfa9..0000000000
--- a/lib/ssl/c_src/esock_poll.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*<copyright>
- * <year>2005-2008</year>
- * <holder>Ericsson AB, All Rights Reserved</holder>
- *</copyright>
- *<legalnotice>
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * The Initial Developer of the Original Code is Ericsson AB.
- *</legalnotice>
- */
-#ifndef ESOCK_POLL_SELECT_H
-#define ESOCK_POLL_SELECT_H
-
-#if !defined(USE_SELECT)
-#include <poll.h>
-#endif
-
-typedef struct esock_poll {
-#ifdef USE_SELECT
- fd_set readmask;
- fd_set writemask;
- fd_set exceptmask;
-#else
- int* fd_to_poll; /* Map from fd to index into poll
- * descriptor array.
- */
- int num_fds; /* Number of entries in fd_to_poll. */
- struct pollfd* fds; /* Array of poll descriptors. */
- int allocated; /* Allocated number of fds. */
- int active; /* Active number of fds */
-#endif
-} EsockPoll;
-
-void esock_poll_init(EsockPoll *ep);
-void esock_poll_zero(EsockPoll *ep);
-
-void esock_poll_fd_set_read(EsockPoll *ep, FD fd);
-void esock_poll_fd_set_write(EsockPoll *ep, FD fd);
-
-void esock_poll_clear_event(EsockPoll *ep, FD fd);
-
-int esock_poll_fd_isset_read(EsockPoll *ep, FD fd);
-int esock_poll_fd_isset_write(EsockPoll *ep, FD fd);
-
-#ifdef __WIN32__
-void esock_poll_fd_set_exception(EsockPoll *ep, FD fd);
-int esock_poll_fd_isset_exception(EsockPoll *ep, FD fd);
-#endif
-
-int esock_poll(EsockPoll *ep, int seconds);
-#endif
diff --git a/lib/ssl/c_src/esock_posix_str.c b/lib/ssl/c_src/esock_posix_str.c
deleted file mode 100644
index 31062baaaf..0000000000
--- a/lib/ssl/c_src/esock_posix_str.c
+++ /dev/null
@@ -1,642 +0,0 @@
-/*
- * %ExternalCopyright%
- */
-
-/*
- * Original: tclPosixStr.c --
- *
- * This file contains procedures that generate strings
- * corresponding to various POSIX-related codes, such
- * as errno and signals.
- *
- * Copyright (c) 1991-1994 The Regents of the University of California.
- * Copyright (c) 1994-1996 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * SCCS: @(#) tclPosixStr.c 1.32 96/10/10 10:09:42
- */
-
-/* Copy of erl_posix_str.c */
-
-#ifdef __WIN32__
-#include "esock_winsock.h"
-#endif
-
-#include <stdio.h>
-#include <errno.h>
-#include "esock_posix_str.h"
-
-/*
- *----------------------------------------------------------------------
- *
- * esock_posix_str --
- *
- * Return a textual identifier for the given errno value.
- *
- * Results:
- * This procedure returns a machine-readable textual identifier
- * that corresponds to the current errno value (e.g. "eperm").
- * The identifier is the same as the #define name in errno.h,
- * except that it is in lowercase.
- *
- *----------------------------------------------------------------------
- */
-
-static char errstrbuf[32];
-
-char *esock_posix_str(int error)
-{
- switch (error) {
-#ifdef E2BIG
- case E2BIG: return "e2big";
-#endif
-#ifdef EACCES
- case EACCES: return "eacces";
-#endif
-#ifdef EADDRINUSE
- case EADDRINUSE: return "eaddrinuse";
-#endif
-#ifdef EADDRNOTAVAIL
- case EADDRNOTAVAIL: return "eaddrnotavail";
-#endif
-#ifdef EADV
- case EADV: return "eadv";
-#endif
-#ifdef EAFNOSUPPORT
- case EAFNOSUPPORT: return "eafnosupport";
-#endif
-#ifdef EAGAIN
- case EAGAIN: return "eagain";
-#endif
-#ifdef EALIGN
- case EALIGN: return "ealign";
-#endif
-#if defined(EALREADY) && (!defined(EBUSY) || (EALREADY != EBUSY ))
- case EALREADY: return "ealready";
-#endif
-#ifdef EBADE
- case EBADE: return "ebade";
-#endif
-#ifdef EBADF
- case EBADF: return "ebadf";
-#endif
-#ifdef EBADFD
- case EBADFD: return "ebadfd";
-#endif
-#ifdef EBADMSG
- case EBADMSG: return "ebadmsg";
-#endif
-#ifdef EBADR
- case EBADR: return "ebadr";
-#endif
-#ifdef EBADRPC
- case EBADRPC: return "ebadrpc";
-#endif
-#ifdef EBADRQC
- case EBADRQC: return "ebadrqc";
-#endif
-#ifdef EBADSLT
- case EBADSLT: return "ebadslt";
-#endif
-#ifdef EBFONT
- case EBFONT: return "ebfont";
-#endif
-#ifdef EBUSY
- case EBUSY: return "ebusy";
-#endif
-#ifdef ECHILD
- case ECHILD: return "echild";
-#endif
-#ifdef ECHRNG
- case ECHRNG: return "echrng";
-#endif
-#ifdef ECOMM
- case ECOMM: return "ecomm";
-#endif
-#ifdef ECONNABORTED
- case ECONNABORTED: return "econnaborted";
-#endif
-#ifdef ECONNREFUSED
- case ECONNREFUSED: return "econnrefused";
-#endif
-#ifdef ECONNRESET
- case ECONNRESET: return "econnreset";
-#endif
-#if defined(EDEADLK) && (!defined(EWOULDBLOCK) || (EDEADLK != EWOULDBLOCK))
- case EDEADLK: return "edeadlk";
-#endif
-#if defined(EDEADLOCK) && (!defined(EDEADLK) || (EDEADLOCK != EDEADLK))
- case EDEADLOCK: return "edeadlock";
-#endif
-#ifdef EDESTADDRREQ
- case EDESTADDRREQ: return "edestaddrreq";
-#endif
-#ifdef EDIRTY
- case EDIRTY: return "edirty";
-#endif
-#ifdef EDOM
- case EDOM: return "edom";
-#endif
-#ifdef EDOTDOT
- case EDOTDOT: return "edotdot";
-#endif
-#ifdef EDQUOT
- case EDQUOT: return "edquot";
-#endif
-#ifdef EDUPPKG
- case EDUPPKG: return "eduppkg";
-#endif
-#ifdef EEXIST
- case EEXIST: return "eexist";
-#endif
-#ifdef EFAULT
- case EFAULT: return "efault";
-#endif
-#ifdef EFBIG
- case EFBIG: return "efbig";
-#endif
-#ifdef EHOSTDOWN
- case EHOSTDOWN: return "ehostdown";
-#endif
-#ifdef EHOSTUNREACH
- case EHOSTUNREACH: return "ehostunreach";
-#endif
-#if defined(EIDRM) && (!defined(EINPROGRESS) || (EIDRM != EINPROGRESS))
- case EIDRM: return "eidrm";
-#endif
-#ifdef EINIT
- case EINIT: return "einit";
-#endif
-#ifdef EINPROGRESS
- case EINPROGRESS: return "einprogress";
-#endif
-#ifdef EINTR
- case EINTR: return "eintr";
-#endif
-#ifdef EINVAL
- case EINVAL: return "einval";
-#endif
-#ifdef EIO
- case EIO: return "eio";
-#endif
-#ifdef EISCONN
- case EISCONN: return "eisconn";
-#endif
-#ifdef EISDIR
- case EISDIR: return "eisdir";
-#endif
-#ifdef EISNAME
- case EISNAM: return "eisnam";
-#endif
-#ifdef ELBIN
- case ELBIN: return "elbin";
-#endif
-#ifdef EL2HLT
- case EL2HLT: return "el2hlt";
-#endif
-#ifdef EL2NSYNC
- case EL2NSYNC: return "el2nsync";
-#endif
-#ifdef EL3HLT
- case EL3HLT: return "el3hlt";
-#endif
-#ifdef EL3RST
- case EL3RST: return "el3rst";
-#endif
-#ifdef ELIBACC
- case ELIBACC: return "elibacc";
-#endif
-#ifdef ELIBBAD
- case ELIBBAD: return "elibbad";
-#endif
-#ifdef ELIBEXEC
- case ELIBEXEC: return "elibexec";
-#endif
-#ifdef ELIBMAX
- case ELIBMAX: return "elibmax";
-#endif
-#ifdef ELIBSCN
- case ELIBSCN: return "elibscn";
-#endif
-#ifdef ELNRNG
- case ELNRNG: return "elnrng";
-#endif
-#if defined(ELOOP) && (!defined(ENOENT) || (ELOOP != ENOENT))
- case ELOOP: return "eloop";
-#endif
-#ifdef EMFILE
- case EMFILE: return "emfile";
-#endif
-#ifdef EMLINK
- case EMLINK: return "emlink";
-#endif
-#ifdef EMSGSIZE
- case EMSGSIZE: return "emsgsize";
-#endif
-#ifdef EMULTIHOP
- case EMULTIHOP: return "emultihop";
-#endif
-#ifdef ENAMETOOLONG
- case ENAMETOOLONG: return "enametoolong";
-#endif
-#ifdef ENAVAIL
- case ENAVAIL: return "enavail";
-#endif
-#ifdef ENET
- case ENET: return "enet";
-#endif
-#ifdef ENETDOWN
- case ENETDOWN: return "enetdown";
-#endif
-#ifdef ENETRESET
- case ENETRESET: return "enetreset";
-#endif
-#ifdef ENETUNREACH
- case ENETUNREACH: return "enetunreach";
-#endif
-#ifdef ENFILE
- case ENFILE: return "enfile";
-#endif
-#ifdef ENOANO
- case ENOANO: return "enoano";
-#endif
-#if defined(ENOBUFS) && (!defined(ENOSR) || (ENOBUFS != ENOSR))
- case ENOBUFS: return "enobufs";
-#endif
-#ifdef ENOCSI
- case ENOCSI: return "enocsi";
-#endif
-#if defined(ENODATA) && (!defined(ECONNREFUSED) || (ENODATA != ECONNREFUSED))
- case ENODATA: return "enodata";
-#endif
-#ifdef ENODEV
- case ENODEV: return "enodev";
-#endif
-#ifdef ENOENT
- case ENOENT: return "enoent";
-#endif
-#ifdef ENOEXEC
- case ENOEXEC: return "enoexec";
-#endif
-#ifdef ENOLCK
- case ENOLCK: return "enolck";
-#endif
-#ifdef ENOLINK
- case ENOLINK: return "enolink";
-#endif
-#ifdef ENOMEM
- case ENOMEM: return "enomem";
-#endif
-#ifdef ENOMSG
- case ENOMSG: return "enomsg";
-#endif
-#ifdef ENONET
- case ENONET: return "enonet";
-#endif
-#ifdef ENOPKG
- case ENOPKG: return "enopkg";
-#endif
-#ifdef ENOPROTOOPT
- case ENOPROTOOPT: return "enoprotoopt";
-#endif
-#ifdef ENOSPC
- case ENOSPC: return "enospc";
-#endif
-#if defined(ENOSR) && (!defined(ENAMETOOLONG) || (ENAMETOOLONG != ENOSR))
- case ENOSR: return "enosr";
-#endif
-#if defined(ENOSTR) && (!defined(ENOTTY) || (ENOTTY != ENOSTR))
- case ENOSTR: return "enostr";
-#endif
-#ifdef ENOSYM
- case ENOSYM: return "enosym";
-#endif
-#ifdef ENOSYS
- case ENOSYS: return "enosys";
-#endif
-#ifdef ENOTBLK
- case ENOTBLK: return "enotblk";
-#endif
-#ifdef ENOTCONN
- case ENOTCONN: return "enotconn";
-#endif
-#ifdef ENOTDIR
- case ENOTDIR: return "enotdir";
-#endif
-#if defined(ENOTEMPTY) && (!defined(EEXIST) || (ENOTEMPTY != EEXIST))
- case ENOTEMPTY: return "enotempty";
-#endif
-#ifdef ENOTNAM
- case ENOTNAM: return "enotnam";
-#endif
-#ifdef ENOTSOCK
- case ENOTSOCK: return "enotsock";
-#endif
-#ifdef ENOTSUP
- case ENOTSUP: return "enotsup";
-#endif
-#ifdef ENOTTY
- case ENOTTY: return "enotty";
-#endif
-#ifdef ENOTUNIQ
- case ENOTUNIQ: return "enotuniq";
-#endif
-#ifdef ENXIO
- case ENXIO: return "enxio";
-#endif
-#if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || EOPNOTSUPP != ENOTSUP)
- case EOPNOTSUPP: return "eopnotsupp";
-#endif
-#ifdef EPERM
- case EPERM: return "eperm";
-#endif
-#if defined(EPFNOSUPPORT) && (!defined(ENOLCK) || (ENOLCK != EPFNOSUPPORT))
- case EPFNOSUPPORT: return "epfnosupport";
-#endif
-#ifdef EPIPE
- case EPIPE: return "epipe";
-#endif
-#ifdef EPROCLIM
- case EPROCLIM: return "eproclim";
-#endif
-#ifdef EPROCUNAVAIL
- case EPROCUNAVAIL: return "eprocunavail";
-#endif
-#ifdef EPROGMISMATCH
- case EPROGMISMATCH: return "eprogmismatch";
-#endif
-#ifdef EPROGUNAVAIL
- case EPROGUNAVAIL: return "eprogunavail";
-#endif
-#ifdef EPROTO
- case EPROTO: return "eproto";
-#endif
-#ifdef EPROTONOSUPPORT
- case EPROTONOSUPPORT: return "eprotonosupport";
-#endif
-#ifdef EPROTOTYPE
- case EPROTOTYPE: return "eprototype";
-#endif
-#ifdef ERANGE
- case ERANGE: return "erange";
-#endif
-#if defined(EREFUSED) && (!defined(ECONNREFUSED) || (EREFUSED != ECONNREFUSED))
- case EREFUSED: return "erefused";
-#endif
-#ifdef EREMCHG
- case EREMCHG: return "eremchg";
-#endif
-#ifdef EREMDEV
- case EREMDEV: return "eremdev";
-#endif
-#ifdef EREMOTE
- case EREMOTE: return "eremote";
-#endif
-#ifdef EREMOTEIO
- case EREMOTEIO: return "eremoteio";
-#endif
-#ifdef EREMOTERELEASE
- case EREMOTERELEASE: return "eremoterelease";
-#endif
-#ifdef EROFS
- case EROFS: return "erofs";
-#endif
-#ifdef ERPCMISMATCH
- case ERPCMISMATCH: return "erpcmismatch";
-#endif
-#ifdef ERREMOTE
- case ERREMOTE: return "erremote";
-#endif
-#ifdef ESHUTDOWN
- case ESHUTDOWN: return "eshutdown";
-#endif
-#ifdef ESOCKTNOSUPPORT
- case ESOCKTNOSUPPORT: return "esocktnosupport";
-#endif
-#ifdef ESPIPE
- case ESPIPE: return "espipe";
-#endif
-#ifdef ESRCH
- case ESRCH: return "esrch";
-#endif
-#ifdef ESRMNT
- case ESRMNT: return "esrmnt";
-#endif
-#ifdef ESTALE
- case ESTALE: return "estale";
-#endif
-#ifdef ESUCCESS
- case ESUCCESS: return "esuccess";
-#endif
-#if defined(ETIME) && (!defined(ELOOP) || (ETIME != ELOOP))
- case ETIME: return "etime";
-#endif
-#if defined(ETIMEDOUT) && (!defined(ENOSTR) || (ETIMEDOUT != ENOSTR))
- case ETIMEDOUT: return "etimedout";
-#endif
-#ifdef ETOOMANYREFS
- case ETOOMANYREFS: return "etoomanyrefs";
-#endif
-#ifdef ETXTBSY
- case ETXTBSY: return "etxtbsy";
-#endif
-#ifdef EUCLEAN
- case EUCLEAN: return "euclean";
-#endif
-#ifdef EUNATCH
- case EUNATCH: return "eunatch";
-#endif
-#ifdef EUSERS
- case EUSERS: return "eusers";
-#endif
-#ifdef EVERSION
- case EVERSION: return "eversion";
-#endif
-#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
- case EWOULDBLOCK: return "ewouldblock";
-#endif
-#ifdef EXDEV
- case EXDEV: return "exdev";
-#endif
-#ifdef EXFULL
- case EXFULL: return "exfull";
-#endif
-#ifdef WSAEINTR
- case WSAEINTR: return "eintr";
-#endif
-#ifdef WSAEBADF
- case WSAEBADF: return "ebadf";
-#endif
-#ifdef WSAEACCES
- case WSAEACCES: return "eacces";
-#endif
-#ifdef WSAEFAULT
- case WSAEFAULT: return "efault";
-#endif
-#ifdef WSAEINVAL
- case WSAEINVAL: return "einval";
-#endif
-#ifdef WSAEMFILE
- case WSAEMFILE: return "emfile";
-#endif
-#ifdef WSAEWOULDBLOCK
- case WSAEWOULDBLOCK: return "ewouldblock";
-#endif
-#ifdef WSAEINPROGRESS
- case WSAEINPROGRESS: return "einprogress";
-#endif
-#ifdef WSAEALREADY
- case WSAEALREADY: return "ealready";
-#endif
-#ifdef WSAENOTSOCK
- case WSAENOTSOCK: return "enotsock";
-#endif
-#ifdef WSAEDESTADDRREQ
- case WSAEDESTADDRREQ: return "edestaddrreq";
-#endif
-#ifdef WSAEMSGSIZE
- case WSAEMSGSIZE: return "emsgsize";
-#endif
-#ifdef WSAEPROTOTYPE
- case WSAEPROTOTYPE: return "eprototype";
-#endif
-#ifdef WSAENOPROTOOPT
- case WSAENOPROTOOPT: return "enoprotoopt";
-#endif
-#ifdef WSAEPROTONOSUPPORT
- case WSAEPROTONOSUPPORT: return "eprotonosupport";
-#endif
-#ifdef WSAESOCKTNOSUPPORT
- case WSAESOCKTNOSUPPORT: return "esocktnosupport";
-#endif
-#ifdef WSAEOPNOTSUPP
- case WSAEOPNOTSUPP: return "eopnotsupp";
-#endif
-#ifdef WSAEPFNOSUPPORT
- case WSAEPFNOSUPPORT: return "epfnosupport";
-#endif
-#ifdef WSAEAFNOSUPPORT
- case WSAEAFNOSUPPORT: return "eafnosupport";
-#endif
-#ifdef WSAEADDRINUSE
- case WSAEADDRINUSE: return "eaddrinuse";
-#endif
-#ifdef WSAEADDRNOTAVAIL
- case WSAEADDRNOTAVAIL: return "eaddrnotavail";
-#endif
-#ifdef WSAENETDOWN
- case WSAENETDOWN: return "enetdown";
-#endif
-#ifdef WSAENETUNREACH
- case WSAENETUNREACH: return "enetunreach";
-#endif
-#ifdef WSAENETRESET
- case WSAENETRESET: return "enetreset";
-#endif
-#ifdef WSAECONNABORTED
- case WSAECONNABORTED: return "econnaborted";
-#endif
-#ifdef WSAECONNRESET
- case WSAECONNRESET: return "econnreset";
-#endif
-#ifdef WSAENOBUFS
- case WSAENOBUFS: return "enobufs";
-#endif
-#ifdef WSAEISCONN
- case WSAEISCONN: return "eisconn";
-#endif
-#ifdef WSAENOTCONN
- case WSAENOTCONN: return "enotconn";
-#endif
-#ifdef WSAESHUTDOWN
- case WSAESHUTDOWN: return "eshutdown";
-#endif
-#ifdef WSAETOOMANYREFS
- case WSAETOOMANYREFS: return "etoomanyrefs";
-#endif
-#ifdef WSAETIMEDOUT
- case WSAETIMEDOUT: return "etimedout";
-#endif
-#ifdef WSAECONNREFUSED
- case WSAECONNREFUSED: return "econnrefused";
-#endif
-#ifdef WSAELOOP
- case WSAELOOP: return "eloop";
-#endif
-#ifdef WSAENAMETOOLONG
- case WSAENAMETOOLONG: return "enametoolong";
-#endif
-#ifdef WSAEHOSTDOWN
- case WSAEHOSTDOWN: return "ehostdown";
-#endif
-#ifdef WSAEHOSTUNREACH
- case WSAEHOSTUNREACH: return "ehostunreach";
-#endif
-#ifdef WSAENOTEMPTY
- case WSAENOTEMPTY: return "enotempty";
-#endif
-#ifdef WSAEPROCLIM
- case WSAEPROCLIM: return "eproclim";
-#endif
-#ifdef WSAEUSERS
- case WSAEUSERS: return "eusers";
-#endif
-#ifdef WSAEDQUOT
- case WSAEDQUOT: return "edquot";
-#endif
-#ifdef WSAESTALE
- case WSAESTALE: return "estale";
-#endif
-#ifdef WSAEREMOTE
- case WSAEREMOTE: return "eremote";
-#endif
-#ifdef WSASYSNOTREADY
- case WSASYSNOTREADY: return "sysnotready";
-#endif
-#ifdef WSAVERNOTSUPPORTED
- case WSAVERNOTSUPPORTED: return "vernotsupported";
-#endif
-#ifdef WSANOTINITIALISED
- case WSANOTINITIALISED: return "notinitialised";
-#endif
-#ifdef WSAEDISCON
- case WSAEDISCON: return "ediscon";
-#endif
-#ifdef WSAENOMORE
- case WSAENOMORE: return "enomore";
-#endif
-#ifdef WSAECANCELLED
- case WSAECANCELLED: return "ecancelled";
-#endif
-#ifdef WSAEINVALIDPROCTABLE
- case WSAEINVALIDPROCTABLE: return "einvalidproctable";
-#endif
-#ifdef WSAEINVALIDPROVIDER
- case WSAEINVALIDPROVIDER: return "einvalidprovider";
-#endif
-#ifdef WSAEPROVIDERFAILEDINIT
- case WSAEPROVIDERFAILEDINIT: return "eproviderfailedinit";
-#endif
-#ifdef WSASYSCALLFAILURE
- case WSASYSCALLFAILURE: return "syscallfailure";
-#endif
-#ifdef WSASERVICE_NOT_FOUND
- case WSASERVICE_NOT_FOUND: return "service_not_found";
-#endif
-#ifdef WSATYPE_NOT_FOUND
- case WSATYPE_NOT_FOUND: return "type_not_found";
-#endif
-#ifdef WSA_E_NO_MORE
- case WSA_E_NO_MORE: return "e_no_more";
-#endif
-#ifdef WSA_E_CANCELLED
- case WSA_E_CANCELLED: return "e_cancelled";
-#endif
- default:
- sprintf(errstrbuf, "unknown:%d", error);
- return errstrbuf;
- }
-}
-
diff --git a/lib/ssl/c_src/esock_posix_str.h b/lib/ssl/c_src/esock_posix_str.h
deleted file mode 100644
index 53916c888a..0000000000
--- a/lib/ssl/c_src/esock_posix_str.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2009. All Rights Reserved.
- *
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * %CopyrightEnd%
- */
-
-/* esock_posix_str.h */
-
-#ifndef ESOCK_POSIX_STR_H
-#define ESOCK_POSIX_STR_H
-
-char *esock_posix_str(int error);
-
-#endif
-
diff --git a/lib/ssl/c_src/esock_ssl.h b/lib/ssl/c_src/esock_ssl.h
deleted file mode 100644
index 535e9a6491..0000000000
--- a/lib/ssl/c_src/esock_ssl.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*<copyright>
- * <year>1999-2008</year>
- * <holder>Ericsson AB, All Rights Reserved</holder>
- *</copyright>
- *<legalnotice>
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * The Initial Developer of the Original Code is Ericsson AB.
- *</legalnotice>
- */
-/*
- * Purpose: Header file for adaptions to various SSL packages.
- */
-
-#ifndef ESOCK_SSL_H
-#define ESOCK_SSL_H
-
-#include <sys/types.h>
-#include <stdio.h>
-#include "esock.h"
-
-typedef struct {
- const char *compile_version;/* version of OpenSSL when compiling esock */
- const char *lib_version; /* version of OpenSSL in library */
-} esock_version;
-
-/* Variables to be set by certain functions (see below) */
-char *esock_ssl_errstr;
-
-/* Ephemeral RSA and DH */
-int ephemeral_rsa, ephemeral_dh;
-
-/* Protocol version (sslv2, sslv3, tlsv1) */
-int protocol_version;
-
-/* version info */
-esock_version *esock_ssl_version(void);
-
-/* ciphers info */
-char *esock_ssl_ciphers(void);
-
-/* seeding */
-void esock_ssl_seed(void *buf, int len);
-
-/* Initialization and finalization of SSL */
-
-int esock_ssl_init(void);
-void esock_ssl_finish(void);
-
-/* Freeing of SSL resources for a connection */
-
-void esock_ssl_free(Connection *cp);
-
-/* Print error diagnostics to a file pointer */
-
-void esock_ssl_print_errors_fp(FILE *fp);
-
-/* All functions below have to return >= 0 on success, and < 0 on
- * failure.
- *
- * If the return indicates a failure (return value < 0) and the failure
- * is temporary the error context (sock_errno()/sock_set_errno()) must
- * be set to ERRNO_BLOCK.
- *
- * If the failure is permanent, the error context must be set to something
- * else than ERRNO_BLOCK, and `esock_ssl_errstr' must be set to point to
- * short diagnostic string describing the error.
- */
-
-int esock_ssl_accept_init(Connection *cp, void *listenssl);
-int esock_ssl_connect_init(Connection *cp);
-int esock_ssl_listen_init(Connection *cp);
-
-/* All functions below may involve non-blocking I/O with a temporary
- * failure. Hence they have to have the error context set to
- * ERRNO_BLOCK, or else have esock_ssl_errstr set to point to a
- * diagnostic string, in case the return value is < 0. If the return
- * value is 0, cp->eof and cp->bp are set, if appropritate.
- */
-
-int esock_ssl_accept(Connection *cp);
-int esock_ssl_connect(Connection *cp);
-
-int esock_ssl_read(Connection *cp, char *buf, int len);
-int esock_ssl_write(Connection *cp, char *buf, int len);
-
-int esock_ssl_shutdown(Connection *cp);
-
-/* Peer certificate */
-
-int esock_ssl_getpeercert(Connection *cp, unsigned char **buf);
-int esock_ssl_getpeercertchain(Connection *cp, unsigned char **buf);
-
-/* Sessions */
-int esock_ssl_session_reused(Connection *cp);
-
-/* Protocol version and cipher of established connection */
-int esock_ssl_getprotocol_version(Connection *cp, char **buf);
-int esock_ssl_getcipher(Connection *cp, char **buf);
-
-#endif
diff --git a/lib/ssl/c_src/esock_utils.c b/lib/ssl/c_src/esock_utils.c
deleted file mode 100644
index 0098a4f5f6..0000000000
--- a/lib/ssl/c_src/esock_utils.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2009. All Rights Reserved.
- *
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * %CopyrightEnd%
- */
-
-/*
- * Purpose: Safe memory allocation and other utilities.
- *
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "esock_utils.h"
-
-static char *strtok_quote(char *s1, const char *s2);
-
-
-void *esock_malloc(size_t size)
-{
- void *p;
-
- p = malloc(size);
- if (!p) {
- fprintf(stderr, "esock_malloc: cannot alloc %d bytes\n", size);
- exit(EXIT_FAILURE);
- }
- return p;
-}
-
-void *esock_realloc(void *p, size_t size)
-{
- void *np;
-
- np = realloc(p, size);
- if (!np) {
- fprintf(stderr, "esock_realloc: cannot realloc %d bytes\n", size);
- exit(EXIT_FAILURE);
- }
- return np;
-}
-
-void esock_free(void *p)
-{
- free(p);
-}
-
-/* Builds an argv array from cmd. Spaces and tabs within double quotes
- * are not considered delimiters. Double quotes are removed.
- *
- * The return value is argc, and the pointer to char ** is set. argc
- * is non-negative, argv[0], ..., argv[argc - 1] are pointers to
- * strings, and argv[argc] == NULL. All argv[0], ..., argv[argc - 1]
- * must be freed by the user, and also the argv pointer itself.
- *
- * Example: cmd = abc"/program files/"olle nisse, results in
- * argv[0] = abc/program files/olle, argv[1] = nisse, argc = 2.
- *
- */
-int esock_build_argv(char *cmd, char ***argvp)
-{
- int argvsize = 10, argc = 0;
- char *args, *tokp, *argp;
- char **argv;
-
- argv = esock_malloc(argvsize * sizeof(char *));
- args = esock_malloc(strlen(cmd) + 1);
- strcpy(args, cmd);
- tokp = strtok_quote(args, " \t");
- while (tokp != NULL) {
- if (argc + 1 >= argvsize) {
- argvsize += 10;
- argv = esock_realloc(argv, argvsize * sizeof(char *));
- }
- argp = esock_malloc(strlen(tokp) + 1);
- strcpy(argp, tokp);
- argv[argc++] = argp;
- tokp = strtok_quote(NULL, " \t");
- }
- esock_free(args);
- argv[argc] = NULL;
- *argvp = argv;
- return argc;
-}
-
-/* strtok_quote
- * Works as strtok, but characters within pairs of double quotes are not
- * considered as delimiters. Quotes are removed.
- */
-static char *strtok_quote(char *s1, const char *s2)
-{
- static char *last;
- char *s, *t, *u;
-
- s = (s1) ? s1 : last;
- if (!s)
- return last = NULL;
-
- while (*s != '"' && *s != '\0' && strchr(s2, *s))
- s++;
- t = s;
-
- while (1) {
- if (*t == '"') {
- t++;
- while (*t != '"' && *t != '\0')
- t++;
- if (*t == '\0') {
- last = NULL;
- goto end;
- }
- t++;
- }
- while(*t != '"' && *t != '\0' && !strchr(s2, *t))
- t++;
- if (*t == '\0') {
- last = NULL;
- goto end;
- } else if (*t != '"') {
- *t = '\0';
- last = t + 1;
- goto end;
- }
- }
-end:
- /* Remove quotes */
- u = t = s;
- while (*u) {
- if (*u == '"')
- u++;
- else
- *t++ = *u++;
- }
- *t = '\0';
- return s;
-}
-
diff --git a/lib/ssl/c_src/esock_utils.h b/lib/ssl/c_src/esock_utils.h
deleted file mode 100644
index 99ed6c23e3..0000000000
--- a/lib/ssl/c_src/esock_utils.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2009. All Rights Reserved.
- *
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * %CopyrightEnd%
- */
-
-#ifndef ESOCK_UTILS_H
-#define ESOCK_UTILS_H
-
-#include <stdlib.h>
-
-void *esock_malloc(size_t size);
-void *esock_realloc(void *p, size_t size);
-void esock_free(void *p);
-int esock_build_argv(char *cmd, char ***argvp);
-
-#endif
-
-
diff --git a/lib/ssl/doc/src/Makefile b/lib/ssl/doc/src/Makefile
index 3119d37af0..5d808d6727 100644
--- a/lib/ssl/doc/src/Makefile
+++ b/lib/ssl/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2010. All Rights Reserved.
+# Copyright Ericsson AB 1999-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -37,7 +37,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
# Target Specs
# ----------------------------------------------------
XML_APPLICATION_FILES = refman.xml
-XML_REF3_FILES = ssl.xml old_ssl.xml ssl_session_cache_api.xml
+XML_REF3_FILES = ssl.xml ssl_session_cache_api.xml
XML_REF6_FILES = ssl_app.xml
XML_PART_FILES = release_notes.xml usersguide.xml
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml
index b2d17925fd..5df2632149 100644
--- a/lib/ssl/doc/src/notes.xml
+++ b/lib/ssl/doc/src/notes.xml
@@ -30,7 +30,59 @@
</header>
<p>This document describes the changes made to the SSL application.</p>
- <section>
+ <section><title>SSL 4.1.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ replace "a ssl" with "an ssl" reindent
+ pkix_path_validation/3 Trivial documentation fixes
+ (Thanks to Christian von Roques )</p>
+ <p>
+ Own Id: OTP-9464</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Adds function clause to avoid denial of service attack.
+ Thanks to Vinod for reporting this vulnerability.</p>
+ <p>
+ Own Id: OTP-9364</p>
+ </item>
+ <item>
+ <p>
+ Error handling code now takes care of inet:getopts/2 and
+ inets:setopts/2 crashes. Thanks to Richard Jones for
+ reporting this.</p>
+ <p>
+ Own Id: OTP-9382</p>
+ </item>
+ <item>
+ <p>
+ Support explicit use of packet option httph and httph_bin</p>
+ <p>
+ Own Id: OTP-9461</p>
+ </item>
+ <item>
+ <p>
+ Decoding of hello extensions could fail to come to the
+ correct conclusion due to an error in a binary match
+ pattern. Thanks to Ben Murphy.</p>
+ <p>
+ Own Id: OTP-9589</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section>
<title>SSL 4.1.5</title>
<section><title>Improvements and New Features</title>
@@ -554,7 +606,7 @@
Own Id: OTP-8224</p>
</item>
<item>
- <p>A ssl:ssl_accept/3 could crash a connection if the
+ <p>An ssl:ssl_accept/3 could crash a connection if the
timing was wrong.</p> <p>Removed info message if the
socket closed without a proper disconnect from the ssl
layer. </p> <p>ssl:send/2 is now blocking until the
@@ -770,7 +822,7 @@
<item>
<p>
The new ssl implementation released as a alfa in this
- version supports upgrading of a tcp connection to a ssl
+ version supports upgrading of a tcp connection to an ssl
connection so that http client and servers may implement
RFC 2817.</p>
<p>
@@ -789,7 +841,7 @@
very crippled as the control of the ssl-socket was deep
down in openssl making it hard if not impossible to
support all inet options, ipv6 and upgrade of a tcp
- connection to a ssl connection. The alfa version has a
+ connection to an ssl connection. The alfa version has a
few limitations that will be removed before the ssl-4.0
release. Main differences and limitations in the alfa are
listed below.</p>
diff --git a/lib/ssl/doc/src/old_ssl.xml b/lib/ssl/doc/src/old_ssl.xml
deleted file mode 100644
index 0d2e1afdbd..0000000000
--- a/lib/ssl/doc/src/old_ssl.xml
+++ /dev/null
@@ -1,709 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1999</year><year>2010</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved online at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- the License for the specific language governing rights and limitations
- under the License.
-
- </legalnotice>
-
- <title>ssl</title>
- <prepared>Peter H&ouml;gfeldt</prepared>
- <responsible>Peter H&ouml;gfeldt</responsible>
- <docno></docno>
- <approved>Peter H&ouml;gfeldt</approved>
- <checked></checked>
- <date>2003-03-25</date>
- <rev>D</rev>
- <file>old_ssl.xml</file>
- </header>
- <module>old_ssl</module>
- <modulesummary>Interface Functions for Secure Socket Layer</modulesummary>
- <description>
- <p>This module contains interface functions to the Secure Socket Layer.</p>
- </description>
-
- <section>
- <title>General</title>
-
- <p>This manual page describes functions that are defined
- in the ssl module and represents the old ssl implementation
- that coexists with the new one until it has been
- totally phased out. </p>
-
- <p>The old implementation can be
- accessed by providing the option {ssl_imp, old} to the
- ssl:connect and ssl:listen functions.</p>
-
- <p>The reader is advised to also read the <c>ssl(6)</c> manual page
- describing the SSL application.
- </p>
- <warning>
- <p>It is strongly advised to seed the random generator after
- the ssl application has been started (see <c>seed/1</c>
- below), and before any connections are established. Although
- the port program interfacing to the ssl libraries does a
- "random" seeding of its own in order to make everything work
- properly, that seeding is by no means random for the world
- since it has a constant value which is known to everyone
- reading the source code of the port program.</p>
- </warning>
- </section>
-
- <section>
- <title>Common data types</title>
- <p>The following datatypes are used in the functions below:
- </p>
- <list type="bulleted">
- <item>
- <p><c>options() = [option()]</c></p>
- </item>
- <item>
- <p><c>option() = socketoption() | ssloption()</c></p>
- </item>
- <item>
- <p><c>socketoption() = {mode, list} | {mode, binary} | binary | {packet, packettype()} | {header, integer()} | {nodelay, boolean()} | {active, activetype()} | {backlog, integer()} | {ip, ipaddress()} | {port, integer()}</c></p>
- </item>
- <item>
- <p><c>ssloption() = {verify, code()} | {depth, depth()} | {certfile, path()} | {keyfile, path()} | {password, string()} | {cacertfile, path()} | {ciphers, string()}</c></p>
- </item>
- <item>
- <p><c>packettype()</c> (see inet(3))</p>
- </item>
- <item>
- <p><c>activetype()</c> (see inet(3))</p>
- </item>
- <item>
- <p><c>reason() = atom() | {atom(), string()}</c></p>
- </item>
- <item>
- <p><c>bytes() = [byte()]</c></p>
- </item>
- <item>
- <p><c>string() = [byte()]</c></p>
- </item>
- <item>
- <p><c>byte() = 0 | 1 | 2 | ... | 255</c></p>
- </item>
- <item>
- <p><c>code() = 0 | 1 | 2</c></p>
- </item>
- <item>
- <p><c>depth() = byte()</c></p>
- </item>
- <item>
- <p><c>address() = hostname() | ipstring() | ipaddress()</c></p>
- </item>
- <item>
- <p><c>ipaddress() = ipstring() | iptuple()</c></p>
- </item>
- <item>
- <p><c>hostname() = string()</c></p>
- </item>
- <item>
- <p><c>ipstring() = string()</c></p>
- </item>
- <item>
- <p><c>iptuple() = {byte(), byte(), byte(), byte()}</c></p>
- </item>
- <item>
- <p><c>sslsocket()</c></p>
- </item>
- <item>
- <p><c>protocol() = sslv2 | sslv3 | tlsv1</c></p>
- </item>
- <item>
- <p><c></c></p>
- </item>
- </list>
- <p>The socket option <c>{backlog, integer()}</c> is for
- <c>listen/2</c> only, and the option <c>{port, integer()}</c>
- is for <c>connect/3/4</c> only.
- </p>
- <p>The following socket options are set by default: <c>{mode, list}</c>, <c>{packet, 0}</c>, <c>{header, 0}</c>, <c>{nodelay, false}</c>, <c>{active, true}</c>, <c>{backlog, 5}</c>,
- <c>{ip, {0,0,0,0}}</c>, and <c>{port, 0}</c>.
- </p>
- <p>Note that the options <c>{mode, binary}</c> and <c>binary</c>
- are equivalent. Similarly <c>{mode, list}</c> and the absence of
- option <c>binary</c> are equivalent.
- </p>
- <p>The ssl options are for setting specific SSL parameters as follows:
- </p>
- <list type="bulleted">
- <item>
- <p><c>{verify, code()}</c> Specifies type of verification:
- 0 = do not verify peer; 1 = verify peer, 2 = verify peer,
- fail if no peer certificate. The default value is 0.
- </p>
- </item>
- <item>
- <p><c>{depth, depth()}</c> Specifies the maximum
- verification depth, i.e. how far in a chain of certificates
- the verification process can proceed before the verification
- is considered to fail.
- </p>
- <p>Peer certificate = 0, CA certificate = 1, higher level CA
- certificate = 2, etc. The value 2 thus means that a chain
- can at most contain peer cert, CA cert, next CA cert, and an
- additional CA cert.
- </p>
- <p>The default value is 1.
- </p>
- </item>
- <item>
- <p><c>{certfile, path()}</c> Path to a file containing the
- user's certificate.
- chain of PEM encoded certificates.</p>
- </item>
- <item>
- <p><c>{keyfile, path()}</c> Path to file containing user's
- private PEM encoded key.</p>
- </item>
- <item>
- <p><c>{password, string()}</c> String containing the user's
- password. Only used if the private keyfile is password protected.</p>
- </item>
- <item>
- <p><c>{cacertfile, path()}</c> Path to file containing PEM encoded
- CA certificates (trusted certificates used for verifying a peer
- certificate).</p>
- </item>
- <item>
- <p><c>{ciphers, string()}</c> String of ciphers as a colon
- separated list of ciphers. The function <c>ciphers/0</c> can
- be used to find all available ciphers.</p>
- </item>
- </list>
- <p>The type <c>sslsocket()</c> is opaque to the user.
- </p>
- <p>The owner of a socket is the one that created it by a call to
- <c>transport_accept/[1,2]</c>, <c>connect/[3,4]</c>,
- or <c>listen/2</c>.
- </p>
- <p>When a socket is in active mode (the default), data from the
- socket is delivered to the owner of the socket in the form of
- messages:
- </p>
- <list type="bulleted">
- <item>
- <p><c>{ssl, Socket, Data}</c></p>
- </item>
- <item>
- <p><c>{ssl_closed, Socket}</c></p>
- </item>
- <item>
- <p><c>{ssl_error, Socket, Reason}</c></p>
- </item>
- </list>
- <p>A <c>Timeout</c> argument specifies a timeout in milliseconds. The
- default value for a <c>Timeout</c> argument is <c>infinity</c>.
- </p>
- <p>Functions listed below may return the value <c>{error, closed}</c>, which only indicates that the SSL socket is
- considered closed for the operation in question. It is for
- instance possible to have <c>{error, closed}</c> returned from
- an call to <c>send/2</c>, and a subsequent call to <c>recv/3</c>
- returning <c>{ok, Data}</c>.
- </p>
- <p>Hence a return value of <c>{error, closed}</c> must not be
- interpreted as if the socket was completely closed. On the
- contrary, in order to free all resources occupied by an SSL
- socket, <c>close/1</c> must be called, or else the process owning
- the socket has to terminate.
- </p>
- <p>For each SSL socket there is an Erlang process representing the
- socket. When a socket is opened, that process links to the
- calling client process. Implementations that want to detect
- abnormal exits from the socket process by receiving <c>{'EXIT', Pid, Reason}</c> messages, should use the function <c>pid/1</c>
- to retrieve the process identifier from the socket, in order to
- be able to match exit messages properly.</p>
- </section>
- <funcs>
- <func>
- <name>ciphers() -> {ok, string()} | {error, enotstarted}</name>
- <fsummary>Get supported ciphers.</fsummary>
- <desc>
- <p>Returns a string consisting of colon separated cipher
- designations that are supported by the current SSL library
- implementation.
- </p>
- <p>The SSL application has to be started to return the string
- of ciphers.</p>
- </desc>
- </func>
- <func>
- <name>close(Socket) -> ok | {error, Reason}</name>
- <fsummary>Close a socket returned by <c>transport_accept/[1,2]</c>, <c>connect/3/4</c>, or <c>listen/2</c>.</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- </type>
- <desc>
- <p>Closes a socket returned by <c>transport_accept/[1,2]</c>,
- <c>connect/[3,4]</c>, or <c>listen/2</c></p>
- </desc>
- </func>
- <func>
- <name>connect(Address, Port, Options) -> {ok, Socket} | {error, Reason}</name>
- <name>connect(Address, Port, Options, Timeout) -> {ok, Socket} | {error, Reason}</name>
- <fsummary>Connect to <c>Port</c>at <c>Address</c>.</fsummary>
- <type>
- <v>Address = address()</v>
- <v>Port = integer()</v>
- <v>Options = [connect_option()]</v>
- <v>connect_option() = {mode, list} | {mode, binary} | binary | {packet, packettype()} | {header, integer()} | {nodelay, boolean()} | {active, activetype()} | {ip, ipaddress()} | {port, integer()} | {verify, code()} | {depth, depth()} | {certfile, path()} | {keyfile, path()} | {password, string()} | {cacertfile, path()} | {ciphers, string()}</v>
- <v>Timeout = integer()</v>
- <v>Socket = sslsocket()</v>
- </type>
- <desc>
- <p>Connects to <c>Port</c> at <c>Address</c>. If the optional
- <c>Timeout</c> argument is specified, and a connection could not
- be established within the given time, <c>{error, timeout}</c> is
- returned. The default value for <c>Timeout</c> is <c>infinity</c>.
- </p>
- <p>The <c>ip</c> and <c>port</c> options are for binding to a
- particular <em>local</em> address and port, respectively.</p>
- </desc>
- </func>
- <func>
- <name>connection_info(Socket) -> {ok, {Protocol, Cipher}} | {error, Reason}</name>
- <fsummary>Get current protocol version and cipher.</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- <v>Protocol = protocol()</v>
- <v>Cipher = string()</v>
- </type>
- <desc>
- <p>Gets the chosen protocol version and cipher for an established
- connection (accepted och connected). </p>
- </desc>
- </func>
- <func>
- <name>controlling_process(Socket, NewOwner) -> ok | {error, Reason}</name>
- <fsummary>Assign a new controlling process to the socket.</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- <v>NewOwner = pid()</v>
- </type>
- <desc>
- <p>Assigns a new controlling process to <c>Socket</c>. A controlling
- process is the owner of a socket, and receives all messages from
- the socket.</p>
- </desc>
- </func>
- <func>
- <name>format_error(ErrorCode) -> string()</name>
- <fsummary>Return an error string.</fsummary>
- <type>
- <v>ErrorCode = term()</v>
- </type>
- <desc>
- <p>Returns a diagnostic string describing an error.</p>
- </desc>
- </func>
- <func>
- <name>getopts(Socket, OptionsTags) -> {ok, Options} | {error, Reason}</name>
- <fsummary>Get options set for socket</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- <v>OptionTags = [optiontag()]()</v>
- </type>
- <desc>
- <p>Returns the options the tags of which are <c>OptionTags</c> for
- for the socket <c>Socket</c>. </p>
- </desc>
- </func>
- <func>
- <name>listen(Port, Options) -> {ok, ListenSocket} | {error, Reason}</name>
- <fsummary>Set up a socket to listen on a port on the local host.</fsummary>
- <type>
- <v>Port = integer()</v>
- <v>Options = [listen_option()]</v>
- <v>listen_option() = {mode, list} | {mode, binary} | binary | {packet, packettype()} | {header, integer()} | {active, activetype()} | {backlog, integer()} | {ip, ipaddress()} | {verify, code()} | {depth, depth()} | {certfile, path()} | {keyfile, path()} | {password, string()} | {cacertfile, path()} | {ciphers, string()}</v>
- <v>ListenSocket = sslsocket()</v>
- </type>
- <desc>
- <p>Sets up a socket to listen on port <c>Port</c> at the local host.
- If <c>Port</c> is zero, <c>listen/2</c> picks an available port
- number (use <c>port/1</c> to retrieve it).
- </p>
- <p>The listen queue size defaults to 5. If a different value is
- wanted, the option <c>{backlog, Size}</c> should be added to the
- list of options.
- </p>
- <p>An empty <c>Options</c> list is considered an error, and
- <c>{error, enooptions}</c> is returned.
- </p>
- <p>The returned <c>ListenSocket</c> can only be used in calls to
- <c>transport_accept/[1,2]</c>.</p>
- </desc>
- </func>
- <func>
- <name>peercert(Socket) -> {ok, Cert} | {error, Reason}</name>
- <fsummary>Return the peer certificate.</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- <v>Cert = binary()()</v>
- <v>Subject = term()()</v>
- </type>
- <desc>
- <p>Returns the DER encoded peer certificate, the certificate can be decoded with
- <c>public_key:pkix_decode_cert/2</c>.
- </p>
- </desc>
- </func>
- <func>
- <name>peername(Socket) -> {ok, {Address, Port}} | {error, Reason}</name>
- <fsummary>Return peer address and port.</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- <v>Address = ipaddress()</v>
- <v>Port = integer()</v>
- </type>
- <desc>
- <p>Returns the address and port number of the peer.</p>
- </desc>
- </func>
- <func>
- <name>pid(Socket) -> pid()</name>
- <fsummary>Return the pid of the socket process.</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- </type>
- <desc>
- <p>Returns the pid of the socket process. The returned pid should
- only be used for receiving exit messages.</p>
- </desc>
- </func>
- <func>
- <name>recv(Socket, Length) -> {ok, Data} | {error, Reason}</name>
- <name>recv(Socket, Length, Timeout) -> {ok, Data} | {error, Reason}</name>
- <fsummary>Receive data on socket.</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- <v>Length = integer() >= 0</v>
- <v>Timeout = integer()</v>
- <v>Data = bytes() | binary()</v>
- </type>
- <desc>
- <p>Receives data on socket <c>Socket</c> when the socket is in
- passive mode, i.e. when the option <c>{active, false}</c>
- has been specified.
- </p>
- <p>A notable return value is <c>{error, closed}</c> which
- indicates that the socket is closed.
- </p>
- <p>A positive value of the <c>Length</c> argument is only
- valid when the socket is in raw mode (option <c>{packet, 0}</c> is set, and the option <c>binary</c> is <em>not</em>
- set); otherwise it should be set to 0, whence all available
- bytes are returned.
- </p>
- <p>If the optional <c>Timeout</c> parameter is specified, and
- no data was available within the given time, <c>{error, timeout}</c> is returned. The default value for
- <c>Timeout</c> is <c>infinity</c>.</p>
- </desc>
- </func>
- <func>
- <name>seed(Data) -> ok | {error, Reason}</name>
- <fsummary>Seed the ssl random generator.</fsummary>
- <type>
- <v>Data = iolist() | binary()</v>
- </type>
- <desc>
- <p>Seeds the ssl random generator.
- </p>
- <p>It is strongly advised to seed the random generator after
- the ssl application has been started, and before any
- connections are established. Although the port program
- interfacing to the OpenSSL libraries does a "random" seeding
- of its own in order to make everything work properly, that
- seeding is by no means random for the world since it has a
- constant value which is known to everyone reading the source
- code of the seeding.
- </p>
- <p>A notable return value is <c>{error, edata}}</c> indicating that
- <c>Data</c> was not a binary nor an iolist.</p>
- </desc>
- </func>
- <func>
- <name>send(Socket, Data) -> ok | {error, Reason}</name>
- <fsummary>Write data to a socket.</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- <v>Data = iolist() | binary()</v>
- </type>
- <desc>
- <p>Writes <c>Data</c> to <c>Socket</c>. </p>
- <p>A notable return value is <c>{error, closed}</c> indicating that
- the socket is closed.</p>
- </desc>
- </func>
- <func>
- <name>setopts(Socket, Options) -> ok | {error, Reason}</name>
- <fsummary>Set socket options.</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- <v>Options = [socketoption]()</v>
- </type>
- <desc>
- <p>Sets options according to <c>Options</c> for the socket
- <c>Socket</c>. </p>
- </desc>
- </func>
- <func>
- <name>ssl_accept(Socket) -> ok | {error, Reason}</name>
- <name>ssl_accept(Socket, Timeout) -> ok | {error, Reason}</name>
- <fsummary>Perform server-side SSL handshake and key exchange</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- <v>Timeout = integer()</v>
- <v>Reason = atom()</v>
- </type>
- <desc>
- <p>The <c>ssl_accept</c> function establish the SSL connection
- on the server side. It should be called directly after
- <c>transport_accept</c>, in the spawned server-loop.</p>
- <p>Note that the ssl connection is not complete until <c>ssl_accept</c>
- has returned <c>true</c>, and if an error is returned, the socket
- is unavailable and for instance <c>close/1</c> will crash.</p>
- </desc>
- </func>
- <func>
- <name>sockname(Socket) -> {ok, {Address, Port}} | {error, Reason}</name>
- <fsummary>Return the local address and port.</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- <v>Address = ipaddress()</v>
- <v>Port = integer()</v>
- </type>
- <desc>
- <p>Returns the local address and port number of the socket
- <c>Socket</c>.</p>
- </desc>
- </func>
- <func>
- <name>transport_accept(Socket) -> {ok, NewSocket} | {error, Reason}</name>
- <name>transport_accept(Socket, Timeout) -> {ok, NewSocket} | {error, Reason}</name>
- <fsummary>Accept an incoming connection and prepare for <c>ssl_accept</c></fsummary>
- <type>
- <v>Socket = NewSocket = sslsocket()</v>
- <v>Timeout = integer()</v>
- <v>Reason = atom()</v>
- </type>
- <desc>
- <p>Accepts an incoming connection request on a listen socket.
- <c>ListenSocket</c> must be a socket returned from <c>listen/2</c>.
- The socket returned should be passed to <c>ssl_accept</c> to
- complete ssl handshaking and establishing the connection.</p>
- <warning>
- <p>The socket returned can only be used with <c>ssl_accept</c>,
- no traffic can be sent or received before that call.</p>
- </warning>
- <p>The accepted socket inherits the options set for <c>ListenSocket</c>
- in <c>listen/2</c>.</p>
- <p>The default value for <c>Timeout</c> is <c>infinity</c>. If
- <c>Timeout</c> is specified, and no connection is accepted within
- the given time, <c>{error, timeout}</c> is returned.</p>
- </desc>
- </func>
- <func>
- <name>version() -> {ok, {SSLVsn, CompVsn, LibVsn}}</name>
- <fsummary>Return the version of SSL.</fsummary>
- <type>
- <v>SSLVsn = CompVsn = LibVsn = string()()</v>
- </type>
- <desc>
- <p>Returns the SSL application version (<c>SSLVsn</c>), the library
- version used when compiling the SSL application port program
- (<c>CompVsn</c>), and the actual library version used when
- dynamically linking in runtime (<c>LibVsn</c>).
- </p>
- <p>If the SSL application has not been started, <c>CompVsn</c> and
- <c>LibVsn</c> are empty strings.
- </p>
- </desc>
- </func>
- </funcs>
-
- <section>
- <title>ERRORS</title>
- <p>The possible error reasons and the corresponding diagnostic strings
- returned by <c>format_error/1</c> are either the same as those defined
- in the <c>inet(3)</c> reference manual, or as follows:
- </p>
- <taglist>
- <tag><c>closed</c></tag>
- <item>
- <p>Connection closed for the operation in question.
- </p>
- </item>
- <tag><c>ebadsocket</c></tag>
- <item>
- <p>Connection not found (internal error).
- </p>
- </item>
- <tag><c>ebadstate</c></tag>
- <item>
- <p>Connection not in connect state (internal error).
- </p>
- </item>
- <tag><c>ebrokertype</c></tag>
- <item>
- <p>Wrong broker type (internal error).
- </p>
- </item>
- <tag><c>ecacertfile</c></tag>
- <item>
- <p>Own CA certificate file is invalid.
- </p>
- </item>
- <tag><c>ecertfile</c></tag>
- <item>
- <p>Own certificate file is invalid.
- </p>
- </item>
- <tag><c>echaintoolong</c></tag>
- <item>
- <p>The chain of certificates provided by peer is too long.
- </p>
- </item>
- <tag><c>ecipher</c></tag>
- <item>
- <p>Own list of specified ciphers is invalid.
- </p>
- </item>
- <tag><c>ekeyfile</c></tag>
- <item>
- <p>Own private key file is invalid.
- </p>
- </item>
- <tag><c>ekeymismatch</c></tag>
- <item>
- <p>Own private key does not match own certificate.
- </p>
- </item>
- <tag><c>enoissuercert</c></tag>
- <item>
- <p>Cannot find certificate of issuer of certificate provided
- by peer.
- </p>
- </item>
- <tag><c>enoservercert</c></tag>
- <item>
- <p>Attempt to do accept without having set own certificate.
- </p>
- </item>
- <tag><c>enotlistener</c></tag>
- <item>
- <p>Attempt to accept on a non-listening socket.
- </p>
- </item>
- <tag><c>enoproxysocket</c></tag>
- <item>
- <p>No proxy socket found (internal error).
- </p>
- </item>
- <tag><c>enooptions</c></tag>
- <item>
- <p>The list of options is empty.
- </p>
- </item>
- <tag><c>enotstarted</c></tag>
- <item>
- <p>The SSL application has not been started.
- </p>
- </item>
- <tag><c>eoptions</c></tag>
- <item>
- <p>Invalid list of options.
- </p>
- </item>
- <tag><c>epeercert</c></tag>
- <item>
- <p>Certificate provided by peer is in error.
- </p>
- </item>
- <tag><c>epeercertexpired</c></tag>
- <item>
- <p>Certificate provided by peer has expired.
- </p>
- </item>
- <tag><c>epeercertinvalid</c></tag>
- <item>
- <p>Certificate provided by peer is invalid.
- </p>
- </item>
- <tag><c>eselfsignedcert</c></tag>
- <item>
- <p>Certificate provided by peer is self signed.
- </p>
- </item>
- <tag><c>esslaccept</c></tag>
- <item>
- <p>Server SSL handshake procedure between client and server failed.
- </p>
- </item>
- <tag><c>esslconnect</c></tag>
- <item>
- <p>Client SSL handshake procedure between client and server failed.
- </p>
- </item>
- <tag><c>esslerrssl</c></tag>
- <item>
- <p>SSL protocol failure. Typically because of a fatal alert
- from peer.
- </p>
- </item>
- <tag><c>ewantconnect</c></tag>
- <item>
- <p>Protocol wants to connect, which is not supported in
- this version of the SSL application.
- </p>
- </item>
- <tag><c>ex509lookup</c></tag>
- <item>
- <p>Protocol wants X.509 lookup, which is not supported in
- this version of the SSL application.
- </p>
- </item>
- <tag><c>{badcall, Call}</c></tag>
- <item>
- <p>Call not recognized for current mode (active or passive) and
- state of socket.
- </p>
- </item>
- <tag><c>{badcast, Cast}</c></tag>
- <item>
- <p>Call not recognized for current mode (active or passive) and
- state of socket.
- </p>
- </item>
- <tag><c>{badinfo, Info}</c></tag>
- <item>
- <p>Call not recognized for current mode (active or passive) and
- state of socket.
- </p>
- </item>
- </taglist>
- </section>
-
- <section>
- <title>SEE ALSO</title>
- <p>gen_tcp(3), inet(3) public_key(3) </p>
- </section>
-
-</erlref>
-
-
diff --git a/lib/ssl/doc/src/refman.xml b/lib/ssl/doc/src/refman.xml
index 68f84660f3..011819e82b 100644
--- a/lib/ssl/doc/src/refman.xml
+++ b/lib/ssl/doc/src/refman.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE application SYSTEM "application.dtd">
<application xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>1999</year><year>2010</year>
+ <year>1999</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -45,7 +45,6 @@
</description>
<xi:include href="ssl_app.xml"/>
<xi:include href="ssl.xml"/>
- <xi:include href="old_ssl.xml"/>
<xi:include href="ssl_session_cache_api.xml"/>
</application>
diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml
index 0da6bbee5b..50268ae206 100644
--- a/lib/ssl/doc/src/ssl.xml
+++ b/lib/ssl/doc/src/ssl.xml
@@ -35,7 +35,7 @@
<title>SSL</title>
<list type="bulleted">
- <item>ssl requires the crypto an public_key applications.</item>
+ <item>ssl requires the crypto and public_key applications.</item>
<item>Supported SSL/TLS-versions are SSL-3.0 and TLS-1.0 </item>
<item>For security reasons sslv2 is not supported.</item>
<item>Ephemeral Diffie-Hellman cipher suites are supported
@@ -71,7 +71,8 @@
{fail_if_no_peer_cert, boolean()}
{depth, integer()} |
{cert, der_encoded()}| {certfile, path()} |
- {key, der_encoded()} | {keyfile, path()} | {password, string()} |
+ {key, {'RSAPrivateKey'| 'DSAPrivateKey' | 'PrivateKeyInfo', der_encoded()}} |
+ {keyfile, path()} | {password, string()} |
{cacerts, [der_encoded()]} | {cacertfile, path()} |
|{dh, der_encoded()} | {dhfile, path()} | {ciphers, ciphers()} |
{ssl_imp, ssl_imp()} | {reuse_sessions, boolean()} | {reuse_session, fun()}
@@ -121,8 +122,6 @@
<p> <c>hash() = md5 | sha
</c></p>
- <p><c>ssl_imp() = new | old - default is new.</c></p>
-
</section>
<section>
@@ -141,7 +140,7 @@
<tag>{certfile, path()}</tag>
<item>Path to a file containing the user's certificate.</item>
- <tag>{key, der_encoded()}</tag>
+ <tag>{key, {'RSAPrivateKey'| 'DSAPrivateKey' | 'PrivateKeyInfo', der_encoded()}}</tag>
<item> The DER encoded users private key. If this option
is supplied it will override the keyfile option.</item>
@@ -177,9 +176,9 @@
by the peer also.
</item>
- <tag>{ssl_imp, ssl_imp()}</tag>
- <item>Specify which ssl implementation you want to use. Defaults to
- new.
+ <tag>{ssl_imp, new | old}</tag>
+ <item>No longer has any meaning as the old implementation has
+ been removed, it will be ignored.
</item>
<tag>{secure_renegotiate, boolean()}</tag>
@@ -216,7 +215,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
application is encountered. Additionally it will be called
when a certificate is considered valid by the path validation
to allow access to each certificate in the path to the user
- application. Note that the it will differentiate between the
+ application. Note that it will differentiate between the
peer certificate and CA certificates by using valid_peer or
valid as the second argument to the verify fun. See <seealso
marker="public_key:cert_records">the public_key User's
@@ -326,10 +325,10 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
</item>
<tag>{fail_if_no_peer_cert, boolean()}</tag>
- <item>Used together with {verify, verify_peer} by a ssl server.
+ <item>Used together with {verify, verify_peer} by an ssl server.
If set to true, the server will fail if the client does not have
a certificate to send, i.e. sends a empty certificate, if set to
- false it will only fail if the client sends a invalid
+ false it will only fail if the client sends an invalid
certificate (an empty certificate is considered valid).
</item>
@@ -343,10 +342,10 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
PeerCert, Compression, CipherSuite) -> boolean()}</tag>
<item>Enables the ssl server to have a local policy
for deciding if a session should be reused or not,
- only meaning full if <c>reuse_sessions</c> is set to true.
+ only meaningful if <c>reuse_sessions</c> is set to true.
SuggestedSessionId is a binary(), PeerCert is a DER encoded
certificate, Compression is an enumeration integer
- and CipherSuite of type ciphersuite().
+ and CipherSuite is of type ciphersuite().
</item>
</taglist>
@@ -355,7 +354,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
<section>
<title>General</title>
- <p>When a ssl socket is in active mode (the default), data from the
+ <p>When an ssl socket is in active mode (the default), data from the
socket is delivered to the owner of the socket in the form of
messages:
</p>
@@ -396,7 +395,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
<name>connect(Socket, SslOptions, Timeout) -> {ok, SslSocket}
| {error, Reason}</name>
<fsummary> Upgrades a gen_tcp, or
- equivalent, connected socket to a ssl socket. </fsummary>
+ equivalent, connected socket to an ssl socket. </fsummary>
<type>
<v>Socket = socket()</v>
<v>SslOptions = [ssloption()]</v>
@@ -405,7 +404,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
<v>Reason = term()</v>
</type>
<desc> <p>Upgrades a gen_tcp, or equivalent,
- connected socket to a ssl socket i.e. performs the
+ connected socket to an ssl socket i.e. performs the
client-side ssl handshake.</p>
</desc>
</func>
@@ -428,12 +427,12 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
<func>
<name>close(SslSocket) -> ok | {error, Reason}</name>
- <fsummary>Close a ssl connection</fsummary>
+ <fsummary>Close an ssl connection</fsummary>
<type>
<v>SslSocket = sslsocket()</v>
<v>Reason = term()</v>
</type>
- <desc><p>Close a ssl connection.</p>
+ <desc><p>Close an ssl connection.</p>
</desc>
</func>
@@ -450,7 +449,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
<v>Reason = term()</v>
</type>
<desc><p>Assigns a new controlling process to the ssl-socket. A
- controlling process is the owner of a ssl-socket, and receives
+ controlling process is the owner of an ssl-socket, and receives
all messages from the socket.</p>
</desc>
</func>
@@ -480,7 +479,6 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
</func>
<func>
- <name>getopts(Socket) -> </name>
<name>getopts(Socket, OptionNames) ->
{ok, [socketoption()]} | {error, Reason}</name>
<fsummary>Get the value of the specified options.</fsummary>
@@ -489,8 +487,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
<v>OptionNames = [atom()]</v>
</type>
<desc>
- <p>Get the value of the specified socket options, if no
- options are specified all options are returned.
+ <p>Get the value of the specified socket options.
</p>
</desc>
</func>
@@ -498,14 +495,14 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
<func>
<name>listen(Port, Options) ->
{ok, ListenSocket} | {error, Reason}</name>
- <fsummary>Creates a ssl listen socket.</fsummary>
+ <fsummary>Creates an ssl listen socket.</fsummary>
<type>
<v>Port = integer()</v>
<v>Options = options()</v>
<v>ListenSocket = sslsocket()</v>
</type>
<desc>
- <p>Creates a ssl listen socket.</p>
+ <p>Creates an ssl listen socket.</p>
</desc>
</func>
@@ -589,6 +586,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
the socket is closed.</p>
</desc>
</func>
+
<func>
<name>setopts(Socket, Options) -> ok | {error, Reason}</name>
<fsummary>Set socket options.</fsummary>
@@ -648,12 +646,12 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
</type>
<desc>
<p> Upgrades a gen_tcp, or
- equivalent, socket to a ssl socket i.e. performs the
+ equivalent, socket to an ssl socket i.e. performs the
ssl server-side handshake.</p>
- <p><warning>Note that the listen socket should be in {active, false} mode
+ <warning><p>Note that the listen socket should be in {active, false} mode
before telling the client that the server is ready to upgrade
and calling this function, otherwise the upgrade may
- or may not succeed depending on timing.</warning></p>
+ or may not succeed depending on timing.</p></warning>
</desc>
</func>
diff --git a/lib/ssl/doc/src/ssl_distribution.xml b/lib/ssl/doc/src/ssl_distribution.xml
index 7bcc12eb5f..4ae4ead3ee 100644
--- a/lib/ssl/doc/src/ssl_distribution.xml
+++ b/lib/ssl/doc/src/ssl_distribution.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2000</year><year>2010</year>
+ <year>2000</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -33,36 +33,32 @@
</header>
<p>This chapter describes how the Erlang distribution can use
SSL to get additional verification and security.
-
- <note><p>Note this
- documentation is written for the old ssl implementation and
- will be updated for the new one once this functionality is
- supported by the new implementation.</p></note>
</p>
<section>
<title>Introduction</title>
<p>The Erlang distribution can in theory use almost any connection
based protocol as bearer. A module that implements the protocol
- specific parts of connection setup is however needed. The
+ specific parts of the connection setup is however needed. The
default distribution module is <c>inet_tcp_dist</c> which is
included in the Kernel application. When starting an
Erlang node distributed, <c>net_kernel</c> uses this module to
setup listen ports and connections. </p>
- <p>In the SSL application there is an additional distribution
- module, <c>inet_ssl_dist</c> which can be used as an
+
+ <p>In the SSL application there is an additional distribution
+ module, <c>inet_tls_dist</c> which can be used as an
alternative. All distribution connections will be using SSL and
all participating Erlang nodes in a distributed system must use
this distribution module.</p>
- <p>The security depends on how the connections are set up, one can
- use key files or certificates to just get a encrypted
- connection. One can also make the SSL package verify the
- certificates of other nodes to get additional security.
- Cookies are however always used as they can be used to
- differentiate between two different Erlang networks.</p>
+
+ <p>The security level depends on the parameters provided to the
+ SSL connection setup. Erlang node cookies are however always
+ used, as they can be used to differentiate between two different
+ Erlang networks.</p>
<p>Setting up Erlang distribution over SSL involves some simple but
necessary steps:</p>
- <list type="bulleted">
+
+ <list type="bulleted">
<item>Building boot scripts including the SSL application</item>
<item>Specifying the distribution module for net_kernel</item>
<item>Specifying security options and other SSL options</item>
@@ -77,122 +73,135 @@
SASL application. Refer to the SASL documentations
for more information on systools. This is only an example of
what can be done.</p>
- <p>The simplest boot script possible includes only the Kernel
+
+ <p>The simplest boot script possible includes only the Kernel
and STDLIB applications. Such a script is located in the
Erlang distributions bin directory. The source for the script
can be found under the Erlang installation top directory under
- <c><![CDATA[releases/<OTP version>start_clean.rel]]></c>. Copy that
+ <c><![CDATA[releases/<OTP version>/start_clean.rel]]></c>. Copy that
script to another location (and preferably another name)
- and add the SSL application with its current version number
+ and add the applications crypto, public_key and SSL with their current version numbers
after the STDLIB application.</p>
<p>An example .rel file with SSL added may look like this:</p>
+
<code type="none">
-{release, {"OTP APN 181 01","P7A"}, {erts, "5.0"},
- [{kernel,"2.5"},
- {stdlib,"1.8.1"},
- {ssl,"2.2.1"}]}. </code>
- <p>Note that the version numbers surely will differ in your system.
- Whenever one of the applications included in the script is
- upgraded, the script has to be changed.</p>
- <p>Assuming the above .rel file is stored in a file
- <c>start_ssl.rel</c> in the current directory, a boot script
- can be built like this:</p>
- <code type="none">
-1> systools:make_script("start_ssl",[]). </code>
- <p>There will now be a file <c>start_ssl.boot</c> in the current
- directory. To test the boot script, start Erlang with the
- <c>-boot</c> command line parameter specifying this boot script
- (with its full path but without the <c>.boot</c> suffix), in
- Unix it could look like this:</p>
- <p></p>
- <code type="none"><![CDATA[
+ {release, {"OTP APN 181 01","R15A"}, {erts, "5.9"},
+ [{kernel,"2.15"},
+ {stdlib,"1.18"},
+ {crypto, "2.0.3"},
+ {public_key, "0.12"},
+ {ssl, "5.0"}
+ ]}.
+ </code>
+
+ <p>Note that the version numbers surely will differ in your system.
+ Whenever one of the applications included in the script is
+ upgraded, the script has to be changed.</p>
+ <p>Assuming the above .rel file is stored in a file
+ <c>start_ssl.rel</c> in the current directory, a boot script
+ can be built like this:</p>
+
+ <code type="none">
+ 1> systools:make_script("start_ssl",[]). </code>
+
+ <p>There will now be a file <c>start_ssl.boot</c> in the current
+ directory. To test the boot script, start Erlang with the
+ <c>-boot</c> command line parameter specifying this boot script
+ (with its full path but without the <c>.boot</c> suffix), in
+ Unix it could look like this:</p>
+ <p></p>
+
+ <code type="none"><![CDATA[
$ erl -boot /home/me/ssl/start_ssl
Erlang (BEAM) emulator version 5.0
Eshell V5.0 (abort with ^G)
-1> whereis(ssl_server).
-<0.32.0> ]]></code>
+1> whereis(ssl_manager).
+<0.41.0> ]]></code>
<p>The <c>whereis</c> function call verifies that the SSL
application is really started.</p>
- <p>As an alternative to building a bootscript, one can explicitly
- add the path to the ssl <c>ebin</c> directory on the command
+
+ <p>As an alternative to building a bootscript, one can explicitly
+ add the path to the SSL <c>ebin</c> directory on the command
line. This is done with the command line option <c>-pa</c>. This
- works as the ssl application really need not be started for the
- distribution to come up, a primitive version of the ssl server
- is started by the distribution module itself, so as long as the
- primitive code server can reach the code, the distribution will
+ works as the SSL application does not need to be started for the
+ distribution to come up, as a clone of the SSL application is
+ hooked into the kernel application, so as long as the
+ SSL applications code can be reached, the distribution will
start. The <c>-pa</c> method is only recommended for testing
purposes.</p>
+
+ <note><p>Note that the clone of the SSL application is necessary to
+ enable the use of the SSL code in such an early bootstage as
+ needed to setup the distribution, however this will make it
+ impossible to soft upgrade the SSL application.</p></note>
</section>
<section>
<title>Specifying distribution module for net_kernel</title>
- <p>The distribution module for SSL is named <c>inet_ssl_dist</c>
- and is specified on the command line whit the <c>-proto_dist</c>
+ <p>The distribution module for SSL is named <c>inet_tls_dist</c>
+ and is specified on the command line with the <c>-proto_dist</c>
option. The argument to <c>-proto_dist</c> should be the module
name without the <c>_dist</c> suffix, so this distribution
- module is specified with <c>-proto_dist inet_ssl</c> on the
+ module is specified with <c>-proto_dist inet_tls</c> on the
command line.</p>
<p></p>
+
<p>Extending the command line from above gives us the following:</p>
<code type="none">
-$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_ssl </code>
- <p>For the distribution to actually be started, we need to give
- the emulator a name as well:</p>
+$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_tls </code>
+
+<p>For the distribution to actually be started, we need to give
+the emulator a name as well:</p>
<code type="none">
-$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_ssl -sname ssl_test
+$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_tls -sname ssl_test
Erlang (BEAM) emulator version 5.0 [source]
Eshell V5.0 (abort with ^G)
(ssl_test@myhost)1> </code>
<p>Note however that a node started in this way will refuse to talk
- to other nodes, as no certificates or key files are supplied
+ to other nodes, as no ssl parameters are supplied
(see below).</p>
- <p>When the SSL distribution starts, the OTP system is in its
- early boot stage, why neither <c>application</c> nor <c>code</c>
- are usable. As SSL needs to start a port program in this early
- stage, it tries to determine the path to that program from the
- primitive code loaders code path. If this fails, one need to
- specify the directory where the port program resides. This can
- be done either with an environment variable
- <c>ERL_SSL_PORTPROGRAM_DIR</c> or with the command line option
- <c>-ssl_portprogram_dir</c>. The value should be the directory
- where the <c>ssl_esock</c> port program is located. Note that
- this option is never needed in a normal Erlang installation.</p>
</section>
<section>
- <title>Specifying security options and other SSL options</title>
- <p>For SSL to work, you either need certificate files or a
- key file. Certificate files can be specified both when working as
- client and as server (connecting or accepting). </p>
- <p></p>
+ <title>Specifying SSL options</title> <p>For SSL to work, at least
+ a public key and certificate needs to be specified for the server
+ side. In the following example the PEM-files consists of two
+ entries the servers certificate and its private key.</p>
+
<p>On the <c>erl</c> command line one can specify options that the
- ssl distribution will add when creation a socket. It is
- mandatory to specify at least a key file or client and server
- certificates. One can specify any <em>SSL option</em> on the
- command line, but must not specify any socket options (like
- packet size and such). The SSL options are listed in the
- Reference Manual. The only difference between the
- options in the reference manual and the ones that can be
- specified to the distribution on the command line is that
- <c>certfile</c> can (and usually needs to) be specified as
- <c>client_certfile</c> and <c>server_certfile</c>. The
- <c>client_certfile</c> is used when the distribution initiates a
- connection to another node and the <c>server_certfile</c> is used
- when accepting a connection from a remote node. </p>
- <p>The command line argument for specifying the SSL options is named
- <c>-ssl_dist_opt</c> and should be followed by an even number of
- SSL options/option values. The <c>-ssl_dist_opt</c> argument can
- be repeated any number of times.</p>
- <p>An example command line would now look something like this
+ SSL distribution will add when creating a socket.</p>
+
+ <p>One can specify the simpler SSL options certfile, keyfile,
+ password, cacertfile, verify, reuse_sessions,
+ secure_renegotiate, depth, hibernate_after and ciphers (use old
+ string format) by adding the prefix server_ or client_ to the
+ option name. The server can also take the options dhfile and
+ fail_if_no_peer_cert (also prefixed).
+ <c>client_</c>-prfixed options are used when the distribution initiates a
+ connection to another node and the <c>server_</c>-prefixed options are used
+ when accepting a connection from a remote node. </p>
+
+ <p> More complex options such as verify_fun are not available at
+ the moment but a mechanism to handle such options may be added in
+ a future release. </p>
+
+ <p> Raw socket options such as packet and size must not be specified on
+ the command line</p>.
+
+ <p>The command line argument for specifying the SSL options is named
+ <c>-ssl_dist_opt</c> and should be followed by pairs of
+ SSL options and their values. The <c>-ssl_dist_opt</c> argument can
+ be repeated any number of times.</p>
+
+ <p>An example command line would now look something like this
(line breaks in the command are for readability,
they should not be there when typed):</p>
<code type="none">
-$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_ssl
- -ssl_dist_opt client_certfile "/home/me/ssl/erlclient.pem"
+$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_tls
-ssl_dist_opt server_certfile "/home/me/ssl/erlserver.pem"
- -ssl_dist_opt verify 1 depth 1
+ -ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true
-sname ssl_test
Erlang (BEAM) emulator version 5.0 [source]
@@ -211,12 +220,11 @@ Eshell V5.0 (abort with ^G)
subsequent invocations of Erlang.</p>
<p></p>
<p>In a Unix (Bourne) shell it could look like this (line breaks for
- readability):</p>
+ readability, they should not be there when typed):</p>
<code type="none">
-$ ERL_FLAGS="-boot \\"/home/me/ssl/start_ssl\\" -proto_dist inet_ssl
- -ssl_dist_opt client_certfile \\"/home/me/ssl/erlclient.pem\\"
- -ssl_dist_opt server_certfile \\"/home/me/ssl/erlserver.pem\\"
- -ssl_dist_opt verify 1 -ssl_dist_opt depth 1"
+$ ERL_FLAGS="-boot /home/me/ssl/start_ssl -proto_dist inet_tls
+ -ssl_dist_opt server_certfile /home/me/ssl/erlserver.pem
+ -ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true"
$ export ERL_FLAGS
$ erl -sname ssl_test
Erlang (BEAM) emulator version 5.0 [source]
@@ -227,15 +235,12 @@ Eshell V5.0 (abort with ^G)
{progname,["erl "]},
{sname,["ssl_test"]},
{boot,["/home/me/ssl/start_ssl"]},
- {proto_dist,["inet_ssl"]},
- {ssl_dist_opt,["client_certfile","/home/me/ssl/erlclient.pem"]},
+ {proto_dist,["inet_tls"]},
{ssl_dist_opt,["server_certfile","/home/me/ssl/erlserver.pem"]},
- {ssl_dist_opt,["verify","1"]},
- {ssl_dist_opt,["depth","1"]},
+ {ssl_dist_opt,["server_secure_renegotiate","true",
+ "client_secure_renegotiate","true"]
{home,["/home/me"]}] </code>
<p>The <c>init:get_arguments()</c> call verifies that the correct
arguments are supplied to the emulator. </p>
</section>
</chapter>
-
-
diff --git a/lib/ssl/doc/src/ssl_protocol.xml b/lib/ssl/doc/src/ssl_protocol.xml
index 6936408881..17268a634d 100644
--- a/lib/ssl/doc/src/ssl_protocol.xml
+++ b/lib/ssl/doc/src/ssl_protocol.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2010</year>
+ <year>2003</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -25,18 +25,18 @@
<file>ssl_protocol.xml</file>
</header>
- <p>The erlang ssl application currently supports SSL 3.0 and TLS 1.0
+ <p>The erlang SSL application currently supports SSL 3.0 and TLS 1.0
RFC 2246, and will in the future also support later versions of TLS.
SSL 2.0 is not supported.
</p>
- <p>By default erlang ssl is run over the TCP/IP protocol even
- though you could plug in an other reliable transport protocol
+ <p>By default erlang SSL is run over the TCP/IP protocol even
+ though you could plug in any other reliable transport protocol
with the same API as gen_tcp.</p>
<p>If a client and server wants to use an upgrade mechanism, such as
- defined by RFC2817, to upgrade a regular TCP/IP connection to a ssl
- connection the erlang ssl API supports this. This can be useful for
+ defined by RFC2817, to upgrade a regular TCP/IP connection to an SSL
+ connection the erlang SSL API supports this. This can be useful for
things such as supporting HTTP and HTTPS on the same port and
implementing virtual hosting.
</p>
@@ -131,7 +131,7 @@
connections. Sessions are used to avoid the expensive negotiation
of new security parameters for each connection."</p>
- <p>Session data is by default kept by the ssl application in a
+ <p>Session data is by default kept by the SSL application in a
memory storage hence session data will be lost at application
restart or takeover. Users may define their own callback module
to handle session data storage if persistent data storage is
@@ -140,8 +140,8 @@
possible to configure the amount of time the session data should be
saved.</p>
- <p>Ssl clients will by default try to reuse an available session,
- ssl servers will by default agree to reuse sessions when clients
+ <p>SSL clients will by default try to reuse an available session,
+ SSL servers will by default agree to reuse sessions when clients
ask to do so.</p>
</section>
diff --git a/lib/ssl/doc/src/using_ssl.xml b/lib/ssl/doc/src/using_ssl.xml
index 605290b6f9..ab837a156a 100644
--- a/lib/ssl/doc/src/using_ssl.xml
+++ b/lib/ssl/doc/src/using_ssl.xml
@@ -56,7 +56,7 @@
<code type="erl">1 server> ssl:start().
ok</code>
- <p>Create a ssl listen socket</p>
+ <p>Create an ssl listen socket</p>
<code type="erl">2 server> {ok, ListenSocket} =
ssl:listen(9999, [{certfile, "cert.pem"}, {keyfile, "key.pem"},{reuseaddr, true}]).
{ok,{sslsocket, [...]}}</code>
@@ -90,7 +90,7 @@ ok</code>
<section>
<title>Upgrade example</title>
- <note><p> To upgrade a TCP/IP connection to a ssl connection the
+ <note><p> To upgrade a TCP/IP connection to an ssl connection the
client and server have to aggre to do so. Agreement
may be accompliced by using a protocol such the one used by HTTP
specified in RFC 2817.</p> </note>
@@ -114,7 +114,7 @@ ok</code>
<code type="erl">2 client> {ok, Socket} = gen_tcp:connect("localhost", 9999, [], infinity).</code>
<p>Make sure active is set to false before trying
- to upgrade a connection to a ssl connection, otherwhise
+ to upgrade a connection to an ssl connection, otherwhise
ssl handshake messages may be deliverd to the wrong process.</p>
<code type="erl">4 server> inet:setopts(Socket, [{active, false}]).
ok</code>
@@ -124,7 +124,7 @@ ok</code>
{certfile, "cert.pem"}, {keyfile, "key.pem"}]).
{ok,{sslsocket,[...]}}</code>
- <p> Upgrade to a ssl connection. Note that the client and server
+ <p> Upgrade to an ssl connection. Note that the client and server
must agree upon the upgrade and the server must call
ssl:accept/2 before the client calls ssl:connect/3.</p>
<code type="erl">3 client>{ok, SSLSocket} = ssl:connect(Socket, [{cacertfile, "cacerts.pem"},
diff --git a/lib/ssl/src/Makefile b/lib/ssl/src/Makefile
index 7514ad2aa2..dc69b53b28 100644
--- a/lib/ssl/src/Makefile
+++ b/lib/ssl/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2010. All Rights Reserved.
+# Copyright Ericsson AB 1999-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -41,12 +41,9 @@ MODULES= \
ssl \
ssl_alert \
ssl_app \
- ssl_broker \
- ssl_broker_sup \
- ssl_server \
+ ssl_dist_sup\
ssl_sup \
- ssl_prim \
- inet_ssl_dist \
+ inet_tls_dist \
ssl_certificate\
ssl_certificate_db\
ssl_cipher \
@@ -62,9 +59,10 @@ MODULES= \
ssl_ssl2 \
ssl_ssl3 \
ssl_tls1 \
+ ssl_tls_dist_proxy
INTERNAL_HRL_FILES = \
- ssl_int.hrl ssl_broker_int.hrl ssl_debug.hrl \
+ ssl_debug.hrl \
ssl_alert.hrl ssl_cipher.hrl ssl_handshake.hrl ssl_internal.hrl \
ssl_record.hrl
diff --git a/lib/ssl/src/inet_ssl_dist.erl b/lib/ssl/src/inet_ssl_dist.erl
deleted file mode 100644
index 6c0fbc0618..0000000000
--- a/lib/ssl/src/inet_ssl_dist.erl
+++ /dev/null
@@ -1,456 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
--module(inet_ssl_dist).
-
-%% Handles the connection setup phase with other Erlang nodes.
-
--export([childspecs/0, listen/1, accept/1, accept_connection/5,
- setup/5, close/1, select/1, is_node_name/1]).
-
-%% internal exports
-
--export([accept_loop/2,do_accept/6,do_setup/6, getstat/1,tick/1]).
-
--import(error_logger,[error_msg/2]).
-
--include("net_address.hrl").
-
-
-
--define(to_port(Socket, Data, Opts),
- case ssl_prim:send(Socket, Data, Opts) of
- {error, closed} ->
- self() ! {ssl_closed, Socket},
- {error, closed};
- R ->
- R
- end).
-
-
--include("dist.hrl").
--include("dist_util.hrl").
-
-%% -------------------------------------------------------------
-%% This function should return a valid childspec, so that
-%% the primitive ssl_server gets supervised
-%% -------------------------------------------------------------
-childspecs() ->
- {ok, [{ssl_server_prim,{ssl_server, start_link_prim, []},
- permanent, 2000, worker, [ssl_server]}]}.
-
-
-%% ------------------------------------------------------------
-%% Select this protocol based on node name
-%% select(Node) => Bool
-%% ------------------------------------------------------------
-
-select(Node) ->
- case split_node(atom_to_list(Node), $@, []) of
- [_,_Host] -> true;
- _ -> false
- end.
-
-%% ------------------------------------------------------------
-%% Create the listen socket, i.e. the port that this erlang
-%% node is accessible through.
-%% ------------------------------------------------------------
-
-listen(Name) ->
- case ssl_prim:listen(0, [{active, false}, {packet,4}] ++
- get_ssl_options(server)) of
- {ok, Socket} ->
- TcpAddress = get_tcp_address(Socket),
- {_,Port} = TcpAddress#net_address.address,
- {ok, Creation} = erl_epmd:register_node(Name, Port),
- {ok, {Socket, TcpAddress, Creation}};
- Error ->
- Error
- end.
-
-%% ------------------------------------------------------------
-%% Accepts new connection attempts from other Erlang nodes.
-%% ------------------------------------------------------------
-
-accept(Listen) ->
- spawn_link(?MODULE, accept_loop, [self(), Listen]).
-
-accept_loop(Kernel, Listen) ->
- process_flag(priority, max),
- case ssl_prim:accept(Listen) of
- {ok, Socket} ->
- Kernel ! {accept,self(),Socket,inet,ssl},
- controller(Kernel, Socket),
- accept_loop(Kernel, Listen);
- Error ->
- exit(Error)
- end.
-
-controller(Kernel, Socket) ->
- receive
- {Kernel, controller, Pid} ->
- flush_controller(Pid, Socket),
- ssl_prim:controlling_process(Socket, Pid),
- flush_controller(Pid, Socket),
- Pid ! {self(), controller};
- {Kernel, unsupported_protocol} ->
- exit(unsupported_protocol)
- end.
-
-flush_controller(Pid, Socket) ->
- receive
- {ssl, Socket, Data} ->
- Pid ! {ssl, Socket, Data},
- flush_controller(Pid, Socket);
- {ssl_closed, Socket} ->
- Pid ! {ssl_closed, Socket},
- flush_controller(Pid, Socket)
- after 0 ->
- ok
- end.
-
-%% ------------------------------------------------------------
-%% Accepts a new connection attempt from another Erlang node.
-%% Performs the handshake with the other side.
-%% ------------------------------------------------------------
-
-accept_connection(AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
- spawn_link(?MODULE, do_accept,
- [self(), AcceptPid, Socket, MyNode,
- Allowed, SetupTime]).
-
-%% Suppress dialyzer warning, we do not really care about old ssl code
-%% as we intend to remove it.
--spec(do_accept(_,_,_,_,_,_) -> no_return()).
-do_accept(Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
- process_flag(priority, max),
- receive
- {AcceptPid, controller} ->
- Timer = dist_util:start_timer(SetupTime),
- case check_ip(Socket) of
- true ->
- HSData = #hs_data{
- kernel_pid = Kernel,
- this_node = MyNode,
- socket = Socket,
- timer = Timer,
- this_flags = 0,
- allowed = Allowed,
- f_send = fun(S,D) -> ssl_prim:send(S,D) end,
- f_recv = fun(S,N,T) -> ssl_prim:recv(S,N,T)
- end,
- f_setopts_pre_nodeup =
- fun(S) ->
- ssl_prim:setopts(S,
- [{active, false}])
- end,
- f_setopts_post_nodeup =
- fun(S) ->
- ssl_prim:setopts(S,
- [{deliver, port},
- {active, true}])
- end,
- f_getll = fun(S) ->
- ssl_prim:getll(S)
- end,
- f_address = fun get_remote_id/2,
- mf_tick = fun ?MODULE:tick/1,
- mf_getstat = fun ?MODULE:getstat/1
- },
- dist_util:handshake_other_started(HSData);
- {false,IP} ->
- error_msg("** Connection attempt from "
- "disallowed IP ~w ** ~n", [IP]),
- ?shutdown(no_node)
- end
- end.
-
-%% ------------------------------------------------------------
-%% Get remote information about a Socket.
-%% ------------------------------------------------------------
-
-get_remote_id(Socket, Node) ->
- {ok, Address} = ssl_prim:peername(Socket),
- [_, Host] = split_node(atom_to_list(Node), $@, []),
- #net_address {
- address = Address,
- host = Host,
- protocol = ssl,
- family = inet }.
-
-%% ------------------------------------------------------------
-%% Setup a new connection to another Erlang node.
-%% Performs the handshake with the other side.
-%% ------------------------------------------------------------
-
-setup(Node, Type, MyNode, LongOrShortNames,SetupTime) ->
- spawn_link(?MODULE, do_setup, [self(),
- Node,
- Type,
- MyNode,
- LongOrShortNames,
- SetupTime]).
-
-%% Suppress dialyzer warning, we do not really care about old ssl code
-%% as we intend to remove it.
--spec(do_setup(_,_,_,_,_,_) -> no_return()).
-do_setup(Kernel, Node, Type, MyNode, LongOrShortNames,SetupTime) ->
- process_flag(priority, max),
- ?trace("~p~n",[{inet_ssl_dist,self(),setup,Node}]),
- [Name, Address] = splitnode(Node, LongOrShortNames),
- case inet:getaddr(Address, inet) of
- {ok, Ip} ->
- Timer = dist_util:start_timer(SetupTime),
- case erl_epmd:port_please(Name, Ip) of
- {port, TcpPort, Version} ->
- ?trace("port_please(~p) -> version ~p~n",
- [Node,Version]),
- dist_util:reset_timer(Timer),
- case ssl_prim:connect(Ip, TcpPort,
- [{active, false},
- {packet,4}] ++
- get_ssl_options(client)) of
- {ok, Socket} ->
- HSData = #hs_data{
- kernel_pid = Kernel,
- other_node = Node,
- this_node = MyNode,
- socket = Socket,
- timer = Timer,
- this_flags = 0,
- other_version = Version,
- f_send = fun(S,D) ->
- ssl_prim:send(S,D)
- end,
- f_recv = fun(S,N,T) ->
- ssl_prim:recv(S,N,T)
- end,
- f_setopts_pre_nodeup =
- fun(S) ->
- ssl_prim:setopts
- (S,
- [{active, false}])
- end,
- f_setopts_post_nodeup =
- fun(S) ->
- ssl_prim:setopts
- (S,
- [{deliver, port},{active, true}])
- end,
- f_getll = fun(S) ->
- ssl_prim:getll(S)
- end,
- f_address =
- fun(_,_) ->
- #net_address {
- address = {Ip,TcpPort},
- host = Address,
- protocol = ssl,
- family = inet}
- end,
- mf_tick = fun ?MODULE:tick/1,
- mf_getstat = fun ?MODULE:getstat/1,
- request_type = Type
- },
- dist_util:handshake_we_started(HSData);
- _ ->
- %% Other Node may have closed since
- %% port_please !
- ?trace("other node (~p) "
- "closed since port_please.~n",
- [Node]),
- ?shutdown(Node)
- end;
- _ ->
- ?trace("port_please (~p) "
- "failed.~n", [Node]),
- ?shutdown(Node)
- end;
- _Other ->
- ?trace("inet_getaddr(~p) "
- "failed (~p).~n", [Node,Other]),
- ?shutdown(Node)
- end.
-
-%%
-%% Close a socket.
-%%
-close(Socket) ->
- ssl_prim:close(Socket).
-
-
-%% If Node is illegal terminate the connection setup!!
-splitnode(Node, LongOrShortNames) ->
- case split_node(atom_to_list(Node), $@, []) of
- [Name|Tail] when Tail =/= [] ->
- Host = lists:append(Tail),
- case split_node(Host, $., []) of
- [_] when LongOrShortNames == longnames ->
- error_msg("** System running to use "
- "fully qualified "
- "hostnames **~n"
- "** Hostname ~s is illegal **~n",
- [Host]),
- ?shutdown(Node);
- [_, _ | _] when LongOrShortNames == shortnames ->
- error_msg("** System NOT running to use fully qualified "
- "hostnames **~n"
- "** Hostname ~s is illegal **~n",
- [Host]),
- ?shutdown(Node);
- _ ->
- [Name, Host]
- end;
- [_] ->
- error_msg("** Nodename ~p illegal, no '@' character **~n",
- [Node]),
- ?shutdown(Node);
- _ ->
- error_msg("** Nodename ~p illegal **~n", [Node]),
- ?shutdown(Node)
- end.
-
-split_node([Chr|T], Chr, Ack) -> [lists:reverse(Ack)|split_node(T, Chr, [])];
-split_node([H|T], Chr, Ack) -> split_node(T, Chr, [H|Ack]);
-split_node([], _, Ack) -> [lists:reverse(Ack)].
-
-%% ------------------------------------------------------------
-%% Fetch local information about a Socket.
-%% ------------------------------------------------------------
-get_tcp_address(Socket) ->
- {ok, Address} = ssl_prim:sockname(Socket),
- {ok, Host} = inet:gethostname(),
- #net_address {
- address = Address,
- host = Host,
- protocol = ssl,
- family = inet
- }.
-
-%% ------------------------------------------------------------
-%% Do only accept new connection attempts from nodes at our
-%% own LAN, if the check_ip environment parameter is true.
-%% ------------------------------------------------------------
-check_ip(Socket) ->
- case application:get_env(check_ip) of
- {ok, true} ->
- case get_ifs(Socket) of
- {ok, IFs, IP} ->
- check_ip(IFs, IP);
- _ ->
- ?shutdown(no_node)
- end;
- _ ->
- true
- end.
-
-get_ifs(Socket) ->
- case ssl_prim:peername(Socket) of
- {ok, {IP, _}} ->
- case ssl_prim:getif(Socket) of
- {ok, IFs} -> {ok, IFs, IP};
- Error -> Error
- end;
- Error ->
- Error
- end.
-
-check_ip([{OwnIP, _, Netmask}|IFs], PeerIP) ->
- case {mask(Netmask, PeerIP), mask(Netmask, OwnIP)} of
- {M, M} -> true;
- _ -> check_ip(IFs, PeerIP)
- end;
-check_ip([], PeerIP) ->
- {false, PeerIP}.
-
-mask({M1,M2,M3,M4}, {IP1,IP2,IP3,IP4}) ->
- {M1 band IP1,
- M2 band IP2,
- M3 band IP3,
- M4 band IP4}.
-
-is_node_name(Node) when is_atom(Node) ->
- case split_node(atom_to_list(Node), $@, []) of
- [_, _Host] -> true;
- _ -> false
- end;
-is_node_name(_Node) ->
- false.
-tick(Sock) ->
- ?to_port(Sock,[],[force]).
-getstat(Socket) ->
- case ssl_prim:getstat(Socket, [recv_cnt, send_cnt, send_pend]) of
- {ok, Stat} ->
- split_stat(Stat,0,0,0);
- Error ->
- Error
- end.
-
-split_stat([{recv_cnt, R}|Stat], _, W, P) ->
- split_stat(Stat, R, W, P);
-split_stat([{send_cnt, W}|Stat], R, _, P) ->
- split_stat(Stat, R, W, P);
-split_stat([{send_pend, P}|Stat], R, W, _) ->
- split_stat(Stat, R, W, P);
-split_stat([], R, W, P) ->
- {ok, R, W, P}.
-
-
-get_ssl_options(Type) ->
- case init:get_argument(ssl_dist_opt) of
- {ok, Args} ->
- ssl_options(Type, Args);
- _ ->
- []
- end.
-
-ssl_options(_,[]) ->
- [];
-ssl_options(server, [["server_certfile", Value]|T]) ->
- [{certfile, Value} | ssl_options(server,T)];
-ssl_options(client, [["client_certfile", Value]|T]) ->
- [{certfile, Value} | ssl_options(client,T)];
-ssl_options(server, [["server_cacertfile", Value]|T]) ->
- [{cacertfile, Value} | ssl_options(server,T)];
-ssl_options(server, [["server_keyfile", Value]|T]) ->
- [{keyfile, Value} | ssl_options(server,T)];
-ssl_options(Type, [["client_certfile", _Value]|T]) ->
- ssl_options(Type,T);
-ssl_options(Type, [["server_certfile", _Value]|T]) ->
- ssl_options(Type,T);
-ssl_options(Type, [[Item, Value]|T]) ->
- [{atomize(Item),fixup(Value)} | ssl_options(Type,T)];
-ssl_options(Type, [[Item,Value |T1]|T2]) ->
- ssl_options(atomize(Type),[[Item,Value],T1|T2]);
-ssl_options(_,_) ->
- exit(malformed_ssl_dist_opt).
-
-fixup(Value) ->
- case catch list_to_integer(Value) of
- {'EXIT',_} ->
- Value;
- Int ->
- Int
- end.
-
-atomize(List) when is_list(List) ->
- list_to_atom(List);
-atomize(Atom) when is_atom(Atom) ->
- Atom.
diff --git a/lib/ssl/src/inet_tls_dist.erl b/lib/ssl/src/inet_tls_dist.erl
new file mode 100644
index 0000000000..115527aae0
--- /dev/null
+++ b/lib/ssl/src/inet_tls_dist.erl
@@ -0,0 +1,275 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(inet_tls_dist).
+
+-export([childspecs/0, listen/1, accept/1, accept_connection/5,
+ setup/5, close/1, select/1, is_node_name/1]).
+
+-include_lib("kernel/include/net_address.hrl").
+-include_lib("kernel/include/dist.hrl").
+-include_lib("kernel/include/dist_util.hrl").
+
+childspecs() ->
+ {ok, [{ssl_dist_sup,{ssl_dist_sup, start_link, []},
+ permanent, 2000, worker, [ssl_dist_sup]}]}.
+
+select(Node) ->
+ case split_node(atom_to_list(Node), $@, []) of
+ [_,_Host] ->
+ true;
+ _ ->
+ false
+ end.
+
+is_node_name(Node) when is_atom(Node) ->
+ select(Node);
+is_node_name(_) ->
+ false.
+
+listen(Name) ->
+ ssl_tls_dist_proxy:listen(Name).
+
+accept(Listen) ->
+ ssl_tls_dist_proxy:accept(Listen).
+
+accept_connection(AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
+ Kernel = self(),
+ spawn_link(fun() -> do_accept(Kernel, AcceptPid, Socket,
+ MyNode, Allowed, SetupTime) end).
+
+setup(Node, Type, MyNode, LongOrShortNames,SetupTime) ->
+ Kernel = self(),
+ spawn(fun() -> do_setup(Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) end).
+
+do_setup(Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
+ [Name, Address] = splitnode(Node, LongOrShortNames),
+ case inet:getaddr(Address, inet) of
+ {ok, Ip} ->
+ Timer = dist_util:start_timer(SetupTime),
+ case erl_epmd:port_please(Name, Ip) of
+ {port, TcpPort, Version} ->
+ ?trace("port_please(~p) -> version ~p~n",
+ [Node,Version]),
+ dist_util:reset_timer(Timer),
+ case ssl_tls_dist_proxy:connect(Ip, TcpPort) of
+ {ok, Socket} ->
+ HSData = connect_hs_data(Kernel, Node, MyNode, Socket,
+ Timer, Version, Ip, TcpPort, Address,
+ Type),
+ dist_util:handshake_we_started(HSData);
+ _ ->
+ %% Other Node may have closed since
+ %% port_please !
+ ?trace("other node (~p) "
+ "closed since port_please.~n",
+ [Node]),
+ ?shutdown(Node)
+ end;
+ _ ->
+ ?trace("port_please (~p) "
+ "failed.~n", [Node]),
+ ?shutdown(Node)
+ end;
+ _Other ->
+ ?trace("inet_getaddr(~p) "
+ "failed (~p).~n", [Node,Other]),
+ ?shutdown(Node)
+ end.
+
+close(Socket) ->
+ try
+ erlang:error(foo)
+ catch _:_ ->
+ io:format("close called ~p ~p~n",[Socket, erlang:get_stacktrace()])
+ end,
+ gen_tcp:close(Socket),
+ ok.
+
+do_accept(Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
+ process_flag(priority, max),
+ receive
+ {AcceptPid, controller} ->
+ Timer = dist_util:start_timer(SetupTime),
+ case check_ip(Socket) of
+ true ->
+ HSData = accept_hs_data(Kernel, MyNode, Socket, Timer, Allowed),
+ dist_util:handshake_other_started(HSData);
+ {false,IP} ->
+ error_logger:error_msg("** Connection attempt from "
+ "disallowed IP ~w ** ~n", [IP]),
+ ?shutdown(no_node)
+ end
+ end.
+%% ------------------------------------------------------------
+%% Do only accept new connection attempts from nodes at our
+%% own LAN, if the check_ip environment parameter is true.
+%% ------------------------------------------------------------
+check_ip(Socket) ->
+ case application:get_env(check_ip) of
+ {ok, true} ->
+ case get_ifs(Socket) of
+ {ok, IFs, IP} ->
+ check_ip(IFs, IP);
+ _ ->
+ ?shutdown(no_node)
+ end;
+ _ ->
+ true
+ end.
+
+get_ifs(Socket) ->
+ case inet:peername(Socket) of
+ {ok, {IP, _}} ->
+ case inet:getif(Socket) of
+ {ok, IFs} -> {ok, IFs, IP};
+ Error -> Error
+ end;
+ Error ->
+ Error
+ end.
+
+check_ip([{OwnIP, _, Netmask}|IFs], PeerIP) ->
+ case {mask(Netmask, PeerIP), mask(Netmask, OwnIP)} of
+ {M, M} -> true;
+ _ -> check_ip(IFs, PeerIP)
+ end;
+check_ip([], PeerIP) ->
+ {false, PeerIP}.
+
+mask({M1,M2,M3,M4}, {IP1,IP2,IP3,IP4}) ->
+ {M1 band IP1,
+ M2 band IP2,
+ M3 band IP3,
+ M4 band IP4};
+
+mask({M1,M2,M3,M4, M5, M6, M7, M8}, {IP1,IP2,IP3,IP4, IP5, IP6, IP7, IP8}) ->
+ {M1 band IP1,
+ M2 band IP2,
+ M3 band IP3,
+ M4 band IP4,
+ M5 band IP5,
+ M6 band IP6,
+ M7 band IP7,
+ M8 band IP8}.
+
+
+%% If Node is illegal terminate the connection setup!!
+splitnode(Node, LongOrShortNames) ->
+ case split_node(atom_to_list(Node), $@, []) of
+ [Name|Tail] when Tail =/= [] ->
+ Host = lists:append(Tail),
+ check_node(Name, Node, Host, LongOrShortNames);
+ [_] ->
+ error_logger:error_msg("** Nodename ~p illegal, no '@' character **~n",
+ [Node]),
+ ?shutdown(Node);
+ _ ->
+ error_logger:error_msg("** Nodename ~p illegal **~n", [Node]),
+ ?shutdown(Node)
+ end.
+
+check_node(Name, Node, Host, LongOrShortNames) ->
+ case split_node(Host, $., []) of
+ [_] when LongOrShortNames == longnames ->
+ error_logger:error_msg("** System running to use "
+ "fully qualified "
+ "hostnames **~n"
+ "** Hostname ~s is illegal **~n",
+ [Host]),
+ ?shutdown(Node);
+ [_, _ | _] when LongOrShortNames == shortnames ->
+ error_logger:error_msg("** System NOT running to use fully qualified "
+ "hostnames **~n"
+ "** Hostname ~s is illegal **~n",
+ [Host]),
+ ?shutdown(Node);
+ _ ->
+ [Name, Host]
+ end.
+
+split_node([Chr|T], Chr, Ack) ->
+ [lists:reverse(Ack)|split_node(T, Chr, [])];
+split_node([H|T], Chr, Ack) ->
+ split_node(T, Chr, [H|Ack]);
+split_node([], _, Ack) ->
+ [lists:reverse(Ack)].
+
+connect_hs_data(Kernel, Node, MyNode, Socket, Timer, Version, Ip, TcpPort, Address, Type) ->
+ common_hs_data(Kernel, MyNode, Socket, Timer,
+ #hs_data{other_node = Node,
+ other_version = Version,
+ f_address =
+ fun(_,_) ->
+ #net_address{address = {Ip,TcpPort},
+ host = Address,
+ protocol = proxy,
+ family = inet}
+ end,
+ request_type = Type
+ }).
+
+accept_hs_data(Kernel, MyNode, Socket, Timer, Allowed) ->
+ common_hs_data(Kernel, MyNode, Socket, Timer, #hs_data{
+ allowed = Allowed,
+ f_address = fun(S, N) ->
+ ssl_tls_dist_proxy:get_remote_id(S, N)
+ end
+ }).
+
+common_hs_data(Kernel, MyNode, Socket, Timer, HsData) ->
+ HsData#hs_data{
+ kernel_pid = Kernel,
+ this_node = MyNode,
+ socket = Socket,
+ timer = Timer,
+ this_flags = 0,
+ f_send =
+ fun(S,D) ->
+ gen_tcp:send(S,D)
+ end,
+ f_recv =
+ fun(S,N,T) ->
+ gen_tcp:recv(S,N,T)
+ end,
+ f_setopts_pre_nodeup =
+ fun(S) ->
+ inet:setopts(S, [{active, false}, {packet, 4}])
+ end,
+ f_setopts_post_nodeup =
+ fun(S) ->
+ inet:setopts(S, [{deliver, port},{active, true}])
+ end,
+ f_getll =
+ fun(S) ->
+ inet:getll(S)
+ end,
+ mf_tick =
+ fun(S) ->
+ gen_tcp:send(S, <<>>)
+ end,
+ mf_getstat =
+ fun(S) ->
+ {ok, Stats} = inet:getstat(S, [recv_cnt, send_cnt, send_pend]),
+ R = proplists:get_value(recv_cnt, Stats, 0),
+ W = proplists:get_value(send_cnt, Stats, 0),
+ P = proplists:get_value(send_pend, Stats, 0),
+ {ok, R,W,P}
+ end}.
diff --git a/lib/ssl/src/ssl.app.src b/lib/ssl/src/ssl.app.src
index b9716786e6..13d5eaf4d7 100644
--- a/lib/ssl/src/ssl.app.src
+++ b/lib/ssl/src/ssl.app.src
@@ -4,11 +4,9 @@
{modules, [ssl,
ssl_app,
ssl_sup,
- ssl_server,
- ssl_broker,
- ssl_broker_sup,
- ssl_prim,
- inet_ssl_dist,
+ inet_tls_dist,
+ ssl_tls_dist_proxy,
+ ssl_dist_sup,
ssl_tls1,
ssl_ssl3,
ssl_ssl2,
@@ -26,7 +24,7 @@
ssl_certificate,
ssl_alert
]},
- {registered, [ssl_sup, ssl_server, ssl_broker_sup]},
+ {registered, [ssl_sup, ssl_manager]},
{applications, [crypto, public_key, kernel, stdlib]},
{env, []},
{mod, {ssl_app, []}}]}.
diff --git a/lib/ssl/src/ssl.appup.src b/lib/ssl/src/ssl.appup.src
index 29674f30da..1b07e76d6a 100644
--- a/lib/ssl/src/ssl.appup.src
+++ b/lib/ssl/src/ssl.appup.src
@@ -1,6 +1,7 @@
%% -*- erlang -*-
{"%VSN%",
[
+ {"4.1.6", [{restart_application, ssl}]},
{"4.1.5", [{restart_application, ssl}]},
{"4.1.4", [{restart_application, ssl}]},
{"4.1.3", [{restart_application, ssl}]},
@@ -10,6 +11,7 @@
{"4.0.1", [{restart_application, ssl}]}
],
[
+ {"4.1.6", [{restart_application, ssl}]},
{"4.1.5", [{restart_application, ssl}]},
{"4.1.4", [{restart_application, ssl}]},
{"4.1.3", [{restart_application, ssl}]},
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index a5e8e7e5c2..d0693445e0 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -25,18 +25,15 @@
-export([start/0, start/1, stop/0, transport_accept/1,
transport_accept/2, ssl_accept/1, ssl_accept/2, ssl_accept/3,
- ciphers/0, cipher_suites/0, cipher_suites/1, close/1, shutdown/2,
+ cipher_suites/0, cipher_suites/1, close/1, shutdown/2,
connect/3, connect/2, connect/4, connection_info/1,
- controlling_process/2, listen/2, pid/1, peername/1, recv/2, recv/3,
- send/2, getopts/2, setopts/2, seed/1, sockname/1, peercert/1,
- peercert/2, version/0, versions/0, session_info/1, format_error/1,
+ controlling_process/2, listen/2, pid/1, peername/1, peercert/1,
+ recv/2, recv/3, send/2, getopts/2, setopts/2, sockname/1,
+ versions/0, session_info/1, format_error/1,
renegotiate/1]).
-%% Should be deprecated as soon as old ssl is removed
-%%-deprecated({pid, 1, next_major_release}).
--deprecated({peercert, 2, next_major_release}).
+-deprecated({pid, 1, next_major_release}).
--include("ssl_int.hrl").
-include("ssl_internal.hrl").
-include("ssl_record.hrl").
-include("ssl_cipher.hrl").
@@ -49,9 +46,12 @@
inet_ssl, %% inet options for internal ssl socket
cb %% Callback info
}).
--type option() :: socketoption() | ssloption() | transportoption().
--type socketoption() :: term(). %% See gen_tcp and inet, import spec later when there is one to import
--type ssloption() :: {verify, verify_type()} |
+-type connect_option() :: socket_connect_option() | ssl_option() | transport_option().
+-type socket_connect_option() :: gen_tcp:connect_option().
+-type listen_option() :: socket_listen_option() | ssl_option() | transport_option().
+-type socket_listen_option() :: gen_tcp:listen_option().
+
+-type ssl_option() :: {verify, verify_type()} |
{verify_fun, {fun(), InitialUserState::term()}} |
{fail_if_no_peer_cert, boolean()} | {depth, integer()} |
{cert, Der::binary()} | {certfile, path()} | {key, Der::binary()} |
@@ -66,7 +66,7 @@
string(). % (according to old API)
-type ssl_imp() :: new | old.
--type transportoption() :: {CallbackModule::atom(), DataTag::atom(), ClosedTag::atom()}.
+-type transport_option() :: {cb_info, {CallbackModule::atom(), DataTag::atom(), ClosedTag::atom()}}.
%%--------------------------------------------------------------------
@@ -96,15 +96,15 @@ stop() ->
application:stop(ssl).
%%--------------------------------------------------------------------
--spec connect(host() | port(), [option()]) -> {ok, #sslsocket{}} |
+-spec connect(host() | port(), [connect_option()]) -> {ok, #sslsocket{}} |
{error, reason()}.
--spec connect(host() | port(), [option()] | port_num(), timeout() | list()) ->
+-spec connect(host() | port(), [connect_option()] | inet:port_number(), timeout() | list()) ->
{ok, #sslsocket{}} | {error, reason()}.
--spec connect(host() | port(), port_num(), list(), timeout()) ->
+-spec connect(host() | port(), inet:port_number(), list(), timeout()) ->
{ok, #sslsocket{}} | {error, reason()}.
%%
-%% Description: Connect to a ssl server.
+%% Description: Connect to an ssl server.
%%--------------------------------------------------------------------
connect(Socket, SslOptions) when is_port(Socket) ->
connect(Socket, SslOptions, infinity).
@@ -112,7 +112,7 @@ connect(Socket, SslOptions) when is_port(Socket) ->
connect(Socket, SslOptions0, Timeout) when is_port(Socket) ->
EmulatedOptions = emulated_options(),
{ok, InetValues} = inet:getopts(Socket, EmulatedOptions),
- inet:setopts(Socket, internal_inet_values()),
+ ok = inet:setopts(Socket, internal_inet_values()),
try handle_options(SslOptions0 ++ InetValues, client) of
{ok, #config{cb=CbInfo, ssl=SslOptions, emulated=EmOpts}} ->
case inet:peername(Socket) of
@@ -131,59 +131,49 @@ connect(Socket, SslOptions0, Timeout) when is_port(Socket) ->
connect(Host, Port, Options) ->
connect(Host, Port, Options, infinity).
-connect(Host, Port, Options0, Timeout) ->
- case proplists:get_value(ssl_imp, Options0, new) of
- new ->
- new_connect(Host, Port, Options0, Timeout);
- old ->
- %% Allow the option reuseaddr to be present
- %% so that new and old ssl can be run by the same
- %% code, however the option will be ignored by old ssl
- %% that hardcodes reuseaddr to true in its portprogram.
- Options1 = proplists:delete(reuseaddr, Options0),
- Options = proplists:delete(ssl_imp, Options1),
- old_connect(Host, Port, Options, Timeout);
- Value ->
- {error, {eoptions, {ssl_imp, Value}}}
+connect(Host, Port, Options, Timeout) ->
+ try handle_options(Options, client) of
+ {ok, Config} ->
+ do_connect(Host,Port,Config,Timeout)
+ catch
+ throw:Error ->
+ Error
end.
%%--------------------------------------------------------------------
--spec listen(port_num(), [option()]) ->{ok, #sslsocket{}} | {error, reason()}.
+-spec listen(inet:port_number(), [listen_option()]) ->{ok, #sslsocket{}} | {error, reason()}.
%%
-%% Description: Creates a ssl listen socket.
+%% Description: Creates an ssl listen socket.
%%--------------------------------------------------------------------
listen(_Port, []) ->
{error, enooptions};
listen(Port, Options0) ->
- case proplists:get_value(ssl_imp, Options0, new) of
- new ->
- new_listen(Port, Options0);
- old ->
- %% Allow the option reuseaddr to be present
- %% so that new and old ssl can be run by the same
- %% code, however the option will be ignored by old ssl
- %% that hardcodes reuseaddr to true in its portprogram.
- Options1 = proplists:delete(reuseaddr, Options0),
- Options = proplists:delete(ssl_imp, Options1),
- old_listen(Port, Options);
- Value ->
- {error, {eoptions, {ssl_imp, Value}}}
+ try
+ {ok, Config} = handle_options(Options0, server),
+ #config{cb={CbModule, _, _, _},inet_user=Options} = Config,
+ case CbModule:listen(Port, Options) of
+ {ok, ListenSocket} ->
+ {ok, #sslsocket{pid = {ListenSocket, Config}, fd = new_ssl}};
+ Err = {error, _} ->
+ Err
+ end
+ catch
+ Error = {error, _} ->
+ Error
end.
-
%%--------------------------------------------------------------------
-spec transport_accept(#sslsocket{}) -> {ok, #sslsocket{}} |
{error, reason()}.
-spec transport_accept(#sslsocket{}, timeout()) -> {ok, #sslsocket{}} |
{error, reason()}.
%%
-%% Description: Performs transport accept on a ssl listen socket
+%% Description: Performs transport accept on an ssl listen socket
%%--------------------------------------------------------------------
transport_accept(ListenSocket) ->
transport_accept(ListenSocket, infinity).
-transport_accept(#sslsocket{pid = {ListenSocket, #config{cb=CbInfo, ssl=SslOpts}},
- fd = new_ssl}, Timeout) ->
+transport_accept(#sslsocket{pid = {ListenSocket, #config{cb=CbInfo, ssl=SslOpts}}}, Timeout) ->
%% The setopt could have been invoked on the listen socket
%% and options should be inherited.
@@ -205,40 +195,30 @@ transport_accept(#sslsocket{pid = {ListenSocket, #config{cb=CbInfo, ssl=SslOpts}
end;
{error, Reason} ->
{error, Reason}
- end;
-
-transport_accept(#sslsocket{} = ListenSocket, Timeout) ->
- ensure_old_ssl_started(),
- {ok, Pid} = ssl_broker:start_broker(acceptor),
- ssl_broker:transport_accept(Pid, ListenSocket, Timeout).
+ end.
%%--------------------------------------------------------------------
-spec ssl_accept(#sslsocket{}) -> ok | {error, reason()}.
--spec ssl_accept(#sslsocket{} | port(), timeout()| [option()]) ->
+-spec ssl_accept(#sslsocket{} | port(), timeout()| [ssl_option() | transport_option()]) ->
ok | {ok, #sslsocket{}} | {error, reason()}.
--spec ssl_accept(port(), [option()], timeout()) -> {ok, #sslsocket{}} | {error, reason()}.
+-spec ssl_accept(port(), [ssl_option()| transport_option()], timeout()) -> {ok, #sslsocket{}} | {error, reason()}.
%%
-%% Description: Performs accept on a ssl listen socket. e.i. performs
+%% Description: Performs accept on an ssl listen socket. e.i. performs
%% ssl handshake.
%%--------------------------------------------------------------------
ssl_accept(ListenSocket) ->
ssl_accept(ListenSocket, infinity).
-ssl_accept(#sslsocket{fd = new_ssl} = Socket, Timeout) ->
+ssl_accept(#sslsocket{} = Socket, Timeout) ->
ssl_connection:handshake(Socket, Timeout);
ssl_accept(ListenSocket, SslOptions) when is_port(ListenSocket) ->
- ssl_accept(ListenSocket, SslOptions, infinity);
-
-%% Old ssl
-ssl_accept(#sslsocket{} = Socket, Timeout) ->
- ensure_old_ssl_started(),
- ssl_broker:ssl_accept(Socket, Timeout).
+ ssl_accept(ListenSocket, SslOptions, infinity).
ssl_accept(Socket, SslOptions, Timeout) when is_port(Socket) ->
EmulatedOptions = emulated_options(),
{ok, InetValues} = inet:getopts(Socket, EmulatedOptions),
- inet:setopts(Socket, internal_inet_values()),
+ ok = inet:setopts(Socket, internal_inet_values()),
try handle_options(SslOptions ++ InetValues, server) of
{ok, #config{cb=CbInfo,ssl=SslOpts, emulated=EmOpts}} ->
{ok, Port} = inet:port(Socket),
@@ -252,27 +232,20 @@ ssl_accept(Socket, SslOptions, Timeout) when is_port(Socket) ->
%%--------------------------------------------------------------------
-spec close(#sslsocket{}) -> term().
%%
-%% Description: Close a ssl connection
+%% Description: Close an ssl connection
%%--------------------------------------------------------------------
-close(#sslsocket{pid = {ListenSocket, #config{cb={CbMod,_, _, _}}}, fd = new_ssl}) ->
+close(#sslsocket{pid = {ListenSocket, #config{cb={CbMod,_, _, _}}}}) ->
CbMod:close(ListenSocket);
-close(#sslsocket{pid = Pid, fd = new_ssl}) ->
- ssl_connection:close(Pid);
-close(Socket = #sslsocket{}) ->
- ensure_old_ssl_started(),
- ssl_broker:close(Socket).
+close(#sslsocket{pid = Pid}) ->
+ ssl_connection:close(Pid).
%%--------------------------------------------------------------------
-spec send(#sslsocket{}, iodata()) -> ok | {error, reason()}.
%%
%% Description: Sends data over the ssl connection
%%--------------------------------------------------------------------
-send(#sslsocket{pid = Pid, fd = new_ssl}, Data) ->
- ssl_connection:send(Pid, Data);
-
-send(#sslsocket{} = Socket, Data) ->
- ensure_old_ssl_started(),
- ssl_broker:send(Socket, Data).
+send(#sslsocket{pid = Pid}, Data) ->
+ ssl_connection:send(Pid, Data).
%%--------------------------------------------------------------------
-spec recv(#sslsocket{}, integer()) -> {ok, binary()| list()} | {error, reason()}.
@@ -283,11 +256,7 @@ send(#sslsocket{} = Socket, Data) ->
recv(Socket, Length) ->
recv(Socket, Length, infinity).
recv(#sslsocket{pid = Pid, fd = new_ssl}, Length, Timeout) ->
- ssl_connection:recv(Pid, Length, Timeout);
-
-recv(Socket = #sslsocket{}, Length, Timeout) ->
- ensure_old_ssl_started(),
- ssl_broker:recv(Socket, Length, Timeout).
+ ssl_connection:recv(Pid, Length, Timeout).
%%--------------------------------------------------------------------
-spec controlling_process(#sslsocket{}, pid()) -> ok | {error, reason()}.
@@ -295,13 +264,8 @@ recv(Socket = #sslsocket{}, Length, Timeout) ->
%% Description: Changes process that receives the messages when active = true
%% or once.
%%--------------------------------------------------------------------
-controlling_process(#sslsocket{pid = Pid, fd = new_ssl}, NewOwner)
- when is_pid(Pid) ->
- ssl_connection:new_user(Pid, NewOwner);
-
-controlling_process(Socket, NewOwner) when is_pid(NewOwner) ->
- ensure_old_ssl_started(),
- ssl_broker:controlling_process(Socket, NewOwner).
+controlling_process(#sslsocket{pid = Pid}, NewOwner) when is_pid(Pid) ->
+ ssl_connection:new_user(Pid, NewOwner).
%%--------------------------------------------------------------------
-spec connection_info(#sslsocket{}) -> {ok, {tls_atom_version(), erl_cipher_suite()}} |
@@ -309,82 +273,31 @@ controlling_process(Socket, NewOwner) when is_pid(NewOwner) ->
%%
%% Description: Returns ssl protocol and cipher used for the connection
%%--------------------------------------------------------------------
-connection_info(#sslsocket{pid = Pid, fd = new_ssl}) ->
- ssl_connection:info(Pid);
+connection_info(#sslsocket{pid = Pid}) ->
+ ssl_connection:info(Pid).
-connection_info(#sslsocket{} = Socket) ->
- ensure_old_ssl_started(),
- ssl_broker:connection_info(Socket).
+%%--------------------------------------------------------------------
+-spec peername(#sslsocket{}) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, reason()}.
+%%
+%% Description: same as inet:peername/1.
+%%--------------------------------------------------------------------
+peername(#sslsocket{pid = Pid}) ->
+ ssl_connection:peername(Pid).
%%--------------------------------------------------------------------
--spec peercert(#sslsocket{}) ->{ok, der_cert()} | {error, reason()}.
+-spec peercert(#sslsocket{}) ->{ok, DerCert::binary()} | {error, reason()}.
%%
%% Description: Returns the peercert.
%%--------------------------------------------------------------------
-peercert(Socket) ->
- peercert(Socket, []).
-
-peercert(#sslsocket{pid = Pid, fd = new_ssl}, Opts) ->
+peercert(#sslsocket{pid = Pid}) ->
case ssl_connection:peer_certificate(Pid) of
{ok, undefined} ->
{error, no_peercert};
- {ok, BinCert} ->
- decode_peercert(BinCert, Opts);
- {error, Reason} ->
- {error, Reason}
- end;
-
-peercert(#sslsocket{} = Socket, Opts) ->
- ensure_old_ssl_started(),
- case ssl_broker:peercert(Socket) of
- {ok, Bin} ->
- decode_peercert(Bin, Opts);
- {error, Reason} ->
- {error, Reason}
- end.
-
-
-decode_peercert(BinCert, Opts) ->
- PKOpts = [case Opt of ssl -> otp; pkix -> plain end ||
- Opt <- Opts, Opt =:= ssl orelse Opt =:= pkix],
- case PKOpts of
- [Opt] ->
- select_part(Opt, public_key:pkix_decode_cert(BinCert, Opt), Opts);
- [] ->
- {ok, BinCert}
- end.
-
-select_part(otp, Cert, Opts) ->
- case lists:member(subject, Opts) of
- true ->
- TBS = Cert#'OTPCertificate'.tbsCertificate,
- {ok, TBS#'OTPTBSCertificate'.subject};
- false ->
- {ok, Cert}
- end;
-
-select_part(plain, Cert, Opts) ->
- case lists:member(subject, Opts) of
- true ->
- TBS = Cert#'Certificate'.tbsCertificate,
- {ok, TBS#'TBSCertificate'.subject};
- false ->
- {ok, Cert}
+ Result ->
+ Result
end.
%%--------------------------------------------------------------------
--spec peername(#sslsocket{}) -> {ok, {tuple(), port_num()}} | {error, reason()}.
-%%
-%% Description: same as inet:peername/1.
-%%--------------------------------------------------------------------
-peername(#sslsocket{fd = new_ssl, pid = Pid}) ->
- ssl_connection:peername(Pid);
-
-peername(#sslsocket{} = Socket) ->
- ensure_old_ssl_started(),
- ssl_broker:peername(Socket).
-
-%%--------------------------------------------------------------------
-spec cipher_suites() -> [erl_cipher_suite()].
-spec cipher_suites(erlang | openssl) -> [erl_cipher_suite()] | [string()].
@@ -402,67 +315,74 @@ cipher_suites(openssl) ->
[ssl_cipher:openssl_suite_name(S) || S <- ssl_cipher:suites(Version)].
%%--------------------------------------------------------------------
--spec getopts(#sslsocket{}, [atom()]) -> {ok, [{atom(), term()}]} | {error, reason()}.
+-spec getopts(#sslsocket{}, [gen_tcp:option_name()]) ->
+ {ok, [gen_tcp:option()]} | {error, reason()}.
%%
%% Description: Gets options
%%--------------------------------------------------------------------
-getopts(#sslsocket{fd = new_ssl, pid = Pid}, OptTags) when is_pid(Pid) ->
- ssl_connection:get_opts(Pid, OptTags);
-getopts(#sslsocket{fd = new_ssl, pid = {ListenSocket, _}}, OptTags) ->
- inet:getopts(ListenSocket, OptTags);
-getopts(#sslsocket{} = Socket, Options) ->
- ensure_old_ssl_started(),
- ssl_broker:getopts(Socket, Options).
+getopts(#sslsocket{pid = Pid}, OptionTags) when is_pid(Pid), is_list(OptionTags) ->
+ ssl_connection:get_opts(Pid, OptionTags);
+getopts(#sslsocket{pid = {ListenSocket, _}}, OptionTags) when is_list(OptionTags) ->
+ try inet:getopts(ListenSocket, OptionTags) of
+ {ok, _} = Result ->
+ Result;
+ {error, InetError} ->
+ {error, {eoptions, {inet_options, OptionTags, InetError}}}
+ catch
+ _:_ ->
+ {error, {eoptions, {inet_options, OptionTags}}}
+ end;
+getopts(#sslsocket{}, OptionTags) ->
+ {error, {eoptions, {inet_options, OptionTags}}}.
%%--------------------------------------------------------------------
--spec setopts(#sslsocket{}, [proplists:property()]) -> ok | {error, reason()}.
+-spec setopts(#sslsocket{}, [gen_tcp:option()]) -> ok | {error, reason()}.
%%
%% Description: Sets options
%%--------------------------------------------------------------------
-setopts(#sslsocket{fd = new_ssl, pid = Pid}, Opts0) when is_pid(Pid) ->
- Opts = proplists:expand([{binary, [{mode, binary}]},
- {list, [{mode, list}]}], Opts0),
- ssl_connection:set_opts(Pid, Opts);
-setopts(#sslsocket{fd = new_ssl, pid = {ListenSocket, _}}, OptTags) ->
- inet:setopts(ListenSocket, OptTags);
-setopts(#sslsocket{} = Socket, Options) ->
- ensure_old_ssl_started(),
- ssl_broker:setopts(Socket, Options).
+setopts(#sslsocket{pid = Pid}, Options0) when is_pid(Pid), is_list(Options0) ->
+ try proplists:expand([{binary, [{mode, binary}]},
+ {list, [{mode, list}]}], Options0) of
+ Options ->
+ ssl_connection:set_opts(Pid, Options)
+ catch
+ _:_ ->
+ {error, {eoptions, {not_a_proplist, Options0}}}
+ end;
+
+setopts(#sslsocket{pid = {ListenSocket, _}}, Options) when is_list(Options) ->
+ try inet:setopts(ListenSocket, Options) of
+ ok ->
+ ok;
+ {error, InetError} ->
+ {error, {eoptions, {inet_options, Options, InetError}}}
+ catch
+ _:Error ->
+ {error, {eoptions, {inet_options, Options, Error}}}
+ end;
+setopts(#sslsocket{}, Options) ->
+ {error, {eoptions,{not_a_proplist, Options}}}.
%%---------------------------------------------------------------
-spec shutdown(#sslsocket{}, read | write | read_write) -> ok | {error, reason()}.
%%
%% Description: Same as gen_tcp:shutdown/2
%%--------------------------------------------------------------------
-shutdown(#sslsocket{pid = {ListenSocket, #config{cb={CbMod,_, _, _}}}, fd = new_ssl}, How) ->
+shutdown(#sslsocket{pid = {ListenSocket, #config{cb={CbMod,_, _, _}}}}, How) ->
CbMod:shutdown(ListenSocket, How);
-shutdown(#sslsocket{pid = Pid, fd = new_ssl}, How) ->
+shutdown(#sslsocket{pid = Pid}, How) ->
ssl_connection:shutdown(Pid, How).
%%--------------------------------------------------------------------
--spec sockname(#sslsocket{}) -> {ok, {tuple(), port_num()}} | {error, reason()}.
+-spec sockname(#sslsocket{}) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, reason()}.
%%
%% Description: Same as inet:sockname/1
%%--------------------------------------------------------------------
-sockname(#sslsocket{fd = new_ssl, pid = {ListenSocket, _}}) ->
+sockname(#sslsocket{pid = {ListenSocket, _}}) ->
inet:sockname(ListenSocket);
-sockname(#sslsocket{fd = new_ssl, pid = Pid}) ->
- ssl_connection:sockname(Pid);
-
-sockname(#sslsocket{} = Socket) ->
- ensure_old_ssl_started(),
- ssl_broker:sockname(Socket).
-
-%%---------------------------------------------------------------
--spec seed(term()) ->term().
-%%
-%% Description: Only used by old ssl.
-%%--------------------------------------------------------------------
-%% TODO: crypto:seed ?
-seed(Data) ->
- ensure_old_ssl_started(),
- ssl_server:seed(Data).
+sockname(#sslsocket{pid = Pid}) ->
+ ssl_connection:sockname(Pid).
%%---------------------------------------------------------------
-spec session_info(#sslsocket{}) -> {ok, list()} | {error, reason()}.
@@ -518,63 +438,6 @@ format_error(esslconnect) ->
format_error({eoptions, Options}) ->
lists:flatten(io_lib:format("Error in options list: ~p~n", [Options]));
-%%%%%%%%%%%% START OLD SSL format_error %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-format_error(ebadsocket) ->
- "Connection not found (internal error).";
-format_error(ebadstate) ->
- "Connection not in connect state (internal error).";
-format_error(ebrokertype) ->
- "Wrong broker type (internal error).";
-format_error(echaintoolong) ->
- "The chain of certificates provided by peer is too long.";
-format_error(ecipher) ->
- "Own list of specified ciphers is invalid.";
-format_error(ekeymismatch) ->
- "Own private key does not match own certificate.";
-format_error(enoissuercert) ->
- "Cannot find certificate of issuer of certificate provided by peer.";
-format_error(enoservercert) ->
- "Attempt to do accept without having set own certificate.";
-format_error(enotlistener) ->
- "Attempt to accept on a non-listening socket.";
-format_error(enoproxysocket) ->
- "No proxy socket found (internal error or max number of file "
- "descriptors exceeded).";
-format_error(enooptions) ->
- "List of options is empty.";
-format_error(enotstarted) ->
- "The SSL application has not been started.";
-format_error(eoptions) ->
- "Invalid list of options.";
-format_error(epeercert) ->
- "Certificate provided by peer is in error.";
-format_error(epeercertexpired) ->
- "Certificate provided by peer has expired.";
-format_error(epeercertinvalid) ->
- "Certificate provided by peer is invalid.";
-format_error(eselfsignedcert) ->
- "Certificate provided by peer is self signed.";
-format_error(esslerrssl) ->
- "SSL protocol failure. Typically because of a fatal alert from peer.";
-format_error(ewantconnect) ->
- "Protocol wants to connect, which is not supported in this "
- "version of the SSL application.";
-format_error(ex509lookup) ->
- "Protocol wants X.509 lookup, which is not supported in this "
- "version of the SSL application.";
-format_error({badcall, _Call}) ->
- "Call not recognized for current mode (active or passive) and state "
- "of socket.";
-format_error({badcast, _Cast}) ->
- "Call not recognized for current mode (active or passive) and state "
- "of socket.";
-
-format_error({badinfo, _Info}) ->
- "Call not recognized for current mode (active or passive) and state "
- "of socket.";
-
-%%%%%%%%%%%%%%%%%% END OLD SSL format_error %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
format_error(Error) ->
case (catch inet:format_error(Error)) of
"unkknown POSIX" ++ _ ->
@@ -588,16 +451,7 @@ format_error(Error) ->
%%%--------------------------------------------------------------
%%% Internal functions
%%%--------------------------------------------------------------------
-new_connect(Address, Port, Options, Timeout) when is_list(Options) ->
- try handle_options(Options, client) of
- {ok, Config} ->
- do_new_connect(Address,Port,Config,Timeout)
- catch
- throw:Error ->
- Error
- end.
-
-do_new_connect(Address, Port,
+do_connect(Address, Port,
#config{cb=CbInfo, inet_user=UserOpts, ssl=SslOpts,
emulated=EmOpts,inet_ssl=SocketOpts},
Timeout) ->
@@ -617,35 +471,9 @@ do_new_connect(Address, Port,
{error, {eoptions, {inet_options, UserOpts}}}
end.
-old_connect(Address, Port, Options, Timeout) ->
- ensure_old_ssl_started(),
- {ok, Pid} = ssl_broker:start_broker(connector),
- ssl_broker:connect(Pid, Address, Port, Options, Timeout).
-
-new_listen(Port, Options0) ->
- try
- {ok, Config} = handle_options(Options0, server),
- #config{cb={CbModule, _, _, _},inet_user=Options} = Config,
- case CbModule:listen(Port, Options) of
- {ok, ListenSocket} ->
- {ok, #sslsocket{pid = {ListenSocket, Config}, fd = new_ssl}};
- Err = {error, _} ->
- Err
- end
- catch
- Error = {error, _} ->
- Error
- end.
-
-old_listen(Port, Options) ->
- ensure_old_ssl_started(),
- {ok, Pid} = ssl_broker:start_broker(listener),
- ssl_broker:listen(Pid, Port, Options).
-
handle_options(Opts0, _Role) ->
Opts = proplists:expand([{binary, [{mode, binary}]},
{list, [{mode, list}]}], Opts0),
-
ReuseSessionFun = fun(_, _, _, _) -> true end,
DefaultVerifyNoneFun =
@@ -712,7 +540,8 @@ handle_options(Opts0, _Role) ->
secure_renegotiate = handle_option(secure_renegotiate, Opts, false),
renegotiate_at = handle_option(renegotiate_at, Opts, ?DEFAULT_RENEGOTIATE_AT),
debug = handle_option(debug, Opts, []),
- hibernate_after = handle_option(hibernate_after, Opts, undefined)
+ hibernate_after = handle_option(hibernate_after, Opts, undefined),
+ erl_dist = handle_option(erl_dist, Opts, false)
},
CbInfo = proplists:get_value(cb_info, Opts, {gen_tcp, tcp, tcp_closed, tcp_error}),
@@ -721,7 +550,7 @@ handle_options(Opts0, _Role) ->
depth, cert, certfile, key, keyfile,
password, cacerts, cacertfile, dh, dhfile, ciphers,
debug, reuse_session, reuse_sessions, ssl_imp,
- cb_info, renegotiate_at, secure_renegotiate, hibernate_after],
+ cb_info, renegotiate_at, secure_renegotiate, hibernate_after, erl_dist],
SockOpts = lists:foldl(fun(Key, PropList) ->
proplists:delete(Key, PropList)
@@ -738,8 +567,6 @@ handle_option(OptionName, Opts, Default) ->
validate_option(versions, Versions) ->
validate_versions(Versions, Versions);
-validate_option(ssl_imp, Value) when Value == new; Value == old ->
- Value;
validate_option(verify, Value)
when Value == verify_none; Value == verify_peer ->
Value;
@@ -781,8 +608,11 @@ validate_option(certfile, Value) when Value == undefined; is_list(Value) ->
validate_option(key, undefined) ->
undefined;
validate_option(key, {KeyType, Value}) when is_binary(Value),
- KeyType == rsa;
- KeyType == dsa ->
+ KeyType == rsa; %% Backwards compatibility
+ KeyType == dsa; %% Backwards compatibility
+ KeyType == 'RSAPrivateKey';
+ KeyType == 'DSAPrivateKey';
+ KeyType == 'PrivateKeyInfo' ->
{KeyType, Value};
validate_option(keyfile, Value) when is_list(Value) ->
Value;
@@ -832,6 +662,9 @@ validate_option(hibernate_after, undefined) ->
undefined;
validate_option(hibernate_after, Value) when is_integer(Value), Value >= 0 ->
Value;
+validate_option(erl_dist,Value) when Value == true;
+ Value == false ->
+ Value;
validate_option(Opt, Value) ->
throw({error, {eoptions, {Opt, Value}}}).
@@ -879,7 +712,6 @@ emulated_options() ->
internal_inet_values() ->
[{packet_size,0},{packet, 0},{header, 0},{active, false},{mode,binary}].
- %%[{packet, ssl},{header, 0},{active, false},{mode,binary}].
socket_options(InetValues) ->
#socket_options{
@@ -940,47 +772,14 @@ cipher_suites(Version, Ciphers0) ->
no_format(Error) ->
lists:flatten(io_lib:format("No format string for error: \"~p\" available.", [Error])).
-
-%% Start old ssl port program if needed.
-ensure_old_ssl_started() ->
- case whereis(ssl_server) of
- undefined ->
- (catch supervisor:start_child(ssl_sup,
- {ssl_server, {ssl_server, start_link, []},
- permanent, 2000, worker, [ssl_server]}));
- _ ->
- ok
- end.
-
-%%%%%%%%%%%%%%%% Deprecated %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-ciphers() ->
- ensure_old_ssl_started(),
- case (catch ssl_server:ciphers()) of
- {'EXIT', _} ->
- {error, enotstarted};
- Res = {ok, _} ->
- Res
- end.
-
-version() ->
- ensure_old_ssl_started(),
- SSLVsn = ?VSN,
- {CompVsn, LibVsn} = case (catch ssl_server:version()) of
- {'EXIT', _} ->
- {"", ""};
- {ok, Vsns} ->
- Vsns
- end,
- {ok, {SSLVsn, CompVsn, LibVsn}}.
-
%% Only used to remove exit messages from old ssl
%% First is a nonsense clause to provide some
-%% backward compability for orber that uses this
+%% backward compatibility for orber that uses this
%% function in a none recommended way, but will
%% work correctly if a valid pid is returned.
+%% Deprcated to be removed in r16
pid(#sslsocket{fd = new_ssl}) ->
- whereis(ssl_connection_sup);
+ whereis(ssl_connection_sup);
pid(#sslsocket{pid = Pid}) ->
- Pid.
+ Pid.
diff --git a/lib/ssl/src/ssl_broker.erl b/lib/ssl/src/ssl_broker.erl
deleted file mode 100644
index 7ef88baf2b..0000000000
--- a/lib/ssl/src/ssl_broker.erl
+++ /dev/null
@@ -1,1188 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-
-%%% Purpose : SSL broker
-
--module(ssl_broker).
--behaviour(gen_server).
-
-%% This module implements brokers for ssl. A broker is either a connector,
-%% an acceptor, or a listener. All brokers are children to ssl_broker_sup,
-%% to which they are linked. Each broker is also linked to ssl_server, and
-%% to its client.
-%%
-%% The purpose of the broker is to set up SSL connections through calls to
-%% ssl_server and gen_tcp. All control information goes to the server,
-%% while all data is exchanged directly between gen_tcp and the port program
-%% of the ssl_server.
-%%
-%% A broker is created by a call to start_broker/3 (do *not* use start_link/4
-%% - it is for ssl_broker_sup to call that one), and then call listen/3,
-%% accept/4, or connect/5.
-%%
-%% The following table shows all functions dependency on status, active
-%% mode etc.
-%%
-%% Permitted status transitions:
-%%
-%% nil -> open
-%% open -> closing | closed (termination)
-%% closing -> closed (termination)
-%%
-%% We are rather sloppy about nil, and consider open/closing == !closed,
-%% open/closing/closed === any etc.
-%%
-%%
-%% function/ valid mode new
-%% message status state
-%%
-%% calls
-%% -----
-%% recv open passive ditto
-%% send open any ditto
-%% transport_accept nil any open
-%% ssl_accept nil any open
-%% connect nil any open
-%% listen nil any open
-%% peername open/closing any ditto
-%% setopts open/closing any ditto
-%% getopts open/closing any ditto
-%% sockname open/closing any ditto
-%% peercert open/closing any ditto
-%% inhibit any any ditto
-%% release any any ditto
-%% close any any closed (1)
-%%
-%% info
-%% ----
-%% tcp open active ditto
-%% tcp_closed open | closing active closing
-%% tcp_error open | closing active closing
-%%
-%% (1) We just terminate.
-%%
-%% TODO
-%%
-%% XXX Timeouts are not checked (integer or infinity).
-%%
-%% XXX The collector thing is not gen_server compliant.
-%%
-%% NOTE: There are three different "modes": (a) passive or active mode,
-%% specified as {active, bool()}, and (b) list or binary mode, specified
-%% as {mode, list | binary}, and (c) encrypted or clear mode
-%%
-
--include("ssl_int.hrl").
-
-%% External exports
-
--export([start_broker/1, start_broker/2, start_link/3,
- transport_accept/3, ssl_accept/2,
- close/1, connect/5, connection_info/1, controlling_process/2,
- listen/3, recv/3, send/2, getopts/2, getopts/3, setopts/2,
- sockname/1, peername/1, peercert/1]).
-
--export([listen_prim/5, connect_prim/8,
- transport_accept_prim/5, ssl_accept_prim/6]).
-
-%% Internal exports
-
--export([init/1, handle_call/3, handle_cast/2, handle_info/2,
- code_change/3, terminate/2, collector_init/1]).
-
--include("ssl_broker_int.hrl").
-
-%% start_broker(Type) -> {ok, Pid} | {error, Reason}
-%% start_broker(Type, GenOpts) -> {ok, Pid} | {error, Reason}
-%% Type = accept | connect | listen
-%% GenOpts = /standard gen_server options/
-%%
-%% This is the function to be called from the interface module ssl.erl.
-%% Links to the caller.
-%%
-start_broker(Type) ->
- start_broker(Type, []).
-
-start_broker(Type, GenOpts) ->
- case lists:member(Type, [listener, acceptor, connector]) of
- true ->
- case supervisor:start_child(ssl_broker_sup,
- [self(), Type, GenOpts]) of
- {ok, Pid} ->
- link(Pid),
- {ok, Pid};
- {error, Reason} ->
- {error, Reason}
- end;
- false ->
- {error, ebrokertype}
- end.
-
-%% start_link(Client, Type, GenOpts) -> {ok, Pid} | {error, Reason}
-%%
-%% Type = accept | connect | listen
-%% GenOpts = /standard gen_server options/
-%%
-%% This function is called by ssl_broker_sup and must *not* be called
-%% from an interface module (ssl.erl).
-
-start_link(Client, Type, GenOpts) ->
- gen_server:start_link(?MODULE, [Client, Type], GenOpts).
-
-
-%% accept(Pid, ListenSocket, Timeout) -> {ok, Socket} | {error, Reason}
-%%
-%% Types: Pid = pid() of acceptor
-%% ListenSocket = Socket = sslsocket()
-%% Timeout = timeout()
-%%
-%% accept(Pid, ListenSocket, Timeout)
-%% when is_pid(Pid), is_record(ListenSocket, sslsocket) ->
-%% Req = {accept, self(), ListenSocket, Timeout},
-%% gen_server:call(Pid, Req, infinity).
-
-%% transport_accept(Pid, ListenSocket, Timeout) -> {ok, Socket} |
-%% {error, Reason}
-%%
-%% Types: Pid = pid() of acceptor
-%% ListenSocket = Socket = sslsocket()
-%% Timeout = timeout()
-%%
-transport_accept(Pid, #sslsocket{} = ListenSocket, Timeout) when is_pid(Pid) ->
- Req = {transport_accept, self(), ListenSocket, Timeout},
- gen_server:call(Pid, Req, infinity).
-
-%% ssl_accept(Pid, Socket, Timeout) -> {ok, Socket} | {error, Reason}
-%%
-%% Types: Pid = pid() of acceptor
-%% ListenSocket = Socket = sslsocket()
-%% Timeout = timeout()
-%%
-ssl_accept(#sslsocket{pid = Pid} = Socket, Timeout) ->
- Req = {ssl_accept, self(), Socket, Timeout},
- gen_server:call(Pid, Req, infinity).
-
-%% close(Socket) -> ok | {error, Reason}
-%%
-%% Types: Socket = sslsocket() | pid()
-%%
-close(#sslsocket{pid = Pid}) ->
- close(Pid);
-close(Pid) when is_pid(Pid) ->
- gen_server:call(Pid, {close, self()}, infinity).
-
-%% connect(Pid, Address, Port, Opts, Timeout) -> {ok, Socket} | {error, Reason}
-%%
-%% Types: Pid = pid() of connector
-%% Address = string() | {byte(), byte(), byte(), byte()}
-%% Port = int()
-%% Opts = options()
-%% Timeout = timeout()
-%% Socket = sslsocket()
-%%
-connect(Pid, Address, Port, Opts, Timeout) when is_pid(Pid), is_list(Opts) ->
- case are_connect_opts(Opts) of
- true ->
- Req = {connect, self(), Address, Port, Opts, Timeout},
- gen_server:call(Pid, Req, infinity);
- false ->
- {error, eoptions}
- end.
-
-%%
-%% connection_info(Socket) -> {ok, {Protocol, Cipher} | {error, Reason}
-%%
-connection_info(#sslsocket{pid = Pid}) ->
- Req = {connection_info, self()},
- gen_server:call(Pid, Req, infinity).
-
-%% controlling_process(Socket, NewOwner) -> ok | {error, Reason}
-
-controlling_process(#sslsocket{pid = Pid}, NewOwner) when is_pid(NewOwner) ->
- case gen_server:call(Pid, {inhibit_msgs, self()}, infinity) of
- ok ->
- transfer_messages(Pid, NewOwner),
- gen_server:call(Pid, {release_msgs, self(), NewOwner}, infinity);
- Error ->
- Error
- end.
-
-%% listen(Pid, Port, Opts) -> {ok, ListenSocket} | {error, Reason}
-%%
-%% Types: Pid = pid() of listener
-%% Port = int()
-%% Opts = options()
-%% ListenSocket = sslsocket()
-%%
-listen(Pid, Port, Opts) when is_pid(Pid) ->
- case are_listen_opts(Opts) of
- true ->
- Req = {listen, self(), Port, Opts},
- gen_server:call(Pid, Req, infinity);
- false ->
- {error, eoptions}
- end.
-
-
-%%
-%% peername(Socket) -> {ok, {Address, Port}} | {error, Reason}
-%%
-peername(#sslsocket{pid = Pid}) ->
- Req = {peername, self()},
- gen_server:call(Pid, Req, infinity).
-
-
-%% recv(Socket, Length, Timeout) -> {ok, Data} | {error, Reason}
-%%
-%% Types: Socket = sslsocket()
-%% Length = Timeout = integer()
-%% Data = bytes() | binary()
-%%
-recv(#sslsocket{pid = Pid}, Length, Timeout) ->
- Req = {recv, self(), Length, Timeout},
- gen_server:call(Pid, Req, infinity).
-
-
-%% send(Socket, Data) -> ok | {error, Reason}
-%%
-%% Types: Socket = sslsocket()
-%%
-send(#sslsocket{pid = Pid}, Data) ->
- gen_server:call(Pid, {send, self(), Data}, infinity).
-
-
-%% getopts(Socket, OptTags) -> {ok, Opts} | {error, einval}
-%%
-%% Types: Pid = pid() of broker
-%% Timeout = timeout()
-%% OptTags = option_tags()
-%% Opts = options()
-%%
-getopts(Socket, OptTags) ->
- getopts(Socket, OptTags, infinity).
-
-getopts(#sslsocket{pid = Pid}, OptTags, Timeout) when is_list(OptTags) ->
- Req = {getopts, self(), OptTags},
- gen_server:call(Pid, Req, Timeout).
-
-
-%%
-%% setopts(Socket, Opts) -> ok | {error, Reason}
-%%
-setopts(#sslsocket{pid = Pid}, Opts) ->
- Req = {setopts, self(), Opts},
- gen_server:call(Pid, Req, infinity).
-
-%%
-%% sockname(Socket) -> {ok, {Address, Port}} | {error, Reason}
-%%
-sockname(#sslsocket{pid = Pid}) ->
- Req = {sockname, self()},
- gen_server:call(Pid, Req, infinity).
-
-
-%%
-%% peercert(Socket) -> {ok, Cert} | {error, Reason}
-%%
-peercert(#sslsocket{pid = Pid}) ->
- Req = {peercert, self()},
- gen_server:call(Pid, Req, infinity).
-
-%%
-%% INIT
-%%
-
-%% init
-%%
-init([Client, Type]) ->
- process_flag(trap_exit, true),
- link(Client),
- Debug = case application:get_env(ssl, edebug) of
- {ok, true} ->
- true;
- _ ->
- case application:get_env(ssl, debug) of
- {ok, true} ->
- true;
- _ ->
- os:getenv("ERL_SSL_DEBUG") =/= false
- end
- end,
- Server = whereis(ssl_server),
- if
- is_pid(Server) ->
- link(Server),
- debug1(Debug, Type, "in start, client = ~w", [Client]),
- {ok, #st{brokertype = Type, server = Server, client = Client,
- collector = Client, debug = Debug}};
- true ->
- {stop, no_ssl_server}
- end.
-
-
-%%
-%% HANDLE CALL
-%%
-
-%% recv - passive mode
-%%
-handle_call({recv, Client, Length, Timeout}, _From,
- #st{active = false, proxysock = Proxysock, status = Status} = St) ->
- debug(St, "recv: client = ~w~n", [Client]),
- if
- Status =/= open ->
- {reply, {error, closed}, St};
- true ->
- case gen_tcp:recv(Proxysock, Length, Timeout) of
- {ok, Data} ->
- {reply, {ok, Data}, St};
- {error, timeout} ->
- {reply, {error, timeout}, St};
- {error, Reason} ->
- {reply, {error, Reason}, St#st{status = closing}}
- end
- end;
-
-%% send
-%%
-handle_call({send, Client, Data}, _From, St) ->
- debug(St, "send: client = ~w~n", [Client]),
- if
- St#st.status =/= open ->
- {reply, {error, closed}, St};
- true ->
- case gen_tcp:send(St#st.proxysock, Data) of
- ok ->
- {reply, ok, St};
- {error, _Reason} ->
- {reply, {error, closed}, St#st{status = closing}}
- end
- end;
-
-%% transport_accept
-%%
-%% Client = pid of client
-%% ListenSocket = sslsocket()
-%%
-handle_call({transport_accept, Client, ListenSocket, Timeout}, _From, St) ->
- debug(St, "transport_accept: client = ~w, listensocket = ~w~n",
- [Client, ListenSocket]),
- case getopts(ListenSocket, tcp_listen_opt_tags(), ?DEF_TIMEOUT) of
- {ok, LOpts} ->
- case transport_accept_prim(
- ssl_server, ListenSocket#sslsocket.fd, LOpts, Timeout, St) of
- {ok, ThisSocket, NSt} ->
- {reply, {ok, ThisSocket}, NSt};
- {error, Reason, St} ->
- What = what(Reason),
- {stop, normal, {error, What}, St}
- end;
- {error, Reason} ->
- What = what(Reason),
- {stop, normal, {error, What}, St}
- end;
-
-%% ssl_accept
-%%
-%% Client = pid of client
-%% ListenSocket = sslsocket()
-%%
-handle_call({ssl_accept, Client, Socket, Timeout}, _From, St) ->
- debug(St, "ssl_accept: client = ~w, socket = ~w~n", [Client, Socket]),
- case ssl_accept_prim(ssl_server, gen_tcp, Client, St#st.opts, Timeout, St#st{thissock=Socket}) of
- {ok, Socket, NSt} ->
- {reply, ok, NSt};
- {error, Reason, St} ->
- What = what(Reason),
- {stop, normal, {error, What}, St}
- end;
-
-%% connect
-%%
-%% Client = client pid
-%% Address = hostname | ipstring | IP
-%% Port = integer()
-%% Opts = options()
-%%
-handle_call({connect, Client, Address, Port, Opts, Timeout}, _From, St) ->
- debug(St, "connect: client = ~w, address = ~p, port = ~w~n",
- [Client, Address, Port]),
- case connect_prim(ssl_server, gen_tcp, Client, Address, Port, Opts,
- Timeout, St) of
- {ok, Res, NSt} ->
- {reply, {ok, Res}, NSt};
- {error, Reason, NSt} ->
- What = what(Reason),
- {stop, normal, {error, What}, NSt}
- end;
-
-%% connection_info
-%%
-handle_call({connection_info, Client}, _From, St) ->
- debug(St, "connection_info: client = ~w~n", [Client]),
- Reply = ssl_server:connection_info(St#st.fd),
- {reply, Reply, St};
-
-%% close from client
-%%
-handle_call({close, Client}, _From, St) ->
- debug(St, "close: client = ~w~n", [Client]),
- %% Terminate
- {stop, normal, ok, St#st{status = closed}};
-
-%% listen
-%%
-%% Client = pid of client
-%% Port = int()
-%% Opts = options()
-%%
-handle_call({listen, Client, Port, Opts}, _From, St) ->
- debug(St, "listen: client = ~w, port = ~w~n",
- [Client, Port]),
- case listen_prim(ssl_server, Client, Port, Opts, St) of
- {ok, Res, NSt} ->
- {reply, {ok, Res}, NSt};
- {error, Reason, NSt} ->
- What = what(Reason),
- {stop, normal, {error, What}, NSt}
- end;
-
-%% peername
-%%
-handle_call({peername, Client}, _From, St) ->
- debug(St, "peername: client = ~w~n", [Client]),
- Reply = case ssl_server:peername(St#st.fd) of
- {ok, {Address, Port}} ->
- {ok, At} = inet_parse:ipv4_address(Address),
- {ok, {At, Port}};
- Error ->
- Error
- end,
- {reply, Reply, St};
-
-%% setopts
-%%
-handle_call({setopts, Client, Opts0}, _From, St0) ->
- debug(St0, "setopts: client = ~w~n", [Client]),
- OptsOK = case St0#st.brokertype of
- listener ->
- are_opts(fun is_tcp_listen_opt/1, Opts0);
- acceptor ->
- are_opts(fun is_tcp_accept_opt/1, Opts0);
- connector ->
- are_opts(fun is_tcp_connect_opt/1, Opts0)
- end,
- if
- OptsOK =:= false ->
- {reply, {error, eoptions}, St0};
- true ->
- Opts1 = lists:keydelete(nodelay, 1, Opts0),
- case inet:setopts(St0#st.proxysock, Opts1) of
- ok ->
- Opts2 = replace_opts(Opts1, St0#st.opts),
- Active = get_active(Opts2),
- St2 = St0#st{opts = Opts2,
- active = Active},
- case get_nodelay(Opts0) of
- empty ->
- {reply, ok, St2};
- Bool ->
- case setnodelay(ssl_server, St0, Bool) of
- ok ->
- Opts3 = replace_opts([{nodelay, Bool}],
- Opts2),
- St3 = St0#st{opts = Opts3,
- active = Active},
- {reply, ok, St3};
- {error, Reason} ->
- {reply, {error, Reason}, St2}
- end
- end;
- {error, Reason} ->
- {reply, {error, Reason}, St0}
- end
- end;
-
-%% sockname
-%%
-handle_call({sockname, Client}, _From, St) ->
- debug(St, "sockname: client = ~w~n", [Client]),
- Reply = case ssl_server:sockname(St#st.fd) of
- {ok, {Address, Port}} ->
- {ok, At} = inet_parse:ipv4_address(Address),
- {ok, {At, Port}};
- Error ->
- Error
- end,
- {reply, Reply, St};
-
-%% peercert
-%%
-handle_call({peercert, Client}, _From, St) ->
- debug(St, "peercert: client = ~w~n", [Client]),
- Reply = ssl_server:peercert(St#st.fd),
- {reply, Reply, St};
-
-%% inhibit msgs
-%%
-handle_call({inhibit_msgs, Client}, _From, #st{client = Client} = St) ->
- debug(St, "inhibit_msgs: client = ~w~n", [Client]),
- {ok, Collector} = start_collector(),
- {reply, ok, St#st{collector = Collector}};
-
-%% release msgs
-%%
-handle_call({release_msgs, Client, NewClient}, _From,
- #st{client = Client, collector = Collector} = St) ->
- debug(St, "release_msgs: client = ~w~n", [Client]),
- unlink(Client),
- link(NewClient),
- release_collector(Collector, NewClient),
- NSt = St#st{client = NewClient, collector = NewClient},
- {reply, ok, NSt};
-
-%% getopts
-%%
-handle_call({getopts, Client, OptTags}, _From, St) ->
- debug(St, "getopts: client = ~w~n", [Client]),
- Reply = case are_opt_tags(St#st.brokertype, OptTags) of
- true ->
- {ok, extract_opts(OptTags, St#st.opts)};
- _ ->
- {error, einval}
- end,
- {reply, Reply, St};
-
-%% bad call
-%%
-handle_call(Request, _From, St) ->
- debug(St, "++++ ssl_broker: bad call: ~w~n", [Request]),
- {reply, {error, {badcall, Request}}, St}.
-
-%%
-%% HANDLE CAST
-%%
-
-handle_cast(Request, St) ->
- debug(St, "++++ ssl_broker: bad cast: ~w~n", [Request]),
- {stop, {error, {badcast, Request}}, St}.
-
-%%
-%% HANDLE INFO
-%%
-
-%% tcp - active mode
-%%
-%% The collector is different from client only during change of
-%% controlling process.
-%%
-handle_info({tcp, Socket, Data},
- #st{active = Active, collector = Collector, status = open,
- proxysock = Socket, thissock = Thissock} = St)
- when Active =/= false ->
- debug(St, "tcp: socket = ~w~n", [Socket]),
- Msg = {ssl, Thissock, Data},
- Collector ! Msg,
- if
- Active =:= once ->
- {noreply, St#st{active = false}};
- true ->
- {noreply, St}
- end;
-
-%% tcp_closed - from proxy socket, active mode
-%%
-%%
-handle_info({tcp_closed, Socket},
- #st{active = Active, collector = Collector,
- proxysock = Socket, thissock = Thissock} = St)
- when Active =/= false ->
- debug(St, "tcp_closed: socket = ~w~n", [Socket]),
- Msg = {ssl_closed, Thissock},
- Collector ! Msg,
- if
- Active =:= once ->
- {noreply, St#st{status = closing, active = false}};
- true ->
- {noreply, St#st{status = closing}}
- end;
-
-%% tcp_error - from proxy socket, active mode
-%%
-%%
-handle_info({tcp_error, Socket, Reason},
- #st{active = Active, collector = Collector,
- proxysock = Socket} = St)
- when Active =/= false ->
- debug(St, "tcp_error: socket = ~w, reason = ~w~n", [Socket, Reason]),
- Msg = {ssl_error, Socket, Reason},
- Collector ! Msg,
- if
- Active =:= once ->
- {noreply, St#st{status = closing, active = false}};
- true ->
- {noreply, St#st{status = closing}}
- end;
-
-%% EXIT - from client
-%%
-%%
-handle_info({'EXIT', Client, Reason}, #st{client = Client} = St) ->
- debug(St, "exit client: client = ~w, reason = ~w~n", [Client, Reason]),
- {stop, normal, St#st{status = closed}}; % do not make noise
-
-%% EXIT - from server
-%%
-%%
-handle_info({'EXIT', Server, Reason}, #st{server = Server} = St) ->
- debug(St, "exit server: reason = ~w~n", [Reason]),
- {stop, Reason, St};
-
-%% handle info catch all
-%%
-handle_info(Info, St) ->
- debug(St, " bad info: ~w~n", [Info]),
- {stop, {error, {badinfo, Info}}, St}.
-
-
-%% terminate
-%%
-%%
-terminate(Reason, St) ->
- debug(St, "in terminate reason: ~w, state: ~w~n", [Reason, St]),
- ok.
-
-%% code_change
-%%
-%%
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%
-%% Primitive interface
-%%
-listen_prim(ServerName, Client, Port, Opts, St) ->
- LOpts = get_tcp_listen_opts(Opts),
- SSLOpts = get_ssl_opts(Opts),
- FlagStr =mk_ssl_optstr(SSLOpts),
- BackLog = get_backlog(LOpts),
- IP = get_ip(LOpts),
- case ssl_server:listen_prim(ServerName, IP, Port, FlagStr, BackLog) of
- {ok, ListenFd, _Port0} ->
- ThisSocket = #sslsocket{fd = ListenFd, pid = self()},
- StOpts = add_default_tcp_listen_opts(LOpts) ++
- add_default_ssl_opts(SSLOpts),
- NSt = St#st{fd = ListenFd,
- active = get_active(LOpts), % irrelevant for listen
- opts = StOpts,
- thissock = ThisSocket,
- status = open},
- debug(St, "listen: ok: client = ~w, listenfd = ~w~n",
- [Client, ListenFd]),
- {ok, ThisSocket, NSt};
- {error, Reason} ->
- {error, Reason, St}
- end.
-
-connect_prim(ServerName, TcpModule, Client, FAddress, FPort, Opts,
- Timeout, St) ->
- COpts = get_tcp_connect_opts(Opts),
- SSLOpts = get_ssl_opts(Opts),
- FlagStr = mk_ssl_optstr(SSLOpts),
- case inet:getaddr(FAddress, inet) of
- {ok, FIP} ->
- %% Timeout is gen_server timeout - hence catch
- LIP = get_ip(COpts),
- LPort = get_port(COpts),
- case (catch ssl_server:connect_prim(ServerName,
- LIP, LPort, FIP, FPort,
- FlagStr, Timeout)) of
- {ok, Fd, ProxyPort} ->
- case connect_proxy(ServerName, TcpModule, Fd,
- ProxyPort, COpts, Timeout) of
- {ok, Socket} ->
- ThisSocket = #sslsocket{fd = Fd, pid = self()},
- StOpts = add_default_tcp_connect_opts(COpts) ++
- add_default_ssl_opts(SSLOpts),
- NSt = St#st{fd = Fd,
- active = get_active(COpts),
- opts = StOpts,
- thissock = ThisSocket,
- proxysock = Socket,
- status = open},
- case get_nodelay(COpts) of
- true -> setnodelay(ServerName, NSt, true);
- _ -> ok
- end,
- debug(St, "connect: ok: client = ~w, fd = ~w~n",
- [Client, Fd]),
- {ok, ThisSocket, NSt};
- {error, Reason} ->
- {error, Reason, St}
- end;
- {'EXIT', Reason} ->
- {error, Reason, St};
- {error, Reason} ->
- {error, Reason, St}
- end;
- {error, Reason} ->
- {error, Reason, St}
- end.
-
-transport_accept_prim(ServerName, ListenFd, LOpts, Timeout, St) ->
- AOpts = get_tcp_accept_opts(LOpts),
- FlagStr = "",
- %% Timeout is gen_server timeout - hence catch.
- case (catch ssl_server:transport_accept_prim(ServerName, ListenFd,
- FlagStr, Timeout)) of
- {ok, Fd, ProxyPort} ->
- ThisSocket = #sslsocket{fd = Fd, pid = self()},
- NSt = St#st{fd = Fd,
- active = get_active(AOpts),
- opts = AOpts,
- thissock = ThisSocket,
- proxyport = ProxyPort,
- encrypted = false},
- debug(St, "transport_accept: ok: fd = ~w~n", [Fd]),
- {ok, ThisSocket, NSt};
- {'EXIT', Reason} ->
- debug(St, "transport_accept: EXIT: Reason = ~w~n", [Reason]),
- {error, Reason, St};
- {error, Reason} ->
- debug(St, "transport_accept: error: Reason = ~w~n", [Reason]),
- {error, Reason, St}
- end.
-
-ssl_accept_prim(ServerName, TcpModule, Client, LOpts, Timeout, St) ->
- FlagStr = [],
- SSLOpts = [],
- AOpts = get_tcp_accept_opts(LOpts),
- %% Timeout is gen_server timeout - hence catch.
- debug(St, "ssl_accept_prim: self() ~w Client ~w~n", [self(), Client]),
- Socket = St#st.thissock,
- Fd = Socket#sslsocket.fd,
- A = (catch ssl_server:ssl_accept_prim(ServerName, Fd, FlagStr, Timeout)),
- debug(St, "ssl_accept_prim: ~w~n", [A]),
- case A of
- ok ->
- B = connect_proxy(ServerName, TcpModule, Fd,
- St#st.proxyport, AOpts, Timeout),
- debug(St, "ssl_accept_prim: connect_proxy ~w~n", [B]),
- case B of
- {ok, Socket2} ->
- StOpts = add_default_tcp_accept_opts(AOpts) ++
- add_default_ssl_opts(SSLOpts),
- NSt = St#st{opts = StOpts,
- proxysock = Socket2,
- encrypted = true,
- status = open},
- case get_nodelay(AOpts) of
- true -> setnodelay(ServerName, NSt, true);
- _ -> ok
- end,
- debug(St, "transport_accept: ok: client = ~w, fd = ~w~n",
- [Client, Fd]),
- {ok, St#st.thissock, NSt};
- {error, Reason} ->
- {error, Reason, St}
- end;
- {'EXIT', Reason} ->
- {error, Reason, St};
- {error, Reason} ->
- {error, Reason, St}
- end.
-
-
-%%
-%% LOCAL FUNCTIONS
-%%
-
-%%
-%% connect_proxy(Fd, ProxyPort, TOpts, Timeout) -> {ok, Socket} |
-%% {error, Reason}
-%%
-connect_proxy(ServerName, TcpModule, Fd, ProxyPort, TOpts, Timeout) ->
- case TcpModule:connect({127, 0, 0, 1}, ProxyPort, TOpts, Timeout) of
- {ok, Socket} ->
- {ok, Port} = inet:port(Socket),
- A = ssl_server:proxy_join_prim(ServerName, Fd, Port),
- case A of
- ok ->
- {ok, Socket};
- Error ->
- Error
- end;
- Error ->
- Error
- end.
-
-
-setnodelay(ServerName, St, Bool) ->
- case ssl_server:setnodelay_prim(ServerName, St#st.fd, Bool) of
- ok ->
- case inet:setopts(St#st.proxysock, [{nodelay, Bool}]) of
- ok ->
- ok;
- {error, Reason} ->
- {error, Reason}
- end;
- {error, Reason} ->
- {error, Reason}
- end.
-
-%%
-%% start_collector()
-%%
-%% A collector is a little process that keeps messages during change of
-%% controlling process.
-%% XXX This is not gen_server compliant :-(.
-%%
-start_collector() ->
- Pid = spawn_link(?MODULE, collector_init, [self()]),
- {ok, Pid}.
-
-%%
-%% release_collector(Collector, NewOwner)
-%%
-release_collector(Collector, NewOwner) ->
- Collector ! {release, self(), NewOwner},
- receive
- %% Reap collector
- {'EXIT', Collector, normal} ->
- ok
- end.
-
-%%
-%% collector_init(Broker) -> void()
-%%
-collector_init(Broker) ->
- receive
- {release, Broker, NewOwner} ->
- transfer_messages(Broker, NewOwner)
- end.
-
-%%
-%% transfer_messages(Pid, NewOwner) -> void()
-%%
-transfer_messages(Pid, NewOwner) ->
- receive
- {ssl, Sock, Data} ->
- NewOwner ! {ssl, Sock, Data},
- transfer_messages(Pid, NewOwner);
- {ssl_closed, Sock} ->
- NewOwner ! {ssl_closed, Sock},
- transfer_messages(Pid, NewOwner);
- {ssl_error, Sock, Reason} ->
- NewOwner ! {ssl_error, Sock, Reason},
- transfer_messages(Pid, NewOwner)
- after 0 ->
- ok
- end.
-
-%%
-%% debug(St, Format, Args) -> void() - printouts
-%%
-debug(St, Format, Args) ->
- debug1(St#st.debug, St#st.brokertype, Format, Args).
-
-debug1(true, Type, Format0, Args) ->
- {_MS, S, MiS} = erlang:now(),
- Secs = S rem 100,
- MiSecs = MiS div 1000,
- Format = "++++ ~3..0w:~3..0w ssl_broker (~w)[~w]: " ++ Format0,
- io:format(Format, [Secs, MiSecs, self(), Type| Args]);
-debug1(_, _, _, _) ->
- ok.
-
-%%
-%% what(Reason) -> What
-%%
-what(Reason) when is_atom(Reason) ->
- Reason;
-what({'EXIT', Reason}) ->
- what(Reason);
-what({What, _Where}) when is_atom(What) ->
- What;
-what(Reason) ->
- Reason.
-
-
-%%
-%% OPTIONS
-%%
-%% Note that `accept' has no options when invoked, but get all its options
-%% by inheritance from `listen'.
-%%
-
-are_opt_tags(listener, OptTags) ->
- is_subset(OptTags, listen_opt_tags());
-are_opt_tags(acceptor, OptTags) ->
- is_subset(OptTags, accept_opt_tags());
-are_opt_tags(connector, OptTags) ->
- is_subset(OptTags, connect_opt_tags()).
-
-listen_opt_tags() ->
- tcp_listen_opt_tags() ++ ssl_opt_tags().
-
-accept_opt_tags() ->
- tcp_gen_opt_tags().
-
-connect_opt_tags() ->
- tcp_gen_opt_tags() ++ ssl_opt_tags().
-
-tcp_listen_opt_tags() ->
- tcp_gen_opt_tags() ++ tcp_listen_only_opt_tags().
-
-tcp_gen_opt_tags() ->
- %% All except `reuseaddr' and `deliver'.
- [nodelay, active, packet, mode, header].
-
-tcp_listen_only_opt_tags() ->
- [ip, backlog].
-
-ssl_opt_tags() ->
- %% XXX Should remove cachetimeout.
- [verify, depth, certfile, password, cacertfile, ciphers, cachetimeout].
-
-%% Options
-
-%%
-%% are_*_opts(Opts) -> boolean()
-%%
-are_connect_opts(Opts) ->
- are_opts(fun is_connect_opt/1, Opts).
-
-are_listen_opts(Opts) ->
- are_opts(fun is_listen_opt/1, Opts).
-
-are_opts(F, Opts) ->
- lists:all(F, transform_opts(Opts)).
-
-%%
-%% get_*_opts(Opts) -> Value
-%%
-get_tcp_accept_opts(Opts) ->
- [O || O <- transform_opts(Opts), is_tcp_accept_opt(O)].
-
-get_tcp_connect_opts(Opts) ->
- [O || O <- transform_opts(Opts), is_tcp_connect_opt(O)].
-
-get_tcp_listen_opts(Opts) ->
- [O || O <- transform_opts(Opts), is_tcp_listen_opt(O)].
-
-get_ssl_opts(Opts) ->
- [O || O <- transform_opts(Opts), is_ssl_opt(O)].
-
-get_active(Opts) ->
- get_tagged_opt(active, Opts, true).
-
-get_backlog(Opts) ->
- get_tagged_opt(backlog, Opts, ?DEF_BACKLOG).
-
-get_ip(Opts) ->
- get_tagged_opt(ip, Opts, {0, 0, 0, 0}).
-
-get_port(Opts) ->
- get_tagged_opt(port, Opts, 0).
-
-get_nodelay(Opts) ->
- get_tagged_opt(nodelay, Opts, empty).
-
-%%
-%% add_default_*_opts(Opts) -> NOpts
-%%
-
-add_default_tcp_accept_opts(Opts) ->
- add_default_opts(Opts, default_tcp_accept_opts()).
-
-add_default_tcp_connect_opts(Opts) ->
- add_default_opts(Opts, default_tcp_connect_opts()).
-
-add_default_tcp_listen_opts(Opts) ->
- add_default_opts(Opts, default_tcp_listen_opts()).
-
-add_default_ssl_opts(Opts) ->
- add_default_opts(Opts, default_ssl_opts()).
-
-add_default_opts(Opts, DefOpts) ->
- TOpts = transform_opts(Opts),
- TOpts ++ [DP || {DTag, _DVal} = DP <- DefOpts,
- not lists:keymember(DTag, 1, TOpts)].
-
-default_tcp_accept_opts() ->
- [O || O <- default_opts(), is_tcp_accept_opt(O)].
-
-default_tcp_connect_opts() ->
- [O || O <- default_opts(), is_tcp_connect_opt(O)].
-
-default_tcp_listen_opts() ->
- [O || O <- default_opts(), is_tcp_listen_opt(O)].
-
-default_ssl_opts() ->
- [O || O <- default_opts(), is_ssl_opt(O)].
-
-default_opts() ->
- [{mode, list}, {packet, 0}, {nodelay, false}, {active, true},
- {backlog, ?DEF_BACKLOG}, {ip, {0, 0, 0, 0}},
- {verify, 0}, {depth, 1}].
-
-
-%% Transform from old to new options, and also from old gen_tcp
-%% options to new ones. All returned options are tagged options.
-%%
-transform_opts(Opts) ->
- lists:flatmap(fun transform_opt/1, Opts).
-
-transform_opt(binary) -> [{mode, binary}];
-transform_opt(list) -> [{mode, list}];
-transform_opt({packet, raw}) -> [{packet, 0}];
-transform_opt(raw) -> [];
-transform_opt(Opt) -> [Opt].
-
-%% NOTE: The is_*_opt/1 functions must be applied on transformed options
-%% only.
-
-is_connect_opt(Opt) ->
- is_tcp_connect_opt(Opt) or is_ssl_opt(Opt).
-
-is_listen_opt(Opt) ->
- is_tcp_listen_opt(Opt) or is_ssl_opt(Opt).
-
-is_tcp_accept_opt(Opt) ->
- is_tcp_gen_opt(Opt).
-
-is_tcp_connect_opt(Opt) ->
- is_tcp_gen_opt(Opt) or is_tcp_connect_only_opt(Opt).
-
-is_tcp_listen_opt(Opt) ->
- is_tcp_gen_opt(Opt) or is_tcp_listen_only_opt(Opt).
-
-%% General options supported by gen_tcp: All except `reuseaddr' and
-%% `deliver'.
-is_tcp_gen_opt({mode, list}) -> true;
-is_tcp_gen_opt({mode, binary}) -> true;
-is_tcp_gen_opt({header, Sz}) when is_integer(Sz), 0 =< Sz -> true;
-is_tcp_gen_opt({packet, Sz}) when is_integer(Sz), 0 =< Sz, Sz =< 4-> true;
-is_tcp_gen_opt({packet, sunrm}) -> true;
-is_tcp_gen_opt({packet, asn1}) -> true;
-is_tcp_gen_opt({packet, cdr}) -> true;
-is_tcp_gen_opt({packet, fcgi}) -> true;
-is_tcp_gen_opt({packet, line}) -> true;
-is_tcp_gen_opt({packet, tpkt}) -> true;
-is_tcp_gen_opt({packet, http}) -> true;
-is_tcp_gen_opt({packet, httph}) -> true;
-is_tcp_gen_opt({nodelay, true}) -> true;
-is_tcp_gen_opt({nodelay, false}) -> true;
-is_tcp_gen_opt({active, true}) -> true;
-is_tcp_gen_opt({active, false}) -> true;
-is_tcp_gen_opt({active, once}) -> true;
-is_tcp_gen_opt({keepalive, true}) -> true;
-is_tcp_gen_opt({keepalive, false}) -> true;
-is_tcp_gen_opt({ip, Addr}) -> is_ip_address(Addr);
-is_tcp_gen_opt(_Opt) -> false.
-
-is_tcp_listen_only_opt({backlog, Size}) when is_integer(Size), 0 =< Size ->
- true;
-is_tcp_listen_only_opt({reuseaddr, Bool}) when is_boolean(Bool) ->
- true;
-is_tcp_listen_only_opt(_Opt) -> false.
-
-is_tcp_connect_only_opt({port, Port}) when is_integer(Port), 0 =< Port -> true;
-is_tcp_connect_only_opt(_Opt) -> false.
-
-%% SSL options
-
-is_ssl_opt({verify, Code}) when 0 =< Code, Code =< 2 -> true;
-is_ssl_opt({depth, Depth}) when 0 =< Depth -> true;
-is_ssl_opt({certfile, String}) -> is_string(String);
-is_ssl_opt({keyfile, String}) -> is_string(String);
-is_ssl_opt({password, String}) -> is_string(String);
-is_ssl_opt({cacertfile, String}) -> is_string(String);
-is_ssl_opt({ciphers, String}) -> is_string(String);
-is_ssl_opt({cachetimeout, Timeout}) when Timeout >= 0 -> true;
-is_ssl_opt(_Opt) -> false.
-
-%% Various types
-is_string(String) when is_list(String) ->
- lists:all(fun (C) when is_integer(C), 0 =< C, C =< 255 -> true;
- (_C) -> false end,
- String);
-is_string(_) ->
- false.
-
-is_ip_address(Addr) when tuple_size(Addr) =:= 4 ->
- is_string(tuple_to_list(Addr));
-is_ip_address(Addr) when is_list(Addr) ->
- is_string(Addr);
-is_ip_address(_) ->
- false.
-
-get_tagged_opt(Tag, Opts, Default) ->
- case lists:keysearch(Tag, 1, Opts) of
- {value, {_, Value}} ->
- Value;
- _Other ->
- Default
- end.
-
-%%
-%% mk_ssl_optstr(Opts) -> string()
-%%
-%% Makes a "command line" string of SSL options
-%%
-mk_ssl_optstr(Opts) ->
- lists:flatten([mk_one_ssl_optstr(O) || O <- Opts]).
-
-mk_one_ssl_optstr({verify, Code}) ->
- [" -verify ", integer_to_list(Code)];
-mk_one_ssl_optstr({depth, Depth}) ->
- [" -depth ", integer_to_list(Depth)];
-mk_one_ssl_optstr({certfile, String}) ->
- [" -certfile ", String];
-mk_one_ssl_optstr({keyfile, String}) ->
- [" -keyfile ", String];
-mk_one_ssl_optstr({password, String}) ->
- [" -password ", String];
-mk_one_ssl_optstr({cacertfile, String}) ->
- [" -cacertfile ", String];
-mk_one_ssl_optstr({ciphers, String}) ->
- [" -ciphers ", String];
-mk_one_ssl_optstr({cachetimeout, Timeout}) ->
- [" -cachetimeout ", integer_to_list(Timeout)];
-mk_one_ssl_optstr(_) ->
- "".
-
-extract_opts(OptTags, Opts) ->
- [O || O = {Tag,_} <- Opts, lists:member(Tag, OptTags)].
-
-replace_opts(NOpts, Opts) ->
- lists:foldl(fun({Key, Val}, Acc) ->
- lists:keyreplace(Key, 1, Acc, {Key, Val});
- %% XXX Check. Patch from Chandrashekhar Mullaparthi.
- (binary, Acc) ->
- lists:keyreplace(mode, 1, Acc, {mode, binary})
- end,
- Opts, NOpts).
-
-%% Misc
-
-is_subset(A, B) ->
- [] =:= A -- B.
diff --git a/lib/ssl/src/ssl_broker_int.hrl b/lib/ssl/src/ssl_broker_int.hrl
deleted file mode 100644
index b791485725..0000000000
--- a/lib/ssl/src/ssl_broker_int.hrl
+++ /dev/null
@@ -1,38 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-
-%% Purpose: record definitions shared between ssl_prim.erl and ssl_broker.erl
-
--record(st, {brokertype = nil, % connector | listener | acceptor
- server = nil, % pid of ssl_server
- client = nil, % client pid
- collector = nil, % client pid, or collector during change of
- % controlling process
- fd = nil, % fd of "external" socket in port program
- active = true, % true | false | once
- opts = [], % options
- thissock = nil, % this sslsocket
- proxysock = nil, % local proxy socket within Erlang
- proxyport = nil, % local port for proxy within Erlang
- status = nil, % open | closing | closed
- encrypted = false, %
- debug = false %
- }).
diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl
index 8c0c2bfa5d..61876e1158 100644
--- a/lib/ssl/src/ssl_certificate.erl
+++ b/lib/ssl/src/ssl_certificate.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -30,9 +30,9 @@
-include("ssl_internal.hrl").
-include_lib("public_key/include/public_key.hrl").
--export([trusted_cert_and_path/2,
- certificate_chain/2,
- file_to_certificats/1,
+-export([trusted_cert_and_path/3,
+ certificate_chain/3,
+ file_to_certificats/2,
validate_extension/3,
is_valid_extkey_usage/2,
is_valid_key_usage/2,
@@ -46,14 +46,14 @@
%%====================================================================
%%--------------------------------------------------------------------
--spec trusted_cert_and_path([der_cert()], certdb_ref()) ->
+-spec trusted_cert_and_path([der_cert()], db_handle(), certdb_ref()) ->
{der_cert() | unknown_ca, [der_cert()]}.
%%
%% Description: Extracts the root cert (if not presents tries to
%% look it up, if not found {bad_cert, unknown_ca} will be added verification
%% errors. Returns {RootCert, Path, VerifyErrors}
%%--------------------------------------------------------------------
-trusted_cert_and_path(CertChain, CertDbRef) ->
+trusted_cert_and_path(CertChain, CertDbHandle, CertDbRef) ->
Path = [Cert | _] = lists:reverse(CertChain),
OtpCert = public_key:pkix_decode_cert(Cert, otp),
SignedAndIssuerID =
@@ -66,7 +66,7 @@ trusted_cert_and_path(CertChain, CertDbRef) ->
{ok, IssuerId} ->
{other, IssuerId};
{error, issuer_not_found} ->
- case find_issuer(OtpCert, no_candidate) of
+ case find_issuer(OtpCert, CertDbHandle) of
{ok, IssuerId} ->
{other, IssuerId};
Other ->
@@ -82,7 +82,7 @@ trusted_cert_and_path(CertChain, CertDbRef) ->
{self, _} when length(Path) == 1 ->
{selfsigned_peer, Path};
{_ ,{SerialNr, Issuer}} ->
- case ssl_manager:lookup_trusted_cert(CertDbRef, SerialNr, Issuer) of
+ case ssl_manager:lookup_trusted_cert(CertDbHandle, CertDbRef, SerialNr, Issuer) of
{ok, {BinCert,_}} ->
{BinCert, Path};
_ ->
@@ -92,23 +92,23 @@ trusted_cert_and_path(CertChain, CertDbRef) ->
end.
%%--------------------------------------------------------------------
--spec certificate_chain(undefined | binary(), certdb_ref()) ->
+-spec certificate_chain(undefined | binary(), db_handle(), certdb_ref()) ->
{error, no_cert} | {ok, [der_cert()]}.
%%
%% Description: Return the certificate chain to send to peer.
%%--------------------------------------------------------------------
-certificate_chain(undefined, _CertsDbRef) ->
+certificate_chain(undefined, _, _) ->
{error, no_cert};
-certificate_chain(OwnCert, CertsDbRef) ->
+certificate_chain(OwnCert, CertDbHandle, CertsDbRef) ->
ErlCert = public_key:pkix_decode_cert(OwnCert, otp),
- certificate_chain(ErlCert, OwnCert, CertsDbRef, [OwnCert]).
+ certificate_chain(ErlCert, OwnCert, CertDbHandle, CertsDbRef, [OwnCert]).
%%--------------------------------------------------------------------
--spec file_to_certificats(string()) -> [der_cert()].
+-spec file_to_certificats(string(), term()) -> [der_cert()].
%%
%% Description: Return list of DER encoded certificates.
%%--------------------------------------------------------------------
-file_to_certificats(File) ->
- {ok, List} = ssl_manager:cache_pem_file(File),
+file_to_certificats(File, DbHandle) ->
+ {ok, List} = ssl_manager:cache_pem_file(File, DbHandle),
[Bin || {'Certificate', Bin, not_encrypted} <- List].
%%--------------------------------------------------------------------
-spec validate_extension(term(), #'Extension'{} | {bad_cert, atom()} | valid,
@@ -180,7 +180,7 @@ signature_type(?'id-dsa-with-sha1') ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-certificate_chain(OtpCert, _Cert, CertsDbRef, Chain) ->
+certificate_chain(OtpCert, _Cert, CertDbHandle, CertsDbRef, Chain) ->
IssuerAndSelfSigned =
case public_key:pkix_is_self_signed(OtpCert) of
true ->
@@ -191,11 +191,11 @@ certificate_chain(OtpCert, _Cert, CertsDbRef, Chain) ->
case IssuerAndSelfSigned of
{_, true = SelfSigned} ->
- certificate_chain(CertsDbRef, Chain, ignore, ignore, SelfSigned);
+ certificate_chain(CertDbHandle, CertsDbRef, Chain, ignore, ignore, SelfSigned);
{{error, issuer_not_found}, SelfSigned} ->
- case find_issuer(OtpCert, no_candidate) of
+ case find_issuer(OtpCert, CertDbHandle) of
{ok, {SerialNr, Issuer}} ->
- certificate_chain(CertsDbRef, Chain,
+ certificate_chain(CertDbHandle, CertsDbRef, Chain,
SerialNr, Issuer, SelfSigned);
_ ->
%% Guess the the issuer must be the root
@@ -205,19 +205,19 @@ certificate_chain(OtpCert, _Cert, CertsDbRef, Chain) ->
{ok, lists:reverse(Chain)}
end;
{{ok, {SerialNr, Issuer}}, SelfSigned} ->
- certificate_chain(CertsDbRef, Chain, SerialNr, Issuer, SelfSigned)
+ certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, SelfSigned)
end.
-certificate_chain(_CertsDbRef, Chain, _SerialNr, _Issuer, true) ->
+certificate_chain(_,_, Chain, _SerialNr, _Issuer, true) ->
{ok, lists:reverse(Chain)};
-certificate_chain(CertsDbRef, Chain, SerialNr, Issuer, _SelfSigned) ->
- case ssl_manager:lookup_trusted_cert(CertsDbRef,
+certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, _SelfSigned) ->
+ case ssl_manager:lookup_trusted_cert(CertDbHandle, CertsDbRef,
SerialNr, Issuer) of
{ok, {IssuerCert, ErlCert}} ->
ErlCert = public_key:pkix_decode_cert(IssuerCert, otp),
certificate_chain(ErlCert, IssuerCert,
- CertsDbRef, [IssuerCert | Chain]);
+ CertDbHandle, CertsDbRef, [IssuerCert | Chain]);
_ ->
%% The trusted cert may be obmitted from the chain as the
%% counter part needs to have it anyway to be able to
@@ -227,17 +227,24 @@ certificate_chain(CertsDbRef, Chain, SerialNr, Issuer, _SelfSigned) ->
{ok, lists:reverse(Chain)}
end.
-find_issuer(OtpCert, PrevCandidateKey) ->
- case ssl_manager:issuer_candidate(PrevCandidateKey) of
- no_more_candidates ->
- {error, issuer_not_found};
- {Key, {_Cert, ErlCertCandidate}} ->
- case public_key:pkix_is_issuer(OtpCert, ErlCertCandidate) of
- true ->
- public_key:pkix_issuer_id(ErlCertCandidate, self);
- false ->
- find_issuer(OtpCert, Key)
- end
+find_issuer(OtpCert, CertDbHandle) ->
+ IsIssuerFun = fun({_Key, {_Der, #'OTPCertificate'{} = ErlCertCandidate}}, Acc) ->
+ case public_key:pkix_is_issuer(OtpCert, ErlCertCandidate) of
+ true ->
+ throw(public_key:pkix_issuer_id(ErlCertCandidate, self));
+ false ->
+ Acc
+ end;
+ (_, Acc) ->
+ Acc
+ end,
+
+ try ssl_certificate_db:foldl(IsIssuerFun, issuer_not_found, CertDbHandle) of
+ issuer_not_found ->
+ {error, issuer_not_found}
+ catch
+ {ok, _IssuerId} = Return ->
+ Return
end.
is_valid_extkey_usage(KeyUse, client) ->
diff --git a/lib/ssl/src/ssl_certificate_db.erl b/lib/ssl/src/ssl_certificate_db.erl
index 3eceefa304..cb2473576a 100644
--- a/lib/ssl/src/ssl_certificate_db.erl
+++ b/lib/ssl/src/ssl_certificate_db.erl
@@ -26,8 +26,8 @@
-include_lib("public_key/include/public_key.hrl").
-export([create/0, remove/1, add_trusted_certs/3,
- remove_trusted_certs/2, lookup_trusted_cert/3, issuer_candidate/1,
- lookup_cached_certs/1, cache_pem_file/4, uncache_pem_file/2, lookup/2]).
+ remove_trusted_certs/2, lookup_trusted_cert/4, foldl/3,
+ lookup_cached_certs/2, cache_pem_file/4, uncache_pem_file/2, lookup/2]).
-type time() :: {non_neg_integer(), non_neg_integer(), non_neg_integer()}.
@@ -36,19 +36,19 @@
%%====================================================================
%%--------------------------------------------------------------------
--spec create() -> certdb_ref().
+-spec create() -> [db_handle()].
%%
%% Description: Creates a new certificate db.
-%% Note: lookup_trusted_cert/3 may be called from any process but only
+%% Note: lookup_trusted_cert/4 may be called from any process but only
%% the process that called create may call the other functions.
%%--------------------------------------------------------------------
create() ->
- [ets:new(certificate_db_name(), [named_table, set, protected]),
- ets:new(ssl_file_to_ref, [named_table, set, protected]),
+ [ets:new(ssl_otp_certificate_db, [set, protected]),
+ ets:new(ssl_file_to_ref, [set, protected]),
ets:new(ssl_pid_to_file, [bag, private])].
%%--------------------------------------------------------------------
--spec remove(certdb_ref()) -> term().
+-spec remove([db_handle()]) -> term().
%%
%% Description: Removes database db
%%--------------------------------------------------------------------
@@ -56,7 +56,7 @@ remove(Dbs) ->
lists:foreach(fun(Db) -> true = ets:delete(Db) end, Dbs).
%%--------------------------------------------------------------------
--spec lookup_trusted_cert(reference(), serialnumber(), issuer()) ->
+-spec lookup_trusted_cert(db_handle(), certdb_ref(), serialnumber(), issuer()) ->
undefined | {ok, {der_cert(), #'OTPCertificate'{}}}.
%%
@@ -64,19 +64,19 @@ remove(Dbs) ->
%% <SerialNumber, Issuer>. Ref is used as it is specified
%% for each connection which certificates are trusted.
%%--------------------------------------------------------------------
-lookup_trusted_cert(Ref, SerialNumber, Issuer) ->
- case lookup({Ref, SerialNumber, Issuer}, certificate_db_name()) of
+lookup_trusted_cert(DbHandle, Ref, SerialNumber, Issuer) ->
+ case lookup({Ref, SerialNumber, Issuer}, DbHandle) of
undefined ->
undefined;
[Certs] ->
{ok, Certs}
end.
-lookup_cached_certs(File) ->
- ets:lookup(certificate_db_name(), {file, File}).
+lookup_cached_certs(DbHandle, File) ->
+ ets:lookup(DbHandle, {file, File}).
%%--------------------------------------------------------------------
--spec add_trusted_certs(pid(), string() | {der, list()}, certdb_ref()) -> {ok, certdb_ref()}.
+-spec add_trusted_certs(pid(), string() | {der, list()}, [db_handle()]) -> {ok, [db_handle()]}.
%%
%% Description: Adds the trusted certificates from file <File> to the
%% runtime database. Returns Ref that should be handed to lookup_trusted_cert
@@ -100,7 +100,7 @@ add_trusted_certs(Pid, File, [CertsDb, FileToRefDb, PidToFileDb]) ->
insert(Pid, File, PidToFileDb),
{ok, Ref}.
%%--------------------------------------------------------------------
--spec cache_pem_file(pid(), string(), time(), certdb_ref()) -> term().
+-spec cache_pem_file(pid(), string(), time(), [db_handle()]) -> term().
%%
%% Description: Cache file as binary in DB
%%--------------------------------------------------------------------
@@ -112,7 +112,7 @@ cache_pem_file(Pid, File, Time, [CertsDb, _FileToRefDb, PidToFileDb]) ->
{ok, Content}.
%--------------------------------------------------------------------
--spec uncache_pem_file(string(), certdb_ref()) -> no_return().
+-spec uncache_pem_file(string(), [db_handle()]) -> no_return().
%%
%% Description: If a cached file is no longer valid (changed on disk)
%% we must terminate the connections using the old file content, and
@@ -127,10 +127,8 @@ uncache_pem_file(File, [_CertsDb, _FileToRefDb, PidToFileDb]) ->
exit(Pid, shutdown)
end, Pids).
-
-
%%--------------------------------------------------------------------
--spec remove_trusted_certs(pid(), certdb_ref()) -> term().
+-spec remove_trusted_certs(pid(), [db_handle()]) -> term().
%%
%% Description: Removes trusted certs originating from
@@ -161,40 +159,7 @@ remove_trusted_certs(Pid, [CertsDb, FileToRefDb, PidToFileDb]) ->
end.
%%--------------------------------------------------------------------
--spec issuer_candidate(no_candidate | cert_key() | {file, term()}) ->
- {cert_key(),{der_cert(), #'OTPCertificate'{}}} | no_more_candidates.
-%%
-%% Description: If a certificat does not define its issuer through
-%% the extension 'ce-authorityKeyIdentifier' we can
-%% try to find the issuer in the database over known
-%% certificates.
-%%--------------------------------------------------------------------
-issuer_candidate(no_candidate) ->
- Db = certificate_db_name(),
- case ets:first(Db) of
- '$end_of_table' ->
- no_more_candidates;
- {file, _} = Key ->
- issuer_candidate(Key);
- Key ->
- [Cert] = lookup(Key, Db),
- {Key, Cert}
- end;
-
-issuer_candidate(PrevCandidateKey) ->
- Db = certificate_db_name(),
- case ets:next(Db, PrevCandidateKey) of
- '$end_of_table' ->
- no_more_candidates;
- {file, _} = Key ->
- issuer_candidate(Key);
- Key ->
- [Cert] = lookup(Key, Db),
- {Key, Cert}
- end.
-
-%%--------------------------------------------------------------------
--spec lookup(term(), term()) -> term() | undefined.
+-spec lookup(term(), db_handle()) -> term() | undefined.
%%
%% Description: Looks up an element in a certificat <Db>.
%%--------------------------------------------------------------------
@@ -208,13 +173,21 @@ lookup(Key, Db) ->
end,
[Pick(Data) || Data <- Contents]
end.
-
+%%--------------------------------------------------------------------
+-spec foldl(fun(), term(), db_handle()) -> term().
+%%
+%% Description: Calls Fun(Elem, AccIn) on successive elements of the
+%% cache, starting with AccIn == Acc0. Fun/2 must return a new
+%% accumulator which is passed to the next call. The function returns
+%% the final value of the accumulator. Acc0 is returned if the certifate
+%% db is empty.
+%%--------------------------------------------------------------------
+foldl(Fun, Acc0, Cache) ->
+ ets:foldl(Fun, Acc0, Cache).
+
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-certificate_db_name() ->
- ssl_otp_certificate_db.
-
insert(Key, Data, Db) ->
true = ets:insert(Db, {Key, Data}).
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index 72f02a4362..95a5efd6d0 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -154,18 +154,23 @@ decipher(?AES, HashSz, CipherState, Fragment, Version) ->
block_decipher(Fun, #cipher_state{key=Key, iv=IV} = CipherState0,
HashSz, Fragment, Version) ->
- try Fun(Key, IV, Fragment) of
- Text ->
- GBC = generic_block_cipher_from_bin(Text, HashSz),
- case is_correct_padding(GBC, Version) of
- true ->
- Content = GBC#generic_block_cipher.content,
- Mac = GBC#generic_block_cipher.mac,
- CipherState1 = CipherState0#cipher_state{iv=next_iv(Fragment, IV)},
- {Content, Mac, CipherState1};
- false ->
- ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
- end
+ try
+ Text = Fun(Key, IV, Fragment),
+ GBC = generic_block_cipher_from_bin(Text, HashSz),
+ Content = GBC#generic_block_cipher.content,
+ Mac = GBC#generic_block_cipher.mac,
+ CipherState1 = CipherState0#cipher_state{iv=next_iv(Fragment, IV)},
+ case is_correct_padding(GBC, Version) of
+ true ->
+ {Content, Mac, CipherState1};
+ false ->
+ %% decryption failed or invalid padding,
+ %% intentionally break Content to make
+ %% sure a packet with a an invalid padding
+ %% but otherwise correct data will fail
+ %% the MAC test later
+ {<<16#F0, Content/binary>>, Mac, CipherState1}
+ end
catch
_:_ ->
%% This is a DECRYPTION_FAILED but
@@ -500,14 +505,38 @@ hash_size(md5) ->
hash_size(sha) ->
20.
+%% RFC 5246: 6.2.3.2. CBC Block Cipher
+%%
+%% Implementation note: Canvel et al. [CBCTIME] have demonstrated a
+%% timing attack on CBC padding based on the time required to compute
+%% the MAC. In order to defend against this attack, implementations
+%% MUST ensure that record processing time is essentially the same
+%% whether or not the padding is correct. In general, the best way to
+%% do this is to compute the MAC even if the padding is incorrect, and
+%% only then reject the packet. For instance, if the pad appears to be
+%% incorrect, the implementation might assume a zero-length pad and then
+%% compute the MAC. This leaves a small timing channel, since MAC
+%% performance depends to some extent on the size of the data fragment,
+%% but it is not believed to be large enough to be exploitable, due to
+%% the large block size of existing MACs and the small size of the
+%% timing signal.
+%%
+%% implementation note:
+%% We return the original (possibly invalid) PadLength in any case.
+%% A invalid PadLength will be cought by is_correct_padding/2
+%%
generic_block_cipher_from_bin(T, HashSize) ->
Sz1 = byte_size(T) - 1,
- <<_:Sz1/binary, ?BYTE(PadLength)>> = T,
+ <<_:Sz1/binary, ?BYTE(PadLength0)>> = T,
+ PadLength = if
+ PadLength0 >= Sz1 -> 0;
+ true -> PadLength0
+ end,
CompressedLength = byte_size(T) - PadLength - 1 - HashSize,
<<Content:CompressedLength/binary, Mac:HashSize/binary,
- Padding:PadLength/binary, ?BYTE(PadLength)>> = T,
+ Padding:PadLength/binary, ?BYTE(PadLength0)>> = T,
#generic_block_cipher{content=Content, mac=Mac,
- padding=Padding, padding_length=PadLength}.
+ padding=Padding, padding_length=PadLength0}.
generic_stream_cipher_from_bin(T, HashSz) ->
Sz = byte_size(T),
@@ -516,17 +545,18 @@ generic_stream_cipher_from_bin(T, HashSz) ->
#generic_stream_cipher{content=Content,
mac=Mac}.
-is_correct_padding(_, {3, 0}) ->
- true;
-%% For interoperability reasons we do not check the padding in TLS 1.0 as it
-%% is not strictly required and breaks interopability with for instance
-%% Google.
-is_correct_padding(_, {3, 1}) ->
- true;
+%% For interoperability reasons we do not check the padding content in
+%% SSL 3.0 and TLS 1.0 as it is not strictly required and breaks
+%% interopability with for instance Google.
+is_correct_padding(#generic_block_cipher{padding_length = Len,
+ padding = Padding}, {3, N})
+ when N == 0; N == 1 ->
+ Len == byte_size(Padding);
%% Padding must be check in TLS 1.1 and after
-is_correct_padding(#generic_block_cipher{padding_length = Len, padding = Padding}, _) ->
- list_to_binary(lists:duplicate(Len, Len)) == Padding.
-
+is_correct_padding(#generic_block_cipher{padding_length = Len,
+ padding = Padding}, _) ->
+ Len == byte_size(Padding) andalso
+ list_to_binary(lists:duplicate(Len, Len)) == Padding.
get_padding(Length, BlockSize) ->
get_padding_aux(BlockSize, Length rem BlockSize).
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index 2c452837f8..0c44d3ae90 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -34,7 +34,6 @@
-include("ssl_record.hrl").
-include("ssl_cipher.hrl").
-include("ssl_internal.hrl").
--include("ssl_int.hrl").
-include_lib("public_key/include/public_key.hrl").
%% Internal application API
@@ -70,6 +69,7 @@
%% {{md5_hash, sha_hash}, {prev_md5, prev_sha}} (binary())
tls_handshake_hashes, % see above
tls_cipher_texts, % list() received but not deciphered yet
+ cert_db, %
session, % #session{} from ssl_handshake.hrl
session_cache, %
session_cache_cb, %
@@ -126,11 +126,11 @@ send(Pid, Data) ->
recv(Pid, Length, Timeout) ->
sync_send_all_state_event(Pid, {recv, Length}, Timeout).
%%--------------------------------------------------------------------
--spec connect(host(), port_num(), port(), {#ssl_options{}, #socket_options{}},
+-spec connect(host(), inet:port_number(), port(), {#ssl_options{}, #socket_options{}},
pid(), tuple(), timeout()) ->
{ok, #sslsocket{}} | {error, reason()}.
%%
-%% Description: Connect to a ssl server.
+%% Description: Connect to an ssl server.
%%--------------------------------------------------------------------
connect(Host, Port, Socket, Options, User, CbInfo, Timeout) ->
try start_fsm(client, Host, Port, Socket, Options, User, CbInfo,
@@ -140,11 +140,11 @@ connect(Host, Port, Socket, Options, User, CbInfo, Timeout) ->
{error, ssl_not_started}
end.
%%--------------------------------------------------------------------
--spec ssl_accept(port_num(), port(), {#ssl_options{}, #socket_options{}},
+-spec ssl_accept(inet:port_number(), port(), {#ssl_options{}, #socket_options{}},
pid(), tuple(), timeout()) ->
{ok, #sslsocket{}} | {error, reason()}.
%%
-%% Description: Performs accept on a ssl listen socket. e.i. performs
+%% Description: Performs accept on an ssl listen socket. e.i. performs
%% ssl handshake.
%%--------------------------------------------------------------------
ssl_accept(Port, Socket, Opts, User, CbInfo, Timeout) ->
@@ -184,7 +184,7 @@ socket_control(Socket, Pid, CbModule) ->
%%--------------------------------------------------------------------
-spec close(pid()) -> ok | {error, reason()}.
%%
-%% Description: Close a ssl connection
+%% Description: Close an ssl connection
%%--------------------------------------------------------------------
close(ConnectionPid) ->
case sync_send_all_state_event(ConnectionPid, close) of
@@ -211,14 +211,14 @@ shutdown(ConnectionPid, How) ->
new_user(ConnectionPid, User) ->
sync_send_all_state_event(ConnectionPid, {new_user, User}).
%%--------------------------------------------------------------------
--spec sockname(pid()) -> {ok, {tuple(), port_num()}} | {error, reason()}.
+-spec sockname(pid()) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, reason()}.
%%
%% Description: Same as inet:sockname/1
%%--------------------------------------------------------------------
sockname(ConnectionPid) ->
sync_send_all_state_event(ConnectionPid, sockname).
%%--------------------------------------------------------------------
--spec peername(pid()) -> {ok, {tuple(), port_num()}} | {error, reason()}.
+-spec peername(pid()) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, reason()}.
%%
%% Description: Same as inet:peername/1
%%--------------------------------------------------------------------
@@ -276,7 +276,7 @@ renegotiation(ConnectionPid) ->
%%====================================================================
%%--------------------------------------------------------------------
--spec start_link(atom(), host(), port_num(), port(), list(), pid(), tuple()) ->
+-spec start_link(atom(), host(), inet:port_number(), port(), list(), pid(), tuple()) ->
{ok, pid()} | ignore | {error, reason()}.
%%
%% Description: Creates a gen_fsm process which calls Module:init/1 to
@@ -303,14 +303,16 @@ init([Role, Host, Port, Socket, {SSLOpts0, _} = Options,
User, CbInfo]) ->
State0 = initial_state(Role, Host, Port, Socket, Options, User, CbInfo),
Hashes0 = ssl_handshake:init_hashes(),
-
+ TimeStamp = calendar:datetime_to_gregorian_seconds({date(), time()}),
try ssl_init(SSLOpts0, Role) of
- {ok, Ref, CacheRef, OwnCert, Key, DHParams} ->
+ {ok, Ref, CertDbHandle, CacheHandle, OwnCert, Key, DHParams} ->
Session = State0#state.session,
State = State0#state{tls_handshake_hashes = Hashes0,
- session = Session#session{own_certificate = OwnCert},
+ session = Session#session{own_certificate = OwnCert,
+ time_stamp = TimeStamp},
cert_db_ref = Ref,
- session_cache = CacheRef,
+ cert_db = CertDbHandle,
+ session_cache = CacheHandle,
private_key = Key,
diffie_hellman_params = DHParams},
{ok, hello, State, get_timeout(State)}
@@ -350,8 +352,7 @@ hello(start, #state{host = Host, port = Port, role = client,
State1 = State0#state{connection_states = CS2,
negotiated_version = Version, %% Requested version
session =
- Session0#session{session_id = Hello#client_hello.session_id,
- is_resumable = false},
+ Session0#session{session_id = Hello#client_hello.session_id},
tls_handshake_hashes = Hashes1},
{Record, State} = next_record(State1),
next_state(hello, Record, State);
@@ -500,9 +501,10 @@ certify(#certificate{asn1_certificates = []},
certify(#certificate{} = Cert,
#state{negotiated_version = Version,
role = Role,
+ cert_db = CertDbHandle,
cert_db_ref = CertDbRef,
ssl_options = Opts} = State) ->
- case ssl_handshake:certify(Cert, CertDbRef, Opts#ssl_options.depth,
+ case ssl_handshake:certify(Cert, CertDbHandle, CertDbRef, Opts#ssl_options.depth,
Opts#ssl_options.verify,
Opts#ssl_options.verify_fun, Role) of
{PeerCert, PublicKeyInfo} ->
@@ -859,23 +861,23 @@ handle_sync_event({set_opts, Opts0}, _From, StateName,
#state{socket_options = Opts1,
socket = Socket,
user_data_buffer = Buffer} = State0) ->
- Opts = set_socket_opts(Socket, Opts0, Opts1, []),
+ {Reply, Opts} = set_socket_opts(Socket, Opts0, Opts1, []),
State1 = State0#state{socket_options = Opts},
if
Opts#socket_options.active =:= false ->
- {reply, ok, StateName, State1, get_timeout(State1)};
+ {reply, Reply, StateName, State1, get_timeout(State1)};
Buffer =:= <<>>, Opts1#socket_options.active =:= false ->
%% Need data, set active once
{Record, State2} = next_record_if_active(State1),
case next_state(StateName, Record, State2) of
{next_state, StateName, State, Timeout} ->
- {reply, ok, StateName, State, Timeout};
+ {reply, Reply, StateName, State, Timeout};
{stop, Reason, State} ->
{stop, Reason, State}
end;
Buffer =:= <<>> ->
%% Active once already set
- {reply, ok, StateName, State1, get_timeout(State1)};
+ {reply, Reply, StateName, State1, get_timeout(State1)};
true ->
case application_data(<<>>, State1) of
Stop = {stop,_,_} ->
@@ -883,7 +885,7 @@ handle_sync_event({set_opts, Opts0}, _From, StateName,
{Record, State2} ->
case next_state(StateName, Record, State2) of
{next_state, StateName, State, Timeout} ->
- {reply, ok, StateName, State, Timeout};
+ {reply, Reply, StateName, State, Timeout};
{stop, Reason, State} ->
{stop, Reason, State}
end
@@ -1030,7 +1032,8 @@ code_change(_OldVsn, StateName, State, _Extra) ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-start_fsm(Role, Host, Port, Socket, Opts, User, {CbModule, _,_, _} = CbInfo,
+start_fsm(Role, Host, Port, Socket, {#ssl_options{erl_dist = false},_} = Opts,
+ User, {CbModule, _,_, _} = CbInfo,
Timeout) ->
try
{ok, Pid} = ssl_connection_sup:start_child([Role, Host, Port, Socket,
@@ -1041,22 +1044,43 @@ start_fsm(Role, Host, Port, Socket, Opts, User, {CbModule, _,_, _} = CbInfo,
catch
error:{badmatch, {error, _} = Error} ->
Error
+ end;
+
+start_fsm(Role, Host, Port, Socket, {#ssl_options{erl_dist = true},_} = Opts,
+ User, {CbModule, _,_, _} = CbInfo,
+ Timeout) ->
+ try
+ {ok, Pid} = ssl_connection_sup:start_child_dist([Role, Host, Port, Socket,
+ Opts, User, CbInfo]),
+ {ok, SslSocket} = socket_control(Socket, Pid, CbModule),
+ ok = handshake(SslSocket, Timeout),
+ {ok, SslSocket}
+ catch
+ error:{badmatch, {error, _} = Error} ->
+ Error
end.
ssl_init(SslOpts, Role) ->
- {ok, CertDbRef, CacheRef, OwnCert} = init_certificates(SslOpts, Role),
+
+ init_manager_name(SslOpts#ssl_options.erl_dist),
+
+ {ok, CertDbRef, CertDbHandle, CacheHandle, OwnCert} = init_certificates(SslOpts, Role),
PrivateKey =
- init_private_key(SslOpts#ssl_options.key, SslOpts#ssl_options.keyfile,
+ init_private_key(CertDbHandle, SslOpts#ssl_options.key, SslOpts#ssl_options.keyfile,
SslOpts#ssl_options.password, Role),
- DHParams = init_diffie_hellman(SslOpts#ssl_options.dh, SslOpts#ssl_options.dhfile, Role),
- {ok, CertDbRef, CacheRef, OwnCert, PrivateKey, DHParams}.
+ DHParams = init_diffie_hellman(CertDbHandle, SslOpts#ssl_options.dh, SslOpts#ssl_options.dhfile, Role),
+ {ok, CertDbRef, CertDbHandle, CacheHandle, OwnCert, PrivateKey, DHParams}.
+init_manager_name(false) ->
+ put(ssl_manager, ssl_manager);
+init_manager_name(true) ->
+ put(ssl_manager, ssl_manager_dist).
init_certificates(#ssl_options{cacerts = CaCerts,
cacertfile = CACertFile,
certfile = CertFile,
cert = Cert}, Role) ->
- {ok, CertDbRef, CacheRef} =
+ {ok, CertDbRef, CertDbHandle, CacheHandle} =
try
Certs = case CaCerts of
undefined ->
@@ -1064,56 +1088,76 @@ init_certificates(#ssl_options{cacerts = CaCerts,
_ ->
{der, CaCerts}
end,
- {ok, _, _} = ssl_manager:connection_init(Certs, Role)
+ {ok, _, _, _} = ssl_manager:connection_init(Certs, Role)
catch
Error:Reason ->
handle_file_error(?LINE, Error, Reason, CACertFile, ecacertfile,
erlang:get_stacktrace())
end,
- init_certificates(Cert, CertDbRef, CacheRef, CertFile, Role).
+ init_certificates(Cert, CertDbRef, CertDbHandle, CacheHandle, CertFile, Role).
-init_certificates(undefined, CertDbRef, CacheRef, "", _) ->
- {ok, CertDbRef, CacheRef, undefined};
+init_certificates(undefined, CertDbRef, CertDbHandle, CacheHandle, "", _) ->
+ {ok, CertDbRef, CertDbHandle, CacheHandle, undefined};
-init_certificates(undefined, CertDbRef, CacheRef, CertFile, client) ->
+init_certificates(undefined, CertDbRef, CertDbHandle, CacheHandle, CertFile, client) ->
try
- [OwnCert] = ssl_certificate:file_to_certificats(CertFile),
- {ok, CertDbRef, CacheRef, OwnCert}
+ [OwnCert] = ssl_certificate:file_to_certificats(CertFile, CertDbHandle),
+ {ok, CertDbRef, CertDbHandle, CacheHandle, OwnCert}
catch _Error:_Reason ->
- {ok, CertDbRef, CacheRef, undefined}
+ {ok, CertDbRef, CertDbHandle, CacheHandle, undefined}
end;
-init_certificates(undefined, CertDbRef, CacheRef, CertFile, server) ->
+init_certificates(undefined, CertDbRef, CertDbHandle, CacheRef, CertFile, server) ->
try
- [OwnCert] = ssl_certificate:file_to_certificats(CertFile),
- {ok, CertDbRef, CacheRef, OwnCert}
+ [OwnCert] = ssl_certificate:file_to_certificats(CertFile, CertDbHandle),
+ {ok, CertDbRef, CertDbHandle, CacheRef, OwnCert}
catch
Error:Reason ->
handle_file_error(?LINE, Error, Reason, CertFile, ecertfile,
erlang:get_stacktrace())
end;
-init_certificates(Cert, CertDbRef, CacheRef, _, _) ->
- {ok, CertDbRef, CacheRef, Cert}.
+init_certificates(Cert, CertDbRef, CertDbHandle, CacheRef, _, _) ->
+ {ok, CertDbRef, CertDbHandle, CacheRef, Cert}.
-init_private_key(undefined, "", _Password, _Client) ->
+init_private_key(_, undefined, "", _Password, _Client) ->
undefined;
-init_private_key(undefined, KeyFile, Password, _) ->
+init_private_key(DbHandle, undefined, KeyFile, Password, _) ->
try
- {ok, List} = ssl_manager:cache_pem_file(KeyFile),
+ {ok, List} = ssl_manager:cache_pem_file(KeyFile, DbHandle),
[PemEntry] = [PemEntry || PemEntry = {PKey, _ , _} <- List,
- PKey =:= 'RSAPrivateKey' orelse
- PKey =:= 'DSAPrivateKey'],
- public_key:pem_entry_decode(PemEntry, Password)
+ PKey =:= 'RSAPrivateKey' orelse
+ PKey =:= 'DSAPrivateKey' orelse
+ PKey =:= 'PrivateKeyInfo'
+ ],
+ private_key(public_key:pem_entry_decode(PemEntry, Password))
catch
Error:Reason ->
handle_file_error(?LINE, Error, Reason, KeyFile, ekeyfile,
erlang:get_stacktrace())
end;
-init_private_key({rsa, PrivateKey}, _, _,_) ->
- public_key:der_decode('RSAPrivateKey', PrivateKey);
-init_private_key({dsa, PrivateKey},_,_,_) ->
- public_key:der_decode('DSAPrivateKey', PrivateKey).
+%% First two clauses are for backwards compatibility
+init_private_key(_,{rsa, PrivateKey}, _, _,_) ->
+ init_private_key('RSAPrivateKey', PrivateKey);
+init_private_key(_,{dsa, PrivateKey},_,_,_) ->
+ init_private_key('DSAPrivateKey', PrivateKey);
+init_private_key(_,{Asn1Type, PrivateKey},_,_,_) ->
+ private_key(init_private_key(Asn1Type, PrivateKey)).
+
+init_private_key(Asn1Type, PrivateKey) ->
+ public_key:der_decode(Asn1Type, PrivateKey).
+
+private_key(#'PrivateKeyInfo'{privateKeyAlgorithm =
+ #'PrivateKeyInfo_privateKeyAlgorithm'{algorithm = ?'rsaEncryption'},
+ privateKey = Key}) ->
+ public_key:der_decode('RSAPrivateKey', iolist_to_binary(Key));
+
+private_key(#'PrivateKeyInfo'{privateKeyAlgorithm =
+ #'PrivateKeyInfo_privateKeyAlgorithm'{algorithm = ?'id-dsa'},
+ privateKey = Key}) ->
+ public_key:der_decode('DSAPrivateKey', iolist_to_binary(Key));
+private_key(Key) ->
+ Key.
-spec(handle_file_error(_,_,_,_,_,_) -> no_return()).
handle_file_error(Line, Error, {badmatch, Reason}, File, Throw, Stack) ->
@@ -1128,15 +1172,15 @@ file_error(Line, Error, Reason, File, Throw, Stack) ->
error_logger:error_report(Report),
throw(Throw).
-init_diffie_hellman(Params, _,_) when is_binary(Params)->
+init_diffie_hellman(_,Params, _,_) when is_binary(Params)->
public_key:der_decode('DHParameter', Params);
-init_diffie_hellman(_,_, client) ->
+init_diffie_hellman(_,_,_, client) ->
undefined;
-init_diffie_hellman(_,undefined, _) ->
+init_diffie_hellman(_,_,undefined, _) ->
?DEFAULT_DIFFIE_HELLMAN_PARAMS;
-init_diffie_hellman(_, DHParamFile, server) ->
+init_diffie_hellman(DbHandle,_, DHParamFile, server) ->
try
- {ok, List} = ssl_manager:cache_pem_file(DHParamFile),
+ {ok, List} = ssl_manager:cache_pem_file(DHParamFile,DbHandle),
case [Entry || Entry = {'DHParameter', _ , _} <- List] of
[Entry] ->
public_key:pem_entry_decode(Entry);
@@ -1180,11 +1224,12 @@ certify_client(#state{client_certificate_requested = true, role = client,
connection_states = ConnectionStates0,
transport_cb = Transport,
negotiated_version = Version,
+ cert_db = CertDbHandle,
cert_db_ref = CertDbRef,
session = #session{own_certificate = OwnCert},
socket = Socket,
tls_handshake_hashes = Hashes0} = State) ->
- Certificate = ssl_handshake:certificate(OwnCert, CertDbRef, client),
+ Certificate = ssl_handshake:certificate(OwnCert, CertDbHandle, CertDbRef, client),
{BinCert, ConnectionStates1, Hashes1} =
encode_handshake(Certificate, Version, ConnectionStates0, Hashes0),
Transport:send(Socket, BinCert),
@@ -1365,9 +1410,10 @@ certify_server(#state{transport_cb = Transport,
negotiated_version = Version,
connection_states = ConnectionStates,
tls_handshake_hashes = Hashes,
+ cert_db = CertDbHandle,
cert_db_ref = CertDbRef,
session = #session{own_certificate = OwnCert}} = State) ->
- case ssl_handshake:certificate(OwnCert, CertDbRef, server) of
+ case ssl_handshake:certificate(OwnCert, CertDbHandle, CertDbRef, server) of
CertMsg = #certificate{} ->
{BinCertMsg, NewConnectionStates, NewHashes} =
encode_handshake(CertMsg, Version, ConnectionStates, Hashes),
@@ -1454,12 +1500,13 @@ rsa_key_exchange(_, _) ->
request_client_cert(#state{ssl_options = #ssl_options{verify = verify_peer},
connection_states = ConnectionStates0,
+ cert_db = CertDbHandle,
cert_db_ref = CertDbRef,
tls_handshake_hashes = Hashes0,
negotiated_version = Version,
socket = Socket,
transport_cb = Transport} = State) ->
- Msg = ssl_handshake:certificate_request(ConnectionStates0, CertDbRef),
+ Msg = ssl_handshake:certificate_request(ConnectionStates0, CertDbHandle, CertDbRef),
{BinMsg, ConnectionStates1, Hashes1} =
encode_handshake(Msg, Version, ConnectionStates0, Hashes0),
Transport:send(Socket, BinMsg),
@@ -1772,7 +1819,8 @@ format_reply(binary, _, N, Data) when N > 0 -> % Header mode
format_reply(binary, _, _, Data) ->
Data;
format_reply(list, Packet, _, Data)
- when Packet == http; Packet == {http, headers}; Packet == http_bin; Packet == {http_bin, headers} ->
+ when Packet == http; Packet == {http, headers}; Packet == http_bin; Packet == {http_bin, headers}; Packet == httph;
+ Packet == httph_bin->
Data;
format_reply(list, _,_, Data) ->
binary_to_list(Data).
@@ -1959,16 +2007,16 @@ next_state_is_connection(State0) ->
public_key_info = undefined,
tls_handshake_hashes = {<<>>, <<>>}}).
-register_session(_, _, _, #session{is_resumable = true} = Session) ->
- Session; %% Already registered
-register_session(client, Host, Port, Session0) ->
+register_session(client, Host, Port, #session{is_resumable = new} = Session0) ->
Session = Session0#session{is_resumable = true},
ssl_manager:register_session(Host, Port, Session),
Session;
-register_session(server, _, Port, Session0) ->
+register_session(server, _, Port, #session{is_resumable = new} = Session0) ->
Session = Session0#session{is_resumable = true},
ssl_manager:register_session(Port, Session),
- Session.
+ Session;
+register_session(_, _, _, Session) ->
+ Session. %% Already registered
invalidate_session(client, Host, Port, Session) ->
ssl_manager:invalidate_session(Host, Port, Session);
@@ -1992,7 +2040,7 @@ initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions}, User,
%% We do not want to save the password in the state so that
%% could be written in the clear into error logs.
ssl_options = SSLOptions#ssl_options{password = undefined},
- session = #session{is_resumable = false},
+ session = #session{is_resumable = new},
transport_cb = CbModule,
data_tag = DataTag,
close_tag = CloseTag,
@@ -2040,31 +2088,69 @@ get_socket_opts(Socket, [active | Tags], SockOpts, Acc) ->
get_socket_opts(Socket, Tags, SockOpts,
[{active, SockOpts#socket_options.active} | Acc]);
get_socket_opts(Socket, [Tag | Tags], SockOpts, Acc) ->
- case inet:getopts(Socket, [Tag]) of
+ try inet:getopts(Socket, [Tag]) of
{ok, [Opt]} ->
get_socket_opts(Socket, Tags, SockOpts, [Opt | Acc]);
{error, Error} ->
- {error, Error}
- end.
+ {error, {eoptions, {inet_option, Tag, Error}}}
+ catch
+ %% So that inet behavior does not crash our process
+ _:Error -> {error, {eoptions, {inet_option, Tag, Error}}}
+ end;
+get_socket_opts(_,Opts, _,_) ->
+ {error, {eoptions, {inet_option, Opts, function_clause}}}.
set_socket_opts(_, [], SockOpts, []) ->
- SockOpts;
+ {ok, SockOpts};
set_socket_opts(Socket, [], SockOpts, Other) ->
%% Set non emulated options
- inet:setopts(Socket, Other),
- SockOpts;
-set_socket_opts(Socket, [{mode, Mode}| Opts], SockOpts, Other) ->
+ try inet:setopts(Socket, Other) of
+ ok ->
+ {ok, SockOpts};
+ {error, InetError} ->
+ {{error, {eoptions, {inet_options, Other, InetError}}}, SockOpts}
+ catch
+ _:Error ->
+ %% So that inet behavior does not crash our process
+ {{error, {eoptions, {inet_options, Other, Error}}}, SockOpts}
+ end;
+
+set_socket_opts(Socket, [{mode, Mode}| Opts], SockOpts, Other) when Mode == list; Mode == binary ->
set_socket_opts(Socket, Opts,
SockOpts#socket_options{mode = Mode}, Other);
-set_socket_opts(Socket, [{packet, Packet}| Opts], SockOpts, Other) ->
+set_socket_opts(_, [{mode, _} = Opt| _], SockOpts, _) ->
+ {{error, {eoptions, {inet_opt, Opt}}}, SockOpts};
+set_socket_opts(Socket, [{packet, Packet}| Opts], SockOpts, Other) when Packet == raw;
+ Packet == 0;
+ Packet == 1;
+ Packet == 2;
+ Packet == 4;
+ Packet == asn1;
+ Packet == cdr;
+ Packet == sunrm;
+ Packet == fcgi;
+ Packet == tpkt;
+ Packet == line;
+ Packet == http;
+ Packet == httph;
+ Packet == http_bin;
+ Packet == httph_bin ->
set_socket_opts(Socket, Opts,
SockOpts#socket_options{packet = Packet}, Other);
-set_socket_opts(Socket, [{header, Header}| Opts], SockOpts, Other) ->
+set_socket_opts(_, [{packet, _} = Opt| _], SockOpts, _) ->
+ {{error, {eoptions, {inet_opt, Opt}}}, SockOpts};
+set_socket_opts(Socket, [{header, Header}| Opts], SockOpts, Other) when is_integer(Header) ->
set_socket_opts(Socket, Opts,
SockOpts#socket_options{header = Header}, Other);
-set_socket_opts(Socket, [{active, Active}| Opts], SockOpts, Other) ->
+set_socket_opts(_, [{header, _} = Opt| _], SockOpts, _) ->
+ {{error,{eoptions, {inet_opt, Opt}}}, SockOpts};
+set_socket_opts(Socket, [{active, Active}| Opts], SockOpts, Other) when Active == once;
+ Active == true;
+ Active == false ->
set_socket_opts(Socket, Opts,
SockOpts#socket_options{active = Active}, Other);
+set_socket_opts(_, [{active, _} = Opt| _], SockOpts, _) ->
+ {{error, {eoptions, {inet_opt, Opt}} }, SockOpts};
set_socket_opts(Socket, [Opt | Opts], SockOpts, Other) ->
set_socket_opts(Socket, Opts, SockOpts, [Opt | Other]).
diff --git a/lib/ssl/src/ssl_connection_sup.erl b/lib/ssl/src/ssl_connection_sup.erl
index e9328d5f7c..78cfda5e63 100644
--- a/lib/ssl/src/ssl_connection_sup.erl
+++ b/lib/ssl/src/ssl_connection_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -26,8 +26,8 @@
-behaviour(supervisor).
%% API
--export([start_link/0]).
--export([start_child/1]).
+-export([start_link/0, start_link_dist/0]).
+-export([start_child/1, start_child_dist/1]).
%% Supervisor callback
-export([init/1]).
@@ -38,9 +38,15 @@
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+start_link_dist() ->
+ supervisor:start_link({local, ssl_connection_sup_dist}, ?MODULE, []).
+
start_child(Args) ->
supervisor:start_child(?MODULE, Args).
+start_child_dist(Args) ->
+ supervisor:start_child(ssl_connection_sup_dist, Args).
+
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
diff --git a/lib/ssl/src/ssl_dist_sup.erl b/lib/ssl/src/ssl_dist_sup.erl
new file mode 100644
index 0000000000..c1912401d7
--- /dev/null
+++ b/lib/ssl/src/ssl_dist_sup.erl
@@ -0,0 +1,84 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(ssl_dist_sup).
+
+-behaviour(supervisor).
+
+%% API
+-export([start_link/0]).
+
+%% Supervisor callback
+-export([init/1]).
+
+%%%=========================================================================
+%%% API
+%%%=========================================================================
+
+-spec start_link() -> {ok, pid()} | ignore | {error, term()}.
+
+start_link() ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+%%%=========================================================================
+%%% Supervisor callback
+%%%=========================================================================
+-spec init([]) -> {ok, {SupFlags :: tuple(), [ChildSpec :: tuple()]}}.
+
+init([]) ->
+ SessionCertManager = session_and_cert_manager_child_spec(),
+ ConnetionManager = connection_manager_child_spec(),
+ ProxyServer = proxy_server_child_spec(),
+
+ {ok, {{one_for_all, 10, 3600}, [SessionCertManager, ConnetionManager,
+ ProxyServer]}}.
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+session_and_cert_manager_child_spec() ->
+ Opts = ssl_sup:manager_opts(),
+ Name = ssl_manager_dist,
+ StartFunc = {ssl_manager, start_link_dist, [Opts]},
+ Restart = permanent,
+ Shutdown = 4000,
+ Modules = [ssl_manager],
+ Type = worker,
+ {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+
+connection_manager_child_spec() ->
+ Name = ssl_connection_dist,
+ StartFunc = {ssl_connection_sup, start_link_dist, []},
+ Restart = permanent,
+ Shutdown = 4000,
+ Modules = [ssl_connection],
+ Type = supervisor,
+ {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+
+proxy_server_child_spec() ->
+ Name = ssl_tls_dist_proxy,
+ StartFunc = {ssl_tls_dist_proxy, start_link, []},
+ Restart = permanent,
+ Shutdown = 4000,
+ Modules = [ssl_tls_dist_proxy],
+ Type = worker,
+ {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index 1f4c44d115..7eb7f44df6 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -31,14 +31,16 @@
-include_lib("public_key/include/public_key.hrl").
-export([master_secret/4, client_hello/6, server_hello/4, hello/4,
- hello_request/0, certify/6, certificate/3,
+ hello_request/0, certify/7, certificate/4,
client_certificate_verify/5, certificate_verify/5,
- certificate_request/2, key_exchange/2, server_key_exchange_hash/2,
+ certificate_request/3, key_exchange/2, server_key_exchange_hash/2,
finished/4, verify_connection/5, get_tls_handshake/2,
decode_client_key/3, server_hello_done/0,
encode_handshake/2, init_hashes/0, update_hashes/2,
decrypt_premaster_secret/2]).
+-export([dec_hello_extensions/2]).
+
-type tls_handshake() :: #client_hello{} | #server_hello{} |
#server_hello_done{} | #certificate{} | #certificate_request{} |
#client_key_exchange{} | #finished{} | #certificate_verify{} |
@@ -48,7 +50,7 @@
%% Internal application API
%%====================================================================
%%--------------------------------------------------------------------
--spec client_hello(host(), port_num(), #connection_states{},
+-spec client_hello(host(), inet:port_number(), #connection_states{},
#ssl_options{}, boolean(), der_cert()) -> #client_hello{}.
%%
%% Description: Creates a client hello message.
@@ -106,7 +108,7 @@ hello_request() ->
%%--------------------------------------------------------------------
-spec hello(#server_hello{} | #client_hello{}, #ssl_options{},
- #connection_states{} | {port_num(), #session{}, cache_ref(),
+ #connection_states{} | {inet:port_number(), #session{}, db_handle(),
atom(), #connection_states{}, binary()},
boolean()) -> {tls_version(), session_id(), #connection_states{}}|
{tls_version(), {resumed | new, #session{}},
@@ -173,13 +175,13 @@ hello(#client_hello{client_version = ClientVersion, random = Random,
end.
%%--------------------------------------------------------------------
--spec certify(#certificate{}, term(), integer() | nolimit,
+-spec certify(#certificate{}, db_handle(), certdb_ref(), integer() | nolimit,
verify_peer | verify_none, {fun(), term},
client | server) -> {der_cert(), public_key_info()} | #alert{}.
%%
%% Description: Handles a certificate handshake message
%%--------------------------------------------------------------------
-certify(#certificate{asn1_certificates = ASN1Certs}, CertDbRef,
+certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef,
MaxPathLen, _Verify, VerifyFunAndState, Role) ->
[PeerCert | _] = ASN1Certs,
@@ -208,7 +210,7 @@ certify(#certificate{asn1_certificates = ASN1Certs}, CertDbRef,
end,
{TrustedErlCert, CertPath} =
- ssl_certificate:trusted_cert_and_path(ASN1Certs, CertDbRef),
+ ssl_certificate:trusted_cert_and_path(ASN1Certs, CertDbHandle, CertDbRef),
case public_key:pkix_path_validation(TrustedErlCert,
CertPath,
@@ -222,13 +224,13 @@ certify(#certificate{asn1_certificates = ASN1Certs}, CertDbRef,
end.
%%--------------------------------------------------------------------
--spec certificate(der_cert(), term(), client | server) -> #certificate{} | #alert{}.
+-spec certificate(der_cert(), db_handle(), certdb_ref(), client | server) -> #certificate{} | #alert{}.
%%
%% Description: Creates a certificate message.
%%--------------------------------------------------------------------
-certificate(OwnCert, CertDbRef, client) ->
+certificate(OwnCert, CertDbHandle, CertDbRef, client) ->
Chain =
- case ssl_certificate:certificate_chain(OwnCert, CertDbRef) of
+ case ssl_certificate:certificate_chain(OwnCert, CertDbHandle, CertDbRef) of
{ok, CertChain} ->
CertChain;
{error, _} ->
@@ -239,8 +241,8 @@ certificate(OwnCert, CertDbRef, client) ->
end,
#certificate{asn1_certificates = Chain};
-certificate(OwnCert, CertDbRef, server) ->
- case ssl_certificate:certificate_chain(OwnCert, CertDbRef) of
+certificate(OwnCert, CertDbHandle, CertDbRef, server) ->
+ case ssl_certificate:certificate_chain(OwnCert, CertDbHandle, CertDbRef) of
{ok, Chain} ->
#certificate{asn1_certificates = Chain};
{error, _} ->
@@ -302,17 +304,17 @@ certificate_verify(Signature, {?'id-dsa' = Algorithm, PublicKey, PublicKeyParams
%%--------------------------------------------------------------------
--spec certificate_request(#connection_states{}, certdb_ref()) ->
+-spec certificate_request(#connection_states{}, db_handle(), certdb_ref()) ->
#certificate_request{}.
%%
%% Description: Creates a certificate_request message, called by the server.
%%--------------------------------------------------------------------
-certificate_request(ConnectionStates, CertDbRef) ->
+certificate_request(ConnectionStates, CertDbHandle, CertDbRef) ->
#connection_state{security_parameters =
#security_parameters{cipher_suite = CipherSuite}} =
ssl_record:pending_connection_state(ConnectionStates, read),
Types = certificate_types(CipherSuite),
- Authorities = certificate_authorities(CertDbRef),
+ Authorities = certificate_authorities(CertDbHandle, CertDbRef),
#certificate_request{
certificate_types = Types,
certificate_authorities = Authorities
@@ -383,8 +385,9 @@ master_secret(Version, #session{master_secret = Mastersecret},
ConnectionStates, Role)
catch
exit:Reason ->
- error_logger:error_report("Key calculation failed due to ~p",
- [Reason]),
+ Report = io_lib:format("Key calculation failed due to ~p",
+ [Reason]),
+ error_logger:error_report(Report),
?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE)
end;
@@ -400,8 +403,9 @@ master_secret(Version, PremasterSecret, ConnectionStates, Role) ->
SecParams, ConnectionStates, Role)
catch
exit:Reason ->
- error_logger:error_report("Master secret calculation failed"
- " due to ~p", [Reason]),
+ Report = io_lib:format("Master secret calculation failed"
+ " due to ~p", [Reason]),
+ error_logger:error_report(Report),
?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE)
end.
@@ -910,9 +914,12 @@ dec_hello_extensions(<<?UINT16(?RENEGOTIATION_EXT), ?UINT16(Len), Info:Len/binar
end,
dec_hello_extensions(Rest, [{renegotiation_info,
#renegotiation_info{renegotiated_connection = RenegotiateInfo}} | Acc]);
-dec_hello_extensions(<<?UINT16(_), ?UINT16(Len), _Unknown:Len, Rest/binary>>, Acc) ->
+
+%% Ignore data following the ClientHello (i.e.,
+%% extensions) if not understood.
+dec_hello_extensions(<<?UINT16(_), ?UINT16(Len), _Unknown:Len/binary, Rest/binary>>, Acc) ->
dec_hello_extensions(Rest, Acc);
-%% Need this clause?
+%% This theoretically should not happen if the protocol is followed, but if it does it is ignored.
dec_hello_extensions(_, Acc) ->
Acc.
@@ -1071,8 +1078,8 @@ certificate_types({KeyExchange, _, _, _})
certificate_types(_) ->
<<?BYTE(?RSA_SIGN)>>.
-certificate_authorities(CertDbRef) ->
- Authorities = certificate_authorities_from_db(CertDbRef),
+certificate_authorities(CertDbHandle, CertDbRef) ->
+ Authorities = certificate_authorities_from_db(CertDbHandle, CertDbRef),
Enc = fun(#'OTPCertificate'{tbsCertificate=TBSCert}) ->
OTPSubj = TBSCert#'OTPTBSCertificate'.subject,
DNEncodedBin = public_key:pkix_encode('Name', OTPSubj, otp),
@@ -1084,19 +1091,13 @@ certificate_authorities(CertDbRef) ->
end,
list_to_binary([Enc(Cert) || {_, Cert} <- Authorities]).
-certificate_authorities_from_db(CertDbRef) ->
- certificate_authorities_from_db(CertDbRef, no_candidate, []).
-
-certificate_authorities_from_db(CertDbRef, PrevKey, Acc) ->
- case ssl_manager:issuer_candidate(PrevKey) of
- no_more_candidates ->
- lists:reverse(Acc);
- {{CertDbRef, _, _} = Key, Cert} ->
- certificate_authorities_from_db(CertDbRef, Key, [Cert|Acc]);
- {Key, _Cert} ->
- %% skip certs not from this ssl connection
- certificate_authorities_from_db(CertDbRef, Key, Acc)
- end.
+certificate_authorities_from_db(CertDbHandle, CertDbRef) ->
+ ConnectionCerts = fun({{Ref, _, _}, Cert}, Acc) when Ref == CertDbRef ->
+ [Cert | Acc];
+ (_, Acc) ->
+ Acc
+ end,
+ ssl_certificate_db:foldl(ConnectionCerts, [], CertDbHandle).
digitally_signed(Hash, #'RSAPrivateKey'{} = Key) ->
public_key:encrypt_private(Hash, Key,
diff --git a/lib/ssl/src/ssl_int.hrl b/lib/ssl/src/ssl_int.hrl
deleted file mode 100644
index 3686deffce..0000000000
--- a/lib/ssl/src/ssl_int.hrl
+++ /dev/null
@@ -1,99 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-
-%% op codes commands are in capital and reply codes in lower case
-
--define(CONNECT, 1).
--define(CONNECT_WAIT, 2).
--define(CONNECT_REP, 3).
--define(CONNECT_ERR, 4).
-
--define(TERMINATE, 5).
--define(CLOSE, 6).
-
--define(LISTEN, 7).
--define(LISTEN_REP, 8).
--define(LISTEN_ERR, 9).
-
--define(TRANSPORT_ACCEPT, 10).
--define(NOACCEPT, 11).
--define(TRANSPORT_ACCEPT_REP, 12).
--define(TRANSPORT_ACCEPT_ERR, 13).
-
--define(FROMNET_CLOSE, 14).
-
--define(CONNECT_SYNC_ERR, 15).
--define(LISTEN_SYNC_ERR, 16).
-
--define(PROXY_PORT, 23).
--define(PROXY_JOIN, 24).
--define(PROXY_JOIN_REP, 25).
--define(PROXY_JOIN_ERR, 26).
-
--define(SET_SOCK_OPT, 27).
--define(IOCTL_OK, 28).
--define(IOCTL_ERR, 29).
-
--define(GETPEERNAME, 30).
--define(GETPEERNAME_REP, 31).
--define(GETPEERNAME_ERR, 32).
-
--define(GETSOCKNAME, 33).
--define(GETSOCKNAME_REP, 34).
--define(GETSOCKNAME_ERR, 35).
-
--define(GETPEERCERT, 36).
--define(GETPEERCERT_REP, 37).
--define(GETPEERCERT_ERR, 38).
-
--define(GETVERSION, 39).
--define(GETVERSION_REP, 40).
-
--define(SET_SEED, 41).
-
--define(GETCONNINFO, 42).
--define(GETCONNINFO_REP, 43).
--define(GETCONNINFO_ERR, 44).
-
--define(SSL_ACCEPT, 45).
--define(SSL_ACCEPT_REP, 46).
--define(SSL_ACCEPT_ERR, 47).
-
--define(DUMP_CMD, 48).
--define(DEBUG_CMD, 49).
--define(DEBUGMSG_CMD, 50).
-
-%% --------------
-
--define(SSLv2, 1).
--define(SSLv3, 2).
--define(TLSv1, 4).
-
-
-%% Set socket options codes 'SET_SOCK_OPT'
--define(SET_TCP_NODELAY, 1).
-
--define(DEF_BACKLOG, 128).
-
--define(DEF_TIMEOUT, 10000).
-
--record(sslsocket, { fd = nil, pid = nil}).
-
diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl
index c28daa271e..18cfcdcd68 100644
--- a/lib/ssl/src/ssl_internal.hrl
+++ b/lib/ssl/src/ssl_internal.hrl
@@ -24,17 +24,19 @@
-include_lib("public_key/include/public_key.hrl").
+%% Looks like it does for backwards compatibility reasons
+-record(sslsocket, {fd = nil, pid = nil}).
+
-type reason() :: term().
-type reply() :: term().
-type msg() :: term().
-type from() :: term().
--type host() :: string() | tuple().
--type port_num() :: integer().
+-type host() :: inet:ip_address() | inet:hostname().
-type session_id() :: 0 | binary().
-type tls_version() :: {integer(), integer()}.
-type tls_atom_version() :: sslv3 | tlsv1.
--type cache_ref() :: term().
--type certdb_ref() :: term().
+-type certdb_ref() :: reference().
+-type db_handle() :: term().
-type key_algo() :: null | rsa | dhe_rsa | dhe_dss | dh_anon.
-type der_cert() :: binary().
-type private_key() :: #'RSAPrivateKey'{} | #'DSAPrivateKey'{}.
@@ -99,10 +101,12 @@
renegotiate_at,
secure_renegotiate,
debug,
- hibernate_after % undefined if not hibernating,
+ hibernate_after,% undefined if not hibernating,
% or number of ms of inactivity
% after which ssl_connection will
% go into hibernation
+ %% This option should only be set to true by inet_tls_dist
+ erl_dist = false
}).
-record(socket_options,
diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl
index 541ca1e918..6a44ef8c3e 100644
--- a/lib/ssl/src/ssl_manager.erl
+++ b/lib/ssl/src/ssl_manager.erl
@@ -27,10 +27,10 @@
-include("ssl_internal.hrl").
%% Internal application API
--export([start_link/1,
- connection_init/2, cache_pem_file/1,
- lookup_trusted_cert/3, issuer_candidate/1, client_session_id/4,
- server_session_id/4,
+-export([start_link/1, start_link_dist/1,
+ connection_init/2, cache_pem_file/2,
+ lookup_trusted_cert/4,
+ client_session_id/4, server_session_id/4,
register_session/2, register_session/3, invalidate_session/2,
invalidate_session/3]).
@@ -50,7 +50,8 @@
session_cache_cb,
session_lifetime,
certificate_db,
- session_validation_timer
+ session_validation_timer,
+ last_delay_timer %% Keep for testing purposes
}).
-define('24H_in_msec', 8640000).
@@ -65,54 +66,55 @@
%%--------------------------------------------------------------------
-spec start_link(list()) -> {ok, pid()} | ignore | {error, term()}.
%%
-%% Description: Starts the server
+%% Description: Starts the ssl manager that takes care of sessions
+%% and certificate caching.
%%--------------------------------------------------------------------
start_link(Opts) ->
- gen_server:start_link({local, ?MODULE}, ?MODULE, [Opts], []).
+ gen_server:start_link({local, ?MODULE}, ?MODULE, [?MODULE, Opts], []).
+
+%%--------------------------------------------------------------------
+-spec start_link_dist(list()) -> {ok, pid()} | ignore | {error, term()}.
+%%
+%% Description: Starts a special instance of the ssl manager to
+%% be used by the erlang distribution. Note disables soft upgrade!
+%%--------------------------------------------------------------------
+start_link_dist(Opts) ->
+ gen_server:start_link({local, ssl_manager_dist}, ?MODULE, [ssl_manager_dist, Opts], []).
%%--------------------------------------------------------------------
-spec connection_init(string()| {der, list()}, client | server) ->
- {ok, reference(), cache_ref()}.
+ {ok, certdb_ref(), db_handle(), db_handle()}.
%%
%% Description: Do necessary initializations for a new connection.
%%--------------------------------------------------------------------
connection_init(Trustedcerts, Role) ->
call({connection_init, Trustedcerts, Role}).
%%--------------------------------------------------------------------
--spec cache_pem_file(string()) -> {ok, term()} | {error, reason()}.
+-spec cache_pem_file(string(), term()) -> {ok, term()} | {error, reason()}.
%%
%% Description: Cach a pem file and return its content.
%%--------------------------------------------------------------------
-cache_pem_file(File) ->
+cache_pem_file(File, DbHandle) ->
try file:read_file_info(File) of
{ok, #file_info{mtime = LastWrite}} ->
- cache_pem_file(File, LastWrite)
+ cache_pem_file(File, LastWrite, DbHandle)
catch
_:Reason ->
{error, Reason}
end.
%%--------------------------------------------------------------------
--spec lookup_trusted_cert(reference(), serialnumber(), issuer()) ->
+-spec lookup_trusted_cert(term(), reference(), serialnumber(), issuer()) ->
undefined |
{ok, {der_cert(), #'OTPCertificate'{}}}.
%%
%% Description: Lookup the trusted cert with Key = {reference(),
%% serialnumber(), issuer()}.
%% --------------------------------------------------------------------
-lookup_trusted_cert(Ref, SerialNumber, Issuer) ->
- ssl_certificate_db:lookup_trusted_cert(Ref, SerialNumber, Issuer).
-%%--------------------------------------------------------------------
--spec issuer_candidate(cert_key() | no_candidate) ->
- {cert_key(),
- {der_cert(),
- #'OTPCertificate'{}}} | no_more_candidates.
-%%
-%% Description: Return next issuer candidate.
-%%--------------------------------------------------------------------
-issuer_candidate(PrevCandidateKey) ->
- ssl_certificate_db:issuer_candidate(PrevCandidateKey).
+lookup_trusted_cert(DbHandle, Ref, SerialNumber, Issuer) ->
+ ssl_certificate_db:lookup_trusted_cert(DbHandle, Ref, SerialNumber, Issuer).
+
%%--------------------------------------------------------------------
--spec client_session_id(host(), port_num(), #ssl_options{},
+-spec client_session_id(host(), inet:port_number(), #ssl_options{},
der_cert() | undefined) -> session_id().
%%
%% Description: Select a session id for the client.
@@ -121,7 +123,7 @@ client_session_id(Host, Port, SslOpts, OwnCert) ->
call({client_session_id, Host, Port, SslOpts, OwnCert}).
%%--------------------------------------------------------------------
--spec server_session_id(host(), port_num(), #ssl_options{},
+-spec server_session_id(host(), inet:port_number(), #ssl_options{},
der_cert()) -> session_id().
%%
%% Description: Select a session id for the server.
@@ -130,8 +132,8 @@ server_session_id(Port, SuggestedSessionId, SslOpts, OwnCert) ->
call({server_session_id, Port, SuggestedSessionId, SslOpts, OwnCert}).
%%--------------------------------------------------------------------
--spec register_session(port_num(), #session{}) -> ok.
--spec register_session(host(), port_num(), #session{}) -> ok.
+-spec register_session(inet:port_number(), #session{}) -> ok.
+-spec register_session(host(), inet:port_number(), #session{}) -> ok.
%%
%% Description: Make the session available for reuse.
%%--------------------------------------------------------------------
@@ -141,8 +143,8 @@ register_session(Host, Port, Session) ->
register_session(Port, Session) ->
cast({register_session, Port, Session}).
%%--------------------------------------------------------------------
--spec invalidate_session(port_num(), #session{}) -> ok.
--spec invalidate_session(host(), port_num(), #session{}) -> ok.
+-spec invalidate_session(inet:port_number(), #session{}) -> ok.
+-spec invalidate_session(host(), inet:port_number(), #session{}) -> ok.
%%
%% Description: Make the session unavailable for reuse. After
%% a the session has been marked "is_resumable = false" for some while
@@ -165,7 +167,8 @@ invalidate_session(Port, Session) ->
%%
%% Description: Initiates the server
%%--------------------------------------------------------------------
-init([Opts]) ->
+init([Name, Opts]) ->
+ put(ssl_manager, Name),
process_flag(trap_exit, true),
CacheCb = proplists:get_value(session_cb, Opts, ssl_session_cache),
SessionLifeTime =
@@ -192,19 +195,20 @@ init([Opts]) ->
%% Description: Handling call messages
%%--------------------------------------------------------------------
handle_call({{connection_init, "", _Role}, Pid}, _From,
- #state{session_cache = Cache} = State) ->
+ #state{certificate_db = [CertDb |_],
+ session_cache = Cache} = State) ->
erlang:monitor(process, Pid),
- Result = {ok, make_ref(), Cache},
+ Result = {ok, make_ref(),CertDb, Cache},
{reply, Result, State};
handle_call({{connection_init, Trustedcerts, _Role}, Pid}, _From,
- #state{certificate_db = Db,
+ #state{certificate_db = [CertDb|_] =Db,
session_cache = Cache} = State) ->
erlang:monitor(process, Pid),
Result =
try
{ok, Ref} = ssl_certificate_db:add_trusted_certs(Pid, Trustedcerts, Db),
- {ok, Ref, Cache}
+ {ok, Ref, CertDb, Cache}
catch
_:Reason ->
{error, Reason}
@@ -265,23 +269,16 @@ handle_cast({register_session, Port, Session},
CacheCb:update(Cache, {Port, NewSession#session.session_id}, NewSession),
{noreply, State};
-%%% When a session is invalidated we need to wait a while before deleting
-%%% it as there might be pending connections that rightfully needs to look
-%%% up the session data but new connections should not get to use this session.
handle_cast({invalidate_session, Host, Port,
#session{session_id = ID} = Session},
#state{session_cache = Cache,
session_cache_cb = CacheCb} = State) ->
- CacheCb:update(Cache, {{Host, Port}, ID}, Session#session{is_resumable = false}),
- timer:send_after(delay_time(), self(), {delayed_clean_session, {{Host, Port}, ID}}),
- {noreply, State};
+ invalidate_session(Cache, CacheCb, {{Host, Port}, ID}, Session, State);
handle_cast({invalidate_session, Port, #session{session_id = ID} = Session},
#state{session_cache = Cache,
session_cache_cb = CacheCb} = State) ->
- CacheCb:update(Cache, {Port, ID}, Session#session{is_resumable = false}),
- timer:send_after(delay_time(), self(), {delayed_clean_session, {Port, ID}}),
- {noreply, State};
+ invalidate_session(Cache, CacheCb, {Port, ID}, Session, State);
handle_cast({recache_pem, File, LastWrite, Pid, From},
#state{certificate_db = [_, FileToRefDb, _]} = State0) ->
@@ -305,7 +302,7 @@ handle_cast({recache_pem, File, LastWrite, Pid, From},
%% {stop, reason(), #state{}}.
%%
%% Description: Handling all non call/cast messages
-%%--------------------------------------------------------------------
+%%-------------------------------------------------------------------
handle_info(validate_sessions, #state{session_cache_cb = CacheCb,
session_cache = Cache,
session_lifetime = LifeTime
@@ -372,10 +369,10 @@ code_change(_OldVsn, State, _Extra) ->
%%% Internal functions
%%--------------------------------------------------------------------
call(Msg) ->
- gen_server:call(?MODULE, {Msg, self()}, infinity).
+ gen_server:call(get(ssl_manager), {Msg, self()}, infinity).
cast(Msg) ->
- gen_server:cast(?MODULE, Msg).
+ gen_server:cast(get(ssl_manager), Msg).
validate_session(Host, Port, Session, LifeTime) ->
case ssl_session:valid_session(Session, LifeTime) of
@@ -395,9 +392,10 @@ validate_session(Port, Session, LifeTime) ->
start_session_validator(Cache, CacheCb, LifeTime) ->
spawn_link(?MODULE, init_session_validator,
- [[Cache, CacheCb, LifeTime]]).
+ [[get(ssl_manager), Cache, CacheCb, LifeTime]]).
-init_session_validator([Cache, CacheCb, LifeTime]) ->
+init_session_validator([SslManagerName, Cache, CacheCb, LifeTime]) ->
+ put(ssl_manager, SslManagerName),
CacheCb:foldl(fun session_validation/2,
LifeTime, Cache).
@@ -408,8 +406,8 @@ session_validation({{Port, _}, Session}, LifeTime) ->
validate_session(Port, Session, LifeTime),
LifeTime.
-cache_pem_file(File, LastWrite) ->
- case ssl_certificate_db:lookup_cached_certs(File) of
+cache_pem_file(File, LastWrite, DbHandle) ->
+ case ssl_certificate_db:lookup_cached_certs(DbHandle,File) of
[{_, {Mtime, Content}}] ->
case LastWrite of
Mtime ->
@@ -428,3 +426,20 @@ delay_time() ->
_ ->
?CLEAN_SESSION_DB
end.
+
+invalidate_session(Cache, CacheCb, Key, Session, State) ->
+ case CacheCb:lookup(Cache, Key) of
+ undefined -> %% Session is already invalidated
+ {noreply, State};
+ #session{is_resumable = new} ->
+ CacheCb:delete(Cache, Key),
+ {noreply, State};
+ _ ->
+ %% When a registered session is invalidated we need to wait a while before deleting
+ %% it as there might be pending connections that rightfully needs to look
+ %% up the session data but new connections should not get to use this session.
+ CacheCb:update(Cache, Key, Session#session{is_resumable = false}),
+ TRef =
+ erlang:send_after(delay_time(), self(), {delayed_clean_session, Key}),
+ {noreply, State#state{last_delay_timer = TRef}}
+ end.
diff --git a/lib/ssl/src/ssl_prim.erl b/lib/ssl/src/ssl_prim.erl
deleted file mode 100644
index e3140a89d1..0000000000
--- a/lib/ssl/src/ssl_prim.erl
+++ /dev/null
@@ -1,173 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-
-%% Purpose: Primitive interface to SSL, without broker process (used by
-%% SSL distribution).
-
--module(ssl_prim).
-
--export([listen/2, connect/3, accept/1, close/1, send/2, send/3, recv/2, recv/3,
- getll/1, getstat/2, setopts/2, controlling_process/2, peername/1,
- sockname/1, getif/1]).
-
--include("ssl_int.hrl").
--include("ssl_broker_int.hrl").
-
-%-define(filter(Call), filter((catch Call))).
--define(filter(Call), filter(Call)).
-
-listen(Port, Opts) ->
- St = newstate(listener),
- ?filter(ssl_broker:listen_prim(ssl_server_prim, self(), Port, nonactive(Opts), St)).
-
-connect(Address, Port, Opts) ->
- St = newstate(connector),
- ?filter(ssl_broker:connect_prim(ssl_server_prim, inet_tcp, self(), Address,
- Port, nonactive(Opts), infinity, St)).
-
-accept(#st{} = ListenSt0) ->
- case transport_accept(ListenSt0) of
- {ok, ListenSt1} ->
- ssl_accept(ListenSt0, ListenSt1);
- Error ->
- Error
- end.
-
-transport_accept(#st{opts = ListenOpts, thissock = ListenSocket}) ->
- NewSt = newstate(acceptor),
- ListenFd = ListenSocket#sslsocket.fd,
- ?filter(ssl_broker:transport_accept_prim(ssl_server_prim, ListenFd,
- ListenOpts, infinity, NewSt)).
-
-ssl_accept(#st{opts = LOpts}, ListenSt1) ->
- ?filter(ssl_broker:ssl_accept_prim(ssl_server_prim, gen_tcp, self(),
- LOpts, infinity, ListenSt1)).
-
-close(#st{fd = Fd}) when is_integer(Fd) ->
- ssl_server:close_prim(ssl_server_prim, Fd),
- ok;
-close(_) ->
- ok.
-
-send(St, Data) ->
- send(St, Data, []).
-
-send(#st{proxysock = Proxysock, status = open}, Data, Opts) ->
- case inet_tcp:send(Proxysock, Data, Opts) of
- ok ->
- ok;
- {error, _} ->
- {error, closed}
- end;
-send(#st{}, _Data, _Opts) ->
- {error, closed}.
-
-recv(St, Length) ->
- recv(St, Length, infinity).
-
-recv(#st{proxysock = Proxysock, status = open}, Length, Tmo) ->
- inet_tcp:recv(Proxysock, Length, Tmo);
-recv(#st{}, _Length, _Tmo) ->
- {error, closed}.
-
-getll(#st{proxysock = Proxysock, status = open}) ->
- inet:getll(Proxysock);
-getll(#st{}) ->
- {error, closed}.
-
-getstat(#st{proxysock = Proxysock, status = open}, Opts) ->
- inet:getstat(Proxysock, Opts);
-getstat(#st{}, _Opts) ->
- {error, closed}.
-
-setopts(#st{proxysock = Proxysock, status = open}, Opts) ->
- case remove_supported(Opts) of
- [] ->
- inet:setopts(Proxysock, Opts);
- _ ->
- {error, enotsup}
- end;
-setopts(#st{}, _Opts) ->
- {error, closed}.
-
-
-controlling_process(#st{proxysock = Proxysock, status = open}, Pid)
- when is_pid(Pid) ->
- inet_tcp:controlling_process(Proxysock, Pid);
-controlling_process(#st{}, Pid) when is_pid(Pid) ->
- {error, closed}.
-
-peername(#st{fd = Fd, status = open}) ->
- case ssl_server:peername_prim(ssl_server_prim, Fd) of
- {ok, {Address, Port}} ->
- {ok, At} = inet_parse:ipv4_address(Address),
- {ok, {At, Port}};
- Error ->
- Error
- end;
-peername(#st{}) ->
- {error, closed}.
-
-sockname(#st{fd = Fd, status = open}) ->
- case ssl_server:sockname_prim(ssl_server_prim, Fd) of
- {ok, {Address, Port}} ->
- {ok, At} = inet_parse:ipv4_address(Address),
- {ok, {At, Port}};
- Error ->
- Error
- end;
-sockname(#st{}) ->
- {error, closed}.
-
-getif(#st{proxysock = Proxysock, status = open}) ->
- inet:getif(Proxysock);
-getif(#st{}) ->
- {error, closed}.
-
-remove_supported([{active, _}|T]) ->
- remove_supported(T);
-remove_supported([{packet,_}|T]) ->
- remove_supported(T);
-remove_supported([{deliver,_}|T]) ->
- remove_supported(T);
-remove_supported([H|T]) ->
- [H | remove_supported(T)];
-remove_supported([]) ->
- [].
-
-filter(Result) ->
- case Result of
- {ok, _Sock,St} ->
- {ok, St};
- {error, Reason, _St} ->
- {error,Reason}
- end.
-
-nonactive([{active,_}|T]) ->
- nonactive(T);
-nonactive([H|T]) ->
- [H | nonactive(T)];
-nonactive([]) ->
- [{active, false}].
-
-newstate(Type) ->
- #st{brokertype = Type, server = whereis(ssl_server_prim),
- client = undefined, collector = undefined, debug = false}.
diff --git a/lib/ssl/src/ssl_record.erl b/lib/ssl/src/ssl_record.erl
index f1c0073965..72091fdd5f 100644
--- a/lib/ssl/src/ssl_record.erl
+++ b/lib/ssl/src/ssl_record.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -62,6 +62,8 @@
-compile(inline).
+-define(INITIAL_BYTES, 5).
+
%%====================================================================
%% Internal application API
%%====================================================================
@@ -340,7 +342,7 @@ get_tls_records_aux(<<?BYTE(?CHANGE_CIPHER_SPEC),?BYTE(MajVer),?BYTE(MinVer),
get_tls_records_aux(Rest, [#ssl_tls{type = ?CHANGE_CIPHER_SPEC,
version = {MajVer, MinVer},
fragment = Data} | Acc]);
-%% Matches a ssl v2 client hello message.
+%% Matches an ssl v2 client hello message.
%% The server must be able to receive such messages, from clients that
%% are willing to use ssl v3 or higher, but have ssl v2 compatibility.
get_tls_records_aux(<<1:1, Length0:15, Data0:Length0/binary, Rest/binary>>,
@@ -360,16 +362,20 @@ get_tls_records_aux(<<1:1, Length0:15, Data0:Length0/binary, Rest/binary>>,
get_tls_records_aux(<<0:1, _CT:7, ?BYTE(_MajVer), ?BYTE(_MinVer),
?UINT16(Length), _/binary>>,
- _Acc) when Length > ?MAX_CIPHER_TEXT_LENGTH->
+ _Acc) when Length > ?MAX_CIPHER_TEXT_LENGTH ->
?ALERT_REC(?FATAL, ?RECORD_OVERFLOW);
get_tls_records_aux(<<1:1, Length0:15, _/binary>>,_Acc)
- when Length0 > ?MAX_CIPHER_TEXT_LENGTH->
+ when Length0 > ?MAX_CIPHER_TEXT_LENGTH ->
?ALERT_REC(?FATAL, ?RECORD_OVERFLOW);
get_tls_records_aux(Data, Acc) ->
- {lists:reverse(Acc), Data}.
-
+ case size(Data) =< ?MAX_CIPHER_TEXT_LENGTH + ?INITIAL_BYTES of
+ true ->
+ {lists:reverse(Acc), Data};
+ false ->
+ ?ALERT_REC(?FATAL, ?UNEXPECTED_MESSAGE)
+ end.
%%--------------------------------------------------------------------
-spec protocol_version(tls_atom_version() | tls_version()) ->
tls_version() | tls_atom_version().
diff --git a/lib/ssl/src/ssl_server.erl b/lib/ssl/src/ssl_server.erl
deleted file mode 100644
index b66e20a397..0000000000
--- a/lib/ssl/src/ssl_server.erl
+++ /dev/null
@@ -1,1378 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-
-%%% Purpose : SSL server
-
-%%
-%% TODO
-%%
-%% XXX The ip option in listen is not general enough. It is assumed
-%% to be a tuple, which is not always the case.
-
--module(ssl_server).
--behaviour(gen_server).
-
-%% External exports
--export([start_link/0]).
-
--export([transport_accept/2, transport_accept/3, ssl_accept/2, ssl_accept/3,
- ciphers/0, connect/5, connect/6,
- connection_info/1, close/1, listen/3, listen/4, peercert/1,
- peername/1, proxy_join/2, seed/1, setnodelay/2, sockname/1,
- version/0]).
-
--export([start_link_prim/0]).
--export([ssl_accept_prim/4, transport_accept_prim/4,
- connect_prim/7, close_prim/2,
- listen_prim/5, proxy_join_prim/3, peername_prim/2, setnodelay_prim/3,
- sockname_prim/2]).
-
--export([dump/0, dump/1]).
--export([enable_debug/0, disable_debug/0, set_debug/1]).
--export([enable_debugmsg/0, disable_debugmsg/0, set_debugmsg/1]).
-
-%% gen_server callbacks
--export([init/1, handle_call/3, handle_cast/2, handle_info/2,
- code_change/3, terminate/2]).
-
--include("ssl_int.hrl").
-
--record(st, {
- port = [], % port() of port program
- progpid = [], % OS pid of port program
- debug = false, % debug printout flag
- cons = [], % All brokers except pending accepts
- paccepts = [], % Pending accept brokers
- proxylsport = [], % proxy listen socket port
- intref = 0, % internal reference counter
- compvsn = "", % ssl compile library version
- libvsn = "", % ssl library version
- ciphers = [] % available ciphers
- }).
-
-
-%% In all functions below IP is a four tuple, e.g. {192, 236, 52, 7}.
-%% Port, Fd and ListenFd are integers; Flags is a string of characters.
-%%
-%% The prefixes F and L mean foreign and local, respectively.
-%% Example: FIP (IP address for foreign end).
-
-%%
-%% start_link() -> {ok, Pid} | {error, Reason}
-%%
-start_link() ->
- gen_server:start_link({local, ssl_server}, ssl_server, [], []).
-
-start_link_prim() ->
- gen_server:start_link({local, ssl_server_prim}, ssl_server, [], []).
-
-%%
-%% transport_accept(ListenFd, Flags) -> {ok, Fd, ProxyLLPort} |
-%% {error, Reason}
-%%
-transport_accept(ListenFd, Flags) ->
- transport_accept(ListenFd, Flags, infinity).
-transport_accept(ListenFd, Flags, Timeout) ->
- transport_accept_prim(ssl_server,ListenFd, Flags, Timeout).
-
-transport_accept_prim(ServerName, ListenFd, Flags, Timeout) ->
- Req = {transport_accept, self(), ListenFd, Flags},
- gen_server:call(ServerName, Req, Timeout).
-
-%%
-%% ssl_accept(ListenFd, Flags) -> {ok, Fd, ProxyLLPort} |
-%% {error, Reason}
-%%
-ssl_accept(ListenFd, Flags) ->
- ssl_accept(ListenFd, Flags, infinity).
-ssl_accept(ListenFd, Flags, Timeout) ->
- ssl_accept_prim(ssl_server, ListenFd, Flags, Timeout).
-
-ssl_accept_prim(ServerName, Fd, Flags, Timeout) ->
- Req = {ssl_accept, Fd, Flags},
- gen_server:call(ServerName, Req, Timeout).
-
-%%
-%% ciphers() -> {ok, Ciphers}
-%%
-ciphers() ->
- gen_server:call(ssl_server, ciphers, infinity).
-
-%%
-%% close(Fd) -> ok
-%%
-close(Fd) ->
- close_prim(ssl_server, Fd).
-close_prim(ServerName, Fd) ->
- gen_server:call(ServerName, {close, self(), Fd}, infinity),
- ok.
-
-%%
-%% connect(LIP, LPort, FIP, FPort, Flags) -> {ok, Fd, ProxyLFPort} |
-%% {error, Reason}
-%%
-connect(LIP, LPort, FIP, FPort, Flags) ->
- connect(LIP, LPort, FIP, FPort, Flags, infinity).
-connect(LIP, LPort, FIP, FPort, Flags, Timeout) ->
- connect_prim(ssl_server, LIP, LPort, FIP, FPort, Flags, Timeout).
-
-connect_prim(ServerName, LIP, LPort, FIP, FPort, Flags, Timeout) ->
- Req = {connect, self(), LIP, LPort, FIP, FPort, Flags},
- gen_server:call(ServerName, Req, Timeout).
-
-%%
-%% connection_info(Fd) -> {ok, {Protocol, Cipher}} | {error, Reason}
-%%
-connection_info(Fd) ->
- Req = {connection_info, self(), Fd},
- gen_server:call(ssl_server, Req, infinity).
-
-%%
-%% listen(IP, LPort, Flags),
-%% listen(IP, LPort, Flags, BackLog) -> {ok, ListenFd, LPort0} |
-%% {error, Reason}
-%%
-listen(IP, LPort, Flags) ->
- listen(IP, LPort, Flags, ?DEF_BACKLOG).
-listen(IP, LPort, Flags, BackLog) ->
- listen_prim(ssl_server, IP, LPort, Flags, BackLog).
-listen_prim(ServerName, IP, LPort, Flags, BackLog) ->
- Req = {listen, self(), IP, LPort, Flags, BackLog},
- gen_server:call(ServerName, Req, infinity).
-
-%%
-%% peercert(Fd) -> {ok, Cert} | {error, Reason}
-%%
-peercert(Fd) ->
- Req = {peercert, self(), Fd},
- gen_server:call(ssl_server, Req, infinity).
-
-%%
-%% peername(Fd) -> {ok, {Address, Port}} | {error, Reason}
-%%
-peername(Fd) ->
- peername_prim(ssl_server, Fd).
-peername_prim(ServerName, Fd) ->
- Req = {peername, self(), Fd},
- gen_server:call(ServerName, Req, infinity).
-
-%%
-%% proxy_join(Fd, LPort) -> ok | {error, Reason}
-%%
-proxy_join(Fd, LPort) ->
- proxy_join_prim(ssl_server, Fd, LPort).
-proxy_join_prim(ServerName, Fd, LPort) ->
- Req = {proxy_join, self(), Fd, LPort},
- gen_server:call(ServerName, Req, infinity).
-
-%%
-%% seed(Data)
-%%
-seed(Data) ->
- Req = {seed, Data},
- gen_server:call(ssl_server, Req, infinity).
-
-%%
-%% set_nodelay(Fd, Boolean)
-%%
-setnodelay(Fd, Boolean) ->
- setnodelay_prim(ssl_server, Fd, Boolean).
-setnodelay_prim(ServerName, Fd, Boolean) ->
- Req = {setnodelay, self(), Fd, Boolean},
- gen_server:call(ServerName, Req, infinity).
-
-%%
-%% sockname(Fd) -> {ok, {Address, Port}} | {error, Reason}
-%%
-sockname(Fd) ->
- sockname_prim(ssl_server, Fd).
-sockname_prim(ServerName, Fd) ->
- Req = {sockname, self(), Fd},
- gen_server:call(ServerName, Req, infinity).
-
-%%
-%% version() -> {ok, {CompVsn, LibVsn}}
-%%
-version() ->
- gen_server:call(ssl_server, version, infinity).
-
-
-enable_debug() ->
- set_debug(true).
-
-disable_debug() ->
- set_debug(false).
-
-set_debug(Bool) ->
- set_debug(Bool, infinity).
-
-set_debug(Bool, Timeout) when is_boolean(Bool) ->
- Req = {set_debug, Bool, self()},
- gen_server:call(ssl_server, Req, Timeout).
-
-enable_debugmsg() ->
- set_debugmsg(true).
-
-disable_debugmsg() ->
- set_debugmsg(false).
-
-set_debugmsg(Bool) ->
- set_debugmsg(Bool, infinity).
-
-set_debugmsg(Bool, Timeout) when is_boolean(Bool) ->
- Req = {set_debugmsg, Bool, self()},
- gen_server:call(ssl_server, Req, Timeout).
-
-dump() ->
- dump(infinity).
-
-dump(Timeout) ->
- Req = {dump, self()},
- gen_server:call(ssl_server, Req, Timeout).
-
-%%
-%% init
-%%
-init([]) ->
- Debug = case application:get_env(ssl, edebug) of
- {ok, true} ->
- true;
- _ ->
- case application:get_env(ssl, debug) of
- {ok, true} ->
- true;
- _ ->
- os:getenv("ERL_SSL_DEBUG") =/= false
- end
- end,
- ProgDir =
- case init:get_argument(ssl_portprogram_dir) of
- {ok, [[D]]} ->
- D;
- _ ->
- find_priv_bin()
- end,
- {Program, Flags} = mk_cmd_line("ssl_esock"),
- Cmd = filename:join(ProgDir, Program) ++ " " ++ Flags,
- debug1(Debug, " start, Cmd = ~s~n", [Cmd]),
- case (catch open_port({spawn, Cmd}, [binary, {packet, 4}])) of
- Port when is_port(Port) ->
- process_flag(trap_exit, true),
- receive
- {Port, {data, Bin}} ->
- {ProxyLLPort, ProgPid, CompVsn, LibVsn, Ciphers} =
- decode_msg(Bin, [int16, int32, string, string,
- string]),
- debug1(Debug, "port program pid = ~w~n",
- [ProgPid]),
- {ok, #st{port = Port,
- proxylsport = ProxyLLPort,
- progpid = ProgPid,
- debug = Debug,
- compvsn = CompVsn,
- libvsn = LibVsn,
- ciphers = Ciphers}};
- {'EXIT', Port, Reason} ->
- {stop, Reason}
- end;
- {'EXIT', Reason} ->
- {stop, Reason}
- end.
-
-%%
-%% transport_accept
-%%
-handle_call({transport_accept, Broker, ListenFd, Flags}, From, St) ->
- debug(St, "transport_accept: broker = ~w, listenfd = ~w~n",
- [Broker, ListenFd]),
- case get_by_fd(ListenFd, St#st.cons) of
- {ok, {ListenFd, _, _}} ->
- send_cmd(St#st.port, ?TRANSPORT_ACCEPT, [int32(ListenFd), Flags, 0]),
- PAccepts = add({ListenFd, Broker, From}, St#st.paccepts),
- %%
- %% We reply when we get TRANSPORT_ACCEPT_REP or ASYNC_ACCEPT_ERR
- %%
- {noreply, St#st{paccepts = PAccepts}};
- _Other ->
- {reply, {error, ebadf}, St}
- end;
-
-%%
-%% ssl_accept
-%%
-handle_call({ssl_accept, Fd, Flags}, From, St) ->
- case replace_from_by_fd(Fd, St#st.cons, From) of
- {ok, _, Cons} = _Rep ->
- send_cmd(St#st.port, ?SSL_ACCEPT, [int32(Fd), Flags, 0]),
- %% We reply when we get SSL_ACCEPT_REP or ASYNC_ACCEPT_ERR
- {noreply, St#st{cons = Cons}};
- _Other ->
- {reply, {error, ebadf}, St}
- end;
-
-%%
-%% version
-%%
-handle_call(ciphers, From, St) ->
- debug(St, "ciphers: from = ~w~n", [From]),
- {reply, {ok, St#st.ciphers}, St};
-
-%%
-%% connect
-%%
-handle_call({connect, Broker, LIP, LPort, FIP, FPort, Flags}, From, St) ->
- debug(St, "connect: broker = ~w, ip = ~w, "
- "sport = ~w~n", [Broker, FIP, FPort]),
- Port = St#st.port,
- LIPStr = ip_to_string(LIP),
- FIPStr = ip_to_string(FIP),
- IntRef = new_intref(St),
- send_cmd(Port, ?CONNECT, [int32(IntRef),
- int16(LPort), LIPStr, 0,
- int16(FPort), FIPStr, 0,
- Flags, 0]),
- Cons = add({{intref, IntRef}, Broker, From}, St#st.cons),
- %% We reply when we have got CONNECT_SYNC_ERR, or CONNECT_WAIT
- %% and CONNECT_REP, or CONNECT_ERR.
- {noreply, St#st{cons = Cons, intref = IntRef}};
-
-%%
-%% connection_info
-%%
-handle_call({connection_info, Broker, Fd}, From, St) ->
- debug(St, "connection_info: broker = ~w, fd = ~w~n",
- [Broker, Fd]),
- case replace_from_by_fd(Fd, St#st.cons, From) of
- {ok, _, Cons} ->
- send_cmd(St#st.port, ?GETCONNINFO, [int32(Fd)]),
- %% We reply when we get GETCONNINFO_REP or GETCONNINFO_ERR.
- {noreply, St#st{cons = Cons}};
- _Other ->
- {reply, {error, ebadf}, St}
- end;
-
-%%
-%% close
-%%
-handle_call({close, Broker, Fd}, _From, St) ->
- debug(St, "close: broker = ~w, fd = ~w~n",
- [Broker, Fd]),
- #st{port = Port, cons = Cons0, paccepts = PAccepts0} = St,
- case delete_by_fd(Fd, Cons0) of
- %% Must match Broker pid; fd may be reused already.
- {ok, {Fd, Broker, _}, Cons} ->
- send_cmd(Port, ?CLOSE, int32(Fd)),
- %% If Fd is a listen socket fd, there might be pending
- %% accepts for that fd.
- case delete_all_by_fd(Fd, PAccepts0) of
- {ok, DelAccepts, RemAccepts} ->
- %% Reply {error, closed} to all pending accepts
- lists:foreach(fun({_, _, AccFrom}) ->
- gen_server:reply(AccFrom,
- {error, closed})
- end, DelAccepts),
- {reply, ok,
- St#st{cons = Cons, paccepts = RemAccepts}};
- _ ->
- {reply, ok, St#st{cons = Cons}}
- end;
- _ ->
- {reply, ok, St}
- end;
-
-%%
-%% listen
-%%
-handle_call({listen, Broker, IP, LPort, Flags, BackLog}, From, St) ->
- debug(St, "listen: broker = ~w, IP = ~w, "
- "sport = ~w~n", [Broker, IP, LPort]),
- Port = St#st.port,
- IPStr = ip_to_string(IP),
- IntRef = new_intref(St),
- send_cmd(Port, ?LISTEN, [int32(IntRef), int16(LPort), IPStr, 0,
- int16(BackLog), Flags, 0]),
- Cons = add({{intref, IntRef}, Broker, From}, St#st.cons),
- %% We reply when we have got LISTEN_REP.
- {noreply, St#st{cons = Cons, intref = IntRef}};
-
-%%
-%% peercert
-%%
-handle_call({peercert, Broker, Fd}, From, St) ->
- debug(St, "peercert: broker = ~w, fd = ~w~n",
- [Broker, Fd]),
- case replace_from_by_fd(Fd, St#st.cons, From) of
- {ok, _, Cons} ->
- send_cmd(St#st.port, ?GETPEERCERT, [int32(Fd)]),
- %% We reply when we get GETPEERCERT_REP or GETPEERCERT_ERR.
- {noreply, St#st{cons = Cons}};
- _Other ->
- {reply, {error, ebadf}, St}
- end;
-
-
-%%
-%% peername
-%%
-handle_call({peername, Broker, Fd}, From, St) ->
- debug(St, "peername: broker = ~w, fd = ~w~n",
- [Broker, Fd]),
- case replace_from_by_fd(Fd, St#st.cons, From) of
- {ok, _, Cons} ->
- send_cmd(St#st.port, ?GETPEERNAME, [int32(Fd)]),
- %% We reply when we get GETPEERNAME_REP or GETPEERNAME_ERR.
- {noreply, St#st{cons = Cons}};
- _Other ->
- {reply, {error, ebadf}, St}
- end;
-
-%%
-%% proxy join
-%%
-handle_call({proxy_join, Broker, Fd, LPort}, From, St) ->
- debug(St, "proxy_join: broker = ~w, fd = ~w, "
- "sport = ~w~n", [Broker, Fd, LPort]),
- case replace_from_by_fd(Fd, St#st.cons, From) of
- {ok, _, Cons} ->
- send_cmd(St#st.port, ?PROXY_JOIN, [int32(Fd),
- int16(LPort)]),
- %% We reply when we get PROXY_JOIN_REP, or PROXY_JOIN_ERR.
- {noreply, St#st{cons = Cons}};
- _Other ->
- {reply, {error, ebadf}, St}
- end;
-
-%%
-%% seed
-%%
-handle_call({seed, Data}, _From, St) when is_binary(Data) ->
- send_cmd(St#st.port, ?SET_SEED, [int32(byte_size(Data)), Data]),
- {reply, ok, St};
-
-handle_call({seed, Data}, From, St) ->
- case catch list_to_binary(Data) of
- {'EXIT', _} ->
- {reply, {error, edata}, St};
- Bin ->
- handle_call({seed, Bin}, From, St)
- end;
-
-%%
-%% setnodelay
-%%
-handle_call({setnodelay, Broker, Fd, Boolean}, From, St) ->
- debug(St, "setnodelay: broker = ~w, fd = ~w, "
- "boolean = ~w~n", [Broker, Fd, Boolean]),
- case replace_from_by_fd(Fd, St#st.cons, From) of
- {ok, _, Cons} ->
- Val = if Boolean == true -> 1; true -> 0 end,
- send_cmd(St#st.port, ?SET_SOCK_OPT,
- [int32(Fd), ?SET_TCP_NODELAY, Val]),
- %% We reply when we get IOCTL_OK or IOCTL_ERR.
- {noreply, St#st{cons = Cons}};
- _Other ->
- {reply, {error, ebadf}, St}
- end;
-
-%%
-%% sockname
-%%
-handle_call({sockname, Broker, Fd}, From, St) ->
- debug(St, "sockname: broker = ~w, fd = ~w~n",
- [Broker, Fd]),
- case replace_from_by_fd(Fd, St#st.cons, From) of
- {ok, _, Cons} ->
- send_cmd(St#st.port, ?GETSOCKNAME, [int32(Fd)]),
- %% We reply when we get GETSOCKNAME_REP or GETSOCKNAME_ERR.
- {noreply, St#st{cons = Cons}};
- _Other ->
- {reply, {error, ebadf}, St}
- end;
-
-%%
-%% version
-%%
-handle_call(version, From, St) ->
- debug(St, "version: from = ~w~n", [From]),
- {reply, {ok, {St#st.compvsn, St#st.libvsn}}, St};
-
-%%
-%% dump
-%%
-handle_call({dump, Broker}, _From, St) ->
- debug(St, "dump: broker = ~w", [Broker]),
- Port = St#st.port,
- send_cmd(Port, ?DUMP_CMD, []),
- {reply, ok, St};
-
-%%
-%% set_debug
-%%
-handle_call({set_debug, Bool, Broker}, _From, St) ->
- debug(St, "set_debug: broker = ~w", [Broker]),
- Value = case Bool of
- true ->
- 1;
- false ->
- 0
- end,
- Port = St#st.port,
- send_cmd(Port, ?DEBUG_CMD, [Value]),
- {reply, ok, St};
-
-%%
-%% set_debugmsg
-%%
-handle_call({set_debugmsg, Bool, Broker}, _From, St) ->
- debug(St, "set_debugmsg: broker = ~w", [Broker]),
- Value = case Bool of
- true ->
- 1;
- false ->
- 0
- end,
- Port = St#st.port,
- send_cmd(Port, ?DEBUGMSG_CMD, [Value]),
- {reply, ok, St};
-
-handle_call(Request, _From, St) ->
- debug(St, "unexpected call: ~w~n", [Request]),
- Reply = {error, {badcall, Request}},
- {reply, Reply, St}.
-
-%%
-%% handle_cast(Msg, St)
-%%
-
-
-handle_cast(Msg, St) ->
- debug(St, "unexpected cast: ~w~n", [Msg]),
- {noreply, St}.
-
-%%
-%% handle_info(Info, St)
-%%
-
-%% Data from port
-%%
-handle_info({Port, {data, Bin}},
- #st{cons = StCons, paccepts = Paccepts,
- port = Port, proxylsport = Proxylsport} = St)
- when is_binary(Bin) ->
- %% io:format("++++ ssl_server got from port: ~w~n", [Bin]),
- <<OpCode:8, _/binary>> = Bin,
- case OpCode of
- %%
- %% transport_accept
- %%
- ?TRANSPORT_ACCEPT_ERR when byte_size(Bin) >= 5 ->
- {ListenFd, Reason} = decode_msg(Bin, [int32, atom]),
- debug(St, "transport_accept_err: listenfd = ~w, "
- "reason = ~w~n", [ListenFd, Reason]),
- case delete_last_by_fd(ListenFd, Paccepts) of
- {ok, {_, _, From}, PAccepts} ->
- gen_server:reply(From, {error, Reason}),
- {noreply, St#st{paccepts = PAccepts}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
- ?TRANSPORT_ACCEPT_REP when byte_size(Bin) >= 9 ->
- {ListenFd, Fd} = decode_msg(Bin, [int32, int32]),
- debug(St, "transport_accept_rep: listenfd = ~w, "
- "fd = ~w~n", [ListenFd, Fd]),
- case delete_last_by_fd(ListenFd, Paccepts) of
- {ok, {_, Broker, From}, PAccepts} ->
- Reply = {ok, Fd, Proxylsport},
- gen_server:reply(From, Reply),
- debug(St, "transport_accept_rep: From = ~w\n", [From]),
- Cons = add({Fd, Broker, From}, StCons),
- {noreply, St#st{cons = Cons, paccepts = PAccepts}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
-
- %%
- %% ssl_accept
- %%
- ?SSL_ACCEPT_ERR when byte_size(Bin) >= 5 ->
- {Fd, Reason} = decode_msg(Bin, [int32, atom]),
- debug(St, "ssl_accept_err: listenfd = ~w, "
- "reason = ~w~n", [Fd, Reason]),
- %% JC: remove this?
- case delete_last_by_fd(Fd, StCons) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {error, Reason}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
- ?SSL_ACCEPT_REP when byte_size(Bin) >= 5 ->
- Fd = decode_msg(Bin, [int32]),
- debug(St, "ssl_accept_rep: Fd = ~w\n", [Fd]),
- case replace_from_by_fd(Fd, StCons, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, ok),
- {noreply, St#st{cons = Cons}};
- _ ->
- {noreply, St}
- end;
-
- %%
- %% connect
- %%
- ?CONNECT_SYNC_ERR when byte_size(Bin) >= 5 ->
- {IntRef, Reason} = decode_msg(Bin, [int32, atom]),
- debug(St, "connect_sync_err: intref = ~w, "
- "reason = ~w~n", [IntRef, Reason]),
- case delete_by_intref(IntRef, StCons) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {error, Reason}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- {noreply, St}
- end;
- ?CONNECT_WAIT when byte_size(Bin) >= 9 ->
- {IntRef, Fd} = decode_msg(Bin, [int32, int32]),
- debug(St, "connect_wait: intref = ~w, "
- "fd = ~w~n", [IntRef, Fd]),
- case replace_fd_by_intref(IntRef, StCons, Fd) of
- {ok, _, Cons} ->
- %% We reply when we get CONNECT_REP or CONNECT_ERR
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% We have a new Fd which must be closed
- send_cmd(Port, ?CLOSE, int32(Fd)),
- {noreply, St}
- end;
- ?CONNECT_REP when byte_size(Bin) >= 5 ->
- %% after CONNECT_WAIT
- Fd = decode_msg(Bin, [int32]),
- debug(St, "connect_rep: fd = ~w~n", [Fd]),
- case replace_from_by_fd(Fd, StCons, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {ok, Fd, Proxylsport}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- {noreply, St}
- end;
- ?CONNECT_ERR when byte_size(Bin) >= 5 ->
- {Fd, Reason} = decode_msg(Bin, [int32, atom]),
- debug(St, "connect_err: fd = ~w, "
- "reason = ~w~n", [Fd, Reason]),
- case delete_by_fd(Fd, StCons) of
- {ok, {_, _, From}, Cons} ->
- %% Fd not yet published - hence close ourselves
- send_cmd(Port, ?CLOSE, int32(Fd)),
- gen_server:reply(From, {error, Reason}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
-
- %%
- %% connection_info
- %%
- ?GETCONNINFO_REP when byte_size(Bin) >= 5 ->
- {Fd, Protocol, Cipher} = decode_msg(Bin, [int32, string, string]),
- debug(St, "connection_info_rep: fd = ~w, "
- "protcol = ~p, ip = ~p~n", [Fd, Protocol, Cipher]),
- case replace_from_by_fd(Fd, StCons, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {ok, {protocol_name(Protocol),
- Cipher}}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
- ?GETCONNINFO_ERR when byte_size(Bin) >= 5 ->
- {Fd, Reason} = decode_msg(Bin, [int32, atom]),
- debug(St, "connection_info_err: fd = ~w, "
- "reason = ~w~n", [Fd, Reason]),
- case replace_from_by_fd(Fd, StCons, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {error, Reason}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
-
- %%
- %% listen
- %%
- ?LISTEN_SYNC_ERR when byte_size(Bin) >= 5 ->
- {IntRef, Reason} = decode_msg(Bin, [int32, atom]),
- debug(St, "listen_sync_err: intref = ~w, "
- "reason = ~w~n", [IntRef, Reason]),
- case delete_by_intref(IntRef, StCons) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {error, Reason}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- {noreply, St}
- end;
- ?LISTEN_REP when byte_size(Bin) >= 11 ->
- {IntRef, ListenFd, LPort} = decode_msg(Bin, [int32, int32, int16]),
- debug(St, "listen_rep: intref = ~w, "
- "listenfd = ~w, sport = ~w~n", [IntRef, ListenFd, LPort]),
- case replace_fd_from_by_intref(IntRef, StCons, ListenFd, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {ok, ListenFd, LPort}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% ListenFd has to be closed.
- send_cmd(Port, ?CLOSE, int32(ListenFd)),
- {noreply, St}
- end;
-
- %%
- %% proxy join
- %%
- ?PROXY_JOIN_REP when byte_size(Bin) >= 5 ->
- Fd = decode_msg(Bin, [int32]),
- debug(St, "proxy_join_rep: fd = ~w~n",
- [Fd]),
- case get_by_fd(Fd, StCons) of
- {ok, {_, _, From}} ->
- gen_server:reply(From, ok),
- {noreply, St};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
- ?PROXY_JOIN_ERR when byte_size(Bin) >= 5 ->
- {Fd, Reason} = decode_msg(Bin, [int32, atom]),
- debug(St, "proxy_join_rep: fd = ~w, "
- "reason = ~w~n", [Fd, Reason]),
- case delete_by_fd(Fd, StCons) of
- {ok, {_, _, From}, Cons} ->
- case Reason of
- enoproxysocket ->
- send_cmd(Port, ?CLOSE, int32(Fd));
- _ ->
- ok
- %% Must not close Fd since it is published
- end,
- gen_server:reply(From, {error, Reason}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
-
- %%
- %% peername
- %%
- ?GETPEERNAME_REP when byte_size(Bin) >= 5 ->
- {Fd, LPort, IPString} = decode_msg(Bin, [int32, int16, string]),
- debug(St, "getpeername_rep: fd = ~w, "
- "sport = ~w, ip = ~p~n", [Fd, LPort, IPString]),
- case replace_from_by_fd(Fd, StCons, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {ok, {IPString, LPort}}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
- ?GETPEERNAME_ERR when byte_size(Bin) >= 5 ->
- {Fd, Reason} = decode_msg(Bin, [int32, atom]),
- debug(St, "getpeername_err: fd = ~w, "
- "reason = ~w~n", [Fd, Reason]),
- case replace_from_by_fd(Fd, StCons, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {error, Reason}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
-
- %%
- %% ioctl
- %%
- ?IOCTL_OK when byte_size(Bin) >= 5 ->
- Fd = decode_msg(Bin, [int32]),
- debug(St, "ioctl_ok: fd = ~w~n",
- [Fd]),
- case replace_from_by_fd(Fd, StCons, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, ok),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
- ?IOCTL_ERR when byte_size(Bin) >= 5 ->
- {Fd, Reason} = decode_msg(Bin, [int32, atom]),
- debug(St, "ioctl_err: fd = ~w, "
- "reason = ~w~n", [Fd, Reason]),
- case replace_from_by_fd(Fd, StCons, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {error, Reason}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
-
- %%
- %% sockname
- %%
- ?GETSOCKNAME_REP when byte_size(Bin) >= 5 ->
- {Fd, LPort, IPString} = decode_msg(Bin, [int32, int16, string]),
- debug(St, "getsockname_rep: fd = ~w, "
- "sport = ~w, ip = ~p~n", [Fd, LPort, IPString]),
- case replace_from_by_fd(Fd, StCons, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {ok, {IPString, LPort}}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
- ?GETSOCKNAME_ERR when byte_size(Bin) >= 5 ->
- {Fd, Reason} = decode_msg(Bin, [int32, atom]),
- debug(St, "getsockname_err: fd = ~w, "
- "reason = ~w~n", [Fd, Reason]),
- case replace_from_by_fd(Fd, StCons, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {error, Reason}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
-
- %%
- %% peercert
- %%
- ?GETPEERCERT_REP when byte_size(Bin) >= 5 ->
- {Fd, Cert} = decode_msg(Bin, [int32, bin]),
- debug(St, "getpeercert_rep: fd = ~w~n", [Fd]),
- case replace_from_by_fd(Fd, StCons, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {ok, Cert}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
- ?GETPEERCERT_ERR when byte_size(Bin) >= 5 ->
- {Fd, Reason} = decode_msg(Bin, [int32, atom]),
- debug(St, "getpeercert_err: fd = ~w, reason = ~w~n",
- [Fd, Reason]),
- case replace_from_by_fd(Fd, StCons, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {error, Reason}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end
- end;
-
-%%
-%% EXIT
-%%
-handle_info({'EXIT', Pid, Reason}, St) when is_pid(Pid) ->
- debug(St, "exit pid = ~w, "
- "reason = ~w~n", [Pid, Reason]),
- case delete_by_pid(Pid, St#st.cons) of
- {ok, {{intref, _}, Pid, _}, Cons} ->
- {noreply, St#st{cons = Cons}};
- {ok, {Fd, Pid, _}, Cons} ->
- send_cmd(St#st.port, ?CLOSE, int32(Fd)),
- %% If Fd is a listen socket fd, there might be pending
- %% accepts for that fd.
- case delete_all_by_fd(Fd, St#st.paccepts) of
- {ok, DelAccepts, RemAccepts} ->
- %% Reply {error, closed} to all pending accepts.
- lists:foreach(fun({_, _, From}) ->
- gen_server:reply(From,
- {error, closed})
- end, DelAccepts),
- {noreply,
- St#st{cons = Cons, paccepts = RemAccepts}};
- _ ->
- {noreply, St#st{cons = Cons}}
- end;
- _ ->
- case delete_by_pid(Pid, St#st.paccepts) of
- {ok, {ListenFd, _, _}, PAccepts} ->
- %% decrement ref count in port program
- send_cmd(St#st.port, ?NOACCEPT, int32(ListenFd)),
- {noreply, St#st{paccepts = PAccepts}};
- _ ->
- {noreply, St}
- end
- end;
-
-%%
-%% 'badsig' means bad message to port. Port program is unaffected.
-%%
-handle_info({'EXIT', Port, badsig}, #st{port = Port} = St) ->
- debug(St, "badsig!!!~n", []),
- {noreply, St};
-
-handle_info({'EXIT', Port, Reason}, #st{port = Port} = St) ->
- {stop, Reason, St};
-
-handle_info(Info, St) ->
- debug(St, "unexpected info: ~w~n", [Info]),
- {noreply, St}.
-
-%%
-%% terminate(Reason, St) -> any
-%%
-terminate(_Reason, _St) ->
- ok.
-
-%%
-%% code_change(OldVsn, St, Extra) -> {ok, NSt}
-%%
-code_change(_OldVsn, St, _Extra) ->
- {ok, St}.
-
-%%%----------------------------------------------------------------------
-%%% Internal functions
-%%%----------------------------------------------------------------------
-
-%%
-%% Send binary command to sock
-%%
-send_cmd(Port, Cmd, Args) ->
- Port ! {self(), {command, [Cmd| Args]}}.
-
-%%
-%% add(Descr, Cons) -> NCons
-%%
-add(D, L) ->
- [D| L].
-
-%%
-%% get_by_fd(Fd, Cons) -> {ok, Descr} | not_found
-%%
-get_by_fd(Fd, Cons) ->
- get_by_pos(Fd, 1, Cons).
-
-%%
-%% delete_by_fd(Fd, Cons) -> {ok, OldDesc, NewCons} | not_found.
-%%
-delete_by_fd(Fd, Cons) ->
- delete_by_pos(Fd, 1, Cons).
-
-%%
-%% delete_all_by_fd(Fd, Cons) -> {ok, DelCons, RemCons} | not_found.
-%%
-delete_all_by_fd(Fd, Cons) ->
- delete_all_by_pos(Fd, 1, Cons).
-
-%%
-%% delete_by_intref(IntRef, Cons) -> {ok, OldDesc, NewCons} | not_found.
-%%
-delete_by_intref(IntRef, Cons) ->
- delete_by_pos({intref, IntRef}, 1, Cons).
-
-%%
-%% delete_by_pid(Pid, Cons) -> {ok, OldDesc, NewCons} | not_found.
-%%
-delete_by_pid(Pid, Cons) ->
- delete_by_pos(Pid, 2, Cons).
-
-%%
-%% delete_last_by_fd(Fd, Cons) -> {ok, OldDesc, NCons} | not_found
-%%
-delete_last_by_fd(Fd, Cons) ->
- case dlbf(Fd, Cons) of
- {X, L} ->
- {ok, X, L};
- _Other ->
- not_found
- end.
-
-dlbf(Fd, [H]) ->
- last_elem(Fd, H, []);
-dlbf(Fd, [H|T]) ->
- case dlbf(Fd, T) of
- {X, L} ->
- {X, [H|L]};
- L ->
- last_elem(Fd, H, L)
- end;
-dlbf(_Fd, []) ->
- [].
-
-last_elem(Fd, H, L) when element(1, H) == Fd ->
- {H, L};
-last_elem(_, H, L) ->
- [H|L].
-
-
-%%
-%% replace_from_by_fd(Fd, Cons, From) -> {ok, OldDesc, NewList} | not_found
-%%
-replace_from_by_fd(Fd, Cons, From) ->
- replace_posn_by_pos(Fd, 1, Cons, [{From, 3}]).
-
-%%
-%% replace_fd_by_intref(IntRef, Cons, Fd) -> {ok, OldDesc, NewList} | not_f.
-%%
-replace_fd_by_intref(IntRef, Cons, Fd) ->
- replace_posn_by_pos({intref, IntRef}, 1, Cons, [{Fd, 1}]).
-
-%%
-%% replace_fd_from_by_intref(IntRef, Cons, NFd, From) ->
-%% {ok, OldDesc, NewList} | not_found
-%%
-replace_fd_from_by_intref(IntRef, Cons, NFd, From) ->
- replace_posn_by_pos({intref, IntRef}, 1, Cons, [{NFd, 1}, {From, 3}]).
-
-
-%%
-%% All *_by_pos functions
-%%
-
-get_by_pos(Key, Pos, [H|_]) when element(Pos, H) == Key ->
- {ok, H};
-get_by_pos(Key, Pos, [_|T]) ->
- get_by_pos(Key, Pos, T);
-get_by_pos(_, _, []) ->
- not_found.
-
-delete_by_pos(Key, Pos, Cons) ->
- case delete_by_pos1(Key, Pos, {not_found, Cons}) of
- {not_found, _} ->
- not_found;
- {ODesc, NCons} ->
- {ok, ODesc, NCons}
- end.
-delete_by_pos1(Key, Pos, {_R, [H|T]}) when element(Pos, H) == Key ->
- {H, T};
-delete_by_pos1(Key, Pos, {R, [H|T]}) ->
- {R0, T0} = delete_by_pos1(Key, Pos, {R, T}),
- {R0, [H| T0]};
-delete_by_pos1(_, _, {R, []}) ->
- {R, []}.
-
-delete_all_by_pos(Key, Pos, Cons) ->
- case lists:foldl(fun(H, {Ds, Rs}) when element(Pos, H) == Key ->
- {[H|Ds], Rs};
- (H, {Ds, Rs}) ->
- {Ds, [H|Rs]}
- end, {[], []}, Cons) of
- {[], _} ->
- not_found;
- {DelCons, RemCons} ->
- {ok, DelCons, RemCons}
- end.
-
-replace_posn_by_pos(Key, Pos, Cons, Repls) ->
- replace_posn_by_pos1(Key, Pos, Cons, Repls, []).
-
-replace_posn_by_pos1(Key, Pos, [H0| T], Repls, Acc)
- when element(Pos, H0) =:= Key ->
- H = lists:foldl(fun({Val, VPos}, Tuple) ->
- setelement(VPos, Tuple, Val)
- end, H0, Repls),
- {ok, H0, lists:reverse(Acc, [H| T])};
-replace_posn_by_pos1(Key, Pos, [H|T], Repls, Acc) ->
- replace_posn_by_pos1(Key, Pos, T, Repls, [H| Acc]);
-replace_posn_by_pos1(_, _, [], _, _) ->
- not_found.
-
-%%
-%% Binary/integer conversions
-%%
-int16(I) ->
- %%[(I bsr 8) band 255, I band 255].
- <<I:16>>.
-
-int32(I) ->
- %% [(I bsr 24) band 255,
- %% (I bsr 16) band 255,
- %% (I bsr 8) band 255,
- %% I band 255].
- <<I:32>>.
-
-%% decode_msg(Bin, Format) -> Tuple | integer() | atom() | string() |
-%% list of binaries()
-%%
-%% Decode message from binary
-%% Format = [spec()]
-%% spec() = int16 | int32 | string | atom | bin | bins
-%%
-%% Notice: The first byte (op code) of the binary message is removed.
-%% Notice: bins returns a *list* of binaries.
-%%
-decode_msg(<<_, Bin/binary>>, Format) ->
- Dec = dec(Format, Bin),
- case Dec of
- [Dec1] -> Dec1;
- _ -> list_to_tuple(Dec)
- end.
-
-dec([], _) ->
- [];
-dec([int16| F], <<N:16, Bin/binary>>) ->
- [N| dec(F, Bin)];
-dec([int32| F], <<N:32, Bin/binary>>) ->
- [N| dec(F, Bin)];
-dec([string| F], Bin0) ->
- {Cs, Bin1} = dec_string(Bin0),
- [Cs| dec(F, Bin1)];
-dec([atom|F], Bin0) ->
- {Cs, Bin1} = dec_string(Bin0),
- [list_to_atom(Cs)| dec(F, Bin1)];
-
-dec([bin|F], Bin) ->
- {Bin1, Bin2} = dec_bin(Bin),
- [Bin1| dec(F, Bin2)].
-
-%% NOTE: This clause is not actually used yet.
-%% dec([bins|F], <<N:32, Bin0/binary>>) ->
-%% {Bins, Bin1} = dec_bins(N, Bin0),
-%% [Bins| dec(F, Bin1)].
-
-dec_string(Bin) ->
- dec_string(Bin, []).
-
-dec_string(<<0, Bin/binary>>, RCs) ->
- {lists:reverse(RCs), Bin};
-dec_string(<<C, Bin/binary>>, RCs) ->
- dec_string(Bin, [C| RCs]).
-
-dec_bin(<<L:32, Bin0/binary>>) ->
- <<Bin1:L/binary, Bin2/binary>> = Bin0,
- {Bin1, Bin2}.
-
-%% dec_bins(N, Bin) ->
-%% dec_bins(N, Bin, []).
-
-%% dec_bins(0, Bin, Acc) ->
-%% {lists:reverse(Acc), Bin};
-%% dec_bins(N, Bin0, Acc) when N > 0 ->
-%% {Bin1, Bin2} = dec_bin(Bin0),
-%% dec_bins(N - 1, Bin2, [Bin1| Acc]).
-
-%%
-%% new_intref
-%%
-new_intref(St) ->
- (St#st.intref + 1) band 16#ffffffff.
-
-%%
-%% {Program, Flags} = mk_cmd_line(DefaultProgram)
-%%
-mk_cmd_line(Default) ->
- {port_program(Default),
- lists:flatten([debug_flag(), " ", debug_port_flag(), " ",
- debugdir_flag(), " ",
- msgdebug_flag(), " ", proxylsport_flag(), " ",
- proxybacklog_flag(), " ", ephemeral_rsa_flag(), " ",
- ephemeral_dh_flag(), " ",
- protocol_version_flag(), " "])}.
-
-port_program(Default) ->
- case application:get_env(ssl, port_program) of
- {ok, Program} when is_list(Program) ->
- Program;
- _Other ->
- Default
- end.
-
-%%
-%% As this server may be started by the distribution, it is not safe to assume
-%% a working code server, neither a working file server.
-%% I try to utilize the most primitive interfaces available to determine
-%% the directory of the port_program.
-%%
-find_priv_bin() ->
- PrivDir = case (catch code:priv_dir(ssl)) of
- {'EXIT', _} ->
- %% Code server probably not startet yet
- {ok, P} = erl_prim_loader:get_path(),
- ModuleFile = atom_to_list(?MODULE) ++ extension(),
- Pd = (catch lists:foldl
- (fun(X,Acc) ->
- M = filename:join([X, ModuleFile]),
- %% The file server probably not started
- %% either, has to use raw interface.
- case file:raw_read_file_info(M) of
- {ok,_} ->
- %% Found our own module in the
- %% path, lets bail out with
- %% the priv_dir of this directory
- Y = filename:split(X),
- throw(filename:join
- (lists:sublist
- (Y,length(Y) - 1)
- ++ ["priv"]));
- _ ->
- Acc
- end
- end,
- false,P)),
- case Pd of
- false ->
- exit(ssl_priv_dir_indeterminate);
- _ ->
- Pd
- end;
- Dir ->
- Dir
- end,
- filename:join([PrivDir, "bin"]).
-
-extension() ->
- %% erlang:info(machine) returns machine name as text in all uppercase
- "." ++ string:to_lower(erlang:system_info(machine)).
-
-debug_flag() ->
- case os:getenv("ERL_SSL_DEBUG") of
- false ->
- get_env(debug, "-d");
- _ ->
- "-d"
- end.
-
-debug_port_flag() ->
- case os:getenv("ERL_SSL_DEBUGPORT") of
- false ->
- get_env(debug, "-d");
- _ ->
- "-d"
- end.
-
-msgdebug_flag() ->
- case os:getenv("ERL_SSL_MSGDEBUG") of
- false ->
- get_env(msgdebug, "-dm");
- _ ->
- "-dm"
- end.
-
-proxylsport_flag() ->
- case application:get_env(ssl, proxylsport) of
- {ok, PortNum} ->
- "-pp " ++ integer_to_list(PortNum);
- _Other ->
- ""
- end.
-
-proxybacklog_flag() ->
- case application:get_env(ssl, proxylsbacklog) of
- {ok, Size} ->
- "-pb " ++ integer_to_list(Size);
- _Other ->
- ""
- end.
-
-debugdir_flag() ->
- case os:getenv("ERL_SSL_DEBUG") of
- false ->
- case application:get_env(ssl, debugdir) of
- {ok, Dir} when is_list(Dir) ->
- "-dd " ++ Dir;
- _Other ->
- ""
- end;
- _ ->
- "-dd ./"
- end.
-
-ephemeral_rsa_flag() ->
- case application:get_env(ssl, ephemeral_rsa) of
- {ok, true} ->
- "-ersa ";
- _Other ->
- ""
- end.
-
-ephemeral_dh_flag() ->
- case application:get_env(ssl, ephemeral_dh) of
- {ok, true} ->
- "-edh ";
- _Other ->
- ""
- end.
-
-protocol_version_flag() ->
- case application:get_env(ssl, protocol_version) of
- {ok, []} ->
- "";
- {ok, Vsns} when is_list(Vsns) ->
- case transform_vsns(Vsns) of
- N when (N > 0) ->
- "-pv " ++ integer_to_list(N);
- _ ->
- ""
- end;
- _Other ->
- ""
- end.
-
-transform_vsns(Vsns) ->
- transform_vsns(Vsns, 0).
-
-transform_vsns([sslv2| Vsns], I) ->
- transform_vsns(Vsns, I bor ?SSLv2);
-transform_vsns([sslv3| Vsns], I) ->
- transform_vsns(Vsns, I bor ?SSLv3);
-transform_vsns([tlsv1| Vsns], I) ->
- transform_vsns(Vsns, I bor ?TLSv1);
-transform_vsns([_ | Vsns], I) ->
- transform_vsns(Vsns, I);
-transform_vsns([], I) ->
- I.
-
-protocol_name("SSLv2") -> sslv2;
-protocol_name("SSLv3") -> sslv3;
-protocol_name("TLSv1") -> tlsv1.
-
-get_env(Key, Val) ->
- case application:get_env(ssl, Key) of
- {ok, true} ->
- Val;
- _Other ->
- ""
- end.
-
-ip_to_string({A,B,C,D}) ->
- [integer_to_list(A),$.,integer_to_list(B),$.,
- integer_to_list(C),$.,integer_to_list(D)].
-
-debug(St, Format, Args) ->
- debug1(St#st.debug, Format, Args).
-
-debug1(true, Format0, Args) ->
- {_MS, S, MiS} = erlang:now(),
- Secs = S rem 100,
- MiSecs = MiS div 1000,
- Format = "++++ ~3..0w:~3..0w ssl_server (~w): " ++ Format0,
- io:format(Format, [Secs, MiSecs, self()| Args]);
-debug1(_, _, _) ->
- ok.
diff --git a/lib/ssl/src/ssl_session.erl b/lib/ssl/src/ssl_session.erl
index dc4b7a711c..df5d7e0146 100644
--- a/lib/ssl/src/ssl_session.erl
+++ b/lib/ssl/src/ssl_session.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -48,7 +48,7 @@ is_new(_ClientSuggestion, _ServerDecision) ->
true.
%%--------------------------------------------------------------------
--spec id({host(), port_num(), #ssl_options{}}, cache_ref(), atom(),
+-spec id({host(), inet:port_number(), #ssl_options{}}, db_handle(), atom(),
undefined | binary()) -> binary().
%%
%% Description: Should be called by the client side to get an id
@@ -63,7 +63,7 @@ id(ClientInfo, Cache, CacheCb, OwnCert) ->
end.
%%--------------------------------------------------------------------
--spec id(port_num(), binary(), #ssl_options{}, cache_ref(),
+-spec id(inet:port_number(), binary(), #ssl_options{}, db_handle(),
atom(), seconds(), binary()) -> binary().
%%
%% Description: Should be called by the server side to get an id
@@ -103,9 +103,9 @@ select_session([], _, _) ->
select_session(Sessions, #ssl_options{ciphers = Ciphers,
reuse_sessions = ReuseSession}, OwnCert) ->
- IsResumable =
- fun(Session) ->
- ReuseSession andalso (Session#session.is_resumable) andalso
+ IsResumable =
+ fun(Session) ->
+ ReuseSession andalso resumable(Session#session.is_resumable) andalso
lists:member(Session#session.cipher_suite, Ciphers)
andalso (OwnCert == Session#session.own_certificate)
end,
@@ -147,10 +147,10 @@ is_resumable(SuggestedSessionId, Port, ReuseEnabled, ReuseFun, Cache,
#session{cipher_suite = CipherSuite,
own_certificate = SessionOwnCert,
compression_method = Compression,
- is_resumable = Is_resumable,
+ is_resumable = IsResumable,
peer_certificate = PeerCert} = Session ->
ReuseEnabled
- andalso Is_resumable
+ andalso resumable(IsResumable)
andalso (OwnCert == SessionOwnCert)
andalso valid_session(Session, SecondLifeTime)
andalso ReuseFun(SuggestedSessionId, PeerCert,
@@ -158,3 +158,8 @@ is_resumable(SuggestedSessionId, Port, ReuseEnabled, ReuseFun, Cache,
undefined ->
false
end.
+
+resumable(new) ->
+ false;
+resumable(IsResumable) ->
+ IsResumable.
diff --git a/lib/ssl/src/ssl_session_cache.erl b/lib/ssl/src/ssl_session_cache.erl
index ae7c67bb98..93969f628f 100644
--- a/lib/ssl/src/ssl_session_cache.erl
+++ b/lib/ssl/src/ssl_session_cache.erl
@@ -28,18 +28,18 @@
-export([init/1, terminate/1, lookup/2, update/3, delete/2, foldl/3,
select_session/2]).
--type key() :: {{host(), port_num()}, session_id()} | {port_num(), session_id()}.
+-type key() :: {{host(), inet:port_number()}, session_id()} | {inet:port_number(), session_id()}.
%%--------------------------------------------------------------------
--spec init(list()) -> cache_ref(). %% Returns reference to the cache (opaque)
+-spec init(list()) -> db_handle(). %% Returns reference to the cache (opaque)
%%
%% Description: Return table reference. Called by ssl_manager process.
%%--------------------------------------------------------------------
init(_) ->
- ets:new(cache_name(), [named_table, set, protected]).
+ ets:new(cache_name(), [set, protected]).
%%--------------------------------------------------------------------
--spec terminate(cache_ref()) -> any(). %%
+-spec terminate(db_handle()) -> any().
%%
%% Description: Handles cache table at termination of ssl manager.
%%--------------------------------------------------------------------
@@ -47,7 +47,7 @@ terminate(Cache) ->
ets:delete(Cache).
%%--------------------------------------------------------------------
--spec lookup(cache_ref(), key()) -> #session{} | undefined.
+-spec lookup(db_handle(), key()) -> #session{} | undefined.
%%
%% Description: Looks up a cach entry. Should be callable from any
%% process.
@@ -61,7 +61,7 @@ lookup(Cache, Key) ->
end.
%%--------------------------------------------------------------------
--spec update(cache_ref(), key(), #session{}) -> any().
+-spec update(db_handle(), key(), #session{}) -> any().
%%
%% Description: Caches a new session or updates a already cached one.
%% Will only be called from the ssl_manager process.
@@ -70,7 +70,7 @@ update(Cache, Key, Session) ->
ets:insert(Cache, {Key, Session}).
%%--------------------------------------------------------------------
--spec delete(cache_ref(), key()) -> any().
+-spec delete(db_handle(), key()) -> any().
%%
%% Description: Delets a cache entry.
%% Will only be called from the ssl_manager process.
@@ -79,7 +79,7 @@ delete(Cache, Key) ->
ets:delete(Cache, Key).
%%--------------------------------------------------------------------
--spec foldl(fun(), term(), cache_ref()) -> term().
+-spec foldl(fun(), term(), db_handle()) -> term().
%%
%% Description: Calls Fun(Elem, AccIn) on successive elements of the
%% cache, starting with AccIn == Acc0. Fun/2 must return a new
@@ -91,7 +91,7 @@ foldl(Fun, Acc0, Cache) ->
ets:foldl(Fun, Acc0, Cache).
%%--------------------------------------------------------------------
--spec select_session(cache_ref(), {host(), port_num()} | port_num()) -> [#session{}].
+-spec select_session(db_handle(), {host(), inet:port_number()} | inet:port_number()) -> [#session{}].
%%
%% Description: Selects a session that could be reused. Should be callable
%% from any process.
diff --git a/lib/ssl/src/ssl_ssl2.erl b/lib/ssl/src/ssl_ssl2.erl
index b1005b1acb..a9ab6a2678 100644
--- a/lib/ssl/src/ssl_ssl2.erl
+++ b/lib/ssl/src/ssl_ssl2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -20,7 +20,7 @@
%%
%%----------------------------------------------------------------------
%% Purpose: Handles sslv2 hello as clients supporting sslv2 and higher
-%% will send a sslv2 hello.
+%% will send an sslv2 hello.
%%----------------------------------------------------------------------
-module(ssl_ssl2).
diff --git a/lib/ssl/src/ssl_sup.erl b/lib/ssl/src/ssl_sup.erl
index 316ed8a4e9..cb10b1362a 100644
--- a/lib/ssl/src/ssl_sup.erl
+++ b/lib/ssl/src/ssl_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -24,7 +24,7 @@
-behaviour(supervisor).
%% API
--export([start_link/0]).
+-export([start_link/0, manager_opts/0]).
%% Supervisor callback
-export([init/1]).
@@ -51,17 +51,32 @@ init([]) ->
%% Does not start any port programs so it does matter
%% so much if it is not used!
- Child2 = {ssl_broker_sup, {ssl_broker_sup, start_link, []},
- permanent, 2000, supervisor, [ssl_broker_sup]},
+ %% Child2 = {ssl_broker_sup, {ssl_broker_sup, start_link, []},
+ %% permanent, 2000, supervisor, [ssl_broker_sup]},
%% New ssl
SessionCertManager = session_and_cert_manager_child_spec(),
ConnetionManager = connection_manager_child_spec(),
- {ok, {{one_for_all, 10, 3600}, [Child2, SessionCertManager,
- ConnetionManager]}}.
+ {ok, {{one_for_all, 10, 3600}, [SessionCertManager, ConnetionManager]}}.
+
+manager_opts() ->
+ CbOpts = case application:get_env(ssl, session_cb) of
+ {ok, Cb} when is_atom(Cb) ->
+ InitArgs = session_cb_init_args(),
+ [{session_cb, Cb}, {session_cb_init_args, InitArgs}];
+ _ ->
+ []
+ end,
+ case application:get_env(ssl, session_lifetime) of
+ {ok, Time} when is_integer(Time) ->
+ [{session_lifetime, Time}| CbOpts];
+ _ ->
+ CbOpts
+ end.
+
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
@@ -86,21 +101,6 @@ connection_manager_child_spec() ->
{Name, StartFunc, Restart, Shutdown, Type, Modules}.
-manager_opts() ->
- CbOpts = case application:get_env(ssl, session_cb) of
- {ok, Cb} when is_atom(Cb) ->
- InitArgs = session_cb_init_args(),
- [{session_cb, Cb}, {session_cb_init_args, InitArgs}];
- _ ->
- []
- end,
- case application:get_env(ssl, session_lifetime) of
- {ok, Time} when is_integer(Time) ->
- [{session_lifetime, Time}| CbOpts];
- _ ->
- CbOpts
- end.
-
session_cb_init_args() ->
case application:get_env(ssl, session_cb_init_args) of
{ok, Args} when is_list(Args) ->
diff --git a/lib/ssl/src/ssl_tls_dist_proxy.erl b/lib/ssl/src/ssl_tls_dist_proxy.erl
new file mode 100644
index 0000000000..d63eada571
--- /dev/null
+++ b/lib/ssl/src/ssl_tls_dist_proxy.erl
@@ -0,0 +1,325 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(ssl_tls_dist_proxy).
+
+
+-export([listen/1, accept/1, connect/2, get_remote_id/2]).
+-export([init/1, start_link/0, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3, ssl_options/2]).
+
+-include_lib("kernel/include/net_address.hrl").
+
+-record(state,
+ {listen,
+ accept_loop
+ }).
+
+-define(PPRE, 4).
+-define(PPOST, 4).
+
+
+%%====================================================================
+%% Internal application API
+%%====================================================================
+
+listen(Name) ->
+ gen_server:call(?MODULE, {listen, Name}, infinity).
+
+accept(Listen) ->
+ gen_server:call(?MODULE, {accept, Listen}, infinity).
+
+connect(Ip, Port) ->
+ gen_server:call(?MODULE, {connect, Ip, Port}, infinity).
+
+get_remote_id(Socket, Node) ->
+ gen_server:call(?MODULE, {get_remote_id, {Socket,Node}}, infinity).
+
+%%====================================================================
+%% gen_server callbacks
+%%====================================================================
+
+start_link() ->
+ gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
+
+init([]) ->
+ process_flag(priority, max),
+ {ok, #state{}}.
+
+handle_call({listen, Name}, _From, State) ->
+ case gen_tcp:listen(0, [{active, false}, {packet,?PPRE}]) of
+ {ok, Socket} ->
+ {ok, World} = gen_tcp:listen(0, [{active, false}, binary, {packet,?PPRE}]),
+ TcpAddress = get_tcp_address(Socket),
+ WorldTcpAddress = get_tcp_address(World),
+ {_,Port} = WorldTcpAddress#net_address.address,
+ {ok, Creation} = erl_epmd:register_node(Name, Port),
+ {reply, {ok, {Socket, TcpAddress, Creation}},
+ State#state{listen={Socket, World}}};
+ Error ->
+ {reply, Error, State}
+ end;
+
+handle_call({accept, Listen}, {From, _}, State = #state{listen={_, World}}) ->
+ Self = self(),
+ ErtsPid = spawn_link(fun() -> accept_loop(Self, erts, Listen, From) end),
+ WorldPid = spawn_link(fun() -> accept_loop(Self, world, World, Listen) end),
+ {reply, ErtsPid, State#state{accept_loop={ErtsPid, WorldPid}}};
+
+handle_call({connect, Ip, Port}, {From, _}, State) ->
+ Me = self(),
+ Pid = spawn_link(fun() -> setup_proxy(Ip, Port, Me) end),
+ receive
+ {Pid, go_ahead, LPort} ->
+ Res = {ok, Socket} = try_connect(LPort),
+ ok = gen_tcp:controlling_process(Socket, From),
+ flush_old_controller(From, Socket),
+ {reply, Res, State};
+ {Pid, Error} ->
+ {reply, Error, State}
+ end;
+
+handle_call({get_remote_id, {Socket,_Node}}, _From, State) ->
+ Address = get_tcp_address(Socket),
+ {reply, Address, State};
+
+handle_call(_What, _From, State) ->
+ {reply, ok, State}.
+
+handle_cast(_What, State) ->
+ {noreply, State}.
+
+handle_info(_What, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _St) ->
+ ok.
+
+code_change(_OldVsn, St, _Extra) ->
+ {ok, St}.
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+get_tcp_address(Socket) ->
+ {ok, Address} = inet:sockname(Socket),
+ {ok, Host} = inet:gethostname(),
+ #net_address{
+ address = Address,
+ host = Host,
+ protocol = proxy,
+ family = inet
+ }.
+
+accept_loop(Proxy, erts = Type, Listen, Extra) ->
+ process_flag(priority, max),
+ case gen_tcp:accept(Listen) of
+ {ok, Socket} ->
+ Extra ! {accept,self(),Socket,inet,proxy},
+ receive
+ {_Kernel, controller, Pid} ->
+ ok = gen_tcp:controlling_process(Socket, Pid),
+ flush_old_controller(Pid, Socket),
+ Pid ! {self(), controller};
+ {_Kernel, unsupported_protocol} ->
+ exit(unsupported_protocol)
+ end;
+ Error ->
+ exit(Error)
+ end,
+ accept_loop(Proxy, Type, Listen, Extra);
+
+accept_loop(Proxy, world = Type, Listen, Extra) ->
+ process_flag(priority, max),
+ case gen_tcp:accept(Listen) of
+ {ok, Socket} ->
+ Opts = get_ssl_options(server),
+ case ssl:ssl_accept(Socket, Opts) of
+ {ok, SslSocket} ->
+ PairHandler =
+ spawn_link(fun() ->
+ setup_connection(SslSocket, Extra)
+ end),
+ ok = ssl:controlling_process(SslSocket, PairHandler),
+ flush_old_controller(PairHandler, SslSocket);
+ _ ->
+ gen_tcp:close(Socket)
+ end;
+ Error ->
+ exit(Error)
+ end,
+ accept_loop(Proxy, Type, Listen, Extra).
+
+try_connect(Port) ->
+ case gen_tcp:connect({127,0,0,1}, Port, [{active, false}, {packet,?PPRE}]) of
+ R = {ok, _S} ->
+ R;
+ {error, _R} ->
+ try_connect(Port)
+ end.
+
+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
+ {ok, World} ->
+ {ok, ErtsL} = gen_tcp:listen(0, [{active, true}, binary, {packet,?PPRE}]),
+ #net_address{address={_,LPort}} = get_tcp_address(ErtsL),
+ Parent ! {self(), go_ahead, LPort},
+ case gen_tcp:accept(ErtsL) of
+ {ok, Erts} ->
+ %% gen_tcp:close(ErtsL),
+ loop_conn_setup(World, Erts);
+ Err ->
+ Parent ! {self(), Err}
+ end;
+ Err ->
+ Parent ! {self(), Err}
+ end.
+
+setup_connection(World, ErtsListen) ->
+ process_flag(trap_exit, true),
+ 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}]),
+ 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}]),
+ loop_conn(World, Erts);
+ {tcp, Erts, Data = <<$a, _/binary>>} ->
+ ssl:send(World, Data),
+ ssl:setopts(World, [{packet,?PPOST}]),
+ inet:setopts(Erts, [{packet,?PPOST}]),
+ loop_conn(World, Erts);
+ {ssl, World, Data = <<_, _/binary>>} ->
+ gen_tcp:send(Erts, Data),
+ loop_conn_setup(World, Erts);
+ {tcp, Erts, Data = <<_, _/binary>>} ->
+ ssl:send(World, Data),
+ loop_conn_setup(World, Erts);
+ {ssl, World, Data} ->
+ gen_tcp:send(Erts, Data),
+ loop_conn_setup(World, Erts);
+ {tcp, Erts, Data} ->
+ ssl:send(World, Data),
+ loop_conn_setup(World, Erts)
+ end.
+
+loop_conn(World, Erts) ->
+ receive
+ {ssl, World, Data} ->
+ gen_tcp:send(Erts, Data),
+ loop_conn(World, Erts);
+ {tcp, Erts, Data} ->
+ ssl:send(World, Data),
+ loop_conn(World, Erts);
+ {tcp_closed, Erts} ->
+ ssl:close(World);
+ {ssl_closed, World} ->
+ gen_tcp:close(Erts)
+ end.
+
+get_ssl_options(Type) ->
+ case init:get_argument(ssl_dist_opt) of
+ {ok, Args} ->
+ [{erl_dist, true} | ssl_options(Type, lists:append(Args))];
+ _ ->
+ [{erl_dist, true}]
+ end.
+
+ssl_options(_,[]) ->
+ [];
+ssl_options(server, ["client_" ++ _, _Value |T]) ->
+ ssl_options(server,T);
+ssl_options(client, ["server_" ++ _, _Value|T]) ->
+ ssl_options(client,T);
+ssl_options(server, ["server_certfile", Value|T]) ->
+ [{certfile, Value} | ssl_options(server,T)];
+ssl_options(client, ["client_certfile", Value | T]) ->
+ [{certfile, Value} | ssl_options(client,T)];
+ssl_options(server, ["server_cacertfile", Value|T]) ->
+ [{cacertfile, Value} | ssl_options(server,T)];
+ssl_options(client, ["client_cacertfile", Value|T]) ->
+ [{cacertfile, Value} | ssl_options(client,T)];
+ssl_options(server, ["server_keyfile", Value|T]) ->
+ [{keyfile, Value} | ssl_options(server,T)];
+ssl_options(client, ["client_keyfile", Value|T]) ->
+ [{keyfile, Value} | ssl_options(client,T)];
+ssl_options(server, ["server_password", Value|T]) ->
+ [{password, Value} | ssl_options(server,T)];
+ssl_options(client, ["client_password", Value|T]) ->
+ [{password, Value} | ssl_options(client,T)];
+ssl_options(server, ["server_verify", Value|T]) ->
+ [{verify, atomize(Value)} | ssl_options(server,T)];
+ssl_options(client, ["client_verify", Value|T]) ->
+ [{verify, atomize(Value)} | ssl_options(client,T)];
+ssl_options(server, ["server_reuse_sessions", Value|T]) ->
+ [{reuse_sessions, atomize(Value)} | ssl_options(server,T)];
+ssl_options(client, ["client_reuse_sessions", Value|T]) ->
+ [{reuse_sessions, atomize(Value)} | ssl_options(client,T)];
+ssl_options(server, ["server_secure_renegotiate", Value|T]) ->
+ [{secure_renegotiate, atomize(Value)} | ssl_options(server,T)];
+ssl_options(client, ["client_secure_renegotiate", Value|T]) ->
+ [{secure_renegotiate, atomize(Value)} | ssl_options(client,T)];
+ssl_options(server, ["server_depth", Value|T]) ->
+ [{depth, list_to_integer(Value)} | ssl_options(server,T)];
+ssl_options(client, ["client_depth", Value|T]) ->
+ [{depth, list_to_integer(Value)} | ssl_options(client,T)];
+ssl_options(server, ["server_hibernate_after", Value|T]) ->
+ [{hibernate_after, list_to_integer(Value)} | ssl_options(server,T)];
+ssl_options(client, ["client_hibernate_after", Value|T]) ->
+ [{hibernate_after, list_to_integer(Value)} | ssl_options(client,T)];
+ssl_options(server, ["server_ciphers", Value|T]) ->
+ [{ciphers, Value} | ssl_options(server,T)];
+ssl_options(client, ["client_ciphers", Value|T]) ->
+ [{ciphers, Value} | ssl_options(client,T)];
+ssl_options(server, ["server_dhfile", Value|T]) ->
+ [{dhfile, Value} | ssl_options(server,T)];
+ssl_options(server, ["server_fail_if_no_peer_cert", Value|T]) ->
+ [{fail_if_no_peer_cert, atomize(Value)} | ssl_options(server,T)];
+ssl_options(_,_) ->
+ exit(malformed_ssl_dist_opt).
+
+atomize(List) when is_list(List) ->
+ list_to_atom(List);
+atomize(Atom) when is_atom(Atom) ->
+ Atom.
+
+flush_old_controller(Pid, Socket) ->
+ receive
+ {tcp, Socket, Data} ->
+ Pid ! {tcp, Socket, Data},
+ flush_old_controller(Pid, Socket);
+ {tcp_closed, Socket} ->
+ Pid ! {tcp_closed, Socket},
+ flush_old_controller(Pid, Socket);
+ {ssl, Socket, Data} ->
+ Pid ! {ssl, Socket, Data},
+ flush_old_controller(Pid, Socket);
+ {ssl_closed, Socket} ->
+ Pid ! {ssl_closed, Socket},
+ flush_old_controller(Pid, Socket)
+ after 0 ->
+ ok
+ end.
diff --git a/lib/ssl/test/Makefile b/lib/ssl/test/Makefile
index 53b2223035..6b1da63d08 100644
--- a/lib/ssl/test/Makefile
+++ b/lib/ssl/test/Makefile
@@ -35,34 +35,29 @@ VSN=$(GS_VSN)
# ----------------------------------------------------
MODULES = \
- ssl_test_lib \
+ ssl_test_lib \
ssl_basic_SUITE \
+ ssl_handshake_SUITE \
ssl_packet_SUITE \
+ ssl_cipher_SUITE \
ssl_payload_SUITE \
ssl_to_openssl_SUITE \
ssl_session_cache_SUITE \
- ssl_test_MACHINE \
- old_ssl_active_SUITE \
- old_ssl_active_once_SUITE \
- old_ssl_passive_SUITE \
- old_ssl_verify_SUITE \
- old_ssl_peer_cert_SUITE \
- old_ssl_misc_SUITE \
- old_ssl_protocol_SUITE \
- old_transport_accept_SUITE \
- old_ssl_dist_SUITE \
+ ssl_dist_SUITE \
make_certs\
erl_make_certs
ERL_FILES = $(MODULES:%=%.erl)
-HRL_FILES = ssl_test_MACHINE.hrl
+HRL_FILES =
HRL_FILES_SRC = \
- ssl_int.hrl \
+ ssl_internal.hrl\
ssl_alert.hrl \
- ssl_handshake.hrl
+ ssl_handshake.hrl \
+ ssl_cipher.hrl \
+ ssl_record.hrl
HRL_FILES_INC =
diff --git a/lib/ssl/test/old_ssl_active_SUITE.erl b/lib/ssl/test/old_ssl_active_SUITE.erl
deleted file mode 100644
index 52ff0bcc5d..0000000000
--- a/lib/ssl/test/old_ssl_active_SUITE.erl
+++ /dev/null
@@ -1,395 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
--module(old_ssl_active_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,
- cinit_return_chkclose/1,
- sinit_return_chkclose/1,
- cinit_big_return_chkclose/1,
- sinit_big_return_chkclose/1,
- cinit_big_echo_chkclose/1,
- cinit_huge_echo_chkclose/1,
- sinit_big_echo_chkclose/1,
- cinit_few_echo_chkclose/1,
- cinit_many_echo_chkclose/1,
- cinit_cnocert/1
- ]).
-
--import(ssl_test_MACHINE, [mk_ssl_cert_opts/1, test_one_listener/7,
- test_server_only/6]).
-
--include_lib("test_server/include/test_server.hrl").
--include("ssl_test_MACHINE.hrl").
-
--define(MANYCONNS, ssl_test_MACHINE:many_conns()).
-
-init_per_testcase(_Case, Config) ->
- WatchDog = ssl_test_lib:timetrap(?DEFAULT_TIMEOUT),
- [{watchdog, WatchDog}| Config].
-
-end_per_testcase(_Case, Config) ->
- WatchDog = ?config(watchdog, Config),
- test_server:timetrap_cancel(WatchDog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [cinit_return_chkclose, sinit_return_chkclose,
- cinit_big_return_chkclose, sinit_big_return_chkclose,
- cinit_big_echo_chkclose, cinit_huge_echo_chkclose,
- sinit_big_echo_chkclose, cinit_few_echo_chkclose,
- cinit_many_echo_chkclose, cinit_cnocert].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_suite(doc) ->
- "Want to se what Config contains, and record the number of available "
- "file descriptors";
-init_per_suite(suite) ->
- [];
-init_per_suite(Config) ->
- io:format("Config: ~p~n", [Config]),
- case os:type() of
- {unix, _} ->
- ?line io:format("Max fd value: ~s", [os:cmd("ulimit -n")]);
- _ ->
- ok
- end,
- %% XXX Also record: Erlang/SSL version, version of OpenSSL,
- %% operating system, version of OTP, Erts, kernel and stdlib.
-
- %% Check if SSL exists. If this case fails, all other cases are skipped
- case catch crypto:start() of
- ok ->
- application:start(public_key),
- case ssl:start() of
- ok -> ssl:stop();
- {error, {already_started, _}} -> ssl:stop();
- Error -> ?t:fail({failed_starting_ssl,Error})
- end,
- Config;
- _Else ->
- {skip,"Could not start crypto!"}
- end.
-
-end_per_suite(doc) ->
- "This test case has no mission other than closing the conf case";
-end_per_suite(suite) ->
- [];
-end_per_suite(Config) ->
- crypto:stop(),
- Config.
-
-cinit_return_chkclose(doc) ->
- "Client sends 1000 bytes to server, that receives them, sends them "
- "back, and closes. Client waits for close. Both have certs.";
-cinit_return_chkclose(suite) ->
- [];
-cinit_return_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {recv, DataSize}, {send, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-sinit_return_chkclose(doc) ->
- "Server sends 1000 bytes to client, that receives them, sends them "
- "back, and closes. Server waits for close. Both have certs.";
-sinit_return_chkclose(suite) ->
- [];
-sinit_return_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, [{ssl_imp, old}|SsslOpts]},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {send, DataSize}, {recv, DataSize},
- await_close],
- CCmds = [{timeout, Timeout},
- {sslopts, [{ssl_imp, old}|CsslOpts]},
- {connect, {Host, LPort}},
- {recv, DataSize}, {send, DataSize},
- close],
-
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-cinit_big_return_chkclose(doc) ->
- "Client sends 50000 bytes to server, that receives them, sends them "
- "back, and closes. Client waits for close. Both have certs.";
-cinit_big_return_chkclose(suite) ->
- [];
-cinit_big_return_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 50000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {recv, DataSize}, {send, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-sinit_big_return_chkclose(doc) ->
- "Server sends 50000 bytes to client, that receives them, sends them "
- "back, and closes. Server waits for close. Both have certs.";
-sinit_big_return_chkclose(suite) ->
- [];
-sinit_big_return_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 50000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {send, DataSize}, {recv, DataSize},
- await_close],
- CCmds = [{timeout, Timeout},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {recv, DataSize}, {send, DataSize},
- close],
-
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-cinit_big_echo_chkclose(doc) ->
- "Client sends 50000 bytes to server, that echoes them back "
- "and closes. Client waits for close. Both have certs.";
-cinit_big_echo_chkclose(suite) ->
- [];
-cinit_big_echo_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 50000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {echo, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-cinit_huge_echo_chkclose(doc) ->
- "Client sends 500000 bytes to server, that echoes them back "
- "and closes. Client waits for close. Both have certs.";
-cinit_huge_echo_chkclose(suite) ->
- [];
-cinit_huge_echo_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 500000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {echo, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-sinit_big_echo_chkclose(doc) ->
- "Server sends 50000 bytes to client, that echoes them back "
- "and closes. Server waits for close. Both have certs.";
-sinit_big_echo_chkclose(suite) ->
- [];
-sinit_big_echo_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 50000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {send, DataSize}, {recv, DataSize},
- await_close],
- CCmds = [{timeout, Timeout},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {echo, DataSize},
- close],
-
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-
-%% This case is repeated several times.
-
-cinit_few_echo_chkclose(X) -> cinit_many_echo_chkclose(X, 7).
-
-cinit_many_echo_chkclose(X) -> cinit_many_echo_chkclose(X, ?MANYCONNS).
-
-cinit_many_echo_chkclose(doc, _NConns) ->
- "N client sends 10000 bytes to server, that echoes them back "
- "and closes. Clients wait for close. All have certs.";
-cinit_many_echo_chkclose(suite, _NConns) ->
- [];
-cinit_many_echo_chkclose(Config, NConns) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 10000, LPort = 3456,
- Timeout = 80000,
-
- io:format("~w connections", [NConns]),
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {echo, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-
-cinit_cnocert(doc) ->
- "Client sends 1000 bytes to server, that receives them, sends them "
- "back, and closes. Client waits for close. Client has no cert, "
- "but server has.";
-cinit_cnocert(suite) ->
- [];
-cinit_cnocert(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3457,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {_CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {recv, DataSize}, {send, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-
diff --git a/lib/ssl/test/old_ssl_active_once_SUITE.erl b/lib/ssl/test/old_ssl_active_once_SUITE.erl
deleted file mode 100644
index c7beadb301..0000000000
--- a/lib/ssl/test/old_ssl_active_once_SUITE.erl
+++ /dev/null
@@ -1,417 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
--module(old_ssl_active_once_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,
- server_accept_timeout/1,
- cinit_return_chkclose/1,
- sinit_return_chkclose/1,
- cinit_big_return_chkclose/1,
- sinit_big_return_chkclose/1,
- cinit_big_echo_chkclose/1,
- cinit_huge_echo_chkclose/1,
- sinit_big_echo_chkclose/1,
- cinit_few_echo_chkclose/1,
- cinit_many_echo_chkclose/1,
- cinit_cnocert/1
- ]).
-
--import(ssl_test_MACHINE, [mk_ssl_cert_opts/1, test_one_listener/7,
- test_server_only/6]).
--include_lib("test_server/include/test_server.hrl").
--include("ssl_test_MACHINE.hrl").
-
--define(MANYCONNS, ssl_test_MACHINE:many_conns()).
-
-init_per_testcase(_Case, Config) ->
- WatchDog = ssl_test_lib:timetrap(?DEFAULT_TIMEOUT),
- [{watchdog, WatchDog}| Config].
-
-end_per_testcase(_Case, Config) ->
- WatchDog = ?config(watchdog, Config),
- test_server:timetrap_cancel(WatchDog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [server_accept_timeout, cinit_return_chkclose,
- sinit_return_chkclose, cinit_big_return_chkclose,
- sinit_big_return_chkclose, cinit_big_echo_chkclose,
- cinit_huge_echo_chkclose, sinit_big_echo_chkclose,
- cinit_few_echo_chkclose, cinit_many_echo_chkclose,
- cinit_cnocert].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_suite(doc) ->
- "Want to se what Config contains.";
-init_per_suite(suite) ->
- [];
-init_per_suite(Config) ->
- io:format("Config: ~p~n", [Config]),
-
- %% Check if SSL exists. If this case fails, all other cases are skipped
- case catch crypto:start() of
- ok ->
- application:start(public_key),
- case ssl:start() of
- ok -> ssl:stop();
- {error, {already_started, _}} -> ssl:stop();
- Error -> ?t:fail({failed_starting_ssl,Error})
- end,
- Config;
- _Else ->
- {skip,"Could not start crypto"}
- end.
-
-end_per_suite(doc) ->
- "This test case has no mission other than closing the conf case";
-end_per_suite(suite) ->
- [];
-end_per_suite(Config) ->
- crypto:stop(),
- Config.
-
-server_accept_timeout(doc) ->
- "Server has one pending accept with timeout. Checks that return "
- "value is {error, timeout}.";
-server_accept_timeout(suite) ->
- [];
-server_accept_timeout(Config) when list(Config) ->
- process_flag(trap_exit, true),
- LPort = 3456,
- Timeout = 40000, NConns = 1,
- AccTimeout = 3000,
-
- ?line {ok, {_, SsslOpts}} = mk_ssl_cert_opts(Config),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, once}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, AccTimeout},
- accept_timeout],
- ?line test_server_only(NConns, LCmds, ACmds, Timeout, ?MODULE,
- Config).
-
-cinit_return_chkclose(doc) ->
- "Client sends 1000 bytes to server, that receives them, sends them "
- "back, and closes. Client waits for close. Both have certs.";
-cinit_return_chkclose(suite) ->
- [];
-cinit_return_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, once}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {recv, DataSize}, {send, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, once}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-sinit_return_chkclose(doc) ->
- "Server sends 1000 bytes to client, that receives them, sends them "
- "back, and closes. Server waits for close. Both have certs.";
-sinit_return_chkclose(suite) ->
- [];
-sinit_return_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, once}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {send, DataSize}, {recv, DataSize},
- await_close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, once}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {recv, DataSize}, {send, DataSize},
- close],
-
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-cinit_big_return_chkclose(doc) ->
- "Client sends 50000 bytes to server, that receives them, sends them "
- "back, and closes. Client waits for close. Both have certs.";
-cinit_big_return_chkclose(suite) ->
- [];
-cinit_big_return_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 50000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- %% Set {active, false} so that accept is passive to begin with.
- LCmds = [{sockopts, [{backlog, NConns}, {active, false}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {sockopts, [{active, once}]}, % {active, once} here.
- {recv, DataSize}, {send, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, once}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-sinit_big_return_chkclose(doc) ->
- "Server sends 50000 bytes to client, that receives them, sends them "
- "back, and closes. Server waits for close. Both have certs.";
-sinit_big_return_chkclose(suite) ->
- [];
-sinit_big_return_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 50000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, once}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {send, DataSize}, {recv, DataSize},
- await_close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, once}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {recv, DataSize}, {send, DataSize},
- close],
-
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-cinit_big_echo_chkclose(doc) ->
- "Client sends 50000 bytes to server, that echoes them back "
- "and closes. Client waits for close. Both have certs.";
-cinit_big_echo_chkclose(suite) ->
- [];
-cinit_big_echo_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 50000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, once}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {echo, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, once}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-cinit_huge_echo_chkclose(doc) ->
- "Client sends 500000 bytes to server, that echoes them back "
- "and closes. Client waits for close. Both have certs.";
-cinit_huge_echo_chkclose(suite) ->
- [];
-cinit_huge_echo_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 500000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, once}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {echo, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, once}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-sinit_big_echo_chkclose(doc) ->
- "Server sends 50000 bytes to client, that echoes them back "
- "and closes. Server waits for close. Both have certs.";
-sinit_big_echo_chkclose(suite) ->
- [];
-sinit_big_echo_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 50000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, once}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {send, DataSize}, {recv, DataSize},
- await_close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, once}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {echo, DataSize},
- close],
-
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-cinit_few_echo_chkclose(X) -> cinit_many_echo_chkclose(X, 7).
-
-cinit_many_echo_chkclose(X) -> cinit_many_echo_chkclose(X, ?MANYCONNS).
-
-cinit_many_echo_chkclose(doc, _NConns) ->
- "client send 10000 bytes to server, that echoes them back "
- "and closes. Clients wait for close. All have certs.";
-cinit_many_echo_chkclose(suite, _NConns) ->
- [];
-cinit_many_echo_chkclose(Config, NConns) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 10000, LPort = 3456,
- Timeout = 80000,
-
- io:format("~w connections", [NConns]),
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, once}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {echo, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, once}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-cinit_cnocert(doc) ->
- "Client sends 1000 bytes to server, that receives them, sends them "
- "back, and closes. Client waits for close. Client has no cert, "
- "but server has.";
-cinit_cnocert(suite) ->
- [];
-cinit_cnocert(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3457,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {_CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, once}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {recv, DataSize}, {send, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, once}]},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-
diff --git a/lib/ssl/test/old_ssl_misc_SUITE.erl b/lib/ssl/test/old_ssl_misc_SUITE.erl
deleted file mode 100644
index ea03e83867..0000000000
--- a/lib/ssl/test/old_ssl_misc_SUITE.erl
+++ /dev/null
@@ -1,117 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
--module(old_ssl_misc_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,
- seed/1,
- app/1
- ]).
-
--import(ssl_test_MACHINE, [mk_ssl_cert_opts/1, test_one_listener/7,
- test_server_only/6]).
--include_lib("test_server/include/test_server.hrl").
--include("ssl_test_MACHINE.hrl").
-
--define(MANYCONNS, 5).
-
-init_per_testcase(_Case, Config) ->
- WatchDog = ssl_test_lib:timetrap(?DEFAULT_TIMEOUT),
- [{watchdog, WatchDog}| Config].
-
-end_per_testcase(_Case, Config) ->
- WatchDog = ?config(watchdog, Config),
- test_server:timetrap_cancel(WatchDog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [seed, app].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_suite(doc) ->
- "Want to se what Config contains.";
-init_per_suite(suite) ->
- [];
-init_per_suite(Config) ->
- io:format("Config: ~p~n", [Config]),
-
- %% Check if SSL exists. If this case fails, all other cases are skipped
- case catch crypto:start() of
- ok ->
- application:start(public_key),
- case ssl:start() of
- ok -> ssl:stop();
- {error, {already_started, _}} -> ssl:stop();
- Error -> ?t:fail({failed_starting_ssl,Error})
- end,
- Config;
- _Else ->
- {skip,"Could not start crypto!"}
- end.
-
-end_per_suite(doc) ->
- "This test case has no mission other than closing the conf case";
-end_per_suite(suite) ->
- [];
-end_per_suite(Config) ->
- crypto:stop(),
- Config.
-
-seed(doc) ->
- "Test that ssl:seed/1 works.";
-seed(suite) ->
- [];
-seed(Config) when list(Config) ->
- process_flag(trap_exit, true),
- LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {_, SsslOpts}} = mk_ssl_cert_opts(Config),
-
- LCmds = [{seed, "tjosan"},
- {sockopts, [{backlog, NConns}, {active, once}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ?line test_server_only(NConns, LCmds, [], Timeout, ?MODULE,
- Config).
-
-app(doc) ->
- "Test that the ssl app file is ok";
-app(suite) ->
- [];
-app(Config) when list(Config) ->
- ?line ok = test_server:app_test(ssl).
-
-
diff --git a/lib/ssl/test/old_ssl_passive_SUITE.erl b/lib/ssl/test/old_ssl_passive_SUITE.erl
deleted file mode 100644
index 7b54fe876a..0000000000
--- a/lib/ssl/test/old_ssl_passive_SUITE.erl
+++ /dev/null
@@ -1,382 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
--module(old_ssl_passive_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,
- server_accept_timeout/1,
- cinit_return_chkclose/1,
- sinit_return_chkclose/1,
- cinit_big_return_chkclose/1,
- sinit_big_return_chkclose/1,
- cinit_big_echo_chkclose/1,
- sinit_big_echo_chkclose/1,
- cinit_few_echo_chkclose/1,
- cinit_many_echo_chkclose/1,
- cinit_cnocert/1
- ]).
-
--import(ssl_test_MACHINE, [mk_ssl_cert_opts/1, test_one_listener/7,
- test_server_only/6]).
-
--include_lib("test_server/include/test_server.hrl").
--include("ssl_test_MACHINE.hrl").
-
--define(MANYCONNS, ssl_test_MACHINE:many_conns()).
-
-init_per_testcase(_Case, Config) ->
- WatchDog = ssl_test_lib:timetrap(?DEFAULT_TIMEOUT),
- [{watchdog, WatchDog}| Config].
-
-end_per_testcase(_Case, Config) ->
- WatchDog = ?config(watchdog, Config),
- test_server:timetrap_cancel(WatchDog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [server_accept_timeout, cinit_return_chkclose,
- sinit_return_chkclose, cinit_big_return_chkclose,
- sinit_big_return_chkclose, cinit_big_echo_chkclose,
- sinit_big_echo_chkclose, cinit_few_echo_chkclose,
- cinit_many_echo_chkclose, cinit_cnocert].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_suite(doc) ->
- "Want to se what Config contains.";
-init_per_suite(suite) ->
- [];
-init_per_suite(Config) ->
- io:format("Config: ~p~n", [Config]),
-
- %% Check if SSL exists. If this case fails, all other cases are skipped
- case catch crypto:start() of
- ok ->
- application:start(public_key),
- case ssl:start() of
- ok -> ssl:stop();
- {error, {already_started, _}} -> ssl:stop();
- Error -> ?t:fail({failed_starting_ssl,Error})
- end,
- Config;
- _Else ->
- {skip,"Could not start crypto"}
- end.
-
-end_per_suite(doc) ->
- "This test case has no mission other than closing the conf case";
-end_per_suite(suite) ->
- [];
-end_per_suite(Config) ->
- crypto:stop(),
- Config.
-
-server_accept_timeout(doc) ->
- "Server has one pending accept with timeout. Checks that return "
- "value is {error, timeout}.";
-server_accept_timeout(suite) ->
- [];
-server_accept_timeout(Config) when list(Config) ->
- process_flag(trap_exit, true),
- LPort = 3456,
- Timeout = 40000, NConns = 1,
- AccTimeout = 3000,
-
- ?line {ok, {_, SsslOpts}} = mk_ssl_cert_opts(Config),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, false}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, AccTimeout},
- accept_timeout],
- ?line test_server_only(NConns, LCmds, ACmds, Timeout, ?MODULE, Config).
-
-cinit_return_chkclose(doc) ->
- "Client sends 1000 bytes to server, that receives them, sends them "
- "back, and closes. Client waits for close. Both have certs.";
-cinit_return_chkclose(suite) ->
- [];
-cinit_return_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, false}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {recv, DataSize}, {send, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, false}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-sinit_return_chkclose(doc) ->
- "Server sends 1000 bytes to client, that receives them, sends them "
- "back, and closes. Server waits for close. Both have certs.";
-sinit_return_chkclose(suite) ->
- [];
-sinit_return_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, false}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {send, DataSize}, {recv, DataSize},
- await_close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, false}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {recv, DataSize}, {send, DataSize},
- close],
-
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-cinit_big_return_chkclose(doc) ->
- "Client sends 50000 bytes to server, that receives them, sends them "
- "back, and closes. Client waits for close. Both have certs.";
-cinit_big_return_chkclose(suite) ->
- [];
-cinit_big_return_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 50000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, false}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {recv, DataSize}, {send, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, false}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-sinit_big_return_chkclose(doc) ->
- "Server sends 50000 bytes to client, that receives them, sends them "
- "back, and closes. Server waits for close. Both have certs.";
-sinit_big_return_chkclose(suite) ->
- [];
-sinit_big_return_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 50000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, false}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {send, DataSize}, {recv, DataSize},
- await_close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, false}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {recv, DataSize}, {send, DataSize},
- close],
-
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-cinit_big_echo_chkclose(doc) ->
- "Client sends 50000 bytes to server, that echoes them back "
- "and closes. Client waits for close. Both have certs.";
-cinit_big_echo_chkclose(suite) ->
- [];
-cinit_big_echo_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 50000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, false}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {echo, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, false}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-sinit_big_echo_chkclose(doc) ->
- "Server sends 50000 bytes to client, that echoes them back "
- "and closes. Server waits for close. Both have certs.";
-sinit_big_echo_chkclose(suite) ->
- [];
-sinit_big_echo_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 50000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, false}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {send, DataSize}, {recv, DataSize},
- await_close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, false}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {echo, DataSize},
- close],
-
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-
-cinit_few_echo_chkclose(X) -> cinit_many_echo_chkclose(X, 7).
-
-cinit_many_echo_chkclose(X) -> cinit_many_echo_chkclose(X, ?MANYCONNS).
-
-cinit_many_echo_chkclose(doc, _NConns) ->
- "clients send 10000 bytes to server, that echoes them back "
- "and closes. Clients wait for close. All have certs.";
-cinit_many_echo_chkclose(suite, _NConns) ->
- [];
-cinit_many_echo_chkclose(Config, NConns) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 10000, LPort = 3456,
- Timeout = 80000,
-
- io:format("~w connections", [NConns]),
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, false}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {echo, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, false}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-cinit_cnocert(doc) ->
- "Client sends 1000 bytes to server, that receives them, sends them "
- "back, and closes. Client waits for close. Client has no cert, "
- "but server has.";
-cinit_cnocert(suite) ->
- [];
-cinit_cnocert(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3457,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {_CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, false}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {recv, DataSize}, {send, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, false}]},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
diff --git a/lib/ssl/test/old_ssl_peer_cert_SUITE.erl b/lib/ssl/test/old_ssl_peer_cert_SUITE.erl
deleted file mode 100644
index ee19bad175..0000000000
--- a/lib/ssl/test/old_ssl_peer_cert_SUITE.erl
+++ /dev/null
@@ -1,191 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
--module(old_ssl_peer_cert_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,
- cinit_plain/1,
- cinit_both_verify/1,
- cinit_cnocert/1
- ]).
-
--import(ssl_test_MACHINE, [mk_ssl_cert_opts/1, test_one_listener/7,
- test_server_only/6]).
--include_lib("test_server/include/test_server.hrl").
--include("ssl_test_MACHINE.hrl").
-
-
-init_per_testcase(_Case, Config) ->
- WatchDog = ssl_test_lib:timetrap(?DEFAULT_TIMEOUT),
- [{watchdog, WatchDog}| Config].
-
-end_per_testcase(_Case, Config) ->
- WatchDog = ?config(watchdog, Config),
- test_server:timetrap_cancel(WatchDog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [cinit_plain, cinit_both_verify, cinit_cnocert].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_suite(doc) ->
- "Want to se what Config contains.";
-init_per_suite(suite) ->
- [];
-init_per_suite(Config) ->
- io:format("Config: ~p~n", [Config]),
-
- %% Check if SSL exists. If this case fails, all other cases are skipped
- case catch crypto:start() of
- ok ->
- application:start(public_key),
- case ssl:start() of
- ok -> ssl:stop();
- {error, {already_started, _}} -> ssl:stop();
- Error -> ?t:fail({failed_starting_ssl,Error})
- end,
- Config;
- _Else ->
- {skip,"Could not start crypto"}
- end.
-
-end_per_suite(doc) ->
- "This test case has no mission other than closing the conf case";
-end_per_suite(suite) ->
- [];
-end_per_suite(Config) ->
- crypto:stop(),
- Config.
-
-cinit_plain(doc) ->
- "Server closes after accept, Client waits for close. Both have certs "
- "but both use the defaults for verify and depth, but still tries "
- "to retreive each others certificates.";
-cinit_plain(suite) ->
- [];
-cinit_plain(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
-
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- nopeercert,
- {recv, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- peercert,
- {send, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout,
- ?MODULE, Config).
-
-cinit_both_verify(doc) ->
- "Server closes after accept, Client waits for close. Both have certs "
- "and both verify each other.";
-cinit_both_verify(suite) ->
- [];
-cinit_both_verify(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts0, SsslOpts0}} = mk_ssl_cert_opts(Config),
- ?line CsslOpts = [{verify, 2}, {depth, 2} | CsslOpts0],
- ?line SsslOpts = [{verify, 2}, {depth, 3} | SsslOpts0],
-
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- peercert,
- {recv, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- peercert,
- {send, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout,
- ?MODULE, Config).
-
-cinit_cnocert(doc) ->
- "Client has no cert. Nor the client, nor the server is verifying its "
- "peer. Server closes, client waits for close.";
-cinit_cnocert(suite) ->
- [];
-cinit_cnocert(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3457,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {_, SsslOpts0}} = mk_ssl_cert_opts(Config),
- ?line SsslOpts = [{verify, 0}, {depth, 2} | SsslOpts0],
-
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {recv, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {connect, {Host, LPort}},
- peercert,
- {send, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout,
- ?MODULE, Config).
-
-
diff --git a/lib/ssl/test/old_ssl_protocol_SUITE.erl b/lib/ssl/test/old_ssl_protocol_SUITE.erl
deleted file mode 100644
index 9b9937c210..0000000000
--- a/lib/ssl/test/old_ssl_protocol_SUITE.erl
+++ /dev/null
@@ -1,185 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
--module(old_ssl_protocol_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,
- sslv2/1, sslv3/1, tlsv1/1, sslv2_sslv3/1,
- sslv2_tlsv1/1, sslv3_tlsv1/1, sslv2_sslv3_tlsv1/1]).
-
--import(ssl_test_MACHINE, [mk_ssl_cert_opts/1, test_one_listener/7,
- test_server_only/6]).
--include_lib("test_server/include/test_server.hrl").
--include("ssl_test_MACHINE.hrl").
-
-
-init_per_testcase(_Case, Config) ->
- WatchDog = test_server:timetrap(?DEFAULT_TIMEOUT),
- [{watchdog, WatchDog}| Config].
-
-end_per_testcase(_Case, Config) ->
- WatchDog = ?config(watchdog, Config),
- test_server:timetrap_cancel(WatchDog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [sslv2, sslv3, tlsv1, sslv2_sslv3, sslv2_tlsv1,
- sslv3_tlsv1, sslv2_sslv3_tlsv1].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_suite(doc) ->
- "Want to se what Config contains.";
-init_per_suite(suite) ->
- [];
-init_per_suite(Config) ->
- io:format("Config: ~p~n", [Config]),
-
- %% Check if SSL exists. If this case fails, all other cases are skipped
- case catch crypto:start() of
- ok ->
- application:start(public_key),
- case ssl:start() of
- ok -> ssl:stop();
- {error, {already_started, _}} -> ssl:stop();
- Error -> ?t:fail({failed_starting_ssl,Error})
- end,
- Config;
- _Else ->
- {skip,"Could not start crypto"}
- end.
-
-end_per_suite(doc) ->
- "This test case has no other purpose than closing the conf case.";
-end_per_suite(suite) ->
- [];
-end_per_suite(Config) ->
- crypto:stop(),
- Config.
-
-%%%%%
-
-sslv2(doc) ->
- "Client has no cert. Nor the client, nor the server is verifying its "
- "peer. Server closes, client waits for close. "
- "Client and server choose SSLv2.";
-sslv2(suite) ->
- [];
-sslv2(Config) when list(Config) ->
- do_run_test(Config, [sslv2]).
-
-sslv3(doc) ->
- "Client has no cert. Nor the client, nor the server is verifying its "
- "peer. Server closes, client waits for close. "
- "Client and server choose SSLv3.";
-sslv3(suite) ->
- [];
-sslv3(Config) when list(Config) ->
- do_run_test(Config, [sslv3]).
-
-tlsv1(doc) ->
- "Client has no cert. Nor the client, nor the server is verifying its "
- "peer. Server closes, client waits for close. "
- "Client and server choose TLSv1.";
-tlsv1(suite) ->
- [];
-tlsv1(Config) when list(Config) ->
- do_run_test(Config, [tlsv1]).
-
-sslv2_sslv3(doc) ->
- "Client has no cert. Nor the client, nor the server is verifying its "
- "peer. Server closes, client waits for close. "
- "Client and server choose between SSLv2 and SSLv3.";
-sslv2_sslv3(suite) ->
- [];
-sslv2_sslv3(Config) when list(Config) ->
- do_run_test(Config, [sslv2, sslv3]).
-
-sslv2_tlsv1(doc) ->
- "Client has no cert. Nor the client, nor the server is verifying its "
- "peer. Server closes, client waits for close. "
- "Client and server choose between SSLv2 and TLSv1.";
-sslv2_tlsv1(suite) ->
- [];
-sslv2_tlsv1(Config) when list(Config) ->
- do_run_test(Config, [sslv2, tlsv1]).
-
-sslv3_tlsv1(doc) ->
- "Client has no cert. Nor the client, nor the server is verifying its "
- "peer. Server closes, client waits for close. "
- "Client and server choose between SSLv3 and TLSv1.";
-sslv3_tlsv1(suite) ->
- [];
-sslv3_tlsv1(Config) when list(Config) ->
- do_run_test(Config, [sslv3, tlsv1]).
-
-sslv2_sslv3_tlsv1(doc) ->
- "Client has no cert. Nor the client, nor the server is verifying its "
- "peer. Server closes, client waits for close. "
- "Client and server choose between SSLv2, SSLv3, and TLSv1.";
-sslv2_sslv3_tlsv1(suite) ->
- [];
-sslv2_sslv3_tlsv1(Config) when list(Config) ->
- do_run_test(Config, [sslv2, sslv3, tlsv1]).
-
-%%%%
-
-do_run_test(Config0, Protocols) ->
- process_flag(trap_exit, true),
- LPort = 3456,
- Timeout = 40000, NConns = 1,
- DataSize = 10,
-
- ?line {ok, {_, SsslOpts0}} = mk_ssl_cert_opts(Config0),
- ?line SsslOpts = [{verify, 0}, {depth, 2} | SsslOpts0],
-
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- connection_info,
- {recv, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {connect, {Host, LPort}},
- connection_info,
- {send, DataSize},
- await_close],
- Config1 = [{env, [{protocol_version, Protocols}]} | Config0],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout,
- ?MODULE, Config1).
-
-
diff --git a/lib/ssl/test/old_ssl_verify_SUITE.erl b/lib/ssl/test/old_ssl_verify_SUITE.erl
deleted file mode 100644
index 4c11ea6850..0000000000
--- a/lib/ssl/test/old_ssl_verify_SUITE.erl
+++ /dev/null
@@ -1,153 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
--module(old_ssl_verify_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,
- cinit_both_verify/1,
- cinit_cnocert/1
- ]).
-
--import(ssl_test_MACHINE, [mk_ssl_cert_opts/1, test_one_listener/7,
- test_server_only/6]).
--include_lib("test_server/include/test_server.hrl").
--include("ssl_test_MACHINE.hrl").
-
-
-init_per_testcase(_Case, Config) ->
- WatchDog = ssl_test_lib:timetrap(?DEFAULT_TIMEOUT),
- [{watchdog, WatchDog}| Config].
-
-end_per_testcase(_Case, Config) ->
- WatchDog = ?config(watchdog, Config),
- test_server:timetrap_cancel(WatchDog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [cinit_both_verify, cinit_cnocert].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_suite(doc) ->
- "Want to se what Config contains.";
-init_per_suite(suite) ->
- [];
-init_per_suite(Config) ->
- io:format("Config: ~p~n", [Config]),
-
- %% Check if SSL exists. If this case fails, all other cases are skipped
- case catch crypto:start() of
- ok ->
- application:start(public_key),
- case ssl:start() of
- ok -> ssl:stop();
- {error, {already_started, _}} -> ssl:stop();
- Error -> ?t:fail({failed_starting_ssl,Error})
- end,
- Config;
- _Else ->
- {skip,"Could not start crypto"}
- end.
-
-end_per_suite(doc) ->
- "This test case has no mission other than closing the conf case";
-end_per_suite(suite) ->
- [];
-end_per_suite(Config) ->
- crypto:stop(),
- Config.
-
-cinit_both_verify(doc) ->
- "Server closes after accept, Client waits for close. Both have certs "
- "and both verify each other.";
-cinit_both_verify(suite) ->
- [];
-cinit_both_verify(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts0, SsslOpts0}} = mk_ssl_cert_opts(Config),
- ?line CsslOpts = [{verify, 2}, {depth, 2} | CsslOpts0],
- ?line SsslOpts = [{verify, 2}, {depth, 3} | SsslOpts0],
-
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {recv, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout,
- ?MODULE, Config).
-
-cinit_cnocert(doc) ->
- "Client has no cert. Nor the client, nor the server is verifying its "
- "peer. Server closes, client waits for close.";
-cinit_cnocert(suite) ->
- [];
-cinit_cnocert(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3457,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {_, SsslOpts0}} = mk_ssl_cert_opts(Config),
- ?line SsslOpts = [{verify, 0}, {depth, 2} | SsslOpts0],
-
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {recv, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {connect, {Host, LPort}},
- {send, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout,
- ?MODULE, Config).
-
-
diff --git a/lib/ssl/test/old_transport_accept_SUITE.erl b/lib/ssl/test/old_transport_accept_SUITE.erl
deleted file mode 100644
index 6f0c8e456b..0000000000
--- a/lib/ssl/test/old_transport_accept_SUITE.erl
+++ /dev/null
@@ -1,258 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
--module(old_transport_accept_SUITE).
--include_lib("common_test/include/ct.hrl").
--include("test_server_line.hrl").
-
-%% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(1)).
--define(application, ssh).
-
--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,
- config/1,
- echo_once/1,
- echo_twice/1,
- close_before_ssl_accept/1,
- server/5,
- tolerant_server/5,
- client/5
- ]).
-
-init_per_testcase(_Case, Config) ->
- WatchDog = ssl_test_lib:timetrap(?default_timeout),
- [{watchdog, WatchDog}, {protomod, gen_tcp}, {serialize_accept, true}|
- Config].
-
-end_per_testcase(_Case, Config) ->
- WatchDog = ?config(watchdog, Config),
- test_server:timetrap_cancel(WatchDog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [config, echo_once, echo_twice, close_before_ssl_accept].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- try crypto:start() of
- ok ->
- Config
- catch _:_ ->
- {skip, "Crypto did not start"}
- end.
-
-end_per_suite(_Config) ->
- application:stop(crypto),
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-config(doc) ->
- "Want to se what Config contains.";
-config(suite) ->
- [];
-config(Config) ->
- io:format("Config: ~p~n", [Config]),
- ok.
-
-echo_once(doc) ->
- "Client sends 256 bytes to server, that receives them, sends them "
- "back, and closes. Client waits for close. Both have certs.";
-echo_once(suite) ->
- [];
-echo_once(Config) when list(Config) ->
- process_flag(trap_exit, true),
- LPort = 3456,
- {ok, Host} = inet:gethostname(),
- {ok, {COpts, SOpts}} = ssl_test_MACHINE:mk_ssl_cert_opts(Config),
- N = 1,
- Msg = lists:seq(0, 255),
- Self = self(),
- Params = "-pa " ++ filename:dirname(code:which(?MODULE)),
- Node = start_node(server, Params),
- CNode = start_node(client, Params),
- Server = spawn_link(Node, ?MODULE, server, [Self, LPort, SOpts, Msg, N]),
- Client = spawn_link(Node, ?MODULE, client, [Host, LPort, COpts, Msg, N]),
- ok = receive
- {Server, listening} ->
- Client ! {Server, listening},
- ok;
- E ->
- io:format("bad receive (1) ~p\n", [E]),
- E
- end,
- receive
- {Server, done} ->
- ok
- end,
- test_server:stop_node(Node),
- test_server:stop_node(CNode).
-
-close_before_ssl_accept(doc) ->
- "Client sends 256 bytes to server, that receives them, sends them "
- "back, and closes. Client waits for close. Both have certs.";
-close_before_ssl_accept(suite) ->
- [];
-close_before_ssl_accept(Config) when list(Config) ->
- process_flag(trap_exit, true),
- LPort = 3456,
- {ok, Host} = inet:gethostname(),
- {ok, {COpts, SOpts}} = ssl_test_MACHINE:mk_ssl_cert_opts(Config),
- Msg = lists:seq(0, 255),
- Self = self(),
- Params = "-pa " ++ filename:dirname(code:which(?MODULE)),
- Node = start_node(server, Params),
- CNode = start_node(client, Params),
- Server = spawn_link(Node, ?MODULE, tolerant_server,
- [Self, LPort, SOpts, Msg, 2]),
- Client = spawn_link(Node, ?MODULE, client,
- [Host, LPort, COpts, Msg, 1]),
- ok = receive
- {Server, listening} ->
- {ok, S} = gen_tcp:connect(Host, LPort, []),
- gen_tcp:close(S),
- Client ! {Server, listening},
- ok;
- E ->
- io:format("bad receive (1) ~p\n", [E]),
- E
- end,
- receive
- {Server, done} ->
- ok
- end,
- test_server:stop_node(Node),
- test_server:stop_node(CNode).
-
-client(Host, LPort, COpts, Msg, N) ->
- ok = receive
- {_Server, listening} ->
- ok;
- E ->
- io:format("bad receive (2) ~p\n", [E]),
- E
- end,
- Opts = COpts ++ [{packet, raw}, {active, false}],
- app(),
- lists:foreach(fun(_) ->
- {ok, S} = ssl:connect(Host, LPort, Opts),
- ssl:send(S, Msg),
- {ok, Msg} = ssl:recv(S, length(Msg)),
- ssl:close(S)
- end, lists:seq(1, N)).
-
-echo_twice(doc) ->
- "Two clients sends 256 bytes to server, that receives them, sends them "
- "back, and closes. Client waits for close. Both have certs.";
-echo_twice(suite) ->
- [];
-echo_twice(Config) when list(Config) ->
- process_flag(trap_exit, true),
- LPort = 3456,
- {ok, Host} = inet:gethostname(),
- {ok, {COpts, SOpts}} = ssl_test_MACHINE:mk_ssl_cert_opts(Config),
- N = 2,
- Msg = lists:seq(0, 255),
- Self = self(),
- Params = "-pa " ++ filename:dirname(code:which(?MODULE)),
- Node = start_node(server, Params),
- CNode = start_node(client, Params),
- Server = spawn_link(Node, ?MODULE, server,
- [Self, LPort, SOpts, Msg, N]),
- Client = spawn_link(Node, ?MODULE, client,
- [Host, LPort, COpts, Msg, N]),
- ok = receive
- {Server, listening} ->
- Client ! {Server, listening},
- ok;
- E ->
- io:format("bad receive (3) ~p\n", [E]),
- E
- end,
- receive
- {Server, done} ->
- ok
- end,
- test_server:stop_node(Node),
- test_server:stop_node(CNode).
-
-server(Client, Port, SOpts, Msg, N) ->
- app(),
- process_flag(trap_exit, true),
- Opts = SOpts ++ [{packet, raw}, {active, false}],
- {ok, LSock} = ssl:listen(Port, Opts),
- Client ! {self(), listening},
- server_loop(Client, LSock, Msg, N).
-
-server_loop(Client, _, _, 0) ->
- Client ! {self(), done};
-server_loop(Client, LSock, Msg, N) ->
- {ok, S} = ssl:transport_accept(LSock),
- ok = ssl:ssl_accept(S),
- %% P = ssl:controlling_process(S, Proxy),
- {ok, Msg} = ssl:recv(S, length(Msg)),
- ok = ssl:send(S, Msg),
- ok = ssl:close(S),
- server_loop(Client, LSock, Msg, N-1).
-
-tolerant_server(Client, Port, SOpts, Msg, N) ->
- app(),
- process_flag(trap_exit, true),
- Opts = SOpts ++ [{packet, raw}, {active, false}],
- {ok, LSock} = ssl:listen(Port, Opts),
- Client ! {self(), listening},
- tolerant_server_loop(Client, LSock, Msg, N).
-
-tolerant_server_loop(Client, _, _, 0) ->
- Client ! {self(), done};
-tolerant_server_loop(Client, LSock, Msg, N) ->
- {ok, S} = ssl:transport_accept(LSock),
- case ssl:ssl_accept(S) of
- ok ->
- %% P = ssl:controlling_process(S, Proxy),
- {ok, Msg} = ssl:recv(S, length(Msg)),
- ok = ssl:send(S, Msg),
- ok = ssl:close(S);
- E ->
- io:format("ssl_accept error: ~p\n", [E])
- end,
- tolerant_server_loop(Client, LSock, Msg, N-1).
-
-app() ->
- crypto:start(),
- application:start(public_key),
- ssl:start().
-
-start_node(Kind, Params) ->
- S = atom_to_list(?MODULE)++"_" ++ atom_to_list(Kind),
- {ok, Node} = test_server:start_node(list_to_atom(S), slave, [{args, Params}]),
- Node.
-
diff --git a/lib/ssl/test/ssl.cover b/lib/ssl/test/ssl.cover
index 60774cc0f1..6b13e07a37 100644
--- a/lib/ssl/test/ssl.cover
+++ b/lib/ssl/test/ssl.cover
@@ -1,21 +1,4 @@
{incl_app,ssl,details}.
-{excl_mods, ssl, [ssl_pkix_oid,
- 'PKIX1Algorithms88',
- 'PKIX1Explicit88',
- 'PKIX1Implicit88',
- 'PKIXAttributeCertificate',
- 'SSL-PKIX',
- ssl_pem,
- ssl_pkix,
- ssl_base64,
- ssl_broker,
- ssl_broker_int,
- ssl_broker_sup,
- ssl_debug,
- ssl_server,
- ssl_prim,
- inet_ssl_dist,
- 'OTP-PKIX'
- ]}.
+{excl_mods, ssl, [ssl_debug]}.
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index ec287ed803..d9cb8002ed 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -25,11 +25,11 @@
-compile(export_all).
-include_lib("common_test/include/ct.hrl").
--include("test_server_line.hrl").
-include_lib("public_key/include/public_key.hrl").
-include("ssl_alert.hrl").
--include("ssl_int.hrl").
+-include("ssl_internal.hrl").
+-include("ssl_record.hrl").
-define('24H_in_sec', 86400).
-define(TIMEOUT, 60000).
@@ -206,10 +206,14 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[app, alerts, connection_info, protocol_versions,
empty_protocol_versions, controlling_process,
- controller_dies, client_closes_socket, peercert,
- connect_dist, peername, sockname, socket_options,
+ controller_dies, client_closes_socket,
+ connect_dist, peername, peercert, sockname, socket_options,
+ invalid_inet_get_option, invalid_inet_get_option_not_list,
+ invalid_inet_get_option_improper_list,
+ invalid_inet_set_option, invalid_inet_set_option_not_list,
+ invalid_inet_set_option_improper_list,
misc_ssl_options, versions, cipher_suites, upgrade,
- upgrade_with_timeout, tcp_connect, ipv6, ekeyfile,
+ upgrade_with_timeout, tcp_connect, tcp_connect_big, ipv6, ekeyfile,
ecertfile, ecacertfile, eoptions, shutdown,
shutdown_write, shutdown_both, shutdown_error,
ciphers_rsa_signed_certs, ciphers_rsa_signed_certs_ssl3,
@@ -248,11 +252,11 @@ all() ->
unknown_server_ca_fail, der_input,
unknown_server_ca_accept_verify_none,
unknown_server_ca_accept_verify_peer,
- unknown_server_ca_accept_backwardscompatibilty,
+ unknown_server_ca_accept_backwardscompatibility,
%%different_ca_peer_sign,
no_reuses_session_server_restart_new_cert,
no_reuses_session_server_restart_new_cert_file, reuseaddr,
- hibernate
+ hibernate, connect_twice
].
groups() ->
@@ -579,50 +583,6 @@ client_closes_socket(Config) when is_list(Config) ->
ssl_test_lib:check_result(Server, {error,closed}).
%%--------------------------------------------------------------------
-
-peercert(doc) ->
- [""];
-
-peercert(suite) ->
- [];
-
-peercert(Config) when is_list(Config) ->
- ClientOpts = ?config(client_opts, Config),
- ServerOpts = ?config(server_opts, Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE, peercert_result, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE, peercert_result, []}},
- {options, ClientOpts}]),
-
- CertFile = proplists:get_value(certfile, ServerOpts),
- [{'Certificate', BinCert, _}]= ssl_test_lib:pem_to_der(CertFile),
- ErlCert = public_key:pkix_decode_cert(BinCert, otp),
-
- ServerMsg = {{error, no_peercert}, {error, no_peercert}},
- ClientMsg = {{ok, BinCert}, {ok, ErlCert}},
-
- test_server:format("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
-
- ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-peercert_result(Socket) ->
- Result1 = ssl:peercert(Socket),
- Result2 = ssl:peercert(Socket, [ssl]),
- {Result1, Result2}.
-
-%%--------------------------------------------------------------------
connect_dist(doc) ->
["Test a simple connect as is used by distribution"];
@@ -703,6 +663,44 @@ peername_result(S) ->
ssl:peername(S).
%%--------------------------------------------------------------------
+peercert(doc) ->
+ [""];
+peercert(suite) ->
+ [];
+peercert(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, peercert_result, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, peercert_result, []}},
+ {options, ClientOpts}]),
+
+ CertFile = proplists:get_value(certfile, ServerOpts),
+ [{'Certificate', BinCert, _}]= ssl_test_lib:pem_to_der(CertFile),
+
+ ServerMsg = {error, no_peercert},
+ ClientMsg = {ok, BinCert},
+
+ test_server:format("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+peercert_result(Socket) ->
+ ssl:peercert(Socket).
+
+%%--------------------------------------------------------------------
sockname(doc) ->
["Test API function sockname/1"];
@@ -808,8 +806,218 @@ socket_options_result(Socket, Options, DefaultValues, NewOptions, NewValues) ->
{ok,[{nodelay,false}]} = ssl:getopts(Socket, [nodelay]),
ssl:setopts(Socket, [{nodelay, true}]),
{ok,[{nodelay, true}]} = ssl:getopts(Socket, [nodelay]),
+ {ok, All} = ssl:getopts(Socket, []),
+ test_server:format("All opts ~p~n", [All]),
+ ok.
+
+
+%%--------------------------------------------------------------------
+invalid_inet_get_option(doc) ->
+ ["Test handling of invalid inet options in getopts"];
+
+invalid_inet_get_option(suite) ->
+ [];
+
+invalid_inet_get_option(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, get_invalid_inet_option, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, ClientOpts}]),
+
+ test_server:format("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+
+get_invalid_inet_option(Socket) ->
+ {error, {eoptions, {inet_option, foo, _}}} = ssl:getopts(Socket, [foo]),
ok.
+
+%%--------------------------------------------------------------------
+invalid_inet_get_option_not_list(doc) ->
+ ["Test handling of invalid type in getopts"];
+
+invalid_inet_get_option_not_list(suite) ->
+ [];
+
+invalid_inet_get_option_not_list(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, get_invalid_inet_option_not_list, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, ClientOpts}]),
+
+ test_server:format("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+ ssl_test_lib:check_result(Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+
+get_invalid_inet_option_not_list(Socket) ->
+ {error, {eoptions, {inet_options, some_invalid_atom_here}}}
+ = ssl:getopts(Socket, some_invalid_atom_here),
+ ok.
+
+%%--------------------------------------------------------------------
+invalid_inet_get_option_improper_list(doc) ->
+ ["Test handling of invalid type in getopts"];
+
+invalid_inet_get_option_improper_list(suite) ->
+ [];
+
+invalid_inet_get_option_improper_list(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, get_invalid_inet_option_improper_list, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, ClientOpts}]),
+
+ test_server:format("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+
+get_invalid_inet_option_improper_list(Socket) ->
+ {error, {eoptions, {inet_option, foo,_}}} = ssl:getopts(Socket, [packet | foo]),
+ ok.
+
+%%--------------------------------------------------------------------
+invalid_inet_set_option(doc) ->
+ ["Test handling of invalid inet options in setopts"];
+
+invalid_inet_set_option(suite) ->
+ [];
+
+invalid_inet_set_option(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, set_invalid_inet_option, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, ClientOpts}]),
+
+ test_server:format("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+set_invalid_inet_option(Socket) ->
+ {error, {eoptions, {inet_opt, {packet, foo}}}} = ssl:setopts(Socket, [{packet, foo}]),
+ {error, {eoptions, {inet_opt, {header, foo}}}} = ssl:setopts(Socket, [{header, foo}]),
+ {error, {eoptions, {inet_opt, {active, foo}}}} = ssl:setopts(Socket, [{active, foo}]),
+ {error, {eoptions, {inet_opt, {mode, foo}}}} = ssl:setopts(Socket, [{mode, foo}]),
+ ok.
+%%--------------------------------------------------------------------
+invalid_inet_set_option_not_list(doc) ->
+ ["Test handling of invalid type in setopts"];
+
+invalid_inet_set_option_not_list(suite) ->
+ [];
+
+invalid_inet_set_option_not_list(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, set_invalid_inet_option_not_list, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, ClientOpts}]),
+
+ test_server:format("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+
+set_invalid_inet_option_not_list(Socket) ->
+ {error, {eoptions, {not_a_proplist, some_invalid_atom_here}}}
+ = ssl:setopts(Socket, some_invalid_atom_here),
+ ok.
+
+%%--------------------------------------------------------------------
+invalid_inet_set_option_improper_list(doc) ->
+ ["Test handling of invalid tye in setopts"];
+
+invalid_inet_set_option_improper_list(suite) ->
+ [];
+
+invalid_inet_set_option_improper_list(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, set_invalid_inet_option_improper_list, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, ClientOpts}]),
+
+ test_server:format("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+set_invalid_inet_option_improper_list(Socket) ->
+ {error, {eoptions, {not_a_proplist, [{packet, 0} | {foo, 2}]}}} =
+ ssl:setopts(Socket, [{packet, 0} | {foo, 2}]),
+ ok.
+
%%--------------------------------------------------------------------
misc_ssl_options(doc) ->
["Test what happens when we give valid options"];
@@ -1097,6 +1305,41 @@ tcp_connect(Config) when is_list(Config) ->
end
end.
+tcp_connect_big(doc) ->
+ ["Test what happens when a tcp tries to connect, i,e. a bad big (ssl) packet is sent first"];
+
+tcp_connect_big(suite) ->
+ [];
+
+tcp_connect_big(Config) when is_list(Config) ->
+ ServerOpts = ?config(server_opts, Config),
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ TcpOpts = [binary, {reuseaddr, true}],
+
+ Server = ssl_test_lib:start_upgrade_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {timeout, 5000},
+ {mfa, {?MODULE, dummy, []}},
+ {tcp_options, TcpOpts},
+ {ssl_options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ {ok, Socket} = gen_tcp:connect(Hostname, Port, [binary, {packet, 0}]),
+ test_server:format("Testcase ~p connected to Server ~p ~n", [self(), Server]),
+
+ Rand = crypto:rand_bytes(?MAX_CIPHER_TEXT_LENGTH+1),
+ gen_tcp:send(Socket, <<?BYTE(0),
+ ?BYTE(3), ?BYTE(1), ?UINT16(?MAX_CIPHER_TEXT_LENGTH), Rand/binary>>),
+
+ receive
+ {tcp_closed, Socket} ->
+ receive
+ {Server, {error, timeout}} ->
+ test_server:fail("hangs");
+ {Server, {error, Error}} ->
+ test_server:format("Error ~p", [Error])
+ end
+ end.
dummy(_Socket) ->
%% Should not happen as the ssl connection will not be established
@@ -1278,7 +1521,6 @@ eoptions(Config) when is_list(Config) ->
end,
TestOpts = [{versions, [sslv2, sslv3]},
- {ssl_imp, cool},
{verify, 4},
{verify_fun, function},
{fail_if_no_peer_cert, 0},
@@ -2350,7 +2592,7 @@ client_renegotiate(Config) when is_list(Config) ->
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
{mfa, {?MODULE,
@@ -2542,7 +2784,7 @@ extended_key_usage_verify_peer(Config) when is_list(Config) ->
KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"),
[KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
- Key = public_key:pem_entry_decode(KeyEntry),
+ Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)),
ServerCertFile = proplists:get_value(certfile, ServerOpts),
NewServerCertFile = filename:join(PrivDir, "server/new_cert.pem"),
@@ -2604,7 +2846,7 @@ extended_key_usage_verify_none(Config) when is_list(Config) ->
KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"),
[KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
- Key = public_key:pem_entry_decode(KeyEntry),
+ Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)),
ServerCertFile = proplists:get_value(certfile, ServerOpts),
NewServerCertFile = filename:join(PrivDir, "server/new_cert.pem"),
@@ -2666,7 +2908,7 @@ no_authority_key_identifier(Config) when is_list(Config) ->
KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"),
[KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
- Key = public_key:pem_entry_decode(KeyEntry),
+ Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)),
CertFile = proplists:get_value(certfile, ServerOpts),
NewCertFile = filename:join(PrivDir, "server/new_cert.pem"),
@@ -2724,7 +2966,7 @@ invalid_signature_server(Config) when is_list(Config) ->
KeyFile = filename:join(PrivDir, "server/key.pem"),
[KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
- Key = public_key:pem_entry_decode(KeyEntry),
+ Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)),
ServerCertFile = proplists:get_value(certfile, ServerOpts),
NewServerCertFile = filename:join(PrivDir, "server/invalid_cert.pem"),
@@ -2764,7 +3006,7 @@ invalid_signature_client(Config) when is_list(Config) ->
KeyFile = filename:join(PrivDir, "client/key.pem"),
[KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
- Key = public_key:pem_entry_decode(KeyEntry),
+ Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)),
ClientCertFile = proplists:get_value(certfile, ClientOpts),
NewClientCertFile = filename:join(PrivDir, "client/invalid_cert.pem"),
@@ -2796,7 +3038,8 @@ tcp_delivery_workaround(Server, ServerMsg, Client, ClientMsg) ->
{Client, ClientMsg} ->
ok;
{Client, {error,closed}} ->
- test_server:format("client got close");
+ test_server:format("client got close"),
+ ok;
Unexpected ->
test_server:fail(Unexpected)
end;
@@ -2841,7 +3084,7 @@ cert_expired(Config) when is_list(Config) ->
KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"),
[KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
- Key = public_key:pem_entry_decode(KeyEntry),
+ Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)),
ServerCertFile = proplists:get_value(certfile, ServerOpts),
NewServerCertFile = filename:join(PrivDir, "server/expired_cert.pem"),
@@ -3032,11 +3275,11 @@ unknown_server_ca_accept_verify_peer(Config) when is_list(Config) ->
ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
-unknown_server_ca_accept_backwardscompatibilty(doc) ->
+unknown_server_ca_accept_backwardscompatibility(doc) ->
["Test that old style verify_funs will work"];
-unknown_server_ca_accept_backwardscompatibilty(suite) ->
+unknown_server_ca_accept_backwardscompatibility(suite) ->
[];
-unknown_server_ca_accept_backwardscompatibilty(Config) when is_list(Config) ->
+unknown_server_ca_accept_backwardscompatibility(Config) when is_list(Config) ->
ClientOpts = ?config(client_opts, Config),
ServerOpts = ?config(server_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
@@ -3116,14 +3359,14 @@ der_input_opts(Opts) ->
Keyfile = proplists:get_value(keyfile, Opts),
Dhfile = proplists:get_value(dhfile, Opts),
[{_, Cert, _}] = ssl_test_lib:pem_to_der(Certfile),
- [{_, Key, _}] = ssl_test_lib:pem_to_der(Keyfile),
+ [{Asn1Type, Key, _}] = ssl_test_lib:pem_to_der(Keyfile),
[{_, DHParams, _}] = ssl_test_lib:pem_to_der(Dhfile),
CaCerts =
lists:map(fun(Entry) ->
{_, CaCert, _} = Entry,
CaCert
end, ssl_test_lib:pem_to_der(CaCertsfile)),
- {Cert, {rsa, Key}, CaCerts, DHParams}.
+ {Cert, {Asn1Type, Key}, CaCerts, DHParams}.
%%--------------------------------------------------------------------
%% different_ca_peer_sign(doc) ->
@@ -3301,6 +3544,7 @@ reuseaddr(Config) when is_list(Config) ->
{options, [{active, false} | ClientOpts]}]),
test_server:sleep(?SLEEP),
ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client),
Server1 =
ssl_test_lib:start_server([{node, ServerNode}, {port, Port},
@@ -3345,19 +3589,66 @@ hibernate(Config) ->
{from, self()},
{mfa, {?MODULE, send_recv_result_active, []}},
{options, [{hibernate_after, 1000}|ClientOpts]}]),
-
- { current_function, { _M, _F, _A } } =
+ {current_function, _} =
process_info(Pid, current_function),
timer:sleep(1100),
- { current_function, { erlang, hibernate, 3} } =
- process_info(Pid, current_function),
+ {current_function, {erlang, hibernate, 3}} =
+ process_info(Pid, current_function),
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
+
+connect_twice(doc) ->
+ [""];
+connect_twice(suite) ->
+ [];
+connect_twice(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, send_recv_result, []}},
+ {options, [{keepalive, true},{active, false}
+ | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client =
+ ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, send_recv_result, []}},
+ {options, [{keepalive, true},{active, false}
+ | ClientOpts]}]),
+ Server ! listen,
+
+ {Client1, #sslsocket{}} =
+ ssl_test_lib:start_client([return_socket,
+ {node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, send_recv_result, []}},
+ {options, [{keepalive, true},{active, false}
+ | ClientOpts]}]),
+
+ test_server:format("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ ssl_test_lib:check_result(Server, ok, Client1, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client),
+ ssl_test_lib:close(Client1).
+
+
+%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
send_recv_result(Socket) ->
@@ -3435,7 +3726,7 @@ session_cache_process_mnesia(suite) ->
session_cache_process_mnesia(Config) when is_list(Config) ->
session_cache_process(mnesia,Config).
-session_cache_process(Type,Config) when is_list(Config) ->
+session_cache_process(_Type,Config) when is_list(Config) ->
reuse_session(Config).
init([Type]) ->
diff --git a/lib/ssl/test/ssl_cipher_SUITE.erl b/lib/ssl/test/ssl_cipher_SUITE.erl
new file mode 100644
index 0000000000..99bc21e820
--- /dev/null
+++ b/lib/ssl/test/ssl_cipher_SUITE.erl
@@ -0,0 +1,163 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(ssl_cipher_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+-include("ssl_internal.hrl").
+-include("ssl_record.hrl").
+-include("ssl_cipher.hrl").
+
+-define(TIMEOUT, 600000).
+
+%% Test server callback functions
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config) -> Config
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Description: Initialization before the whole suite
+%%
+%% Note: This function is free to add any key/value pairs to the Config
+%% variable, but should NOT alter/remove any existing entries.
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ try crypto:start() of
+ ok ->
+ Config
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config) -> _
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Description: Cleanup after the whole suite
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:stop(crypto).
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config) -> Config
+%% Case - atom()
+%% Name of the test case that is about to be run.
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%%
+%% Description: Initialization before each test case
+%%
+%% Note: This function is free to add any key/value pairs to the Config
+%% variable, but should NOT alter/remove any existing entries.
+%% Description: Initialization before each test case
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config0) ->
+ Config = lists:keydelete(watchdog, 1, Config0),
+ Dog = ssl_test_lib:timetrap(?TIMEOUT),
+ [{watchdog, Dog} | Config].
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config) -> _
+%% Case - atom()
+%% Name of the test case that is about to be run.
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Description: Cleanup after each test case
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, Config) ->
+ Dog = ?config(watchdog, Config),
+ case Dog of
+ undefined ->
+ ok;
+ _ ->
+ test_server:timetrap_cancel(Dog)
+ end.
+
+%%--------------------------------------------------------------------
+%% Function: all(Clause) -> TestCases
+%% Clause - atom() - suite | doc
+%% TestCases - [Case]
+%% Case - atom()
+%% Name of a test case.
+%% Description: Returns a list of all test cases in this test suite
+%%--------------------------------------------------------------------
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [aes_decipher_good, aes_decipher_fail].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+%% Test cases starts here.
+%%--------------------------------------------------------------------
+aes_decipher_good(doc) ->
+ ["Decipher a known cryptotext."];
+
+aes_decipher_good(suite) ->
+ [];
+
+aes_decipher_good(Config) when is_list(Config) ->
+ HashSz = 32,
+ CipherState = #cipher_state{iv = <<59,201,85,117,188,206,224,136,5,109,46,70,104,79,4,9>>,
+ key = <<72,196,247,97,62,213,222,109,210,204,217,186,172,184,197,148>>},
+ Fragment = <<220,193,179,139,171,33,143,245,202,47,123,251,13,232,114,8,
+ 190,162,74,31,186,227,119,155,94,74,119,79,169,193,240,160,
+ 198,181,81,19,98,162,213,228,74,224,253,168,156,59,195,122,
+ 108,101,107,242,20,15,169,150,163,107,101,94,93,104,241,165>>,
+ Version = {3,3},
+ Content = <<183,139,16,132,10,209,67,86,168,100,61,217,145,57,36,56,72,69,76,76,79,10>>,
+ Mac = <<71,136,212,107,223,200,70,232,127,116,148,205,232,35,158,113,237,174,15,217,192,168,35,8,6,107,107,233,25,174,90,111>>,
+ {Content, Mac, _} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version),
+ ok.
+
+%%--------------------------------------------------------------------
+
+aes_decipher_fail(doc) ->
+ ["Decipher a known cryptotext."];
+
+aes_decipher_fail(suite) ->
+ [];
+
+%% same as above, last byte of key replaced
+aes_decipher_fail(Config) when is_list(Config) ->
+ HashSz = 32,
+ CipherState = #cipher_state{iv = <<59,201,85,117,188,206,224,136,5,109,46,70,104,79,4,9>>,
+ key = <<72,196,247,97,62,213,222,109,210,204,217,186,172,184,197,254>>},
+ Fragment = <<220,193,179,139,171,33,143,245,202,47,123,251,13,232,114,8,
+ 190,162,74,31,186,227,119,155,94,74,119,79,169,193,240,160,
+ 198,181,81,19,98,162,213,228,74,224,253,168,156,59,195,122,
+ 108,101,107,242,20,15,169,150,163,107,101,94,93,104,241,165>>,
+ Version = {3,3},
+ {Content, Mac, _} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version),
+ 32 = byte_size(Content),
+ 32 = byte_size(Mac),
+ ok.
+
+%%--------------------------------------------------------------------
diff --git a/lib/ssl/test/old_ssl_dist_SUITE.erl b/lib/ssl/test/ssl_dist_SUITE.erl
index 4544fb616a..8fe55ee7a4 100644
--- a/lib/ssl/test/old_ssl_dist_SUITE.erl
+++ b/lib/ssl/test/ssl_dist_SUITE.erl
@@ -17,41 +17,32 @@
%% %CopyrightEnd%
%%
-%%
-
-
-%%%-------------------------------------------------------------------
-%%% File : ssl_dist_SUITE.erl
-%%% Author : Rickard Green
-%%% Description : Test that the Erlang distribution works over ssl.
-%%%
-%%% Created : 15 Nov 2007 by Rickard Green
-%%%-------------------------------------------------------------------
--module(old_ssl_dist_SUITE).
+-module(ssl_dist_SUITE).
-include_lib("test_server/include/test_server.hrl").
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
-define(DEFAULT_TIMETRAP_SECS, 240).
-define(AWAIT_SLL_NODE_UP_TIMEOUT, 30000).
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]).
--export([init_per_suite/1,
- end_per_suite/1,
- init_per_testcase/2,
- end_per_testcase/2]).
--export([cnct2tstsrvr/1]).
+-record(node_handle,
+ {connection_handler,
+ socket,
+ name,
+ nodename}
+ ).
--export([basic/1]).
+%% Test server callback functions
+suite() ->
+ [{ct_hooks,[ts_install_cth]}].
--record(node_handle, {connection_handler, socket, name, nodename}).
+all() ->
+ [basic, payload, plain_options, plain_verify_options].
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [basic].
-
-groups() ->
+groups() ->
[].
init_per_group(_GroupName, Config) ->
@@ -60,11 +51,17 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-
-init_per_suite(Config) ->
+init_per_suite(Config0) ->
try crypto:start() of
ok ->
- add_ssl_opts_config(Config)
+ case test_server:is_cover() of
+ false ->
+ Config = add_ssl_opts_config(Config0),
+ setup_certs(Config),
+ Config;
+ true ->
+ {skip, "Can not be covered"}
+ end
catch _:_ ->
{skip, "Crypto did not start"}
end.
@@ -73,85 +70,184 @@ end_per_suite(Config) ->
application:stop(crypto),
Config.
-init_per_testcase(Case, Config) when list(Config) ->
+init_per_testcase(plain_verify_options = Case, Config) when is_list(Config) ->
+ SslFlags = setup_dist_opts([{many_verify_opts, true} | Config]),
+ Flags = case os:getenv("ERL_FLAGS") of
+ false ->
+ os:putenv("ERL_FLAGS", SslFlags),
+ "";
+ OldFlags ->
+ os:putenv("ERL_FLAGS", OldFlags ++ "" ++ SslFlags),
+ OldFlags
+ end,
+ common_init(Case, [{old_flags, Flags} | Config]);
+
+init_per_testcase(Case, Config) when is_list(Config) ->
+ common_init(Case, Config).
+
+common_init(Case, Config) ->
Dog = ?t:timetrap(?t:seconds(?DEFAULT_TIMETRAP_SECS)),
[{watchdog, Dog},{testcase, Case}|Config].
-end_per_testcase(_Case, Config) when list(Config) ->
+end_per_testcase(Case, Config) when is_list(Config) ->
+ Flags = proplists:get_value(old_flags, Config),
+ os:putenv("ERL_FLAGS", Flags),
+ common_end(Case, Config).
+
+common_end(_, Config) ->
Dog = ?config(watchdog, Config),
?t:timetrap_cancel(Dog),
ok.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% Testcases %%
-%% %%
-
+%%--------------------------------------------------------------------
+%% Test cases starts here.
+%%--------------------------------------------------------------------
basic(doc) ->
["Test that two nodes can connect via ssl distribution"];
-basic(suite) ->
- [];
basic(Config) when is_list(Config) ->
- ?line NH1 = start_ssl_node(Config),
- ?line Node1 = NH1#node_handle.nodename,
- ?line NH2 = start_ssl_node(Config),
- ?line Node2 = NH2#node_handle.nodename,
+ NH1 = start_ssl_node(Config),
+ Node1 = NH1#node_handle.nodename,
+ NH2 = start_ssl_node(Config),
+ Node2 = NH2#node_handle.nodename,
- ?line pong = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end),
+ pong = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end),
- ?line [Node2] = apply_on_ssl_node(NH1, fun () -> nodes() end),
- ?line [Node1] = apply_on_ssl_node(NH2, fun () -> nodes() end),
+ [Node2] = apply_on_ssl_node(NH1, fun () -> nodes() end),
+ [Node1] = apply_on_ssl_node(NH2, fun () -> nodes() end),
%% The test_server node has the same cookie as the ssl nodes
%% but it should not be able to communicate with the ssl nodes
%% via the erlang distribution.
- ?line pang = net_adm:ping(Node1),
- ?line pang = net_adm:ping(Node2),
-
+ pang = net_adm:ping(Node1),
+ pang = net_adm:ping(Node2),
%%
%% Check that we are able to communicate over the erlang
%% distribution between the ssl nodes.
%%
- ?line Ref = make_ref(),
- ?line spawn(fun () ->
- apply_on_ssl_node(
- NH1,
- fun () ->
- tstsrvr_format("Hi from ~p!~n",
- [node()]),
- send_to_tstcntrl({Ref, self()}),
- receive
- {From, ping} ->
- From ! {self(), pong}
- end
- end)
- end),
- ?line receive
- {Ref, SslPid} ->
- ?line ok = apply_on_ssl_node(
- NH2,
- fun () ->
- tstsrvr_format("Hi from ~p!~n",
- [node()]),
- SslPid ! {self(), ping},
- receive
- {SslPid, pong} ->
- ok
- end
- end)
- end,
-
- ?line stop_ssl_node(NH1),
- ?line stop_ssl_node(NH2),
- ?line success(Config).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% Internal functions %%
-%% %%
+ Ref = make_ref(),
+ spawn(fun () ->
+ apply_on_ssl_node(
+ NH1,
+ fun () ->
+ tstsrvr_format("Hi from ~p!~n", [node()]),
+ send_to_tstcntrl({Ref, self()}),
+ receive
+ {From, ping} ->
+ tstsrvr_format("Received ping ~p!~n", [node()]),
+ From ! {self(), pong}
+ end
+ end)
+ end),
+ receive
+ {Ref, SslPid} ->
+ ok = apply_on_ssl_node(
+ NH2,
+ fun () ->
+ tstsrvr_format("Hi from ~p!~n", [node()]),
+ SslPid ! {self(), ping},
+ receive
+ {SslPid, pong} ->
+ ok
+ end
+ end)
+ end,
+ stop_ssl_node(NH1),
+ stop_ssl_node(NH2),
+ success(Config).
+
+%%--------------------------------------------------------------------
+payload(doc) ->
+ ["Test that send a lot of data between the ssl distributed noes"];
+payload(Config) when is_list(Config) ->
+ NH1 = start_ssl_node(Config),
+ Node1 = NH1#node_handle.nodename,
+ NH2 = start_ssl_node(Config),
+ Node2 = NH2#node_handle.nodename,
+
+ pong = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end),
+
+ [Node2] = apply_on_ssl_node(NH1, fun () -> nodes() end),
+ [Node1] = apply_on_ssl_node(NH2, fun () -> nodes() end),
+
+ Ref = make_ref(),
+ spawn(fun () ->
+ apply_on_ssl_node(
+ NH1,
+ fun () ->
+ send_to_tstcntrl({Ref, self()}),
+ receive
+ {From, Msg} ->
+ From ! {self(), Msg}
+ end
+ end)
+ end),
+ receive
+ {Ref, SslPid} ->
+ ok = apply_on_ssl_node(
+ NH2,
+ fun () ->
+ Msg = crypto:rand_bytes(100000),
+ SslPid ! {self(), Msg},
+ receive
+ {SslPid, Msg} ->
+ ok
+ end
+ end)
+ end,
+ stop_ssl_node(NH1),
+ stop_ssl_node(NH2),
+ success(Config).
+%%--------------------------------------------------------------------
+plain_options(doc) ->
+ ["Test specifying additional options"];
+plain_options(Config) when is_list(Config) ->
+ DistOpts = "-ssl_dist_opt server_secure_renegotiate true "
+ "client_secure_renegotiate true "
+ "server_reuse_sessions true client_reuse_sessions true "
+ "client_verify verify_none server_verify verify_none "
+ "server_depth 1 client_depth 1 "
+ "server_hibernate_after 500 client_hibernate_after 500",
+
+ NH1 = start_ssl_node([{additional_dist_opts, DistOpts} | Config]),
+ Node1 = NH1#node_handle.nodename,
+ NH2 = start_ssl_node([{additional_dist_opts, DistOpts} | Config]),
+ Node2 = NH2#node_handle.nodename,
+
+ pong = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end),
+
+ [Node2] = apply_on_ssl_node(NH1, fun () -> nodes() end),
+ [Node1] = apply_on_ssl_node(NH2, fun () -> nodes() end),
+
+ stop_ssl_node(NH1),
+ stop_ssl_node(NH2),
+ success(Config).
+%%--------------------------------------------------------------------
+plain_verify_options(doc) ->
+ ["Test specifying additional options"];
+plain_verify_options(Config) when is_list(Config) ->
+ DistOpts = "-ssl_dist_opt server_secure_renegotiate true "
+ "client_secure_renegotiate true "
+ "server_reuse_sessions true client_reuse_sessions true "
+ "server_hibernate_after 500 client_hibernate_after 500",
+
+ NH1 = start_ssl_node([{additional_dist_opts, DistOpts} | Config]),
+ Node1 = NH1#node_handle.nodename,
+ NH2 = start_ssl_node([{additional_dist_opts, DistOpts} | Config]),
+ Node2 = NH2#node_handle.nodename,
+
+ pong = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end),
+
+ [Node2] = apply_on_ssl_node(NH1, fun () -> nodes() end),
+ [Node1] = apply_on_ssl_node(NH2, fun () -> nodes() end),
+
+ stop_ssl_node(NH1),
+ stop_ssl_node(NH2),
+ success(Config).
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
-%%
%% ssl_node side api
%%
@@ -166,7 +262,7 @@ send_to_tstcntrl(Message) ->
%% test_server side api
%%
-apply_on_ssl_node(Node, M, F, A) when atom(M), atom(F), list(A) ->
+apply_on_ssl_node(Node, M, F, A) when is_atom(M), is_atom(F), is_list(A) ->
Ref = make_ref(),
send_to_ssl_node(Node, {apply, self(), Ref, M, F, A}),
receive
@@ -208,7 +304,7 @@ start_ssl_node(Config) ->
start_ssl_node(Config, XArgs) ->
Name = mk_node_name(Config),
SSL = ?config(ssl_opts, Config),
- SSLDistOpts = setup_dist_opts(Name, ?config(priv_dir, Config)),
+ SSLDistOpts = setup_dist_opts(Config),
start_ssl_node_raw(Name, SSL ++ " " ++ SSLDistOpts ++ XArgs).
start_ssl_node_raw(Name, Args) ->
@@ -218,7 +314,7 @@ start_ssl_node_raw(Name, Args) ->
CmdLine = mk_node_cmdline(ListenPort, Name, Args),
?t:format("Attempting to start ssl node ~s: ~s~n", [Name, CmdLine]),
case open_port({spawn, CmdLine}, []) of
- Port when port(Port) ->
+ Port when is_port(Port) ->
unlink(Port),
erlang:port_close(Port),
case await_ssl_node_up(Name, LSock) of
@@ -270,8 +366,8 @@ mk_node_cmdline(ListenPort, Name, Args) ->
Prog ++ " "
++ Static ++ " "
++ NameSw ++ " " ++ Name ++ " "
- ++ "-pa " ++ Pa ++ " "
- ++ "-run application start crypto -run application start public_key "
+ ++ "-pa " ++ Pa ++ " "
+ ++ "-run application start crypto -run application start public_key "
++ "-run " ++ atom_to_list(?MODULE) ++ " cnct2tstsrvr "
++ host_name() ++ " "
++ integer_to_list(ListenPort) ++ " "
@@ -355,6 +451,7 @@ tstsrvr_con_loop(Name, Socket, Parent) ->
{format, FmtStr, ArgList} ->
?t:format(FmtStr, ArgList);
{message, Msg} ->
+ ?t:format("Got message ~p", [Msg]),
Parent ! Msg;
{apply_res, To, Ref, Res} ->
To ! {Ref, Res};
@@ -376,7 +473,7 @@ tstsrvr_con_loop(Name, Socket, Parent) ->
%%
% cnct2tstsrvr() is called via command line arg -run ...
-cnct2tstsrvr([Host, Port]) when list(Host), list(Port) ->
+cnct2tstsrvr([Host, Port]) when is_list(Host), is_list(Port) ->
%% Spawn connection handler on ssl node side
ConnHandler
= spawn(fun () ->
@@ -395,8 +492,10 @@ cnct2tstsrvr([Host, Port]) when list(Host), list(Port) ->
ets:insert(test_server_info,
{test_server_handler, self()}),
ssl_node_con_loop(Socket);
- _Error ->
- halt("Failed to connect to test server")
+ Error ->
+ halt("Failed to connect to test server " ++
+ lists:flatten(io_lib:format("Host:~p ~n Port:~p~n Error:~p~n",
+ [Host, Port, Error])))
end
end),
spawn(fun () ->
@@ -404,9 +503,8 @@ cnct2tstsrvr([Host, Port]) when list(Host), list(Port) ->
receive
{'DOWN', Mon, process, ConnHandler, Reason} ->
receive after 1000 -> ok end,
- halt("test server connection handler terminated: "
- ++
- lists:flatten(io_lib:format("~p", [Reason])))
+ halt("test server connection handler terminated: " ++
+ lists:flatten(io_lib:format("~p", [Reason])))
end
end).
@@ -419,7 +517,7 @@ notify_ssl_node_up(Socket) ->
send_to_tstsrvr(Term) ->
case catch ets:lookup_element(test_server_info, test_server_handler, 2) of
- Hndlr when pid(Hndlr) ->
+ Hndlr when is_pid(Hndlr) ->
Hndlr ! {relay_to_test_server, term_to_binary(Term)}, ok;
_ ->
receive after 200 -> ok end,
@@ -499,9 +597,10 @@ do_append_files([F|Fs], RF) ->
{ok, Data} = file:read_file(F),
ok = file:write(RF, Data),
do_append_files(Fs, RF).
-
-setup_dist_opts(Name, PrivDir) ->
- NodeDir = filename:join([PrivDir, Name]),
+
+setup_certs(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ NodeDir = filename:join([PrivDir, "Certs"]),
RGenDir = filename:join([NodeDir, "rand_gen"]),
ok = file:make_dir(NodeDir),
ok = file:make_dir(RGenDir),
@@ -516,11 +615,61 @@ setup_dist_opts(Name, PrivDir) ->
CC = filename:join([CDir, "cert.pem"]),
CK = filename:join([CDir, "key.pem"]),
CKC = filename:join([CDir, "keycert.pem"]),
- append_files([CK, CC], CKC),
- "-proto_dist inet_ssl "
- ++ "-ssl_dist_opt server_certfile " ++ SKC ++ " "
- ++ "-ssl_dist_opt client_certfile " ++ CKC ++ " "
-.% ++ "-ssl_dist_opt verify 1 depth 1".
+ append_files([CK, CC], CKC).
+
+setup_dist_opts(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ DataDir = ?config(data_dir, Config),
+ Dhfile = filename:join([DataDir, "dHParam.pem"]),
+ NodeDir = filename:join([PrivDir, "Certs"]),
+ SDir = filename:join([NodeDir, "server"]),
+ CDir = filename:join([NodeDir, "client"]),
+ SC = filename:join([SDir, "cert.pem"]),
+ SK = filename:join([SDir, "key.pem"]),
+ SKC = filename:join([SDir, "keycert.pem"]),
+ SCA = filename:join([CDir, "cacerts.pem"]),
+ CC = filename:join([CDir, "cert.pem"]),
+ CK = filename:join([CDir, "key.pem"]),
+ CKC = filename:join([CDir, "keycert.pem"]),
+ CCA = filename:join([SDir, "cacerts.pem"]),
+
+ DistOpts = case proplists:get_value(many_verify_opts, Config, false) of
+ false ->
+ "-proto_dist inet_tls "
+ ++ "-ssl_dist_opt server_certfile " ++ SKC ++ " "
+ ++ "-ssl_dist_opt client_certfile " ++ CKC ++ " ";
+ true ->
+ case os:type() of
+ {win32, _} ->
+ "-proto_dist inet_tls "
+ ++ "-ssl_dist_opt server_certfile " ++ SKC ++ " "
+ ++ "-ssl_dist_opt server_cacertfile " ++ SCA ++ " "
+ ++ "-ssl_dist_opt server_verify verify_peer "
+ ++ "-ssl_dist_opt server_fail_if_no_peer_cert true "
+ ++ "-ssl_dist_opt server_ciphers DHE-RSA-AES256-SHA\:DHE-RSA-AES128-SHA "
+ ++ "-ssl_dist_opt server_dhfile " ++ Dhfile ++ " "
+ ++ "-ssl_dist_opt client_certfile " ++ CKC ++ " "
+ ++ "-ssl_dist_opt client_cacertfile " ++ CCA ++ " "
+ ++ "-ssl_dist_opt client_verify verify_peer "
+ ++ "-ssl_dist_opt client_ciphers DHE-RSA-AES256-SHA\:DHE-RSA-AES128-SHA ";
+ _ ->
+ "-proto_dist inet_tls "
+ ++ "-ssl_dist_opt server_certfile " ++ SC ++ " "
+ ++ "-ssl_dist_opt server_keyfile " ++ SK ++ " "
+ ++ "-ssl_dist_opt server_cacertfile " ++ SCA ++ " "
+ ++ "-ssl_dist_opt server_verify verify_peer "
+ ++ "-ssl_dist_opt server_fail_if_no_peer_cert true "
+ ++ "-ssl_dist_opt server_ciphers DHE-RSA-AES256-SHA\:DHE-RSA-AES128-SHA "
+ ++ "-ssl_dist_opt server_dhfile " ++ Dhfile ++ " "
+ ++ "-ssl_dist_opt client_certfile " ++ CC ++ " "
+ ++ "-ssl_dist_opt client_keyfile " ++ CK ++ " "
+ ++ "-ssl_dist_opt client_cacertfile " ++ CCA ++ " "
+ ++ "-ssl_dist_opt client_verify verify_peer "
+ ++ "-ssl_dist_opt client_ciphers DHE-RSA-AES256-SHA\:DHE-RSA-AES128-SHA "
+ end
+ end,
+ MoreOpts = proplists:get_value(additional_dist_opts, Config, []),
+ DistOpts ++ MoreOpts.
%%
%% Start scripts etc...
@@ -544,7 +693,7 @@ add_ssl_opts_config(Config) ->
SSL_VSN = vsn(ssl),
VSN_CRYPTO = vsn(crypto),
VSN_PKEY = vsn(public_key),
-
+
SslDir = filename:join([LibDir, "ssl-" ++ SSL_VSN]),
{ok, _} = file:read_file_info(SslDir),
%% We are using an installed otp system, create the boot script.
diff --git a/lib/ssl/test/ssl_dist_SUITE_data/dHParam.pem b/lib/ssl/test/ssl_dist_SUITE_data/dHParam.pem
new file mode 100644
index 0000000000..feb581da30
--- /dev/null
+++ b/lib/ssl/test/ssl_dist_SUITE_data/dHParam.pem
@@ -0,0 +1,5 @@
+-----BEGIN DH PARAMETERS-----
+MIGHAoGBAMY5VmCZ22ZEy/KO8kjt94PH7ZtSG0Z0zitlMlvd4VsNkDzXsVeu+wkH
+FGDC3h3vgv6iwXGCbmrSOVk/FPZbzLhwZ8aLnkUFOBbOvVvb1JptQwOt8mf+eScG
+M2gGBktheQV5Nf1IrzOctG7VGt+neiqb/Y86uYCcDdL+M8++0qnLAgEC
+-----END DH PARAMETERS-----
diff --git a/lib/ssl/test/ssl_handshake_SUITE.erl b/lib/ssl/test/ssl_handshake_SUITE.erl
new file mode 100644
index 0000000000..08c23b2d47
--- /dev/null
+++ b/lib/ssl/test/ssl_handshake_SUITE.erl
@@ -0,0 +1,67 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(ssl_handshake_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include("ssl_internal.hrl").
+-include("ssl_handshake.hrl").
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() -> [
+ decode_hello_handshake,
+ decode_single_hello_extension_correctly,
+ decode_unknown_hello_extension_correctly].
+
+decode_hello_handshake(_Config) ->
+ HelloPacket = <<16#02, 16#00, 16#00,
+ 16#44, 16#03, 16#03, 16#4e, 16#7f, 16#c1, 16#03, 16#35,
+ 16#c2, 16#07, 16#b9, 16#4a, 16#58, 16#af, 16#34, 16#07,
+ 16#a6, 16#7e, 16#ef, 16#52, 16#cb, 16#e0, 16#ea, 16#b7,
+ 16#aa, 16#47, 16#c8, 16#c2, 16#2c, 16#66, 16#fa, 16#f8,
+ 16#09, 16#42, 16#cf, 16#00, 16#c0, 16#30, 16#00, 16#00,
+ 16#1c,
+ 16#00, 16#0b, 16#00, 16#04, 16#03, 16#00, 16#01, 16#02, % ec_point_formats
+ 16#ff, 16#01, 16#00, 16#01, 16#00, %% renegotiate
+ 16#00, 16#23,
+ 16#00, 16#00, 16#33, 16#74, 16#00, 16#07, 16#06, 16#73,
+ 16#70, 16#64, 16#79, 16#2f, 16#32>>,
+
+ {Records, _Buffer} = ssl_handshake:get_tls_handshake(HelloPacket, <<>>),
+
+ {Hello, _Data} = hd(Records),
+ #renegotiation_info{renegotiated_connection = <<0>>} = Hello#server_hello.renegotiation_info.
+
+decode_single_hello_extension_correctly(_Config) ->
+ Renegotiation = <<?UINT16(?RENEGOTIATION_EXT), ?UINT16(1), 0>>,
+ Extensions = ssl_handshake:dec_hello_extensions(Renegotiation, []),
+ [{renegotiation_info,#renegotiation_info{renegotiated_connection = <<0>>}}] = Extensions.
+
+
+decode_unknown_hello_extension_correctly(_Config) ->
+ FourByteUnknown = <<16#CA,16#FE, ?UINT16(4), 3, 0, 1, 2>>,
+ Renegotiation = <<?UINT16(?RENEGOTIATION_EXT), ?UINT16(1), 0>>,
+ Extensions = ssl_handshake:dec_hello_extensions(<<FourByteUnknown/binary, Renegotiation/binary>>, []),
+ [{renegotiation_info,#renegotiation_info{renegotiated_connection = <<0>>}}] = Extensions.
+
diff --git a/lib/ssl/test/ssl_packet_SUITE.erl b/lib/ssl/test/ssl_packet_SUITE.erl
index d22d5d2954..9d2599b778 100644
--- a/lib/ssl/test/ssl_packet_SUITE.erl
+++ b/lib/ssl/test/ssl_packet_SUITE.erl
@@ -151,6 +151,9 @@ all() ->
packet_cdr_decode, packet_cdr_decode_list,
packet_http_decode, packet_http_decode_list,
packet_http_bin_decode_multi, packet_http_error_passive,
+ packet_httph_active, packet_httph_bin_active,
+ packet_httph_active_once, packet_httph_bin_active_once,
+ packet_httph_passive, packet_httph_bin_passive,
packet_line_decode, packet_line_decode_list,
packet_asn1_decode, packet_asn1_decode_list,
packet_tpkt_decode, packet_tpkt_decode_list,
@@ -1594,7 +1597,7 @@ client_http_decode(Socket, HttpRequest) ->
%%--------------------------------------------------------------------
packet_http_decode_list(doc) ->
["Test setting the packet option {packet, http}, {mode, list}"
- "(Body will be litst too)"];
+ "(Body will be list too)"];
packet_http_decode_list(suite) ->
[];
packet_http_decode_list(Config) when is_list(Config) ->
@@ -1804,7 +1807,304 @@ server_http_decode_error(Socket, HttpResponse) ->
assert_packet_opt(Socket, http),
ok = ssl:send(Socket, HttpResponse),
ok.
+%%--------------------------------------------------------------------
+packet_httph_active(doc) ->
+ ["Test setting the packet option {packet, httph}"];
+packet_httph_active(suite) ->
+ [];
+packet_httph_active(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Trailer = "Content-Encoding: gzip\r\n"
+ "\r\n",
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, server_send_trailer,
+ [Trailer]}},
+ {options, [{active, true}, binary |
+ ServerOpts]}]),
+
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, client_http_decode_trailer_active,
+ []}},
+ {options, [{active, true},
+ {packet, httph},
+ list |
+ ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+server_send_trailer(Socket, Trailer)->
+ ssl:send(Socket, Trailer),
+ ok.
+
+client_http_decode_trailer_active(Socket) ->
+ receive
+ {ssl, Socket,
+ {http_header,36,'Content-Encoding',undefined,"gzip"}} ->
+ ok;
+ Other1 ->
+ exit({?LINE, Other1})
+ end,
+ receive
+ {ssl, Socket, http_eoh} ->
+ ok;
+ Other2 ->
+ exit({?LINE, Other2})
+ end,
+ ok.
+
+%%--------------------------------------------------------------------
+packet_httph_bin_active(doc) ->
+ ["Test setting the packet option {packet, httph_bin}"];
+packet_httph_bin_active(suite) ->
+ [];
+packet_httph_bin_active(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Trailer = "Content-Encoding: gzip\r\n"
+ "\r\n",
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, server_send_trailer,
+ [Trailer]}},
+ {options, [{active, true}, binary |
+ ServerOpts]}]),
+
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, client_http_decode_trailer_bin_active,
+ []}},
+ {options, [{active, true},
+ {packet, httph_bin},
+ list |
+ ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+client_http_decode_trailer_bin_active(Socket) ->
+ receive
+ {ssl, Socket,
+ {http_header,36,'Content-Encoding',undefined, <<"gzip">>}} ->
+ ok;
+ Other1 ->
+ exit({?LINE, Other1})
+ end,
+ receive
+ {ssl, Socket, http_eoh} ->
+ ok;
+ Other2 ->
+ exit({?LINE, Other2})
+ end,
+ ok.
+%%--------------------------------------------------------------------
+packet_httph_active_once(doc) ->
+ ["Test setting the packet option {packet, httph}"];
+packet_httph_active_once(suite) ->
+ [];
+packet_httph_active_once(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Trailer = "Content-Encoding: gzip\r\n"
+ "\r\n",
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, server_send_trailer,
+ [Trailer]}},
+ {options, [{active, true}, binary |
+ ServerOpts]}]),
+
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, client_http_decode_trailer_active_once,
+ []}},
+ {options, [{active, false},
+ {packet, httph},
+ list |
+ ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+
+client_http_decode_trailer_active_once(Socket) ->
+ ssl:setopts(Socket, [{active, once}]),
+ receive
+ {ssl, Socket,
+ {http_header,36,'Content-Encoding',undefined,"gzip"}} ->
+ ok;
+ Other1 ->
+ exit({?LINE, Other1})
+ end,
+ ssl:setopts(Socket, [{active, once}]),
+ receive
+ {ssl, Socket, http_eoh} ->
+ ok;
+ Other2 ->
+ exit({?LINE, Other2})
+ end,
+ ok.
+%%--------------------------------------------------------------------
+packet_httph_bin_active_once(doc) ->
+ ["Test setting the packet option {packet, httph_bin}"];
+packet_httph_bin_active_once(suite) ->
+ [];
+packet_httph_bin_active_once(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Trailer = "Content-Encoding: gzip\r\n"
+ "\r\n",
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, server_send_trailer,
+ [Trailer]}},
+ {options, [{active, true}, binary |
+ ServerOpts]}]),
+
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, client_http_decode_trailer_bin_active_once,
+ []}},
+ {options, [{active, false},
+ {packet, httph_bin},
+ list |
+ ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+client_http_decode_trailer_bin_active_once(Socket) ->
+ ssl:setopts(Socket, [{active, once}]),
+ receive
+ {ssl, Socket,
+ {http_header,36,'Content-Encoding',undefined, <<"gzip">>}} ->
+ ok;
+ Other1 ->
+ exit({?LINE, Other1})
+ end,
+ ssl:setopts(Socket, [{active, once}]),
+ receive
+ {ssl, Socket, http_eoh} ->
+ ok;
+ Other2 ->
+ exit({?LINE, Other2})
+ end,
+ ok.
+
+%%--------------------------------------------------------------------
+
+packet_httph_passive(doc) ->
+ ["Test setting the packet option {packet, httph}"];
+packet_httph_passive(suite) ->
+ [];
+packet_httph_passive(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Trailer = "Content-Encoding: gzip\r\n"
+ "\r\n",
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, server_send_trailer,
+ [Trailer]}},
+ {options, [{active, true}, binary |
+ ServerOpts]}]),
+
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, client_http_decode_trailer_passive,
+ []}},
+ {options, [{active, false},
+ {packet, httph},
+ list |
+ ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+client_http_decode_trailer_passive(Socket) ->
+ {ok,{http_header,36,'Content-Encoding',undefined,"gzip"}} = ssl:recv(Socket, 0),
+ {ok, http_eoh} = ssl:recv(Socket, 0),
+ ok.
+
+%%--------------------------------------------------------------------
+packet_httph_bin_passive(doc) ->
+ ["Test setting the packet option {packet, httph_bin}"];
+packet_httph_bin_passive(suite) ->
+ [];
+packet_httph_bin_passive(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Trailer = "Content-Encoding: gzip\r\n"
+ "\r\n",
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, server_send_trailer,
+ [Trailer]}},
+ {options, [{active, true}, binary |
+ ServerOpts]}]),
+
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, client_http_decode_trailer_bin_passive,
+ []}},
+ {options, [{active, false},
+ {packet, httph_bin},
+ list |
+ ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+client_http_decode_trailer_bin_passive(Socket) ->
+ {ok,{http_header,36,'Content-Encoding',undefined,<<"gzip">>}} = ssl:recv(Socket, 0),
+ {ok, http_eoh} = ssl:recv(Socket, 0),
+ ok.
%%--------------------------------------------------------------------
packet_line_decode(doc) ->
diff --git a/lib/ssl/test/ssl_session_cache_SUITE.erl b/lib/ssl/test/ssl_session_cache_SUITE.erl
index 62d404092f..8cdfdec2ce 100644
--- a/lib/ssl/test/ssl_session_cache_SUITE.erl
+++ b/lib/ssl/test/ssl_session_cache_SUITE.erl
@@ -26,6 +26,7 @@
-include_lib("common_test/include/ct.hrl").
+-define(DELAY, 500).
-define(SLEEP, 500).
-define(TIMEOUT, 60000).
-define(LONG_TIMEOUT, 600000).
@@ -102,7 +103,7 @@ init_per_testcase(session_cleanup, Config0) ->
ssl:stop(),
application:load(ssl),
application:set_env(ssl, session_lifetime, 5),
- application:set_env(ssl, session_delay_cleanup_time, ?SLEEP),
+ application:set_env(ssl, session_delay_cleanup_time, ?DELAY),
ssl:start(),
[{watchdog, Dog} | Config];
@@ -178,7 +179,7 @@ end_per_group(_GroupName, Config) ->
%%--------------------------------------------------------------------
session_cleanup(doc) ->
["Test that sessions are cleand up eventually, so that the session table "
- "does grow and grow ..."];
+ "does not grow and grow ..."];
session_cleanup(suite) ->
[];
session_cleanup(Config)when is_list(Config) ->
@@ -207,24 +208,62 @@ session_cleanup(Config)when is_list(Config) ->
%% Make sure session is registered
test_server:sleep(?SLEEP),
+ {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
+ [_, _,_, _, Prop] = StatusInfo,
+ State = state(Prop),
+ Cache = element(2, State),
+ SessionTimer = element(6, State),
+
Id = proplists:get_value(session_id, SessionInfo),
- CSession = ssl_session_cache:lookup(ssl_otp_session_cache, {{Hostname, Port}, Id}),
- SSession = ssl_session_cache:lookup(ssl_otp_session_cache, {Port, Id}),
+ CSession = ssl_session_cache:lookup(Cache, {{Hostname, Port}, Id}),
+ SSession = ssl_session_cache:lookup(Cache, {Port, Id}),
true = CSession =/= undefined,
true = SSession =/= undefined,
%% Make sure session has expired and been cleaned up
- test_server:sleep(5000), %% Expire time
- test_server:sleep(?SLEEP *4), %% Clean up delay
+ check_timer(SessionTimer),
+ test_server:sleep(?DELAY *2), %% Delay time + some extra time
+
+ DelayTimer = get_delay_timer(),
+
+ check_timer(DelayTimer),
- undefined = ssl_session_cache:lookup(ssl_otp_session_cache, {{Hostname, Port}, Id}),
- undefined = ssl_session_cache:lookup(ssl_otp_session_cache, {Port, Id}),
+ test_server:sleep(?SLEEP), %% Make sure clean has had time to run
+
+ undefined = ssl_session_cache:lookup(Cache, {{Hostname, Port}, Id}),
+ undefined = ssl_session_cache:lookup(Cache, {Port, Id}),
process_flag(trap_exit, false),
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
+state([{data,[{"State", State}]} | _]) ->
+ State;
+state([_ | Rest]) ->
+ state(Rest).
+
+check_timer(Timer) ->
+ case erlang:read_timer(Timer) of
+ false ->
+ {status, _, _, _} = sys:get_status(whereis(ssl_manager)),
+ ok;
+ Int ->
+ test_server:sleep(Int),
+ check_timer(Timer)
+ end.
+
+get_delay_timer() ->
+ {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
+ [_, _,_, _, Prop] = StatusInfo,
+ State = state(Prop),
+ case element(7, State) of
+ undefined ->
+ test_server:sleep(?SLEEP),
+ get_delay_timer();
+ DelayTimer ->
+ DelayTimer
+ end.
%%--------------------------------------------------------------------
session_cache_process_list(doc) ->
["Test reuse of sessions (short handshake)"];
@@ -242,7 +281,6 @@ session_cache_process_mnesia(suite) ->
session_cache_process_mnesia(Config) when is_list(Config) ->
session_cache_process(mnesia,Config).
-
%%--------------------------------------------------------------------
%%% Session cache API callbacks
%%--------------------------------------------------------------------
diff --git a/lib/ssl/test/ssl_test_MACHINE.erl b/lib/ssl/test/ssl_test_MACHINE.erl
deleted file mode 100644
index e0ffa15d80..0000000000
--- a/lib/ssl/test/ssl_test_MACHINE.erl
+++ /dev/null
@@ -1,940 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
--module(ssl_test_MACHINE).
-
--export([many_conns/0, mk_ssl_cert_opts/1, test_one_listener/7,
- test_server_only/6]).
-
--export([process_init/3, do_start/1]).
-
-
--include("test_server.hrl").
--include("ssl_test_MACHINE.hrl").
-
--define(WAIT_TIMEOUT, 10000).
--define(CLOSE_WAIT, 1000).
-
-%%
-%% many_conns() -> ManyConnections
-%%
-%% Choose a suitable number of "many connections" depending on platform
-%% and current limit for file descriptors.
-%%
-many_conns() ->
- case os:type() of
- {unix,_} -> many_conns_1();
- _ -> 10
- end.
-
-many_conns_1() ->
- N0 = os:cmd("ulimit -n"),
- N1 = lists:reverse(N0),
- N2 = lists:dropwhile(fun($\r) -> true;
- ($\n) -> true;
- (_) -> false
- end, N1),
- N = list_to_integer(lists:reverse(N2)),
- lists:min([(N - 10) div 2, 501]).
-
-%%
-%% mk_ssl_cert_opts(Config) -> {ok, {COpts, SOpts}}
-%%
-%%
-mk_ssl_cert_opts(_Config) ->
- Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]),
- COpts = [{ssl_imp, old},
- {cacertfile, filename:join([Dir, "client", "cacerts.pem"])},
- {certfile, filename:join([Dir, "client", "cert.pem"])},
- {keyfile, filename:join([Dir, "client", "key.pem"])}],
- SOpts = [{ssl_imp, old},
- {cacertfile, filename:join([Dir, "server", "cacerts.pem"])},
- {certfile, filename:join([Dir, "server", "cert.pem"])},
- {keyfile, filename:join([Dir, "server", "key.pem"])}],
- {ok, {COpts, SOpts}}.
-
-%%
-%% Cmds:
-%% {protomod, gen_tcp | ssl} default = ssl
-%% {serialize_accept, true | false} default = false
-%% {timeout, Timeout}
-%% {sockopts, Opts}
-%% {sslopts, Opts}
-%% {protocols, Protocols} [sslv2|sslv3|tlsv1]
-%% {listen, Port}
-%% {lsock, LSock} listen socket for acceptor
-%% peercert
-%% accept
-%% {connect, {Host, Port}}
-%% {recv, N}
-%% {send, N}
-%% {echo, N} async echo back
-%% close close connection socket
-%% {close, Time} wait time and then close socket
-%% lclose close listen socket
-%% await_close wait for close
-%% wait_sync listener's wait for sync from parent
-%% connection_info
-%% {exit, Reason} exit
-%%
-%%
-%% We cannot have more than `backlog' acceptors at the same time.
-%%
-
-
-%%
-%% test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, Suite, Config)
-%%
-%% Creates one client and one server node, and runs one listener on
-%% the server node (according to LCmds), and creates NConns acceptors
-%% on the server node, and the same number of connectors on the client
-%% node. The acceptors and and connectors execute according to ACmds
-%% and CCmds, respectively.
-%%
-%% It is a good idea to have the backlog size in LCmds set to
-%% be at least as large as NConns.
-%%
-test_one_listener(NConns, LCmds0, ACmds0, CCmds0, Timeout, Suite, Config) ->
- ProtoMod = get_protomod(Config),
- SerializeAccept = get_serialize_accept(Config),
- ?line {ok, {CNode, SNode}} = start_client_server_nodes(Suite),
- case ProtoMod of
- ssl ->
- ?line ok = start_ssl([CNode, SNode], Config);
- gen_tcp ->
- ok
- end,
- LCmds = [{protomod, ProtoMod}| LCmds0],
- ACmds = [{protomod, ProtoMod}, {serialize_accept, SerializeAccept}|
- ACmds0],
- CCmds = [{protomod, ProtoMod}| CCmds0],
-
- ?line {ok, Listener} = start_process(SNode, self(), LCmds, listener),
- ?line {ok, LSock} = wait_lsock(Listener, ?WAIT_TIMEOUT),
- ?line {ok, Accs0} = start_processes(NConns, SNode, self(),
- [{lsock, LSock}| ACmds], acceptor),
- Accs = case ProtoMod of
- gen_tcp ->
- [Acc1| Accs1] = Accs0,
- Acc1 ! {continue_accept, self()},
- Accs1;
- ssl ->
- Accs0
- end,
- ?line {ok, Conns} = start_processes(NConns, CNode, self(),
- CCmds, connector),
- ?line case wait_ack(Accs, Accs0 ++ Conns, Timeout) of
- ok ->
- ?line sync([Listener]),
- ?line wait_ack([], [Listener], ?WAIT_TIMEOUT);
- {error, Reason} ->
- ?line stop_node(SNode),
- ?line stop_node(CNode),
- exit(Reason)
- end,
- ?line stop_node(SNode),
- ?line stop_node(CNode),
- ok.
-
-%%
-%% test_server_only(NConns, LCmds, ACmds, Timeout, Suite, Config)
-%%
-%% Creates only one server node, and runs one listener on
-%% the server node (according to LCmds), and creates NConns acceptors
-%% on the server node. The acceptors execute according to ACmds.
-%% There are no connectors.
-%%
-test_server_only(NConns, LCmds0, ACmds0, Timeout, Suite, Config) ->
- ProtoMod = get_protomod(Config),
- ?line {ok, SNode} = start_server_node(Suite),
- case ProtoMod of
- ssl ->
- ?line ok = start_ssl([SNode], Config);
- gen_tcp ->
- ok
- end,
- LCmds = [{protomod, ProtoMod}| LCmds0],
- ACmds = [{protomod, ProtoMod}| ACmds0],
- ?line {ok, Listener} = start_process(SNode, self(), LCmds, listener),
- ?line {ok, LSock} = wait_lsock(Listener, ?WAIT_TIMEOUT),
- ?line {ok, Accs0} = start_processes(NConns, SNode, self(),
- [{lsock, LSock}| ACmds], acceptor),
- Accs = case ProtoMod of
- gen_tcp ->
- [Acc1| Accs1] = Accs0,
- Acc1 ! {continue_accept, self()},
- Accs1;
- ssl ->
- Accs0
- end,
- ?line case wait_ack(Accs, Accs0, Timeout) of
- ok ->
- ?line sync([Listener]),
- ?line wait_ack([], [Listener], ?WAIT_TIMEOUT);
- {error, Reason} ->
- ?line stop_node(SNode),
- exit(Reason)
- end,
- ?line stop_node(SNode),
- ok.
-
-%%
-%% start_client_server_nodes(Suite) -> {ok, {CNode, SNode}}
-%%
-start_client_server_nodes(Suite) ->
- {ok, CNode} = start_client_node(Suite),
- {ok, SNode} = start_server_node(Suite),
- {ok, {CNode, SNode}}.
-
-start_client_node(Suite) ->
- start_node(lists:concat([Suite, "_client"])).
-
-start_server_node(Suite) ->
- start_node(lists:concat([Suite, "_server"])).
-
-%%
-%% start_ssl(Nodes, Config)
-%%
-start_ssl(Nodes, Config) ->
- Env0 = lists:flatten([Env00 || {env, Env00} <- Config]),
- Env1 = case os:getenv("SSL_DEBUG") of
- false ->
- [];
- _ ->
- Dir = ?config(priv_dir, Config),
- [{debug, true}, {debugdir, Dir}]
- end,
- Env = Env0 ++ Env1,
- lists:foreach(
- fun(Node) -> rpc:call(Node, ?MODULE, do_start, [Env]) end, Nodes),
- ok.
-
-do_start(Env) ->
- application:start(crypto),
- application:start(public_key),
- application:load(ssl),
- lists:foreach(
- fun({Par, Val}) -> application:set_env(ssl, Par, Val) end, Env),
- application:start(ssl).
-
-
-%%
-%% start_node(Name) -> {ok, Node}
-%% start_node(Name, ExtraParams) -> {ok, Node}
-%%
-start_node(Name) ->
- start_node(Name, []).
-start_node(Name, ExtraParams) ->
- Params = "-pa " ++ filename:dirname(code:which(?MODULE)) ++ " " ++
- ExtraParams,
- test_server:start_node(Name, slave, [{args, Params}]).
-
-stop_node(Node) ->
- test_server:stop_node(Node).
-
-%%
-%% start_processes(N, Node, Parent, Cmds, Type) -> {ok, Pids}
-%%
-start_processes(M, Node, Parent, Cmds, Type) ->
- start_processes1(0, M, Node, Parent, Cmds, Type, []).
-start_processes1(M, M, _, _, _, _, Pids) ->
- {ok, lists:reverse(Pids)};
-start_processes1(N, M, Node, Parent, Cmds, Type, Pids) ->
- {ok, Pid} = start_process(Node, Parent, Cmds, {Type, N + 1}),
- start_processes1(N + 1, M, Node, Parent, Cmds, Type, [Pid| Pids]).
-
-%%
-%% start_process(Node, Parent, Cmds, Type) -> {ok, Pid}
-%%
-start_process(Node, Parent, Cmds0, Type) ->
- Cmds = case os:type() of
- {win32, _} ->
- lists:map(fun(close) -> {close, ?CLOSE_WAIT};
- (Term) -> Term end, Cmds0);
- _ ->
- Cmds0
- end,
- Pid = spawn_link(Node, ?MODULE, process_init, [Parent, Cmds, Type]),
- {ok, Pid}.
-
-process_init(Parent, Cmds, Type) ->
- ?debug("#### ~w start~n", [{Type, self()}]),
- pre_main_loop(Cmds, #st{parent = Parent, type = Type}).
-
-%%
-%% pre_main_loop
-%%
-pre_main_loop([], St) ->
- ?debug("#### ~w end~n", [{St#st.type, self()}]),
- main_loop([], St);
-pre_main_loop(Cmds, St) ->
- ?debug("#### ~w -> ~w~n",
- [{St#st.type, self(), St#st.sock, St#st.port,
- St#st.peer, St#st.active}, hd(Cmds)]),
- main_loop(Cmds, St).
-
-%%
-%% main_loop(Cmds, St)
-%%
-main_loop([{protomod, ProtoMod}| Cmds], St) ->
- pre_main_loop(Cmds, St#st{protomod = ProtoMod});
-
-main_loop([{serialize_accept, Bool}| Cmds], St) ->
- pre_main_loop(Cmds, St#st{serialize_accept = Bool});
-
-main_loop([{sockopts, Opts}| Cmds], St) ->
- pre_main_loop(Cmds, St#st{sockopts = Opts});
-
-main_loop([{sslopts, Opts}| Cmds], St) ->
- pre_main_loop(Cmds, St#st{sslopts = Opts});
-
-main_loop([{protocols, Protocols}| Cmds], St) ->
- pre_main_loop(Cmds, St#st{protocols = Protocols});
-
-main_loop([{timeout, T}| Cmds], St) ->
- pre_main_loop(Cmds, St#st{timeout = T});
-
-main_loop([{lsock, LSock}| Cmds], St) ->
- pre_main_loop(Cmds, St#st{lsock = LSock});
-
-main_loop([{seed, Data}| Cmds], St) ->
- case ssl:seed("tjosan") of
- ok ->
- pre_main_loop(Cmds, St);
- {error, Reason} ->
- ?error("#### ~w(~w) in seed: error: ~w~n",
- [St#st.type, self(), Reason]),
- exit(Reason)
- end;
-
-main_loop([{listen, Port}| Cmds], St) ->
- case listen(St, Port) of
- {ok, LSock} ->
- ack_lsock(St#st.parent, LSock),
- NSt = get_active(St#st{port = Port, sock = LSock, lsock = LSock}),
- pre_main_loop(Cmds, St);
- {error, Reason} ->
- ?error("#### ~w(~w) in listen: error: ~w~n",
- [St#st.type, self(), Reason]),
- exit(Reason)
- end;
-
-main_loop([accept| Cmds], St) ->
- case St#st.serialize_accept of
- true ->
- Parent = St#st.parent,
- receive
- {continue_accept, Parent} ->
- ok
- end;
- false ->
- ok
- end,
- case accept(St) of
- {ok, Sock, Port, Peer} ->
- case St#st.serialize_accept of
- true ->
- St#st.parent ! {one_accept_done, self()};
- false ->
- ok
- end,
- NSt = get_active(St#st{sock = Sock, port = Port, peer = Peer}),
- pre_main_loop(Cmds, NSt);
- {error, Reason} ->
- ?error("#### ~w(~w) in accept: error: ~w~n",
- [St#st.type, self(), Reason]),
- exit(Reason)
- end;
-
-main_loop([accept_timeout| Cmds], St) ->
- case accept(St) of
- {error, timeout} ->
- pre_main_loop(Cmds, St);
- {error, Reason} ->
- ?error("#### ~w(~w) in accept_timeout: error: ~w~n",
- [St#st.type, self(), Reason]),
- exit(Reason)
- end;
-
-
-main_loop([{connect, {Host, Port}}| Cmds], St) ->
- case connect(St, Host, Port) of
- {ok, Sock, LPort, Peer} ->
- NSt = get_active(St#st{sock = Sock, port = LPort, peer = Peer}),
- pre_main_loop(Cmds, NSt);
- {error, Reason} ->
- ?error("#### ~w(~w) in connect: error: ~w~n",
- [St#st.type, self(), Reason]),
- exit(Reason)
- end;
-
-main_loop([connection_info| Cmds], St) ->
- case connection_info(St) of
- {ok, ProtoInfo} ->
- io:fwrite("Got connection_info:~n~p~n", [ProtoInfo]),
- pre_main_loop(Cmds, St);
- {error, Reason} ->
- ?error("#### ~w(~w) in connection_info: error: ~w~n",
- [St#st.type, self(), Reason]),
- exit(Reason)
- end;
-
-main_loop([peercert| Cmds], St) ->
- case peercert(St) of
- {ok, Cert} ->
- io:fwrite("Got cert:~n~p~n", [Cert]),
- pre_main_loop(Cmds, St);
- {error, Reason} ->
- ?error("#### ~w(~w) in peercert: error: ~w~n",
- [St#st.type, self(), Reason]),
- exit(Reason)
- end;
-
-main_loop([nopeercert| Cmds], St) ->
- case peercert(St) of
- {error, Reason} ->
- io:fwrite("Got no cert as expected. reason:~n~p~n", [Reason]),
- pre_main_loop(Cmds, St);
- {ok, Cert} ->
- ?error("#### ~w(~w) in peercert: error: got cert: ~p~n",
- [St#st.type, self(), Cert]),
- exit(peercert)
- end;
-
-main_loop([{recv, N}| Cmds], St) ->
- recv_loop([{recv, N}| Cmds], fun recv/1, St); % Returns to main_loop/2.
-
-main_loop([{send, N}| Cmds], St) ->
- Msg = mk_msg(N),
- case send(St, Msg) of
- ok ->
- pre_main_loop(Cmds, St);
- {error, Reason} ->
- ?error("#### ~w(~w) in send: error: ~w~n",
- [St#st.type, self(), Reason]),
- exit(Reason)
- end;
-
-main_loop([{echo, N}| Cmds], St) ->
- recv_loop([{echo, N}| Cmds], fun echo/1, St); % Returns to main_loop/2.
-
-main_loop([{close, WaitTime}| Cmds], St) ->
- wait(WaitTime),
- pre_main_loop([close| Cmds], St);
-
-main_loop([close| Cmds], St) ->
- case close(St) of
- ok ->
- pre_main_loop(Cmds, St#st{sock = nil});
- {error, Reason} ->
- ?error("#### ~w(~w) in close: error: ~w~n",
- [St#st.type, self(), Reason]),
- exit(Reason)
- end;
-
-main_loop([lclose| Cmds], St) ->
- case lclose(St) of
- ok ->
- pre_main_loop(Cmds, St#st{lsock = nil});
- {error, Reason} ->
- ?error("#### ~w(~w) in lclose: error: ~w~n",
- [St#st.type, self(), Reason]),
- exit(Reason)
- end;
-
-main_loop([await_close| Cmds], St) ->
- case await_close(St) of
- ok ->
- pre_main_loop(Cmds, St#st{sock = nil});
- {error, Reason} ->
- ?error("#### ~w(~w) in await_close: error: ~w~n",
- [St#st.type, self(), Reason]),
- exit(Reason)
- end;
-
-main_loop([wait_sync| Cmds], St) ->
- wait_sync(St),
- pre_main_loop(Cmds, St);
-
-main_loop({exit, Reason}, _St) ->
- exit(Reason);
-
-main_loop([], _St) ->
- ok.
-
-%%
-%% recv_loop(Cmds, F, St)
-%%
-%% F = recv/1 | echo/1
-%%
-recv_loop([{_Tag, 0}| Cmds], _, St) ->
- pre_main_loop(Cmds, St);
-recv_loop([{_Tag, N}| _Cmds], _, St) when N < 0 ->
- ?error("#### ~w(~w) in recv_loop: error: too much: ~w~n",
- [St#st.type, self(), N]),
- exit(toomuch); % XXX or {error, Reason}?
-recv_loop([{Tag, N}| Cmds], F, St) ->
- case F(St) of
- {ok, Len} ->
- NSt = St#st{active = new_active(St#st.active)},
- if
- Len == N ->
- pre_main_loop(Cmds, NSt);
- true ->
- ?debug("#### ~w -> ~w~n",
- [{NSt#st.type, self(), NSt#st.sock, NSt#st.port,
- NSt#st.peer, NSt#st.active}, {Tag, N - Len}]),
- recv_loop([{Tag, N - Len}| Cmds], F, NSt)
- end;
- {error, Reason} ->
- ?error("#### ~w(~w) in recv_loop: error: ~w, ~w bytes remain~n",
- [St#st.type, self(), Reason, N]),
- exit(Reason)
- end.
-
-new_active(once) ->
- false;
-new_active(A) ->
- A.
-
-get_active(St) ->
- A = case proplists:get_value(active, St#st.sockopts, undefined) of
- undefined ->
- Mod = case St#st.protomod of
- ssl ->
- ssl;
- gen_tcp ->
- inet
- end,
- {ok, [{active, Ax}]} = Mod:getopts(St#st.sock, [active]),
- Ax;
- Ay ->
- Ay
- end,
- ?debug("#### ~w(~w) get_active: ~p\n", [St#st.type, self(), A]),
- St#st{active = A}.
-
-
-%%
-%% SOCKET FUNCTIONS
-%%
-
-%%
-%% ssl
-%%
-
-%%
-%% listen(St, LPort) -> {ok, LSock} | {error, Reason}
-%%
-listen(St, LPort) ->
- case St#st.protomod of
- ssl ->
- ssl:listen(LPort, [{ssl_imp, old} | St#st.sockopts ++ St#st.sslopts]);
- gen_tcp ->
- gen_tcp:listen(LPort, St#st.sockopts)
- end.
-
-%%
-%% accept(St) -> {ok, Sock} | {error, Reason}
-%%
-accept(St) ->
- case St#st.protomod of
- ssl ->
- case ssl:transport_accept(St#st.lsock, St#st.timeout) of
- {ok, Sock} ->
- case ssl:ssl_accept(Sock, St#st.timeout) of
- ok ->
- {ok, Port} = ssl:sockname(Sock),
- {ok, Peer} = ssl:peername(Sock),
- {ok, Sock, Port, Peer};
- Other ->
- Other
- end;
- Other ->
- Other
- end;
- gen_tcp ->
- case gen_tcp:accept(St#st.lsock, St#st.timeout) of
- {ok, Sock} ->
- {ok, Port} = inet:port(Sock),
- {ok, Peer} = inet:peername(Sock),
- {ok, Sock, Port, Peer};
- Other ->
- Other
- end
- end.
-
-%%
-%% connect(St, Host, Port) -> {ok, Sock} | {error, Reason}
-%%
-connect(St, Host, Port) ->
-
- case St#st.protomod of
- ssl ->
- case ssl:connect(Host, Port,
- [{ssl_imp, old} | St#st.sockopts ++ St#st.sslopts],
- St#st.timeout) of
- {ok, Sock} ->
- {ok, LPort} = ssl:sockname(Sock),
- {ok, Peer} = ssl:peername(Sock),
- {ok, Sock, LPort, Peer};
- Other ->
- Other
- end;
- gen_tcp ->
- case gen_tcp:connect(Host, Port, St#st.sockopts, St#st.timeout) of
- {ok, Sock} ->
- {ok, LPort} = inet:port(Sock),
- {ok, Peer} = inet:peername(Sock),
- {ok, Sock, LPort, Peer};
- Other ->
- Other
- end
- end.
-
-%%
-%% peercert(St) -> {ok, Cert} | {error, Reason}
-%%
-peercert(St) ->
- case St#st.protomod of
- ssl ->
- ssl:peercert(St#st.sock, [ssl]);
- gen_tcp ->
- {ok, <<>>}
- end.
-
-%%
-%% connection_info(St) -> {ok, ProtoInfo} | {error, Reason}
-%%
-connection_info(St) ->
- case St#st.protomod of
- ssl ->
- case ssl:connection_info(St#st.sock) of
- Res = {ok, {Proto, _}} ->
- case St#st.protocols of
- [] ->
- Res;
- Protocols ->
- case lists:member(Proto, Protocols) of
- true ->
- Res;
- false ->
- {error, Proto}
- end
- end;
- Error ->
- Error
- end;
- gen_tcp ->
- {ok, <<>>}
- end.
-
-%%
-%% close(St) -> ok | {error, Reason}
-%%
-
-close(St) ->
- Mod = St#st.protomod,
- case St#st.sock of
- nil ->
- ok;
- _ ->
- Mod:close(St#st.sock)
- end.
-
-%%
-%% lclose(St) -> ok | {error, Reason}
-%%
-lclose(St) ->
- Mod = St#st.protomod,
- case St#st.lsock of
- nil ->
- ok;
- _ ->
- Mod:close(St#st.lsock)
- end.
-
-%%
-%% recv(St) = {ok, Len} | {error, Reason}
-%%
-recv(St) ->
- case do_recv(St) of
- {ok, Msg} ->
- {ok, length(Msg)};
- {error, Reason} ->
- {error, Reason}
- end.
-
-do_recv(St) when St#st.active == false ->
- %% First check that we do *not* have any ssl/gen_tcp messages in the
- %% message queue, then call the receive function.
- Sock = St#st.sock,
- case St#st.protomod of
- ssl ->
- receive
- M = {ssl, Sock, _Msg} ->
- {error, {unexpected_messagex, M}};
- M = {ssl_closed, Sock} ->
- {error, {unexpected_message, M}};
- M = {ssl_error, Sock, _Reason} ->
- {error, {unexpected_message, M}}
- after 0 ->
- ssl:recv(St#st.sock, 0, St#st.timeout)
- end;
- gen_tcp ->
- receive
- M = {tcp, Sock, _Msg} ->
- {error, {unexpected_message, M}};
- M = {tcp_closed, Sock} ->
- {error, {unexpected_message, M}};
- M = {tcp_error, Sock, _Reason} ->
- {error, {unexpected_message, M}}
- after 0 ->
- gen_tcp:recv(St#st.sock, 0, St#st.timeout)
- end
- end;
-do_recv(St) ->
- Sock = St#st.sock,
- Timeout = St#st.timeout,
- case St#st.protomod of
- ssl ->
- receive
- {ssl, Sock, Msg} ->
- {ok, Msg};
- {ssl_closed, Sock} ->
- {error, closed};
- {ssl_error, Sock, Reason} ->
- {error, Reason}
- after Timeout ->
- {error, timeout}
- end;
- gen_tcp ->
- receive
- {tcp, Sock, Msg} ->
- {ok, Msg};
- {tcp_closed, Sock} ->
- {error, closed};
- {tcp_error, Sock, Reason} ->
- {error, Reason}
- after Timeout ->
- {error, timeout}
- end
- end.
-
-%%
-%% echo(St) = {ok, Len} | {error, Reason}
-%%
-echo(St) ->
- Sock = St#st.sock,
- case do_recv(St) of
- {ok, Msg} ->
- Mod = St#st.protomod,
- case Mod:send(Sock, Msg) of
- ok ->
- {ok, length(Msg)};
- {error, Reason} ->
- {error, Reason}
- end;
- {error, Reason} ->
- {error, Reason}
- end.
-
-%%
-%% send(St, Msg) -> ok | {error, Reason}
-%%
-send(St, Msg) ->
- Mod = St#st.protomod,
- Mod:send(St#st.sock, Msg).
-
-%%
-%% await_close(St) -> ok | {error, Reason}
-%%
-await_close(St) when St#st.active == false ->
- %% First check that we do *not* have any ssl/gen_tcp messages in the
- %% message queue, then call the receive function.
- Sock = St#st.sock,
- Res = case St#st.protomod of
- ssl ->
- receive
- M = {ssl, Sock, _Msg0} ->
- {error, {unexpected_message, M}};
- M = {ssl_closed, Sock} ->
- {error, {unexpected_message, M}};
- M = {ssl_error, Sock, _Reason} ->
- {error, {unexpected_message, M}}
- after 0 ->
- ok
- end;
- gen_tcp ->
- receive
- M = {tcp, Sock, _Msg0} ->
- {error, {unexpected_message, M}};
- M = {tcp_closed, Sock} ->
- {error, {unexpected_message, M}};
- M = {tcp_error, Sock, _Reason} ->
- {error, {unexpected_message, M}}
- after 0 ->
- ok
- end
- end,
- case Res of
- ok ->
- Mod = St#st.protomod,
- case Mod:recv(St#st.sock, 0, St#st.timeout) of
- {ok, _Msg} ->
- {error, toomuch};
- {error, _} ->
- ok
- end;
- _ ->
- Res
- end;
-await_close(St) ->
- Sock = St#st.sock,
- Timeout = St#st.timeout,
- case St#st.protomod of
- ssl ->
- receive
- {ssl, Sock, _Msg} ->
- {error, toomuch};
- {ssl_closed, Sock} ->
- ok;
- {ssl_error, Sock, Reason} ->
- {error, Reason}
- after Timeout ->
- {error, timeout}
- end;
- gen_tcp ->
- receive
- {tcp, Sock, _Msg} ->
- {error, toomuch};
- {tcp_closed, Sock} ->
- ok;
- {tcp_error, Sock, Reason} ->
- {error, Reason}
- after Timeout ->
- {error, timeout}
- end
- end.
-
-
-%%
-%% HELP FUNCTIONS
-%%
-
-wait_ack(_, [], _) ->
- ok;
-wait_ack(AccPids0, Pids, Timeout) ->
- ?debug("#### CONTROLLER: waiting for ~w~n", [Pids]),
- receive
- {one_accept_done, Pid} ->
- case lists:delete(Pid, AccPids0) of
- [] ->
- wait_ack([], Pids, Timeout);
- [AccPid| AccPids1] ->
- AccPid ! {continue_accept, self()},
- wait_ack(AccPids1, Pids, Timeout)
- end;
- {'EXIT', Pid, normal} ->
- wait_ack(AccPids0, lists:delete(Pid, Pids), Timeout);
- {'EXIT', Pid, Reason} ->
- ?error("#### CONTROLLER got abnormal exit: ~w, ~w~n",
- [Pid, Reason]),
- {error, Reason}
- after Timeout ->
- ?error("#### CONTROLLER exiting because of timeout = ~w~n",
- [Timeout]),
- {error, Timeout}
- end.
-
-
-%%
-%% ack_lsock(Pid, LSock)
-%%
-ack_lsock(Pid, LSock) ->
- Pid ! {lsock, self(), LSock}.
-
-wait_lsock(Pid, Timeout) ->
- receive
- {lsock, Pid, LSock} ->
- {ok, LSock}
- after Timeout ->
- exit(timeout)
- end.
-
-%%
-%% sync(Pids)
-%%
-sync(Pids) ->
- lists:foreach(fun (Pid) -> Pid ! {self(), sync} end, Pids).
-
-%%
-%% wait_sync(St)
-%%
-wait_sync(St) ->
- Pid = St#st.parent,
- receive
- {Pid, sync} ->
- ok
- end.
-
-%%
-%% wait(Time)
-%%
-wait(Time) ->
- receive
- after Time ->
- ok
- end.
-
-%%
-%% mk_msg(Size)
-%%
-mk_msg(Size) ->
- mk_msg(0, Size, []).
-
-mk_msg(_, 0, Acc) ->
- Acc;
-mk_msg(Pos, Size, Acc) ->
- C = (((Pos + Size) rem 256) - 1) band 255,
- mk_msg(Pos, Size - 1, [C| Acc]).
-
-%%
-%% get_protomod(Config)
-%%
-get_protomod(Config) ->
- case lists:keysearch(protomod, 1, Config) of
- {value, {_, ProtoMod}} ->
- ProtoMod;
- false ->
- ssl
- end.
-
-%%
-%% get_serialize_accept(Config)
-%%
-get_serialize_accept(Config) ->
- case lists:keysearch(serialize_accept, 1, Config) of
- {value, {_, Val}} ->
- Val;
- false ->
- false
- end.
-
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index b7916b96eb..46a8112a41 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -22,6 +22,7 @@
-include("test_server.hrl").
-include("test_server_line.hrl").
+-include_lib("public_key/include/public_key.hrl").
%% Note: This directive should only be used in test suites.
-compile(export_all).
@@ -673,3 +674,16 @@ cipher_result(Socket, Result) ->
session_info_result(Socket) ->
ssl:session_info(Socket).
+
+
+public_key(#'PrivateKeyInfo'{privateKeyAlgorithm =
+ #'PrivateKeyInfo_privateKeyAlgorithm'{algorithm = ?rsaEncryption},
+ privateKey = Key}) ->
+ public_key:der_decode('RSAPrivateKey', iolist_to_binary(Key));
+
+public_key(#'PrivateKeyInfo'{privateKeyAlgorithm =
+ #'PrivateKeyInfo_privateKeyAlgorithm'{algorithm = ?'id-dsa'},
+ privateKey = Key}) ->
+ public_key:der_decode('DSAPrivateKey', iolist_to_binary(Key));
+public_key(Key) ->
+ Key.
diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl
index 64a6a9eaf8..f37baeb9de 100644
--- a/lib/ssl/test/ssl_to_openssl_SUITE.erl
+++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl
@@ -109,6 +109,9 @@ special_init(TestCase, Config)
TestCase == erlang_server_openssl_client_no_wrap_sequence_number ->
check_sane_openssl_renegotaite(Config);
+special_init(ssl2_erlang_server_openssl_client, Config) ->
+ check_sane_openssl_sslv2(Config);
+
special_init(_, Config) ->
Config.
@@ -168,7 +171,8 @@ all() ->
tls1_erlang_server_openssl_client_client_cert,
tls1_erlang_server_erlang_client_client_cert,
ciphers_rsa_signed_certs, ciphers_dsa_signed_certs,
- erlang_client_bad_openssl_server, expired_session,
+ erlang_client_bad_openssl_server,
+ expired_session,
ssl2_erlang_server_openssl_client].
groups() ->
@@ -222,7 +226,6 @@ erlang_client_openssl_server(Config) when is_list(Config) ->
%% Clean close down! Server needs to be closed first !!
close_port(OpensslPort),
-
ssl_test_lib:close(Client),
process_flag(trap_exit, false),
ok.
@@ -256,9 +259,9 @@ erlang_server_openssl_client(Config) when is_list(Config) ->
port_command(OpenSslPort, Data),
ssl_test_lib:check_result(Server, ok),
-
- ssl_test_lib:close(Server),
+ %% Clean close down! Server needs to be closed first !!
+ ssl_test_lib:close(Server),
close_port(OpenSslPort),
process_flag(trap_exit, false),
ok.
@@ -306,7 +309,6 @@ tls1_erlang_client_openssl_server_dsa_cert(Config) when is_list(Config) ->
%% Clean close down! Server needs to be closed first !!
close_port(OpensslPort),
-
ssl_test_lib:close(Client),
process_flag(trap_exit, false),
ok.
@@ -346,8 +348,8 @@ tls1_erlang_server_openssl_client_dsa_cert(Config) when is_list(Config) ->
ssl_test_lib:check_result(Server, ok),
+ %% Clean close down! Server needs to be closed first !!
ssl_test_lib:close(Server),
-
close_port(OpenSslPort),
process_flag(trap_exit, false),
ok.
@@ -395,7 +397,6 @@ ssl3_erlang_client_openssl_server_dsa_cert(Config) when is_list(Config) ->
%% Clean close down! Server needs to be closed first !!
close_port(OpensslPort),
-
ssl_test_lib:close(Client),
process_flag(trap_exit, false),
ok.
@@ -435,8 +436,8 @@ ssl3_erlang_server_openssl_client_dsa_cert(Config) when is_list(Config) ->
ssl_test_lib:check_result(Server, ok),
+ %% Clean close down! Server needs to be closed first !!
ssl_test_lib:close(Server),
-
close_port(OpenSslPort),
process_flag(trap_exit, false),
ok.
@@ -475,8 +476,8 @@ erlang_server_openssl_client_reuse_session(Config) when is_list(Config) ->
ssl_test_lib:check_result(Server, ok),
+ %% Clean close down! Server needs to be closed first !!
ssl_test_lib:close(Server),
-
close_port(OpenSslPort),
process_flag(trap_exit, false),
ok.
@@ -525,7 +526,6 @@ erlang_client_openssl_server_renegotiate(Config) when is_list(Config) ->
%% Clean close down! Server needs to be closed first !!
close_port(OpensslPort),
-
ssl_test_lib:close(Client),
process_flag(trap_exit, false),
ok.
@@ -574,7 +574,6 @@ erlang_client_openssl_server_no_wrap_sequence_number(Config) when is_list(Config
%% Clean close down! Server needs to be closed first !!
close_port(OpensslPort),
-
ssl_test_lib:close(Client),
process_flag(trap_exit, false),
ok.
@@ -615,8 +614,8 @@ erlang_server_openssl_client_no_wrap_sequence_number(Config) when is_list(Config
ssl_test_lib:check_result(Server, ok),
+ %% Clean close down! Server needs to be closed first !!
ssl_test_lib:close(Server),
-
close_port(OpenSslPort),
process_flag(trap_exit, false),
ok.
@@ -663,7 +662,6 @@ erlang_client_openssl_server_no_server_ca_cert(Config) when is_list(Config) ->
%% Clean close down! Server needs to be closed first !!
close_port(OpensslPort),
-
ssl_test_lib:close(Client),
process_flag(trap_exit, false),
ok.
@@ -674,6 +672,7 @@ ssl3_erlang_client_openssl_server(doc) ->
ssl3_erlang_client_openssl_server(suite) ->
[];
ssl3_erlang_client_openssl_server(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
ServerOpts = ?config(server_opts, Config),
ClientOpts = ?config(client_opts, Config),
@@ -700,11 +699,11 @@ ssl3_erlang_client_openssl_server(Config) when is_list(Config) ->
{options,
[{versions, [sslv3]} | ClientOpts]}]),
ssl_test_lib:check_result(Client, ok),
-
- ssl_test_lib:close(Client),
- %% Clean close down!
+
+ %% Clean close down! Server needs to be closed first !!
close_port(OpensslPort),
- test_server:sleep(?SLEEP),
+ ssl_test_lib:close(Client),
+ process_flag(trap_exit, false),
ok.
%%--------------------------------------------------------------------
@@ -714,6 +713,7 @@ ssl3_erlang_server_openssl_client(doc) ->
ssl3_erlang_server_openssl_client(suite) ->
[];
ssl3_erlang_server_openssl_client(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
ServerOpts = ?config(server_opts, Config),
{_, ServerNode, _} = ssl_test_lib:run_where(Config),
@@ -734,10 +734,10 @@ ssl3_erlang_server_openssl_client(Config) when is_list(Config) ->
OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
ssl_test_lib:check_result(Server, ok),
-
- close_port(OpenSslPort), %% openssl server first
+ %% Clean close down! Server needs to be closed first !!
ssl_test_lib:close(Server),
- test_server:sleep(?SLEEP),
+ close_port(OpenSslPort),
+ process_flag(trap_exit, false),
ok.
%%--------------------------------------------------------------------
@@ -779,7 +779,7 @@ ssl3_erlang_client_openssl_server_client_cert(Config) when is_list(Config) ->
ssl_test_lib:check_result(Client, ok),
- %% Clean close down!
+ %% Clean close down! Server needs to be closed first !!
close_port(OpensslPort),
ssl_test_lib:close(Client),
process_flag(trap_exit, false),
@@ -824,9 +824,9 @@ ssl3_erlang_server_openssl_client_client_cert(Config) when is_list(Config) ->
ssl_test_lib:check_result(Server, ok),
- close_port(OpenSslPort), %% openssl server first
+ %% Clean close down! Server needs to be closed first !!
+ close_port(OpenSslPort),
ssl_test_lib:close(Server),
- %% Clean close down!
process_flag(trap_exit, false),
ok.
@@ -907,10 +907,10 @@ tls1_erlang_client_openssl_server(Config) when is_list(Config) ->
[{versions, [tlsv1]} | ClientOpts]}]),
ssl_test_lib:check_result(Client, ok),
-
- ssl_test_lib:close(Client),
- %% Clean close down!
+
+ %% Clean close down! Server needs to be closed first !!
close_port(OpensslPort),
+ ssl_test_lib:close(Client),
process_flag(trap_exit, false),
ok.
@@ -943,9 +943,9 @@ tls1_erlang_server_openssl_client(Config) when is_list(Config) ->
ssl_test_lib:check_result(Server, ok),
- %% Clean close down!
- close_port(OpenSslPort),
+ %% Clean close down! Server needs to be closed first !!
ssl_test_lib:close(Server),
+ close_port(OpenSslPort),
process_flag(trap_exit, false),
ok.
@@ -989,7 +989,7 @@ tls1_erlang_client_openssl_server_client_cert(Config) when is_list(Config) ->
ssl_test_lib:check_result(Client, ok),
- %% Clean close down!
+ %% Clean close down! Server needs to be closed first !!
close_port(OpensslPort),
ssl_test_lib:close(Client),
process_flag(trap_exit, false),
@@ -1034,9 +1034,9 @@ tls1_erlang_server_openssl_client_client_cert(Config) when is_list(Config) ->
ssl_test_lib:check_result(Server, ok),
- %% Clean close down!
- close_port(OpenSslPort),
+ %% Clean close down! Server needs to be closed first !!
ssl_test_lib:close(Server),
+ close_port(OpenSslPort),
process_flag(trap_exit, false),
ok.
@@ -1071,9 +1071,7 @@ tls1_erlang_server_erlang_client_client_cert(Config) when is_list(Config) ->
[{versions, [tlsv1]} | ClientOpts]}]),
ssl_test_lib:check_result(Server, ok, Client, ok),
-
ssl_test_lib:close(Server),
- %% Clean close down!
process_flag(trap_exit, false),
ok.
%%--------------------------------------------------------------------
@@ -1136,7 +1134,7 @@ cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) ->
CertFile = proplists:get_value(certfile, ServerOpts),
KeyFile = proplists:get_value(keyfile, ServerOpts),
- Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++
+ Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ version_flag(Version) ++
" -cert " ++ CertFile ++ " -key " ++ KeyFile ++ "",
test_server:format("openssl cmd: ~p~n", [Cmd]),
@@ -1171,8 +1169,8 @@ cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) ->
Result = ssl_test_lib:wait_for_result(Client, ok),
+ %% Clean close down! Server needs to be closed first !!
close_port(OpenSslPort),
- %% Clean close down!
ssl_test_lib:close(Client),
Return = case Result of
@@ -1184,6 +1182,12 @@ cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) ->
process_flag(trap_exit, false),
Return.
+
+version_flag(tlsv1) ->
+ " -tls1 ";
+version_flag(sslv3) ->
+ " -ssl3 ".
+
%%--------------------------------------------------------------------
erlang_client_bad_openssl_server(doc) ->
[""];
@@ -1199,26 +1203,26 @@ erlang_client_bad_openssl_server(Config) when is_list(Config) ->
Port = ssl_test_lib:inet_port(node()),
CertFile = proplists:get_value(certfile, ServerOpts),
KeyFile = proplists:get_value(keyfile, ServerOpts),
-
+
Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++
- " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ "",
-
+ " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ "",
+
test_server:format("openssl cmd: ~p~n", [Cmd]),
OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
-
+
wait_for_openssl_server(),
Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE, server_sent_garbage, []}},
- {options,
- [{versions, [tlsv1]} | ClientOpts]}]),
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, server_sent_garbage, []}},
+ {options,
+ [{versions, [tlsv1]} | ClientOpts]}]),
%% Send garbage
port_command(OpensslPort, ?OPENSSL_GARBAGE),
-
+
test_server:sleep(?SLEEP),
Client0 ! server_sent_garbage,
@@ -1228,17 +1232,16 @@ erlang_client_bad_openssl_server(Config) when is_list(Config) ->
ssl_test_lib:close(Client0),
%% Make sure openssl does not hang and leave zombie process
- Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, no_result_msg, []}},
- {options,
- [{versions, [tlsv1]} | ClientOpts]}]),
-
- ssl_test_lib:close(Client1),
-
- %% Clean close down!
+ Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result_msg, []}},
+ {options,
+ [{versions, [tlsv1]} | ClientOpts]}]),
+
+ %% Clean close down! Server needs to be closed first !!
close_port(OpensslPort),
+ ssl_test_lib:close(Client1),
process_flag(trap_exit, false),
ok.
@@ -1297,6 +1300,7 @@ expired_session(Config) when is_list(Config) ->
{mfa, {ssl_test_lib, no_result, []}},
{from, self()}, {options, ClientOpts}]),
+ %% Clean close down! Server needs to be closed first !!
close_port(OpensslPort),
ssl_test_lib:close(Client2),
process_flag(trap_exit, false).
@@ -1329,8 +1333,8 @@ ssl2_erlang_server_openssl_client(Config) when is_list(Config) ->
ssl_test_lib:check_result(Server, {error,"protocol version"}),
+ %% Clean close down! Server needs to be closed first !!
ssl_test_lib:close(Server),
-
close_port(OpenSslPort),
process_flag(trap_exit, false),
ok.
@@ -1433,3 +1437,11 @@ check_sane_openssl_renegotaite(Config) ->
_ ->
Config
end.
+
+check_sane_openssl_sslv2(Config) ->
+ case os:cmd("openssl version") of
+ "OpenSSL 1.0.0e" ++ _ ->
+ {skip, "Known option bug"};
+ _ ->
+ Config
+ end.
diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk
index 64a7603c44..2255798f1d 100644
--- a/lib/ssl/vsn.mk
+++ b/lib/ssl/vsn.mk
@@ -1 +1 @@
-SSL_VSN = 4.1.5.1
+SSL_VSN = 5.0
diff --git a/lib/stdlib/doc/src/beam_lib.xml b/lib/stdlib/doc/src/beam_lib.xml
index 013e94c393..db65eb3848 100644
--- a/lib/stdlib/doc/src/beam_lib.xml
+++ b/lib/stdlib/doc/src/beam_lib.xml
@@ -88,7 +88,6 @@
it is recommended that it contains at least 32 characters and
that both upper and lower case letters as well as digits and
special characters are used.</p>
- <p></p>
<p>The default type -- and currently the only type -- of crypto
algorithm is <c>des3_cbc</c>, three rounds of DES. The key string
will be scrambled using <c>erlang:md5/1</c> to generate
diff --git a/lib/stdlib/doc/src/calendar.xml b/lib/stdlib/doc/src/calendar.xml
index 4876b37127..f8db48e00c 100644
--- a/lib/stdlib/doc/src/calendar.xml
+++ b/lib/stdlib/doc/src/calendar.xml
@@ -75,13 +75,13 @@
<datatypes>
<datatype>
- <name name="t_datetime"/>
+ <name name="datetime"/>
</datatype>
<datatype>
- <name name="t_datetime1970"/>
+ <name name="datetime1970"/>
</datatype>
<datatype>
- <name name="t_date"/>
+ <name name="date"/>
</datatype>
<datatype>
<name name="year"/>
@@ -100,7 +100,7 @@
<name name="day"/>
</datatype>
<datatype>
- <name name="t_time"/>
+ <name name="time"/>
</datatype>
<datatype>
<name name="hour"/>
@@ -118,12 +118,7 @@
<name name="ldom"/>
</datatype>
<datatype>
- <name name="t_now"/>
- <desc><p>See <seealso marker="erts:erlang#now/0">erlang:now/0</seealso>.</p>
- </desc>
- </datatype>
- <datatype>
- <name name="t_yearweeknum"/>
+ <name name="yearweeknum"/>
</datatype>
<datatype>
<name name="weeknum"/>
diff --git a/lib/stdlib/doc/src/dets.xml b/lib/stdlib/doc/src/dets.xml
index 2512c84e18..215ec154ed 100644
--- a/lib/stdlib/doc/src/dets.xml
+++ b/lib/stdlib/doc/src/dets.xml
@@ -1006,8 +1006,7 @@ ok
<name name="table" arity="2"/>
<fsummary>Return a QLC query handle.</fsummary>
<desc>
- <p><marker id="qlc_table"></marker>
- Returns a QLC (Query List
+ <p><marker id="qlc_table"></marker>Returns a QLC (Query List
Comprehension) query handle. The module <c>qlc</c>
implements a query language aimed mainly at Mnesia but Ets
tables, Dets tables, and lists are also recognized by <c>qlc</c>
@@ -1105,7 +1104,7 @@ fun(X) -> {continue, X} end. </pre>
<p>Terminate the traversal and return <c>[<anno>Value</anno> | Acc]</c>.</p>
</item>
</taglist>
- <p>Any other value returned by <c><anno>Fun</anno></c> terminates the
+ <p>Any other value <c><anno>OtherValue</anno></c> returned by <c><anno>Fun</anno></c> terminates the
traversal and is immediately returned.
</p>
</desc>
diff --git a/lib/stdlib/doc/src/erl_tar.xml b/lib/stdlib/doc/src/erl_tar.xml
index 929620bb88..fe166dbd01 100644
--- a/lib/stdlib/doc/src/erl_tar.xml
+++ b/lib/stdlib/doc/src/erl_tar.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2003</year><year>2009</year>
+ <year>2003</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -89,9 +89,8 @@
<v>Reason = term()</v>
</type>
<desc>
- <p>The <marker id="add"></marker>
-<c>add/3</c> function adds a file to a tar file
- that has been opened for writing by
+ <p>The <marker id="add"></marker><c>add/3</c> function adds
+ a file to a tar file that has been opened for writing by
<seealso marker="#open">open/1</seealso>.</p>
<taglist>
<tag><c>dereference</c></tag>
@@ -138,8 +137,8 @@
<v>TarDescriptor = term()</v>
</type>
<desc>
- <p>The <marker id="close"></marker>
-<c>close/1</c> function closes a tar file
+ <p>The <marker id="close"></marker><c>close/1</c> function
+ closes a tar file
opened by <seealso marker="#open">open/1</seealso>.</p>
</desc>
</func>
@@ -151,11 +150,12 @@
<v>FileList = [Filename|{NameInArchive, binary()},{NameInArchive, Filename}]</v>
<v>Filename = filename()</v>
<v>NameInArchive = filename()</v>
- <v>RetValue = ok|{error,{Name,Reason}} &lt;V>Reason = term()</v>
+ <v>RetValue = ok|{error,{Name,Reason}}</v>
+ <v>Reason = term()</v>
</type>
<desc>
- <p>The <marker id="create_2"></marker>
-<c>create/2</c> function creates a tar file and
+ <p>The <marker id="create_2"></marker><c>create/2</c> function
+ creates a tar file and
archives the files whose names are given in <c>FileList</c> into it.
The files may either be read from disk or given as
binaries.</p>
@@ -171,11 +171,11 @@
<v>NameInArchive = filename()</v>
<v>OptionList = [Option]</v>
<v>Option = compressed|cooked|dereference|verbose</v>
- <v>RetValue = ok|{error,{Name,Reason}} &lt;V>Reason = term()</v>
+ <v>RetValue = ok|{error,{Name,Reason}}</v>
+ <v>Reason = term()</v>
</type>
<desc>
- <p>The <marker id="create_3"></marker>
-<c>create/3</c> function
+ <p>The <marker id="create_3"></marker><c>create/3</c> function
creates a tar file and archives the files whose names are given
in <c>FileList</c> into it. The files may either be read from
disk or given as binaries.</p>
@@ -220,9 +220,8 @@
<v>Reason = term()</v>
</type>
<desc>
- <p>The <marker id="extract_1"></marker>
-<c>extract/1</c> function extracts
- all files from a tar archive.</p>
+ <p>The <marker id="extract_1"></marker><c>extract/1</c> function
+ extracts all files from a tar archive.</p>
<p>If the <c>Name</c> argument is given as "<c>{binary,Binary}</c>",
the contents of the binary is assumed to be a tar archive.
</p>
@@ -250,9 +249,8 @@
<v>Reason = term()</v>
</type>
<desc>
- <p>The <marker id="extract_2"></marker>
-<c>extract/2</c> function extracts
- files from a tar archive.</p>
+ <p>The <marker id="extract_2"></marker><c>extract/2</c> function
+ extracts files from a tar archive.</p>
<p>If the <c>Name</c> argument is given as "<c>{binary,Binary}</c>",
the contents of the binary is assumed to be a tar archive.
</p>
@@ -322,8 +320,8 @@
<v>Reason = term()</v>
</type>
<desc>
- <p>The <marker id="format_error_1"></marker>
-<c>format_error/1</c> converts
+ <p>The <marker id="format_error_1"></marker><c>format_error/1</c>
+ function converts
an error reason term to a human-readable error message string.</p>
</desc>
</func>
@@ -339,8 +337,8 @@
<v>Reason = term()</v>
</type>
<desc>
- <p>The <marker id="open"></marker>
-<c>open/2</c> function creates a tar file for writing.
+ <p>The <marker id="open"></marker><c>open/2</c> function creates
+ a tar file for writing.
(Any existing file with the same name will be truncated.)</p>
<p>By convention, the name of a tar file should end in "<c>.tar</c>".
To abide to the convention, you'll need to add "<c>.tar</c>" yourself
@@ -373,7 +371,6 @@
You should not rely on the specific contents of the <c>TarDescriptor</c>
term, as it may change in future versions as more features are added
to the <c>erl_tar</c> module.</p>
- <p></p>
</warning>
</desc>
</func>
@@ -386,9 +383,8 @@
<v>Reason = term()</v>
</type>
<desc>
- <p>The <marker id="table_1"></marker>
-<c>table/1</c> function retrieves
- the names of all files in the tar file <c>Name</c>.</p>
+ <p>The <marker id="table_1"></marker><c>table/1</c> function
+ retrieves the names of all files in the tar file <c>Name</c>.</p>
</desc>
</func>
<func>
@@ -398,9 +394,8 @@
<v>Name = filename()</v>
</type>
<desc>
- <p>The <marker id="table_2"></marker>
-<c>table/2</c> function retrieves
- the names of all files in the tar file <c>Name</c>.</p>
+ <p>The <marker id="table_2"></marker><c>table/2</c> function
+ retrieves the names of all files in the tar file <c>Name</c>.</p>
</desc>
</func>
<func>
@@ -410,8 +405,7 @@
<v>Name = filename()</v>
</type>
<desc>
- <p>The <marker id="t_1"></marker>
-<c>t/1</c> function prints the names
+ <p>The <marker id="t_1"></marker><c>t/1</c> function prints the names
of all files in the tar file <c>Name</c> to the Erlang shell.
(Similar to "<c>tar&nbsp;t</c>".)</p>
</desc>
@@ -423,8 +417,8 @@
<v>Name = filename()</v>
</type>
<desc>
- <p>The <marker id="tt_1"></marker>
-<c>tt/1</c> function prints names and
+ <p>The <marker id="tt_1"></marker><c>tt/1</c> function prints
+ names and
information about all files in the tar file <c>Name</c> to
the Erlang shell. (Similar to "<c>tar&nbsp;tv</c>".)</p>
</desc>
diff --git a/lib/stdlib/doc/src/ets.xml b/lib/stdlib/doc/src/ets.xml
index 8c952708c5..efd9514db6 100644
--- a/lib/stdlib/doc/src/ets.xml
+++ b/lib/stdlib/doc/src/ets.xml
@@ -512,8 +512,10 @@ Error: fun containing local Erlang function calls
of the reference counter, keeping track of how many times
the table has been fixed by the process.</p>
<p>If the table never has been fixed, the call returns
- <c>false</c>.</p>
- </item>
+ <c>false</c>.</p></item>
+ <item><p><c>Item=stats, Value=tuple()</c> <br></br>
+ Returns internal statistics about set, bag and duplicate_bag tables on an internal format used by OTP test suites.
+ Not for production use.</p></item>
</list>
</desc>
</func>
@@ -658,9 +660,9 @@ ets:is_compiled_ms(Broken).</code>
table. The difference being the same as between <c>=:=</c>
and <c>==</c>. As an example, one might insert an object
with the
- <c>integer()</c><c>1</c> as a key in an <c>ordered_set</c>
+ <c>integer()</c> <c>1</c> as a key in an <c>ordered_set</c>
and get the object returned as a result of doing a
- <c>lookup/2</c> with the <c>float()</c><c>1.0</c> as the
+ <c>lookup/2</c> with the <c>float()</c> <c>1.0</c> as the
key to search for.</p>
<p>If the table is of type <c>set</c> or <c>ordered_set</c>,
the function returns either the empty list or a list with one
@@ -943,7 +945,7 @@ ets:select(Table,MatchSpec),</code>
table is named or not. If one or more options are left out,
the default values are used. This means that not specifying
any options (<c>[]</c>) is the same as specifying
- <c>[set,protected,{keypos,1},{heir,none},{write_concurrency,false},{read_concurrency,false}]</c>.</p>
+ <c>[set, protected, {keypos,1}, {heir,none}, {write_concurrency,false}, {read_concurrency,false}]</c>.</p>
<list type="bulleted">
<item>
<p><c>set</c>
@@ -960,7 +962,7 @@ ets:select(Table,MatchSpec),</code>
<c>ordered_set</c> tables regard keys as equal when they
<em>compare equal</em>, not only when they match. This
means that to an <c>ordered_set</c>, the
- <c>integer()</c><c>1</c> and the <c>float()</c><c>1.0</c> are regarded as equal. This also means that the
+ <c>integer()</c> <c>1</c> and the <c>float()</c> <c>1.0</c> are regarded as equal. This also means that the
key used to lookup an element not necessarily
<em>matches</em> the key in the elements returned, if
<c>float()</c>'s and <c>integer()</c>'s are mixed in
diff --git a/lib/stdlib/doc/src/gb_sets.xml b/lib/stdlib/doc/src/gb_sets.xml
index 38de51322f..f91fac9c82 100644
--- a/lib/stdlib/doc/src/gb_sets.xml
+++ b/lib/stdlib/doc/src/gb_sets.xml
@@ -61,7 +61,6 @@
and do the same thing in the <c>sets</c> and <c>ordsets</c>
modules. That is, by only changing the module name for each call,
you can try out different set representations.</p>
- <p></p>
<list type="bulleted">
<item>
<p><c>add_element/2</c></p>
diff --git a/lib/stdlib/doc/src/gen_fsm.xml b/lib/stdlib/doc/src/gen_fsm.xml
index d15383c621..421eeb4fd3 100644
--- a/lib/stdlib/doc/src/gen_fsm.xml
+++ b/lib/stdlib/doc/src/gen_fsm.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2010</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -430,7 +430,6 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4
denote a state of the state machine. <em>state data</em> is used
to denote the internal state of the Erlang process which
implements the state machine.</p>
- <p></p>
</section>
<funcs>
<func>
@@ -438,7 +437,7 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4
<fsummary>Initialize process and internal state name and state data.</fsummary>
<type>
<v>Args = term()</v>
- <v>Return = {ok,StateName,StateData} | {ok,StateName,StateData,Timeout}</v>
+ <v>Result = {ok,StateName,StateData} | {ok,StateName,StateData,Timeout}</v>
<v>&nbsp;&nbsp;| {ok,StateName,StateData,hibernate}</v>
<v>&nbsp;&nbsp;| {stop,Reason} | ignore</v>
<v>&nbsp;StateName = atom()</v>
@@ -639,9 +638,9 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4
<v>StateName = atom()</v>
<v>StateData = term()</v>
<v>Result = {next_state,NextStateName,NewStateData}</v>
- <v>&nbsp;>&nbsp;| {next_state,NextStateName,NewStateData,Timeout}</v>
- <v>&nbsp;>&nbsp;| {next_state,NextStateName,NewStateData,hibernate}</v>
- <v>&nbsp;>&nbsp;| {stop,Reason,NewStateData}</v>
+ <v>&nbsp;&nbsp;| {next_state,NextStateName,NewStateData,Timeout}</v>
+ <v>&nbsp;&nbsp;| {next_state,NextStateName,NewStateData,hibernate}</v>
+ <v>&nbsp;&nbsp;| {stop,Reason,NewStateData}</v>
<v>&nbsp;NextStateName = atom()</v>
<v>&nbsp;NewStateData = term()</v>
<v>&nbsp;Timeout = int()>0 | infinity</v>
diff --git a/lib/stdlib/doc/src/io.xml b/lib/stdlib/doc/src/io.xml
index af9c75d546..667d758e29 100644
--- a/lib/stdlib/doc/src/io.xml
+++ b/lib/stdlib/doc/src/io.xml
@@ -439,7 +439,7 @@ ok</pre>
<item>
<p>Prints the argument with the <c>string</c> syntax. The
argument is, if no Unicode translation modifier is present, an
- <seealso marker="erts:erlang#iolist_definition">I/O list</seealso>, a binary, or an atom. If the Unicode translation modifier ('t') is in effect, the argument is unicode:chardata(), meaning that binaries are in UTF-8. The characters
+ iolist(), a binary, or an atom. If the Unicode translation modifier ('t') is in effect, the argument is unicode:chardata(), meaning that binaries are in UTF-8. The characters
are printed without quotes. The string is first truncated
by the given precision and then padded and justified
to the given field width. The default precision is the field width.</p>
diff --git a/lib/stdlib/doc/src/lists.xml b/lib/stdlib/doc/src/lists.xml
index 6f3ed7af98..7042c84437 100644
--- a/lib/stdlib/doc/src/lists.xml
+++ b/lib/stdlib/doc/src/lists.xml
@@ -240,7 +240,7 @@ flatmap(Fun, List1) ->
<func>
<name name="keydelete" arity="3"/>
<fsummary>Delete an element from a list of tuples</fsummary>
- <type_desc variable="N">1..tuple_size(Tuple)</type_desc>
+ <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
<p>Returns a copy of <c><anno>TupleList1</anno></c> where the first
occurrence of a tuple whose <c><anno>N</anno></c>th element compares equal to
@@ -266,7 +266,7 @@ flatmap(Fun, List1) ->
<func>
<name name="keymap" arity="3"/>
<fsummary>Map a function over a list of tuples</fsummary>
- <type_desc variable="N">1..tuple_size(Tuple)</type_desc>
+ <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
<p>Returns a list of tuples where, for each tuple in
<c><anno>TupleList1</anno></c>, the <c><anno>N</anno></c>th element <c><anno>Term1</anno></c> of the tuple
@@ -298,7 +298,7 @@ flatmap(Fun, List1) ->
<func>
<name name="keymerge" arity="3"/>
<fsummary>Merge two key-sorted lists of tuples</fsummary>
- <type_desc variable="N">1..tuple_size(Tuple)</type_desc>
+ <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
<p>Returns the sorted list formed by merging <c><anno>TupleList1</anno></c>
and <c><anno>TupleList2</anno></c>. The merge is performed on
@@ -312,7 +312,7 @@ flatmap(Fun, List1) ->
<func>
<name name="keyreplace" arity="4"/>
<fsummary>Replace an element in a list of tuples</fsummary>
- <type_desc variable="N">1..tuple_size(Tuple)</type_desc>
+ <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
<p>Returns a copy of <c><anno>TupleList1</anno></c> where the first
occurrence of a <c>T</c> tuple whose <c><anno>N</anno></c>th element
@@ -342,7 +342,7 @@ flatmap(Fun, List1) ->
<func>
<name name="keysort" arity="2"/>
<fsummary>Sort a list of tuples</fsummary>
- <type_desc variable="N">1..tuple_size(Tuple)</type_desc>
+ <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
<p>Returns a list containing the sorted elements of the list
<c><anno>TupleList1</anno></c>. Sorting is performed on the <c><anno>N</anno></c>th
@@ -352,7 +352,7 @@ flatmap(Fun, List1) ->
<func>
<name name="keystore" arity="4"/>
<fsummary>Store an element in a list of tuples</fsummary>
- <type_desc variable="N">1..tuple_size(Tuple)</type_desc>
+ <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
<p>Returns a copy of <c><anno>TupleList1</anno></c> where the first
occurrence of a tuple <c>T</c> whose <c><anno>N</anno></c>th element
@@ -366,7 +366,7 @@ flatmap(Fun, List1) ->
<func>
<name name="keytake" arity="3"/>
<fsummary>Extract an element from a list of tuples</fsummary>
- <type_desc variable="N">1..tuple_size(Tuple)</type_desc>
+ <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
<p>Searches the list of tuples <c><anno>TupleList1</anno></c> for a tuple
whose <c><anno>N</anno></c>th element compares equal to <c><anno>Key</anno></c>.
@@ -500,7 +500,7 @@ flatmap(Fun, List1) ->
<func>
<name name="nth" arity="2"/>
<fsummary>Return the Nth element of a list</fsummary>
- <type_desc variable="N">1..length(List)</type_desc>
+ <type_desc variable="N">1..length(<anno>List</anno>)</type_desc>
<desc>
<p>Returns the <c><anno>N</anno></c>th element of <c><anno>List</anno></c>. For example:</p>
<pre>
@@ -511,7 +511,7 @@ c</pre>
<func>
<name name="nthtail" arity="2"/>
<fsummary>Return the Nth tail of a list</fsummary>
- <type_desc variable="N">0..length(List)</type_desc>
+ <type_desc variable="N">0..length(<anno>List</anno>)</type_desc>
<desc>
<p>Returns the <c><anno>N</anno></c>th tail of <c><anno>List</anno></c>, that is, the sublist of
<c><anno>List</anno></c> starting at <c><anno>N</anno>+1</c> and continuing up to
@@ -630,7 +630,7 @@ length(lists:seq(From, To, Incr)) == (To-From+Incr) div Incr</code>
<func>
<name name="split" arity="2"/>
<fsummary>Split a list into two lists</fsummary>
- <type_desc variable="N">0..length(List1)</type_desc>
+ <type_desc variable="N">0..length(<anno>List1</anno>)</type_desc>
<desc>
<p>Splits <c><anno>List1</anno></c> into <c><anno>List2</anno></c> and <c><anno>List3</anno></c>.
<c><anno>List2</anno></c> contains the first <c><anno>N</anno></c> elements and
@@ -670,7 +670,7 @@ splitwith(Pred, List) ->
<func>
<name name="sublist" arity="3"/>
<fsummary>Return a sub-list starting at a given position and with a given number of elements</fsummary>
- <type_desc variable="Start">1..(length(List1)+1)</type_desc>
+ <type_desc variable="Start">1..(length(<anno>List1</anno>)+1)</type_desc>
<desc>
<p>Returns the sub-list of <c><anno>List1</anno></c> starting at <c><anno>Start</anno></c>
and with (max) <c><anno>Len</anno></c> elements. It is not an error for
@@ -732,7 +732,7 @@ splitwith(Pred, List) ->
<func>
<name name="ukeymerge" arity="3"/>
<fsummary>Merge two key-sorted lists of tuples, removing duplicates</fsummary>
- <type_desc variable="N">1..tuple_size(Tuple)</type_desc>
+ <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
<p>Returns the sorted list formed by merging <c><anno>TupleList1</anno></c>
and <c><anno>TupleList2</anno></c>. The merge is performed on the
@@ -746,7 +746,7 @@ splitwith(Pred, List) ->
<func>
<name name="ukeysort" arity="2"/>
<fsummary>Sort a list of tuples, removing duplicates</fsummary>
- <type_desc variable="N">1..tuple_size(Tuple)</type_desc>
+ <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
<p>Returns a list containing the sorted elements of the list
<c><anno>TupleList1</anno></c> where all but the first tuple of the
diff --git a/lib/stdlib/doc/src/make.dep b/lib/stdlib/doc/src/make.dep
deleted file mode 100644
index 48ee6209ef..0000000000
--- a/lib/stdlib/doc/src/make.dep
+++ /dev/null
@@ -1,40 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: array.tex base64.tex beam_lib.tex book.tex \
- c.tex calendar.tex dets.tex dict.tex digraph.tex \
- digraph_utils.tex epp.tex erl_eval.tex erl_expand_records.tex \
- erl_id_trans.tex erl_internal.tex erl_lint.tex \
- erl_parse.tex erl_pp.tex erl_scan.tex erl_tar.tex \
- ets.tex file_sorter.tex filelib.tex filename.tex \
- gb_sets.tex gb_trees.tex gen_event.tex gen_fsm.tex \
- gen_server.tex io.tex io_lib.tex io_protocol.tex \
- lib.tex lists.tex log_mf_h.tex math.tex ms_transform.tex \
- orddict.tex ordsets.tex part.tex pg.tex pool.tex \
- proc_lib.tex proplists.tex qlc.tex queue.tex \
- random.tex re.tex ref_man.tex regexp.tex sets.tex \
- shell.tex shell_default.tex slave.tex sofs.tex \
- stdlib_app.tex string.tex supervisor.tex supervisor_bridge.tex \
- sys.tex timer.tex unicode.tex unicode_usage.tex \
- win32reg.tex zip.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: ushell1.ps
-
diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml
index 60c0b91212..d9c220b996 100644
--- a/lib/stdlib/doc/src/notes.xml
+++ b/lib/stdlib/doc/src/notes.xml
@@ -30,6 +30,168 @@
</header>
<p>This document describes the changes made to the STDLIB application.</p>
+<section><title>STDLIB 1.17.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ erl_tar:extract failed when executed inside a directory
+ with some parent directory to which the user has no read
+ access. This has been corrected.</p>
+ <p>
+ Own Id: OTP-9368</p>
+ </item>
+ <item>
+ <p> A bug in <c>erl_scan:set_attribute/3</c> has been
+ fixed. </p>
+ <p>
+ Own Id: OTP-9412</p>
+ </item>
+ <item>
+ <p> The contract of <c>io_lib:fread()</c> has been
+ corrected. </p>
+ <p>
+ Own Id: OTP-9413 Aux Id: seq11873 </p>
+ </item>
+ <item>
+ <p>
+ A crash in io_lib:fread/2 when end of input data was
+ encountered while trying to match literal characters,
+ which should return {more,_,_,_} but instead crashed, has
+ been corrected. Reported by Klas Johansson.</p>
+ <p>
+ A similar peculiarity for io:fread when encountering end
+ of file before any field data has also been corrected.</p>
+ <p>
+ Own Id: OTP-9439</p>
+ </item>
+ <item>
+ <p> The contract of <c>timer:now_diff()</c> has been
+ corrected. (Thanks to Alex Morarash). </p>
+ <p>
+ Own Id: OTP-9450</p>
+ </item>
+ <item>
+ <p>
+ Fix minor typo in gen_fsm documentation (Thanks to Haitao
+ Li)</p>
+ <p>
+ Own Id: OTP-9456</p>
+ </item>
+ <item>
+ <p>The contracts of <c>zip:zip_list_dir/1</c> and
+ <c>zip:zip_get/2</c> have been corrected. </p>
+ <p>
+ Own Id: OTP-9471 Aux Id: seq11887, OTP-9472 </p>
+ </item>
+ <item>
+ <p> A bug in <c>zip:zip_open()</c> has been fixed. </p>
+ <p>
+ Own Id: OTP-9472 Aux Id: seq11887, OTP-9471 </p>
+ </item>
+ <item>
+ <p>
+ Fix trivial documentation errors(Thanks to Matthias Lang)</p>
+ <p>
+ Own Id: OTP-9498</p>
+ </item>
+ <item>
+ <p>
+ Add a proplist() type</p>
+ <p>
+ Recently I was adding specs to an API and found that
+ there is no canonical proplist() type defined. (Thanks to
+ Ryan Zezeski)</p>
+ <p>
+ Own Id: OTP-9499</p>
+ </item>
+ <item>
+ <p>
+ fix supervisors restarting temporary children</p>
+ <p>
+ In the current implementation of supervisors, temporary
+ children should never be restarted. However, when a
+ temporary child is restarted as part of a one_for_all or
+ rest_for_one strategy where the failing process is not
+ the temporary child, the supervisor still tries to
+ restart it.</p>
+ <p>
+ Because the supervisor doesn't keep some of the MFA
+ information of temporary children, this causes the
+ supervisor to hit its restart limit and crash.</p>
+ <p>
+ This patch fixes the behaviour by inserting a clause in
+ terminate_children/2-3 (private function) that will omit
+ temporary children when building a list of killed
+ processes, to avoid having the supervisor trying to
+ restart them again.</p>
+ <p>
+ Only supervisors in need of restarting children used the
+ list, so the change should be of no impact for the
+ functions that called terminate_children/2-3 only to kill
+ all children.</p>
+ <p>
+ The documentation has been modified to make this
+ behaviour more explicit. (Thanks to Fred Hebert)</p>
+ <p>
+ Own Id: OTP-9502</p>
+ </item>
+ <item>
+ <p>
+ fix broken edoc annotations (Thanks to Richard Carlsson)</p>
+ <p>
+ Own Id: OTP-9516</p>
+ </item>
+ <item>
+ <p> XML files have been corrected. </p>
+ <p>
+ Own Id: OTP-9550 Aux Id: OTP-9541 </p>
+ </item>
+ <item>
+ <p>
+ Handle rare race in the crypto key server functionality</p>
+ <p>
+ Own Id: OTP-9586</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Types and specifications have been added. </p>
+ <p>
+ Own Id: OTP-9356</p>
+ </item>
+ <item>
+ <p> The contracts of the <c>queue</c> module have been
+ modified. </p>
+ <p>
+ Own Id: OTP-9418</p>
+ </item>
+ <item>
+ <p> Contracts in STDLIB and Kernel have been improved and
+ type errors have been corrected. </p>
+ <p>
+ Own Id: OTP-9485</p>
+ </item>
+ <item>
+ <p>
+ Types for several BIFs have been extended/corrected. Also
+ the types for types for <c>lists:keyfind/3</c>,
+ <c>lists:keysearch/3</c>, and <c>lists:keyemember/3</c>
+ have been corrected. The incorrect/incomplete types could
+ cause false dialyzer warnings.</p>
+ <p>
+ Own Id: OTP-9496</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>STDLIB 1.17.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -2632,7 +2794,7 @@
that is, also when starting a gen_server, gen_fsm etc. </p>
<p>This limitation has now been properly documented and the
behavior of the <c>gen_fsm</c>, <c>gen_server</c>, and
- <c>proc_lib</c><c>start</c> and <c>start_link</c>
+ <c>proc_lib</c> <c>start</c> and <c>start_link</c>
functions when providing this option has been changed
from hanging indefinitely to failing with reason
<c>badarg</c>.</p>
@@ -2749,7 +2911,6 @@
<c>join</c> option that can be used to force QLC to use a
particular kind of join in some QLC expression.</p>
<p>Several other changes have also been included:</p>
- <p></p>
<list type="bulleted">
<item>
<p>The new <c>tmpdir</c> option of <c>cursor/2</c>,
diff --git a/lib/stdlib/doc/src/qlc.xml b/lib/stdlib/doc/src/qlc.xml
index 6a45ade447..ce50631ca9 100644
--- a/lib/stdlib/doc/src/qlc.xml
+++ b/lib/stdlib/doc/src/qlc.xml
@@ -688,7 +688,6 @@ ets:match_spec_run(ets:lookup(86033, {2,2}),
</datatype>
<datatype>
<name name="tmp_file_usage"></name>
- <desc><p></p></desc>
</datatype>
</datatypes>
diff --git a/lib/stdlib/doc/src/random.xml b/lib/stdlib/doc/src/random.xml
index 93affc3191..1b8fa44883 100644
--- a/lib/stdlib/doc/src/random.xml
+++ b/lib/stdlib/doc/src/random.xml
@@ -136,6 +136,11 @@
<c>random_seed</c> to remember the current seed.</p>
<p>If a process calls <c>uniform/0</c> or <c>uniform/1</c> without
setting a seed first, <c>seed/0</c> is called automatically.</p>
+ <p>The implementation changed in R15. Upgrading to R15 will break
+ applications that expect a specific output for a given seed. The output
+ is still deterministic number series, but different compared to releases
+ older than R15. The seed <c>{0,0,0}</c> will for example no longer
+ produce a flawed series of only zeros.</p>
</section>
</erlref>
diff --git a/lib/stdlib/doc/src/supervisor.xml b/lib/stdlib/doc/src/supervisor.xml
index 009aa60faa..cddb55e5c5 100644
--- a/lib/stdlib/doc/src/supervisor.xml
+++ b/lib/stdlib/doc/src/supervisor.xml
@@ -59,7 +59,6 @@
processes are started in order from left to right according to
this list. When the supervisor terminates, it first terminates
its child processes in reversed start order, from right to left.</p>
- <p></p>
<p>A supervisor can have one of the following <em>restart strategies</em>:</p>
<list type="bulleted">
<item>
@@ -94,6 +93,10 @@
instead the child specification identifier is used,
<c>terminate_child/2</c> will return
<c>{error,simple_one_for_one}</c>.</p>
+ <p>Because a <c>simple_one_for_one</c> supervisor could have many
+ children, it shuts them all down at same time. So, order in which they
+ are stopped is not defined. For the same reason, it could have an
+ overhead with regards to the <c>Shutdown</c> strategy.</p>
</item>
</list>
<p>To prevent a supervisor from getting into an infinite loop of
@@ -150,9 +153,12 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
<p><c>Restart</c> defines when a terminated child process
should be restarted. A <c>permanent</c> child process should
always be restarted, a <c>temporary</c> child process should
- never be restarted and a <c>transient</c> child process
- should be restarted only if it terminates abnormally, i.e.
- with another exit reason than <c>normal</c>.</p>
+ never be restarted (even when the supervisor's restart strategy
+ is <c>rest_for_one</c> or <c>one_for_all</c> and a sibling's
+ death causes the temporary process to be terminated) and a
+ <c>transient</c> child process should be restarted only if
+ it terminates abnormally, i.e. with another exit reason
+ than <c>normal</c>, <c>shutdown</c> or <c>{shutdown,Term}</c>.</p>
</item>
<item>
<p><c>Shutdown</c> defines how a child process should be
@@ -167,7 +173,15 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
<c>exit(Child,kill)</c>.</p>
<p>If the child process is another supervisor, <c>Shutdown</c>
should be set to <c>infinity</c> to give the subtree ample
- time to shutdown.</p>
+ time to shutdown. It is also allowed to set it to <c>infinity</c>,
+ if the child process is a worker.</p>
+ <warning>
+ <p>Be careful by setting the <c>Shutdown</c> strategy to
+ <c>infinity</c> when the child process is a worker. Because, in this
+ situation, the termination of the supervision tree depends on the
+ child process, it must be implemented in a safe way and its cleanup
+ procedure must always return.</p>
+ </warning>
<p><em>Important note on simple-one-for-one supervisors:</em>
The dynamically created child processes of a
simple-one-for-one supervisor are not explicitly killed,
@@ -341,14 +355,23 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
<desc>
<p>Tells the supervisor <c><anno>SupRef</anno></c> to terminate the given
child.</p>
+
<p>If the supervisor is not <c>simple_one_for_one</c>,
- <c><anno>Id</anno></c> must be the child specification identifier. The
- process, if there is one, is terminated but the child
- specification is kept by the supervisor. The child process
- may later be restarted by the supervisor. The child process
- can also be restarted explicitly by calling
+ <c><anno>Id</anno></c> must be the child specification
+ identifier. The process, if there is one, is terminated and,
+ unless it is a temporary child, the child specification is
+ kept by the supervisor. The child process may later be
+ restarted by the supervisor. The child process can also be
+ restarted explicitly by calling
<c>restart_child/2</c>. Use <c>delete_child/2</c> to remove
the child specification.</p>
+
+ <p>If the child is temporary, the child specification is deleted as
+ soon as the process terminates. This means
+ that <c>delete_child/2</c> has no meaning
+ and <c>restart_child/2</c> can not be used for these
+ children.</p>
+
<p>If the supervisor is <c>simple_one_for_one</c>, <c><anno>Id</anno></c>
must be the child process' <c>pid()</c>. I the specified
process is alive, but is not a child of the given
@@ -385,26 +408,34 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
<name name="restart_child" arity="2"/>
<fsummary>Restart a terminated child process belonging to a supervisor.</fsummary>
<desc>
- <p>Tells the supervisor <c><anno>SupRef</anno></c> to restart a child process
- corresponding to the child specification identified by
- <c><anno>Id</anno></c>. The child specification must exist and
- the corresponding child process must not be running.</p>
- <p>See <seealso marker="#SupRef"><c>start_child/2</c></seealso> for a description of
- <c>SupRef</c>.</p>
- <p>If the child specification identified by <c><anno>Id</anno></c> does not
- exist, the function returns <c>{error,not_found}</c>. If
- the child specification exists but the corresponding process
- is already running, the function returns
+ <p>Tells the supervisor <c><anno>SupRef</anno></c> to restart
+ a child process corresponding to the child specification
+ identified by <c><anno>Id</anno></c>. The child
+ specification must exist and the corresponding child process
+ must not be running.</p>
+ <p>Note that for temporary children, the child specification
+ is automatically deleted when the child terminates, and thus
+ it is not possible to restart such children.</p>
+ <p>See <seealso marker="#SupRef"><c>start_child/2</c></seealso>
+ for a description of <c>SupRef</c>.</p>
+ <p>If the child specification identified
+ by <c><anno>Id</anno></c> does not exist, the function
+ returns <c>{error,not_found}</c>. If the child specification
+ exists but the corresponding process is already running, the
+ function returns
<c>{error,running}</c>.</p>
- <p>If the child process start function returns <c>{ok,<anno>Child</anno>}</c>
- or <c>{ok,<anno>Child</anno>,<anno>Info</anno>}</c>, the pid is added to the supervisor
- and the function returns the same value.</p>
+ <p>If the child process start function
+ returns <c>{ok,<anno>Child</anno>}</c>
+ or <c>{ok,<anno>Child</anno>,<anno>Info</anno>}</c>, the pid
+ is added to the supervisor and the function returns the same
+ value.</p>
<p>If the child process start function returns <c>ignore</c>,
the pid remains set to <c>undefined</c> and the function
returns <c>{ok,undefined}</c>.</p>
- <p>If the child process start function returns an error tuple or
- an erroneous value, or if it fails, the function returns
- <c>{error,<anno>Error</anno>}</c> where <c><anno>Error</anno></c> is a term containing
+ <p>If the child process start function returns an error tuple
+ or an erroneous value, or if it fails, the function returns
+ <c>{error,<anno>Error</anno>}</c>
+ where <c><anno>Error</anno></c> is a term containing
information about the error.</p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/timer.xml b/lib/stdlib/doc/src/timer.xml
index b741ab7db1..0c1e398dc4 100644
--- a/lib/stdlib/doc/src/timer.xml
+++ b/lib/stdlib/doc/src/timer.xml
@@ -84,7 +84,7 @@
<name name="send_after" arity="3"/>
<fsummary>Send <c>Message</c>to <c>Pid</c>after a specified <c>Time</c>.</fsummary>
<desc>
- <p></p>
+ <p>
<taglist>
<tag><c>send_after/3</c></tag>
<item>
@@ -98,6 +98,7 @@
<p>Same as <c>send_after(<anno>Time</anno>, self(), <anno>Message</anno>)</c>.</p>
</item>
</taglist>
+ </p>
</desc>
</func>
<func>
@@ -107,7 +108,7 @@
<name name="exit_after" arity="3"/>
<fsummary>Send an exit signal with <c>Reason</c>after a specified <c>Time</c>.</fsummary>
<desc>
- <p></p>
+ <p>
<taglist>
<tag><c>exit_after/3</c></tag>
<item>
@@ -128,6 +129,7 @@
<p>Same as <c>exit_after(<anno>Time</anno>, self(), kill)</c>. </p>
</item>
</taglist>
+ </p>
</desc>
</func>
<func>
@@ -144,7 +146,7 @@
<name name="send_interval" arity="3"/>
<fsummary>Send <c>Message</c>repeatedly at intervals of <c>Time</c>.</fsummary>
<desc>
- <p></p>
+ <p>
<taglist>
<tag><c>send_interval/3</c></tag>
<item>
@@ -158,6 +160,7 @@
<p>Same as <c>send_interval(<anno>Time</anno>, self(), <anno>Message</anno>)</c>.</p>
</item>
</taglist>
+ </p>
</desc>
</func>
<func>
@@ -188,7 +191,7 @@
Function, Arguments)</c> or <c>apply(Fun, Arguments)</c></fsummary>
<type_desc variable="Time">In microseconds</type_desc>
<desc>
- <p></p>
+ <p>
<taglist>
<tag><c>tc/3</c></tag>
<item>
@@ -209,6 +212,7 @@
</item>
</taglist>
+ </p>
</desc>
</func>
<func>
@@ -254,7 +258,6 @@
<section>
<title>Examples</title>
<p>This example illustrates how to print out "Hello World!" in 5 seconds:</p>
- <p></p>
<pre>
1> <input>timer:apply_after(5000, io, format, ["~nHello World!~n", []]).</input>
{ok,TRef}
diff --git a/lib/stdlib/doc/src/unicode.xml b/lib/stdlib/doc/src/unicode.xml
index d02763f75c..1001ebbae4 100644
--- a/lib/stdlib/doc/src/unicode.xml
+++ b/lib/stdlib/doc/src/unicode.xml
@@ -203,8 +203,7 @@
<item>greater than <c>16#10FFFF</c>
(the maximum unicode character),</item>
<item>in the range <c>16#D800</c> to <c>16#DFFF</c>
- (invalid unicode range)</item>
- <item>or equal to 16#FFFE or 16#FFFF (non characters)</item>
+ (invalid range reserved for UTF-16 surrogate pairs)</item>
</list>
is found.
</item>
diff --git a/lib/stdlib/doc/src/unicode_usage.xml b/lib/stdlib/doc/src/unicode_usage.xml
index 416df1f02c..0fa7de0a5c 100644
--- a/lib/stdlib/doc/src/unicode_usage.xml
+++ b/lib/stdlib/doc/src/unicode_usage.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1999</year>
- <year>2010</year>
+ <year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -52,7 +52,7 @@
<tag>UCS-4</tag>
<item>Basically the same as UTF-32, but without some Unicode semantics, defined by IEEE and has little use as a separate encoding standard. For all normal (and possibly abnormal) usages, UTF-32 and UCS-4 are interchangeable.</item>
</taglist>
-<p>Certain ranges of characters are left unused and certain ranges are even deemed invalid. The most notable invalid range is 16#D800 - 16#DFFF, as the UTF-16 encoding does not allow for encoding of these numbers. It can be speculated that the UTF-16 encoding standard was, from the beginning, expected to be able to hold all Unicode characters in one 16-bit entity, but then had to be extended, leaving a whole in the Unicode range to cope with backward compatibility.</p>
+<p>Certain ranges of characters are left unused and certain ranges are even deemed invalid. The most notable invalid range is 16#D800 - 16#DFFF, as the UTF-16 encoding does not allow for encoding of these numbers. It can be speculated that the UTF-16 encoding standard was, from the beginning, expected to be able to hold all Unicode characters in one 16-bit entity, but then had to be extended, leaving a hole in the Unicode range to cope with backward compatibility.</p>
<p>Additionally, the codepoint 16#FEFF is used for byte order marks (BOM's) and use of that character is not encouraged in other contexts than that. It actually is valid though, as the character "ZWNBS" (Zero Width Non Breaking Space). BOM's are used to identify encodings and byte order for programs where such parameters are not known in advance. Byte order marks are more seldom used than one could expect, put their use is becoming more widely spread as they provide the means for programs to make educated guesses about the Unicode format of a certain file.</p>
</section>
<section>
diff --git a/lib/stdlib/doc/src/zip.xml b/lib/stdlib/doc/src/zip.xml
index b03fc7f4e2..cf0d581352 100644
--- a/lib/stdlib/doc/src/zip.xml
+++ b/lib/stdlib/doc/src/zip.xml
@@ -243,12 +243,10 @@
<name name="extract" arity="2"/>
<fsummary>Extract files from a zip archive</fsummary>
<desc>
- <p>The <marker id="unzip_1"></marker>
-<c>unzip/1</c> function extracts
- all files from a zip archive. The
- <marker id="unzip_2"></marker>
-<c>unzip/2</c> function provides options
- to extract some files, and more.</p>
+ <p>The <marker id="unzip_1"></marker><c>unzip/1</c> function extracts
+ all files from a zip archive.
+ The <marker id="unzip_2"></marker><c>unzip/2</c> function provides
+ options to extract some files, and more.</p>
<p>If the <c><anno>Archive</anno></c> argument is given as a binary,
the contents of the binary is assumed to be a zip archive,
otherwise it should be a filename.</p>
@@ -413,8 +411,8 @@
<name name="zip_open" arity="2"/>
<fsummary>Open an archive and return a handle to it</fsummary>
<desc>
- <p>The <marker id="zip_open"></marker>
-<c>zip_open</c> function opens a
+ <p>The <marker id="zip_open"></marker><c>zip_open</c> function
+ opens a
zip archive, and reads and saves its directory. This
means that subsequently reading files from the archive will be
faster than unzipping files one at a time with <c>unzip</c>.</p>
@@ -436,8 +434,7 @@
<name name="zip_get" arity="2"/>
<fsummary>Extract files from an open archive</fsummary>
<desc>
- <p>The <marker id="zip_get"></marker>
-<c>zip_get</c> function extracts
+ <p>The <marker id="zip_get"></marker><c>zip_get</c> function extracts
one or all files from an open archive.</p>
<p>The files will be unzipped to memory or to file, depending on
the options given to the <c>zip_open</c> function when the
@@ -448,9 +445,8 @@
<name name="zip_close" arity="1"/>
<fsummary>Close an open archive</fsummary>
<desc>
- <p>The <marker id="zip_close"></marker>
-<c>zip_close/1</c> function closes
- a zip archive, previously opened with <c>zip_open</c>. All
+ <p>The <marker id="zip_close"></marker><c>zip_close/1</c> function
+ closes a zip archive, previously opened with <c>zip_open</c>. All
resources are closed, and the handle should not be used after
closing.</p>
</desc>
diff --git a/lib/stdlib/examples/erl_id_trans.erl b/lib/stdlib/examples/erl_id_trans.erl
index b63acdd40a..72e41d6473 100644
--- a/lib/stdlib/examples/erl_id_trans.erl
+++ b/lib/stdlib/examples/erl_id_trans.erl
@@ -419,7 +419,14 @@ expr({'fun',Line,Body}) ->
{'fun',Line,{clauses,Cs1}};
{function,F,A} ->
{'fun',Line,{function,F,A}};
- {function,M,F,A} -> %R10B-6: fun M:F/A.
+ {function,M,F,A} when is_atom(M), is_atom(F), is_integer(A) ->
+ %% R10B-6: fun M:F/A. (Backward compatibility)
+ {'fun',Line,{function,M,F,A}};
+ {function,M0,F0,A0} ->
+ %% R15: fun M:F/A with variables.
+ M = expr(M0),
+ F = expr(F0),
+ A = expr(A0),
{'fun',Line,{function,M,F,A}}
end;
expr({call,Line,F0,As0}) ->
diff --git a/lib/stdlib/src/beam_lib.erl b/lib/stdlib/src/beam_lib.erl
index d9c645d787..e9a5e6831e 100644
--- a/lib/stdlib/src/beam_lib.erl
+++ b/lib/stdlib/src/beam_lib.erl
@@ -224,7 +224,7 @@ version(File) ->
MD5 :: binary().
md5(File) ->
- case catch read_significant_chunks(File) of
+ case catch read_significant_chunks(File, md5_chunks()) of
{ok, {Module, Chunks0}} ->
Chunks = filter_funtab(Chunks0),
{ok, {Module, erlang:md5([C || {_Id, C} <- Chunks])}};
@@ -395,7 +395,7 @@ strip_fils(Files) ->
%% -> {ok, {Mod, FileName}} | {ok, {Mod, binary()}} | throw(Error)
strip_file(File) ->
- {ok, {Mod, Chunks}} = read_significant_chunks(File),
+ {ok, {Mod, Chunks}} = read_significant_chunks(File, significant_chunks()),
{ok, Stripped0} = build_module(Chunks),
Stripped = compress(Stripped0),
case File of
@@ -453,8 +453,8 @@ is_useless_chunk("CInf") -> true;
is_useless_chunk(_) -> false.
%% -> {ok, {Module, Chunks}} | throw(Error)
-read_significant_chunks(File) ->
- case read_chunk_data(File, significant_chunks(), [allow_missing_chunks]) of
+read_significant_chunks(File, ChunkList) ->
+ case read_chunk_data(File, ChunkList, [allow_missing_chunks]) of
{ok, {Module, Chunks0}} ->
Mandatory = mandatory_chunks(),
Chunks = filter_significant_chunks(Chunks0, Mandatory, File, Module),
@@ -835,12 +835,15 @@ file_error(FileName, {error, Reason}) ->
error(Reason) ->
throw({error, ?MODULE, Reason}).
-
-%% The following chunks are significant when calculating the MD5 for a module,
-%% and also the modules that must be retained when stripping a file.
-%% They are listed in the order that they should be MD5:ed.
+%% The following chunks must be kept when stripping a BEAM file.
significant_chunks() ->
+ ["Line" | md5_chunks()].
+
+%% The following chunks are significant when calculating the MD5
+%% for a module. They are listed in the order that they should be MD5:ed.
+
+md5_chunks() ->
["Atom", "Code", "StrT", "ImpT", "ExpT", "FunT", "LitT"].
%% The following chunks are mandatory in every Beam file.
@@ -893,13 +896,17 @@ call_crypto_server(Req) ->
gen_server:call(?CRYPTO_KEY_SERVER, Req, infinity)
catch
exit:{noproc,_} ->
- start_crypto_server(),
- erlang:yield(),
- call_crypto_server(Req)
+ %% Not started.
+ call_crypto_server_1(Req);
+ exit:{normal,_} ->
+ %% The process finished just as we called it.
+ call_crypto_server_1(Req)
end.
-start_crypto_server() ->
- gen_server:start({local,?CRYPTO_KEY_SERVER}, ?MODULE, [], []).
+call_crypto_server_1(Req) ->
+ gen_server:start({local,?CRYPTO_KEY_SERVER}, ?MODULE, [], []),
+ erlang:yield(),
+ call_crypto_server(Req).
-spec init([]) -> {'ok', #state{}}.
diff --git a/lib/stdlib/src/c.erl b/lib/stdlib/src/c.erl
index febfdd6285..a920921a5e 100644
--- a/lib/stdlib/src/c.erl
+++ b/lib/stdlib/src/c.erl
@@ -797,7 +797,7 @@ appcall(App, M, F, Args) ->
catch
error:undef ->
case erlang:get_stacktrace() of
- [{M,F,Args}|_] ->
+ [{M,F,Args,_}|_] ->
Arity = length(Args),
io:format("Call to ~w:~w/~w in application ~w failed.\n",
[M,F,Arity,App]);
diff --git a/lib/stdlib/src/calendar.erl b/lib/stdlib/src/calendar.erl
index 8d1071209e..0320e0cd0e 100644
--- a/lib/stdlib/src/calendar.erl
+++ b/lib/stdlib/src/calendar.erl
@@ -63,7 +63,7 @@
%% Types
%%----------------------------------------------------------------------
--export_type([t_now/0]).
+-export_type([date/0, time/0, datetime/0, datetime1970/0]).
-type year() :: non_neg_integer().
-type year1970() :: 1970..10000. % should probably be 1970..
@@ -76,15 +76,11 @@
-type ldom() :: 28 | 29 | 30 | 31. % last day of month
-type weeknum() :: 1..53.
--type t_now() :: {MegaSecs :: non_neg_integer(),
- Secs :: non_neg_integer(),
- MicroSecs :: non_neg_integer()}.
-
--type t_date() :: {year(),month(),day()}.
--type t_time() :: {hour(),minute(),second()}.
--type t_datetime() :: {t_date(),t_time()}.
--type t_datetime1970() :: {{year1970(),month(),day()},t_time()}.
--type t_yearweeknum() :: {year(),weeknum()}.
+-type date() :: {year(),month(),day()}.
+-type time() :: {hour(),minute(),second()}.
+-type datetime() :: {date(),time()}.
+-type datetime1970() :: {{year1970(),month(),day()},time()}.
+-type yearweeknum() :: {year(),weeknum()}.
%%----------------------------------------------------------------------
@@ -123,7 +119,7 @@ date_to_gregorian_days(Year, Month, Day) when is_integer(Day), Day > 0 ->
end.
-spec date_to_gregorian_days(Date) -> Days when
- Date :: t_date(),
+ Date :: date(),
Days :: non_neg_integer().
date_to_gregorian_days({Year, Month, Day}) ->
date_to_gregorian_days(Year, Month, Day).
@@ -135,7 +131,7 @@ date_to_gregorian_days({Year, Month, Day}) ->
%% January 1st.
%%
-spec datetime_to_gregorian_seconds(DateTime) -> Seconds when
- DateTime :: t_datetime(),
+ DateTime :: datetime(),
Seconds :: non_neg_integer().
datetime_to_gregorian_seconds({Date, Time}) ->
?SECONDS_PER_DAY*date_to_gregorian_days(Date) +
@@ -155,14 +151,14 @@ day_of_the_week(Year, Month, Day) ->
(date_to_gregorian_days(Year, Month, Day) + 5) rem 7 + 1.
-spec day_of_the_week(Date) -> daynum() when
- Date:: t_date().
+ Date:: date().
day_of_the_week({Year, Month, Day}) ->
day_of_the_week(Year, Month, Day).
%% gregorian_days_to_date(Days) = {Year, Month, Day}
%%
--spec gregorian_days_to_date(Days) -> t_date() when
+-spec gregorian_days_to_date(Days) -> date() when
Days :: non_neg_integer().
gregorian_days_to_date(Days) ->
{Year, DayOfYear} = day_to_year(Days),
@@ -172,7 +168,7 @@ gregorian_days_to_date(Days) ->
%% gregorian_seconds_to_datetime(Secs)
%%
--spec gregorian_seconds_to_datetime(Seconds) -> t_datetime() when
+-spec gregorian_seconds_to_datetime(Seconds) -> datetime() when
Seconds :: non_neg_integer().
gregorian_seconds_to_datetime(Secs) when Secs >= 0 ->
Days = Secs div ?SECONDS_PER_DAY,
@@ -198,7 +194,7 @@ is_leap_year1(_) -> false.
%%
%% Calculates the iso week number for the current date.
%%
--spec iso_week_number() -> t_yearweeknum().
+-spec iso_week_number() -> yearweeknum().
iso_week_number() ->
{Date, _} = local_time(),
iso_week_number(Date).
@@ -207,8 +203,8 @@ iso_week_number() ->
%%
%% Calculates the iso week number for the given date.
%%
--spec iso_week_number(Date) -> t_yearweeknum() when
- Date :: t_date().
+-spec iso_week_number(Date) -> yearweeknum() when
+ Date :: date().
iso_week_number({Year, Month, Day}) ->
D = date_to_gregorian_days({Year, Month, Day}),
W01_1_Year = gregorian_days_of_iso_w01_1(Year),
@@ -260,7 +256,7 @@ last_day_of_the_month1(_, M) when is_integer(M), M > 0, M < 13 ->
%% local_time()
%%
%% Returns: {date(), time()}, date() = {Y, M, D}, time() = {H, M, S}.
--spec local_time() -> t_datetime().
+-spec local_time() -> datetime().
local_time() ->
erlang:localtime().
@@ -268,20 +264,20 @@ local_time() ->
%% local_time_to_universal_time(DateTime)
%%
-spec local_time_to_universal_time(DateTime1) -> DateTime2 when
- DateTime1 :: t_datetime1970(),
- DateTime2 :: t_datetime1970().
+ DateTime1 :: datetime1970(),
+ DateTime2 :: datetime1970().
local_time_to_universal_time(DateTime) ->
erlang:localtime_to_universaltime(DateTime).
--spec local_time_to_universal_time(t_datetime1970(),
+-spec local_time_to_universal_time(datetime1970(),
'true' | 'false' | 'undefined') ->
- t_datetime1970().
+ datetime1970().
local_time_to_universal_time(DateTime, IsDst) ->
erlang:localtime_to_universaltime(DateTime, IsDst).
-spec local_time_to_universal_time_dst(DateTime1) -> [DateTime] when
- DateTime1 :: t_datetime1970(),
- DateTime :: t_datetime1970().
+ DateTime1 :: datetime1970(),
+ DateTime :: datetime1970().
local_time_to_universal_time_dst(DateTime) ->
UtDst = erlang:localtime_to_universaltime(DateTime, true),
Ut = erlang:localtime_to_universaltime(DateTime, false),
@@ -309,14 +305,14 @@ local_time_to_universal_time_dst(DateTime) ->
%% = MilliSec = integer()
%% Returns: {date(), time()}, date() = {Y, M, D}, time() = {H, M, S}.
%%
--spec now_to_datetime(Now) -> t_datetime1970() when
- Now :: t_now().
+-spec now_to_datetime(Now) -> datetime1970() when
+ Now :: erlang:timestamp().
now_to_datetime({MSec, Sec, _uSec}) ->
Sec0 = MSec*1000000 + Sec + ?DAYS_FROM_0_TO_1970*?SECONDS_PER_DAY,
gregorian_seconds_to_datetime(Sec0).
--spec now_to_universal_time(Now) -> t_datetime1970() when
- Now :: t_now().
+-spec now_to_universal_time(Now) -> datetime1970() when
+ Now :: erlang:timestamp().
now_to_universal_time(Now) ->
now_to_datetime(Now).
@@ -325,8 +321,8 @@ now_to_universal_time(Now) ->
%%
%% Args: Now = now()
%%
--spec now_to_local_time(Now) -> t_datetime1970() when
- Now :: t_now().
+-spec now_to_local_time(Now) -> datetime1970() when
+ Now :: erlang:timestamp().
now_to_local_time({MSec, Sec, _uSec}) ->
erlang:universaltime_to_localtime(
now_to_universal_time({MSec, Sec, _uSec})).
@@ -338,7 +334,7 @@ now_to_local_time({MSec, Sec, _uSec}) ->
-spec seconds_to_daystime(Seconds) -> {Days, Time} when
Seconds :: integer(),
Days :: integer(),
- Time :: t_time().
+ Time :: time().
seconds_to_daystime(Secs) ->
Days0 = Secs div ?SECONDS_PER_DAY,
Secs0 = Secs rem ?SECONDS_PER_DAY,
@@ -356,7 +352,7 @@ seconds_to_daystime(Secs) ->
%% Wraps.
%%
-type secs_per_day() :: 0..?SECONDS_PER_DAY.
--spec seconds_to_time(Seconds) -> t_time() when
+-spec seconds_to_time(Seconds) -> time() when
Seconds :: secs_per_day().
seconds_to_time(Secs) when Secs >= 0, Secs < ?SECONDS_PER_DAY ->
Secs0 = Secs rem ?SECONDS_PER_DAY,
@@ -375,10 +371,10 @@ seconds_to_time(Secs) when Secs >= 0, Secs < ?SECONDS_PER_DAY ->
%% Year = Month = Day = Hour = Minute = Sec = integer()
%%
-spec time_difference(T1, T2) -> {Days, Time} when
- T1 :: t_datetime(),
- T2 :: t_datetime(),
+ T1 :: datetime(),
+ T2 :: datetime(),
Days :: integer(),
- Time :: t_time().
+ Time :: time().
time_difference({{Y1, Mo1, D1}, {H1, Mi1, S1}},
{{Y2, Mo2, D2}, {H2, Mi2, S2}}) ->
Secs = datetime_to_gregorian_seconds({{Y2, Mo2, D2}, {H2, Mi2, S2}}) -
@@ -390,7 +386,7 @@ time_difference({{Y1, Mo1, D1}, {H1, Mi1, S1}},
%% time_to_seconds(Time)
%%
-spec time_to_seconds(Time) -> secs_per_day() when
- Time :: t_time().
+ Time :: time().
time_to_seconds({H, M, S}) when is_integer(H), is_integer(M), is_integer(S) ->
H * ?SECONDS_PER_HOUR +
M * ?SECONDS_PER_MINUTE + S.
@@ -399,15 +395,15 @@ time_to_seconds({H, M, S}) when is_integer(H), is_integer(M), is_integer(S) ->
%% universal_time()
%%
%% Returns: {date(), time()}, date() = {Y, M, D}, time() = {H, M, S}.
--spec universal_time() -> t_datetime().
+-spec universal_time() -> datetime().
universal_time() ->
erlang:universaltime().
%% universal_time_to_local_time(DateTime)
%%
--spec universal_time_to_local_time(DateTime) -> t_datetime() when
- DateTime :: t_datetime1970().
+-spec universal_time_to_local_time(DateTime) -> datetime() when
+ DateTime :: datetime1970().
universal_time_to_local_time(DateTime) ->
erlang:universaltime_to_localtime(DateTime).
@@ -429,7 +425,7 @@ valid_date1(_, _, _) ->
false.
-spec valid_date(Date) -> boolean() when
- Date :: t_date().
+ Date :: date().
valid_date({Y, M, D}) ->
valid_date(Y, M, D).
diff --git a/lib/stdlib/src/dets.erl b/lib/stdlib/src/dets.erl
index 671b5a9dd4..c0f9ce34b0 100644
--- a/lib/stdlib/src/dets.erl
+++ b/lib/stdlib/src/dets.erl
@@ -411,7 +411,8 @@ init_table(Tab, InitFun) ->
InitFun :: fun((Arg) -> Res),
Arg :: read | close,
Res :: end_of_input | {[object()], InitFun} | {Data, InitFun} | term(),
- Options :: [{min_no_slots,no_slots()} | {format,term | bchunk}],
+ Options :: Option | [Option],
+ Option :: {min_no_slots,no_slots()} | {format,term | bchunk},
Reason :: term(),
Data :: binary() | tuple().
@@ -871,11 +872,15 @@ to_ets(DTab, ETab) ->
-spec traverse(Name, Fun) -> Return | {'error', Reason} when
Name :: tab_name(),
Fun :: fun((Object) -> FunReturn),
- FunReturn :: 'continue' | {'continue', Val} | {'done', Value},
+ Object :: object(),
+ FunReturn :: 'continue'
+ | {'continue', Val}
+ | {'done', Value}
+ | OtherValue,
+ Return :: [term()] | OtherValue,
Val :: term(),
Value :: term(),
- Object :: object(),
- Return :: [term()],
+ OtherValue :: term(),
Reason :: term().
traverse(Tab, Fun) ->
@@ -1749,17 +1754,6 @@ system_code_change(State, _Module, _OldVsn, _Extra) ->
%%% Internal functions
%%%----------------------------------------------------------------------
-constants(FH, FileName) ->
- Version = FH#fileheader.version,
- if
- Version =< 8 ->
- dets_v8:constants();
- Version =:= 9 ->
- dets_v9:constants();
- true ->
- throw({error, {not_a_dets_file, FileName}})
- end.
-
%% -> {ok, Fd, fileheader()} | throw(Error)
read_file_header(FileName, Access, RamFile) ->
BF = if
@@ -1837,7 +1831,11 @@ do_bchunk_init(Head, Tab) ->
{H2, {error, old_version}};
Parms ->
L = dets_utils:all_allocated(H2),
- C0 = #dets_cont{no_objs = default, bin = <<>>, alloc = L},
+ Bin = if
+ L =:= <<>> -> eof;
+ true -> <<>>
+ end,
+ C0 = #dets_cont{no_objs = default, bin = Bin, alloc = L},
BinParms = term_to_binary(Parms),
{H2, {C0#dets_cont{tab = Tab, proc = self(),what = bchunk},
[BinParms]}}
@@ -2470,10 +2468,23 @@ fopen2(Fname, Tab) ->
%% Fd is not always closed upon error, but exit is soon called.
{ok, Fd, FH} = read_file_header(Fname, Acc, Ram),
Mod = FH#fileheader.mod,
- case Mod:check_file_header(FH, Fd) of
- {error, not_closed} ->
- io:format(user,"dets: file ~p not properly closed, "
- "repairing ...~n", [Fname]),
+ Do = case Mod:check_file_header(FH, Fd) of
+ {ok, Head1, ExtraInfo} ->
+ Head2 = Head1#head{filename = Fname},
+ try {ok, Mod:init_freelist(Head2, ExtraInfo)}
+ catch
+ throw:_ ->
+ {repair, " has bad free lists, repairing ..."}
+ end;
+ {error, not_closed} ->
+ M = " not properly closed, repairing ...",
+ {repair, M};
+ Else ->
+ Else
+ end,
+ case Do of
+ {repair, Mess} ->
+ io:format(user, "dets: file ~p~s~n", [Fname, Mess]),
Version = default,
case fsck(Fd, Tab, Fname, FH, default, default, Version) of
ok ->
@@ -2481,9 +2492,9 @@ fopen2(Fname, Tab) ->
Error ->
throw(Error)
end;
- {ok, Head, ExtraInfo} ->
+ {ok, Head} ->
open_final(Head, Fname, Acc, Ram, ?DEFAULT_CACHE,
- Tab, ExtraInfo, false);
+ Tab, false);
{error, Reason} ->
throw({error, {Reason, Fname}})
end;
@@ -2515,12 +2526,13 @@ fopen_existing_file(Tab, OpenArgs) ->
V9 = (Version =:= 9) or (Version =:= default),
MinF = (MinSlots =:= default) or (MinSlots =:= FH#fileheader.min_no_slots),
MaxF = (MaxSlots =:= default) or (MaxSlots =:= FH#fileheader.max_no_slots),
- Do = case (FH#fileheader.mod):check_file_header(FH, Fd) of
+ Mod = (FH#fileheader.mod),
+ Wh = case Mod:check_file_header(FH, Fd) of
{ok, Head, true} when Rep =:= force, Acc =:= read_write,
FH#fileheader.version =:= 9,
FH#fileheader.no_colls =/= undefined,
MinF, MaxF, V9 ->
- {compact, Head};
+ {compact, Head, true};
{ok, _Head, _Extra} when Rep =:= force, Acc =:= read ->
throw({error, {access_mode, Fname}});
{ok, Head, need_compacting} when Acc =:= read ->
@@ -2550,6 +2562,17 @@ fopen_existing_file(Tab, OpenArgs) ->
{error, Reason} ->
throw({error, {Reason, Fname}})
end,
+ Do = case Wh of
+ {Tag, Hd, Extra} when Tag =:= final; Tag =:= compact ->
+ Hd1 = Hd#head{filename = Fname},
+ try {Tag, Mod:init_freelist(Hd1, Extra)}
+ catch
+ throw:_ ->
+ {repair, " has bad free lists, repairing ..."}
+ end;
+ Else ->
+ Else
+ end,
case Do of
_ when FH#fileheader.type =/= Type ->
throw({error, {type_mismatch, Fname}});
@@ -2558,8 +2581,7 @@ fopen_existing_file(Tab, OpenArgs) ->
{compact, SourceHead} ->
io:format(user, "dets: file ~p is now compacted ...~n", [Fname]),
{ok, NewSourceHead} = open_final(SourceHead, Fname, read, false,
- ?DEFAULT_CACHE, Tab, true,
- Debug),
+ ?DEFAULT_CACHE, Tab, Debug),
case catch compact(NewSourceHead) of
ok ->
erlang:garbage_collect(),
@@ -2579,9 +2601,9 @@ fopen_existing_file(Tab, OpenArgs) ->
Version, OpenArgs);
_ when FH#fileheader.version =/= Version, Version =/= default ->
throw({error, {version_mismatch, Fname}});
- {final, H, EI} ->
+ {final, H} ->
H1 = H#head{auto_save = Auto},
- open_final(H1, Fname, Acc, Ram, CacheSz, Tab, EI, Debug)
+ open_final(H1, Fname, Acc, Ram, CacheSz, Tab, Debug)
end.
do_repair(Fd, Tab, Fname, FH, MinSlots, MaxSlots, Version, OpenArgs) ->
@@ -2595,19 +2617,16 @@ do_repair(Fd, Tab, Fname, FH, MinSlots, MaxSlots, Version, OpenArgs) ->
end.
%% -> {ok, head()} | throw(Error)
-open_final(Head, Fname, Acc, Ram, CacheSz, Tab, ExtraInfo, Debug) ->
+open_final(Head, Fname, Acc, Ram, CacheSz, Tab, Debug) ->
Head1 = Head#head{access = Acc,
ram_file = Ram,
filename = Fname,
name = Tab,
cache = dets_utils:new_cache(CacheSz)},
init_disk_map(Head1#head.version, Tab, Debug),
- Mod = Head#head.mod,
- Mod:cache_segps(Head1#head.fptr, Fname, Head1#head.next),
- Ftab = Mod:init_freelist(Head1, ExtraInfo),
+ (Head1#head.mod):cache_segps(Head1#head.fptr, Fname, Head1#head.next),
check_growth(Head1),
- NewHead = Head1#head{freelists = Ftab},
- {ok, NewHead}.
+ {ok, Head1}.
%% -> {ok, head()} | throw(Error)
fopen_init_file(Tab, OpenArgs) ->
@@ -3134,8 +3153,12 @@ init_scan(Head, NoObjs) ->
check_safe_fixtable(Head),
FreeLists = dets_utils:get_freelists(Head),
Base = Head#head.base,
- {From, To} = dets_utils:find_next_allocated(FreeLists, Base, Base),
- #dets_cont{no_objs = NoObjs, bin = <<>>, alloc = {From, To, <<>>}}.
+ case dets_utils:find_next_allocated(FreeLists, Base, Base) of
+ {From, To} ->
+ #dets_cont{no_objs = NoObjs, bin = <<>>, alloc = {From,To,<<>>}};
+ none ->
+ #dets_cont{no_objs = NoObjs, bin = eof, alloc = <<>>}
+ end.
check_safe_fixtable(Head) ->
case (Head#head.fixed =:= false) andalso
@@ -3236,18 +3259,20 @@ view(FileName) ->
case catch read_file_header(FileName, read, false) of
{ok, Fd, FH} ->
Mod = FH#fileheader.mod,
- case Mod:check_file_header(FH, Fd) of
- {ok, H0, ExtraInfo} ->
- Ftab = Mod:init_freelist(H0, ExtraInfo),
- {_Bump, Base} = constants(FH, FileName),
- H = H0#head{freelists=Ftab, base = Base},
- v_free_list(H),
- Mod:v_segments(H),
- file:close(Fd);
- X ->
- file:close(Fd),
- X
- end;
+ try Mod:check_file_header(FH, Fd) of
+ {ok, H0, ExtraInfo} ->
+ Mod = FH#fileheader.mod,
+ case Mod:check_file_header(FH, Fd) of
+ {ok, H0, ExtraInfo} ->
+ H = Mod:init_freelist(H0, ExtraInfo),
+ v_free_list(H),
+ Mod:v_segments(H),
+ ok;
+ X ->
+ X
+ end
+ after file:close(Fd)
+ end;
X ->
X
end.
diff --git a/lib/stdlib/src/dets.hrl b/lib/stdlib/src/dets.hrl
index fbffc9d008..a3f99357a2 100644
--- a/lib/stdlib/src/dets.hrl
+++ b/lib/stdlib/src/dets.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -92,6 +92,7 @@
%% Info extracted from the file header.
-record(fileheader, {
freelist,
+ fl_base,
cookie,
closed_properly,
type,
diff --git a/lib/stdlib/src/dets_v8.erl b/lib/stdlib/src/dets_v8.erl
index af36958c1c..3e962a1c8b 100644
--- a/lib/stdlib/src/dets_v8.erl
+++ b/lib/stdlib/src/dets_v8.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -21,7 +21,7 @@
%% Dets files, implementation part. This module handles versions up to
%% and including 8(c). To be called from dets.erl only.
--export([constants/0, mark_dirty/1, read_file_header/2,
+-export([mark_dirty/1, read_file_header/2,
check_file_header/2, do_perform_save/1, initiate_file/11,
init_freelist/2, fsck_input/4,
bulk_input/3, output_objs/4, write_cache/1, may_grow/3,
@@ -163,7 +163,7 @@
%% The 8(c) version uses a different hashing algorithm, erlang:phash
%% (former versions use erlang:hash).
%% Version 8(b) files are only converted to version 8(c) if repair is
-%% done, so we need compatability with 8(b) for a _long_ time.
+%% done, so we need compatibility with 8(b) for a _long_ time.
%%
%% There are known bugs due to the fact that keys and objects are
%% sometimes compared (==) and sometimes matched (=:=). The version
@@ -196,10 +196,6 @@
%%-define(DEBUGF(X,Y), io:format(X, Y)).
-define(DEBUGF(X,Y), void).
-%% {Bump}
-constants() ->
- {?BUMP, ?BASE}.
-
%% -> ok | throw({NewHead,Error})
mark_dirty(Head) ->
Dirty = [{?CLOSED_PROPERLY_POS, <<?NOT_PROPERLY_CLOSED:32>>}],
@@ -308,8 +304,9 @@ init_freelist(Head, {convert_freelist,_Version}) ->
Pos = Head#head.freelists_p,
case catch prterm(Head, Pos, ?OHDSZ) of
{0, _Sz, Term} ->
- FreeList = lists:reverse(Term),
- dets_utils:init_slots_from_old_file(FreeList, Ftab);
+ FreeList1 = lists:reverse(Term),
+ FreeList = dets_utils:init_slots_from_old_file(FreeList1, Ftab),
+ Head#head{freelists = FreeList, base = ?BASE};
_ ->
throw({error, {bad_freelists, Head#head.filename}})
end;
@@ -318,7 +315,7 @@ init_freelist(Head, _) ->
Pos = Head#head.freelists_p,
case catch prterm(Head, Pos, ?OHDSZ) of
{0, _Sz, Term} ->
- Term;
+ Head#head{freelists = Term, base = ?BASE};
_ ->
throw({error, {bad_freelists, Head#head.filename}})
end.
@@ -331,6 +328,7 @@ read_file_header(Fd, FileName) ->
{ok, EOF} = dets_utils:position_close(Fd, FileName, eof),
{ok, <<FileSize:32>>} = dets_utils:pread_close(Fd, FileName, EOF-4, 4),
FH = #fileheader{freelist = Freelist,
+ fl_base = ?BASE,
cookie = Cookie,
closed_properly = CP,
type = dets_utils:code_to_type(Type2),
@@ -413,7 +411,7 @@ check_file_header(FH, Fd) ->
version = ?FILE_FORMAT_VERSION,
mod = ?MODULE,
bump = ?BUMP,
- base = ?BASE},
+ base = FH#fileheader.fl_base},
{ok, H, ExtraInfo};
Error ->
Error
diff --git a/lib/stdlib/src/dets_v9.erl b/lib/stdlib/src/dets_v9.erl
index 132af01f79..f577b4410f 100644
--- a/lib/stdlib/src/dets_v9.erl
+++ b/lib/stdlib/src/dets_v9.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -21,7 +21,7 @@
%% Dets files, implementation part. This module handles version 9.
%% To be called from dets.erl only.
--export([constants/0, mark_dirty/1, read_file_header/2,
+-export([mark_dirty/1, read_file_header/2,
check_file_header/2, do_perform_save/1, initiate_file/11,
prep_table_copy/9, init_freelist/2, fsck_input/4,
bulk_input/3, output_objs/4, bchunk_init/2,
@@ -70,6 +70,17 @@
%% 16 MD5-sum for the 44 plus 112 bytes before the MD5-sum.
%% (FreelistsPointer, Cookie and ClosedProperly are not digested.)
%% 128 Reserved for future versions. Initially zeros.
+%% Version 9(d), introduced in R15A, has instead:
+%% 112 28 counters for the buddy system sizes (as for 9(b)).
+%% 16 MD5-sum for the 44 plus 112 bytes before the MD5-sum.
+%% (FreelistsPointer, Cookie and ClosedProperly are not digested.)
+%% 4 Base of the buddy system.
+%% 0 (zero) if the base is equal to ?BASE. Compatible with R14B.
+%% File size at the end of the file is RealFileSize - Base.
+%% The reason for modifying file size is that when a file created
+%% by R15 is read by R14 a repair takes place immediately, which
+%% is acceptable when downgrading.
+%% 124 Reserved for future versions. Initially zeros.
%% ---
%% ------------------ end of file header
%% 4*256 SegmentArray Pointers.
@@ -86,7 +97,7 @@
%% -----------------------------
%% ??? Free lists
%% -----------------------------
-%% 4 File size, in bytes.
+%% 4 File size, in bytes. See 9(d) obove.
%% Before we can find an object we must find the slot where the
%% object resides. Each slot is a (possibly empty) list (or chain) of
@@ -177,14 +188,14 @@
%%% File header
%%%
--define(RESERVED, 128). % Reserved for future use.
+-define(RESERVED, 124). % Reserved for future use.
-define(COLL_CNTRS, (28*4)). % Counters for the buddy system.
-define(MD5SZ, 16).
+-define(FL_BASE, 4).
--define(HEADSZ,
- 56+?COLL_CNTRS+?MD5SZ). % The size of the file header, in bytes,
- % not including the reserved part.
+-define(HEADSZ, 56+?COLL_CNTRS % The size of the file header, in bytes,
+ +?MD5SZ+?FL_BASE). % not including the reserved part.
-define(HEADEND, (?HEADSZ+?RESERVED)).
% End of header and reserved area.
-define(SEGSZ, 512). % Size of a segment, in words. SZOBJP*SEGSZP.
@@ -270,10 +281,6 @@
%%-define(DEBUGF(X,Y), io:format(X, Y)).
-define(DEBUGF(X,Y), void).
-%% {Bump}
-constants() ->
- {?BUMP, ?BASE}.
-
%% -> ok | throw({NewHead,Error})
mark_dirty(Head) ->
Dirty = [{?CLOSED_PROPERLY_POS, <<?NOT_PROPERLY_CLOSED:32>>}],
@@ -356,7 +363,7 @@ init_file(Fd, Tab, Fname, Type, Kp, MinSlots, MaxSlots, Ram, CacheSz,
cache = dets_utils:new_cache(CacheSz),
version = ?FILE_FORMAT_VERSION,
bump = ?BUMP,
- base = ?BASE,
+ base = ?BASE, % to be overwritten
mod = ?MODULE
},
@@ -378,13 +385,20 @@ init_file(Fd, Tab, Fname, Type, Kp, MinSlots, MaxSlots, Ram, CacheSz,
{Head1, Ws1} = init_parts(Head0, 0, no_parts(Next), Zero, []),
NoSegs = no_segs(Next),
- {Head, WsI, WsP} = init_segments(Head1, 0, NoSegs, Zero, [], []),
+ {Head2, WsI, WsP} = init_segments(Head1, 0, NoSegs, Zero, [], []),
Ws2 = if
DoInitSegments -> WsP ++ WsI;
true -> WsP
end,
dets_utils:pwrite(Fd, Fname, [W0 | lists:append(Ws1) ++ Ws2]),
- true = hash_invars(Head),
+ true = hash_invars(Head2),
+ %% The allocations that have been made so far (parts, segments)
+ %% are permanent; the table will never shrink. Therefore the base
+ %% of the Buddy system can be set to the first free object.
+ %% This is used in allocate_all(), see below.
+ {_, Where, _} = dets_utils:alloc(Head2, ?BUMP),
+ NewFtab = dets_utils:init_alloc(Where),
+ Head = Head2#head{freelists = NewFtab, base = Where},
{ok, Head}.
%% Returns a power of two not less than 256.
@@ -451,8 +465,9 @@ read_file_header(Fd, FileName) ->
Version:32, M:32, Next:32, Kp:32,
NoObjects:32, NoKeys:32, MinNoSlots:32, MaxNoSlots:32,
HashMethod:32, N:32, NoCollsB:?COLL_CNTRS/binary,
- MD5:?MD5SZ/binary>> = Bin,
- <<_:12/binary,MD5DigestedPart:(?HEADSZ-?MD5SZ-12)/binary,_/binary>> = Bin,
+ MD5:?MD5SZ/binary, FlBase:32>> = Bin,
+ <<_:12/binary,MD5DigestedPart:(?HEADSZ-?MD5SZ-?FL_BASE-12)/binary,
+ _/binary>> = Bin,
{ok, EOF} = dets_utils:position_close(Fd, FileName, eof),
{ok, <<FileSize:32>>} = dets_utils:pread_close(Fd, FileName, EOF-4, 4),
{CL, <<>>} = lists:foldl(fun(LSz, {Acc,<<NN:32,R/binary>>}) ->
@@ -468,8 +483,12 @@ read_file_header(Fd, FileName) ->
true ->
lists:reverse(CL)
end,
-
+ Base = case FlBase of
+ 0 -> ?BASE;
+ _ -> FlBase
+ end,
FH = #fileheader{freelist = FreeList,
+ fl_base = Base,
cookie = Cookie,
closed_properly = CP,
type = dets_utils:code_to_type(Type2),
@@ -486,7 +505,7 @@ read_file_header(Fd, FileName) ->
read_md5 = MD5,
has_md5 = <<0:?MD5SZ/unit:8>> =/= MD5,
md5 = erlang:md5(MD5DigestedPart),
- trailer = FileSize,
+ trailer = FileSize + FlBase,
eof = EOF,
n = N,
mod = ?MODULE},
@@ -544,7 +563,7 @@ check_file_header(FH, Fd) ->
version = ?FILE_FORMAT_VERSION,
mod = ?MODULE,
bump = ?BUMP,
- base = ?BASE},
+ base = FH#fileheader.fl_base},
{ok, H, ExtraInfo};
Error ->
Error
@@ -1185,41 +1204,25 @@ write_loop(Head, BytesToWrite, Bin) ->
write_loop(Head, BytesToWrite, SmallBin).
%% By allocating bigger objects before smaller ones, holes in the
-%% buddy system memory map are avoided. Unfortunately, the segments
-%% are always allocated first, so if there are objects bigger than a
-%% segment, there is a hole to handle. (Haven't considered placing the
-%% segments among other objects of the same size.)
+%% buddy system memory map are avoided.
allocate_all_objects(Head, SizeT) ->
DTL = lists:reverse(lists:keysort(1, ets:tab2list(SizeT))),
MaxSz = element(1, hd(DTL)),
- SegSize = ?ACTUAL_SEG_SIZE,
- {Head1, HSz, HN, HA} = alloc_hole(MaxSz, Head, SegSize),
- {Head2, NL} = allocate_all(Head1, DTL, []),
+ {Head1, NL} = allocate_all(Head, DTL, []),
%% Find the position that will be the end of the file by allocating
%% a minimal object.
- {_Head, EndOfFile, _} = dets_utils:alloc(Head2, ?BUMP),
- Head3 = free_hole(Head2, HSz, HN, HA),
- NewHead = Head3#head{maxobjsize = max_objsize(Head3#head.no_collections)},
+ {_Head, EndOfFile, _} = dets_utils:alloc(Head1, ?BUMP),
+ NewHead = Head1#head{maxobjsize = max_objsize(Head1#head.no_collections)},
{NewHead, NL, MaxSz, EndOfFile}.
-alloc_hole(LSize, Head, SegSz) when ?POW(LSize-1) > SegSz ->
- Size = ?POW(LSize-1),
- {_, SegAddr, _} = dets_utils:alloc(Head, adjsz(SegSz)),
- {_, Addr, _} = dets_utils:alloc(Head, adjsz(Size)),
- N = (Addr - SegAddr) div SegSz,
- Head1 = dets_utils:alloc_many(Head, SegSz, N, SegAddr),
- {Head1, SegSz, N, SegAddr};
-alloc_hole(_MaxSz, Head, _SegSz) ->
- {Head, 0, 0, 0}.
-
-free_hole(Head, _Size, 0, _Addr) ->
- Head;
-free_hole(Head, Size, N, Addr) ->
- {Head1, _} = dets_utils:free(Head, Addr, adjsz(Size)),
- free_hole(Head1, Size, N-1, Addr+Size).
-
%% One (temporary) file for each buddy size, write all objects of that
%% size to the file.
+%%
+%% Before R15 a "hole" was needed before the first bucket if the size
+%% of the biggest bucket was greater than the size of a segment. The
+%% hole proved to be a problem with almost full tables with huge
+%% buckets. Since R15 the hole is no longer needed due to the fact
+%% that the base of the Buddy system is flexible.
allocate_all(Head, [{?FSCK_SEGMENT,_,Data,_}], L) ->
%% And one file for the segments...
%% Note that space for the array parts and the segments has
@@ -1593,23 +1596,28 @@ do_perform_save(H) ->
H1 = H#head{freelists_p = FreeListsPointer},
{FLW, FLSize} = free_lists_to_file(H1),
FileSize = FreeListsPointer + FLSize + 4,
- ok = dets_utils:write(H1, [FLW | <<FileSize:32>>]),
+ AdjustedFileSize = case H#head.base of
+ ?BASE -> FileSize;
+ Base -> FileSize - Base
+ end,
+ ok = dets_utils:write(H1, [FLW | <<AdjustedFileSize:32>>]),
FileHeader = file_header(H1, FreeListsPointer, ?CLOSED_PROPERLY),
case dets_utils:debug_mode() of
true ->
- TmpHead = H1#head{freelists = init_freelist(H1, true),
- fixed = false},
+ TmpHead0 = init_freelist(H1#head{fixed = false}, true),
+ TmpHead = TmpHead0#head{base = H1#head.base},
case
catch dets_utils:all_allocated_as_list(TmpHead)
=:= dets_utils:all_allocated_as_list(H1)
- of
+ of
true ->
dets_utils:pwrite(H1, [{0, FileHeader}]);
_ ->
+ throw(
dets_utils:corrupt_reason(H1, {failed_to_save_free_lists,
FreeListsPointer,
TmpHead#head.freelists,
- H1#head.freelists})
+ H1#head.freelists}))
end;
false ->
dets_utils:pwrite(H1, [{0, FileHeader}])
@@ -1648,7 +1656,11 @@ file_header(Head, FreeListsPointer, ClosedProperly, NoColls) ->
true -> erlang:md5(DigH);
false -> <<0:?MD5SZ/unit:8>>
end,
- [H1, DigH, MD5 | <<0:?RESERVED/unit:8>>].
+ Base = case Head#head.base of
+ ?BASE -> <<0:32>>;
+ FlBase -> <<FlBase:32>>
+ end,
+ [H1, DigH, MD5, Base | <<0:?RESERVED/unit:8>>].
%% Going through some trouble to avoid creating one single binary for
%% the free lists. If the free lists are huge, binary_to_term and
@@ -1695,8 +1707,8 @@ free_lists_from_file(H, Pos) ->
case catch bin_to_tree([], H, start, FL, -1, []) of
{'EXIT', _} ->
throw({error, {bad_freelists, H#head.filename}});
- Reply ->
- Reply
+ Ftab ->
+ H#head{freelists = Ftab, base = ?BASE}
end.
bin_to_tree(Bin, H, LastPos, Ftab, A0, L) ->
diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl
index d804c1dee5..ccc14610d7 100644
--- a/lib/stdlib/src/epp.erl
+++ b/lib/stdlib/src/epp.erl
@@ -267,8 +267,10 @@ init_server(Pid, Name, File, AtLocation, Path, Pdm, Pre) ->
case user_predef(Pdm, Ms0) of
{ok,Ms1} ->
epp_reply(Pid, {ok,self()}),
+ %% ensure directory of current source file is first in path
+ Path1 = [filename:dirname(Name) | Path],
St = #epp{file=File, location=AtLocation, delta=0, name=Name,
- name2=Name, path=Path, macs=Ms1, pre_opened = Pre},
+ name2=Name, path=Path1, macs=Ms1, pre_opened = Pre},
From = wait_request(St),
enter_file_reply(From, Name, AtLocation, AtLocation),
wait_req_scan(St);
@@ -360,18 +362,18 @@ wait_req_skip(St, Sis) ->
From = wait_request(St),
skip_toks(From, St, Sis).
-%% enter_file(Path, FileName, IncludeToken, From, EppState)
+%% enter_file(FileName, IncludeToken, From, EppState)
%% leave_file(From, EppState)
%% Handle entering and leaving included files. Notify caller when the
%% current file is changed. Note it is an error to exit a file if we are
%% in a conditional. These functions never return.
-enter_file(_Path, _NewName, Inc, From, St)
+enter_file(_NewName, Inc, From, St)
when length(St#epp.sstk) >= 8 ->
epp_reply(From, {error,{abs_loc(Inc),epp,{depth,"include"}}}),
wait_req_scan(St);
-enter_file(Path, NewName, Inc, From, St) ->
- case file:path_open(Path, NewName, [read]) of
+enter_file(NewName, Inc, From, St) ->
+ case file:path_open(St#epp.path, NewName, [read]) of
{ok,NewF,Pname} ->
Loc = start_loc(St#epp.location),
wait_req_scan(enter_file2(NewF, Pname, From, St, Loc));
@@ -384,13 +386,16 @@ enter_file(Path, NewName, Inc, From, St) ->
%% Set epp to use this file and "enter" it.
enter_file2(NewF, Pname, From, St, AtLocation) ->
- enter_file2(NewF, Pname, From, St, AtLocation, []).
-
-enter_file2(NewF, Pname, From, St, AtLocation, ExtraPath) ->
Loc = start_loc(AtLocation),
enter_file_reply(From, Pname, Loc, AtLocation),
Ms = dict:store({atom,'FILE'}, {none,[{string,Loc,Pname}]}, St#epp.macs),
- Path = St#epp.path ++ ExtraPath,
+ %% update the head of the include path to be the directory of the new
+ %% source file, so that an included file can always include other files
+ %% relative to its current location (this is also how C does it); note
+ %% that the directory of the parent source file (the previous head of
+ %% the path) must be dropped, otherwise the path used within the current
+ %% file will depend on the order of file inclusions in the parent files
+ Path = [filename:dirname(Pname) | tl(St#epp.path)],
#epp{file=NewF,location=Loc,name=Pname,delta=0,
sstk=[St|St#epp.sstk],path=Path,macs=Ms}.
@@ -655,7 +660,7 @@ scan_undef(_Toks, Undef, From, St) ->
scan_include([{'(',_Llp},{string,_Lf,NewName0},{')',_Lrp},{dot,_Ld}], Inc,
From, St) ->
NewName = expand_var(NewName0),
- enter_file(St#epp.path, NewName, Inc, From, St);
+ enter_file(NewName, Inc, From, St);
scan_include(_Toks, Inc, From, St) ->
epp_reply(From, {error,{abs_loc(Inc),epp,{bad,include}}}),
wait_req_scan(St).
@@ -684,12 +689,11 @@ scan_include_lib([{'(',_Llp},{string,_Lf,NewName0},{')',_Lrp},{dot,_Ld}],
{error,_E1} ->
case catch find_lib_dir(NewName) of
{LibDir, Rest} when is_list(LibDir) ->
- LibName = filename:join([LibDir | Rest]),
+ LibName = fname_join([LibDir | Rest]),
case file:open(LibName, [read]) of
{ok,NewF} ->
- ExtraPath = [filename:dirname(LibName)],
wait_req_scan(enter_file2(NewF, LibName, From,
- St, Loc, ExtraPath));
+ St, Loc));
{error,_E2} ->
epp_reply(From,
{error,{abs_loc(Inc),epp,
@@ -1154,7 +1158,12 @@ expand_var1(NewName) ->
[[$$ | Var] | Rest] = filename:split(NewName),
Value = os:getenv(Var),
true = Value =/= false,
- {ok, filename:join([Value | Rest])}.
+ {ok, fname_join([Value | Rest])}.
+
+fname_join(["." | [_|_]=Rest]) ->
+ fname_join(Rest);
+fname_join(Components) ->
+ filename:join(Components).
%% The line only. (Other tokens may have the column and text as well...)
loc_attr(Line) when is_integer(Line) ->
diff --git a/lib/stdlib/src/erl_compile.erl b/lib/stdlib/src/erl_compile.erl
index abff37e4bc..ff032b129c 100644
--- a/lib/stdlib/src/erl_compile.erl
+++ b/lib/stdlib/src/erl_compile.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -41,7 +41,6 @@ compiler(".idl") -> {ic, compile};
compiler(".asn1") -> {asn1ct, compile_asn1};
compiler(".asn") -> {asn1ct, compile_asn};
compiler(".py") -> {asn1ct, compile_py};
-compiler(".xml") -> {xmerl_scan, process};
compiler(_) -> no.
%% Entry from command line.
diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl
index 515ea2ebb7..88a0094d57 100644
--- a/lib/stdlib/src/erl_eval.erl
+++ b/lib/stdlib/src/erl_eval.erl
@@ -256,7 +256,8 @@ expr({'receive',_,Cs}, Bs, Lf, Ef, RBs) ->
expr({'receive',_, Cs, E, TB}, Bs0, Lf, Ef, RBs) ->
{value,T,Bs} = expr(E, Bs0, Lf, Ef, none),
receive_clauses(T, Cs, {TB,Bs}, Bs0, Lf, Ef, [], RBs);
-expr({'fun',_Line,{function,Mod,Name,Arity}}, Bs, _Lf, _Ef, RBs) ->
+expr({'fun',_Line,{function,Mod0,Name0,Arity0}}, Bs0, Lf, Ef, RBs) ->
+ {[Mod,Name,Arity],Bs} = expr_list([Mod0,Name0,Arity0], Bs0, Lf, Ef),
F = erlang:make_fun(Mod, Name, Arity),
ret_expr(F, Bs, RBs);
expr({'fun',_Line,{function,Name,Arity}}, _Bs0, _Lf, _Ef, _RBs) -> % R8
@@ -621,7 +622,7 @@ eval_generate(Term, _P, _Bs0, _Lf, _Ef, _CompFun, _Acc) ->
erlang:raise(error, {bad_generator,Term}, stacktrace()).
eval_b_generate(<<_/bitstring>>=Bin, P, Bs0, Lf, Ef, CompFun, Acc) ->
- Mfun = fun(L, R, Bs) -> match1(L, R, Bs, Bs0) end,
+ Mfun = match_fun(Bs0),
Efun = fun(Exp, Bs) -> expr(Exp, Bs, Lf, Ef, none) end,
case eval_bits:bin_gen(P, Bin, new_bindings(), Bs0, Mfun, Efun) of
{match, Rest, Bs1} ->
@@ -1024,7 +1025,7 @@ match1({tuple,_,_}, _, _Bs, _BBs) ->
throw(nomatch);
match1({bin, _, Fs}, <<_/bitstring>>=B, Bs0, BBs) ->
eval_bits:match_bits(Fs, B, Bs0, BBs,
- fun(L, R, Bs) -> match1(L, R, Bs, BBs) end,
+ match_fun(BBs),
fun(E, Bs) -> expr(E, Bs, none, none, none) end);
match1({bin,_,_}, _, _Bs, _BBs) ->
throw(nomatch);
@@ -1053,6 +1054,12 @@ match1({op,Line,Op,L,R}, Term, Bs, BBs) ->
match1(_, _, _Bs, _BBs) ->
throw(invalid).
+match_fun(BBs) ->
+ fun(match, {L,R,Bs}) -> match1(L, R, Bs, BBs);
+ (binding, {Name,Bs}) -> binding(Name, Bs);
+ (add_binding, {Name,Val,Bs}) -> add_binding(Name, Val, Bs)
+ end.
+
match_tuple([E|Es], Tuple, I, Bs0, BBs) ->
{match,Bs} = match1(E, element(I, Tuple), Bs0, BBs),
match_tuple(Es, Tuple, I+1, Bs, BBs);
diff --git a/lib/stdlib/src/erl_expand_records.erl b/lib/stdlib/src/erl_expand_records.erl
index eada563914..20fd247cea 100644
--- a/lib/stdlib/src/erl_expand_records.erl
+++ b/lib/stdlib/src/erl_expand_records.erl
@@ -35,7 +35,7 @@
trecords=sets:new(), % Typed records
uses_types=false, % Are there -spec or -type in the module
strict_ra=[], % strict record accesses
- checked_ra=[] % succesfully accessed records
+ checked_ra=[] % successfully accessed records
}).
-spec(module(AbsForms, CompileOptions) -> AbsForms when
diff --git a/lib/stdlib/src/erl_internal.erl b/lib/stdlib/src/erl_internal.erl
index 478f05e792..cd3b531d10 100644
--- a/lib/stdlib/src/erl_internal.erl
+++ b/lib/stdlib/src/erl_internal.erl
@@ -262,8 +262,8 @@ bif(bitsize, 1) -> true;
bif(bit_size, 1) -> true;
bif(bitstring_to_list, 1) -> true;
bif(byte_size, 1) -> true;
+bif(check_old_code, 1) -> true;
bif(check_process_code, 2) -> true;
-bif(concat_binary, 1) -> true;
bif(date, 0) -> true;
bif(delete_module, 1) -> true;
bif(demonitor, 1) -> true;
@@ -405,7 +405,6 @@ old_bif(bit_size, 1) -> true;
old_bif(bitstring_to_list, 1) -> true;
old_bif(byte_size, 1) -> true;
old_bif(check_process_code, 2) -> true;
-old_bif(concat_binary, 1) -> true;
old_bif(date, 0) -> true;
old_bif(delete_module, 1) -> true;
old_bif(disconnect_node, 1) -> true;
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index dd0b9bc2ab..5d45260fe9 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -123,6 +123,7 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) ->
called= [] :: [{fa(),line()}], %Called functions
usage = #usage{} :: #usage{},
specs = dict:new() :: dict(), %Type specifications
+ callbacks = dict:new() :: dict(), %Callback types
types = dict:new() :: dict(), %Type definitions
exp_types=gb_sets:empty():: gb_set() %Exported types
}).
@@ -310,8 +311,6 @@ format_error({conflicting_behaviours,{Name,Arity},B,FirstL,FirstB}) ->
format_error({undefined_behaviour_func, {Func,Arity}, Behaviour}) ->
io_lib:format("undefined callback function ~w/~w (behaviour '~w')",
[Func,Arity,Behaviour]);
-format_error({undefined_behaviour_func, {Func,Arity,_Spec}, Behaviour}) ->
- format_error({undefined_behaviour_func, {Func,Arity}, Behaviour});
format_error({undefined_behaviour,Behaviour}) ->
io_lib:format("behaviour ~w undefined", [Behaviour]);
format_error({undefined_behaviour_callbacks,Behaviour}) ->
@@ -320,6 +319,9 @@ format_error({undefined_behaviour_callbacks,Behaviour}) ->
format_error({ill_defined_behaviour_callbacks,Behaviour}) ->
io_lib:format("behaviour ~w callback functions erroneously defined",
[Behaviour]);
+format_error({behaviour_info, {_M,F,A}}) ->
+ io_lib:format("cannot define callback attibute for ~w/~w when "
+ "behaviour_info is defined",[F,A]);
%% --- types and specs ---
format_error({singleton_typevar, Name}) ->
io_lib:format("type variable ~w is only used once (is unbound)", [Name]);
@@ -348,12 +350,16 @@ format_error({type_syntax, Constr}) ->
io_lib:format("bad ~w type", [Constr]);
format_error({redefine_spec, {M, F, A}}) ->
io_lib:format("spec for ~w:~w/~w already defined", [M, F, A]);
+format_error({redefine_callback, {M, F, A}}) ->
+ io_lib:format("callback ~w:~w/~w already defined", [M, F, A]);
format_error({spec_fun_undefined, {M, F, A}}) ->
io_lib:format("spec for undefined function ~w:~w/~w", [M, 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";
+format_error(callback_wrong_arity) ->
+ "callback has the wrong arity";
format_error({imported_predefined_type, Name}) ->
io_lib:format("referring to built-in type ~w as a remote type; "
"please take out the module name", [Name]);
@@ -747,6 +753,8 @@ attribute_state({attribute,L,opaque,{TypeName,TypeDef,Args}}, St) ->
type_def(opaque, L, TypeName, TypeDef, Args, St);
attribute_state({attribute,L,spec,{Fun,Types}}, St) ->
spec_decl(L, Fun, Types, St);
+attribute_state({attribute,L,callback,{Fun,Types}}, St) ->
+ callback_decl(L, Fun, Types, St);
attribute_state({attribute,L,on_load,Val}, St) ->
on_load(L, Val, St);
attribute_state({attribute,_L,_Other,_Val}, St) -> % Ignore others
@@ -840,7 +848,8 @@ post_traversal_check(Forms, St0) ->
StB = check_unused_types(Forms, StA),
StC = check_untyped_records(Forms, StB),
StD = check_on_load(StC),
- check_unused_records(Forms, StD).
+ StE = check_unused_records(Forms, StD),
+ check_callback_information(StE).
%% check_behaviour(State0) -> State
%% Check that the behaviour attribute is valid.
@@ -1139,6 +1148,23 @@ check_unused_records(Forms, St0) ->
St0
end.
+check_callback_information(#lint{callbacks = Callbacks,
+ defined = Defined} = State) ->
+ case gb_sets:is_member({behaviour_info,1}, Defined) of
+ false -> State;
+ true ->
+ case dict:size(Callbacks) of
+ 0 -> State;
+ _ ->
+ CallbacksList = dict:to_list(Callbacks),
+ FoldL =
+ fun({Fa,Line},St) ->
+ add_error(Line, {behaviour_info, Fa}, St)
+ end,
+ lists:foldl(FoldL, State, CallbacksList)
+ end
+ end.
+
%% For storing the import list we use the orddict module.
%% We know an empty set is [].
@@ -2101,8 +2127,13 @@ expr({'fun',Line,Body}, Vt, St) ->
true -> {[],St};
false -> {[],call_function(Line, F, A, St)}
end;
- {function,_M,_F,_A} ->
- {[],St}
+ {function,M,F,A} when is_atom(M), is_atom(F), is_integer(A) ->
+ %% Compatibility with pre-R15 abstract format.
+ {[],St};
+ {function,M,F,A} ->
+ %% New in R15.
+ {Bvt, St1} = expr_list([M,F,A], Vt, St),
+ {vtupdate(Bvt, Vt),St1}
end;
expr({call,_Line,{atom,_Lr,is_record},[E,{atom,Ln,Name}]}, Vt, St0) ->
{Rvt,St1} = expr(E, Vt, St0),
@@ -2770,6 +2801,20 @@ spec_decl(Line, MFA0, TypeSpecs, St0 = #lint{specs = Specs, module = Mod}) ->
false -> check_specs(TypeSpecs, Arity, St1)
end.
+%% callback_decl(Line, Fun, Types, State) -> State.
+
+callback_decl(Line, MFA0, TypeSpecs,
+ St0 = #lint{callbacks = Callbacks, module = Mod}) ->
+ MFA = case MFA0 of
+ {F, Arity} -> {Mod, F, Arity};
+ {_M, _F, Arity} -> MFA0
+ end,
+ St1 = St0#lint{callbacks = dict:store(MFA, Line, Callbacks)},
+ case dict:is_key(MFA, Callbacks) of
+ true -> add_error(Line, {redefine_callback, MFA}, St1);
+ false -> check_specs(TypeSpecs, Arity, St1)
+ end.
+
check_specs([FunType|Left], Arity, St0) ->
{FunType1, CTypes} =
case FunType of
@@ -3275,6 +3320,8 @@ modify_line1({attribute,L,record,{Name,Fields}}, Mf) ->
{attribute,Mf(L),record,{Name,modify_line1(Fields, Mf)}};
modify_line1({attribute,L,spec,{Fun,Types}}, Mf) ->
{attribute,Mf(L),spec,{Fun,modify_line1(Types, Mf)}};
+modify_line1({attribute,L,callback,{Fun,Types}}, Mf) ->
+ {attribute,Mf(L),callback,{Fun,modify_line1(Types, Mf)}};
modify_line1({attribute,L,type,{TypeName,TypeDef,Args}}, Mf) ->
{attribute,Mf(L),type,{TypeName,modify_line1(TypeDef, Mf),
modify_line1(Args, Mf)}};
diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl
index bd5d65a1e1..928c10f7f2 100644
--- a/lib/stdlib/src/erl_parse.yrl
+++ b/lib/stdlib/src/erl_parse.yrl
@@ -35,7 +35,7 @@ tuple
%struct
record_expr record_tuple record_field record_fields
if_expr if_clause if_clauses case_expr cr_clause cr_clauses receive_expr
-fun_expr fun_clause fun_clauses
+fun_expr fun_clause fun_clauses atom_or_var integer_or_var
try_expr try_catch try_clause try_clauses query_expr
function_call argument_list
exprs guard
@@ -62,7 +62,7 @@ char integer float atom string var
'==' '/=' '=<' '<' '>=' '>' '=:=' '=/=' '<='
'<<' '>>'
'!' '=' '::' '..' '...'
-'spec' % helper
+'spec' 'callback' % helper
dot.
Expect 2.
@@ -77,6 +77,7 @@ attribute -> '-' atom attr_val : build_attribute('$2', '$3').
attribute -> '-' atom typed_attr_val : build_typed_attribute('$2','$3').
attribute -> '-' atom '(' typed_attr_val ')' : build_typed_attribute('$2','$4').
attribute -> '-' 'spec' type_spec : build_type_spec('$2', '$3').
+attribute -> '-' 'callback' type_spec : build_type_spec('$2', '$3').
type_spec -> spec_fun type_sigs : {'$1', '$2'}.
type_spec -> '(' spec_fun type_sigs ')' : {'$2', '$3'}.
@@ -394,11 +395,17 @@ receive_expr -> 'receive' cr_clauses 'after' expr clause_body 'end' :
fun_expr -> 'fun' atom '/' integer :
{'fun',?line('$1'),{function,element(3, '$2'),element(3, '$4')}}.
-fun_expr -> 'fun' atom ':' atom '/' integer :
- {'fun',?line('$1'),{function,element(3, '$2'),element(3, '$4'),element(3,'$6')}}.
+fun_expr -> 'fun' atom_or_var ':' atom_or_var '/' integer_or_var :
+ {'fun',?line('$1'),{function,'$2','$4','$6'}}.
fun_expr -> 'fun' fun_clauses 'end' :
build_fun(?line('$1'), '$2').
+atom_or_var -> atom : '$1'.
+atom_or_var -> var : '$1'.
+
+integer_or_var -> integer : '$1'.
+integer_or_var -> var : '$1'.
+
fun_clauses -> fun_clause : ['$1'].
fun_clauses -> fun_clause ';' fun_clauses : ['$1' | '$3'].
@@ -549,6 +556,8 @@ Erlang code.
ErrorInfo :: error_info().
parse_form([{'-',L1},{atom,L2,spec}|Tokens]) ->
parse([{'-',L1},{'spec',L2}|Tokens]);
+parse_form([{'-',L1},{atom,L2,callback}|Tokens]) ->
+ parse([{'-',L1},{'callback',L2}|Tokens]);
parse_form(Tokens) ->
parse(Tokens).
@@ -603,7 +612,8 @@ build_typed_attribute({atom,La,Attr},_) ->
_ -> ret_err(La, "bad attribute")
end.
-build_type_spec({spec,La}, {SpecFun, TypeSpecs}) ->
+build_type_spec({Kind,La}, {SpecFun, TypeSpecs})
+ when (Kind =:= spec) or (Kind =:= callback) ->
NewSpecFun =
case SpecFun of
{atom, _, Fun} ->
@@ -617,7 +627,7 @@ build_type_spec({spec,La}, {SpecFun, TypeSpecs}) ->
%% Old style spec. Allow this for now.
{Mod,Fun,Arity}
end,
- {attribute,La,spec,{NewSpecFun, TypeSpecs}}.
+ {attribute,La,Kind,{NewSpecFun, TypeSpecs}}.
find_arity_from_specs([Spec|_]) ->
%% Use the first spec to find the arity. If all are not the same,
diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl
index 7dc19f2e9b..6b5aa951cf 100644
--- a/lib/stdlib/src/erl_pp.erl
+++ b/lib/stdlib/src/erl_pp.erl
@@ -457,8 +457,16 @@ lexpr({'fun',_,{function,F,A}}, _Prec, _Hook) ->
leaf(format("fun ~w/~w", [F,A]));
lexpr({'fun',_,{function,F,A},Extra}, _Prec, _Hook) ->
{force_nl,fun_info(Extra),leaf(format("fun ~w/~w", [F,A]))};
-lexpr({'fun',_,{function,M,F,A}}, _Prec, _Hook) ->
+lexpr({'fun',_,{function,M,F,A}}, _Prec, _Hook)
+ when is_atom(M), is_atom(F), is_integer(A) ->
+ %% For backward compatibility with pre-R15 abstract format.
leaf(format("fun ~w:~w/~w", [M,F,A]));
+lexpr({'fun',_,{function,M,F,A}}, _Prec, Hook) ->
+ %% New format in R15.
+ NameItem = lexpr(M, Hook),
+ CallItem = lexpr(F, Hook),
+ ArityItem = lexpr(A, Hook),
+ ["fun ",NameItem,$:,CallItem,$/,ArityItem];
lexpr({'fun',_,{clauses,Cs}}, _Prec, Hook) ->
{list,[{first,'fun',fun_clauses(Cs, Hook)},'end']};
lexpr({'fun',_,{clauses,Cs},Extra}, _Prec, Hook) ->
diff --git a/lib/stdlib/src/erl_scan.erl b/lib/stdlib/src/erl_scan.erl
index 718ca2e91a..10b2ed2e49 100644
--- a/lib/stdlib/src/erl_scan.erl
+++ b/lib/stdlib/src/erl_scan.erl
@@ -408,7 +408,12 @@ set_attr(line, {Line,Column}, Fun) when ?ALINE(Line), ?COLUMN(Column) ->
end;
set_attr(line=Tag, Attrs, Fun) when is_list(Attrs) ->
{line,Line} = lists:keyfind(Tag, 1, Attrs),
- lists:keyreplace(Tag, 1, Attrs, {line,Fun(Line)});
+ case lists:keyreplace(Tag, 1, Attrs, {line,Fun(Line)}) of
+ [{line,Ln}] when ?ALINE(Ln) ->
+ Ln;
+ As ->
+ As
+ end;
set_attr(T1, T2, T3) ->
erlang:error(badarg, [T1,T2,T3]).
diff --git a/lib/stdlib/src/erl_tar.erl b/lib/stdlib/src/erl_tar.erl
index fd85c7aef5..306834e845 100644
--- a/lib/stdlib/src/erl_tar.erl
+++ b/lib/stdlib/src/erl_tar.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -798,30 +798,10 @@ set_extracted_file_info(Name, #tar_header{mode=Mode, mtime=Mtime}) ->
%% Makes all directories leading up to the file.
-make_dirs(Name, Type) ->
- make_dirs1(filename:split(Name), Type).
-
-make_dirs1([Dir, Next|Rest], Type) ->
- case file:read_file_info(Dir) of
- {ok, #file_info{type=directory}} ->
- make_dirs1([filename:join(Dir, Next)|Rest], Type);
- {ok, #file_info{}} ->
- throw({error, enotdir});
- {error, _} ->
- case file:make_dir(Dir) of
- ok ->
- make_dirs1([filename:join(Dir, Next)|Rest], Type);
- {error, Reason} ->
- throw({error, Reason})
- end
- end;
-make_dirs1([_], file) -> ok;
-make_dirs1([Dir], dir) ->
- file:make_dir(Dir);
-make_dirs1([], _) ->
- %% There must be something wrong here. The list was not supposed
- %% to be empty.
- throw({error, enoent}).
+make_dirs(Name, file) ->
+ filelib:ensure_dir(Name);
+make_dirs(Name, dir) ->
+ filelib:ensure_dir(filename:join(Name,"*")).
%% Prints the message on if the verbose option is given (for reading).
diff --git a/lib/stdlib/src/error_logger_tty_h.erl b/lib/stdlib/src/error_logger_tty_h.erl
index 435e57aa0e..fa13fbb2bd 100644
--- a/lib/stdlib/src/error_logger_tty_h.erl
+++ b/lib/stdlib/src/error_logger_tty_h.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -34,10 +34,12 @@
handle_event/2, handle_call/2, handle_info/2,
terminate/2, code_change/3]).
+-export([write_event/2]).
+
%% This one is used when we takeover from the simple error_logger.
init({[], {error_logger, Buf}}) ->
User = set_group_leader(),
- write_events(Buf),
+ write_events(Buf,io),
{ok, {User, error_logger}};
%% This one is used if someone took over from us, and now wants to
%% go back.
@@ -52,7 +54,7 @@ init([]) ->
handle_event({_Type, GL, _Msg}, State) when node(GL) =/= node() ->
{ok, State};
handle_event(Event, State) ->
- write_event(tag_event(Event)),
+ write_event(tag_event(Event),io),
{ok, State}.
handle_info({'EXIT', User, _Reason}, {User, PrevHandler}) ->
@@ -64,10 +66,10 @@ handle_info({'EXIT', User, _Reason}, {User, PrevHandler}) ->
PrevHandler, go_back}
end;
handle_info({emulator, GL, Chars}, State) when node(GL) == node() ->
- write_event(tag_event({emulator, GL, Chars})),
+ write_event(tag_event({emulator, GL, Chars}),io),
{ok, State};
handle_info({emulator, noproc, Chars}, State) ->
- write_event(tag_event({emulator, noproc, Chars})),
+ write_event(tag_event({emulator, noproc, Chars}),io),
{ok, State};
handle_info(_, State) ->
{ok, State}.
@@ -97,65 +99,65 @@ set_group_leader() ->
tag_event(Event) ->
{erlang:localtime(), Event}.
-write_events(Events) -> write_events1(lists:reverse(Events)).
+write_events(Events,IOMod) -> write_events1(lists:reverse(Events),IOMod).
-write_events1([Event|Es]) ->
- write_event(Event),
- write_events1(Es);
-write_events1([]) ->
+write_events1([Event|Es],IOMod) ->
+ write_event(Event,IOMod),
+ write_events1(Es,IOMod);
+write_events1([],_IOMod) ->
ok.
-write_event({Time, {error, _GL, {Pid, Format, Args}}}) ->
+write_event({Time, {error, _GL, {Pid, Format, Args}}},IOMod) ->
T = write_time(maybe_utc(Time)),
case catch io_lib:format(add_node(Format,Pid), Args) of
S when is_list(S) ->
- format(T ++ S);
+ format(IOMod, T ++ S);
_ ->
F = add_node("ERROR: ~p - ~p~n", Pid),
- format(T ++ F, [Format,Args])
+ format(IOMod, T ++ F, [Format,Args])
end;
-write_event({Time, {emulator, _GL, Chars}}) ->
+write_event({Time, {emulator, _GL, Chars}},IOMod) ->
T = write_time(maybe_utc(Time)),
case catch io_lib:format(Chars, []) of
S when is_list(S) ->
- format(T ++ S);
+ format(IOMod, T ++ S);
_ ->
- format(T ++ "ERROR: ~p ~n", [Chars])
+ format(IOMod, T ++ "ERROR: ~p ~n", [Chars])
end;
-write_event({Time, {info, _GL, {Pid, Info, _}}}) ->
+write_event({Time, {info, _GL, {Pid, Info, _}}},IOMod) ->
T = write_time(maybe_utc(Time)),
- format(T ++ add_node("~p~n",Pid),[Info]);
-write_event({Time, {error_report, _GL, {Pid, std_error, Rep}}}) ->
+ format(IOMod, T ++ add_node("~p~n",Pid),[Info]);
+write_event({Time, {error_report, _GL, {Pid, std_error, Rep}}},IOMod) ->
T = write_time(maybe_utc(Time)),
S = format_report(Rep),
- format(T ++ S ++ add_node("", Pid));
-write_event({Time, {info_report, _GL, {Pid, std_info, Rep}}}) ->
+ format(IOMod, T ++ S ++ add_node("", Pid));
+write_event({Time, {info_report, _GL, {Pid, std_info, Rep}}},IOMod) ->
T = write_time(maybe_utc(Time), "INFO REPORT"),
S = format_report(Rep),
- format(T ++ S ++ add_node("", Pid));
-write_event({Time, {info_msg, _GL, {Pid, Format, Args}}}) ->
+ format(IOMod, T ++ S ++ add_node("", Pid));
+write_event({Time, {info_msg, _GL, {Pid, Format, Args}}},IOMod) ->
T = write_time(maybe_utc(Time), "INFO REPORT"),
case catch io_lib:format(add_node(Format,Pid), Args) of
S when is_list(S) ->
- format(T ++ S);
+ format(IOMod, T ++ S);
_ ->
F = add_node("ERROR: ~p - ~p~n", Pid),
- format(T ++ F, [Format,Args])
+ format(IOMod, T ++ F, [Format,Args])
end;
-write_event({Time, {warning_report, _GL, {Pid, std_warning, Rep}}}) ->
+write_event({Time, {warning_report, _GL, {Pid, std_warning, Rep}}},IOMod) ->
T = write_time(maybe_utc(Time), "WARNING REPORT"),
S = format_report(Rep),
- format(T ++ S ++ add_node("", Pid));
-write_event({Time, {warning_msg, _GL, {Pid, Format, Args}}}) ->
+ format(IOMod, T ++ S ++ add_node("", Pid));
+write_event({Time, {warning_msg, _GL, {Pid, Format, Args}}},IOMod) ->
T = write_time(maybe_utc(Time), "WARNING REPORT"),
case catch io_lib:format(add_node(Format,Pid), Args) of
S when is_list(S) ->
- format(T ++ S);
+ format(IOMod, T ++ S);
_ ->
F = add_node("ERROR: ~p - ~p~n", Pid),
- format(T ++ F, [Format,Args])
+ format(IOMod, T ++ F, [Format,Args])
end;
-write_event({_Time, _Error}) ->
+write_event({_Time, _Error},_IOMod) ->
ok.
maybe_utc(Time) ->
@@ -178,8 +180,9 @@ maybe_utc(Time) ->
Time
end.
-format(String) -> io:format(user, String, []).
-format(String, Args) -> io:format(user, String, Args).
+format(IOMod, String) -> format(IOMod, String, []).
+format(io_lib, String, Args) -> io_lib:format(String, Args);
+format(io, String, Args) -> io:format(user, String, Args).
format_report(Rep) when is_list(Rep) ->
case string_p(Rep) of
diff --git a/lib/stdlib/src/escript.erl b/lib/stdlib/src/escript.erl
index d67617260e..ad49d89908 100644
--- a/lib/stdlib/src/escript.erl
+++ b/lib/stdlib/src/escript.erl
@@ -62,10 +62,10 @@
-type zip_create_option() :: term().
-type section() ::
shebang
- | {shebang, shebang()}
+ | {shebang, shebang() | default | undefined}
| comment
- | {comment, comment()}
- | {emu_args, emu_args()}
+ | {comment, comment() | default | undefined}
+ | {emu_args, emu_args() | undefined}
| {source, file:filename() | binary()}
| {beam, file:filename() | binary()}
| {archive, file:filename() | binary()}
@@ -866,7 +866,7 @@ hidden_apply(App, M, F, Args) ->
catch
error:undef ->
case erlang:get_stacktrace() of
- [{M,F,Args} | _] ->
+ [{M,F,Args,_} | _] ->
Arity = length(Args),
Text = io_lib:format("Call to ~w:~w/~w in application ~w failed.\n",
[M, F, Arity, App]),
diff --git a/lib/stdlib/src/eval_bits.erl b/lib/stdlib/src/eval_bits.erl
index 2cbd6cdae7..f40904df1c 100644
--- a/lib/stdlib/src/eval_bits.erl
+++ b/lib/stdlib/src/eval_bits.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -31,15 +31,16 @@
%% @type evalfun(). A closure which evaluates an expression given an
%% environment
%%
-%% @type matchfun(). A closure which performs a match given a value, a
-%% pattern and an environment
+%% @type matchfun(). A closure which depending on its first argument
+%% can perform a match (given a value, a pattern and an environment),
+%% lookup a variable in the bindings, or add a new binding
%%
-%% @type field() represents a field in a "bin"
+%% @type field(). Represents a field in a "bin".
%%% Part 1: expression evaluation (binary construction)
%% @spec expr_grp(Fields::[field()], Bindings::bindings(),
-%% EvalFun::evalfun()) ->
+%% EvalFun::evalfun(), term(), term()) ->
%% {value, binary(), bindings()}
%%
%% @doc Returns a tuple with {value,Bin,Bs} where Bin is the binary
@@ -144,7 +145,8 @@ eval_exp_field(Val, Size, Unit, binary, _, _) ->
bin_gen({bin,_,Fs}, Bin, Bs0, BBs0, Mfun, Efun) ->
bin_gen(Fs, Bin, Bs0, BBs0, Mfun, Efun, true).
-bin_gen([F|Fs], Bin, Bs0, BBs0, Mfun, Efun, Flag) ->
+bin_gen([F|Fs], Bin, Bs0, BBs0, Mfun, Efun, Flag)
+ when is_function(Mfun, 2), is_function(Efun, 2) ->
case bin_gen_field(F, Bin, Bs0, BBs0, Mfun, Efun) of
{match,Bs,BBs,Rest} ->
bin_gen(Fs, Rest, Bs, BBs, Mfun, Efun, Flag);
@@ -175,14 +177,14 @@ bin_gen_field({bin_element,Line,VE,Size0,Options0},
{Size1, [Type,{unit,Unit},Sign,Endian]} =
make_bit_type(Line, Size0, Options0),
V = erl_eval:partial_eval(VE),
- match_check_size(Size1, BBs0),
+ match_check_size(Mfun, Size1, BBs0),
{value, Size, _BBs} = Efun(Size1, BBs0),
case catch get_value(Bin, Type, Size, Unit, Sign, Endian) of
{Val,<<_/bitstring>>=Rest} ->
NewV = coerce_to_float(V, Type),
- case catch Mfun(NewV, Val, Bs0) of
+ case catch Mfun(match, {NewV,Val,Bs0}) of
{match,Bs} ->
- BBs = add_bin_binding(NewV, Bs, BBs0),
+ BBs = add_bin_binding(Mfun, NewV, Bs, BBs0),
{match,Bs,BBs,Rest};
_ ->
{nomatch,Rest}
@@ -192,9 +194,9 @@ bin_gen_field({bin_element,Line,VE,Size0,Options0},
end.
%%% Part 3: binary pattern matching
-%% @spec match_bits(Fields::[field()], Bin::binary()
+%% @spec match_bits(Fields::[field()], Bin::binary(),
%% GlobalEnv::bindings(), LocalEnv::bindings(),
-%% MatchFun::matchfun(),EvalFun::evalfun()) ->
+%% MatchFun::matchfun(),EvalFun::evalfun(), term()) ->
%% {match, bindings()}
%% @doc Used to perform matching. If the match succeeds a new
%% environment is returned. If the match have some syntactic or
@@ -205,7 +207,8 @@ bin_gen_field({bin_element,Line,VE,Size0,Options0},
match_bits(Fs, Bin, Bs0, BBs, Mfun, Efun, _) ->
match_bits(Fs, Bin, Bs0, BBs, Mfun, Efun).
-match_bits(Fs, Bin, Bs0, BBs, Mfun, Efun) ->
+match_bits(Fs, Bin, Bs0, BBs, Mfun, Efun)
+ when is_function(Mfun, 2), is_function(Efun, 2) ->
case catch match_bits_1(Fs, Bin, Bs0, BBs, Mfun, Efun) of
{match,Bs} -> {match,Bs};
invalid -> throw(invalid);
@@ -230,12 +233,12 @@ match_field_1({bin_element,Line,VE,Size0,Options0},
make_bit_type(Line, Size0, Options0),
V = erl_eval:partial_eval(VE),
Size2 = erl_eval:partial_eval(Size1),
- match_check_size(Size2, BBs0),
+ match_check_size(Mfun, Size2, BBs0),
{value, Size, _BBs} = Efun(Size2, BBs0),
{Val,Rest} = get_value(Bin, Type, Size, Unit, Sign, Endian),
NewV = coerce_to_float(V, Type),
- {match,Bs} = Mfun(NewV, Val, Bs0),
- BBs = add_bin_binding(NewV, Bs, BBs0),
+ {match,Bs} = Mfun(match, {NewV,Val,Bs0}),
+ BBs = add_bin_binding(Mfun, NewV, Bs, BBs0),
{Bs,BBs,Rest}.
%% Almost identical to the one in sys_pre_expand.
@@ -249,12 +252,12 @@ coerce_to_float({integer,L,I}=E, float) ->
coerce_to_float(E, _Type) ->
E.
-add_bin_binding({var,_,'_'}, _Bs, BBs) ->
+add_bin_binding(_, {var,_,'_'}, _Bs, BBs) ->
BBs;
-add_bin_binding({var,_,Name}, Bs, BBs) ->
- {value,Value} = erl_eval:binding(Name, Bs),
- erl_eval:add_binding(Name, Value, BBs);
-add_bin_binding(_, _Bs, BBs) ->
+add_bin_binding(Mfun, {var,_,Name}, Bs, BBs) ->
+ {value,Value} = Mfun(binding, {Name,Bs}),
+ Mfun(add_binding, {Name,Value,BBs});
+add_bin_binding(_, _, _Bs, BBs) ->
BBs.
get_value(Bin, integer, Size, Unit, Sign, Endian) ->
@@ -327,20 +330,20 @@ make_bit_type(_Line, Size, Type0) -> %Size evaluates to an integer or 'all'
{error,Reason} -> error(Reason)
end.
-match_check_size({var,_,V}, Bs) ->
- case erl_eval:binding(V, Bs) of
+match_check_size(Mfun, {var,_,V}, Bs) ->
+ case Mfun(binding, {V,Bs}) of
{value,_} -> ok;
unbound -> throw(invalid) % or, rather, error({unbound,V})
end;
-match_check_size({atom,_,all}, _Bs) ->
+match_check_size(_, {atom,_,all}, _Bs) ->
ok;
-match_check_size({atom,_,undefined}, _Bs) ->
+match_check_size(_, {atom,_,undefined}, _Bs) ->
ok;
-match_check_size({integer,_,_}, _Bs) ->
+match_check_size(_, {integer,_,_}, _Bs) ->
ok;
-match_check_size({value,_,_}, _Bs) ->
+match_check_size(_, {value,_,_}, _Bs) ->
ok; %From the debugger.
-match_check_size(_, _Bs) ->
+match_check_size(_, _, _Bs) ->
throw(invalid).
%% error(Reason) -> exception thrown
diff --git a/lib/stdlib/src/filename.erl b/lib/stdlib/src/filename.erl
index 1cb9e4a25e..2fc9128e4e 100644
--- a/lib/stdlib/src/filename.erl
+++ b/lib/stdlib/src/filename.erl
@@ -147,9 +147,10 @@ basename(Name) when is_binary(Name) ->
end;
basename(Name0) ->
- Name = flatten(Name0),
+ Name1 = flatten(Name0),
{DirSep2, DrvSep} = separators(),
- basename1(skip_prefix(Name, DrvSep), [], DirSep2).
+ Name = skip_prefix(Name1, DrvSep),
+ basename1(Name, Name, DirSep2).
win_basenameb(<<Letter,$:,Rest/binary>>) when ?IS_DRIVELETTER(Letter) ->
basenameb(Rest,[<<"/">>,<<"\\">>]);
@@ -167,16 +168,18 @@ basenameb(Bin,Sep) ->
-basename1([$/|[]], Tail, DirSep2) ->
- basename1([], Tail, DirSep2);
+basename1([$/], Tail0, _DirSep2) ->
+ %% End of filename -- must get rid of trailing directory separator.
+ [_|Tail] = lists:reverse(Tail0),
+ lists:reverse(Tail);
basename1([$/|Rest], _Tail, DirSep2) ->
- basename1(Rest, [], DirSep2);
+ basename1(Rest, Rest, DirSep2);
basename1([DirSep2|Rest], Tail, DirSep2) when is_integer(DirSep2) ->
basename1([$/|Rest], Tail, DirSep2);
basename1([Char|Rest], Tail, DirSep2) when is_integer(Char) ->
- basename1(Rest, [Char|Tail], DirSep2);
+ basename1(Rest, Tail, DirSep2);
basename1([], Tail, _DirSep2) ->
- lists:reverse(Tail).
+ Tail.
skip_prefix(Name, false) ->
Name;
@@ -369,8 +372,8 @@ extension(Name0) ->
Name = flatten(Name0),
extension(Name, [], major_os_type()).
-extension([$.|Rest], _Result, OsType) ->
- extension(Rest, [$.], OsType);
+extension([$.|Rest]=Result, _Result, OsType) ->
+ extension(Rest, Result, OsType);
extension([Char|Rest], [], OsType) when is_integer(Char) ->
extension(Rest, [], OsType);
extension([$/|Rest], _Result, OsType) ->
@@ -378,9 +381,9 @@ extension([$/|Rest], _Result, OsType) ->
extension([$\\|Rest], _Result, win32) ->
extension(Rest, [], win32);
extension([Char|Rest], Result, OsType) when is_integer(Char) ->
- extension(Rest, [Char|Result], OsType);
+ extension(Rest, Result, OsType);
extension([], Result, _OsType) ->
- lists:reverse(Result).
+ Result.
%% Joins a list of filenames with directory separators.
diff --git a/lib/stdlib/src/gen.erl b/lib/stdlib/src/gen.erl
index 574146b1cd..5d803091b6 100644
--- a/lib/stdlib/src/gen.erl
+++ b/lib/stdlib/src/gen.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -273,7 +273,7 @@ reply({To, Tag}, Reply) ->
%%%-----------------------------------------------------------------
%%% Misc. functions.
%%%-----------------------------------------------------------------
-where({global, Name}) -> global:safe_whereis_name(Name);
+where({global, Name}) -> global:whereis_name(Name);
where({local, Name}) -> whereis(Name).
name_register({local, Name} = LN) ->
diff --git a/lib/stdlib/src/gen_event.erl b/lib/stdlib/src/gen_event.erl
index 1c4a73680b..9879b76391 100644
--- a/lib/stdlib/src/gen_event.erl
+++ b/lib/stdlib/src/gen_event.erl
@@ -36,8 +36,6 @@
add_handler/3, add_sup_handler/3, delete_handler/3, swap_handler/3,
swap_sup_handler/3, which_handlers/1, call/3, call/4, wake_hib/4]).
--export([behaviour_info/1]).
-
-export([init_it/6,
system_continue/3,
system_terminate/4,
@@ -60,14 +58,6 @@
%%% API
%%%=========================================================================
--spec behaviour_info(atom()) -> 'undefined' | [{atom(), arity()}].
-
-behaviour_info(callbacks) ->
- [{init,1},{handle_event,2},{handle_call,2},{handle_info,2},
- {terminate,2},{code_change,3}];
-behaviour_info(_Other) ->
- undefined.
-
%% gen_event:start(Handler) -> {ok, Pid} | {error, What}
%% gen_event:add_handler(Handler, Mod, Args) -> ok | Other
%% gen_event:notify(Handler, Event) -> ok
@@ -78,41 +68,36 @@ behaviour_info(_Other) ->
%% gen_event:which_handler(Handler) -> [Mod]
%% gen_event:stop(Handler) -> ok
-
-%% handlers must export
-%% Mod:init(Args) -> {ok, State} | Other
-%% Mod:handle_event(Event, State) ->
-%% {ok, State'} | remove_handler | {swap_handler,Args1,State1,Mod2,Args2}
-%% Mod:handle_info(Info, State) ->
-%% {ok, State'} | remove_handler | {swap_handler,Args1,State1,Mod2,Args2}
-%% Mod:handle_call(Query, State) ->
-%% {ok, Reply, State'} | {remove_handler, Reply} |
-%% {swap_handler, Reply, Args1,State1,Mod2,Args2}
-%% Mod:terminate(Args, State) -> Val
-
-
-%% add_handler(H, Mod, Args) -> ok | Other
-%% Mod:init(Args) -> {ok, State} | Other
-
-%% delete_handler(H, Mod, Args) -> Val
-%% Mod:terminate(Args, State) -> Val
-
-%% notify(H, Event)
-%% Mod:handle_event(Event, State) ->
-%% {ok, State1}
-%% remove_handler
-%% Mod:terminate(remove_handler, State) is called
-%% the return value is ignored
-%% {swap_handler, Args1, State1, Mod2, Args2}
-%% State2 = Mod:terminate(Args1, State1) is called
-%% the return value is chained into the new module and
-%% Mod2:init({Args2, State2}) is called
-%% Other
-%% Mod:terminate({error, Other}, State) is called
-%% The return value is ignored
-%% call(H, Mod, Query) -> Val
-%% call(H, Mod, Query, Timeout) -> Val
-%% Mod:handle_call(Query, State) -> as above
+-callback init(InitArgs :: term()) ->
+ {ok, State :: term()} |
+ {ok, State :: term(), hibernate}.
+-callback handle_event(Event :: term(), State :: term()) ->
+ {ok, NewState :: term()} |
+ {ok, NewState :: term(), hibernate} |
+ {swap_handler, Args1 :: term(), NewState :: term(),
+ Handler2 :: (atom() | {atom(), Id :: term()}), Args2 :: term()} |
+ remove_handler.
+-callback handle_call(Request :: term(), State :: term()) ->
+ {ok, Reply :: term(), NewState :: term()} |
+ {ok, Reply :: term(), NewState :: term(), hibernate} |
+ {swap_handler, Reply :: term(), Args1 :: term(), NewState :: term(),
+ Handler2 :: (atom() | {atom(), Id :: term()}), Args2 :: term()} |
+ {remove_handler, Reply :: term()}.
+-callback handle_info(Info :: term(), State :: term()) ->
+ {ok, NewState :: term()} |
+ {ok, NewState :: term(), hibernate} |
+ {swap_handler, Args1 :: term(), NewState :: term(),
+ Handler2 :: (atom() | {atom(), Id :: term()}), Args2 :: term()} |
+ remove_handler.
+-callback terminate(Args :: (term() | {stop, Reason :: term()} |
+ stop | remove_handler |
+ {error, {'EXIT', Reason :: term()}} |
+ {error, term()}),
+ State :: term()) ->
+ term().
+-callback code_change(OldVsn :: (term() | {down, term()}),
+ State :: term(), Extra :: term()) ->
+ {ok, NewState :: term()}.
%%---------------------------------------------------------------------------
@@ -667,16 +652,16 @@ report_error(_Handler, {swapped,_,_}, _, _, _) -> ok;
report_error(Handler, Reason, State, LastIn, SName) ->
Reason1 =
case Reason of
- {'EXIT',{undef,[{M,F,A}|MFAs]}} ->
+ {'EXIT',{undef,[{M,F,A,L}|MFAs]}} ->
case code:is_loaded(M) of
false ->
- {'module could not be loaded',[{M,F,A}|MFAs]};
+ {'module could not be loaded',[{M,F,A,L}|MFAs]};
_ ->
case erlang:function_exported(M, F, length(A)) of
true ->
- {undef,[{M,F,A}|MFAs]};
+ {undef,[{M,F,A,L}|MFAs]};
false ->
- {'function not exported',[{M,F,A}|MFAs]}
+ {'function not exported',[{M,F,A,L}|MFAs]}
end
end;
{'EXIT',Why} ->
diff --git a/lib/stdlib/src/gen_fsm.erl b/lib/stdlib/src/gen_fsm.erl
index f2f1365d3d..57734a075c 100644
--- a/lib/stdlib/src/gen_fsm.erl
+++ b/lib/stdlib/src/gen_fsm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -113,8 +113,6 @@
start_timer/2,send_event_after/2,cancel_timer/1,
enter_loop/4, enter_loop/5, enter_loop/6, wake_hib/6]).
--export([behaviour_info/1]).
-
%% Internal exports
-export([init_it/6,
system_continue/3,
@@ -128,13 +126,38 @@
%%% Interface functions.
%%% ---------------------------------------------------
--spec behaviour_info(atom()) -> 'undefined' | [{atom(), arity()}].
-
-behaviour_info(callbacks) ->
- [{init,1},{handle_event,3},{handle_sync_event,4},{handle_info,3},
- {terminate,3},{code_change,4}];
-behaviour_info(_Other) ->
- undefined.
+-callback init(Args :: term()) ->
+ {ok, StateName :: atom(), StateData :: term()} |
+ {ok, StateName :: atom(), StateData :: term(), timeout() | hibernate} |
+ {stop, Reason :: term()} | ignore.
+-callback handle_event(Event :: term(), StateName :: atom(),
+ StateData :: term()) ->
+ {next_state, NextStateName :: atom(), NewStateData :: term()} |
+ {next_state, NextStateName :: atom(), NewStateData :: term(),
+ timeout() | hibernate} |
+ {stop, Reason :: term(), NewStateData :: term()}.
+-callback handle_sync_event(Event :: term(), From :: {pid(), Tag :: term()},
+ StateName :: atom(), StateData :: term()) ->
+ {reply, Reply :: term(), NextStateName :: atom(), NewStateData :: term()} |
+ {reply, Reply :: term(), NextStateName :: atom(), NewStateData :: term(),
+ timeout() | hibernate} |
+ {next_state, NextStateName :: atom(), NewStateData :: term()} |
+ {next_state, NextStateName :: atom(), NewStateData :: term(),
+ timeout() | hibernate} |
+ {stop, Reason :: term(), Reply :: term(), NewStateData :: term()} |
+ {stop, Reason :: term(), NewStateData :: term()}.
+-callback handle_info(Info :: term(), StateName :: atom(),
+ StateData :: term()) ->
+ {next_state, NextStateName :: atom(), NewStateData :: term()} |
+ {next_state, NextStateName :: atom(), NewStateData :: term(),
+ timeout() | hibernate} |
+ {stop, Reason :: normal | term(), NewStateData :: term()}.
+-callback terminate(Reason :: normal | shutdown | {shutdown, term()}
+ | term(), StateName :: atom(), StateData :: term()) ->
+ term().
+-callback code_change(OldVsn :: term() | {down, term()}, StateName :: atom(),
+ StateData :: term(), Extra :: term()) ->
+ {ok, NextStateName :: atom(), NewStateData :: term()}.
%%% ---------------------------------------------------
%%% Starts a generic state machine.
@@ -273,7 +296,7 @@ get_proc_name({local, Name}) ->
exit(process_not_registered)
end;
get_proc_name({global, Name}) ->
- case global:safe_whereis_name(Name) of
+ case global:whereis_name(Name) of
undefined ->
exit(process_not_registered_globally);
Pid when Pid =:= self() ->
@@ -295,7 +318,7 @@ get_parent() ->
name_to_pid(Name) ->
case whereis(Name) of
undefined ->
- case global:safe_whereis_name(Name) of
+ case global:whereis_name(Name) of
undefined ->
exit(could_not_find_registerd_name);
Pid ->
@@ -325,12 +348,15 @@ init_it(Starter, Parent, Name0, Mod, Args, Options) ->
proc_lib:init_ack(Starter, {ok, self()}),
loop(Parent, Name, StateName, StateData, Mod, Timeout, Debug);
{stop, Reason} ->
+ unregister_name(Name0),
proc_lib:init_ack(Starter, {error, Reason}),
exit(Reason);
ignore ->
+ unregister_name(Name0),
proc_lib:init_ack(Starter, ignore),
exit(normal);
{'EXIT', Reason} ->
+ unregister_name(Name0),
proc_lib:init_ack(Starter, {error, Reason}),
exit(Reason);
Else ->
@@ -343,6 +369,13 @@ name({local,Name}) -> Name;
name({global,Name}) -> Name;
name(Pid) when is_pid(Pid) -> Pid.
+unregister_name({local,Name}) ->
+ _ = (catch unregister(Name));
+unregister_name({global,Name}) ->
+ _ = global:unregister_name(Name);
+unregister_name(Pid) when is_pid(Pid) ->
+ Pid.
+
%%-----------------------------------------------------------------
%% The MAIN loop
%%-----------------------------------------------------------------
@@ -561,16 +594,16 @@ terminate(Reason, Name, Msg, Mod, StateName, StateData, Debug) ->
error_info(Reason, Name, Msg, StateName, StateData, Debug) ->
Reason1 =
case Reason of
- {undef,[{M,F,A}|MFAs]} ->
+ {undef,[{M,F,A,L}|MFAs]} ->
case code:is_loaded(M) of
false ->
- {'module could not be loaded',[{M,F,A}|MFAs]};
+ {'module could not be loaded',[{M,F,A,L}|MFAs]};
_ ->
case erlang:function_exported(M, F, length(A)) of
true ->
Reason;
false ->
- {'function not exported',[{M,F,A}|MFAs]}
+ {'function not exported',[{M,F,A,L}|MFAs]}
end
end;
_ ->
diff --git a/lib/stdlib/src/gen_server.erl b/lib/stdlib/src/gen_server.erl
index 09d94a9c40..6f075bbe5a 100644
--- a/lib/stdlib/src/gen_server.erl
+++ b/lib/stdlib/src/gen_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -94,8 +94,6 @@
multi_call/2, multi_call/3, multi_call/4,
enter_loop/3, enter_loop/4, enter_loop/5, wake_hib/5]).
--export([behaviour_info/1]).
-
%% System exports
-export([system_continue/3,
system_terminate/4,
@@ -111,13 +109,32 @@
%%% API
%%%=========================================================================
--spec behaviour_info(atom()) -> 'undefined' | [{atom(), arity()}].
-
-behaviour_info(callbacks) ->
- [{init,1},{handle_call,3},{handle_cast,2},{handle_info,2},
- {terminate,2},{code_change,3}];
-behaviour_info(_Other) ->
- undefined.
+-callback init(Args :: term()) ->
+ {ok, State :: term()} | {ok, State :: term(), timeout() | hibernate} |
+ {stop, Reason :: term()} | ignore.
+-callback handle_call(Request :: term(), From :: {pid(), Tag :: term()},
+ State :: term()) ->
+ {reply, Reply :: term(), NewState :: term()} |
+ {reply, Reply :: term(), NewState :: term(), timeout() | hibernate} |
+ {noreply, NewState :: term()} |
+ {noreply, NewState :: term(), timeout() | hibernate} |
+ {stop, Reason :: term(), Reply :: term(), NewState :: term()} |
+ {stop, Reason :: term(), NewState :: term()}.
+-callback handle_cast(Request :: term(), State :: term()) ->
+ {noreply, NewState :: term()} |
+ {noreply, NewState :: term(), timeout() | hibernate} |
+ {stop, Reason :: term(), NewState :: term()}.
+-callback handle_info(Info :: timeout() | term(), State :: term()) ->
+ {noreply, NewState :: term()} |
+ {noreply, NewState :: term(), timeout() | hibernate} |
+ {stop, Reason :: term(), NewState :: term()}.
+-callback terminate(Reason :: (normal | shutdown | {shutdown, term()} |
+ term()),
+ State :: term()) ->
+ term().
+-callback code_change(OldVsn :: (term() | {down, term()}), State :: term(),
+ Extra :: term()) ->
+ {ok, NewState :: term()}.
%%% -----------------------------------------------------------------
%%% Starts a generic server.
@@ -729,16 +746,16 @@ error_info(_Reason, application_controller, _Msg, _State, _Debug) ->
error_info(Reason, Name, Msg, State, Debug) ->
Reason1 =
case Reason of
- {undef,[{M,F,A}|MFAs]} ->
+ {undef,[{M,F,A,L}|MFAs]} ->
case code:is_loaded(M) of
false ->
- {'module could not be loaded',[{M,F,A}|MFAs]};
+ {'module could not be loaded',[{M,F,A,L}|MFAs]};
_ ->
case erlang:function_exported(M, F, length(A)) of
true ->
Reason;
false ->
- {'function not exported',[{M,F,A}|MFAs]}
+ {'function not exported',[{M,F,A,L}|MFAs]}
end
end;
_ ->
@@ -803,7 +820,7 @@ get_proc_name({local, Name}) ->
exit(process_not_registered)
end;
get_proc_name({global, Name}) ->
- case global:safe_whereis_name(Name) of
+ case global:whereis_name(Name) of
undefined ->
exit(process_not_registered_globally);
Pid when Pid =:= self() ->
@@ -825,7 +842,7 @@ get_parent() ->
name_to_pid(Name) ->
case whereis(Name) of
undefined ->
- case global:safe_whereis_name(Name) of
+ case global:whereis_name(Name) of
undefined ->
exit(could_not_find_registerd_name);
Pid ->
diff --git a/lib/stdlib/src/io_lib.erl b/lib/stdlib/src/io_lib.erl
index 54c7283abf..0252cdf742 100644
--- a/lib/stdlib/src/io_lib.erl
+++ b/lib/stdlib/src/io_lib.erl
@@ -100,7 +100,7 @@ fwrite(Format, Args) ->
-spec fread(Format, String) -> Result when
Format :: string(),
String :: string(),
- Result :: {'ok', InputList :: chars(), LeftOverChars :: string()}
+ Result :: {'ok', InputList :: [term()], LeftOverChars :: string()}
| {'more', RestFormat :: string(),
Nchars :: non_neg_integer(),
InputStack :: chars()}
@@ -109,13 +109,13 @@ fwrite(Format, Args) ->
fread(Chars, Format) ->
io_lib_fread:fread(Chars, Format).
--spec fread(Continuation, String, Format) -> Return when
+-spec fread(Continuation, CharSpec, Format) -> Return when
Continuation :: continuation() | [],
- String :: string(),
+ CharSpec :: string() | eof,
Format :: string(),
Return :: {'more', Continuation1 :: continuation()}
| {'done', Result, LeftOverChars :: string()},
- Result :: {'ok', InputList :: chars()}
+ Result :: {'ok', InputList :: [term()]}
| 'eof'
| {'error', What :: term()}.
diff --git a/lib/stdlib/src/io_lib_fread.erl b/lib/stdlib/src/io_lib_fread.erl
index 52aa4d073c..ded1346097 100644
--- a/lib/stdlib/src/io_lib_fread.erl
+++ b/lib/stdlib/src/io_lib_fread.erl
@@ -24,6 +24,10 @@
-import(lists, [reverse/1,reverse/2]).
+-define(is_whitespace(C),
+ ((C) =:= $\s orelse (C) =:= $\t
+ orelse (C) =:= $\r orelse (C) =:= $\n)).
+
%%-----------------------------------------------------------------------
%% fread(Continuation, CharList, FormatString)
@@ -106,31 +110,27 @@ fread_line(Format0, Line, N0, Results0, More, Newline) ->
fread(Format, Line) ->
fread(Format, Line, 0, []).
-fread([$~|Format0], Line, N, Results) ->
+fread([$~|Format0]=AllFormat, Line, N, Results) ->
{Format,F,Sup,Unicode} = fread_field(Format0),
- fread1(Format, F, Sup, Unicode, Line, N, Results, Format0);
-fread([$\s|Format], Line, N, Results) ->
- fread_skip_white(Format, Line, N, Results);
-fread([$\t|Format], Line, N, Results) ->
- fread_skip_white(Format, Line, N, Results);
-fread([$\r|Format], Line, N, Results) ->
- fread_skip_white(Format, Line, N, Results);
-fread([$\n|Format], Line, N, Results) ->
+ fread1(Format, F, Sup, Unicode, Line, N, Results, AllFormat);
+fread([C|Format], Line, N, Results) when ?is_whitespace(C) ->
fread_skip_white(Format, Line, N, Results);
fread([C|Format], [C|Line], N, Results) ->
fread(Format, Line, N+1, Results);
fread([_F|_Format], [_C|_Line], _N, _Results) ->
fread_error(input);
+fread([_|_]=Format, [], N, Results) ->
+ {more,Format,N,Results};
+fread([_|_], eof, 0, []) ->
+ %% This is at start of input so no error.
+ eof;
+fread([_|_], eof, _N, _Results) ->
+ %% This is an error as there is no more input.
+ fread_error(input);
fread([], Line, _N, Results) ->
{ok,reverse(Results),Line}.
-fread_skip_white(Format, [$\s|Line], N, Results) ->
- fread_skip_white(Format, Line, N+1, Results);
-fread_skip_white(Format, [$\t|Line], N, Results) ->
- fread_skip_white(Format, Line, N+1, Results);
-fread_skip_white(Format, [$\r|Line], N, Results) ->
- fread_skip_white(Format, Line, N+1, Results);
-fread_skip_white(Format, [$\n|Line], N, Results) ->
+fread_skip_white(Format, [C|Line], N, Results) when ?is_whitespace(C) ->
fread_skip_white(Format, Line, N+1, Results);
fread_skip_white(Format, Line, N, Results) ->
fread(Format, Line, N, Results).
@@ -166,9 +166,9 @@ fread1([$l|Format], _F, Sup, _U, Line, N, Res, _AllFormat) ->
fread(Format, Line, N, fread_result(Sup, N, Res));
fread1(_Format, _F, _Sup, _U, [], N, Res, AllFormat) ->
%% Need more input here.
- {more,[$~|AllFormat],N,Res};
-fread1(_Format, _F, _Sup, _U, eof, _N, [], _AllFormat) ->
- %% This is at start of format string so no error.
+ {more,AllFormat,N,Res};
+fread1(_Format, _F, _Sup, _U, eof, 0, [], _AllFormat) ->
+ %% This is at start of input so no error.
eof;
fread1(_Format, _F, _Sup, _U, eof, _N, _Res, _AllFormat) ->
%% This is an error as there is no more input.
@@ -386,26 +386,16 @@ fread_string_cs(Line0, N0, true) ->
%% fread_digits(Line, N, Base, Characters)
%% Read segments of things, return "thing" characters in reverse order.
-fread_skip_white([$\s|Line]) -> fread_skip_white(Line);
-fread_skip_white([$\t|Line]) -> fread_skip_white(Line);
-fread_skip_white([$\r|Line]) -> fread_skip_white(Line);
-fread_skip_white([$\n|Line]) -> fread_skip_white(Line);
+fread_skip_white([C|Line]) when ?is_whitespace(C) ->
+ fread_skip_white(Line);
fread_skip_white(Line) -> Line.
-fread_skip_white([$\s|Line], N) ->
- fread_skip_white(Line, N+1);
-fread_skip_white([$\t|Line], N) ->
- fread_skip_white(Line, N+1);
-fread_skip_white([$\r|Line], N) ->
- fread_skip_white(Line, N+1);
-fread_skip_white([$\n|Line], N) ->
+fread_skip_white([C|Line], N) when ?is_whitespace(C) ->
fread_skip_white(Line, N+1);
fread_skip_white(Line, N) -> {Line,N}.
-fread_skip_latin1_nonwhite([$\s|Line], N, Cs) -> {[$\s|Line],N,Cs};
-fread_skip_latin1_nonwhite([$\t|Line], N, Cs) -> {[$\t|Line],N,Cs};
-fread_skip_latin1_nonwhite([$\r|Line], N, Cs) -> {[$\r|Line],N,Cs};
-fread_skip_latin1_nonwhite([$\n|Line], N, Cs) -> {[$\n|Line],N,Cs};
+fread_skip_latin1_nonwhite([C|Line], N, Cs) when ?is_whitespace(C) ->
+ {[C|Line],N,Cs};
fread_skip_latin1_nonwhite([C|Line], N, []) when C > 255 ->
{[C|Line],N,error};
fread_skip_latin1_nonwhite([C|Line], N, Cs) when C > 255 ->
@@ -414,10 +404,8 @@ fread_skip_latin1_nonwhite([C|Line], N, Cs) ->
fread_skip_latin1_nonwhite(Line, N+1, [C|Cs]);
fread_skip_latin1_nonwhite([], N, Cs) -> {[],N,Cs}.
-fread_skip_nonwhite([$\s|Line], N, Cs) -> {[$\s|Line],N,Cs};
-fread_skip_nonwhite([$\t|Line], N, Cs) -> {[$\t|Line],N,Cs};
-fread_skip_nonwhite([$\r|Line], N, Cs) -> {[$\r|Line],N,Cs};
-fread_skip_nonwhite([$\n|Line], N, Cs) -> {[$\n|Line],N,Cs};
+fread_skip_nonwhite([C|Line], N, Cs) when ?is_whitespace(C) ->
+ {[C|Line],N,Cs};
fread_skip_nonwhite([C|Line], N, Cs) ->
fread_skip_nonwhite(Line, N+1, [C|Cs]);
fread_skip_nonwhite([], N, Cs) -> {[],N,Cs}.
diff --git a/lib/stdlib/src/lib.erl b/lib/stdlib/src/lib.erl
index c303ae60b5..314fd60903 100644
--- a/lib/stdlib/src/lib.erl
+++ b/lib/stdlib/src/lib.erl
@@ -173,12 +173,12 @@ format_fun(Fun) when is_function(Fun) ->
analyze_exception(error, Term, Stack) ->
case {is_stacktrace(Stack), Stack, Term} of
- {true, [{_M,_F,As}=MFA|MFAs], function_clause} when is_list(As) ->
- {Term,[MFA],MFAs};
- {true, [{shell,F,A}], function_clause} when is_integer(A) ->
+ {true, [{_,_,As,_}=MFAL|MFAs], function_clause} when is_list(As) ->
+ {Term,[MFAL],MFAs};
+ {true, [{shell,F,A,_}], function_clause} when is_integer(A) ->
{Term, [{F,A}], []};
- {true, [{_M,_F,_AorAs}=MFA|MFAs], undef} ->
- {Term,[MFA],MFAs};
+ {true, [{_,_,_,_}=MFAL|MFAs], undef} ->
+ {Term,[MFAL],MFAs};
{true, _, _} ->
{Term,[],Stack};
{false, _, _} ->
@@ -194,9 +194,11 @@ analyze_exception(_Class, Term, Stack) ->
is_stacktrace([]) ->
true;
-is_stacktrace([{M,F,A}|Fs]) when is_atom(M), is_atom(F), is_integer(A) ->
+is_stacktrace([{M,F,A,I}|Fs])
+ when is_atom(M), is_atom(F), is_integer(A), is_list(I) ->
is_stacktrace(Fs);
-is_stacktrace([{M,F,As}|Fs]) when is_atom(M), is_atom(F), length(As) >= 0 ->
+is_stacktrace([{M,F,As,I}|Fs])
+ when is_atom(M), is_atom(F), length(As) >= 0, is_list(I) ->
is_stacktrace(Fs);
is_stacktrace(_) ->
false.
@@ -225,9 +227,9 @@ explain_reason(function_clause, error, [{F,A}], _PF, _S) ->
%% Shell commands
FAs = io_lib:fwrite(<<"~w/~w">>, [F, A]),
[<<"no function clause matching call to ">> | FAs];
-explain_reason(function_clause, error=Cl, [{M,F,As}], PF, S) ->
+explain_reason(function_clause, error=Cl, [{M,F,As,Loc}], PF, S) ->
Str = <<"no function clause matching ">>,
- format_errstr_call(Str, Cl, {M,F}, As, PF, S);
+ [format_errstr_call(Str, Cl, {M,F}, As, PF, S),$\s|location(Loc)];
explain_reason(if_clause, error, [], _PF, _S) ->
<<"no true branch found when evaluating an if expression">>;
explain_reason(noproc, error, [], _PF, _S) ->
@@ -242,11 +244,11 @@ explain_reason({try_clause,V}, error=Cl, [], PF, S) ->
%% "there is no try clause with a true guard sequence and a
%% pattern matching..."
format_value(V, <<"no try clause matching ">>, Cl, PF, S);
-explain_reason(undef, error, [{M,F,A}], _PF, _S) ->
+explain_reason(undef, error, [{M,F,A,_}], _PF, _S) ->
%% Only the arity is displayed, not the arguments, if there are any.
io_lib:fwrite(<<"undefined function ~s">>,
[mfa_to_string(M, F, n_args(A))]);
-explain_reason({shell_undef,F,A}, error, [], _PF, _S) ->
+explain_reason({shell_undef,F,A,_}, error, [], _PF, _S) ->
%% Give nicer reports for undefined shell functions
%% (but not when the user actively calls shell_default:F(...)).
io_lib:fwrite(<<"undefined shell command ~s/~w">>, [F, n_args(A)]);
@@ -292,17 +294,19 @@ argss(I) ->
io_lib:fwrite(<<"~w arguments">>, [I]).
format_stacktrace1(S0, Stack0, PF, SF) ->
- Stack1 = lists:dropwhile(fun({M,F,A}) -> SF(M, F, A)
+ Stack1 = lists:dropwhile(fun({M,F,A,_}) -> SF(M, F, A)
end, lists:reverse(Stack0)),
S = [" " | S0],
Stack = lists:reverse(Stack1),
format_stacktrace2(S, Stack, 1, PF).
-format_stacktrace2(S, [{M,F,A}|Fs], N, PF) when is_integer(A) ->
- [io_lib:fwrite(<<"~s~s ~s">>,
- [sep(N, S), origin(N, M, F, A), mfa_to_string(M, F, A)])
+format_stacktrace2(S, [{M,F,A,L}|Fs], N, PF) when is_integer(A) ->
+ [io_lib:fwrite(<<"~s~s ~s ~s">>,
+ [sep(N, S), origin(N, M, F, A),
+ mfa_to_string(M, F, A),
+ location(L)])
| format_stacktrace2(S, Fs, N + 1, PF)];
-format_stacktrace2(S, [{M,F,As}|Fs], N, PF) when is_list(As) ->
+format_stacktrace2(S, [{M,F,As,_}|Fs], N, PF) when is_list(As) ->
A = length(As),
CalledAs = [S,<<" called as ">>],
C = format_call("", CalledAs, {M,F}, As, PF),
@@ -313,6 +317,16 @@ format_stacktrace2(S, [{M,F,As}|Fs], N, PF) when is_list(As) ->
format_stacktrace2(_S, [], _N, _PF) ->
"".
+location(L) ->
+ File = proplists:get_value(file, L),
+ Line = proplists:get_value(line, L),
+ if
+ File =/= undefined, Line =/= undefined ->
+ io_lib:format("(~s, line ~w)", [File, Line]);
+ true ->
+ ""
+ end.
+
sep(1, S) -> S;
sep(_, S) -> [$\n | S].
diff --git a/lib/stdlib/src/lists.erl b/lib/stdlib/src/lists.erl
index bba46e4cb6..e73c087753 100644
--- a/lib/stdlib/src/lists.erl
+++ b/lib/stdlib/src/lists.erl
@@ -628,9 +628,10 @@ keydelete3(_, _, []) -> [].
-spec keyreplace(Key, N, TupleList1, NewTuple) -> TupleList2 when
Key :: term(),
N :: pos_integer(),
- TupleList1 :: [tuple()],
- TupleList2 :: [tuple()],
- NewTuple :: tuple().
+ TupleList1 :: [Tuple],
+ TupleList2 :: [Tuple],
+ NewTuple :: Tuple,
+ Tuple :: tuple().
keyreplace(K, N, L, New) when is_integer(N), N > 0, is_tuple(New) ->
keyreplace3(K, N, L, New).
@@ -660,9 +661,10 @@ keytake(_K, _N, [], _L) -> false.
-spec keystore(Key, N, TupleList1, NewTuple) -> TupleList2 when
Key :: term(),
N :: pos_integer(),
- TupleList1 :: [tuple()],
- TupleList2 :: [tuple(), ...],
- NewTuple :: tuple().
+ TupleList1 :: [Tuple],
+ TupleList2 :: [Tuple, ...],
+ NewTuple :: Tuple,
+ Tuple :: tuple().
keystore(K, N, L, New) when is_integer(N), N > 0, is_tuple(New) ->
keystore2(K, N, L, New).
@@ -740,8 +742,9 @@ keysort_1(_I, X, _EX, [], R) ->
TupleList1 :: [T1],
TupleList2 :: [T2],
TupleList3 :: [(T1 | T2)],
- T1 :: tuple(),
- T2 :: tuple().
+ T1 :: Tuple,
+ T2 :: Tuple,
+ Tuple :: tuple().
keymerge(Index, T1, L2) when is_integer(Index), Index > 0 ->
case L2 of
@@ -842,8 +845,9 @@ ukeysort_1(_I, X, _EX, []) ->
TupleList1 :: [T1],
TupleList2 :: [T2],
TupleList3 :: [(T1 | T2)],
- T1 :: tuple(),
- T2 :: tuple().
+ T1 :: Tuple,
+ T2 :: Tuple,
+ Tuple :: tuple().
ukeymerge(Index, L1, T2) when is_integer(Index), Index > 0 ->
case L1 of
@@ -873,8 +877,9 @@ rukeymerge(Index, T1, L2) when is_integer(Index), Index > 0 ->
-spec keymap(Fun, N, TupleList1) -> TupleList2 when
Fun :: fun((Term1 :: term()) -> Term2 :: term()),
N :: pos_integer(),
- TupleList1 :: [tuple()],
- TupleList2 :: [tuple()].
+ TupleList1 :: [Tuple],
+ TupleList2 :: [Tuple],
+ Tuple :: tuple().
keymap(Fun, Index, [Tup|Tail]) ->
[setelement(Index, Tup, Fun(element(Index, Tup)))|keymap(Fun, Index, Tail)];
diff --git a/lib/stdlib/src/ms_transform.erl b/lib/stdlib/src/ms_transform.erl
index 48e22e53fa..63b397f3a5 100644
--- a/lib/stdlib/src/ms_transform.erl
+++ b/lib/stdlib/src/ms_transform.erl
@@ -333,17 +333,18 @@ form({function,Line,Name0,Arity0,Clauses0}) ->
form(AnyOther) ->
AnyOther.
function(Name, Arity, Clauses0) ->
- {Clauses1,_} = clauses(Clauses0,gb_sets:new()),
+ Clauses1 = clauses(Clauses0),
{Name,Arity,Clauses1}.
-clauses([C0|Cs],Bound) ->
- {C1,Bound1} = clause(C0,Bound),
- {C2,Bound2} = clauses(Cs,Bound1),
- {[C1|C2],Bound2};
-clauses([],Bound) -> {[],Bound}.
+clauses([C0|Cs]) ->
+ C1 = clause(C0,gb_sets:new()),
+ C2 = clauses(Cs),
+ [C1|C2];
+clauses([]) -> [].
+
clause({clause,Line,H0,G0,B0},Bound) ->
{H1,Bound1} = copy(H0,Bound),
- {B1,Bound2} = copy(B0,Bound1),
- {{clause,Line,H1,G0,B1},Bound2}.
+ {B1,_Bound2} = copy(B0,Bound1),
+ {clause,Line,H1,G0,B1}.
copy({call,Line,{remote,_Line2,{atom,_Line3,ets},{atom,_Line4,fun2ms}},
As0},Bound) ->
diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl
index 39d017d430..c1285dab60 100644
--- a/lib/stdlib/src/otp_internal.erl
+++ b/lib/stdlib/src/otp_internal.erl
@@ -330,22 +330,22 @@ obsolete_1(erlang, fault, 2) ->
obsolete_1(file, rawopen, 2) ->
{removed, "deprecated (will be removed in R13B); use file:open/2 with the raw option"};
-obsolete_1(http, request, 1) -> {deprecated,{httpc,request,1},"R15B"};
-obsolete_1(http, request, 2) -> {deprecated,{httpc,request,2},"R15B"};
-obsolete_1(http, request, 4) -> {deprecated,{httpc,request,4},"R15B"};
-obsolete_1(http, request, 5) -> {deprecated,{httpc,request,5},"R15B"};
-obsolete_1(http, cancel_request, 1) -> {deprecated,{httpc,cancel_request,1},"R15B"};
-obsolete_1(http, cancel_request, 2) -> {deprecated,{httpc,cancel_request,2},"R15B"};
-obsolete_1(http, set_option, 2) -> {deprecated,{httpc,set_option,2},"R15B"};
-obsolete_1(http, set_option, 3) -> {deprecated,{httpc,set_option,3},"R15B"};
-obsolete_1(http, set_options, 1) -> {deprecated,{httpc,set_options,1},"R15B"};
-obsolete_1(http, set_options, 2) -> {deprecated,{httpc,set_options,2},"R15B"};
-obsolete_1(http, verify_cookies, 2) -> {deprecated,{httpc,verify_cookies,2},"R15B"};
-obsolete_1(http, verify_cookies, 3) -> {deprecated,{httpc,verify_cookies,3},"R15B"};
-obsolete_1(http, cookie_header, 1) -> {deprecated,{httpc,cookie_header,1},"R15B"};
-obsolete_1(http, cookie_header, 2) -> {deprecated,{httpc,cookie_header,2},"R15B"};
-obsolete_1(http, stream_next, 1) -> {deprecated,{httpc,stream_next,1},"R15B"};
-obsolete_1(http, default_profile, 0) -> {deprecated,{httpc,default_profile,0},"R15B"};
+obsolete_1(http, request, 1) -> {removed,{httpc,request,1},"R15B"};
+obsolete_1(http, request, 2) -> {removed,{httpc,request,2},"R15B"};
+obsolete_1(http, request, 4) -> {removed,{httpc,request,4},"R15B"};
+obsolete_1(http, request, 5) -> {removed,{httpc,request,5},"R15B"};
+obsolete_1(http, cancel_request, 1) -> {removed,{httpc,cancel_request,1},"R15B"};
+obsolete_1(http, cancel_request, 2) -> {removed,{httpc,cancel_request,2},"R15B"};
+obsolete_1(http, set_option, 2) -> {removed,{httpc,set_option,2},"R15B"};
+obsolete_1(http, set_option, 3) -> {removed,{httpc,set_option,3},"R15B"};
+obsolete_1(http, set_options, 1) -> {removed,{httpc,set_options,1},"R15B"};
+obsolete_1(http, set_options, 2) -> {removed,{httpc,set_options,2},"R15B"};
+obsolete_1(http, verify_cookies, 2) -> {removed,{httpc,store_cookies,2},"R15B"};
+obsolete_1(http, verify_cookies, 3) -> {removed,{httpc,store_cookies,3},"R15B"};
+obsolete_1(http, cookie_header, 1) -> {removed,{httpc,cookie_header,1},"R15B"};
+obsolete_1(http, cookie_header, 2) -> {removed,{httpc,cookie_header,2},"R15B"};
+obsolete_1(http, stream_next, 1) -> {removed,{httpc,stream_next,1},"R15B"};
+obsolete_1(http, default_profile, 0) -> {removed,{httpc,default_profile,0},"R15B"};
obsolete_1(httpd, start, 0) -> {removed,{inets,start,[2,3]},"R14B"};
obsolete_1(httpd, start, 1) -> {removed,{inets,start,[2,3]},"R14B"};
@@ -449,7 +449,7 @@ obsolete_1(ssl_pkix, decode_cert, A) when A =:= 1; A =:= 2 ->
%% Added in R13B04.
obsolete_1(erlang, concat_binary, 1) ->
- {deprecated,{erlang,list_to_binary,1},"R15B"};
+ {removed,{erlang,list_to_binary,1},"R15B"};
%% Added in R14A.
obsolete_1(ssl, peercert, 2) ->
@@ -461,6 +461,18 @@ obsolete_1(public_key, pem_to_der, 1) ->
obsolete_1(public_key, decode_private_key, A) when A =:= 1; A =:= 2 ->
{deprecated,{public_key,pem_entry_decode,1},"R15A"};
+%% Added in R14B03.
+obsolete_1(docb_gen, _, _) ->
+ {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"};
+obsolete_1(docb_transform, _, _) ->
+ {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"};
+obsolete_1(docb_xml_check, _, _) ->
+ {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"};
+
+%% Added in R15B
+obsolete_1(asn1rt, F, _) when F == load_driver; F == unload_driver ->
+ {deprecated,"deprecated (will be removed in R16A); has no effect as drivers are no longer used."};
+
obsolete_1(_, _, _) ->
no.
diff --git a/lib/stdlib/src/proplists.erl b/lib/stdlib/src/proplists.erl
index 68697d0da2..e3eda5d932 100644
--- a/lib/stdlib/src/proplists.erl
+++ b/lib/stdlib/src/proplists.erl
@@ -49,9 +49,10 @@
%% ---------------------------------------------------------------------
--export_type([property/0]).
+-export_type([property/0, proplist/0]).
-type property() :: atom() | tuple().
+-type proplist() :: [property()].
%% ---------------------------------------------------------------------
diff --git a/lib/stdlib/src/qlc.erl b/lib/stdlib/src/qlc.erl
index 5ca04ff023..2b691e6abf 100644
--- a/lib/stdlib/src/qlc.erl
+++ b/lib/stdlib/src/qlc.erl
@@ -123,7 +123,7 @@
-record(setup, {parent}).
--define(THROWN_ERROR, {?MODULE, throw_error, _}).
+-define(THROWN_ERROR, {?MODULE, throw_error, _, _}).
-export_type([query_handle/0]).
@@ -1272,7 +1272,10 @@ abstr_term(Fun, Line) when is_function(Fun) ->
case erlang:fun_info(Fun, type) of
{type, external} ->
{module, Module} = erlang:fun_info(Fun, module),
- {'fun', Line, {function,Module,Name,Arity}};
+ {'fun', Line, {function,
+ {atom,Line,Module},
+ {atom,Line,Name},
+ {integer,Line,Arity}}};
{type, local} ->
{'fun', Line, {function,Name,Arity}}
end
@@ -3701,7 +3704,8 @@ lookup_join(F1, C1, LuF, C2, Rev) ->
maybe_error_logger(allowed, _) ->
ok;
maybe_error_logger(Name, Why) ->
- [_, _, {?MODULE,maybe_error_logger,_} | Stacktrace] = expand_stacktrace(),
+ [_, _, {?MODULE,maybe_error_logger,_,_} | Stacktrace] =
+ expand_stacktrace(),
Trimmer = fun(M, _F, _A) -> M =:= erl_eval end,
Formater = fun(Term, I) -> io_lib:print(Term, I, 80, -1) end,
X = lib:format_stacktrace(1, Stacktrace, Trimmer, Formater),
@@ -3720,7 +3724,7 @@ expand_stacktrace() ->
expand_stacktrace(D) ->
_ = erlang:system_flag(backtrace_depth, D),
{'EXIT', {foo, Stacktrace}} = (catch erlang:error(foo)),
- L = lists:takewhile(fun({M,_,_}) -> M =/= ?MODULE
+ L = lists:takewhile(fun({M,_,_,_}) -> M =/= ?MODULE
end, lists:reverse(Stacktrace)),
if
length(L) < 3 andalso length(Stacktrace) =:= D ->
diff --git a/lib/stdlib/src/queue.erl b/lib/stdlib/src/queue.erl
index 4c6b4d710b..afe917b151 100644
--- a/lib/stdlib/src/queue.erl
+++ b/lib/stdlib/src/queue.erl
@@ -56,16 +56,14 @@
new() -> {[],[]}. %{RearList,FrontList}
%% O(1)
--spec is_queue(Term) -> boolean() when
- Term :: term().
+-spec is_queue(Term :: term()) -> boolean().
is_queue({R,F}) when is_list(R), is_list(F) ->
true;
is_queue(_) ->
false.
%% O(1)
--spec is_empty(Q) -> boolean() when
- Q :: queue().
+-spec is_empty(Q :: queue()) -> boolean().
is_empty({[],[]}) ->
true;
is_empty({In,Out}) when is_list(In), is_list(Out) ->
@@ -74,16 +72,14 @@ is_empty(Q) ->
erlang:error(badarg, [Q]).
%% O(len(Q))
--spec len(Q) -> non_neg_integer() when
- Q :: queue().
+-spec len(Q :: queue()) -> non_neg_integer().
len({R,F}) when is_list(R), is_list(F) ->
length(R)+length(F);
len(Q) ->
erlang:error(badarg, [Q]).
%% O(len(Q))
--spec to_list(Q) -> list() when
- Q :: queue().
+-spec to_list(Q :: queue()) -> list().
to_list({In,Out}) when is_list(In), is_list(Out) ->
Out++lists:reverse(In, []);
to_list(Q) ->
@@ -92,8 +88,7 @@ to_list(Q) ->
%% Create queue from list
%%
%% O(length(L))
--spec from_list(L) -> queue() when
- L :: list().
+-spec from_list(L :: list()) -> queue().
from_list(L) when is_list(L) ->
f2r(L);
from_list(L) ->
@@ -102,9 +97,7 @@ from_list(L) ->
%% Return true or false depending on if element is in queue
%%
%% O(length(Q)) worst case
--spec member(Item, Q) -> boolean() when
- Item :: term(),
- Q :: queue().
+-spec member(Item :: term(), Q :: queue()) -> boolean().
member(X, {R,F}) when is_list(R), is_list(F) ->
lists:member(X, R) orelse lists:member(X, F);
member(X, Q) ->
@@ -117,10 +110,7 @@ member(X, Q) ->
%% Put at least one element in each list, if it is cheap
%%
%% O(1)
--spec in(Item, Q1) -> Q2 when
- Item :: term(),
- Q1 :: queue(),
- Q2 :: queue().
+-spec in(Item :: term(), Q1 :: queue()) -> Q2 :: queue().
in(X, {[_]=In,[]}) ->
{[X], In};
in(X, {In,Out}) when is_list(In), is_list(Out) ->
@@ -132,10 +122,7 @@ in(X, Q) ->
%% Put at least one element in each list, if it is cheap
%%
%% O(1)
--spec in_r(Item, Q1) -> Q2 when
- Item :: term(),
- Q1 :: queue(),
- Q2 :: queue().
+-spec in_r(Item :: term(), Q1 :: queue()) -> Q2 :: queue().
in_r(X, {[],[_]=F}) ->
{F,[X]};
in_r(X, {R,F}) when is_list(R), is_list(F) ->
@@ -146,10 +133,9 @@ in_r(X, Q) ->
%% Take from head/front
%%
%% O(1) amortized, O(len(Q)) worst case
--spec out(Q1) -> Result when
- Q1 :: queue(),
- Q2 :: queue(),
- Result :: {{value, Item :: term()}, Q2} | {empty, Q1}.
+-spec out(Q1 :: queue()) ->
+ {{value, Item :: term()}, Q2 :: queue()} |
+ {empty, Q1 :: queue()}.
out({[],[]}=Q) ->
{empty,Q};
out({[V],[]}) ->
@@ -167,10 +153,9 @@ out(Q) ->
%% Take from tail/rear
%%
%% O(1) amortized, O(len(Q)) worst case
--spec out_r(Q1) -> Result when
- Q1 :: queue(),
- Q2 :: queue(),
- Result :: {{value, Item :: term()}, Q2} | {empty, Q1}.
+-spec out_r(Q1 :: queue()) ->
+ {{value, Item :: term()}, Q2 :: queue()} |
+ {empty, Q1 :: queue()}.
out_r({[],[]}=Q) ->
{empty,Q};
out_r({[],[V]}) ->
@@ -191,9 +176,7 @@ out_r(Q) ->
%% Return the first element in the queue
%%
%% O(1) since the queue is supposed to be well formed
--spec get(Q) -> Item when
- Q :: queue(),
- Item :: term().
+-spec get(Q :: queue()) -> Item :: term().
get({[],[]}=Q) ->
erlang:error(empty, [Q]);
get({R,F}) when is_list(R), is_list(F) ->
@@ -212,9 +195,7 @@ get([_|R], []) -> % malformed queue -> O(len(Q))
%% Return the last element in the queue
%%
%% O(1) since the queue is supposed to be well formed
--spec get_r(Q) -> Item when
- Q :: queue(),
- Item :: term().
+-spec get_r(Q :: queue()) -> Item :: term().
get_r({[],[]}=Q) ->
erlang:error(empty, [Q]);
get_r({[H|_],F}) when is_list(F) ->
@@ -229,9 +210,7 @@ get_r(Q) ->
%% Return the first element in the queue
%%
%% O(1) since the queue is supposed to be well formed
--spec peek(Q) -> 'empty' | {'value',Item} when
- Q :: queue(),
- Item :: term().
+-spec peek(Q :: queue()) -> empty | {value,Item :: term()}.
peek({[],[]}) ->
empty;
peek({R,[H|_]}) when is_list(R) ->
@@ -246,9 +225,7 @@ peek(Q) ->
%% Return the last element in the queue
%%
%% O(1) since the queue is supposed to be well formed
--spec peek_r(Q) -> 'empty' | {'value',Item} when
- Q :: queue(),
- Item :: term().
+-spec peek_r(Q :: queue()) -> empty | {value,Item :: term()}.
peek_r({[],[]}) ->
empty;
peek_r({[H|_],F}) when is_list(F) ->
@@ -263,9 +240,7 @@ peek_r(Q) ->
%% Remove the first element and return resulting queue
%%
%% O(1) amortized
--spec drop(Q1) -> Q2 when
- Q1 :: queue(),
- Q2 :: queue().
+-spec drop(Q1 :: queue()) -> Q2 :: queue().
drop({[],[]}=Q) ->
erlang:error(empty, [Q]);
drop({[_],[]}) ->
@@ -283,9 +258,7 @@ drop(Q) ->
%% Remove the last element and return resulting queue
%%
%% O(1) amortized
--spec drop_r(Q1) -> Q2 when
- Q1 :: queue(),
- Q2 :: queue().
+-spec drop_r(Q1 :: queue()) -> Q2 :: queue().
drop_r({[],[]}=Q) ->
erlang:error(empty, [Q]);
drop_r({[],[_]}) ->
@@ -306,9 +279,7 @@ drop_r(Q) ->
%% Return reversed queue
%%
%% O(1)
--spec reverse(Q1) -> Q2 when
- Q1 :: queue(),
- Q2 :: queue().
+-spec reverse(Q1 :: queue()) -> Q2 :: queue().
reverse({R,F}) when is_list(R), is_list(F) ->
{F,R};
reverse(Q) ->
@@ -318,10 +289,7 @@ reverse(Q) ->
%%
%% Q2 empty: O(1)
%% else: O(len(Q1))
--spec join(Q1, Q2) -> Q3 when
- Q1 :: queue(),
- Q2 :: queue(),
- Q3 :: queue().
+-spec join(Q1 :: queue(), Q2 :: queue()) -> Q3 :: queue().
join({R,F}=Q, {[],[]}) when is_list(R), is_list(F) ->
Q;
join({[],[]}, {R,F}=Q) when is_list(R), is_list(F) ->
@@ -335,11 +303,8 @@ join(Q1, Q2) ->
%%
%% N = 0..len(Q)
%% O(max(N, len(Q)))
--spec split(N, Q1) -> {Q2,Q3} when
- N :: non_neg_integer(),
- Q1 :: queue(),
- Q2 :: queue(),
- Q3 :: queue().
+-spec split(N :: non_neg_integer(), Q1 :: queue()) ->
+ {Q2 :: queue(),Q3 :: queue()}.
split(0, {R,F}=Q) when is_list(R), is_list(F) ->
{{[],[]},Q};
split(N, {R,F}=Q) when is_integer(N), N >= 1, is_list(R), is_list(F) ->
@@ -380,10 +345,8 @@ split_r1_to_f2(N, [X|R1], F1, R2, F2) ->
%%
%% Fun(_) -> List: O(length(List) * len(Q))
%% else: O(len(Q)
--spec filter(Fun, Q1) -> Q2 when
- Fun :: fun((Item :: term()) -> boolean() | list()),
- Q1 :: queue(),
- Q2 :: queue().
+-spec filter(Fun, Q1 :: queue()) -> Q2 :: queue() when
+ Fun :: fun((Item :: term()) -> boolean() | list()).
filter(Fun, {R0,F0}) when is_function(Fun, 1), is_list(R0), is_list(F0) ->
F = filter_f(Fun, F0),
R = filter_r(Fun, R0),
@@ -459,10 +422,7 @@ filter_r(Fun, [X|R0]) ->
%% Cons to head
%%
--spec cons(Item, Q1) -> Q2 when
- Item :: term(),
- Q1 :: queue(),
- Q2 :: queue().
+-spec cons(Item :: term(), Q1 :: queue()) -> Q2 :: queue().
cons(X, Q) ->
in_r(X, Q).
@@ -471,9 +431,7 @@ cons(X, Q) ->
%% Return the first element in the queue
%%
%% O(1) since the queue is supposed to be well formed
--spec head(Q) -> Item when
- Q :: queue(),
- Item :: term().
+-spec head(Q :: queue()) -> Item :: term().
head({[],[]}=Q) ->
erlang:error(empty, [Q]);
head({R,F}) when is_list(R), is_list(F) ->
@@ -483,9 +441,7 @@ head(Q) ->
%% Remove head element and return resulting queue
%%
--spec tail(Q1) -> Q2 when
- Q1 :: queue(),
- Q2 :: queue().
+-spec tail(Q1 :: queue()) -> Q2 :: queue().
tail(Q) ->
drop(Q).
@@ -493,35 +449,22 @@ tail(Q) ->
%% Cons to tail
%%
--spec snoc(Q1, Item) -> Q2 when
- Q1 :: queue(),
- Q2 :: queue(),
- Item :: term().
+-spec snoc(Q1 :: queue(), Item :: term()) -> Q2 :: queue().
snoc(Q, X) ->
in(X, Q).
%% Return last element
--spec daeh(Q) -> Item when
- Q :: queue(),
- Item :: term().
+-spec daeh(Q :: queue()) -> Item :: term().
daeh(Q) -> get_r(Q).
--spec last(Q) -> Item when
- Q :: queue(),
- Item :: term().
+-spec last(Q :: queue()) -> Item :: term().
last(Q) -> get_r(Q).
%% Remove last element and return resulting queue
--spec liat(Q1) -> Q2 when
- Q1 :: queue(),
- Q2 :: queue().
+-spec liat(Q1 :: queue()) -> Q2 :: queue().
liat(Q) -> drop_r(Q).
--spec lait(Q1) -> Q2 when
- Q1 :: queue(),
- Q2 :: queue().
+-spec lait(Q1 :: queue()) -> Q2 :: queue().
lait(Q) -> drop_r(Q). %% Oops, mis-spelled 'tail' reversed. Forget this one.
--spec init(Q1) -> Q2 when
- Q1 :: queue(),
- Q2 :: queue().
+-spec init(Q1 :: queue()) -> Q2 :: queue().
init(Q) -> drop_r(Q).
%%--------------------------------------------------------------------------
diff --git a/lib/stdlib/src/random.erl b/lib/stdlib/src/random.erl
index dbb524cc74..d7b51a151c 100644
--- a/lib/stdlib/src/random.erl
+++ b/lib/stdlib/src/random.erl
@@ -26,6 +26,10 @@
-export([seed/0, seed/1, seed/3, uniform/0, uniform/1,
uniform_s/1, uniform_s/2, seed0/0]).
+-define(PRIME1, 30269).
+-define(PRIME2, 30307).
+-define(PRIME3, 30323).
+
%%-----------------------------------------------------------------------
%% The type of the state
@@ -44,7 +48,11 @@ seed0() ->
-spec seed() -> ran().
seed() ->
- reseed(seed0()).
+ case seed_put(seed0()) of
+ undefined -> seed0();
+ {_,_,_} = Tuple -> Tuple
+ end.
+
%% seed({A1, A2, A3})
%% Seed random number generation
@@ -66,17 +74,15 @@ seed({A1, A2, A3}) ->
A3 :: integer().
seed(A1, A2, A3) ->
- put(random_seed,
- {abs(A1) rem 30269, abs(A2) rem 30307, abs(A3) rem 30323}).
+ seed_put({(abs(A1) rem (?PRIME1-1)) + 1, % Avoid seed numbers that are
+ (abs(A2) rem (?PRIME2-1)) + 1, % even divisors of the
+ (abs(A3) rem (?PRIME3-1)) + 1}). % corresponding primes.
--spec reseed(ran()) -> ran().
-
-reseed({A1, A2, A3}) ->
- case seed(A1, A2, A3) of
- undefined -> seed0();
- {_,_,_} = Tuple -> Tuple
- end.
+-spec seed_put(ran()) -> 'undefined' | ran().
+
+seed_put(Seed) ->
+ put(random_seed, Seed).
%% uniform()
%% Returns a random float between 0 and 1.
@@ -88,11 +94,11 @@ uniform() ->
undefined -> seed0();
Tuple -> Tuple
end,
- B1 = (A1*171) rem 30269,
- B2 = (A2*172) rem 30307,
- B3 = (A3*170) rem 30323,
+ B1 = (A1*171) rem ?PRIME1,
+ B2 = (A2*172) rem ?PRIME2,
+ B3 = (A3*170) rem ?PRIME3,
put(random_seed, {B1,B2,B3}),
- R = A1/30269 + A2/30307 + A3/30323,
+ R = B1/?PRIME1 + B2/?PRIME2 + B3/?PRIME3,
R - trunc(R).
%% uniform(N) -> I
@@ -116,10 +122,10 @@ uniform(N) when is_integer(N), N >= 1 ->
State1 :: ran().
uniform_s({A1, A2, A3}) ->
- B1 = (A1*171) rem 30269,
- B2 = (A2*172) rem 30307,
- B3 = (A3*170) rem 30323,
- R = A1/30269 + A2/30307 + A3/30323,
+ B1 = (A1*171) rem ?PRIME1,
+ B2 = (A2*172) rem ?PRIME2,
+ B3 = (A3*170) rem ?PRIME3,
+ R = B1/?PRIME1 + B2/?PRIME2 + B3/?PRIME3,
{R - trunc(R), {B1,B2,B3}}.
%% uniform_s(N, State) -> {I, NewState}
diff --git a/lib/stdlib/src/re.erl b/lib/stdlib/src/re.erl
index e08258a535..246d535943 100644
--- a/lib/stdlib/src/re.erl
+++ b/lib/stdlib/src/re.erl
@@ -48,7 +48,7 @@ split(Subject,RE) ->
Subject :: iodata() | unicode:charlist(),
RE :: mp() | iodata() | unicode:charlist(),
Options :: [ Option ],
- Option :: anchored | global | notbol | noteol | notempty
+ Option :: anchored | notbol | noteol | notempty
| {offset, non_neg_integer()} | {newline, nl_spec()}
| bsr_anycrlf | bsr_unicode | {return, ReturnType}
| {parts, NumParts} | group | trim | CompileOpt,
@@ -573,10 +573,10 @@ ucompile(RE,Options) ->
re:compile(unicode:characters_to_binary(RE,unicode),Options)
catch
error:AnyError ->
- {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} =
+ {'EXIT',{new_stacktrace,[{Mod,_,L,Loc}|Rest]}} =
(catch erlang:error(new_stacktrace,
[RE,Options])),
- erlang:raise(error,AnyError,[{Mod,compile,L}|Rest])
+ erlang:raise(error,AnyError,[{Mod,compile,L,Loc}|Rest])
end.
@@ -585,10 +585,10 @@ urun(Subject,RE,Options) ->
urun2(Subject,RE,Options)
catch
error:AnyError ->
- {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} =
+ {'EXIT',{new_stacktrace,[{Mod,_,L,Loc}|Rest]}} =
(catch erlang:error(new_stacktrace,
[Subject,RE,Options])),
- erlang:raise(error,AnyError,[{Mod,run,L}|Rest])
+ erlang:raise(error,AnyError,[{Mod,run,L,Loc}|Rest])
end.
urun2(Subject0,RE0,Options0) ->
@@ -625,20 +625,20 @@ grun(Subject,RE,{Options,NeedClean}) ->
grun2(Subject,RE,{Options,NeedClean})
catch
error:AnyError ->
- {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} =
+ {'EXIT',{new_stacktrace,[{Mod,_,L,Loc}|Rest]}} =
(catch erlang:error(new_stacktrace,
[Subject,RE,Options])),
- erlang:raise(error,AnyError,[{Mod,run,L}|Rest])
+ erlang:raise(error,AnyError,[{Mod,run,L,Loc}|Rest])
end;
grun(Subject,RE,{Options,NeedClean,OrigRE}) ->
try
grun2(Subject,RE,{Options,NeedClean})
catch
error:AnyError ->
- {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} =
+ {'EXIT',{new_stacktrace,[{Mod,_,L,Loc}|Rest]}} =
(catch erlang:error(new_stacktrace,
[Subject,OrigRE,Options])),
- erlang:raise(error,AnyError,[{Mod,run,L}|Rest])
+ erlang:raise(error,AnyError,[{Mod,run,L,Loc}|Rest])
end.
grun2(Subject,RE,{Options,NeedClean}) ->
diff --git a/lib/stdlib/src/shell.erl b/lib/stdlib/src/shell.erl
index e3e23e09bc..964697cae6 100644
--- a/lib/stdlib/src/shell.erl
+++ b/lib/stdlib/src/shell.erl
@@ -1088,7 +1088,7 @@ shell_default(F,As,Bs) ->
end.
shell_undef(F,A) ->
- erlang:error({shell_undef,F,A}).
+ erlang:error({shell_undef,F,A,[]}).
local_func_handler(Shell, RT, Ef) ->
H = fun(Lf) ->
diff --git a/lib/stdlib/src/sofs.erl b/lib/stdlib/src/sofs.erl
index d38b8ab37a..34eb224647 100644
--- a/lib/stdlib/src/sofs.erl
+++ b/lib/stdlib/src/sofs.erl
@@ -81,7 +81,8 @@
-define(ORDTAG, 'OrdSet').
-record(?TAG, {data = [] :: list(), type = type :: term()}).
--record(?ORDTAG, {orddata = {} :: tuple(), ordtype = type :: term()}).
+-record(?ORDTAG, {orddata = {} :: tuple() | atom(),
+ ordtype = type :: term()}).
-define(LIST(S), (S)#?TAG.data).
-define(TYPE(S), (S)#?TAG.type).
@@ -375,7 +376,7 @@ to_sets(S) when ?IS_ORDSET(S) ->
-spec(no_elements(ASet) -> NoElements when
ASet :: a_set() | ordset(),
- NoElements :: pos_integer()).
+ NoElements :: non_neg_integer()).
no_elements(S) when ?IS_SET(S) ->
length(?LIST(S));
no_elements(S) when ?IS_ORDSET(S), is_tuple(?ORDTYPE(S)) ->
diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl
index e60706ed05..2dd5ccce7a 100644
--- a/lib/stdlib/src/supervisor.erl
+++ b/lib/stdlib/src/supervisor.erl
@@ -27,8 +27,6 @@
which_children/1, count_children/1,
check_childspecs/1]).
--export([behaviour_info/1]).
-
%% Internal exports
-export([init/1, handle_call/3, handle_info/2, terminate/2, code_change/3]).
-export([handle_cast/2]).
@@ -90,14 +88,12 @@
-define(is_simple(State), State#state.strategy =:= simple_one_for_one).
-%%--------------------------------------------------------------------------
-
--spec behaviour_info(atom()) -> 'undefined' | [{atom(), arity()}].
-
-behaviour_info(callbacks) ->
- [{init,1}];
-behaviour_info(_Other) ->
- undefined.
+-callback init(Args :: term()) ->
+ {ok, {{RestartStrategy :: strategy(),
+ MaxR :: non_neg_integer(),
+ MaxT :: non_neg_integer()},
+ [ChildSpec :: child_spec()]}}
+ | ignore.
%%% ---------------------------------------------------
%%% This is a general process supervisor built upon gen_server.erl.
@@ -519,9 +515,12 @@ handle_info(Msg, State) ->
%%
-spec terminate(term(), state()) -> 'ok'.
+terminate(_Reason, #state{children=[Child]} = State) when ?is_simple(State) ->
+ terminate_dynamic_children(Child, dynamics_db(Child#child.restart_type,
+ State#state.dynamics),
+ State#state.name);
terminate(_Reason, State) ->
- terminate_children(State#state.children, State#state.name),
- ok.
+ terminate_children(State#state.children, State#state.name).
%%
%% Change code for the supervisor.
@@ -661,6 +660,9 @@ do_restart(_, normal, Child, State) ->
do_restart(_, shutdown, Child, State) ->
NState = state_del_child(Child, State),
{ok, NState};
+do_restart(_, {shutdown, _Term}, Child, State) ->
+ NState = state_del_child(Child, State),
+ {ok, NState};
do_restart(transient, Reason, Child, State) ->
report_error(child_terminated, Reason, Child, State#state.name),
restart(Child, State);
@@ -735,6 +737,13 @@ restart(one_for_all, Child, State) ->
terminate_children(Children, SupName) ->
terminate_children(Children, SupName, []).
+%% Temporary children should not be restarted and thus should
+%% be skipped when building the list of terminated children, although
+%% we do want them to be shut down as many functions from this module
+%% use this function to just clear everything.
+terminate_children([Child = #child{restart_type=temporary} | Children], SupName, Res) ->
+ do_terminate(Child, SupName),
+ terminate_children(Children, SupName, Res);
terminate_children([Child | Children], SupName, Res) ->
NChild = do_terminate(Child, SupName),
terminate_children(Children, SupName, [NChild | Res]);
@@ -824,8 +833,109 @@ monitor_child(Pid) ->
%% that will be handled in shutdown/2.
ok
end.
-
-
+
+
+%%-----------------------------------------------------------------
+%% Func: terminate_dynamic_children/3
+%% Args: Child = child_rec()
+%% Dynamics = ?DICT() | ?SET()
+%% SupName = {local, atom()} | {global, atom()} | {pid(),Mod}
+%% Returns: ok
+%%
+%%
+%% Shutdown all dynamic children. This happens when the supervisor is
+%% stopped. Because the supervisor can have millions of dynamic children, we
+%% can have an significative overhead here.
+%%-----------------------------------------------------------------
+terminate_dynamic_children(Child, Dynamics, SupName) ->
+ {Pids, EStack0} = monitor_dynamic_children(Child, Dynamics),
+ Sz = ?SETS:size(Pids),
+ EStack = case Child#child.shutdown of
+ brutal_kill ->
+ ?SETS:fold(fun(P, _) -> exit(P, kill) end, ok, Pids),
+ wait_dynamic_children(Child, Pids, Sz, undefined, EStack0);
+ infinity ->
+ ?SETS:fold(fun(P, _) -> exit(P, shutdown) end, ok, Pids),
+ wait_dynamic_children(Child, Pids, Sz, undefined, EStack0);
+ Time ->
+ ?SETS:fold(fun(P, _) -> exit(P, shutdown) end, ok, Pids),
+ TRef = erlang:start_timer(Time, self(), kill),
+ wait_dynamic_children(Child, Pids, Sz, TRef, EStack0)
+ end,
+ %% Unrool stacked errors and report them
+ ?DICT:fold(fun(Reason, Ls, _) ->
+ report_error(shutdown_error, Reason,
+ Child#child{pid=Ls}, SupName)
+ end, ok, EStack).
+
+
+monitor_dynamic_children(#child{restart_type=temporary}, Dynamics) ->
+ ?SETS:fold(fun(P, {Pids, EStack}) ->
+ case monitor_child(P) of
+ ok ->
+ {?SETS:add_element(P, Pids), EStack};
+ {error, normal} ->
+ {Pids, EStack};
+ {error, Reason} ->
+ {Pids, ?DICT:append(Reason, P, EStack)}
+ end
+ end, {?SETS:new(), ?DICT:new()}, Dynamics);
+monitor_dynamic_children(#child{restart_type=RType}, Dynamics) ->
+ ?DICT:fold(fun(P, _, {Pids, EStack}) ->
+ case monitor_child(P) of
+ ok ->
+ {?SETS:add_element(P, Pids), EStack};
+ {error, normal} when RType =/= permanent ->
+ {Pids, EStack};
+ {error, Reason} ->
+ {Pids, ?DICT:append(Reason, P, EStack)}
+ end
+ end, {?SETS:new(), ?DICT:new()}, Dynamics).
+
+
+wait_dynamic_children(_Child, _Pids, 0, undefined, EStack) ->
+ EStack;
+wait_dynamic_children(_Child, _Pids, 0, TRef, EStack) ->
+ %% If the timer has expired before its cancellation, we must empty the
+ %% mail-box of the 'timeout'-message.
+ erlang:cancel_timer(TRef),
+ receive
+ {timeout, TRef, kill} ->
+ EStack
+ after 0 ->
+ EStack
+ end;
+wait_dynamic_children(#child{shutdown=brutal_kill} = Child, Pids, Sz,
+ TRef, EStack) ->
+ receive
+ {'DOWN', _MRef, process, Pid, killed} ->
+ wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1,
+ TRef, EStack);
+
+ {'DOWN', _MRef, process, Pid, Reason} ->
+ wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1,
+ TRef, ?DICT:append(Reason, Pid, EStack))
+ end;
+wait_dynamic_children(#child{restart_type=RType} = Child, Pids, Sz,
+ TRef, EStack) ->
+ receive
+ {'DOWN', _MRef, process, Pid, shutdown} ->
+ wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1,
+ TRef, EStack);
+
+ {'DOWN', _MRef, process, Pid, normal} when RType =/= permanent ->
+ wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1,
+ TRef, EStack);
+
+ {'DOWN', _MRef, process, Pid, Reason} ->
+ wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1,
+ TRef, ?DICT:append(Reason, Pid, EStack));
+
+ {timeout, TRef, kill} ->
+ ?SETS:fold(fun(P, _) -> exit(P, kill) end, ok, Pids),
+ wait_dynamic_children(Child, Pids, Sz-1, undefined, EStack)
+ end.
+
%%-----------------------------------------------------------------
%% Child/State manipulating functions.
%%-----------------------------------------------------------------
@@ -1047,7 +1157,7 @@ validRestartType(RestartType) -> throw({invalid_restart_type, RestartType}).
validShutdown(Shutdown, _)
when is_integer(Shutdown), Shutdown > 0 -> true;
-validShutdown(infinity, supervisor) -> true;
+validShutdown(infinity, _) -> true;
validShutdown(brutal_kill, _) -> true;
validShutdown(Shutdown, _) -> throw({invalid_shutdown, Shutdown}).
@@ -1128,6 +1238,13 @@ report_error(Error, Reason, Child, SupName) ->
error_logger:error_report(supervisor_report, ErrorMsg).
+extract_child(Child) when is_list(Child#child.pid) ->
+ [{nb_children, length(Child#child.pid)},
+ {name, Child#child.name},
+ {mfargs, Child#child.mfargs},
+ {restart_type, Child#child.restart_type},
+ {shutdown, Child#child.shutdown},
+ {child_type, Child#child.child_type}];
extract_child(Child) ->
[{pid, Child#child.pid},
{name, Child#child.name},
diff --git a/lib/stdlib/src/supervisor_bridge.erl b/lib/stdlib/src/supervisor_bridge.erl
index 555cb5a66f..e8405ab9a4 100644
--- a/lib/stdlib/src/supervisor_bridge.erl
+++ b/lib/stdlib/src/supervisor_bridge.erl
@@ -22,15 +22,14 @@
%% External exports
-export([start_link/2, start_link/3]).
--export([behaviour_info/1]).
%% Internal exports
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2]).
-export([code_change/3]).
-behaviour_info(callbacks) ->
- [{init,1},{terminate,2}];
-behaviour_info(_Other) ->
- undefined.
+-callback init(Args :: term()) ->
+ {ok, Pid :: pid(), State :: term()} | ignore | {error, Error :: term()}.
+-callback terminate(Reason :: (shutdown | term()), State :: term()) ->
+ Ignored :: term().
%%%-----------------------------------------------------------------
%%% This is a rewrite of supervisor_bridge from BS.3.
diff --git a/lib/stdlib/src/sys.erl b/lib/stdlib/src/sys.erl
index 8ab72c9b50..f34201604c 100644
--- a/lib/stdlib/src/sys.erl
+++ b/lib/stdlib/src/sys.erl
@@ -154,7 +154,7 @@ log_to_file(Name, FileName, Timeout) ->
-spec statistics(Name, Flag) -> 'ok' | {'ok', Statistics} when
Name :: name(),
Flag :: 'true' | 'false' | 'get',
- Statistics :: [StatisticsTuple],
+ Statistics :: [StatisticsTuple] | no_statistics,
StatisticsTuple :: {'start_time', DateTime1}
| {'current_time', DateTime2}
| {'reductions', non_neg_integer()}
@@ -168,7 +168,7 @@ statistics(Name, Flag) ->
-spec statistics(Name, Flag, Timeout) -> 'ok' | {'ok', Statistics} when
Name :: name(),
Flag :: 'true' | 'false' | 'get',
- Statistics :: [StatisticsTuple],
+ Statistics :: [StatisticsTuple] | no_statistics,
StatisticsTuple :: {'start_time', DateTime1}
| {'current_time', DateTime2}
| {'reductions', non_neg_integer()}
diff --git a/lib/stdlib/src/timer.erl b/lib/stdlib/src/timer.erl
index 89fae05e4f..689e42051f 100644
--- a/lib/stdlib/src/timer.erl
+++ b/lib/stdlib/src/timer.erl
@@ -199,9 +199,9 @@ tc(M, F, A) ->
%% Calculate the time difference (in microseconds) of two
%% erlang:now() timestamps, T2-T1.
%%
--spec now_diff(T1, T2) -> Tdiff when
- T1 :: calendar:t_now(),
- T2 :: calendar:t_now(),
+-spec now_diff(T2, T1) -> Tdiff when
+ T1 :: erlang:timestamp(),
+ T2 :: erlang:timestamp(),
Tdiff :: integer().
now_diff({A2, B2, C2}, {A1, B1, C1}) ->
((A2-A1)*1000000 + B2-B1)*1000000 + C2-C1.
diff --git a/lib/stdlib/src/unicode.erl b/lib/stdlib/src/unicode.erl
index a5d9965ca2..e9b90befe6 100644
--- a/lib/stdlib/src/unicode.erl
+++ b/lib/stdlib/src/unicode.erl
@@ -73,7 +73,7 @@ characters_to_list_int(ML, Encoding) ->
_ ->
badarg
end,
- {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} =
+ {'EXIT',{new_stacktrace,[{Mod,_,L,_}|Rest]}} =
(catch erlang:error(new_stacktrace,
[ML,Encoding])),
erlang:raise(error,TheError,[{Mod,characters_to_list,L}|Rest])
@@ -109,7 +109,7 @@ characters_to_binary(ML) ->
_ ->
badarg
end,
- {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} =
+ {'EXIT',{new_stacktrace,[{Mod,_,L,_}|Rest]}} =
(catch erlang:error(new_stacktrace,
[ML])),
erlang:raise(error,TheError,[{Mod,characters_to_binary,L}|Rest])
@@ -127,7 +127,7 @@ characters_to_binary_int(ML,InEncoding) ->
_ ->
badarg
end,
- {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} =
+ {'EXIT',{new_stacktrace,[{Mod,_,L,_}|Rest]}} =
(catch erlang:error(new_stacktrace,
[ML,InEncoding])),
erlang:raise(error,TheError,[{Mod,characters_to_binary,L}|Rest])
@@ -159,7 +159,7 @@ characters_to_binary(ML, latin1, Uni) when is_binary(ML) and ((Uni =:= utf8) or
_ ->
badarg
end,
- {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} =
+ {'EXIT',{new_stacktrace,[{Mod,_,L,_}|Rest]}} =
(catch erlang:error(new_stacktrace,
[ML,latin1,Uni])),
erlang:raise(error,TheError,
@@ -181,7 +181,7 @@ characters_to_binary(ML,Uni,latin1) when is_binary(ML) and ((Uni =:= utf8) or
_ ->
badarg
end,
- {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} =
+ {'EXIT',{new_stacktrace,[{Mod,_,L,_}|Rest]}} =
(catch erlang:error(new_stacktrace,
[ML,Uni,latin1])),
erlang:raise(error,TheError,
@@ -200,7 +200,7 @@ characters_to_binary(ML, InEncoding, OutEncoding) ->
_ ->
badarg
end,
- {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} =
+ {'EXIT',{new_stacktrace,[{Mod,_,L,_}|Rest]}} =
(catch erlang:error(new_stacktrace,
[ML,InEncoding,OutEncoding])),
erlang:raise(error,TheError,[{Mod,characters_to_binary,L}|Rest])
diff --git a/lib/stdlib/src/zip.erl b/lib/stdlib/src/zip.erl
index 524d709431..c82c8159b6 100644
--- a/lib/stdlib/src/zip.erl
+++ b/lib/stdlib/src/zip.erl
@@ -223,7 +223,7 @@ openzip_open(F, Options) ->
do_openzip_open(F, Options) ->
Opts = get_openzip_options(Options),
#openzip_opts{output = Output, open_opts = OpO, cwd = CWD} = Opts,
- Input = get_zip_input(F),
+ Input = get_input(F),
In0 = Input({open, F, OpO -- [write]}, []),
{[#zip_comment{comment = C} | Files], In1} =
get_central_dir(In0, fun raw_file_info_etc/5, Input),
@@ -489,7 +489,7 @@ do_list_dir(F, Options) ->
%% Print zip directory in short form
-spec(t(Archive) -> ok when
- Archive :: file:name() | binary | ZipHandle,
+ Archive :: file:name() | binary() | ZipHandle,
ZipHandle :: pid()).
t(F) when is_pid(F) -> zip_t(F);
@@ -513,7 +513,7 @@ do_t(F, RawPrint) ->
%% Print zip directory in long form (like ls -l)
-spec(tt(Archive) -> ok when
- Archive :: file:name() | binary | ZipHandle,
+ Archive :: file:name() | binary() | ZipHandle,
ZipHandle :: pid()).
tt(F) when is_pid(F) -> zip_tt(F);
@@ -1174,7 +1174,7 @@ zip_get(Pid) when is_pid(Pid) ->
zip_close(Pid) when is_pid(Pid) ->
request(self(), Pid, close).
--spec(zip_get(FileName, ZipHandle) -> {ok, [Result]} | {error, Reason} when
+-spec(zip_get(FileName, ZipHandle) -> {ok, Result} | {error, Reason} when
FileName :: file:name(),
ZipHandle :: pid(),
Result :: file:name() | {file:name(), binary()},
@@ -1183,7 +1183,7 @@ zip_close(Pid) when is_pid(Pid) ->
zip_get(FileName, Pid) when is_pid(Pid) ->
request(self(), Pid, {get, FileName}).
--spec(zip_list_dir(ZipHandle) -> Result | {error, Reason} when
+-spec(zip_list_dir(ZipHandle) -> {ok, Result} | {error, Reason} when
Result :: [zip_comment() | zip_file()],
ZipHandle :: pid(),
Reason :: term()).
diff --git a/lib/stdlib/test/Makefile b/lib/stdlib/test/Makefile
index 5502c69fa5..aa6a660c34 100644
--- a/lib/stdlib/test/Makefile
+++ b/lib/stdlib/test/Makefile
@@ -65,6 +65,7 @@ MODULES= \
stdlib_SUITE \
string_SUITE \
supervisor_1 \
+ supervisor_2 \
naughty_child \
shell_SUITE \
supervisor_SUITE \
diff --git a/lib/stdlib/test/beam_lib_SUITE.erl b/lib/stdlib/test/beam_lib_SUITE.erl
index 4ccc863795..5df19ca7f1 100644
--- a/lib/stdlib/test/beam_lib_SUITE.erl
+++ b/lib/stdlib/test/beam_lib_SUITE.erl
@@ -181,7 +181,8 @@ error(Conf) when is_list(Conf) ->
?line verify(not_a_beam_file, beam_lib:info(<<"short">>)),
?line {Binary1, _} = split_binary(Binary, byte_size(Binary)-10),
- ?line verify(chunk_too_big, beam_lib:chunks(Binary1, ["Abst"])),
+ LastChunk = last_chunk(Binary),
+ ?line verify(chunk_too_big, beam_lib:chunks(Binary1, [LastChunk])),
?line Chunks = chunk_info(Binary),
?line {value, {_, AbstractStart, _}} = lists:keysearch("Abst", 1, Chunks),
?line {Binary2, _} = split_binary(Binary, AbstractStart),
@@ -205,6 +206,12 @@ error(Conf) when is_list(Conf) ->
?line file:delete(ACopy),
ok.
+last_chunk(Bin) ->
+ L = beam_lib:info(Bin),
+ {chunks,Chunks} = lists:keyfind(chunks, 1, L),
+ {Last,_,_} = lists:last(Chunks),
+ Last.
+
do_error(BeamFile, ACopy) ->
% evil tests
?line Chunks = chunk_info(BeamFile),
@@ -242,8 +249,8 @@ cmp(doc) -> ["Compare contents of BEAM files and directories"];
cmp(Conf) when is_list(Conf) ->
?line PrivDir = ?privdir,
- ?line Dir1 = filename:join(PrivDir, dir1),
- ?line Dir2 = filename:join(PrivDir, dir2),
+ ?line Dir1 = filename:join(PrivDir, "dir1"),
+ ?line Dir2 = filename:join(PrivDir, "dir2"),
ok = file:make_dir(Dir1),
ok = file:make_dir(Dir2),
@@ -292,8 +299,8 @@ cmp_literals(doc) -> ["Compare contents of BEAM files having literals"];
cmp_literals(Conf) when is_list(Conf) ->
?line PrivDir = ?privdir,
- ?line Dir1 = filename:join(PrivDir, dir1),
- ?line Dir2 = filename:join(PrivDir, dir2),
+ ?line Dir1 = filename:join(PrivDir, "dir1"),
+ ?line Dir2 = filename:join(PrivDir, "dir2"),
ok = file:make_dir(Dir1),
ok = file:make_dir(Dir2),
@@ -330,6 +337,7 @@ strip(Conf) when is_list(Conf) ->
?line {Source2D1, BeamFile2D1} = make_beam(PrivDir, simple2, concat),
?line {Source3D1, BeamFile3D1} = make_beam(PrivDir, make_fun, make_fun),
?line {Source4D1, BeamFile4D1} = make_beam(PrivDir, constant, constant),
+ ?line {Source5D1, BeamFile5D1} = make_beam(PrivDir, lines, lines),
?line NoOfTables = length(ets:all()),
?line P0 = pps(),
@@ -360,13 +368,25 @@ strip(Conf) when is_list(Conf) ->
?line {module, make_fun} = code:load_abs(filename:rootname(BeamFile3D1)),
?line {module, constant} = code:load_abs(filename:rootname(BeamFile4D1)),
+ %% check that line number information is still present after stripping
+ ?line {module, lines} = code:load_abs(filename:rootname(BeamFile5D1)),
+ ?line {'EXIT',{badarith,[{lines,t,1,Info}|_]}} =
+ (catch lines:t(atom)),
+ ?line true = code:delete(lines),
+ ?line false = code:purge(lines),
+ ?line {ok, {lines,BeamFile5D1}} = beam_lib:strip(BeamFile5D1),
+ ?line {module, lines} = code:load_abs(filename:rootname(BeamFile5D1)),
+ ?line {'EXIT',{badarith,[{lines,t,1,Info}|_]}} =
+ (catch lines:t(atom)),
+
?line true = (P0 == pps()),
?line NoOfTables = length(ets:all()),
?line delete_files([SourceD1, BeamFileD1,
Source2D1, BeamFile2D1,
Source3D1, BeamFile3D1,
- Source4D1, BeamFile4D1]),
+ Source4D1, BeamFile4D1,
+ Source5D1, BeamFile5D1]),
ok.
@@ -381,7 +401,7 @@ otp_6711(Conf) when is_list(Conf) ->
(catch {a, beam_lib:strip_files([3])}),
?line PrivDir = ?privdir,
- ?line Dir = filename:join(PrivDir, dir),
+ ?line Dir = filename:join(PrivDir, "dir"),
?line Lib = filename:join(Dir, "lib"),
?line App = filename:join(Lib, "app"),
?line EBin = filename:join(App, "ebin"),
@@ -417,8 +437,8 @@ building(doc) -> "Testing building of BEAM files.";
building(Conf) when is_list(Conf) ->
?line PrivDir = ?privdir,
- ?line Dir1 = filename:join(PrivDir, b_dir1),
- ?line Dir2 = filename:join(PrivDir, b_dir2),
+ ?line Dir1 = filename:join(PrivDir, "b_dir1"),
+ ?line Dir2 = filename:join(PrivDir, "b_dir2"),
ok = file:make_dir(Dir1),
ok = file:make_dir(Dir2),
@@ -571,8 +591,18 @@ do_encrypted_abstr(Beam, Key) ->
?line {ok,{simple,[{"Abst",Abst}]}} = beam_lib:chunks(Beam, ["Abst"]),
?line {ok,cleared} = beam_lib:clear_crypto_key_fun(),
+
+ %% Try to force a stop/start race.
+ ?line start_stop_race(10000),
+
ok.
+start_stop_race(0) ->
+ ok;
+start_stop_race(N) ->
+ {error,_} = beam_lib:crypto_key_fun(bad_fun),
+ undefined = beam_lib:clear_crypto_key_fun(),
+ start_stop_race(N-1).
bad_fun(F) ->
{error,E} = beam_lib:crypto_key_fun(F),
@@ -688,7 +718,7 @@ chunk_info(File) ->
Chunks.
make_beam(Dir, Module, F) ->
- ?line FileBase = filename:join(Dir, Module),
+ ?line FileBase = filename:join(Dir, atom_to_list(Module)),
?line Source = FileBase ++ ".erl",
?line BeamFile = FileBase ++ ".beam",
?line simple_file(Source, Module, F),
@@ -773,6 +803,12 @@ simple_file(File, Module, constant2) ->
"t(A) -> "
" {a,b,[2,3],x,y}. "]),
ok = file:write_file(File, B);
+simple_file(File, Module, lines) ->
+ B = list_to_binary(["-module(", atom_to_list(Module), ").\n"
+ "-export([t/1]).\n"
+ "t(A) ->\n"
+ " A+1.\n"]),
+ ok = file:write_file(File, B);
simple_file(File, Module, F) ->
B = list_to_binary(["-module(", atom_to_list(Module), "). "
"-export([t/0]). "
diff --git a/lib/stdlib/test/dets_SUITE.erl b/lib/stdlib/test/dets_SUITE.erl
index 698070368f..6f77cff2b9 100644
--- a/lib/stdlib/test/dets_SUITE.erl
+++ b/lib/stdlib/test/dets_SUITE.erl
@@ -34,6 +34,8 @@
-define(datadir(Conf), ?config(data_dir, Conf)).
-endif.
+-compile(r13). % OTP-9607
+
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
not_run/1, newly_started/1, basic_v8/1, basic_v9/1,
@@ -53,7 +55,7 @@
simultaneous_open/1, insert_new/1, repair_continuation/1,
otp_5487/1, otp_6206/1, otp_6359/1, otp_4738/1, otp_7146/1,
otp_8070/1, otp_8856/1, otp_8898/1, otp_8899/1, otp_8903/1,
- otp_8923/1, otp_9282/1]).
+ otp_8923/1, otp_9282/1, otp_9607/1]).
-export([dets_dirty_loop/0]).
@@ -112,7 +114,7 @@ all() ->
many_clients, otp_4906, otp_5402, simultaneous_open,
insert_new, repair_continuation, otp_5487, otp_6206,
otp_6359, otp_4738, otp_7146, otp_8070, otp_8856, otp_8898,
- otp_8899, otp_8903, otp_8923, otp_9282]
+ otp_8899, otp_8903, otp_8923, otp_9282, otp_9607]
end.
groups() ->
@@ -554,7 +556,11 @@ dets_dirty_loop() ->
{From, [write, Name, Value]} ->
Ret = dets:insert(Name, Value),
From ! {self(), Ret},
- dets_dirty_loop()
+ dets_dirty_loop();
+ {From, [close, Name]} ->
+ Ret = dets:close(Name),
+ From ! {self(), Ret},
+ dets_dirty_loop()
end.
@@ -1516,7 +1522,7 @@ repair(Config, V) ->
if
V =:= 8 ->
%% first estimated number of objects is wrong, repair once more
- ?line {ok, Fd} = file:open(Fname, read_write),
+ ?line {ok, Fd} = file:open(Fname, [read,write]),
NoPos = HeadSize - 8, % no_objects
?line file:pwrite(Fd, NoPos, <<0:32>>), % NoItems
ok = file:close(Fd),
@@ -1568,8 +1574,10 @@ repair(Config, V) ->
?line FileSize = dets:info(TabRef, memory),
?line ok = dets:close(TabRef),
crash(Fname, FileSize+20),
- ?line {error, {bad_freelists, Fname}} =
+ %% Used to return bad_freelists, but that changed in OTP-9622
+ ?line {ok, TabRef} =
dets:open_file(TabRef, [{file,Fname},{version,V}]),
+ ?line ok = dets:close(TabRef),
?line file:delete(Fname),
%% File not closed, opening with read and read_write access tried.
@@ -1857,10 +1865,10 @@ fixtable(Config, Version) when is_list(Config) ->
?line {ok, _} = dets:open_file(T, Args),
%% badarg
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} =
- (catch dets:safe_fixtable(no_table,true)),
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[T,undefined]}|_]}} =
- (catch dets:safe_fixtable(T,undefined)),
+ ?line check_badarg(catch dets:safe_fixtable(no_table,true),
+ dets, safe_fixtable, [no_table,true]),
+ ?line check_badarg(catch dets:safe_fixtable(T,undefined),
+ dets, safe_fixtable, [T,undefined]),
%% The table is not allowed to grow while the elements are inserted:
@@ -1940,22 +1948,22 @@ match(Config, Version) ->
%% match, badarg
MSpec = [{'_',[],['$_']}],
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} =
- (catch dets:match(no_table, '_')),
- ?line {'EXIT', {badarg, [{dets,match,[T,'_',not_a_number]}|_]}} =
- (catch dets:match(T, '_', not_a_number)),
+ ?line check_badarg(catch dets:match(no_table, '_'),
+ dets, safe_fixtable, [no_table,true]),
+ ?line check_badarg(catch dets:match(T, '_', not_a_number),
+ dets, match, [T,'_',not_a_number]),
?line {EC1, _} = dets:select(T, MSpec, 1),
- ?line {'EXIT', {badarg, [{dets,match,[EC1]}|_]}} =
- (catch dets:match(EC1)),
+ ?line check_badarg(catch dets:match(EC1),
+ dets, match, [EC1]),
%% match_object, badarg
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} =
- (catch dets:match_object(no_table, '_')),
- ?line {'EXIT', {badarg, [{dets,match_object,[T,'_',not_a_number]}|_]}} =
- (catch dets:match_object(T, '_', not_a_number)),
+ ?line check_badarg(catch dets:match_object(no_table, '_'),
+ dets, safe_fixtable, [no_table,true]),
+ ?line check_badarg(catch dets:match_object(T, '_', not_a_number),
+ dets, match_object, [T,'_',not_a_number]),
?line {EC2, _} = dets:select(T, MSpec, 1),
- ?line {'EXIT', {badarg, [{dets,match_object,[EC2]}|_]}} =
- (catch dets:match_object(EC2)),
+ ?line check_badarg(catch dets:match_object(EC2),
+ dets, match_object, [EC2]),
dets:safe_fixtable(T, true),
?line {[_, _], C1} = dets:match_object(T, '_', 2),
@@ -2118,17 +2126,17 @@ select(Config, Version) ->
%% badarg
MSpec = [{'_',[],['$_']}],
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} =
- (catch dets:select(no_table, MSpec)),
- ?line {'EXIT', {badarg, [{dets,select,[T,<<17>>]}|_]}} =
- (catch dets:select(T, <<17>>)),
- ?line {'EXIT', {badarg, [{dets,select,[T,[]]}|_]}} =
- (catch dets:select(T, [])),
- ?line {'EXIT', {badarg, [{dets,select,[T,MSpec,not_a_number]}|_]}} =
- (catch dets:select(T, MSpec, not_a_number)),
+ ?line check_badarg(catch dets:select(no_table, MSpec),
+ dets, safe_fixtable, [no_table,true]),
+ ?line check_badarg(catch dets:select(T, <<17>>),
+ dets, select, [T,<<17>>]),
+ ?line check_badarg(catch dets:select(T, []),
+ dets, select, [T,[]]),
+ ?line check_badarg(catch dets:select(T, MSpec, not_a_number),
+ dets, select, [T,MSpec,not_a_number]),
?line {EC, _} = dets:match(T, '_', 1),
- ?line {'EXIT', {badarg, [{dets,select,[EC]}|_]}} =
- (catch dets:select(EC)),
+ ?line check_badarg(catch dets:select(EC),
+ dets, select, [EC]),
AllSpec = [{'_',[],['$_']}],
@@ -2210,8 +2218,8 @@ update_counter(Config) when is_list(Config) ->
?line file:delete(Fname),
P0 = pps(),
- ?line {'EXIT', {badarg, [{dets,update_counter,[no_table,1,1]}|_]}} =
- (catch dets:update_counter(no_table, 1, 1)),
+ ?line check_badarg(catch dets:update_counter(no_table, 1, 1),
+ dets, update_counter, [no_table,1,1]),
Args = [{file,Fname},{keypos,2}],
?line {ok, _} = dets:open_file(T, [{type,set} | Args]),
@@ -2254,66 +2262,66 @@ badarg(Config) when is_list(Config) ->
%% badargs are tested in match, select and fixtable too.
%% open
- ?line {'EXIT', {badarg, [{dets,open_file,[{a,tuple},[]]}|_]}} =
- (catch dets:open_file({a,tuple},[])),
- ?line {'EXIT', {badarg, [{dets,open_file,[{a,tuple}]}|_]}} =
- (catch dets:open_file({a,tuple})),
- ?line {'EXIT', {badarg, [{dets,open_file,[file,[foo]]}|_]}} =
- (catch dets:open_file(file,[foo])),
- ?line {'EXIT', {badarg,[{dets,open_file,[{hej,san},[{type,set}|3]]}|_]}} =
- (catch dets:open_file({hej,san},[{type,set}|3])),
+ ?line check_badarg(catch dets:open_file({a,tuple},[]),
+ dets, open_file, [{a,tuple},[]]),
+ ?line check_badarg(catch dets:open_file({a,tuple}),
+ dets, open_file,[{a,tuple}]),
+ ?line check_badarg(catch dets:open_file(file,[foo]),
+ dets, open_file, [file,[foo]]),
+ ?line check_badarg(catch dets:open_file({hej,san},[{type,set}|3]),
+ dets, open_file, [{hej,san},[{type,set}|3]]),
%% insert
- ?line {'EXIT', {badarg, [{dets,insert,[no_table,{1,2}]}|_]}} =
- (catch dets:insert(no_table, {1,2})),
- ?line {'EXIT', {badarg, [{dets,insert,[no_table,[{1,2}]]}|_]}} =
- (catch dets:insert(no_table, [{1,2}])),
- ?line {'EXIT', {badarg, [{dets,insert,[T,{1,2}]}|_]}} =
- (catch dets:insert(T, {1,2})),
- ?line {'EXIT', {badarg, [{dets,insert,[T,[{1,2}]]}|_]}} =
- (catch dets:insert(T, [{1,2}])),
- ?line {'EXIT', {badarg, [{dets,insert,[T,[{1,2,3}|3]]}|_]}} =
- (catch dets:insert(T, [{1,2,3} | 3])),
+ ?line check_badarg(catch dets:insert(no_table, {1,2}),
+ dets, insert, [no_table,{1,2}]),
+ ?line check_badarg(catch dets:insert(no_table, [{1,2}]),
+ dets, insert, [no_table,[{1,2}]]),
+ ?line check_badarg(catch dets:insert(T, {1,2}),
+ dets, insert, [T,{1,2}]),
+ ?line check_badarg(catch dets:insert(T, [{1,2}]),
+ dets, insert, [T,[{1,2}]]),
+ ?line check_badarg(catch dets:insert(T, [{1,2,3} | 3]),
+ dets, insert, [T,[{1,2,3}|3]]),
%% lookup{_keys}
- ?line {'EXIT', {badarg, [{dets,lookup_keys,[badarg,[]]}|_]}} =
- (catch dets:lookup_keys(T, [])),
- ?line {'EXIT', {badarg, [{dets,lookup,[no_table,1]}|_]}} =
- (catch dets:lookup(no_table, 1)),
- ?line {'EXIT', {badarg, [{dets,lookup_keys,[T,[1|2]]}|_]}} =
- (catch dets:lookup_keys(T, [1 | 2])),
+ ?line check_badarg(catch dets:lookup_keys(T, []),
+ dets, lookup_keys, [badarg,[]]),
+ ?line check_badarg(catch dets:lookup(no_table, 1),
+ dets, lookup, [no_table,1]),
+ ?line check_badarg(catch dets:lookup_keys(T, [1 | 2]),
+ dets, lookup_keys, [T,[1|2]]),
%% member
- ?line {'EXIT', {badarg, [{dets,member,[no_table,1]}|_]}} =
- (catch dets:member(no_table, 1)),
+ ?line check_badarg(catch dets:member(no_table, 1),
+ dets, member, [no_table,1]),
%% sync
- ?line {'EXIT', {badarg, [{dets,sync,[no_table]}|_]}} =
- (catch dets:sync(no_table)),
+ ?line check_badarg(catch dets:sync(no_table),
+ dets, sync, [no_table]),
%% delete{_keys}
- ?line {'EXIT', {badarg, [{dets,delete,[no_table,1]}|_]}} =
- (catch dets:delete(no_table, 1)),
+ ?line check_badarg(catch dets:delete(no_table, 1),
+ dets, delete, [no_table,1]),
%% delete_object
- ?line {'EXIT', {badarg, [{dets,delete_object,[no_table,{1,2,3}]}|_]}} =
- (catch dets:delete_object(no_table, {1,2,3})),
- ?line {'EXIT', {badarg, [{dets,delete_object,[T,{1,2}]}|_]}} =
- (catch dets:delete_object(T, {1,2})),
- ?line {'EXIT', {badarg, [{dets,delete_object,[no_table,[{1,2,3}]]}|_]}} =
- (catch dets:delete_object(no_table, [{1,2,3}])),
- ?line {'EXIT', {badarg, [{dets,delete_object,[T,[{1,2}]]}|_]}} =
- (catch dets:delete_object(T, [{1,2}])),
- ?line {'EXIT', {badarg, [{dets,delete_object,[T,[{1,2,3}|3]]}|_]}} =
- (catch dets:delete_object(T, [{1,2,3} | 3])),
+ ?line check_badarg(catch dets:delete_object(no_table, {1,2,3}),
+ dets, delete_object, [no_table,{1,2,3}]),
+ ?line check_badarg(catch dets:delete_object(T, {1,2}),
+ dets, delete_object, [T,{1,2}]),
+ ?line check_badarg(catch dets:delete_object(no_table, [{1,2,3}]),
+ dets, delete_object, [no_table,[{1,2,3}]]),
+ ?line check_badarg(catch dets:delete_object(T, [{1,2}]),
+ dets, delete_object, [T,[{1,2}]]),
+ ?line check_badarg(catch dets:delete_object(T, [{1,2,3} | 3]),
+ dets, delete_object, [T,[{1,2,3}|3]]),
%% first,next,slot
- ?line {'EXIT', {badarg, [{dets,first,[no_table]}|_]}} =
- (catch dets:first(no_table)),
- ?line {'EXIT', {badarg, [{dets,next,[no_table,1]}|_]}} =
- (catch dets:next(no_table, 1)),
- ?line {'EXIT', {badarg, [{dets,slot,[no_table,0]}|_]}} =
- (catch dets:slot(no_table, 0)),
+ ?line check_badarg(catch dets:first(no_table),
+ dets, first, [no_table]),
+ ?line check_badarg(catch dets:next(no_table, 1),
+ dets, next, [no_table,1]),
+ ?line check_badarg(catch dets:slot(no_table, 0),
+ dets, slot, [no_table,0]),
%% info
?line undefined = dets:info(no_table),
@@ -2321,27 +2329,27 @@ badarg(Config) when is_list(Config) ->
?line undefined = dets:info(T, foo),
%% match_delete
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} =
- (catch dets:match_delete(no_table, '_')),
+ ?line check_badarg(catch dets:match_delete(no_table, '_'),
+ dets, safe_fixtable, [no_table,true]),
%% delete_all_objects
- ?line {'EXIT', {badarg, [{dets,delete_all_objects,[no_table]}|_]}} =
- (catch dets:delete_all_objects(no_table)),
+ ?line check_badarg(catch dets:delete_all_objects(no_table),
+ dets, delete_all_objects, [no_table]),
%% select_delete
MSpec = [{'_',[],['$_']}],
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} =
- (catch dets:select_delete(no_table, MSpec)),
- ?line {'EXIT', {badarg, [{dets,select_delete,[T, <<17>>]}|_]}} =
- (catch dets:select_delete(T, <<17>>)),
+ ?line check_badarg(catch dets:select_delete(no_table, MSpec),
+ dets, safe_fixtable, [no_table,true]),
+ ?line check_badarg(catch dets:select_delete(T, <<17>>),
+ dets, select_delete, [T, <<17>>]),
%% traverse, fold
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} =
- (catch dets:traverse(no_table, fun(_) -> continue end)),
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} =
- (catch dets:foldl(fun(_, A) -> A end, [], no_table)),
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} =
- (catch dets:foldr(fun(_, A) -> A end, [], no_table)),
+ ?line check_badarg(catch dets:traverse(no_table, fun(_) -> continue end),
+ dets, safe_fixtable, [no_table,true]),
+ ?line check_badarg(catch dets:foldl(fun(_, A) -> A end, [], no_table),
+ dets, safe_fixtable, [no_table,true]),
+ ?line check_badarg(catch dets:foldr(fun(_, A) -> A end, [], no_table),
+ dets, safe_fixtable, [no_table,true]),
%% close
?line ok = dets:close(T),
@@ -2349,15 +2357,16 @@ badarg(Config) when is_list(Config) ->
?line {error, not_owner} = dets:close(T),
%% init_table
- ?line {'EXIT', {badarg,[{dets,init_table,[no_table,_,[]]}|_]}} =
- (catch dets:init_table(no_table, fun(X) -> X end)),
- ?line {'EXIT', {badarg,[{dets,init_table,[no_table,_,[]]}|_]}} =
- (catch dets:init_table(no_table, fun(X) -> X end, [])),
+ IF = fun(X) -> X end,
+ ?line check_badarg(catch dets:init_table(no_table, IF),
+ dets, init_table, [no_table,IF,[]]),
+ ?line check_badarg(catch dets:init_table(no_table, IF, []),
+ dets, init_table, [no_table,IF,[]]),
%% from_ets
Ets = ets:new(ets,[]),
- ?line {'EXIT', {badarg,[{dets,from_ets,[no_table,_]}|_]}} =
- (catch dets:from_ets(no_table, Ets)),
+ ?line check_badarg(catch dets:from_ets(no_table, Ets),
+ dets, from_ets, [no_table,Ets]),
ets:delete(Ets),
?line {ok, T} = dets:open_file(T, Args),
@@ -3247,7 +3256,7 @@ otp_5402(suite) ->
[];
otp_5402(Config) when is_list(Config) ->
Tab = otp_5402,
- ?line File = filename:join([cannot, write, this, file]),
+ ?line File = filename:join(["cannot", "write", "this", "file"]),
%% close
?line{ok, T} = dets:open_file(Tab, [{ram_file,true},
@@ -3879,15 +3888,96 @@ some_calls(Tab, Config) ->
?line ok = dets:close(T),
file:delete(File).
+otp_9607(doc) ->
+ ["OTP-9607. Test downgrading the slightly changed format."];
+otp_9607(suite) ->
+ [];
+otp_9607(Config) when is_list(Config) ->
+ %% Note: the bug is about almost full tables. The fix of that
+ %% problem is *not* tested here.
+ Version = r13b,
+ case ?t:is_release_available(atom_to_list(Version)) of
+ true ->
+ T = otp_9607,
+ File = filename(T, Config),
+ Key = a,
+ Value = 1,
+ Args = [{file,File}],
+ ?line {ok, T} = dets:open_file(T, Args),
+ ?line ok = dets:insert(T, {Key, Value}),
+ ?line ok = dets:close(T),
+
+ ?line Call = fun(P, A) ->
+ P ! {self(), A},
+ receive
+ {P, Ans} ->
+ Ans
+ after 5000 ->
+ exit(other_process_dead)
+ end
+ end,
+ %% Create a file on the modified format, read the file
+ %% with an emulator that doesn't know about the modified
+ %% format.
+ ?line {ok, Node} = start_node_rel(Version, Version, slave),
+ ?line Pid = rpc:call(Node, erlang, spawn,
+ [?MODULE, dets_dirty_loop, []]),
+ ?line {error,{needs_repair, File}} =
+ Call(Pid, [open, T, Args++[{repair,false}]]),
+ io:format("Expect repair:~n"),
+ ?line {ok, T} = Call(Pid, [open, T, Args]),
+ ?line [{Key,Value}] = Call(Pid, [read, T, Key]),
+ ?line ok = Call(Pid, [close, T]),
+ file:delete(File),
+
+ %% Create a file on the unmodified format. Modify the file
+ %% using an emulator that must not turn the file into the
+ %% modified format. Read the file and make sure it is not
+ %% repaired.
+ ?line {ok, T} = Call(Pid, [open, T, Args]),
+ ?line ok = Call(Pid, [write, T, {Key,Value}]),
+ ?line [{Key,Value}] = Call(Pid, [read, T, Key]),
+ ?line ok = Call(Pid, [close, T]),
+
+ Key2 = b,
+ Value2 = 2,
+
+ ?line {ok, T} = dets:open_file(T, Args),
+ ?line [{Key,Value}] = dets:lookup(T, Key),
+ ?line ok = dets:insert(T, {Key2,Value2}),
+ ?line ok = dets:close(T),
+
+ ?line {ok, T} = Call(Pid, [open, T, Args++[{repair,false}]]),
+ ?line [{Key2,Value2}] = Call(Pid, [read, T, Key2]),
+ ?line ok = Call(Pid, [close, T]),
+
+ ?t:stop_node(Node),
+ file:delete(File),
+ ok;
+ false ->
+ {skipped, "No support for old node"}
+ end.
+
+
+
%%
%% Parts common to several test cases
%%
+start_node_rel(Name, Rel, How) ->
+ Release = [{release, atom_to_list(Rel)}],
+ ?line Pa = filename:dirname(code:which(?MODULE)),
+ ?line test_server:start_node(Name, How,
+ [{args,
+ " -kernel net_setuptime 100 "
+ " -pa " ++ Pa},
+ {erl, Release}]).
+
crash(File, Where) ->
crash(File, Where, 10).
crash(File, Where, What) when is_integer(What) ->
- ?line {ok, Fd} = file:open(File, read_write),
+ ?line {ok, Fd} = file:open(File, [read,write]),
?line file:position(Fd, Where),
?line ok = file:write(Fd, [What]),
?line ok = file:close(Fd).
@@ -4031,7 +4121,7 @@ writable(Fname) ->
?line file:write_file_info(Fname, Info#file_info{mode = Mode}).
truncate(File, Where) ->
- ?line {ok, Fd} = file:open(File, read_write),
+ ?line {ok, Fd} = file:open(File, [read,write]),
?line file:position(Fd, Where),
?line ok = file:truncate(Fd),
?line ok = file:close(Fd).
@@ -4268,6 +4358,11 @@ bad_object({error,{{bad_object,_}, FileName}}, FileName) ->
bad_object({error,{{{bad_object,_,_},_,_,_}, FileName}}, FileName) ->
ok. % Debug.
+check_badarg({'EXIT', {badarg, [{M,F,Args,_} | _]}}, M, F, Args) ->
+ true;
+check_badarg({'EXIT', {badarg, [{M,F,A,_} | _]}}, M, F, Args) ->
+ true = test_server:is_native(M) andalso length(Args) =:= A.
+
check_pps(P0) ->
case pps() of
P0 ->
diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl
index 9b024a5b49..f79414db49 100644
--- a/lib/stdlib/test/epp_SUITE.erl
+++ b/lib/stdlib/test/epp_SUITE.erl
@@ -20,7 +20,7 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
--export([rec_1/1, predef_mac/1,
+-export([rec_1/1, include_local/1, predef_mac/1,
upcase_mac_1/1, upcase_mac_2/1,
variable_1/1, otp_4870/1, otp_4871/1, otp_5362/1,
pmod/1, not_circular/1, skip_header/1, otp_6277/1, otp_7702/1,
@@ -63,7 +63,7 @@ end_per_testcase(_, Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [rec_1, {group, upcase_mac}, predef_mac,
+ [rec_1, {group, upcase_mac}, include_local, predef_mac,
{group, variable}, otp_4870, otp_4871, otp_5362, pmod,
not_circular, skip_header, otp_6277, otp_7702, otp_8130,
overload_mac, otp_8388, otp_8470, otp_8503, otp_8562,
@@ -97,6 +97,22 @@ rec_1(Config) when is_list(Config) ->
?line check_errors(List),
ok.
+include_local(doc) ->
+ [];
+include_local(suite) ->
+ [];
+include_local(Config) when is_list(Config) ->
+ ?line DataDir = ?config(data_dir, Config),
+ ?line File = filename:join(DataDir, "include_local.erl"),
+ %% include_local.erl includes include/foo.hrl which
+ %% includes bar.hrl (also in include/) without requiring
+ %% any additional include path, and overriding any file
+ %% of the same name that the path points to
+ ?line {ok, List} = epp:parse_file(File, [DataDir], []),
+ ?line {value, {attribute,_,a,{true,true}}} =
+ lists:keysearch(a,3,List),
+ ok.
+
%%% Here is a little reimplementation of epp:parse_file, which times out
%%% after 4 seconds if the epp server doesn't respond. If we use the
%%% regular epp:parse_file, the test case will time out, and then epp
@@ -234,16 +250,23 @@ otp_4871(Config) when is_list(Config) ->
%% so there are some sanity checks before killing.
?line {ok,Epp} = epp:open(File, []),
timer:sleep(1),
- ?line {current_function,{epp,_,_}} = process_info(Epp, current_function),
+ ?line true = current_module(Epp, epp),
?line {monitored_by,[Io]} = process_info(Epp, monitored_by),
- ?line {current_function,{file_io_server,_,_}} =
- process_info(Io, current_function),
+ ?line true = current_module(Io, file_io_server),
?line exit(Io, emulate_crash),
timer:sleep(1),
?line {error,{_Line,epp,cannot_parse}} = otp_4871_parse_file(Epp),
?line epp:close(Epp),
ok.
+current_module(Pid, Mod) ->
+ case process_info(Pid, current_function) of
+ {current_function, undefined} ->
+ true = test_server:is_native(Mod);
+ {current_function, {Mod, _, _}} ->
+ true
+ end.
+
otp_4871_parse_file(Epp) ->
case epp:parse_erl_form(Epp) of
{ok,_} -> otp_4871_parse_file(Epp);
@@ -1280,7 +1303,7 @@ eval_tests(Config, Fun, Tests) ->
check_test(Config, Test) ->
- Filename = 'epp_test.erl',
+ Filename = "epp_test.erl",
?line PrivDir = ?config(priv_dir, Config),
?line File = filename:join(PrivDir, Filename),
?line ok = file:write_file(File, Test),
@@ -1293,7 +1316,7 @@ check_test(Config, Test) ->
compile_test(Config, Test0) ->
Test = [<<"-module(epp_test). -compile(export_all). ">>, Test0],
- Filename = 'epp_test.erl',
+ Filename = "epp_test.erl",
?line PrivDir = ?config(priv_dir, Config),
?line File = filename:join(PrivDir, Filename),
?line ok = file:write_file(File, Test),
diff --git a/lib/stdlib/test/epp_SUITE_data/bar.hrl b/lib/stdlib/test/epp_SUITE_data/bar.hrl
new file mode 100644
index 0000000000..01c527d549
--- /dev/null
+++ b/lib/stdlib/test/epp_SUITE_data/bar.hrl
@@ -0,0 +1,4 @@
+%% should not be included from include/foo.hrl even though the
+%% include path points here - include/bar.hrl overrides it
+
+-define(BAR_HRL, false).
diff --git a/lib/stdlib/test/epp_SUITE_data/include/bar.hrl b/lib/stdlib/test/epp_SUITE_data/include/bar.hrl
new file mode 100644
index 0000000000..038d3c900e
--- /dev/null
+++ b/lib/stdlib/test/epp_SUITE_data/include/bar.hrl
@@ -0,0 +1,3 @@
+%% included from foo.hrl in same directory
+
+-define(BAR_HRL, true).
diff --git a/lib/stdlib/test/epp_SUITE_data/include/foo.hrl b/lib/stdlib/test/epp_SUITE_data/include/foo.hrl
new file mode 100644
index 0000000000..a6dfa3d18a
--- /dev/null
+++ b/lib/stdlib/test/epp_SUITE_data/include/foo.hrl
@@ -0,0 +1,4 @@
+%% includes bar.hrl in same directory
+
+-define(FOO_HRL, true).
+-include("bar.hrl").
diff --git a/lib/stdlib/test/epp_SUITE_data/include_local.erl b/lib/stdlib/test/epp_SUITE_data/include_local.erl
new file mode 100644
index 0000000000..c8e155a064
--- /dev/null
+++ b/lib/stdlib/test/epp_SUITE_data/include_local.erl
@@ -0,0 +1,6 @@
+
+-module(include_local).
+
+-include("include/foo.hrl").
+
+-a({?FOO_HRL, ?BAR_HRL}).
diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl
index 0bcf3c5b71..369d8b224e 100644
--- a/lib/stdlib/test/erl_eval_SUITE.erl
+++ b/lib/stdlib/test/erl_eval_SUITE.erl
@@ -1036,6 +1036,12 @@ funs(Config) when is_list(Config) ->
lists:usort([run_many_args(SAs) || SAs <- many_args(MaxArgs)]),
?line {'EXIT',{{argument_limit,_},_}} =
(catch run_many_args(many_args1(MaxArgs+1))),
+
+ ?line check(fun() -> M = lists, F = fun M:reverse/1,
+ [1,2] = F([2,1]), ok end,
+ "begin M = lists, F = fun M:reverse/1,"
+ " [1,2] = F([2,1]), ok end.",
+ ok),
ok.
run_many_args({S, As}) ->
@@ -1189,7 +1195,7 @@ lfh() ->
{eval, fun(F, As, Bs) -> local_func(F, As, Bs) end}.
local_func(F, As0, Bs0) when is_atom(F) ->
- {As,Bs} = erl_eval:expr_list(As0, Bs0, {eval,lfh()}),
+ {As,Bs} = erl_eval:expr_list(As0, Bs0, lfh()),
case erlang:function_exported(?MODULE, F, length(As)) of
true ->
{value,apply(?MODULE, F, As),Bs};
diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl
index f980d52e4e..9041adbe5c 100644
--- a/lib/stdlib/test/erl_lint_SUITE.erl
+++ b/lib/stdlib/test/erl_lint_SUITE.erl
@@ -2981,7 +2981,7 @@ run_test(Conf, Test0, Warnings0) ->
run_test2(Conf, Test, Warnings0).
run_test2(Conf, Test, Warnings0) ->
- Filename = 'lint_test.erl',
+ Filename = "lint_test.erl",
DataDir = ?privdir,
File = filename:join(DataDir, Filename),
Opts = case Warnings0 of
diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl
index 280c95b1aa..64853ca078 100644
--- a/lib/stdlib/test/erl_pp_SUITE.erl
+++ b/lib/stdlib/test/erl_pp_SUITE.erl
@@ -116,7 +116,6 @@ func(Config) when is_list(Config) ->
{func_3,
<<"t() -> fun t/0.">>},
{func_4,
- %% Has already been expanded away in sys_pre_expand.
<<"t() -> fun modul:foo/3.">>},
{func_5, % 'when' is moved down one line
<<"tkjlksjflksdjflsdjlk()
@@ -127,7 +126,9 @@ func(Config) when is_list(Config) ->
<<"t() ->
(fun() ->
true
- end)().">>}
+ end)().">>},
+ {func_7,
+ <<"t(M, F, A) -> fun M:F/A.">>}
],
?line compile(Config, Ts),
ok.
diff --git a/lib/stdlib/test/erl_scan_SUITE.erl b/lib/stdlib/test/erl_scan_SUITE.erl
index 31a4f94294..4298b2c701 100644
--- a/lib/stdlib/test/erl_scan_SUITE.erl
+++ b/lib/stdlib/test/erl_scan_SUITE.erl
@@ -737,6 +737,10 @@ set_attribute() ->
(catch {foo, erl_scan:set_attribute(line, [], F2)}), % type error
?line {'EXIT',{badarg,_}} =
(catch {foo, erl_scan:set_attribute(column, [], F2)}), % type error
+
+ %% OTP-9412
+ ?line 8 = erl_scan:set_attribute(line, [{line,{nos,'X',8}}],
+ fun({nos,_V,VL}) -> VL end),
ok.
column_errors() ->
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index c9d82ec5f5..0e8849b5b3 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -72,8 +72,9 @@
exit_many_many_tables_owner/1]).
-export([write_concurrency/1, heir/1, give_away/1, setopts/1]).
-export([bad_table/1, types/1]).
+-export([otp_9423/1]).
--export([init_per_testcase/2, end_per_testcase/2]).
+-export([init_per_testcase/2]).
%% Convenience for manual testing
-export([random_test/0]).
@@ -143,7 +144,8 @@ all() ->
otp_8166, exit_large_table_owner,
exit_many_large_table_owner, exit_many_tables_owner,
exit_many_many_tables_owner, write_concurrency, heir,
- give_away, setopts, bad_table, types].
+ give_away, setopts, bad_table, types,
+ otp_9423].
groups() ->
[{new, [],
@@ -174,6 +176,7 @@ groups() ->
meta_newdel_unnamed, meta_newdel_named]}].
init_per_suite(Config) ->
+ erts_debug:set_internal_state(available_internal_state, true),
Config.
end_per_suite(_Config) ->
@@ -302,7 +305,6 @@ t_match_spec_run(Config) when is_list(Config) ->
end,
repeat_for_permutations(F, N_MS)
end,
-
test_terms(Fun, skip_refc_check),
?line verify_etsmem(EtsMem).
@@ -322,7 +324,7 @@ t_match_spec_run_test(List, MS, Result) ->
%% Check that tracing agree
Self = self(),
- {Tracee, MonRef} = spawn_monitor(fun() -> ms_tracee(Self, List) end),
+ {Tracee, MonRef} = my_spawn_monitor(fun() -> ms_tracee(Self, List) end),
receive {Tracee, ready} -> ok end,
MST = lists:map(fun(Clause) -> ms_clause_ets_to_trace(Clause) end, MS),
@@ -583,7 +585,6 @@ select_fail_do(Opts) ->
memory(doc) -> ["Whitebox test of ets:info(X,memory)"];
memory(suite) -> [];
memory(Config) when is_list(Config) ->
- ?line erts_debug:set_internal_state(available_internal_state, true),
?line ok = chk_normal_tab_struct_size(),
repeat_for_opts(memory_do,[compressed]),
?line catch erts_debug:set_internal_state(available_internal_state, false).
@@ -793,21 +794,26 @@ t_ets_dets(Config, Opts) ->
?line true = ets:from_dets(ETab,DTab),
?line 3000 = ets:info(ETab,size),
?line ets:delete(ETab),
- ?line {'EXIT',{badarg,[{ets,to_dets,[ETab,DTab]}|_]}} =
- (catch ets:to_dets(ETab,DTab)),
- ?line {'EXIT',{badarg,[{ets,from_dets,[ETab,DTab]}|_]}} =
- (catch ets:from_dets(ETab,DTab)),
+ ?line check_badarg(catch ets:to_dets(ETab,DTab),
+ ets, to_dets, [ETab,DTab]),
+ ?line check_badarg(catch ets:from_dets(ETab,DTab),
+ ets, from_dets, [ETab,DTab]),
?line ETab2 = ets_new(x,Opts),
?line filltabint(ETab2,3000),
?line dets:close(DTab),
- ?line {'EXIT',{badarg,[{ets,to_dets,[ETab2,DTab]}|_]}} =
- (catch ets:to_dets(ETab2,DTab)),
- ?line {'EXIT',{badarg,[{ets,from_dets,[ETab2,DTab]}|_]}} =
- (catch ets:from_dets(ETab2,DTab)),
+ ?line check_badarg(catch ets:to_dets(ETab2,DTab),
+ ets, to_dets, [ETab2,DTab]),
+ ?line check_badarg(catch ets:from_dets(ETab2,DTab),
+ ets, from_dets, [ETab2,DTab]),
?line ets:delete(ETab2),
?line (catch file:delete(Fname)),
ok.
+check_badarg({'EXIT', {badarg, [{M,F,Args,_} | _]}}, M, F, Args) ->
+ true;
+check_badarg({'EXIT', {badarg, [{M,F,A,_} | _]}}, M, F, Args) ->
+ true = test_server:is_native(M) andalso length(Args) =:= A.
+
t_delete_all_objects(doc) ->
["Test ets:delete_all_objects/1"];
t_delete_all_objects(suite) ->
@@ -817,6 +823,14 @@ t_delete_all_objects(Config) when is_list(Config) ->
repeat_for_opts(t_delete_all_objects_do),
?line verify_etsmem(EtsMem).
+get_kept_objects(T) ->
+ case ets:info(T,stats) of
+ false ->
+ 0;
+ {_,_,_,_,_,_,KO} ->
+ KO
+ end.
+
t_delete_all_objects_do(Opts) ->
?line T=ets_new(x,Opts),
?line filltabint(T,4000),
@@ -826,10 +840,10 @@ t_delete_all_objects_do(Opts) ->
?line true = ets:delete_all_objects(T),
?line '$end_of_table' = ets:next(T,O),
?line 0 = ets:info(T,size),
- ?line 4000 = ets:info(T,kept_objects),
+ ?line 4000 = get_kept_objects(T),
?line ets:safe_fixtable(T,false),
?line 0 = ets:info(T,size),
- ?line 0 = ets:info(T,kept_objects),
+ ?line 0 = get_kept_objects(T),
?line filltabint(T,4000),
?line 4000 = ets:info(T,size),
?line true = ets:delete_all_objects(T),
@@ -859,10 +873,10 @@ t_delete_object_do(Opts) ->
?line ets:delete_object(T,{First, integer_to_list(First)}),
?line Next = ets:next(T,First),
?line 3999 = ets:info(T,size),
- ?line 1 = ets:info(T,kept_objects),
+ ?line 1 = get_kept_objects(T),
?line ets:safe_fixtable(T,false),
?line 3999 = ets:info(T,size),
- ?line 0 = ets:info(T,kept_objects),
+ ?line 0 = get_kept_objects(T),
?line ets:delete(T),
?line T1 = ets_new(x,[ordered_set | Opts]),
?line filltabint(T1,4000),
@@ -1932,7 +1946,7 @@ evil_update_counter(Config) when is_list(Config) ->
evil_update_counter_do(Opts) ->
?line EtsMem = etsmem(),
?line process_flag(trap_exit, true),
- ?line Pids = [spawn_link(fun() -> evil_counter(I,Opts) end) || I <- lists:seq(1, 40)],
+ ?line Pids = [my_spawn_link(fun() -> evil_counter(I,Opts) end) || I <- lists:seq(1, 40)],
?line wait_for_all(gb_sets:from_list(Pids)),
?line verify_etsmem(EtsMem),
ok.
@@ -2138,24 +2152,24 @@ heir_do(Opts) ->
Combos),
%% No heir
- {Founder1,MrefF1} = spawn_monitor(fun()->heir_founder(Master,foo_data,Opts)end),
+ {Founder1,MrefF1} = my_spawn_monitor(fun()->heir_founder(Master,foo_data,Opts)end),
Founder1 ! {go, none},
?line {"No heir",Founder1} = receive_any(),
?line {'DOWN', MrefF1, process, Founder1, normal} = receive_any(),
?line undefined = ets:info(foo),
%% An already dead heir
- {Heir2,MrefH2} = spawn_monitor(fun()->die end),
+ {Heir2,MrefH2} = my_spawn_monitor(fun()->die end),
?line {'DOWN', MrefH2, process, Heir2, normal} = receive_any(),
- {Founder2,MrefF2} = spawn_monitor(fun()->heir_founder(Master,foo_data,Opts)end),
+ {Founder2,MrefF2} = my_spawn_monitor(fun()->heir_founder(Master,foo_data,Opts)end),
Founder2 ! {go, Heir2},
?line {"No heir",Founder2} = receive_any(),
?line {'DOWN', MrefF2, process, Founder2, normal} = receive_any(),
?line undefined = ets:info(foo),
%% When heir dies before founder
- {Founder3,MrefF3} = spawn_monitor(fun()->heir_founder(Master,"The dying heir",Opts)end),
- {Heir3,MrefH3} = spawn_monitor(fun()->heir_heir(Founder3)end),
+ {Founder3,MrefF3} = my_spawn_monitor(fun()->heir_founder(Master,"The dying heir",Opts)end),
+ {Heir3,MrefH3} = my_spawn_monitor(fun()->heir_heir(Founder3)end),
Founder3 ! {go, Heir3},
?line {'DOWN', MrefH3, process, Heir3, normal} = receive_any(),
Founder3 ! die_please,
@@ -2163,14 +2177,12 @@ heir_do(Opts) ->
?line undefined = ets:info(foo),
%% When heir dies and pid reused before founder dies
- erts_debug:set_internal_state(available_internal_state,true),
NextPidIx = erts_debug:get_internal_state(next_pid),
- {Founder4,MrefF4} = spawn_monitor(fun()->heir_founder(Master,"The dying heir",Opts)end),
- {Heir4,MrefH4} = spawn_monitor(fun()->heir_heir(Founder4)end),
+ {Founder4,MrefF4} = my_spawn_monitor(fun()->heir_founder(Master,"The dying heir",Opts)end),
+ {Heir4,MrefH4} = my_spawn_monitor(fun()->heir_heir(Founder4)end),
Founder4 ! {go, Heir4},
?line {'DOWN', MrefH4, process, Heir4, normal} = receive_any(),
erts_debug:set_internal_state(next_pid, NextPidIx),
- erts_debug:set_internal_state(available_internal_state,false),
{Heir4,MrefH4_B} = spawn_monitor_with_pid(Heir4,
fun()-> ?line die_please = receive_any() end),
Founder4 ! die_please,
@@ -2246,9 +2258,9 @@ heir_heir(Founder, Mode) ->
heir_1(HeirData,Mode,Opts) ->
io:format("test with heir_data = ~p\n", [HeirData]),
Master = self(),
- ?line Founder = spawn_link(fun() -> heir_founder(Master,HeirData,Opts) end),
+ ?line Founder = my_spawn_link(fun() -> heir_founder(Master,HeirData,Opts) end),
io:format("founder spawned = ~p\n", [Founder]),
- ?line {Heir,Mref} = spawn_monitor(fun() -> heir_heir(Founder,Mode) end),
+ ?line {Heir,Mref} = my_spawn_monitor(fun() -> heir_heir(Founder,Mode) end),
io:format("heir spawned = ~p\n", [{Heir,Mref}]),
?line Founder ! {go, Heir},
?line {'DOWN', Mref, process, Heir, normal} = receive_any().
@@ -2265,7 +2277,7 @@ give_away_do(Opts) ->
Parent = self(),
%% Give and then give back
- ?line {Receiver,Mref} = spawn_monitor(fun()-> give_away_receiver(T,Parent) end),
+ ?line {Receiver,Mref} = my_spawn_monitor(fun()-> give_away_receiver(T,Parent) end),
?line give_me = receive_any(),
?line true = ets:give_away(T,Receiver,here_you_are),
?line {'EXIT',{badarg,_}} = (catch ets:lookup(T,key)),
@@ -2276,7 +2288,7 @@ give_away_do(Opts) ->
%% Give and then let receiver keep it
?line true = ets:insert(T,{key,1}),
- ?line {Receiver3,Mref3} = spawn_monitor(fun()-> give_away_receiver(T,Parent) end),
+ ?line {Receiver3,Mref3} = my_spawn_monitor(fun()-> give_away_receiver(T,Parent) end),
?line give_me = receive_any(),
?line true = ets:give_away(T,Receiver3,here_you_are),
?line {'EXIT',{badarg,_}} = (catch ets:lookup(T,key)),
@@ -2288,7 +2300,7 @@ give_away_do(Opts) ->
?line T2 = ets_new(foo,[private | Opts]),
?line true = ets:insert(T2,{key,1}),
?line ets:setopts(T2,{heir,self(),"Som en gummiboll..."}),
- ?line {Receiver2,Mref2} = spawn_monitor(fun()-> give_away_receiver(T2,Parent) end),
+ ?line {Receiver2,Mref2} = my_spawn_monitor(fun()-> give_away_receiver(T2,Parent) end),
?line give_me = receive_any(),
?line true = ets:give_away(T2,Receiver2,here_you_are),
?line {'EXIT',{badarg,_}} = (catch ets:lookup(T2,key)),
@@ -2303,12 +2315,12 @@ give_away_do(Opts) ->
?line {'EXIT',{badarg,_}} = (catch ets:give_away(T2,"not a pid","To wrong type")),
?line true = ets:delete(T2),
- ?line {ReceiverNeg,MrefNeg} = spawn_monitor(fun()-> give_away_receiver(T2,Parent) end),
+ ?line {ReceiverNeg,MrefNeg} = my_spawn_monitor(fun()-> give_away_receiver(T2,Parent) end),
?line give_me = receive_any(),
?line {'EXIT',{badarg,_}} = (catch ets:give_away(T2,ReceiverNeg,"A deleted table")),
?line T3 = ets_new(foo,[public | Opts]),
- spawn_link(fun()-> {'EXIT',{badarg,_}} = (catch ets:give_away(T3,ReceiverNeg,"From non owner")),
+ my_spawn_link(fun()-> {'EXIT',{badarg,_}} = (catch ets:give_away(T3,ReceiverNeg,"From non owner")),
Parent ! done
end),
?line done = receive_any(),
@@ -2344,7 +2356,7 @@ setopts_do(Opts) ->
Self = self(),
?line T = ets_new(foo,[named_table, private | Opts]),
?line none = ets:info(T,heir),
- Heir = spawn_link(fun()->heir_heir(Self) end),
+ Heir = my_spawn_link(fun()->heir_heir(Self) end),
?line ets:setopts(T,{heir,Heir,"Data"}),
?line Heir = ets:info(T,heir),
?line ets:setopts(T,{heir,self(),"Data"}),
@@ -2395,14 +2407,14 @@ bad_table(Config) when is_list(Config) ->
bad_table_do(Opts, DummyFile) ->
Parent = self(),
- {Pid,Mref} = spawn_opt(fun()-> ets_new(priv,[private,named_table | Opts]),
- Priv = ets_new(priv,[private | Opts]),
- ets_new(prot,[protected,named_table | Opts]),
- Prot = ets_new(prot,[protected | Opts]),
- Parent ! {self(),Priv,Prot},
- die_please = receive_any()
- end,
- [link, monitor]),
+ {Pid,Mref} = my_spawn_opt(fun()-> ets_new(priv,[private,named_table | Opts]),
+ Priv = ets_new(priv,[private | Opts]),
+ ets_new(prot,[protected,named_table | Opts]),
+ Prot = ets_new(prot,[protected | Opts]),
+ Parent ! {self(),Priv,Prot},
+ die_please = receive_any()
+ end,
+ [link, monitor]),
{Pid,Priv,Prot} = receive_any(),
MatchSpec = {{key,'_'}, [], ['$$']},
Fun = fun(X,_) -> X end,
@@ -2642,7 +2654,7 @@ maybe_sort(L) when is_list(L) ->
%maybe_sort({'EXIT',{Reason, [{Module, Function, _}|_]}}) ->
% {'EXIT',{Reason, [{Module, Function, '_'}]}};
maybe_sort({'EXIT',{Reason, List}}) when is_list(List) ->
- {'EXIT',{Reason, lists:map(fun({Module, Function, _}) ->
+ {'EXIT',{Reason, lists:map(fun({Module, Function, _, _}) ->
{Module, Function, '_'}
end,
List)}};
@@ -2715,7 +2727,8 @@ ordered_do(Opts) ->
9,10,11,12,
1,2,3,4,
17,18,19,20,
- 13,14,15,16
+ 13,14,15,16,
+ 1 bsl 33
],
?line lists:foreach(fun(X) ->
ets:insert(T,{X,integer_to_list(X)})
@@ -2730,13 +2743,14 @@ ordered_do(Opts) ->
?line S2 = L2,
?line [{1,"1"}] = ets:slot(T,0),
?line [{28,"28"}] = ets:slot(T,27),
+ ?line [{1 bsl 33,_}] = ets:slot(T,28),
?line 27 = ets:prev(T,28),
?line [{7,"7"}] = ets:slot(T,6),
- ?line '$end_of_table' = ets:next(T,28),
+ ?line '$end_of_table' = ets:next(T,1 bsl 33),
?line [{12,"12"}] = ets:slot(T,11),
- ?line '$end_of_table' = ets:slot(T,28),
+ ?line '$end_of_table' = ets:slot(T,29),
?line [{1,"1"}] = ets:slot(T,0),
- ?line 28 = ets:prev(T,29),
+ ?line 28 = ets:prev(T,1 bsl 33),
?line 1 = ets:next(T,0),
?line pick_all_forward(T),
?line [{7,"7"}] = ets:slot(T,6),
@@ -3246,7 +3260,7 @@ delete_large_named_table_1(Name, Flags, Data, Fix) ->
?line lists:foreach(fun({K,_}) -> ets:delete(Tab, K) end, Data)
end,
Parent = self(),
- Pid = spawn_link(fun() ->
+ Pid = my_spawn_link(fun() ->
receive
{trace,Parent,call,_} ->
ets_new(Name, [named_table])
@@ -3608,7 +3622,7 @@ cycle(Tab, L) ->
ets:insert(Tab,list_to_tuple(L)),
cycle(Tab, tl(L)++[hd(L)]).
-dynamic_go() -> spawn_link(fun dynamic_init/0).
+dynamic_go() -> my_spawn_link(fun dynamic_init/0).
dynamic_init() -> [dyn_lookup(?MODULE) || _ <- lists:seq(1, 10)].
@@ -3835,7 +3849,7 @@ safe_fixtable_do(Opts) ->
Self = self(),
?line {{_,_,_},[{Self,1}]} = ets:info(Tab,safe_fixed),
%% Test that an unjustified 'unfix' is a no-op.
- {Pid,MRef} = spawn_monitor(fun() -> true = ets:safe_fixtable(Tab,false) end),
+ {Pid,MRef} = my_spawn_monitor(fun() -> true = ets:safe_fixtable(Tab,false) end),
{'DOWN', MRef, process, Pid, normal} = receive M -> M end,
?line true = ets:info(Tab,fixed),
?line {{_,_,_},[{Self,1}]} = ets:info(Tab,safe_fixed),
@@ -4239,7 +4253,7 @@ do_heavy_concurrent(Opts) ->
?line ok = fill_tab2(Tab, 0, Size),
?line Procs = lists:map(
fun (N) ->
- spawn_link(
+ my_spawn_link(
fun () ->
do_heavy_concurrent_proc(Tab, Size, N)
end)
@@ -4843,12 +4857,7 @@ otp_7665_act(Tab,Min,Max,DelNr) ->
%% Whitebox testing of meta name table hashing.
meta_wb(Config) when is_list(Config) ->
?line EtsMem = etsmem(),
- ?line erts_debug:set_internal_state(available_internal_state, true),
- try
- repeat_for_opts(meta_wb_do)
- after
- erts_debug:set_internal_state(available_internal_state, false)
- end,
+ repeat_for_opts(meta_wb_do),
?line verify_etsmem(EtsMem).
@@ -4917,12 +4926,15 @@ colliding_names(Name) ->
grow_shrink(Config) when is_list(Config) ->
?line EtsMem = etsmem(),
- grow_shrink_0(lists:seq(3071, 5000), EtsMem).
+ ?line grow_shrink_0(lists:seq(3071, 5000), EtsMem),
+ ?line verify_etsmem(EtsMem).
grow_shrink_0([N|Ns], EtsMem) ->
?line grow_shrink_1(N, [set]),
?line grow_shrink_1(N, [ordered_set]),
- ?line verify_etsmem(EtsMem),
+ %% Verifying ets-memory here takes too long time, since
+ %% lock-free allocators were introduced...
+ %% ?line verify_etsmem(EtsMem),
grow_shrink_0(Ns, EtsMem);
grow_shrink_0([], _) -> ok.
@@ -4967,21 +4979,21 @@ grow_pseudo_deleted_do(Type) ->
[true]}]),
Left = Mult*(Mod-1),
?line Left = ets:info(T,size),
- ?line Mult = ets:info(T,kept_objects),
+ ?line Mult = get_kept_objects(T),
filltabstr(T,Mult),
- spawn_opt(fun()-> ?line true = ets:info(T,fixed),
- Self ! start,
- io:format("Starting to filltabstr... ~p\n",[now()]),
- filltabstr(T,Mult,Mult+10000),
- io:format("Done with filltabstr. ~p\n",[now()]),
- Self ! done
- end, [link, {scheduler,2}]),
+ my_spawn_opt(fun()-> ?line true = ets:info(T,fixed),
+ Self ! start,
+ io:format("Starting to filltabstr... ~p\n",[now()]),
+ filltabstr(T,Mult,Mult+10000),
+ io:format("Done with filltabstr. ~p\n",[now()]),
+ Self ! done
+ end, [link, {scheduler,2}]),
?line start = receive_any(),
io:format("Unfixing table...~p nitems=~p\n",[now(),ets:info(T,size)]),
?line true = ets:safe_fixtable(T,false),
io:format("Unfix table done. ~p nitems=~p\n",[now(),ets:info(T,size)]),
?line false = ets:info(T,fixed),
- ?line 0 = ets:info(T,kept_objects),
+ ?line 0 = get_kept_objects(T),
?line done = receive_any(),
%%verify_table_load(T), % may fail if concurrency is poor (genny)
ets:delete(T),
@@ -5008,20 +5020,20 @@ shrink_pseudo_deleted_do(Type) ->
[{'>', '$1', Half}],
[true]}]),
?line Half = ets:info(T,size),
- ?line Half = ets:info(T,kept_objects),
- spawn_opt(fun()-> ?line true = ets:info(T,fixed),
- Self ! start,
- io:format("Starting to delete... ~p\n",[now()]),
- del_one_by_one_set(T,1,Half+1),
- io:format("Done with delete. ~p\n",[now()]),
- Self ! done
- end, [link, {scheduler,2}]),
+ ?line Half = get_kept_objects(T),
+ my_spawn_opt(fun()-> ?line true = ets:info(T,fixed),
+ Self ! start,
+ io:format("Starting to delete... ~p\n",[now()]),
+ del_one_by_one_set(T,1,Half+1),
+ io:format("Done with delete. ~p\n",[now()]),
+ Self ! done
+ end, [link, {scheduler,2}]),
?line start = receive_any(),
io:format("Unfixing table...~p nitems=~p\n",[now(),ets:info(T,size)]),
?line true = ets:safe_fixtable(T,false),
io:format("Unfix table done. ~p nitems=~p\n",[now(),ets:info(T,size)]),
?line false = ets:info(T,fixed),
- ?line 0 = ets:info(T,kept_objects),
+ ?line 0 = get_kept_objects(T),
?line done = receive_any(),
%%verify_table_load(T), % may fail if concurrency is poor (genny)
ets:delete(T),
@@ -5137,7 +5149,7 @@ smp_fixed_delete_do() ->
?line 0 = ets:info(T,size),
?line true = ets:info(T,fixed),
?line Buckets = num_of_buckets(T),
- ?line NumOfObjs = ets:info(T,kept_objects),
+ ?line NumOfObjs = get_kept_objects(T),
ets:safe_fixtable(T,false),
%% Will fail as unfix does not shrink the table:
%%?line Mem = ets:info(T,memory),
@@ -5169,27 +5181,27 @@ smp_unfix_fix_do() ->
Left = NumOfObjs - Deleted,
?line Left = ets:info(T,size),
?line true = ets:info(T,fixed),
- ?line Deleted = ets:info(T,kept_objects),
+ ?line Deleted = get_kept_objects(T),
{Child, Mref} =
- spawn_opt(fun()-> ?line true = ets:info(T,fixed),
- Parent ! start,
- io:format("Child waiting for table to be unfixed... now=~p mem=~p\n",
- [now(),ets:info(T,memory)]),
- repeat_while(fun()-> ets:info(T,fixed) end),
- io:format("Table unfixed. Child Fixating! now=~p mem=~p\n",
- [now(),ets:info(T,memory)]),
- ?line true = ets:safe_fixtable(T,true),
- repeat_while(fun(Key) when Key =< NumOfObjs ->
- ets:delete(T,Key), {true,Key+1};
- (Key) -> {false,Key}
- end,
- Deleted),
- ?line 0 = ets:info(T,size),
- ?line true = ets:info(T,kept_objects) >= Left,
- ?line done = receive_any()
- end,
- [link, monitor, {scheduler,2}]),
+ my_spawn_opt(fun()-> ?line true = ets:info(T,fixed),
+ Parent ! start,
+ io:format("Child waiting for table to be unfixed... now=~p mem=~p\n",
+ [now(),ets:info(T,memory)]),
+ repeat_while(fun()-> ets:info(T,fixed) end),
+ io:format("Table unfixed. Child Fixating! now=~p mem=~p\n",
+ [now(),ets:info(T,memory)]),
+ ?line true = ets:safe_fixtable(T,true),
+ repeat_while(fun(Key) when Key =< NumOfObjs ->
+ ets:delete(T,Key), {true,Key+1};
+ (Key) -> {false,Key}
+ end,
+ Deleted),
+ ?line 0 = ets:info(T,size),
+ ?line true = get_kept_objects(T) >= Left,
+ ?line done = receive_any()
+ end,
+ [link, monitor, {scheduler,2}]),
?line start = receive_any(),
?line true = ets:info(T,fixed),
@@ -5199,7 +5211,7 @@ smp_unfix_fix_do() ->
Child ! done,
{'DOWN', Mref, process, Child, normal} = receive_any(),
?line false = ets:info(T,fixed),
- ?line 0 = ets:info(T,kept_objects),
+ ?line 0 = get_kept_objects(T),
%%verify_table_load(T),
ets:delete(T),
process_flag(scheduler,0).
@@ -5220,11 +5232,11 @@ otp_8166_do(WC) ->
Deleted = NumOfObjs div 2,
filltabint(T,NumOfObjs),
{ReaderPid, ReaderMref} =
- spawn_opt(fun()-> otp_8166_reader(T,NumOfObjs) end,
- [link, monitor, {scheduler,2}]),
+ my_spawn_opt(fun()-> otp_8166_reader(T,NumOfObjs) end,
+ [link, monitor, {scheduler,2}]),
{ZombieCrPid, ZombieCrMref} =
- spawn_opt(fun()-> otp_8166_zombie_creator(T,Deleted) end,
- [link, monitor, {scheduler,3}]),
+ my_spawn_opt(fun()-> otp_8166_zombie_creator(T,Deleted) end,
+ [link, monitor, {scheduler,3}]),
repeat(fun() -> ZombieCrPid ! {loop, self()},
zombies_created = receive_any(),
@@ -5237,7 +5249,7 @@ otp_8166_do(WC) ->
ZombieCrPid ! quit,
{'DOWN', ZombieCrMref, process, ZombieCrPid, normal} = receive_any(),
?line false = ets:info(T,fixed),
- ?line 0 = ets:info(T,kept_objects),
+ ?line 0 = get_kept_objects(T),
%%verify_table_load(T),
ets:delete(T),
process_flag(scheduler,0).
@@ -5304,7 +5316,7 @@ otp_8166_zombie_creator(T,Deleted) ->
verify_table_load(T) ->
?line Stats = ets:info(T,stats),
- ?line {Buckets,AvgLen,StdDev,ExpSD,_MinLen,_MaxLen} = Stats,
+ ?line {Buckets,AvgLen,StdDev,ExpSD,_MinLen,_MaxLen,_} = Stats,
?line ok = if
AvgLen > 7 ->
io:format("Table overloaded: Stats=~p\n~p\n",
@@ -5420,7 +5432,39 @@ types_do(Opts) ->
?line verify_etsmem(EtsMem).
-
+otp_9423(doc) -> ["vm-deadlock caused by race between ets:delete and others on write_concurrency table"];
+otp_9423(Config) when is_list(Config) ->
+ InitF = fun(_) -> {0,0} end,
+ ExecF = fun({S,F}) ->
+ receive
+ stop ->
+ io:format("~p got stop\n", [self()]),
+ [end_of_work | {"Succeded=",S,"Failed=",F}]
+ after 0 ->
+ %%io:format("~p (~p) doing lookup\n", [self(), {S,F}]),
+ try ets:lookup(otp_9423, key) of
+ [] -> {S+1,F}
+ catch
+ error:badarg -> {S,F+1}
+ end
+ end
+ end,
+ FiniF = fun(R) -> R end,
+ case run_workers(InitF, ExecF, FiniF, infinite, 1) of
+ Pids when is_list(Pids) ->
+ %%[P ! start || P <- Pids],
+ repeat(fun() -> ets:new(otp_9423, [named_table, public, {write_concurrency,true}]),
+ ets:delete(otp_9423)
+ end, 10000),
+ [P ! stop || P <- Pids],
+ wait_pids(Pids),
+ ok;
+
+ Skipped -> Skipped
+ end.
+
+
+
%
% Utility functions:
@@ -5434,21 +5478,30 @@ add_lists([E1|T1], [E2|T2], Acc) ->
add_lists(T1, T2, [E1+E2 | Acc]).
run_workers(InitF,ExecF,FiniF,Laps) ->
+ run_workers(InitF,ExecF,FiniF,Laps, 0).
+run_workers(InitF,ExecF,FiniF,Laps, Exclude) ->
case erlang:system_info(smp_support) of
true ->
- run_workers_do(InitF,ExecF,FiniF,Laps);
+ run_workers_do(InitF,ExecF,FiniF,Laps, Exclude);
false ->
{skipped,"No smp support"}
end.
-
+
run_workers_do(InitF,ExecF,FiniF,Laps) ->
- NumOfProcs = erlang:system_info(schedulers),
+ run_workers_do(InitF,ExecF,FiniF,Laps, 0).
+run_workers_do(InitF,ExecF,FiniF,Laps, Exclude) ->
+ ?line NumOfProcs = case erlang:system_info(schedulers) of
+ 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)],
Parent = self(),
- Pids = [spawn_link(fun()-> worker(Seed,InitF,ExecF,FiniF,Laps,Parent,NumOfProcs) end)
+ Pids = [my_spawn_link(fun()-> worker(Seed,InitF,ExecF,FiniF,Laps,Parent,NumOfProcs) end)
|| Seed <- Seeds],
- wait_pids(Pids).
+ case Laps of
+ infinite -> Pids;
+ _ -> wait_pids(Pids)
+ end.
worker({ProcN,Seed}, InitF, ExecF, FiniF, Laps, Parent, NumOfProcs) ->
io:format("smp worker ~p, seed=~p~n",[self(),Seed]),
@@ -5463,6 +5516,8 @@ worker_loop(0, _, State) ->
State;
worker_loop(_, _, [end_of_work|State]) ->
State;
+worker_loop(infinite, ExecF, State) ->
+ worker_loop(infinite,ExecF,ExecF(State));
worker_loop(N, ExecF, State) ->
worker_loop(N-1,ExecF,ExecF(State)).
@@ -5490,31 +5545,30 @@ my_tab_to_list(_Ts,'$end_of_table', Acc) -> lists:reverse(Acc);
my_tab_to_list(Ts,Key, Acc) ->
my_tab_to_list(Ts,ets:next(Ts,Key),[ets:lookup(Ts, Key)| Acc]).
-wait_for_all_schedulers_online_to_execute() ->
- PMs = lists:map(fun (Sched) ->
- spawn_opt(fun () -> ok end,
- [monitor, {scheduler, Sched}])
- end,
- lists:seq(1,erlang:system_info(schedulers_online))),
- lists:foreach(fun ({P, M}) ->
- receive
- {'DOWN', M, process, P, _} -> ok
- end
- end,
- PMs),
- ok.
+
+wait_for_memory_deallocations() ->
+ try
+ erts_debug:set_internal_state(wait, deallocations)
+ catch
+ error:undef ->
+ erts_debug:set_internal_state(available_internal_state, true),
+ wait_for_memory_deallocations()
+ end.
+
etsmem() ->
- %% Wait until it is guaranteed that all already scheduled
- %% deallocations of DbTable structures have completed.
- wait_for_all_schedulers_online_to_execute(),
+ wait_for_memory_deallocations(),
AllTabs = lists:map(fun(T) -> {T,ets:info(T,name),ets:info(T,size),
ets:info(T,memory),ets:info(T,type)}
end, ets:all()),
+
+ EtsAllocInfo = erlang:system_info({allocator,ets_alloc}),
+ ErlangMemoryEts = try erlang:memory(ets) catch error:notsup -> notsup end,
+
Mem =
- {try erlang:memory(ets) catch error:notsup -> notsup end,
- case erlang:system_info({allocator,ets_alloc}) of
+ {ErlangMemoryEts,
+ case EtsAllocInfo of
false -> undefined;
MemInfo ->
CS = lists:foldl(
@@ -5591,6 +5645,7 @@ spawn_logger(Procs) ->
true -> exit(Proc, kill);
_ -> ok
end,
+ erlang:display(process_info(Proc)),
receive
{'DOWN', Mon, _, _, _} ->
ok
@@ -5626,7 +5681,7 @@ wait_for_test_procs(Kill) ->
ets_test_spawn_logger ! {sync_test_procs, Kill, self()},
receive test_procs_synced -> ok end.
-log_test_proc(Proc) ->
+log_test_proc(Proc) when is_pid(Proc) ->
ets_test_spawn_logger ! {new_test_proc, Proc},
Proc.
@@ -5638,9 +5693,17 @@ my_spawn_link(Fun) -> log_test_proc(spawn_link(Fun)).
my_spawn_link(M,F,A) -> log_test_proc(spawn_link(M,F,A)).
%%my_spawn_link(N,M,F,A) -> log_test_proc(spawn_link(N,M,F,A)).
-my_spawn_opt(Fun,Opts) -> log_test_proc(spawn_opt(Fun,Opts)).
-%%my_spawn_opt(M,F,A,Opts) -> log_test_proc(spawn_opt(M,F,A,Opts)).
-%%my_spawn_opt(N,M,F,A,Opts) -> log_test_proc(spawn_opt(N,M,F,A,Opts)).
+my_spawn_opt(Fun,Opts) ->
+ case spawn_opt(Fun,Opts) of
+ Pid when is_pid(Pid) -> log_test_proc(Pid);
+ {Pid, _} = Res when is_pid(Pid) -> log_test_proc(Pid), Res
+ end.
+
+my_spawn_monitor(Fun) ->
+ Res = spawn_monitor(Fun),
+ {Pid, _} = Res,
+ log_test_proc(Pid),
+ Res.
repeat(_Fun, 0) ->
ok;
@@ -5703,11 +5766,11 @@ spawn_monitor_with_pid(Pid, Fun, N, M) when N > M*10 ->
spawn_monitor_with_pid(Pid, Fun, N, M*10);
spawn_monitor_with_pid(Pid, Fun, N, M) ->
?line false = is_process_alive(Pid),
- case spawn(fun()-> case self() of
- Pid -> Fun();
- _ -> die
- end
- end) of
+ case my_spawn(fun()-> case self() of
+ Pid -> Fun();
+ _ -> die
+ end
+ end) of
Pid ->
{Pid, erlang:monitor(process, Pid)};
Other ->
@@ -5873,7 +5936,7 @@ very_big_num(0, Result) ->
?line Result.
make_port() ->
- ?line open_port({spawn, efile}, [eof]).
+ ?line open_port({spawn, "efile"}, [eof]).
make_pid() ->
?line spawn_link(?MODULE, sleeper, []).
diff --git a/lib/stdlib/test/file_sorter_SUITE.erl b/lib/stdlib/test/file_sorter_SUITE.erl
index 80d4ea5fdc..74c08912be 100644
--- a/lib/stdlib/test/file_sorter_SUITE.erl
+++ b/lib/stdlib/test/file_sorter_SUITE.erl
@@ -89,7 +89,7 @@ basic(suite) ->
basic(Config) when is_list(Config) ->
Fmt = binary,
Arg = {format,Fmt},
- Foo = outfile(foo, Config),
+ Foo = outfile("foo", Config),
P0 = pps(),
?line F1s = [F1] = to_files([[]], Fmt, Config),
@@ -455,7 +455,7 @@ inout(suite) ->
[];
inout(Config) when is_list(Config) ->
BTF = {format, binary_term},
- Foo = outfile(foo, Config),
+ Foo = outfile("foo", Config),
%% Input is fun.
End = fun(read) -> end_of_input end,
@@ -522,7 +522,7 @@ many(doc) ->
many(suite) ->
[];
many(Config) when is_list(Config) ->
- Foo = outfile(foo, Config),
+ Foo = outfile("foo", Config),
PrivDir = ?privdir(Config),
P0 = pps(),
@@ -587,7 +587,7 @@ misc(suite) ->
[];
misc(Config) when is_list(Config) ->
BTF = {format, binary_term},
- Foo = outfile(foo, Config),
+ Foo = outfile("foo", Config),
FFoo = filename:absname(Foo),
P0 = pps(),
@@ -704,7 +704,7 @@ misc(Config) when is_list(Config) ->
sort(Fmt, XArgs, Config) ->
Args = make_args(Fmt, [{size,5} | XArgs]),
TmpArgs = [{tmpdir,?privdir(Config)} | Args],
- Foo = outfile(foo, Config),
+ Foo = outfile("foo", Config),
%% Input is a fun. Output is a fun.
?line [] = file_sorter:sort(input([], 2, Fmt), output([], Fmt), Args),
@@ -777,7 +777,7 @@ sort(Fmt, XArgs, Config) ->
keysort(Fmt, XArgs, Config) ->
Args = make_args(Fmt, [{size,50}, {no_files, 2} | XArgs]),
TmpArgs = Args ++ [{tmpdir,?privdir(Config)}],
- Foo = outfile(foo, Config),
+ Foo = outfile("foo", Config),
%% Input is files. Output is a file.
?line ok = file_sorter:keysort(2, [], Foo, Args),
@@ -836,7 +836,7 @@ keysort(Fmt, XArgs, Config) ->
merge(Fmt, XArgs, Config) ->
Args = make_args(Fmt, [{size,5} | XArgs]),
- Foo = outfile(foo, Config),
+ Foo = outfile("foo", Config),
%% Input is a file. Output is a fun.
?line [] = file_sorter:merge([], output([], Fmt), Args),
@@ -873,7 +873,7 @@ merge(Fmt, XArgs, Config) ->
keymerge(Fmt, XArgs, Config) ->
Args = make_args(Fmt, [{size,50}, {no_files, 2} | XArgs]),
- Foo = outfile(foo, Config),
+ Foo = outfile("foo", Config),
%% Input is files. Output is a file.
?line ok = file_sorter:keymerge(2, [], Foo, Args),
diff --git a/lib/stdlib/test/filelib_SUITE.erl b/lib/stdlib/test/filelib_SUITE.erl
index a355097fe2..1de639a166 100644
--- a/lib/stdlib/test/filelib_SUITE.erl
+++ b/lib/stdlib/test/filelib_SUITE.erl
@@ -97,11 +97,12 @@ wildcard_errors(Config) when is_list(Config) ->
wcc(Wc, Error) ->
{'EXIT',{{badpattern,Error},
- [{filelib,compile_wildcard,1}|_]}} = (catch filelib:compile_wildcard(Wc)),
+ [{filelib,compile_wildcard,1,_}|_]}} =
+ (catch filelib:compile_wildcard(Wc)),
{'EXIT',{{badpattern,Error},
- [{filelib,wildcard,1}|_]}} = (catch filelib:wildcard(Wc)),
+ [{filelib,wildcard,1,_}|_]}} = (catch filelib:wildcard(Wc)),
{'EXIT',{{badpattern,Error},
- [{filelib,wildcard,2}|_]}} = (catch filelib:wildcard(Wc, ".")).
+ [{filelib,wildcard,2,_}|_]}} = (catch filelib:wildcard(Wc, ".")).
do_wildcard_1(Dir, Wcf0) ->
do_wildcard_2(Dir, Wcf0),
@@ -243,7 +244,7 @@ otp_5960(doc) ->
["Test that filelib:ensure_dir/1 returns ok or {error,Reason}"];
otp_5960(Config) when is_list(Config) ->
?line PrivDir = ?config(priv_dir, Config),
- ?line Dir = filename:join(PrivDir, otp_5960_dir),
+ ?line Dir = filename:join(PrivDir, "otp_5960_dir"),
?line Name1 = filename:join(Dir, name1),
?line Name2 = filename:join(Dir, name2),
?line ok = filelib:ensure_dir(Name1), % parent is created
@@ -268,7 +269,7 @@ otp_5960(Config) when is_list(Config) ->
ensure_dir_eexist(Config) when is_list(Config) ->
?line PrivDir = ?config(priv_dir, Config),
- ?line Dir = filename:join(PrivDir, ensure_dir_eexist),
+ ?line Dir = filename:join(PrivDir, "ensure_dir_eexist"),
?line Name = filename:join(Dir, "same_name_as_file_and_dir"),
?line ok = filelib:ensure_dir(Name),
?line ok = file:write_file(Name, <<"some string\n">>),
diff --git a/lib/stdlib/test/gen_server_SUITE.erl b/lib/stdlib/test/gen_server_SUITE.erl
index a614d6595d..7fb8d54f2d 100644
--- a/lib/stdlib/test/gen_server_SUITE.erl
+++ b/lib/stdlib/test/gen_server_SUITE.erl
@@ -694,7 +694,7 @@ multicall_down(Config) when is_list(Config) ->
%% We use 'global' as a gen_server to call.
?line {Good, Bad} = gen_server:multi_call([Name, node()],
global_name_server,
- {whereis, gurkburk},
+ info,
3000),
io:format("good = ~p, bad = ~p~n", [Good, Bad]),
?line [Name] = Bad,
diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl
index 54a98985cd..bb02a879c2 100644
--- a/lib/stdlib/test/io_SUITE.erl
+++ b/lib/stdlib/test/io_SUITE.erl
@@ -27,7 +27,7 @@
otp_6282/1, otp_6354/1, otp_6495/1, otp_6517/1, otp_6502/1,
manpage/1, otp_6708/1, otp_7084/1, otp_7421/1,
io_lib_collect_line_3_wb/1, cr_whitespace_in_string/1,
- io_fread_newlines/1, otp_8989/1]).
+ io_fread_newlines/1, otp_8989/1, io_lib_fread_literal/1]).
%-define(debug, true).
@@ -62,7 +62,7 @@ all() ->
otp_6282, otp_6354, otp_6495, otp_6517, otp_6502,
manpage, otp_6708, otp_7084, otp_7421,
io_lib_collect_line_3_wb, cr_whitespace_in_string,
- io_fread_newlines, otp_8989].
+ io_fread_newlines, otp_8989, io_lib_fread_literal].
groups() ->
[].
@@ -1995,3 +1995,29 @@ otp_8989(Suite) when is_list(Suite) ->
?line "Hel " = fmt("~-4.*s", [3,Hello]),
?line "Hel " = fmt("~*.*s", [-4,3,Hello]),
ok.
+
+io_lib_fread_literal(doc) ->
+ "OTP-9439 io_lib:fread bug for literate at end";
+io_lib_fread_literal(Suite) when is_list(Suite) ->
+ ?line {more,"~d",0,""} = io_lib:fread("~d", ""),
+ ?line {error,{fread,integer}} = io_lib:fread("~d", " "),
+ ?line {more,"~d",1,""} = io_lib:fread(" ~d", " "),
+ ?line {ok,[17],"X"} = io_lib:fread(" ~d", " 17X"),
+ %%
+ ?line {more,"d",0,""} = io_lib:fread("d", ""),
+ ?line {error,{fread,input}} = io_lib:fread("d", " "),
+ ?line {more,"d",1,""} = io_lib:fread(" d", " "),
+ ?line {ok,[],"X"} = io_lib:fread(" d", " dX"),
+ %%
+ ?line {done,eof,_} = io_lib:fread([], eof, "~d"),
+ ?line {done,eof,_} = io_lib:fread([], eof, " ~d"),
+ ?line {more,C1} = io_lib:fread([], " \n", " ~d"),
+ ?line {done,{error,{fread,input}},_} = io_lib:fread(C1, eof, " ~d"),
+ ?line {done,{ok,[18]},""} = io_lib:fread(C1, "18\n", " ~d"),
+ %%
+ ?line {done,eof,_} = io_lib:fread([], eof, "d"),
+ ?line {done,eof,_} = io_lib:fread([], eof, " d"),
+ ?line {more,C2} = io_lib:fread([], " \n", " d"),
+ ?line {done,{error,{fread,input}},_} = io_lib:fread(C2, eof, " d"),
+ ?line {done,{ok,[]},[]} = io_lib:fread(C2, "d\n", " d"),
+ ok.
diff --git a/lib/stdlib/test/ms_transform_SUITE.erl b/lib/stdlib/test/ms_transform_SUITE.erl
index 4e5df12798..c9688354b1 100644
--- a/lib/stdlib/test/ms_transform_SUITE.erl
+++ b/lib/stdlib/test/ms_transform_SUITE.erl
@@ -39,6 +39,7 @@
-export([float_1_function/1]).
-export([action_function/1]).
-export([warnings/1]).
+-export([no_warnings/1]).
-export([init_per_testcase/2, end_per_testcase/2]).
init_per_testcase(_Func, Config) ->
@@ -55,7 +56,7 @@ all() ->
[from_shell, basic_ets, basic_dbg, records,
record_index, multipass, bitsyntax, record_defaults,
andalso_orelse, float_1_function, action_function,
- warnings, top_match, old_guards, autoimported,
+ warnings, no_warnings, top_match, old_guards, autoimported,
semicolon].
groups() ->
@@ -155,6 +156,34 @@ warnings(Config) when is_list(Config) ->
compile_ww(Prog7),
ok.
+no_warnings(suite) ->
+ [];
+no_warnings(doc) ->
+ ["Check that variables bound in other function clauses don't generate "
+ "warning"];
+no_warnings(Config) when is_list(Config) ->
+ ?line setup(Config),
+ Prog = <<"tmp(X) when X > 100 ->\n",
+ " Y=X,\n"
+ " Y;\n"
+ "tmp(X) ->\n"
+ " ets:fun2ms(fun(Y) ->\n"
+ " {X, 3*Y}\n"
+ " end)">>,
+ ?line [] = compile_no_ww(Prog),
+
+ Prog2 = <<"tmp(X) when X > 100 ->\n",
+ " Y=X,\n"
+ " Y;\n"
+ "tmp(X) when X < 200 ->\n"
+ " ok;\n"
+ "tmp(X) ->\n"
+ " ets:fun2ms(fun(Y) ->\n"
+ " {X, 3*Y}\n"
+ " end)">>,
+ ?line [] = compile_no_ww(Prog2),
+ ok.
+
andalso_orelse(suite) ->
[];
andalso_orelse(doc) ->
@@ -842,6 +871,20 @@ compile_ww(Records,Expr) ->
nowarn_unused_record]),
Wlist.
+compile_no_ww(Expr) ->
+ Prog = <<
+ "-module(tmp).\n",
+ "-include_lib(\"stdlib/include/ms_transform.hrl\").\n",
+ "-export([tmp/1]).\n\n",
+ Expr/binary,".\n">>,
+ FN=temp_name(),
+ file:write_file(FN,Prog),
+ {ok,Forms} = epp:parse_file(FN,"",""),
+ {ok,tmp,_Bin,Wlist} = compile:forms(Forms,[return_warnings,
+ nowarn_unused_vars,
+ nowarn_unused_record]),
+ Wlist.
+
do_eval(String) ->
{done,{ok,T,_},[]} = erl_scan:tokens(
[],
diff --git a/lib/stdlib/test/proc_lib_SUITE.erl b/lib/stdlib/test/proc_lib_SUITE.erl
index 1565aa9bba..c95089117c 100644
--- a/lib/stdlib/test/proc_lib_SUITE.erl
+++ b/lib/stdlib/test/proc_lib_SUITE.erl
@@ -328,7 +328,7 @@ otp_6345(doc) ->
["'monitor' spawn_opt option"];
otp_6345(Config) when is_list(Config) ->
Opts = [link,monitor],
- {'EXIT', {badarg,[{proc_lib,check_for_monitor,_}|_Stack]}} =
+ {'EXIT', {badarg,[{proc_lib,check_for_monitor,_,_}|_Stack]}} =
(catch proc_lib:start(?MODULE, otp_6345_init, [self()],
1000, Opts)),
ok.
diff --git a/lib/stdlib/test/qlc_SUITE.erl b/lib/stdlib/test/qlc_SUITE.erl
index 98eeaee118..8a9d8f7883 100644
--- a/lib/stdlib/test/qlc_SUITE.erl
+++ b/lib/stdlib/test/qlc_SUITE.erl
@@ -6632,7 +6632,7 @@ otp_7232(Config) when is_list(Config) ->
{call,_,
{remote,_,{atom,_,qlc},{atom,_,sort}},
[{cons,_,
- {'fun',_,{function,math,sqrt,_}},
+ {'fun',_,{function,{atom,_,math},{atom,_,sqrt},_}},
{cons,_,
{string,_,\"<0.4.1>\"}, % could use list_to_pid..
{cons,_,{string,_,\"#Ref<\"++_},{nil,_}}}},
diff --git a/lib/stdlib/test/re_SUITE.erl b/lib/stdlib/test/re_SUITE.erl
index c4817c0d38..3b2e637c84 100644
--- a/lib/stdlib/test/re_SUITE.erl
+++ b/lib/stdlib/test/re_SUITE.erl
@@ -454,115 +454,115 @@ error_handling(Config) when is_list(Config) ->
% The malformed precomiled RE is detected after
% the trap to re:grun from grun, in the grun function clause
% that handles precompiled expressions
- ?line {'EXIT',{badarg,[{re,run,["apa",{1,2,3,4},[global]]},
- {?MODULE, error_handling,1} | _]}} =
+ ?line {'EXIT',{badarg,[{re,run,["apa",{1,2,3,4},[global]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:run("apa",{1,2,3,4},[global])),
% An invalid capture list will also cause a badarg late,
% but with a non pre compiled RE, the exception should be thrown by the
% grun function clause that handles RE's compiled implicitly by
% the run/3 BIF before trapping.
- ?line {'EXIT',{badarg,[{re,run,["apa","p",[{capture,[1,{a}]},global]]},
- {?MODULE, error_handling,1} | _]}} =
+ ?line {'EXIT',{badarg,[{re,run,["apa","p",[{capture,[1,{a}]},global]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:run("apa","p",[{capture,[1,{a}]},global])),
% And so the case of a precompiled expression together with
% a compile-option (binary and list subject):
?line {ok,RE} = re:compile("(p)"),
?line {match,[[{1,1},{1,1}]]} = re:run(<<"apa">>,RE,[global]),
?line {match,[[{1,1},{1,1}]]} = re:run("apa",RE,[global]),
- {'EXIT',{badarg,[{re,run,
- [<<"apa">>,
- {re_pattern,1,0,_},
- [global,unicode]]},
- {?MODULE, error_handling,1} | _]}} =
+ ?line {'EXIT',{badarg,[{re,run,
+ [<<"apa">>,
+ {re_pattern,1,0,_},
+ [global,unicode]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:run(<<"apa">>,RE,[global,unicode])),
- {'EXIT',{badarg,[{re,run,
- ["apa",
- {re_pattern,1,0,_},
- [global,unicode]]},
- {?MODULE, error_handling,1} | _]}} =
+ ?line {'EXIT',{badarg,[{re,run,
+ ["apa",
+ {re_pattern,1,0,_},
+ [global,unicode]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:run("apa",RE,[global,unicode])),
?line {'EXIT',{badarg,_}} = (catch re:run("apa","(p",[])),
?line {'EXIT',{badarg,_}} = (catch re:run("apa","(p",[global])),
% The replace errors:
- ?line {'EXIT',{badarg,[{re,replace,["apa",{1,2,3,4},"X",[]]},
- {?MODULE, error_handling,1} | _]}} =
+ ?line {'EXIT',{badarg,[{re,replace,["apa",{1,2,3,4},"X",[]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:replace("apa",{1,2,3,4},"X",[])),
- ?line {'EXIT',{badarg,[{re,replace,["apa",{1,2,3,4},"X",[global]]},
- {?MODULE, error_handling,1} | _]}} =
+ ?line {'EXIT',{badarg,[{re,replace,["apa",{1,2,3,4},"X",[global]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:replace("apa",{1,2,3,4},"X",[global])),
?line {'EXIT',{badarg,[{re,replace,
["apa",
{re_pattern,1,0,_},
"X",
- [unicode]]},
- {?MODULE, error_handling,1} | _]}} =
+ [unicode]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:replace("apa",RE,"X",[unicode])),
?line <<"aXa">> = iolist_to_binary(re:replace("apa","p","X",[])),
?line {'EXIT',{badarg,[{re,replace,
- ["apa","p","X",[{capture,all,binary}]]},
- {?MODULE, error_handling,1} | _]}} =
+ ["apa","p","X",[{capture,all,binary}]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch iolist_to_binary(re:replace("apa","p","X",
[{capture,all,binary}]))),
?line {'EXIT',{badarg,[{re,replace,
- ["apa","p","X",[{capture,all}]]},
- {?MODULE, error_handling,1} | _]}} =
+ ["apa","p","X",[{capture,all}]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch iolist_to_binary(re:replace("apa","p","X",
[{capture,all}]))),
?line {'EXIT',{badarg,[{re,replace,
- ["apa","p","X",[{return,banana}]]},
- {?MODULE, error_handling,1} | _]}} =
+ ["apa","p","X",[{return,banana}]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch iolist_to_binary(re:replace("apa","p","X",
[{return,banana}]))),
?line {'EXIT',{badarg,_}} = (catch re:replace("apa","(p","X",[])),
% Badarg, not compile error.
?line {'EXIT',{badarg,[{re,replace,
- ["apa","(p","X",[{return,banana}]]},
- {?MODULE, error_handling,1} | _]}} =
+ ["apa","(p","X",[{return,banana}]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch iolist_to_binary(re:replace("apa","(p","X",
[{return,banana}]))),
% And the split errors:
?line [<<"a">>,<<"a">>] = (catch re:split("apa","p",[])),
?line [<<"a">>,<<"p">>,<<"a">>] = (catch re:split("apa",RE,[])),
- ?line {'EXIT',{badarg,[{re,split,["apa","p",[global]]},
- {?MODULE, error_handling,1} | _]}} =
+ ?line {'EXIT',{badarg,[{re,split,["apa","p",[global]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:split("apa","p",[global])),
- ?line {'EXIT',{badarg,[{re,split,["apa","p",[{capture,all}]]},
- {?MODULE, error_handling,1} | _]}} =
+ ?line {'EXIT',{badarg,[{re,split,["apa","p",[{capture,all}]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:split("apa","p",[{capture,all}])),
- ?line {'EXIT',{badarg,[{re,split,["apa","p",[{capture,all,binary}]]},
- {?MODULE, error_handling,1} | _]}} =
+ ?line {'EXIT',{badarg,[{re,split,["apa","p",[{capture,all,binary}]],_},
+ {?MODULE, error_handling,1,_} | _]}} =
(catch re:split("apa","p",[{capture,all,binary}])),
- ?line {'EXIT',{badarg,[{re,split,["apa",{1,2,3,4},[]]},
- {?MODULE, error_handling,1} | _]}} =
+ ?line {'EXIT',{badarg,[{re,split,["apa",{1,2,3,4},[]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:split("apa",{1,2,3,4})),
- ?line {'EXIT',{badarg,[{re,split,["apa",{1,2,3,4},[]]},
- {?MODULE, error_handling,1} | _]}} =
+ ?line {'EXIT',{badarg,[{re,split,["apa",{1,2,3,4},[]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:split("apa",{1,2,3,4},[])),
?line {'EXIT',{badarg,[{re,split,
["apa",
RE,
- [unicode]]},
- {?MODULE, error_handling,1} | _]}} =
+ [unicode]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:split("apa",RE,[unicode])),
?line {'EXIT',{badarg,[{re,split,
["apa",
RE,
- [{return,banana}]]},
- {?MODULE, error_handling,1} | _]}} =
+ [{return,banana}]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:split("apa",RE,[{return,banana}])),
?line {'EXIT',{badarg,[{re,split,
["apa",
RE,
- [banana]]},
- {?MODULE, error_handling,1} | _]}} =
+ [banana]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:split("apa",RE,[banana])),
?line {'EXIT',{badarg,_}} = (catch re:split("apa","(p")),
%Exception on bad argument, not compilation error
?line {'EXIT',{badarg,[{re,split,
["apa",
"(p",
- [banana]]},
- {?MODULE, error_handling,1} | _]}} =
+ [banana]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:split("apa","(p",[banana])),
?t:timetrap_cancel(Dog),
ok.
diff --git a/lib/stdlib/test/shell_SUITE.erl b/lib/stdlib/test/shell_SUITE.erl
index 8273377ba1..b6019b86f0 100644
--- a/lib/stdlib/test/shell_SUITE.erl
+++ b/lib/stdlib/test/shell_SUITE.erl
@@ -2388,12 +2388,12 @@ otp_6554(Config) when is_list(Config) ->
comm_err(<<"V = lists:seq(1, 20), case V of a -> ok end.">>),
?line "exception error: no function clause matching" =
comm_err(<<"fun(P) when is_pid(P) -> true end(a).">>),
- ?line "exception error: {function_clause,[{erl_eval,do_apply,[unproper|list]}"++_ =
+ ?line "exception error: {function_clause," =
comm_err(<<"erlang:error(function_clause, [unproper | list]).">>),
?line "exception error: function_clause" =
comm_err(<<"erlang:error(function_clause, 4).">>),
%% Cheating:
- ?line "exception error: no function clause matching erl_eval:do_apply(4)" =
+ ?line "exception error: no function clause matching erl_eval:do_apply(4)" ++ _ =
comm_err(<<"erlang:error(function_clause, [4]).">>),
?line "exception error: no function clause matching" ++ _ =
comm_err(<<"fun(a, b, c, d) -> foo end"
@@ -2406,7 +2406,7 @@ otp_6554(Config) when is_list(Config) ->
comm_err(<<"fun(P, q) when is_pid(P) -> true end(a, b).">>),
?line "exception error: no function clause matching lists:reverse(" ++ _ =
comm_err(<<"F=fun() -> hello end, lists:reverse(F).">>),
- ?line "exception error: no function clause matching lists:reverse(34)" =
+ ?line "exception error: no function clause matching lists:reverse(34) (lists.erl, line " ++ _ =
comm_err(<<"lists:reverse(34).">>),
?line "exception error: no true branch found when evaluating an if expression" =
comm_err(<<"if length([a,b]) > 17 -> a end.">>),
diff --git a/lib/stdlib/test/sofs_SUITE.erl b/lib/stdlib/test/sofs_SUITE.erl
index d6f88a655e..73b282149a 100644
--- a/lib/stdlib/test/sofs_SUITE.erl
+++ b/lib/stdlib/test/sofs_SUITE.erl
@@ -1879,11 +1879,11 @@ digraph(Conf) when is_list(Conf) ->
?line {'EXIT', {badarg, _}} =
(catch family_to_digraph(set([a]))),
- ?line {'EXIT', {badarg, [{sofs,family_to_digraph,[_,_]}|_]}} =
+ ?line {'EXIT', {badarg, [{sofs,family_to_digraph,[_,_],_}|_]}} =
(catch family_to_digraph(set([a]), [foo])),
- ?line {'EXIT', {badarg, [{sofs,family_to_digraph,[_,_]}|_]}} =
+ ?line {'EXIT', {badarg, [{sofs,family_to_digraph,[_,_],_}|_]}} =
(catch family_to_digraph(F, [foo])),
- ?line {'EXIT', {cyclic, [{sofs,family_to_digraph,[_,_]}|_]}} =
+ ?line {'EXIT', {cyclic, [{sofs,family_to_digraph,[_,_],_}|_]}} =
(catch family_to_digraph(family([{a,[a]}]),[acyclic])),
?line G1 = family_to_digraph(E),
diff --git a/lib/stdlib/test/string_SUITE.erl b/lib/stdlib/test/string_SUITE.erl
index 1dcd4be21e..6969c095a0 100644
--- a/lib/stdlib/test/string_SUITE.erl
+++ b/lib/stdlib/test/string_SUITE.erl
@@ -273,9 +273,9 @@ words(Config) when is_list(Config) ->
?line 2 = string:words("2.35", $.),
?line 100 = string:words(string:copies(". ", 100)),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:chars(hej)),
+ ?line {'EXIT',_} = (catch string:chars(hej, 1)),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:chars("hej", " ")),
+ ?line {'EXIT',_} = (catch string:chars("hej", 1, " ")),
ok.
diff --git a/lib/stdlib/test/supervisor_1.erl b/lib/stdlib/test/supervisor_1.erl
index 3198be0fed..f819594c46 100644
--- a/lib/stdlib/test/supervisor_1.erl
+++ b/lib/stdlib/test/supervisor_1.erl
@@ -62,6 +62,12 @@ handle_info(die, State) ->
handle_info(stop, State) ->
{stop, normal, State};
+handle_info({'EXIT',_,shutdown}, State) ->
+ {stop, shutdown, State};
+
+handle_info({'EXIT',_,{shutdown,Term}}, State) ->
+ {stop, {shutdown,Term}, State};
+
handle_info({sleep, Time}, State) ->
io:format("FOO: ~p~n", [Time]),
timer:sleep(Time),
diff --git a/lib/ssl/test/ssl_test_MACHINE.hrl b/lib/stdlib/test/supervisor_2.erl
index e78b33f505..67aacf5a9c 100644
--- a/lib/ssl/test/ssl_test_MACHINE.hrl
+++ b/lib/stdlib/test/supervisor_2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -16,24 +16,27 @@
%%
%% %CopyrightEnd%
%%
+%% Description: Simulates the behaviour that a child process may have.
+%% Is used by the supervisor_SUITE test suite.
+-module(supervisor_2).
--record(st, {protomod = ssl,
- serialize_accept = false,
- parent = nil,
- type = nil,
- active = nil,
- port = 0,
- peer = nil,
- lsock = nil,
- sock = nil,
- timeout = infinity,
- sockopts = [],
- sslopts = [],
- protocols = []}).
+-export([start_child/1, init/1]).
-%%-define(debug(X, Y), io:format(X, Y)).
--define(debug(X, Y), ok).
--define(error(X, Y), io:format(X, Y)).
+-export([handle_call/3, handle_info/2, terminate/2]).
--define(DEFAULT_TIMEOUT, 240000).
+start_child(Time) when is_integer(Time), Time > 0 ->
+ gen_server:start_link(?MODULE, Time, []).
+init(Time) ->
+ process_flag(trap_exit, true),
+ {ok, Time}.
+
+handle_call(Req, _From, State) ->
+ {reply, Req, State}.
+
+handle_info(_, State) ->
+ {noreply, State}.
+
+terminate(_Reason, Time) ->
+ timer:sleep(Time),
+ ok.
diff --git a/lib/stdlib/test/supervisor_SUITE.erl b/lib/stdlib/test/supervisor_SUITE.erl
index c79a5002fb..d3d140abbc 100644
--- a/lib/stdlib/test/supervisor_SUITE.erl
+++ b/lib/stdlib/test/supervisor_SUITE.erl
@@ -29,7 +29,8 @@
end_per_testcase/2]).
%% Internal export
--export([init/1, terminate_all_children/1]).
+-export([init/1, terminate_all_children/1,
+ middle9212/0, gen_server9212/0, handle_info/2]).
%% API tests
-export([ sup_start_normal/1, sup_start_ignore_init/1,
@@ -41,8 +42,10 @@
%% Tests concept permanent, transient and temporary
-export([ permanent_normal/1, transient_normal/1,
temporary_normal/1,
+ permanent_shutdown/1, transient_shutdown/1,
+ temporary_shutdown/1,
permanent_abnormal/1, transient_abnormal/1,
- temporary_abnormal/1]).
+ temporary_abnormal/1, temporary_bystander/1]).
%% Restart strategy tests
-export([ one_for_one/1,
@@ -50,13 +53,14 @@
one_for_all_escalation/1,
simple_one_for_one/1, simple_one_for_one_escalation/1,
rest_for_one/1, rest_for_one_escalation/1,
- simple_one_for_one_extra/1]).
+ simple_one_for_one_extra/1, simple_one_for_one_shutdown/1]).
%% Misc tests
-export([child_unlink/1, tree/1, count_children_memory/1,
do_not_save_start_parameters_for_temporary_children/1,
do_not_save_child_specs_for_temporary_children/1,
- simple_one_for_one_scale_many_temporary_children/1]).
+ simple_one_for_one_scale_many_temporary_children/1,
+ simple_global_supervisor/1]).
%%-------------------------------------------------------------------------
@@ -71,10 +75,12 @@ all() ->
{group, restart_simple_one_for_one},
{group, restart_rest_for_one},
{group, normal_termination},
+ {group, shutdown_termination},
{group, abnormal_termination}, child_unlink, tree,
count_children_memory, do_not_save_start_parameters_for_temporary_children,
do_not_save_child_specs_for_temporary_children,
- simple_one_for_one_scale_many_temporary_children].
+ simple_one_for_one_scale_many_temporary_children, temporary_bystander,
+ simple_global_supervisor].
groups() ->
[{sup_start, [],
@@ -86,6 +92,8 @@ groups() ->
sup_stop_brutal_kill]},
{normal_termination, [],
[permanent_normal, transient_normal, temporary_normal]},
+ {shutdown_termination, [],
+ [permanent_shutdown, transient_shutdown, temporary_shutdown]},
{abnormal_termination, [],
[permanent_abnormal, transient_abnormal,
temporary_abnormal]},
@@ -94,8 +102,8 @@ groups() ->
{restart_one_for_all, [],
[one_for_all, one_for_all_escalation]},
{restart_simple_one_for_one, [],
- [simple_one_for_one, simple_one_for_one_extra,
- simple_one_for_one_escalation]},
+ [simple_one_for_one, simple_one_for_one_shutdown,
+ simple_one_for_one_extra, simple_one_for_one_escalation]},
{restart_rest_for_one, [],
[rest_for_one, rest_for_one_escalation]}].
@@ -114,16 +122,20 @@ end_per_group(_GroupName, Config) ->
Config.
init_per_testcase(count_children_memory, Config) ->
- MemoryState = erlang:system_info(allocator),
- case count_children_allocator_test(MemoryState) of
- true -> Config;
- false ->
+ try erlang:memory() of
+ _ ->
+ erts_debug:set_internal_state(available_internal_state, true),
+ Config
+ catch error:notsup ->
{skip, "+Meamin used during test; erlang:memory/1 not available"}
end;
init_per_testcase(_Case, Config) ->
erlang:display(_Case),
Config.
+end_per_testcase(count_children_memory, _Config) ->
+ catch erts_debug:set_internal_state(available_internal_state, false),
+ ok;
end_per_testcase(_Case, _Config) ->
ok.
@@ -205,8 +217,8 @@ sup_start_fail(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
sup_stop_infinity(doc) ->
- ["See sup_stop/1 when Shutdown = infinity, this walue is only allowed "
- "for children of type supervisor"];
+ ["See sup_stop/1 when Shutdown = infinity, this walue is allowed "
+ "for children of type supervisor _AND_ worker"];
sup_stop_infinity(suite) -> [];
sup_stop_infinity(Config) when is_list(Config) ->
@@ -217,12 +229,13 @@ sup_stop_infinity(Config) when is_list(Config) ->
Child2 = {child2, {supervisor_1, start_child, []}, permanent,
infinity, worker, []},
{ok, CPid1} = supervisor:start_child(sup_test, Child1),
+ {ok, CPid2} = supervisor:start_child(sup_test, Child2),
link(CPid1),
- {error, {invalid_shutdown,infinity}} =
- supervisor:start_child(sup_test, Child2),
+ link(CPid2),
terminate(Pid, shutdown),
- check_exit_reason(CPid1, shutdown).
+ check_exit_reason(CPid1, shutdown),
+ check_exit_reason(CPid2, shutdown).
%%-------------------------------------------------------------------------
@@ -454,9 +467,8 @@ child_specs(Config) when is_list(Config) ->
B2 = {child, {m,f,[a]}, prmanent, 1000, worker, []},
B3 = {child, {m,f,[a]}, permanent, -10, worker, []},
B4 = {child, {m,f,[a]}, permanent, 10, wrker, []},
- B5 = {child, {m,f,[a]}, permanent, infinity, worker, []},
- B6 = {child, {m,f,[a]}, permanent, 1000, worker, dy},
- B7 = {child, {m,f,[a]}, permanent, 1000, worker, [1,2,3]},
+ B5 = {child, {m,f,[a]}, permanent, 1000, worker, dy},
+ B6 = {child, {m,f,[a]}, permanent, 1000, worker, [1,2,3]},
%% Correct child specs!
%% <Modules> (last parameter in a child spec) can be [] as we do
@@ -465,6 +477,7 @@ child_specs(Config) when is_list(Config) ->
C2 = {child, {m,f,[a]}, permanent, 1000, supervisor, []},
C3 = {child, {m,f,[a]}, temporary, 1000, worker, dynamic},
C4 = {child, {m,f,[a]}, transient, 1000, worker, [m]},
+ C5 = {child, {m,f,[a]}, permanent, infinity, worker, [m]},
{error, {invalid_mfa,mfa}} = supervisor:start_child(sup_test, B1),
{error, {invalid_restart_type, prmanent}} =
@@ -473,9 +486,8 @@ child_specs(Config) when is_list(Config) ->
= supervisor:start_child(sup_test, B3),
{error, {invalid_child_type,wrker}}
= supervisor:start_child(sup_test, B4),
- {error, _} = supervisor:start_child(sup_test, B5),
{error, {invalid_modules,dy}}
- = supervisor:start_child(sup_test, B6),
+ = supervisor:start_child(sup_test, B5),
{error, {invalid_mfa,mfa}} = supervisor:check_childspecs([B1]),
{error, {invalid_restart_type,prmanent}} =
@@ -483,15 +495,15 @@ child_specs(Config) when is_list(Config) ->
{error, {invalid_shutdown,-10}} = supervisor:check_childspecs([B3]),
{error, {invalid_child_type,wrker}}
= supervisor:check_childspecs([B4]),
- {error, _} = supervisor:check_childspecs([B5]),
- {error, {invalid_modules,dy}} = supervisor:check_childspecs([B6]),
+ {error, {invalid_modules,dy}} = supervisor:check_childspecs([B5]),
{error, {invalid_module, 1}} =
- supervisor:check_childspecs([B7]),
+ supervisor:check_childspecs([B6]),
ok = supervisor:check_childspecs([C1]),
ok = supervisor:check_childspecs([C2]),
ok = supervisor:check_childspecs([C3]),
ok = supervisor:check_childspecs([C4]),
+ ok = supervisor:check_childspecs([C5]),
ok.
%%-------------------------------------------------------------------------
@@ -550,6 +562,87 @@ temporary_normal(Config) when is_list(Config) ->
[0,0,0,0] = get_child_counts(sup_test).
%%-------------------------------------------------------------------------
+permanent_shutdown(doc) ->
+ ["A permanent child should always be restarted"];
+permanent_shutdown(suite) -> [];
+permanent_shutdown(Config) when is_list(Config) ->
+ {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
+ Child1 = {child1, {supervisor_1, start_child, []}, permanent, 1000,
+ worker, []},
+
+ {ok, CPid1} = supervisor:start_child(sup_test, Child1),
+
+ terminate(SupPid, CPid1, child1, shutdown),
+
+ [{child1, CPid2 ,worker,[]}] = supervisor:which_children(sup_test),
+ case is_pid(CPid2) of
+ true ->
+ ok;
+ false ->
+ test_server:fail({permanent_child_not_restarted, Child1})
+ end,
+ [1,1,0,1] = get_child_counts(sup_test),
+
+ terminate(SupPid, CPid2, child1, {shutdown, some_info}),
+
+ [{child1, CPid3 ,worker,[]}] = supervisor:which_children(sup_test),
+ case is_pid(CPid3) of
+ true ->
+ ok;
+ false ->
+ test_server:fail({permanent_child_not_restarted, Child1})
+ end,
+
+ [1,1,0,1] = get_child_counts(sup_test).
+
+%%-------------------------------------------------------------------------
+transient_shutdown(doc) ->
+ ["A transient child should not be restarted if it exits with "
+ "reason shutdown or {shutdown,Term}"];
+transient_shutdown(suite) -> [];
+transient_shutdown(Config) when is_list(Config) ->
+ {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
+ Child1 = {child1, {supervisor_1, start_child, []}, transient, 1000,
+ worker, []},
+
+ {ok, CPid1} = supervisor:start_child(sup_test, Child1),
+
+ terminate(SupPid, CPid1, child1, shutdown),
+
+ [{child1,undefined,worker,[]}] = supervisor:which_children(sup_test),
+ [1,0,0,1] = get_child_counts(sup_test),
+
+ {ok, CPid2} = supervisor:restart_child(sup_test, child1),
+
+ terminate(SupPid, CPid2, child1, {shutdown, some_info}),
+
+ [{child1,undefined,worker,[]}] = supervisor:which_children(sup_test),
+ [1,0,0,1] = get_child_counts(sup_test).
+
+%%-------------------------------------------------------------------------
+temporary_shutdown(doc) ->
+ ["A temporary process should never be restarted"];
+temporary_shutdown(suite) -> [];
+temporary_shutdown(Config) when is_list(Config) ->
+ {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
+ Child1 = {child1, {supervisor_1, start_child, []}, temporary, 1000,
+ worker, []},
+
+ {ok, CPid1} = supervisor:start_child(sup_test, Child1),
+
+ terminate(SupPid, CPid1, child1, shutdown),
+
+ [] = supervisor:which_children(sup_test),
+ [0,0,0,0] = get_child_counts(sup_test),
+
+ {ok, CPid2} = supervisor:start_child(sup_test, Child1),
+
+ terminate(SupPid, CPid2, child1, {shutdown, some_info}),
+
+ [] = supervisor:which_children(sup_test),
+ [0,0,0,0] = get_child_counts(sup_test).
+
+%%-------------------------------------------------------------------------
permanent_abnormal(doc) ->
["A permanent child should always be restarted"];
permanent_abnormal(suite) -> [];
@@ -608,6 +701,37 @@ temporary_abnormal(Config) when is_list(Config) ->
[0,0,0,0] = get_child_counts(sup_test).
%%-------------------------------------------------------------------------
+temporary_bystander(doc) ->
+ ["A temporary process killed as part of a rest_for_one or one_for_all "
+ "restart strategy should not be restarted given its args are not "
+ " saved. Otherwise the supervisor hits its limit and crashes."];
+temporary_bystander(suite) -> [];
+temporary_bystander(_Config) ->
+ Child1 = {child1, {supervisor_1, start_child, []}, permanent, 100,
+ worker, []},
+ Child2 = {child2, {supervisor_1, start_child, []}, temporary, 100,
+ worker, []},
+ {ok, SupPid1} = supervisor:start_link(?MODULE, {ok, {{one_for_all, 2, 300}, []}}),
+ {ok, SupPid2} = supervisor:start_link(?MODULE, {ok, {{rest_for_one, 2, 300}, []}}),
+ unlink(SupPid1), % otherwise we crash with it
+ unlink(SupPid2), % otherwise we crash with it
+ {ok, CPid1} = supervisor:start_child(SupPid1, Child1),
+ {ok, _CPid2} = supervisor:start_child(SupPid1, Child2),
+ {ok, CPid3} = supervisor:start_child(SupPid2, Child1),
+ {ok, _CPid4} = supervisor:start_child(SupPid2, Child2),
+ terminate(SupPid1, CPid1, child1, normal),
+ terminate(SupPid2, CPid3, child1, normal),
+ timer:sleep(350),
+ catch link(SupPid1),
+ catch link(SupPid2),
+ %% The supervisor would die attempting to restart child2
+ true = erlang:is_process_alive(SupPid1),
+ true = erlang:is_process_alive(SupPid2),
+ %% Child2 has not been restarted
+ [{child1, _, _, _}] = supervisor:which_children(SupPid1),
+ [{child1, _, _, _}] = supervisor:which_children(SupPid2).
+
+%%-------------------------------------------------------------------------
one_for_one(doc) ->
["Test the one_for_one base case."];
one_for_one(suite) -> [];
@@ -752,6 +876,38 @@ simple_one_for_one(Config) when is_list(Config) ->
terminate(SupPid, Pid4, Id4, abnormal),
check_exit([SupPid]).
+
+%%-------------------------------------------------------------------------
+simple_one_for_one_shutdown(doc) ->
+ ["Test simple_one_for_one children shutdown accordingly to the "
+ "supervisor's shutdown strategy."];
+simple_one_for_one_shutdown(suite) -> [];
+simple_one_for_one_shutdown(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ ShutdownTime = 1000,
+ Child = {child, {supervisor_2, start_child, []},
+ permanent, 2*ShutdownTime, worker, []},
+ {ok, SupPid} = start_link({ok, {{simple_one_for_one, 2, 3600}, [Child]}}),
+
+ %% Will be gracefully shutdown
+ {ok, _CPid1} = supervisor:start_child(sup_test, [ShutdownTime]),
+ {ok, _CPid2} = supervisor:start_child(sup_test, [ShutdownTime]),
+
+ %% Will be killed after 2*ShutdownTime milliseconds
+ {ok, _CPid3} = supervisor:start_child(sup_test, [5*ShutdownTime]),
+
+ {T, ok} = timer:tc(fun terminate/2, [SupPid, shutdown]),
+ if T < 1000*ShutdownTime ->
+ %% Because supervisor's children wait before exiting, it can't
+ %% terminate quickly
+ test_server:fail({shutdown_too_short, T});
+ T >= 1000*5*ShutdownTime ->
+ test_server:fail({shutdown_too_long, T});
+ true ->
+ check_exit([SupPid])
+ end.
+
+
%%-------------------------------------------------------------------------
simple_one_for_one_extra(doc) ->
["Tests automatic restart of children "
@@ -988,25 +1144,25 @@ count_children_memory(Config) when is_list(Config) ->
[supervisor:start_child(sup_test, []) || _Ignore <- lists:seq(1,1000)],
garbage_collect(),
- _Size1 = erlang:memory(processes_used),
+ _Size1 = proc_memory(),
Children = supervisor:which_children(sup_test),
- _Size2 = erlang:memory(processes_used),
+ _Size2 = proc_memory(),
ChildCount = get_child_counts(sup_test),
- _Size3 = erlang:memory(processes_used),
+ _Size3 = proc_memory(),
[supervisor:start_child(sup_test, []) || _Ignore2 <- lists:seq(1,1000)],
garbage_collect(),
Children2 = supervisor:which_children(sup_test),
- Size4 = erlang:memory(processes_used),
+ Size4 = proc_memory(),
ChildCount2 = get_child_counts(sup_test),
- Size5 = erlang:memory(processes_used),
+ Size5 = proc_memory(),
garbage_collect(),
Children3 = supervisor:which_children(sup_test),
- Size6 = erlang:memory(processes_used),
+ Size6 = proc_memory(),
ChildCount3 = get_child_counts(sup_test),
- Size7 = erlang:memory(processes_used),
+ Size7 = proc_memory(),
1000 = length(Children),
[1,1000,0,1000] = ChildCount,
@@ -1032,16 +1188,9 @@ count_children_memory(Config) when is_list(Config) ->
[terminate(SupPid, Pid, child, kill) || {undefined, Pid, worker, _Modules} <- Children3],
[1,0,0,0] = get_child_counts(sup_test).
-count_children_allocator_test(MemoryState) ->
- Allocators = [temp_alloc, eheap_alloc, binary_alloc, ets_alloc,
- driver_alloc, sl_alloc, ll_alloc, fix_alloc, std_alloc,
- sys_alloc],
- MemoryStateList = element(4, MemoryState),
- AllocTypes = [lists:keyfind(Alloc, 1, MemoryStateList)
- || Alloc <- Allocators],
- AllocStates = [lists:keyfind(e, 1, AllocValue)
- || {_Type, AllocValue} <- AllocTypes],
- lists:all(fun(State) -> State == {e, true} end, AllocStates).
+proc_memory() ->
+ erts_debug:set_internal_state(wait, deallocations),
+ erlang:memory(processes_used).
%%-------------------------------------------------------------------------
do_not_save_start_parameters_for_temporary_children(doc) ->
@@ -1242,6 +1391,92 @@ terminate_all_children([]) ->
done.
+%%-------------------------------------------------------------------------
+%% OTP-9212. Restart of global supervisor.
+simple_global_supervisor(_Config) ->
+ kill_supervisor(),
+ kill_worker(),
+ exit_worker(),
+ restart_worker(),
+ ok.
+
+kill_supervisor() ->
+ {Top, Sup2_1, Server_1} = start9212(),
+
+ %% Killing a supervisor isn't really supported, but try it anyway...
+ exit(Sup2_1, kill),
+ timer:sleep(200),
+ Sup2_2 = global:whereis_name(sup2),
+ Server_2 = global:whereis_name(server),
+ true = is_pid(Sup2_2),
+ true = is_pid(Server_2),
+ true = Sup2_1 =/= Sup2_2,
+ true = Server_1 =/= Server_2,
+
+ stop9212(Top).
+
+handle_info({fail, With, After}, _State) ->
+ timer:sleep(After),
+ erlang:error(With).
+
+kill_worker() ->
+ {Top, _Sup2, Server_1} = start9212(),
+ exit(Server_1, kill),
+ timer:sleep(200),
+ Server_2 = global:whereis_name(server),
+ true = is_pid(Server_2),
+ true = Server_1 =/= Server_2,
+ stop9212(Top).
+
+exit_worker() ->
+ %% Very much the same as kill_worker().
+ {Top, _Sup2, Server_1} = start9212(),
+ Server_1 ! {fail, normal, 0},
+ timer:sleep(200),
+ Server_2 = global:whereis_name(server),
+ true = is_pid(Server_2),
+ true = Server_1 =/= Server_2,
+ stop9212(Top).
+
+restart_worker() ->
+ {Top, _Sup2, Server_1} = start9212(),
+ ok = supervisor:terminate_child({global, sup2}, child),
+ {ok, _Child} = supervisor:restart_child({global, sup2}, child),
+ Server_2 = global:whereis_name(server),
+ true = is_pid(Server_2),
+ true = Server_1 =/= Server_2,
+ stop9212(Top).
+
+start9212() ->
+ Middle = {middle,{?MODULE,middle9212,[]}, permanent,2000,supervisor,[]},
+ InitResult = {ok, {{one_for_all,3,60}, [Middle]}},
+ {ok, TopPid} = start_link(InitResult),
+
+ Sup2 = global:whereis_name(sup2),
+ Server = global:whereis_name(server),
+ true = is_pid(Sup2),
+ true = is_pid(Server),
+ {TopPid, Sup2, Server}.
+
+stop9212(Top) ->
+ Old = process_flag(trap_exit, true),
+ exit(Top, kill),
+ timer:sleep(200),
+ undefined = global:whereis_name(sup2),
+ undefined = global:whereis_name(server),
+ check_exit([Top]),
+ _ = process_flag(trap_exit, Old),
+ ok.
+
+middle9212() ->
+ Child = {child, {?MODULE,gen_server9212,[]},permanent, 2000, worker, []},
+ InitResult = {ok, {{one_for_all,3,60}, [Child]}},
+ supervisor:start_link({global,sup2}, ?MODULE, InitResult).
+
+gen_server9212() ->
+ InitResult = {ok, []},
+ gen_server:start_link({global,server}, ?MODULE, InitResult, []).
+
%%-------------------------------------------------------------------------
terminate(Pid, Reason) when Reason =/= supervisor ->
@@ -1263,6 +1498,13 @@ terminate(_, ChildPid, _, shutdown) ->
{'DOWN', Ref, process, ChildPid, shutdown} ->
ok
end;
+terminate(_, ChildPid, _, {shutdown, Term}) ->
+ Ref = erlang:monitor(process, ChildPid),
+ exit(ChildPid, {shutdown, Term}),
+ receive
+ {'DOWN', Ref, process, ChildPid, {shutdown, Term}} ->
+ ok
+ end;
terminate(_, ChildPid, _, normal) ->
Ref = erlang:monitor(process, ChildPid),
ChildPid ! stop,
diff --git a/lib/stdlib/test/supervisor_bridge_SUITE.erl b/lib/stdlib/test/supervisor_bridge_SUITE.erl
index f2dbad0b3b..b3056ff41a 100644
--- a/lib/stdlib/test/supervisor_bridge_SUITE.erl
+++ b/lib/stdlib/test/supervisor_bridge_SUITE.erl
@@ -19,8 +19,9 @@
-module(supervisor_bridge_SUITE).
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,starting/1,
- mini_terminate/1,mini_die/1,badstart/1]).
--export([client/1,init/1,internal_loop_init/1,terminate/2]).
+ mini_terminate/1,mini_die/1,badstart/1,
+ simple_global_supervisor/1]).
+-export([client/1,init/1,internal_loop_init/1,terminate/2,server9212/0]).
-include_lib("test_server/include/test_server.hrl").
-define(bridge_name,supervisor_bridge_SUITE_server).
@@ -31,7 +32,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [starting, mini_terminate, mini_die, badstart].
+ [starting, mini_terminate, mini_die, badstart, simple_global_supervisor].
groups() ->
[].
@@ -138,7 +139,9 @@ init(3) ->
receive
{InternalPid,init_done} ->
{ok,InternalPid,self()}
- end.
+ end;
+init({4,Result}) ->
+ Result.
internal_loop_init(Parent) ->
register(?work_bridge_name, self()),
@@ -158,9 +161,11 @@ internal_loop(State) ->
terminate(Reason,{Parent,Worker}) ->
%% This func knows about supervisor_bridge
io:format("Terminating bridge...\n"),
- exit(kill,Worker),
+ exit(Worker,kill),
Parent ! {dying,Reason},
- anything.
+ anything;
+terminate(_Reason, _State) ->
+ any.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -197,3 +202,30 @@ badstart(Config) when is_list(Config) ->
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% OTP-9212. Restart of global supervisor.
+
+simple_global_supervisor(suite) -> [];
+simple_global_supervisor(doc) -> "Globally registered supervisor.";
+simple_global_supervisor(Config) when is_list(Config) ->
+ ?line Dog = test_server:timetrap({seconds,10}),
+
+ Child = {child, {?MODULE,server9212,[]}, permanent, 2000, worker, []},
+ InitResult = {ok, {{one_for_all,3,60}, [Child]}},
+ {ok, Sup} =
+ supervisor:start_link({local,bridge9212}, ?MODULE, {4,InitResult}),
+
+ BN_1 = global:whereis_name(?bridge_name),
+ ?line exit(BN_1, kill),
+ timer:sleep(200),
+ BN_2 = global:whereis_name(?bridge_name),
+ ?line true = is_pid(BN_2),
+ ?line true = BN_1 =/= BN_2,
+
+ ?line process_flag(trap_exit, true),
+ exit(Sup, kill),
+ ?line receive {'EXIT', Sup, killed} -> ok end,
+ ?line test_server:timetrap_cancel(Dog),
+ ok.
+
+server9212() ->
+ supervisor_bridge:start_link({global,?bridge_name}, ?MODULE, 3).
diff --git a/lib/stdlib/test/sys_SUITE.erl b/lib/stdlib/test/sys_SUITE.erl
index 72b089aa3f..fe039e8bcc 100644
--- a/lib/stdlib/test/sys_SUITE.erl
+++ b/lib/stdlib/test/sys_SUITE.erl
@@ -71,7 +71,7 @@ log_to_file(Config) when is_list(Config) ->
?line ok = sys:log_to_file(?server,TempName),
?line {ok,-44} = public_call(44),
?line ok = sys:log_to_file(?server,false),
- ?line {ok,Fd} = file:open(TempName,read),
+ ?line {ok,Fd} = file:open(TempName,[read]),
?line Msg1 = io:get_line(Fd,''),
?line Msg2 = io:get_line(Fd,''),
?line file:close(Fd),
diff --git a/lib/stdlib/test/tar_SUITE.erl b/lib/stdlib/test/tar_SUITE.erl
index e32704ca65..9ad3936928 100644
--- a/lib/stdlib/test/tar_SUITE.erl
+++ b/lib/stdlib/test/tar_SUITE.erl
@@ -65,7 +65,7 @@ borderline(Config) when is_list(Config) ->
?line {ok, Cwd} = file:get_cwd(),
?line RootDir = ?config(priv_dir, Config),
- ?line TempDir = remove_prefix(Cwd++"/", filename:join(RootDir, borderline)),
+ ?line TempDir = remove_prefix(Cwd++"/", filename:join(RootDir, "borderline")),
?line ok = file:make_dir(TempDir),
?line Record = 512,
@@ -283,17 +283,16 @@ long_names(doc) ->
long_names(Config) when is_list(Config) ->
?line DataDir = ?config(data_dir, Config),
?line Long = filename:join(DataDir, "long_names.tar"),
+ run_in_short_tempdir(Config,
+ fun() -> do_long_names(Long) end).
+do_long_names(Long) ->
%% Try table/2 and extract/2.
?line case erl_tar:table(Long, [verbose]) of
{ok,List} when is_list(List) ->
?line io:format("~p\n", [List])
end,
-
- %% To avoid getting too long paths for Windows to handle, extract into
- %% the current directory (which is the test_server directory). Its path
- %% is quite a bit shorter than the path to priv_dir.
?line {ok,Cwd} = file:get_cwd(),
?line ok = erl_tar:extract(Long),
?line Base = filename:join([Cwd, "original_software", "written_by",
@@ -312,29 +311,28 @@ long_names(Config) when is_list(Config) ->
?line "Here"++_ = binary_to_list(First),
?line "And"++_ = binary_to_list(Second),
- %% Clean up.
- ?line delete_files([filename:join(Cwd, "original_software"),EmptyDir]),
-
ok.
create_long_names(doc) ->
["Creates a tar file from a deep directory structure (filenames are ",
"longer than 100 characters)."];
create_long_names(Config) when is_list(Config) ->
- ?line PrivDir = ?config(priv_dir, Config),
- ?line ok = file:set_cwd(PrivDir),
- Dirs = [aslfjkshjkhliuf,
- asdhjfehnbfsky,
- sahajfskdfhsz,
- asldfkdlfy4y8rchg,
- f7nafhjgffagkhsfkhsjk,
- dfjasldkfjsdkfjashbv],
+ run_in_short_tempdir(Config, fun create_long_names/0).
+
+create_long_names() ->
+ ?line {ok,Dir} = file:get_cwd(),
+ Dirs = ["aslfjkshjkhliuf",
+ "asdhjfehnbfsky",
+ "sahajfskdfhsz",
+ "asldfkdlfy4y8rchg",
+ "f7nafhjgffagkhsfkhsjk",
+ "dfjasldkfjsdkfjashbv"],
?line DeepDir = make_dirs(Dirs, []),
?line AFile = filename:join(DeepDir, "a_file"),
?line Hello = "hello, world\n",
?line ok = file:write_file(AFile, Hello),
- ?line TarName = filename:join(PrivDir, "my_tar_with_long_names.tar"),
+ ?line TarName = filename:join(Dir, "my_tar_with_long_names.tar"),
?line ok = erl_tar:create(TarName, [AFile]),
%% Print contents.
@@ -347,9 +345,6 @@ create_long_names(Config) when is_list(Config) ->
?line {ok, Bin} = file:read_file(filename:join(ExtractDir, AFile)),
?line Hello = binary_to_list(Bin),
- %% Clean up.
- ?line delete_files([ExtractDir,TarName,hd(Dirs)]),
-
ok.
make_dirs([Dir|Rest], []) ->
@@ -487,7 +482,7 @@ extract_from_binary_compressed(Config) when is_list(Config) ->
%% Trying extracting from a binary.
?line ok = erl_tar:extract({binary,Bin}, [compressed,{cwd,ExtractDir}]),
- ?line {ok,List} = file:list_dir(filename:join(ExtractDir, ddll_SUITE_data)),
+ ?line {ok,List} = file:list_dir(filename:join(ExtractDir, "ddll_SUITE_data")),
?line io:format("~p\n", [List]),
?line 19 = length(List),
@@ -676,7 +671,7 @@ cooked_compressed(Config) when is_list(Config) ->
end, List),
%% Clean up.
- ?line delete_files([filename:join(PrivDir, ddll_SUITE_data)]),
+ ?line delete_files([filename:join(PrivDir, "ddll_SUITE_data")]),
ok.
memory(doc) ->
@@ -734,3 +729,42 @@ delete_files([Item|Rest]) ->
end,
delete_files(Rest).
+%% Move to a temporary directory with as short name as possible and
+%% execute Fun. Remove the directory and any files in it afterwards.
+%% This is necessary because pathnames on Windows may be limited to
+%% 260 characters.
+run_in_short_tempdir(Config, Fun) ->
+ {ok,Cwd} = file:get_cwd(),
+ PrivDir0 = ?config(priv_dir, Config),
+
+ %% Normalize name to make sure that there is no slash at the end.
+ PrivDir = filename:absname(PrivDir0),
+
+ %% We need a base directory with a much shorter pathname than
+ %% priv_dir. We KNOW that priv_dir is located four levels below
+ %% the directory that common_test puts the ct_run.* directories
+ %% in. That fact is not documented, but an usually reliable source
+ %% assured me that the directory structure is unlikely to change
+ %% in future versions of common_test because of backward
+ %% compatibility (tools developed by users of common_test depend
+ %% on the current directory layout).
+ Base = lists:foldl(fun(_, D) ->
+ filename:dirname(D)
+ end, PrivDir, [1,2,3,4]),
+
+ Dir = make_temp_dir(Base, 0),
+ ok = file:set_cwd(Dir),
+ io:format("Running test in ~s\n", [Dir]),
+ try
+ Fun()
+ after
+ file:set_cwd(Cwd),
+ delete_files([Dir])
+ end.
+
+make_temp_dir(Base, I) ->
+ Name = filename:join(Base, integer_to_list(I, 36)),
+ case file:make_dir(Name) of
+ ok -> Name;
+ {error,eexist} -> make_temp_dir(Base, I+1)
+ end.
diff --git a/lib/stdlib/test/unicode_SUITE.erl b/lib/stdlib/test/unicode_SUITE.erl
index 9aa800209d..4055af2741 100644
--- a/lib/stdlib/test/unicode_SUITE.erl
+++ b/lib/stdlib/test/unicode_SUITE.erl
@@ -322,7 +322,7 @@ roundtrips(Config) when is_list(Config) ->
ex_roundtrips(Config) when is_list(Config) ->
?line L1 = ranges(0, 16#D800 - 1,
erlang:system_info(context_reductions) * 11),
- ?line L2 = ranges(16#DFFF + 1, 16#FFFE - 1,
+ ?line L2 = ranges(16#DFFF + 1, 16#10000 - 1,
erlang:system_info(context_reductions) * 11),
%?line L3 = ranges(16#FFFF + 1, 16#10FFFF,
% erlang:system_info(context_reductions) * 11),
@@ -569,7 +569,6 @@ utf16_illegal_sequences_bif(Config) when is_list(Config) ->
ex_utf16_illegal_sequences_bif(Config) when is_list(Config) ->
?line utf16_fail_range_bif_simple(16#10FFFF+1, 16#10FFFF+512), %Too large.
?line utf16_fail_range_bif(16#D800, 16#DFFF), %Reserved for UTF-16.
- ?line utf16_fail_range_bif(16#FFFE, 16#FFFF), %Non-characters.
?line lonely_hi_surrogate_bif(16#D800, 16#DBFF,incomplete),
?line lonely_hi_surrogate_bif(16#DC00, 16#DFFF,error),
@@ -644,7 +643,6 @@ utf8_illegal_sequences_bif(Config) when is_list(Config) ->
ex_utf8_illegal_sequences_bif(Config) when is_list(Config) ->
?line fail_range_bif(16#10FFFF+1, 16#10FFFF+512), %Too large.
?line fail_range_bif(16#D800, 16#DFFF), %Reserved for UTF-16.
- ?line fail_range_bif(16#FFFE, 16#FFFF), %Reserved (BOM).
%% Illegal first character.
?line [fail_bif(<<I,16#8F,16#8F,16#8F>>,unicode) || I <- lists:seq(16#80, 16#BF)],
diff --git a/lib/stdlib/test/zip_SUITE.erl b/lib/stdlib/test/zip_SUITE.erl
index d5f2cd52d4..7233c061ef 100644
--- a/lib/stdlib/test/zip_SUITE.erl
+++ b/lib/stdlib/test/zip_SUITE.erl
@@ -375,7 +375,8 @@ zip_options(Config) when is_list(Config) ->
ok = file:set_cwd(?config(data_dir, Config)),
%% Create a zip archive
- {ok, Zip} = zip:zip("filename_not_used.zip", Names, [memory, {cwd, PrivDir}]),
+ {ok, {_,Zip}} =
+ zip:zip("filename_not_used.zip", Names, [memory, {cwd, PrivDir}]),
%% Open archive
{ok, ZipSrv} = zip:zip_open(Zip, [memory]),
diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk
index c0956030cf..2f0ecd3863 100644
--- a/lib/stdlib/vsn.mk
+++ b/lib/stdlib/vsn.mk
@@ -1 +1 @@
-STDLIB_VSN = 1.17.4
+STDLIB_VSN = 1.18
diff --git a/lib/syntax_tools/doc/Makefile b/lib/syntax_tools/doc/Makefile
index 6afd16f669..d9981de880 100644
--- a/lib/syntax_tools/doc/Makefile
+++ b/lib/syntax_tools/doc/Makefile
@@ -78,12 +78,3 @@ release_docs_spec: docs
release_spec:
-
-
-
-# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-#-include make.dep
-
-
diff --git a/lib/syntax_tools/doc/src/make.dep b/lib/syntax_tools/doc/src/make.dep
deleted file mode 100644
index acc76857bb..0000000000
--- a/lib/syntax_tools/doc/src/make.dep
+++ /dev/null
@@ -1,22 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex chapter.tex epp_dodger.tex erl_comment_scan.tex \
- erl_prettypr.tex erl_recomment.tex erl_syntax.tex \
- erl_syntax_lib.tex erl_tidy.tex igor.tex part.tex \
- prettypr.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/syntax_tools/doc/src/notes.xml b/lib/syntax_tools/doc/src/notes.xml
index ec2dd762b8..5948f7ada3 100644
--- a/lib/syntax_tools/doc/src/notes.xml
+++ b/lib/syntax_tools/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2007</year><year>2010</year>
+ <year>2007</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl
index 9df5f26454..7f58fda519 100644
--- a/lib/syntax_tools/src/erl_syntax.erl
+++ b/lib/syntax_tools/src/erl_syntax.erl
@@ -6093,11 +6093,16 @@ implicit_fun_name(Node) ->
{'fun', Pos, {function, Atom, Arity}} ->
arity_qualifier(set_pos(atom(Atom), Pos),
set_pos(integer(Arity), Pos));
- {'fun', Pos, {function, Module, Atom, Arity}} ->
+ {'fun', Pos, {function, Module, Atom, Arity}}
+ when is_atom(Module), is_atom(Atom), is_integer(Arity) ->
+ %% Backward compatibility with pre-R15 abstract format.
module_qualifier(set_pos(atom(Module), Pos),
arity_qualifier(
set_pos(atom(Atom), Pos),
set_pos(integer(Arity), Pos)));
+ {'fun', Pos, {function, Module, Atom, Arity}} ->
+ %% New in R15: fun M:F/A.
+ module_qualifier(Module, arity_qualifier(Atom, Arity));
Node1 ->
data(Node1)
end.
diff --git a/lib/syntax_tools/src/erl_tidy.erl b/lib/syntax_tools/src/erl_tidy.erl
index 1cfdc7234a..09efc9c392 100644
--- a/lib/syntax_tools/src/erl_tidy.erl
+++ b/lib/syntax_tools/src/erl_tidy.erl
@@ -103,7 +103,7 @@ dir(Dir) ->
%% <dt>{regexp, string()}</dt>
%%
%% <dd>The value denotes a regular expression (see module
-%% `regexp'). Tidying will only be applied to those
+%% `re'). Tidying will only be applied to those
%% regular files whose names match this pattern. The default
%% value is `".*\\.erl$"', which matches normal
%% Erlang source file names.</dd>
@@ -124,7 +124,7 @@ dir(Dir) ->
%%
%% See the function {@link file/2} for further options.
%%
-%% @see //stdlib/regexp
+%% @see //stdlib/re
%% @see file/2
-record(dir, {follow_links = false :: boolean(),
diff --git a/lib/test_server/doc/src/Makefile b/lib/test_server/doc/src/Makefile
index c7ba415e5b..f0be284324 100644
--- a/lib/test_server/doc/src/Makefile
+++ b/lib/test_server/doc/src/Makefile
@@ -133,9 +133,3 @@ release_docs_spec: docs
release_spec:
release_tests_spec:
-
-# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-include make.dep
diff --git a/lib/test_server/doc/src/make.dep b/lib/test_server/doc/src/make.dep
deleted file mode 100644
index ee9100bd08..0000000000
--- a/lib/test_server/doc/src/make.dep
+++ /dev/null
@@ -1,24 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: basics_chapter.tex book.tex example_chapter.tex \
- part.tex ref_man.tex run_test_chapter.tex \
- test_server_app.tex test_server_ctrl.tex \
- test_server.tex test_spec_chapter.tex \
- write_framework_chapter.tex \
- write_test_chapter.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/test_server/doc/src/notes.xml b/lib/test_server/doc/src/notes.xml
index 50923b1b03..beeff55ffe 100644
--- a/lib/test_server/doc/src/notes.xml
+++ b/lib/test_server/doc/src/notes.xml
@@ -32,6 +32,150 @@
<file>notes.xml</file>
</header>
+<section><title>Test_Server 3.4.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ An error in how comments are colored in the test suite
+ overview html log file has been corrected. As result, a
+ new framework callback function, format_comment/1, has
+ been introduced.</p>
+ <p>
+ Own Id: OTP-9237</p>
+ </item>
+ <item>
+ <p>
+ Test Server did not release SASL TTY handlers
+ (sasl_report_tty_h and error_logger_tty_h) properly after
+ each test run. This error has been fixed.</p>
+ <p>
+ Own Id: OTP-9311</p>
+ </item>
+ <item>
+ <p>
+ Automatically generated init- and end-configuration
+ functions for test case groups caused incorrect execution
+ order of test cases. This has been corrected.</p>
+ <p>
+ Own Id: OTP-9369</p>
+ </item>
+ <item>
+ <p>
+ If ct:log/2 was called with bad arguments, this could
+ cause the Common Test IO handling process to crash. This
+ fault has been corrected.</p>
+ <p>
+ Own Id: OTP-9371 Aux Id: OTP-8933 </p>
+ </item>
+ <item>
+ <p>
+ A bug has been fixed that made Test Server call the
+ end_tc/3 framework function with an incorrect module name
+ as first argument.</p>
+ <p>
+ Own Id: OTP-9379 Aux Id: seq11863 </p>
+ </item>
+ <item>
+ <p>
+ If end_per_testcase caused a timetrap timeout, the actual
+ test case status was discarded and the test case logged
+ as successful (even if the case had actually failed
+ before the call to end_per_testcase). This fault has been
+ fixed.</p>
+ <p>
+ Own Id: OTP-9397</p>
+ </item>
+ <item>
+ <p>
+ If a timetrap timeout occured during execution of of a
+ function in a lib module (i.e. a function called directly
+ or indirectly from a test case), the Suite argument in
+ the end_tc/3 framework callback function would not
+ correctly contain the name of the test suite, but the lib
+ module. (This would only happen if the lib module was
+ compiled with ct.hrl included). This error has been
+ solved.</p>
+ <p>
+ Own Id: OTP-9398</p>
+ </item>
+ <item>
+ <p>
+ Add a proplist() type</p>
+ <p>
+ Recently I was adding specs to an API and found that
+ there is no canonical proplist() type defined. (Thanks to
+ Ryan Zezeski)</p>
+ <p>
+ Own Id: OTP-9499</p>
+ </item>
+ <item>
+ <p> XML files have been corrected. </p>
+ <p>
+ Own Id: OTP-9550 Aux Id: OTP-9541 </p>
+ </item>
+ <item>
+ <p>
+ If a test suite would start with a test case group
+ defined without the init_per_group/2 and end_per_group/2
+ function, init_per_suite/1 would not execute initially
+ and logging of the test run would fail. This error has
+ been fixed.</p>
+ <p>
+ Own Id: OTP-9584</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ A new option, 'logopts', has been introduced, to make it
+ possible to modify some aspects of the logging behaviour
+ in Common Test (or Test Server). For example, whenever an
+ io printout is made, test_server adds newline (\n) to the
+ end of the output string. This may not always be a
+ preferred action and can therefore be disabled by means
+ of "ct_run ... -logopts no_nl" (or ct:run_test([...,
+ {logopts,[no_nl]}])). A new framework callback function,
+ get_logopts/0, has been introduced (see the ct_framework
+ module for details).</p>
+ <p>
+ Own Id: OTP-9372 Aux Id: OTP-9396 </p>
+ </item>
+ <item>
+ <p>
+ A new option, 'logopts', has been introduced, to make it
+ possible to modify some aspects of the logging behaviour
+ in Common Test (or Test Server). For example, if the html
+ version of the test suite source code should not be
+ generated during the test run (and consequently be
+ unavailable in the log file system), the feature may be
+ disabled by means of "ct_run ... -logopts no_src" (or
+ ct:run_test([..., {logopts,[no_src]}])). A new framework
+ callback function, get_logopts/0, has been introduced
+ (see the ct_framework module for details).</p>
+ <p>
+ Own Id: OTP-9396 Aux Id: seq11869, OTP-9372 </p>
+ </item>
+ <item>
+ <p>
+ It is now possible to use a tuple {M,F,A}, or a fun, as
+ timetrap specification in the suite info function or test
+ case info functions. The function must return a valid
+ timeout value, as documented in the common_test man page
+ and in the User's Guide.</p>
+ <p>
+ Own Id: OTP-9501 Aux Id: seq11894 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Test_Server 3.4.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/test_server/doc/src/ts.xml b/lib/test_server/doc/src/ts.xml
index 496ad3667a..f9b48d8372 100644
--- a/lib/test_server/doc/src/ts.xml
+++ b/lib/test_server/doc/src/ts.xml
@@ -77,7 +77,7 @@
</p>
<p><c>ts:install/0</c> is used if the target platform is the
same as the controller host, i.e. if you run on "local target"
- and no options are needed. Then running <c>ts:install/0</c><c>ts</c>
+ and no options are needed. Then running <c>ts:install/0</c> <c>ts</c>
will run an autoconf script for your current
environment and set up the necessary variables needed by the
test suites.
diff --git a/lib/test_server/include/test_server.hrl b/lib/test_server/include/test_server.hrl
index 4b96d84ace..36e7e1f83d 100644
--- a/lib/test_server/include/test_server.hrl
+++ b/lib/test_server/include/test_server.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -20,11 +20,10 @@
-ifdef(line_trace).
-line_trace(true).
-define(line,
- put(test_server_loc,{?MODULE,?LINE}),
io:format(lists:concat([?MODULE,",",integer_to_list(?LINE),": ~p"]),
[erlang:now()]),).
-else.
--define(line,put(test_server_loc,{?MODULE,?LINE}),).
+-define(line,).
-endif.
-define(t,test_server).
-define(config,test_server:lookup_config).
diff --git a/lib/test_server/include/test_server_line.hrl b/lib/test_server/include/test_server_line.hrl
index 60ef860883..3c309d3ee5 100644
--- a/lib/test_server/include/test_server_line.hrl
+++ b/lib/test_server/include/test_server_line.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -16,5 +16,4 @@
%%
%% %CopyrightEnd%
%%
--compile({parse_transform,test_server_line}).
diff --git a/lib/test_server/src/Makefile b/lib/test_server/src/Makefile
index 63a585d526..4bc51873c2 100644
--- a/lib/test_server/src/Makefile
+++ b/lib/test_server/src/Makefile
@@ -43,7 +43,6 @@ MODULES= test_server_ctrl \
test_server_node \
test_server \
test_server_sup \
- test_server_line \
test_server_h \
erl2html2 \
vxworks_client
diff --git a/lib/test_server/src/test_server.app.src b/lib/test_server/src/test_server.app.src
index af2d4dc2cb..7e87583a7b 100644
--- a/lib/test_server/src/test_server.app.src
+++ b/lib/test_server/src/test_server.app.src
@@ -24,7 +24,6 @@
test_server_ctrl,
test_server,
test_server_h,
- test_server_line,
test_server_node,
test_server_sup
]},
diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl
index 591329b361..49f97686a0 100644
--- a/lib/test_server/src/test_server.erl
+++ b/lib/test_server/src/test_server.erl
@@ -612,6 +612,7 @@ do_run_test_case_apply(Mod, Func, Args, Name, RunInit, TimetrapData) ->
print(minor, "Current directory is ~p\n", [Cwd]),
print_timestamp(minor,"Started at "),
TCCallback = get(test_server_testcase_callback),
+ LogOpts = get(test_server_logopts),
Ref = make_ref(),
OldGLeader = group_leader(),
%% Set ourself to group leader for the spawned process
@@ -621,7 +622,7 @@ do_run_test_case_apply(Mod, Func, Args, Name, RunInit, TimetrapData) ->
fun() ->
run_test_case_eval(Mod, Func, Args, Name, Ref,
RunInit, TimetrapData,
- TCCallback)
+ LogOpts, TCCallback)
end),
group_leader(OldGLeader, self()),
put(test_server_detected_fail, []),
@@ -733,15 +734,23 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
print(Detail,Format,Args),
run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
{comment,NewComment} ->
+ NewComment1 = test_server_ctrl:to_string(NewComment),
+ NewComment2 = test_server_sup:framework_call(format_comment,
+ [NewComment1],
+ NewComment1),
Terminate1 =
case Terminate of
{true,{Time,Value,Loc,Opts,_OldComment}} ->
- {true,{Time,Value,mod_loc(Loc),Opts,NewComment}};
+ {true,{Time,Value,mod_loc(Loc),Opts,NewComment2}};
Other ->
Other
end,
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate1,NewComment,CurrConf);
- {set_curr_conf,NewCurrConf} ->
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate1,NewComment2,CurrConf);
+ {read_comment,From} ->
+ From ! {self(),read_comment,Comment},
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
+ {set_curr_conf,From,NewCurrConf} ->
+ From ! {self(),set_curr_conf,ok},
run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,NewCurrConf);
{'EXIT',Pid,{Ref,Time,Value,Loc,Opts}} ->
RetVal = {Time/1000000,Value,mod_loc(Loc),Opts,Comment},
@@ -753,13 +762,12 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
case mod_loc(Loc) of
{FwMod,FwFunc,framework} ->
%% timout during framework call
- spawn_fw_call(FwMod,FwFunc,Pid,
+ spawn_fw_call(FwMod,FwFunc,CurrConf,Pid,
{framework_error,{timetrap,TVal}},
unknown,self(),Comment),
run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,
Comment,undefined);
Loc1 ->
- {Mod,Func} = get_mf(Loc1),
%% call end_per_testcase on a separate process,
%% only so that the user has a chance to clean up
%% after init_per_testcase, even after a timetrap timeout
@@ -775,11 +783,13 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
TVal),
{EndConfPid,{Mod,Func},Conf};
_ ->
+ {Mod,Func} = get_mf(Loc1),
%% The framework functions mustn't execute on this
%% group leader process or io will cause deadlock,
%% so we spawn a dedicated process for the operation
%% and let the group leader go back to handle io.
- spawn_fw_call(Mod,Func,Pid,{timetrap_timeout,TVal},
+ spawn_fw_call(Mod,Func,CurrConf,Pid,
+ {timetrap_timeout,TVal},
Loc1,self(),Comment),
undefined
end,
@@ -790,12 +800,13 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
case mod_loc(Loc) of
{FwMod,FwFunc,framework} ->
%% timout during framework call
- spawn_fw_call(FwMod,FwFunc,Pid,
+ spawn_fw_call(FwMod,FwFunc,CurrConf,Pid,
{framework_error,{timetrap,TVal}},
unknown,self(),Comment);
Loc1 ->
{Mod,_Func} = get_mf(Loc1),
- spawn_fw_call(Mod,InitOrEnd,Pid,{timetrap_timeout,TVal},
+ spawn_fw_call(Mod,InitOrEnd,CurrConf,Pid,
+ {timetrap_timeout,TVal},
Loc1,self(),Comment)
end,
run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
@@ -804,13 +815,12 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
case mod_loc(AbortLoc) of
{FwMod,FwFunc,framework} ->
%% abort during framework call
- spawn_fw_call(FwMod,FwFunc,Pid,
+ spawn_fw_call(FwMod,FwFunc,CurrConf,Pid,
{framework_error,ErrorMsg},
unknown,self(),Comment),
run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,
Comment,undefined);
Loc1 ->
- {Mod,Func} = get_mf(Loc1),
%% call end_per_testcase on a separate process, only so
%% that the user has a chance to clean up after init_per_testcase,
%% even after abortion
@@ -828,7 +838,8 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
TVal),
{EndConfPid,{Mod,Func},Conf};
_ ->
- spawn_fw_call(Mod,Func,Pid,ErrorMsg,
+ {Mod,Func} = get_mf(Loc1),
+ spawn_fw_call(Mod,Func,CurrConf,Pid,ErrorMsg,
Loc1,self(),Comment),
undefined
end,
@@ -839,17 +850,18 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
%% result of an exit(TestCase,kill) call, which is the
%% only way to abort a testcase process that traps exits
%% (see abort_current_testcase)
- spawn_fw_call(undefined,undefined,Pid,testcase_aborted_or_killed,
+ spawn_fw_call(undefined,undefined,CurrConf,Pid,
+ testcase_aborted_or_killed,
unknown,self(),Comment),
run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
{fw_error,{FwMod,FwFunc,FwError}} ->
- spawn_fw_call(FwMod,FwFunc,Pid,{framework_error,FwError},
+ spawn_fw_call(FwMod,FwFunc,CurrConf,Pid,{framework_error,FwError},
unknown,self(),Comment),
run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
_Other ->
%% the testcase has terminated because of Reason (e.g. an exit
%% because a linked process failed)
- spawn_fw_call(undefined,undefined,Pid,Reason,
+ spawn_fw_call(undefined,undefined,CurrConf,Pid,Reason,
unknown,self(),Comment),
run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf)
end;
@@ -857,7 +869,7 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
case CurrConf of
{EndConfPid,{Mod,Func},_Conf} ->
{_Mod,_Func,TCPid,TCExitReason,Loc} = Data,
- spawn_fw_call(Mod,Func,TCPid,TCExitReason,Loc,self(),Comment),
+ spawn_fw_call(Mod,Func,CurrConf,TCPid,TCExitReason,Loc,self(),Comment),
run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,undefined);
_ ->
run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf)
@@ -928,7 +940,7 @@ call_end_conf(Mod,Func,TCPid,TCExitReason,Loc,Conf,TVal) ->
ok
end,
Supervisor ! {self(),end_conf}
- end,
+ end,
Pid = spawn_link(EndConfApply),
receive
{Pid,end_conf} ->
@@ -941,50 +953,72 @@ call_end_conf(Mod,Func,TCPid,TCExitReason,Loc,Conf,TVal) ->
end,
spawn_link(EndConfProc).
-spawn_fw_call(Mod,{init_per_testcase,Func},Pid,{timetrap_timeout,TVal}=Why,
+spawn_fw_call(Mod,{init_per_testcase,Func},_,Pid,{timetrap_timeout,TVal}=Why,
Loc,SendTo,Comment) ->
FwCall =
fun() ->
- Skip = {skip,{failed,{Mod,init_per_testcase,Why}}},
- %% if init_per_testcase fails, the test case
- %% should be skipped
- case catch do_end_tc_call(Mod,Func,{Pid,Skip,[[]]},Why) of
- {'EXIT',FwEndTCErr} ->
- exit({fw_notify_done,end_tc,FwEndTCErr});
- _ ->
- ok
- end,
- %% finished, report back
- SendTo ! {self(),fw_notify_done,
- {TVal/1000,Skip,Loc,[],Comment}}
+ Skip = {skip,{failed,{Mod,init_per_testcase,Why}}},
+ %% if init_per_testcase fails, the test case
+ %% should be skipped
+ case catch do_end_tc_call(Mod,Func, Loc, {Pid,Skip,[[]]}, Why) of
+ {'EXIT',FwEndTCErr} ->
+ exit({fw_notify_done,end_tc,FwEndTCErr});
+ _ ->
+ ok
+ end,
+ %% finished, report back
+ SendTo ! {self(),fw_notify_done,
+ {TVal/1000,Skip,Loc,[],Comment}}
end,
spawn_link(FwCall);
-spawn_fw_call(Mod,{end_per_testcase,Func},Pid,{timetrap_timeout,TVal}=Why,
- Loc,SendTo,_Comment) ->
+spawn_fw_call(Mod,{end_per_testcase,Func},EndConf,Pid,
+ {timetrap_timeout,TVal}=Why,_Loc,SendTo,Comment) ->
+ %%! This is a temporary fix that keeps Test Server alive during
+ %%! execution of a parallel test case group, when sometimes
+ %%! this clause gets called with EndConf == undefined. See OTP-9594
+ %%! for more info.
+ EndConf1 = if EndConf == undefined ->
+ [{tc_status,{failed,{Mod,end_per_testcase,Why}}}];
+ true ->
+ EndConf
+ end,
FwCall =
fun() ->
- Conf = [{tc_status,ok}],
- %% if end_per_testcase fails, the test case should be
- %% reported successful with a warning printed as comment
- case catch do_end_tc_call(Mod,Func,{Pid,
- {failed,{Mod,end_per_testcase,Why}},
- [Conf]}, Why) of
- {'EXIT',FwEndTCErr} ->
- exit({fw_notify_done,end_tc,FwEndTCErr});
- _ ->
- ok
- end,
- %% finished, report back
- SendTo ! {self(),fw_notify_done,
- {TVal/1000,{error,{Mod,end_per_testcase,Why}},Loc,[],
- ["<font color=\"red\">"
- "WARNING: end_per_testcase timed out!"
- "</font>"]}}
+ {RetVal,Report} =
+ case proplists:get_value(tc_status, EndConf1) of
+ undefined ->
+ E = {failed,{Mod,end_per_testcase,Why}},
+ {E,E};
+ E = {failed,Reason} ->
+ {E,{error,Reason}};
+ Result ->
+ E = {failed,{Mod,end_per_testcase,Why}},
+ {Result,E}
+ end,
+ FailLoc = proplists:get_value(tc_fail_loc, EndConf1),
+ case catch do_end_tc_call(Mod,Func, FailLoc,
+ {Pid,Report,[EndConf1]}, Why) of
+ {'EXIT',FwEndTCErr} ->
+ exit({fw_notify_done,end_tc,FwEndTCErr});
+ _ ->
+ ok
+ end,
+ %% if end_per_testcase fails a warning should be
+ %% printed as comment
+ Comment1 = if Comment == "" -> "";
+ true -> Comment ++ "<br>"
+ end,
+ %% finished, report back
+ SendTo ! {self(),fw_notify_done,
+ {TVal/1000,RetVal,FailLoc,[],
+ [Comment1,"<font color=\"red\">"
+ "WARNING: end_per_testcase timed out!"
+ "</font>"]}}
end,
spawn_link(FwCall);
-spawn_fw_call(FwMod,FwFunc,_Pid,{framework_error,FwError},_,SendTo,_Comment) ->
+spawn_fw_call(FwMod,FwFunc,_,_Pid,{framework_error,FwError},_,SendTo,_Comment) ->
FwCall =
fun() ->
test_server_sup:framework_call(report, [framework_error,
@@ -999,7 +1033,7 @@ spawn_fw_call(FwMod,FwFunc,_Pid,{framework_error,FwError},_,SendTo,_Comment) ->
end,
spawn_link(FwCall);
-spawn_fw_call(Mod,Func,Pid,Error,Loc,SendTo,Comment) ->
+spawn_fw_call(Mod,Func,_,Pid,Error,Loc,SendTo,Comment) ->
FwCall =
fun() ->
case catch fw_error_notify(Mod,Func,[],
@@ -1011,7 +1045,8 @@ spawn_fw_call(Mod,Func,Pid,Error,Loc,SendTo,Comment) ->
ok
end,
Conf = [{tc_status,{failed,timetrap_timeout}}],
- case catch do_end_tc_call(Mod,Func,{Pid,Error,[Conf]},Error) of
+ case catch do_end_tc_call(Mod,Func, Loc,
+ {Pid,Error,[Conf]},Error) of
{'EXIT',FwEndTCErr} ->
exit({fw_notify_done,end_tc,FwEndTCErr});
_ ->
@@ -1072,8 +1107,9 @@ job_proxy_msgloop() ->
%% or sends a message {failed, File, Line} to it's group_leader
run_test_case_eval(Mod, Func, Args0, Name, Ref, RunInit,
- TimetrapData, TCCallback) ->
- put(test_server_multiply_timetraps,TimetrapData),
+ TimetrapData, LogOpts, TCCallback) ->
+ put(test_server_multiply_timetraps, TimetrapData),
+ put(test_server_logopts, LogOpts),
{{Time,Value},Loc,Opts} =
case test_server_sup:framework_call(init_tc,[?pl2a(Mod),Func,Args0],
@@ -1081,22 +1117,26 @@ run_test_case_eval(Mod, Func, Args0, Name, Ref, RunInit,
{ok,Args} ->
run_test_case_eval1(Mod, Func, Args, Name, RunInit, TCCallback);
Error = {error,_Reason} ->
- NewResult = do_end_tc_call(Mod,Func,{Error,Args0},
+ Where = {Mod,Func},
+ NewResult = do_end_tc_call(Mod,Func, Where, {Error,Args0},
{skip,{failed,Error}}),
- {{0,NewResult},{Mod,Func},[]};
+ {{0,NewResult},Where,[]};
{fail,Reason} ->
Conf = [{tc_status,{failed,Reason}} | hd(Args0)],
+ Where = {Mod,Func},
fw_error_notify(Mod, Func, Conf, Reason),
- NewResult = do_end_tc_call(Mod,Func, {{error,Reason},[Conf]},
+ NewResult = do_end_tc_call(Mod,Func, Where, {{error,Reason},[Conf]},
{fail,Reason}),
- {{0,NewResult},{Mod,Func},[]};
+ {{0,NewResult},Where,[]};
Skip = {skip,_Reason} ->
- NewResult = do_end_tc_call(Mod,Func,{Skip,Args0},Skip),
- {{0,NewResult},{Mod,Func},[]};
+ Where = {Mod,Func},
+ NewResult = do_end_tc_call(Mod,Func, Where, {Skip,Args0}, Skip),
+ {{0,NewResult},Where,[]};
{auto_skip,Reason} ->
- NewResult = do_end_tc_call(Mod, Func, {{skip,Reason},Args0},
+ Where = {Mod,Func},
+ NewResult = do_end_tc_call(Mod,Func, Where, {{skip,Reason},Args0},
{skip,{fw_auto_skip,Reason}}),
- {{0,NewResult},{Mod,Func},[]}
+ {{0,NewResult},Where,[]}
end,
exit({Ref,Time,Value,Loc,Opts}).
@@ -1110,18 +1150,19 @@ run_test_case_eval1(Mod, Func, Args, Name, RunInit, TCCallback) ->
Skip = {skip,Reason} ->
Line = get_loc(),
Conf = [{tc_status,{skipped,Reason}}],
- NewRes = do_end_tc_call(Mod,Func,{Skip,[Conf]}, Skip),
+ NewRes = do_end_tc_call(Mod,Func, Line, {Skip,[Conf]}, Skip),
{{0,NewRes},Line,[]};
{skip_and_save,Reason,SaveCfg} ->
Line = get_loc(),
Conf = [{tc_status,{skipped,Reason}},{save_config,SaveCfg}],
- NewRes = do_end_tc_call(Mod, Func, {{skip,Reason},[Conf]},
- {skip, Reason}),
+ NewRes = do_end_tc_call(Mod,Func, Line, {{skip,Reason},[Conf]},
+ {skip,Reason}),
{{0,NewRes},Line,[]};
FailTC = {fail,Reason} -> % user fails the testcase
EndConf = [{tc_status,{failed,Reason}} | hd(Args)],
fw_error_notify(Mod, Func, EndConf, Reason),
- NewRes = do_end_tc_call(Mod, Func, {{error,Reason},[EndConf]},
+ NewRes = do_end_tc_call(Mod,Func, {Mod,Func},
+ {{error,Reason},[EndConf]},
FailTC),
{{0,NewRes},{Mod,Func},[]};
{ok,NewConf} ->
@@ -1129,47 +1170,61 @@ run_test_case_eval1(Mod, Func, Args, Name, RunInit, TCCallback) ->
%% call user callback function if defined
NewConf1 = user_callback(TCCallback, Mod, Func, init, NewConf),
%% save current state in controller loop
- group_leader() ! {set_curr_conf,{{Mod,Func},NewConf1}},
+ sync_send(group_leader(),set_curr_conf,{{Mod,Func},NewConf1},
+ 5000, fun() -> exit(no_answer_from_group_leader) end),
put(test_server_loc, {Mod,Func}),
%% execute the test case
{{T,Return},Loc} = {ts_tc(Mod, Func, [NewConf1]),get_loc()},
{EndConf,TSReturn,FWReturn} =
case Return of
{E,TCError} when E=='EXIT' ; E==failed ->
+ ModLoc = mod_loc(Loc),
fw_error_notify(Mod, Func, NewConf1,
- TCError, mod_loc(Loc)),
- {[{tc_status,{failed,TCError}}|NewConf1],
+ TCError, ModLoc),
+ {[{tc_status,{failed,TCError}},
+ {tc_fail_loc,ModLoc}|NewConf1],
Return,{error,TCError}};
SaveCfg={save_config,_} ->
{[{tc_status,ok},SaveCfg|NewConf1],Return,ok};
{skip_and_save,Why,SaveCfg} ->
Skip = {skip,Why},
- {[{tc_status,{skipped,Why}},{save_config,SaveCfg}|NewConf1],
+ {[{tc_status,{skipped,Why}},
+ {save_config,SaveCfg}|NewConf1],
Skip,Skip};
{skip,Why} ->
{[{tc_status,{skipped,Why}}|NewConf1],Return,Return};
_ ->
{[{tc_status,ok}|NewConf1],Return,ok}
end,
- %% clear current state in controller loop
- group_leader() ! {set_curr_conf,undefined},
%% call user callback function if defined
EndConf1 = user_callback(TCCallback, Mod, Func, 'end', EndConf),
+ %% update current state in controller loop
+ sync_send(group_leader(),set_curr_conf,EndConf1,
+ 5000, fun() -> exit(no_answer_from_group_leader) end),
{FWReturn1,TSReturn1,EndConf2} =
case end_per_testcase(Mod, Func, EndConf1) of
SaveCfg1={save_config,_} ->
{FWReturn,TSReturn,[SaveCfg1|lists:keydelete(save_config,1,
EndConf1)]};
- {fail,ReasonToFail} -> % user has failed the testcase
+ {fail,ReasonToFail} ->
+ %% user has failed the testcase
fw_error_notify(Mod, Func, EndConf1, ReasonToFail),
{{error,ReasonToFail},{failed,ReasonToFail},EndConf1};
- {failed,{_,end_per_testcase,_}} = Failure -> % unexpected termination
+ {failed,{_,end_per_testcase,_}} = Failure when FWReturn == ok ->
+ %% unexpected termination in end_per_testcase
+ %% report this as the result to the framework
{Failure,TSReturn,EndConf1};
_ ->
+ %% test case result should be reported to framework
+ %% no matter the status of end_per_testcase
{FWReturn,TSReturn,EndConf1}
end,
+ %% clear current state in controller loop
+ sync_send(group_leader(),set_curr_conf,undefined,
+ 5000, fun() -> exit(no_answer_from_group_leader) end),
put(test_server_init_or_end_conf,undefined),
- case do_end_tc_call(Mod, Func, {FWReturn1,[EndConf2]}, TSReturn1) of
+ case do_end_tc_call(Mod,Func, Loc,
+ {FWReturn1,[EndConf2]}, TSReturn1) of
{failed,Reason} = NewReturn ->
fw_error_notify(Mod,Func,EndConf2, Reason),
{{T,NewReturn},{Mod,Func},[]};
@@ -1193,18 +1248,43 @@ run_test_case_eval1(Mod, Func, Args, Name, RunInit, TCCallback) ->
%% call user callback function if defined
Return1 = user_callback(TCCallback, Mod, Func, 'end', Return),
{Return2,Opts} = process_return_val([Return1], Mod, Func,
- Args1, Loc, Return1),
+ Args1, {Mod,Func}, Return1),
{{T,Return2},Loc,Opts}
end.
-do_end_tc_call(M,F,Res,Return) ->
+do_end_tc_call(M,F, Loc, Res, Return) ->
+ FwMod = os:getenv("TEST_SERVER_FRAMEWORK"),
+ {Mod,Func} =
+ if FwMod == M ; FwMod == "undefined"; FwMod == false ->
+ {M,F};
+ is_list(Loc) and (length(Loc)>1) ->
+ %% If failure in other module (M) than suite, try locate
+ %% suite name in Loc list and call end_tc with Suite:TestCase
+ %% instead of M:F.
+ GetSuite = fun(S,TC) ->
+ case lists:reverse(atom_to_list(S)) of
+ [$E,$T,$I,$U,$S,$_|_] -> [{S,TC}];
+ _ -> []
+ end
+ end,
+ case lists:flatmap(fun({S,TC,_}) -> GetSuite(S,TC);
+ ({{S,TC},_}) -> GetSuite(S,TC);
+ ({S,TC}) -> GetSuite(S,TC);
+ (_) -> []
+ end, Loc) of
+ [] ->
+ {M,F};
+ [FoundSuite|_] ->
+ FoundSuite
+ end;
+ true ->
+ {M,F}
+ end,
+
Ref = make_ref(),
- case os:getenv("TEST_SERVER_FRAMEWORK") of
- FW when FW == "ct_framework";
- FW == "undefined";
- FW == false ->
+ if FwMod == "ct_framework" ; FwMod == "undefined"; FwMod == false ->
case test_server_sup:framework_call(
- end_tc, [?pl2a(M),F,Res, Return], ok) of
+ end_tc, [?pl2a(Mod),Func,Res, Return], ok) of
{fail,FWReason} ->
{failed,FWReason};
ok ->
@@ -1217,9 +1297,9 @@ do_end_tc_call(M,F,Res,Return) ->
NewReturn ->
NewReturn
end;
- Other ->
- case test_server_sup:framework_call(
- end_tc, [Other,F,Res], Ref) of
+ true ->
+ case test_server_sup:framework_call(FwMod, end_tc,
+ [?pl2a(Mod),Func,Res], Ref) of
{fail,FWReason} ->
{failed,FWReason};
_Else ->
@@ -1242,7 +1322,7 @@ process_return_val([Return], M,F,A, Loc, Final) when is_list(Return) ->
true -> % must be return value from end conf case
process_return_val1(Return, M,F,A, Loc, Final, []);
false -> % must be Config value from init conf case
- case do_end_tc_call(M,F,{ok,A}, Return) of
+ case do_end_tc_call(M, F, Loc, {ok,A}, Return) of
{failed, FWReason} = Failed ->
fw_error_notify(M,F,A, FWReason),
{Failed, []};
@@ -1259,8 +1339,9 @@ process_return_val1([Failed={E,TCError}|_], M,F,A=[Args], Loc, _, SaveOpts)
when E=='EXIT';
E==failed ->
fw_error_notify(M,F,A, TCError, mod_loc(Loc)),
- case do_end_tc_call(M,F,{{error,TCError},
- [[{tc_status,{failed,TCError}}|Args]]}, Failed) of
+ case do_end_tc_call(M,F, Loc, {{error,TCError},
+ [[{tc_status,{failed,TCError}}|Args]]},
+ Failed) of
{failed,FWReason} ->
{{failed,FWReason},SaveOpts};
NewReturn ->
@@ -1277,8 +1358,8 @@ process_return_val1([RetVal={Tag,_}|Opts], M,F,A, Loc, _, SaveOpts) when Tag==sk
process_return_val1(Opts, M,F,A, Loc, RetVal, SaveOpts);
process_return_val1([_|Opts], M,F,A, Loc, Final, SaveOpts) ->
process_return_val1(Opts, M,F,A, Loc, Final, SaveOpts);
-process_return_val1([], M,F,A, _Loc, Final, SaveOpts) ->
- case do_end_tc_call(M,F,{Final,A}, Final) of
+process_return_val1([], M,F,A, Loc, Final, SaveOpts) ->
+ case do_end_tc_call(M,F, Loc, {Final,A}, Final) of
{failed,FWReason} ->
{{failed,FWReason},SaveOpts};
NewReturn ->
@@ -1307,57 +1388,62 @@ init_per_testcase(Mod, Func, Args) ->
false -> code:load_file(Mod);
_ -> ok
end,
- %% init_per_testcase defined, returns new configuration
- case erlang:function_exported(Mod,init_per_testcase,2) of
+ case erlang:function_exported(Mod, init_per_testcase, 2) of
true ->
- case catch my_apply(Mod, init_per_testcase, [Func|Args]) of
- {'$test_server_ok',{Skip,Reason}} when Skip==skip;
- Skip==skipped ->
- {skip,Reason};
- {'$test_server_ok',Res={skip_and_save,_,_}} ->
- Res;
- {'$test_server_ok',NewConf} when is_list(NewConf) ->
- case lists:filter(fun(T) when is_tuple(T) -> false;
- (_) -> true end, NewConf) of
- [] ->
- {ok,NewConf};
- Bad ->
- group_leader() ! {printout,12,
- "ERROR! init_per_testcase has returned "
- "bad elements in Config: ~p\n",[Bad]},
- {skip,{failed,{Mod,init_per_testcase,bad_return}}}
- end;
- {'$test_server_ok',Res={fail,_Reason}} ->
- Res;
- {'$test_server_ok',_Other} ->
- group_leader() ! {printout,12,
- "ERROR! init_per_testcase did not return "
- "a Config list.\n",[]},
- {skip,{failed,{Mod,init_per_testcase,bad_return}}};
- {'EXIT',Reason} ->
- Line = get_loc(),
- FormattedLoc = test_server_sup:format_loc(mod_loc(Line)),
- group_leader() ! {printout,12,
- "ERROR! init_per_testcase crashed!\n"
- "\tLocation: ~s\n\tReason: ~p\n",
- [FormattedLoc,Reason]},
- {skip,{failed,{Mod,init_per_testcase,Reason}}};
- Other ->
- Line = get_loc(),
- FormattedLoc = test_server_sup:format_loc(mod_loc(Line)),
- group_leader() ! {printout,12,
- "ERROR! init_per_testcase thrown!\n"
- "\tLocation: ~s\n\tReason: ~p\n",
- [FormattedLoc, Other]},
- {skip,{failed,{Mod,init_per_testcase,Other}}}
- end;
+ do_init_per_testcase(Mod, [Func|Args]);
false ->
-%% Optional init_per_testcase not defined
-%% keep quiet.
+ %% Optional init_per_testcase is not defined -- keep quiet.
[Config] = Args,
{ok, Config}
end.
+do_init_per_testcase(Mod, Args) ->
+ try apply(Mod, init_per_testcase, Args) of
+ {Skip,Reason} when Skip =:= skip; Skip =:= skipped ->
+ {skip,Reason};
+ {skip_and_save,_,_}=Res ->
+ Res;
+ NewConf when is_list(NewConf) ->
+ case lists:filter(fun(T) when is_tuple(T) -> false;
+ (_) -> true end, NewConf) of
+ [] ->
+ {ok,NewConf};
+ Bad ->
+ group_leader() ! {printout,12,
+ "ERROR! init_per_testcase has returned "
+ "bad elements in Config: ~p\n",[Bad]},
+ {skip,{failed,{Mod,init_per_testcase,bad_return}}}
+ end;
+ {fail,_Reason}=Res ->
+ Res;
+ _Other ->
+ group_leader() ! {printout,12,
+ "ERROR! init_per_testcase did not return "
+ "a Config list.\n",[]},
+ {skip,{failed,{Mod,init_per_testcase,bad_return}}}
+ catch
+ throw:Other ->
+ set_loc(erlang:get_stacktrace()),
+ Line = get_loc(),
+ FormattedLoc = test_server_sup:format_loc(mod_loc(Line)),
+ group_leader() ! {printout,12,
+ "ERROR! init_per_testcase thrown!\n"
+ "\tLocation: ~s\n\tReason: ~p\n",
+ [FormattedLoc, Other]},
+ {skip,{failed,{Mod,init_per_testcase,Other}}};
+ _:Reason0 ->
+ Stk = erlang:get_stacktrace(),
+ Reason = {Reason0,Stk},
+ set_loc(Stk),
+ Line = get_loc(),
+ FormattedLoc = test_server_sup:format_loc(mod_loc(Line)),
+ group_leader() ! {printout,12,
+ "ERROR! init_per_testcase crashed!\n"
+ "\tLocation: ~s\n\tReason: ~p\n",
+ [FormattedLoc,Reason]},
+ {skip,{failed,{Mod,init_per_testcase,Reason}}}
+ end.
+
end_per_testcase(Mod, Func, Conf) ->
case erlang:function_exported(Mod,end_per_testcase,2) of
true ->
@@ -1375,57 +1461,87 @@ end_per_testcase(Mod, Func, Conf) ->
do_end_per_testcase(Mod,EndFunc,Func,Conf) ->
put(test_server_init_or_end_conf,{EndFunc,Func}),
put(test_server_loc, {Mod,{EndFunc,Func}}),
- case catch my_apply(Mod, EndFunc, [Func,Conf]) of
- {'$test_server_ok',SaveCfg={save_config,_}} ->
+ try Mod:EndFunc(Func, Conf) of
+ {save_config,_}=SaveCfg ->
SaveCfg;
- {'$test_server_ok',{fail,_}=Fail} ->
+ {fail,_}=Fail ->
Fail;
- {'$test_server_ok',_} ->
- ok;
- {'EXIT',Reason} = Why ->
- comment(io_lib:format("<font color=\"red\">"
- "WARNING: ~w crashed!"
- "</font>\n",[EndFunc])),
+ _ ->
+ ok
+ catch
+ throw:Other ->
+ Comment0 = case read_comment() of
+ "" -> "";
+ Cmt -> Cmt ++ "<br>"
+ end,
+ set_loc(erlang:get_stacktrace()),
+ comment(io_lib:format("~s<font color=\"red\">"
+ "WARNING: ~w thrown!"
+ "</font>\n",[Comment0,EndFunc])),
group_leader() ! {printout,12,
- "WARNING: ~w crashed!\n"
+ "WARNING: ~w thrown!\n"
"Reason: ~p\n"
"Line: ~s\n",
- [EndFunc, Reason,
+ [EndFunc, Other,
test_server_sup:format_loc(
mod_loc(get_loc()))]},
- {failed,{Mod,end_per_testcase,Why}};
- Other ->
- comment(io_lib:format("<font color=\"red\">"
- "WARNING: ~w thrown!"
- "</font>\n",[EndFunc])),
+ {failed,{Mod,end_per_testcase,Other}};
+ Class:Reason ->
+ Stk = erlang:get_stacktrace(),
+ set_loc(Stk),
+ Why = case Class of
+ exit -> {'EXIT',Reason};
+ error -> {'EXIT',{Reason,Stk}}
+ end,
+ Comment0 = case read_comment() of
+ "" -> "";
+ Cmt -> Cmt ++ "<br>"
+ end,
+ comment(io_lib:format("~s<font color=\"red\">"
+ "WARNING: ~w crashed!"
+ "</font>\n",[Comment0,EndFunc])),
group_leader() ! {printout,12,
- "WARNING: ~w thrown!\n"
+ "WARNING: ~w crashed!\n"
"Reason: ~p\n"
"Line: ~s\n",
- [EndFunc, Other,
+ [EndFunc, Reason,
test_server_sup:format_loc(
mod_loc(get_loc()))]},
- {failed,{Mod,end_per_testcase,Other}}
+ {failed,{Mod,end_per_testcase,Why}}
end.
get_loc() ->
- case catch test_server_line:get_lines() of
- [] ->
- get(test_server_loc);
- {'EXIT',_} ->
- get(test_server_loc);
- Loc ->
- Loc
- end.
+ get(test_server_loc).
get_loc(Pid) ->
- {dictionary,Dict} = process_info(Pid, dictionary),
- lists:foreach(fun({Key,Val}) -> put(Key,Val) end,Dict),
+ [{current_stacktrace,Stk0},{dictionary,Dict}] =
+ process_info(Pid, [current_stacktrace,dictionary]),
+ lists:foreach(fun({Key,Val}) -> put(Key, Val) end, Dict),
+ Stk = [rewrite_loc_item(Loc) || Loc <- Stk0],
+ put(test_server_loc, Stk),
get_loc().
-get_mf([{M,F,_}|_]) -> {M,F};
-get_mf([{M,F}|_]) -> {M,F};
-get_mf(_) -> {undefined,undefined}.
+%% find the latest known Suite:Testcase
+get_mf(MFs) ->
+ get_mf(MFs, {undefined,undefined}).
+
+get_mf([MF|MFs], Found) when is_tuple(MF) ->
+ ModFunc = {Mod,_} = case MF of
+ {M,F,_} -> {M,F};
+ MF -> MF
+ end,
+ case is_suite(Mod) of
+ true -> ModFunc;
+ false -> get_mf(MFs, ModFunc)
+ end;
+get_mf(_, Found) ->
+ Found.
+
+is_suite(Mod) ->
+ case lists:reverse(atom_to_list(Mod)) of
+ "ETIUS" ++ _ -> true;
+ _ -> false
+ end.
mod_loc(Loc) ->
%% handle diff line num versions
@@ -1498,16 +1614,22 @@ lookup_config(Key,Config) ->
%% timer:tc/3
ts_tc(M, F, A) ->
Before = erlang:now(),
- Val = (catch my_apply(M, F, A)),
+ Result = try
+ apply(M, F, A)
+ catch
+ Type:Reason ->
+ Stk = erlang:get_stacktrace(),
+ set_loc(Stk),
+ case Type of
+ throw ->
+ {failed,{thrown,Reason}};
+ error ->
+ {'EXIT',{Reason,Stk}};
+ exit ->
+ {'EXIT',Reason}
+ end
+ end,
After = erlang:now(),
- Result = case Val of
- {'$test_server_ok', R} ->
- R; % test case ok
- {'EXIT',_Reason} = R ->
- R; % test case crashed
- Other ->
- {failed, {thrown,Other}} % test case was thrown
- end,
Elapsed =
(element(1,After)*1000000000000
+element(2,After)*1000000+element(3,After)) -
@@ -1515,8 +1637,12 @@ ts_tc(M, F, A) ->
+element(2,Before)*1000000+element(3,Before)),
{Elapsed, Result}.
-my_apply(M, F, A) ->
- {'$test_server_ok',apply(M, F, A)}.
+set_loc(Stk) ->
+ Loc = [rewrite_loc_item(I) || {_,_,_,_}=I <- Stk],
+ put(test_server_loc, Loc).
+
+rewrite_loc_item({M,F,_,Loc}) ->
+ {M,F,proplists:get_value(line, Loc, 0)}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1679,7 +1805,16 @@ adjusted_sleep(MSecs) ->
%% to read when using this function, rather than exit directly.
fail(Reason) ->
comment(cast_to_list(Reason)),
- exit({suite_failed,Reason}).
+ try
+ exit({suite_failed,Reason})
+ catch
+ Class:R ->
+ case erlang:get_stacktrace() of
+ [{?MODULE,fail,1,_}|Stk] -> ok;
+ Stk -> ok
+ end,
+ erlang:raise(Class, R, Stk)
+ end.
cast_to_list(X) when is_list(X) -> X;
cast_to_list(X) when is_atom(X) -> atom_to_list(X);
@@ -1693,7 +1828,16 @@ cast_to_list(X) -> lists:flatten(io_lib:format("~p", [X])).
%% Immediately calls exit. Included because test suites are easier
%% to read when using this function, rather than exit directly.
fail() ->
- exit(suite_failed).
+ try
+ exit(suite_failed)
+ catch
+ Class:R ->
+ case erlang:get_stacktrace() of
+ [{?MODULE,fail,0,_}|Stk] -> ok;
+ Stk -> ok
+ end,
+ erlang:raise(Class, R, Stk)
+ end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% break(Comment) -> ok
@@ -1845,11 +1989,54 @@ time_ms({seconds,N}) -> seconds(N);
time_ms({Other,_N}) ->
format("=== ERROR: Invalid time specification: ~p. "
"Should be seconds, minutes, or hours.~n", [Other]),
- exit({invalid_time_spec,Other});
+ exit({invalid_time_format,Other});
time_ms(Ms) when is_integer(Ms) -> Ms;
time_ms(infinity) -> infinity;
-time_ms(Other) -> exit({invalid_time_spec,Other}).
+time_ms(Fun) when is_function(Fun) ->
+ time_ms_apply(Fun);
+time_ms({M,F,A}=MFA) when is_atom(M), is_atom(F), is_list(A) ->
+ time_ms_apply(MFA);
+time_ms(Other) -> exit({invalid_time_format,Other}).
+
+time_ms_apply(Func) ->
+ time_ms_apply(Func, [5000,30000,60000,infinity]).
+
+time_ms_apply(Func, TOs) ->
+ Apply = fun() ->
+ case Func of
+ {M,F,A} ->
+ exit({self(),apply(M, F, A)});
+ Fun ->
+ exit({self(),Fun()})
+ end
+ end,
+ Pid = spawn(Apply),
+ Ref = monitor(process, Pid),
+ time_ms_wait(Func, Pid, Ref, TOs).
+time_ms_wait(Func, Pid, Ref, [TO|TOs]) ->
+ receive
+ {'DOWN',Ref,process,Pid,{Pid,Result}} ->
+ time_ms_check(Result);
+ {'DOWN',Ref,process,Pid,Error} ->
+ exit({timetrap_error,Error})
+ after
+ TO ->
+ format("=== WARNING: No return from timetrap function ~p~n", [Func]),
+ time_ms_wait(Func, Pid, Ref, TOs)
+ end;
+%% this clause will never execute if 'infinity' is in TOs list, that's ok!
+time_ms_wait(Func, Pid, Ref, []) ->
+ demonitor(Ref),
+ exit(Pid, kill),
+ exit({timetrap_error,{no_return_from_timetrap_function,Func}}).
+
+time_ms_check(MFA = {M,F,A}) when is_atom(M), is_atom(F), is_list(A) ->
+ exit({invalid_time_format,MFA});
+time_ms_check(Fun) when is_function(Fun) ->
+ exit({invalid_time_format,Fun});
+time_ms_check(Other) ->
+ time_ms(Other).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% timetrap_cancel(Handle) -> ok
@@ -1897,6 +2084,19 @@ hours(N) -> trunc(N * 1000 * 60 * 60).
minutes(N) -> trunc(N * 1000 * 60).
seconds(N) -> trunc(N * 1000).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% sync_send(Pid,Tag,Msg,Timeout,DoAfter) -> Result
+%%
+sync_send(Pid,Tag,Msg,Timeout,DoAfter) ->
+ Pid ! {Tag,self(),Msg},
+ receive
+ {Pid,Tag,Result} ->
+ Result
+ after Timeout ->
+ DoAfter()
+ end.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% timecall(M,F,A) -> {Time,Val}
%% Time = float()
@@ -2283,6 +2483,21 @@ comment(String) ->
group_leader() ! {comment,String},
ok.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% read_comment() -> string()
+%%
+%% Read the current comment string stored in
+%% state during test case execution.
+read_comment() ->
+ MsgLooper = group_leader(),
+ MsgLooper ! {read_comment,self()},
+ receive
+ {MsgLooper,read_comment,Comment} ->
+ Comment
+ after
+ 5000 ->
+ ""
+ end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% os_type() -> OsType
diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl
index de9b962dfc..4fad86d16d 100644
--- a/lib/test_server/src/test_server_ctrl.erl
+++ b/lib/test_server/src/test_server_ctrl.erl
@@ -173,7 +173,7 @@
%%% TEST_SERVER INTERFACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-export([output/2, print/2, print/3, print_timestamp/2]).
-export([start_node/3, stop_node/1, wait_for_node/1, is_release_available/1]).
--export([format/1, format/2, format/3]).
+-export([format/1, format/2, format/3, to_string/1]).
-export([get_target_info/0]).
-export([get_hosts/0]).
-export([get_target_os_type/0]).
@@ -1297,6 +1297,7 @@ terminate(_Reason, State) ->
end,
kill_all_jobs(State#state.jobs),
test_server_node:stop(State#state.target_info),
+ test_server_h:restore(),
ok.
kill_all_jobs([{_Name,JobPid}|Jobs]) ->
@@ -1349,6 +1350,10 @@ init_tester(Mod, Func, Args, Dir, Name, {SumLev,MajLev,MinLev},
put(test_server_minor_level, MinLev),
put(test_server_random_seed, proplists:get_value(random_seed, ExtraTools)),
put(test_server_testcase_callback, TCCallback),
+ %% before first print, read and set logging options
+ LogOpts = test_server_sup:framework_call(get_logopts, [], []),
+ put(test_server_logopts, LogOpts),
+ put(test_server_log_nl, not lists:member(no_nl, LogOpts)),
StartedExtraTools = start_extra_tools(ExtraTools),
{TimeMy,Result} = ts_tc(Mod, Func, Args),
put(test_server_common_io_handler, undefined),
@@ -1664,6 +1669,11 @@ do_test_cases(TopCases, SkipCases,
Config, TimetrapData) when is_list(TopCases),
is_tuple(TimetrapData) ->
start_log_file(),
+ FwMod =
+ case os:getenv("TEST_SERVER_FRAMEWORK") of
+ FW when FW =:= false; FW =:= "undefined" -> ?MODULE;
+ FW -> list_to_atom(FW)
+ end,
case collect_all_cases(TopCases, SkipCases) of
{error,Why} ->
print(1, "Error starting: ~p", [Why]),
@@ -1676,11 +1686,11 @@ do_test_cases(TopCases, SkipCases,
put(test_server_cases, N),
put(test_server_case_num, 0),
TestSpec =
- add_init_and_end_per_suite(TestSpec0, undefined, undefined),
-
+ add_init_and_end_per_suite(TestSpec0, undefined, undefined, FwMod),
TI = get_target_info(),
- print(1, "Starting test~s", [print_if_known(N, {", ~w test cases",[N]},
- {" (with repeated test cases)",[]})]),
+ print(1, "Starting test~s",
+ [print_if_known(N, {", ~w test cases",[N]},
+ {" (with repeated test cases)",[]})]),
Test = get(test_server_name),
test_server_sup:framework_call(report, [tests_start,{Test,N}]),
@@ -1709,13 +1719,12 @@ do_test_cases(TopCases, SkipCases,
print(html, "<br>Used Erlang ~s in <tt>~s</tt>.\n",
[erlang:system_info(version), code:root_dir()]),
- case os:getenv("TEST_SERVER_FRAMEWORK") of
- FW when FW =:= false; FW =:= "undefined" ->
+ if FwMod == ?MODULE ->
print(html, "<p>Target:<br>\n"),
print_who(TI#target_info.host, TI#target_info.username),
print(html, "<br>Used Erlang ~s in <tt>~s</tt>.\n",
[TI#target_info.version, TI#target_info.root_dir]);
- _ ->
+ true ->
case test_server_sup:framework_call(target_info, []) of
TargetInfo when is_list(TargetInfo),
length(TargetInfo) > 0 ->
@@ -1884,11 +1893,12 @@ start_minor_log_file1(Mod, Func, LogDir, AbsName) ->
[]),
SrcListing = downcase(cast_to_list(Mod)) ++ ?src_listing_ext,
- case filelib:is_file(filename:join(LogDir, SrcListing)) of
- true ->
+ case {filelib:is_file(filename:join(LogDir, SrcListing)),
+ lists:member(no_src, get(test_server_logopts))} of
+ {true,false} ->
print(Lev, "<a href=\"~s#~s\">source code for ~p:~p/1</a>\n",
[SrcListing,Func,Mod,Func]);
- false -> ok
+ _ -> ok
end,
io:fwrite(Fd, "<pre>\n", []),
@@ -2005,54 +2015,69 @@ copy_html_file(Src, DestDir) ->
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% add_init_and_end_per_suite(TestSpec, Mod, Ref) -> NewTestSpec
+%% add_init_and_end_per_suite(TestSpec, Mod, Ref, FwMod) -> NewTestSpec
%%
%% Expands TestSpec with an initial init_per_suite, and a final
%% end_per_suite element, per each discovered suite in the list.
-add_init_and_end_per_suite([{make,_,_}=Case|Cases], LastMod, LastRef) ->
- [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef)];
-add_init_and_end_per_suite([{skip_case,{{Mod,all},_}}=Case|Cases], LastMod, LastRef)
- when Mod =/= LastMod ->
+add_init_and_end_per_suite([{make,_,_}=Case|Cases], LastMod, LastRef, FwMod) ->
+ [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef, FwMod)];
+add_init_and_end_per_suite([{skip_case,{{Mod,all},_}}=Case|Cases], LastMod,
+ LastRef, FwMod) when Mod =/= LastMod ->
{PreCases, NextMod, NextRef} =
do_add_end_per_suite_and_skip(LastMod, LastRef, Mod),
- PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef)];
-add_init_and_end_per_suite([{skip_case,{{Mod,_},_}}=Case|Cases], LastMod, LastRef)
- when Mod =/= LastMod ->
+ PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)];
+add_init_and_end_per_suite([{skip_case,{{Mod,_},_}}=Case|Cases], LastMod,
+ LastRef, FwMod) when Mod =/= LastMod ->
{PreCases, NextMod, NextRef} =
do_add_init_and_end_per_suite(LastMod, LastRef, Mod),
- PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef)];
-add_init_and_end_per_suite([{skip_case,{conf,_,{Mod,_},_}}=Case|Cases], LastMod, LastRef)
- when Mod =/= LastMod ->
+ PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)];
+add_init_and_end_per_suite([{skip_case,{conf,_,{Mod,_},_}}=Case|Cases], LastMod,
+ LastRef, FwMod) when Mod =/= LastMod ->
{PreCases, NextMod, NextRef} =
do_add_init_and_end_per_suite(LastMod, LastRef, Mod),
- PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef)];
-add_init_and_end_per_suite([{skip_case,_}=Case|Cases], LastMod, LastRef) ->
- [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef)];
-add_init_and_end_per_suite([{conf,_,_,{Mod,_}}=Case|Cases], LastMod, LastRef)
- when Mod =/= LastMod ->
+ PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)];
+add_init_and_end_per_suite([{skip_case,_}=Case|Cases], LastMod, LastRef, FwMod) ->
+ [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef, FwMod)];
+add_init_and_end_per_suite([{conf,Ref,Props,{FwMod,Func}}=Case|Cases], LastMod,
+ LastRef, FwMod) ->
+ %% if Mod == FwMod, this conf test is (probably) a test case group where
+ %% the init- and end-functions are missing in the suite, and if so,
+ %% the suite name should be stored as {suite,Suite} in Props
+ case proplists:get_value(suite, Props) of
+ Suite when Suite =/= undefined, Suite =/= LastMod ->
+ {PreCases, NextMod, NextRef} =
+ do_add_init_and_end_per_suite(LastMod, LastRef, Suite),
+ Case1 = {conf,Ref,proplists:delete(suite,Props),{FwMod,Func}},
+ PreCases ++ [Case1|add_init_and_end_per_suite(Cases, NextMod,
+ NextRef, FwMod)];
+ _ ->
+ [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef, FwMod)]
+ end;
+add_init_and_end_per_suite([{conf,_,_,{Mod,_}}=Case|Cases], LastMod,
+ LastRef, FwMod) when Mod =/= LastMod, Mod =/= FwMod ->
{PreCases, NextMod, NextRef} =
do_add_init_and_end_per_suite(LastMod, LastRef, Mod),
- PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef)];
-add_init_and_end_per_suite([{conf,_,_,_}=Case|Cases], LastMod, LastRef) ->
- [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef)];
-add_init_and_end_per_suite([{Mod,_}=Case|Cases], LastMod, LastRef)
- when Mod =/= LastMod ->
+ PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)];
+add_init_and_end_per_suite([{conf,_,_,_}=Case|Cases], LastMod, LastRef, FwMod) ->
+ [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef, FwMod)];
+add_init_and_end_per_suite([{Mod,_}=Case|Cases], LastMod, LastRef, FwMod)
+ when Mod =/= LastMod, Mod =/= FwMod ->
{PreCases, NextMod, NextRef} =
do_add_init_and_end_per_suite(LastMod, LastRef, Mod),
- PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef)];
-add_init_and_end_per_suite([{Mod,_,_}=Case|Cases], LastMod, LastRef)
- when Mod =/= LastMod ->
+ PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)];
+add_init_and_end_per_suite([{Mod,_,_}=Case|Cases], LastMod, LastRef, FwMod)
+ when Mod =/= LastMod, Mod =/= FwMod ->
{PreCases, NextMod, NextRef} =
do_add_init_and_end_per_suite(LastMod, LastRef, Mod),
- PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef)];
-add_init_and_end_per_suite([Case|Cases], LastMod, LastRef)->
- [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef)];
-add_init_and_end_per_suite([], _LastMod, undefined) ->
+ PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)];
+add_init_and_end_per_suite([Case|Cases], LastMod, LastRef, FwMod)->
+ [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef, FwMod)];
+add_init_and_end_per_suite([], _LastMod, undefined, _FwMod) ->
[];
-add_init_and_end_per_suite([], _LastMod, skipped_suite) ->
+add_init_and_end_per_suite([], _LastMod, skipped_suite, _FwMod) ->
[];
-add_init_and_end_per_suite([], LastMod, LastRef) ->
+add_init_and_end_per_suite([], LastMod, LastRef, _FwMod) ->
[{conf,LastRef,[],{LastMod,end_per_suite}}].
do_add_init_and_end_per_suite(LastMod, LastRef, Mod) ->
@@ -2101,7 +2126,12 @@ run_test_cases(TestSpec, Config, TimetrapData) ->
maybe_open_job_sock(),
- html_convert_modules(TestSpec, Config),
+ case lists:member(no_src, get(test_server_logopts)) of
+ true ->
+ ok;
+ false ->
+ html_convert_modules(TestSpec, Config)
+ end,
run_test_cases_loop(TestSpec, [Config], TimetrapData, [], []),
@@ -2310,7 +2340,8 @@ run_test_cases_loop([{auto_skip_case,{Type,Ref,Case,Comment},SkipMode}|Cases],
handle_test_case_io_and_status(),
set_io_buffering(undefined),
{Mod,Func} = skip_case(auto, Ref, 0, Case, Comment, false, SkipMode),
- test_server_sup:framework_call(report, [tc_auto_skip,{?pl2a(Mod),Func,Comment}]),
+ test_server_sup:framework_call(report, [tc_auto_skip,
+ {?pl2a(Mod),Func,Comment}]),
run_test_cases_loop(Cases, Config, TimetrapData, ParentMode,
delete_status(Ref, Status));
_ ->
@@ -2318,7 +2349,8 @@ run_test_cases_loop([{auto_skip_case,{Type,Ref,Case,Comment},SkipMode}|Cases],
%% parallel group (io buffering is active)
wait_for_cases(Ref),
{Mod,Func} = skip_case(auto, Ref, 0, Case, Comment, true, SkipMode),
- test_server_sup:framework_call(report, [tc_auto_skip,{?pl2a(Mod),Func,Comment}]),
+ test_server_sup:framework_call(report, [tc_auto_skip,
+ {?pl2a(Mod),Func,Comment}]),
case CurrIOHandler of
{Ref,_} ->
%% current_io_handler was set by start conf of this
@@ -3959,8 +3991,11 @@ progress(ok, _CaseNum, Mod, Func, _Loc, RetVal, Time,
case RetVal of
{comment,RetComment} ->
String = to_string(RetComment),
+ HtmlCmt = test_server_sup:framework_call(format_comment,
+ [String],
+ String),
print(major, "=result ok: ~s", [String]),
- "<td>" ++ String ++ "</td>";
+ "<td>" ++ HtmlCmt ++ "</td>";
_ ->
print(major, "=result ok", []),
case Comment0 of
@@ -4345,14 +4380,18 @@ output_to_fd(Fd, [$=|Msg], internal) ->
io:put_chars(Fd, [$=]),
io:put_chars(Fd, Msg),
io:put_chars(Fd, "\n");
+
output_to_fd(Fd, Msg, internal) ->
io:put_chars(Fd, [$=,$=,$=,$ ]),
io:put_chars(Fd, Msg),
io:put_chars(Fd, "\n");
+
output_to_fd(Fd, Msg, _Sender) ->
io:put_chars(Fd, Msg),
- io:put_chars(Fd, "\n").
-
+ case get(test_server_log_nl) of
+ false -> ok;
+ _ -> io:put_chars(Fd, "\n")
+ end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% timestamp_filename_get(Leader) -> string()
@@ -4665,7 +4704,7 @@ collect_case_invoke(Mod, Case, MFA, St) ->
collect_subcases(Mod, Case, MFA, St, Suite)
end;
_ ->
- Suite = test_server_sup:framework_call(get_suite, [?pl2a(Mod),Case],[]),
+ Suite = test_server_sup:framework_call(get_suite, [?pl2a(Mod),Case], []),
collect_subcases(Mod, Case, MFA, St, Suite)
end.
@@ -4674,13 +4713,13 @@ collect_subcases(Mod, Case, MFA, St, Suite) ->
[] when Case == all -> {ok,[],St};
[] when element(1, Case) == conf -> {ok,[],St};
[] -> {ok,[MFA],St};
-%%%! --- START Kept for backwards compatibilty ---
+%%%! --- START Kept for backwards compatibility ---
%%%! Requirements are not used
{req,ReqList} ->
collect_case_deny(Mod, Case, MFA, ReqList, [], St);
{req,ReqList,SubCases} ->
collect_case_deny(Mod, Case, MFA, ReqList, SubCases, St);
-%%%! --- END Kept for backwards compatibilty ---
+%%%! --- END Kept for backwards compatibility ---
{Skip,Reason} when Skip==skip; Skip==skipped ->
{ok,[{skip_case,{MFA,Reason}}],St};
{error,Reason} ->
diff --git a/lib/test_server/src/test_server_line.erl b/lib/test_server/src/test_server_line.erl
deleted file mode 100644
index 848a9c23dd..0000000000
--- a/lib/test_server/src/test_server_line.erl
+++ /dev/null
@@ -1,387 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
--module(test_server_line).
-
-%% User interface
--export([get_lines/0]).
--export([clear/0]).
-
-%% Parse transform functions
--export([parse_transform/2]).
--export(['$test_server_line'/3]).
--export(['$test_server_lineQ'/3]).
--export([trace_line/3]).
-
--define(TEST_SERVER_LINE_SIZE, 10).
-%-define(STORAGE_FUNCTION, '$test_server_line').
--define(STORAGE_FUNCTION, '$test_server_lineQ').
-
--include("test_server.hrl").
-
--record(vars, {module, % atom() Module name
- function, % atom() Function name
- arity, % int() Function arity
- lines, % [int()] seen lines
- is_guard=false, % boolean()
- no_lines=[], % [{atom(),integer()}]
- % Functions to exclude
- line_trace=false
- }).
-
-
-
-
-%% Process dictionary littering variant
-%%
-
-'$test_server_line'(Mod, Func, Line) ->
- {Prev,Next} =
- case get('$test_server_line') of
- I when is_integer(I) ->
- if 1 =< I, I < ?TEST_SERVER_LINE_SIZE -> {I,I+1};
- true -> {?TEST_SERVER_LINE_SIZE,1}
- end;
- _ -> {?TEST_SERVER_LINE_SIZE,1}
- end,
- PrevTag = {'$test_server_line',Prev},
- case get(PrevTag) of
- {Mod,Func,_} -> put(PrevTag, {Mod,Func,Line});
- _ ->
- put({'$test_server_line',Next}, {Mod,Func,Line}),
- put('$test_server_line', Next)
- end, ok.
-
-test_server_line_get() ->
- case get('$test_server_line') of
- I when is_integer(I), 1 =< I, I =< ?TEST_SERVER_LINE_SIZE ->
- test_server_line_get_1(?TEST_SERVER_LINE_SIZE, I, []);
- _ -> []
- end.
-
-test_server_line_get_1(0, _I, R) ->
- R;
-test_server_line_get_1(Cnt, I, R) ->
- J = if I < ?TEST_SERVER_LINE_SIZE -> I+1;
- true -> 1 end,
- case get({'$test_server_line',J}) of
- undefined ->
- %% Less than ?TEST_SERVER_LINE_SIZE number of lines stored
- %% Start from line 1 and stop at actutual number of lines
- case get({'$test_server_line',1}) of
- undefined -> R; % no lines at all stored
- E -> test_server_line_get_1(I-1,1,[E|R])
- end;
- E ->
- test_server_line_get_1(Cnt-1, J, [E|R])
- end.
-
-test_server_line_clear() ->
- Is = lists:seq(1,?TEST_SERVER_LINE_SIZE),
- lists:foreach(fun (I) -> erase({'$test_server_line',I}) end, Is),
- erase('$test_server_line'),
- ok.
-
-
-%% Queue variant, uses just one process dictionary entry
-%%
-
-'$test_server_lineQ'(Mod, Func, Line) ->
- case get('$test_server_lineQ') of
- {I,Q} when is_integer(I), 1 =< I, I =< ?TEST_SERVER_LINE_SIZE ->
- case queue:head(Q) of
- {Mod,Func,_} ->
- %% Replace queue head
- put('$test_server_lineQ',
- {I,queue:cons({Mod,Func,Line}, queue:tail(Q))});
- _ when I < ?TEST_SERVER_LINE_SIZE ->
- put('$test_server_lineQ',
- {I+1,queue:cons({Mod,Func,Line}, Q)});
- _ ->
- %% Waste last in queue
- put('$test_server_lineQ',
- {I,queue:cons({Mod,Func,Line}, queue:lait(Q))})
- end;
- _ ->
- Q = queue:new(),
- put('$test_server_lineQ', {1,queue:cons({Mod,Func,Line}, Q)})
- end, ok.
-
-%test_server_lineQ_get() ->
-% case get('$test_server_lineQ') of
-% {I,Q} when integer(I), 1 =< I, I =< ?TEST_SERVER_LINE_SIZE ->
-% queue:to_list(Q);
-% _ -> []
-% end.
-
-test_server_lineQ_clear() ->
- erase('$test_server_lineQ'),
- ok.
-
-
-%% Get line - check if queue or dictionary is used, then get the lines
-%%
-
-get_lines() ->
- case get('$test_server_lineQ') of
- {I,Q} when is_integer(I), 1 =< I, I =< ?TEST_SERVER_LINE_SIZE ->
- queue:to_list(Q);
- _ ->
- test_server_line_get()
- end.
-
-%% Clear all dictionary entries
-%%
-clear() ->
- test_server_line_clear(),
- test_server_lineQ_clear().
-
-
-trace_line(Mod,Func,Line) ->
- io:format(lists:concat([Mod,":",Func,",",integer_to_list(Line),": ~p"]),
- [erlang:now()]).
-
-
-%%%=================================================================
-%%%========= **** PARSE TRANSFORM **** ========================
-%%%=================================================================
-parse_transform(Forms, _Options) ->
- transform(Forms, _Options).
-
-%% forms(Fs) -> lists:map(fun (F) -> form(F) end, Fs).
-
-transform(Forms, _Options)->
- Vars0 = #vars{},
- {ok, MungedForms, _Vars} = transform(Forms, [], Vars0),
- MungedForms.
-
-
-transform([Form|Forms], MungedForms, Vars) ->
- case munge(Form, Vars) of
- ignore ->
- transform(Forms, MungedForms, Vars);
- {MungedForm, Vars2} ->
- transform(Forms, [MungedForm|MungedForms], Vars2)
- end;
-transform([], MungedForms, Vars) ->
- {ok, lists:reverse(MungedForms), Vars}.
-
-%% This code traverses the abstract code, stored as the abstract_code
-%% chunk in the BEAM file, as described in absform(3) for Erlang/OTP R8B
-%% (Vsn=abstract_v2).
-%% The abstract format after preprocessing differs slightly from the abstract
-%% format given eg using epp:parse_form, this has been noted in comments.
-munge(Form={attribute,_,module,Module}, Vars) ->
- Vars2 = Vars#vars{module=Module},
- {Form, Vars2};
-
-munge(Form={attribute,_,no_lines,Funcs}, Vars) ->
- Vars2 = Vars#vars{no_lines=Funcs},
- {Form, Vars2};
-
-munge(Form={attribute,_,line_trace,_}, Vars) ->
- Vars2 = Vars#vars{line_trace=true},
- {Form, Vars2};
-
-munge({function,0,module_info,_Arity,_Clauses}, _Vars) ->
- ignore; % module_info will be added again when the forms are recompiled
-munge(Form = {function,Line,Function,Arity,Clauses}, Vars) ->
- case lists:member({Function,Arity},Vars#vars.no_lines) of
- true ->
- %% Line numbers in this function shall not be stored
- {Form,Vars};
- false ->
- Vars2 = Vars#vars{function=Function,
- arity=Arity,
- lines=[]},
- {MungedClauses, Vars3} = munge_clauses(Clauses, Vars2, []),
- {{function,Line,Function,Arity,MungedClauses}, Vars3}
- end;
-munge(Form, Vars) -> % attributes
- {Form, Vars}.
-
-munge_clauses([{clause,Line,Pattern,Guards,Body}|Clauses], Vars, MClauses) ->
- {MungedGuards, _Vars} = munge_exprs(Guards, Vars#vars{is_guard=true},[]),
- {MungedBody, Vars2} = munge_body(Body, Vars, []),
- munge_clauses(Clauses, Vars2,
- [{clause,Line,Pattern,MungedGuards,MungedBody}|
- MClauses]);
-munge_clauses([], Vars, MungedClauses) ->
- {lists:reverse(MungedClauses), Vars}.
-
-munge_body([Expr|Body], Vars, MungedBody) ->
- %% Here is the place to add a call to storage function!
- Line = element(2, Expr),
- Lines = Vars#vars.lines,
- case lists:member(Line,Lines) of
- true -> % already a bump at this line!
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- munge_body(Body, Vars2, [MungedExpr|MungedBody]);
- false ->
- Bump = {call, 0, {remote,0,
- {atom,0,?MODULE},
- {atom,0,?STORAGE_FUNCTION}},
- [{atom,0,Vars#vars.module},
- {atom, 0, Vars#vars.function},
- {integer, 0, Line}]},
- Lines2 = [Line|Lines],
-
- {MungedExpr, Vars2} = munge_expr(Expr, Vars#vars{lines=Lines2}),
- MungedBody2 =
- if Vars#vars.line_trace ->
- LineTrace = {call, 0, {remote,0,
- {atom,0,?MODULE},
- {atom,0,trace_line}},
- [{atom,0,Vars#vars.module},
- {atom, 0, Vars#vars.function},
- {integer, 0, Line}]},
- [MungedExpr,LineTrace,Bump|MungedBody];
- true ->
- [MungedExpr,Bump|MungedBody]
- end,
- munge_body(Body, Vars2, MungedBody2)
- end;
-munge_body([], Vars, MungedBody) ->
- {lists:reverse(MungedBody), Vars}.
-
-munge_expr({match,Line,ExprL,ExprR}, Vars) ->
- {MungedExprL, Vars2} = munge_expr(ExprL, Vars),
- {MungedExprR, Vars3} = munge_expr(ExprR, Vars2),
- {{match,Line,MungedExprL,MungedExprR}, Vars3};
-munge_expr({tuple,Line,Exprs}, Vars) ->
- {MungedExprs, Vars2} = munge_exprs(Exprs, Vars, []),
- {{tuple,Line,MungedExprs}, Vars2};
-munge_expr({record,Line,Expr,Exprs}, Vars) ->
- %% Only for Vsn=raw_abstract_v1
- {MungedExprName, Vars2} = munge_expr(Expr, Vars),
- {MungedExprFields, Vars3} = munge_exprs(Exprs, Vars2, []),
- {{record,Line,MungedExprName,MungedExprFields}, Vars3};
-munge_expr({record_field,Line,ExprL,ExprR}, Vars) ->
- %% Only for Vsn=raw_abstract_v1
- {MungedExprL, Vars2} = munge_expr(ExprL, Vars),
- {MungedExprR, Vars3} = munge_expr(ExprR, Vars2),
- {{record_field,Line,MungedExprL,MungedExprR}, Vars3};
-munge_expr({cons,Line,ExprH,ExprT}, Vars) ->
- {MungedExprH, Vars2} = munge_expr(ExprH, Vars),
- {MungedExprT, Vars3} = munge_expr(ExprT, Vars2),
- {{cons,Line,MungedExprH,MungedExprT}, Vars3};
-munge_expr({op,Line,Op,ExprL,ExprR}, Vars) ->
- {MungedExprL, Vars2} = munge_expr(ExprL, Vars),
- {MungedExprR, Vars3} = munge_expr(ExprR, Vars2),
- {{op,Line,Op,MungedExprL,MungedExprR}, Vars3};
-munge_expr({op,Line,Op,Expr}, Vars) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- {{op,Line,Op,MungedExpr}, Vars2};
-munge_expr({'catch',Line,Expr}, Vars) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- {{'catch',Line,MungedExpr}, Vars2};
-munge_expr({call,Line1,{remote,Line2,ExprM,ExprF},Exprs},
- Vars) when Vars#vars.is_guard==false->
- {MungedExprM, Vars2} = munge_expr(ExprM, Vars),
- {MungedExprF, Vars3} = munge_expr(ExprF, Vars2),
- {MungedExprs, Vars4} = munge_exprs(Exprs, Vars3, []),
- {{call,Line1,{remote,Line2,MungedExprM,MungedExprF},MungedExprs}, Vars4};
-munge_expr({call,Line1,{remote,_Line2,_ExprM,ExprF},Exprs},
- Vars) when Vars#vars.is_guard==true ->
- %% Difference in abstract format after preprocessing: BIF calls in guards
- %% are translated to {remote,...} (which is not allowed as source form)
- %% NOT NECESSARY FOR Vsn=raw_abstract_v1
- munge_expr({call,Line1,ExprF,Exprs}, Vars);
-munge_expr({call,Line,Expr,Exprs}, Vars) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- {MungedExprs, Vars3} = munge_exprs(Exprs, Vars2, []),
- {{call,Line,MungedExpr,MungedExprs}, Vars3};
-munge_expr({lc,Line,Expr,LC}, Vars) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- {MungedLC, Vars3} = munge_lc(LC, Vars2, []),
- {{lc,Line,MungedExpr,MungedLC}, Vars3};
-munge_expr({block,Line,Body}, Vars) ->
- {MungedBody, Vars2} = munge_body(Body, Vars, []),
- {{block,Line,MungedBody}, Vars2};
-munge_expr({'if',Line,Clauses}, Vars) ->
- {MungedClauses,Vars2} = munge_clauses(Clauses, Vars, []),
- {{'if',Line,MungedClauses}, Vars2};
-munge_expr({'case',Line,Expr,Clauses}, Vars) ->
- {MungedExpr,Vars2} = munge_expr(Expr,Vars),
- {MungedClauses,Vars3} = munge_clauses(Clauses, Vars2, []),
- {{'case',Line,MungedExpr,MungedClauses}, Vars3};
-munge_expr({'receive',Line,Clauses}, Vars) ->
- {MungedClauses,Vars2} = munge_clauses(Clauses, Vars, []),
- {{'receive',Line,MungedClauses}, Vars2};
-munge_expr({'receive',Line,Clauses,Expr,Body}, Vars) ->
- {MungedClauses,Vars2} = munge_clauses(Clauses, Vars, []),
- {MungedExpr, Vars3} = munge_expr(Expr, Vars2),
- {MungedBody, Vars4} = munge_body(Body, Vars3, []),
- {{'receive',Line,MungedClauses,MungedExpr,MungedBody}, Vars4};
-munge_expr({'try',Line,Exprs,Clauses,CatchClauses,After}, Vars) ->
- {MungedExprs, Vars1} = munge_exprs(Exprs, Vars, []),
- {MungedClauses, Vars2} = munge_clauses(Clauses, Vars1, []),
- {MungedCatchClauses, Vars3} = munge_clauses(CatchClauses, Vars2, []),
- {MungedAfter, Vars4} = munge_body(After, Vars3, []),
- {{'try',Line,MungedExprs,MungedClauses,MungedCatchClauses,MungedAfter},
- Vars4};
-%% Difference in abstract format after preprocessing: Funs get an extra
-%% element Extra.
-%% NOT NECESSARY FOR Vsn=raw_abstract_v1
-munge_expr({'fun',Line,{function,Name,Arity},_Extra}, Vars) ->
- {{'fun',Line,{function,Name,Arity}}, Vars};
-munge_expr({'fun',Line,{clauses,Clauses},_Extra}, Vars) ->
- {MungedClauses,Vars2}=munge_clauses(Clauses, Vars, []),
- {{'fun',Line,{clauses,MungedClauses}}, Vars2};
-munge_expr({'fun',Line,{clauses,Clauses}}, Vars) ->
- %% Only for Vsn=raw_abstract_v1
- {MungedClauses,Vars2}=munge_clauses(Clauses, Vars, []),
- {{'fun',Line,{clauses,MungedClauses}}, Vars2};
-munge_expr({bc,Line,Expr,LC}, Vars) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- {MungedLC, Vars3} = munge_lc(LC, Vars2, []),
- {{bc,Line,MungedExpr,MungedLC}, Vars3};
-munge_expr(Form, Vars) -> % var|char|integer|float|string|atom|nil|bin|eof
- {Form, Vars}.
-
-munge_exprs([Expr|Exprs], Vars, MungedExprs) when Vars#vars.is_guard==true,
- is_list(Expr) ->
- {MungedExpr, _Vars} = munge_exprs(Expr, Vars, []),
- munge_exprs(Exprs, Vars, [MungedExpr|MungedExprs]);
-munge_exprs([Expr|Exprs], Vars, MungedExprs) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- munge_exprs(Exprs, Vars2, [MungedExpr|MungedExprs]);
-munge_exprs([], Vars, MungedExprs) ->
- {lists:reverse(MungedExprs), Vars}.
-
-munge_lc([{generate,Line,Pattern,Expr}|LC], Vars, MungedLC) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- munge_lc(LC, Vars2, [{generate,Line,Pattern,MungedExpr}|MungedLC]);
-munge_lc([{b_generate,Line,Pattern,Expr}|LC], Vars, MungedLC) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- munge_lc(LC, Vars2, [{b_generate,Line,Pattern,MungedExpr}|MungedLC]);
-munge_lc([Expr|LC], Vars, MungedLC) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- munge_lc(LC, Vars2, [MungedExpr|MungedLC]);
-munge_lc([], Vars, MungedLC) ->
- {lists:reverse(MungedLC), Vars}.
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/test_server/src/test_server_sup.erl b/lib/test_server/src/test_server_sup.erl
index 53dfb45e3a..875f45eea6 100644
--- a/lib/test_server/src/test_server_sup.erl
+++ b/lib/test_server/src/test_server_sup.erl
@@ -26,7 +26,7 @@
cleanup_crash_dumps/0, crash_dump_dir/0, tar_crash_dumps/0,
get_username/0, get_os_family/0,
hostatom/0, hostatom/1, hoststr/0, hoststr/1,
- framework_call/2,framework_call/3,
+ framework_call/2,framework_call/3,framework_call/4,
format_loc/1, package_str/1, package_atom/1,
call_trace/1]).
-include("test_server_internal.hrl").
@@ -51,18 +51,19 @@ timetrap(Timeout0, Scale, Pid) ->
Timeout = if not Scale -> Timeout0;
true -> test_server:timetrap_scale_factor() * Timeout0
end,
+ TruncTO = trunc(Timeout),
receive
- after trunc(Timeout) ->
- Line = test_server:get_loc(Pid),
+ after TruncTO ->
+ MFLs = test_server:get_loc(Pid),
Mon = erlang:monitor(process, Pid),
Trap =
case get(test_server_init_or_end_conf) of
undefined ->
- {timetrap_timeout,trunc(Timeout),Line};
+ {timetrap_timeout,TruncTO,MFLs};
InitOrEnd ->
- {timetrap_timeout,trunc(Timeout),Line,InitOrEnd}
+ {timetrap_timeout,TruncTO,MFLs,InitOrEnd}
end,
- exit(Pid,Trap),
+ exit(Pid, Trap),
receive
{'DOWN', Mon, process, Pid, _} ->
ok
@@ -540,8 +541,9 @@ format_loc({Mod,Func}) when is_atom(Func) ->
format_loc({Mod,Line}) when is_integer(Line) ->
%% ?line macro is used
ModStr = package_str(Mod),
- case lists:reverse(ModStr) of
- [$E,$T,$I,$U,$S,$_|_] ->
+ case {lists:member(no_src, get(test_server_logopts)),
+ lists:reverse(ModStr)} of
+ {false,[$E,$T,$I,$U,$S,$_|_]} ->
io_lib:format("{~s,<a href=\"~s~s#~w\">~w</a>}",
[ModStr,downcase(ModStr),?src_listing_ext,
round_to_10(Line),Line]);
@@ -557,8 +559,9 @@ format_loc1([{Mod,Func,Line}|Rest]) ->
[" ",format_loc1({Mod,Func,Line}),",\n"|format_loc1(Rest)];
format_loc1({Mod,Func,Line}) ->
ModStr = package_str(Mod),
- case lists:reverse(ModStr) of
- [$E,$T,$I,$U,$S,$_|_] ->
+ case {lists:member(no_src, get(test_server_logopts)),
+ lists:reverse(ModStr)} of
+ {false,[$E,$T,$I,$U,$S,$_|_]} ->
io_lib:format("{~s,~w,<a href=\"~s~s#~w\">~w</a>}",
[ModStr,Func,downcase(ModStr),?src_listing_ext,
round_to_10(Line),Line]);
diff --git a/lib/test_server/src/ts.config b/lib/test_server/src/ts.config
index f021f5958b..cf3d269616 100644
--- a/lib/test_server/src/ts.config
+++ b/lib/test_server/src/ts.config
@@ -12,7 +12,7 @@
% "10.10.0.1", %IP string
% {10,10,0,1}, %IP tuple
% ["my_ip4_host"], %Any aliases
-% "::ffff:10.10.0.1", %IPv6 string (compatibilty addr)
+% "::ffff:10.10.0.1", %IPv6 string (compatibility addr)
% {0,0,0,0,0,65535,2570,1} %IPv6 tuple
% }}.
diff --git a/lib/test_server/src/ts_erl_config.erl b/lib/test_server/src/ts_erl_config.erl
index 640c8ddc9f..3b41f90d55 100644
--- a/lib/test_server/src/ts_erl_config.erl
+++ b/lib/test_server/src/ts_erl_config.erl
@@ -222,7 +222,6 @@ erl_interface(Vars,OsType) ->
end,
CrossCompile = case OsType of
vxworks -> "true";
- ose -> "true";
_ -> "false"
end,
[{erl_interface_libpath, filename:nativename(LibPath)},
@@ -329,8 +328,6 @@ sock_libraries({win32, _}) ->
sock_libraries({unix, _}) ->
""; % Included in general libraries if needed.
sock_libraries(vxworks) ->
- "";
-sock_libraries(ose) ->
"".
link_library(LibName,{win32, _}) ->
@@ -339,8 +336,6 @@ link_library(LibName,{unix, _}) ->
"lib" ++ LibName ++ ".a";
link_library(LibName,vxworks) ->
"lib" ++ LibName ++ ".a";
-link_library(_LibName,ose) ->
- "";
link_library(_LibName,_Other) ->
exit({link_library, not_supported}).
diff --git a/lib/test_server/src/ts_install_cth.erl b/lib/test_server/src/ts_install_cth.erl
index c5444a342f..a41916fd0a 100644
--- a/lib/test_server/src/ts_install_cth.erl
+++ b/lib/test_server/src/ts_install_cth.erl
@@ -49,8 +49,7 @@
-include_lib("kernel/include/file.hrl").
--type proplist() :: list({atom(),term()}).
--type config() :: proplist().
+-type config() :: proplists:proplist().
-type reason() :: term().
-type skip_or_fail() :: {skip, reason()} |
{auto_skip, reason()} |
@@ -65,19 +64,19 @@ id(_Opts) ->
?MODULE.
%% @doc Always called before any other callback function.
--spec init(Id :: term(), Opts :: proplist()) ->
- State :: #state{}.
+-spec init(Id :: term(), Opts :: proplists:proplist()) ->
+ {ok, State :: #state{}}.
init(_Id, Opts) ->
Nodenames = proplists:get_value(nodenames, Opts, 0),
Nodes = proplists:get_value(nodes, Opts, 0),
TSConfDir = proplists:get_value(ts_conf_dir, Opts),
TargetSystem = proplists:get_value(target_system, Opts, install_local),
InstallOpts = proplists:get_value(install_opts, Opts, []),
- #state{ nodenames = Nodenames,
- nodes = Nodes,
- ts_conf_dir = TSConfDir,
- target_system = TargetSystem,
- install_opts = InstallOpts }.
+ {ok, #state{ nodenames = Nodenames,
+ nodes = Nodes,
+ ts_conf_dir = TSConfDir,
+ target_system = TargetSystem,
+ install_opts = InstallOpts } }.
%% @doc Called before init_per_suite is called.
-spec pre_init_per_suite(Suite :: atom(),
diff --git a/lib/test_server/test/Makefile b/lib/test_server/test/Makefile
index ab72a9d579..198440bb17 100644
--- a/lib/test_server/test/Makefile
+++ b/lib/test_server/test/Makefile
@@ -85,7 +85,7 @@ release_spec: opt
release_tests_spec: make_emakefile
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(EMAKEFILE) $(ERL_FILES) $(COVERFILE) $(RELSYSDIR)
- $(INSTALL_DATA) test_server.spec test_server.cover $(RELSYSDIR)
+ $(INSTALL_DATA) test_server_test_lib.hrl test_server.spec test_server.cover $(RELSYSDIR)
chmod -R u+w $(RELSYSDIR)
@tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
diff --git a/lib/test_server/test/test_server_SUITE.erl b/lib/test_server/test/test_server_SUITE.erl
index 4c344717f0..a8532b08ab 100644
--- a/lib/test_server/test/test_server_SUITE.erl
+++ b/lib/test_server/test/test_server_SUITE.erl
@@ -119,6 +119,11 @@ test_server_conf02_SUITE(Config) ->
run_test_server_tests(SuiteName, NCases, NFail, NExpected, NSucc,
NUsrSkip, NAutoSkip,
NActualSkip, NActualFail, NActualSucc, Config) ->
+
+ ct:log("See test case log files under:~n~p~n",
+ [filename:join([proplists:get_value(priv_dir, Config),
+ SuiteName++".logs"])]),
+
Node = proplists:get_value(node, Config),
{ok,_Pid} = rpc:call(Node,test_server_ctrl, start, []),
rpc:call(Node,
@@ -132,6 +137,7 @@ run_test_server_tests(SuiteName, NCases, NFail, NExpected, NSucc,
end),
rpc:call(Node,test_server_ctrl, stop, []),
+
{ok,#suite{ n_cases = NCases,
n_cases_failed = NFail,
n_cases_expected = NExpected,
diff --git a/lib/test_server/vsn.mk b/lib/test_server/vsn.mk
index 1dd4a84ce9..563c1b6db6 100644
--- a/lib/test_server/vsn.mk
+++ b/lib/test_server/vsn.mk
@@ -1,2 +1,2 @@
-TEST_SERVER_VSN = 3.4.4
+TEST_SERVER_VSN = 3.4.5
diff --git a/lib/toolbar/doc/src/make.dep b/lib/toolbar/doc/src/make.dep
deleted file mode 100644
index d93ff2a315..0000000000
--- a/lib/toolbar/doc/src/make.dep
+++ /dev/null
@@ -1,26 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex part.tex ref_man.tex toolbar.tex \
- toolbar_chapter.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: bar.ps create_tool.ps
-
diff --git a/lib/toolbar/doc/src/notes.xml b/lib/toolbar/doc/src/notes.xml
index e2a3c22684..ffca2c5fbf 100644
--- a/lib/toolbar/doc/src/notes.xml
+++ b/lib/toolbar/doc/src/notes.xml
@@ -31,6 +31,22 @@
<p>This document describes the changes made to the Toolbar
application.</p>
+<section><title>Toolbar 1.4.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improve spelling throughout documentation, code comments
+ and error messages</p>
+ <p>
+ Own Id: OTP-9555</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Toolbar 1.4.1</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/toolbar/src/toolbar_toolconfig.erl b/lib/toolbar/src/toolbar_toolconfig.erl
index 7d8f2b4d21..6dccb7ba72 100644
--- a/lib/toolbar/src/toolbar_toolconfig.erl
+++ b/lib/toolbar/src/toolbar_toolconfig.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -126,7 +126,7 @@ loop(S,Window) ->
show_info(Window,Info),
move_focus(Window,file);
- %% Erronous version number -- Notify user
+ %% Erroneous version number -- Notify user
{error,version} ->
Win = Window#tfwindow.window,
tool_utils:notify(Win,[FileName,
@@ -136,7 +136,7 @@ loop(S,Window) ->
_Error ->
Win = Window#tfwindow.window,
tool_utils:notify(Win,[FileName,
- "File is on erronous format"])
+ "File is in erroneous format"])
end;
%% The file can not be read, show default values
diff --git a/lib/toolbar/vsn.mk b/lib/toolbar/vsn.mk
index 47d18e29f0..105303d785 100644
--- a/lib/toolbar/vsn.mk
+++ b/lib/toolbar/vsn.mk
@@ -1,4 +1,4 @@
-TOOLBAR_VSN = 1.4.1
+TOOLBAR_VSN = 1.4.2
diff --git a/lib/tools/c_src/Makefile.in b/lib/tools/c_src/Makefile.in
index 65a7f5f424..6921193154 100644
--- a/lib/tools/c_src/Makefile.in
+++ b/lib/tools/c_src/Makefile.in
@@ -142,7 +142,9 @@ EMEM_OBJS = $(addprefix $(EMEM_OBJ_DIR)/,$(notdir $(EMEM_SRCS:.c=.o)))
# Misc targets
#
-all: $(CREATE_DIRS) erts_lib $(PROGS) $(DRIVERS)
+_create_dirs := $(shell mkdir -p $(CREATE_DIRS))
+
+all: erts_lib $(PROGS) $(DRIVERS)
erts_lib:
cd $(ERL_TOP)/erts/lib_src && $(MAKE) $(TYPE)
@@ -158,13 +160,6 @@ clean:
.PHONY: all erts_lib docs clean
#
-# Make dir targets
-#
-
-$(CREATE_DIRS):
- $(MKDIR) -p $@
-
-#
# Object targets
#
diff --git a/lib/tools/doc/src/eprof.xml b/lib/tools/doc/src/eprof.xml
index 6d68c90768..1dbc41ec8e 100644
--- a/lib/tools/doc/src/eprof.xml
+++ b/lib/tools/doc/src/eprof.xml
@@ -147,7 +147,7 @@
</type>
<desc>
<p>This function ensures that the results displayed by
- <c>analyse/0</c> and <c>total_analyse/0</c> are printed both to
+ <c>analyze/0,1,2</c> are printed both to
the file <c>File</c> and the screen.</p>
</desc>
</func>
diff --git a/lib/tools/doc/src/instrument.xml b/lib/tools/doc/src/instrument.xml
index 12877994de..b7e48ea306 100644
--- a/lib/tools/doc/src/instrument.xml
+++ b/lib/tools/doc/src/instrument.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1998</year><year>2009</year>
+ <year>1998</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -342,7 +342,7 @@
<p>Stores the current memory allocation map on the file
<c>File</c>. Returns <c>true</c> if the emulator has been
started with the "<c>+Mim true</c>" command-line argument, and
- the map was successfuly stored; otherwise, <c>false</c>. The
+ the map was successfully stored; otherwise, <c>false</c>. The
contents of the file can later be read using
<seealso marker="#read_memory_data/1">read_memory_data/1</seealso>.
<em>NOTE:</em><c>store_memory_data/0</c> blocks execution of
@@ -360,7 +360,7 @@
<p>Stores the current memory status on the file
<c>File</c>. Returns <c>true</c> if the emulator has been
started with the "<c>+Mis true</c>", or "<c>+Mim true</c>"
- command-line arguments, and the data was successfuly stored;
+ command-line arguments, and the data was successfully stored;
otherwise, <c>false</c>. The contents of the file can later be
read using
<seealso marker="#read_memory_status/1">read_memory_status/1</seealso>.</p>
diff --git a/lib/tools/doc/src/make.dep b/lib/tools/doc/src/make.dep
deleted file mode 100644
index 11fa090d6f..0000000000
--- a/lib/tools/doc/src/make.dep
+++ /dev/null
@@ -1,33 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex cover.tex cover_chapter.tex cprof.tex \
- cprof_chapter.tex eprof.tex erlang_mode.tex \
- erlang_mode_chapter.tex fprof.tex fprof_chapter.tex \
- instrument.tex make.tex part.tex ref_man.tex \
- tags.tex xref.tex xref_chapter.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-cprof.tex: ../../../../system/doc/definitions/term.defs
-
-xref.tex: ../../../../system/doc/definitions/term.defs
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: venn1.ps venn2.ps
-
diff --git a/lib/tools/doc/src/notes.xml b/lib/tools/doc/src/notes.xml
index 02d92fc4e7..17506fb6e2 100644
--- a/lib/tools/doc/src/notes.xml
+++ b/lib/tools/doc/src/notes.xml
@@ -30,6 +30,44 @@
</header>
<p>This document describes the changes made to the Tools application.</p>
+<section><title>Tools 2.6.6.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Teach the emacs mode to compile yecc and leex files</p>
+ <p>
+ If visiting a .yrl or .xrl file in emacs with
+ erlang-mode, then the `erlang-compile' function (normally
+ bound to C-c C-k), now knows how to compile yecc and leex
+ files, and then, if that compilation succeeds, also
+ compiles the resulting .erl files.</p>
+ <p>
+ Also introduce a `erlang-compile-command-function-alist'
+ to make it possible to hook in other functions for
+ computing compilation commands/expressions, depending on
+ file name. (Thanks to Tomas Abrahamsson )</p>
+ <p>
+ Own Id: OTP-9503</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Bugs in xref(3) have been fixed. (Thanks to Matthias
+ Lang.) </p>
+ <p>
+ Own Id: OTP-9416</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Tools 2.6.6.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/tools/doc/src/xref.xml b/lib/tools/doc/src/xref.xml
index 75ffa25311..17de66bb22 100644
--- a/lib/tools/doc/src/xref.xml
+++ b/lib/tools/doc/src/xref.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2000</year><year>2010</year>
+ <year>2000</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -1465,8 +1465,8 @@ Evaluates a predefined analysis.
<name>start(NameOrOptions) -> Return</name>
<fsummary>Create an Xref server.</fsummary>
<type>
- <v>Name = atom()()</v>
- <v>XrefOrOptions = Xref | Options</v>
+ <v>NameOrOptions = Name | Options</v>
+ <v>Name = atom()</v>
<v>Options = [Option] | Option</v>
<v>Option = {xref_mode, mode()} | term()</v>
<v>Return = {ok, pid()} | {error, {already_started, pid()}}</v>
@@ -1483,7 +1483,7 @@ Evaluates a predefined analysis.
<name>start(Name, Options) -> Return</name>
<fsummary>Create an Xref server.</fsummary>
<type>
- <v>Name = atom()()</v>
+ <v>Name = atom()</v>
<v>Options = [Option] | Option</v>
<v>Option = {xref_mode, mode()} | term()</v>
<v>Return = {ok, pid()} | {error, {already_started, pid()}}</v>
diff --git a/lib/tools/emacs/erlang.el b/lib/tools/emacs/erlang.el
index 6728bef2a4..bc7a190fb4 100644
--- a/lib/tools/emacs/erlang.el
+++ b/lib/tools/emacs/erlang.el
@@ -523,6 +523,32 @@ This is an elisp list of options. Each option can be either:
- a string
Example: '(bin_opt_info (i . \"/path1/include\") (i . \"/path2/include\"))")
+(defvar erlang-compile-command-function-alist
+ '((".erl\\'" . inferior-erlang-compute-erl-compile-command)
+ (".xrl\\'" . inferior-erlang-compute-leex-compile-command)
+ (".yrl\\'" . inferior-erlang-compute-yecc-compile-command)
+ ("." . inferior-erlang-compute-erl-compile-command))
+ "*Alist of filename patterns vs corresponding compilation functions.
+Each element looks like (REGEXP . FUNCTION). Compiling a file whose name
+matches REGEXP specifies FUNCTION to use to compute the compilation
+command. The FUNCTION will be called with two arguments: module name and
+default compilation options, like output directory. The FUNCTION
+is expected to return a string.")
+
+(defvar erlang-leex-compile-opts '()
+ "*Options to pass to leex when compiling xrl files.
+This is an elisp list of options. Each option can be either:
+- an atom
+- a dotted pair
+- a string")
+
+(defvar erlang-yecc-compile-opts '()
+ "*Options to pass to yecc when compiling yrl files.
+This is an elisp list of options. Each option can be either:
+- an atom
+- a dotted pair
+- a string")
+
(eval-and-compile
(defvar erlang-regexp-modern-p
(if (> erlang-emacs-major-version 21) t nil)
@@ -1199,7 +1225,7 @@ Lock syntax table. The effect is that `apply' in the atom
`( (char-after (1- (or ,pos (point)))))))
;; defvar some obsolete variables, which we still support for
-;; backwardscompatibility reasons.
+;; backwards compatibility reasons.
(eval-when-compile
(defvar comment-indent-hook)
(defvar dabbrev-case-fold-search)
@@ -5276,6 +5302,22 @@ unless the optional NO-DISPLAY is non-nil."
(file-name-as-directory buffer-dir))))
(defun inferior-erlang-compute-compile-command (module-name opts)
+ (let ((ccfn erlang-compile-command-function-alist)
+ (res (inferior-erlang-compute-erl-compile-command module-name opts))
+ ccfn-entry
+ done)
+ (if (not (null (buffer-file-name)))
+ (while (and (not done) (not (null ccfn)))
+ (setq ccfn-entry (car ccfn))
+ (setq ccfn (cdr ccfn))
+ (if (string-match (car ccfn-entry) (buffer-file-name))
+ (let ((c-fn (cdr ccfn-entry)))
+ (setq done t)
+ (if (not (null c-fn))
+ (setq result (funcall c-fn module-name opts)))))))
+ result))
+
+(defun inferior-erlang-compute-erl-compile-command (module-name opts)
(let* ((out-dir-opt (assoc 'outdir opts))
(out-dir (cdr out-dir-opt)))
(if erlang-compile-use-outdir
@@ -5299,6 +5341,48 @@ unless the optional NO-DISPLAY is non-nil."
(remq out-dir-opt opts))
tmpvar tmpvar tmpvar2)))))
+(defun inferior-erlang-compute-leex-compile-command (module-name opts)
+ (let ((file-name (buffer-file-name))
+ (erl-compile-expr (inferior-erlang-remove-any-trailing-dot
+ (inferior-erlang-compute-erl-compile-command
+ module-name opts))))
+ (format (concat "f(LErr1__), f(LErr2__), "
+ "case case leex:file(\"%s\", [%s]) of"
+ " ok -> ok;"
+ " {ok,_} -> ok;"
+ " {ok,_,_} -> ok;"
+ " LErr1__ -> LErr1__ "
+ "end of"
+ " ok -> %s;"
+ " LErr2__ -> LErr2__ "
+ "end.")
+ file-name
+ (inferior-erlang-format-comma-opts erlang-leex-compile-opts)
+ erl-compile-expr)))
+
+(defun inferior-erlang-compute-yecc-compile-command (module-name opts)
+ (let ((file-name (buffer-file-name))
+ (erl-compile-expr (inferior-erlang-remove-any-trailing-dot
+ (inferior-erlang-compute-erl-compile-command
+ module-name opts))))
+ (format (concat "f(YErr1__), f(YErr2__), "
+ "case case yecc:file(\"%s\", [%s]) of"
+ " {ok,_} -> ok;"
+ " {ok,_,_} -> ok;"
+ " YErr1__ -> YErr1__ "
+ "end of"
+ " ok -> %s;"
+ " YErr2__ -> YErr2__ "
+ "end.")
+ file-name
+ (inferior-erlang-format-comma-opts erlang-yecc-compile-opts)
+ erl-compile-expr)))
+
+(defun inferior-erlang-remove-any-trailing-dot (str)
+ (if (string= (substring str -1) ".")
+ (substring str 0 (1- (length str)))
+ str))
+
(defun inferior-erlang-format-comma-opts (opts)
(if (null opts)
""
diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl
index 905ad895c9..e21bd1b88c 100644
--- a/lib/tools/src/cover.erl
+++ b/lib/tools/src/cover.erl
@@ -55,14 +55,14 @@
%% compiled module. This is necessary so that the code can be loaded
%% on remote nodes that are started after the compilation.
%%
-%% PARELLALISM
+%% PARALLELISM
%% To take advantage of SMP when doing the cover analysis both the data
%% collection and analysis has been parallelized. One process is spawned for
%% each node when collecting data, and on the remote node when collecting data
%% one process is spawned per module.
%%
%% When analyzing data it is possible to issue multiple analyse(_to_file)/X
-%% calls at once. They are however all calls (for backwardscompatability
+%% calls at once. They are however all calls (for backwards compatibility
%% reasons) so the user of cover will have to spawn several processes to to the
%% calls ( or use async_analyse_to_file ).
%%
@@ -522,7 +522,7 @@ call(Request) ->
{?SERVER,Reply} ->
Reply
end,
- erlang:demonitor(Ref),
+ erlang:demonitor(Ref, [flush]),
Return
end.
@@ -545,7 +545,7 @@ remote_call(Node,Request) ->
{?SERVER,Reply} ->
Reply
end,
- erlang:demonitor(Ref),
+ erlang:demonitor(Ref, [flush]),
Return
end.
diff --git a/lib/tools/src/xref_reader.erl b/lib/tools/src/xref_reader.erl
index d22f0df164..92f0c45c7b 100644
--- a/lib/tools/src/xref_reader.erl
+++ b/lib/tools/src/xref_reader.erl
@@ -158,15 +158,20 @@ expr({'try',_Line,Es,Scs,Ccs,As}, S) ->
S2 = clauses(Scs, S1),
S3 = clauses(Ccs, S2),
expr(As, S3);
-expr({call, Line,
- {remote, _, {atom,_,erlang}, {atom,_,make_fun}},
- [{atom,_,Mod}, {atom,_,Fun}, {integer,_,Arity}]}, S) ->
- %% Added in R10B-6. M:F/A.
- expr({'fun', Line, {function, Mod, Fun, Arity}}, S);
-expr({'fun', Line, {function, Mod, Name, Arity}}, S) ->
- %% Added in R10B-6. M:F/A.
+expr({'fun', Line, {function, {atom,_,Mod},
+ {atom,_,Name},
+ {integer,_,Arity}}}, S) ->
+ %% New format in R15. M:F/A (literals).
As = lists:duplicate(Arity, {atom, Line, foo}),
external_call(Mod, Name, As, Line, false, S);
+expr({'fun', Line, {function, Mod, Name, {integer,_,Arity}}}, S) ->
+ %% New format in R15. M:F/A (one or more variables).
+ As = lists:duplicate(Arity, {atom, Line, foo}),
+ external_call(erlang, apply, [Mod, Name, list2term(As)], Line, true, S);
+expr({'fun', Line, {function, Mod, Name, _Arity}}, S) ->
+ %% New format in R15. M:F/A (one or more variables).
+ As = {var, Line, '_'},
+ external_call(erlang, apply, [Mod, Name, As], Line, true, S);
expr({'fun', Line, {function, Name, Arity}, _Extra}, S) ->
%% Added in R8.
handle_call(local, S#xrefr.module, Name, Arity, Line, S);
@@ -286,10 +291,10 @@ check_funarg(W, ArgsList, Line, S) ->
expr(ArgsList, S1).
funarg({'fun', _, _Clauses, _Extra}, _S) -> true;
-funarg({var, _, Var}, S) -> member(Var, S#xrefr.funvars);
-funarg({call,_,{remote,_,{atom,_,erlang},{atom,_,make_fun}},_MFA}, _S) ->
- %% R10B-6. M:F/A.
+funarg({'fun', _, {function,_,_,_}}, _S) ->
+ %% New abstract format for fun M:F/A in R15.
true;
+funarg({var, _, Var}, S) -> member(Var, S#xrefr.funvars);
funarg(_, _S) -> false.
fun_args(apply2, [FunArg, Args]) -> {FunArg, Args};
diff --git a/lib/tools/test/cover_SUITE.erl b/lib/tools/test/cover_SUITE.erl
index fe7f92de78..881a3c2997 100644
--- a/lib/tools/test/cover_SUITE.erl
+++ b/lib/tools/test/cover_SUITE.erl
@@ -583,21 +583,14 @@ otp_6115_1(Config) ->
%% called -- running cover compiled code when there is no cover
%% server and thus no ets tables to bump counters in, makes no
%% sense.
- ?line Pid1 = f1:start_fail(),
-
- %% If f1 is cover compiled, a process P is started with a
- %% reference to the fun created in start_ok/0, and
- %% cover:stop() is called, then P should survive.
- %% This is because (the fun held by) P always references the current
- %% version of the module, and is thus not affected by the cover
- %% compiled version being unloaded.
- ?line Pid2 = f1:start_ok(),
+ Pid1 = f1:start_a(),
+ Pid2 = f1:start_b(),
%% Now stop cover
?line cover:stop(),
- %% Ensure that f1 is loaded (and not cover compiled), that Pid1
- %% is dead and Pid2 is alive, but with no reference to old code
+ %% Ensure that f1 is loaded (and not cover compiled), and that
+ %% both Pid1 and Pid2 are dead.
case code:which(f1) of
Beam when is_list(Beam) ->
ok;
@@ -608,19 +601,15 @@ otp_6115_1(Config) ->
undefined ->
ok;
_PI1 ->
- RefToOldP = erlang:check_process_code(Pid1, f1),
- ?line ?t:fail({"Pid1 still alive", RefToOldP})
+ RefToOldP1 = erlang:check_process_code(Pid1, f1),
+ ?t:fail({"Pid1 still alive", RefToOldP1})
end,
case process_info(Pid2) of
- PI2 when is_list(PI2) ->
- case erlang:check_process_code(Pid2, f2) of
- false ->
- ok;
- true ->
- ?line ?t:fail("Pid2 has ref to old code")
- end;
undefined ->
- ?line ?t:fail("Pid2 has died")
+ ok;
+ _PI2 ->
+ RefToOldP2 = erlang:check_process_code(Pid1, f2),
+ ?t:fail({"Pid2 still alive", RefToOldP2})
end,
?line file:set_cwd(CWD),
diff --git a/lib/tools/test/cover_SUITE_data/otp_6115/f1.erl b/lib/tools/test/cover_SUITE_data/otp_6115/f1.erl
index b659e5d818..5399b33f19 100644
--- a/lib/tools/test/cover_SUITE_data/otp_6115/f1.erl
+++ b/lib/tools/test/cover_SUITE_data/otp_6115/f1.erl
@@ -1,12 +1,13 @@
-module(f1).
--export([start_fail/0, start_ok/0]).
+-export([start_a/0, start_b/0]).
-start_fail() ->
+start_a() ->
f2:start(fun() ->
- io:format("this does not work\n",[])
+ ok
end).
-start_ok() ->
+start_b() ->
f2:start(fun fun1/0).
+
fun1() ->
- io:format("this works\n",[]).
+ ok.
diff --git a/lib/tools/test/eprof_SUITE_data/ed.script b/lib/tools/test/eprof_SUITE_data/ed.script
index 94531a9e98..fe1625bc50 100644
--- a/lib/tools/test/eprof_SUITE_data/ed.script
+++ b/lib/tools/test/eprof_SUITE_data/ed.script
@@ -1,5 +1,7 @@
H
r eed.erl
+1,$s/Created :/Skapad :/p
+/^cmd_line/,/^file/-1p
g/^[a-z][a-zA-Z_]*\(/i\
%%% -------------------------------------------------------------\
%%% A stupid function header.\
diff --git a/lib/tools/test/eprof_SUITE_data/eed.erl b/lib/tools/test/eprof_SUITE_data/eed.erl
index 0175abdd0e..520c5f3dd1 100644
--- a/lib/tools/test/eprof_SUITE_data/eed.erl
+++ b/lib/tools/test/eprof_SUITE_data/eed.erl
@@ -10,6 +10,8 @@
-export([edit/0, edit/1, file/1, cmd_line/1]).
+-compile({no_auto_import,[error/1]}).
+
-record(state, {dot = 0, % Line number of dot.
upto_dot = [], % Lines up to dot (reversed).
after_dot = [], % Lines after dot.
@@ -60,7 +62,7 @@ loop(St0) ->
ok;
{error, Reason} ->
loop(print_error(Reason, St1));
- St2 when record(St2, state) ->
+ St2 when is_record(St2, state) ->
loop(St2)
end.
@@ -68,7 +70,7 @@ command(Cmd, St) ->
case parse_command(Cmd, St) of
quit ->
quit;
- St1 when function(St1#state.print) ->
+ St1 when is_function(St1#state.print) ->
if
St1#state.dot /= 0 ->
print_current(St1);
@@ -76,7 +78,7 @@ command(Cmd, St) ->
ok
end,
St1#state{print=false};
- St1 when record(St1, state) ->
+ St1 when is_record(St1, state) ->
St1
end.
@@ -103,13 +105,13 @@ get_input([C|Rest], St, Result) ->
get_line1(Io, Prompt, Result) ->
get_line2(Io, io:get_line(Io, Prompt), Result).
-get_line2(Io, eof, []) ->
+get_line2(_Io, eof, []) ->
eof;
-get_line2(Io, eof, Result) ->
+get_line2(_Io, eof, Result) ->
lists:reverse(Result);
get_line2(Io, [$\\, $\n], Result) ->
get_line1(Io, '', [$\n|Result]);
-get_line2(Io, [$\n], Result) ->
+get_line2(_Io, [$\n], Result) ->
lists:reverse(Result, [$\n]);
get_line2(Io, [C|Rest], Result) ->
get_line2(Io, Rest, [C|Result]).
@@ -193,7 +195,7 @@ get_one1([$+|Rest], Sum, St) ->
get_one2({ok, 1, Rest}, 1, Sum, St);
get_one1([$-|Rest], Sum, St) ->
get_one2({ok, 1, Rest}, -1, Sum, St);
-get_one1(Cmd, false, St) ->
+get_one1(_Cmd, false, _St) ->
false;
get_one1(Cmd, Sum, St) ->
{ok, Sum, Cmd, St}.
@@ -222,13 +224,13 @@ get_address([$', Mark|Rest], St) when $a =< Mark, Mark =< $z ->
false ->
{ok, 0, Rest, St}
end;
-get_address([$'|Rest], State) ->
+get_address([$'|_Rest], _State) ->
error(bad_mark);
get_address([$/|Rest], State) ->
scan_forward($/, Rest, State);
-get_address([$?|Rest], State) ->
+get_address([$?|_Rest], _State) ->
error(not_implemented);
-get_address(Cmd, St) ->
+get_address(_Cmd, _St) ->
false.
scan_forward(End, Patt0, State) ->
@@ -238,8 +240,8 @@ scan_forward(End, Patt0, State) ->
scan_forward1(Dot+1, After, NewState, Rest).
scan_forward1(Linenum, [Line|Rest], State, RestCmd) ->
- case regexp:first_match(Line#line.contents, State#state.pattern) of
- {match, _, _} ->
+ case re:run(Line#line.contents, State#state.pattern, [{capture, none}]) of
+ match ->
{ok, Linenum, RestCmd, State};
nomatch ->
scan_forward1(Linenum+1, Rest, State, RestCmd)
@@ -254,13 +256,14 @@ scan_forward1(_, [], State, RestCmd) ->
Other
end.
-scan_forward2(0, [], State, RestCmd) ->
+scan_forward2(0, [], _State, _RestCmd) ->
false;
scan_forward2(Linenum, [Line|Rest], State, RestCmd) ->
case scan_forward2(Linenum-1, Rest, State, RestCmd) of
false ->
- case regexp:first_match(Line#line.contents, State#state.pattern) of
- {match, _, _} ->
+ case re:run(Line#line.contents, State#state.pattern,
+ [{capture, none}]) of
+ match ->
{ok, Linenum, RestCmd, State};
nomatch ->
false
@@ -296,7 +299,7 @@ parse_cmd_char($t, Cont) -> Cont(fun transpose_command/3, 2, dot);
parse_cmd_char($u, Cont) -> Cont(fun undo_command/3, 0, none);
parse_cmd_char($v, Cont) -> Cont(fun vglobal_command/3, 2, all);
parse_cmd_char($w, Cont) -> Cont(fun write_command/3, 2, all);
-parse_cmd_char(_, Cont) -> error(bad_command).
+parse_cmd_char(_, _Cont) -> error(bad_command).
execute_command(Fun, NumLines, Def, State, Nums, Rest) ->
Lines = check_lines(NumLines, Def, Nums, State),
@@ -380,7 +383,7 @@ change_command(Rest, Lines, St0) ->
%% (.,.)d - delete lines
-delete_command(Rest, [0, Last], St) ->
+delete_command(_Rest, [0, _Last], _St) ->
error(bad_linenum);
delete_command(Rest, [First, Last], St0) ->
St1 = check_trailing_p(Rest, save_for_undo(St0)),
@@ -396,7 +399,7 @@ delete(Left, St0) ->
%% e file - replace buffer with new file
-enter_command(Name, [], St) when St#state.modified == true ->
+enter_command(_Name, [], St) when St#state.modified == true ->
error(buffer_modified);
enter_command(Name, [], St0) ->
enter_always_command(Name, [], St0).
@@ -439,7 +442,7 @@ mark(Sense, [First, Last], St0) ->
St1 = move_to(Last, St0),
mark1(Sense, First-1, St1).
-mark1(Sense, First, St) when St#state.dot == First ->
+mark1(_Sense, First, St) when St#state.dot == First ->
St;
mark1(Sense, First, St) ->
[Line|Prev] = St#state.upto_dot,
@@ -507,16 +510,16 @@ help_always_command([], [], St) ->
%% (.)i - insert text
-insert_command(Rest, [0], State) ->
+insert_command(_Rest, [0], _State) ->
error(bad_linenum);
insert_command(Rest, [Line], State) ->
append_command(Rest, [Line-1], State).
%% (.)kx - mark line
-mark_command(_, [0], St) ->
+mark_command(_, [0], _St) ->
error(bad_linenum);
-mark_command([Mark|Rest], [Line], St) when $a =< Mark, Mark =< $z ->
+mark_command([Mark|_Rest], [_Line], _St) when $a =< Mark, Mark =< $z ->
error(not_implemented);
mark_command(_, _, _) ->
error(bad_mark).
@@ -528,12 +531,12 @@ list_command(Rest, Lines, St) ->
%% (.,.)m - move lines
-move_command(Cmd, [First, Last], St) ->
+move_command(_Cmd, [_First, _Last], _St) ->
error(not_implemented).
%% (.,.)t - copy lines
-transpose_command(Cmd, [First, Last], St) ->
+transpose_command(_Cmd, [_First, _Last], _St) ->
error(not_implemented).
%% (.,.)n - print lines with line numbers
@@ -604,39 +607,41 @@ read(After, Name, St0) ->
subst_command(_, [0, _], _) ->
error(bad_linenum);
-subst_command([$ |Cmd0], [First, Last], St0) ->
+subst_command([$ |_Cmd0], [_First, _Last], _St0) ->
error(bad_delimiter);
-subst_command([$\n|Cmd0], [First, Last], St0) ->
+subst_command([$\n|_Cmd0], [_First, _Last], _St0) ->
error(bad_delimiter);
subst_command([Sep|Cmd0], [First, Last], St0) ->
St1 = save_for_undo(St0),
{ok, Cmd1, St2} = get_pattern(Sep, Cmd0, St1),
{ok, Replacement, Cmd2} = get_replacement(Sep, Cmd1),
- {ok, Sub, Cmd3} = subst_check_gflag(Cmd2),
+ {ok, Opts, Cmd3} = subst_check_gflag(Cmd2),
St3 = check_trailing_p(Cmd3, St2),
- subst_command(Last-First+1, Sub, Replacement, move_to(First-1, St3), nomatch);
+ subst_command(Last-First+1, Opts, Replacement,
+ move_to(First-1, St3), nomatch);
subst_command([], _, _) ->
error(bad_delimiter).
subst_command(0, _, _, _, nomatch) ->
error(nomatch);
-subst_command(0, _, _, _, StLast) when record(StLast, state) ->
+subst_command(0, _, _, _, StLast) when is_record(StLast, state) ->
StLast;
-subst_command(Left, Sub, Repl, St0, LastMatch) ->
+subst_command(Left, Opts, Repl, St0, LastMatch) ->
St1 = next_line(St0),
[Line|_] = St1#state.upto_dot,
- case regexp:Sub(Line#line.contents, St1#state.pattern, Repl) of
- {ok, _, 0} ->
- subst_command(Left-1, Sub, Repl, St1, LastMatch);
- {ok, NewContents, _} ->
+ Contents = Line#line.contents,
+ case re:replace(Contents, St1#state.pattern, Repl, Opts) of
+ Contents ->
+ subst_command(Left-1, Opts, Repl, St1, LastMatch);
+ NewContents ->
%% XXX This doesn't work with marks.
St2 = delete_current_line(St1),
St3 = insert_line(NewContents, St2),
- subst_command(Left-1, Sub, Repl, St3, St3)
+ subst_command(Left-1, Opts, Repl, St3, St3)
end.
-subst_check_gflag([$g|Cmd]) -> {ok, gsub, Cmd};
-subst_check_gflag(Cmd) -> {ok, sub, Cmd}.
+subst_check_gflag([$g|Cmd]) -> {ok, [global,{return,list}], Cmd};
+subst_check_gflag(Cmd) -> {ok, [{return,list}], Cmd}.
%% u - undo
@@ -649,7 +654,7 @@ undo_command(_, _, _) ->
%% (1,$)w - write buffer to file
-write_command(Cmd, [First, Last], St) ->
+write_command(_Cmd, [_First, _Last], _St) ->
error(not_implemented).
@@ -721,7 +726,7 @@ get_pattern(End, Cmd, State) ->
get_pattern(End, [End|Rest], State, []) when State#state.pattern /= undefined ->
{ok, Rest, State};
get_pattern(End, [End|Rest], State, Result) ->
- case regexp:parse(lists:reverse(Result)) of
+ case re:compile(lists:reverse(Result)) of
{error, _} ->
error(bad_pattern);
{ok, Re} ->
@@ -754,7 +759,7 @@ check_trailing_p([$p], St) ->
St#state{print=fun(Line, _) -> io:put_chars(Line) end};
check_trailing_p([], State) ->
State;
-check_trailing_p(Other, State) ->
+check_trailing_p(_Other, _State) ->
error(garbage_after_command).
error(Reason) ->
@@ -765,9 +770,9 @@ match(State) when State#state.dot == 0 ->
match(State) ->
[Line|_] = State#state.upto_dot,
Re = State#state.pattern,
- case regexp:first_match(Line#line.contents, Re) of
- {match, _, _} -> true;
- nomatch -> false
+ case re:run(Line#line.contents, Re, [{capture, none}]) of
+ match -> true;
+ nomatch -> false
end.
skip_blanks([$ |Rest]) ->
diff --git a/lib/tools/test/xref_SUITE.erl b/lib/tools/test/xref_SUITE.erl
index 2f83ab4995..e0876381ca 100644
--- a/lib/tools/test/xref_SUITE.erl
+++ b/lib/tools/test/xref_SUITE.erl
@@ -46,7 +46,8 @@
-export([
add/1, default/1, info/1, lib/1, read/1, read2/1, remove/1,
replace/1, update/1, deprecated/1, trycatch/1,
- abstract_modules/1, fun_mfa/1, qlc/1]).
+ abstract_modules/1, fun_mfa/1, fun_mfa_r14/1,
+ fun_mfa_vars/1, qlc/1]).
-export([
analyze/1, basic/1, md/1, q/1, variables/1, unused_locals/1]).
@@ -82,7 +83,7 @@ groups() ->
{files, [],
[add, default, info, lib, read, read2, remove, replace,
update, deprecated, trycatch, abstract_modules, fun_mfa,
- qlc]},
+ fun_mfa_r14, fun_mfa_vars, qlc]},
{analyses, [],
[analyze, basic, md, q, variables, unused_locals]},
{misc, [], [format_error, otp_7423, otp_7831]}].
@@ -1771,6 +1772,88 @@ fun_mfa(Conf) when is_list(Conf) ->
?line ok = file:delete(Beam),
ok.
+%% Same as the previous test case, except that we use a BEAM file
+%% that was compiled by an R14 compiler to test backward compatibility.
+fun_mfa_r14(Conf) when is_list(Conf) ->
+ Dir = ?config(data_dir, Conf),
+ MFile = fname(Dir, "fun_mfa_r14"),
+
+ A = fun_mfa_r14,
+ {ok, _} = xref:start(s),
+ {ok, A} = xref:add_module(s, MFile, {warnings,false}),
+ {ok, [{{{A,t,0},{'$M_EXPR','$F_EXPR',0}},[7]},
+ {{{A,t,0},{A,t,0}},[6]},
+ {{{A,t1,0},{'$M_EXPR','$F_EXPR',0}},[11]},
+ {{{A,t1,0},{A,t,0}},[10]},
+ {{{A,t2,0},{A,t,0}},[14]},
+ {{{A,t3,0},{A,t3,0}},[17]}]} =
+ xref:q(s, "(Lin) E"),
+
+ ok = check_state(s),
+ xref:stop(s),
+
+ ok.
+
+%% fun M:F/A with varibles.
+fun_mfa_vars(Conf) when is_list(Conf) ->
+ Dir = ?copydir,
+ File = fname(Dir, "fun_mfa_vars.erl"),
+ MFile = fname(Dir, "fun_mfa_vars"),
+ Beam = fname(Dir, "fun_mfa_vars.beam"),
+ Test = <<"-module(fun_mfa_vars).
+
+ -export([t/1, t1/1, t2/3]).
+
+ t(Mod) ->
+ F = fun Mod:bar/2,
+ (F)(a, b).
+
+ t1(Name) ->
+ F = fun ?MODULE:Name/1,
+ (F)(a).
+
+ t2(Mod, Name, Arity) ->
+ F = fun Mod:Name/Arity,
+ (F)(a).
+
+ t3(Arity) ->
+ F = fun ?MODULE:t/Arity,
+ (F)(1, 2, 3).
+
+ t4(Mod, Name) ->
+ F = fun Mod:Name/3,
+ (F)(a, b, c).
+
+ t5(Mod, Arity) ->
+ F = fun Mod:t/Arity,
+ (F)().
+ ">>,
+
+ ok = file:write_file(File, Test),
+ A = fun_mfa_vars,
+ {ok, A} = compile:file(File, [report,debug_info,{outdir,Dir}]),
+ {ok, _} = xref:start(s),
+ {ok, A} = xref:add_module(s, MFile, {warnings,false}),
+ {ok, [{{{A,t,1},{'$M_EXPR','$F_EXPR',2}},[7]},
+ {{{A,t,1},{'$M_EXPR',bar,2}},[6]},
+ {{{A,t1,1},{'$M_EXPR','$F_EXPR',1}},[11]},
+ {{{A,t1,1},{A,'$F_EXPR',1}},[10]},
+ {{{A,t2,3},{'$M_EXPR','$F_EXPR',-1}},[14]},
+ {{{A,t2,3},{'$M_EXPR','$F_EXPR',1}},[15]},
+ {{{A,t3,1},{'$M_EXPR','$F_EXPR',3}},[19]},
+ {{{A,t3,1},{fun_mfa_vars,t,-1}},[18]},
+ {{{A,t4,2},{'$M_EXPR','$F_EXPR',3}},[22,23]},
+ {{{A,t5,2},{'$M_EXPR','$F_EXPR',0}},[27]},
+ {{{A,t5,2},{'$M_EXPR',t,-1}},[26]}]} =
+ xref:q(s, "(Lin) E"),
+
+ ok = check_state(s),
+ xref:stop(s),
+
+ ok = file:delete(File),
+ ok = file:delete(Beam),
+ ok.
+
qlc(suite) -> [];
qlc(doc) -> ["OTP-5195: A bug fix when using qlc:q/1,2."];
qlc(Conf) when is_list(Conf) ->
diff --git a/lib/tools/test/xref_SUITE_data/fun_mfa_r14.beam b/lib/tools/test/xref_SUITE_data/fun_mfa_r14.beam
new file mode 100644
index 0000000000..4645525690
--- /dev/null
+++ b/lib/tools/test/xref_SUITE_data/fun_mfa_r14.beam
Binary files differ
diff --git a/lib/tools/test/xref_SUITE_data/fun_mfa_r14.erl b/lib/tools/test/xref_SUITE_data/fun_mfa_r14.erl
new file mode 100644
index 0000000000..293bd83a8b
--- /dev/null
+++ b/lib/tools/test/xref_SUITE_data/fun_mfa_r14.erl
@@ -0,0 +1,18 @@
+-module(fun_mfa_r14).
+
+-export([t/0, t1/0, t2/0, t3/0]).
+
+t() ->
+ F = fun ?MODULE:t/0,
+ (F)().
+
+t1() ->
+ F = fun t/0,
+ (F)().
+
+t2() ->
+ fun ?MODULE:t/0().
+
+t3() ->
+ fun t3/0().
+
diff --git a/lib/tools/vsn.mk b/lib/tools/vsn.mk
index 6999c695e6..2d63a33554 100644
--- a/lib/tools/vsn.mk
+++ b/lib/tools/vsn.mk
@@ -1 +1 @@
-TOOLS_VSN = 2.6.6.4
+TOOLS_VSN = 2.6.6.5
diff --git a/lib/tv/doc/src/Makefile b/lib/tv/doc/src/Makefile
index f30e0307a9..5a41b28d48 100644
--- a/lib/tv/doc/src/Makefile
+++ b/lib/tv/doc/src/Makefile
@@ -26,14 +26,6 @@ VSN=$(TV_VSN)
APPLICATION=tv
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -89,32 +81,10 @@ EXTRA_FILES = \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = tv-$(VSN).pdf
-TOP_PS_FILE = tv-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -127,8 +97,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -144,31 +112,6 @@ clean clean_docs:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES) gifs
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ $(LATEX_CLEAN)
-endif
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -181,8 +124,6 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
$(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
$(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
@@ -193,29 +134,5 @@ release_docs_spec: docs
$(INSTALL_DIR) $(RELEASE_PATH)/man/man3
$(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-endif
-endif
-
-endif
-
release_spec:
diff --git a/lib/tv/doc/src/make.dep b/lib/tv/doc/src/make.dep
deleted file mode 100644
index 8437e320c6..0000000000
--- a/lib/tv/doc/src/make.dep
+++ /dev/null
@@ -1,32 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex part.tex ref_man.tex table_visualizer_chapter.tex \
- tv.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: info_window.ps set_poll_int.ps tv_create_table.ps \
- tv_record_editor_mnesia.ps tv_row_marked.ps \
- tv_row_marked_popup.ps tv_search_result.ps \
- tv_search_window.ps tv_start.ps tv_start_mnesia.ps \
- tv_start_other_node.ps tv_start_pid_sorted.ps \
- tv_start_system.ps tv_start_system_unreadable.ps \
- tv_table_browser.ps tv_table_browser_updated.ps
-
diff --git a/lib/tv/doc/src/notes.xml b/lib/tv/doc/src/notes.xml
index b3f2f5587f..77a6a43d51 100644
--- a/lib/tv/doc/src/notes.xml
+++ b/lib/tv/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/tv/src/tv_db_search.erl b/lib/tv/src/tv_db_search.erl
index edd3c188e2..7634bc63b6 100644
--- a/lib/tv/src/tv_db_search.erl
+++ b/lib/tv/src/tv_db_search.erl
@@ -244,10 +244,10 @@ get_entry_text() ->
string_to_regexp(Str) ->
- case regexp:parse(Str) of
+ case re:compile(Str) of
{ok, RegExp} ->
{ok, RegExp};
- _Error ->
+ {error, _Error} ->
case get(error_msg_mode) of
normal ->
{error, {not_a_regexp, "Please enter a regular expression!"}};
@@ -410,33 +410,11 @@ search_for_regexp(Pattern, Elem, ListAsStr) ->
lists:flatten(tv_io_lib:write(Elem))
end,
- case regexp:first_match(ListToSearch, Pattern) of
- {match, _, _} ->
+ case re:run(ListToSearch, Pattern, [{capture,none}]) of
+ match ->
found;
- _Other ->
+ nomatch ->
not_found
- %% The code below shall be used instead if it is desired to
- %% compare each *element* in the tuples to the regular expression,
- %% i.e., treat each element as a new line/string.
- %% The difference is most easily explained through an example:
- %% If we treat each tuple as a new line/string, the regular expression
- %% "^{win" will match the string "{win, 1, 2, 3}", but not the string
- %% "{1, {win,2}}".
- %% If we treat each element as a new line/string, the RE "^{win" will match
- %% both strings above.
-
- %% SearchList = tuple_to_list(Elem),
- %% case lists:dropwhile(
- %% fun(H) ->
- %% nomatch == regexp:first_match(lists:flatten(io_lib:write(H)),
- %% Pattern)
- %% end,
- %% SearchList) of
- %% [] ->
- %% not_found;
- %% _AnyList ->
- %% found
- %% end
end.
diff --git a/lib/tv/src/tv_main.erl b/lib/tv/src/tv_main.erl
index 2f743c2397..283ba4c967 100644
--- a/lib/tv/src/tv_main.erl
+++ b/lib/tv/src/tv_main.erl
@@ -312,7 +312,7 @@ analyze_error(Cause, Node, Table) ->
handle_error(mnesia_not_started, Node, Table);
{badrpc, {'EXIT', {aborted, {node_not_running,_ErrNode}}}} ->
handle_error(mnesia_not_started, Node, Table);
- {'EXIT', {undef, {mnesia,_Fcn,_Args}}} ->
+ {'EXIT', {undef, {mnesia,_Fcn,_Args,_}}} ->
handle_error(mnesia_not_started, Node, Table);
{'EXIT', Reason} ->
diff --git a/lib/tv/src/tv_mnesia_rpc.erl b/lib/tv/src/tv_mnesia_rpc.erl
index a2385714ec..4a75994145 100644
--- a/lib/tv/src/tv_mnesia_rpc.erl
+++ b/lib/tv/src/tv_mnesia_rpc.erl
@@ -87,6 +87,8 @@ chk(Result) ->
throw(mnesia_not_started);
{badrpc, _Reason} ->
throw(mnesia_not_started);
+ {'EXIT', {undef, {mnesia,_Fcn,_Args,_}}} ->
+ throw(mnesia_not_started);
{'EXIT', {undef, {mnesia,_Fcn,_Args}}} ->
throw(mnesia_not_started);
diff --git a/lib/typer/src/typer.erl b/lib/typer/src/typer.erl
index e40c4f39cd..f2a70f49b7 100644
--- a/lib/typer/src/typer.erl
+++ b/lib/typer/src/typer.erl
@@ -466,14 +466,20 @@ write_typed_file(File, Info) ->
case file:make_dir(TyperAnnDir) of
{error, Reason} ->
case Reason of
- eexist -> %% TypEr dir exists; remove old typer files
- ok = file:delete(NewFileName),
+ eexist -> %% TypEr dir exists; remove old typer files if they exist
+ case file:delete(NewFileName) of
+ ok -> ok;
+ {error, enoent} -> ok;
+ {error, _} ->
+ Msg = io_lib:format("Error in deleting file ~s\n", [NewFileName]),
+ fatal_error(Msg)
+ end,
write_typed_file(File, Info, NewFileName);
enospc ->
Msg = io_lib:format("Not enough space in ~p\n", [Dir]),
fatal_error(Msg);
eacces ->
- Msg = io:format("No write permission in ~p\n", [Dir]),
+ Msg = io_lib:format("No write permission in ~p\n", [Dir]),
fatal_error(Msg);
_ ->
Msg = io_lib:format("Unhandled error ~s when writing ~p\n",
@@ -539,7 +545,7 @@ get_type_string(F, A, Info, Mode) ->
case {Mode, Type} of
{file, {contract, _}} -> "";
_ ->
- Prefix = lists:concat(["-spec ", F]),
+ Prefix = lists:concat(["-spec ", erl_types:atom_to_string(F)]),
lists:concat([Prefix, TypeStr, "."])
end;
true ->
diff --git a/lib/typer/vsn.mk b/lib/typer/vsn.mk
index fe8faabdf8..9e73aed286 100644
--- a/lib/typer/vsn.mk
+++ b/lib/typer/vsn.mk
@@ -1 +1 @@
-TYPER_VSN = 0.9.1
+TYPER_VSN = 0.9.2
diff --git a/lib/webtool/doc/src/make.dep b/lib/webtool/doc/src/make.dep
deleted file mode 100644
index 87526b3f73..0000000000
--- a/lib/webtool/doc/src/make.dep
+++ /dev/null
@@ -1,20 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex part.tex ref_man.tex start_webtool.tex \
- webtool.tex webtool_chapter.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/webtool/doc/src/notes.xml b/lib/webtool/doc/src/notes.xml
index b7e6f0421c..c58a440937 100644
--- a/lib/webtool/doc/src/notes.xml
+++ b/lib/webtool/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,22 @@
<p>This document describes the changes made to the Webtool
application.</p>
+<section><title>WebTool 0.8.9</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Do not install *.bat files on non-win32 machines (Thanks
+ to Hans Ulrich Niedermann)</p>
+ <p>
+ Own Id: OTP-9515</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>WebTool 0.8.8</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/webtool/priv/Makefile b/lib/webtool/priv/Makefile
index 56ab772c45..6e1c6606fe 100644
--- a/lib/webtool/priv/Makefile
+++ b/lib/webtool/priv/Makefile
@@ -39,8 +39,12 @@ HTDOCS_FILES = root/doc/index.html \
root/doc/tool_management.html \
root/doc/start_info.html
-SCRIPTS = bin/start_webtool \
- bin/start_webtool.bat
+ifeq ($(findstring win32,$(TARGET)),win32)
+WIN32_SCRIPTS= bin/start_webtool.bat
+else
+WIN32_SCRIPTS=
+endif
+SCRIPTS = bin/start_webtool $(WIN32_SCRIPTS)
# ----------------------------------------------------
# FLAGS
diff --git a/lib/webtool/vsn.mk b/lib/webtool/vsn.mk
index d687b4ff81..2643be866e 100644
--- a/lib/webtool/vsn.mk
+++ b/lib/webtool/vsn.mk
@@ -1 +1 @@
-WEBTOOL_VSN=0.8.8
+WEBTOOL_VSN=0.8.9
diff --git a/lib/wx/api_gen/gen_util.erl b/lib/wx/api_gen/gen_util.erl
index b53f817ce0..df5b4c3405 100644
--- a/lib/wx/api_gen/gen_util.erl
+++ b/lib/wx/api_gen/gen_util.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -43,23 +43,27 @@ strip_name(String,[]) -> String.
get_hook(_Type, undefined) -> ignore;
get_hook(Type, List) -> proplists:get_value(Type, List, ignore).
-
+
+get_taylor_made(Str, Name) ->
+ re:run(Str, "<<"++Name++"(.*)"++Name++">>",
+ [dotall, {capture, all_but_first, list}]).
+
open_write(File) ->
%% io:format("Generating ~s~n",[File]),
{ok, Fd} = file:open(File++".temp", [write]),
put(current_file, {Fd,File}).
-
+
close() ->
case get(current_file) of
- undefined ->
+ undefined ->
ok;
{closed, File} ->
io:format("Closing twice ~s~n",[File]);
{Fd,File} ->
file:close(Fd),
case os:cmd("diff " ++ File ++ " " ++ File ++ ".temp" ++ "| head -30") of
- [] ->
+ [] ->
ok = file:delete(File ++ ".temp"),
%% So that make understands that we have made this
%% case os:getenv("CLEARCASE_ROOT") of
@@ -71,11 +75,11 @@ close() ->
case check_diff(Diff) of
copyright -> %% We ignore copyright changes only
ok = file:delete(File ++ ".temp");
- _ ->
+ _ ->
io:format("Diff in ~s~n~s ~n", [File, Diff]),
case file:rename(File ++ ".temp", File) of
ok -> ok;
- _ ->
+ _ ->
io:format("***** Failed to save file ~p ~n",[File])
end
end
@@ -85,9 +89,9 @@ close() ->
check_diff(Diff) ->
- try
+ try
[_,D1,_,D2|Tail] = re:split(Diff, "\n"),
- case Tail of
+ case Tail of
[] -> ok;
[<<>>] -> ok;
_ -> throw(diff)
@@ -117,29 +121,29 @@ args(Fun, Limit, List, Max) ->
args(Fun, Limit, List, Max, 0).
args(_Fun, _Limit, [], _Max, _) -> ""; %% No args
-args(Fun, _Limit, [Last], _Max, _Pos) ->
- case Fun(Last) of
+args(Fun, _Limit, [Last], _Max, _Pos) ->
+ case Fun(Last) of
skip -> ""; %% FIXME bug if last skips
Str -> Str
end;
args(Fun, Limit, [H|R], Max, Pos) ->
- case Fun(H) of
+ case Fun(H) of
skip -> args(Fun,Limit,R, Max, Pos);
- Str ->
- {NL, NewPos} =
+ Str ->
+ {NL, NewPos} =
case length(Str) + Pos of
Curr when Curr > Max ->
{"\n ", 0};
- Curr ->
+ Curr ->
{"", Curr}
end,
- case args(Fun,Limit,R, Max, NewPos) of
+ case args(Fun,Limit,R, Max, NewPos) of
"" -> Str;
End -> Str ++ Limit ++ NL ++ End
end
end.
-
+
tokens(S) ->
@@ -167,11 +171,11 @@ replace_and_remove([E|R], Acc) when is_list(E) -> %% Keep everything that is a w
replace_and_remove(R, [E|Acc]);
replace_and_remove([$\n | R], Acc) -> %% It is semi line oriented so keep eol
replace_and_remove(R, [eol|Acc]);
-replace_and_remove([$( | R], Acc) ->
+replace_and_remove([$( | R], Acc) ->
replace_and_remove(R, ["("|Acc]);
replace_and_remove([$) | R], Acc) ->
replace_and_remove(R, [")"|Acc]);
-replace_and_remove([${ | R], Acc) ->
+replace_and_remove([${ | R], Acc) ->
replace_and_remove(R, ["{"|Acc]);
replace_and_remove([$} | R], Acc) ->
replace_and_remove(R, ["}"|Acc]);
@@ -187,7 +191,7 @@ replace_and_remove([$, | R], Acc) ->
replace_and_remove(R, [cont|Acc]);
replace_and_remove([$; | R], Acc) ->
replace_and_remove(R, [eoe|Acc]);
-replace_and_remove([$@ | R], Acc) ->
+replace_and_remove([$@ | R], Acc) ->
replace_and_remove(R, [directive|Acc]);
replace_and_remove([_E|R], Acc) -> %% Ignore everthing else
@@ -213,7 +217,7 @@ erl_copyright() ->
w("%%~n",[]),
w("%% %CopyrightBegin%~n",[]),
w("%%~n",[]),
- w("%% Copyright Ericsson AB ~p-2010. All Rights Reserved.~n",
+ w("%% Copyright Ericsson AB ~p-2011. All Rights Reserved.~n",
[StartYear]),
w("%%~n",[]),
w("%% The contents of this file are subject to the Erlang Public License,~n",[]),
@@ -229,11 +233,11 @@ erl_copyright() ->
w("%%~n",[]),
w("%% %CopyrightEnd%~n",[]).
-c_copyright() ->
+c_copyright() ->
w("/*~n",[]),
w(" * %CopyrightBegin%~n",[]),
w(" *~n",[]),
- w(" * Copyright Ericsson AB 2008-2010. All Rights Reserved.~n",[]),
+ w(" * Copyright Ericsson AB 2008-2011. All Rights Reserved.~n",[]),
w(" *~n",[]),
w(" * The contents of this file are subject to the Erlang Public License,~n",[]),
w(" * Version 1.1, (the \"License\"); you may not use this file except in~n",[]),
diff --git a/lib/wx/api_gen/gl_gen.erl b/lib/wx/api_gen/gl_gen.erl
index 374e0bd12b..8998d341e7 100644
--- a/lib/wx/api_gen/gl_gen.erl
+++ b/lib/wx/api_gen/gl_gen.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -44,7 +44,7 @@ devcode() -> spawn(fun() -> safe(fun gen_code/0,false) end).
safe(What, QuitOnErr) ->
try
What(),
- io:format("Completed succesfully~n~n", []),
+ io:format("Completed successfully~n~n", []),
QuitOnErr andalso gen_util:halt(0)
catch Err:Reason ->
io:format("Error ~p: ~p:~p~n ~p~n",
diff --git a/lib/wx/api_gen/wx_doxygen.conf b/lib/wx/api_gen/wx_doxygen.conf
index df150fd154..829702cbbf 100644
--- a/lib/wx/api_gen/wx_doxygen.conf
+++ b/lib/wx/api_gen/wx_doxygen.conf
@@ -251,6 +251,7 @@ PREDEFINED = \
wxUSE_DATAOBJ=1 \
wxUSE_SLIDER=1 \
wxUSE_CLIPBOARD=1 \
+ wxUSE_SYSTEM_OPTIONS=1 \
wxABI_VERSION=20809 \
__WXGTK24__=1 \
__WXGTK20__=1 \
diff --git a/lib/wx/api_gen/wx_extra/wxListCtrl.c_src b/lib/wx/api_gen/wx_extra/wxListCtrl.c_src
index cd3074e481..54d6fafd01 100644
--- a/lib/wx/api_gen/wx_extra/wxListCtrl.c_src
+++ b/lib/wx/api_gen/wx_extra/wxListCtrl.c_src
@@ -1,3 +1,161 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+
+<<wxListCtrl_class
+class EwxListCtrl : public wxListCtrl {
+ public: ~EwxListCtrl();
+ EwxListCtrl(wxWindow * parent,wxWindowID winid,const wxPoint& pos,const wxSize& size,long style,const wxValidator& validator) : wxListCtrl(parent,winid,pos,size,style,validator) {};
+ EwxListCtrl() : wxListCtrl() {};
+
+ int onGetItemText;
+ int onGetItemAttr;
+ int onGetItemColumnImage;
+ ErlDrvPort port;
+
+ private:
+ virtual wxString OnGetItemText(long item, long col) const;
+ virtual wxListItemAttr* OnGetItemAttr(long item) const;
+ virtual int OnGetItemImage(long item) const;
+ virtual int OnGetItemColumnImage(long item, long column) const;
+};
+wxListCtrl_class>>
+
+<<wxListCtrl_new_0
+case ~s: { // wxListCtrl::wxListCtrl
+ wxListCtrl * Result = new EwxListCtrl();
+ newPtr((void *) Result, 0, memenv);
+ rt.addRef(getRef((void *)Result,memenv), "wxListCtrl");
+ break;
+}
+wxListCtrl_new_0>>
+
+<<wxListCtrl_new_2
+case ~s: { // wxListCtrl::wxListCtrl
+ wxWindowID winid=wxID_ANY;
+ wxPoint pos= wxDefaultPosition;
+ wxSize size= wxDefaultSize;
+ long style=wxLC_ICON;
+ const wxValidator * validator= &wxDefaultValidator;
+ wxWindow *parent = (wxWindow *) getPtr(bp,memenv); bp += 4;
+ int onGetItemText = 0, onGetItemAttr = 0, onGetItemColumnImage = 0;
+
+ bp += 4; /* Align */
+ while( * (int*) bp) { switch (* (int*) bp) {
+ case 1: {bp += 4;
+ winid = (wxWindowID)*(int *) bp; bp += 4;
+ } break;
+ case 2: {bp += 4;
+ int * posX = (int *) bp; bp += 4;
+ int * posY = (int *) bp; bp += 4;
+ pos = wxPoint(*posX,*posY);
+ bp += 4; /* Align */
+ } break;
+ case 3: {bp += 4;
+ int * sizeW = (int *) bp; bp += 4;
+ int * sizeH = (int *) bp; bp += 4;
+ size = wxSize(*sizeW,*sizeH);
+ bp += 4; /* Align */
+ } break;
+ case 4: {bp += 4;
+ style = (long)*(int *) bp; bp += 4;
+ } break;
+ case 5: {bp += 4;
+validator = (wxValidator *) getPtr(bp,memenv); bp += 4;
+ } break;
+ case 6: {bp += 4;
+ onGetItemText = *(int *) bp; bp += 4;
+ } break;
+ case 7: {bp += 4;
+ onGetItemAttr = *(int *) bp; bp += 4;
+ } break;
+ case 8: {bp += 4;
+ onGetItemColumnImage = *(int *) bp; bp += 4;
+ } break;
+ }};
+ EwxListCtrl * Result = new EwxListCtrl(parent,winid,pos,size,style,*validator);
+ Result->onGetItemText = onGetItemText;
+ Result->onGetItemAttr = onGetItemAttr;
+ Result->onGetItemColumnImage = onGetItemColumnImage;
+ Result->port = Ecmd.port;
+ newPtr((void *) Result, 0, memenv);
+ rt.addRef(getRef((void *)Result,memenv), "wxListCtrl");
+ break;
+}
+wxListCtrl_new_2>>
+
+<<Create
+case ~s: { // wxListCtrl::Create
+ wxWindowID winid=wxID_ANY;
+ wxPoint pos= wxDefaultPosition;
+ wxSize size= wxDefaultSize;
+ long style=wxLC_ICON;
+ const wxValidator * validator= &wxDefaultValidator;
+ EwxListCtrl *This = (EwxListCtrl *) getPtr(bp,memenv); bp += 4;
+ wxWindow *parent = (wxWindow *) getPtr(bp,memenv); bp += 4;
+ int onGetItemText = 0, onGetItemAttr = 0, onGetItemColumnImage = 0;
+
+ bp += 4; /* Align */
+ while( * (int*) bp) { switch (* (int*) bp) {
+ case 1: {bp += 4;
+ winid = (wxWindowID)*(int *) bp; bp += 4;
+ } break;
+ case 2: {bp += 4;
+ int * posX = (int *) bp; bp += 4;
+ int * posY = (int *) bp; bp += 4;
+ pos = wxPoint(*posX,*posY);
+ bp += 4; /* Align */
+ } break;
+ case 3: {bp += 4;
+ int * sizeW = (int *) bp; bp += 4;
+ int * sizeH = (int *) bp; bp += 4;
+ size = wxSize(*sizeW,*sizeH);
+ bp += 4; /* Align */
+ } break;
+ case 4: {bp += 4;
+ style = (long)*(int *) bp; bp += 4;
+ } break;
+ case 5: {bp += 4;
+validator = (wxValidator *) getPtr(bp,memenv); bp += 4;
+ } break;
+ case 6: {bp += 4;
+ onGetItemText = *(int *) bp; bp += 4;
+ } break;
+ case 7: {bp += 4;
+ onGetItemAttr = *(int *) bp; bp += 4;
+ } break;
+ case 8: {bp += 4;
+ onGetItemColumnImage = *(int *) bp; bp += 4;
+ } break;
+ }};
+ if(!This) throw wxe_badarg(0);
+ bool Result = This->Create(parent,winid,pos,size,style,*validator);
+ This->onGetItemText = onGetItemText;
+ This->onGetItemAttr = onGetItemAttr;
+ This->onGetItemColumnImage = onGetItemColumnImage;
+ This->port = Ecmd.port;
+
+ rt.addBool(Result);
+ break;
+}
+Create>>
+
<<SortItems
case ~s: { // wxListCtrl::SortItems taylormade
wxListCtrl *This = (wxListCtrl *) getPtr(bp,memenv); bp += 4;
@@ -22,3 +180,6 @@ case ~s: { // wxListCtrl::SortItems taylormade
break;
}
SortItems>>
+
+
+
diff --git a/lib/wx/api_gen/wx_extra/wxListCtrl.erl b/lib/wx/api_gen/wx_extra/wxListCtrl.erl
index e6470182cb..99255bc53f 100644
--- a/lib/wx/api_gen/wx_extra/wxListCtrl.erl
+++ b/lib/wx/api_gen/wx_extra/wxListCtrl.erl
@@ -1,32 +1,33 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2011. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
+
<<EXPORT:SortItems sortItems/2 SortItems:EXPORT>>
<<SortItems
%% @spec (This::wxListCtrl(), SortCallBack::function()) -> boolean()
%% @doc Sort the items in the list control<br />
-%% <pre>SortCalBack(Item1,Item2) -> integer()</pre>
+%% <pre>SortCallBack(Item1,Item2) -> integer()</pre>
%% <br /> SortCallBack receives the client data associated with two items
%% to compare, and should return 0 if the items are equal, a negative
%% value if the first item is less than the second one and a positive
%% value if the first item is greater than the second one.
-%% <br /> NOTE: The callback may not call other processes.
+%% <br /> NOTE: The callback may not call other (wx) processes.
sortItems(#wx_ref{type=ThisT,ref=ThisRef}, SortCallBack)
when is_function(SortCallBack, 2) ->
?CLASS(ThisT,wxListCtrl),
@@ -37,3 +38,100 @@ sortItems(#wx_ref{type=ThisT,ref=ThisRef}, SortCallBack)
SortId = wxe_util:get_cbId(Sort),
wxe_util:call(~s, <<ThisRef:32/?UI,SortId:32/?UI>>).
SortItems>>
+
+<<EXPORT:wxListCtrl new/0, new/1, new/2 wxListCtrl:EXPORT>>
+
+<<wxListCtrl_new_0
+%% @spec () -> wxListCtrl()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlwxlistctrl">external documentation</a>.
+new() ->
+ wxe_util:construct(~s, <<>>).
+wxListCtrl_new_0>>
+
+<<wxListCtrl_new_2
+%% @spec (Parent::wxWindow:wxWindow()) -> wxListCtrl()
+%% @equiv new(Parent, [])
+new(Parent)
+ when is_record(Parent, wx_ref) ->
+ new(Parent, []).
+
+%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxListCtrl()
+%% Option = {winid, integer()} |
+%% {pos, {X::integer(),Y::integer()}} |
+%% {size, {W::integer(),H::integer()}} |
+%% {style, integer()} |
+%% {validator, wx:wx()} |
+%% {onGetItemText, OnGetItemText} |
+%% {onGetItemAttr, OnGetItemAttr} |
+%% {onGetItemColumnImage, OnGetItemColumnImage}
+%%
+%% OnGetItemText = (This, Item, Column) -> wxString()
+%% OnGetItemAttr = (This, Item) -> wxListItemAttr()
+%% OnGetItemColumnImage = (This, Item, Column) -> integer()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlwxlistctrl">external documentation</a>.
+
+new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
+ when is_list(Options)->
+ ?CLASS(ParentT,wxWindow),
+ MOpts = fun({winid, Winid}, Acc) -> [<<1:32/?UI,Winid:32/?UI>>|Acc];
+ ({pos, {PosX,PosY}}, Acc) -> [<<2:32/?UI,PosX:32/?UI,PosY:32/?UI,0:32>>|Acc];
+ ({size, {SizeW,SizeH}}, Acc) -> [<<3:32/?UI,SizeW:32/?UI,SizeH:32/?UI,0:32>>|Acc];
+ ({style, Style}, Acc) -> [<<4:32/?UI,Style:32/?UI>>|Acc];
+ ({validator, #wx_ref{type=ValidatorT,ref=ValidatorRef}}, Acc) ->
+ ?CLASS(ValidatorT,wx),[<<5:32/?UI,ValidatorRef:32/?UI>>|Acc];
+ ({onGetItemText, F}, Acc) when is_function(F) ->
+ Fun = fun([This,Item,Col]) -> unicode:characters_to_binary([F(This,Item,Col),0]) end,
+ [<<6:32/?UI,(wxe_util:get_cbId(Fun)):32/?UI>>|Acc];
+ ({onGetItemAttr, F}, Acc) when is_function(F) ->
+ Fun = fun([This,Item]) ->
+ #wx_ref{type=wxListItemAttr,ref=ThisRef} = F(This,Item),
+ <<ThisRef:32/?UI>>
+ end,
+ [<<7:32/?UI,(wxe_util:get_cbId(Fun)):32/?UI>>|Acc];
+ ({onGetItemColumnImage, F}, Acc) when is_function(F) ->
+ Fun = fun([This,Item, Col]) -> <<(F(This,Item,Col)):32/?I>> end,
+ [<<8:32/?UI,(wxe_util:get_cbId(Fun)):32/?UI>>|Acc];
+ (BadOpt, _) -> erlang:error({badoption, BadOpt}) end,
+ BinOpt = list_to_binary(lists:foldl(MOpts, [<<0:32>>], Options)),
+ wxe_util:construct(~s, <<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
+
+wxListCtrl_new_2>>
+
+<<EXPORT:Create create/2, create/3 Create:EXPORT>>
+
+<<Create
+%% @spec (This::wxListCtrl(), Parent::wxWindow:wxWindow()) -> bool()
+%% @equiv create(This,Parent, [])
+create(This,Parent)
+ when is_record(This, wx_ref),is_record(Parent, wx_ref) ->
+ create(This,Parent, []).
+
+%% @spec (This::wxListCtrl(), Parent::wxWindow:wxWindow(), [Option]) -> bool()
+%% Option = {winid, integer()} |
+%% {pos, {X::integer(),Y::integer()}} |
+%% {size, {W::integer(),H::integer()}} |
+%% {style, integer()} |
+%% {validator, wx:wx()} |
+%% {onGetItemText, OnGetItemText} |
+%% {onGetItemAttr, OnGetItemAttr} |
+%% {onGetItemColumnImage, OnGetItemColumnImage}
+%%
+%% OnGetItemText = (This, Item, Column) -> wxString()
+%% OnGetItemAttr = (This, Item) -> wxListItemAttr()
+%% OnGetItemColumnImage = (This, Item, Column) -> integer()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlcreate">external documentation</a>.
+create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
+ when is_list(Options) ->
+ ?CLASS(ThisT,wxListCtrl),
+ ?CLASS(ParentT,wxWindow),
+ MOpts = fun({winid, Winid}, Acc) -> [<<1:32/?UI,Winid:32/?UI>>|Acc];
+ ({pos, {PosX,PosY}}, Acc) -> [<<2:32/?UI,PosX:32/?UI,PosY:32/?UI,0:32>>|Acc];
+ ({size, {SizeW,SizeH}}, Acc) -> [<<3:32/?UI,SizeW:32/?UI,SizeH:32/?UI,0:32>>|Acc];
+ ({style, Style}, Acc) -> [<<4:32/?UI,Style:32/?UI>>|Acc];
+ ({validator, #wx_ref{type=ValidatorT,ref=ValidatorRef}}, Acc) -> ?CLASS(ValidatorT,wx),[<<5:32/?UI,ValidatorRef:32/?UI>>|Acc];
+ (BadOpt, _) -> erlang:error({badoption, BadOpt}) end,
+ BinOpt = list_to_binary(lists:foldl(MOpts, [<<0:32>>], Options)),
+ wxe_util:call(~s,
+ <<ThisRef:32/?UI,ParentRef:32/?UI, BinOpt/binary>>).
+
+Create>>
diff --git a/lib/wx/api_gen/wx_gen.erl b/lib/wx/api_gen/wx_gen.erl
index 2f20c42a5d..209de48496 100644
--- a/lib/wx/api_gen/wx_gen.erl
+++ b/lib/wx/api_gen/wx_gen.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -30,6 +30,12 @@
-compile(export_all).
+-define(DBGCF(Class, Func, Format, Args),
+ case {get(current_class), get(current_func)} of
+ {Class, Func} -> io:format("~p:~p: " ++ Format, [?MODULE,?LINE] ++ Args);
+ _ -> ok
+ end).
+
code() -> safe(fun gen_code/0,true).
xml() -> safe(fun gen_xml/0,true).
@@ -38,7 +44,7 @@ devcode() -> erase(),safe(fun gen_code/0,false).
safe(What, QuitOnErr) ->
try
What(),
- io:format("Completed succesfully~n~n", []),
+ io:format("Completed successfully~n~n", []),
QuitOnErr andalso gen_util:halt(0)
catch Err:Reason ->
io:format("Error in ~p ~p~n", [get(current_class),get(current_func)]),
@@ -957,17 +963,17 @@ erl_skip_opt(All=[Ms=[{_,{Len,_,_},_}|_]|R],Acc1=[{_,{N,_,_},_}|_], Acc2) ->
end;
erl_skip_opt([],Acc1,Acc2) -> [strip_ti(Acc1)|Acc2].
-erl_skip_opt2([F={_,{N,In,_},M=#method{where=Where}}|Ms],Acc1,Acc2,Check) ->
+erl_skip_opt2([F={_,{N,In,_},M=#method{where=Where}}|Ms],Acc1,Acc2,Check) ->
case N > 0 andalso lists:last(In) =:= opt_list of
- true when Where =/= merged_c, Where =/= taylormade ->
- case Check of
- [] ->
+ true when Where =/= merged_c, Where =/= taylormade ->
+ case Check of
+ [] ->
erl_skip_opt2(Ms,[F|Acc1],[M#method{where=erl_no_opt}|Acc2],[]);
- _ ->
+ _ ->
Skipped = reverse(tl(reverse(In))),
T = fun({_,{_,Args,_},_}) -> true =:= types_differ(Skipped,Args) end,
case lists:all(T, Check) of
- true ->
+ true ->
erl_skip_opt2(Ms,[F|Acc1],
[M#method{where=erl_no_opt}|Acc2],
Check);
@@ -976,7 +982,7 @@ erl_skip_opt2([F={_,{N,In,_},M=#method{where=Where}}|Ms],Acc1,Acc2,Check) ->
end
end;
_ ->
- erl_skip_opt2(Ms,[F|Acc1],Acc2,[])
+ erl_skip_opt2(Ms,[F|Acc1],Acc2,Check)
end;
erl_skip_opt2([],Acc1,Acc2,_) -> {Acc1,Acc2}.
@@ -1025,7 +1031,6 @@ types_differ([{class,C1}|R1], [{class,C2}|R2]) ->
true ->
true;
false ->
-%% _ ->
{class,C1,C2};
{class,C1,C2} ->
{class,C1,C2};
diff --git a/lib/wx/api_gen/wx_gen_cpp.erl b/lib/wx/api_gen/wx_gen_cpp.erl
index 4b33068d8f..1b4c32db24 100644
--- a/lib/wx/api_gen/wx_gen_cpp.erl
+++ b/lib/wx/api_gen/wx_gen_cpp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,7 +19,7 @@
%%%-------------------------------------------------------------------
%%% File : wx_gen_cpp.erl
%%% Author : Dan Gudmundsson <[email protected]>
-%%% Description :
+%%% Description :
%%%
%%% Created : 19 Feb 2007 by Dan Gudmundsson <[email protected]>
%%%-------------------------------------------------------------------
@@ -35,7 +35,7 @@
args/3, strip_name/2]).
-import(wx_gen, [next_id/1]).
-gen(Defs) ->
+gen(Defs) ->
open_write("../c_src/gen/wxe_derived_dest.h"),
c_copyright(),
w("~n/***** This file is generated do not edit ****/~n~n", []),
@@ -49,48 +49,26 @@ gen(Defs) ->
open_write("../c_src/gen/wxe_macros.h"),
c_copyright(),
- gen_macros(),
+ gen_macros(),
close(),
open_write("../c_src/gen/wxe_init.cpp"),
c_copyright(),
build_enums(),
close(),
-
+
build_events(),
Res.
-
+
gen_derived_dest(Defs) ->
[gen_derived_dest_2(Class) || Class <- Defs],
-
- UglySkipList = ["wxCaret", "wxCalendarDateAttr",
- "wxFileDataObject", "wxTextDataObject", "wxBitmapDataObject"
- ],
-
- ?WTC("gen_derived_dest"),
- w("void WxeApp::delete_object(void *ptr, wxeRefData *refd) {~n", []),
- w(" switch(refd->type) {~n", []),
- Case = fun(#class{name=Class, id=Id, abstract=IsAbs, parent=P}) when P /= "static" ->
- UglyWorkaround = lists:member(Class, UglySkipList),
- case hd(reverse(wx_gen_erl:parents(Class))) of
- root when IsAbs == false, UglyWorkaround == false ->
- w(" case ~p: delete (~s *) ptr; break;~n", [Id, Class]);
- root when IsAbs == false, UglyWorkaround == true ->
- w(" case ~p: /* delete (~s *) ptr;"
- "These objects must be deleted by owner object */ "
- "break;~n", [Id, Class]);
- _ -> ok
- end;
- (_) -> ok
- end,
- [Case(Class) || Class <- Defs],
- w(" default: delete (wxObject *) ptr;~n", []),
- w("}}~n~n", []).
+ ok.
gen_derived_dest_2(C=#class{name=Class}) ->
- case is_derived(C) of
- true ->
- ?WTC("gen_derived_dest_2"),
+ ?WTC("gen_derived_dest_2"),
+ Derived = is_derived(C),
+ TaylorMade = taylormade_class(C),
+ if Derived andalso (TaylorMade =:= false) ->
w("class E~s : public ~s {~n",[Class,Class]),
case Class of
"wxGLCanvas" -> %% Special for cleaning up gl context
@@ -101,15 +79,32 @@ gen_derived_dest_2(C=#class{name=Class}) ->
end,
gen_constructors(C),
w("};~n~n", []);
- false ->
+ TaylorMade /= false ->
+ w("~s~n", [TaylorMade]);
+ true ->
ignore
end.
+taylormade_class(#class{name=CName, methods=Ms}) ->
+ TaylorMade = lists:any(fun([#method{where=taylormade}|_]) -> true;
+ (_) -> false
+ end, Ms),
+ case TaylorMade of
+ false -> false;
+ true ->
+ {ok, Bin} = file:read_file(filename:join([wx_extra, CName ++".c_src"])),
+ Src = binary_to_list(Bin),
+ case gen_util:get_taylor_made(Src, CName ++ "_class") of
+ nomatch -> false;
+ {match, [Str0]} -> Str0
+ end
+ end.
+
gen_constructors(#class{name=Class, methods=Ms0}) ->
Ms = lists:append(Ms0),
Cs = lists:filter(fun(#method{method_type=MT}) -> MT =:= constructor end, Ms),
[gen_constructor(Class, Const) || Const <- Cs].
-
+
gen_constructor(_Class, #method{where=merged_c}) -> ok;
gen_constructor(_Class, #method{where=erl_no_opt}) -> ok;
gen_constructor(Class, _M=#method{params=Ps}) ->
@@ -119,7 +114,7 @@ gen_constructor(Class, _M=#method{params=Ps}) ->
HaveMergedType = fun(#param{type={merged,_,_,_,_,_,_}}) -> true; (_) -> false end,
?WTC("gen_constructor"),
case lists:any(HaveMergedType, Ps) of
- false ->
+ false ->
w(" E~s(~s) : ~s(~s) {};~n",
[Class,args(Gen1,",",Ps),Class,args(CallA,",",Ps)]);
true ->
@@ -141,9 +136,9 @@ gen_type(#type{name=Type, ref=undefined, single=array, mod=Mod},_) ->
mods(Mod) ++ to_string(Type) ++ " * ";
gen_type(#type{name=Type, ref=undefined, mod=Mod},_) ->
mods(Mod) ++ to_string(Type) ++ " ";
-gen_type({merged, _, T1, _,_, _T2,_}, 1) ->
+gen_type({merged, _, T1, _,_, _T2,_}, 1) ->
gen_type(T1,error);
-gen_type({merged, _, _T1,_, _, T2,_}, 2) ->
+gen_type({merged, _, _T1,_, _, T2,_}, 2) ->
gen_type(T2,error).
gen_funcs(Defs) ->
@@ -168,7 +163,7 @@ gen_funcs(Defs) ->
%% w(" case WXE_REMOVE_PORT:~n", []),
%% w(" { destroyMemEnv(Ecmd.port); } break;~n", []),
w(" case DESTROY_OBJECT: {~n"),
- w(" wxObject *This = (wxObject *) getPtr(bp,memenv); "),
+ w(" wxObject *This = (wxObject *) getPtr(bp,memenv); "),
w(" if(This) {"),
w(" ((WxeApp *) wxTheApp)->clearPtr((void *) This);~n"),
w(" delete This; }~n } break;~n"),
@@ -203,16 +198,39 @@ gen_funcs(Defs) ->
w(" error.addTupleCount(2);~n"),
w(" error.addTupleCount(3);~n"),
w(" error.send();~n"),
- w("}} /* The End */~n"),
+ w("}} /* The End */~n~n~n"),
+
+ UglySkipList = ["wxCaret", "wxCalendarDateAttr",
+ "wxFileDataObject", "wxTextDataObject", "wxBitmapDataObject"
+ ],
+
+ w("void WxeApp::delete_object(void *ptr, wxeRefData *refd) {~n", []),
+ w(" switch(refd->type) {~n", []),
+ Case = fun(#class{name=Class, id=Id, abstract=IsAbs, parent=P}) when P /= "static" ->
+ UglyWorkaround = lists:member(Class, UglySkipList),
+ case hd(reverse(wx_gen_erl:parents(Class))) of
+ root when IsAbs == false, UglyWorkaround == false ->
+ w(" case ~p: delete (~s *) ptr; break;~n", [Id, Class]);
+ root when IsAbs == false, UglyWorkaround == true ->
+ w(" case ~p: /* delete (~s *) ptr;"
+ "These objects must be deleted by owner object */ "
+ "break;~n", [Id, Class]);
+ _ -> ok
+ end;
+ (_) -> ok
+ end,
+ [Case(Class) || Class <- Defs],
+ w(" default: delete (wxObject *) ptr;~n", []),
+ w("}}~n~n", []),
Res.
-
+
gen_class(C=#class{name=Name,methods=Ms,options=Opts}) ->
put(current_class, Name),
- NewMs =
+ NewMs =
case lists:member(taylormade, Opts) of
true ->
{ok, Bin} = file:read_file(filename:join([wx_extra,Name++".c_src"])),
- ?WTC("gen_class"),
+ ?WTC("gen_class"),
w("~s~n", [binary_to_list(Bin)]),
Ms;
false ->
@@ -220,13 +238,13 @@ gen_class(C=#class{name=Name,methods=Ms,options=Opts}) ->
{value, {ifdef, What}} ->
w("#if ~p~n",[What]),
Methods = lists:flatten(Ms),
- MsR = [gen_method(Name,M) ||
+ MsR = [gen_method(Name,M) ||
M <- lists:keysort(#method.id, Methods)],
w("#endif // ~p~n",[What]),
MsR;
false ->
Methods = lists:flatten(Ms),
- [gen_method(Name,M) ||
+ [gen_method(Name,M) ||
M <- lists:keysort(#method.id, Methods)]
end
end,
@@ -234,15 +252,19 @@ gen_class(C=#class{name=Name,methods=Ms,options=Opts}) ->
C#class{methods=NewMs}.
gen_method(_CName, M=#method{where=erl_no_opt}) -> M;
-gen_method(CName, M=#method{where=taylormade, name=Name, id=Id}) ->
+gen_method(CName, M=#method{where=taylormade, name=Name, id=Id}) ->
{ok, Bin} = file:read_file(filename:join([wx_extra, CName ++".c_src"])),
- Str0 = binary_to_list(Bin),
+ Src = binary_to_list(Bin),
%% io:format("C++ Class ~p ~p~n", [CName, Name]),
-
- {match, [Str1]} = re:run(Str0, "<<"++Name++"(.*)"++Name++">>",
- [dotall, {capture, all_but_first, list}]),
+ Str = case gen_util:get_taylor_made(Src, Name) of
+ nomatch ->
+ {match, [Str0]} = gen_util:get_taylor_made(Src, wx_gen_erl:get_unique_name(Id)),
+ Str0;
+ {match, [Str0]} ->
+ Str0
+ end,
?WTC("gen_method"),
- w(Str1, [wx_gen_erl:get_unique_name(Id)]),
+ w(Str, [wx_gen_erl:get_unique_name(Id)]),
M;
gen_method(CName, M=#method{name=N,params=[Ps],method_type=destructor,id=MethodId}) ->
case hd(reverse(wx_gen_erl:parents(CName))) of
@@ -253,7 +275,7 @@ gen_method(CName, M=#method{name=N,params=[Ps],method_type=destructor,id=MethodI
w(" if(This) {", []),
w(" ((WxeApp *) wxTheApp)->clearPtr((void *) This);~n", []),
w(" delete This;}~n", []),
- free_args(),
+ free_args(),
w(" break;~n}~n", []);
object -> %% Use default
ignore
@@ -266,7 +288,7 @@ gen_method(CName, M=#method{name=N,params=Ps0,type=T,method_type=MT,id=MethodId
w("case ~s: { // ~s::~s~n", [wx_gen_erl:get_unique_name(MethodId),CName,N]),
Ps1 = declare_variables(void, Ps0),
{Ps2,Align} = decode_arguments(Ps1),
- Opts = [Opt || Opt = #param{def=Def,in=In,where=Where} <- Ps2,
+ Opts = [Opt || Opt = #param{def=Def,in=In,where=Where} <- Ps2,
Def =/= none, In =/= false, Where =/= c],
decode_options(Opts, Align),
case gen_util:get_hook(c, M#method.pre_hook) of
@@ -292,7 +314,7 @@ declare_variables(T, Ps) ->
declare_var(P = #param{where=erl}) -> P;
declare_var(P = #param{where=this}) -> P;
-declare_var(P = #param{name=Name,def=Def,type=Type,in=true}) when Def =/= none ->
+declare_var(P = #param{name=Name,def=Def,type=Type,in=true}) when Def =/= none ->
declare_type(Name, true, Def, Type),
P;
declare_var(P = #param{in=In}) when In =/= false -> P;
@@ -304,7 +326,7 @@ declare_type(N,false,_,#type{name="wxArrayInt"}) ->
w(" wxArrayInt ~s;~n", [N]);
declare_type(N,false,_,#type{name="wxArrayString"}) ->
w(" wxArrayString ~s;~n", [N]);
-declare_type(N,false,_,#type{base=Base,single=true,name=Type,by_val=false,mod=Mod})
+declare_type(N,false,_,#type{base=Base,single=true,name=Type,by_val=false,mod=Mod})
when Base =:= int; Base =:= long; Base =:= float; Base =:= double ->
w(" ~s~s ~s;~n", [mods(Mod),Type,N]);
declare_type(N,false,_,#type{base={enum,_},single=true,name=Type,by_val=false,mod=Mod}) ->
@@ -315,7 +337,7 @@ declare_type(N,false,_,#type{name="wxDateTime"}) ->
w(" wxDateTime ~s;~n", [N]);
declare_type(N,false,_,#type{name=Type, base=int64, ref=reference}) ->
w(" ~s ~s;~n", [Type,N]);
-declare_type(N,true,Def,#type{base=Base,single=true,name=Type,by_val=true})
+declare_type(N,true,Def,#type{base=Base,single=true,name=Type,by_val=true})
when Base =:= int; Base =:= long; Base =:= float; Base =:= double; Base =:= bool ->
w(" ~s ~s=~s;~n", [Type,N,Def]);
declare_type(N,true,Def,#type{base={comp,_,_},single=true,name=Type,mod=Mod,ref={pointer,1}}) ->
@@ -328,7 +350,7 @@ declare_type(N,true,Def,#type{base={class,_},single=true,name=Type,ref={pointer,
w(" ~s~s * ~s=~s;~n", [mods(Mod),Type,N,Def]);
declare_type(N,true,Def,#type{base={class,_},single=true,name=Type,ref=reference,mod=Mod}) ->
w(" ~s~s * ~s= &~s;~n", [mods(Mod),Type,N,Def]);
-declare_type(N,true,Def,#type{base=Base,single=true,name=Type,by_val=false,ref={pointer,1}})
+declare_type(N,true,Def,#type{base=Base,single=true,name=Type,by_val=false,ref={pointer,1}})
when Base =:= int; Base =:= long; Base =:= float; Base =:= double; Base =:= bool ->
w(" ~s *~s=~s;~n", [Type,N,Def]);
declare_type(N,true,Def,#type{single=true,name="wxArtClient"}) ->
@@ -345,7 +367,7 @@ declare_type(N,true,Def,#type{name=Type, ref={pointer,2}}) ->
%% xxxx
w(" ~s ** ~s = ~s;~n", [Type,N,Def]);
declare_type(N,true,Def,#type{name=Type, single=array, ref={pointer,1}}) ->
- w(" int * ~sLen = 0;~n", [N]),
+ w(" int * ~sLen = 0;~n", [N]),
w(" ~s * ~s = ~s;~n", [Type,N,Def]);
declare_type(N,true,"",#type{name="wxArrayString", single=array, ref=reference}) ->
w(" wxArrayString ~s;~n", [N]);
@@ -363,12 +385,12 @@ decode_options(Opts, Align) ->
decode_opt(#param{name=Name,type=Type}, N) ->
w(" case ~p: {bp += 4;~n", [N]),
- Align = decode_arg(Name,Type,opt,1),
+ Align = decode_arg(Name,Type,opt,1),
align(Align, 64),
w(" } break;~n", []),
N+1.
-decode_arguments(Ps0) ->
+decode_arguments(Ps0) ->
lists:mapfoldl(fun decode_arg/2,0,Ps0).
store_free(N) ->
@@ -380,7 +402,7 @@ store_free(N) ->
free_args() ->
case get(free_args) of
undefined -> ignore;
- List ->
+ List ->
erase(free_args),
[w(" driver_free(~s);~n", [Arg]) || Arg <- List]
end.
@@ -388,7 +410,7 @@ free_args() ->
decode_arg(P = #param{where=erl},A) -> {P,A};
decode_arg(P = #param{where=c},A) -> {P,A};
decode_arg(P = #param{in=false},A) -> {P,A};
-decode_arg(P = #param{def=Def},A) when Def =/= none -> {P,A};
+decode_arg(P = #param{def=Def},A) when Def =/= none -> {P,A};
decode_arg(P = #param{name=Name,type=Type},A0) ->
A = decode_arg(Name, Type, arg, A0),
{P, A}.
@@ -426,22 +448,22 @@ decode_arg(N,#type{base=float,single=true,name=Type},arg,A0) ->
align(A0,32);
decode_arg(N,#type{base=double,single=true,name=Type},Arg,A0) ->
A = align(A0,64),
- case Arg of
+ case Arg of
arg -> w(" ~s * ~s = (~s *) bp; bp += 8;~n", [Type,N,Type]);
opt -> w(" ~s = * (~s *) bp; bp += 8;~n", [N,Type])
end,
A;
decode_arg(N,#type{base=bool,single=true,name=Type},Arg,A0) ->
- case Arg of
+ case Arg of
arg -> w(" bool * ~s = (~s *) bp; bp += 4;~n", [N,Type]);
opt -> w(" ~s = *(~s *) bp; bp += 4;~n", [N,Type])
end,
align(A0,32);
decode_arg(N,#type{base={enum,Type},single=true},Arg,A0) ->
- wa(" ~s ", [enum_type(Type)], "~s = *(~s *) bp; bp += 4;;~n",[N, enum_type(Type)], Arg),
+ wa(" ~s ", [enum_type(Type)], "~s = *(~s *) bp; bp += 4;;~n",[N, enum_type(Type)], Arg),
align(A0,32);
decode_arg(N,#type{base={comp,"wxDateTime",List},single=true,name=Type,ref=Ref},Arg,A0) ->
- Decl = fun({int,Spec}) ->
+ Decl = fun({int,Spec}) ->
w(" int * ~s~s = (int *) bp; bp += 4;~n", [N,Spec])
end,
align(A0,32),
@@ -452,15 +474,15 @@ decode_arg(N,#type{base={comp,"wxDateTime",List},single=true,name=Type,ref=Ref},
end,
case Arg of
arg -> w(" ~s ~s = ~s(~s);~n", [Type,N,Type,args(Name, ",", List)]);
- opt when Ref =:= {pointer,1} ->
- w(" ~sTmp = ~s(~s); ~s = & ~sTmp;~n",
+ opt when Ref =:= {pointer,1} ->
+ w(" ~sTmp = ~s(~s); ~s = & ~sTmp;~n",
[N,Type,args(Name, ",", List), N,N]);
opt ->
w(" ~s = ~s(~s);~n", [N,Type,args(Name, ",", List)])
end,
(A0+length(List)) rem 2;
decode_arg(N,#type{base={comp,_,List},single=true,name=Type,ref=Ref},Arg,A0) ->
- Decl = fun({int,Spec}) ->
+ Decl = fun({int,Spec}) ->
w(" int * ~s~s = (int *) bp; bp += 4;~n", [N,Spec]);
({double, Spec}) ->
w(" wxDouble * ~s~s = (wxDouble *) bp; bp += 8;~n", [N,Spec])
@@ -473,8 +495,8 @@ decode_arg(N,#type{base={comp,_,List},single=true,name=Type,ref=Ref},Arg,A0) ->
Name = fun({_,Spec}) -> "*"++N++Spec end,
case Arg of
arg -> w(" ~s ~s = ~s(~s);~n", [Type,N,Type,args(Name, ",", List)]);
- opt when Ref =:= {pointer,1} ->
- w(" ~sTmp = ~s(~s); ~s = & ~sTmp;~n",
+ opt when Ref =:= {pointer,1} ->
+ w(" ~sTmp = ~s(~s); ~s = & ~sTmp;~n",
[N,Type,args(Name, ",", List), N,N]);
opt ->
w(" ~s = ~s(~s);~n", [N,Type,args(Name, ",", List)])
@@ -483,7 +505,7 @@ decode_arg(N,#type{base={comp,_,List},single=true,name=Type,ref=Ref},Arg,A0) ->
{int, _} -> (A0+length(List)) rem 2;
{double, _} -> 0
end;
-
+
decode_arg(N,#type{name=Class="wxTreeItemId",single=true},Arg,A0) ->
A = align(A0,64),
wa(" ~s ",[Class],"~s = wxTreeItemId((void *) *(wxUint64 *) bp); bp += 8;~n",[N],Arg),
@@ -492,7 +514,7 @@ decode_arg(N,#type{name=Class="wxTreeItemIdValue",single=true},Arg,A0) ->
A = align(A0,64),
wa(" ~s ",[Class],"~s = (~s) * (wxUint64 *) bp; bp += 8;~n",[N,Class],Arg),
A;
-decode_arg(N,#type{name="wxChar", single=S},Arg,A0)
+decode_arg(N,#type{name="wxChar", single=S},Arg,A0)
when S =/= true ->
w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]),
wa(" wxString", []," ~s = wxString(bp, wxConvUTF8);~n", [N],Arg),
@@ -501,7 +523,7 @@ decode_arg(N,#type{name="wxChar", single=S},Arg,A0)
decode_arg(N,#type{base=string, name="wxFileName"},Arg,A0) ->
w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]),
wa(" wxString", []," ~sStr = wxString(bp, wxConvUTF8);~n", [N],Arg),
- w(" bp += *~sLen+((8-((~p+ *~sLen) & 7)) & 7);~n", [N,4*((A0+1) rem 2),N]),
+ w(" bp += *~sLen+((8-((~p+ *~sLen) & 7)) & 7);~n", [N,4*((A0+1) rem 2),N]),
w(" wxFileName ~s = wxFileName(~sStr);~n",[N,N]),
0;
decode_arg(N,#type{base=string},Arg,A0) ->
@@ -541,7 +563,7 @@ decode_arg(N,#type{name="wxArrayDouble"},arg,A0) ->
decode_arg(_N,#type{base=eventType},_Arg,A0) ->
%% w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]),
%% case Arg of
-%% arg ->
+%% arg ->
%% w(" int ~s = wxeEventTypeFromAtom(bp);bp += *~sLen;~n",[N,N]),
%% w(" char *class_name = bp;~n", []),
%% w(" wxeCallbackData * Evt_cb = new wxeCallbackData(Ecmd.caller,This,class_name);~n",
@@ -551,7 +573,7 @@ decode_arg(_N,#type{base=eventType},_Arg,A0) ->
decode_arg(N,#type{name=Type,base=binary,mod=Mod0},Arg,A0) ->
Mod = mods([M || M <- Mod0]),
case Arg of
- arg ->
+ arg ->
w(" ~s~s * ~s = (~s~s*) Ecmd.bin[~p]->base;~n",
[Mod,Type,N,Mod,Type, next_id(bin_count)]);
opt ->
@@ -564,10 +586,10 @@ decode_arg(N,#type{base={term,"wxTreeItemData"},mod=Mod0},Arg,A0) ->
Type = "wxETreeItemData",
BinCnt = next_id(bin_count),
case Arg of
- arg ->
+ arg ->
w(" ~s~s * ~s = new ~s(Ecmd.bin[~p]->size, Ecmd.bin[~p]->base);~n",
[Mod,Type,N,Type,BinCnt,BinCnt]);
- opt ->
+ opt ->
w(" ~s = new ~s(Ecmd.bin[~p]->size, Ecmd.bin[~p]->base);~n",
[N,Type,BinCnt,BinCnt])
end,
@@ -576,10 +598,10 @@ decode_arg(N,#type{name=Type,base={term,_},mod=Mod0},Arg,A0) ->
Mod = mods([M || M <- Mod0]),
BinCnt = next_id(bin_count),
case Arg of
- arg ->
+ arg ->
w(" ~s~s * ~s = new ~s(Ecmd.bin[~p]);~n",
[Mod,Type,N,Type,BinCnt]);
- opt ->
+ opt ->
w(" ~s = new ~s(Ecmd.bin[~p]);~n",
[N,Type,BinCnt])
end,
@@ -588,17 +610,17 @@ decode_arg(N,#type{single=array,base=int},Arg,A0) ->
case Arg of
arg ->
w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]),
- w(" int * ~s = (int *) bp; bp += *~sLen*4+((~p+ *~sLen)%2 )*4;~n",
+ w(" int * ~s = (int *) bp; bp += *~sLen*4+((~p+ *~sLen)%2 )*4;~n",
[N,N,(A0+1) rem 2,N]);
- opt ->
+ opt ->
w(" ~sLen = (int *) bp; bp += 4;~n", [N]),
- w(" ~s = (int *) bp; bp += *~sLen*4+((~p+ *~sLen)%2 )*4;~n",
+ w(" ~s = (int *) bp; bp += *~sLen*4+((~p+ *~sLen)%2 )*4;~n",
[N,N,(A0+1) rem 2,N])
end,
0;
decode_arg(N,#type{by_val=true,single=array,base={comp,Class="wxPoint",_}},arg,A0) ->
- w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]),
- w(" ~s *~s;~n",[Class,N]),
+ w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]),
+ w(" ~s *~s;~n",[Class,N]),
w(" ~s = (~s *) driver_alloc(sizeof(~s) * *~sLen);~n",[N,Class,Class,N]),
store_free(N),
w(" for(int i=0; i < *~sLen; i++) {~n", [N]),
@@ -629,13 +651,13 @@ decode_arg(Name,T, Arg,_A) ->
align(0, 32) -> 1;
align(1, 32) -> 0;
align(0, 64) -> 0;
-align(1, 64) ->
+align(1, 64) ->
w(" bp += 4; /* Align */~n"),
0;
align(N,Sz) ->
align(N rem 2, Sz).
-call_wx(_N,{constructor,_},#type{base={class,RClass}},Ps) ->
+call_wx(_N,{constructor,_},#type{base={class,RClass}},Ps) ->
#class{id=Id} = ClassDef = get({class,RClass}),
Class = case is_derived(ClassDef) of
true -> "E" ++ RClass;
@@ -648,8 +670,8 @@ call_wx(_N,{constructor,_},#type{base={class,RClass}},Ps) ->
case is_dialog(RClass) of
true -> 2; %% Dialogs must be closed first event before windows
false -> 0
- end;
- false ->
+ end;
+ false ->
case hd(reverse(wx_gen_erl:parents(RClass))) of
root -> Id;
_ -> 1
@@ -682,10 +704,10 @@ call_wx(N,{static,Class},Type,Ps) ->
return_res(void) -> {"", ""};
return_res(Type = #type{mod=Mod}) ->
case lists:member(const, Mod) of
- true ->
- {Beg, End} = return_res1(Type),
+ true ->
+ {Beg, End} = return_res1(Type),
{"const " ++ Beg, End};
- _ ->
+ _ ->
return_res1(Type)
end.
@@ -695,8 +717,8 @@ return_res1(#type{name=Type,ref={pointer,_}}) ->
{Type ++ " * Result = (" ++ Type ++ "*)", ""};
return_res1(#type{name=Type,single=true,ref=reference}) ->
{Type ++ " * Result = &", ""};
-return_res1(#type{name=Type,single=true,by_val=true})
- when is_atom(Type) ->
+return_res1(#type{name=Type,single=true,by_val=true})
+ when is_atom(Type) ->
{atom_to_list(Type) ++ " Result = ", ""};
return_res1(#type{name=Type="wxArrayInt"}) ->
{Type ++ " Result = ", ""};
@@ -705,19 +727,19 @@ return_res1(#type{name=Type,base={class,_},single=list,ref=reference}) ->
return_res1(#type{name=Type,base={comp,_,_},single=array,by_val=true}) ->
{Type ++ " Result = ", ""};
return_res1(#type{name=Type,single=true,by_val=true, base={class, _}}) ->
- %% Memory leak !!!!!! XXXX BUGBUG FIXME or doument!!
- case Type of
+ %% Memory leak !!!!!! XXXX BUGBUG FIXME or doument!!
+ case Type of
"wxImage" -> ok;
"wxFont" -> ok;
"wxBitmap" -> ok;
"wxIcon" -> ok;
"wxGraphics" ++ _ -> ok;
_ ->
- io:format("~s::~s Building return value of temp ~s~n",
+ io:format("~s::~s Building return value of temp ~s~n",
[get(current_class),get(current_func),Type])
end,
%% #class{id=Id} = get({class,Type}),
- {Type ++ " * Result = new " ++ Type ++ "(", "); newPtr((void *) Result,"
+ {Type ++ " * Result = new " ++ Type ++ "(", "); newPtr((void *) Result,"
++ "3, memenv);"};
return_res1(#type{base={enum,_Type},single=true,by_val=true}) ->
{"int Result = " , ""};
@@ -730,7 +752,7 @@ return_res1(#type{name=Type,single=true,by_val=true}) ->
filter(Ps) ->
lists:filter(fun filter_arg/1, Ps).
-filter_arg(#param{where=erl}) -> false;
+filter_arg(#param{where=erl}) -> false;
filter_arg(#param{where=this}) -> false;
filter_arg(#param{}) -> true.
%%filter_arg(#param{def=Def, in=In}) -> Def =:= none orelse In =:= false.
@@ -739,20 +761,20 @@ filter_arg(#param{}) -> true.
call_arg(#param{where=c, alt={length,Alt}}) when is_list(Alt) ->
"*" ++ Alt ++ "Len";
call_arg(#param{where=c, alt={size,Id}}) when is_integer(Id) ->
- %% It's a binary
+ %% It's a binary
"Ecmd.bin["++ integer_to_list(Id) ++ "]->size";
-call_arg(#param{name=N,def=Def,type=#type{name=Type,by_val=true,single=true,base=Base}})
- when Base =:= int; Base =:= long; Base =:= float; Base =:= double; Base =:= bool ->
+call_arg(#param{name=N,def=Def,type=#type{name=Type,by_val=true,single=true,base=Base}})
+ when Base =:= int; Base =:= long; Base =:= float; Base =:= double; Base =:= bool ->
case Def of
none -> "(" ++ to_string(Type) ++ ") *" ++ N;
_ -> N
end;
-call_arg(#param{name=N,type=#type{base={enum,Type}, by_val=true,single=true}}) ->
+call_arg(#param{name=N,type=#type{base={enum,Type}, by_val=true,single=true}}) ->
"(" ++ enum_type(Type) ++") " ++ N;
call_arg(#param{name=N,type=#type{base={class,_},by_val=true,single=true}}) -> "*" ++ N;
call_arg(#param{name=N,type=#type{base={class,_},ref=reference,single=true}}) -> "*" ++ N;
-call_arg(#param{name=N,type=#type{base=eventType}}) ->
+call_arg(#param{name=N,type=#type{base=eventType}}) ->
N ++ ", (wxObjectEventFunction)(wxEventFunction) &WxeApp::handle_evt, Evt_cb, this";
call_arg(#param{name=N,type=#type{by_val=true, single=_False}}) -> N;
call_arg(#param{name=N,def=Def,type=#type{by_val=false, ref={pointer,2}}})
@@ -760,20 +782,20 @@ call_arg(#param{name=N,def=Def,type=#type{by_val=false, ref={pointer,2}}})
call_arg(#param{name=N,type=#type{by_val=false, ref={pointer,2}}}) -> "&" ++ N;
call_arg(#param{name=N,in=false,type=#type{ref=reference, single=true}}) -> N;
call_arg(#param{name=N,in=false,type=#type{by_val=false, single=true}}) -> "&" ++ N;
-call_arg(#param{name=N,def=Def,type=#type{base={comp,_,_},ref={pointer,1},single=true}})
+call_arg(#param{name=N,def=Def,type=#type{base={comp,_,_},ref={pointer,1},single=true}})
when Def =:= none ->
"&" ++N;
call_arg(#param{name=N,type=#type{by_val=false}}) -> N;
call_arg(#param{name=N,type={merged,_,#type{base={class,_},single=true,
by_val=ByVal,
- ref=Ref},_,_,_,_}})
- when ByVal =:= true; Ref =:= reference ->
+ ref=Ref},_,_,_,_}})
+ when ByVal =:= true; Ref =:= reference ->
"*" ++ N;
-call_arg(#param{def=Def, type=void}) when Def =/= none -> Def;
+call_arg(#param{def=Def, type=void}) when Def =/= none -> Def;
call_arg(#param{name=N,type=#type{base={ref,_},by_val=true,single=true}}) -> N;
call_arg(#param{name=N,type={merged,_,_,_,_,_,_}}) -> N.
-%% call_arg(#param{name=N,type=#type{base=Tuple,ref=reference}})
+%% call_arg(#param{name=N,type=#type{base=Tuple,ref=reference}})
%% when is_tuple(Tuple) -> "&" ++ N;
to_string(Type) when is_atom(Type) -> atom_to_list(Type);
@@ -781,19 +803,19 @@ to_string(Type) when is_list(Type) -> Type.
virtual_dest(#class{abstract=true, parent="root"}) -> false;
virtual_dest(#class{abstract=true, parent="object"}) -> true;
-virtual_dest(#class{abstract=true, parent=Parent}) ->
+virtual_dest(#class{abstract=true, parent=Parent}) ->
virtual_dest(get({class,Parent}));
virtual_dest(#class{methods=Ms, parent=Parent}) ->
case lists:keysearch(destructor,#method.method_type, lists:append(Ms)) of
{value, #method{method_type=destructor, virtual=Virtual}} ->
case Virtual of
- undefined ->
+ undefined ->
case get({class,Parent}) of
- undefined ->
+ undefined ->
case Parent of
- "object" ->
+ "object" ->
true;
- "root" ->
+ "root" ->
false;
_ ->
io:format("Error: ~p~n",[Parent]),
@@ -802,10 +824,10 @@ virtual_dest(#class{methods=Ms, parent=Parent}) ->
PClass ->
virtual_dest(PClass)
end;
- _ ->
+ _ ->
Virtual
end;
- false ->
+ false ->
false
end.
@@ -819,24 +841,24 @@ is_derived(#class{abstract=true}) -> false;
is_derived(C = #class{}) -> virtual_dest(C).
is_window(Class) ->
- lists:member("wxWindow", wx_gen_erl:parents(Class)).
+ lists:member("wxWindow", wx_gen_erl:parents(Class)).
is_dialog(Class) ->
lists:member("wxDialog", wx_gen_erl:parents(Class)).
-
+
build_return_vals(Type,Ps) ->
HaveType = case Type of void -> 0; _ -> 1 end,
NoOut = lists:sum([1 || #param{in=In} <- Ps, In =/= true]) + HaveType,
OutTupSz = if NoOut > 1 -> NoOut; true -> 0 end,
-
+
build_ret_types(Type,Ps),
- if
+ if
OutTupSz > 1 -> w(" rt.addTupleCount(~p);~n",[OutTupSz]);
true -> ignore
- end,
+ end,
Ps.
-build_ret_types(void,Ps) ->
+build_ret_types(void,Ps) ->
Calc = fun(#param{name=N,in=False,type=T}, Free) when False =/= true ->
case build_ret(N, False, T) of
ok -> Free;
@@ -845,7 +867,7 @@ build_ret_types(void,Ps) ->
(_, Free) -> Free
end,
lists:foldl(Calc, [], Ps);
-build_ret_types(Type,Ps) ->
+build_ret_types(Type,Ps) ->
Free = case build_ret("Result", out, Type) of
ok -> [];
FreeStr -> [FreeStr]
@@ -854,8 +876,8 @@ build_ret_types(Type,Ps) ->
case build_ret(N, False, T) of
ok -> FreeAcc;
FreeMe -> [FreeMe|FreeAcc]
- end;
- (_, FreeAcc) -> FreeAcc
+ end;
+ (_, FreeAcc) -> FreeAcc
end,
lists:foldl(Calc, Free, Ps).
@@ -898,17 +920,17 @@ build_ret(Name,_,#type{name="wxArrayInt"}) ->
build_ret(Name,_,#type{base={comp,_,_},single=array}) ->
w(" for(unsigned int i=0; i < ~s.GetCount(); i++) {~n", [Name]),
w(" rt.add(~s[i]);~n }~n",[Name]),
- w(" rt.endList(~s.GetCount());~n",[Name]);
+ w(" rt.endList(~s.GetCount());~n",[Name]);
build_ret(Name,_,#type{name=List,single=list,base={class,Class}}) ->
w(" int i=0;~n"),
w(" for(~s::const_iterator it = ~s.begin(); it != ~s.end(); ++it) {~n",
[List, Name, Name]),
w(" ~s * ~sTmp = *it;~n", [Class,Name]),
w(" rt.addRef(getRef((void *)~sTmp,memenv), \"~s\"); i++;}~n",[Name,Class]),
- w(" rt.endList(~s.GetCount());~n",[Name]);
-
+ w(" rt.endList(~s.GetCount());~n",[Name]);
+
build_ret(Name,_,#type{name="wxArrayTreeItemIds"}) ->
- w(" for(unsigned int i=0; i < ~s.GetCount(); i++) {~n", [Name]),
+ w(" for(unsigned int i=0; i < ~s.GetCount(); i++) {~n", [Name]),
w(" rt.add((wxUIntPtr *)~s[i].m_pItem);}~n",[Name]),
w(" rt.endList(~s.GetCount());~n",[Name]);
@@ -923,10 +945,10 @@ build_ret(Name,_,#type{name="wxArrayString", single=array}) ->
w(" rt.add(~s);~n", [Name]);
build_ret(Name,In,T) ->
?error({nyi, Name,In, T}).
-
+
mods([const|R]) -> "const " ++ mods(R);
mods([unsigned|R]) -> "unsigned " ++ mods(R);
-mods([]) -> "".
+mods([]) -> "".
build_enums() ->
Tree = get(consts),
@@ -935,13 +957,13 @@ build_enums() ->
w("#include \"../wxe_impl.h\"~n"),
w("#include \"wxe_macros.h\"~n"),
w("#include \"../wxe_return.h\"~n"),
- w("void WxeApp::init_nonconsts(wxeMemEnv *memenv, ErlDrvTermData caller) {~n"),
+ w("void WxeApp::init_nonconsts(wxeMemEnv *memenv, ErlDrvTermData caller) {~n"),
NotConsts = [NC || NC = #const{is_const=false} <- gb_trees:values(Tree)],
Size = length(NotConsts),
GVars = get(gvars),
GSize = length(GVars),
w(" wxeReturn rt = wxeReturn(WXE_DRV_PORT, caller);~n"),
- w(" rt.addAtom((char*)\"wx_consts\");~n"),
+ w(" rt.addAtom((char*)\"wx_consts\");~n"),
[build_enum(NConst) || NConst <- lists:keysort(#const.val, NotConsts)],
_Cnt = foldl(fun(Gvar, I) -> build_gvar(Gvar,I) end, 0, lists:sort(GVars)),
w(" rt.endList(~p);~n", [Size+GSize]),
@@ -968,9 +990,9 @@ build_gvar({Name, Class, _Id}, Cnt) ->
Cnt+1.
gen_macros() ->
- w("#include <wx/caret.h>~n"), %% Arrg wxw forgot?? some files
- w("#include <wx/tooltip.h>~n"),
- w("#include <wx/gbsizer.h>~n"),
+ w("#include <wx/caret.h>~n"), %% Arrg wxw forgot?? some files
+ w("#include <wx/tooltip.h>~n"),
+ w("#include <wx/gbsizer.h>~n"),
w("#include <wx/splash.h>~n"),
w("#include <wx/grid.h>~n"),
w("#include <wx/image.h>~n"),
@@ -995,15 +1017,15 @@ gen_macros() ->
w("#include <wx/stc/stc.h>~n"),
w("#include <wx/minifram.h>~n"),
w("#include <wx/sashwin.h>~n"),
- w("#include <wx/laywin.h>~n"),
- w("#include <wx/graphics.h>~n"),
- w("#include <wx/aui/aui.h>~n"),
- w("#include <wx/datectrl.h>~n"),
- w("#include <wx/filepicker.h>~n"),
- w("#include <wx/fontpicker.h>~n"),
- w("#include <wx/clrpicker.h>~n"),
- w("#include <wx/statline.h>~n"),
- w("#include <wx/clipbrd.h>~n"),
+ w("#include <wx/laywin.h>~n"),
+ w("#include <wx/graphics.h>~n"),
+ w("#include <wx/aui/aui.h>~n"),
+ w("#include <wx/datectrl.h>~n"),
+ w("#include <wx/filepicker.h>~n"),
+ w("#include <wx/fontpicker.h>~n"),
+ w("#include <wx/clrpicker.h>~n"),
+ w("#include <wx/statline.h>~n"),
+ w("#include <wx/clipbrd.h>~n"),
w("#include <wx/splitter.h>~n"),
w("#include <wx/choicebk.h>~n"),
w("#include <wx/toolbook.h>~n"),
@@ -1012,14 +1034,15 @@ gen_macros() ->
w("#include <wx/html/htmlwin.h>~n"),
w("#include <wx/html/htmlcell.h>~n"),
w("#include <wx/filename.h>~n"),
-
+ w("#include <wx/sysopt.h>~n"),
+
w("~n~n", []),
w("#ifndef wxICON_DEFAULT_BITMAP_TYPE~n",[]),
w(" #define wxICON_DEFAULT_BITMAP_TYPE wxBITMAP_TYPE_ICO_RESOURCE~n",[]),
w("#endif~n", []),
w("~n~n", []),
- [w("#define ~s_~s ~p~n", [Class,Name,Id]) ||
+ [w("#define ~s_~s ~p~n", [Class,Name,Id]) ||
{Class,Name,_,Id} <- wx_gen_erl:get_unique_names()],
w("~n~n").
@@ -1032,29 +1055,29 @@ build_events() ->
w("#include \"wxe_macros.h\"~n"),
w("#include \"../wxe_events.h\"~n~n"),
w("#include \"../wxe_return.h\"~n~n"),
-
+
w("wxeEtype::wxeEtype(const char *name, int Id) {eName = name;cID = Id;}~n~n"),
w("WX_DECLARE_HASH_MAP(int, wxeEtype*, wxIntegerHash, wxIntegerEqual, wxeETmap );~n~n"),
-
+
w("wxeETmap etmap;~n~n"),
-
+
w(
"int wxeEventTypeFromAtom(char *etype_atom) {
wxeETmap::iterator it;
for(it = etmap.begin(); it != etmap.end(); ++it) {
wxeEtype * value = it->second;
- if(strcmp(value->eName, etype_atom) == 0) {
- if(it->first > wxEVT_USER_FIRST) {
+ if(strcmp(value->eName, etype_atom) == 0) {
+ if(it->first > wxEVT_USER_FIRST) {
return it->first - wxEVT_USER_FIRST;
} else {
return it->first;
}
}
- }
- return -1;
+ }
+ return -1;
}
-"),
+"),
Evs0 = [C || {_,C=#class{event=Evs}} <- get(), Evs =/= false],
Evs = lists:keysort(#class.id, Evs0),
@@ -1067,7 +1090,7 @@ initEventTable(Evs) ->
w(" struct { ",[]),
w("int ev_type; int class_id; const char * ev_name;} event_types[] =~n {~n",[]),
- lists:foreach(fun(Ev) -> init_event_classes(Ev) end,
+ lists:foreach(fun(Ev) -> init_event_classes(Ev) end,
[#class{id=0,event=[wxEVT_NULL]}|Evs]),
w(" {-1, 0, ""}~n };~n",[]),
w(" for(int i=0; event_types[i].ev_type != -1; i++) {~n",[]),
@@ -1085,7 +1108,7 @@ initEventTable(Evs) ->
" }~n"
" }~n", []),
w("}~n~n").
-
+
init_event_classes(#class{event=ETs, id=Id}) ->
F = fun({Eev, Cev, OtherClass}) ->
w(" {~w + wxEVT_USER_FIRST, ~w, ~p},~n",
@@ -1105,7 +1128,7 @@ find_id(OtherClass) ->
Class = get({class,atom_to_list(OtherClass)}),
%%{value, Class} = lists:keysearch(atom_to_list(OtherClass), #class.name, All),
Class#class.id.
-
+
encode_events(Evs) ->
?WTC("encode_events"),
w("void wxeEvtListener::forward(wxEvent& event)~n"
@@ -1132,7 +1155,7 @@ encode_events(Evs) ->
" wxeMemEnv *memenv = app->getMemEnv(port);~n"
" if(!memenv) return 0;~n~n"
" wxeReturn rt = wxeReturn(port, cb->listener);~n"),
-
+
w("~n rt.addAtom((char*)\"wx\");~n"
" rt.addInt((int) event->GetId());~n"
" rt.addRef(getRef((void *)(cb->obj), memenv), cb->class_name);~n"
@@ -1155,15 +1178,15 @@ encode_events(Evs) ->
w(" app->clearPtr((void *) event);~n"),
w(" } else {~n"),
w(" send_res = rt.send();~n"),
- w(" if(cb->skip) event->Skip();~n"),
+ w(" if(cb->skip) event->Skip();~n"),
w(" };~n"),
w(" return send_res;~n"),
w(" }~n").
encode_event(C = #class{name=Class, id=Id, options=Opts}) ->
?WTC("encode_event"),
- case proplists:get_value("mixed_event", Opts) of
- undefined ->
+ case proplists:get_value("mixed_event", Opts) of
+ undefined ->
w("case ~p: {// ~s~n", [Id,Class]),
encode_event2(C),
ok;
@@ -1189,10 +1212,10 @@ encode_event2(Class = #class{name=Name}) ->
build_event_attrs(ClassRec = #class{name=Class}) ->
Attrs0 = wx_gen_erl:filter_attrs(ClassRec),
- Rename =
- fun(Att = #param{name=Name,prot=public,acc=undefined}, {All,Use}) ->
+ Rename =
+ fun(Att = #param{name=Name,prot=public,acc=undefined}, {All,Use}) ->
{[Att#param{name= "ev->" ++ Name}|All],Use};
- (Att = #param{acc=Acc}, {All,_}) ->
+ (Att = #param{acc=Acc}, {All,_}) ->
{[Att#param{name= "ev->" ++ Acc}|All], true}
end,
case foldr(Rename,{[],false},Attrs0) of
@@ -1202,9 +1225,9 @@ build_event_attrs(ClassRec = #class{name=Class}) ->
%% Attrs;
{Attrs,_} ->
w(" ~s * ev = (~s *) event;~n",[Class,Class]),
- FixClass =
+ FixClass =
fun(P=#param{name=N,acc=Acc,type=#type{single=Single,by_val=ByVal,
- base={class,C}}})
+ base={class,C}}})
when Acc =/= undefined ->
Var = var_name(N),
if Single, ByVal ->
@@ -1215,17 +1238,17 @@ build_event_attrs(ClassRec = #class{name=Class}) ->
end,
P#param{name=Var};
(P) -> P
- end,
+ end,
lists:map(FixClass, Attrs)
end.
-var_name("ev->" ++ Name0) ->
+var_name("ev->" ++ Name0) ->
case reverse(Name0) of
")(" ++ Name -> reverse(Name);
_ -> Name0
end;
var_name(Name) -> Name.
-
+
enum_name({Class,Type}) ->
uppercase_all(Class ++ "_" ++ Type);
enum_name(Type) ->
diff --git a/lib/wx/api_gen/wx_gen_erl.erl b/lib/wx/api_gen/wx_gen_erl.erl
index e1201ab0d4..5d73d93ead 100644
--- a/lib/wx/api_gen/wx_gen_erl.erl
+++ b/lib/wx/api_gen/wx_gen_erl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,7 +19,7 @@
%%%-------------------------------------------------------------------
%%% File : wx_gen_erl.erl
%%% Author : Dan Gudmundsson <[email protected]>
-%%% Description :
+%%% Description :
%%%
%%% Created : 25 Jan 2007 by Dan Gudmundsson <[email protected]>
%%%-------------------------------------------------------------------
@@ -32,7 +32,7 @@
-import(lists, [foldl/3,foldr/3,reverse/1, keysearch/3, map/2, filter/2]).
-import(gen_util, [lowercase/1, lowercase_all/1, uppercase/1, uppercase_all/1,
- open_write/1, close/0, erl_copyright/0, w/2,
+ open_write/1, close/0, erl_copyright/0, w/2,
args/3, args/4, strip_name/2]).
gen(Defs) ->
@@ -42,9 +42,9 @@ gen(Defs) ->
gen_enums_ints(),
[gen_class(Class) || Class <- Defs],
gen_funcnames().
-
+
gen_class(Class) ->
- try
+ try
gen_class1(Class)
catch throw:skipped ->
Class
@@ -52,10 +52,10 @@ gen_class(Class) ->
gen_class1(C=#class{name=Name,parent="static",methods=Ms,options=_Opts}) ->
open_write("../src/gen/wx_misc.erl"),
- put(current_class, Name),
+ put(current_class, Name),
erl_copyright(),
w("", []),
- w("%% This file is generated DO NOT EDIT~n~n", []),
+ w("%% This file is generated DO NOT EDIT~n~n", []),
w("%% @doc See external documentation: "
"<a href=\"http://www.wxwidgets.org/manuals/stable/wx_miscellany.html\">Misc</a>.\n\n",[]),
@@ -67,8 +67,8 @@ gen_class1(C=#class{name=Name,parent="static",methods=Ms,options=_Opts}) ->
Exp = fun(M) -> gen_export(C,M) end,
ExportList = lists:usort(lists:append(lists:map(Exp,reverse(Ms)))),
w("-export([~s]).~n~n", [args(fun(EF) -> EF end, ",", ExportList, 60)]),
-
-
+
+
Gen = fun(M) -> gen_method(Name,M) end,
NewMs = lists:map(Gen,reverse(Ms)),
close(),
@@ -79,13 +79,13 @@ gen_class1(C=#class{name=Name,parent=Parent,methods=Ms,options=Opts}) ->
case Opts of
["ignore"] -> throw(skipped);
_ -> ok
- end,
+ end,
open_write("../src/gen/"++Name++".erl"),
- put(current_class, Name),
+ put(current_class, Name),
erl_copyright(),
w("", []),
- w("%% This file is generated DO NOT EDIT~n~n", []),
-
+ w("%% This file is generated DO NOT EDIT~n~n", []),
+
case lists:member(taylormade, Opts) of
true ->
{ok, Bin} = file:read_file(filename:join([wx_extra, Name++".erl"])),
@@ -95,33 +95,33 @@ gen_class1(C=#class{name=Name,parent=Parent,methods=Ms,options=Opts}) ->
w("%% @doc See external documentation: "
"<a href=\"http://www.wxwidgets.org/manuals/stable/wx_~s.html\">~s</a>.\n",
[lowercase_all(Name), Name]),
-
+
case C#class.doc of
undefined -> ignore;
Str -> w("%%~n%% ~s~n~n%%~n", [Str])
end,
-
+
case C#class.event of
false -> ignore;
Evs ->
EvTypes = [event_type_name(Ev) || Ev <- Evs],
EvStr = args(fun(Ev) -> "<em>"++Ev++"</em>" end, ", ", EvTypes),
-
+
w("%% <dl><dt>Use {@link wxEvtHandler:connect/3.} with EventType:</dt>~n",[]),
w("%% <dd>~s</dd></dl>~n", [EvStr]),
- w("%% See also the message variant {@link wxEvtHandler:~s(). #~s{}} event record type.~n",
+ w("%% See also the message variant {@link wxEvtHandler:~s(). #~s{}} event record type.~n",
[event_rec_name(Name),event_rec_name(Name)]),
w("%%~n",[]),
ok
end,
-
+
Parents = parents(Parent),
case [P || P <- Parents, P =/= root, P =/= object] of
[] -> ignore;
- Ps ->
+ Ps ->
w("%% <p>This class is derived (and can use functions) from:~n", []),
[w("%% <br />{@link ~s}~n", [P]) || P <- Ps],
- w("%% </p>~n",[])
+ w("%% </p>~n",[])
end,
w("%% @type ~s(). An object reference, The representation is internal~n",[Name]),
w("%% and can be changed without notice. It can't be used for comparsion~n", []),
@@ -137,17 +137,17 @@ gen_class1(C=#class{name=Name,parent=Parent,methods=Ms,options=Opts}) ->
Done0 = ["Destroy", "New", "Create", "destroy", "new", "create"],
Done = gb_sets:from_list(Done0 ++ [M|| #method{name=M} <- lists:append(Ms)]),
{_, InExported} = gen_inherited(Parents, Done, []),
- w("-export([~s]).~n~n", [args(fun(EF) -> EF end, ",",
- lists:usort(["parent_class/1"|InExported]),
+ w("-export([~s]).~n~n", [args(fun(EF) -> EF end, ",",
+ lists:usort(["parent_class/1"|InExported]),
60)]),
-
+
w("%% @hidden~n", []),
parents_check(Parents),
-
+
Gen = fun(M) -> gen_method(Name,M) end,
NewMs = lists:map(Gen,reverse(Ms)),
- gen_dest(C, Ms),
-
+ gen_dest(C, Ms),
+
gen_inherited(Parents, Done, true)
end,
@@ -203,26 +203,26 @@ gen_export(#class{name=Class,abstract=Abs},Ms0) ->
[] -> [];
[M=#method{where=taylormade}|_] ->
[taylormade_export(Class, M)];
- Ms ->
+ Ms ->
GetF = fun(#method{method_type=constructor,where=W,params=Ps}) ->
{Args,Opts} = split_optional(Ps),
- OptLen = case Opts of
- [] -> 0;
+ OptLen = case Opts of
+ [] -> 0;
_ when W =:= erl_no_opt -> 0;
- _ -> 1
+ _ -> 1
end,
"new/" ++ integer_to_list(length(Args)+OptLen);
(#method{method_type=destructor}) ->
- case Abs of
- true -> [];
+ case Abs of
+ true -> [];
_ -> "destroy/1"
end;
(#method{name=N,alias=A,where=W, params=Ps}) ->
{Args,Opts} = split_optional(Ps),
- OptLen = case Opts of
- [] -> 0;
+ OptLen = case Opts of
+ [] -> 0;
_ when W =:= erl_no_opt -> 0;
- _ -> 1
+ _ -> 1
end,
erl_func_name(N,A) ++ "/" ++ integer_to_list(length(Args) + OptLen)
end,
@@ -235,10 +235,10 @@ gen_method(Class,Ms0) ->
Res = filter(RemoveC, Ms0),
case Res of
[] -> Ms0;
- [M=#method{where=taylormade}|_] ->
- taylormade_func(Class, M),
+ [#method{where=taylormade}|_] ->
+ taylormade_func(Class, Res),
Ms0;
- Ms ->
+ Ms ->
gen_doc(Class,Ms),
gen_method1(Ms),
Ms0
@@ -279,22 +279,22 @@ gen_method2(M=#method{name=N,alias=A,params=Ps,type=T,method_type=MT,id=MethodId
ignore -> skip;
_ -> w(" _Result =", [])
end,
-
+
case have_return_vals(T, Ps) of
_ when MT =:= constructor ->
w(" wxe_util:construct(~s,~n <<~s~s>>)", [MId, MArgs,MOpts]);
true ->
w(" wxe_util:call(~s,~n <<~s~s>>)", [MId, MArgs,MOpts]);
- false ->
+ false ->
w(" wxe_util:cast(~s,~n <<~s~s>>)", [MId, MArgs,MOpts])
end,
case gen_util:get_hook(erl, M#method.post_hook) of
ignore -> skip;
- Post ->
+ Post ->
w(",~n ~s~n", [Post]),
w(" _Result", [])
end,
-
+
erase(current_func),
M.
@@ -306,9 +306,9 @@ gen_dest(#class{name=CName,abstract=Abs}, Ms) ->
case lists:keysearch(destructor,#method.method_type, lists:append(Ms)) of
{value, #method{method_type=destructor, id=Id}} ->
case hd(reverse(parents(CName))) of
- object ->
+ object ->
gen_dest2(CName, object);
- root ->
+ root ->
gen_dest2(CName, Id)
end;
false ->
@@ -320,7 +320,7 @@ gen_dest2(Class, Id) ->
w("%% @spec (This::~s()) -> ok~n", [Class]),
w("%% @doc Destroys this object, do not use object again~n", []),
w("destroy(Obj=#wx_ref{type=Type}) ->~n", []),
- w(" ?CLASS(Type,~s),~n",[Class]),
+ w(" ?CLASS(Type,~s),~n",[Class]),
case Id of
object ->
w(" wxe_util:destroy(?DESTROY_OBJECT,Obj),~n ok.~n", []);
@@ -341,14 +341,14 @@ gen_inherited([Parent|Ps], Done0, Exported0) ->
gen_inherited(Ps, gb_sets:union(Done,Done0), Exported).
gen_inherited_ms([[#method{name=Name,alias=A,params=Ps0,where=W,method_type=MT}|_]|R],
- Class,Skip,Done, Exported)
- when W =/= merged_c ->
+ Class,Skip,Done, Exported)
+ when W =/= merged_c ->
case gb_sets:is_member(Name,Skip) of
false when MT =:= member, Exported =:= true ->
Ps = [patch_param(P,all) || P <- Ps0],
Opts = if W =:= erl_no_opt -> [];
- true ->
- [Opt || Opt = #param{def=Def,in=In, where=Where} <- Ps,
+ true ->
+ [Opt || Opt = #param{def=Def,in=In, where=Where} <- Ps,
Def =/= none, In =/= false, Where =/= c]
end,
w("%% @hidden~n", []),
@@ -359,10 +359,10 @@ gen_inherited_ms([[#method{name=Name,alias=A,params=Ps0,where=W,method_type=MT}|
gen_inherited_ms(R,Class, Skip, gb_sets:add(Name,Done), Exported);
false when MT =:= member, is_list(Exported) ->
{Args,Opts} = split_optional(Ps0),
- OptLen = case Opts of
- [] -> 0;
+ OptLen = case Opts of
+ [] -> 0;
_ when W =:= erl_no_opt -> 0;
- _ -> 1
+ _ -> 1
end,
Export = erl_func_name(Name,A) ++ "/" ++ integer_to_list(length(Args) + OptLen),
gen_inherited_ms(R,Class,Skip, gb_sets:add(Name,Done), [Export|Exported]);
@@ -374,17 +374,21 @@ gen_inherited_ms([[_|Check]|R],Class,Skip, Done0,Exp) ->
gen_inherited_ms([[]|R],Class,Skip,Done0,Exp) ->
gen_inherited_ms(R,Class,Skip,Done0,Exp);
gen_inherited_ms([], _, _Skip, Done,Exp) -> {Done,Exp}.
-
+
%%%%%%%%%%%%%%%
-taylormade_func(Class, #method{name=Name, id=Id}) ->
+taylormade_func(Class, [#method{name=Name, id=Id}|_]) ->
{ok, Bin} = file:read_file(filename:join([wx_extra, Class ++".erl"])),
- Str0 = binary_to_list(Bin),
- {match, [Str1]} = re:run(Str0, "<<"++Name++"(.*)"++Name++">>",
- [dotall, {capture, all_but_first, list}]),
-
- w(Str1, ["?" ++ get_unique_name(Id)]),
+ Src = binary_to_list(Bin),
+ Str = case gen_util:get_taylor_made(Src, Name) of
+ nomatch ->
+ {match, [Str0]} = gen_util:get_taylor_made(Src, get_unique_name(Id)),
+ Str0;
+ {match, [Str0]} ->
+ Str0
+ end,
+ w(Str, ["?" ++ get_unique_name(Id)]),
ok.
taylormade_export(Class, #method{name=Name}) ->
@@ -398,12 +402,12 @@ taylormade_export(Class, #method{name=Name}) ->
arg_type_tests([P|Ps], Mid0) ->
case arg_type_test(P,"\n",Mid0) of
- Mid0 ->
+ Mid0 ->
arg_type_tests(Ps, Mid0);
Mid -> %% Already checked the other args
Mid
end;
-arg_type_tests([],Mid) -> Mid.
+arg_type_tests([],Mid) -> Mid.
arg_type_test(#param{where=c}, _, Acc) ->
Acc;
@@ -412,7 +416,7 @@ arg_type_test(#param{name=Name0,in=In,type=#type{base={class,T},single=true},def
Name = erl_arg_name(Name0),
w(" ?CLASS(~sT,~s),~s", [Name,T,EOS]),
Acc;
-arg_type_test(#param{name=Name0,in=In,type=#type{base={class,T}}, def=none},EOS,Acc)
+arg_type_test(#param{name=Name0,in=In,type=#type{base={class,T}}, def=none},EOS,Acc)
when In =/= false ->
Name = erl_arg_name(Name0),
w(" [?CLASS(~sT,~s) || #wx_ref{type=~sT} <- ~s],~s", [Name,T,Name,Name,EOS]),
@@ -420,35 +424,35 @@ arg_type_test(#param{name=Name0,in=In,type=#type{base={class,T}}, def=none},EOS,
arg_type_test(#param{name=Name0,def=none,in=In,
type={merged,
M1, #type{base={class,T1},single=true},Ps1,
- M2, #type{base={class,T2},single=true},Ps2}}, EOS, _Acc)
+ M2, #type{base={class,T2},single=true},Ps2}}, EOS, _Acc)
when In =/= false ->
Name = erl_arg_name(Name0),
Opname = Name++"OP",
w(" ~s = case ?CLASS_T(~sT,~s) of~n true ->\n ", [Opname,Name,T1]),
- lists:foreach(fun(Param) -> arg_type_test(Param,"\n ", ignore) end,
+ lists:foreach(fun(Param) -> arg_type_test(Param,"\n ", ignore) end,
element(1,split_optional(Ps1))),
w("?~s;~n",[get_unique_name(M1)]),
w(" _ -> ?CLASS(~sT,~s),\n ",[Name,T2]),
{Ps21,_} = split_optional(patchArgName(Ps2,Ps1)),
- lists:foreach(fun(Param) -> arg_type_test(Param,"\n ", ignore) end,
+ lists:foreach(fun(Param) -> arg_type_test(Param,"\n ", ignore) end,
Ps21),
w("?~s\n end,~s",[get_unique_name(M2),EOS]),
Opname;
-arg_type_test(#param{name=Name0, type=#type{base=eventType}}, EOS, Acc) ->
+arg_type_test(#param{name=Name0, type=#type{base=eventType}}, EOS, Acc) ->
Name = erl_arg_name(Name0),
w(" ~sBin = list_to_binary([atom_to_list(~s)|[0]]),~s", [Name,Name,EOS]),
w(" ThisTypeBin = list_to_binary([atom_to_list(ThisT)|[0]]),~s", [EOS]),
Acc;
-arg_type_test(#param{name=Name0,def=none,type=#type{base={term,_}}}, EOS, Acc) ->
+arg_type_test(#param{name=Name0,def=none,type=#type{base={term,_}}}, EOS, Acc) ->
Name = erl_arg_name(Name0),
w(" wxe_util:send_bin(term_to_binary(~s)),~s", [Name,EOS]),
Acc;
-arg_type_test(#param{name=Name0,type=#type{base=binary}},EOS,Acc) ->
+arg_type_test(#param{name=Name0,type=#type{base=binary}},EOS,Acc) ->
Name = erl_arg_name(Name0),
w(" wxe_util:send_bin(~s),~s", [Name,EOS]),
Acc;
-arg_type_test(#param{name=Name0,type=#type{name=Type,base=Base,single=Single}},EOS,Acc) ->
- if
+arg_type_test(#param{name=Name0,type=#type{name=Type,base=Base,single=Single}},EOS,Acc) ->
+ if
Type =:= "wxArtClient", Single =:= true ->
Name = erl_arg_name(Name0),
w(" ~s_UC = unicode:characters_to_binary([~s, $_, $C,0]),~s",
@@ -458,11 +462,11 @@ arg_type_test(#param{name=Name0,type=#type{name=Type,base=Base,single=Single}},E
w(" ~s_UC = unicode:characters_to_binary([~s,0]),~s", [Name,Name,EOS]);
Type =:= "wxArrayString" ->
Name = erl_arg_name(Name0),
- w(" ~s_UCA = [unicode:characters_to_binary([~sTemp,0]) || ~s",
+ w(" ~s_UCA = [unicode:characters_to_binary([~sTemp,0]) || ~s",
[Name,Name, EOS]),
w(" ~sTemp <- ~s],~s", [Name,Name,EOS]);
true -> %% Not a string
- ignore
+ ignore
end,
Acc;
arg_type_test(_,_,Acc) -> Acc.
@@ -476,10 +480,10 @@ have_return_vals(void, Ps) ->
have_return_vals(#type{}, _) -> true.
gen_function_clause(Name0,MT,Ps,Optional,Variant) ->
- PArg = fun(Arg) ->
+ PArg = fun(Arg) ->
case lists:member(name_only, Variant) of
true -> func_arg_name(Arg);
- false ->
+ false ->
case lists:member(name_type, Variant) of
true ->
Name = func_arg_name(Arg),
@@ -495,17 +499,17 @@ gen_function_clause(Name0,MT,Ps,Optional,Variant) ->
Args = args(PArg, ",", Ps),
Name = case MT of constructor -> "new"; _ -> Name0 end,
w("~s(~s",[Name,Args]),
- Opts = case Optional of
+ Opts = case Optional of
[] -> "";
empty_list when Args =:= [] -> "[]";
empty_list -> ", []";
_ when Args =:= [] -> "Options";
- _ -> ", Options"
+ _ -> ", Options"
end,
w("~s)", [Opts]),
case lists:member(no_guards, Variant) of
true -> ok;
- false ->
+ false ->
Guards = args(fun guard_test/1, ",", Ps),
if
Guards =:= [], Opts =:= "" -> w(" ->~n", []);
@@ -517,10 +521,10 @@ gen_function_clause(Name0,MT,Ps,Optional,Variant) ->
split_optional(Ps) ->
split_optional(Ps, [], []).
-split_optional([P=#param{def=Def,in=In, where=Where}|Ps], Standard, Opts)
+split_optional([P=#param{def=Def,in=In, where=Where}|Ps], Standard, Opts)
when Def =/= none, In =/= false, Where =/= c ->
split_optional(Ps, Standard, [P|Opts]);
-split_optional([P=#param{def=Def,in=In, where=Where}|Ps], Standard, Opts)
+split_optional([P=#param{def=Def,in=In, where=Where}|Ps], Standard, Opts)
when Def =:= none, In =/= false, Where =/= c ->
split_optional(Ps, [P|Standard], Opts);
split_optional([_|Ps], Standard, Opts) ->
@@ -532,24 +536,24 @@ patch_param(P=#param{type=#type{base=Tuple}}, all) when is_tuple(Tuple) ->
P#param{type={class,ignore}};
patch_param(P=#param{type={merged,_,_,_,_,_,_}}, _) ->
P#param{type={class,ignore}};
-patch_param(P=#param{type=#type{base={class,_}}},_) ->
+patch_param(P=#param{type=#type{base={class,_}}},_) ->
P#param{type={class,ignore}};
-patch_param(P=#param{type=#type{base={ref,_}}},_) ->
+patch_param(P=#param{type=#type{base={ref,_}}},_) ->
P#param{type={class,ignore}};
patch_param(P,_) -> P.
func_arg_name(#param{def=Def}) when Def =/= none -> skip;
func_arg_name(#param{in=false}) -> skip;
func_arg_name(#param{where=c}) -> skip;
-func_arg_name(#param{name=Name}) ->
+func_arg_name(#param{name=Name}) ->
erl_arg_name(Name).
func_arg(#param{def=Def}) when Def =/= none -> skip;
func_arg(#param{in=false}) -> skip;
func_arg(#param{where=c}) -> skip;
-func_arg(#param{name=Name,type=#type{base=string}}) ->
+func_arg(#param{name=Name,type=#type{base=string}}) ->
erl_arg_name(Name);
-func_arg(#param{name=Name,type=#type{name="wxArrayString"}}) ->
+func_arg(#param{name=Name,type=#type{name="wxArrayString"}}) ->
erl_arg_name(Name);
func_arg(#param{name=Name0,type=#type{base={class,_CN}, single=true}}) ->
Name = erl_arg_name(Name0),
@@ -570,7 +574,7 @@ func_arg(#param{name=Name,type=#type{base={comp,"wxDateTime",_Tup}, single=true}
func_arg(#param{name=Name,type=#type{name="wxArtClient", single=true}}) ->
erl_arg_name(Name);
func_arg(#param{name=Name,type=#type{base={comp,_,Tup}, single=true}}) ->
- N = erl_arg_name(Name),
+ N = erl_arg_name(Name),
Doc = fun({_,V}) -> erl_arg_name(N)++V end,
"{" ++ args(Doc, ",", Tup) ++ "}";
func_arg(#param{name=Name}) ->
@@ -587,7 +591,7 @@ guard_test(#param{name=N, type=#type{name="wxArtClient"}}) ->
"is_list(" ++ erl_arg_name(N) ++")";
guard_test(#param{name=N, type=#type{name="wxArrayString"}}) ->
"is_list(" ++ erl_arg_name(N) ++")";
-guard_test(#param{name=Name,type=#type{single=Single}})
+guard_test(#param{name=Name,type=#type{single=Single}})
when Single =/= true->
"is_list(" ++ erl_arg_name(Name) ++ ")";
guard_test(#param{name=N,type=#type{base=int}}) ->
@@ -637,42 +641,42 @@ gen_doc(_Class,[#method{name=N,alias=A,params=Ps,type=T,where=erl_no_opt,method_
gen_function_clause(erl_func_name(N,A),MT,Ps,empty_list,[no_guards,name_only]);
gen_doc(Class,[#method{name=N,params=Ps,type=T}])->
{_, Optional} = split_optional(Ps),
- NonDef = [Arg || Arg = #param{def=Def,in=In, where=Where} <- Ps,
+ NonDef = [Arg || Arg = #param{def=Def,in=In, where=Where} <- Ps,
Def =:= none, In =/= false, Where =/= c],
OptsType = case Optional of
[] -> "";
_ when NonDef =:= [] -> "[Option]";
- _ -> ", [Option]"
+ _ -> ", [Option]"
end,
w("%% @spec (~s~s) -> ~s~n",
[doc_arg_types(Ps),OptsType,doc_return_types(T,Ps)]),
doc_optional(Optional, normal),
- DocEnum = doc_enum(T,Ps, normal),
+ DocEnum = doc_enum(T,Ps, normal),
case Class of
"utils" ->
w("%% @doc See <a href=\"http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#~s\">"
- "external documentation</a>.~n",
+ "external documentation</a>.~n",
[lowercase_all(N)]);
_ ->
w("%% @doc See <a href=\"http://www.wxwidgets.org/manuals/stable/wx_~s.html#~s~s\">"
- "external documentation</a>.~n",
+ "external documentation</a>.~n",
[lowercase_all(Class),lowercase_all(Class),lowercase_all(N)])
end,
doc_enum_desc(DocEnum);
gen_doc(Class, Cs = [#method{name=N, alias=A,method_type=MT}|_]) ->
- GetRet = fun(#method{params=Ps,type=T}) ->
+ GetRet = fun(#method{params=Ps,type=T}) ->
doc_return_types(T,Ps)
end,
- GetArgs = fun(#method{params=Ps, where=Where}) ->
+ GetArgs = fun(#method{params=Ps, where=Where}) ->
Opt = case Where of
erl_no_opt -> [];
- _ ->
+ _ ->
case split_optional(Ps) of
{_, []} -> [];
_ -> ["[Option]"]
end
end,
- [doc_arg_type(P) ||
+ [doc_arg_type(P) ||
P=#param{in=In,def=none,where=W} <- Ps,
In =/= false, W =/= c] ++ Opt
end,
@@ -682,16 +686,16 @@ gen_doc(Class, Cs = [#method{name=N, alias=A,method_type=MT}|_]) ->
case Class of
"utils" ->
w("%% @doc See <a href=\"http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#~s\">"
- "external documentation</a>.~n",
+ "external documentation</a>.~n",
[lowercase_all(N)]);
_ ->
w("%% @doc See <a href=\"http://www.wxwidgets.org/manuals/stable/wx_~s.html#~s~s\">"
- "external documentation</a>.~n",
+ "external documentation</a>.~n",
[lowercase_all(Class),lowercase_all(Class),lowercase_all(N)])
end,
Name = case MT of constructor -> "new"; _ -> erl_func_name(N,A) end,
w("%% <br /> Alternatives:~n",[]),
- [gen_doc2(Name, Clause) || Clause <- Cs],
+ [gen_doc2(Name, Clause) || Clause <- Cs],
ok.
gen_doc2(Name,#method{params=Ps,where=erl_no_opt,method_type=MT}) ->
@@ -704,11 +708,11 @@ gen_doc2(Name,#method{params=Ps,type=T}) ->
OptsType = case Optional of
[] -> "";
_ when NonDef =:= [] -> "[Option]";
- _ -> ", [Option]"
+ _ -> ", [Option]"
end,
w("%% <p><c>~n",[]),
w("%% ~s(~s~s) -> ~s </c>~n",
- [Name,doc_arg_types(Ps),OptsType,doc_return_types(T,Ps)]),
+ [Name,doc_arg_types(Ps),OptsType,doc_return_types(T,Ps)]),
doc_optional(Optional, xhtml),
DocEnum = doc_enum(T,Ps, xhtml),
doc_enum_desc(DocEnum),
@@ -717,7 +721,7 @@ gen_doc2(Name,#method{params=Ps,type=T}) ->
doc_arg(ArgList) ->
case all_eq(ArgList) of
true -> hd(ArgList);
- false ->
+ false ->
Get = fun(Str) ->
[_Name|Types] = string:tokens(Str, ":"),
case Types of
@@ -734,12 +738,12 @@ doc_arg(ArgList) ->
doc_ret(ArgList) ->
case all_eq(ArgList) of
true -> hd(ArgList);
- false ->
+ false ->
args(fun(A) -> A end, "|", ArgList)
end.
unique([], U) -> reverse(U);
-unique([H|R], U) ->
+unique([H|R], U) ->
case lists:member(H,U) of
false -> unique(R,[H|U]);
true -> unique(R,U)
@@ -756,7 +760,7 @@ zip(List) ->
zip([[F|L1]|List], Rest, AccL, Acc) ->
zip(List, [L1|Rest], [F|AccL], Acc);
-zip(Empty, Rest, AccL, Acc) ->
+zip(Empty, Rest, AccL, Acc) ->
true = empty(Empty),
case empty(Rest) andalso empty(AccL) of
true -> reverse(Acc);
@@ -779,7 +783,7 @@ doc_arg_type(_) -> skip.
doc_arg_type2(T=#type{single=Single}) when Single =:= array; Single =:= list ->
"[" ++ doc_arg_type3(T) ++ "]";
-doc_arg_type2(T) ->
+doc_arg_type2(T) ->
doc_arg_type3(T).
doc_arg_type3(#type{base=string}) -> "string()";
@@ -799,8 +803,8 @@ doc_arg_type3(#type{base={binary,_}}) -> "binary()";
doc_arg_type3(#type{base=eventType}) -> "atom()";
doc_arg_type3(#type{base={ref,N}}) -> N++"()";
doc_arg_type3(#type{base={term,_N}}) -> "term()";
-doc_arg_type3(T=#type{base={class,N}}) ->
- check_class(T),
+doc_arg_type3(T=#type{base={class,N}}) ->
+ check_class(T),
case get(current_class) of
N -> N ++ "()";
_ -> N++":" ++ N++"()"
@@ -809,7 +813,7 @@ doc_arg_type3({merged,_,T1=#type{base={class,N1}},_,_,T2=#type{base={class,N2}},
check_class(T1),
check_class(T2),
Curr = get(current_class),
- if
+ if
N1 =:= Curr, N2 =:= Curr -> N1++"() | "++ N2++"()";
N1 =:= Curr -> N1++"() | "++ N2++":" ++ N2++"()";
N2 =:= Curr -> N1++":" ++ N1++"() | "++ N2++"()";
@@ -824,9 +828,9 @@ doc_arg_type3(#type{base={comp,_,{record,Name}}}) ->
"wx:" ++ atom_to_list(Name) ++ "()";
doc_arg_type3(#type{base={comp,_,Tup}}) ->
Doc = fun({int,V}) -> V ++ "::integer()";
- ({double,V}) -> V ++ "::float()"
+ ({double,V}) -> V ++ "::float()"
end,
- "{" ++ args(Doc, ",", Tup) ++ "}";
+ "{" ++ args(Doc, ", ", Tup) ++ "}";
doc_arg_type3(T) -> ?error({unknown_type,T}).
doc_return_types(T, Ps) ->
@@ -834,10 +838,10 @@ doc_return_types(T, Ps) ->
doc_return_types2(void, []) -> "ok";
doc_return_types2(void, [#param{type=T}]) -> doc_arg_type2(T);
doc_return_types2(T, []) -> doc_arg_type2(T);
-doc_return_types2(void, Ps) ->
- "{" ++ args(fun doc_arg_type/1,",",Ps) ++ "}";
+doc_return_types2(void, Ps) ->
+ "{" ++ args(fun doc_arg_type/1,", ",Ps) ++ "}";
doc_return_types2(T, Ps) ->
- "{" ++ doc_arg_type2(T) ++ "," ++ args(fun doc_arg_type/1,",",Ps) ++ "}".
+ "{" ++ doc_arg_type2(T) ++ ", " ++ args(fun doc_arg_type/1,", ",Ps) ++ "}".
break(xhtml) -> "<br />";
break(_) -> "".
@@ -887,7 +891,7 @@ check_name(Name) -> Name.
marshal_opts([], _,_) -> ""; %% No opts skip this!
marshal_opts(Opts, Align, Args) ->
- w(" MOpts = fun", []),
+ w(" MOpts = fun", []),
marshal_opts1(Opts,1),
w(";~n (BadOpt, _) -> erlang:error({badoption, BadOpt}) end,~n", []),
w(" BinOpt = list_to_binary(lists:foldl(MOpts, [<<0:32>>], Options)),~n", []),
@@ -896,7 +900,7 @@ marshal_opts(Opts, Align, Args) ->
[] -> Str; % All Args are optional
_ -> ", " ++ Str
end.
-
+
marshal_opts1([P],N) ->
marshal_opt(P,N);
marshal_opts1([P|R],N) ->
@@ -909,15 +913,15 @@ marshal_opt(P0=#param{name=Name,type=Type},N) ->
{Arg,Align} = marshal_arg(Type,erl_arg_name(Name),1),
AStr = if Align =:= 0 -> "";
Align =:= 1 -> ",0:32"
- end,
- w("({~s, ~s}, Acc) -> ", [erl_option_name(Name), func_arg(P)]),
+ end,
+ w("({~s, ~s}, Acc) -> ", [erl_option_name(Name), func_arg(P)]),
arg_type_test(P,"",[]),
case Arg of
- skip ->
+ skip ->
w("[<<~p:32/?UI~s>>|Acc]", [N, AStr]);
- _ ->
+ _ ->
w("[<<~p:32/?UI,~s~s>>|Acc]", [N, Arg,AStr])
- end.
+ end.
marshal_args(Ps) ->
marshal_args(Ps, [], 0).
@@ -957,23 +961,23 @@ marshal_arg(#type{single=true,base={enum,_Enum}}, Name, Align) ->
marshal_arg(#type{single=true,base=bool}, Name, Align) ->
align(32, Align, "(wxe_util:from_bool(" ++ Name ++ ")):32/?UI");
-marshal_arg(#type{name="wxChar", single=Single}, Name, Align0)
+marshal_arg(#type{name="wxChar", single=Single}, Name, Align0)
when Single =/= true ->
- {Str,Align} =
+ {Str,Align} =
align(32,Align0, "(byte_size("++Name++"_UC)):32/?UI,(" ++ Name ++ "_UC)/binary"),
MsgSize = "(" ++ integer_to_list(Align*4)++"+byte_size("++Name++"_UC))",
{Str++", 0:(((8- (" ++ MsgSize ++" band 16#7)) band 16#7))/unit:8",0};
marshal_arg(#type{base=string}, Name, Align0) ->
- {Str,Align} =
+ {Str,Align} =
align(32,Align0, "(byte_size("++Name++"_UC)):32/?UI,(" ++ Name ++ "_UC)/binary"),
MsgSize = "(" ++ integer_to_list(Align*4)++"+byte_size("++Name++"_UC))",
{Str++", 0:(((8- (" ++ MsgSize ++" band 16#7)) band 16#7))/unit:8",0};
marshal_arg(#type{name="wxArrayString"}, Name, Align0) ->
- InnerBin = "<<(byte_size(UC_Str)):32/?UI, UC_Str/binary>>",
+ InnerBin = "<<(byte_size(UC_Str)):32/?UI, UC_Str/binary>>",
Outer = "(<< " ++ InnerBin ++ "|| UC_Str <- "++ Name ++"_UCA>>)/binary",
Str0 = "(length("++Name++"_UCA)):32/?UI, " ++ Outer,
{Str,Align} = align(32,Align0,Str0),
- MsgSize = "("++integer_to_list(Align*4) ++
+ MsgSize = "("++integer_to_list(Align*4) ++
" + lists:sum([byte_size(S)+4||S<-" ++ Name ++"_UCA]))",
AStr = ", 0:(((8- (" ++ MsgSize ++" band 16#7)) band 16#7))/unit:8",
{Str ++ AStr, 0};
@@ -997,15 +1001,15 @@ marshal_arg(#type{base={term,_}}, _Name, Align0) ->
{skip,Align0};
marshal_arg(#type{base=binary}, _Name, Align0) ->
{skip,Align0};
-marshal_arg(#type{base=Base, single=Single}, Name, Align0)
+marshal_arg(#type{base=Base, single=Single}, Name, Align0)
when Single =/= true ->
- case Base of
- int ->
+ case Base of
+ int ->
Str0 = "(length("++Name++")):32/?UI,\n"
" (<< <<C:32/?I>> || C <- "++Name++">>)/binary",
{Str,Align} = align(32,Align0, Str0),
{Str ++ ", 0:((("++integer_to_list(Align)++"+length("++Name++ ")) rem 2)*32)", 0};
- {ObjRef,_} when ObjRef =:= class; ObjRef =:= ref ->
+ {ObjRef,_} when ObjRef =:= class; ObjRef =:= ref ->
Str0 = "(length("++Name++")):32/?UI,",
Str1 = "\n (<< <<(C#wx_ref.ref):32/?UI>> || C <- "++Name++">>)/binary",
{Str2,Align} = align(32, Align0, Str1),
@@ -1033,7 +1037,7 @@ align(64, 0, Str) -> {Str, 0};
align(64, 1, Str) -> {"0:32," ++ Str,0};
align(Sz, W, Str) -> align(Sz, W rem 2, Str).
-enum_name(Name) ->
+enum_name(Name) ->
case string:tokens(Name, ":") of
[Name] -> Name;
[C,N] -> C ++ "_" ++ N
@@ -1053,10 +1057,10 @@ gen_enums_ints() ->
" }).~n", []),
w("~n%% Hardcoded Defines~n", []),
Enums = [E || {{enum,_},E = #enum{as_atom=false}} <- get()],
- w("-define(wxDefaultSize, {-1,-1}).~n", []),
- w("-define(wxDefaultPosition, {-1,-1}).~n", []),
+ w("-define(wxDefaultSize, {-1,-1}).~n", []),
+ w("-define(wxDefaultPosition, {-1,-1}).~n", []),
w("~n%% Global Variables~n", []),
- [w("-define(~s, wxe_util:get_const(~s)).~n", [Gvar, Gvar]) ||
+ [w("-define(~s, wxe_util:get_const(~s)).~n", [Gvar, Gvar]) ||
{Gvar,_,_Id} <- get(gvars)],
w("~n%% Enum and defines~n", []),
foldl(fun(Enum= #enum{vals=Vals}, Done) when Vals =/= [] ->
@@ -1076,7 +1080,7 @@ build_enum_ints(#enum{from=From, vals=Vals},Done) ->
{_File, Class, Name} ->
w("% From class ~s::~s~n",[Class, Name])
end,
-
+
Format = fun(#const{name="wxEVT_" ++ _}) ->
ignore; %% Ignore event macros they are not valid in our event model
(#const{name=Name,val=Value,is_const=true}) when is_integer(Value) ->
@@ -1100,12 +1104,12 @@ build_enum_ints(#enum{from=From, vals=Vals},Done) ->
Consts = get(consts),
Write = fun({Name,_What}, Skip) ->
case gb_sets:is_member(Name,Skip) of
- true ->
+ true ->
Skip;
false ->
case gb_trees:lookup(Name, Consts) of
{value, Const} ->
- Format(Const),
+ Format(Const),
gb_sets:add(Name,Skip);
none -> Skip
end
@@ -1119,8 +1123,8 @@ gen_event_recs() ->
w("", []),
w("%% This file is generated DO NOT EDIT~n~n", []),
w("%% All event messages are encapsulated in a wx record~n"
- "%% they contain the widget id and a specialized event record.~n"
- "%% Each event record may be sent for one or more event types.~n"
+ "%% they contain the widget id and a specialized event record.~n"
+ "%% Each event record may be sent for one or more event types.~n"
"%% The mapping to wxWidgets is one record per class.~n~n",[]),
w("%% @type wx() = #wx{id=integer(), obj=wx:wxObject(), userData=term(), event=Rec}. Rec is a event record.~n",[]),
w("-record(wx, {id, %% Integer Identity of object.~n"
@@ -1130,7 +1134,7 @@ gen_event_recs() ->
w("%% Here comes the definitions of all event records.~n"
"%% they contain the event type and possible some extra information.~n~n",[]),
Types = [build_event_rec(C) || {_,C=#class{event=Evs}} <- get(), Evs =/= false],
- w("%% @type wxEventType() = ~s.~n",
+ w("%% @type wxEventType() = ~s.~n",
[args(fun(Ev) -> Ev end, " | ", lists:sort(lists:append(Types)))]),
%% close(), closed in gen_enums_ints
ok.
@@ -1145,22 +1149,22 @@ find_inherited_attr(Param = {PName,_}, Name) ->
end.
filter_attrs(#class{name=Name, parent=Parent,attributes=Attrs}) ->
- Attr1 = lists:foldl(fun(#param{acc=skip},Acc) -> Acc;
+ Attr1 = lists:foldl(fun(#param{acc=skip},Acc) -> Acc;
(P=#param{prot=public},Acc) -> [P|Acc];
- (#param{acc=undefined},Acc) -> Acc;
+ (#param{acc=undefined},Acc) -> Acc;
({inherited, PName},Acc) ->
case find_inherited_attr(PName, Parent) of
- undefined ->
+ undefined ->
io:format("~p:~p: Missing Event Attr ~p in ~p~n",
[?MODULE,?LINE, PName, Name]),
Acc;
- P ->
+ P ->
[P|Acc]
end;
(P, Acc) -> [P|Acc]
end, [], Attrs),
lists:reverse(Attr1).
-
+
build_event_rec(Class=#class{name=Name, event=Evs}) ->
EvTypes = [event_type_name(Ev) || Ev <- Evs],
Str = args(fun(Ev) -> "<em>"++Ev++"</em>" end, ", ", EvTypes),
@@ -1168,26 +1172,26 @@ build_event_rec(Class=#class{name=Name, event=Evs}) ->
Rec = event_rec_name(Name),
GetName = fun(#param{name=N}) ->event_attr_name(N) end,
GetType = fun(#param{name=N,type=T}) ->
- event_attr_name(N) ++ "=" ++ doc_arg_type2(T)
+ event_attr_name(N) ++ "=" ++ doc_arg_type2(T)
end,
case Attr =:= [] of
- true ->
+ true ->
w("%% @type ~s() = #~s{type=wxEventType()}.~n", [Rec,Rec]),
w("%% <dl><dt>EventType:</dt> <dd>~s</dd></dl>~n",[Str]),
-%% case is_command_event(Name) of
+%% case is_command_event(Name) of
%% true -> w("%% This event skips other event handlers.~n",[]);
%% false -> w("%% This event will be handled by other handlers~n",[])
%% end,
w("%% Callback event: {@link ~s}~n", [Name]),
w("-record(~s, {type}).~n~n", [Rec]);
false ->
- w("%% @type ~s() = #~s{type=wxEventType(),~s}.~n",
+ w("%% @type ~s() = #~s{type=wxEventType(),~s}.~n",
[Rec,Rec,args(GetType,",",Attr)]),
w("%% <dl><dt>EventType:</dt> <dd>~s</dd></dl>~n",[Str]),
-%% case is_command_event(Name) of
+%% case is_command_event(Name) of
%% true -> w("%% This event skips other event handlers.~n",[]);
%% false -> w("%% This event will be handled by other handlers~n",[])
-%% end,
+%% end,
w("%% Callback event: {@link ~s}~n", [Name]),
w("-record(~s,{type, ~s}).~n~n", [Rec,args(GetName,",",Attr)])
end,
@@ -1198,7 +1202,7 @@ is_command_event(Name) ->
true -> true;
false -> false
end.
-
+
event_rec_name(Name0 = "wx" ++ _) ->
"tnevE" ++ Name1 = reverse(Name0),
reverse(Name1).
@@ -1215,7 +1219,7 @@ event_attr_name(Attr) ->
lowercase(Attr).
-gen_funcnames() ->
+gen_funcnames() ->
open_write("../src/gen/wxe_debug.hrl"),
erl_copyright(),
w("%% This file is generated DO NOT EDIT~n~n", []),
@@ -1257,7 +1261,7 @@ unique_names(Ms0, Class) ->
Ms = split_list(fun(#method{name=N}, M) -> {N =:= M, N} end, undefined, Ms2),
unique_names2(Ms,Class).
%% by Names
-unique_names2([[#method{id=Id, name=Method,alias=Alias, max_arity=A}]|Ms], Class) ->
+unique_names2([[#method{id=Id, name=Method,alias=Alias, max_arity=A}]|Ms], Class) ->
[{Class,uname(alias(Method,Alias),Class),A,Id} | unique_names2(Ms,Class)];
unique_names2([Ms0|RMs], Class) ->
Split = fun(#method{max_arity=A}, P) -> {A =:= P, A} end,
@@ -1278,11 +1282,11 @@ unique_names4([], _, _Class) -> [].
alias(Method, undefined) -> Method;
alias(_, Alias) -> Alias.
-
+
uname(Class,Class) -> "new";
uname([$~ | _], _ ) -> "destruct";
uname(Name, _) -> Name.
-
+
split_list(F, Keep, List) ->
split_list(F, Keep, List, []).
@@ -1297,5 +1301,5 @@ split_list(F, Keep, [M|Ms], Acc) ->
end;
split_list(_, _, [], []) -> [];
split_list(_, _, [], Acc) -> [lists:reverse(Acc)].
-
+
diff --git a/lib/wx/api_gen/wxapi.conf b/lib/wx/api_gen/wxapi.conf
index aec8a4944a..ff618faf04 100644
--- a/lib/wx/api_gen/wxapi.conf
+++ b/lib/wx/api_gen/wxapi.conf
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -756,7 +756,9 @@
'SetFirstItem']}.
{class, wxListCtrl, wxControl, [],
- ['wxListCtrl','~wxListCtrl','Arrange','AssignImageList','ClearAll','Create',
+ [{'wxListCtrl', [{where, taylormade}]},
+ '~wxListCtrl','Arrange','AssignImageList','ClearAll',
+ {'Create',[{where, taylormade}]},
'DeleteAllItems','DeleteColumn','DeleteItem',
{'EditLabel',[{"textControlClass",nowhere}]},
'EnsureVisible',
@@ -788,6 +790,13 @@
'SetFont','SetId','SetImage','SetMask','SetState',
'SetStateMask','SetText','SetTextColour','SetWidth']}.
+{class, wxListItemAttr, root, [],
+ ['wxListItemAttr','~wxListItemAttr',
+ 'GetBackgroundColour', 'GetFont',
+ 'GetTextColour', 'HasBackgroundColour', 'HasFont',
+ 'HasTextColour', 'SetBackgroundColour', 'SetFont', 'SetTextColour'
+ ]}.
+
{class, wxImageList, object, [{skip, [{'Create',1}]}], %% No create/0 on windows
['wxImageList','~wxImageList','Add','Create','Draw','GetBitmap','GetIcon','GetImageCount',
'GetSize','Remove','RemoveAll','Replace']}.
@@ -1746,6 +1755,9 @@
'GetColour','GetFont','GetMetric','GetScreenType'
]}.
+{class, wxSystemOptions, object, [],
+ ['GetOption', 'GetOptionInt', 'HasOption', 'IsFalse', 'SetOption']}.
+
{class, wxAuiNotebookEvent, wxNotifyEvent,
[{acc, [{old_selection, "GetOldSelection()"},
{selection, "GetSelection()"},
diff --git a/lib/wx/c_src/egl_impl.cpp b/lib/wx/c_src/egl_impl.cpp
index e2dbbb73c4..1379f07523 100644
--- a/lib/wx/c_src/egl_impl.cpp
+++ b/lib/wx/c_src/egl_impl.cpp
@@ -1,20 +1,20 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 2010. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 2011. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
- * %CopyrightEnd%
+ *
+ * %CopyrightEnd%
*/
#include <stdio.h>
@@ -35,8 +35,8 @@ void init_tess();
void exit_tess();
int load_gl_functions();
-/* ****************************************************************************
- * OPENGL INITIALIZATION
+/* ****************************************************************************
+ * OPENGL INITIALIZATION
*****************************************************************************/
int egl_initiated = 0;
@@ -51,7 +51,7 @@ void * dlsym(HMODULE Lib, const char *func) {
void * funcp;
if((funcp = (void *) GetProcAddress(Lib, func)))
return funcp;
- else
+ else
return (void *) wglGetProcAddress(func);
}
@@ -70,17 +70,17 @@ typedef char DL_CHAR;
# define OPENGL_LIB "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib"
# define OPENGLU_LIB "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLU.dylib"
# else
-# define OPENGL_LIB "libGL.so"
-# define OPENGLU_LIB "libGLU.so"
+# define OPENGL_LIB "libGL.so.1"
+# define OPENGLU_LIB "libGLU.so.1"
# endif
-#endif
+#endif
extern "C" {
-DRIVER_INIT(EGL_DRIVER) {
+DRIVER_INIT(EGL_DRIVER) {
return NULL;
}
}
-int egl_init_opengl(void *erlCallbacks)
+int egl_init_opengl(void *erlCallbacks)
{
#ifdef _WIN32
driver_init((TWinDynDriverCallbacks *) erlCallbacks);
@@ -95,7 +95,7 @@ int egl_init_opengl(void *erlCallbacks)
}
int load_gl_functions() {
- DL_CHAR * DLName = OPENGL_LIB;
+ DL_CHAR * DLName = (DL_CHAR *) OPENGL_LIB;
DL_LIB_P LIBhandle = dlopen(DLName, RTLD_LAZY);
//fprintf(stderr, "Loading GL: %s\r\n", (const char*)DLName);
void * func = NULL;
@@ -121,19 +121,19 @@ int load_gl_functions() {
}
}
}
- dlclose(LIBhandle);
+ // dlclose(LIBhandle);
// fprintf(stderr, "OPENGL library is loaded\r\n");
} else {
fprintf(stderr, "Could NOT load OpenGL library: %s\r\n", DLName);
};
- DLName = OPENGLU_LIB;
+ DLName = (DL_CHAR *) OPENGLU_LIB;
LIBhandle = dlopen(DLName, RTLD_LAZY);
// fprintf(stderr, "Loading GLU: %s\r\n", (const char*)DLName);
func = NULL;
if(LIBhandle) {
- for(i=0; glu_fns[i].name != NULL; i++) {
+ for(i=0; glu_fns[i].name != NULL; i++) {
if((func = dlsym(LIBhandle, glu_fns[i].name))) {
* (void **) (glu_fns[i].func) = func;
} else {
@@ -150,7 +150,7 @@ int load_gl_functions() {
}
}
}
- dlclose(LIBhandle);
+ // dlclose(LIBhandle);
// fprintf(stderr, "GLU library is loaded\r\n");
} else {
fprintf(stderr, "Could NOT load OpenGL GLU library: %s\r\n", DLName);
@@ -195,13 +195,13 @@ egl_ogla_error(GLenum errorCode)
// msg.Printf(wxT("Tesselation error: %d: "), (int)errorCode);
// msg += wxString::FromAscii((char *) err);
// send_msg("error", &msg);
- fprintf(stderr, "Tesselation error: %d\r\n", (int) errorCode);
+ fprintf(stderr, "Tesselation error: %d: %s\r\n", (int) errorCode, err);
}
void CALLBACK
egl_ogla_combine(GLdouble coords[3],
void* vertex_data[4],
- GLfloat w[4],
+ GLfloat w[4],
void **dataOut)
{
GLdouble* vertex = tess_alloc_vertex;
@@ -226,7 +226,7 @@ egl_ogla_combine(GLdouble coords[3],
*dataOut = vertex;
}
-void init_tess()
+void init_tess()
{
tess = gluNewTess();
@@ -237,7 +237,7 @@ void init_tess()
}
-void exit_tess()
+void exit_tess()
{
gluDeleteTess(tess);
}
@@ -250,23 +250,23 @@ int erl_tess_impl(char* buff, ErlDrvPort port, ErlDrvTermData caller)
int *vertices;
int num_vertices;
GLdouble *n;
- int n_pos, AP, res;
-
+ int n_pos, AP;
+
num_vertices = * (int *) buff; buff += 8; /* Align */
n = (double *) buff; buff += 8*3;
- bin = driver_alloc_binary(num_vertices*6*sizeof(GLdouble));
+ bin = driver_alloc_binary(num_vertices*6*sizeof(GLdouble));
new_vertices = tess_coords = (double *) bin->orig_bytes;
memcpy(tess_coords,buff,num_vertices*3*sizeof(GLdouble));
tess_alloc_vertex = tess_coords + num_vertices*3;
#if 0
fprintf(stderr, "n=%d\r\n", num_vertices);
-#endif
+#endif
vertices = (int *) driver_alloc(sizeof(int) * 16*num_vertices);
-
+
tess_vertices = vertices;
-
+
gluTessNormal(tess, n[0], n[1], n[2]);
gluTessBeginPolygon(tess, 0);
gluTessBeginContour(tess);
@@ -275,9 +275,9 @@ int erl_tess_impl(char* buff, ErlDrvPort port, ErlDrvTermData caller)
}
gluTessEndContour(tess);
gluTessEndPolygon(tess);
-
- n_pos = (tess_vertices - vertices);
-
+
+ n_pos = (tess_vertices - vertices);
+
AP = 0; ErlDrvTermData *rt;
rt = (ErlDrvTermData *) driver_alloc(sizeof(ErlDrvTermData) * (13+n_pos*2));
rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
@@ -287,13 +287,13 @@ int erl_tess_impl(char* buff, ErlDrvPort port, ErlDrvTermData caller)
};
rt[AP++] = ERL_DRV_NIL; rt[AP++] = ERL_DRV_LIST; rt[AP++] = n_pos+1;
- rt[AP++] = ERL_DRV_BINARY; rt[AP++] = (ErlDrvTermData) bin;
+ rt[AP++] = ERL_DRV_BINARY; rt[AP++] = (ErlDrvTermData) bin;
rt[AP++] = (tess_alloc_vertex-new_vertices)*sizeof(GLdouble); rt[AP++] = 0;
-
+
rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2; // Return tuple {list, Bin}
rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2; // Result tuple
-
- res = driver_send_term(port,caller,rt,AP);
+
+ driver_send_term(port,caller,rt,AP);
/* fprintf(stderr, "List %d: %d %d %d \r\n", */
/* res, */
/* n_pos, */
diff --git a/lib/wx/c_src/gen/wxe_derived_dest.h b/lib/wx/c_src/gen/wxe_derived_dest.h
index ad46a98c90..4e4aea098d 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-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -362,10 +362,22 @@ class EwxListBox : public wxListBox {
EwxListBox() : wxListBox() {};
};
+
class EwxListCtrl : public wxListCtrl {
- public: ~EwxListCtrl() {((WxeApp *)wxTheApp)->clearPtr(this);};
+ public: ~EwxListCtrl();
EwxListCtrl(wxWindow * parent,wxWindowID winid,const wxPoint& pos,const wxSize& size,long style,const wxValidator& validator) : wxListCtrl(parent,winid,pos,size,style,validator) {};
EwxListCtrl() : wxListCtrl() {};
+
+ int onGetItemText;
+ int onGetItemAttr;
+ int onGetItemColumnImage;
+ ErlDrvPort port;
+
+ private:
+ virtual wxString OnGetItemText(long item, long col) const;
+ virtual wxListItemAttr* OnGetItemAttr(long item) const;
+ virtual int OnGetItemImage(long item) const;
+ virtual int OnGetItemColumnImage(long item, long column) const;
};
class EwxListItem : public wxListItem {
@@ -715,28 +727,3 @@ class EwxHtmlWindow : public wxHtmlWindow {
EwxHtmlWindow() : wxHtmlWindow() {};
};
-void WxeApp::delete_object(void *ptr, wxeRefData *refd) {
- switch(refd->type) {
- case 24: delete (wxGridCellBoolRenderer *) ptr; break;
- case 25: delete (wxGridCellBoolEditor *) ptr; break;
- case 26: delete (wxGridCellFloatRenderer *) ptr; break;
- case 27: delete (wxGridCellFloatEditor *) ptr; break;
- case 28: delete (wxGridCellStringRenderer *) ptr; break;
- case 29: delete (wxGridCellTextEditor *) ptr; break;
- case 30: delete (wxGridCellChoiceEditor *) ptr; break;
- case 31: delete (wxGridCellNumberRenderer *) ptr; break;
- case 32: delete (wxGridCellNumberEditor *) ptr; break;
- case 61: delete (wxIconBundle *) ptr; break;
- case 69: delete (wxAcceleratorEntry *) ptr; break;
- case 70: /* delete (wxCaret *) ptr;These objects must be deleted by owner object */ break;
- case 72: delete (wxSizerFlags *) ptr; break;
- case 88: /* delete (wxCalendarDateAttr *) ptr;These objects must be deleted by owner object */ break;
- case 102: delete (wxTextAttr *) ptr; break;
- case 154: delete (wxAuiPaneInfo *) ptr; break;
- case 211: /* delete (wxFileDataObject *) ptr;These objects must be deleted by owner object */ break;
- case 212: /* delete (wxTextDataObject *) ptr;These objects must be deleted by owner object */ break;
- case 213: /* delete (wxBitmapDataObject *) ptr;These objects must be deleted by owner object */ break;
- case 223: delete (wxLogNull *) ptr; break;
- default: delete (wxObject *) ptr;
-}}
-
diff --git a/lib/wx/c_src/gen/wxe_events.cpp b/lib/wx/c_src/gen/wxe_events.cpp
index 692eef858c..cda98bfc3f 100644
--- a/lib/wx/c_src/gen/wxe_events.cpp
+++ b/lib/wx/c_src/gen/wxe_events.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -37,15 +37,15 @@ int wxeEventTypeFromAtom(char *etype_atom) {
wxeETmap::iterator it;
for(it = etmap.begin(); it != etmap.end(); ++it) {
wxeEtype * value = it->second;
- if(strcmp(value->eName, etype_atom) == 0) {
- if(it->first > wxEVT_USER_FIRST) {
+ if(strcmp(value->eName, etype_atom) == 0) {
+ if(it->first > wxEVT_USER_FIRST) {
return it->first - wxEVT_USER_FIRST;
} else {
return it->first;
}
}
- }
- return -1;
+ }
+ return -1;
}
void initEventTable()
@@ -53,254 +53,254 @@ void initEventTable()
struct { int ev_type; int class_id; const char * ev_name;} event_types[] =
{
{wxEVT_NULL, 0, "null"},
- {wxEVT_COMMAND_BUTTON_CLICKED, 163, "command_button_clicked"},
- {wxEVT_COMMAND_CHECKBOX_CLICKED, 163, "command_checkbox_clicked"},
- {wxEVT_COMMAND_CHOICE_SELECTED, 163, "command_choice_selected"},
- {wxEVT_COMMAND_LISTBOX_SELECTED, 163, "command_listbox_selected"},
- {wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, 163, "command_listbox_doubleclicked"},
- {wxEVT_COMMAND_TEXT_UPDATED, 163, "command_text_updated"},
- {wxEVT_COMMAND_TEXT_ENTER, 163, "command_text_enter"},
- {wxEVT_COMMAND_MENU_SELECTED, 163, "command_menu_selected"},
- {wxEVT_COMMAND_SLIDER_UPDATED, 163, "command_slider_updated"},
- {wxEVT_COMMAND_RADIOBOX_SELECTED, 163, "command_radiobox_selected"},
- {wxEVT_COMMAND_RADIOBUTTON_SELECTED, 163, "command_radiobutton_selected"},
- {wxEVT_COMMAND_SCROLLBAR_UPDATED, 163, "command_scrollbar_updated"},
- {wxEVT_COMMAND_VLBOX_SELECTED, 163, "command_vlbox_selected"},
- {wxEVT_COMMAND_COMBOBOX_SELECTED, 163, "command_combobox_selected"},
- {wxEVT_COMMAND_TOOL_RCLICKED, 163, "command_tool_rclicked"},
- {wxEVT_COMMAND_TOOL_ENTER, 163, "command_tool_enter"},
- {wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, 163, "command_checklistbox_toggled"},
- {wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, 163, "command_togglebutton_clicked"},
- {wxEVT_COMMAND_LEFT_CLICK, 163, "command_left_click"},
- {wxEVT_COMMAND_LEFT_DCLICK, 163, "command_left_dclick"},
- {wxEVT_COMMAND_RIGHT_CLICK, 163, "command_right_click"},
- {wxEVT_COMMAND_SET_FOCUS, 163, "command_set_focus"},
- {wxEVT_COMMAND_KILL_FOCUS, 163, "command_kill_focus"},
- {wxEVT_COMMAND_ENTER, 163, "command_enter"},
- {wxEVT_SCROLL_TOP, 164, "scroll_top"},
- {wxEVT_SCROLL_BOTTOM, 164, "scroll_bottom"},
- {wxEVT_SCROLL_LINEUP, 164, "scroll_lineup"},
- {wxEVT_SCROLL_LINEDOWN, 164, "scroll_linedown"},
- {wxEVT_SCROLL_PAGEUP, 164, "scroll_pageup"},
- {wxEVT_SCROLL_PAGEDOWN, 164, "scroll_pagedown"},
- {wxEVT_SCROLL_THUMBTRACK, 164, "scroll_thumbtrack"},
- {wxEVT_SCROLL_THUMBRELEASE, 164, "scroll_thumbrelease"},
- {wxEVT_SCROLL_CHANGED, 164, "scroll_changed"},
- {wxEVT_SCROLLWIN_TOP, 165, "scrollwin_top"},
- {wxEVT_SCROLLWIN_BOTTOM, 165, "scrollwin_bottom"},
- {wxEVT_SCROLLWIN_LINEUP, 165, "scrollwin_lineup"},
- {wxEVT_SCROLLWIN_LINEDOWN, 165, "scrollwin_linedown"},
- {wxEVT_SCROLLWIN_PAGEUP, 165, "scrollwin_pageup"},
- {wxEVT_SCROLLWIN_PAGEDOWN, 165, "scrollwin_pagedown"},
- {wxEVT_SCROLLWIN_THUMBTRACK, 165, "scrollwin_thumbtrack"},
- {wxEVT_SCROLLWIN_THUMBRELEASE, 165, "scrollwin_thumbrelease"},
- {wxEVT_LEFT_DOWN, 166, "left_down"},
- {wxEVT_LEFT_UP, 166, "left_up"},
- {wxEVT_MIDDLE_DOWN, 166, "middle_down"},
- {wxEVT_MIDDLE_UP, 166, "middle_up"},
- {wxEVT_RIGHT_DOWN, 166, "right_down"},
- {wxEVT_RIGHT_UP, 166, "right_up"},
- {wxEVT_MOTION, 166, "motion"},
- {wxEVT_ENTER_WINDOW, 166, "enter_window"},
- {wxEVT_LEAVE_WINDOW, 166, "leave_window"},
- {wxEVT_LEFT_DCLICK, 166, "left_dclick"},
- {wxEVT_MIDDLE_DCLICK, 166, "middle_dclick"},
- {wxEVT_RIGHT_DCLICK, 166, "right_dclick"},
- {wxEVT_MOUSEWHEEL, 166, "mousewheel"},
- {wxEVT_NC_LEFT_DOWN, 166, "nc_left_down"},
- {wxEVT_NC_LEFT_UP, 166, "nc_left_up"},
- {wxEVT_NC_MIDDLE_DOWN, 166, "nc_middle_down"},
- {wxEVT_NC_MIDDLE_UP, 166, "nc_middle_up"},
- {wxEVT_NC_RIGHT_DOWN, 166, "nc_right_down"},
- {wxEVT_NC_RIGHT_UP, 166, "nc_right_up"},
- {wxEVT_NC_MOTION, 166, "nc_motion"},
- {wxEVT_NC_ENTER_WINDOW, 166, "nc_enter_window"},
- {wxEVT_NC_LEAVE_WINDOW, 166, "nc_leave_window"},
- {wxEVT_NC_LEFT_DCLICK, 166, "nc_left_dclick"},
- {wxEVT_NC_MIDDLE_DCLICK, 166, "nc_middle_dclick"},
- {wxEVT_NC_RIGHT_DCLICK, 166, "nc_right_dclick"},
- {wxEVT_SET_CURSOR, 167, "set_cursor"},
- {wxEVT_CHAR, 168, "char"},
- {wxEVT_CHAR_HOOK, 168, "char_hook"},
- {wxEVT_KEY_DOWN, 168, "key_down"},
- {wxEVT_KEY_UP, 168, "key_up"},
- {wxEVT_SIZE, 169, "size"},
- {wxEVT_MOVE, 170, "move"},
- {wxEVT_PAINT, 171, "paint"},
- {wxEVT_PAINT_ICON, 171, "paint_icon"},
- {wxEVT_NC_PAINT, 172, "nc_paint"},
- {wxEVT_ERASE_BACKGROUND, 173, "erase_background"},
- {wxEVT_SET_FOCUS, 174, "set_focus"},
- {wxEVT_KILL_FOCUS, 174, "kill_focus"},
- {wxEVT_CHILD_FOCUS, 175, "child_focus"},
- {wxEVT_MENU_OPEN, 176, "menu_open"},
- {wxEVT_MENU_CLOSE, 176, "menu_close"},
- {wxEVT_MENU_HIGHLIGHT, 176, "menu_highlight"},
- {wxEVT_CLOSE_WINDOW, 177, "close_window"},
- {wxEVT_END_SESSION, 177, "end_session"},
- {wxEVT_QUERY_END_SESSION, 177, "query_end_session"},
- {wxEVT_SHOW, 178, "show"},
- {wxEVT_ICONIZE, 179, "iconize"},
- {wxEVT_MAXIMIZE, 180, "maximize"},
- {wxEVT_JOY_BUTTON_DOWN, 181, "joy_button_down"},
- {wxEVT_JOY_BUTTON_UP, 181, "joy_button_up"},
- {wxEVT_JOY_MOVE, 181, "joy_move"},
- {wxEVT_JOY_ZMOVE, 181, "joy_zmove"},
- {wxEVT_UPDATE_UI, 182, "update_ui"},
- {wxEVT_SYS_COLOUR_CHANGED, 183, "sys_colour_changed"},
- {wxEVT_MOUSE_CAPTURE_CHANGED, 184, "mouse_capture_changed"},
- {wxEVT_DISPLAY_CHANGED, 185, "display_changed"},
- {wxEVT_PALETTE_CHANGED, 186, "palette_changed"},
- {wxEVT_QUERY_NEW_PALETTE, 187, "query_new_palette"},
- {wxEVT_NAVIGATION_KEY, 188, "navigation_key"},
- {wxEVT_CREATE, 189, "create"},
- {wxEVT_DESTROY, 190, "destroy"},
- {wxEVT_HELP, 191, "help"},
- {wxEVT_DETAILED_HELP, 191, "detailed_help"},
- {wxEVT_CONTEXT_MENU, 192, "context_menu"},
- {wxEVT_IDLE, 193, "idle"},
- {wxEVT_GRID_CELL_LEFT_CLICK, 194, "grid_cell_left_click"},
- {wxEVT_GRID_CELL_RIGHT_CLICK, 194, "grid_cell_right_click"},
- {wxEVT_GRID_CELL_LEFT_DCLICK, 194, "grid_cell_left_dclick"},
- {wxEVT_GRID_CELL_RIGHT_DCLICK, 194, "grid_cell_right_dclick"},
- {wxEVT_GRID_LABEL_LEFT_CLICK, 194, "grid_label_left_click"},
- {wxEVT_GRID_LABEL_RIGHT_CLICK, 194, "grid_label_right_click"},
- {wxEVT_GRID_LABEL_LEFT_DCLICK, 194, "grid_label_left_dclick"},
- {wxEVT_GRID_LABEL_RIGHT_DCLICK, 194, "grid_label_right_dclick"},
- {wxEVT_GRID_ROW_SIZE, 194, "grid_row_size"},
- {wxEVT_GRID_COL_SIZE, 194, "grid_col_size"},
- {wxEVT_GRID_RANGE_SELECT, 194, "grid_range_select"},
- {wxEVT_GRID_CELL_CHANGE, 194, "grid_cell_change"},
- {wxEVT_GRID_SELECT_CELL, 194, "grid_select_cell"},
- {wxEVT_GRID_EDITOR_SHOWN, 194, "grid_editor_shown"},
- {wxEVT_GRID_EDITOR_HIDDEN, 194, "grid_editor_hidden"},
- {wxEVT_GRID_EDITOR_CREATED, 194, "grid_editor_created"},
- {wxEVT_GRID_CELL_BEGIN_DRAG, 194, "grid_cell_begin_drag"},
- {wxEVT_SASH_DRAGGED, 196, "sash_dragged"},
- {wxEVT_COMMAND_LIST_BEGIN_DRAG, 197, "command_list_begin_drag"},
- {wxEVT_COMMAND_LIST_BEGIN_RDRAG, 197, "command_list_begin_rdrag"},
- {wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT, 197, "command_list_begin_label_edit"},
- {wxEVT_COMMAND_LIST_END_LABEL_EDIT, 197, "command_list_end_label_edit"},
- {wxEVT_COMMAND_LIST_DELETE_ITEM, 197, "command_list_delete_item"},
- {wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS, 197, "command_list_delete_all_items"},
- {wxEVT_COMMAND_LIST_KEY_DOWN, 197, "command_list_key_down"},
- {wxEVT_COMMAND_LIST_INSERT_ITEM, 197, "command_list_insert_item"},
- {wxEVT_COMMAND_LIST_COL_CLICK, 197, "command_list_col_click"},
- {wxEVT_COMMAND_LIST_COL_RIGHT_CLICK, 197, "command_list_col_right_click"},
- {wxEVT_COMMAND_LIST_COL_BEGIN_DRAG, 197, "command_list_col_begin_drag"},
- {wxEVT_COMMAND_LIST_COL_DRAGGING, 197, "command_list_col_dragging"},
- {wxEVT_COMMAND_LIST_COL_END_DRAG, 197, "command_list_col_end_drag"},
- {wxEVT_COMMAND_LIST_ITEM_SELECTED, 197, "command_list_item_selected"},
- {wxEVT_COMMAND_LIST_ITEM_DESELECTED, 197, "command_list_item_deselected"},
- {wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, 197, "command_list_item_right_click"},
- {wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK, 197, "command_list_item_middle_click"},
- {wxEVT_COMMAND_LIST_ITEM_ACTIVATED, 197, "command_list_item_activated"},
- {wxEVT_COMMAND_LIST_ITEM_FOCUSED, 197, "command_list_item_focused"},
- {wxEVT_COMMAND_LIST_CACHE_HINT, 197, "command_list_cache_hint"},
- {wxEVT_DATE_CHANGED, 198, "date_changed"},
- {wxEVT_CALENDAR_SEL_CHANGED, 199, "calendar_sel_changed"},
- {wxEVT_CALENDAR_DAY_CHANGED, 199, "calendar_day_changed"},
- {wxEVT_CALENDAR_MONTH_CHANGED, 199, "calendar_month_changed"},
- {wxEVT_CALENDAR_YEAR_CHANGED, 199, "calendar_year_changed"},
- {wxEVT_CALENDAR_DOUBLECLICKED, 199, "calendar_doubleclicked"},
- {wxEVT_CALENDAR_WEEKDAY_CLICKED, 199, "calendar_weekday_clicked"},
- {wxEVT_COMMAND_FILEPICKER_CHANGED, 200, "command_filepicker_changed"},
- {wxEVT_COMMAND_DIRPICKER_CHANGED, 200, "command_dirpicker_changed"},
- {wxEVT_COMMAND_COLOURPICKER_CHANGED, 201, "command_colourpicker_changed"},
- {wxEVT_COMMAND_FONTPICKER_CHANGED, 202, "command_fontpicker_changed"},
- {wxEVT_STC_CHANGE, 203, "stc_change"},
- {wxEVT_STC_STYLENEEDED, 203, "stc_styleneeded"},
- {wxEVT_STC_CHARADDED, 203, "stc_charadded"},
- {wxEVT_STC_SAVEPOINTREACHED, 203, "stc_savepointreached"},
- {wxEVT_STC_SAVEPOINTLEFT, 203, "stc_savepointleft"},
- {wxEVT_STC_ROMODIFYATTEMPT, 203, "stc_romodifyattempt"},
- {wxEVT_STC_KEY, 203, "stc_key"},
- {wxEVT_STC_DOUBLECLICK, 203, "stc_doubleclick"},
- {wxEVT_STC_UPDATEUI, 203, "stc_updateui"},
- {wxEVT_STC_MODIFIED, 203, "stc_modified"},
- {wxEVT_STC_MACRORECORD, 203, "stc_macrorecord"},
- {wxEVT_STC_MARGINCLICK, 203, "stc_marginclick"},
- {wxEVT_STC_NEEDSHOWN, 203, "stc_needshown"},
- {wxEVT_STC_PAINTED, 203, "stc_painted"},
- {wxEVT_STC_USERLISTSELECTION, 203, "stc_userlistselection"},
- {wxEVT_STC_URIDROPPED, 203, "stc_uridropped"},
- {wxEVT_STC_DWELLSTART, 203, "stc_dwellstart"},
- {wxEVT_STC_DWELLEND, 203, "stc_dwellend"},
- {wxEVT_STC_START_DRAG, 203, "stc_start_drag"},
- {wxEVT_STC_DRAG_OVER, 203, "stc_drag_over"},
- {wxEVT_STC_DO_DROP, 203, "stc_do_drop"},
- {wxEVT_STC_ZOOM, 203, "stc_zoom"},
- {wxEVT_STC_HOTSPOT_CLICK, 203, "stc_hotspot_click"},
- {wxEVT_STC_HOTSPOT_DCLICK, 203, "stc_hotspot_dclick"},
- {wxEVT_STC_CALLTIP_CLICK, 203, "stc_calltip_click"},
- {wxEVT_STC_AUTOCOMP_SELECTION, 203, "stc_autocomp_selection"},
- {wxEVT_COMMAND_TREE_BEGIN_DRAG, 208, "command_tree_begin_drag"},
- {wxEVT_COMMAND_TREE_BEGIN_RDRAG, 208, "command_tree_begin_rdrag"},
- {wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, 208, "command_tree_begin_label_edit"},
- {wxEVT_COMMAND_TREE_END_LABEL_EDIT, 208, "command_tree_end_label_edit"},
- {wxEVT_COMMAND_TREE_DELETE_ITEM, 208, "command_tree_delete_item"},
- {wxEVT_COMMAND_TREE_GET_INFO, 208, "command_tree_get_info"},
- {wxEVT_COMMAND_TREE_SET_INFO, 208, "command_tree_set_info"},
- {wxEVT_COMMAND_TREE_ITEM_EXPANDED, 208, "command_tree_item_expanded"},
- {wxEVT_COMMAND_TREE_ITEM_EXPANDING, 208, "command_tree_item_expanding"},
- {wxEVT_COMMAND_TREE_ITEM_COLLAPSED, 208, "command_tree_item_collapsed"},
- {wxEVT_COMMAND_TREE_ITEM_COLLAPSING, 208, "command_tree_item_collapsing"},
- {wxEVT_COMMAND_TREE_SEL_CHANGED, 208, "command_tree_sel_changed"},
- {wxEVT_COMMAND_TREE_SEL_CHANGING, 208, "command_tree_sel_changing"},
- {wxEVT_COMMAND_TREE_KEY_DOWN, 208, "command_tree_key_down"},
- {wxEVT_COMMAND_TREE_ITEM_ACTIVATED, 208, "command_tree_item_activated"},
- {wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK, 208, "command_tree_item_right_click"},
- {wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK, 208, "command_tree_item_middle_click"},
- {wxEVT_COMMAND_TREE_END_DRAG, 208, "command_tree_end_drag"},
- {wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK, 208, "command_tree_state_image_click"},
- {wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP, 208, "command_tree_item_gettooltip"},
- {wxEVT_COMMAND_TREE_ITEM_MENU, 208, "command_tree_item_menu"},
- {wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, 209, "command_notebook_page_changed"},
- {wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, 209, "command_notebook_page_changing"},
- {wxEVT_COMMAND_SPINCTRL_UPDATED, 215, "command_spinctrl_updated"},
- {wxEVT_SCROLL_LINEUP + wxEVT_USER_FIRST, 164, "spin_up"},
- {wxEVT_SCROLL_LINEDOWN + wxEVT_USER_FIRST, 164, "spin_down"},
- {wxEVT_SCROLL_THUMBTRACK + wxEVT_USER_FIRST, 164, "spin"},
- {wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED, 217, "command_splitter_sash_pos_changed"},
- {wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGING, 217, "command_splitter_sash_pos_changing"},
- {wxEVT_COMMAND_SPLITTER_DOUBLECLICKED, 217, "command_splitter_doubleclicked"},
- {wxEVT_COMMAND_SPLITTER_UNSPLIT, 217, "command_splitter_unsplit"},
- {wxEVT_COMMAND_HTML_LINK_CLICKED, 219, "command_html_link_clicked"},
- {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, 221, "command_auinotebook_page_close"},
- {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, 221, "command_auinotebook_page_changed"},
- {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, 221, "command_auinotebook_page_changing"},
- {wxEVT_COMMAND_AUINOTEBOOK_BUTTON, 221, "command_auinotebook_button"},
- {wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, 221, "command_auinotebook_begin_drag"},
- {wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, 221, "command_auinotebook_end_drag"},
- {wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, 221, "command_auinotebook_drag_motion"},
- {wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, 221, "command_auinotebook_allow_dnd"},
+ {wxEVT_COMMAND_BUTTON_CLICKED, 164, "command_button_clicked"},
+ {wxEVT_COMMAND_CHECKBOX_CLICKED, 164, "command_checkbox_clicked"},
+ {wxEVT_COMMAND_CHOICE_SELECTED, 164, "command_choice_selected"},
+ {wxEVT_COMMAND_LISTBOX_SELECTED, 164, "command_listbox_selected"},
+ {wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, 164, "command_listbox_doubleclicked"},
+ {wxEVT_COMMAND_TEXT_UPDATED, 164, "command_text_updated"},
+ {wxEVT_COMMAND_TEXT_ENTER, 164, "command_text_enter"},
+ {wxEVT_COMMAND_MENU_SELECTED, 164, "command_menu_selected"},
+ {wxEVT_COMMAND_SLIDER_UPDATED, 164, "command_slider_updated"},
+ {wxEVT_COMMAND_RADIOBOX_SELECTED, 164, "command_radiobox_selected"},
+ {wxEVT_COMMAND_RADIOBUTTON_SELECTED, 164, "command_radiobutton_selected"},
+ {wxEVT_COMMAND_SCROLLBAR_UPDATED, 164, "command_scrollbar_updated"},
+ {wxEVT_COMMAND_VLBOX_SELECTED, 164, "command_vlbox_selected"},
+ {wxEVT_COMMAND_COMBOBOX_SELECTED, 164, "command_combobox_selected"},
+ {wxEVT_COMMAND_TOOL_RCLICKED, 164, "command_tool_rclicked"},
+ {wxEVT_COMMAND_TOOL_ENTER, 164, "command_tool_enter"},
+ {wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, 164, "command_checklistbox_toggled"},
+ {wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, 164, "command_togglebutton_clicked"},
+ {wxEVT_COMMAND_LEFT_CLICK, 164, "command_left_click"},
+ {wxEVT_COMMAND_LEFT_DCLICK, 164, "command_left_dclick"},
+ {wxEVT_COMMAND_RIGHT_CLICK, 164, "command_right_click"},
+ {wxEVT_COMMAND_SET_FOCUS, 164, "command_set_focus"},
+ {wxEVT_COMMAND_KILL_FOCUS, 164, "command_kill_focus"},
+ {wxEVT_COMMAND_ENTER, 164, "command_enter"},
+ {wxEVT_SCROLL_TOP, 165, "scroll_top"},
+ {wxEVT_SCROLL_BOTTOM, 165, "scroll_bottom"},
+ {wxEVT_SCROLL_LINEUP, 165, "scroll_lineup"},
+ {wxEVT_SCROLL_LINEDOWN, 165, "scroll_linedown"},
+ {wxEVT_SCROLL_PAGEUP, 165, "scroll_pageup"},
+ {wxEVT_SCROLL_PAGEDOWN, 165, "scroll_pagedown"},
+ {wxEVT_SCROLL_THUMBTRACK, 165, "scroll_thumbtrack"},
+ {wxEVT_SCROLL_THUMBRELEASE, 165, "scroll_thumbrelease"},
+ {wxEVT_SCROLL_CHANGED, 165, "scroll_changed"},
+ {wxEVT_SCROLLWIN_TOP, 166, "scrollwin_top"},
+ {wxEVT_SCROLLWIN_BOTTOM, 166, "scrollwin_bottom"},
+ {wxEVT_SCROLLWIN_LINEUP, 166, "scrollwin_lineup"},
+ {wxEVT_SCROLLWIN_LINEDOWN, 166, "scrollwin_linedown"},
+ {wxEVT_SCROLLWIN_PAGEUP, 166, "scrollwin_pageup"},
+ {wxEVT_SCROLLWIN_PAGEDOWN, 166, "scrollwin_pagedown"},
+ {wxEVT_SCROLLWIN_THUMBTRACK, 166, "scrollwin_thumbtrack"},
+ {wxEVT_SCROLLWIN_THUMBRELEASE, 166, "scrollwin_thumbrelease"},
+ {wxEVT_LEFT_DOWN, 167, "left_down"},
+ {wxEVT_LEFT_UP, 167, "left_up"},
+ {wxEVT_MIDDLE_DOWN, 167, "middle_down"},
+ {wxEVT_MIDDLE_UP, 167, "middle_up"},
+ {wxEVT_RIGHT_DOWN, 167, "right_down"},
+ {wxEVT_RIGHT_UP, 167, "right_up"},
+ {wxEVT_MOTION, 167, "motion"},
+ {wxEVT_ENTER_WINDOW, 167, "enter_window"},
+ {wxEVT_LEAVE_WINDOW, 167, "leave_window"},
+ {wxEVT_LEFT_DCLICK, 167, "left_dclick"},
+ {wxEVT_MIDDLE_DCLICK, 167, "middle_dclick"},
+ {wxEVT_RIGHT_DCLICK, 167, "right_dclick"},
+ {wxEVT_MOUSEWHEEL, 167, "mousewheel"},
+ {wxEVT_NC_LEFT_DOWN, 167, "nc_left_down"},
+ {wxEVT_NC_LEFT_UP, 167, "nc_left_up"},
+ {wxEVT_NC_MIDDLE_DOWN, 167, "nc_middle_down"},
+ {wxEVT_NC_MIDDLE_UP, 167, "nc_middle_up"},
+ {wxEVT_NC_RIGHT_DOWN, 167, "nc_right_down"},
+ {wxEVT_NC_RIGHT_UP, 167, "nc_right_up"},
+ {wxEVT_NC_MOTION, 167, "nc_motion"},
+ {wxEVT_NC_ENTER_WINDOW, 167, "nc_enter_window"},
+ {wxEVT_NC_LEAVE_WINDOW, 167, "nc_leave_window"},
+ {wxEVT_NC_LEFT_DCLICK, 167, "nc_left_dclick"},
+ {wxEVT_NC_MIDDLE_DCLICK, 167, "nc_middle_dclick"},
+ {wxEVT_NC_RIGHT_DCLICK, 167, "nc_right_dclick"},
+ {wxEVT_SET_CURSOR, 168, "set_cursor"},
+ {wxEVT_CHAR, 169, "char"},
+ {wxEVT_CHAR_HOOK, 169, "char_hook"},
+ {wxEVT_KEY_DOWN, 169, "key_down"},
+ {wxEVT_KEY_UP, 169, "key_up"},
+ {wxEVT_SIZE, 170, "size"},
+ {wxEVT_MOVE, 171, "move"},
+ {wxEVT_PAINT, 172, "paint"},
+ {wxEVT_PAINT_ICON, 172, "paint_icon"},
+ {wxEVT_NC_PAINT, 173, "nc_paint"},
+ {wxEVT_ERASE_BACKGROUND, 174, "erase_background"},
+ {wxEVT_SET_FOCUS, 175, "set_focus"},
+ {wxEVT_KILL_FOCUS, 175, "kill_focus"},
+ {wxEVT_CHILD_FOCUS, 176, "child_focus"},
+ {wxEVT_MENU_OPEN, 177, "menu_open"},
+ {wxEVT_MENU_CLOSE, 177, "menu_close"},
+ {wxEVT_MENU_HIGHLIGHT, 177, "menu_highlight"},
+ {wxEVT_CLOSE_WINDOW, 178, "close_window"},
+ {wxEVT_END_SESSION, 178, "end_session"},
+ {wxEVT_QUERY_END_SESSION, 178, "query_end_session"},
+ {wxEVT_SHOW, 179, "show"},
+ {wxEVT_ICONIZE, 180, "iconize"},
+ {wxEVT_MAXIMIZE, 181, "maximize"},
+ {wxEVT_JOY_BUTTON_DOWN, 182, "joy_button_down"},
+ {wxEVT_JOY_BUTTON_UP, 182, "joy_button_up"},
+ {wxEVT_JOY_MOVE, 182, "joy_move"},
+ {wxEVT_JOY_ZMOVE, 182, "joy_zmove"},
+ {wxEVT_UPDATE_UI, 183, "update_ui"},
+ {wxEVT_SYS_COLOUR_CHANGED, 184, "sys_colour_changed"},
+ {wxEVT_MOUSE_CAPTURE_CHANGED, 185, "mouse_capture_changed"},
+ {wxEVT_DISPLAY_CHANGED, 186, "display_changed"},
+ {wxEVT_PALETTE_CHANGED, 187, "palette_changed"},
+ {wxEVT_QUERY_NEW_PALETTE, 188, "query_new_palette"},
+ {wxEVT_NAVIGATION_KEY, 189, "navigation_key"},
+ {wxEVT_CREATE, 190, "create"},
+ {wxEVT_DESTROY, 191, "destroy"},
+ {wxEVT_HELP, 192, "help"},
+ {wxEVT_DETAILED_HELP, 192, "detailed_help"},
+ {wxEVT_CONTEXT_MENU, 193, "context_menu"},
+ {wxEVT_IDLE, 194, "idle"},
+ {wxEVT_GRID_CELL_LEFT_CLICK, 195, "grid_cell_left_click"},
+ {wxEVT_GRID_CELL_RIGHT_CLICK, 195, "grid_cell_right_click"},
+ {wxEVT_GRID_CELL_LEFT_DCLICK, 195, "grid_cell_left_dclick"},
+ {wxEVT_GRID_CELL_RIGHT_DCLICK, 195, "grid_cell_right_dclick"},
+ {wxEVT_GRID_LABEL_LEFT_CLICK, 195, "grid_label_left_click"},
+ {wxEVT_GRID_LABEL_RIGHT_CLICK, 195, "grid_label_right_click"},
+ {wxEVT_GRID_LABEL_LEFT_DCLICK, 195, "grid_label_left_dclick"},
+ {wxEVT_GRID_LABEL_RIGHT_DCLICK, 195, "grid_label_right_dclick"},
+ {wxEVT_GRID_ROW_SIZE, 195, "grid_row_size"},
+ {wxEVT_GRID_COL_SIZE, 195, "grid_col_size"},
+ {wxEVT_GRID_RANGE_SELECT, 195, "grid_range_select"},
+ {wxEVT_GRID_CELL_CHANGE, 195, "grid_cell_change"},
+ {wxEVT_GRID_SELECT_CELL, 195, "grid_select_cell"},
+ {wxEVT_GRID_EDITOR_SHOWN, 195, "grid_editor_shown"},
+ {wxEVT_GRID_EDITOR_HIDDEN, 195, "grid_editor_hidden"},
+ {wxEVT_GRID_EDITOR_CREATED, 195, "grid_editor_created"},
+ {wxEVT_GRID_CELL_BEGIN_DRAG, 195, "grid_cell_begin_drag"},
+ {wxEVT_SASH_DRAGGED, 197, "sash_dragged"},
+ {wxEVT_COMMAND_LIST_BEGIN_DRAG, 198, "command_list_begin_drag"},
+ {wxEVT_COMMAND_LIST_BEGIN_RDRAG, 198, "command_list_begin_rdrag"},
+ {wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT, 198, "command_list_begin_label_edit"},
+ {wxEVT_COMMAND_LIST_END_LABEL_EDIT, 198, "command_list_end_label_edit"},
+ {wxEVT_COMMAND_LIST_DELETE_ITEM, 198, "command_list_delete_item"},
+ {wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS, 198, "command_list_delete_all_items"},
+ {wxEVT_COMMAND_LIST_KEY_DOWN, 198, "command_list_key_down"},
+ {wxEVT_COMMAND_LIST_INSERT_ITEM, 198, "command_list_insert_item"},
+ {wxEVT_COMMAND_LIST_COL_CLICK, 198, "command_list_col_click"},
+ {wxEVT_COMMAND_LIST_COL_RIGHT_CLICK, 198, "command_list_col_right_click"},
+ {wxEVT_COMMAND_LIST_COL_BEGIN_DRAG, 198, "command_list_col_begin_drag"},
+ {wxEVT_COMMAND_LIST_COL_DRAGGING, 198, "command_list_col_dragging"},
+ {wxEVT_COMMAND_LIST_COL_END_DRAG, 198, "command_list_col_end_drag"},
+ {wxEVT_COMMAND_LIST_ITEM_SELECTED, 198, "command_list_item_selected"},
+ {wxEVT_COMMAND_LIST_ITEM_DESELECTED, 198, "command_list_item_deselected"},
+ {wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, 198, "command_list_item_right_click"},
+ {wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK, 198, "command_list_item_middle_click"},
+ {wxEVT_COMMAND_LIST_ITEM_ACTIVATED, 198, "command_list_item_activated"},
+ {wxEVT_COMMAND_LIST_ITEM_FOCUSED, 198, "command_list_item_focused"},
+ {wxEVT_COMMAND_LIST_CACHE_HINT, 198, "command_list_cache_hint"},
+ {wxEVT_DATE_CHANGED, 199, "date_changed"},
+ {wxEVT_CALENDAR_SEL_CHANGED, 200, "calendar_sel_changed"},
+ {wxEVT_CALENDAR_DAY_CHANGED, 200, "calendar_day_changed"},
+ {wxEVT_CALENDAR_MONTH_CHANGED, 200, "calendar_month_changed"},
+ {wxEVT_CALENDAR_YEAR_CHANGED, 200, "calendar_year_changed"},
+ {wxEVT_CALENDAR_DOUBLECLICKED, 200, "calendar_doubleclicked"},
+ {wxEVT_CALENDAR_WEEKDAY_CLICKED, 200, "calendar_weekday_clicked"},
+ {wxEVT_COMMAND_FILEPICKER_CHANGED, 201, "command_filepicker_changed"},
+ {wxEVT_COMMAND_DIRPICKER_CHANGED, 201, "command_dirpicker_changed"},
+ {wxEVT_COMMAND_COLOURPICKER_CHANGED, 202, "command_colourpicker_changed"},
+ {wxEVT_COMMAND_FONTPICKER_CHANGED, 203, "command_fontpicker_changed"},
+ {wxEVT_STC_CHANGE, 204, "stc_change"},
+ {wxEVT_STC_STYLENEEDED, 204, "stc_styleneeded"},
+ {wxEVT_STC_CHARADDED, 204, "stc_charadded"},
+ {wxEVT_STC_SAVEPOINTREACHED, 204, "stc_savepointreached"},
+ {wxEVT_STC_SAVEPOINTLEFT, 204, "stc_savepointleft"},
+ {wxEVT_STC_ROMODIFYATTEMPT, 204, "stc_romodifyattempt"},
+ {wxEVT_STC_KEY, 204, "stc_key"},
+ {wxEVT_STC_DOUBLECLICK, 204, "stc_doubleclick"},
+ {wxEVT_STC_UPDATEUI, 204, "stc_updateui"},
+ {wxEVT_STC_MODIFIED, 204, "stc_modified"},
+ {wxEVT_STC_MACRORECORD, 204, "stc_macrorecord"},
+ {wxEVT_STC_MARGINCLICK, 204, "stc_marginclick"},
+ {wxEVT_STC_NEEDSHOWN, 204, "stc_needshown"},
+ {wxEVT_STC_PAINTED, 204, "stc_painted"},
+ {wxEVT_STC_USERLISTSELECTION, 204, "stc_userlistselection"},
+ {wxEVT_STC_URIDROPPED, 204, "stc_uridropped"},
+ {wxEVT_STC_DWELLSTART, 204, "stc_dwellstart"},
+ {wxEVT_STC_DWELLEND, 204, "stc_dwellend"},
+ {wxEVT_STC_START_DRAG, 204, "stc_start_drag"},
+ {wxEVT_STC_DRAG_OVER, 204, "stc_drag_over"},
+ {wxEVT_STC_DO_DROP, 204, "stc_do_drop"},
+ {wxEVT_STC_ZOOM, 204, "stc_zoom"},
+ {wxEVT_STC_HOTSPOT_CLICK, 204, "stc_hotspot_click"},
+ {wxEVT_STC_HOTSPOT_DCLICK, 204, "stc_hotspot_dclick"},
+ {wxEVT_STC_CALLTIP_CLICK, 204, "stc_calltip_click"},
+ {wxEVT_STC_AUTOCOMP_SELECTION, 204, "stc_autocomp_selection"},
+ {wxEVT_COMMAND_TREE_BEGIN_DRAG, 209, "command_tree_begin_drag"},
+ {wxEVT_COMMAND_TREE_BEGIN_RDRAG, 209, "command_tree_begin_rdrag"},
+ {wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, 209, "command_tree_begin_label_edit"},
+ {wxEVT_COMMAND_TREE_END_LABEL_EDIT, 209, "command_tree_end_label_edit"},
+ {wxEVT_COMMAND_TREE_DELETE_ITEM, 209, "command_tree_delete_item"},
+ {wxEVT_COMMAND_TREE_GET_INFO, 209, "command_tree_get_info"},
+ {wxEVT_COMMAND_TREE_SET_INFO, 209, "command_tree_set_info"},
+ {wxEVT_COMMAND_TREE_ITEM_EXPANDED, 209, "command_tree_item_expanded"},
+ {wxEVT_COMMAND_TREE_ITEM_EXPANDING, 209, "command_tree_item_expanding"},
+ {wxEVT_COMMAND_TREE_ITEM_COLLAPSED, 209, "command_tree_item_collapsed"},
+ {wxEVT_COMMAND_TREE_ITEM_COLLAPSING, 209, "command_tree_item_collapsing"},
+ {wxEVT_COMMAND_TREE_SEL_CHANGED, 209, "command_tree_sel_changed"},
+ {wxEVT_COMMAND_TREE_SEL_CHANGING, 209, "command_tree_sel_changing"},
+ {wxEVT_COMMAND_TREE_KEY_DOWN, 209, "command_tree_key_down"},
+ {wxEVT_COMMAND_TREE_ITEM_ACTIVATED, 209, "command_tree_item_activated"},
+ {wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK, 209, "command_tree_item_right_click"},
+ {wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK, 209, "command_tree_item_middle_click"},
+ {wxEVT_COMMAND_TREE_END_DRAG, 209, "command_tree_end_drag"},
+ {wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK, 209, "command_tree_state_image_click"},
+ {wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP, 209, "command_tree_item_gettooltip"},
+ {wxEVT_COMMAND_TREE_ITEM_MENU, 209, "command_tree_item_menu"},
+ {wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, 210, "command_notebook_page_changed"},
+ {wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, 210, "command_notebook_page_changing"},
+ {wxEVT_COMMAND_SPINCTRL_UPDATED, 216, "command_spinctrl_updated"},
+ {wxEVT_SCROLL_LINEUP + wxEVT_USER_FIRST, 165, "spin_up"},
+ {wxEVT_SCROLL_LINEDOWN + wxEVT_USER_FIRST, 165, "spin_down"},
+ {wxEVT_SCROLL_THUMBTRACK + wxEVT_USER_FIRST, 165, "spin"},
+ {wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED, 218, "command_splitter_sash_pos_changed"},
+ {wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGING, 218, "command_splitter_sash_pos_changing"},
+ {wxEVT_COMMAND_SPLITTER_DOUBLECLICKED, 218, "command_splitter_doubleclicked"},
+ {wxEVT_COMMAND_SPLITTER_UNSPLIT, 218, "command_splitter_unsplit"},
+ {wxEVT_COMMAND_HTML_LINK_CLICKED, 220, "command_html_link_clicked"},
+ {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, 223, "command_auinotebook_page_close"},
+ {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, 223, "command_auinotebook_page_changed"},
+ {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, 223, "command_auinotebook_page_changing"},
+ {wxEVT_COMMAND_AUINOTEBOOK_BUTTON, 223, "command_auinotebook_button"},
+ {wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, 223, "command_auinotebook_begin_drag"},
+ {wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, 223, "command_auinotebook_end_drag"},
+ {wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, 223, "command_auinotebook_drag_motion"},
+ {wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, 223, "command_auinotebook_allow_dnd"},
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, 221, "command_auinotebook_tab_middle_down"},
+ {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, 223, "command_auinotebook_tab_middle_down"},
#endif
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, 221, "command_auinotebook_tab_middle_up"},
+ {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, 223, "command_auinotebook_tab_middle_up"},
#endif
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, 221, "command_auinotebook_tab_right_down"},
+ {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, 223, "command_auinotebook_tab_right_down"},
#endif
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, 221, "command_auinotebook_tab_right_up"},
+ {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, 223, "command_auinotebook_tab_right_up"},
#endif
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, 221, "command_auinotebook_page_closed"},
+ {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, 223, "command_auinotebook_page_closed"},
#endif
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, 221, "command_auinotebook_drag_done"},
+ {wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, 223, "command_auinotebook_drag_done"},
#endif
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, 221, "command_auinotebook_bg_dclick"},
+ {wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, 223, "command_auinotebook_bg_dclick"},
#endif
- {wxEVT_AUI_PANE_BUTTON, 222, "aui_pane_button"},
- {wxEVT_AUI_PANE_CLOSE, 222, "aui_pane_close"},
- {wxEVT_AUI_PANE_MAXIMIZE, 222, "aui_pane_maximize"},
- {wxEVT_AUI_PANE_RESTORE, 222, "aui_pane_restore"},
- {wxEVT_AUI_RENDER, 222, "aui_render"},
- {wxEVT_AUI_FIND_MANAGER, 222, "aui_find_manager"},
+ {wxEVT_AUI_PANE_BUTTON, 224, "aui_pane_button"},
+ {wxEVT_AUI_PANE_CLOSE, 224, "aui_pane_close"},
+ {wxEVT_AUI_PANE_MAXIMIZE, 224, "aui_pane_maximize"},
+ {wxEVT_AUI_PANE_RESTORE, 224, "aui_pane_restore"},
+ {wxEVT_AUI_RENDER, 224, "aui_render"},
+ {wxEVT_AUI_FIND_MANAGER, 224, "aui_find_manager"},
{-1, 0, }
};
for(int i=0; event_types[i].ev_type != -1; i++) {
@@ -353,7 +353,7 @@ bool sendevent(wxEvent *event, ErlDrvPort port)
rt.addRef(getRef((void *)(cb->obj), memenv), cb->class_name);
rt.addExt2Term(cb->user_data);
switch(Etype->cID) {
-case 163: {// wxCommandEvent
+case 164: {// wxCommandEvent
wxCommandEvent * ev = (wxCommandEvent *) event;
evClass = (char*)"wxCommandEvent";
rt.addAtom((char*)"wxCommand");
@@ -364,7 +364,7 @@ case 163: {// wxCommandEvent
rt.addTupleCount(5);
break;
}
-case 164: {// wxScrollEvent or wxSpinEvent
+case 165: {// wxScrollEvent or wxSpinEvent
if(event->IsKindOf(CLASSINFO(wxScrollEvent))) {
wxScrollEvent * ev = (wxScrollEvent *) event;
evClass = (char*)"wxScrollEvent";
@@ -384,14 +384,14 @@ case 164: {// wxScrollEvent or wxSpinEvent
}
break;
}
-case 165: {// wxScrollWinEvent
+case 166: {// wxScrollWinEvent
evClass = (char*)"wxScrollWinEvent";
rt.addAtom((char*)"wxScrollWin");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 166: {// wxMouseEvent
+case 167: {// wxMouseEvent
wxMouseEvent * ev = (wxMouseEvent *) event;
evClass = (char*)"wxMouseEvent";
rt.addAtom((char*)"wxMouse");
@@ -411,14 +411,14 @@ case 166: {// wxMouseEvent
rt.addTupleCount(14);
break;
}
-case 167: {// wxSetCursorEvent
+case 168: {// wxSetCursorEvent
evClass = (char*)"wxSetCursorEvent";
rt.addAtom((char*)"wxSetCursor");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 168: {// wxKeyEvent
+case 169: {// wxKeyEvent
wxKeyEvent * ev = (wxKeyEvent *) event;
evClass = (char*)"wxKeyEvent";
rt.addAtom((char*)"wxKey");
@@ -437,7 +437,7 @@ case 168: {// wxKeyEvent
rt.addTupleCount(13);
break;
}
-case 169: {// wxSizeEvent
+case 170: {// wxSizeEvent
wxSizeEvent * ev = (wxSizeEvent *) event;
evClass = (char*)"wxSizeEvent";
rt.addAtom((char*)"wxSize");
@@ -447,28 +447,28 @@ case 169: {// wxSizeEvent
rt.addTupleCount(4);
break;
}
-case 170: {// wxMoveEvent
+case 171: {// wxMoveEvent
evClass = (char*)"wxMoveEvent";
rt.addAtom((char*)"wxMove");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 171: {// wxPaintEvent
+case 172: {// wxPaintEvent
evClass = (char*)"wxPaintEvent";
rt.addAtom((char*)"wxPaint");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 172: {// wxNcPaintEvent
+case 173: {// wxNcPaintEvent
evClass = (char*)"wxNcPaintEvent";
rt.addAtom((char*)"wxNcPaint");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 173: {// wxEraseEvent
+case 174: {// wxEraseEvent
wxEraseEvent * ev = (wxEraseEvent *) event;
wxDC * GetDC = ev->GetDC();
evClass = (char*)"wxEraseEvent";
@@ -478,105 +478,105 @@ case 173: {// wxEraseEvent
rt.addTupleCount(3);
break;
}
-case 174: {// wxFocusEvent
+case 175: {// wxFocusEvent
evClass = (char*)"wxFocusEvent";
rt.addAtom((char*)"wxFocus");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 175: {// wxChildFocusEvent
+case 176: {// wxChildFocusEvent
evClass = (char*)"wxChildFocusEvent";
rt.addAtom((char*)"wxChildFocus");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 176: {// wxMenuEvent
+case 177: {// wxMenuEvent
evClass = (char*)"wxMenuEvent";
rt.addAtom((char*)"wxMenu");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 177: {// wxCloseEvent
+case 178: {// wxCloseEvent
evClass = (char*)"wxCloseEvent";
rt.addAtom((char*)"wxClose");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 178: {// wxShowEvent
+case 179: {// wxShowEvent
evClass = (char*)"wxShowEvent";
rt.addAtom((char*)"wxShow");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 179: {// wxIconizeEvent
+case 180: {// wxIconizeEvent
evClass = (char*)"wxIconizeEvent";
rt.addAtom((char*)"wxIconize");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 180: {// wxMaximizeEvent
+case 181: {// wxMaximizeEvent
evClass = (char*)"wxMaximizeEvent";
rt.addAtom((char*)"wxMaximize");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 181: {// wxJoystickEvent
+case 182: {// wxJoystickEvent
evClass = (char*)"wxJoystickEvent";
rt.addAtom((char*)"wxJoystick");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 182: {// wxUpdateUIEvent
+case 183: {// wxUpdateUIEvent
evClass = (char*)"wxUpdateUIEvent";
rt.addAtom((char*)"wxUpdateUI");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 183: {// wxSysColourChangedEvent
+case 184: {// wxSysColourChangedEvent
evClass = (char*)"wxSysColourChangedEvent";
rt.addAtom((char*)"wxSysColourChanged");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 184: {// wxMouseCaptureChangedEvent
+case 185: {// wxMouseCaptureChangedEvent
evClass = (char*)"wxMouseCaptureChangedEvent";
rt.addAtom((char*)"wxMouseCaptureChanged");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 185: {// wxDisplayChangedEvent
+case 186: {// wxDisplayChangedEvent
evClass = (char*)"wxDisplayChangedEvent";
rt.addAtom((char*)"wxDisplayChanged");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 186: {// wxPaletteChangedEvent
+case 187: {// wxPaletteChangedEvent
evClass = (char*)"wxPaletteChangedEvent";
rt.addAtom((char*)"wxPaletteChanged");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 187: {// wxQueryNewPaletteEvent
+case 188: {// wxQueryNewPaletteEvent
evClass = (char*)"wxQueryNewPaletteEvent";
rt.addAtom((char*)"wxQueryNewPalette");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 188: {// wxNavigationKeyEvent
+case 189: {// wxNavigationKeyEvent
wxNavigationKeyEvent * ev = (wxNavigationKeyEvent *) event;
evClass = (char*)"wxNavigationKeyEvent";
rt.addAtom((char*)"wxNavigationKey");
@@ -586,42 +586,42 @@ case 188: {// wxNavigationKeyEvent
rt.addTupleCount(4);
break;
}
-case 189: {// wxWindowCreateEvent
+case 190: {// wxWindowCreateEvent
evClass = (char*)"wxWindowCreateEvent";
rt.addAtom((char*)"wxWindowCreate");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 190: {// wxWindowDestroyEvent
+case 191: {// wxWindowDestroyEvent
evClass = (char*)"wxWindowDestroyEvent";
rt.addAtom((char*)"wxWindowDestroy");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 191: {// wxHelpEvent
+case 192: {// wxHelpEvent
evClass = (char*)"wxHelpEvent";
rt.addAtom((char*)"wxHelp");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 192: {// wxContextMenuEvent
+case 193: {// wxContextMenuEvent
evClass = (char*)"wxContextMenuEvent";
rt.addAtom((char*)"wxContextMenu");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 193: {// wxIdleEvent
+case 194: {// wxIdleEvent
evClass = (char*)"wxIdleEvent";
rt.addAtom((char*)"wxIdle");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 194: {// wxGridEvent
+case 195: {// wxGridEvent
wxGridEvent * ev = (wxGridEvent *) event;
evClass = (char*)"wxGridEvent";
rt.addAtom((char*)"wxGrid");
@@ -638,7 +638,7 @@ case 194: {// wxGridEvent
rt.addTupleCount(11);
break;
}
-case 196: {// wxSashEvent
+case 197: {// wxSashEvent
wxSashEvent * ev = (wxSashEvent *) event;
evClass = (char*)"wxSashEvent";
rt.addAtom((char*)"wxSash");
@@ -649,7 +649,7 @@ case 196: {// wxSashEvent
rt.addTupleCount(5);
break;
}
-case 197: {// wxListEvent
+case 198: {// wxListEvent
wxListEvent * ev = (wxListEvent *) event;
evClass = (char*)"wxListEvent";
rt.addAtom((char*)"wxList");
@@ -662,7 +662,7 @@ case 197: {// wxListEvent
rt.addTupleCount(7);
break;
}
-case 198: {// wxDateEvent
+case 199: {// wxDateEvent
wxDateEvent * ev = (wxDateEvent *) event;
evClass = (char*)"wxDateEvent";
rt.addAtom((char*)"wxDate");
@@ -671,14 +671,14 @@ case 198: {// wxDateEvent
rt.addTupleCount(3);
break;
}
-case 199: {// wxCalendarEvent
+case 200: {// wxCalendarEvent
evClass = (char*)"wxCalendarEvent";
rt.addAtom((char*)"wxCalendar");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 200: {// wxFileDirPickerEvent
+case 201: {// wxFileDirPickerEvent
wxFileDirPickerEvent * ev = (wxFileDirPickerEvent *) event;
evClass = (char*)"wxFileDirPickerEvent";
rt.addAtom((char*)"wxFileDirPicker");
@@ -687,7 +687,7 @@ case 200: {// wxFileDirPickerEvent
rt.addTupleCount(3);
break;
}
-case 201: {// wxColourPickerEvent
+case 202: {// wxColourPickerEvent
wxColourPickerEvent * ev = (wxColourPickerEvent *) event;
evClass = (char*)"wxColourPickerEvent";
rt.addAtom((char*)"wxColourPicker");
@@ -696,7 +696,7 @@ case 201: {// wxColourPickerEvent
rt.addTupleCount(3);
break;
}
-case 202: {// wxFontPickerEvent
+case 203: {// wxFontPickerEvent
wxFontPickerEvent * ev = (wxFontPickerEvent *) event;
wxFont * GetFont = new wxFont(ev->GetFont());
app->newPtr((void *) GetFont,3, memenv);
@@ -707,7 +707,7 @@ case 202: {// wxFontPickerEvent
rt.addTupleCount(3);
break;
}
-case 203: {// wxStyledTextEvent
+case 204: {// wxStyledTextEvent
wxStyledTextEvent * ev = (wxStyledTextEvent *) event;
evClass = (char*)"wxStyledTextEvent";
rt.addAtom((char*)"wxStyledText");
@@ -735,7 +735,7 @@ case 203: {// wxStyledTextEvent
rt.addTupleCount(22);
break;
}
-case 208: {// wxTreeEvent
+case 209: {// wxTreeEvent
wxTreeEvent * ev = (wxTreeEvent *) event;
evClass = (char*)"wxTreeEvent";
rt.addAtom((char*)"wxTree");
@@ -746,14 +746,14 @@ case 208: {// wxTreeEvent
rt.addTupleCount(5);
break;
}
-case 209: {// wxNotebookEvent
+case 210: {// wxNotebookEvent
evClass = (char*)"wxNotebookEvent";
rt.addAtom((char*)"wxNotebook");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 215: {// wxSpinEvent
+case 216: {// wxSpinEvent
wxSpinEvent * ev = (wxSpinEvent *) event;
evClass = (char*)"wxSpinEvent";
rt.addAtom((char*)"wxSpin");
@@ -762,14 +762,14 @@ case 215: {// wxSpinEvent
rt.addTupleCount(3);
break;
}
-case 217: {// wxSplitterEvent
+case 218: {// wxSplitterEvent
evClass = (char*)"wxSplitterEvent";
rt.addAtom((char*)"wxSplitter");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 219: {// wxHtmlLinkEvent
+case 220: {// wxHtmlLinkEvent
wxHtmlLinkEvent * ev = (wxHtmlLinkEvent *) event;
evClass = (char*)"wxHtmlLinkEvent";
rt.addAtom((char*)"wxHtmlLink");
@@ -778,7 +778,7 @@ case 219: {// wxHtmlLinkEvent
rt.addTupleCount(3);
break;
}
-case 221: {// wxAuiNotebookEvent
+case 223: {// wxAuiNotebookEvent
wxAuiNotebookEvent * ev = (wxAuiNotebookEvent *) event;
wxAuiNotebook * GetDragSource = ev->GetDragSource();
evClass = (char*)"wxAuiNotebookEvent";
@@ -790,7 +790,7 @@ case 221: {// wxAuiNotebookEvent
rt.addTupleCount(5);
break;
}
-case 222: {// wxAuiManagerEvent
+case 224: {// wxAuiManagerEvent
wxAuiManagerEvent * ev = (wxAuiManagerEvent *) event;
wxAuiManager * GetManager = ev->GetManager();
wxAuiPaneInfo * GetPane = ev->GetPane();
diff --git a/lib/wx/c_src/gen/wxe_funcs.cpp b/lib/wx/c_src/gen/wxe_funcs.cpp
index 479d7679a4..f456bd3287 100644
--- a/lib/wx/c_src/gen/wxe_funcs.cpp
+++ b/lib/wx/c_src/gen/wxe_funcs.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -4486,7 +4486,7 @@ case wxGridCellBoolEditor_IsTrueValue: { // wxGridCellBoolEditor::IsTrueValue
break;
}
case wxGridCellBoolEditor_UseStringValues: { // wxGridCellBoolEditor::UseStringValues
- wxString valueTrue= _T("1");
+ wxString valueTrue= wxT("1");
wxString valueFalse= wxEmptyString;
while( * (int*) bp) { switch (* (int*) bp) {
case 1: {bp += 4;
@@ -15143,12 +15143,14 @@ case wxListBox_SetFirstItem_1_1: { // wxListBox::SetFirstItem
This->SetFirstItem(s);
break;
}
+
case wxListCtrl_new_0: { // wxListCtrl::wxListCtrl
wxListCtrl * Result = new EwxListCtrl();
newPtr((void *) Result, 0, memenv);
rt.addRef(getRef((void *)Result,memenv), "wxListCtrl");
break;
}
+
case wxListCtrl_new_2: { // wxListCtrl::wxListCtrl
wxWindowID winid=wxID_ANY;
wxPoint pos= wxDefaultPosition;
@@ -15156,6 +15158,8 @@ case wxListCtrl_new_2: { // wxListCtrl::wxListCtrl
long style=wxLC_ICON;
const wxValidator * validator= &wxDefaultValidator;
wxWindow *parent = (wxWindow *) getPtr(bp,memenv); bp += 4;
+ int onGetItemText = 0, onGetItemAttr = 0, onGetItemColumnImage = 0;
+
bp += 4; /* Align */
while( * (int*) bp) { switch (* (int*) bp) {
case 1: {bp += 4;
@@ -15179,8 +15183,21 @@ case wxListCtrl_new_2: { // wxListCtrl::wxListCtrl
case 5: {bp += 4;
validator = (wxValidator *) getPtr(bp,memenv); bp += 4;
} break;
+ case 6: {bp += 4;
+ onGetItemText = *(int *) bp; bp += 4;
+ } break;
+ case 7: {bp += 4;
+ onGetItemAttr = *(int *) bp; bp += 4;
+ } break;
+ case 8: {bp += 4;
+ onGetItemColumnImage = *(int *) bp; bp += 4;
+ } break;
}};
- wxListCtrl * Result = new EwxListCtrl(parent,winid,pos,size,style,*validator);
+ EwxListCtrl * Result = new EwxListCtrl(parent,winid,pos,size,style,*validator);
+ Result->onGetItemText = onGetItemText;
+ Result->onGetItemAttr = onGetItemAttr;
+ Result->onGetItemColumnImage = onGetItemColumnImage;
+ Result->port = Ecmd.port;
newPtr((void *) Result, 0, memenv);
rt.addRef(getRef((void *)Result,memenv), "wxListCtrl");
break;
@@ -15213,14 +15230,18 @@ case wxListCtrl_ClearAll: { // wxListCtrl::ClearAll
This->ClearAll();
break;
}
+
case wxListCtrl_Create: { // wxListCtrl::Create
wxWindowID winid=wxID_ANY;
wxPoint pos= wxDefaultPosition;
wxSize size= wxDefaultSize;
long style=wxLC_ICON;
const wxValidator * validator= &wxDefaultValidator;
- wxListCtrl *This = (wxListCtrl *) getPtr(bp,memenv); bp += 4;
+ EwxListCtrl *This = (EwxListCtrl *) getPtr(bp,memenv); bp += 4;
wxWindow *parent = (wxWindow *) getPtr(bp,memenv); bp += 4;
+ int onGetItemText = 0, onGetItemAttr = 0, onGetItemColumnImage = 0;
+
+ bp += 4; /* Align */
while( * (int*) bp) { switch (* (int*) bp) {
case 1: {bp += 4;
winid = (wxWindowID)*(int *) bp; bp += 4;
@@ -15243,9 +15264,23 @@ case wxListCtrl_Create: { // wxListCtrl::Create
case 5: {bp += 4;
validator = (wxValidator *) getPtr(bp,memenv); bp += 4;
} break;
+ case 6: {bp += 4;
+ onGetItemText = *(int *) bp; bp += 4;
+ } break;
+ case 7: {bp += 4;
+ onGetItemAttr = *(int *) bp; bp += 4;
+ } break;
+ case 8: {bp += 4;
+ onGetItemColumnImage = *(int *) bp; bp += 4;
+ } break;
}};
if(!This) throw wxe_badarg(0);
bool Result = This->Create(parent,winid,pos,size,style,*validator);
+ This->onGetItemText = onGetItemText;
+ This->onGetItemAttr = onGetItemAttr;
+ This->onGetItemColumnImage = onGetItemColumnImage;
+ This->port = Ecmd.port;
+
rt.addBool(Result);
break;
}
@@ -16095,6 +16130,106 @@ case wxListItem_SetWidth: { // wxListItem::SetWidth
This->SetWidth((int) *width);
break;
}
+case wxListItemAttr_new_0: { // wxListItemAttr::wxListItemAttr
+ wxListItemAttr * Result = new wxListItemAttr();
+ newPtr((void *) Result, 101, memenv);
+ rt.addRef(getRef((void *)Result,memenv), "wxListItemAttr");
+ break;
+}
+case wxListItemAttr_new_3: { // wxListItemAttr::wxListItemAttr
+ int * colTextR = (int *) bp; bp += 4;
+ int * colTextG = (int *) bp; bp += 4;
+ int * colTextB = (int *) bp; bp += 4;
+ int * colTextA = (int *) bp; bp += 4;
+ wxColour colText = wxColour(*colTextR,*colTextG,*colTextB,*colTextA);
+ int * colBackR = (int *) bp; bp += 4;
+ int * colBackG = (int *) bp; bp += 4;
+ int * colBackB = (int *) bp; bp += 4;
+ int * colBackA = (int *) bp; bp += 4;
+ wxColour colBack = wxColour(*colBackR,*colBackG,*colBackB,*colBackA);
+ wxFont *font = (wxFont *) getPtr(bp,memenv); bp += 4;
+ wxListItemAttr * Result = new wxListItemAttr(colText,colBack,*font);
+ newPtr((void *) Result, 101, memenv);
+ rt.addRef(getRef((void *)Result,memenv), "wxListItemAttr");
+ break;
+}
+case wxListItemAttr_GetBackgroundColour: { // wxListItemAttr::GetBackgroundColour
+ wxListItemAttr *This = (wxListItemAttr *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ const wxColour * Result = &This->GetBackgroundColour();
+ rt.add((*Result));
+ break;
+}
+case wxListItemAttr_GetFont: { // wxListItemAttr::GetFont
+ wxListItemAttr *This = (wxListItemAttr *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ const wxFont * Result = &This->GetFont();
+ rt.addRef(getRef((void *)Result,memenv), "wxFont");
+ break;
+}
+case wxListItemAttr_GetTextColour: { // wxListItemAttr::GetTextColour
+ wxListItemAttr *This = (wxListItemAttr *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ const wxColour * Result = &This->GetTextColour();
+ rt.add((*Result));
+ break;
+}
+case wxListItemAttr_HasBackgroundColour: { // wxListItemAttr::HasBackgroundColour
+ wxListItemAttr *This = (wxListItemAttr *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ bool Result = This->HasBackgroundColour();
+ rt.addBool(Result);
+ break;
+}
+case wxListItemAttr_HasFont: { // wxListItemAttr::HasFont
+ wxListItemAttr *This = (wxListItemAttr *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ bool Result = This->HasFont();
+ rt.addBool(Result);
+ break;
+}
+case wxListItemAttr_HasTextColour: { // wxListItemAttr::HasTextColour
+ wxListItemAttr *This = (wxListItemAttr *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ bool Result = This->HasTextColour();
+ rt.addBool(Result);
+ break;
+}
+case wxListItemAttr_SetBackgroundColour: { // wxListItemAttr::SetBackgroundColour
+ wxListItemAttr *This = (wxListItemAttr *) getPtr(bp,memenv); bp += 4;
+ int * colBackR = (int *) bp; bp += 4;
+ int * colBackG = (int *) bp; bp += 4;
+ int * colBackB = (int *) bp; bp += 4;
+ int * colBackA = (int *) bp; bp += 4;
+ wxColour colBack = wxColour(*colBackR,*colBackG,*colBackB,*colBackA);
+ if(!This) throw wxe_badarg(0);
+ This->SetBackgroundColour(colBack);
+ break;
+}
+case wxListItemAttr_SetFont: { // wxListItemAttr::SetFont
+ wxListItemAttr *This = (wxListItemAttr *) getPtr(bp,memenv); bp += 4;
+ wxFont *font = (wxFont *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ This->SetFont(*font);
+ break;
+}
+case wxListItemAttr_SetTextColour: { // wxListItemAttr::SetTextColour
+ wxListItemAttr *This = (wxListItemAttr *) getPtr(bp,memenv); bp += 4;
+ int * colTextR = (int *) bp; bp += 4;
+ int * colTextG = (int *) bp; bp += 4;
+ int * colTextB = (int *) bp; bp += 4;
+ int * colTextA = (int *) bp; bp += 4;
+ wxColour colText = wxColour(*colTextR,*colTextG,*colTextB,*colTextA);
+ if(!This) throw wxe_badarg(0);
+ This->SetTextColour(colText);
+ break;
+}
+case wxListItemAttr_destroy: { // wxListItemAttr::destroy
+ wxListItemAttr *This = (wxListItemAttr *) getPtr(bp,memenv); bp += 4;
+ if(This) { ((WxeApp *) wxTheApp)->clearPtr((void *) This);
+ delete This;}
+ break;
+}
case wxImageList_new_0: { // wxImageList::wxImageList
wxImageList * Result = new EwxImageList();
newPtr((void *) Result, 1, memenv);
@@ -16263,7 +16398,7 @@ case wxImageList_Replace_3: { // wxImageList::Replace
}
case wxTextAttr_new_0: { // wxTextAttr::wxTextAttr
wxTextAttr * Result = new wxTextAttr();
- newPtr((void *) Result, 102, memenv);
+ newPtr((void *) Result, 103, memenv);
rt.addRef(getRef((void *)Result,memenv), "wxTextAttr");
break;
}
@@ -16293,7 +16428,7 @@ alignment = *(wxTextAttrAlignment *) bp; bp += 4;;
} break;
}};
wxTextAttr * Result = new wxTextAttr(colText,colBack,*font,(wxTextAttrAlignment) alignment);
- newPtr((void *) Result, 102, memenv);
+ newPtr((void *) Result, 103, memenv);
rt.addRef(getRef((void *)Result,memenv), "wxTextAttr");
break;
}
@@ -22711,7 +22846,7 @@ case wxPreviewFrame_new: { // wxPreviewFrame::wxPreviewFrame
wxString title= wxT("Print Preview");
wxPoint pos= wxDefaultPosition;
wxSize size= wxDefaultSize;
- long style=wxDEFAULT_FRAME_STYLE;
+ long style=wxDEFAULT_FRAME_STYLE|wxFRAME_FLOAT_ON_PARENT;
wxPrintPreview *preview = (wxPrintPreview *) getPtr(bp,memenv); bp += 4;
wxWindow *parent = (wxWindow *) getPtr(bp,memenv); bp += 4;
while( * (int*) bp) { switch (* (int*) bp) {
@@ -23742,14 +23877,14 @@ case wxAuiManager_Update: { // wxAuiManager::Update
#if wxUSE_AUI
case wxAuiPaneInfo_new_0: { // wxAuiPaneInfo::wxAuiPaneInfo
wxAuiPaneInfo * Result = new wxAuiPaneInfo();
- newPtr((void *) Result, 154, memenv);
+ newPtr((void *) Result, 155, memenv);
rt.addRef(getRef((void *)Result,memenv), "wxAuiPaneInfo");
break;
}
case wxAuiPaneInfo_new_1: { // wxAuiPaneInfo::wxAuiPaneInfo
wxAuiPaneInfo *c = (wxAuiPaneInfo *) getPtr(bp,memenv); bp += 4;
wxAuiPaneInfo * Result = new wxAuiPaneInfo(*c);
- newPtr((void *) Result, 154, memenv);
+ newPtr((void *) Result, 155, memenv);
rt.addRef(getRef((void *)Result,memenv), "wxAuiPaneInfo");
break;
}
@@ -30292,7 +30427,7 @@ case wxNotebookEvent_SetSelection: { // wxNotebookEvent::SetSelection
}
case wxFileDataObject_new: { // wxFileDataObject::wxFileDataObject
wxFileDataObject * Result = new wxFileDataObject();
- newPtr((void *) Result, 211, memenv);
+ newPtr((void *) Result, 212, memenv);
rt.addRef(getRef((void *)Result,memenv), "wxFileDataObject");
break;
}
@@ -30328,7 +30463,7 @@ case wxTextDataObject_new: { // wxTextDataObject::wxTextDataObject
} break;
}};
wxTextDataObject * Result = new wxTextDataObject(text);
- newPtr((void *) Result, 212, memenv);
+ newPtr((void *) Result, 213, memenv);
rt.addRef(getRef((void *)Result,memenv), "wxTextDataObject");
break;
}
@@ -30364,7 +30499,7 @@ case wxTextDataObject_destroy: { // wxTextDataObject::destroy
case wxBitmapDataObject_new_1_1: { // wxBitmapDataObject::wxBitmapDataObject
wxBitmap *bitmap = (wxBitmap *) getPtr(bp,memenv); bp += 4;
wxBitmapDataObject * Result = new wxBitmapDataObject(*bitmap);
- newPtr((void *) Result, 213, memenv);
+ newPtr((void *) Result, 214, memenv);
rt.addRef(getRef((void *)Result,memenv), "wxBitmapDataObject");
break;
}
@@ -30376,7 +30511,7 @@ bitmap = (wxBitmap *) getPtr(bp,memenv); bp += 4;
} break;
}};
wxBitmapDataObject * Result = new wxBitmapDataObject(*bitmap);
- newPtr((void *) Result, 213, memenv);
+ newPtr((void *) Result, 214, memenv);
rt.addRef(getRef((void *)Result,memenv), "wxBitmapDataObject");
break;
}
@@ -31025,6 +31160,56 @@ case wxSystemSettings_GetScreenType: { // wxSystemSettings::GetScreenType
rt.addInt(Result);
break;
}
+case wxSystemOptions_GetOption: { // wxSystemOptions::GetOption
+ int * nameLen = (int *) bp; bp += 4;
+ wxString name = wxString(bp, wxConvUTF8);
+ bp += *nameLen+((8-((4+ *nameLen) & 7)) & 7);
+ wxString Result = wxSystemOptions::GetOption(name);
+ rt.add(Result);
+ break;
+}
+case wxSystemOptions_GetOptionInt: { // wxSystemOptions::GetOptionInt
+ int * nameLen = (int *) bp; bp += 4;
+ wxString name = wxString(bp, wxConvUTF8);
+ bp += *nameLen+((8-((4+ *nameLen) & 7)) & 7);
+ int Result = wxSystemOptions::GetOptionInt(name);
+ rt.addInt(Result);
+ break;
+}
+case wxSystemOptions_HasOption: { // wxSystemOptions::HasOption
+ int * nameLen = (int *) bp; bp += 4;
+ wxString name = wxString(bp, wxConvUTF8);
+ bp += *nameLen+((8-((4+ *nameLen) & 7)) & 7);
+ bool Result = wxSystemOptions::HasOption(name);
+ rt.addBool(Result);
+ break;
+}
+case wxSystemOptions_IsFalse: { // wxSystemOptions::IsFalse
+ int * nameLen = (int *) bp; bp += 4;
+ wxString name = wxString(bp, wxConvUTF8);
+ bp += *nameLen+((8-((4+ *nameLen) & 7)) & 7);
+ bool Result = wxSystemOptions::IsFalse(name);
+ rt.addBool(Result);
+ break;
+}
+case wxSystemOptions_SetOption_2_1: { // wxSystemOptions::SetOption
+ int * nameLen = (int *) bp; bp += 4;
+ wxString name = wxString(bp, wxConvUTF8);
+ bp += *nameLen+((8-((4+ *nameLen) & 7)) & 7);
+ int * valueLen = (int *) bp; bp += 4;
+ wxString value = wxString(bp, wxConvUTF8);
+ bp += *valueLen+((8-((4+ *valueLen) & 7)) & 7);
+ wxSystemOptions::SetOption(name,value);
+ break;
+}
+case wxSystemOptions_SetOption_2_0: { // wxSystemOptions::SetOption
+ int * nameLen = (int *) bp; bp += 4;
+ wxString name = wxString(bp, wxConvUTF8);
+ bp += *nameLen+((8-((4+ *nameLen) & 7)) & 7);
+ int * value = (int *) bp; bp += 4;
+ wxSystemOptions::SetOption(name,(int) *value);
+ break;
+}
case wxAuiNotebookEvent_SetSelection: { // wxAuiNotebookEvent::SetSelection
wxAuiNotebookEvent *This = (wxAuiNotebookEvent *) getPtr(bp,memenv); bp += 4;
int * s = (int *) bp; bp += 4;
@@ -31159,7 +31344,7 @@ case wxAuiManagerEvent_CanVeto: { // wxAuiManagerEvent::CanVeto
}
case wxLogNull_new: { // wxLogNull::wxLogNull
wxLogNull * Result = new wxLogNull();
- newPtr((void *) Result, 223, memenv);
+ newPtr((void *) Result, 225, memenv);
rt.addRef(getRef((void *)Result,memenv), "wxLogNull");
break;
}
@@ -31188,3 +31373,31 @@ case wxLogNull_destroy: { // wxLogNull::destroy
error.addTupleCount(3);
error.send();
}} /* The End */
+
+
+void WxeApp::delete_object(void *ptr, wxeRefData *refd) {
+ switch(refd->type) {
+ case 24: delete (wxGridCellBoolRenderer *) ptr; break;
+ case 25: delete (wxGridCellBoolEditor *) ptr; break;
+ case 26: delete (wxGridCellFloatRenderer *) ptr; break;
+ case 27: delete (wxGridCellFloatEditor *) ptr; break;
+ case 28: delete (wxGridCellStringRenderer *) ptr; break;
+ case 29: delete (wxGridCellTextEditor *) ptr; break;
+ case 30: delete (wxGridCellChoiceEditor *) ptr; break;
+ case 31: delete (wxGridCellNumberRenderer *) ptr; break;
+ case 32: delete (wxGridCellNumberEditor *) ptr; break;
+ case 61: delete (wxIconBundle *) ptr; break;
+ case 69: delete (wxAcceleratorEntry *) ptr; break;
+ case 70: /* delete (wxCaret *) ptr;These objects must be deleted by owner object */ break;
+ case 72: delete (wxSizerFlags *) ptr; break;
+ case 88: /* delete (wxCalendarDateAttr *) ptr;These objects must be deleted by owner object */ break;
+ case 101: delete (wxListItemAttr *) ptr; break;
+ case 103: delete (wxTextAttr *) ptr; break;
+ case 155: delete (wxAuiPaneInfo *) ptr; break;
+ case 212: /* delete (wxFileDataObject *) ptr;These objects must be deleted by owner object */ break;
+ case 213: /* delete (wxTextDataObject *) ptr;These objects must be deleted by owner object */ break;
+ case 214: /* delete (wxBitmapDataObject *) ptr;These objects must be deleted by owner object */ break;
+ case 225: delete (wxLogNull *) ptr; break;
+ default: delete (wxObject *) ptr;
+}}
+
diff --git a/lib/wx/c_src/gen/wxe_init.cpp b/lib/wx/c_src/gen/wxe_init.cpp
index bab3261be4..a75298392b 100644
--- a/lib/wx/c_src/gen/wxe_init.cpp
+++ b/lib/wx/c_src/gen/wxe_init.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/wx/c_src/gen/wxe_macros.h b/lib/wx/c_src/gen/wxe_macros.h
index 4fb76f960b..ddc7c0155f 100644
--- a/lib/wx/c_src/gen/wxe_macros.h
+++ b/lib/wx/c_src/gen/wxe_macros.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -60,6 +60,7 @@
#include <wx/html/htmlwin.h>
#include <wx/html/htmlcell.h>
#include <wx/filename.h>
+#include <wx/sysopt.h>
#ifndef wxICON_DEFAULT_BITMAP_TYPE
@@ -1648,1683 +1649,1701 @@
#define wxListItem_SetText 1754
#define wxListItem_SetTextColour 1755
#define wxListItem_SetWidth 1756
-#define wxImageList_new_0 1757
-#define wxImageList_new_3 1758
-#define wxImageList_Add_1 1759
-#define wxImageList_Add_2_0 1760
-#define wxImageList_Add_2_1 1761
-#define wxImageList_Create 1762
-#define wxImageList_Draw 1764
-#define wxImageList_GetBitmap 1765
-#define wxImageList_GetIcon 1766
-#define wxImageList_GetImageCount 1767
-#define wxImageList_GetSize 1768
-#define wxImageList_Remove 1769
-#define wxImageList_RemoveAll 1770
-#define wxImageList_Replace_2 1771
-#define wxImageList_Replace_3 1772
-#define wxImageList_destroy 1773
-#define wxTextAttr_new_0 1774
-#define wxTextAttr_new_2 1775
-#define wxTextAttr_GetAlignment 1776
-#define wxTextAttr_GetBackgroundColour 1777
-#define wxTextAttr_GetFont 1778
-#define wxTextAttr_GetLeftIndent 1779
-#define wxTextAttr_GetLeftSubIndent 1780
-#define wxTextAttr_GetRightIndent 1781
-#define wxTextAttr_GetTabs 1782
-#define wxTextAttr_GetTextColour 1783
-#define wxTextAttr_HasBackgroundColour 1784
-#define wxTextAttr_HasFont 1785
-#define wxTextAttr_HasTextColour 1786
-#define wxTextAttr_GetFlags 1787
-#define wxTextAttr_IsDefault 1788
-#define wxTextAttr_SetAlignment 1789
-#define wxTextAttr_SetBackgroundColour 1790
-#define wxTextAttr_SetFlags 1791
-#define wxTextAttr_SetFont 1792
-#define wxTextAttr_SetLeftIndent 1793
-#define wxTextAttr_SetRightIndent 1794
-#define wxTextAttr_SetTabs 1795
-#define wxTextAttr_SetTextColour 1796
-#define wxTextAttr_destroy 1797
-#define wxTextCtrl_new_3 1799
-#define wxTextCtrl_new_0 1800
-#define wxTextCtrl_destruct 1802
-#define wxTextCtrl_AppendText 1803
-#define wxTextCtrl_CanCopy 1804
-#define wxTextCtrl_CanCut 1805
-#define wxTextCtrl_CanPaste 1806
-#define wxTextCtrl_CanRedo 1807
-#define wxTextCtrl_CanUndo 1808
-#define wxTextCtrl_Clear 1809
-#define wxTextCtrl_Copy 1810
-#define wxTextCtrl_Create 1811
-#define wxTextCtrl_Cut 1812
-#define wxTextCtrl_DiscardEdits 1813
-#define wxTextCtrl_EmulateKeyPress 1814
-#define wxTextCtrl_GetDefaultStyle 1815
-#define wxTextCtrl_GetInsertionPoint 1816
-#define wxTextCtrl_GetLastPosition 1817
-#define wxTextCtrl_GetLineLength 1818
-#define wxTextCtrl_GetLineText 1819
-#define wxTextCtrl_GetNumberOfLines 1820
-#define wxTextCtrl_GetRange 1821
-#define wxTextCtrl_GetSelection 1822
-#define wxTextCtrl_GetStringSelection 1823
-#define wxTextCtrl_GetStyle 1824
-#define wxTextCtrl_GetValue 1825
-#define wxTextCtrl_IsEditable 1826
-#define wxTextCtrl_IsModified 1827
-#define wxTextCtrl_IsMultiLine 1828
-#define wxTextCtrl_IsSingleLine 1829
-#define wxTextCtrl_LoadFile 1830
-#define wxTextCtrl_MarkDirty 1831
-#define wxTextCtrl_Paste 1832
-#define wxTextCtrl_PositionToXY 1833
-#define wxTextCtrl_Redo 1834
-#define wxTextCtrl_Remove 1835
-#define wxTextCtrl_Replace 1836
-#define wxTextCtrl_SaveFile 1837
-#define wxTextCtrl_SetDefaultStyle 1838
-#define wxTextCtrl_SetEditable 1839
-#define wxTextCtrl_SetInsertionPoint 1840
-#define wxTextCtrl_SetInsertionPointEnd 1841
-#define wxTextCtrl_SetMaxLength 1843
-#define wxTextCtrl_SetSelection 1844
-#define wxTextCtrl_SetStyle 1845
-#define wxTextCtrl_SetValue 1846
-#define wxTextCtrl_ShowPosition 1847
-#define wxTextCtrl_Undo 1848
-#define wxTextCtrl_WriteText 1849
-#define wxTextCtrl_XYToPosition 1850
-#define wxNotebook_new_0 1853
-#define wxNotebook_new_3 1854
-#define wxNotebook_destruct 1855
-#define wxNotebook_AddPage 1856
-#define wxNotebook_AdvanceSelection 1857
-#define wxNotebook_AssignImageList 1858
-#define wxNotebook_Create 1859
-#define wxNotebook_DeleteAllPages 1860
-#define wxNotebook_DeletePage 1861
-#define wxNotebook_RemovePage 1862
-#define wxNotebook_GetCurrentPage 1863
-#define wxNotebook_GetImageList 1864
-#define wxNotebook_GetPage 1866
-#define wxNotebook_GetPageCount 1867
-#define wxNotebook_GetPageImage 1868
-#define wxNotebook_GetPageText 1869
-#define wxNotebook_GetRowCount 1870
-#define wxNotebook_GetSelection 1871
-#define wxNotebook_GetThemeBackgroundColour 1872
-#define wxNotebook_HitTest 1874
-#define wxNotebook_InsertPage 1876
-#define wxNotebook_SetImageList 1877
-#define wxNotebook_SetPadding 1878
-#define wxNotebook_SetPageSize 1879
-#define wxNotebook_SetPageImage 1880
-#define wxNotebook_SetPageText 1881
-#define wxNotebook_SetSelection 1882
-#define wxNotebook_ChangeSelection 1883
-#define wxChoicebook_new_0 1884
-#define wxChoicebook_new_3 1885
-#define wxChoicebook_AddPage 1886
-#define wxChoicebook_AdvanceSelection 1887
-#define wxChoicebook_AssignImageList 1888
-#define wxChoicebook_Create 1889
-#define wxChoicebook_DeleteAllPages 1890
-#define wxChoicebook_DeletePage 1891
-#define wxChoicebook_RemovePage 1892
-#define wxChoicebook_GetCurrentPage 1893
-#define wxChoicebook_GetImageList 1894
-#define wxChoicebook_GetPage 1896
-#define wxChoicebook_GetPageCount 1897
-#define wxChoicebook_GetPageImage 1898
-#define wxChoicebook_GetPageText 1899
-#define wxChoicebook_GetSelection 1900
-#define wxChoicebook_HitTest 1901
-#define wxChoicebook_InsertPage 1902
-#define wxChoicebook_SetImageList 1903
-#define wxChoicebook_SetPageSize 1904
-#define wxChoicebook_SetPageImage 1905
-#define wxChoicebook_SetPageText 1906
-#define wxChoicebook_SetSelection 1907
-#define wxChoicebook_ChangeSelection 1908
-#define wxChoicebook_destroy 1909
-#define wxToolbook_new_0 1910
-#define wxToolbook_new_3 1911
-#define wxToolbook_AddPage 1912
-#define wxToolbook_AdvanceSelection 1913
-#define wxToolbook_AssignImageList 1914
-#define wxToolbook_Create 1915
-#define wxToolbook_DeleteAllPages 1916
-#define wxToolbook_DeletePage 1917
-#define wxToolbook_RemovePage 1918
-#define wxToolbook_GetCurrentPage 1919
-#define wxToolbook_GetImageList 1920
-#define wxToolbook_GetPage 1922
-#define wxToolbook_GetPageCount 1923
-#define wxToolbook_GetPageImage 1924
-#define wxToolbook_GetPageText 1925
-#define wxToolbook_GetSelection 1926
-#define wxToolbook_HitTest 1928
-#define wxToolbook_InsertPage 1929
-#define wxToolbook_SetImageList 1930
-#define wxToolbook_SetPageSize 1931
-#define wxToolbook_SetPageImage 1932
-#define wxToolbook_SetPageText 1933
-#define wxToolbook_SetSelection 1934
-#define wxToolbook_ChangeSelection 1935
-#define wxToolbook_destroy 1936
-#define wxListbook_new_0 1937
-#define wxListbook_new_3 1938
-#define wxListbook_AddPage 1939
-#define wxListbook_AdvanceSelection 1940
-#define wxListbook_AssignImageList 1941
-#define wxListbook_Create 1942
-#define wxListbook_DeleteAllPages 1943
-#define wxListbook_DeletePage 1944
-#define wxListbook_RemovePage 1945
-#define wxListbook_GetCurrentPage 1946
-#define wxListbook_GetImageList 1947
-#define wxListbook_GetPage 1949
-#define wxListbook_GetPageCount 1950
-#define wxListbook_GetPageImage 1951
-#define wxListbook_GetPageText 1952
-#define wxListbook_GetSelection 1953
-#define wxListbook_HitTest 1955
-#define wxListbook_InsertPage 1956
-#define wxListbook_SetImageList 1957
-#define wxListbook_SetPageSize 1958
-#define wxListbook_SetPageImage 1959
-#define wxListbook_SetPageText 1960
-#define wxListbook_SetSelection 1961
-#define wxListbook_ChangeSelection 1962
-#define wxListbook_destroy 1963
-#define wxTreebook_new_0 1964
-#define wxTreebook_new_3 1965
-#define wxTreebook_AddPage 1966
-#define wxTreebook_AdvanceSelection 1967
-#define wxTreebook_AssignImageList 1968
-#define wxTreebook_Create 1969
-#define wxTreebook_DeleteAllPages 1970
-#define wxTreebook_DeletePage 1971
-#define wxTreebook_RemovePage 1972
-#define wxTreebook_GetCurrentPage 1973
-#define wxTreebook_GetImageList 1974
-#define wxTreebook_GetPage 1976
-#define wxTreebook_GetPageCount 1977
-#define wxTreebook_GetPageImage 1978
-#define wxTreebook_GetPageText 1979
-#define wxTreebook_GetSelection 1980
-#define wxTreebook_ExpandNode 1981
-#define wxTreebook_IsNodeExpanded 1982
-#define wxTreebook_HitTest 1984
-#define wxTreebook_InsertPage 1985
-#define wxTreebook_InsertSubPage 1986
-#define wxTreebook_SetImageList 1987
-#define wxTreebook_SetPageSize 1988
-#define wxTreebook_SetPageImage 1989
-#define wxTreebook_SetPageText 1990
-#define wxTreebook_SetSelection 1991
-#define wxTreebook_ChangeSelection 1992
-#define wxTreebook_destroy 1993
-#define wxTreeCtrl_new_2 1996
-#define wxTreeCtrl_new_0 1997
-#define wxTreeCtrl_destruct 1999
-#define wxTreeCtrl_AddRoot 2000
-#define wxTreeCtrl_AppendItem 2001
-#define wxTreeCtrl_AssignImageList 2002
-#define wxTreeCtrl_AssignStateImageList 2003
-#define wxTreeCtrl_Collapse 2004
-#define wxTreeCtrl_CollapseAndReset 2005
-#define wxTreeCtrl_Create 2006
-#define wxTreeCtrl_Delete 2007
-#define wxTreeCtrl_DeleteAllItems 2008
-#define wxTreeCtrl_DeleteChildren 2009
-#define wxTreeCtrl_EditLabel 2010
-#define wxTreeCtrl_EnsureVisible 2011
-#define wxTreeCtrl_Expand 2012
-#define wxTreeCtrl_GetBoundingRect 2013
-#define wxTreeCtrl_GetChildrenCount 2015
-#define wxTreeCtrl_GetCount 2016
-#define wxTreeCtrl_GetEditControl 2017
-#define wxTreeCtrl_GetFirstChild 2018
-#define wxTreeCtrl_GetNextChild 2019
-#define wxTreeCtrl_GetFirstVisibleItem 2020
-#define wxTreeCtrl_GetImageList 2021
-#define wxTreeCtrl_GetIndent 2022
-#define wxTreeCtrl_GetItemBackgroundColour 2023
-#define wxTreeCtrl_GetItemData 2024
-#define wxTreeCtrl_GetItemFont 2025
-#define wxTreeCtrl_GetItemImage_1 2026
-#define wxTreeCtrl_GetItemImage_2 2027
-#define wxTreeCtrl_GetItemText 2028
-#define wxTreeCtrl_GetItemTextColour 2029
-#define wxTreeCtrl_GetLastChild 2030
-#define wxTreeCtrl_GetNextSibling 2031
-#define wxTreeCtrl_GetNextVisible 2032
-#define wxTreeCtrl_GetItemParent 2033
-#define wxTreeCtrl_GetPrevSibling 2034
-#define wxTreeCtrl_GetPrevVisible 2035
-#define wxTreeCtrl_GetRootItem 2036
-#define wxTreeCtrl_GetSelection 2037
-#define wxTreeCtrl_GetSelections 2038
-#define wxTreeCtrl_GetStateImageList 2039
-#define wxTreeCtrl_HitTest 2040
-#define wxTreeCtrl_InsertItem 2042
-#define wxTreeCtrl_IsBold 2043
-#define wxTreeCtrl_IsExpanded 2044
-#define wxTreeCtrl_IsSelected 2045
-#define wxTreeCtrl_IsVisible 2046
-#define wxTreeCtrl_ItemHasChildren 2047
-#define wxTreeCtrl_PrependItem 2048
-#define wxTreeCtrl_ScrollTo 2049
-#define wxTreeCtrl_SelectItem_1 2050
-#define wxTreeCtrl_SelectItem_2 2051
-#define wxTreeCtrl_SetIndent 2052
-#define wxTreeCtrl_SetImageList 2053
-#define wxTreeCtrl_SetItemBackgroundColour 2054
-#define wxTreeCtrl_SetItemBold 2055
-#define wxTreeCtrl_SetItemData 2056
-#define wxTreeCtrl_SetItemDropHighlight 2057
-#define wxTreeCtrl_SetItemFont 2058
-#define wxTreeCtrl_SetItemHasChildren 2059
-#define wxTreeCtrl_SetItemImage_2 2060
-#define wxTreeCtrl_SetItemImage_3 2061
-#define wxTreeCtrl_SetItemText 2062
-#define wxTreeCtrl_SetItemTextColour 2063
-#define wxTreeCtrl_SetStateImageList 2064
-#define wxTreeCtrl_SetWindowStyle 2065
-#define wxTreeCtrl_SortChildren 2066
-#define wxTreeCtrl_Toggle 2067
-#define wxTreeCtrl_ToggleItemSelection 2068
-#define wxTreeCtrl_Unselect 2069
-#define wxTreeCtrl_UnselectAll 2070
-#define wxTreeCtrl_UnselectItem 2071
-#define wxScrollBar_new_0 2072
-#define wxScrollBar_new_3 2073
-#define wxScrollBar_destruct 2074
-#define wxScrollBar_Create 2075
-#define wxScrollBar_GetRange 2076
-#define wxScrollBar_GetPageSize 2077
-#define wxScrollBar_GetThumbPosition 2078
-#define wxScrollBar_GetThumbSize 2079
-#define wxScrollBar_SetThumbPosition 2080
-#define wxScrollBar_SetScrollbar 2081
-#define wxSpinButton_new_2 2083
-#define wxSpinButton_new_0 2084
-#define wxSpinButton_Create 2085
-#define wxSpinButton_GetMax 2086
-#define wxSpinButton_GetMin 2087
-#define wxSpinButton_GetValue 2088
-#define wxSpinButton_SetRange 2089
-#define wxSpinButton_SetValue 2090
-#define wxSpinButton_destroy 2091
-#define wxSpinCtrl_new_0 2092
-#define wxSpinCtrl_new_2 2093
-#define wxSpinCtrl_Create 2095
-#define wxSpinCtrl_SetValue_1_1 2098
-#define wxSpinCtrl_SetValue_1_0 2099
-#define wxSpinCtrl_GetValue 2101
-#define wxSpinCtrl_SetRange 2103
-#define wxSpinCtrl_SetSelection 2104
-#define wxSpinCtrl_GetMin 2106
-#define wxSpinCtrl_GetMax 2108
-#define wxSpinCtrl_destroy 2109
-#define wxStaticText_new_0 2110
-#define wxStaticText_new_4 2111
-#define wxStaticText_Create 2112
-#define wxStaticText_GetLabel 2113
-#define wxStaticText_SetLabel 2114
-#define wxStaticText_Wrap 2115
-#define wxStaticText_destroy 2116
-#define wxStaticBitmap_new_0 2117
-#define wxStaticBitmap_new_4 2118
-#define wxStaticBitmap_Create 2119
-#define wxStaticBitmap_GetBitmap 2120
-#define wxStaticBitmap_SetBitmap 2121
-#define wxStaticBitmap_destroy 2122
-#define wxRadioBox_new 2123
-#define wxRadioBox_destruct 2125
-#define wxRadioBox_Create 2126
-#define wxRadioBox_Enable_2 2127
-#define wxRadioBox_Enable_1 2128
-#define wxRadioBox_GetSelection 2129
-#define wxRadioBox_GetString 2130
-#define wxRadioBox_SetSelection 2131
-#define wxRadioBox_Show_2 2132
-#define wxRadioBox_Show_1 2133
-#define wxRadioBox_GetColumnCount 2134
-#define wxRadioBox_GetItemHelpText 2135
-#define wxRadioBox_GetItemToolTip 2136
-#define wxRadioBox_GetItemFromPoint 2138
-#define wxRadioBox_GetRowCount 2139
-#define wxRadioBox_IsItemEnabled 2140
-#define wxRadioBox_IsItemShown 2141
-#define wxRadioBox_SetItemHelpText 2142
-#define wxRadioBox_SetItemToolTip 2143
-#define wxRadioButton_new_0 2144
-#define wxRadioButton_new_4 2145
-#define wxRadioButton_Create 2146
-#define wxRadioButton_GetValue 2147
-#define wxRadioButton_SetValue 2148
-#define wxRadioButton_destroy 2149
-#define wxSlider_new_6 2151
-#define wxSlider_new_0 2152
-#define wxSlider_Create 2153
-#define wxSlider_GetLineSize 2154
-#define wxSlider_GetMax 2155
-#define wxSlider_GetMin 2156
-#define wxSlider_GetPageSize 2157
-#define wxSlider_GetThumbLength 2158
-#define wxSlider_GetValue 2159
-#define wxSlider_SetLineSize 2160
-#define wxSlider_SetPageSize 2161
-#define wxSlider_SetRange 2162
-#define wxSlider_SetThumbLength 2163
-#define wxSlider_SetValue 2164
-#define wxSlider_destroy 2165
-#define wxDialog_new_4 2167
-#define wxDialog_new_0 2168
-#define wxDialog_destruct 2170
-#define wxDialog_Create 2171
-#define wxDialog_CreateButtonSizer 2172
-#define wxDialog_CreateStdDialogButtonSizer 2173
-#define wxDialog_EndModal 2174
-#define wxDialog_GetAffirmativeId 2175
-#define wxDialog_GetReturnCode 2176
-#define wxDialog_IsModal 2177
-#define wxDialog_SetAffirmativeId 2178
-#define wxDialog_SetReturnCode 2179
-#define wxDialog_Show 2180
-#define wxDialog_ShowModal 2181
-#define wxColourDialog_new_0 2182
-#define wxColourDialog_new_2 2183
-#define wxColourDialog_destruct 2184
-#define wxColourDialog_Create 2185
-#define wxColourDialog_GetColourData 2186
-#define wxColourData_new_0 2187
-#define wxColourData_new_1 2188
-#define wxColourData_destruct 2189
-#define wxColourData_GetChooseFull 2190
-#define wxColourData_GetColour 2191
-#define wxColourData_GetCustomColour 2193
-#define wxColourData_SetChooseFull 2194
-#define wxColourData_SetColour 2195
-#define wxColourData_SetCustomColour 2196
-#define wxPalette_new_0 2197
-#define wxPalette_new_4 2198
-#define wxPalette_destruct 2200
-#define wxPalette_Create 2201
-#define wxPalette_GetColoursCount 2202
-#define wxPalette_GetPixel 2203
-#define wxPalette_GetRGB 2204
-#define wxPalette_IsOk 2205
-#define wxDirDialog_new 2209
-#define wxDirDialog_destruct 2210
-#define wxDirDialog_GetPath 2211
-#define wxDirDialog_GetMessage 2212
-#define wxDirDialog_SetMessage 2213
-#define wxDirDialog_SetPath 2214
-#define wxFileDialog_new 2218
-#define wxFileDialog_destruct 2219
-#define wxFileDialog_GetDirectory 2220
-#define wxFileDialog_GetFilename 2221
-#define wxFileDialog_GetFilenames 2222
-#define wxFileDialog_GetFilterIndex 2223
-#define wxFileDialog_GetMessage 2224
-#define wxFileDialog_GetPath 2225
-#define wxFileDialog_GetPaths 2226
-#define wxFileDialog_GetWildcard 2227
-#define wxFileDialog_SetDirectory 2228
-#define wxFileDialog_SetFilename 2229
-#define wxFileDialog_SetFilterIndex 2230
-#define wxFileDialog_SetMessage 2231
-#define wxFileDialog_SetPath 2232
-#define wxFileDialog_SetWildcard 2233
-#define wxPickerBase_SetInternalMargin 2234
-#define wxPickerBase_GetInternalMargin 2235
-#define wxPickerBase_SetTextCtrlProportion 2236
-#define wxPickerBase_SetPickerCtrlProportion 2237
-#define wxPickerBase_GetTextCtrlProportion 2238
-#define wxPickerBase_GetPickerCtrlProportion 2239
-#define wxPickerBase_HasTextCtrl 2240
-#define wxPickerBase_GetTextCtrl 2241
-#define wxPickerBase_IsTextCtrlGrowable 2242
-#define wxPickerBase_SetPickerCtrlGrowable 2243
-#define wxPickerBase_SetTextCtrlGrowable 2244
-#define wxPickerBase_IsPickerCtrlGrowable 2245
-#define wxFilePickerCtrl_new_0 2246
-#define wxFilePickerCtrl_new_3 2247
-#define wxFilePickerCtrl_Create 2248
-#define wxFilePickerCtrl_GetPath 2249
-#define wxFilePickerCtrl_SetPath 2250
-#define wxFilePickerCtrl_destroy 2251
-#define wxDirPickerCtrl_new_0 2252
-#define wxDirPickerCtrl_new_3 2253
-#define wxDirPickerCtrl_Create 2254
-#define wxDirPickerCtrl_GetPath 2255
-#define wxDirPickerCtrl_SetPath 2256
-#define wxDirPickerCtrl_destroy 2257
-#define wxColourPickerCtrl_new_0 2258
-#define wxColourPickerCtrl_new_3 2259
-#define wxColourPickerCtrl_Create 2260
-#define wxColourPickerCtrl_GetColour 2261
-#define wxColourPickerCtrl_SetColour_1_1 2262
-#define wxColourPickerCtrl_SetColour_1_0 2263
-#define wxColourPickerCtrl_destroy 2264
-#define wxDatePickerCtrl_new_0 2265
-#define wxDatePickerCtrl_new_3 2266
-#define wxDatePickerCtrl_GetRange 2267
-#define wxDatePickerCtrl_GetValue 2268
-#define wxDatePickerCtrl_SetRange 2269
-#define wxDatePickerCtrl_SetValue 2270
-#define wxDatePickerCtrl_destroy 2271
-#define wxFontPickerCtrl_new_0 2272
-#define wxFontPickerCtrl_new_3 2273
-#define wxFontPickerCtrl_Create 2274
-#define wxFontPickerCtrl_GetSelectedFont 2275
-#define wxFontPickerCtrl_SetSelectedFont 2276
-#define wxFontPickerCtrl_GetMaxPointSize 2277
-#define wxFontPickerCtrl_SetMaxPointSize 2278
-#define wxFontPickerCtrl_destroy 2279
-#define wxFindReplaceDialog_new_0 2282
-#define wxFindReplaceDialog_new_4 2283
-#define wxFindReplaceDialog_destruct 2284
-#define wxFindReplaceDialog_Create 2285
-#define wxFindReplaceDialog_GetData 2286
-#define wxFindReplaceData_new_0 2287
-#define wxFindReplaceData_new_1 2288
-#define wxFindReplaceData_GetFindString 2289
-#define wxFindReplaceData_GetReplaceString 2290
-#define wxFindReplaceData_GetFlags 2291
-#define wxFindReplaceData_SetFlags 2292
-#define wxFindReplaceData_SetFindString 2293
-#define wxFindReplaceData_SetReplaceString 2294
-#define wxFindReplaceData_destroy 2295
-#define wxMultiChoiceDialog_new_0 2296
-#define wxMultiChoiceDialog_new_5 2298
-#define wxMultiChoiceDialog_GetSelections 2299
-#define wxMultiChoiceDialog_SetSelections 2300
-#define wxMultiChoiceDialog_destroy 2301
-#define wxSingleChoiceDialog_new_0 2302
-#define wxSingleChoiceDialog_new_5 2304
-#define wxSingleChoiceDialog_GetSelection 2305
-#define wxSingleChoiceDialog_GetStringSelection 2306
-#define wxSingleChoiceDialog_SetSelection 2307
-#define wxSingleChoiceDialog_destroy 2308
-#define wxTextEntryDialog_new 2309
-#define wxTextEntryDialog_GetValue 2310
-#define wxTextEntryDialog_SetValue 2311
-#define wxTextEntryDialog_destroy 2312
-#define wxPasswordEntryDialog_new 2313
-#define wxPasswordEntryDialog_destroy 2314
-#define wxFontData_new_0 2315
-#define wxFontData_new_1 2316
-#define wxFontData_destruct 2317
-#define wxFontData_EnableEffects 2318
-#define wxFontData_GetAllowSymbols 2319
-#define wxFontData_GetColour 2320
-#define wxFontData_GetChosenFont 2321
-#define wxFontData_GetEnableEffects 2322
-#define wxFontData_GetInitialFont 2323
-#define wxFontData_GetShowHelp 2324
-#define wxFontData_SetAllowSymbols 2325
-#define wxFontData_SetChosenFont 2326
-#define wxFontData_SetColour 2327
-#define wxFontData_SetInitialFont 2328
-#define wxFontData_SetRange 2329
-#define wxFontData_SetShowHelp 2330
-#define wxFontDialog_new_0 2334
-#define wxFontDialog_new_2 2336
-#define wxFontDialog_Create 2338
-#define wxFontDialog_GetFontData 2339
-#define wxFontDialog_destroy 2341
-#define wxProgressDialog_new 2342
-#define wxProgressDialog_destruct 2343
-#define wxProgressDialog_Resume 2344
-#define wxProgressDialog_Update_2 2345
-#define wxProgressDialog_Update_0 2346
-#define wxMessageDialog_new 2347
-#define wxMessageDialog_destruct 2348
-#define wxPageSetupDialog_new 2349
-#define wxPageSetupDialog_destruct 2350
-#define wxPageSetupDialog_GetPageSetupData 2351
-#define wxPageSetupDialog_ShowModal 2352
-#define wxPageSetupDialogData_new_0 2353
-#define wxPageSetupDialogData_new_1_0 2354
-#define wxPageSetupDialogData_new_1_1 2355
-#define wxPageSetupDialogData_destruct 2356
-#define wxPageSetupDialogData_EnableHelp 2357
-#define wxPageSetupDialogData_EnableMargins 2358
-#define wxPageSetupDialogData_EnableOrientation 2359
-#define wxPageSetupDialogData_EnablePaper 2360
-#define wxPageSetupDialogData_EnablePrinter 2361
-#define wxPageSetupDialogData_GetDefaultMinMargins 2362
-#define wxPageSetupDialogData_GetEnableMargins 2363
-#define wxPageSetupDialogData_GetEnableOrientation 2364
-#define wxPageSetupDialogData_GetEnablePaper 2365
-#define wxPageSetupDialogData_GetEnablePrinter 2366
-#define wxPageSetupDialogData_GetEnableHelp 2367
-#define wxPageSetupDialogData_GetDefaultInfo 2368
-#define wxPageSetupDialogData_GetMarginTopLeft 2369
-#define wxPageSetupDialogData_GetMarginBottomRight 2370
-#define wxPageSetupDialogData_GetMinMarginTopLeft 2371
-#define wxPageSetupDialogData_GetMinMarginBottomRight 2372
-#define wxPageSetupDialogData_GetPaperId 2373
-#define wxPageSetupDialogData_GetPaperSize 2374
-#define wxPageSetupDialogData_GetPrintData 2376
-#define wxPageSetupDialogData_IsOk 2377
-#define wxPageSetupDialogData_SetDefaultInfo 2378
-#define wxPageSetupDialogData_SetDefaultMinMargins 2379
-#define wxPageSetupDialogData_SetMarginTopLeft 2380
-#define wxPageSetupDialogData_SetMarginBottomRight 2381
-#define wxPageSetupDialogData_SetMinMarginTopLeft 2382
-#define wxPageSetupDialogData_SetMinMarginBottomRight 2383
-#define wxPageSetupDialogData_SetPaperId 2384
-#define wxPageSetupDialogData_SetPaperSize_1_1 2385
-#define wxPageSetupDialogData_SetPaperSize_1_0 2386
-#define wxPageSetupDialogData_SetPrintData 2387
-#define wxPrintDialog_new_2_0 2388
-#define wxPrintDialog_new_2_1 2389
-#define wxPrintDialog_destruct 2390
-#define wxPrintDialog_GetPrintDialogData 2391
-#define wxPrintDialog_GetPrintDC 2392
-#define wxPrintDialogData_new_0 2393
-#define wxPrintDialogData_new_1_1 2394
-#define wxPrintDialogData_new_1_0 2395
-#define wxPrintDialogData_destruct 2396
-#define wxPrintDialogData_EnableHelp 2397
-#define wxPrintDialogData_EnablePageNumbers 2398
-#define wxPrintDialogData_EnablePrintToFile 2399
-#define wxPrintDialogData_EnableSelection 2400
-#define wxPrintDialogData_GetAllPages 2401
-#define wxPrintDialogData_GetCollate 2402
-#define wxPrintDialogData_GetFromPage 2403
-#define wxPrintDialogData_GetMaxPage 2404
-#define wxPrintDialogData_GetMinPage 2405
-#define wxPrintDialogData_GetNoCopies 2406
-#define wxPrintDialogData_GetPrintData 2407
-#define wxPrintDialogData_GetPrintToFile 2408
-#define wxPrintDialogData_GetSelection 2409
-#define wxPrintDialogData_GetToPage 2410
-#define wxPrintDialogData_IsOk 2411
-#define wxPrintDialogData_SetCollate 2412
-#define wxPrintDialogData_SetFromPage 2413
-#define wxPrintDialogData_SetMaxPage 2414
-#define wxPrintDialogData_SetMinPage 2415
-#define wxPrintDialogData_SetNoCopies 2416
-#define wxPrintDialogData_SetPrintData 2417
-#define wxPrintDialogData_SetPrintToFile 2418
-#define wxPrintDialogData_SetSelection 2419
-#define wxPrintDialogData_SetToPage 2420
-#define wxPrintData_new_0 2421
-#define wxPrintData_new_1 2422
-#define wxPrintData_destruct 2423
-#define wxPrintData_GetCollate 2424
-#define wxPrintData_GetBin 2425
-#define wxPrintData_GetColour 2426
-#define wxPrintData_GetDuplex 2427
-#define wxPrintData_GetNoCopies 2428
-#define wxPrintData_GetOrientation 2429
-#define wxPrintData_GetPaperId 2430
-#define wxPrintData_GetPrinterName 2431
-#define wxPrintData_GetQuality 2432
-#define wxPrintData_IsOk 2433
-#define wxPrintData_SetBin 2434
-#define wxPrintData_SetCollate 2435
-#define wxPrintData_SetColour 2436
-#define wxPrintData_SetDuplex 2437
-#define wxPrintData_SetNoCopies 2438
-#define wxPrintData_SetOrientation 2439
-#define wxPrintData_SetPaperId 2440
-#define wxPrintData_SetPrinterName 2441
-#define wxPrintData_SetQuality 2442
-#define wxPrintPreview_new_2 2445
-#define wxPrintPreview_new_3 2446
-#define wxPrintPreview_destruct 2448
-#define wxPrintPreview_GetCanvas 2449
-#define wxPrintPreview_GetCurrentPage 2450
-#define wxPrintPreview_GetFrame 2451
-#define wxPrintPreview_GetMaxPage 2452
-#define wxPrintPreview_GetMinPage 2453
-#define wxPrintPreview_GetPrintout 2454
-#define wxPrintPreview_GetPrintoutForPrinting 2455
-#define wxPrintPreview_IsOk 2456
-#define wxPrintPreview_PaintPage 2457
-#define wxPrintPreview_Print 2458
-#define wxPrintPreview_RenderPage 2459
-#define wxPrintPreview_SetCanvas 2460
-#define wxPrintPreview_SetCurrentPage 2461
-#define wxPrintPreview_SetFrame 2462
-#define wxPrintPreview_SetPrintout 2463
-#define wxPrintPreview_SetZoom 2464
-#define wxPreviewFrame_new 2465
-#define wxPreviewFrame_destruct 2466
-#define wxPreviewFrame_CreateControlBar 2467
-#define wxPreviewFrame_CreateCanvas 2468
-#define wxPreviewFrame_Initialize 2469
-#define wxPreviewFrame_OnCloseWindow 2470
-#define wxPreviewControlBar_new 2471
-#define wxPreviewControlBar_destruct 2472
-#define wxPreviewControlBar_CreateButtons 2473
-#define wxPreviewControlBar_GetPrintPreview 2474
-#define wxPreviewControlBar_GetZoomControl 2475
-#define wxPreviewControlBar_SetZoomControl 2476
-#define wxPrinter_new 2478
-#define wxPrinter_CreateAbortWindow 2479
-#define wxPrinter_GetAbort 2480
-#define wxPrinter_GetLastError 2481
-#define wxPrinter_GetPrintDialogData 2482
-#define wxPrinter_Print 2483
-#define wxPrinter_PrintDialog 2484
-#define wxPrinter_ReportError 2485
-#define wxPrinter_Setup 2486
-#define wxPrinter_destroy 2487
-#define wxXmlResource_new_1 2488
-#define wxXmlResource_new_2 2489
-#define wxXmlResource_destruct 2490
-#define wxXmlResource_AttachUnknownControl 2491
-#define wxXmlResource_ClearHandlers 2492
-#define wxXmlResource_CompareVersion 2493
-#define wxXmlResource_Get 2494
-#define wxXmlResource_GetFlags 2495
-#define wxXmlResource_GetVersion 2496
-#define wxXmlResource_GetXRCID 2497
-#define wxXmlResource_InitAllHandlers 2498
-#define wxXmlResource_Load 2499
-#define wxXmlResource_LoadBitmap 2500
-#define wxXmlResource_LoadDialog_2 2501
-#define wxXmlResource_LoadDialog_3 2502
-#define wxXmlResource_LoadFrame_2 2503
-#define wxXmlResource_LoadFrame_3 2504
-#define wxXmlResource_LoadIcon 2505
-#define wxXmlResource_LoadMenu 2506
-#define wxXmlResource_LoadMenuBar_2 2507
-#define wxXmlResource_LoadMenuBar_1 2508
-#define wxXmlResource_LoadPanel_2 2509
-#define wxXmlResource_LoadPanel_3 2510
-#define wxXmlResource_LoadToolBar 2511
-#define wxXmlResource_Set 2512
-#define wxXmlResource_SetFlags 2513
-#define wxXmlResource_Unload 2514
-#define wxXmlResource_xrcctrl 2515
-#define wxHtmlEasyPrinting_new 2516
-#define wxHtmlEasyPrinting_destruct 2517
-#define wxHtmlEasyPrinting_GetPrintData 2518
-#define wxHtmlEasyPrinting_GetPageSetupData 2519
-#define wxHtmlEasyPrinting_PreviewFile 2520
-#define wxHtmlEasyPrinting_PreviewText 2521
-#define wxHtmlEasyPrinting_PrintFile 2522
-#define wxHtmlEasyPrinting_PrintText 2523
-#define wxHtmlEasyPrinting_PageSetup 2524
-#define wxHtmlEasyPrinting_SetFonts 2525
-#define wxHtmlEasyPrinting_SetHeader 2526
-#define wxHtmlEasyPrinting_SetFooter 2527
-#define wxGLCanvas_new_2 2529
-#define wxGLCanvas_new_3_1 2530
-#define wxGLCanvas_new_3_0 2531
-#define wxGLCanvas_GetContext 2532
-#define wxGLCanvas_SetCurrent 2534
-#define wxGLCanvas_SwapBuffers 2535
-#define wxGLCanvas_destroy 2536
-#define wxAuiManager_new 2537
-#define wxAuiManager_destruct 2538
-#define wxAuiManager_AddPane_2_1 2539
-#define wxAuiManager_AddPane_3 2540
-#define wxAuiManager_AddPane_2_0 2541
-#define wxAuiManager_DetachPane 2542
-#define wxAuiManager_GetAllPanes 2543
-#define wxAuiManager_GetArtProvider 2544
-#define wxAuiManager_GetDockSizeConstraint 2545
-#define wxAuiManager_GetFlags 2546
-#define wxAuiManager_GetManagedWindow 2547
-#define wxAuiManager_GetManager 2548
-#define wxAuiManager_GetPane_1_1 2549
-#define wxAuiManager_GetPane_1_0 2550
-#define wxAuiManager_HideHint 2551
-#define wxAuiManager_InsertPane 2552
-#define wxAuiManager_LoadPaneInfo 2553
-#define wxAuiManager_LoadPerspective 2554
-#define wxAuiManager_SavePaneInfo 2555
-#define wxAuiManager_SavePerspective 2556
-#define wxAuiManager_SetArtProvider 2557
-#define wxAuiManager_SetDockSizeConstraint 2558
-#define wxAuiManager_SetFlags 2559
-#define wxAuiManager_SetManagedWindow 2560
-#define wxAuiManager_ShowHint 2561
-#define wxAuiManager_UnInit 2562
-#define wxAuiManager_Update 2563
-#define wxAuiPaneInfo_new_0 2564
-#define wxAuiPaneInfo_new_1 2565
-#define wxAuiPaneInfo_destruct 2566
-#define wxAuiPaneInfo_BestSize_1 2567
-#define wxAuiPaneInfo_BestSize_2 2568
-#define wxAuiPaneInfo_Bottom 2569
-#define wxAuiPaneInfo_BottomDockable 2570
-#define wxAuiPaneInfo_Caption 2571
-#define wxAuiPaneInfo_CaptionVisible 2572
-#define wxAuiPaneInfo_Centre 2573
-#define wxAuiPaneInfo_CentrePane 2574
-#define wxAuiPaneInfo_CloseButton 2575
-#define wxAuiPaneInfo_DefaultPane 2576
-#define wxAuiPaneInfo_DestroyOnClose 2577
-#define wxAuiPaneInfo_Direction 2578
-#define wxAuiPaneInfo_Dock 2579
-#define wxAuiPaneInfo_Dockable 2580
-#define wxAuiPaneInfo_Fixed 2581
-#define wxAuiPaneInfo_Float 2582
-#define wxAuiPaneInfo_Floatable 2583
-#define wxAuiPaneInfo_FloatingPosition_1 2584
-#define wxAuiPaneInfo_FloatingPosition_2 2585
-#define wxAuiPaneInfo_FloatingSize_1 2586
-#define wxAuiPaneInfo_FloatingSize_2 2587
-#define wxAuiPaneInfo_Gripper 2588
-#define wxAuiPaneInfo_GripperTop 2589
-#define wxAuiPaneInfo_HasBorder 2590
-#define wxAuiPaneInfo_HasCaption 2591
-#define wxAuiPaneInfo_HasCloseButton 2592
-#define wxAuiPaneInfo_HasFlag 2593
-#define wxAuiPaneInfo_HasGripper 2594
-#define wxAuiPaneInfo_HasGripperTop 2595
-#define wxAuiPaneInfo_HasMaximizeButton 2596
-#define wxAuiPaneInfo_HasMinimizeButton 2597
-#define wxAuiPaneInfo_HasPinButton 2598
-#define wxAuiPaneInfo_Hide 2599
-#define wxAuiPaneInfo_IsBottomDockable 2600
-#define wxAuiPaneInfo_IsDocked 2601
-#define wxAuiPaneInfo_IsFixed 2602
-#define wxAuiPaneInfo_IsFloatable 2603
-#define wxAuiPaneInfo_IsFloating 2604
-#define wxAuiPaneInfo_IsLeftDockable 2605
-#define wxAuiPaneInfo_IsMovable 2606
-#define wxAuiPaneInfo_IsOk 2607
-#define wxAuiPaneInfo_IsResizable 2608
-#define wxAuiPaneInfo_IsRightDockable 2609
-#define wxAuiPaneInfo_IsShown 2610
-#define wxAuiPaneInfo_IsToolbar 2611
-#define wxAuiPaneInfo_IsTopDockable 2612
-#define wxAuiPaneInfo_Layer 2613
-#define wxAuiPaneInfo_Left 2614
-#define wxAuiPaneInfo_LeftDockable 2615
-#define wxAuiPaneInfo_MaxSize_1 2616
-#define wxAuiPaneInfo_MaxSize_2 2617
-#define wxAuiPaneInfo_MaximizeButton 2618
-#define wxAuiPaneInfo_MinSize_1 2619
-#define wxAuiPaneInfo_MinSize_2 2620
-#define wxAuiPaneInfo_MinimizeButton 2621
-#define wxAuiPaneInfo_Movable 2622
-#define wxAuiPaneInfo_Name 2623
-#define wxAuiPaneInfo_PaneBorder 2624
-#define wxAuiPaneInfo_PinButton 2625
-#define wxAuiPaneInfo_Position 2626
-#define wxAuiPaneInfo_Resizable 2627
-#define wxAuiPaneInfo_Right 2628
-#define wxAuiPaneInfo_RightDockable 2629
-#define wxAuiPaneInfo_Row 2630
-#define wxAuiPaneInfo_SafeSet 2631
-#define wxAuiPaneInfo_SetFlag 2632
-#define wxAuiPaneInfo_Show 2633
-#define wxAuiPaneInfo_ToolbarPane 2634
-#define wxAuiPaneInfo_Top 2635
-#define wxAuiPaneInfo_TopDockable 2636
-#define wxAuiPaneInfo_Window 2637
-#define wxAuiNotebook_new_0 2638
-#define wxAuiNotebook_new_2 2639
-#define wxAuiNotebook_AddPage 2640
-#define wxAuiNotebook_Create 2641
-#define wxAuiNotebook_DeletePage 2642
-#define wxAuiNotebook_GetArtProvider 2643
-#define wxAuiNotebook_GetPage 2644
-#define wxAuiNotebook_GetPageBitmap 2645
-#define wxAuiNotebook_GetPageCount 2646
-#define wxAuiNotebook_GetPageIndex 2647
-#define wxAuiNotebook_GetPageText 2648
-#define wxAuiNotebook_GetSelection 2649
-#define wxAuiNotebook_InsertPage 2650
-#define wxAuiNotebook_RemovePage 2651
-#define wxAuiNotebook_SetArtProvider 2652
-#define wxAuiNotebook_SetFont 2653
-#define wxAuiNotebook_SetPageBitmap 2654
-#define wxAuiNotebook_SetPageText 2655
-#define wxAuiNotebook_SetSelection 2656
-#define wxAuiNotebook_SetTabCtrlHeight 2657
-#define wxAuiNotebook_SetUniformBitmapSize 2658
-#define wxAuiNotebook_destroy 2659
-#define wxMDIParentFrame_new_0 2660
-#define wxMDIParentFrame_new_4 2661
-#define wxMDIParentFrame_destruct 2662
-#define wxMDIParentFrame_ActivateNext 2663
-#define wxMDIParentFrame_ActivatePrevious 2664
-#define wxMDIParentFrame_ArrangeIcons 2665
-#define wxMDIParentFrame_Cascade 2666
-#define wxMDIParentFrame_Create 2667
-#define wxMDIParentFrame_GetActiveChild 2668
-#define wxMDIParentFrame_GetClientWindow 2669
-#define wxMDIParentFrame_Tile 2670
-#define wxMDIChildFrame_new_0 2671
-#define wxMDIChildFrame_new_4 2672
-#define wxMDIChildFrame_destruct 2673
-#define wxMDIChildFrame_Activate 2674
-#define wxMDIChildFrame_Create 2675
-#define wxMDIChildFrame_Maximize 2676
-#define wxMDIChildFrame_Restore 2677
-#define wxMDIClientWindow_new_0 2678
-#define wxMDIClientWindow_new_2 2679
-#define wxMDIClientWindow_destruct 2680
-#define wxMDIClientWindow_CreateClient 2681
-#define wxLayoutAlgorithm_new 2682
-#define wxLayoutAlgorithm_LayoutFrame 2683
-#define wxLayoutAlgorithm_LayoutMDIFrame 2684
-#define wxLayoutAlgorithm_LayoutWindow 2685
-#define wxLayoutAlgorithm_destroy 2686
-#define wxEvent_GetId 2687
-#define wxEvent_GetSkipped 2688
-#define wxEvent_GetTimestamp 2689
-#define wxEvent_IsCommandEvent 2690
-#define wxEvent_ResumePropagation 2691
-#define wxEvent_ShouldPropagate 2692
-#define wxEvent_Skip 2693
-#define wxEvent_StopPropagation 2694
-#define wxCommandEvent_getClientData 2695
-#define wxCommandEvent_GetExtraLong 2696
-#define wxCommandEvent_GetInt 2697
-#define wxCommandEvent_GetSelection 2698
-#define wxCommandEvent_GetString 2699
-#define wxCommandEvent_IsChecked 2700
-#define wxCommandEvent_IsSelection 2701
-#define wxCommandEvent_SetInt 2702
-#define wxCommandEvent_SetString 2703
-#define wxScrollEvent_GetOrientation 2704
-#define wxScrollEvent_GetPosition 2705
-#define wxScrollWinEvent_GetOrientation 2706
-#define wxScrollWinEvent_GetPosition 2707
-#define wxMouseEvent_AltDown 2708
-#define wxMouseEvent_Button 2709
-#define wxMouseEvent_ButtonDClick 2710
-#define wxMouseEvent_ButtonDown 2711
-#define wxMouseEvent_ButtonUp 2712
-#define wxMouseEvent_CmdDown 2713
-#define wxMouseEvent_ControlDown 2714
-#define wxMouseEvent_Dragging 2715
-#define wxMouseEvent_Entering 2716
-#define wxMouseEvent_GetButton 2717
-#define wxMouseEvent_GetPosition 2720
-#define wxMouseEvent_GetLogicalPosition 2721
-#define wxMouseEvent_GetLinesPerAction 2722
-#define wxMouseEvent_GetWheelRotation 2723
-#define wxMouseEvent_GetWheelDelta 2724
-#define wxMouseEvent_GetX 2725
-#define wxMouseEvent_GetY 2726
-#define wxMouseEvent_IsButton 2727
-#define wxMouseEvent_IsPageScroll 2728
-#define wxMouseEvent_Leaving 2729
-#define wxMouseEvent_LeftDClick 2730
-#define wxMouseEvent_LeftDown 2731
-#define wxMouseEvent_LeftIsDown 2732
-#define wxMouseEvent_LeftUp 2733
-#define wxMouseEvent_MetaDown 2734
-#define wxMouseEvent_MiddleDClick 2735
-#define wxMouseEvent_MiddleDown 2736
-#define wxMouseEvent_MiddleIsDown 2737
-#define wxMouseEvent_MiddleUp 2738
-#define wxMouseEvent_Moving 2739
-#define wxMouseEvent_RightDClick 2740
-#define wxMouseEvent_RightDown 2741
-#define wxMouseEvent_RightIsDown 2742
-#define wxMouseEvent_RightUp 2743
-#define wxMouseEvent_ShiftDown 2744
-#define wxSetCursorEvent_GetCursor 2745
-#define wxSetCursorEvent_GetX 2746
-#define wxSetCursorEvent_GetY 2747
-#define wxSetCursorEvent_HasCursor 2748
-#define wxSetCursorEvent_SetCursor 2749
-#define wxKeyEvent_AltDown 2750
-#define wxKeyEvent_CmdDown 2751
-#define wxKeyEvent_ControlDown 2752
-#define wxKeyEvent_GetKeyCode 2753
-#define wxKeyEvent_GetModifiers 2754
-#define wxKeyEvent_GetPosition 2757
-#define wxKeyEvent_GetRawKeyCode 2758
-#define wxKeyEvent_GetRawKeyFlags 2759
-#define wxKeyEvent_GetUnicodeKey 2760
-#define wxKeyEvent_GetX 2761
-#define wxKeyEvent_GetY 2762
-#define wxKeyEvent_HasModifiers 2763
-#define wxKeyEvent_MetaDown 2764
-#define wxKeyEvent_ShiftDown 2765
-#define wxSizeEvent_GetSize 2766
-#define wxMoveEvent_GetPosition 2767
-#define wxEraseEvent_GetDC 2768
-#define wxFocusEvent_GetWindow 2769
-#define wxChildFocusEvent_GetWindow 2770
-#define wxMenuEvent_GetMenu 2771
-#define wxMenuEvent_GetMenuId 2772
-#define wxMenuEvent_IsPopup 2773
-#define wxCloseEvent_CanVeto 2774
-#define wxCloseEvent_GetLoggingOff 2775
-#define wxCloseEvent_SetCanVeto 2776
-#define wxCloseEvent_SetLoggingOff 2777
-#define wxCloseEvent_Veto 2778
-#define wxShowEvent_SetShow 2779
-#define wxShowEvent_GetShow 2780
-#define wxIconizeEvent_Iconized 2781
-#define wxJoystickEvent_ButtonDown 2782
-#define wxJoystickEvent_ButtonIsDown 2783
-#define wxJoystickEvent_ButtonUp 2784
-#define wxJoystickEvent_GetButtonChange 2785
-#define wxJoystickEvent_GetButtonState 2786
-#define wxJoystickEvent_GetJoystick 2787
-#define wxJoystickEvent_GetPosition 2788
-#define wxJoystickEvent_GetZPosition 2789
-#define wxJoystickEvent_IsButton 2790
-#define wxJoystickEvent_IsMove 2791
-#define wxJoystickEvent_IsZMove 2792
-#define wxUpdateUIEvent_CanUpdate 2793
-#define wxUpdateUIEvent_Check 2794
-#define wxUpdateUIEvent_Enable 2795
-#define wxUpdateUIEvent_Show 2796
-#define wxUpdateUIEvent_GetChecked 2797
-#define wxUpdateUIEvent_GetEnabled 2798
-#define wxUpdateUIEvent_GetShown 2799
-#define wxUpdateUIEvent_GetSetChecked 2800
-#define wxUpdateUIEvent_GetSetEnabled 2801
-#define wxUpdateUIEvent_GetSetShown 2802
-#define wxUpdateUIEvent_GetSetText 2803
-#define wxUpdateUIEvent_GetText 2804
-#define wxUpdateUIEvent_GetMode 2805
-#define wxUpdateUIEvent_GetUpdateInterval 2806
-#define wxUpdateUIEvent_ResetUpdateTime 2807
-#define wxUpdateUIEvent_SetMode 2808
-#define wxUpdateUIEvent_SetText 2809
-#define wxUpdateUIEvent_SetUpdateInterval 2810
-#define wxMouseCaptureChangedEvent_GetCapturedWindow 2811
-#define wxPaletteChangedEvent_SetChangedWindow 2812
-#define wxPaletteChangedEvent_GetChangedWindow 2813
-#define wxQueryNewPaletteEvent_SetPaletteRealized 2814
-#define wxQueryNewPaletteEvent_GetPaletteRealized 2815
-#define wxNavigationKeyEvent_GetDirection 2816
-#define wxNavigationKeyEvent_SetDirection 2817
-#define wxNavigationKeyEvent_IsWindowChange 2818
-#define wxNavigationKeyEvent_SetWindowChange 2819
-#define wxNavigationKeyEvent_IsFromTab 2820
-#define wxNavigationKeyEvent_SetFromTab 2821
-#define wxNavigationKeyEvent_GetCurrentFocus 2822
-#define wxNavigationKeyEvent_SetCurrentFocus 2823
-#define wxHelpEvent_GetOrigin 2824
-#define wxHelpEvent_GetPosition 2825
-#define wxHelpEvent_SetOrigin 2826
-#define wxHelpEvent_SetPosition 2827
-#define wxContextMenuEvent_GetPosition 2828
-#define wxContextMenuEvent_SetPosition 2829
-#define wxIdleEvent_CanSend 2830
-#define wxIdleEvent_GetMode 2831
-#define wxIdleEvent_RequestMore 2832
-#define wxIdleEvent_MoreRequested 2833
-#define wxIdleEvent_SetMode 2834
-#define wxGridEvent_AltDown 2835
-#define wxGridEvent_ControlDown 2836
-#define wxGridEvent_GetCol 2837
-#define wxGridEvent_GetPosition 2838
-#define wxGridEvent_GetRow 2839
-#define wxGridEvent_MetaDown 2840
-#define wxGridEvent_Selecting 2841
-#define wxGridEvent_ShiftDown 2842
-#define wxNotifyEvent_Allow 2843
-#define wxNotifyEvent_IsAllowed 2844
-#define wxNotifyEvent_Veto 2845
-#define wxSashEvent_GetEdge 2846
-#define wxSashEvent_GetDragRect 2847
-#define wxSashEvent_GetDragStatus 2848
-#define wxListEvent_GetCacheFrom 2849
-#define wxListEvent_GetCacheTo 2850
-#define wxListEvent_GetKeyCode 2851
-#define wxListEvent_GetIndex 2852
-#define wxListEvent_GetColumn 2853
-#define wxListEvent_GetPoint 2854
-#define wxListEvent_GetLabel 2855
-#define wxListEvent_GetText 2856
-#define wxListEvent_GetImage 2857
-#define wxListEvent_GetData 2858
-#define wxListEvent_GetMask 2859
-#define wxListEvent_GetItem 2860
-#define wxListEvent_IsEditCancelled 2861
-#define wxDateEvent_GetDate 2862
-#define wxCalendarEvent_GetWeekDay 2863
-#define wxFileDirPickerEvent_GetPath 2864
-#define wxColourPickerEvent_GetColour 2865
-#define wxFontPickerEvent_GetFont 2866
-#define wxStyledTextEvent_GetPosition 2867
-#define wxStyledTextEvent_GetKey 2868
-#define wxStyledTextEvent_GetModifiers 2869
-#define wxStyledTextEvent_GetModificationType 2870
-#define wxStyledTextEvent_GetText 2871
-#define wxStyledTextEvent_GetLength 2872
-#define wxStyledTextEvent_GetLinesAdded 2873
-#define wxStyledTextEvent_GetLine 2874
-#define wxStyledTextEvent_GetFoldLevelNow 2875
-#define wxStyledTextEvent_GetFoldLevelPrev 2876
-#define wxStyledTextEvent_GetMargin 2877
-#define wxStyledTextEvent_GetMessage 2878
-#define wxStyledTextEvent_GetWParam 2879
-#define wxStyledTextEvent_GetLParam 2880
-#define wxStyledTextEvent_GetListType 2881
-#define wxStyledTextEvent_GetX 2882
-#define wxStyledTextEvent_GetY 2883
-#define wxStyledTextEvent_GetDragText 2884
-#define wxStyledTextEvent_GetDragAllowMove 2885
-#define wxStyledTextEvent_GetDragResult 2886
-#define wxStyledTextEvent_GetShift 2887
-#define wxStyledTextEvent_GetControl 2888
-#define wxStyledTextEvent_GetAlt 2889
-#define utils_wxGetKeyState 2890
-#define utils_wxGetMousePosition 2891
-#define utils_wxGetMouseState 2892
-#define utils_wxSetDetectableAutoRepeat 2893
-#define utils_wxBell 2894
-#define utils_wxFindMenuItemId 2895
-#define utils_wxGenericFindWindowAtPoint 2896
-#define utils_wxFindWindowAtPoint 2897
-#define utils_wxBeginBusyCursor 2898
-#define utils_wxEndBusyCursor 2899
-#define utils_wxIsBusy 2900
-#define utils_wxShutdown 2901
-#define utils_wxShell 2902
-#define utils_wxLaunchDefaultBrowser 2903
-#define utils_wxGetEmailAddress 2904
-#define utils_wxGetUserId 2905
-#define utils_wxGetHomeDir 2906
-#define utils_wxNewId 2907
-#define utils_wxRegisterId 2908
-#define utils_wxGetCurrentId 2909
-#define utils_wxGetOsDescription 2910
-#define utils_wxIsPlatformLittleEndian 2911
-#define utils_wxIsPlatform64Bit 2912
-#define wxPrintout_new 2913
-#define wxPrintout_destruct 2914
-#define wxPrintout_GetDC 2915
-#define wxPrintout_GetPageSizeMM 2916
-#define wxPrintout_GetPageSizePixels 2917
-#define wxPrintout_GetPaperRectPixels 2918
-#define wxPrintout_GetPPIPrinter 2919
-#define wxPrintout_GetPPIScreen 2920
-#define wxPrintout_GetTitle 2921
-#define wxPrintout_IsPreview 2922
-#define wxPrintout_FitThisSizeToPaper 2923
-#define wxPrintout_FitThisSizeToPage 2924
-#define wxPrintout_FitThisSizeToPageMargins 2925
-#define wxPrintout_MapScreenSizeToPaper 2926
-#define wxPrintout_MapScreenSizeToPage 2927
-#define wxPrintout_MapScreenSizeToPageMargins 2928
-#define wxPrintout_MapScreenSizeToDevice 2929
-#define wxPrintout_GetLogicalPaperRect 2930
-#define wxPrintout_GetLogicalPageRect 2931
-#define wxPrintout_GetLogicalPageMarginsRect 2932
-#define wxPrintout_SetLogicalOrigin 2933
-#define wxPrintout_OffsetLogicalOrigin 2934
-#define wxStyledTextCtrl_new_2 2935
-#define wxStyledTextCtrl_new_0 2936
-#define wxStyledTextCtrl_destruct 2937
-#define wxStyledTextCtrl_Create 2938
-#define wxStyledTextCtrl_AddText 2939
-#define wxStyledTextCtrl_AddStyledText 2940
-#define wxStyledTextCtrl_InsertText 2941
-#define wxStyledTextCtrl_ClearAll 2942
-#define wxStyledTextCtrl_ClearDocumentStyle 2943
-#define wxStyledTextCtrl_GetLength 2944
-#define wxStyledTextCtrl_GetCharAt 2945
-#define wxStyledTextCtrl_GetCurrentPos 2946
-#define wxStyledTextCtrl_GetAnchor 2947
-#define wxStyledTextCtrl_GetStyleAt 2948
-#define wxStyledTextCtrl_Redo 2949
-#define wxStyledTextCtrl_SetUndoCollection 2950
-#define wxStyledTextCtrl_SelectAll 2951
-#define wxStyledTextCtrl_SetSavePoint 2952
-#define wxStyledTextCtrl_GetStyledText 2953
-#define wxStyledTextCtrl_CanRedo 2954
-#define wxStyledTextCtrl_MarkerLineFromHandle 2955
-#define wxStyledTextCtrl_MarkerDeleteHandle 2956
-#define wxStyledTextCtrl_GetUndoCollection 2957
-#define wxStyledTextCtrl_GetViewWhiteSpace 2958
-#define wxStyledTextCtrl_SetViewWhiteSpace 2959
-#define wxStyledTextCtrl_PositionFromPoint 2960
-#define wxStyledTextCtrl_PositionFromPointClose 2961
-#define wxStyledTextCtrl_GotoLine 2962
-#define wxStyledTextCtrl_GotoPos 2963
-#define wxStyledTextCtrl_SetAnchor 2964
-#define wxStyledTextCtrl_GetCurLine 2965
-#define wxStyledTextCtrl_GetEndStyled 2966
-#define wxStyledTextCtrl_ConvertEOLs 2967
-#define wxStyledTextCtrl_GetEOLMode 2968
-#define wxStyledTextCtrl_SetEOLMode 2969
-#define wxStyledTextCtrl_StartStyling 2970
-#define wxStyledTextCtrl_SetStyling 2971
-#define wxStyledTextCtrl_GetBufferedDraw 2972
-#define wxStyledTextCtrl_SetBufferedDraw 2973
-#define wxStyledTextCtrl_SetTabWidth 2974
-#define wxStyledTextCtrl_GetTabWidth 2975
-#define wxStyledTextCtrl_SetCodePage 2976
-#define wxStyledTextCtrl_MarkerDefine 2977
-#define wxStyledTextCtrl_MarkerSetForeground 2978
-#define wxStyledTextCtrl_MarkerSetBackground 2979
-#define wxStyledTextCtrl_MarkerAdd 2980
-#define wxStyledTextCtrl_MarkerDelete 2981
-#define wxStyledTextCtrl_MarkerDeleteAll 2982
-#define wxStyledTextCtrl_MarkerGet 2983
-#define wxStyledTextCtrl_MarkerNext 2984
-#define wxStyledTextCtrl_MarkerPrevious 2985
-#define wxStyledTextCtrl_MarkerDefineBitmap 2986
-#define wxStyledTextCtrl_MarkerAddSet 2987
-#define wxStyledTextCtrl_MarkerSetAlpha 2988
-#define wxStyledTextCtrl_SetMarginType 2989
-#define wxStyledTextCtrl_GetMarginType 2990
-#define wxStyledTextCtrl_SetMarginWidth 2991
-#define wxStyledTextCtrl_GetMarginWidth 2992
-#define wxStyledTextCtrl_SetMarginMask 2993
-#define wxStyledTextCtrl_GetMarginMask 2994
-#define wxStyledTextCtrl_SetMarginSensitive 2995
-#define wxStyledTextCtrl_GetMarginSensitive 2996
-#define wxStyledTextCtrl_StyleClearAll 2997
-#define wxStyledTextCtrl_StyleSetForeground 2998
-#define wxStyledTextCtrl_StyleSetBackground 2999
-#define wxStyledTextCtrl_StyleSetBold 3000
-#define wxStyledTextCtrl_StyleSetItalic 3001
-#define wxStyledTextCtrl_StyleSetSize 3002
-#define wxStyledTextCtrl_StyleSetFaceName 3003
-#define wxStyledTextCtrl_StyleSetEOLFilled 3004
-#define wxStyledTextCtrl_StyleResetDefault 3005
-#define wxStyledTextCtrl_StyleSetUnderline 3006
-#define wxStyledTextCtrl_StyleSetCase 3007
-#define wxStyledTextCtrl_StyleSetHotSpot 3008
-#define wxStyledTextCtrl_SetSelForeground 3009
-#define wxStyledTextCtrl_SetSelBackground 3010
-#define wxStyledTextCtrl_GetSelAlpha 3011
-#define wxStyledTextCtrl_SetSelAlpha 3012
-#define wxStyledTextCtrl_SetCaretForeground 3013
-#define wxStyledTextCtrl_CmdKeyAssign 3014
-#define wxStyledTextCtrl_CmdKeyClear 3015
-#define wxStyledTextCtrl_CmdKeyClearAll 3016
-#define wxStyledTextCtrl_SetStyleBytes 3017
-#define wxStyledTextCtrl_StyleSetVisible 3018
-#define wxStyledTextCtrl_GetCaretPeriod 3019
-#define wxStyledTextCtrl_SetCaretPeriod 3020
-#define wxStyledTextCtrl_SetWordChars 3021
-#define wxStyledTextCtrl_BeginUndoAction 3022
-#define wxStyledTextCtrl_EndUndoAction 3023
-#define wxStyledTextCtrl_IndicatorSetStyle 3024
-#define wxStyledTextCtrl_IndicatorGetStyle 3025
-#define wxStyledTextCtrl_IndicatorSetForeground 3026
-#define wxStyledTextCtrl_IndicatorGetForeground 3027
-#define wxStyledTextCtrl_SetWhitespaceForeground 3028
-#define wxStyledTextCtrl_SetWhitespaceBackground 3029
-#define wxStyledTextCtrl_GetStyleBits 3030
-#define wxStyledTextCtrl_SetLineState 3031
-#define wxStyledTextCtrl_GetLineState 3032
-#define wxStyledTextCtrl_GetMaxLineState 3033
-#define wxStyledTextCtrl_GetCaretLineVisible 3034
-#define wxStyledTextCtrl_SetCaretLineVisible 3035
-#define wxStyledTextCtrl_GetCaretLineBackground 3036
-#define wxStyledTextCtrl_SetCaretLineBackground 3037
-#define wxStyledTextCtrl_AutoCompShow 3038
-#define wxStyledTextCtrl_AutoCompCancel 3039
-#define wxStyledTextCtrl_AutoCompActive 3040
-#define wxStyledTextCtrl_AutoCompPosStart 3041
-#define wxStyledTextCtrl_AutoCompComplete 3042
-#define wxStyledTextCtrl_AutoCompStops 3043
-#define wxStyledTextCtrl_AutoCompSetSeparator 3044
-#define wxStyledTextCtrl_AutoCompGetSeparator 3045
-#define wxStyledTextCtrl_AutoCompSelect 3046
-#define wxStyledTextCtrl_AutoCompSetCancelAtStart 3047
-#define wxStyledTextCtrl_AutoCompGetCancelAtStart 3048
-#define wxStyledTextCtrl_AutoCompSetFillUps 3049
-#define wxStyledTextCtrl_AutoCompSetChooseSingle 3050
-#define wxStyledTextCtrl_AutoCompGetChooseSingle 3051
-#define wxStyledTextCtrl_AutoCompSetIgnoreCase 3052
-#define wxStyledTextCtrl_AutoCompGetIgnoreCase 3053
-#define wxStyledTextCtrl_UserListShow 3054
-#define wxStyledTextCtrl_AutoCompSetAutoHide 3055
-#define wxStyledTextCtrl_AutoCompGetAutoHide 3056
-#define wxStyledTextCtrl_AutoCompSetDropRestOfWord 3057
-#define wxStyledTextCtrl_AutoCompGetDropRestOfWord 3058
-#define wxStyledTextCtrl_RegisterImage 3059
-#define wxStyledTextCtrl_ClearRegisteredImages 3060
-#define wxStyledTextCtrl_AutoCompGetTypeSeparator 3061
-#define wxStyledTextCtrl_AutoCompSetTypeSeparator 3062
-#define wxStyledTextCtrl_AutoCompSetMaxWidth 3063
-#define wxStyledTextCtrl_AutoCompGetMaxWidth 3064
-#define wxStyledTextCtrl_AutoCompSetMaxHeight 3065
-#define wxStyledTextCtrl_AutoCompGetMaxHeight 3066
-#define wxStyledTextCtrl_SetIndent 3067
-#define wxStyledTextCtrl_GetIndent 3068
-#define wxStyledTextCtrl_SetUseTabs 3069
-#define wxStyledTextCtrl_GetUseTabs 3070
-#define wxStyledTextCtrl_SetLineIndentation 3071
-#define wxStyledTextCtrl_GetLineIndentation 3072
-#define wxStyledTextCtrl_GetLineIndentPosition 3073
-#define wxStyledTextCtrl_GetColumn 3074
-#define wxStyledTextCtrl_SetUseHorizontalScrollBar 3075
-#define wxStyledTextCtrl_GetUseHorizontalScrollBar 3076
-#define wxStyledTextCtrl_SetIndentationGuides 3077
-#define wxStyledTextCtrl_GetIndentationGuides 3078
-#define wxStyledTextCtrl_SetHighlightGuide 3079
-#define wxStyledTextCtrl_GetHighlightGuide 3080
-#define wxStyledTextCtrl_GetLineEndPosition 3081
-#define wxStyledTextCtrl_GetCodePage 3082
-#define wxStyledTextCtrl_GetCaretForeground 3083
-#define wxStyledTextCtrl_GetReadOnly 3084
-#define wxStyledTextCtrl_SetCurrentPos 3085
-#define wxStyledTextCtrl_SetSelectionStart 3086
-#define wxStyledTextCtrl_GetSelectionStart 3087
-#define wxStyledTextCtrl_SetSelectionEnd 3088
-#define wxStyledTextCtrl_GetSelectionEnd 3089
-#define wxStyledTextCtrl_SetPrintMagnification 3090
-#define wxStyledTextCtrl_GetPrintMagnification 3091
-#define wxStyledTextCtrl_SetPrintColourMode 3092
-#define wxStyledTextCtrl_GetPrintColourMode 3093
-#define wxStyledTextCtrl_FindText 3094
-#define wxStyledTextCtrl_FormatRange 3095
-#define wxStyledTextCtrl_GetFirstVisibleLine 3096
-#define wxStyledTextCtrl_GetLine 3097
-#define wxStyledTextCtrl_GetLineCount 3098
-#define wxStyledTextCtrl_SetMarginLeft 3099
-#define wxStyledTextCtrl_GetMarginLeft 3100
-#define wxStyledTextCtrl_SetMarginRight 3101
-#define wxStyledTextCtrl_GetMarginRight 3102
-#define wxStyledTextCtrl_GetModify 3103
-#define wxStyledTextCtrl_SetSelection 3104
-#define wxStyledTextCtrl_GetSelectedText 3105
-#define wxStyledTextCtrl_GetTextRange 3106
-#define wxStyledTextCtrl_HideSelection 3107
-#define wxStyledTextCtrl_LineFromPosition 3108
-#define wxStyledTextCtrl_PositionFromLine 3109
-#define wxStyledTextCtrl_LineScroll 3110
-#define wxStyledTextCtrl_EnsureCaretVisible 3111
-#define wxStyledTextCtrl_ReplaceSelection 3112
-#define wxStyledTextCtrl_SetReadOnly 3113
-#define wxStyledTextCtrl_CanPaste 3114
-#define wxStyledTextCtrl_CanUndo 3115
-#define wxStyledTextCtrl_EmptyUndoBuffer 3116
-#define wxStyledTextCtrl_Undo 3117
-#define wxStyledTextCtrl_Cut 3118
-#define wxStyledTextCtrl_Copy 3119
-#define wxStyledTextCtrl_Paste 3120
-#define wxStyledTextCtrl_Clear 3121
-#define wxStyledTextCtrl_SetText 3122
-#define wxStyledTextCtrl_GetText 3123
-#define wxStyledTextCtrl_GetTextLength 3124
-#define wxStyledTextCtrl_GetOvertype 3125
-#define wxStyledTextCtrl_SetCaretWidth 3126
-#define wxStyledTextCtrl_GetCaretWidth 3127
-#define wxStyledTextCtrl_SetTargetStart 3128
-#define wxStyledTextCtrl_GetTargetStart 3129
-#define wxStyledTextCtrl_SetTargetEnd 3130
-#define wxStyledTextCtrl_GetTargetEnd 3131
-#define wxStyledTextCtrl_ReplaceTarget 3132
-#define wxStyledTextCtrl_SearchInTarget 3133
-#define wxStyledTextCtrl_SetSearchFlags 3134
-#define wxStyledTextCtrl_GetSearchFlags 3135
-#define wxStyledTextCtrl_CallTipShow 3136
-#define wxStyledTextCtrl_CallTipCancel 3137
-#define wxStyledTextCtrl_CallTipActive 3138
-#define wxStyledTextCtrl_CallTipPosAtStart 3139
-#define wxStyledTextCtrl_CallTipSetHighlight 3140
-#define wxStyledTextCtrl_CallTipSetBackground 3141
-#define wxStyledTextCtrl_CallTipSetForeground 3142
-#define wxStyledTextCtrl_CallTipSetForegroundHighlight 3143
-#define wxStyledTextCtrl_CallTipUseStyle 3144
-#define wxStyledTextCtrl_VisibleFromDocLine 3145
-#define wxStyledTextCtrl_DocLineFromVisible 3146
-#define wxStyledTextCtrl_WrapCount 3147
-#define wxStyledTextCtrl_SetFoldLevel 3148
-#define wxStyledTextCtrl_GetFoldLevel 3149
-#define wxStyledTextCtrl_GetLastChild 3150
-#define wxStyledTextCtrl_GetFoldParent 3151
-#define wxStyledTextCtrl_ShowLines 3152
-#define wxStyledTextCtrl_HideLines 3153
-#define wxStyledTextCtrl_GetLineVisible 3154
-#define wxStyledTextCtrl_SetFoldExpanded 3155
-#define wxStyledTextCtrl_GetFoldExpanded 3156
-#define wxStyledTextCtrl_ToggleFold 3157
-#define wxStyledTextCtrl_EnsureVisible 3158
-#define wxStyledTextCtrl_SetFoldFlags 3159
-#define wxStyledTextCtrl_EnsureVisibleEnforcePolicy 3160
-#define wxStyledTextCtrl_SetTabIndents 3161
-#define wxStyledTextCtrl_GetTabIndents 3162
-#define wxStyledTextCtrl_SetBackSpaceUnIndents 3163
-#define wxStyledTextCtrl_GetBackSpaceUnIndents 3164
-#define wxStyledTextCtrl_SetMouseDwellTime 3165
-#define wxStyledTextCtrl_GetMouseDwellTime 3166
-#define wxStyledTextCtrl_WordStartPosition 3167
-#define wxStyledTextCtrl_WordEndPosition 3168
-#define wxStyledTextCtrl_SetWrapMode 3169
-#define wxStyledTextCtrl_GetWrapMode 3170
-#define wxStyledTextCtrl_SetWrapVisualFlags 3171
-#define wxStyledTextCtrl_GetWrapVisualFlags 3172
-#define wxStyledTextCtrl_SetWrapVisualFlagsLocation 3173
-#define wxStyledTextCtrl_GetWrapVisualFlagsLocation 3174
-#define wxStyledTextCtrl_SetWrapStartIndent 3175
-#define wxStyledTextCtrl_GetWrapStartIndent 3176
-#define wxStyledTextCtrl_SetLayoutCache 3177
-#define wxStyledTextCtrl_GetLayoutCache 3178
-#define wxStyledTextCtrl_SetScrollWidth 3179
-#define wxStyledTextCtrl_GetScrollWidth 3180
-#define wxStyledTextCtrl_TextWidth 3181
-#define wxStyledTextCtrl_GetEndAtLastLine 3182
-#define wxStyledTextCtrl_TextHeight 3183
-#define wxStyledTextCtrl_SetUseVerticalScrollBar 3184
-#define wxStyledTextCtrl_GetUseVerticalScrollBar 3185
-#define wxStyledTextCtrl_AppendText 3186
-#define wxStyledTextCtrl_GetTwoPhaseDraw 3187
-#define wxStyledTextCtrl_SetTwoPhaseDraw 3188
-#define wxStyledTextCtrl_TargetFromSelection 3189
-#define wxStyledTextCtrl_LinesJoin 3190
-#define wxStyledTextCtrl_LinesSplit 3191
-#define wxStyledTextCtrl_SetFoldMarginColour 3192
-#define wxStyledTextCtrl_SetFoldMarginHiColour 3193
-#define wxStyledTextCtrl_LineDown 3194
-#define wxStyledTextCtrl_LineDownExtend 3195
-#define wxStyledTextCtrl_LineUp 3196
-#define wxStyledTextCtrl_LineUpExtend 3197
-#define wxStyledTextCtrl_CharLeft 3198
-#define wxStyledTextCtrl_CharLeftExtend 3199
-#define wxStyledTextCtrl_CharRight 3200
-#define wxStyledTextCtrl_CharRightExtend 3201
-#define wxStyledTextCtrl_WordLeft 3202
-#define wxStyledTextCtrl_WordLeftExtend 3203
-#define wxStyledTextCtrl_WordRight 3204
-#define wxStyledTextCtrl_WordRightExtend 3205
-#define wxStyledTextCtrl_Home 3206
-#define wxStyledTextCtrl_HomeExtend 3207
-#define wxStyledTextCtrl_LineEnd 3208
-#define wxStyledTextCtrl_LineEndExtend 3209
-#define wxStyledTextCtrl_DocumentStart 3210
-#define wxStyledTextCtrl_DocumentStartExtend 3211
-#define wxStyledTextCtrl_DocumentEnd 3212
-#define wxStyledTextCtrl_DocumentEndExtend 3213
-#define wxStyledTextCtrl_PageUp 3214
-#define wxStyledTextCtrl_PageUpExtend 3215
-#define wxStyledTextCtrl_PageDown 3216
-#define wxStyledTextCtrl_PageDownExtend 3217
-#define wxStyledTextCtrl_EditToggleOvertype 3218
-#define wxStyledTextCtrl_Cancel 3219
-#define wxStyledTextCtrl_DeleteBack 3220
-#define wxStyledTextCtrl_Tab 3221
-#define wxStyledTextCtrl_BackTab 3222
-#define wxStyledTextCtrl_NewLine 3223
-#define wxStyledTextCtrl_FormFeed 3224
-#define wxStyledTextCtrl_VCHome 3225
-#define wxStyledTextCtrl_VCHomeExtend 3226
-#define wxStyledTextCtrl_ZoomIn 3227
-#define wxStyledTextCtrl_ZoomOut 3228
-#define wxStyledTextCtrl_DelWordLeft 3229
-#define wxStyledTextCtrl_DelWordRight 3230
-#define wxStyledTextCtrl_LineCut 3231
-#define wxStyledTextCtrl_LineDelete 3232
-#define wxStyledTextCtrl_LineTranspose 3233
-#define wxStyledTextCtrl_LineDuplicate 3234
-#define wxStyledTextCtrl_LowerCase 3235
-#define wxStyledTextCtrl_UpperCase 3236
-#define wxStyledTextCtrl_LineScrollDown 3237
-#define wxStyledTextCtrl_LineScrollUp 3238
-#define wxStyledTextCtrl_DeleteBackNotLine 3239
-#define wxStyledTextCtrl_HomeDisplay 3240
-#define wxStyledTextCtrl_HomeDisplayExtend 3241
-#define wxStyledTextCtrl_LineEndDisplay 3242
-#define wxStyledTextCtrl_LineEndDisplayExtend 3243
-#define wxStyledTextCtrl_HomeWrapExtend 3244
-#define wxStyledTextCtrl_LineEndWrap 3245
-#define wxStyledTextCtrl_LineEndWrapExtend 3246
-#define wxStyledTextCtrl_VCHomeWrap 3247
-#define wxStyledTextCtrl_VCHomeWrapExtend 3248
-#define wxStyledTextCtrl_LineCopy 3249
-#define wxStyledTextCtrl_MoveCaretInsideView 3250
-#define wxStyledTextCtrl_LineLength 3251
-#define wxStyledTextCtrl_BraceHighlight 3252
-#define wxStyledTextCtrl_BraceBadLight 3253
-#define wxStyledTextCtrl_BraceMatch 3254
-#define wxStyledTextCtrl_GetViewEOL 3255
-#define wxStyledTextCtrl_SetViewEOL 3256
-#define wxStyledTextCtrl_SetModEventMask 3257
-#define wxStyledTextCtrl_GetEdgeColumn 3258
-#define wxStyledTextCtrl_SetEdgeColumn 3259
-#define wxStyledTextCtrl_GetEdgeMode 3260
-#define wxStyledTextCtrl_GetEdgeColour 3261
-#define wxStyledTextCtrl_SetEdgeColour 3262
-#define wxStyledTextCtrl_SearchAnchor 3263
-#define wxStyledTextCtrl_SearchNext 3264
-#define wxStyledTextCtrl_SearchPrev 3265
-#define wxStyledTextCtrl_LinesOnScreen 3266
-#define wxStyledTextCtrl_UsePopUp 3267
-#define wxStyledTextCtrl_SelectionIsRectangle 3268
-#define wxStyledTextCtrl_SetZoom 3269
-#define wxStyledTextCtrl_GetZoom 3270
-#define wxStyledTextCtrl_GetModEventMask 3271
-#define wxStyledTextCtrl_SetSTCFocus 3272
-#define wxStyledTextCtrl_GetSTCFocus 3273
-#define wxStyledTextCtrl_SetStatus 3274
-#define wxStyledTextCtrl_GetStatus 3275
-#define wxStyledTextCtrl_SetMouseDownCaptures 3276
-#define wxStyledTextCtrl_GetMouseDownCaptures 3277
-#define wxStyledTextCtrl_SetSTCCursor 3278
-#define wxStyledTextCtrl_GetSTCCursor 3279
-#define wxStyledTextCtrl_SetControlCharSymbol 3280
-#define wxStyledTextCtrl_GetControlCharSymbol 3281
-#define wxStyledTextCtrl_WordPartLeft 3282
-#define wxStyledTextCtrl_WordPartLeftExtend 3283
-#define wxStyledTextCtrl_WordPartRight 3284
-#define wxStyledTextCtrl_WordPartRightExtend 3285
-#define wxStyledTextCtrl_SetVisiblePolicy 3286
-#define wxStyledTextCtrl_DelLineLeft 3287
-#define wxStyledTextCtrl_DelLineRight 3288
-#define wxStyledTextCtrl_GetXOffset 3289
-#define wxStyledTextCtrl_ChooseCaretX 3290
-#define wxStyledTextCtrl_SetXCaretPolicy 3291
-#define wxStyledTextCtrl_SetYCaretPolicy 3292
-#define wxStyledTextCtrl_GetPrintWrapMode 3293
-#define wxStyledTextCtrl_SetHotspotActiveForeground 3294
-#define wxStyledTextCtrl_SetHotspotActiveBackground 3295
-#define wxStyledTextCtrl_SetHotspotActiveUnderline 3296
-#define wxStyledTextCtrl_SetHotspotSingleLine 3297
-#define wxStyledTextCtrl_ParaDownExtend 3298
-#define wxStyledTextCtrl_ParaUp 3299
-#define wxStyledTextCtrl_ParaUpExtend 3300
-#define wxStyledTextCtrl_PositionBefore 3301
-#define wxStyledTextCtrl_PositionAfter 3302
-#define wxStyledTextCtrl_CopyRange 3303
-#define wxStyledTextCtrl_CopyText 3304
-#define wxStyledTextCtrl_SetSelectionMode 3305
-#define wxStyledTextCtrl_GetSelectionMode 3306
-#define wxStyledTextCtrl_LineDownRectExtend 3307
-#define wxStyledTextCtrl_LineUpRectExtend 3308
-#define wxStyledTextCtrl_CharLeftRectExtend 3309
-#define wxStyledTextCtrl_CharRightRectExtend 3310
-#define wxStyledTextCtrl_HomeRectExtend 3311
-#define wxStyledTextCtrl_VCHomeRectExtend 3312
-#define wxStyledTextCtrl_LineEndRectExtend 3313
-#define wxStyledTextCtrl_PageUpRectExtend 3314
-#define wxStyledTextCtrl_PageDownRectExtend 3315
-#define wxStyledTextCtrl_StutteredPageUp 3316
-#define wxStyledTextCtrl_StutteredPageUpExtend 3317
-#define wxStyledTextCtrl_StutteredPageDown 3318
-#define wxStyledTextCtrl_StutteredPageDownExtend 3319
-#define wxStyledTextCtrl_WordLeftEnd 3320
-#define wxStyledTextCtrl_WordLeftEndExtend 3321
-#define wxStyledTextCtrl_WordRightEnd 3322
-#define wxStyledTextCtrl_WordRightEndExtend 3323
-#define wxStyledTextCtrl_SetWhitespaceChars 3324
-#define wxStyledTextCtrl_SetCharsDefault 3325
-#define wxStyledTextCtrl_AutoCompGetCurrent 3326
-#define wxStyledTextCtrl_Allocate 3327
-#define wxStyledTextCtrl_FindColumn 3328
-#define wxStyledTextCtrl_GetCaretSticky 3329
-#define wxStyledTextCtrl_SetCaretSticky 3330
-#define wxStyledTextCtrl_ToggleCaretSticky 3331
-#define wxStyledTextCtrl_SetPasteConvertEndings 3332
-#define wxStyledTextCtrl_GetPasteConvertEndings 3333
-#define wxStyledTextCtrl_SelectionDuplicate 3334
-#define wxStyledTextCtrl_SetCaretLineBackAlpha 3335
-#define wxStyledTextCtrl_GetCaretLineBackAlpha 3336
-#define wxStyledTextCtrl_StartRecord 3337
-#define wxStyledTextCtrl_StopRecord 3338
-#define wxStyledTextCtrl_SetLexer 3339
-#define wxStyledTextCtrl_GetLexer 3340
-#define wxStyledTextCtrl_Colourise 3341
-#define wxStyledTextCtrl_SetProperty 3342
-#define wxStyledTextCtrl_SetKeyWords 3343
-#define wxStyledTextCtrl_SetLexerLanguage 3344
-#define wxStyledTextCtrl_GetProperty 3345
-#define wxStyledTextCtrl_GetStyleBitsNeeded 3346
-#define wxStyledTextCtrl_GetCurrentLine 3347
-#define wxStyledTextCtrl_StyleSetSpec 3348
-#define wxStyledTextCtrl_StyleSetFont 3349
-#define wxStyledTextCtrl_StyleSetFontAttr 3350
-#define wxStyledTextCtrl_StyleSetCharacterSet 3351
-#define wxStyledTextCtrl_StyleSetFontEncoding 3352
-#define wxStyledTextCtrl_CmdKeyExecute 3353
-#define wxStyledTextCtrl_SetMargins 3354
-#define wxStyledTextCtrl_GetSelection 3355
-#define wxStyledTextCtrl_PointFromPosition 3356
-#define wxStyledTextCtrl_ScrollToLine 3357
-#define wxStyledTextCtrl_ScrollToColumn 3358
-#define wxStyledTextCtrl_SendMsg 3359
-#define wxStyledTextCtrl_SetVScrollBar 3360
-#define wxStyledTextCtrl_SetHScrollBar 3361
-#define wxStyledTextCtrl_GetLastKeydownProcessed 3362
-#define wxStyledTextCtrl_SetLastKeydownProcessed 3363
-#define wxStyledTextCtrl_SaveFile 3364
-#define wxStyledTextCtrl_LoadFile 3365
-#define wxStyledTextCtrl_DoDragOver 3366
-#define wxStyledTextCtrl_DoDropText 3367
-#define wxStyledTextCtrl_GetUseAntiAliasing 3368
-#define wxStyledTextCtrl_AddTextRaw 3369
-#define wxStyledTextCtrl_InsertTextRaw 3370
-#define wxStyledTextCtrl_GetCurLineRaw 3371
-#define wxStyledTextCtrl_GetLineRaw 3372
-#define wxStyledTextCtrl_GetSelectedTextRaw 3373
-#define wxStyledTextCtrl_GetTextRangeRaw 3374
-#define wxStyledTextCtrl_SetTextRaw 3375
-#define wxStyledTextCtrl_GetTextRaw 3376
-#define wxStyledTextCtrl_AppendTextRaw 3377
-#define wxArtProvider_GetBitmap 3378
-#define wxArtProvider_GetIcon 3379
-#define wxTreeEvent_GetKeyCode 3380
-#define wxTreeEvent_GetItem 3381
-#define wxTreeEvent_GetKeyEvent 3382
-#define wxTreeEvent_GetLabel 3383
-#define wxTreeEvent_GetOldItem 3384
-#define wxTreeEvent_GetPoint 3385
-#define wxTreeEvent_IsEditCancelled 3386
-#define wxTreeEvent_SetToolTip 3387
-#define wxNotebookEvent_GetOldSelection 3388
-#define wxNotebookEvent_GetSelection 3389
-#define wxNotebookEvent_SetOldSelection 3390
-#define wxNotebookEvent_SetSelection 3391
-#define wxFileDataObject_new 3392
-#define wxFileDataObject_AddFile 3393
-#define wxFileDataObject_GetFilenames 3394
-#define wxFileDataObject_destroy 3395
-#define wxTextDataObject_new 3396
-#define wxTextDataObject_GetTextLength 3397
-#define wxTextDataObject_GetText 3398
-#define wxTextDataObject_SetText 3399
-#define wxTextDataObject_destroy 3400
-#define wxBitmapDataObject_new_1_1 3401
-#define wxBitmapDataObject_new_1_0 3402
-#define wxBitmapDataObject_GetBitmap 3403
-#define wxBitmapDataObject_SetBitmap 3404
-#define wxBitmapDataObject_destroy 3405
-#define wxClipboard_new 3407
-#define wxClipboard_destruct 3408
-#define wxClipboard_AddData 3409
-#define wxClipboard_Clear 3410
-#define wxClipboard_Close 3411
-#define wxClipboard_Flush 3412
-#define wxClipboard_GetData 3413
-#define wxClipboard_IsOpened 3414
-#define wxClipboard_Open 3415
-#define wxClipboard_SetData 3416
-#define wxClipboard_UsePrimarySelection 3418
-#define wxClipboard_IsSupported 3419
-#define wxClipboard_Get 3420
-#define wxSpinEvent_GetPosition 3421
-#define wxSpinEvent_SetPosition 3422
-#define wxSplitterWindow_new_0 3423
-#define wxSplitterWindow_new_2 3424
-#define wxSplitterWindow_destruct 3425
-#define wxSplitterWindow_Create 3426
-#define wxSplitterWindow_GetMinimumPaneSize 3427
-#define wxSplitterWindow_GetSashGravity 3428
-#define wxSplitterWindow_GetSashPosition 3429
-#define wxSplitterWindow_GetSplitMode 3430
-#define wxSplitterWindow_GetWindow1 3431
-#define wxSplitterWindow_GetWindow2 3432
-#define wxSplitterWindow_Initialize 3433
-#define wxSplitterWindow_IsSplit 3434
-#define wxSplitterWindow_ReplaceWindow 3435
-#define wxSplitterWindow_SetSashGravity 3436
-#define wxSplitterWindow_SetSashPosition 3437
-#define wxSplitterWindow_SetSashSize 3438
-#define wxSplitterWindow_SetMinimumPaneSize 3439
-#define wxSplitterWindow_SetSplitMode 3440
-#define wxSplitterWindow_SplitHorizontally 3441
-#define wxSplitterWindow_SplitVertically 3442
-#define wxSplitterWindow_Unsplit 3443
-#define wxSplitterWindow_UpdateSize 3444
-#define wxSplitterEvent_GetSashPosition 3445
-#define wxSplitterEvent_GetX 3446
-#define wxSplitterEvent_GetY 3447
-#define wxSplitterEvent_GetWindowBeingRemoved 3448
-#define wxSplitterEvent_SetSashPosition 3449
-#define wxHtmlWindow_new_0 3450
-#define wxHtmlWindow_new_2 3451
-#define wxHtmlWindow_AppendToPage 3452
-#define wxHtmlWindow_GetOpenedAnchor 3453
-#define wxHtmlWindow_GetOpenedPage 3454
-#define wxHtmlWindow_GetOpenedPageTitle 3455
-#define wxHtmlWindow_GetRelatedFrame 3456
-#define wxHtmlWindow_HistoryBack 3457
-#define wxHtmlWindow_HistoryCanBack 3458
-#define wxHtmlWindow_HistoryCanForward 3459
-#define wxHtmlWindow_HistoryClear 3460
-#define wxHtmlWindow_HistoryForward 3461
-#define wxHtmlWindow_LoadFile 3462
-#define wxHtmlWindow_LoadPage 3463
-#define wxHtmlWindow_SelectAll 3464
-#define wxHtmlWindow_SelectionToText 3465
-#define wxHtmlWindow_SelectLine 3466
-#define wxHtmlWindow_SelectWord 3467
-#define wxHtmlWindow_SetBorders 3468
-#define wxHtmlWindow_SetFonts 3469
-#define wxHtmlWindow_SetPage 3470
-#define wxHtmlWindow_SetRelatedFrame 3471
-#define wxHtmlWindow_SetRelatedStatusBar 3472
-#define wxHtmlWindow_ToText 3473
-#define wxHtmlWindow_destroy 3474
-#define wxHtmlLinkEvent_GetLinkInfo 3475
-#define wxSystemSettings_GetColour 3476
-#define wxSystemSettings_GetFont 3477
-#define wxSystemSettings_GetMetric 3478
-#define wxSystemSettings_GetScreenType 3479
-#define wxAuiNotebookEvent_SetSelection 3480
-#define wxAuiNotebookEvent_GetSelection 3481
-#define wxAuiNotebookEvent_SetOldSelection 3482
-#define wxAuiNotebookEvent_GetOldSelection 3483
-#define wxAuiNotebookEvent_SetDragSource 3484
-#define wxAuiNotebookEvent_GetDragSource 3485
-#define wxAuiManagerEvent_SetManager 3486
-#define wxAuiManagerEvent_GetManager 3487
-#define wxAuiManagerEvent_SetPane 3488
-#define wxAuiManagerEvent_GetPane 3489
-#define wxAuiManagerEvent_SetButton 3490
-#define wxAuiManagerEvent_GetButton 3491
-#define wxAuiManagerEvent_SetDC 3492
-#define wxAuiManagerEvent_GetDC 3493
-#define wxAuiManagerEvent_Veto 3494
-#define wxAuiManagerEvent_GetVeto 3495
-#define wxAuiManagerEvent_SetCanVeto 3496
-#define wxAuiManagerEvent_CanVeto 3497
-#define wxLogNull_new 3498
-#define wxLogNull_destroy 3499
+#define wxListItemAttr_new_0 1757
+#define wxListItemAttr_new_3 1758
+#define wxListItemAttr_GetBackgroundColour 1759
+#define wxListItemAttr_GetFont 1760
+#define wxListItemAttr_GetTextColour 1761
+#define wxListItemAttr_HasBackgroundColour 1762
+#define wxListItemAttr_HasFont 1763
+#define wxListItemAttr_HasTextColour 1764
+#define wxListItemAttr_SetBackgroundColour 1765
+#define wxListItemAttr_SetFont 1766
+#define wxListItemAttr_SetTextColour 1767
+#define wxListItemAttr_destroy 1768
+#define wxImageList_new_0 1769
+#define wxImageList_new_3 1770
+#define wxImageList_Add_1 1771
+#define wxImageList_Add_2_0 1772
+#define wxImageList_Add_2_1 1773
+#define wxImageList_Create 1774
+#define wxImageList_Draw 1776
+#define wxImageList_GetBitmap 1777
+#define wxImageList_GetIcon 1778
+#define wxImageList_GetImageCount 1779
+#define wxImageList_GetSize 1780
+#define wxImageList_Remove 1781
+#define wxImageList_RemoveAll 1782
+#define wxImageList_Replace_2 1783
+#define wxImageList_Replace_3 1784
+#define wxImageList_destroy 1785
+#define wxTextAttr_new_0 1786
+#define wxTextAttr_new_2 1787
+#define wxTextAttr_GetAlignment 1788
+#define wxTextAttr_GetBackgroundColour 1789
+#define wxTextAttr_GetFont 1790
+#define wxTextAttr_GetLeftIndent 1791
+#define wxTextAttr_GetLeftSubIndent 1792
+#define wxTextAttr_GetRightIndent 1793
+#define wxTextAttr_GetTabs 1794
+#define wxTextAttr_GetTextColour 1795
+#define wxTextAttr_HasBackgroundColour 1796
+#define wxTextAttr_HasFont 1797
+#define wxTextAttr_HasTextColour 1798
+#define wxTextAttr_GetFlags 1799
+#define wxTextAttr_IsDefault 1800
+#define wxTextAttr_SetAlignment 1801
+#define wxTextAttr_SetBackgroundColour 1802
+#define wxTextAttr_SetFlags 1803
+#define wxTextAttr_SetFont 1804
+#define wxTextAttr_SetLeftIndent 1805
+#define wxTextAttr_SetRightIndent 1806
+#define wxTextAttr_SetTabs 1807
+#define wxTextAttr_SetTextColour 1808
+#define wxTextAttr_destroy 1809
+#define wxTextCtrl_new_3 1811
+#define wxTextCtrl_new_0 1812
+#define wxTextCtrl_destruct 1814
+#define wxTextCtrl_AppendText 1815
+#define wxTextCtrl_CanCopy 1816
+#define wxTextCtrl_CanCut 1817
+#define wxTextCtrl_CanPaste 1818
+#define wxTextCtrl_CanRedo 1819
+#define wxTextCtrl_CanUndo 1820
+#define wxTextCtrl_Clear 1821
+#define wxTextCtrl_Copy 1822
+#define wxTextCtrl_Create 1823
+#define wxTextCtrl_Cut 1824
+#define wxTextCtrl_DiscardEdits 1825
+#define wxTextCtrl_EmulateKeyPress 1826
+#define wxTextCtrl_GetDefaultStyle 1827
+#define wxTextCtrl_GetInsertionPoint 1828
+#define wxTextCtrl_GetLastPosition 1829
+#define wxTextCtrl_GetLineLength 1830
+#define wxTextCtrl_GetLineText 1831
+#define wxTextCtrl_GetNumberOfLines 1832
+#define wxTextCtrl_GetRange 1833
+#define wxTextCtrl_GetSelection 1834
+#define wxTextCtrl_GetStringSelection 1835
+#define wxTextCtrl_GetStyle 1836
+#define wxTextCtrl_GetValue 1837
+#define wxTextCtrl_IsEditable 1838
+#define wxTextCtrl_IsModified 1839
+#define wxTextCtrl_IsMultiLine 1840
+#define wxTextCtrl_IsSingleLine 1841
+#define wxTextCtrl_LoadFile 1842
+#define wxTextCtrl_MarkDirty 1843
+#define wxTextCtrl_Paste 1844
+#define wxTextCtrl_PositionToXY 1845
+#define wxTextCtrl_Redo 1846
+#define wxTextCtrl_Remove 1847
+#define wxTextCtrl_Replace 1848
+#define wxTextCtrl_SaveFile 1849
+#define wxTextCtrl_SetDefaultStyle 1850
+#define wxTextCtrl_SetEditable 1851
+#define wxTextCtrl_SetInsertionPoint 1852
+#define wxTextCtrl_SetInsertionPointEnd 1853
+#define wxTextCtrl_SetMaxLength 1855
+#define wxTextCtrl_SetSelection 1856
+#define wxTextCtrl_SetStyle 1857
+#define wxTextCtrl_SetValue 1858
+#define wxTextCtrl_ShowPosition 1859
+#define wxTextCtrl_Undo 1860
+#define wxTextCtrl_WriteText 1861
+#define wxTextCtrl_XYToPosition 1862
+#define wxNotebook_new_0 1865
+#define wxNotebook_new_3 1866
+#define wxNotebook_destruct 1867
+#define wxNotebook_AddPage 1868
+#define wxNotebook_AdvanceSelection 1869
+#define wxNotebook_AssignImageList 1870
+#define wxNotebook_Create 1871
+#define wxNotebook_DeleteAllPages 1872
+#define wxNotebook_DeletePage 1873
+#define wxNotebook_RemovePage 1874
+#define wxNotebook_GetCurrentPage 1875
+#define wxNotebook_GetImageList 1876
+#define wxNotebook_GetPage 1878
+#define wxNotebook_GetPageCount 1879
+#define wxNotebook_GetPageImage 1880
+#define wxNotebook_GetPageText 1881
+#define wxNotebook_GetRowCount 1882
+#define wxNotebook_GetSelection 1883
+#define wxNotebook_GetThemeBackgroundColour 1884
+#define wxNotebook_HitTest 1886
+#define wxNotebook_InsertPage 1888
+#define wxNotebook_SetImageList 1889
+#define wxNotebook_SetPadding 1890
+#define wxNotebook_SetPageSize 1891
+#define wxNotebook_SetPageImage 1892
+#define wxNotebook_SetPageText 1893
+#define wxNotebook_SetSelection 1894
+#define wxNotebook_ChangeSelection 1895
+#define wxChoicebook_new_0 1896
+#define wxChoicebook_new_3 1897
+#define wxChoicebook_AddPage 1898
+#define wxChoicebook_AdvanceSelection 1899
+#define wxChoicebook_AssignImageList 1900
+#define wxChoicebook_Create 1901
+#define wxChoicebook_DeleteAllPages 1902
+#define wxChoicebook_DeletePage 1903
+#define wxChoicebook_RemovePage 1904
+#define wxChoicebook_GetCurrentPage 1905
+#define wxChoicebook_GetImageList 1906
+#define wxChoicebook_GetPage 1908
+#define wxChoicebook_GetPageCount 1909
+#define wxChoicebook_GetPageImage 1910
+#define wxChoicebook_GetPageText 1911
+#define wxChoicebook_GetSelection 1912
+#define wxChoicebook_HitTest 1913
+#define wxChoicebook_InsertPage 1914
+#define wxChoicebook_SetImageList 1915
+#define wxChoicebook_SetPageSize 1916
+#define wxChoicebook_SetPageImage 1917
+#define wxChoicebook_SetPageText 1918
+#define wxChoicebook_SetSelection 1919
+#define wxChoicebook_ChangeSelection 1920
+#define wxChoicebook_destroy 1921
+#define wxToolbook_new_0 1922
+#define wxToolbook_new_3 1923
+#define wxToolbook_AddPage 1924
+#define wxToolbook_AdvanceSelection 1925
+#define wxToolbook_AssignImageList 1926
+#define wxToolbook_Create 1927
+#define wxToolbook_DeleteAllPages 1928
+#define wxToolbook_DeletePage 1929
+#define wxToolbook_RemovePage 1930
+#define wxToolbook_GetCurrentPage 1931
+#define wxToolbook_GetImageList 1932
+#define wxToolbook_GetPage 1934
+#define wxToolbook_GetPageCount 1935
+#define wxToolbook_GetPageImage 1936
+#define wxToolbook_GetPageText 1937
+#define wxToolbook_GetSelection 1938
+#define wxToolbook_HitTest 1940
+#define wxToolbook_InsertPage 1941
+#define wxToolbook_SetImageList 1942
+#define wxToolbook_SetPageSize 1943
+#define wxToolbook_SetPageImage 1944
+#define wxToolbook_SetPageText 1945
+#define wxToolbook_SetSelection 1946
+#define wxToolbook_ChangeSelection 1947
+#define wxToolbook_destroy 1948
+#define wxListbook_new_0 1949
+#define wxListbook_new_3 1950
+#define wxListbook_AddPage 1951
+#define wxListbook_AdvanceSelection 1952
+#define wxListbook_AssignImageList 1953
+#define wxListbook_Create 1954
+#define wxListbook_DeleteAllPages 1955
+#define wxListbook_DeletePage 1956
+#define wxListbook_RemovePage 1957
+#define wxListbook_GetCurrentPage 1958
+#define wxListbook_GetImageList 1959
+#define wxListbook_GetPage 1961
+#define wxListbook_GetPageCount 1962
+#define wxListbook_GetPageImage 1963
+#define wxListbook_GetPageText 1964
+#define wxListbook_GetSelection 1965
+#define wxListbook_HitTest 1967
+#define wxListbook_InsertPage 1968
+#define wxListbook_SetImageList 1969
+#define wxListbook_SetPageSize 1970
+#define wxListbook_SetPageImage 1971
+#define wxListbook_SetPageText 1972
+#define wxListbook_SetSelection 1973
+#define wxListbook_ChangeSelection 1974
+#define wxListbook_destroy 1975
+#define wxTreebook_new_0 1976
+#define wxTreebook_new_3 1977
+#define wxTreebook_AddPage 1978
+#define wxTreebook_AdvanceSelection 1979
+#define wxTreebook_AssignImageList 1980
+#define wxTreebook_Create 1981
+#define wxTreebook_DeleteAllPages 1982
+#define wxTreebook_DeletePage 1983
+#define wxTreebook_RemovePage 1984
+#define wxTreebook_GetCurrentPage 1985
+#define wxTreebook_GetImageList 1986
+#define wxTreebook_GetPage 1988
+#define wxTreebook_GetPageCount 1989
+#define wxTreebook_GetPageImage 1990
+#define wxTreebook_GetPageText 1991
+#define wxTreebook_GetSelection 1992
+#define wxTreebook_ExpandNode 1993
+#define wxTreebook_IsNodeExpanded 1994
+#define wxTreebook_HitTest 1996
+#define wxTreebook_InsertPage 1997
+#define wxTreebook_InsertSubPage 1998
+#define wxTreebook_SetImageList 1999
+#define wxTreebook_SetPageSize 2000
+#define wxTreebook_SetPageImage 2001
+#define wxTreebook_SetPageText 2002
+#define wxTreebook_SetSelection 2003
+#define wxTreebook_ChangeSelection 2004
+#define wxTreebook_destroy 2005
+#define wxTreeCtrl_new_2 2008
+#define wxTreeCtrl_new_0 2009
+#define wxTreeCtrl_destruct 2011
+#define wxTreeCtrl_AddRoot 2012
+#define wxTreeCtrl_AppendItem 2013
+#define wxTreeCtrl_AssignImageList 2014
+#define wxTreeCtrl_AssignStateImageList 2015
+#define wxTreeCtrl_Collapse 2016
+#define wxTreeCtrl_CollapseAndReset 2017
+#define wxTreeCtrl_Create 2018
+#define wxTreeCtrl_Delete 2019
+#define wxTreeCtrl_DeleteAllItems 2020
+#define wxTreeCtrl_DeleteChildren 2021
+#define wxTreeCtrl_EditLabel 2022
+#define wxTreeCtrl_EnsureVisible 2023
+#define wxTreeCtrl_Expand 2024
+#define wxTreeCtrl_GetBoundingRect 2025
+#define wxTreeCtrl_GetChildrenCount 2027
+#define wxTreeCtrl_GetCount 2028
+#define wxTreeCtrl_GetEditControl 2029
+#define wxTreeCtrl_GetFirstChild 2030
+#define wxTreeCtrl_GetNextChild 2031
+#define wxTreeCtrl_GetFirstVisibleItem 2032
+#define wxTreeCtrl_GetImageList 2033
+#define wxTreeCtrl_GetIndent 2034
+#define wxTreeCtrl_GetItemBackgroundColour 2035
+#define wxTreeCtrl_GetItemData 2036
+#define wxTreeCtrl_GetItemFont 2037
+#define wxTreeCtrl_GetItemImage_1 2038
+#define wxTreeCtrl_GetItemImage_2 2039
+#define wxTreeCtrl_GetItemText 2040
+#define wxTreeCtrl_GetItemTextColour 2041
+#define wxTreeCtrl_GetLastChild 2042
+#define wxTreeCtrl_GetNextSibling 2043
+#define wxTreeCtrl_GetNextVisible 2044
+#define wxTreeCtrl_GetItemParent 2045
+#define wxTreeCtrl_GetPrevSibling 2046
+#define wxTreeCtrl_GetPrevVisible 2047
+#define wxTreeCtrl_GetRootItem 2048
+#define wxTreeCtrl_GetSelection 2049
+#define wxTreeCtrl_GetSelections 2050
+#define wxTreeCtrl_GetStateImageList 2051
+#define wxTreeCtrl_HitTest 2052
+#define wxTreeCtrl_InsertItem 2054
+#define wxTreeCtrl_IsBold 2055
+#define wxTreeCtrl_IsExpanded 2056
+#define wxTreeCtrl_IsSelected 2057
+#define wxTreeCtrl_IsVisible 2058
+#define wxTreeCtrl_ItemHasChildren 2059
+#define wxTreeCtrl_PrependItem 2060
+#define wxTreeCtrl_ScrollTo 2061
+#define wxTreeCtrl_SelectItem_1 2062
+#define wxTreeCtrl_SelectItem_2 2063
+#define wxTreeCtrl_SetIndent 2064
+#define wxTreeCtrl_SetImageList 2065
+#define wxTreeCtrl_SetItemBackgroundColour 2066
+#define wxTreeCtrl_SetItemBold 2067
+#define wxTreeCtrl_SetItemData 2068
+#define wxTreeCtrl_SetItemDropHighlight 2069
+#define wxTreeCtrl_SetItemFont 2070
+#define wxTreeCtrl_SetItemHasChildren 2071
+#define wxTreeCtrl_SetItemImage_2 2072
+#define wxTreeCtrl_SetItemImage_3 2073
+#define wxTreeCtrl_SetItemText 2074
+#define wxTreeCtrl_SetItemTextColour 2075
+#define wxTreeCtrl_SetStateImageList 2076
+#define wxTreeCtrl_SetWindowStyle 2077
+#define wxTreeCtrl_SortChildren 2078
+#define wxTreeCtrl_Toggle 2079
+#define wxTreeCtrl_ToggleItemSelection 2080
+#define wxTreeCtrl_Unselect 2081
+#define wxTreeCtrl_UnselectAll 2082
+#define wxTreeCtrl_UnselectItem 2083
+#define wxScrollBar_new_0 2084
+#define wxScrollBar_new_3 2085
+#define wxScrollBar_destruct 2086
+#define wxScrollBar_Create 2087
+#define wxScrollBar_GetRange 2088
+#define wxScrollBar_GetPageSize 2089
+#define wxScrollBar_GetThumbPosition 2090
+#define wxScrollBar_GetThumbSize 2091
+#define wxScrollBar_SetThumbPosition 2092
+#define wxScrollBar_SetScrollbar 2093
+#define wxSpinButton_new_2 2095
+#define wxSpinButton_new_0 2096
+#define wxSpinButton_Create 2097
+#define wxSpinButton_GetMax 2098
+#define wxSpinButton_GetMin 2099
+#define wxSpinButton_GetValue 2100
+#define wxSpinButton_SetRange 2101
+#define wxSpinButton_SetValue 2102
+#define wxSpinButton_destroy 2103
+#define wxSpinCtrl_new_0 2104
+#define wxSpinCtrl_new_2 2105
+#define wxSpinCtrl_Create 2107
+#define wxSpinCtrl_SetValue_1_1 2110
+#define wxSpinCtrl_SetValue_1_0 2111
+#define wxSpinCtrl_GetValue 2113
+#define wxSpinCtrl_SetRange 2115
+#define wxSpinCtrl_SetSelection 2116
+#define wxSpinCtrl_GetMin 2118
+#define wxSpinCtrl_GetMax 2120
+#define wxSpinCtrl_destroy 2121
+#define wxStaticText_new_0 2122
+#define wxStaticText_new_4 2123
+#define wxStaticText_Create 2124
+#define wxStaticText_GetLabel 2125
+#define wxStaticText_SetLabel 2126
+#define wxStaticText_Wrap 2127
+#define wxStaticText_destroy 2128
+#define wxStaticBitmap_new_0 2129
+#define wxStaticBitmap_new_4 2130
+#define wxStaticBitmap_Create 2131
+#define wxStaticBitmap_GetBitmap 2132
+#define wxStaticBitmap_SetBitmap 2133
+#define wxStaticBitmap_destroy 2134
+#define wxRadioBox_new 2135
+#define wxRadioBox_destruct 2137
+#define wxRadioBox_Create 2138
+#define wxRadioBox_Enable_2 2139
+#define wxRadioBox_Enable_1 2140
+#define wxRadioBox_GetSelection 2141
+#define wxRadioBox_GetString 2142
+#define wxRadioBox_SetSelection 2143
+#define wxRadioBox_Show_2 2144
+#define wxRadioBox_Show_1 2145
+#define wxRadioBox_GetColumnCount 2146
+#define wxRadioBox_GetItemHelpText 2147
+#define wxRadioBox_GetItemToolTip 2148
+#define wxRadioBox_GetItemFromPoint 2150
+#define wxRadioBox_GetRowCount 2151
+#define wxRadioBox_IsItemEnabled 2152
+#define wxRadioBox_IsItemShown 2153
+#define wxRadioBox_SetItemHelpText 2154
+#define wxRadioBox_SetItemToolTip 2155
+#define wxRadioButton_new_0 2156
+#define wxRadioButton_new_4 2157
+#define wxRadioButton_Create 2158
+#define wxRadioButton_GetValue 2159
+#define wxRadioButton_SetValue 2160
+#define wxRadioButton_destroy 2161
+#define wxSlider_new_6 2163
+#define wxSlider_new_0 2164
+#define wxSlider_Create 2165
+#define wxSlider_GetLineSize 2166
+#define wxSlider_GetMax 2167
+#define wxSlider_GetMin 2168
+#define wxSlider_GetPageSize 2169
+#define wxSlider_GetThumbLength 2170
+#define wxSlider_GetValue 2171
+#define wxSlider_SetLineSize 2172
+#define wxSlider_SetPageSize 2173
+#define wxSlider_SetRange 2174
+#define wxSlider_SetThumbLength 2175
+#define wxSlider_SetValue 2176
+#define wxSlider_destroy 2177
+#define wxDialog_new_4 2179
+#define wxDialog_new_0 2180
+#define wxDialog_destruct 2182
+#define wxDialog_Create 2183
+#define wxDialog_CreateButtonSizer 2184
+#define wxDialog_CreateStdDialogButtonSizer 2185
+#define wxDialog_EndModal 2186
+#define wxDialog_GetAffirmativeId 2187
+#define wxDialog_GetReturnCode 2188
+#define wxDialog_IsModal 2189
+#define wxDialog_SetAffirmativeId 2190
+#define wxDialog_SetReturnCode 2191
+#define wxDialog_Show 2192
+#define wxDialog_ShowModal 2193
+#define wxColourDialog_new_0 2194
+#define wxColourDialog_new_2 2195
+#define wxColourDialog_destruct 2196
+#define wxColourDialog_Create 2197
+#define wxColourDialog_GetColourData 2198
+#define wxColourData_new_0 2199
+#define wxColourData_new_1 2200
+#define wxColourData_destruct 2201
+#define wxColourData_GetChooseFull 2202
+#define wxColourData_GetColour 2203
+#define wxColourData_GetCustomColour 2205
+#define wxColourData_SetChooseFull 2206
+#define wxColourData_SetColour 2207
+#define wxColourData_SetCustomColour 2208
+#define wxPalette_new_0 2209
+#define wxPalette_new_4 2210
+#define wxPalette_destruct 2212
+#define wxPalette_Create 2213
+#define wxPalette_GetColoursCount 2214
+#define wxPalette_GetPixel 2215
+#define wxPalette_GetRGB 2216
+#define wxPalette_IsOk 2217
+#define wxDirDialog_new 2221
+#define wxDirDialog_destruct 2222
+#define wxDirDialog_GetPath 2223
+#define wxDirDialog_GetMessage 2224
+#define wxDirDialog_SetMessage 2225
+#define wxDirDialog_SetPath 2226
+#define wxFileDialog_new 2230
+#define wxFileDialog_destruct 2231
+#define wxFileDialog_GetDirectory 2232
+#define wxFileDialog_GetFilename 2233
+#define wxFileDialog_GetFilenames 2234
+#define wxFileDialog_GetFilterIndex 2235
+#define wxFileDialog_GetMessage 2236
+#define wxFileDialog_GetPath 2237
+#define wxFileDialog_GetPaths 2238
+#define wxFileDialog_GetWildcard 2239
+#define wxFileDialog_SetDirectory 2240
+#define wxFileDialog_SetFilename 2241
+#define wxFileDialog_SetFilterIndex 2242
+#define wxFileDialog_SetMessage 2243
+#define wxFileDialog_SetPath 2244
+#define wxFileDialog_SetWildcard 2245
+#define wxPickerBase_SetInternalMargin 2246
+#define wxPickerBase_GetInternalMargin 2247
+#define wxPickerBase_SetTextCtrlProportion 2248
+#define wxPickerBase_SetPickerCtrlProportion 2249
+#define wxPickerBase_GetTextCtrlProportion 2250
+#define wxPickerBase_GetPickerCtrlProportion 2251
+#define wxPickerBase_HasTextCtrl 2252
+#define wxPickerBase_GetTextCtrl 2253
+#define wxPickerBase_IsTextCtrlGrowable 2254
+#define wxPickerBase_SetPickerCtrlGrowable 2255
+#define wxPickerBase_SetTextCtrlGrowable 2256
+#define wxPickerBase_IsPickerCtrlGrowable 2257
+#define wxFilePickerCtrl_new_0 2258
+#define wxFilePickerCtrl_new_3 2259
+#define wxFilePickerCtrl_Create 2260
+#define wxFilePickerCtrl_GetPath 2261
+#define wxFilePickerCtrl_SetPath 2262
+#define wxFilePickerCtrl_destroy 2263
+#define wxDirPickerCtrl_new_0 2264
+#define wxDirPickerCtrl_new_3 2265
+#define wxDirPickerCtrl_Create 2266
+#define wxDirPickerCtrl_GetPath 2267
+#define wxDirPickerCtrl_SetPath 2268
+#define wxDirPickerCtrl_destroy 2269
+#define wxColourPickerCtrl_new_0 2270
+#define wxColourPickerCtrl_new_3 2271
+#define wxColourPickerCtrl_Create 2272
+#define wxColourPickerCtrl_GetColour 2273
+#define wxColourPickerCtrl_SetColour_1_1 2274
+#define wxColourPickerCtrl_SetColour_1_0 2275
+#define wxColourPickerCtrl_destroy 2276
+#define wxDatePickerCtrl_new_0 2277
+#define wxDatePickerCtrl_new_3 2278
+#define wxDatePickerCtrl_GetRange 2279
+#define wxDatePickerCtrl_GetValue 2280
+#define wxDatePickerCtrl_SetRange 2281
+#define wxDatePickerCtrl_SetValue 2282
+#define wxDatePickerCtrl_destroy 2283
+#define wxFontPickerCtrl_new_0 2284
+#define wxFontPickerCtrl_new_3 2285
+#define wxFontPickerCtrl_Create 2286
+#define wxFontPickerCtrl_GetSelectedFont 2287
+#define wxFontPickerCtrl_SetSelectedFont 2288
+#define wxFontPickerCtrl_GetMaxPointSize 2289
+#define wxFontPickerCtrl_SetMaxPointSize 2290
+#define wxFontPickerCtrl_destroy 2291
+#define wxFindReplaceDialog_new_0 2294
+#define wxFindReplaceDialog_new_4 2295
+#define wxFindReplaceDialog_destruct 2296
+#define wxFindReplaceDialog_Create 2297
+#define wxFindReplaceDialog_GetData 2298
+#define wxFindReplaceData_new_0 2299
+#define wxFindReplaceData_new_1 2300
+#define wxFindReplaceData_GetFindString 2301
+#define wxFindReplaceData_GetReplaceString 2302
+#define wxFindReplaceData_GetFlags 2303
+#define wxFindReplaceData_SetFlags 2304
+#define wxFindReplaceData_SetFindString 2305
+#define wxFindReplaceData_SetReplaceString 2306
+#define wxFindReplaceData_destroy 2307
+#define wxMultiChoiceDialog_new_0 2308
+#define wxMultiChoiceDialog_new_5 2310
+#define wxMultiChoiceDialog_GetSelections 2311
+#define wxMultiChoiceDialog_SetSelections 2312
+#define wxMultiChoiceDialog_destroy 2313
+#define wxSingleChoiceDialog_new_0 2314
+#define wxSingleChoiceDialog_new_5 2316
+#define wxSingleChoiceDialog_GetSelection 2317
+#define wxSingleChoiceDialog_GetStringSelection 2318
+#define wxSingleChoiceDialog_SetSelection 2319
+#define wxSingleChoiceDialog_destroy 2320
+#define wxTextEntryDialog_new 2321
+#define wxTextEntryDialog_GetValue 2322
+#define wxTextEntryDialog_SetValue 2323
+#define wxTextEntryDialog_destroy 2324
+#define wxPasswordEntryDialog_new 2325
+#define wxPasswordEntryDialog_destroy 2326
+#define wxFontData_new_0 2327
+#define wxFontData_new_1 2328
+#define wxFontData_destruct 2329
+#define wxFontData_EnableEffects 2330
+#define wxFontData_GetAllowSymbols 2331
+#define wxFontData_GetColour 2332
+#define wxFontData_GetChosenFont 2333
+#define wxFontData_GetEnableEffects 2334
+#define wxFontData_GetInitialFont 2335
+#define wxFontData_GetShowHelp 2336
+#define wxFontData_SetAllowSymbols 2337
+#define wxFontData_SetChosenFont 2338
+#define wxFontData_SetColour 2339
+#define wxFontData_SetInitialFont 2340
+#define wxFontData_SetRange 2341
+#define wxFontData_SetShowHelp 2342
+#define wxFontDialog_new_0 2346
+#define wxFontDialog_new_2 2348
+#define wxFontDialog_Create 2350
+#define wxFontDialog_GetFontData 2351
+#define wxFontDialog_destroy 2353
+#define wxProgressDialog_new 2354
+#define wxProgressDialog_destruct 2355
+#define wxProgressDialog_Resume 2356
+#define wxProgressDialog_Update_2 2357
+#define wxProgressDialog_Update_0 2358
+#define wxMessageDialog_new 2359
+#define wxMessageDialog_destruct 2360
+#define wxPageSetupDialog_new 2361
+#define wxPageSetupDialog_destruct 2362
+#define wxPageSetupDialog_GetPageSetupData 2363
+#define wxPageSetupDialog_ShowModal 2364
+#define wxPageSetupDialogData_new_0 2365
+#define wxPageSetupDialogData_new_1_0 2366
+#define wxPageSetupDialogData_new_1_1 2367
+#define wxPageSetupDialogData_destruct 2368
+#define wxPageSetupDialogData_EnableHelp 2369
+#define wxPageSetupDialogData_EnableMargins 2370
+#define wxPageSetupDialogData_EnableOrientation 2371
+#define wxPageSetupDialogData_EnablePaper 2372
+#define wxPageSetupDialogData_EnablePrinter 2373
+#define wxPageSetupDialogData_GetDefaultMinMargins 2374
+#define wxPageSetupDialogData_GetEnableMargins 2375
+#define wxPageSetupDialogData_GetEnableOrientation 2376
+#define wxPageSetupDialogData_GetEnablePaper 2377
+#define wxPageSetupDialogData_GetEnablePrinter 2378
+#define wxPageSetupDialogData_GetEnableHelp 2379
+#define wxPageSetupDialogData_GetDefaultInfo 2380
+#define wxPageSetupDialogData_GetMarginTopLeft 2381
+#define wxPageSetupDialogData_GetMarginBottomRight 2382
+#define wxPageSetupDialogData_GetMinMarginTopLeft 2383
+#define wxPageSetupDialogData_GetMinMarginBottomRight 2384
+#define wxPageSetupDialogData_GetPaperId 2385
+#define wxPageSetupDialogData_GetPaperSize 2386
+#define wxPageSetupDialogData_GetPrintData 2388
+#define wxPageSetupDialogData_IsOk 2389
+#define wxPageSetupDialogData_SetDefaultInfo 2390
+#define wxPageSetupDialogData_SetDefaultMinMargins 2391
+#define wxPageSetupDialogData_SetMarginTopLeft 2392
+#define wxPageSetupDialogData_SetMarginBottomRight 2393
+#define wxPageSetupDialogData_SetMinMarginTopLeft 2394
+#define wxPageSetupDialogData_SetMinMarginBottomRight 2395
+#define wxPageSetupDialogData_SetPaperId 2396
+#define wxPageSetupDialogData_SetPaperSize_1_1 2397
+#define wxPageSetupDialogData_SetPaperSize_1_0 2398
+#define wxPageSetupDialogData_SetPrintData 2399
+#define wxPrintDialog_new_2_0 2400
+#define wxPrintDialog_new_2_1 2401
+#define wxPrintDialog_destruct 2402
+#define wxPrintDialog_GetPrintDialogData 2403
+#define wxPrintDialog_GetPrintDC 2404
+#define wxPrintDialogData_new_0 2405
+#define wxPrintDialogData_new_1_1 2406
+#define wxPrintDialogData_new_1_0 2407
+#define wxPrintDialogData_destruct 2408
+#define wxPrintDialogData_EnableHelp 2409
+#define wxPrintDialogData_EnablePageNumbers 2410
+#define wxPrintDialogData_EnablePrintToFile 2411
+#define wxPrintDialogData_EnableSelection 2412
+#define wxPrintDialogData_GetAllPages 2413
+#define wxPrintDialogData_GetCollate 2414
+#define wxPrintDialogData_GetFromPage 2415
+#define wxPrintDialogData_GetMaxPage 2416
+#define wxPrintDialogData_GetMinPage 2417
+#define wxPrintDialogData_GetNoCopies 2418
+#define wxPrintDialogData_GetPrintData 2419
+#define wxPrintDialogData_GetPrintToFile 2420
+#define wxPrintDialogData_GetSelection 2421
+#define wxPrintDialogData_GetToPage 2422
+#define wxPrintDialogData_IsOk 2423
+#define wxPrintDialogData_SetCollate 2424
+#define wxPrintDialogData_SetFromPage 2425
+#define wxPrintDialogData_SetMaxPage 2426
+#define wxPrintDialogData_SetMinPage 2427
+#define wxPrintDialogData_SetNoCopies 2428
+#define wxPrintDialogData_SetPrintData 2429
+#define wxPrintDialogData_SetPrintToFile 2430
+#define wxPrintDialogData_SetSelection 2431
+#define wxPrintDialogData_SetToPage 2432
+#define wxPrintData_new_0 2433
+#define wxPrintData_new_1 2434
+#define wxPrintData_destruct 2435
+#define wxPrintData_GetCollate 2436
+#define wxPrintData_GetBin 2437
+#define wxPrintData_GetColour 2438
+#define wxPrintData_GetDuplex 2439
+#define wxPrintData_GetNoCopies 2440
+#define wxPrintData_GetOrientation 2441
+#define wxPrintData_GetPaperId 2442
+#define wxPrintData_GetPrinterName 2443
+#define wxPrintData_GetQuality 2444
+#define wxPrintData_IsOk 2445
+#define wxPrintData_SetBin 2446
+#define wxPrintData_SetCollate 2447
+#define wxPrintData_SetColour 2448
+#define wxPrintData_SetDuplex 2449
+#define wxPrintData_SetNoCopies 2450
+#define wxPrintData_SetOrientation 2451
+#define wxPrintData_SetPaperId 2452
+#define wxPrintData_SetPrinterName 2453
+#define wxPrintData_SetQuality 2454
+#define wxPrintPreview_new_2 2457
+#define wxPrintPreview_new_3 2458
+#define wxPrintPreview_destruct 2460
+#define wxPrintPreview_GetCanvas 2461
+#define wxPrintPreview_GetCurrentPage 2462
+#define wxPrintPreview_GetFrame 2463
+#define wxPrintPreview_GetMaxPage 2464
+#define wxPrintPreview_GetMinPage 2465
+#define wxPrintPreview_GetPrintout 2466
+#define wxPrintPreview_GetPrintoutForPrinting 2467
+#define wxPrintPreview_IsOk 2468
+#define wxPrintPreview_PaintPage 2469
+#define wxPrintPreview_Print 2470
+#define wxPrintPreview_RenderPage 2471
+#define wxPrintPreview_SetCanvas 2472
+#define wxPrintPreview_SetCurrentPage 2473
+#define wxPrintPreview_SetFrame 2474
+#define wxPrintPreview_SetPrintout 2475
+#define wxPrintPreview_SetZoom 2476
+#define wxPreviewFrame_new 2477
+#define wxPreviewFrame_destruct 2478
+#define wxPreviewFrame_CreateControlBar 2479
+#define wxPreviewFrame_CreateCanvas 2480
+#define wxPreviewFrame_Initialize 2481
+#define wxPreviewFrame_OnCloseWindow 2482
+#define wxPreviewControlBar_new 2483
+#define wxPreviewControlBar_destruct 2484
+#define wxPreviewControlBar_CreateButtons 2485
+#define wxPreviewControlBar_GetPrintPreview 2486
+#define wxPreviewControlBar_GetZoomControl 2487
+#define wxPreviewControlBar_SetZoomControl 2488
+#define wxPrinter_new 2490
+#define wxPrinter_CreateAbortWindow 2491
+#define wxPrinter_GetAbort 2492
+#define wxPrinter_GetLastError 2493
+#define wxPrinter_GetPrintDialogData 2494
+#define wxPrinter_Print 2495
+#define wxPrinter_PrintDialog 2496
+#define wxPrinter_ReportError 2497
+#define wxPrinter_Setup 2498
+#define wxPrinter_destroy 2499
+#define wxXmlResource_new_1 2500
+#define wxXmlResource_new_2 2501
+#define wxXmlResource_destruct 2502
+#define wxXmlResource_AttachUnknownControl 2503
+#define wxXmlResource_ClearHandlers 2504
+#define wxXmlResource_CompareVersion 2505
+#define wxXmlResource_Get 2506
+#define wxXmlResource_GetFlags 2507
+#define wxXmlResource_GetVersion 2508
+#define wxXmlResource_GetXRCID 2509
+#define wxXmlResource_InitAllHandlers 2510
+#define wxXmlResource_Load 2511
+#define wxXmlResource_LoadBitmap 2512
+#define wxXmlResource_LoadDialog_2 2513
+#define wxXmlResource_LoadDialog_3 2514
+#define wxXmlResource_LoadFrame_2 2515
+#define wxXmlResource_LoadFrame_3 2516
+#define wxXmlResource_LoadIcon 2517
+#define wxXmlResource_LoadMenu 2518
+#define wxXmlResource_LoadMenuBar_2 2519
+#define wxXmlResource_LoadMenuBar_1 2520
+#define wxXmlResource_LoadPanel_2 2521
+#define wxXmlResource_LoadPanel_3 2522
+#define wxXmlResource_LoadToolBar 2523
+#define wxXmlResource_Set 2524
+#define wxXmlResource_SetFlags 2525
+#define wxXmlResource_Unload 2526
+#define wxXmlResource_xrcctrl 2527
+#define wxHtmlEasyPrinting_new 2528
+#define wxHtmlEasyPrinting_destruct 2529
+#define wxHtmlEasyPrinting_GetPrintData 2530
+#define wxHtmlEasyPrinting_GetPageSetupData 2531
+#define wxHtmlEasyPrinting_PreviewFile 2532
+#define wxHtmlEasyPrinting_PreviewText 2533
+#define wxHtmlEasyPrinting_PrintFile 2534
+#define wxHtmlEasyPrinting_PrintText 2535
+#define wxHtmlEasyPrinting_PageSetup 2536
+#define wxHtmlEasyPrinting_SetFonts 2537
+#define wxHtmlEasyPrinting_SetHeader 2538
+#define wxHtmlEasyPrinting_SetFooter 2539
+#define wxGLCanvas_new_2 2541
+#define wxGLCanvas_new_3_1 2542
+#define wxGLCanvas_new_3_0 2543
+#define wxGLCanvas_GetContext 2544
+#define wxGLCanvas_SetCurrent 2546
+#define wxGLCanvas_SwapBuffers 2547
+#define wxGLCanvas_destroy 2548
+#define wxAuiManager_new 2549
+#define wxAuiManager_destruct 2550
+#define wxAuiManager_AddPane_2_1 2551
+#define wxAuiManager_AddPane_3 2552
+#define wxAuiManager_AddPane_2_0 2553
+#define wxAuiManager_DetachPane 2554
+#define wxAuiManager_GetAllPanes 2555
+#define wxAuiManager_GetArtProvider 2556
+#define wxAuiManager_GetDockSizeConstraint 2557
+#define wxAuiManager_GetFlags 2558
+#define wxAuiManager_GetManagedWindow 2559
+#define wxAuiManager_GetManager 2560
+#define wxAuiManager_GetPane_1_1 2561
+#define wxAuiManager_GetPane_1_0 2562
+#define wxAuiManager_HideHint 2563
+#define wxAuiManager_InsertPane 2564
+#define wxAuiManager_LoadPaneInfo 2565
+#define wxAuiManager_LoadPerspective 2566
+#define wxAuiManager_SavePaneInfo 2567
+#define wxAuiManager_SavePerspective 2568
+#define wxAuiManager_SetArtProvider 2569
+#define wxAuiManager_SetDockSizeConstraint 2570
+#define wxAuiManager_SetFlags 2571
+#define wxAuiManager_SetManagedWindow 2572
+#define wxAuiManager_ShowHint 2573
+#define wxAuiManager_UnInit 2574
+#define wxAuiManager_Update 2575
+#define wxAuiPaneInfo_new_0 2576
+#define wxAuiPaneInfo_new_1 2577
+#define wxAuiPaneInfo_destruct 2578
+#define wxAuiPaneInfo_BestSize_1 2579
+#define wxAuiPaneInfo_BestSize_2 2580
+#define wxAuiPaneInfo_Bottom 2581
+#define wxAuiPaneInfo_BottomDockable 2582
+#define wxAuiPaneInfo_Caption 2583
+#define wxAuiPaneInfo_CaptionVisible 2584
+#define wxAuiPaneInfo_Centre 2585
+#define wxAuiPaneInfo_CentrePane 2586
+#define wxAuiPaneInfo_CloseButton 2587
+#define wxAuiPaneInfo_DefaultPane 2588
+#define wxAuiPaneInfo_DestroyOnClose 2589
+#define wxAuiPaneInfo_Direction 2590
+#define wxAuiPaneInfo_Dock 2591
+#define wxAuiPaneInfo_Dockable 2592
+#define wxAuiPaneInfo_Fixed 2593
+#define wxAuiPaneInfo_Float 2594
+#define wxAuiPaneInfo_Floatable 2595
+#define wxAuiPaneInfo_FloatingPosition_1 2596
+#define wxAuiPaneInfo_FloatingPosition_2 2597
+#define wxAuiPaneInfo_FloatingSize_1 2598
+#define wxAuiPaneInfo_FloatingSize_2 2599
+#define wxAuiPaneInfo_Gripper 2600
+#define wxAuiPaneInfo_GripperTop 2601
+#define wxAuiPaneInfo_HasBorder 2602
+#define wxAuiPaneInfo_HasCaption 2603
+#define wxAuiPaneInfo_HasCloseButton 2604
+#define wxAuiPaneInfo_HasFlag 2605
+#define wxAuiPaneInfo_HasGripper 2606
+#define wxAuiPaneInfo_HasGripperTop 2607
+#define wxAuiPaneInfo_HasMaximizeButton 2608
+#define wxAuiPaneInfo_HasMinimizeButton 2609
+#define wxAuiPaneInfo_HasPinButton 2610
+#define wxAuiPaneInfo_Hide 2611
+#define wxAuiPaneInfo_IsBottomDockable 2612
+#define wxAuiPaneInfo_IsDocked 2613
+#define wxAuiPaneInfo_IsFixed 2614
+#define wxAuiPaneInfo_IsFloatable 2615
+#define wxAuiPaneInfo_IsFloating 2616
+#define wxAuiPaneInfo_IsLeftDockable 2617
+#define wxAuiPaneInfo_IsMovable 2618
+#define wxAuiPaneInfo_IsOk 2619
+#define wxAuiPaneInfo_IsResizable 2620
+#define wxAuiPaneInfo_IsRightDockable 2621
+#define wxAuiPaneInfo_IsShown 2622
+#define wxAuiPaneInfo_IsToolbar 2623
+#define wxAuiPaneInfo_IsTopDockable 2624
+#define wxAuiPaneInfo_Layer 2625
+#define wxAuiPaneInfo_Left 2626
+#define wxAuiPaneInfo_LeftDockable 2627
+#define wxAuiPaneInfo_MaxSize_1 2628
+#define wxAuiPaneInfo_MaxSize_2 2629
+#define wxAuiPaneInfo_MaximizeButton 2630
+#define wxAuiPaneInfo_MinSize_1 2631
+#define wxAuiPaneInfo_MinSize_2 2632
+#define wxAuiPaneInfo_MinimizeButton 2633
+#define wxAuiPaneInfo_Movable 2634
+#define wxAuiPaneInfo_Name 2635
+#define wxAuiPaneInfo_PaneBorder 2636
+#define wxAuiPaneInfo_PinButton 2637
+#define wxAuiPaneInfo_Position 2638
+#define wxAuiPaneInfo_Resizable 2639
+#define wxAuiPaneInfo_Right 2640
+#define wxAuiPaneInfo_RightDockable 2641
+#define wxAuiPaneInfo_Row 2642
+#define wxAuiPaneInfo_SafeSet 2643
+#define wxAuiPaneInfo_SetFlag 2644
+#define wxAuiPaneInfo_Show 2645
+#define wxAuiPaneInfo_ToolbarPane 2646
+#define wxAuiPaneInfo_Top 2647
+#define wxAuiPaneInfo_TopDockable 2648
+#define wxAuiPaneInfo_Window 2649
+#define wxAuiNotebook_new_0 2650
+#define wxAuiNotebook_new_2 2651
+#define wxAuiNotebook_AddPage 2652
+#define wxAuiNotebook_Create 2653
+#define wxAuiNotebook_DeletePage 2654
+#define wxAuiNotebook_GetArtProvider 2655
+#define wxAuiNotebook_GetPage 2656
+#define wxAuiNotebook_GetPageBitmap 2657
+#define wxAuiNotebook_GetPageCount 2658
+#define wxAuiNotebook_GetPageIndex 2659
+#define wxAuiNotebook_GetPageText 2660
+#define wxAuiNotebook_GetSelection 2661
+#define wxAuiNotebook_InsertPage 2662
+#define wxAuiNotebook_RemovePage 2663
+#define wxAuiNotebook_SetArtProvider 2664
+#define wxAuiNotebook_SetFont 2665
+#define wxAuiNotebook_SetPageBitmap 2666
+#define wxAuiNotebook_SetPageText 2667
+#define wxAuiNotebook_SetSelection 2668
+#define wxAuiNotebook_SetTabCtrlHeight 2669
+#define wxAuiNotebook_SetUniformBitmapSize 2670
+#define wxAuiNotebook_destroy 2671
+#define wxMDIParentFrame_new_0 2672
+#define wxMDIParentFrame_new_4 2673
+#define wxMDIParentFrame_destruct 2674
+#define wxMDIParentFrame_ActivateNext 2675
+#define wxMDIParentFrame_ActivatePrevious 2676
+#define wxMDIParentFrame_ArrangeIcons 2677
+#define wxMDIParentFrame_Cascade 2678
+#define wxMDIParentFrame_Create 2679
+#define wxMDIParentFrame_GetActiveChild 2680
+#define wxMDIParentFrame_GetClientWindow 2681
+#define wxMDIParentFrame_Tile 2682
+#define wxMDIChildFrame_new_0 2683
+#define wxMDIChildFrame_new_4 2684
+#define wxMDIChildFrame_destruct 2685
+#define wxMDIChildFrame_Activate 2686
+#define wxMDIChildFrame_Create 2687
+#define wxMDIChildFrame_Maximize 2688
+#define wxMDIChildFrame_Restore 2689
+#define wxMDIClientWindow_new_0 2690
+#define wxMDIClientWindow_new_2 2691
+#define wxMDIClientWindow_destruct 2692
+#define wxMDIClientWindow_CreateClient 2693
+#define wxLayoutAlgorithm_new 2694
+#define wxLayoutAlgorithm_LayoutFrame 2695
+#define wxLayoutAlgorithm_LayoutMDIFrame 2696
+#define wxLayoutAlgorithm_LayoutWindow 2697
+#define wxLayoutAlgorithm_destroy 2698
+#define wxEvent_GetId 2699
+#define wxEvent_GetSkipped 2700
+#define wxEvent_GetTimestamp 2701
+#define wxEvent_IsCommandEvent 2702
+#define wxEvent_ResumePropagation 2703
+#define wxEvent_ShouldPropagate 2704
+#define wxEvent_Skip 2705
+#define wxEvent_StopPropagation 2706
+#define wxCommandEvent_getClientData 2707
+#define wxCommandEvent_GetExtraLong 2708
+#define wxCommandEvent_GetInt 2709
+#define wxCommandEvent_GetSelection 2710
+#define wxCommandEvent_GetString 2711
+#define wxCommandEvent_IsChecked 2712
+#define wxCommandEvent_IsSelection 2713
+#define wxCommandEvent_SetInt 2714
+#define wxCommandEvent_SetString 2715
+#define wxScrollEvent_GetOrientation 2716
+#define wxScrollEvent_GetPosition 2717
+#define wxScrollWinEvent_GetOrientation 2718
+#define wxScrollWinEvent_GetPosition 2719
+#define wxMouseEvent_AltDown 2720
+#define wxMouseEvent_Button 2721
+#define wxMouseEvent_ButtonDClick 2722
+#define wxMouseEvent_ButtonDown 2723
+#define wxMouseEvent_ButtonUp 2724
+#define wxMouseEvent_CmdDown 2725
+#define wxMouseEvent_ControlDown 2726
+#define wxMouseEvent_Dragging 2727
+#define wxMouseEvent_Entering 2728
+#define wxMouseEvent_GetButton 2729
+#define wxMouseEvent_GetPosition 2732
+#define wxMouseEvent_GetLogicalPosition 2733
+#define wxMouseEvent_GetLinesPerAction 2734
+#define wxMouseEvent_GetWheelRotation 2735
+#define wxMouseEvent_GetWheelDelta 2736
+#define wxMouseEvent_GetX 2737
+#define wxMouseEvent_GetY 2738
+#define wxMouseEvent_IsButton 2739
+#define wxMouseEvent_IsPageScroll 2740
+#define wxMouseEvent_Leaving 2741
+#define wxMouseEvent_LeftDClick 2742
+#define wxMouseEvent_LeftDown 2743
+#define wxMouseEvent_LeftIsDown 2744
+#define wxMouseEvent_LeftUp 2745
+#define wxMouseEvent_MetaDown 2746
+#define wxMouseEvent_MiddleDClick 2747
+#define wxMouseEvent_MiddleDown 2748
+#define wxMouseEvent_MiddleIsDown 2749
+#define wxMouseEvent_MiddleUp 2750
+#define wxMouseEvent_Moving 2751
+#define wxMouseEvent_RightDClick 2752
+#define wxMouseEvent_RightDown 2753
+#define wxMouseEvent_RightIsDown 2754
+#define wxMouseEvent_RightUp 2755
+#define wxMouseEvent_ShiftDown 2756
+#define wxSetCursorEvent_GetCursor 2757
+#define wxSetCursorEvent_GetX 2758
+#define wxSetCursorEvent_GetY 2759
+#define wxSetCursorEvent_HasCursor 2760
+#define wxSetCursorEvent_SetCursor 2761
+#define wxKeyEvent_AltDown 2762
+#define wxKeyEvent_CmdDown 2763
+#define wxKeyEvent_ControlDown 2764
+#define wxKeyEvent_GetKeyCode 2765
+#define wxKeyEvent_GetModifiers 2766
+#define wxKeyEvent_GetPosition 2769
+#define wxKeyEvent_GetRawKeyCode 2770
+#define wxKeyEvent_GetRawKeyFlags 2771
+#define wxKeyEvent_GetUnicodeKey 2772
+#define wxKeyEvent_GetX 2773
+#define wxKeyEvent_GetY 2774
+#define wxKeyEvent_HasModifiers 2775
+#define wxKeyEvent_MetaDown 2776
+#define wxKeyEvent_ShiftDown 2777
+#define wxSizeEvent_GetSize 2778
+#define wxMoveEvent_GetPosition 2779
+#define wxEraseEvent_GetDC 2780
+#define wxFocusEvent_GetWindow 2781
+#define wxChildFocusEvent_GetWindow 2782
+#define wxMenuEvent_GetMenu 2783
+#define wxMenuEvent_GetMenuId 2784
+#define wxMenuEvent_IsPopup 2785
+#define wxCloseEvent_CanVeto 2786
+#define wxCloseEvent_GetLoggingOff 2787
+#define wxCloseEvent_SetCanVeto 2788
+#define wxCloseEvent_SetLoggingOff 2789
+#define wxCloseEvent_Veto 2790
+#define wxShowEvent_SetShow 2791
+#define wxShowEvent_GetShow 2792
+#define wxIconizeEvent_Iconized 2793
+#define wxJoystickEvent_ButtonDown 2794
+#define wxJoystickEvent_ButtonIsDown 2795
+#define wxJoystickEvent_ButtonUp 2796
+#define wxJoystickEvent_GetButtonChange 2797
+#define wxJoystickEvent_GetButtonState 2798
+#define wxJoystickEvent_GetJoystick 2799
+#define wxJoystickEvent_GetPosition 2800
+#define wxJoystickEvent_GetZPosition 2801
+#define wxJoystickEvent_IsButton 2802
+#define wxJoystickEvent_IsMove 2803
+#define wxJoystickEvent_IsZMove 2804
+#define wxUpdateUIEvent_CanUpdate 2805
+#define wxUpdateUIEvent_Check 2806
+#define wxUpdateUIEvent_Enable 2807
+#define wxUpdateUIEvent_Show 2808
+#define wxUpdateUIEvent_GetChecked 2809
+#define wxUpdateUIEvent_GetEnabled 2810
+#define wxUpdateUIEvent_GetShown 2811
+#define wxUpdateUIEvent_GetSetChecked 2812
+#define wxUpdateUIEvent_GetSetEnabled 2813
+#define wxUpdateUIEvent_GetSetShown 2814
+#define wxUpdateUIEvent_GetSetText 2815
+#define wxUpdateUIEvent_GetText 2816
+#define wxUpdateUIEvent_GetMode 2817
+#define wxUpdateUIEvent_GetUpdateInterval 2818
+#define wxUpdateUIEvent_ResetUpdateTime 2819
+#define wxUpdateUIEvent_SetMode 2820
+#define wxUpdateUIEvent_SetText 2821
+#define wxUpdateUIEvent_SetUpdateInterval 2822
+#define wxMouseCaptureChangedEvent_GetCapturedWindow 2823
+#define wxPaletteChangedEvent_SetChangedWindow 2824
+#define wxPaletteChangedEvent_GetChangedWindow 2825
+#define wxQueryNewPaletteEvent_SetPaletteRealized 2826
+#define wxQueryNewPaletteEvent_GetPaletteRealized 2827
+#define wxNavigationKeyEvent_GetDirection 2828
+#define wxNavigationKeyEvent_SetDirection 2829
+#define wxNavigationKeyEvent_IsWindowChange 2830
+#define wxNavigationKeyEvent_SetWindowChange 2831
+#define wxNavigationKeyEvent_IsFromTab 2832
+#define wxNavigationKeyEvent_SetFromTab 2833
+#define wxNavigationKeyEvent_GetCurrentFocus 2834
+#define wxNavigationKeyEvent_SetCurrentFocus 2835
+#define wxHelpEvent_GetOrigin 2836
+#define wxHelpEvent_GetPosition 2837
+#define wxHelpEvent_SetOrigin 2838
+#define wxHelpEvent_SetPosition 2839
+#define wxContextMenuEvent_GetPosition 2840
+#define wxContextMenuEvent_SetPosition 2841
+#define wxIdleEvent_CanSend 2842
+#define wxIdleEvent_GetMode 2843
+#define wxIdleEvent_RequestMore 2844
+#define wxIdleEvent_MoreRequested 2845
+#define wxIdleEvent_SetMode 2846
+#define wxGridEvent_AltDown 2847
+#define wxGridEvent_ControlDown 2848
+#define wxGridEvent_GetCol 2849
+#define wxGridEvent_GetPosition 2850
+#define wxGridEvent_GetRow 2851
+#define wxGridEvent_MetaDown 2852
+#define wxGridEvent_Selecting 2853
+#define wxGridEvent_ShiftDown 2854
+#define wxNotifyEvent_Allow 2855
+#define wxNotifyEvent_IsAllowed 2856
+#define wxNotifyEvent_Veto 2857
+#define wxSashEvent_GetEdge 2858
+#define wxSashEvent_GetDragRect 2859
+#define wxSashEvent_GetDragStatus 2860
+#define wxListEvent_GetCacheFrom 2861
+#define wxListEvent_GetCacheTo 2862
+#define wxListEvent_GetKeyCode 2863
+#define wxListEvent_GetIndex 2864
+#define wxListEvent_GetColumn 2865
+#define wxListEvent_GetPoint 2866
+#define wxListEvent_GetLabel 2867
+#define wxListEvent_GetText 2868
+#define wxListEvent_GetImage 2869
+#define wxListEvent_GetData 2870
+#define wxListEvent_GetMask 2871
+#define wxListEvent_GetItem 2872
+#define wxListEvent_IsEditCancelled 2873
+#define wxDateEvent_GetDate 2874
+#define wxCalendarEvent_GetWeekDay 2875
+#define wxFileDirPickerEvent_GetPath 2876
+#define wxColourPickerEvent_GetColour 2877
+#define wxFontPickerEvent_GetFont 2878
+#define wxStyledTextEvent_GetPosition 2879
+#define wxStyledTextEvent_GetKey 2880
+#define wxStyledTextEvent_GetModifiers 2881
+#define wxStyledTextEvent_GetModificationType 2882
+#define wxStyledTextEvent_GetText 2883
+#define wxStyledTextEvent_GetLength 2884
+#define wxStyledTextEvent_GetLinesAdded 2885
+#define wxStyledTextEvent_GetLine 2886
+#define wxStyledTextEvent_GetFoldLevelNow 2887
+#define wxStyledTextEvent_GetFoldLevelPrev 2888
+#define wxStyledTextEvent_GetMargin 2889
+#define wxStyledTextEvent_GetMessage 2890
+#define wxStyledTextEvent_GetWParam 2891
+#define wxStyledTextEvent_GetLParam 2892
+#define wxStyledTextEvent_GetListType 2893
+#define wxStyledTextEvent_GetX 2894
+#define wxStyledTextEvent_GetY 2895
+#define wxStyledTextEvent_GetDragText 2896
+#define wxStyledTextEvent_GetDragAllowMove 2897
+#define wxStyledTextEvent_GetDragResult 2898
+#define wxStyledTextEvent_GetShift 2899
+#define wxStyledTextEvent_GetControl 2900
+#define wxStyledTextEvent_GetAlt 2901
+#define utils_wxGetKeyState 2902
+#define utils_wxGetMousePosition 2903
+#define utils_wxGetMouseState 2904
+#define utils_wxSetDetectableAutoRepeat 2905
+#define utils_wxBell 2906
+#define utils_wxFindMenuItemId 2907
+#define utils_wxGenericFindWindowAtPoint 2908
+#define utils_wxFindWindowAtPoint 2909
+#define utils_wxBeginBusyCursor 2910
+#define utils_wxEndBusyCursor 2911
+#define utils_wxIsBusy 2912
+#define utils_wxShutdown 2913
+#define utils_wxShell 2914
+#define utils_wxLaunchDefaultBrowser 2915
+#define utils_wxGetEmailAddress 2916
+#define utils_wxGetUserId 2917
+#define utils_wxGetHomeDir 2918
+#define utils_wxNewId 2919
+#define utils_wxRegisterId 2920
+#define utils_wxGetCurrentId 2921
+#define utils_wxGetOsDescription 2922
+#define utils_wxIsPlatformLittleEndian 2923
+#define utils_wxIsPlatform64Bit 2924
+#define wxPrintout_new 2925
+#define wxPrintout_destruct 2926
+#define wxPrintout_GetDC 2927
+#define wxPrintout_GetPageSizeMM 2928
+#define wxPrintout_GetPageSizePixels 2929
+#define wxPrintout_GetPaperRectPixels 2930
+#define wxPrintout_GetPPIPrinter 2931
+#define wxPrintout_GetPPIScreen 2932
+#define wxPrintout_GetTitle 2933
+#define wxPrintout_IsPreview 2934
+#define wxPrintout_FitThisSizeToPaper 2935
+#define wxPrintout_FitThisSizeToPage 2936
+#define wxPrintout_FitThisSizeToPageMargins 2937
+#define wxPrintout_MapScreenSizeToPaper 2938
+#define wxPrintout_MapScreenSizeToPage 2939
+#define wxPrintout_MapScreenSizeToPageMargins 2940
+#define wxPrintout_MapScreenSizeToDevice 2941
+#define wxPrintout_GetLogicalPaperRect 2942
+#define wxPrintout_GetLogicalPageRect 2943
+#define wxPrintout_GetLogicalPageMarginsRect 2944
+#define wxPrintout_SetLogicalOrigin 2945
+#define wxPrintout_OffsetLogicalOrigin 2946
+#define wxStyledTextCtrl_new_2 2947
+#define wxStyledTextCtrl_new_0 2948
+#define wxStyledTextCtrl_destruct 2949
+#define wxStyledTextCtrl_Create 2950
+#define wxStyledTextCtrl_AddText 2951
+#define wxStyledTextCtrl_AddStyledText 2952
+#define wxStyledTextCtrl_InsertText 2953
+#define wxStyledTextCtrl_ClearAll 2954
+#define wxStyledTextCtrl_ClearDocumentStyle 2955
+#define wxStyledTextCtrl_GetLength 2956
+#define wxStyledTextCtrl_GetCharAt 2957
+#define wxStyledTextCtrl_GetCurrentPos 2958
+#define wxStyledTextCtrl_GetAnchor 2959
+#define wxStyledTextCtrl_GetStyleAt 2960
+#define wxStyledTextCtrl_Redo 2961
+#define wxStyledTextCtrl_SetUndoCollection 2962
+#define wxStyledTextCtrl_SelectAll 2963
+#define wxStyledTextCtrl_SetSavePoint 2964
+#define wxStyledTextCtrl_GetStyledText 2965
+#define wxStyledTextCtrl_CanRedo 2966
+#define wxStyledTextCtrl_MarkerLineFromHandle 2967
+#define wxStyledTextCtrl_MarkerDeleteHandle 2968
+#define wxStyledTextCtrl_GetUndoCollection 2969
+#define wxStyledTextCtrl_GetViewWhiteSpace 2970
+#define wxStyledTextCtrl_SetViewWhiteSpace 2971
+#define wxStyledTextCtrl_PositionFromPoint 2972
+#define wxStyledTextCtrl_PositionFromPointClose 2973
+#define wxStyledTextCtrl_GotoLine 2974
+#define wxStyledTextCtrl_GotoPos 2975
+#define wxStyledTextCtrl_SetAnchor 2976
+#define wxStyledTextCtrl_GetCurLine 2977
+#define wxStyledTextCtrl_GetEndStyled 2978
+#define wxStyledTextCtrl_ConvertEOLs 2979
+#define wxStyledTextCtrl_GetEOLMode 2980
+#define wxStyledTextCtrl_SetEOLMode 2981
+#define wxStyledTextCtrl_StartStyling 2982
+#define wxStyledTextCtrl_SetStyling 2983
+#define wxStyledTextCtrl_GetBufferedDraw 2984
+#define wxStyledTextCtrl_SetBufferedDraw 2985
+#define wxStyledTextCtrl_SetTabWidth 2986
+#define wxStyledTextCtrl_GetTabWidth 2987
+#define wxStyledTextCtrl_SetCodePage 2988
+#define wxStyledTextCtrl_MarkerDefine 2989
+#define wxStyledTextCtrl_MarkerSetForeground 2990
+#define wxStyledTextCtrl_MarkerSetBackground 2991
+#define wxStyledTextCtrl_MarkerAdd 2992
+#define wxStyledTextCtrl_MarkerDelete 2993
+#define wxStyledTextCtrl_MarkerDeleteAll 2994
+#define wxStyledTextCtrl_MarkerGet 2995
+#define wxStyledTextCtrl_MarkerNext 2996
+#define wxStyledTextCtrl_MarkerPrevious 2997
+#define wxStyledTextCtrl_MarkerDefineBitmap 2998
+#define wxStyledTextCtrl_MarkerAddSet 2999
+#define wxStyledTextCtrl_MarkerSetAlpha 3000
+#define wxStyledTextCtrl_SetMarginType 3001
+#define wxStyledTextCtrl_GetMarginType 3002
+#define wxStyledTextCtrl_SetMarginWidth 3003
+#define wxStyledTextCtrl_GetMarginWidth 3004
+#define wxStyledTextCtrl_SetMarginMask 3005
+#define wxStyledTextCtrl_GetMarginMask 3006
+#define wxStyledTextCtrl_SetMarginSensitive 3007
+#define wxStyledTextCtrl_GetMarginSensitive 3008
+#define wxStyledTextCtrl_StyleClearAll 3009
+#define wxStyledTextCtrl_StyleSetForeground 3010
+#define wxStyledTextCtrl_StyleSetBackground 3011
+#define wxStyledTextCtrl_StyleSetBold 3012
+#define wxStyledTextCtrl_StyleSetItalic 3013
+#define wxStyledTextCtrl_StyleSetSize 3014
+#define wxStyledTextCtrl_StyleSetFaceName 3015
+#define wxStyledTextCtrl_StyleSetEOLFilled 3016
+#define wxStyledTextCtrl_StyleResetDefault 3017
+#define wxStyledTextCtrl_StyleSetUnderline 3018
+#define wxStyledTextCtrl_StyleSetCase 3019
+#define wxStyledTextCtrl_StyleSetHotSpot 3020
+#define wxStyledTextCtrl_SetSelForeground 3021
+#define wxStyledTextCtrl_SetSelBackground 3022
+#define wxStyledTextCtrl_GetSelAlpha 3023
+#define wxStyledTextCtrl_SetSelAlpha 3024
+#define wxStyledTextCtrl_SetCaretForeground 3025
+#define wxStyledTextCtrl_CmdKeyAssign 3026
+#define wxStyledTextCtrl_CmdKeyClear 3027
+#define wxStyledTextCtrl_CmdKeyClearAll 3028
+#define wxStyledTextCtrl_SetStyleBytes 3029
+#define wxStyledTextCtrl_StyleSetVisible 3030
+#define wxStyledTextCtrl_GetCaretPeriod 3031
+#define wxStyledTextCtrl_SetCaretPeriod 3032
+#define wxStyledTextCtrl_SetWordChars 3033
+#define wxStyledTextCtrl_BeginUndoAction 3034
+#define wxStyledTextCtrl_EndUndoAction 3035
+#define wxStyledTextCtrl_IndicatorSetStyle 3036
+#define wxStyledTextCtrl_IndicatorGetStyle 3037
+#define wxStyledTextCtrl_IndicatorSetForeground 3038
+#define wxStyledTextCtrl_IndicatorGetForeground 3039
+#define wxStyledTextCtrl_SetWhitespaceForeground 3040
+#define wxStyledTextCtrl_SetWhitespaceBackground 3041
+#define wxStyledTextCtrl_GetStyleBits 3042
+#define wxStyledTextCtrl_SetLineState 3043
+#define wxStyledTextCtrl_GetLineState 3044
+#define wxStyledTextCtrl_GetMaxLineState 3045
+#define wxStyledTextCtrl_GetCaretLineVisible 3046
+#define wxStyledTextCtrl_SetCaretLineVisible 3047
+#define wxStyledTextCtrl_GetCaretLineBackground 3048
+#define wxStyledTextCtrl_SetCaretLineBackground 3049
+#define wxStyledTextCtrl_AutoCompShow 3050
+#define wxStyledTextCtrl_AutoCompCancel 3051
+#define wxStyledTextCtrl_AutoCompActive 3052
+#define wxStyledTextCtrl_AutoCompPosStart 3053
+#define wxStyledTextCtrl_AutoCompComplete 3054
+#define wxStyledTextCtrl_AutoCompStops 3055
+#define wxStyledTextCtrl_AutoCompSetSeparator 3056
+#define wxStyledTextCtrl_AutoCompGetSeparator 3057
+#define wxStyledTextCtrl_AutoCompSelect 3058
+#define wxStyledTextCtrl_AutoCompSetCancelAtStart 3059
+#define wxStyledTextCtrl_AutoCompGetCancelAtStart 3060
+#define wxStyledTextCtrl_AutoCompSetFillUps 3061
+#define wxStyledTextCtrl_AutoCompSetChooseSingle 3062
+#define wxStyledTextCtrl_AutoCompGetChooseSingle 3063
+#define wxStyledTextCtrl_AutoCompSetIgnoreCase 3064
+#define wxStyledTextCtrl_AutoCompGetIgnoreCase 3065
+#define wxStyledTextCtrl_UserListShow 3066
+#define wxStyledTextCtrl_AutoCompSetAutoHide 3067
+#define wxStyledTextCtrl_AutoCompGetAutoHide 3068
+#define wxStyledTextCtrl_AutoCompSetDropRestOfWord 3069
+#define wxStyledTextCtrl_AutoCompGetDropRestOfWord 3070
+#define wxStyledTextCtrl_RegisterImage 3071
+#define wxStyledTextCtrl_ClearRegisteredImages 3072
+#define wxStyledTextCtrl_AutoCompGetTypeSeparator 3073
+#define wxStyledTextCtrl_AutoCompSetTypeSeparator 3074
+#define wxStyledTextCtrl_AutoCompSetMaxWidth 3075
+#define wxStyledTextCtrl_AutoCompGetMaxWidth 3076
+#define wxStyledTextCtrl_AutoCompSetMaxHeight 3077
+#define wxStyledTextCtrl_AutoCompGetMaxHeight 3078
+#define wxStyledTextCtrl_SetIndent 3079
+#define wxStyledTextCtrl_GetIndent 3080
+#define wxStyledTextCtrl_SetUseTabs 3081
+#define wxStyledTextCtrl_GetUseTabs 3082
+#define wxStyledTextCtrl_SetLineIndentation 3083
+#define wxStyledTextCtrl_GetLineIndentation 3084
+#define wxStyledTextCtrl_GetLineIndentPosition 3085
+#define wxStyledTextCtrl_GetColumn 3086
+#define wxStyledTextCtrl_SetUseHorizontalScrollBar 3087
+#define wxStyledTextCtrl_GetUseHorizontalScrollBar 3088
+#define wxStyledTextCtrl_SetIndentationGuides 3089
+#define wxStyledTextCtrl_GetIndentationGuides 3090
+#define wxStyledTextCtrl_SetHighlightGuide 3091
+#define wxStyledTextCtrl_GetHighlightGuide 3092
+#define wxStyledTextCtrl_GetLineEndPosition 3093
+#define wxStyledTextCtrl_GetCodePage 3094
+#define wxStyledTextCtrl_GetCaretForeground 3095
+#define wxStyledTextCtrl_GetReadOnly 3096
+#define wxStyledTextCtrl_SetCurrentPos 3097
+#define wxStyledTextCtrl_SetSelectionStart 3098
+#define wxStyledTextCtrl_GetSelectionStart 3099
+#define wxStyledTextCtrl_SetSelectionEnd 3100
+#define wxStyledTextCtrl_GetSelectionEnd 3101
+#define wxStyledTextCtrl_SetPrintMagnification 3102
+#define wxStyledTextCtrl_GetPrintMagnification 3103
+#define wxStyledTextCtrl_SetPrintColourMode 3104
+#define wxStyledTextCtrl_GetPrintColourMode 3105
+#define wxStyledTextCtrl_FindText 3106
+#define wxStyledTextCtrl_FormatRange 3107
+#define wxStyledTextCtrl_GetFirstVisibleLine 3108
+#define wxStyledTextCtrl_GetLine 3109
+#define wxStyledTextCtrl_GetLineCount 3110
+#define wxStyledTextCtrl_SetMarginLeft 3111
+#define wxStyledTextCtrl_GetMarginLeft 3112
+#define wxStyledTextCtrl_SetMarginRight 3113
+#define wxStyledTextCtrl_GetMarginRight 3114
+#define wxStyledTextCtrl_GetModify 3115
+#define wxStyledTextCtrl_SetSelection 3116
+#define wxStyledTextCtrl_GetSelectedText 3117
+#define wxStyledTextCtrl_GetTextRange 3118
+#define wxStyledTextCtrl_HideSelection 3119
+#define wxStyledTextCtrl_LineFromPosition 3120
+#define wxStyledTextCtrl_PositionFromLine 3121
+#define wxStyledTextCtrl_LineScroll 3122
+#define wxStyledTextCtrl_EnsureCaretVisible 3123
+#define wxStyledTextCtrl_ReplaceSelection 3124
+#define wxStyledTextCtrl_SetReadOnly 3125
+#define wxStyledTextCtrl_CanPaste 3126
+#define wxStyledTextCtrl_CanUndo 3127
+#define wxStyledTextCtrl_EmptyUndoBuffer 3128
+#define wxStyledTextCtrl_Undo 3129
+#define wxStyledTextCtrl_Cut 3130
+#define wxStyledTextCtrl_Copy 3131
+#define wxStyledTextCtrl_Paste 3132
+#define wxStyledTextCtrl_Clear 3133
+#define wxStyledTextCtrl_SetText 3134
+#define wxStyledTextCtrl_GetText 3135
+#define wxStyledTextCtrl_GetTextLength 3136
+#define wxStyledTextCtrl_GetOvertype 3137
+#define wxStyledTextCtrl_SetCaretWidth 3138
+#define wxStyledTextCtrl_GetCaretWidth 3139
+#define wxStyledTextCtrl_SetTargetStart 3140
+#define wxStyledTextCtrl_GetTargetStart 3141
+#define wxStyledTextCtrl_SetTargetEnd 3142
+#define wxStyledTextCtrl_GetTargetEnd 3143
+#define wxStyledTextCtrl_ReplaceTarget 3144
+#define wxStyledTextCtrl_SearchInTarget 3145
+#define wxStyledTextCtrl_SetSearchFlags 3146
+#define wxStyledTextCtrl_GetSearchFlags 3147
+#define wxStyledTextCtrl_CallTipShow 3148
+#define wxStyledTextCtrl_CallTipCancel 3149
+#define wxStyledTextCtrl_CallTipActive 3150
+#define wxStyledTextCtrl_CallTipPosAtStart 3151
+#define wxStyledTextCtrl_CallTipSetHighlight 3152
+#define wxStyledTextCtrl_CallTipSetBackground 3153
+#define wxStyledTextCtrl_CallTipSetForeground 3154
+#define wxStyledTextCtrl_CallTipSetForegroundHighlight 3155
+#define wxStyledTextCtrl_CallTipUseStyle 3156
+#define wxStyledTextCtrl_VisibleFromDocLine 3157
+#define wxStyledTextCtrl_DocLineFromVisible 3158
+#define wxStyledTextCtrl_WrapCount 3159
+#define wxStyledTextCtrl_SetFoldLevel 3160
+#define wxStyledTextCtrl_GetFoldLevel 3161
+#define wxStyledTextCtrl_GetLastChild 3162
+#define wxStyledTextCtrl_GetFoldParent 3163
+#define wxStyledTextCtrl_ShowLines 3164
+#define wxStyledTextCtrl_HideLines 3165
+#define wxStyledTextCtrl_GetLineVisible 3166
+#define wxStyledTextCtrl_SetFoldExpanded 3167
+#define wxStyledTextCtrl_GetFoldExpanded 3168
+#define wxStyledTextCtrl_ToggleFold 3169
+#define wxStyledTextCtrl_EnsureVisible 3170
+#define wxStyledTextCtrl_SetFoldFlags 3171
+#define wxStyledTextCtrl_EnsureVisibleEnforcePolicy 3172
+#define wxStyledTextCtrl_SetTabIndents 3173
+#define wxStyledTextCtrl_GetTabIndents 3174
+#define wxStyledTextCtrl_SetBackSpaceUnIndents 3175
+#define wxStyledTextCtrl_GetBackSpaceUnIndents 3176
+#define wxStyledTextCtrl_SetMouseDwellTime 3177
+#define wxStyledTextCtrl_GetMouseDwellTime 3178
+#define wxStyledTextCtrl_WordStartPosition 3179
+#define wxStyledTextCtrl_WordEndPosition 3180
+#define wxStyledTextCtrl_SetWrapMode 3181
+#define wxStyledTextCtrl_GetWrapMode 3182
+#define wxStyledTextCtrl_SetWrapVisualFlags 3183
+#define wxStyledTextCtrl_GetWrapVisualFlags 3184
+#define wxStyledTextCtrl_SetWrapVisualFlagsLocation 3185
+#define wxStyledTextCtrl_GetWrapVisualFlagsLocation 3186
+#define wxStyledTextCtrl_SetWrapStartIndent 3187
+#define wxStyledTextCtrl_GetWrapStartIndent 3188
+#define wxStyledTextCtrl_SetLayoutCache 3189
+#define wxStyledTextCtrl_GetLayoutCache 3190
+#define wxStyledTextCtrl_SetScrollWidth 3191
+#define wxStyledTextCtrl_GetScrollWidth 3192
+#define wxStyledTextCtrl_TextWidth 3193
+#define wxStyledTextCtrl_GetEndAtLastLine 3194
+#define wxStyledTextCtrl_TextHeight 3195
+#define wxStyledTextCtrl_SetUseVerticalScrollBar 3196
+#define wxStyledTextCtrl_GetUseVerticalScrollBar 3197
+#define wxStyledTextCtrl_AppendText 3198
+#define wxStyledTextCtrl_GetTwoPhaseDraw 3199
+#define wxStyledTextCtrl_SetTwoPhaseDraw 3200
+#define wxStyledTextCtrl_TargetFromSelection 3201
+#define wxStyledTextCtrl_LinesJoin 3202
+#define wxStyledTextCtrl_LinesSplit 3203
+#define wxStyledTextCtrl_SetFoldMarginColour 3204
+#define wxStyledTextCtrl_SetFoldMarginHiColour 3205
+#define wxStyledTextCtrl_LineDown 3206
+#define wxStyledTextCtrl_LineDownExtend 3207
+#define wxStyledTextCtrl_LineUp 3208
+#define wxStyledTextCtrl_LineUpExtend 3209
+#define wxStyledTextCtrl_CharLeft 3210
+#define wxStyledTextCtrl_CharLeftExtend 3211
+#define wxStyledTextCtrl_CharRight 3212
+#define wxStyledTextCtrl_CharRightExtend 3213
+#define wxStyledTextCtrl_WordLeft 3214
+#define wxStyledTextCtrl_WordLeftExtend 3215
+#define wxStyledTextCtrl_WordRight 3216
+#define wxStyledTextCtrl_WordRightExtend 3217
+#define wxStyledTextCtrl_Home 3218
+#define wxStyledTextCtrl_HomeExtend 3219
+#define wxStyledTextCtrl_LineEnd 3220
+#define wxStyledTextCtrl_LineEndExtend 3221
+#define wxStyledTextCtrl_DocumentStart 3222
+#define wxStyledTextCtrl_DocumentStartExtend 3223
+#define wxStyledTextCtrl_DocumentEnd 3224
+#define wxStyledTextCtrl_DocumentEndExtend 3225
+#define wxStyledTextCtrl_PageUp 3226
+#define wxStyledTextCtrl_PageUpExtend 3227
+#define wxStyledTextCtrl_PageDown 3228
+#define wxStyledTextCtrl_PageDownExtend 3229
+#define wxStyledTextCtrl_EditToggleOvertype 3230
+#define wxStyledTextCtrl_Cancel 3231
+#define wxStyledTextCtrl_DeleteBack 3232
+#define wxStyledTextCtrl_Tab 3233
+#define wxStyledTextCtrl_BackTab 3234
+#define wxStyledTextCtrl_NewLine 3235
+#define wxStyledTextCtrl_FormFeed 3236
+#define wxStyledTextCtrl_VCHome 3237
+#define wxStyledTextCtrl_VCHomeExtend 3238
+#define wxStyledTextCtrl_ZoomIn 3239
+#define wxStyledTextCtrl_ZoomOut 3240
+#define wxStyledTextCtrl_DelWordLeft 3241
+#define wxStyledTextCtrl_DelWordRight 3242
+#define wxStyledTextCtrl_LineCut 3243
+#define wxStyledTextCtrl_LineDelete 3244
+#define wxStyledTextCtrl_LineTranspose 3245
+#define wxStyledTextCtrl_LineDuplicate 3246
+#define wxStyledTextCtrl_LowerCase 3247
+#define wxStyledTextCtrl_UpperCase 3248
+#define wxStyledTextCtrl_LineScrollDown 3249
+#define wxStyledTextCtrl_LineScrollUp 3250
+#define wxStyledTextCtrl_DeleteBackNotLine 3251
+#define wxStyledTextCtrl_HomeDisplay 3252
+#define wxStyledTextCtrl_HomeDisplayExtend 3253
+#define wxStyledTextCtrl_LineEndDisplay 3254
+#define wxStyledTextCtrl_LineEndDisplayExtend 3255
+#define wxStyledTextCtrl_HomeWrapExtend 3256
+#define wxStyledTextCtrl_LineEndWrap 3257
+#define wxStyledTextCtrl_LineEndWrapExtend 3258
+#define wxStyledTextCtrl_VCHomeWrap 3259
+#define wxStyledTextCtrl_VCHomeWrapExtend 3260
+#define wxStyledTextCtrl_LineCopy 3261
+#define wxStyledTextCtrl_MoveCaretInsideView 3262
+#define wxStyledTextCtrl_LineLength 3263
+#define wxStyledTextCtrl_BraceHighlight 3264
+#define wxStyledTextCtrl_BraceBadLight 3265
+#define wxStyledTextCtrl_BraceMatch 3266
+#define wxStyledTextCtrl_GetViewEOL 3267
+#define wxStyledTextCtrl_SetViewEOL 3268
+#define wxStyledTextCtrl_SetModEventMask 3269
+#define wxStyledTextCtrl_GetEdgeColumn 3270
+#define wxStyledTextCtrl_SetEdgeColumn 3271
+#define wxStyledTextCtrl_GetEdgeMode 3272
+#define wxStyledTextCtrl_GetEdgeColour 3273
+#define wxStyledTextCtrl_SetEdgeColour 3274
+#define wxStyledTextCtrl_SearchAnchor 3275
+#define wxStyledTextCtrl_SearchNext 3276
+#define wxStyledTextCtrl_SearchPrev 3277
+#define wxStyledTextCtrl_LinesOnScreen 3278
+#define wxStyledTextCtrl_UsePopUp 3279
+#define wxStyledTextCtrl_SelectionIsRectangle 3280
+#define wxStyledTextCtrl_SetZoom 3281
+#define wxStyledTextCtrl_GetZoom 3282
+#define wxStyledTextCtrl_GetModEventMask 3283
+#define wxStyledTextCtrl_SetSTCFocus 3284
+#define wxStyledTextCtrl_GetSTCFocus 3285
+#define wxStyledTextCtrl_SetStatus 3286
+#define wxStyledTextCtrl_GetStatus 3287
+#define wxStyledTextCtrl_SetMouseDownCaptures 3288
+#define wxStyledTextCtrl_GetMouseDownCaptures 3289
+#define wxStyledTextCtrl_SetSTCCursor 3290
+#define wxStyledTextCtrl_GetSTCCursor 3291
+#define wxStyledTextCtrl_SetControlCharSymbol 3292
+#define wxStyledTextCtrl_GetControlCharSymbol 3293
+#define wxStyledTextCtrl_WordPartLeft 3294
+#define wxStyledTextCtrl_WordPartLeftExtend 3295
+#define wxStyledTextCtrl_WordPartRight 3296
+#define wxStyledTextCtrl_WordPartRightExtend 3297
+#define wxStyledTextCtrl_SetVisiblePolicy 3298
+#define wxStyledTextCtrl_DelLineLeft 3299
+#define wxStyledTextCtrl_DelLineRight 3300
+#define wxStyledTextCtrl_GetXOffset 3301
+#define wxStyledTextCtrl_ChooseCaretX 3302
+#define wxStyledTextCtrl_SetXCaretPolicy 3303
+#define wxStyledTextCtrl_SetYCaretPolicy 3304
+#define wxStyledTextCtrl_GetPrintWrapMode 3305
+#define wxStyledTextCtrl_SetHotspotActiveForeground 3306
+#define wxStyledTextCtrl_SetHotspotActiveBackground 3307
+#define wxStyledTextCtrl_SetHotspotActiveUnderline 3308
+#define wxStyledTextCtrl_SetHotspotSingleLine 3309
+#define wxStyledTextCtrl_ParaDownExtend 3310
+#define wxStyledTextCtrl_ParaUp 3311
+#define wxStyledTextCtrl_ParaUpExtend 3312
+#define wxStyledTextCtrl_PositionBefore 3313
+#define wxStyledTextCtrl_PositionAfter 3314
+#define wxStyledTextCtrl_CopyRange 3315
+#define wxStyledTextCtrl_CopyText 3316
+#define wxStyledTextCtrl_SetSelectionMode 3317
+#define wxStyledTextCtrl_GetSelectionMode 3318
+#define wxStyledTextCtrl_LineDownRectExtend 3319
+#define wxStyledTextCtrl_LineUpRectExtend 3320
+#define wxStyledTextCtrl_CharLeftRectExtend 3321
+#define wxStyledTextCtrl_CharRightRectExtend 3322
+#define wxStyledTextCtrl_HomeRectExtend 3323
+#define wxStyledTextCtrl_VCHomeRectExtend 3324
+#define wxStyledTextCtrl_LineEndRectExtend 3325
+#define wxStyledTextCtrl_PageUpRectExtend 3326
+#define wxStyledTextCtrl_PageDownRectExtend 3327
+#define wxStyledTextCtrl_StutteredPageUp 3328
+#define wxStyledTextCtrl_StutteredPageUpExtend 3329
+#define wxStyledTextCtrl_StutteredPageDown 3330
+#define wxStyledTextCtrl_StutteredPageDownExtend 3331
+#define wxStyledTextCtrl_WordLeftEnd 3332
+#define wxStyledTextCtrl_WordLeftEndExtend 3333
+#define wxStyledTextCtrl_WordRightEnd 3334
+#define wxStyledTextCtrl_WordRightEndExtend 3335
+#define wxStyledTextCtrl_SetWhitespaceChars 3336
+#define wxStyledTextCtrl_SetCharsDefault 3337
+#define wxStyledTextCtrl_AutoCompGetCurrent 3338
+#define wxStyledTextCtrl_Allocate 3339
+#define wxStyledTextCtrl_FindColumn 3340
+#define wxStyledTextCtrl_GetCaretSticky 3341
+#define wxStyledTextCtrl_SetCaretSticky 3342
+#define wxStyledTextCtrl_ToggleCaretSticky 3343
+#define wxStyledTextCtrl_SetPasteConvertEndings 3344
+#define wxStyledTextCtrl_GetPasteConvertEndings 3345
+#define wxStyledTextCtrl_SelectionDuplicate 3346
+#define wxStyledTextCtrl_SetCaretLineBackAlpha 3347
+#define wxStyledTextCtrl_GetCaretLineBackAlpha 3348
+#define wxStyledTextCtrl_StartRecord 3349
+#define wxStyledTextCtrl_StopRecord 3350
+#define wxStyledTextCtrl_SetLexer 3351
+#define wxStyledTextCtrl_GetLexer 3352
+#define wxStyledTextCtrl_Colourise 3353
+#define wxStyledTextCtrl_SetProperty 3354
+#define wxStyledTextCtrl_SetKeyWords 3355
+#define wxStyledTextCtrl_SetLexerLanguage 3356
+#define wxStyledTextCtrl_GetProperty 3357
+#define wxStyledTextCtrl_GetStyleBitsNeeded 3358
+#define wxStyledTextCtrl_GetCurrentLine 3359
+#define wxStyledTextCtrl_StyleSetSpec 3360
+#define wxStyledTextCtrl_StyleSetFont 3361
+#define wxStyledTextCtrl_StyleSetFontAttr 3362
+#define wxStyledTextCtrl_StyleSetCharacterSet 3363
+#define wxStyledTextCtrl_StyleSetFontEncoding 3364
+#define wxStyledTextCtrl_CmdKeyExecute 3365
+#define wxStyledTextCtrl_SetMargins 3366
+#define wxStyledTextCtrl_GetSelection 3367
+#define wxStyledTextCtrl_PointFromPosition 3368
+#define wxStyledTextCtrl_ScrollToLine 3369
+#define wxStyledTextCtrl_ScrollToColumn 3370
+#define wxStyledTextCtrl_SendMsg 3371
+#define wxStyledTextCtrl_SetVScrollBar 3372
+#define wxStyledTextCtrl_SetHScrollBar 3373
+#define wxStyledTextCtrl_GetLastKeydownProcessed 3374
+#define wxStyledTextCtrl_SetLastKeydownProcessed 3375
+#define wxStyledTextCtrl_SaveFile 3376
+#define wxStyledTextCtrl_LoadFile 3377
+#define wxStyledTextCtrl_DoDragOver 3378
+#define wxStyledTextCtrl_DoDropText 3379
+#define wxStyledTextCtrl_GetUseAntiAliasing 3380
+#define wxStyledTextCtrl_AddTextRaw 3381
+#define wxStyledTextCtrl_InsertTextRaw 3382
+#define wxStyledTextCtrl_GetCurLineRaw 3383
+#define wxStyledTextCtrl_GetLineRaw 3384
+#define wxStyledTextCtrl_GetSelectedTextRaw 3385
+#define wxStyledTextCtrl_GetTextRangeRaw 3386
+#define wxStyledTextCtrl_SetTextRaw 3387
+#define wxStyledTextCtrl_GetTextRaw 3388
+#define wxStyledTextCtrl_AppendTextRaw 3389
+#define wxArtProvider_GetBitmap 3390
+#define wxArtProvider_GetIcon 3391
+#define wxTreeEvent_GetKeyCode 3392
+#define wxTreeEvent_GetItem 3393
+#define wxTreeEvent_GetKeyEvent 3394
+#define wxTreeEvent_GetLabel 3395
+#define wxTreeEvent_GetOldItem 3396
+#define wxTreeEvent_GetPoint 3397
+#define wxTreeEvent_IsEditCancelled 3398
+#define wxTreeEvent_SetToolTip 3399
+#define wxNotebookEvent_GetOldSelection 3400
+#define wxNotebookEvent_GetSelection 3401
+#define wxNotebookEvent_SetOldSelection 3402
+#define wxNotebookEvent_SetSelection 3403
+#define wxFileDataObject_new 3404
+#define wxFileDataObject_AddFile 3405
+#define wxFileDataObject_GetFilenames 3406
+#define wxFileDataObject_destroy 3407
+#define wxTextDataObject_new 3408
+#define wxTextDataObject_GetTextLength 3409
+#define wxTextDataObject_GetText 3410
+#define wxTextDataObject_SetText 3411
+#define wxTextDataObject_destroy 3412
+#define wxBitmapDataObject_new_1_1 3413
+#define wxBitmapDataObject_new_1_0 3414
+#define wxBitmapDataObject_GetBitmap 3415
+#define wxBitmapDataObject_SetBitmap 3416
+#define wxBitmapDataObject_destroy 3417
+#define wxClipboard_new 3419
+#define wxClipboard_destruct 3420
+#define wxClipboard_AddData 3421
+#define wxClipboard_Clear 3422
+#define wxClipboard_Close 3423
+#define wxClipboard_Flush 3424
+#define wxClipboard_GetData 3425
+#define wxClipboard_IsOpened 3426
+#define wxClipboard_Open 3427
+#define wxClipboard_SetData 3428
+#define wxClipboard_UsePrimarySelection 3430
+#define wxClipboard_IsSupported 3431
+#define wxClipboard_Get 3432
+#define wxSpinEvent_GetPosition 3433
+#define wxSpinEvent_SetPosition 3434
+#define wxSplitterWindow_new_0 3435
+#define wxSplitterWindow_new_2 3436
+#define wxSplitterWindow_destruct 3437
+#define wxSplitterWindow_Create 3438
+#define wxSplitterWindow_GetMinimumPaneSize 3439
+#define wxSplitterWindow_GetSashGravity 3440
+#define wxSplitterWindow_GetSashPosition 3441
+#define wxSplitterWindow_GetSplitMode 3442
+#define wxSplitterWindow_GetWindow1 3443
+#define wxSplitterWindow_GetWindow2 3444
+#define wxSplitterWindow_Initialize 3445
+#define wxSplitterWindow_IsSplit 3446
+#define wxSplitterWindow_ReplaceWindow 3447
+#define wxSplitterWindow_SetSashGravity 3448
+#define wxSplitterWindow_SetSashPosition 3449
+#define wxSplitterWindow_SetSashSize 3450
+#define wxSplitterWindow_SetMinimumPaneSize 3451
+#define wxSplitterWindow_SetSplitMode 3452
+#define wxSplitterWindow_SplitHorizontally 3453
+#define wxSplitterWindow_SplitVertically 3454
+#define wxSplitterWindow_Unsplit 3455
+#define wxSplitterWindow_UpdateSize 3456
+#define wxSplitterEvent_GetSashPosition 3457
+#define wxSplitterEvent_GetX 3458
+#define wxSplitterEvent_GetY 3459
+#define wxSplitterEvent_GetWindowBeingRemoved 3460
+#define wxSplitterEvent_SetSashPosition 3461
+#define wxHtmlWindow_new_0 3462
+#define wxHtmlWindow_new_2 3463
+#define wxHtmlWindow_AppendToPage 3464
+#define wxHtmlWindow_GetOpenedAnchor 3465
+#define wxHtmlWindow_GetOpenedPage 3466
+#define wxHtmlWindow_GetOpenedPageTitle 3467
+#define wxHtmlWindow_GetRelatedFrame 3468
+#define wxHtmlWindow_HistoryBack 3469
+#define wxHtmlWindow_HistoryCanBack 3470
+#define wxHtmlWindow_HistoryCanForward 3471
+#define wxHtmlWindow_HistoryClear 3472
+#define wxHtmlWindow_HistoryForward 3473
+#define wxHtmlWindow_LoadFile 3474
+#define wxHtmlWindow_LoadPage 3475
+#define wxHtmlWindow_SelectAll 3476
+#define wxHtmlWindow_SelectionToText 3477
+#define wxHtmlWindow_SelectLine 3478
+#define wxHtmlWindow_SelectWord 3479
+#define wxHtmlWindow_SetBorders 3480
+#define wxHtmlWindow_SetFonts 3481
+#define wxHtmlWindow_SetPage 3482
+#define wxHtmlWindow_SetRelatedFrame 3483
+#define wxHtmlWindow_SetRelatedStatusBar 3484
+#define wxHtmlWindow_ToText 3485
+#define wxHtmlWindow_destroy 3486
+#define wxHtmlLinkEvent_GetLinkInfo 3487
+#define wxSystemSettings_GetColour 3488
+#define wxSystemSettings_GetFont 3489
+#define wxSystemSettings_GetMetric 3490
+#define wxSystemSettings_GetScreenType 3491
+#define wxSystemOptions_GetOption 3492
+#define wxSystemOptions_GetOptionInt 3493
+#define wxSystemOptions_HasOption 3494
+#define wxSystemOptions_IsFalse 3495
+#define wxSystemOptions_SetOption_2_1 3496
+#define wxSystemOptions_SetOption_2_0 3497
+#define wxAuiNotebookEvent_SetSelection 3498
+#define wxAuiNotebookEvent_GetSelection 3499
+#define wxAuiNotebookEvent_SetOldSelection 3500
+#define wxAuiNotebookEvent_GetOldSelection 3501
+#define wxAuiNotebookEvent_SetDragSource 3502
+#define wxAuiNotebookEvent_GetDragSource 3503
+#define wxAuiManagerEvent_SetManager 3504
+#define wxAuiManagerEvent_GetManager 3505
+#define wxAuiManagerEvent_SetPane 3506
+#define wxAuiManagerEvent_GetPane 3507
+#define wxAuiManagerEvent_SetButton 3508
+#define wxAuiManagerEvent_GetButton 3509
+#define wxAuiManagerEvent_SetDC 3510
+#define wxAuiManagerEvent_GetDC 3511
+#define wxAuiManagerEvent_Veto 3512
+#define wxAuiManagerEvent_GetVeto 3513
+#define wxAuiManagerEvent_SetCanVeto 3514
+#define wxAuiManagerEvent_CanVeto 3515
+#define wxLogNull_new 3516
+#define wxLogNull_destroy 3517
diff --git a/lib/wx/c_src/wxePrintout.cpp b/lib/wx/c_src/wxePrintout.cpp
index ea1c76edcc..90959df379 100644
--- a/lib/wx/c_src/wxePrintout.cpp
+++ b/lib/wx/c_src/wxePrintout.cpp
@@ -1,41 +1,62 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 2008-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 2008-2011. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
- * %CopyrightEnd%
+ *
+ * %CopyrightEnd%
*/
#include <wx/wx.h>
#include "wxe_impl.h"
#include "wxe_return.h"
+#include "gen/wxe_macros.h"
+#include "gen/wxe_derived_dest.h"
/* *****************************************************************/
/* Special Class impls */
+#define INVOKE_CALLBACK_INIT(port, callback, class_str) \
+ { \
+ wxeMemEnv * memenv = ((WxeApp *) wxTheApp)->getMemEnv(port); \
+ wxeReturn rt = wxeReturn(WXE_DRV_PORT, memenv->owner, false); \
+ rt.addInt(callback); \
+ rt.addRef(((WxeApp *) wxTheApp)->getRef((void *)this, memenv), class_str);
+
+#define INVOKE_CALLBACK_END(port, args) \
+ rt.endList(1 + (args)); \
+ rt.addAtom("_wx_invoke_cb_"); \
+ rt.addTupleCount(3); \
+ rt.send(); \
+ handle_event_callback(port, memenv->owner); \
+ }
+
+#define INVOKE_CALLBACK(port, callback, class_str) \
+ INVOKE_CALLBACK_INIT(port, callback, class_str); \
+ INVOKE_CALLBACK_END(port, 0)
+/* *****************************************************************/
/* Printing special */
wxEPrintout::~wxEPrintout() {
- clear_cb(onPrintPage);
- clear_cb(onPreparePrinting);
- clear_cb(onBeginPrinting);
- clear_cb(onEndPrinting);
- clear_cb(onBeginDocument);
- clear_cb(onEndDocument);
- clear_cb(hasPage);
- clear_cb(getPageInfo);
+ clear_cb(port, onPrintPage);
+ clear_cb(port, onPreparePrinting);
+ clear_cb(port, onBeginPrinting);
+ clear_cb(port, onEndPrinting);
+ clear_cb(port, onBeginDocument);
+ clear_cb(port, onEndDocument);
+ clear_cb(port, hasPage);
+ clear_cb(port, getPageInfo);
((WxeApp *)wxTheApp)->clearPtr(this);
}
@@ -43,73 +64,44 @@ wxEPrintout::~wxEPrintout() {
bool wxEPrintout::OnBeginDocument(int startPage, int endPage)
{
if(onBeginDocument) {
- wxeMemEnv * memenv = ((WxeApp *) wxTheApp)->getMemEnv(port);
- char * bp = ((WxeApp *) wxTheApp)->cb_buff;
-
- wxeReturn rt = wxeReturn(WXE_DRV_PORT, memenv->owner, false);
- rt.addInt(onBeginDocument);
- rt.addRef(((WxeApp *) wxTheApp)->getRef((void *)this, memenv), "wxPrintout");
+ INVOKE_CALLBACK_INIT(port, onBeginDocument, "wxPrintout");
rt.addInt(startPage);
rt.addInt(endPage);
- rt.endList(3);
- rt.addAtom("_wx_invoke_cb_");
- rt.addTupleCount(3);
- rt.send();
- handle_callback_batch(port);
- return *(int*) bp;
- } else {
- return wxPrintout::OnBeginDocument(startPage,endPage);
- }
+ INVOKE_CALLBACK_END(port, 2);
+ if(((WxeApp *) wxTheApp)->cb_buff) {
+ int res = * (int*) ((WxeApp *) wxTheApp)->cb_buff;
+ driver_free(((WxeApp *) wxTheApp)->cb_buff);
+ ((WxeApp *) wxTheApp)->cb_buff = NULL;
+ return res;
+ }
+ }
+ return wxPrintout::OnBeginDocument(startPage,endPage);
}
-void wxEPrintout::OnEndDocument()
+void wxEPrintout::OnEndDocument()
{
if(onEndDocument) {
- wxeMemEnv * memenv = ((WxeApp *) wxTheApp)->getMemEnv(port);
- wxeReturn rt = wxeReturn(WXE_DRV_PORT, memenv->owner, false);
- rt.addInt(onEndDocument);
- rt.addRef(((WxeApp *) wxTheApp)->getRef((void *)this, memenv), "wxPrintout");
- rt.endList(1);
- rt.addAtom("_wx_invoke_cb_");
- rt.addTupleCount(3);
- rt.send();
- handle_callback_batch(port);
+ INVOKE_CALLBACK(port, onEndDocument, "wxPrintout");
} else {
wxPrintout::OnEndDocument();
- }
+ }
}
-void wxEPrintout::OnBeginPrinting()
+void wxEPrintout::OnBeginPrinting()
{
if(onBeginPrinting) {
- wxeMemEnv * memenv = ((WxeApp *) wxTheApp)->getMemEnv(port);
- wxeReturn rt = wxeReturn(WXE_DRV_PORT, memenv->owner, false);
- rt.addInt(onBeginPrinting);
- rt.addRef(((WxeApp *) wxTheApp)->getRef((void *)this, memenv), "wxPrintout");
- rt.endList(1);
- rt.addAtom("_wx_invoke_cb_");
- rt.addTupleCount(3);
- rt.send();
- handle_callback_batch(port);
+ INVOKE_CALLBACK(port, onBeginPrinting, "wxPrintout");
} else {
wxPrintout::OnBeginPrinting();
- }
+ }
}
-void wxEPrintout::OnEndPrinting()
+void wxEPrintout::OnEndPrinting()
{
if(onEndPrinting) {
- wxeMemEnv * memenv = ((WxeApp *) wxTheApp)->getMemEnv(port);
- wxeReturn rt = wxeReturn(WXE_DRV_PORT, memenv->owner, false);
- rt.addInt(onEndPrinting);
- rt.addRef(((WxeApp *) wxTheApp)->getRef((void *)this, memenv), "wxPrintout");
- rt.endList(1);
- rt.addAtom("_wx_invoke_cb_");
- rt.addTupleCount(3);
- rt.send();
- handle_callback_batch(port);
+ INVOKE_CALLBACK(port, onEndPrinting, "wxPrintout");
} else {
wxPrintout::OnEndPrinting();
}
@@ -119,92 +111,133 @@ void wxEPrintout::OnPreparePrinting()
{
if(onPreparePrinting) {
- wxeMemEnv * memenv = ((WxeApp *) wxTheApp)->getMemEnv(port);
- wxeReturn rt = wxeReturn(WXE_DRV_PORT, memenv->owner, false);
- rt.addInt(onPreparePrinting);
- rt.addRef(((WxeApp *) wxTheApp)->getRef((void *)this, memenv), "wxPrintout");
- rt.endList(1);
- rt.addAtom("_wx_invoke_cb_");
- rt.addTupleCount(3);
- rt.send();
- handle_callback_batch(port);
+ INVOKE_CALLBACK(port, onPreparePrinting, "wxPrintout");
} else {
wxPrintout::OnPreparePrinting();
- }
+ }
}
-bool wxEPrintout::HasPage(int page)
+bool wxEPrintout::HasPage(int page)
{
if(hasPage) {
- wxeMemEnv * memenv = ((WxeApp *) wxTheApp)->getMemEnv(port);
- wxeReturn rt = wxeReturn(WXE_DRV_PORT, memenv->owner, false);
- rt.addInt(hasPage);
- rt.addRef(((WxeApp *) wxTheApp)->getRef((void *)this, memenv), "wxPrintout");
+ INVOKE_CALLBACK_INIT(port, hasPage, "wxPrintout");
rt.addInt(page);
- rt.endList(2);
- rt.addAtom("_wx_invoke_cb_");
- rt.addTupleCount(3);
- rt.send();
- char * bp = ((WxeApp *) wxTheApp)->cb_buff;
- handle_callback_batch(port);
- return *(int*) bp;
- } else {
- return wxPrintout::HasPage(page);
- }
+ INVOKE_CALLBACK_END(port, 1);
+ if(((WxeApp *) wxTheApp)->cb_buff) {
+ int res = * (int*) ((WxeApp *) wxTheApp)->cb_buff;
+ driver_free(((WxeApp *) wxTheApp)->cb_buff);
+ ((WxeApp *) wxTheApp)->cb_buff = NULL;
+ return res;
+ }
+ }
+ return wxPrintout::HasPage(page);
}
bool wxEPrintout::OnPrintPage(int page)
{
- wxeMemEnv * memenv = ((WxeApp *) wxTheApp)->getMemEnv(port);
- wxeReturn rt = wxeReturn(WXE_DRV_PORT, memenv->owner, false);
- rt.addInt(onPrintPage);
- rt.addRef(((WxeApp *) wxTheApp)->getRef((void *)this, memenv), "wxPrintout");
+ INVOKE_CALLBACK_INIT(port, onPrintPage, "wxPrintout");
rt.addInt(page);
- rt.endList(2);
- rt.addAtom("_wx_invoke_cb_");
- rt.addTupleCount(3);
- rt.send();
- handle_callback_batch(port);
- //fprintf(stderr,"%d ", __LINE__);handle_callback_batch(port); fprintf(stderr,"%d\r\n", __LINE__);
- char * bp = ((WxeApp *) wxTheApp)->cb_buff;
- return *(int*) bp;
+ INVOKE_CALLBACK_END(port, 1);
+ if(((WxeApp *) wxTheApp)->cb_buff) {
+ int res = * (int*) ((WxeApp *) wxTheApp)->cb_buff;
+ driver_free(((WxeApp *) wxTheApp)->cb_buff);
+ ((WxeApp *) wxTheApp)->cb_buff = NULL;
+ return res;
+ }
+ return FALSE;
}
-
+
void wxEPrintout::GetPageInfo(int *minPage, int *maxPage, int *pageFrom, int *pageTo)
{
if(getPageInfo) {
- wxeMemEnv * memenv = ((WxeApp *) wxTheApp)->getMemEnv(port);
- wxeReturn rt = wxeReturn(WXE_DRV_PORT, memenv->owner, false);
- rt.addInt(getPageInfo);
- rt.addRef(((WxeApp *) wxTheApp)->getRef((void *)this, memenv), "wxPrintout");
- rt.endList(1);
- rt.addAtom("_wx_invoke_cb_");
- rt.addTupleCount(3);
- rt.send();
- handle_callback_batch(port);
- //fprintf(stderr,"%d ", __LINE__);handle_callback_batch(port); fprintf(stderr,"%d\r\n", __LINE__);
+ INVOKE_CALLBACK(port, getPageInfo, "wxPrintout");
+ if(((WxeApp *) wxTheApp)->cb_buff) {
+ char * bp = ((WxeApp *) wxTheApp)->cb_buff;
+ *minPage = *(int *) bp; bp += 4;
+ *maxPage = *(int *) bp; bp += 4;
+ *pageFrom = *(int *) bp; bp += 4;
+ *pageTo = *(int *) bp; bp += 4;
+ driver_free(((WxeApp *) wxTheApp)->cb_buff);
+ ((WxeApp *) wxTheApp)->cb_buff = NULL;
+ }
+ }
+ wxPrintout::GetPageInfo(minPage, maxPage, pageFrom, pageTo);
+}
+
+/* *****************************************************************/
+// ListCtrl with callbacks for VIRTUAL_TABLES
+
+wxString EwxListCtrl::OnGetItemText(long item, long col) const {
+ if(onGetItemText) {
+ INVOKE_CALLBACK_INIT(port, onGetItemText, "wxListCtrl");
+ rt.addInt(item);
+ rt.addInt(col);
+ INVOKE_CALLBACK_END(port, 2);
+ if(((WxeApp *) wxTheApp)->cb_buff) {
+ char * bp = ((WxeApp *) wxTheApp)->cb_buff;
+ wxString str = wxString(bp, wxConvUTF8);
+ driver_free(((WxeApp *) wxTheApp)->cb_buff);
+ ((WxeApp *) wxTheApp)->cb_buff = NULL;
+ return str;
+ }
+ }
+ return wxT("OnGetItemText not correctly defined");
+}
+wxListItemAttr* EwxListCtrl::OnGetItemAttr(long item) const {
+ if(onGetItemAttr) {
+ INVOKE_CALLBACK_INIT(port, onGetItemAttr, "wxListCtrl");
+ rt.addInt(item);
+ INVOKE_CALLBACK_END(port, 1);
char * bp = ((WxeApp *) wxTheApp)->cb_buff;
- *minPage = *(int *) bp; bp += 4;
- *maxPage = *(int *) bp; bp += 4;
- *pageFrom = *(int *) bp; bp += 4;
- *pageTo = *(int *) bp; bp += 4;
- } else {
- wxPrintout::GetPageInfo(minPage, maxPage, pageFrom, pageTo);
+ wxeMemEnv * memenv = ((WxeApp *) wxTheApp)->getMemEnv(port);
+ if(bp) {
+ wxListItemAttr * result = (wxListItemAttr *)((WxeApp *) wxTheApp)->getPtr(bp, memenv);
+ driver_free(((WxeApp *) wxTheApp)->cb_buff);
+ ((WxeApp *) wxTheApp)->cb_buff = NULL;
+ return result;
+ }
}
+ return NULL;
+}
+
+int EwxListCtrl::OnGetItemImage(long item) const {
+ return OnGetItemColumnImage(item, 0);
}
-void wxEPrintout::clear_cb(int callback)
+int EwxListCtrl::OnGetItemColumnImage(long item, long col) const {
+ if(onGetItemColumnImage) {
+ INVOKE_CALLBACK_INIT(port, onGetItemColumnImage, "wxListCtrl");
+ rt.addInt(item);
+ rt.addInt(col);
+ INVOKE_CALLBACK_END(port, 2);
+ if(((WxeApp *) wxTheApp)->cb_buff) {
+ int res = * (int*) ((WxeApp *) wxTheApp)->cb_buff;
+ driver_free(((WxeApp *) wxTheApp)->cb_buff);
+ ((WxeApp *) wxTheApp)->cb_buff = NULL;
+ return res;
+ }
+ }
+ return -1;
+}
+
+EwxListCtrl::~EwxListCtrl() {
+ clear_cb(port, onGetItemText);
+ clear_cb(port, onGetItemAttr);
+ clear_cb(port, onGetItemColumnImage);
+ ((WxeApp *)wxTheApp)->clearPtr(this);
+}
+// tools
+
+void clear_cb(ErlDrvPort port, int callback)
{
if(callback > 0) {
wxeMemEnv * memenv = ((WxeApp *) wxTheApp)->getMemEnv(port);
wxeReturn rt = wxeReturn(WXE_DRV_PORT, memenv->owner, false);
- // NOTE: Remove this later when changing from funs to gen_server
rt.addAtom("wx_delete_cb");
rt.addInt(callback);
rt.addTupleCount(2);
rt.send();
}
}
-
diff --git a/lib/wx/c_src/wxe_impl.cpp b/lib/wx/c_src/wxe_impl.cpp
index 365fb691a1..69fcd4e362 100644
--- a/lib/wx/c_src/wxe_impl.cpp
+++ b/lib/wx/c_src/wxe_impl.cpp
@@ -14,7 +14,7 @@
* the License for the specific language governing rights and limitations
* under the License.
*
- * %CopyrightEnd%
+ * %CopyrightEnd%
*/
#include <stdio.h>
@@ -49,7 +49,7 @@ DEFINE_EVENT_TYPE(wxeEVT_META_COMMAND)
#define WXE_NORMAL 0
#define WXE_CALLBACK 1
-#define WXE_STORED 2
+#define WXE_STORED 2
ErlDrvTid wxe_thread;
@@ -67,7 +67,7 @@ wxList * wxe_batch_cb_saved = NULL;
ErlDrvTermData wxe_batch_caller = 0;
ErlDrvTermData init_caller = 0;
-// extern opengl
+// extern opengl
void gl_dispatch(int op, char *bp, ErlDrvTermData caller, WXEBinRef *bins[]);
@@ -99,7 +99,7 @@ void *wxe_main_loop(void * );
* START AND STOP of driver thread
* ************************************************************/
-int load_native_gui()
+int load_native_gui()
{
return 1;
}
@@ -112,7 +112,7 @@ int start_native_gui(wxe_data *sd)
wxe_batch_locker_m = erl_drv_mutex_create((char *)"wxe_batch_locker_m");
wxe_batch_locker_c = erl_drv_cond_create((char *)"wxe_batch_locker_c");
- init_caller = driver_connected(sd->port);
+ init_caller = driver_connected(sd->port);
#ifdef __DARWIN__
res = erl_drv_steal_main_thread((char *)"wxwidgets",
@@ -152,9 +152,9 @@ void stop_native_gui(wxe_data *sd)
erl_drv_cond_destroy(wxe_batch_locker_c);
}
-void unload_native_gui()
+void unload_native_gui()
{
-
+
}
/* ************************************************************
@@ -162,13 +162,13 @@ void unload_native_gui()
* Called by emulator thread
* ************************************************************/
-void push_command(int op,char * buf,int len, wxe_data *sd)
-{
+void push_command(int op,char * buf,int len, wxe_data *sd)
+{
// fprintf(stderr, "Op %d %d\r\n", op, (int) driver_caller(sd->port)),fflush(stderr);
wxeCommand *Cmd = new wxeCommand(op, buf, len, sd);
erl_drv_mutex_lock(wxe_batch_locker_m);
wxe_batch->Append(Cmd);
-
+
if(wxe_batch_caller > 0) {
// wx-thread is waiting on batch end in cond_wait
erl_drv_cond_signal(wxe_batch_locker_c);
@@ -179,11 +179,11 @@ void push_command(int op,char * buf,int len, wxe_data *sd)
}
erl_drv_cond_signal(wxe_batch_locker_c);
wxWakeUpIdle();
- }
+ }
erl_drv_mutex_unlock(wxe_batch_locker_m);
}
-void meta_command(int what, wxe_data *sd) {
+void meta_command(int what, wxe_data *sd) {
if(what == PING_PORT) {
erl_drv_mutex_lock(wxe_batch_locker_m);
if(wxe_batch_caller > 0) {
@@ -203,17 +203,17 @@ void meta_command(int what, wxe_data *sd) {
}
/* ************************************************************
- * wxWidgets Thread
+ * wxWidgets Thread
* ************************************************************/
void *wxe_main_loop(void *vpdl)
{
- int result;
+ int result;
int argc = 1;
char * temp = (char *) "Erlang";
char * argv[] = {temp,NULL};
ErlDrvPDL pdl = (ErlDrvPDL) vpdl;
-
+
driver_pdl_inc_refc(pdl);
// ErlDrvSysInfo einfo;
@@ -223,7 +223,7 @@ void *wxe_main_loop(void *vpdl)
#ifndef _WIN32
erts_thread_disable_fpe();
#endif
-
+
result = wxEntry(argc, argv);
// fprintf(stderr, "WXWidgets quits main loop %d \r\n", result);
if(result >= 0 && wxe_status == WXE_INITIATED) {
@@ -240,17 +240,17 @@ void *wxe_main_loop(void *vpdl)
erl_drv_cond_signal(wxe_status_c);
erl_drv_mutex_unlock(wxe_status_m);
driver_pdl_dec_refc(pdl);
- return NULL;
+ return NULL;
}
}
wxFrame * dummy_window;
void create_dummy_window() {
- dummy_window = new wxFrame(NULL,-1, wxT("wx driver"),
- wxDefaultPosition, wxSize(5,5),
+ dummy_window = new wxFrame(NULL,-1, wxT("wx driver"),
+ wxDefaultPosition, wxSize(5,5),
wxFRAME_NO_TASKBAR);
- dummy_window->Connect(wxID_ANY, wxEVT_CLOSE_WINDOW,
+ dummy_window->Connect(wxID_ANY, wxEVT_CLOSE_WINDOW,
(wxObjectEventFunction) (wxEventFunction) &WxeApp::dummy_close);
}
@@ -262,7 +262,7 @@ void WxeApp::dummy_close(wxEvent& Ev) {
create_dummy_window();
}
-// Init wx-widgets thread
+// Init wx-widgets thread
bool WxeApp::OnInit()
{
wxe_ps_init();
@@ -270,16 +270,17 @@ bool WxeApp::OnInit()
global_me = new wxeMemEnv();
wxe_batch = new wxList;
wxe_batch_cb_saved = new wxList;
+ cb_buff = NULL;
wxIdleEvent::SetMode(wxIDLE_PROCESS_SPECIFIED);
- this->Connect(wxID_ANY, wxEVT_IDLE,
+ this->Connect(wxID_ANY, wxEVT_IDLE,
(wxObjectEventFunction) (wxEventFunction) &WxeApp::idle);
- this->Connect(CREATE_PORT, wxeEVT_META_COMMAND,
+ this->Connect(CREATE_PORT, wxeEVT_META_COMMAND,
(wxObjectEventFunction) (wxEventFunction) &WxeApp::newMemEnv);
- this->Connect(DELETE_PORT, wxeEVT_META_COMMAND,
+ this->Connect(DELETE_PORT, wxeEVT_META_COMMAND,
(wxObjectEventFunction) (wxEventFunction) &WxeApp::destroyMemEnv);
- this->Connect(WXE_SHUTDOWN, wxeEVT_META_COMMAND,
+ this->Connect(WXE_SHUTDOWN, wxeEVT_META_COMMAND,
(wxObjectEventFunction) (wxEventFunction) &WxeApp::shutdown);
// fprintf(stderr, "Size void* %d: long %d long long %d int64 %d \r\n",
@@ -287,9 +288,9 @@ bool WxeApp::OnInit()
initEventTable();
wxInitAllImageHandlers();
- /* Create a dummy window so wxWidgets don't automagicly quits the main loop
+ /* Create a dummy window so wxWidgets don't automagicly quits the main loop
after the last window */
- create_dummy_window();
+ create_dummy_window();
init_nonconsts(global_me, init_caller);
erl_drv_mutex_lock(wxe_status_m);
@@ -308,19 +309,19 @@ void send_msg(const char * type, wxString * msg) {
wxeReturn rt = wxeReturn(WXE_DRV_PORT, init_caller);
rt.addAtom((char *) "wxe_driver");
rt.addAtom((char *) type);
- rt.add(msg);
+ rt.add(msg);
rt.addTupleCount(3);
rt.send();
}
/* ************************************************************
- * Erlang Command execution *
+ * Erlang Command execution *
* ************************************************************/
-/* Callback from printer and event callbacks */
+/* Callback from printer and event callbacks */
void pre_callback()
{
- // no-op
+ // no-op
}
void handle_event_callback(ErlDrvPort port, ErlDrvTermData process)
@@ -330,29 +331,19 @@ void handle_event_callback(ErlDrvPort port, ErlDrvTermData process)
driver_monitor_process(port, process, &monitor);
// Should we be able to handle commands when recursing? probably
erl_drv_mutex_lock(wxe_batch_locker_m);
- //fprintf(stderr, "\r\nCB Start ");fflush(stderr);
+ //fprintf(stderr, "\r\nCB EV Start %lu \r\n", process);fflush(stderr);
app->dispatch_cb(wxe_batch, wxe_batch_cb_saved, process);
- //fprintf(stderr, ".. done \r\n");fflush(stderr);
+ //fprintf(stderr, "CB EV done %lu \r\n", process);fflush(stderr);
wxe_batch_caller = 0;
erl_drv_mutex_unlock(wxe_batch_locker_m);
driver_demonitor_process(port, &monitor);
}
-void handle_callback_batch(ErlDrvPort port)
-{
- WxeApp * app = (WxeApp *) wxTheApp;
- // Should we be able to handle commands when recursing? probably
- erl_drv_mutex_lock(wxe_batch_locker_m);
- app->dispatch(wxe_batch, 0, WXE_CALLBACK);
- wxe_batch_caller = 0;
- erl_drv_mutex_unlock(wxe_batch_locker_m);
-}
-
// Called by wx thread
void WxeApp::idle(wxIdleEvent& event) {
dispatch_cmds();
}
-
+
void WxeApp::dispatch_cmds() {
erl_drv_mutex_lock(wxe_batch_locker_m);
int level = dispatch(wxe_batch_cb_saved, 0, WXE_STORED);
@@ -361,14 +352,14 @@ void WxeApp::dispatch_cmds() {
erl_drv_mutex_unlock(wxe_batch_locker_m);
}
-// Should have erl_drv_mutex_lock(wxe_batch_locker_m);
-// when entering this function and it should be released
+// Should have erl_drv_mutex_lock(wxe_batch_locker_m);
+// when entering this function and it should be released
// afterwards
-int WxeApp::dispatch(wxList * batch, int blevel, int list_type)
+int WxeApp::dispatch(wxList * batch, int blevel, int list_type)
{
int ping = 0;
// erl_drv_mutex_lock(wxe_batch_locker_m); must be locked already
- while(true)
+ while(true)
{
if (batch->size() > 0) {
for( wxList::compatibility_iterator node = batch->GetFirst();
@@ -385,19 +376,22 @@ int WxeApp::dispatch(wxList * batch, int blevel, int list_type)
{blevel++; }
break;
case WXE_DEBUG_PING:
- // When in debugger we don't want to hang waiting for a BATCH_END
+ // When in debugger we don't want to hang waiting for a BATCH_END
// that never comes, because a breakpoint have hit.
ping++;
- if(ping > 2)
+ if(ping > 2)
blevel = 0;
break;
case WXE_CB_RETURN:
// erl_drv_mutex_unlock(wxe_batch_locker_m); should be called after
// whatever cleaning is necessary
- memcpy(cb_buff, event->buffer, event->len);
+ if(event->len > 0) {
+ cb_buff = (char *) driver_alloc(event->len);
+ memcpy(cb_buff, event->buffer, event->len);
+ }
return blevel;
default:
- erl_drv_mutex_unlock(wxe_batch_locker_m);
+ erl_drv_mutex_unlock(wxe_batch_locker_m);
if(event->op < OPENGL_START) {
// fprintf(stderr, " c %d (%d) \r\n", event->op, blevel);
wxe_dispatch(*event);
@@ -436,10 +430,11 @@ void WxeApp::dispatch_cb(wxList * batch, wxList * temp, ErlDrvTermData process)
wxeCommand *event = (wxeCommand *)node->GetData();
wxeMemEnv *memenv = getMemEnv(event->port);
batch->Erase(node);
- if(event->caller == process || // Callbacks from CB process only
- event->op == WXE_CB_START || // Recursive event callback allow
+ // fprintf(stderr, " Ev %d %lu\r\n", event->op, event->caller);
+ if(event->caller == process || // Callbacks from CB process only
+ event->op == WXE_CB_START || // Event callback start change process
// Allow connect_cb during CB i.e. msg from wxe_server.
- (memenv && event->caller == memenv->owner))
+ (memenv && event->caller == memenv->owner))
{
switch(event->op) {
case WXE_BATCH_END:
@@ -447,7 +442,10 @@ void WxeApp::dispatch_cb(wxList * batch, wxList * temp, ErlDrvTermData process)
case WXE_DEBUG_PING:
break;
case WXE_CB_RETURN:
- memcpy(cb_buff, event->buffer, event->len);
+ if(event->len > 0) {
+ cb_buff = (char *) driver_alloc(event->len);
+ memcpy(cb_buff, event->buffer, event->len);
+ }
callback_returned = 1;
return;
case WXE_CB_START:
@@ -456,6 +454,7 @@ void WxeApp::dispatch_cb(wxList * batch, wxList * temp, ErlDrvTermData process)
break;
default:
erl_drv_mutex_unlock(wxe_batch_locker_m);
+ size_t start=temp->GetCount();
if(event->op < OPENGL_START) {
// fprintf(stderr, " cb %d \r\n", event->op);
wxe_dispatch(*event);
@@ -463,13 +462,27 @@ void WxeApp::dispatch_cb(wxList * batch, wxList * temp, ErlDrvTermData process)
gl_dispatch(event->op,event->buffer,event->caller,event->bin);
}
erl_drv_mutex_lock(wxe_batch_locker_m);
- break;
- if(callback_returned)
+ if(temp->GetCount() > start) {
+ // We have recursed dispatch_cb and messages for this
+ // callback may be saved on temp list move them
+ // to orig list
+ for(wxList::compatibility_iterator node = temp->Item(start);
+ node;
+ node = node->GetNext()) {
+ wxeCommand *ev = (wxeCommand *)node->GetData();
+ if(ev->caller == process) {
+ batch->Append(ev);
+ temp->Erase(node);
+ }
+ }
+ }
+ if(callback_returned)
return;
+ break;
}
delete event;
} else {
- // fprintf(stderr, " sav %d \r\n", event->op);
+ // fprintf(stderr, " save %d \r\n", event->op);
temp->Append(event);
}
}
@@ -494,13 +507,13 @@ void WxeApp::newMemEnv(wxeMetaCommand& Ecmd) {
driver_pdl_inc_refc(Ecmd.pdl);
for(int i = 0; i < global_me->next; i++) {
- memenv->ref2ptr[i] = global_me->ref2ptr[i];
+ memenv->ref2ptr[i] = global_me->ref2ptr[i];
}
memenv->next = global_me->next;
refmap[(ErlDrvTermData) Ecmd.port] = memenv;
memenv->owner = Ecmd.caller;
- ErlDrvTermData rt[] = {ERL_DRV_ATOM, driver_mk_atom((char *)"wx_port_initiated")};
+ ErlDrvTermData rt[] = {ERL_DRV_ATOM, driver_mk_atom((char *)"wx_port_initiated")};
driver_send_term(WXE_DRV_PORT,Ecmd.caller,rt,2);
}
@@ -519,13 +532,13 @@ void WxeApp::destroyMemEnv(wxeMetaCommand& Ecmd) {
// pre-pass delete all dialogs first since they might crash erlang otherwise
for(int i=1; i < memenv->next; i++) {
wxObject * ptr = (wxObject *) memenv->ref2ptr[i];
- if(ptr) {
+ if(ptr) {
ptrMap::iterator it = ptr2ref.find(ptr);
if(it != ptr2ref.end()) {
wxeRefData *refd = it->second;
if(refd->alloc_in_erl) {
if(refd->type == 2) {
- wxDialog *win = (wxDialog *) ptr;
+ wxDialog *win = (wxDialog *) ptr;
if(win->IsModal()) {
win->EndModal(-1);
}
@@ -535,25 +548,25 @@ void WxeApp::destroyMemEnv(wxeMetaCommand& Ecmd) {
if(parentRef == ptr2ref.end()) {
// The parent is already dead delete the parent ref
win->SetParent(NULL);
- }
+ }
}
delete win;
- }
+ }
}
}
}
}
- // First pass, delete all top parents/windows of all linked objects
+ // First pass, delete all top parents/windows of all linked objects
// fprintf(stderr, "close port %x\r\n", Ecmd.port);fflush(stderr);
for(int i=1; i < memenv->next; i++) {
void * ptr = memenv->ref2ptr[i];
- if(ptr) {
+ if(ptr) {
ptrMap::iterator it = ptr2ref.find(ptr);
if(it != ptr2ref.end()) {
wxeRefData *refd = it->second;
if(refd->alloc_in_erl && refd->type == 0) {
- parent = (wxWindow *) ptr;
+ parent = (wxWindow *) ptr;
// fprintf(stderr, "window %x %d\r\n", (int) parent, refd->ref);
while(parent->GetParent()) {
parent = parent->GetParent();
@@ -573,7 +586,7 @@ void WxeApp::destroyMemEnv(wxeMetaCommand& Ecmd) {
// everything linked from windows should now be deleted
for(int i=1; i < memenv->next; i++) {
void * ptr = memenv->ref2ptr[i];
- if(ptr) {
+ if(ptr) {
ptrMap::iterator it = ptr2ref.find(ptr);
if(it != ptr2ref.end()) {
wxeRefData *refd = it->second;
@@ -585,33 +598,33 @@ void WxeApp::destroyMemEnv(wxeMetaCommand& Ecmd) {
wxString msg;
if((refd->type == 0)) { // Maybe also class 1
wxClassInfo *cinfo = ((wxObject *)ptr)->GetClassInfo();
- msg.Printf(wxT("Memory leak: {wx_ref, %d, %s}"),
+ msg.Printf(wxT("Memory leak: {wx_ref, %d, %s}"),
refd->ref, cinfo->GetClassName());
send_msg("error", &msg);
} else {
delete_object(ptr, refd);
}
- if(type == 0 || type > 3) {
- // Delete refs for leaks and non overridden allocs
+ if(type == 0 || type > 2) {
+ // Delete refs for leaks and non overridden allocs
delete refd;
ptr2ref.erase(it);
} // overridden allocs deletes meta-data in clearPtr
} else { // Not alloced in erl just delete references
if(refd->ref >= global_me->next) { // if it is not part of global ptrs
- delete refd;
+ delete refd;
ptr2ref.erase(it);
}
}
}
}
- }
- // Assert ?
-// for(ptrMap::iterator it = ptr2ref.begin(); it != ptr2ref.end(); it++) {
-// wxeRefData *refd = it->second;
-// if(refd->ref >= global_me->next)
-// fprintf(stderr, "L %d %d\r\n", refd->ref, refd->alloc_in_erl);
-// }
-// fflush(stderr);
+ }
+// // Assert ?
+// for(ptrMap::iterator it = ptr2ref.begin(); it != ptr2ref.end(); it++) {
+// wxeRefData *refd = it->second;
+// if(refd->ref >= global_me->next)
+// fprintf(stderr, "L %d %d %d\r\n", refd->ref, refd->type, refd->alloc_in_erl);
+// }
+// fflush(stderr);
delete memenv;
driver_pdl_dec_refc(Ecmd.pdl);
refmap.erase((ErlDrvTermData) Ecmd.port);
@@ -624,7 +637,7 @@ wxeMemEnv * WxeApp::getMemEnv(ErlDrvPort port) {
int WxeApp::newPtr(void * ptr, int type, wxeMemEnv *memenv) {
int ref;
intList free = memenv->free;
-
+
if(free.IsEmpty()) {
ref = memenv->next++;
} else {
@@ -632,8 +645,8 @@ int WxeApp::newPtr(void * ptr, int type, wxeMemEnv *memenv) {
};
if(ref >= memenv->max) {
memenv->max *= 2;
- memenv->ref2ptr =
- (void **) driver_realloc(memenv->ref2ptr,memenv->max * sizeof(void*));
+ memenv->ref2ptr =
+ (void **) driver_realloc(memenv->ref2ptr,memenv->max * sizeof(void*));
}
memenv->ref2ptr[ref] = ptr;
@@ -653,12 +666,12 @@ int WxeApp::getRef(void * ptr, wxeMemEnv *memenv) {
ptrMap::iterator it = ptr2ref.find(ptr);
if(it != ptr2ref.end()) {
wxeRefData *refd = it->second;
- if(refd->memenv == memenv) {
+ if(refd->memenv == memenv || refd->memenv == global_me) {
// Found it return
return refd->ref;
} // else
// Old reference to deleted object, release old and recreate in current memenv.
- clearPtr(ptr);
+ ptr2ref.erase(it);
}
int ref;
intList free = memenv->free;
@@ -687,7 +700,7 @@ void WxeApp::clearPtr(void * ptr) {
if(it != ptr2ref.end()) {
wxeRefData *refd = it->second;
intList free = refd->memenv->free;
- int ref = refd->ref;
+ int ref = refd->ref;
refd->memenv->ref2ptr[ref] = NULL;
free.Append(ref);
@@ -696,7 +709,7 @@ void WxeApp::clearPtr(void * ptr) {
msg.Printf(wxT("Deleting {wx_ref, %d, unknown} at %p "), ref, ptr);
send_msg("debug", &msg);
}
-
+
if(((int) refd->pid) != -1) {
// Send terminate pid to owner
wxeReturn rt = wxeReturn(WXE_DRV_PORT,refd->memenv->owner, false);
@@ -709,30 +722,30 @@ void WxeApp::clearPtr(void * ptr) {
if(refd->type == 1 && ((wxObject*)ptr)->IsKindOf(CLASSINFO(wxSizer))) {
wxSizerItemList list = ((wxSizer*)ptr)->GetChildren();
for(wxSizerItemList::compatibility_iterator node = list.GetFirst();
- node; node = node->GetNext()) {
+ node; node = node->GetNext()) {
wxSizerItem *item = node->GetData();
wxObject *content=NULL;
- if((content = item->GetWindow()))
+ if((content = item->GetWindow()))
if(ptr2ref.end() == ptr2ref.find(content)) {
wxString msg;
wxClassInfo *cinfo = ((wxObject *)ptr)->GetClassInfo();
msg.Printf(wxT("Double usage detected of window at %p in sizer {wx_ref, %d, %s}"),
content, ref, cinfo->GetClassName());
send_msg("error", &msg);
- ((wxSizer*)ptr)->Detach((wxWindow*)content);
+ ((wxSizer*)ptr)->Detach((wxWindow*)content);
}
- if((content = item->GetSizer()))
+ if((content = item->GetSizer()))
if(ptr2ref.end() == ptr2ref.find(content)) {
wxString msg;
wxClassInfo *cinfo = ((wxObject *)ptr)->GetClassInfo();
msg.Printf(wxT("Double usage detected of sizer at %p in sizer {wx_ref, %d, %s}"),
content, ref, cinfo->GetClassName());
send_msg("error", &msg);
- ((wxSizer*)ptr)->Detach((wxSizer*)content);
+ ((wxSizer*)ptr)->Detach((wxSizer*)content);
}
}
}
-
+
delete refd;
ptr2ref.erase(it);
}
@@ -753,7 +766,7 @@ void * WxeApp::getPtr(char * bp, wxeMemEnv *memenv) {
void WxeApp::registerPid(char * bp, ErlDrvTermData pid, wxeMemEnv * memenv) {
int index = *(int *) bp;
- if(!memenv)
+ if(!memenv)
throw wxe_badarg(index);
void * temp = memenv->ref2ptr[index];
if((index < memenv->next) && ((index == 0) || (temp > NULL))) {
@@ -773,14 +786,14 @@ void WxeApp::registerPid(char * bp, ErlDrvTermData pid, wxeMemEnv * memenv) {
* Misc utility classes
* ************************************************************/
-/* ****************************************************************************
- * Memory handling
+/* ****************************************************************************
+ * Memory handling
* ****************************************************************************/
wxeMemEnv::wxeMemEnv() {
- ref2ptr = (void **) driver_alloc(128*sizeof(void *));
+ ref2ptr = (void **) driver_alloc(128*sizeof(void *));
ref2ptr[0] = NULL;
- next = 1;
+ next = 1;
max = 128;
}
@@ -788,12 +801,12 @@ wxeMemEnv::~wxeMemEnv() {
driver_free(ref2ptr);
}
-/* ****************************************************************************
+/* ****************************************************************************
* Erlang Commands (don't need to be derived of wxEvent anymore should
* be re-written to own class struct)
* ****************************************************************************/
-wxeCommand::wxeCommand(int fc,char * cbuf,int buflen, wxe_data *sd)
+wxeCommand::wxeCommand(int fc,char * cbuf,int buflen, wxe_data *sd)
: wxObject()
{
WXEBinRef *temp, *start, *prev;
@@ -809,12 +822,12 @@ wxeCommand::wxeCommand(int fc,char * cbuf,int buflen, wxe_data *sd)
if(cbuf) {
buffer = (char *) driver_alloc(len);
memcpy((void *) buffer, (void *) cbuf, len);;
-
+
temp = sd->bin;
-
+
prev = NULL;
start = temp;
-
+
while(temp) {
if(caller == temp->from) {
bin[n++] = temp;
@@ -839,7 +852,7 @@ wxeCommand::~wxeCommand() {
int n = 0;
if(buffer) {
while(bin[n]) {
- if(bin[n]->bin)
+ if(bin[n]->bin)
driver_free_binary(bin[n]->bin);
driver_free(bin[n++]);
}
@@ -847,26 +860,26 @@ wxeCommand::~wxeCommand() {
}
}
-/* ****************************************************************************
- * TreeItemData
+/* ****************************************************************************
+ * TreeItemData
* ****************************************************************************/
-wxETreeItemData::wxETreeItemData(int sz, char * data) {
+wxETreeItemData::wxETreeItemData(int sz, char * data) {
size = sz;
bin = (char *) driver_alloc(sz);
memcpy(bin, data, sz);
}
-wxETreeItemData::~wxETreeItemData()
+wxETreeItemData::~wxETreeItemData()
{
driver_free(bin);
}
-/* ****************************************************************************
+/* ****************************************************************************
* CallbackData *
* ****************************************************************************/
-wxeCallbackData::wxeCallbackData(ErlDrvTermData caller,void * req, char *req_type,
+wxeCallbackData::wxeCallbackData(ErlDrvTermData caller,void * req, char *req_type,
int funcb, int skip_ev, wxeErlTerm * userData)
: wxObject()
{
@@ -893,8 +906,6 @@ int wxCALLBACK wxEListCtrlCompare(long item1, long item2, long callbackInfoPtr)
{
callbackInfo * cb = (callbackInfo *)callbackInfoPtr;
wxeMemEnv * memenv = ((WxeApp *) wxTheApp)->getMemEnv(cb->port);
- char * bp = ((WxeApp *) wxTheApp)->cb_buff;
-
wxeReturn rt = wxeReturn(WXE_DRV_PORT, memenv->owner, false);
rt.addInt(cb->callbackID);
rt.addInt(item1);
@@ -903,6 +914,13 @@ int wxCALLBACK wxEListCtrlCompare(long item1, long item2, long callbackInfoPtr)
rt.addAtom("_wx_invoke_cb_");
rt.addTupleCount(3);
rt.send();
- handle_callback_batch(cb->port);
- return *(int*) bp;
+ handle_event_callback(cb->port, memenv->owner);
+
+ if(((WxeApp *) wxTheApp)->cb_buff) {
+ int res = * (int*) ((WxeApp *) wxTheApp)->cb_buff;
+ driver_free(((WxeApp *) wxTheApp)->cb_buff);
+ ((WxeApp *) wxTheApp)->cb_buff = NULL;
+ return res;
+ }
+ return 0;
}
diff --git a/lib/wx/c_src/wxe_impl.h b/lib/wx/c_src/wxe_impl.h
index 39c02f8c1a..ee31068d5d 100644
--- a/lib/wx/c_src/wxe_impl.h
+++ b/lib/wx/c_src/wxe_impl.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -178,7 +178,8 @@ public:
wxeMemEnv * global_me;
// Temp container for callbacks
- char cb_buff[256];
+ char *cb_buff;
+ int cb_len;
};
class wxETreeItemData : public wxTreeItemData
@@ -194,7 +195,6 @@ class wxETreeItemData : public wxTreeItemData
bool sendevent(wxEvent * event, ErlDrvPort port);
void pre_callback();
-void handle_callback_batch(ErlDrvPort port); // For wxePrintout
void handle_event_callback(ErlDrvPort port, ErlDrvTermData process);
void activateGL(ErlDrvTermData caller);
@@ -232,8 +232,6 @@ class wxEPrintout : public wxPrintout
bool OnPrintPage(int page);
void GetPageInfo(int *minPage, int *maxPage, int *pageFrom, int *pageTo);
- void clear_cb(int callback);
-
int onPrintPage;
int onPreparePrinting;
int onBeginPrinting;
@@ -246,6 +244,9 @@ class wxEPrintout : public wxPrintout
ErlDrvPort port;
};
+void clear_cb(ErlDrvPort port, int callback);
+
+
// Implementation of wxListCtrlCompare
struct callbackInfo {
ErlDrvPort port;
diff --git a/lib/wx/doc/src/make.dep b/lib/wx/doc/src/make.dep
deleted file mode 100644
index 91001be438..0000000000
--- a/lib/wx/doc/src/make.dep
+++ /dev/null
@@ -1,13 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex chapter.tex part.tex
-
diff --git a/lib/wx/doc/src/notes.xml b/lib/wx/doc/src/notes.xml
index 26d1f892b2..7bd8d18592 100644
--- a/lib/wx/doc/src/notes.xml
+++ b/lib/wx/doc/src/notes.xml
@@ -31,6 +31,39 @@
<p>This document describes the changes made to the wxErlang
application.</p>
+<section><title>Wx 0.99</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ wx: fix obsolete guard warning (list/1) (Thanks to Tuncer
+ Ayaz)</p>
+ <p>
+ Own Id: OTP-9513</p>
+ </item>
+ <item>
+ <p> XML files have been corrected. </p>
+ <p>
+ Own Id: OTP-9550 Aux Id: OTP-9541 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Support virtual tables in wxListCtrl.</p>
+ <p>
+ Own Id: OTP-9415</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Wx 0.98.10</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/wx/examples/demo/Makefile b/lib/wx/examples/demo/Makefile
index 98d7c6a130..8afa0e780e 100755..100644
--- a/lib/wx/examples/demo/Makefile
+++ b/lib/wx/examples/demo/Makefile
@@ -80,7 +80,7 @@ include $(ERL_TOP)/make/otp_release_targets.mk
docs:
-release_spec:
+release_spec: opt
$(INSTALL_DIR) $(EXRELSYSDIR)
$(INSTALL_DATA) $(TESTSRC) $(EXRELSYSDIR)
$(INSTALL_DATA) $(TESTTARGETS) $(EXRELSYSDIR)
diff --git a/lib/wx/examples/demo/ex_listCtrl.erl b/lib/wx/examples/demo/ex_listCtrl.erl
index c574c7247a..3faec4e229 100644
--- a/lib/wx/examples/demo/ex_listCtrl.erl
+++ b/lib/wx/examples/demo/ex_listCtrl.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
-module(ex_listCtrl).
@@ -25,7 +25,7 @@
-export([start/1, init/1, terminate/2, code_change/3,
handle_info/2, handle_call/3, handle_event/2]).
--record(state,
+-record(state,
{
parent,
config,
@@ -40,11 +40,11 @@ init(Config) ->
wx:batch(fun() -> do_init(Config) end).
do_init(Config) ->
- Parent = proplists:get_value(parent, Config),
+ Parent = proplists:get_value(parent, Config),
Panel = wxPanel:new(Parent, []),
%% Setup sizers
- MainSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ MainSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
[{label, "wxListCtrl"}]),
Notebook = wxNotebook:new(Panel, 1, [{style, ?wxBK_DEFAULT}]),
@@ -81,14 +81,46 @@ do_init(Config) ->
wxListCtrl:setItemBackgroundColour(ListCtrl3,3,?wxGREEN),
wxListCtrl:setItemBackgroundColour(ListCtrl3,0,?wxCYAN),
+ IA = wxListItemAttr:new(),
+ wxListItemAttr:setTextColour(IA, {190, 25, 25}),
+ LC4Opts = [{style, ?wxLC_REPORT bor ?wxLC_VIRTUAL},
+ {onGetItemText, fun(_This, Item, 0) ->
+ "Row " ++ integer_to_list(Item);
+ (_, Item, 1) when Item rem 5 == 0 ->
+ "Column 2";
+ (_, _, _) -> ""
+ end},
+ {onGetItemAttr, fun(_This, Item) when Item rem 3 == 0 ->
+ IA;
+ (_This, _Item) ->
+ wx:typeCast(wx:null(), wxListItemAttr)
+ end},
+ {onGetItemColumnImage, fun(_This, Item, 1) ->
+ Item rem 4;
+ (_, _, _) ->
+ -1
+ end}
+ ],
+ ListCtrl4 = wxListCtrl:new(Notebook, LC4Opts),
+ wxListCtrl:setImageList(ListCtrl4, IL, ?wxIMAGE_LIST_SMALL),
+
+ wxListCtrl:insertColumn(ListCtrl4, 0, "Column 1"),
+ wxListCtrl:insertColumn(ListCtrl4, 1, "Column 2"),
+ wxListCtrl:setColumnWidth(ListCtrl4, 0, 200),
+ wxListCtrl:setColumnWidth(ListCtrl4, 1, 200),
+ wxListCtrl:setItemCount(ListCtrl4, 1000000),
+
+
wxListCtrl:connect(ListCtrl1, command_list_item_selected, []),
wxListCtrl:connect(ListCtrl2, command_list_item_selected, []),
wxListCtrl:connect(ListCtrl3, command_list_item_selected, []),
+ wxListCtrl:connect(ListCtrl4, command_list_item_selected, []),
%% Add to sizers
wxNotebook:addPage(Notebook, ListCtrl1, "List", []),
wxNotebook:addPage(Notebook, ListCtrl2, "Report", []),
wxNotebook:addPage(Notebook, ListCtrl3, "Colored multiselect", []),
+ wxNotebook:addPage(Notebook, ListCtrl4, "Virtual Report", []),
wxSizer:add(MainSizer, Notebook, [{proportion, 1},
{flag, ?wxEXPAND}]),
@@ -145,4 +177,4 @@ create_list_ctrl(Win, Options) ->
ListCtrl.
-
+
diff --git a/lib/wx/examples/simple/Makefile b/lib/wx/examples/simple/Makefile
index 41f0b46eb1..66f5952f0d 100644
--- a/lib/wx/examples/simple/Makefile
+++ b/lib/wx/examples/simple/Makefile
@@ -51,7 +51,7 @@ include $(ERL_TOP)/make/otp_release_targets.mk
docs:
-release_spec:
+release_spec: opt
$(INSTALL_DIR) $(EXRELSYSDIR)
$(INSTALL_DATA) $(TESTSRC) $(EXRELSYSDIR)
$(INSTALL_DATA) copy.xpm sample.xpm $(TESTTARGETS) $(EXRELSYSDIR)
diff --git a/lib/wx/examples/simple/hello.erl b/lib/wx/examples/simple/hello.erl
index dc845ddfbb..dc845ddfbb 100755..100644
--- a/lib/wx/examples/simple/hello.erl
+++ b/lib/wx/examples/simple/hello.erl
diff --git a/lib/wx/examples/simple/menu.erl b/lib/wx/examples/simple/menu.erl
index d573fcf13a..d573fcf13a 100755..100644
--- a/lib/wx/examples/simple/menu.erl
+++ b/lib/wx/examples/simple/menu.erl
diff --git a/lib/wx/examples/simple/minimal.erl b/lib/wx/examples/simple/minimal.erl
index dca4adc643..dca4adc643 100755..100644
--- a/lib/wx/examples/simple/minimal.erl
+++ b/lib/wx/examples/simple/minimal.erl
diff --git a/lib/wx/examples/simple/sample.xpm b/lib/wx/examples/simple/sample.xpm
index 3263b15f8a..3263b15f8a 100755..100644
--- a/lib/wx/examples/simple/sample.xpm
+++ b/lib/wx/examples/simple/sample.xpm
diff --git a/lib/wx/examples/sudoku/Makefile b/lib/wx/examples/sudoku/Makefile
index b86c654fdd..33725756b7 100755..100644
--- a/lib/wx/examples/sudoku/Makefile
+++ b/lib/wx/examples/sudoku/Makefile
@@ -51,7 +51,7 @@ include $(ERL_TOP)/make/otp_release_targets.mk
docs:
-release_spec:
+release_spec: opt
$(INSTALL_DIR) $(EXRELSYSDIR)
$(INSTALL_DATA) $(TESTSRC) sudoku.hrl $(EXRELSYSDIR)
$(INSTALL_DATA) $(TESTTARGETS) $(EXRELSYSDIR)
diff --git a/lib/wx/examples/sudoku/sudoku.erl b/lib/wx/examples/sudoku/sudoku.erl
index 01caeb9524..01caeb9524 100755..100644
--- a/lib/wx/examples/sudoku/sudoku.erl
+++ b/lib/wx/examples/sudoku/sudoku.erl
diff --git a/lib/wx/examples/sudoku/sudoku.hrl b/lib/wx/examples/sudoku/sudoku.hrl
index 775b563bdc..775b563bdc 100755..100644
--- a/lib/wx/examples/sudoku/sudoku.hrl
+++ b/lib/wx/examples/sudoku/sudoku.hrl
diff --git a/lib/wx/examples/sudoku/sudoku_board.erl b/lib/wx/examples/sudoku/sudoku_board.erl
index 756837582f..756837582f 100755..100644
--- a/lib/wx/examples/sudoku/sudoku_board.erl
+++ b/lib/wx/examples/sudoku/sudoku_board.erl
diff --git a/lib/wx/examples/sudoku/sudoku_game.erl b/lib/wx/examples/sudoku/sudoku_game.erl
index 470aee0e3b..470aee0e3b 100755..100644
--- a/lib/wx/examples/sudoku/sudoku_game.erl
+++ b/lib/wx/examples/sudoku/sudoku_game.erl
diff --git a/lib/wx/examples/sudoku/sudoku_gui.erl b/lib/wx/examples/sudoku/sudoku_gui.erl
index 4aaecfe086..4aaecfe086 100755..100644
--- a/lib/wx/examples/sudoku/sudoku_gui.erl
+++ b/lib/wx/examples/sudoku/sudoku_gui.erl
diff --git a/lib/wx/examples/xrc/Makefile b/lib/wx/examples/xrc/Makefile
index 1dfaae9689..aba58e0d0f 100755..100644
--- a/lib/wx/examples/xrc/Makefile
+++ b/lib/wx/examples/xrc/Makefile
@@ -28,7 +28,8 @@ TESTMODS = xrc
TESTTARGETS = $(TESTMODS:%=%.beam)
TESTSRC = $(TESTMODS:%=%.erl)
-RESOURCEFILES = appicon.ico basicdlg.xpm custclas.xpm fileopen.gif menu.xrc \
+RESOURCEFILES = \
+ appicon.ico basicdlg.xpm custclas.xpm fileopen.gif menu.xrc \
resource.xrc uncenter.xpm variable.xrc appicon.xpm basicdlg.xrc \
custclas.xrc filesave.gif platform.xpm stop.xpm uncenter.xrc \
artprov.xpm controls.xpm derivdlg.xpm frame.xrc platform.xrc \
@@ -59,7 +60,7 @@ include $(ERL_TOP)/make/otp_release_targets.mk
docs:
-release_spec:
+release_spec: opt
$(INSTALL_DIR) $(EXRELSYSDIR)
$(INSTALL_DATA) $(TESTSRC) $(EXRELSYSDIR)
$(INSTALL_DATA) $(TESTTARGETS) $(EXRELSYSDIR)
diff --git a/lib/wx/include/gl.hrl b/lib/wx/include/gl.hrl
index 52f2635af9..54eb551285 100644
--- a/lib/wx/include/gl.hrl
+++ b/lib/wx/include/gl.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -21,32 +21,22 @@
%% This file is generated DO NOT EDIT
-define(GL_VERSION_1_1, 1).
--define(GL_CURRENT_BIT, 16#1).
--define(GL_POINT_BIT, 16#2).
--define(GL_LINE_BIT, 16#4).
--define(GL_POLYGON_BIT, 16#8).
--define(GL_POLYGON_STIPPLE_BIT, 16#10).
--define(GL_PIXEL_MODE_BIT, 16#20).
--define(GL_LIGHTING_BIT, 16#40).
--define(GL_FOG_BIT, 16#80).
--define(GL_DEPTH_BUFFER_BIT, 16#100).
--define(GL_ACCUM_BUFFER_BIT, 16#200).
--define(GL_STENCIL_BUFFER_BIT, 16#400).
--define(GL_VIEWPORT_BIT, 16#800).
--define(GL_TRANSFORM_BIT, 16#1000).
--define(GL_ENABLE_BIT, 16#2000).
--define(GL_COLOR_BUFFER_BIT, 16#4000).
--define(GL_HINT_BIT, 16#8000).
--define(GL_EVAL_BIT, 16#10000).
--define(GL_LIST_BIT, 16#20000).
--define(GL_TEXTURE_BIT, 16#40000).
--define(GL_SCISSOR_BIT, 16#80000).
--define(GL_ALL_ATTRIB_BITS, 16#FFFFFFFF).
--define(GL_CLIENT_PIXEL_STORE_BIT, 16#1).
--define(GL_CLIENT_VERTEX_ARRAY_BIT, 16#2).
--define(GL_CLIENT_ALL_ATTRIB_BITS, 16#FFFFFFFF).
--define(GL_FALSE, 0).
--define(GL_TRUE, 1).
+-define(GL_VERSION_1_2, 1).
+-define(GL_VERSION_1_3, 1).
+-define(GL_ARB_imaging, 1).
+-define(GL_FALSE, 16#0).
+-define(GL_TRUE, 16#1).
+-define(GL_BYTE, 16#1400).
+-define(GL_UNSIGNED_BYTE, 16#1401).
+-define(GL_SHORT, 16#1402).
+-define(GL_UNSIGNED_SHORT, 16#1403).
+-define(GL_INT, 16#1404).
+-define(GL_UNSIGNED_INT, 16#1405).
+-define(GL_FLOAT, 16#1406).
+-define(GL_2_BYTES, 16#1407).
+-define(GL_3_BYTES, 16#1408).
+-define(GL_4_BYTES, 16#1409).
+-define(GL_DOUBLE, 16#140A).
-define(GL_POINTS, 16#0).
-define(GL_LINES, 16#1).
-define(GL_LINE_LOOP, 16#2).
@@ -57,11 +47,85 @@
-define(GL_QUADS, 16#7).
-define(GL_QUAD_STRIP, 16#8).
-define(GL_POLYGON, 16#9).
--define(GL_ACCUM, 16#100).
--define(GL_LOAD, 16#101).
--define(GL_RETURN, 16#102).
--define(GL_MULT, 16#103).
--define(GL_ADD, 16#104).
+-define(GL_VERTEX_ARRAY, 16#8074).
+-define(GL_NORMAL_ARRAY, 16#8075).
+-define(GL_COLOR_ARRAY, 16#8076).
+-define(GL_INDEX_ARRAY, 16#8077).
+-define(GL_TEXTURE_COORD_ARRAY, 16#8078).
+-define(GL_EDGE_FLAG_ARRAY, 16#8079).
+-define(GL_VERTEX_ARRAY_SIZE, 16#807A).
+-define(GL_VERTEX_ARRAY_TYPE, 16#807B).
+-define(GL_VERTEX_ARRAY_STRIDE, 16#807C).
+-define(GL_NORMAL_ARRAY_TYPE, 16#807E).
+-define(GL_NORMAL_ARRAY_STRIDE, 16#807F).
+-define(GL_COLOR_ARRAY_SIZE, 16#8081).
+-define(GL_COLOR_ARRAY_TYPE, 16#8082).
+-define(GL_COLOR_ARRAY_STRIDE, 16#8083).
+-define(GL_INDEX_ARRAY_TYPE, 16#8085).
+-define(GL_INDEX_ARRAY_STRIDE, 16#8086).
+-define(GL_TEXTURE_COORD_ARRAY_SIZE, 16#8088).
+-define(GL_TEXTURE_COORD_ARRAY_TYPE, 16#8089).
+-define(GL_TEXTURE_COORD_ARRAY_STRIDE, 16#808A).
+-define(GL_EDGE_FLAG_ARRAY_STRIDE, 16#808C).
+-define(GL_VERTEX_ARRAY_POINTER, 16#808E).
+-define(GL_NORMAL_ARRAY_POINTER, 16#808F).
+-define(GL_COLOR_ARRAY_POINTER, 16#8090).
+-define(GL_INDEX_ARRAY_POINTER, 16#8091).
+-define(GL_TEXTURE_COORD_ARRAY_POINTER, 16#8092).
+-define(GL_EDGE_FLAG_ARRAY_POINTER, 16#8093).
+-define(GL_V2F, 16#2A20).
+-define(GL_V3F, 16#2A21).
+-define(GL_C4UB_V2F, 16#2A22).
+-define(GL_C4UB_V3F, 16#2A23).
+-define(GL_C3F_V3F, 16#2A24).
+-define(GL_N3F_V3F, 16#2A25).
+-define(GL_C4F_N3F_V3F, 16#2A26).
+-define(GL_T2F_V3F, 16#2A27).
+-define(GL_T4F_V4F, 16#2A28).
+-define(GL_T2F_C4UB_V3F, 16#2A29).
+-define(GL_T2F_C3F_V3F, 16#2A2A).
+-define(GL_T2F_N3F_V3F, 16#2A2B).
+-define(GL_T2F_C4F_N3F_V3F, 16#2A2C).
+-define(GL_T4F_C4F_N3F_V4F, 16#2A2D).
+-define(GL_MATRIX_MODE, 16#BA0).
+-define(GL_MODELVIEW, 16#1700).
+-define(GL_PROJECTION, 16#1701).
+-define(GL_TEXTURE, 16#1702).
+-define(GL_POINT_SMOOTH, 16#B10).
+-define(GL_POINT_SIZE, 16#B11).
+-define(GL_POINT_SIZE_GRANULARITY, 16#B13).
+-define(GL_POINT_SIZE_RANGE, 16#B12).
+-define(GL_LINE_SMOOTH, 16#B20).
+-define(GL_LINE_STIPPLE, 16#B24).
+-define(GL_LINE_STIPPLE_PATTERN, 16#B25).
+-define(GL_LINE_STIPPLE_REPEAT, 16#B26).
+-define(GL_LINE_WIDTH, 16#B21).
+-define(GL_LINE_WIDTH_GRANULARITY, 16#B23).
+-define(GL_LINE_WIDTH_RANGE, 16#B22).
+-define(GL_POINT, 16#1B00).
+-define(GL_LINE, 16#1B01).
+-define(GL_FILL, 16#1B02).
+-define(GL_CW, 16#900).
+-define(GL_CCW, 16#901).
+-define(GL_FRONT, 16#404).
+-define(GL_BACK, 16#405).
+-define(GL_POLYGON_MODE, 16#B40).
+-define(GL_POLYGON_SMOOTH, 16#B41).
+-define(GL_POLYGON_STIPPLE, 16#B42).
+-define(GL_EDGE_FLAG, 16#B43).
+-define(GL_CULL_FACE, 16#B44).
+-define(GL_CULL_FACE_MODE, 16#B45).
+-define(GL_FRONT_FACE, 16#B46).
+-define(GL_POLYGON_OFFSET_FACTOR, 16#8038).
+-define(GL_POLYGON_OFFSET_UNITS, 16#2A00).
+-define(GL_POLYGON_OFFSET_POINT, 16#2A01).
+-define(GL_POLYGON_OFFSET_LINE, 16#2A02).
+-define(GL_POLYGON_OFFSET_FILL, 16#8037).
+-define(GL_COMPILE, 16#1300).
+-define(GL_COMPILE_AND_EXECUTE, 16#1301).
+-define(GL_LIST_BASE, 16#B32).
+-define(GL_LIST_INDEX, 16#B33).
+-define(GL_LIST_MODE, 16#B30).
-define(GL_NEVER, 16#200).
-define(GL_LESS, 16#201).
-define(GL_EQUAL, 16#202).
@@ -70,8 +134,71 @@
-define(GL_NOTEQUAL, 16#205).
-define(GL_GEQUAL, 16#206).
-define(GL_ALWAYS, 16#207).
--define(GL_ZERO, 0).
--define(GL_ONE, 1).
+-define(GL_DEPTH_TEST, 16#B71).
+-define(GL_DEPTH_BITS, 16#D56).
+-define(GL_DEPTH_CLEAR_VALUE, 16#B73).
+-define(GL_DEPTH_FUNC, 16#B74).
+-define(GL_DEPTH_RANGE, 16#B70).
+-define(GL_DEPTH_WRITEMASK, 16#B72).
+-define(GL_DEPTH_COMPONENT, 16#1902).
+-define(GL_LIGHTING, 16#B50).
+-define(GL_LIGHT0, 16#4000).
+-define(GL_LIGHT1, 16#4001).
+-define(GL_LIGHT2, 16#4002).
+-define(GL_LIGHT3, 16#4003).
+-define(GL_LIGHT4, 16#4004).
+-define(GL_LIGHT5, 16#4005).
+-define(GL_LIGHT6, 16#4006).
+-define(GL_LIGHT7, 16#4007).
+-define(GL_SPOT_EXPONENT, 16#1205).
+-define(GL_SPOT_CUTOFF, 16#1206).
+-define(GL_CONSTANT_ATTENUATION, 16#1207).
+-define(GL_LINEAR_ATTENUATION, 16#1208).
+-define(GL_QUADRATIC_ATTENUATION, 16#1209).
+-define(GL_AMBIENT, 16#1200).
+-define(GL_DIFFUSE, 16#1201).
+-define(GL_SPECULAR, 16#1202).
+-define(GL_SHININESS, 16#1601).
+-define(GL_EMISSION, 16#1600).
+-define(GL_POSITION, 16#1203).
+-define(GL_SPOT_DIRECTION, 16#1204).
+-define(GL_AMBIENT_AND_DIFFUSE, 16#1602).
+-define(GL_COLOR_INDEXES, 16#1603).
+-define(GL_LIGHT_MODEL_TWO_SIDE, 16#B52).
+-define(GL_LIGHT_MODEL_LOCAL_VIEWER, 16#B51).
+-define(GL_LIGHT_MODEL_AMBIENT, 16#B53).
+-define(GL_FRONT_AND_BACK, 16#408).
+-define(GL_SHADE_MODEL, 16#B54).
+-define(GL_FLAT, 16#1D00).
+-define(GL_SMOOTH, 16#1D01).
+-define(GL_COLOR_MATERIAL, 16#B57).
+-define(GL_COLOR_MATERIAL_FACE, 16#B55).
+-define(GL_COLOR_MATERIAL_PARAMETER, 16#B56).
+-define(GL_NORMALIZE, 16#BA1).
+-define(GL_CLIP_PLANE0, 16#3000).
+-define(GL_CLIP_PLANE1, 16#3001).
+-define(GL_CLIP_PLANE2, 16#3002).
+-define(GL_CLIP_PLANE3, 16#3003).
+-define(GL_CLIP_PLANE4, 16#3004).
+-define(GL_CLIP_PLANE5, 16#3005).
+-define(GL_ACCUM_RED_BITS, 16#D58).
+-define(GL_ACCUM_GREEN_BITS, 16#D59).
+-define(GL_ACCUM_BLUE_BITS, 16#D5A).
+-define(GL_ACCUM_ALPHA_BITS, 16#D5B).
+-define(GL_ACCUM_CLEAR_VALUE, 16#B80).
+-define(GL_ACCUM, 16#100).
+-define(GL_ADD, 16#104).
+-define(GL_LOAD, 16#101).
+-define(GL_MULT, 16#103).
+-define(GL_RETURN, 16#102).
+-define(GL_ALPHA_TEST, 16#BC0).
+-define(GL_ALPHA_TEST_REF, 16#BC2).
+-define(GL_ALPHA_TEST_FUNC, 16#BC1).
+-define(GL_BLEND, 16#BE2).
+-define(GL_BLEND_SRC, 16#BE1).
+-define(GL_BLEND_DST, 16#BE0).
+-define(GL_ZERO, 16#0).
+-define(GL_ONE, 16#1).
-define(GL_SRC_COLOR, 16#300).
-define(GL_ONE_MINUS_SRC_COLOR, 16#301).
-define(GL_SRC_ALPHA, 16#302).
@@ -81,121 +208,58 @@
-define(GL_DST_COLOR, 16#306).
-define(GL_ONE_MINUS_DST_COLOR, 16#307).
-define(GL_SRC_ALPHA_SATURATE, 16#308).
--define(GL_NONE, 0).
--define(GL_FRONT_LEFT, 16#400).
--define(GL_FRONT_RIGHT, 16#401).
--define(GL_BACK_LEFT, 16#402).
--define(GL_BACK_RIGHT, 16#403).
--define(GL_FRONT, 16#404).
--define(GL_BACK, 16#405).
--define(GL_LEFT, 16#406).
--define(GL_RIGHT, 16#407).
--define(GL_FRONT_AND_BACK, 16#408).
--define(GL_AUX0, 16#409).
--define(GL_AUX1, 16#40A).
--define(GL_AUX2, 16#40B).
--define(GL_AUX3, 16#40C).
--define(GL_NO_ERROR, 0).
--define(GL_INVALID_ENUM, 16#500).
--define(GL_INVALID_VALUE, 16#501).
--define(GL_INVALID_OPERATION, 16#502).
--define(GL_STACK_OVERFLOW, 16#503).
--define(GL_STACK_UNDERFLOW, 16#504).
--define(GL_OUT_OF_MEMORY, 16#505).
--define(GL_TABLE_TOO_LARGE, 16#8031).
+-define(GL_FEEDBACK, 16#1C01).
+-define(GL_RENDER, 16#1C00).
+-define(GL_SELECT, 16#1C02).
-define(GL_2D, 16#600).
-define(GL_3D, 16#601).
-define(GL_3D_COLOR, 16#602).
-define(GL_3D_COLOR_TEXTURE, 16#603).
-define(GL_4D_COLOR_TEXTURE, 16#604).
--define(GL_PASS_THROUGH_TOKEN, 16#700).
-define(GL_POINT_TOKEN, 16#701).
-define(GL_LINE_TOKEN, 16#702).
+-define(GL_LINE_RESET_TOKEN, 16#707).
-define(GL_POLYGON_TOKEN, 16#703).
-define(GL_BITMAP_TOKEN, 16#704).
-define(GL_DRAW_PIXEL_TOKEN, 16#705).
-define(GL_COPY_PIXEL_TOKEN, 16#706).
--define(GL_LINE_RESET_TOKEN, 16#707).
--define(GL_EXP, 16#800).
--define(GL_EXP2, 16#801).
--define(GL_CW, 16#900).
--define(GL_CCW, 16#901).
--define(GL_COEFF, 16#A00).
--define(GL_ORDER, 16#A01).
--define(GL_DOMAIN, 16#A02).
--define(GL_PIXEL_MAP_I_TO_I, 16#C70).
--define(GL_PIXEL_MAP_S_TO_S, 16#C71).
--define(GL_PIXEL_MAP_I_TO_R, 16#C72).
--define(GL_PIXEL_MAP_I_TO_G, 16#C73).
--define(GL_PIXEL_MAP_I_TO_B, 16#C74).
--define(GL_PIXEL_MAP_I_TO_A, 16#C75).
--define(GL_PIXEL_MAP_R_TO_R, 16#C76).
--define(GL_PIXEL_MAP_G_TO_G, 16#C77).
--define(GL_PIXEL_MAP_B_TO_B, 16#C78).
--define(GL_PIXEL_MAP_A_TO_A, 16#C79).
--define(GL_VERTEX_ARRAY_POINTER, 16#808E).
--define(GL_NORMAL_ARRAY_POINTER, 16#808F).
--define(GL_COLOR_ARRAY_POINTER, 16#8090).
--define(GL_INDEX_ARRAY_POINTER, 16#8091).
--define(GL_TEXTURE_COORD_ARRAY_POINTER, 16#8092).
--define(GL_EDGE_FLAG_ARRAY_POINTER, 16#8093).
--define(GL_CURRENT_COLOR, 16#B00).
--define(GL_CURRENT_INDEX, 16#B01).
--define(GL_CURRENT_NORMAL, 16#B02).
--define(GL_CURRENT_TEXTURE_COORDS, 16#B03).
--define(GL_CURRENT_RASTER_COLOR, 16#B04).
--define(GL_CURRENT_RASTER_INDEX, 16#B05).
--define(GL_CURRENT_RASTER_TEXTURE_COORDS, 16#B06).
--define(GL_CURRENT_RASTER_POSITION, 16#B07).
--define(GL_CURRENT_RASTER_POSITION_VALID, 16#B08).
--define(GL_CURRENT_RASTER_DISTANCE, 16#B09).
--define(GL_POINT_SMOOTH, 16#B10).
--define(GL_POINT_SIZE, 16#B11).
--define(GL_SMOOTH_POINT_SIZE_RANGE, 16#B12).
--define(GL_SMOOTH_POINT_SIZE_GRANULARITY, 16#B13).
--define(GL_POINT_SIZE_RANGE, ?GL_SMOOTH_POINT_SIZE_RANGE).
--define(GL_POINT_SIZE_GRANULARITY, ?GL_SMOOTH_POINT_SIZE_GRANULARITY).
--define(GL_LINE_SMOOTH, 16#B20).
--define(GL_LINE_WIDTH, 16#B21).
--define(GL_SMOOTH_LINE_WIDTH_RANGE, 16#B22).
--define(GL_SMOOTH_LINE_WIDTH_GRANULARITY, 16#B23).
--define(GL_LINE_WIDTH_RANGE, ?GL_SMOOTH_LINE_WIDTH_RANGE).
--define(GL_LINE_WIDTH_GRANULARITY, ?GL_SMOOTH_LINE_WIDTH_GRANULARITY).
--define(GL_LINE_STIPPLE, 16#B24).
--define(GL_LINE_STIPPLE_PATTERN, 16#B25).
--define(GL_LINE_STIPPLE_REPEAT, 16#B26).
--define(GL_LIST_MODE, 16#B30).
--define(GL_MAX_LIST_NESTING, 16#B31).
--define(GL_LIST_BASE, 16#B32).
--define(GL_LIST_INDEX, 16#B33).
--define(GL_POLYGON_MODE, 16#B40).
--define(GL_POLYGON_SMOOTH, 16#B41).
--define(GL_POLYGON_STIPPLE, 16#B42).
--define(GL_EDGE_FLAG, 16#B43).
--define(GL_CULL_FACE, 16#B44).
--define(GL_CULL_FACE_MODE, 16#B45).
--define(GL_FRONT_FACE, 16#B46).
--define(GL_LIGHTING, 16#B50).
--define(GL_LIGHT_MODEL_LOCAL_VIEWER, 16#B51).
--define(GL_LIGHT_MODEL_TWO_SIDE, 16#B52).
--define(GL_LIGHT_MODEL_AMBIENT, 16#B53).
--define(GL_SHADE_MODEL, 16#B54).
--define(GL_COLOR_MATERIAL_FACE, 16#B55).
--define(GL_COLOR_MATERIAL_PARAMETER, 16#B56).
--define(GL_COLOR_MATERIAL, 16#B57).
+-define(GL_PASS_THROUGH_TOKEN, 16#700).
+-define(GL_FEEDBACK_BUFFER_POINTER, 16#DF0).
+-define(GL_FEEDBACK_BUFFER_SIZE, 16#DF1).
+-define(GL_FEEDBACK_BUFFER_TYPE, 16#DF2).
+-define(GL_SELECTION_BUFFER_POINTER, 16#DF3).
+-define(GL_SELECTION_BUFFER_SIZE, 16#DF4).
-define(GL_FOG, 16#B60).
--define(GL_FOG_INDEX, 16#B61).
+-define(GL_FOG_MODE, 16#B65).
-define(GL_FOG_DENSITY, 16#B62).
+-define(GL_FOG_COLOR, 16#B66).
+-define(GL_FOG_INDEX, 16#B61).
-define(GL_FOG_START, 16#B63).
-define(GL_FOG_END, 16#B64).
--define(GL_FOG_MODE, 16#B65).
--define(GL_FOG_COLOR, 16#B66).
--define(GL_DEPTH_RANGE, 16#B70).
--define(GL_DEPTH_TEST, 16#B71).
--define(GL_DEPTH_WRITEMASK, 16#B72).
--define(GL_DEPTH_CLEAR_VALUE, 16#B73).
--define(GL_DEPTH_FUNC, 16#B74).
--define(GL_ACCUM_CLEAR_VALUE, 16#B80).
+-define(GL_LINEAR, 16#2601).
+-define(GL_EXP, 16#800).
+-define(GL_EXP2, 16#801).
+-define(GL_LOGIC_OP, 16#BF1).
+-define(GL_INDEX_LOGIC_OP, 16#BF1).
+-define(GL_COLOR_LOGIC_OP, 16#BF2).
+-define(GL_LOGIC_OP_MODE, 16#BF0).
+-define(GL_CLEAR, 16#1500).
+-define(GL_SET, 16#150F).
+-define(GL_COPY, 16#1503).
+-define(GL_COPY_INVERTED, 16#150C).
+-define(GL_NOOP, 16#1505).
+-define(GL_INVERT, 16#150A).
+-define(GL_AND, 16#1501).
+-define(GL_NAND, 16#150E).
+-define(GL_OR, 16#1507).
+-define(GL_NOR, 16#1508).
+-define(GL_XOR, 16#1506).
+-define(GL_EQUIV, 16#1509).
+-define(GL_AND_REVERSE, 16#1502).
+-define(GL_AND_INVERTED, 16#1504).
+-define(GL_OR_REVERSE, 16#150B).
+-define(GL_OR_INVERTED, 16#150D).
+-define(GL_STENCIL_BITS, 16#D57).
-define(GL_STENCIL_TEST, 16#B90).
-define(GL_STENCIL_CLEAR_VALUE, 16#B91).
-define(GL_STENCIL_FUNC, 16#B92).
@@ -205,89 +269,48 @@
-define(GL_STENCIL_PASS_DEPTH_PASS, 16#B96).
-define(GL_STENCIL_REF, 16#B97).
-define(GL_STENCIL_WRITEMASK, 16#B98).
--define(GL_MATRIX_MODE, 16#BA0).
--define(GL_NORMALIZE, 16#BA1).
--define(GL_VIEWPORT, 16#BA2).
--define(GL_MODELVIEW_STACK_DEPTH, 16#BA3).
--define(GL_PROJECTION_STACK_DEPTH, 16#BA4).
--define(GL_TEXTURE_STACK_DEPTH, 16#BA5).
--define(GL_MODELVIEW_MATRIX, 16#BA6).
--define(GL_PROJECTION_MATRIX, 16#BA7).
--define(GL_TEXTURE_MATRIX, 16#BA8).
--define(GL_ATTRIB_STACK_DEPTH, 16#BB0).
--define(GL_CLIENT_ATTRIB_STACK_DEPTH, 16#BB1).
--define(GL_ALPHA_TEST, 16#BC0).
--define(GL_ALPHA_TEST_FUNC, 16#BC1).
--define(GL_ALPHA_TEST_REF, 16#BC2).
--define(GL_DITHER, 16#BD0).
--define(GL_BLEND_DST, 16#BE0).
--define(GL_BLEND_SRC, 16#BE1).
--define(GL_BLEND, 16#BE2).
--define(GL_LOGIC_OP_MODE, 16#BF0).
--define(GL_INDEX_LOGIC_OP, 16#BF1).
--define(GL_LOGIC_OP, ?GL_INDEX_LOGIC_OP).
--define(GL_COLOR_LOGIC_OP, 16#BF2).
+-define(GL_STENCIL_INDEX, 16#1901).
+-define(GL_KEEP, 16#1E00).
+-define(GL_REPLACE, 16#1E01).
+-define(GL_INCR, 16#1E02).
+-define(GL_DECR, 16#1E03).
+-define(GL_NONE, 16#0).
+-define(GL_LEFT, 16#406).
+-define(GL_RIGHT, 16#407).
+-define(GL_FRONT_LEFT, 16#400).
+-define(GL_FRONT_RIGHT, 16#401).
+-define(GL_BACK_LEFT, 16#402).
+-define(GL_BACK_RIGHT, 16#403).
+-define(GL_AUX0, 16#409).
+-define(GL_AUX1, 16#40A).
+-define(GL_AUX2, 16#40B).
+-define(GL_AUX3, 16#40C).
+-define(GL_COLOR_INDEX, 16#1900).
+-define(GL_RED, 16#1903).
+-define(GL_GREEN, 16#1904).
+-define(GL_BLUE, 16#1905).
+-define(GL_ALPHA, 16#1906).
+-define(GL_LUMINANCE, 16#1909).
+-define(GL_LUMINANCE_ALPHA, 16#190A).
+-define(GL_ALPHA_BITS, 16#D55).
+-define(GL_RED_BITS, 16#D52).
+-define(GL_GREEN_BITS, 16#D53).
+-define(GL_BLUE_BITS, 16#D54).
+-define(GL_INDEX_BITS, 16#D51).
+-define(GL_SUBPIXEL_BITS, 16#D50).
-define(GL_AUX_BUFFERS, 16#C00).
--define(GL_DRAW_BUFFER, 16#C01).
-define(GL_READ_BUFFER, 16#C02).
--define(GL_SCISSOR_BOX, 16#C10).
--define(GL_SCISSOR_TEST, 16#C11).
--define(GL_INDEX_CLEAR_VALUE, 16#C20).
--define(GL_INDEX_WRITEMASK, 16#C21).
--define(GL_COLOR_CLEAR_VALUE, 16#C22).
--define(GL_COLOR_WRITEMASK, 16#C23).
--define(GL_INDEX_MODE, 16#C30).
--define(GL_RGBA_MODE, 16#C31).
+-define(GL_DRAW_BUFFER, 16#C01).
-define(GL_DOUBLEBUFFER, 16#C32).
-define(GL_STEREO, 16#C33).
--define(GL_RENDER_MODE, 16#C40).
--define(GL_PERSPECTIVE_CORRECTION_HINT, 16#C50).
--define(GL_POINT_SMOOTH_HINT, 16#C51).
--define(GL_LINE_SMOOTH_HINT, 16#C52).
--define(GL_POLYGON_SMOOTH_HINT, 16#C53).
--define(GL_FOG_HINT, 16#C54).
--define(GL_TEXTURE_GEN_S, 16#C60).
--define(GL_TEXTURE_GEN_T, 16#C61).
--define(GL_TEXTURE_GEN_R, 16#C62).
--define(GL_TEXTURE_GEN_Q, 16#C63).
--define(GL_PIXEL_MAP_I_TO_I_SIZE, 16#CB0).
--define(GL_PIXEL_MAP_S_TO_S_SIZE, 16#CB1).
--define(GL_PIXEL_MAP_I_TO_R_SIZE, 16#CB2).
--define(GL_PIXEL_MAP_I_TO_G_SIZE, 16#CB3).
--define(GL_PIXEL_MAP_I_TO_B_SIZE, 16#CB4).
--define(GL_PIXEL_MAP_I_TO_A_SIZE, 16#CB5).
--define(GL_PIXEL_MAP_R_TO_R_SIZE, 16#CB6).
--define(GL_PIXEL_MAP_G_TO_G_SIZE, 16#CB7).
--define(GL_PIXEL_MAP_B_TO_B_SIZE, 16#CB8).
--define(GL_PIXEL_MAP_A_TO_A_SIZE, 16#CB9).
--define(GL_UNPACK_SWAP_BYTES, 16#CF0).
--define(GL_UNPACK_LSB_FIRST, 16#CF1).
--define(GL_UNPACK_ROW_LENGTH, 16#CF2).
--define(GL_UNPACK_SKIP_ROWS, 16#CF3).
--define(GL_UNPACK_SKIP_PIXELS, 16#CF4).
--define(GL_UNPACK_ALIGNMENT, 16#CF5).
--define(GL_PACK_SWAP_BYTES, 16#D00).
--define(GL_PACK_LSB_FIRST, 16#D01).
--define(GL_PACK_ROW_LENGTH, 16#D02).
--define(GL_PACK_SKIP_ROWS, 16#D03).
--define(GL_PACK_SKIP_PIXELS, 16#D04).
--define(GL_PACK_ALIGNMENT, 16#D05).
--define(GL_MAP_COLOR, 16#D10).
--define(GL_MAP_STENCIL, 16#D11).
--define(GL_INDEX_SHIFT, 16#D12).
--define(GL_INDEX_OFFSET, 16#D13).
--define(GL_RED_SCALE, 16#D14).
--define(GL_RED_BIAS, 16#D15).
--define(GL_ZOOM_X, 16#D16).
--define(GL_ZOOM_Y, 16#D17).
--define(GL_GREEN_SCALE, 16#D18).
--define(GL_GREEN_BIAS, 16#D19).
--define(GL_BLUE_SCALE, 16#D1A).
--define(GL_BLUE_BIAS, 16#D1B).
--define(GL_ALPHA_SCALE, 16#D1C).
--define(GL_ALPHA_BIAS, 16#D1D).
--define(GL_DEPTH_SCALE, 16#D1E).
--define(GL_DEPTH_BIAS, 16#D1F).
+-define(GL_BITMAP, 16#1A00).
+-define(GL_COLOR, 16#1800).
+-define(GL_DEPTH, 16#1801).
+-define(GL_STENCIL, 16#1802).
+-define(GL_DITHER, 16#BD0).
+-define(GL_RGB, 16#1907).
+-define(GL_RGBA, 16#1908).
+-define(GL_MAX_LIST_NESTING, 16#B31).
-define(GL_MAX_EVAL_ORDER, 16#D30).
-define(GL_MAX_LIGHTS, 16#D31).
-define(GL_MAX_CLIP_PLANES, 16#D32).
@@ -300,19 +323,33 @@
-define(GL_MAX_TEXTURE_STACK_DEPTH, 16#D39).
-define(GL_MAX_VIEWPORT_DIMS, 16#D3A).
-define(GL_MAX_CLIENT_ATTRIB_STACK_DEPTH, 16#D3B).
--define(GL_SUBPIXEL_BITS, 16#D50).
--define(GL_INDEX_BITS, 16#D51).
--define(GL_RED_BITS, 16#D52).
--define(GL_GREEN_BITS, 16#D53).
--define(GL_BLUE_BITS, 16#D54).
--define(GL_ALPHA_BITS, 16#D55).
--define(GL_DEPTH_BITS, 16#D56).
--define(GL_STENCIL_BITS, 16#D57).
--define(GL_ACCUM_RED_BITS, 16#D58).
--define(GL_ACCUM_GREEN_BITS, 16#D59).
--define(GL_ACCUM_BLUE_BITS, 16#D5A).
--define(GL_ACCUM_ALPHA_BITS, 16#D5B).
+-define(GL_ATTRIB_STACK_DEPTH, 16#BB0).
+-define(GL_CLIENT_ATTRIB_STACK_DEPTH, 16#BB1).
+-define(GL_COLOR_CLEAR_VALUE, 16#C22).
+-define(GL_COLOR_WRITEMASK, 16#C23).
+-define(GL_CURRENT_INDEX, 16#B01).
+-define(GL_CURRENT_COLOR, 16#B00).
+-define(GL_CURRENT_NORMAL, 16#B02).
+-define(GL_CURRENT_RASTER_COLOR, 16#B04).
+-define(GL_CURRENT_RASTER_DISTANCE, 16#B09).
+-define(GL_CURRENT_RASTER_INDEX, 16#B05).
+-define(GL_CURRENT_RASTER_POSITION, 16#B07).
+-define(GL_CURRENT_RASTER_TEXTURE_COORDS, 16#B06).
+-define(GL_CURRENT_RASTER_POSITION_VALID, 16#B08).
+-define(GL_CURRENT_TEXTURE_COORDS, 16#B03).
+-define(GL_INDEX_CLEAR_VALUE, 16#C20).
+-define(GL_INDEX_MODE, 16#C30).
+-define(GL_INDEX_WRITEMASK, 16#C21).
+-define(GL_MODELVIEW_MATRIX, 16#BA6).
+-define(GL_MODELVIEW_STACK_DEPTH, 16#BA3).
-define(GL_NAME_STACK_DEPTH, 16#D70).
+-define(GL_PROJECTION_MATRIX, 16#BA7).
+-define(GL_PROJECTION_STACK_DEPTH, 16#BA4).
+-define(GL_RENDER_MODE, 16#C40).
+-define(GL_RGBA_MODE, 16#C31).
+-define(GL_TEXTURE_MATRIX, 16#BA8).
+-define(GL_TEXTURE_STACK_DEPTH, 16#BA5).
+-define(GL_VIEWPORT, 16#BA2).
-define(GL_AUTO_NORMAL, 16#D80).
-define(GL_MAP1_COLOR_4, 16#D90).
-define(GL_MAP1_INDEX, 16#D91).
@@ -336,166 +373,149 @@
-define(GL_MAP1_GRID_SEGMENTS, 16#DD1).
-define(GL_MAP2_GRID_DOMAIN, 16#DD2).
-define(GL_MAP2_GRID_SEGMENTS, 16#DD3).
+-define(GL_COEFF, 16#A00).
+-define(GL_ORDER, 16#A01).
+-define(GL_DOMAIN, 16#A02).
+-define(GL_PERSPECTIVE_CORRECTION_HINT, 16#C50).
+-define(GL_POINT_SMOOTH_HINT, 16#C51).
+-define(GL_LINE_SMOOTH_HINT, 16#C52).
+-define(GL_POLYGON_SMOOTH_HINT, 16#C53).
+-define(GL_FOG_HINT, 16#C54).
+-define(GL_DONT_CARE, 16#1100).
+-define(GL_FASTEST, 16#1101).
+-define(GL_NICEST, 16#1102).
+-define(GL_SCISSOR_BOX, 16#C10).
+-define(GL_SCISSOR_TEST, 16#C11).
+-define(GL_MAP_COLOR, 16#D10).
+-define(GL_MAP_STENCIL, 16#D11).
+-define(GL_INDEX_SHIFT, 16#D12).
+-define(GL_INDEX_OFFSET, 16#D13).
+-define(GL_RED_SCALE, 16#D14).
+-define(GL_RED_BIAS, 16#D15).
+-define(GL_GREEN_SCALE, 16#D18).
+-define(GL_GREEN_BIAS, 16#D19).
+-define(GL_BLUE_SCALE, 16#D1A).
+-define(GL_BLUE_BIAS, 16#D1B).
+-define(GL_ALPHA_SCALE, 16#D1C).
+-define(GL_ALPHA_BIAS, 16#D1D).
+-define(GL_DEPTH_SCALE, 16#D1E).
+-define(GL_DEPTH_BIAS, 16#D1F).
+-define(GL_PIXEL_MAP_S_TO_S_SIZE, 16#CB1).
+-define(GL_PIXEL_MAP_I_TO_I_SIZE, 16#CB0).
+-define(GL_PIXEL_MAP_I_TO_R_SIZE, 16#CB2).
+-define(GL_PIXEL_MAP_I_TO_G_SIZE, 16#CB3).
+-define(GL_PIXEL_MAP_I_TO_B_SIZE, 16#CB4).
+-define(GL_PIXEL_MAP_I_TO_A_SIZE, 16#CB5).
+-define(GL_PIXEL_MAP_R_TO_R_SIZE, 16#CB6).
+-define(GL_PIXEL_MAP_G_TO_G_SIZE, 16#CB7).
+-define(GL_PIXEL_MAP_B_TO_B_SIZE, 16#CB8).
+-define(GL_PIXEL_MAP_A_TO_A_SIZE, 16#CB9).
+-define(GL_PIXEL_MAP_S_TO_S, 16#C71).
+-define(GL_PIXEL_MAP_I_TO_I, 16#C70).
+-define(GL_PIXEL_MAP_I_TO_R, 16#C72).
+-define(GL_PIXEL_MAP_I_TO_G, 16#C73).
+-define(GL_PIXEL_MAP_I_TO_B, 16#C74).
+-define(GL_PIXEL_MAP_I_TO_A, 16#C75).
+-define(GL_PIXEL_MAP_R_TO_R, 16#C76).
+-define(GL_PIXEL_MAP_G_TO_G, 16#C77).
+-define(GL_PIXEL_MAP_B_TO_B, 16#C78).
+-define(GL_PIXEL_MAP_A_TO_A, 16#C79).
+-define(GL_PACK_ALIGNMENT, 16#D05).
+-define(GL_PACK_LSB_FIRST, 16#D01).
+-define(GL_PACK_ROW_LENGTH, 16#D02).
+-define(GL_PACK_SKIP_PIXELS, 16#D04).
+-define(GL_PACK_SKIP_ROWS, 16#D03).
+-define(GL_PACK_SWAP_BYTES, 16#D00).
+-define(GL_UNPACK_ALIGNMENT, 16#CF5).
+-define(GL_UNPACK_LSB_FIRST, 16#CF1).
+-define(GL_UNPACK_ROW_LENGTH, 16#CF2).
+-define(GL_UNPACK_SKIP_PIXELS, 16#CF4).
+-define(GL_UNPACK_SKIP_ROWS, 16#CF3).
+-define(GL_UNPACK_SWAP_BYTES, 16#CF0).
+-define(GL_ZOOM_X, 16#D16).
+-define(GL_ZOOM_Y, 16#D17).
+-define(GL_TEXTURE_ENV, 16#2300).
+-define(GL_TEXTURE_ENV_MODE, 16#2200).
-define(GL_TEXTURE_1D, 16#DE0).
-define(GL_TEXTURE_2D, 16#DE1).
--define(GL_FEEDBACK_BUFFER_POINTER, 16#DF0).
--define(GL_FEEDBACK_BUFFER_SIZE, 16#DF1).
--define(GL_FEEDBACK_BUFFER_TYPE, 16#DF2).
--define(GL_SELECTION_BUFFER_POINTER, 16#DF3).
--define(GL_SELECTION_BUFFER_SIZE, 16#DF4).
--define(GL_POLYGON_OFFSET_UNITS, 16#2A00).
--define(GL_POLYGON_OFFSET_POINT, 16#2A01).
--define(GL_POLYGON_OFFSET_LINE, 16#2A02).
--define(GL_POLYGON_OFFSET_FILL, 16#8037).
--define(GL_POLYGON_OFFSET_FACTOR, 16#8038).
--define(GL_TEXTURE_BINDING_1D, 16#8068).
--define(GL_TEXTURE_BINDING_2D, 16#8069).
--define(GL_TEXTURE_BINDING_3D, 16#806A).
--define(GL_VERTEX_ARRAY, 16#8074).
--define(GL_NORMAL_ARRAY, 16#8075).
--define(GL_COLOR_ARRAY, 16#8076).
--define(GL_INDEX_ARRAY, 16#8077).
--define(GL_TEXTURE_COORD_ARRAY, 16#8078).
--define(GL_EDGE_FLAG_ARRAY, 16#8079).
--define(GL_VERTEX_ARRAY_SIZE, 16#807A).
--define(GL_VERTEX_ARRAY_TYPE, 16#807B).
--define(GL_VERTEX_ARRAY_STRIDE, 16#807C).
--define(GL_NORMAL_ARRAY_TYPE, 16#807E).
--define(GL_NORMAL_ARRAY_STRIDE, 16#807F).
--define(GL_COLOR_ARRAY_SIZE, 16#8081).
--define(GL_COLOR_ARRAY_TYPE, 16#8082).
--define(GL_COLOR_ARRAY_STRIDE, 16#8083).
--define(GL_INDEX_ARRAY_TYPE, 16#8085).
--define(GL_INDEX_ARRAY_STRIDE, 16#8086).
--define(GL_TEXTURE_COORD_ARRAY_SIZE, 16#8088).
--define(GL_TEXTURE_COORD_ARRAY_TYPE, 16#8089).
--define(GL_TEXTURE_COORD_ARRAY_STRIDE, 16#808A).
--define(GL_EDGE_FLAG_ARRAY_STRIDE, 16#808C).
+-define(GL_TEXTURE_WRAP_S, 16#2802).
+-define(GL_TEXTURE_WRAP_T, 16#2803).
+-define(GL_TEXTURE_MAG_FILTER, 16#2800).
+-define(GL_TEXTURE_MIN_FILTER, 16#2801).
+-define(GL_TEXTURE_ENV_COLOR, 16#2201).
+-define(GL_TEXTURE_GEN_S, 16#C60).
+-define(GL_TEXTURE_GEN_T, 16#C61).
+-define(GL_TEXTURE_GEN_MODE, 16#2500).
+-define(GL_TEXTURE_BORDER_COLOR, 16#1004).
-define(GL_TEXTURE_WIDTH, 16#1000).
-define(GL_TEXTURE_HEIGHT, 16#1001).
--define(GL_TEXTURE_INTERNAL_FORMAT, 16#1003).
--define(GL_TEXTURE_COMPONENTS, ?GL_TEXTURE_INTERNAL_FORMAT).
--define(GL_TEXTURE_BORDER_COLOR, 16#1004).
-define(GL_TEXTURE_BORDER, 16#1005).
+-define(GL_TEXTURE_COMPONENTS, 16#1003).
-define(GL_TEXTURE_RED_SIZE, 16#805C).
-define(GL_TEXTURE_GREEN_SIZE, 16#805D).
-define(GL_TEXTURE_BLUE_SIZE, 16#805E).
-define(GL_TEXTURE_ALPHA_SIZE, 16#805F).
-define(GL_TEXTURE_LUMINANCE_SIZE, 16#8060).
-define(GL_TEXTURE_INTENSITY_SIZE, 16#8061).
--define(GL_TEXTURE_PRIORITY, 16#8066).
--define(GL_TEXTURE_RESIDENT, 16#8067).
--define(GL_DONT_CARE, 16#1100).
--define(GL_FASTEST, 16#1101).
--define(GL_NICEST, 16#1102).
--define(GL_AMBIENT, 16#1200).
--define(GL_DIFFUSE, 16#1201).
--define(GL_SPECULAR, 16#1202).
--define(GL_POSITION, 16#1203).
--define(GL_SPOT_DIRECTION, 16#1204).
--define(GL_SPOT_EXPONENT, 16#1205).
--define(GL_SPOT_CUTOFF, 16#1206).
--define(GL_CONSTANT_ATTENUATION, 16#1207).
--define(GL_LINEAR_ATTENUATION, 16#1208).
--define(GL_QUADRATIC_ATTENUATION, 16#1209).
--define(GL_COMPILE, 16#1300).
--define(GL_COMPILE_AND_EXECUTE, 16#1301).
--define(GL_BYTE, 16#1400).
--define(GL_UNSIGNED_BYTE, 16#1401).
--define(GL_SHORT, 16#1402).
--define(GL_UNSIGNED_SHORT, 16#1403).
--define(GL_INT, 16#1404).
--define(GL_UNSIGNED_INT, 16#1405).
--define(GL_FLOAT, 16#1406).
--define(GL_2_BYTES, 16#1407).
--define(GL_3_BYTES, 16#1408).
--define(GL_4_BYTES, 16#1409).
--define(GL_DOUBLE, 16#140A).
--define(GL_DOUBLE_EXT, 16#140A).
--define(GL_CLEAR, 16#1500).
--define(GL_AND, 16#1501).
--define(GL_AND_REVERSE, 16#1502).
--define(GL_COPY, 16#1503).
--define(GL_AND_INVERTED, 16#1504).
--define(GL_NOOP, 16#1505).
--define(GL_XOR, 16#1506).
--define(GL_OR, 16#1507).
--define(GL_NOR, 16#1508).
--define(GL_EQUIV, 16#1509).
--define(GL_INVERT, 16#150A).
--define(GL_OR_REVERSE, 16#150B).
--define(GL_COPY_INVERTED, 16#150C).
--define(GL_OR_INVERTED, 16#150D).
--define(GL_NAND, 16#150E).
--define(GL_SET, 16#150F).
--define(GL_EMISSION, 16#1600).
--define(GL_SHININESS, 16#1601).
--define(GL_AMBIENT_AND_DIFFUSE, 16#1602).
--define(GL_COLOR_INDEXES, 16#1603).
--define(GL_MODELVIEW, 16#1700).
--define(GL_PROJECTION, 16#1701).
--define(GL_TEXTURE, 16#1702).
--define(GL_COLOR, 16#1800).
--define(GL_DEPTH, 16#1801).
--define(GL_STENCIL, 16#1802).
--define(GL_COLOR_INDEX, 16#1900).
--define(GL_STENCIL_INDEX, 16#1901).
--define(GL_DEPTH_COMPONENT, 16#1902).
--define(GL_RED, 16#1903).
--define(GL_GREEN, 16#1904).
--define(GL_BLUE, 16#1905).
--define(GL_ALPHA, 16#1906).
--define(GL_RGB, 16#1907).
--define(GL_RGBA, 16#1908).
--define(GL_LUMINANCE, 16#1909).
--define(GL_LUMINANCE_ALPHA, 16#190A).
--define(GL_BITMAP, 16#1A00).
--define(GL_POINT, 16#1B00).
--define(GL_LINE, 16#1B01).
--define(GL_FILL, 16#1B02).
--define(GL_RENDER, 16#1C00).
--define(GL_FEEDBACK, 16#1C01).
--define(GL_SELECT, 16#1C02).
--define(GL_FLAT, 16#1D00).
--define(GL_SMOOTH, 16#1D01).
--define(GL_KEEP, 16#1E00).
--define(GL_REPLACE, 16#1E01).
--define(GL_INCR, 16#1E02).
--define(GL_DECR, 16#1E03).
--define(GL_VENDOR, 16#1F00).
--define(GL_RENDERER, 16#1F01).
--define(GL_VERSION, 16#1F02).
--define(GL_EXTENSIONS, 16#1F03).
--define(GL_S, 16#2000).
--define(GL_T, 16#2001).
--define(GL_R, 16#2002).
--define(GL_Q, 16#2003).
--define(GL_MODULATE, 16#2100).
--define(GL_DECAL, 16#2101).
--define(GL_TEXTURE_ENV_MODE, 16#2200).
--define(GL_TEXTURE_ENV_COLOR, 16#2201).
--define(GL_TEXTURE_ENV, 16#2300).
--define(GL_EYE_LINEAR, 16#2400).
+-define(GL_NEAREST_MIPMAP_NEAREST, 16#2700).
+-define(GL_NEAREST_MIPMAP_LINEAR, 16#2702).
+-define(GL_LINEAR_MIPMAP_NEAREST, 16#2701).
+-define(GL_LINEAR_MIPMAP_LINEAR, 16#2703).
-define(GL_OBJECT_LINEAR, 16#2401).
--define(GL_SPHERE_MAP, 16#2402).
--define(GL_TEXTURE_GEN_MODE, 16#2500).
-define(GL_OBJECT_PLANE, 16#2501).
+-define(GL_EYE_LINEAR, 16#2400).
-define(GL_EYE_PLANE, 16#2502).
+-define(GL_SPHERE_MAP, 16#2402).
+-define(GL_DECAL, 16#2101).
+-define(GL_MODULATE, 16#2100).
-define(GL_NEAREST, 16#2600).
--define(GL_LINEAR, 16#2601).
--define(GL_NEAREST_MIPMAP_NEAREST, 16#2700).
--define(GL_LINEAR_MIPMAP_NEAREST, 16#2701).
--define(GL_NEAREST_MIPMAP_LINEAR, 16#2702).
--define(GL_LINEAR_MIPMAP_LINEAR, 16#2703).
--define(GL_TEXTURE_MAG_FILTER, 16#2800).
--define(GL_TEXTURE_MIN_FILTER, 16#2801).
--define(GL_TEXTURE_WRAP_S, 16#2802).
--define(GL_TEXTURE_WRAP_T, 16#2803).
+-define(GL_REPEAT, 16#2901).
+-define(GL_CLAMP, 16#2900).
+-define(GL_S, 16#2000).
+-define(GL_T, 16#2001).
+-define(GL_R, 16#2002).
+-define(GL_Q, 16#2003).
+-define(GL_TEXTURE_GEN_R, 16#C62).
+-define(GL_TEXTURE_GEN_Q, 16#C63).
+-define(GL_VENDOR, 16#1F00).
+-define(GL_RENDERER, 16#1F01).
+-define(GL_VERSION, 16#1F02).
+-define(GL_EXTENSIONS, 16#1F03).
+-define(GL_NO_ERROR, 16#0).
+-define(GL_INVALID_ENUM, 16#500).
+-define(GL_INVALID_VALUE, 16#501).
+-define(GL_INVALID_OPERATION, 16#502).
+-define(GL_STACK_OVERFLOW, 16#503).
+-define(GL_STACK_UNDERFLOW, 16#504).
+-define(GL_OUT_OF_MEMORY, 16#505).
+-define(GL_CURRENT_BIT, 16#1).
+-define(GL_POINT_BIT, 16#2).
+-define(GL_LINE_BIT, 16#4).
+-define(GL_POLYGON_BIT, 16#8).
+-define(GL_POLYGON_STIPPLE_BIT, 16#10).
+-define(GL_PIXEL_MODE_BIT, 16#20).
+-define(GL_LIGHTING_BIT, 16#40).
+-define(GL_FOG_BIT, 16#80).
+-define(GL_DEPTH_BUFFER_BIT, 16#100).
+-define(GL_ACCUM_BUFFER_BIT, 16#200).
+-define(GL_STENCIL_BUFFER_BIT, 16#400).
+-define(GL_VIEWPORT_BIT, 16#800).
+-define(GL_TRANSFORM_BIT, 16#1000).
+-define(GL_ENABLE_BIT, 16#2000).
+-define(GL_COLOR_BUFFER_BIT, 16#4000).
+-define(GL_HINT_BIT, 16#8000).
+-define(GL_EVAL_BIT, 16#10000).
+-define(GL_LIST_BIT, 16#20000).
+-define(GL_TEXTURE_BIT, 16#40000).
+-define(GL_SCISSOR_BIT, 16#80000).
+-define(GL_ALL_ATTRIB_BITS, 16#FFFFF).
-define(GL_PROXY_TEXTURE_1D, 16#8063).
-define(GL_PROXY_TEXTURE_2D, 16#8064).
--define(GL_CLAMP, 16#2900).
--define(GL_REPEAT, 16#2901).
--define(GL_R3_G3_B2, 16#2A10).
+-define(GL_TEXTURE_PRIORITY, 16#8066).
+-define(GL_TEXTURE_RESIDENT, 16#8067).
+-define(GL_TEXTURE_BINDING_1D, 16#8068).
+-define(GL_TEXTURE_BINDING_2D, 16#8069).
+-define(GL_TEXTURE_INTERNAL_FORMAT, 16#1003).
-define(GL_ALPHA4, 16#803B).
-define(GL_ALPHA8, 16#803C).
-define(GL_ALPHA12, 16#803D).
@@ -515,6 +535,7 @@
-define(GL_INTENSITY8, 16#804B).
-define(GL_INTENSITY12, 16#804C).
-define(GL_INTENSITY16, 16#804D).
+-define(GL_R3_G3_B2, 16#2A10).
-define(GL_RGB4, 16#804F).
-define(GL_RGB5, 16#8050).
-define(GL_RGB8, 16#8051).
@@ -528,51 +549,14 @@
-define(GL_RGB10_A2, 16#8059).
-define(GL_RGBA12, 16#805A).
-define(GL_RGBA16, 16#805B).
--define(GL_V2F, 16#2A20).
--define(GL_V3F, 16#2A21).
--define(GL_C4UB_V2F, 16#2A22).
--define(GL_C4UB_V3F, 16#2A23).
--define(GL_C3F_V3F, 16#2A24).
--define(GL_N3F_V3F, 16#2A25).
--define(GL_C4F_N3F_V3F, 16#2A26).
--define(GL_T2F_V3F, 16#2A27).
--define(GL_T4F_V4F, 16#2A28).
--define(GL_T2F_C4UB_V3F, 16#2A29).
--define(GL_T2F_C3F_V3F, 16#2A2A).
--define(GL_T2F_N3F_V3F, 16#2A2B).
--define(GL_T2F_C4F_N3F_V3F, 16#2A2C).
--define(GL_T4F_C4F_N3F_V4F, 16#2A2D).
--define(GL_CLIP_PLANE0, 16#3000).
--define(GL_CLIP_PLANE1, 16#3001).
--define(GL_CLIP_PLANE2, 16#3002).
--define(GL_CLIP_PLANE3, 16#3003).
--define(GL_CLIP_PLANE4, 16#3004).
--define(GL_CLIP_PLANE5, 16#3005).
--define(GL_LIGHT0, 16#4000).
--define(GL_LIGHT1, 16#4001).
--define(GL_LIGHT2, 16#4002).
--define(GL_LIGHT3, 16#4003).
--define(GL_LIGHT4, 16#4004).
--define(GL_LIGHT5, 16#4005).
--define(GL_LIGHT6, 16#4006).
--define(GL_LIGHT7, 16#4007).
--define(GL_ABGR_EXT, 16#8000).
--define(GL_FUNC_SUBTRACT_EXT, 16#800A).
--define(GL_FUNC_REVERSE_SUBTRACT_EXT, 16#800B).
--define(GL_UNSIGNED_BYTE_3_3_2_EXT, 16#8032).
--define(GL_UNSIGNED_SHORT_4_4_4_4_EXT, 16#8033).
--define(GL_UNSIGNED_SHORT_5_5_5_1_EXT, 16#8034).
--define(GL_UNSIGNED_INT_8_8_8_8_EXT, 16#8035).
--define(GL_UNSIGNED_INT_10_10_10_2_EXT, 16#8036).
--define(GL_PACK_SKIP_IMAGES, 16#806B).
--define(GL_PACK_IMAGE_HEIGHT, 16#806C).
--define(GL_UNPACK_SKIP_IMAGES, 16#806D).
--define(GL_UNPACK_IMAGE_HEIGHT, 16#806E).
--define(GL_TEXTURE_3D, 16#806F).
--define(GL_PROXY_TEXTURE_3D, 16#8070).
--define(GL_TEXTURE_DEPTH, 16#8071).
--define(GL_TEXTURE_WRAP_R, 16#8072).
--define(GL_MAX_3D_TEXTURE_SIZE, 16#8073).
+-define(GL_CLIENT_PIXEL_STORE_BIT, 16#1).
+-define(GL_CLIENT_VERTEX_ARRAY_BIT, 16#2).
+-define(GL_ALL_CLIENT_ATTRIB_BITS, 16#FFFFFFFF).
+-define(GL_CLIENT_ALL_ATTRIB_BITS, 16#FFFFFFFF).
+-define(GL_RESCALE_NORMAL, 16#803A).
+-define(GL_CLAMP_TO_EDGE, 16#812F).
+-define(GL_MAX_ELEMENTS_VERTICES, 16#80E8).
+-define(GL_MAX_ELEMENTS_INDICES, 16#80E9).
-define(GL_BGR, 16#80E0).
-define(GL_BGRA, 16#80E1).
-define(GL_UNSIGNED_BYTE_3_3_2, 16#8032).
@@ -587,22 +571,104 @@
-define(GL_UNSIGNED_INT_8_8_8_8_REV, 16#8367).
-define(GL_UNSIGNED_INT_10_10_10_2, 16#8036).
-define(GL_UNSIGNED_INT_2_10_10_10_REV, 16#8368).
--define(GL_RESCALE_NORMAL, 16#803A).
-define(GL_LIGHT_MODEL_COLOR_CONTROL, 16#81F8).
-define(GL_SINGLE_COLOR, 16#81F9).
-define(GL_SEPARATE_SPECULAR_COLOR, 16#81FA).
--define(GL_CLAMP_TO_EDGE, 16#812F).
-define(GL_TEXTURE_MIN_LOD, 16#813A).
-define(GL_TEXTURE_MAX_LOD, 16#813B).
-define(GL_TEXTURE_BASE_LEVEL, 16#813C).
-define(GL_TEXTURE_MAX_LEVEL, 16#813D).
--define(GL_MAX_ELEMENTS_VERTICES, 16#80E8).
--define(GL_MAX_ELEMENTS_INDICES, 16#80E9).
+-define(GL_SMOOTH_POINT_SIZE_RANGE, 16#B12).
+-define(GL_SMOOTH_POINT_SIZE_GRANULARITY, 16#B13).
+-define(GL_SMOOTH_LINE_WIDTH_RANGE, 16#B22).
+-define(GL_SMOOTH_LINE_WIDTH_GRANULARITY, 16#B23).
-define(GL_ALIASED_POINT_SIZE_RANGE, 16#846D).
-define(GL_ALIASED_LINE_WIDTH_RANGE, 16#846E).
--define(GL_ACTIVE_TEXTURE, 16#84E0).
--define(GL_CLIENT_ACTIVE_TEXTURE, 16#84E1).
--define(GL_MAX_TEXTURE_UNITS, 16#84E2).
+-define(GL_PACK_SKIP_IMAGES, 16#806B).
+-define(GL_PACK_IMAGE_HEIGHT, 16#806C).
+-define(GL_UNPACK_SKIP_IMAGES, 16#806D).
+-define(GL_UNPACK_IMAGE_HEIGHT, 16#806E).
+-define(GL_TEXTURE_3D, 16#806F).
+-define(GL_PROXY_TEXTURE_3D, 16#8070).
+-define(GL_TEXTURE_DEPTH, 16#8071).
+-define(GL_TEXTURE_WRAP_R, 16#8072).
+-define(GL_MAX_3D_TEXTURE_SIZE, 16#8073).
+-define(GL_TEXTURE_BINDING_3D, 16#806A).
+-define(GL_CONSTANT_COLOR, 16#8001).
+-define(GL_ONE_MINUS_CONSTANT_COLOR, 16#8002).
+-define(GL_CONSTANT_ALPHA, 16#8003).
+-define(GL_ONE_MINUS_CONSTANT_ALPHA, 16#8004).
+-define(GL_COLOR_TABLE, 16#80D0).
+-define(GL_POST_CONVOLUTION_COLOR_TABLE, 16#80D1).
+-define(GL_POST_COLOR_MATRIX_COLOR_TABLE, 16#80D2).
+-define(GL_PROXY_COLOR_TABLE, 16#80D3).
+-define(GL_PROXY_POST_CONVOLUTION_COLOR_TABLE, 16#80D4).
+-define(GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE, 16#80D5).
+-define(GL_COLOR_TABLE_SCALE, 16#80D6).
+-define(GL_COLOR_TABLE_BIAS, 16#80D7).
+-define(GL_COLOR_TABLE_FORMAT, 16#80D8).
+-define(GL_COLOR_TABLE_WIDTH, 16#80D9).
+-define(GL_COLOR_TABLE_RED_SIZE, 16#80DA).
+-define(GL_COLOR_TABLE_GREEN_SIZE, 16#80DB).
+-define(GL_COLOR_TABLE_BLUE_SIZE, 16#80DC).
+-define(GL_COLOR_TABLE_ALPHA_SIZE, 16#80DD).
+-define(GL_COLOR_TABLE_LUMINANCE_SIZE, 16#80DE).
+-define(GL_COLOR_TABLE_INTENSITY_SIZE, 16#80DF).
+-define(GL_CONVOLUTION_1D, 16#8010).
+-define(GL_CONVOLUTION_2D, 16#8011).
+-define(GL_SEPARABLE_2D, 16#8012).
+-define(GL_CONVOLUTION_BORDER_MODE, 16#8013).
+-define(GL_CONVOLUTION_FILTER_SCALE, 16#8014).
+-define(GL_CONVOLUTION_FILTER_BIAS, 16#8015).
+-define(GL_REDUCE, 16#8016).
+-define(GL_CONVOLUTION_FORMAT, 16#8017).
+-define(GL_CONVOLUTION_WIDTH, 16#8018).
+-define(GL_CONVOLUTION_HEIGHT, 16#8019).
+-define(GL_MAX_CONVOLUTION_WIDTH, 16#801A).
+-define(GL_MAX_CONVOLUTION_HEIGHT, 16#801B).
+-define(GL_POST_CONVOLUTION_RED_SCALE, 16#801C).
+-define(GL_POST_CONVOLUTION_GREEN_SCALE, 16#801D).
+-define(GL_POST_CONVOLUTION_BLUE_SCALE, 16#801E).
+-define(GL_POST_CONVOLUTION_ALPHA_SCALE, 16#801F).
+-define(GL_POST_CONVOLUTION_RED_BIAS, 16#8020).
+-define(GL_POST_CONVOLUTION_GREEN_BIAS, 16#8021).
+-define(GL_POST_CONVOLUTION_BLUE_BIAS, 16#8022).
+-define(GL_POST_CONVOLUTION_ALPHA_BIAS, 16#8023).
+-define(GL_CONSTANT_BORDER, 16#8151).
+-define(GL_REPLICATE_BORDER, 16#8153).
+-define(GL_CONVOLUTION_BORDER_COLOR, 16#8154).
+-define(GL_COLOR_MATRIX, 16#80B1).
+-define(GL_COLOR_MATRIX_STACK_DEPTH, 16#80B2).
+-define(GL_MAX_COLOR_MATRIX_STACK_DEPTH, 16#80B3).
+-define(GL_POST_COLOR_MATRIX_RED_SCALE, 16#80B4).
+-define(GL_POST_COLOR_MATRIX_GREEN_SCALE, 16#80B5).
+-define(GL_POST_COLOR_MATRIX_BLUE_SCALE, 16#80B6).
+-define(GL_POST_COLOR_MATRIX_ALPHA_SCALE, 16#80B7).
+-define(GL_POST_COLOR_MATRIX_RED_BIAS, 16#80B8).
+-define(GL_POST_COLOR_MATRIX_GREEN_BIAS, 16#80B9).
+-define(GL_POST_COLOR_MATRIX_BLUE_BIAS, 16#80BA).
+-define(GL_POST_COLOR_MATRIX_ALPHA_BIAS, 16#80BB).
+-define(GL_HISTOGRAM, 16#8024).
+-define(GL_PROXY_HISTOGRAM, 16#8025).
+-define(GL_HISTOGRAM_WIDTH, 16#8026).
+-define(GL_HISTOGRAM_FORMAT, 16#8027).
+-define(GL_HISTOGRAM_RED_SIZE, 16#8028).
+-define(GL_HISTOGRAM_GREEN_SIZE, 16#8029).
+-define(GL_HISTOGRAM_BLUE_SIZE, 16#802A).
+-define(GL_HISTOGRAM_ALPHA_SIZE, 16#802B).
+-define(GL_HISTOGRAM_LUMINANCE_SIZE, 16#802C).
+-define(GL_HISTOGRAM_SINK, 16#802D).
+-define(GL_MINMAX, 16#802E).
+-define(GL_MINMAX_FORMAT, 16#802F).
+-define(GL_MINMAX_SINK, 16#8030).
+-define(GL_TABLE_TOO_LARGE, 16#8031).
+-define(GL_BLEND_EQUATION, 16#8009).
+-define(GL_MIN, 16#8007).
+-define(GL_MAX, 16#8008).
+-define(GL_FUNC_ADD, 16#8006).
+-define(GL_FUNC_SUBTRACT, 16#800A).
+-define(GL_FUNC_REVERSE_SUBTRACT, 16#800B).
+-define(GL_BLEND_COLOR, 16#8005).
-define(GL_TEXTURE0, 16#84C0).
-define(GL_TEXTURE1, 16#84C1).
-define(GL_TEXTURE2, 16#84C2).
@@ -635,6 +701,9 @@
-define(GL_TEXTURE29, 16#84DD).
-define(GL_TEXTURE30, 16#84DE).
-define(GL_TEXTURE31, 16#84DF).
+-define(GL_ACTIVE_TEXTURE, 16#84E0).
+-define(GL_CLIENT_ACTIVE_TEXTURE, 16#84E1).
+-define(GL_MAX_TEXTURE_UNITS, 16#84E2).
-define(GL_NORMAL_MAP, 16#8511).
-define(GL_REFLECTION_MAP, 16#8512).
-define(GL_TEXTURE_CUBE_MAP, 16#8513).
@@ -647,32 +716,6 @@
-define(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 16#851A).
-define(GL_PROXY_TEXTURE_CUBE_MAP, 16#851B).
-define(GL_MAX_CUBE_MAP_TEXTURE_SIZE, 16#851C).
--define(GL_COMBINE, 16#8570).
--define(GL_COMBINE_RGB, 16#8571).
--define(GL_COMBINE_ALPHA, 16#8572).
--define(GL_RGB_SCALE, 16#8573).
--define(GL_ADD_SIGNED, 16#8574).
--define(GL_INTERPOLATE, 16#8575).
--define(GL_CONSTANT, 16#8576).
--define(GL_PRIMARY_COLOR, 16#8577).
--define(GL_PREVIOUS, 16#8578).
--define(GL_SOURCE0_RGB, 16#8580).
--define(GL_SOURCE1_RGB, 16#8581).
--define(GL_SOURCE2_RGB, 16#8582).
--define(GL_SOURCE0_ALPHA, 16#8588).
--define(GL_SOURCE1_ALPHA, 16#8589).
--define(GL_SOURCE2_ALPHA, 16#858A).
--define(GL_OPERAND0_RGB, 16#8590).
--define(GL_OPERAND1_RGB, 16#8591).
--define(GL_OPERAND2_RGB, 16#8592).
--define(GL_OPERAND0_ALPHA, 16#8598).
--define(GL_OPERAND1_ALPHA, 16#8599).
--define(GL_OPERAND2_ALPHA, 16#859A).
--define(GL_SUBTRACT, 16#84E7).
--define(GL_TRANSPOSE_MODELVIEW_MATRIX, 16#84E3).
--define(GL_TRANSPOSE_PROJECTION_MATRIX, 16#84E4).
--define(GL_TRANSPOSE_TEXTURE_MATRIX, 16#84E5).
--define(GL_TRANSPOSE_COLOR_MATRIX, 16#84E6).
-define(GL_COMPRESSED_ALPHA, 16#84E9).
-define(GL_COMPRESSED_LUMINANCE, 16#84EA).
-define(GL_COMPRESSED_LUMINANCE_ALPHA, 16#84EB).
@@ -684,9 +727,6 @@
-define(GL_TEXTURE_COMPRESSED, 16#86A1).
-define(GL_NUM_COMPRESSED_TEXTURE_FORMATS, 16#86A2).
-define(GL_COMPRESSED_TEXTURE_FORMATS, 16#86A3).
--define(GL_DOT3_RGB, 16#86AE).
--define(GL_DOT3_RGBA, 16#86AF).
--define(GL_CLAMP_TO_BORDER, 16#812D).
-define(GL_MULTISAMPLE, 16#809D).
-define(GL_SAMPLE_ALPHA_TO_COVERAGE, 16#809E).
-define(GL_SAMPLE_ALPHA_TO_ONE, 16#809F).
@@ -696,57 +736,120 @@
-define(GL_SAMPLE_COVERAGE_VALUE, 16#80AA).
-define(GL_SAMPLE_COVERAGE_INVERT, 16#80AB).
-define(GL_MULTISAMPLE_BIT, 16#20000000).
--define(GL_VERTEX_ARRAY_EXT, 16#8074).
--define(GL_NORMAL_ARRAY_EXT, 16#8075).
--define(GL_COLOR_ARRAY_EXT, 16#8076).
--define(GL_INDEX_ARRAY_EXT, 16#8077).
--define(GL_TEXTURE_COORD_ARRAY_EXT, 16#8078).
--define(GL_EDGE_FLAG_ARRAY_EXT, 16#8079).
--define(GL_VERTEX_ARRAY_SIZE_EXT, 16#807A).
--define(GL_VERTEX_ARRAY_TYPE_EXT, 16#807B).
--define(GL_VERTEX_ARRAY_STRIDE_EXT, 16#807C).
--define(GL_VERTEX_ARRAY_COUNT_EXT, 16#807D).
--define(GL_NORMAL_ARRAY_TYPE_EXT, 16#807E).
--define(GL_NORMAL_ARRAY_STRIDE_EXT, 16#807F).
--define(GL_NORMAL_ARRAY_COUNT_EXT, 16#8080).
--define(GL_COLOR_ARRAY_SIZE_EXT, 16#8081).
--define(GL_COLOR_ARRAY_TYPE_EXT, 16#8082).
--define(GL_COLOR_ARRAY_STRIDE_EXT, 16#8083).
--define(GL_COLOR_ARRAY_COUNT_EXT, 16#8084).
--define(GL_INDEX_ARRAY_TYPE_EXT, 16#8085).
--define(GL_INDEX_ARRAY_STRIDE_EXT, 16#8086).
--define(GL_INDEX_ARRAY_COUNT_EXT, 16#8087).
--define(GL_TEXTURE_COORD_ARRAY_SIZE_EXT, 16#8088).
--define(GL_TEXTURE_COORD_ARRAY_TYPE_EXT, 16#8089).
--define(GL_TEXTURE_COORD_ARRAY_STRIDE_EXT, 16#808A).
--define(GL_TEXTURE_COORD_ARRAY_COUNT_EXT, 16#808B).
--define(GL_EDGE_FLAG_ARRAY_STRIDE_EXT, 16#808C).
--define(GL_EDGE_FLAG_ARRAY_COUNT_EXT, 16#808D).
--define(GL_VERTEX_ARRAY_POINTER_EXT, 16#808E).
--define(GL_NORMAL_ARRAY_POINTER_EXT, 16#808F).
--define(GL_COLOR_ARRAY_POINTER_EXT, 16#8090).
--define(GL_INDEX_ARRAY_POINTER_EXT, 16#8091).
--define(GL_TEXTURE_COORD_ARRAY_POINTER_EXT, 16#8092).
--define(GL_EDGE_FLAG_ARRAY_POINTER_EXT, 16#8093).
--define(GL_TEXTURE_MIN_LOD_SGIS, 16#813A).
--define(GL_TEXTURE_MAX_LOD_SGIS, 16#813B).
--define(GL_TEXTURE_BASE_LEVEL_SGIS, 16#813C).
--define(GL_TEXTURE_MAX_LEVEL_SGIS, 16#813D).
--define(GL_SHARED_TEXTURE_PALETTE_EXT, 16#81FB).
--define(GL_RESCALE_NORMAL_EXT, 16#803A).
--define(GL_TEXTURE_COMPARE_SGIX, 16#819A).
--define(GL_TEXTURE_COMPARE_OPERATOR_SGIX, 16#819B).
--define(GL_TEXTURE_LEQUAL_R_SGIX, 16#819C).
--define(GL_TEXTURE_GEQUAL_R_SGIX, 16#819D).
--define(GL_DEPTH_COMPONENT16_SGIX, 16#81A5).
--define(GL_DEPTH_COMPONENT24_SGIX, 16#81A6).
--define(GL_DEPTH_COMPONENT32_SGIX, 16#81A7).
--define(GL_GENERATE_MIPMAP_SGIS, 16#8191).
--define(GL_GENERATE_MIPMAP_HINT_SGIS, 16#8192).
+-define(GL_TRANSPOSE_MODELVIEW_MATRIX, 16#84E3).
+-define(GL_TRANSPOSE_PROJECTION_MATRIX, 16#84E4).
+-define(GL_TRANSPOSE_TEXTURE_MATRIX, 16#84E5).
+-define(GL_TRANSPOSE_COLOR_MATRIX, 16#84E6).
+-define(GL_COMBINE, 16#8570).
+-define(GL_COMBINE_RGB, 16#8571).
+-define(GL_COMBINE_ALPHA, 16#8572).
+-define(GL_SOURCE0_RGB, 16#8580).
+-define(GL_SOURCE1_RGB, 16#8581).
+-define(GL_SOURCE2_RGB, 16#8582).
+-define(GL_SOURCE0_ALPHA, 16#8588).
+-define(GL_SOURCE1_ALPHA, 16#8589).
+-define(GL_SOURCE2_ALPHA, 16#858A).
+-define(GL_OPERAND0_RGB, 16#8590).
+-define(GL_OPERAND1_RGB, 16#8591).
+-define(GL_OPERAND2_RGB, 16#8592).
+-define(GL_OPERAND0_ALPHA, 16#8598).
+-define(GL_OPERAND1_ALPHA, 16#8599).
+-define(GL_OPERAND2_ALPHA, 16#859A).
+-define(GL_RGB_SCALE, 16#8573).
+-define(GL_ADD_SIGNED, 16#8574).
+-define(GL_INTERPOLATE, 16#8575).
+-define(GL_SUBTRACT, 16#84E7).
+-define(GL_CONSTANT, 16#8576).
+-define(GL_PRIMARY_COLOR, 16#8577).
+-define(GL_PREVIOUS, 16#8578).
+-define(GL_DOT3_RGB, 16#86AE).
+-define(GL_DOT3_RGBA, 16#86AF).
+-define(GL_CLAMP_TO_BORDER, 16#812D).
+-define(GL_ARB_multitexture, 1).
+-define(GL_TEXTURE0_ARB, 16#84C0).
+-define(GL_TEXTURE1_ARB, 16#84C1).
+-define(GL_TEXTURE2_ARB, 16#84C2).
+-define(GL_TEXTURE3_ARB, 16#84C3).
+-define(GL_TEXTURE4_ARB, 16#84C4).
+-define(GL_TEXTURE5_ARB, 16#84C5).
+-define(GL_TEXTURE6_ARB, 16#84C6).
+-define(GL_TEXTURE7_ARB, 16#84C7).
+-define(GL_TEXTURE8_ARB, 16#84C8).
+-define(GL_TEXTURE9_ARB, 16#84C9).
+-define(GL_TEXTURE10_ARB, 16#84CA).
+-define(GL_TEXTURE11_ARB, 16#84CB).
+-define(GL_TEXTURE12_ARB, 16#84CC).
+-define(GL_TEXTURE13_ARB, 16#84CD).
+-define(GL_TEXTURE14_ARB, 16#84CE).
+-define(GL_TEXTURE15_ARB, 16#84CF).
+-define(GL_TEXTURE16_ARB, 16#84D0).
+-define(GL_TEXTURE17_ARB, 16#84D1).
+-define(GL_TEXTURE18_ARB, 16#84D2).
+-define(GL_TEXTURE19_ARB, 16#84D3).
+-define(GL_TEXTURE20_ARB, 16#84D4).
+-define(GL_TEXTURE21_ARB, 16#84D5).
+-define(GL_TEXTURE22_ARB, 16#84D6).
+-define(GL_TEXTURE23_ARB, 16#84D7).
+-define(GL_TEXTURE24_ARB, 16#84D8).
+-define(GL_TEXTURE25_ARB, 16#84D9).
+-define(GL_TEXTURE26_ARB, 16#84DA).
+-define(GL_TEXTURE27_ARB, 16#84DB).
+-define(GL_TEXTURE28_ARB, 16#84DC).
+-define(GL_TEXTURE29_ARB, 16#84DD).
+-define(GL_TEXTURE30_ARB, 16#84DE).
+-define(GL_TEXTURE31_ARB, 16#84DF).
+-define(GL_ACTIVE_TEXTURE_ARB, 16#84E0).
+-define(GL_CLIENT_ACTIVE_TEXTURE_ARB, 16#84E1).
+-define(GL_MAX_TEXTURE_UNITS_ARB, 16#84E2).
+-define(GL_MESA_packed_depth_stencil, 1).
+-define(GL_DEPTH_STENCIL_MESA, 16#8750).
+-define(GL_UNSIGNED_INT_24_8_MESA, 16#8751).
+-define(GL_UNSIGNED_INT_8_24_REV_MESA, 16#8752).
+-define(GL_UNSIGNED_SHORT_15_1_MESA, 16#8753).
+-define(GL_UNSIGNED_SHORT_1_15_REV_MESA, 16#8754).
+-define(GL_MESA_program_debug, 1).
+-define(GL_FRAGMENT_PROGRAM_POSITION_MESA, 16#8BB0).
+-define(GL_FRAGMENT_PROGRAM_CALLBACK_MESA, 16#8BB1).
+-define(GL_FRAGMENT_PROGRAM_CALLBACK_FUNC_MESA, 16#8BB2).
+-define(GL_FRAGMENT_PROGRAM_CALLBACK_DATA_MESA, 16#8BB3).
+-define(GL_VERTEX_PROGRAM_POSITION_MESA, 16#8BB4).
+-define(GL_VERTEX_PROGRAM_CALLBACK_MESA, 16#8BB5).
+-define(GL_VERTEX_PROGRAM_CALLBACK_FUNC_MESA, 16#8BB6).
+-define(GL_VERTEX_PROGRAM_CALLBACK_DATA_MESA, 16#8BB7).
+-define(GL_MESA_texture_array, 1).
+-define(GL_TEXTURE_1D_ARRAY_EXT, 16#8C18).
+-define(GL_PROXY_TEXTURE_1D_ARRAY_EXT, 16#8C19).
+-define(GL_TEXTURE_2D_ARRAY_EXT, 16#8C1A).
+-define(GL_PROXY_TEXTURE_2D_ARRAY_EXT, 16#8C1B).
+-define(GL_TEXTURE_BINDING_1D_ARRAY_EXT, 16#8C1C).
+-define(GL_TEXTURE_BINDING_2D_ARRAY_EXT, 16#8C1D).
+-define(GL_MAX_ARRAY_TEXTURE_LAYERS_EXT, 16#88FF).
+-define(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT, 16#8CD4).
+-define(GL_ATI_blend_equation_separate, 1).
+-define(GL_ALPHA_BLEND_EQUATION_ATI, 16#883D).
+-define(GL_OES_EGL_image, 1).
+-define(GL_GLEXT_VERSION, 66).
+-define(GL_BLEND_DST_RGB, 16#80C8).
+-define(GL_BLEND_SRC_RGB, 16#80C9).
+-define(GL_BLEND_DST_ALPHA, 16#80CA).
+-define(GL_BLEND_SRC_ALPHA, 16#80CB).
+-define(GL_POINT_FADE_THRESHOLD_SIZE, 16#8128).
+-define(GL_DEPTH_COMPONENT16, 16#81A5).
+-define(GL_DEPTH_COMPONENT24, 16#81A6).
+-define(GL_DEPTH_COMPONENT32, 16#81A7).
+-define(GL_MIRRORED_REPEAT, 16#8370).
+-define(GL_MAX_TEXTURE_LOD_BIAS, 16#84FD).
+-define(GL_TEXTURE_LOD_BIAS, 16#8501).
+-define(GL_INCR_WRAP, 16#8507).
+-define(GL_DECR_WRAP, 16#8508).
+-define(GL_TEXTURE_DEPTH_SIZE, 16#884A).
+-define(GL_TEXTURE_COMPARE_MODE, 16#884C).
+-define(GL_TEXTURE_COMPARE_FUNC, 16#884D).
-define(GL_POINT_SIZE_MIN, 16#8126).
-define(GL_POINT_SIZE_MAX, 16#8127).
--define(GL_POINT_FADE_THRESHOLD_SIZE, 16#8128).
-define(GL_POINT_DISTANCE_ATTENUATION, 16#8129).
+-define(GL_GENERATE_MIPMAP, 16#8191).
+-define(GL_GENERATE_MIPMAP_HINT, 16#8192).
-define(GL_FOG_COORDINATE_SOURCE, 16#8450).
-define(GL_FOG_COORDINATE, 16#8451).
-define(GL_FRAGMENT_DEPTH, 16#8452).
@@ -762,101 +865,9 @@
-define(GL_SECONDARY_COLOR_ARRAY_STRIDE, 16#845C).
-define(GL_SECONDARY_COLOR_ARRAY_POINTER, 16#845D).
-define(GL_SECONDARY_COLOR_ARRAY, 16#845E).
--define(GL_INCR_WRAP, 16#8507).
--define(GL_DECR_WRAP, 16#8508).
--define(GL_MAX_TEXTURE_LOD_BIAS, 16#84FD).
-define(GL_TEXTURE_FILTER_CONTROL, 16#8500).
--define(GL_TEXTURE_LOD_BIAS, 16#8501).
--define(GL_GENERATE_MIPMAP, 16#8191).
--define(GL_GENERATE_MIPMAP_HINT, 16#8192).
--define(GL_BLEND_DST_RGB, 16#80C8).
--define(GL_BLEND_SRC_RGB, 16#80C9).
--define(GL_BLEND_DST_ALPHA, 16#80CA).
--define(GL_BLEND_SRC_ALPHA, 16#80CB).
--define(GL_MIRRORED_REPEAT, 16#8370).
--define(GL_DEPTH_COMPONENT16, 16#81A5).
--define(GL_DEPTH_COMPONENT24, 16#81A6).
--define(GL_DEPTH_COMPONENT32, 16#81A7).
--define(GL_TEXTURE_DEPTH_SIZE, 16#884A).
-define(GL_DEPTH_TEXTURE_MODE, 16#884B).
--define(GL_TEXTURE_COMPARE_MODE, 16#884C).
--define(GL_TEXTURE_COMPARE_FUNC, 16#884D).
-define(GL_COMPARE_R_TO_TEXTURE, 16#884E).
--define(GL_GLEXT_VERSION, 65).
--define(GL_CONSTANT_COLOR, 16#8001).
--define(GL_ONE_MINUS_CONSTANT_COLOR, 16#8002).
--define(GL_CONSTANT_ALPHA, 16#8003).
--define(GL_ONE_MINUS_CONSTANT_ALPHA, 16#8004).
--define(GL_BLEND_COLOR, 16#8005).
--define(GL_FUNC_ADD, 16#8006).
--define(GL_MIN, 16#8007).
--define(GL_MAX, 16#8008).
--define(GL_BLEND_EQUATION, 16#8009).
--define(GL_FUNC_SUBTRACT, 16#800A).
--define(GL_FUNC_REVERSE_SUBTRACT, 16#800B).
--define(GL_CONVOLUTION_1D, 16#8010).
--define(GL_CONVOLUTION_2D, 16#8011).
--define(GL_SEPARABLE_2D, 16#8012).
--define(GL_CONVOLUTION_BORDER_MODE, 16#8013).
--define(GL_CONVOLUTION_FILTER_SCALE, 16#8014).
--define(GL_CONVOLUTION_FILTER_BIAS, 16#8015).
--define(GL_REDUCE, 16#8016).
--define(GL_CONVOLUTION_FORMAT, 16#8017).
--define(GL_CONVOLUTION_WIDTH, 16#8018).
--define(GL_CONVOLUTION_HEIGHT, 16#8019).
--define(GL_MAX_CONVOLUTION_WIDTH, 16#801A).
--define(GL_MAX_CONVOLUTION_HEIGHT, 16#801B).
--define(GL_POST_CONVOLUTION_RED_SCALE, 16#801C).
--define(GL_POST_CONVOLUTION_GREEN_SCALE, 16#801D).
--define(GL_POST_CONVOLUTION_BLUE_SCALE, 16#801E).
--define(GL_POST_CONVOLUTION_ALPHA_SCALE, 16#801F).
--define(GL_POST_CONVOLUTION_RED_BIAS, 16#8020).
--define(GL_POST_CONVOLUTION_GREEN_BIAS, 16#8021).
--define(GL_POST_CONVOLUTION_BLUE_BIAS, 16#8022).
--define(GL_POST_CONVOLUTION_ALPHA_BIAS, 16#8023).
--define(GL_HISTOGRAM, 16#8024).
--define(GL_PROXY_HISTOGRAM, 16#8025).
--define(GL_HISTOGRAM_WIDTH, 16#8026).
--define(GL_HISTOGRAM_FORMAT, 16#8027).
--define(GL_HISTOGRAM_RED_SIZE, 16#8028).
--define(GL_HISTOGRAM_GREEN_SIZE, 16#8029).
--define(GL_HISTOGRAM_BLUE_SIZE, 16#802A).
--define(GL_HISTOGRAM_ALPHA_SIZE, 16#802B).
--define(GL_HISTOGRAM_LUMINANCE_SIZE, 16#802C).
--define(GL_HISTOGRAM_SINK, 16#802D).
--define(GL_MINMAX, 16#802E).
--define(GL_MINMAX_FORMAT, 16#802F).
--define(GL_MINMAX_SINK, 16#8030).
--define(GL_COLOR_MATRIX, 16#80B1).
--define(GL_COLOR_MATRIX_STACK_DEPTH, 16#80B2).
--define(GL_MAX_COLOR_MATRIX_STACK_DEPTH, 16#80B3).
--define(GL_POST_COLOR_MATRIX_RED_SCALE, 16#80B4).
--define(GL_POST_COLOR_MATRIX_GREEN_SCALE, 16#80B5).
--define(GL_POST_COLOR_MATRIX_BLUE_SCALE, 16#80B6).
--define(GL_POST_COLOR_MATRIX_ALPHA_SCALE, 16#80B7).
--define(GL_POST_COLOR_MATRIX_RED_BIAS, 16#80B8).
--define(GL_POST_COLOR_MATRIX_GREEN_BIAS, 16#80B9).
--define(GL_POST_COLOR_MATRIX_BLUE_BIAS, 16#80BA).
--define(GL_POST_COLOR_MATRIX_ALPHA_BIAS, 16#80BB).
--define(GL_COLOR_TABLE, 16#80D0).
--define(GL_POST_CONVOLUTION_COLOR_TABLE, 16#80D1).
--define(GL_POST_COLOR_MATRIX_COLOR_TABLE, 16#80D2).
--define(GL_PROXY_COLOR_TABLE, 16#80D3).
--define(GL_PROXY_POST_CONVOLUTION_COLOR_TABLE, 16#80D4).
--define(GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE, 16#80D5).
--define(GL_COLOR_TABLE_SCALE, 16#80D6).
--define(GL_COLOR_TABLE_BIAS, 16#80D7).
--define(GL_COLOR_TABLE_FORMAT, 16#80D8).
--define(GL_COLOR_TABLE_WIDTH, 16#80D9).
--define(GL_COLOR_TABLE_RED_SIZE, 16#80DA).
--define(GL_COLOR_TABLE_GREEN_SIZE, 16#80DB).
--define(GL_COLOR_TABLE_BLUE_SIZE, 16#80DC).
--define(GL_COLOR_TABLE_ALPHA_SIZE, 16#80DD).
--define(GL_COLOR_TABLE_LUMINANCE_SIZE, 16#80DE).
--define(GL_COLOR_TABLE_INTENSITY_SIZE, 16#80DF).
--define(GL_CONSTANT_BORDER, 16#8151).
--define(GL_REPLICATE_BORDER, 16#8153).
--define(GL_CONVOLUTION_BORDER_COLOR, 16#8154).
-define(GL_BUFFER_SIZE, 16#8764).
-define(GL_BUFFER_USAGE, 16#8765).
-define(GL_QUERY_COUNTER_BITS, 16#8864).
@@ -1184,41 +1195,6 @@
-define(GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW, 16#900D).
-define(GL_INT_SAMPLER_CUBE_MAP_ARRAY, 16#900E).
-define(GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY, 16#900F).
--define(GL_TEXTURE0_ARB, 16#84C0).
--define(GL_TEXTURE1_ARB, 16#84C1).
--define(GL_TEXTURE2_ARB, 16#84C2).
--define(GL_TEXTURE3_ARB, 16#84C3).
--define(GL_TEXTURE4_ARB, 16#84C4).
--define(GL_TEXTURE5_ARB, 16#84C5).
--define(GL_TEXTURE6_ARB, 16#84C6).
--define(GL_TEXTURE7_ARB, 16#84C7).
--define(GL_TEXTURE8_ARB, 16#84C8).
--define(GL_TEXTURE9_ARB, 16#84C9).
--define(GL_TEXTURE10_ARB, 16#84CA).
--define(GL_TEXTURE11_ARB, 16#84CB).
--define(GL_TEXTURE12_ARB, 16#84CC).
--define(GL_TEXTURE13_ARB, 16#84CD).
--define(GL_TEXTURE14_ARB, 16#84CE).
--define(GL_TEXTURE15_ARB, 16#84CF).
--define(GL_TEXTURE16_ARB, 16#84D0).
--define(GL_TEXTURE17_ARB, 16#84D1).
--define(GL_TEXTURE18_ARB, 16#84D2).
--define(GL_TEXTURE19_ARB, 16#84D3).
--define(GL_TEXTURE20_ARB, 16#84D4).
--define(GL_TEXTURE21_ARB, 16#84D5).
--define(GL_TEXTURE22_ARB, 16#84D6).
--define(GL_TEXTURE23_ARB, 16#84D7).
--define(GL_TEXTURE24_ARB, 16#84D8).
--define(GL_TEXTURE25_ARB, 16#84D9).
--define(GL_TEXTURE26_ARB, 16#84DA).
--define(GL_TEXTURE27_ARB, 16#84DB).
--define(GL_TEXTURE28_ARB, 16#84DC).
--define(GL_TEXTURE29_ARB, 16#84DD).
--define(GL_TEXTURE30_ARB, 16#84DE).
--define(GL_TEXTURE31_ARB, 16#84DF).
--define(GL_ACTIVE_TEXTURE_ARB, 16#84E0).
--define(GL_CLIENT_ACTIVE_TEXTURE_ARB, 16#84E1).
--define(GL_MAX_TEXTURE_UNITS_ARB, 16#84E2).
-define(GL_TRANSPOSE_MODELVIEW_MATRIX_ARB, 16#84E3).
-define(GL_TRANSPOSE_PROJECTION_MATRIX_ARB, 16#84E4).
-define(GL_TRANSPOSE_TEXTURE_MATRIX_ARB, 16#84E5).
@@ -1956,6 +1932,7 @@
-define(GL_UNKNOWN_CONTEXT_RESET_ARB, 16#8255).
-define(GL_RESET_NOTIFICATION_STRATEGY_ARB, 16#8256).
-define(GL_NO_RESET_NOTIFICATION_ARB, 16#8261).
+-define(GL_ABGR_EXT, 16#8000).
-define(GL_CONSTANT_COLOR_EXT, 16#8001).
-define(GL_ONE_MINUS_CONSTANT_COLOR_EXT, 16#8002).
-define(GL_CONSTANT_ALPHA_EXT, 16#8003).
@@ -2118,6 +2095,15 @@
-define(GL_LINEAR_SHARPEN_ALPHA_SGIS, 16#80AE).
-define(GL_LINEAR_SHARPEN_COLOR_SGIS, 16#80AF).
-define(GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS, 16#80B0).
+-define(GL_UNSIGNED_BYTE_3_3_2_EXT, 16#8032).
+-define(GL_UNSIGNED_SHORT_4_4_4_4_EXT, 16#8033).
+-define(GL_UNSIGNED_SHORT_5_5_5_1_EXT, 16#8034).
+-define(GL_UNSIGNED_INT_8_8_8_8_EXT, 16#8035).
+-define(GL_UNSIGNED_INT_10_10_10_2_EXT, 16#8036).
+-define(GL_TEXTURE_MIN_LOD_SGIS, 16#813A).
+-define(GL_TEXTURE_MAX_LOD_SGIS, 16#813B).
+-define(GL_TEXTURE_BASE_LEVEL_SGIS, 16#813C).
+-define(GL_TEXTURE_MAX_LEVEL_SGIS, 16#813D).
-define(GL_MULTISAMPLE_SGIS, 16#809D).
-define(GL_SAMPLE_ALPHA_TO_MASK_SGIS, 16#809E).
-define(GL_SAMPLE_ALPHA_TO_ONE_SGIS, 16#809F).
@@ -2134,6 +2120,41 @@
-define(GL_SAMPLE_MASK_VALUE_SGIS, 16#80AA).
-define(GL_SAMPLE_MASK_INVERT_SGIS, 16#80AB).
-define(GL_SAMPLE_PATTERN_SGIS, 16#80AC).
+-define(GL_RESCALE_NORMAL_EXT, 16#803A).
+-define(GL_VERTEX_ARRAY_EXT, 16#8074).
+-define(GL_NORMAL_ARRAY_EXT, 16#8075).
+-define(GL_COLOR_ARRAY_EXT, 16#8076).
+-define(GL_INDEX_ARRAY_EXT, 16#8077).
+-define(GL_TEXTURE_COORD_ARRAY_EXT, 16#8078).
+-define(GL_EDGE_FLAG_ARRAY_EXT, 16#8079).
+-define(GL_VERTEX_ARRAY_SIZE_EXT, 16#807A).
+-define(GL_VERTEX_ARRAY_TYPE_EXT, 16#807B).
+-define(GL_VERTEX_ARRAY_STRIDE_EXT, 16#807C).
+-define(GL_VERTEX_ARRAY_COUNT_EXT, 16#807D).
+-define(GL_NORMAL_ARRAY_TYPE_EXT, 16#807E).
+-define(GL_NORMAL_ARRAY_STRIDE_EXT, 16#807F).
+-define(GL_NORMAL_ARRAY_COUNT_EXT, 16#8080).
+-define(GL_COLOR_ARRAY_SIZE_EXT, 16#8081).
+-define(GL_COLOR_ARRAY_TYPE_EXT, 16#8082).
+-define(GL_COLOR_ARRAY_STRIDE_EXT, 16#8083).
+-define(GL_COLOR_ARRAY_COUNT_EXT, 16#8084).
+-define(GL_INDEX_ARRAY_TYPE_EXT, 16#8085).
+-define(GL_INDEX_ARRAY_STRIDE_EXT, 16#8086).
+-define(GL_INDEX_ARRAY_COUNT_EXT, 16#8087).
+-define(GL_TEXTURE_COORD_ARRAY_SIZE_EXT, 16#8088).
+-define(GL_TEXTURE_COORD_ARRAY_TYPE_EXT, 16#8089).
+-define(GL_TEXTURE_COORD_ARRAY_STRIDE_EXT, 16#808A).
+-define(GL_TEXTURE_COORD_ARRAY_COUNT_EXT, 16#808B).
+-define(GL_EDGE_FLAG_ARRAY_STRIDE_EXT, 16#808C).
+-define(GL_EDGE_FLAG_ARRAY_COUNT_EXT, 16#808D).
+-define(GL_VERTEX_ARRAY_POINTER_EXT, 16#808E).
+-define(GL_NORMAL_ARRAY_POINTER_EXT, 16#808F).
+-define(GL_COLOR_ARRAY_POINTER_EXT, 16#8090).
+-define(GL_INDEX_ARRAY_POINTER_EXT, 16#8091).
+-define(GL_TEXTURE_COORD_ARRAY_POINTER_EXT, 16#8092).
+-define(GL_EDGE_FLAG_ARRAY_POINTER_EXT, 16#8093).
+-define(GL_GENERATE_MIPMAP_SGIS, 16#8191).
+-define(GL_GENERATE_MIPMAP_HINT_SGIS, 16#8192).
-define(GL_LINEAR_CLIPMAP_LINEAR_SGIX, 16#8170).
-define(GL_TEXTURE_CLIPMAP_CENTER_SGIX, 16#8171).
-define(GL_TEXTURE_CLIPMAP_FRAME_SGIX, 16#8172).
@@ -2146,12 +2167,18 @@
-define(GL_NEAREST_CLIPMAP_NEAREST_SGIX, 16#844D).
-define(GL_NEAREST_CLIPMAP_LINEAR_SGIX, 16#844E).
-define(GL_LINEAR_CLIPMAP_NEAREST_SGIX, 16#844F).
+-define(GL_TEXTURE_COMPARE_SGIX, 16#819A).
+-define(GL_TEXTURE_COMPARE_OPERATOR_SGIX, 16#819B).
+-define(GL_TEXTURE_LEQUAL_R_SGIX, 16#819C).
+-define(GL_TEXTURE_GEQUAL_R_SGIX, 16#819D).
-define(GL_CLAMP_TO_EDGE_SGIS, 16#812F).
-define(GL_CLAMP_TO_BORDER_SGIS, 16#812D).
-define(GL_FUNC_ADD_EXT, 16#8006).
-define(GL_MIN_EXT, 16#8007).
-define(GL_MAX_EXT, 16#8008).
-define(GL_BLEND_EQUATION_EXT, 16#8009).
+-define(GL_FUNC_SUBTRACT_EXT, 16#800A).
+-define(GL_FUNC_REVERSE_SUBTRACT_EXT, 16#800B).
-define(GL_INTERLACE_SGIX, 16#8094).
-define(GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX, 16#813E).
-define(GL_PIXEL_TILE_CACHE_INCREMENT_SGIX, 16#813F).
@@ -2216,6 +2243,9 @@
-define(GL_MAX_DEFORMATION_ORDER_SGIX, 16#8197).
-define(GL_REFERENCE_PLANE_SGIX, 16#817D).
-define(GL_REFERENCE_PLANE_EQUATION_SGIX, 16#817E).
+-define(GL_DEPTH_COMPONENT16_SGIX, 16#81A5).
+-define(GL_DEPTH_COMPONENT24_SGIX, 16#81A6).
+-define(GL_DEPTH_COMPONENT32_SGIX, 16#81A7).
-define(GL_FOG_FUNC_SGIS, 16#812A).
-define(GL_FOG_FUNC_POINTS_SGIS, 16#812B).
-define(GL_MAX_FOG_FUNC_POINTS_SGIS, 16#812C).
@@ -2393,6 +2423,7 @@
-define(GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT, 16#8336).
-define(GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT, 16#8337).
-define(GL_PIXEL_TRANSFORM_2D_MATRIX_EXT, 16#8338).
+-define(GL_SHARED_TEXTURE_PALETTE_EXT, 16#81FB).
-define(GL_LIGHT_MODEL_COLOR_CONTROL_EXT, 16#81F8).
-define(GL_SINGLE_COLOR_EXT, 16#81F9).
-define(GL_SEPARATE_SPECULAR_COLOR_EXT, 16#81FA).
@@ -3387,7 +3418,6 @@
-define(GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT, 16#8DA7).
-define(GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT, 16#8DA8).
-define(GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT, 16#8DA9).
--define(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT, 16#8CD4).
-define(GL_PROGRAM_POINT_SIZE_EXT, 16#8642).
-define(GL_GEOMETRY_SHADER_EXT, 16#8DD9).
-define(GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT, 16#8DDD).
@@ -3425,13 +3455,6 @@
-define(GL_R11F_G11F_B10F_EXT, 16#8C3A).
-define(GL_UNSIGNED_INT_10F_11F_11F_REV_EXT, 16#8C3B).
-define(GL_RGBA_SIGNED_COMPONENTS_EXT, 16#8C3C).
--define(GL_TEXTURE_1D_ARRAY_EXT, 16#8C18).
--define(GL_PROXY_TEXTURE_1D_ARRAY_EXT, 16#8C19).
--define(GL_TEXTURE_2D_ARRAY_EXT, 16#8C1A).
--define(GL_PROXY_TEXTURE_2D_ARRAY_EXT, 16#8C1B).
--define(GL_TEXTURE_BINDING_1D_ARRAY_EXT, 16#8C1C).
--define(GL_TEXTURE_BINDING_2D_ARRAY_EXT, 16#8C1D).
--define(GL_MAX_ARRAY_TEXTURE_LAYERS_EXT, 16#88FF).
-define(GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT, 16#884E).
-define(GL_TEXTURE_BUFFER_EXT, 16#8C2A).
-define(GL_MAX_TEXTURE_BUFFER_SIZE_EXT, 16#8C2B).
@@ -3857,396 +3880,5 @@
-define(GL_SURFACE_REGISTERED_NV, 16#86FD).
-define(GL_SURFACE_MAPPED_NV, 16#8700).
-define(GL_WRITE_DISCARD_NV, 16#88BE).
--define(GL_VERSION_1_2, 1).
--define(GL_VERSION_1_2_DEPRECATED, 1).
--define(GL_VERSION_1_3, 1).
--define(GL_VERSION_1_3_DEPRECATED, 1).
--define(GL_VERSION_1_4, 1).
--define(GL_VERSION_1_4_DEPRECATED, 1).
--define(GL_VERSION_1_5, 1).
--define(GL_VERSION_2_0, 1).
--define(GL_VERSION_2_1, 1).
--define(GL_VERSION_3_0, 1).
--define(GL_VERSION_3_1, 1).
--define(GL_VERSION_3_2, 1).
--define(GL_VERSION_3_3, 1).
--define(GL_VERSION_4_0, 1).
--define(GL_VERSION_4_1, 1).
--define(GL_ARB_multitexture, 1).
--define(GL_ARB_transpose_matrix, 1).
--define(GL_ARB_multisample, 1).
--define(GL_ARB_texture_env_add, 1).
--define(GL_ARB_texture_cube_map, 1).
--define(GL_ARB_texture_compression, 1).
--define(GL_ARB_texture_border_clamp, 1).
--define(GL_ARB_point_parameters, 1).
--define(GL_ARB_vertex_blend, 1).
--define(GL_ARB_matrix_palette, 1).
--define(GL_ARB_texture_env_combine, 1).
--define(GL_ARB_texture_env_crossbar, 1).
--define(GL_ARB_texture_env_dot3, 1).
--define(GL_ARB_texture_mirrored_repeat, 1).
--define(GL_ARB_depth_texture, 1).
--define(GL_ARB_shadow, 1).
--define(GL_ARB_shadow_ambient, 1).
--define(GL_ARB_window_pos, 1).
--define(GL_ARB_vertex_program, 1).
--define(GL_ARB_fragment_program, 1).
--define(GL_ARB_vertex_buffer_object, 1).
--define(GL_ARB_occlusion_query, 1).
--define(GL_ARB_shader_objects, 1).
--define(GL_ARB_vertex_shader, 1).
--define(GL_ARB_fragment_shader, 1).
--define(GL_ARB_shading_language_100, 1).
--define(GL_ARB_texture_non_power_of_two, 1).
--define(GL_ARB_point_sprite, 1).
--define(GL_ARB_fragment_program_shadow, 1).
--define(GL_ARB_draw_buffers, 1).
--define(GL_ARB_texture_rectangle, 1).
--define(GL_ARB_color_buffer_float, 1).
--define(GL_ARB_half_float_pixel, 1).
--define(GL_ARB_texture_float, 1).
--define(GL_ARB_pixel_buffer_object, 1).
--define(GL_ARB_depth_buffer_float, 1).
--define(GL_ARB_draw_instanced, 1).
--define(GL_ARB_framebuffer_object, 1).
--define(GL_ARB_framebuffer_sRGB, 1).
--define(GL_ARB_geometry_shader4, 1).
--define(GL_ARB_half_float_vertex, 1).
--define(GL_ARB_instanced_arrays, 1).
--define(GL_ARB_map_buffer_range, 1).
--define(GL_ARB_texture_buffer_object, 1).
--define(GL_ARB_texture_compression_rgtc, 1).
--define(GL_ARB_texture_rg, 1).
--define(GL_ARB_vertex_array_object, 1).
--define(GL_ARB_uniform_buffer_object, 1).
--define(GL_ARB_compatibility, 1).
--define(GL_ARB_copy_buffer, 1).
--define(GL_ARB_shader_texture_lod, 1).
--define(GL_ARB_depth_clamp, 1).
--define(GL_ARB_draw_elements_base_vertex, 1).
--define(GL_ARB_fragment_coord_conventions, 1).
--define(GL_ARB_provoking_vertex, 1).
--define(GL_ARB_seamless_cube_map, 1).
--define(GL_ARB_sync, 1).
--define(GL_ARB_texture_multisample, 1).
--define(GL_ARB_vertex_array_bgra, 1).
--define(GL_ARB_draw_buffers_blend, 1).
--define(GL_ARB_sample_shading, 1).
--define(GL_ARB_texture_cube_map_array, 1).
--define(GL_ARB_texture_gather, 1).
--define(GL_ARB_texture_query_lod, 1).
--define(GL_ARB_shading_language_include, 1).
--define(GL_ARB_texture_compression_bptc, 1).
--define(GL_ARB_blend_func_extended, 1).
--define(GL_ARB_explicit_attrib_location, 1).
--define(GL_ARB_occlusion_query2, 1).
--define(GL_ARB_sampler_objects, 1).
--define(GL_ARB_texture_rgb10_a2ui, 1).
--define(GL_ARB_texture_swizzle, 1).
--define(GL_ARB_timer_query, 1).
--define(GL_ARB_vertex_type_2_10_10_10_rev, 1).
--define(GL_ARB_draw_indirect, 1).
--define(GL_ARB_gpu_shader5, 1).
--define(GL_ARB_gpu_shader_fp64, 1).
--define(GL_ARB_shader_subroutine, 1).
--define(GL_ARB_tessellation_shader, 1).
--define(GL_ARB_texture_buffer_object_rgb32, 1).
--define(GL_ARB_transform_feedback2, 1).
--define(GL_ARB_transform_feedback3, 1).
--define(GL_ARB_ES2_compatibility, 1).
--define(GL_ARB_get_program_binary, 1).
--define(GL_ARB_separate_shader_objects, 1).
--define(GL_ARB_vertex_attrib_64bit, 1).
--define(GL_ARB_viewport_array, 1).
--define(GL_ARB_cl_event, 1).
--define(GL_ARB_debug_output, 1).
--define(GL_ARB_robustness, 1).
--define(GL_ARB_shader_stencil_export, 1).
--define(GL_EXT_abgr, 1).
--define(GL_EXT_blend_color, 1).
--define(GL_EXT_polygon_offset, 1).
--define(GL_EXT_texture, 1).
--define(GL_EXT_texture3D, 1).
--define(GL_SGIS_texture_filter4, 1).
--define(GL_EXT_subtexture, 1).
--define(GL_EXT_copy_texture, 1).
--define(GL_EXT_histogram, 1).
--define(GL_EXT_convolution, 1).
--define(GL_SGI_color_matrix, 1).
--define(GL_SGI_color_table, 1).
--define(GL_SGIX_pixel_texture, 1).
--define(GL_SGIS_pixel_texture, 1).
--define(GL_SGIS_texture4D, 1).
--define(GL_SGI_texture_color_table, 1).
--define(GL_EXT_cmyka, 1).
--define(GL_EXT_texture_object, 1).
--define(GL_SGIS_detail_texture, 1).
--define(GL_SGIS_sharpen_texture, 1).
--define(GL_EXT_packed_pixels, 1).
--define(GL_SGIS_texture_lod, 1).
--define(GL_SGIS_multisample, 1).
--define(GL_EXT_rescale_normal, 1).
--define(GL_EXT_vertex_array, 1).
--define(GL_EXT_misc_attribute, 1).
--define(GL_SGIS_generate_mipmap, 1).
--define(GL_SGIX_clipmap, 1).
--define(GL_SGIX_shadow, 1).
--define(GL_SGIS_texture_edge_clamp, 1).
--define(GL_SGIS_texture_border_clamp, 1).
--define(GL_EXT_blend_minmax, 1).
--define(GL_EXT_blend_subtract, 1).
--define(GL_EXT_blend_logic_op, 1).
--define(GL_SGIX_interlace, 1).
--define(GL_SGIX_pixel_tiles, 1).
--define(GL_SGIX_texture_select, 1).
--define(GL_SGIX_sprite, 1).
--define(GL_SGIX_texture_multi_buffer, 1).
--define(GL_EXT_point_parameters, 1).
--define(GL_SGIS_point_parameters, 1).
--define(GL_SGIX_instruments, 1).
--define(GL_SGIX_texture_scale_bias, 1).
--define(GL_SGIX_framezoom, 1).
--define(GL_SGIX_tag_sample_buffer, 1).
--define(GL_SGIX_polynomial_ffd, 1).
--define(GL_SGIX_reference_plane, 1).
--define(GL_SGIX_flush_raster, 1).
--define(GL_SGIX_depth_texture, 1).
--define(GL_SGIS_fog_function, 1).
--define(GL_SGIX_fog_offset, 1).
--define(GL_HP_image_transform, 1).
--define(GL_HP_convolution_border_modes, 1).
--define(GL_SGIX_texture_add_env, 1).
--define(GL_EXT_color_subtable, 1).
--define(GL_PGI_vertex_hints, 1).
--define(GL_PGI_misc_hints, 1).
--define(GL_EXT_paletted_texture, 1).
--define(GL_EXT_clip_volume_hint, 1).
--define(GL_SGIX_list_priority, 1).
--define(GL_SGIX_ir_instrument1, 1).
--define(GL_SGIX_calligraphic_fragment, 1).
--define(GL_SGIX_texture_lod_bias, 1).
--define(GL_SGIX_shadow_ambient, 1).
--define(GL_EXT_index_texture, 1).
--define(GL_EXT_index_material, 1).
--define(GL_EXT_index_func, 1).
--define(GL_EXT_index_array_formats, 1).
--define(GL_EXT_compiled_vertex_array, 1).
--define(GL_EXT_cull_vertex, 1).
--define(GL_SGIX_ycrcb, 1).
--define(GL_SGIX_fragment_lighting, 1).
--define(GL_IBM_rasterpos_clip, 1).
--define(GL_HP_texture_lighting, 1).
--define(GL_EXT_draw_range_elements, 1).
--define(GL_WIN_phong_shading, 1).
--define(GL_WIN_specular_fog, 1).
--define(GL_EXT_light_texture, 1).
--define(GL_SGIX_blend_alpha_minmax, 1).
--define(GL_EXT_bgra, 1).
--define(GL_SGIX_async, 1).
--define(GL_SGIX_async_pixel, 1).
--define(GL_SGIX_async_histogram, 1).
--define(GL_INTEL_parallel_arrays, 1).
--define(GL_HP_occlusion_test, 1).
--define(GL_EXT_pixel_transform, 1).
--define(GL_EXT_pixel_transform_color_table, 1).
--define(GL_EXT_shared_texture_palette, 1).
--define(GL_EXT_separate_specular_color, 1).
--define(GL_EXT_secondary_color, 1).
--define(GL_EXT_texture_perturb_normal, 1).
--define(GL_EXT_multi_draw_arrays, 1).
--define(GL_EXT_fog_coord, 1).
--define(GL_REND_screen_coordinates, 1).
--define(GL_EXT_coordinate_frame, 1).
--define(GL_EXT_texture_env_combine, 1).
--define(GL_APPLE_specular_vector, 1).
--define(GL_APPLE_transform_hint, 1).
--define(GL_SGIX_fog_scale, 1).
--define(GL_SUNX_constant_data, 1).
--define(GL_SUN_global_alpha, 1).
--define(GL_SUN_triangle_list, 1).
--define(GL_SUN_vertex, 1).
--define(GL_EXT_blend_func_separate, 1).
--define(GL_INGR_blend_func_separate, 1).
--define(GL_INGR_color_clamp, 1).
--define(GL_INGR_interlace_read, 1).
--define(GL_EXT_stencil_wrap, 1).
--define(GL_EXT_422_pixels, 1).
--define(GL_NV_texgen_reflection, 1).
--define(GL_SUN_convolution_border_modes, 1).
--define(GL_EXT_texture_env_add, 1).
--define(GL_EXT_texture_lod_bias, 1).
--define(GL_EXT_texture_filter_anisotropic, 1).
--define(GL_EXT_vertex_weighting, 1).
--define(GL_NV_light_max_exponent, 1).
--define(GL_NV_vertex_array_range, 1).
--define(GL_NV_register_combiners, 1).
--define(GL_NV_fog_distance, 1).
--define(GL_NV_texgen_emboss, 1).
--define(GL_NV_blend_square, 1).
--define(GL_NV_texture_env_combine4, 1).
--define(GL_MESA_resize_buffers, 1).
--define(GL_MESA_window_pos, 1).
--define(GL_IBM_cull_vertex, 1).
--define(GL_IBM_multimode_draw_arrays, 1).
--define(GL_IBM_vertex_array_lists, 1).
--define(GL_SGIX_subsample, 1).
--define(GL_SGIX_ycrcba, 1).
--define(GL_SGIX_ycrcb_subsample, 1).
--define(GL_SGIX_depth_pass_instrument, 1).
--define(GL_3DFX_texture_compression_FXT1, 1).
--define(GL_3DFX_multisample, 1).
--define(GL_3DFX_tbuffer, 1).
--define(GL_EXT_multisample, 1).
--define(GL_SGIX_vertex_preclip, 1).
--define(GL_SGIX_convolution_accuracy, 1).
--define(GL_SGIX_resample, 1).
--define(GL_SGIS_point_line_texgen, 1).
--define(GL_SGIS_texture_color_mask, 1).
--define(GL_SGIX_igloo_interface, 1).
--define(GL_EXT_texture_env_dot3, 1).
--define(GL_ATI_texture_mirror_once, 1).
--define(GL_NV_fence, 1).
--define(GL_NV_evaluators, 1).
--define(GL_NV_packed_depth_stencil, 1).
--define(GL_NV_register_combiners2, 1).
--define(GL_NV_texture_compression_vtc, 1).
--define(GL_NV_texture_rectangle, 1).
--define(GL_NV_texture_shader, 1).
--define(GL_NV_texture_shader2, 1).
--define(GL_NV_vertex_array_range2, 1).
--define(GL_NV_vertex_program, 1).
--define(GL_SGIX_texture_coordinate_clamp, 1).
--define(GL_SGIX_scalebias_hint, 1).
--define(GL_OML_interlace, 1).
--define(GL_OML_subsample, 1).
--define(GL_OML_resample, 1).
--define(GL_NV_copy_depth_to_color, 1).
--define(GL_ATI_envmap_bumpmap, 1).
--define(GL_ATI_fragment_shader, 1).
--define(GL_ATI_pn_triangles, 1).
--define(GL_ATI_vertex_array_object, 1).
--define(GL_EXT_vertex_shader, 1).
--define(GL_ATI_vertex_streams, 1).
--define(GL_ATI_element_array, 1).
--define(GL_SUN_mesh_array, 1).
--define(GL_SUN_slice_accum, 1).
--define(GL_NV_multisample_filter_hint, 1).
--define(GL_NV_depth_clamp, 1).
--define(GL_NV_occlusion_query, 1).
--define(GL_NV_point_sprite, 1).
--define(GL_NV_texture_shader3, 1).
--define(GL_NV_vertex_program1_1, 1).
--define(GL_EXT_shadow_funcs, 1).
--define(GL_EXT_stencil_two_side, 1).
--define(GL_ATI_text_fragment_shader, 1).
--define(GL_APPLE_client_storage, 1).
--define(GL_APPLE_element_array, 1).
--define(GL_APPLE_fence, 1).
--define(GL_APPLE_vertex_array_object, 1).
--define(GL_APPLE_vertex_array_range, 1).
--define(GL_APPLE_ycbcr_422, 1).
--define(GL_S3_s3tc, 1).
--define(GL_ATI_draw_buffers, 1).
--define(GL_ATI_pixel_format_float, 1).
--define(GL_ATI_texture_env_combine3, 1).
--define(GL_ATI_texture_float, 1).
--define(GL_NV_float_buffer, 1).
--define(GL_NV_fragment_program, 1).
--define(GL_NV_half_float, 1).
--define(GL_NV_pixel_data_range, 1).
--define(GL_NV_primitive_restart, 1).
--define(GL_NV_texture_expand_normal, 1).
--define(GL_NV_vertex_program2, 1).
--define(GL_ATI_map_object_buffer, 1).
--define(GL_ATI_separate_stencil, 1).
--define(GL_ATI_vertex_attrib_array_object, 1).
--define(GL_OES_read_format, 1).
--define(GL_EXT_depth_bounds_test, 1).
--define(GL_EXT_texture_mirror_clamp, 1).
--define(GL_EXT_blend_equation_separate, 1).
--define(GL_MESA_pack_invert, 1).
--define(GL_MESA_ycbcr_texture, 1).
--define(GL_EXT_pixel_buffer_object, 1).
--define(GL_NV_fragment_program_option, 1).
--define(GL_NV_fragment_program2, 1).
--define(GL_NV_vertex_program2_option, 1).
--define(GL_NV_vertex_program3, 1).
--define(GL_EXT_framebuffer_object, 1).
--define(GL_GREMEDY_string_marker, 1).
--define(GL_EXT_packed_depth_stencil, 1).
--define(GL_EXT_stencil_clear_tag, 1).
--define(GL_EXT_texture_sRGB, 1).
--define(GL_EXT_framebuffer_blit, 1).
--define(GL_EXT_framebuffer_multisample, 1).
--define(GL_MESAX_texture_stack, 1).
--define(GL_EXT_timer_query, 1).
--define(GL_EXT_gpu_program_parameters, 1).
--define(GL_APPLE_flush_buffer_range, 1).
--define(GL_NV_gpu_program4, 1).
--define(GL_NV_geometry_program4, 1).
--define(GL_EXT_geometry_shader4, 1).
--define(GL_NV_vertex_program4, 1).
--define(GL_EXT_gpu_shader4, 1).
--define(GL_EXT_draw_instanced, 1).
--define(GL_EXT_packed_float, 1).
--define(GL_EXT_texture_array, 1).
--define(GL_EXT_texture_buffer_object, 1).
--define(GL_EXT_texture_compression_latc, 1).
--define(GL_EXT_texture_compression_rgtc, 1).
--define(GL_EXT_texture_shared_exponent, 1).
--define(GL_NV_depth_buffer_float, 1).
--define(GL_NV_fragment_program4, 1).
--define(GL_NV_framebuffer_multisample_coverage, 1).
--define(GL_EXT_framebuffer_sRGB, 1).
--define(GL_NV_geometry_shader4, 1).
--define(GL_NV_parameter_buffer_object, 1).
--define(GL_EXT_draw_buffers2, 1).
--define(GL_NV_transform_feedback, 1).
--define(GL_EXT_bindable_uniform, 1).
--define(GL_EXT_texture_integer, 1).
--define(GL_GREMEDY_frame_terminator, 1).
--define(GL_NV_conditional_render, 1).
--define(GL_NV_present_video, 1).
--define(GL_EXT_transform_feedback, 1).
--define(GL_EXT_direct_state_access, 1).
--define(GL_EXT_vertex_array_bgra, 1).
--define(GL_EXT_texture_swizzle, 1).
--define(GL_NV_explicit_multisample, 1).
--define(GL_NV_transform_feedback2, 1).
--define(GL_ATI_meminfo, 1).
--define(GL_AMD_performance_monitor, 1).
--define(GL_AMD_texture_texture4, 1).
--define(GL_AMD_vertex_shader_tesselator, 1).
--define(GL_EXT_provoking_vertex, 1).
--define(GL_EXT_texture_snorm, 1).
--define(GL_AMD_draw_buffers_blend, 1).
--define(GL_APPLE_texture_range, 1).
--define(GL_APPLE_float_pixels, 1).
--define(GL_APPLE_vertex_program_evaluators, 1).
--define(GL_APPLE_aux_depth_stencil, 1).
--define(GL_APPLE_object_purgeable, 1).
--define(GL_APPLE_row_bytes, 1).
--define(GL_APPLE_rgb_422, 1).
--define(GL_NV_video_capture, 1).
--define(GL_NV_copy_image, 1).
--define(GL_EXT_separate_shader_objects, 1).
--define(GL_NV_parameter_buffer_object2, 1).
--define(GL_NV_shader_buffer_load, 1).
--define(GL_NV_vertex_buffer_unified_memory, 1).
--define(GL_NV_texture_barrier, 1).
--define(GL_AMD_shader_stencil_export, 1).
--define(GL_AMD_seamless_cubemap_per_texture, 1).
--define(GL_AMD_conservative_depth, 1).
--define(GL_EXT_shader_image_load_store, 1).
--define(GL_EXT_vertex_attrib_64bit, 1).
--define(GL_NV_gpu_program5, 1).
--define(GL_NV_gpu_shader5, 1).
--define(GL_NV_shader_buffer_store, 1).
--define(GL_NV_tessellation_program5, 1).
--define(GL_NV_vertex_attrib_integer_64bit, 1).
--define(GL_NV_multisample_coverage, 1).
--define(GL_AMD_name_gen_delete, 1).
--define(GL_AMD_debug_output, 1).
--define(GL_NV_vdpau_interop, 1).
--define(GL_AMD_transform_feedback3_lines_triangles, 1).
+-define(GL_DEPTH_CLAMP_NEAR_AMD, 16#901E).
+-define(GL_DEPTH_CLAMP_FAR_AMD, 16#901F).
diff --git a/lib/wx/include/wx.hrl b/lib/wx/include/wx.hrl
index 8659b71985..029b9a88df 100644
--- a/lib/wx/include/wx.hrl
+++ b/lib/wx/include/wx.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -36,12 +36,12 @@
%% Callback event: {@link wxNavigationKeyEvent}
-record(wxNavigationKey,{type, flags,focus}).
-%% @type wxSash() = #wxSash{type=wxEventType(),edge=WxSashEdgePosition,dragRect={X::integer(),Y::integer(),W::integer(),H::integer()},dragStatus=WxSashDragStatus}.
+%% @type wxSash() = #wxSash{type=wxEventType(),edge=WxSashEdgePosition,dragRect={X::integer(), Y::integer(), W::integer(), H::integer()},dragStatus=WxSashDragStatus}.
%% <dl><dt>EventType:</dt> <dd><em>sash_dragged</em></dd></dl>
%% Callback event: {@link wxSashEvent}
-record(wxSash,{type, edge,dragRect,dragStatus}).
-%% @type wxList() = #wxList{type=wxEventType(),code=integer(),oldItemIndex=integer(),itemIndex=integer(),col=integer(),pointDrag={X::integer(),Y::integer()}}.
+%% @type wxList() = #wxList{type=wxEventType(),code=integer(),oldItemIndex=integer(),itemIndex=integer(),col=integer(),pointDrag={X::integer(), Y::integer()}}.
%% <dl><dt>EventType:</dt> <dd><em>command_list_begin_drag</em>, <em>command_list_begin_rdrag</em>, <em>command_list_begin_label_edit</em>, <em>command_list_end_label_edit</em>, <em>command_list_delete_item</em>, <em>command_list_delete_all_items</em>, <em>command_list_key_down</em>, <em>command_list_insert_item</em>, <em>command_list_col_click</em>, <em>command_list_col_right_click</em>, <em>command_list_col_begin_drag</em>, <em>command_list_col_dragging</em>, <em>command_list_col_end_drag</em>, <em>command_list_item_selected</em>, <em>command_list_item_deselected</em>, <em>command_list_item_right_click</em>, <em>command_list_item_middle_click</em>, <em>command_list_item_activated</em>, <em>command_list_item_focused</em>, <em>command_list_cache_hint</em></dd></dl>
%% Callback event: {@link wxListEvent}
-record(wxList,{type, code,oldItemIndex,itemIndex,col,pointDrag}).
@@ -186,7 +186,7 @@
%% Callback event: {@link wxUpdateUIEvent}
-record(wxUpdateUI, {type}).
-%% @type wxSize() = #wxSize{type=wxEventType(),size={W::integer(),H::integer()},rect={X::integer(),Y::integer(),W::integer(),H::integer()}}.
+%% @type wxSize() = #wxSize{type=wxEventType(),size={W::integer(), H::integer()},rect={X::integer(), Y::integer(), W::integer(), H::integer()}}.
%% <dl><dt>EventType:</dt> <dd><em>size</em></dd></dl>
%% Callback event: {@link wxSizeEvent}
-record(wxSize,{type, size,rect}).
@@ -261,7 +261,7 @@
%% Callback event: {@link wxColourPickerEvent}
-record(wxColourPicker,{type, colour}).
-%% @type wxTree() = #wxTree{type=wxEventType(),item=integer(),itemOld=integer(),pointDrag={X::integer(),Y::integer()}}.
+%% @type wxTree() = #wxTree{type=wxEventType(),item=integer(),itemOld=integer(),pointDrag={X::integer(), Y::integer()}}.
%% <dl><dt>EventType:</dt> <dd><em>command_tree_begin_drag</em>, <em>command_tree_begin_rdrag</em>, <em>command_tree_begin_label_edit</em>, <em>command_tree_end_label_edit</em>, <em>command_tree_delete_item</em>, <em>command_tree_get_info</em>, <em>command_tree_set_info</em>, <em>command_tree_item_expanded</em>, <em>command_tree_item_expanding</em>, <em>command_tree_item_collapsed</em>, <em>command_tree_item_collapsing</em>, <em>command_tree_sel_changed</em>, <em>command_tree_sel_changing</em>, <em>command_tree_key_down</em>, <em>command_tree_item_activated</em>, <em>command_tree_item_right_click</em>, <em>command_tree_item_middle_click</em>, <em>command_tree_end_drag</em>, <em>command_tree_state_image_click</em>, <em>command_tree_item_gettooltip</em>, <em>command_tree_item_menu</em></dd></dl>
%% Callback event: {@link wxTreeEvent}
-record(wxTree,{type, item,itemOld,pointDrag}).
diff --git a/lib/wx/src/gen/wxArtProvider.erl b/lib/wx/src/gen/wxArtProvider.erl
index 7a45b0d79d..1955bd2e29 100644
--- a/lib/wx/src/gen/wxArtProvider.erl
+++ b/lib/wx/src/gen/wxArtProvider.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -39,7 +39,7 @@ getBitmap(Id)
getBitmap(Id, []).
%% @spec (Id::string(), [Option]) -> wxBitmap:wxBitmap()
-%% Option = {client, string()} | {size, {W::integer(),H::integer()}}
+%% Option = {client, string()} | {size, {W::integer(), H::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxartprovider.html#wxartprovidergetbitmap">external documentation</a>.
getBitmap(Id, Options)
when is_list(Id),is_list(Options) ->
@@ -58,7 +58,7 @@ getIcon(Id)
getIcon(Id, []).
%% @spec (Id::string(), [Option]) -> wxIcon:wxIcon()
-%% Option = {client, string()} | {size, {W::integer(),H::integer()}}
+%% Option = {client, string()} | {size, {W::integer(), H::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxartprovider.html#wxartprovidergeticon">external documentation</a>.
getIcon(Id, Options)
when is_list(Id),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxAuiManager.erl b/lib/wx/src/gen/wxAuiManager.erl
index ad0af6652d..893867cec1 100644
--- a/lib/wx/src/gen/wxAuiManager.erl
+++ b/lib/wx/src/gen/wxAuiManager.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -91,7 +91,7 @@ addPane(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef},#wx_
wxe_util:call(?wxAuiManager_AddPane_2_1,
<<ThisRef:32/?UI,WindowRef:32/?UI,Pane_infoRef:32/?UI>>).
-%% @spec (This::wxAuiManager(), Window::wxWindow:wxWindow(), Pane_info::wxAuiPaneInfo:wxAuiPaneInfo(), Drop_pos::{X::integer(),Y::integer()}) -> bool()
+%% @spec (This::wxAuiManager(), Window::wxWindow:wxWindow(), Pane_info::wxAuiPaneInfo:wxAuiPaneInfo(), Drop_pos::{X::integer(), Y::integer()}) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanageraddpane">external documentation</a>.
addPane(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef},#wx_ref{type=Pane_infoT,ref=Pane_infoRef},{Drop_posX,Drop_posY})
when is_integer(Drop_posX),is_integer(Drop_posY) ->
@@ -123,7 +123,7 @@ getArtProvider(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxAuiManager_GetArtProvider,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiManager()) -> {Width_pct::float(),Height_pct::float()}
+%% @spec (This::wxAuiManager()) -> {Width_pct::float(), Height_pct::float()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanagergetdocksizeconstraint">external documentation</a>.
getDockSizeConstraint(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiManager),
@@ -275,7 +275,7 @@ setManagedWindow(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=Managed_wndT,ref=M
wxe_util:cast(?wxAuiManager_SetManagedWindow,
<<ThisRef:32/?UI,Managed_wndRef:32/?UI>>).
-%% @spec (This::wxAuiManager(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> ok
+%% @spec (This::wxAuiManager(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanagershowhint">external documentation</a>.
showHint(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
diff --git a/lib/wx/src/gen/wxAuiNotebook.erl b/lib/wx/src/gen/wxAuiNotebook.erl
index 5d486aeaa2..5862bb26c7 100644
--- a/lib/wx/src/gen/wxAuiNotebook.erl
+++ b/lib/wx/src/gen/wxAuiNotebook.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -92,7 +92,7 @@ new(Parent)
new(Parent, []).
%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxAuiNotebook()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {id, integer()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebook.html#wxauinotebookwxauinotebook">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
@@ -134,7 +134,7 @@ create(This,Parent)
create(This,Parent, []).
%% @spec (This::wxAuiNotebook(), Parent::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {id, integer()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebook.html#wxauinotebookcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
@@ -289,7 +289,7 @@ setTabCtrlHeight(#wx_ref{type=ThisT,ref=ThisRef},Height)
wxe_util:cast(?wxAuiNotebook_SetTabCtrlHeight,
<<ThisRef:32/?UI,Height:32/?UI>>).
-%% @spec (This::wxAuiNotebook(), Size::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxAuiNotebook(), Size::{W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebook.html#wxauinotebooksetuniformbitmapsize">external documentation</a>.
setUniformBitmapSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
diff --git a/lib/wx/src/gen/wxAuiPaneInfo.erl b/lib/wx/src/gen/wxAuiPaneInfo.erl
index 7b1401b069..b15f91c675 100644
--- a/lib/wx/src/gen/wxAuiPaneInfo.erl
+++ b/lib/wx/src/gen/wxAuiPaneInfo.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -60,7 +60,7 @@ new(#wx_ref{type=CT,ref=CRef}) ->
wxe_util:construct(?wxAuiPaneInfo_new_1,
<<CRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo(), Size::{W::integer(),H::integer()}) -> wxAuiPaneInfo()
+%% @spec (This::wxAuiPaneInfo(), Size::{W::integer(), H::integer()}) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfobestsize">external documentation</a>.
bestSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
@@ -250,7 +250,7 @@ floatable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxAuiPaneInfo_Floatable,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxAuiPaneInfo(), Pos::{X::integer(),Y::integer()}) -> wxAuiPaneInfo()
+%% @spec (This::wxAuiPaneInfo(), Pos::{X::integer(), Y::integer()}) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfofloatingposition">external documentation</a>.
floatingPosition(#wx_ref{type=ThisT,ref=ThisRef},{PosX,PosY})
when is_integer(PosX),is_integer(PosY) ->
@@ -266,7 +266,7 @@ floatingPosition(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
wxe_util:call(?wxAuiPaneInfo_FloatingPosition_2,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo(), Size::{W::integer(),H::integer()}) -> wxAuiPaneInfo()
+%% @spec (This::wxAuiPaneInfo(), Size::{W::integer(), H::integer()}) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfofloatingsize">external documentation</a>.
floatingSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
@@ -513,7 +513,7 @@ leftDockable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxAuiPaneInfo_LeftDockable,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxAuiPaneInfo(), Size::{W::integer(),H::integer()}) -> wxAuiPaneInfo()
+%% @spec (This::wxAuiPaneInfo(), Size::{W::integer(), H::integer()}) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfomaxsize">external documentation</a>.
maxSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
@@ -547,7 +547,7 @@ maximizeButton(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxAuiPaneInfo_MaximizeButton,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxAuiPaneInfo(), Size::{W::integer(),H::integer()}) -> wxAuiPaneInfo()
+%% @spec (This::wxAuiPaneInfo(), Size::{W::integer(), H::integer()}) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfominsize">external documentation</a>.
minSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
diff --git a/lib/wx/src/gen/wxBitmap.erl b/lib/wx/src/gen/wxBitmap.erl
index 53c57e4393..bd2f83c6eb 100644
--- a/lib/wx/src/gen/wxBitmap.erl
+++ b/lib/wx/src/gen/wxBitmap.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -194,7 +194,7 @@ getWidth(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxBitmap_GetWidth,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxBitmap(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> wxBitmap()
+%% @spec (This::wxBitmap(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> wxBitmap()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmap.html#wxbitmapgetsubbitmap">external documentation</a>.
getSubBitmap(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
diff --git a/lib/wx/src/gen/wxBitmapButton.erl b/lib/wx/src/gen/wxBitmapButton.erl
index 0c187bf1c1..d2353466e7 100644
--- a/lib/wx/src/gen/wxBitmapButton.erl
+++ b/lib/wx/src/gen/wxBitmapButton.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -92,7 +92,7 @@ new(Parent,Id,Bitmap)
new(Parent,Id,Bitmap, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Bitmap::wxBitmap:wxBitmap(), [Option]) -> wxBitmapButton()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmapbutton.html#wxbitmapbuttonwxbitmapbutton">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,#wx_ref{type=BitmapT,ref=BitmapRef}, Options)
when is_integer(Id),is_list(Options) ->
@@ -114,7 +114,7 @@ create(This,Parent,Id,Bitmap)
create(This,Parent,Id,Bitmap, []).
%% @spec (This::wxBitmapButton(), Parent::wxWindow:wxWindow(), Id::integer(), Bitmap::wxBitmap:wxBitmap(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmapbutton.html#wxbitmapbuttoncreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,#wx_ref{type=BitmapT,ref=BitmapRef}, Options)
when is_integer(Id),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxBoxSizer.erl b/lib/wx/src/gen/wxBoxSizer.erl
index 1d5b1cf2fa..e6287945a9 100644
--- a/lib/wx/src/gen/wxBoxSizer.erl
+++ b/lib/wx/src/gen/wxBoxSizer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -102,7 +102,7 @@ prepend(This,Width,Height, Options) -> wxSizer:prepend(This,Width,Height, Option
%% @hidden
prepend(This,Width,Height) -> wxSizer:prepend(This,Width,Height).
%% @hidden
-prepend(This,Window) -> wxSizer:prepend(This,Window).
+prepend(This,Item) -> wxSizer:prepend(This,Item).
%% @hidden
layout(This) -> wxSizer:layout(This).
%% @hidden
@@ -118,7 +118,7 @@ insert(This,Index,Width,Height, Options) -> wxSizer:insert(This,Index,Width,Heig
%% @hidden
insert(This,Index,Width,Height) -> wxSizer:insert(This,Index,Width,Height).
%% @hidden
-insert(This,Index,Window) -> wxSizer:insert(This,Index,Window).
+insert(This,Index,Item) -> wxSizer:insert(This,Index,Item).
%% @hidden
hide(This,Window, Options) -> wxSizer:hide(This,Window, Options).
%% @hidden
diff --git a/lib/wx/src/gen/wxBufferedDC.erl b/lib/wx/src/gen/wxBufferedDC.erl
index 6e341a8552..9096f95612 100644
--- a/lib/wx/src/gen/wxBufferedDC.erl
+++ b/lib/wx/src/gen/wxBufferedDC.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -74,7 +74,7 @@ new(Dc)
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbuffereddc.html#wxbuffereddcwxbuffereddc">external documentation</a>.
%% <br /> Alternatives:
%% <p><c>
-%% new(Dc::wxDC:wxDC(), Area::{W::integer(),H::integer()}) -> new(Dc,Area, []) </c></p>
+%% new(Dc::wxDC:wxDC(), Area::{W::integer(), H::integer()}) -> new(Dc,Area, []) </c></p>
%% <p><c>
%% new(Dc::wxDC:wxDC(), [Option]) -> wxBufferedDC() </c>
%%<br /> Option = {buffer, wxBitmap:wxBitmap()} | {style, integer()}
@@ -93,7 +93,7 @@ new(#wx_ref{type=DcT,ref=DcRef}, Options)
wxe_util:construct(?wxBufferedDC_new_2,
<<DcRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (Dc::wxDC:wxDC(), Area::{W::integer(),H::integer()}, [Option]) -> wxBufferedDC()
+%% @spec (Dc::wxDC:wxDC(), Area::{W::integer(), H::integer()}, [Option]) -> wxBufferedDC()
%% Option = {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbuffereddc.html#wxbuffereddcwxbuffereddc">external documentation</a>.
new(#wx_ref{type=DcT,ref=DcRef},{AreaW,AreaH}, Options)
@@ -115,7 +115,7 @@ init(This,Dc)
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbuffereddc.html#wxbuffereddcinit">external documentation</a>.
%% <br /> Alternatives:
%% <p><c>
-%% init(This::wxBufferedDC(), Dc::wxDC:wxDC(), Area::{W::integer(),H::integer()}) -> init(This,Dc,Area, []) </c></p>
+%% init(This::wxBufferedDC(), Dc::wxDC:wxDC(), Area::{W::integer(), H::integer()}) -> init(This,Dc,Area, []) </c></p>
%% <p><c>
%% init(This::wxBufferedDC(), Dc::wxDC:wxDC(), [Option]) -> ok </c>
%%<br /> Option = {buffer, wxBitmap:wxBitmap()} | {style, integer()}
@@ -135,7 +135,7 @@ init(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=DcT,ref=DcRef}, Options)
wxe_util:cast(?wxBufferedDC_Init_2,
<<ThisRef:32/?UI,DcRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxBufferedDC(), Dc::wxDC:wxDC(), Area::{W::integer(),H::integer()}, [Option]) -> ok
+%% @spec (This::wxBufferedDC(), Dc::wxDC:wxDC(), Area::{W::integer(), H::integer()}, [Option]) -> ok
%% Option = {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbuffereddc.html#wxbuffereddcinit">external documentation</a>.
init(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=DcT,ref=DcRef},{AreaW,AreaH}, Options)
diff --git a/lib/wx/src/gen/wxButton.erl b/lib/wx/src/gen/wxButton.erl
index c0e21a5657..a75c45c5a3 100644
--- a/lib/wx/src/gen/wxButton.erl
+++ b/lib/wx/src/gen/wxButton.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -89,7 +89,7 @@ new(Parent,Id)
new(Parent,Id, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxButton()
-%% Option = {label, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {label, string()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbutton.html#wxbuttonwxbutton">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
@@ -111,7 +111,7 @@ create(This,Parent,Id)
create(This,Parent,Id, []).
%% @spec (This::wxButton(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {label, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {label, string()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbutton.html#wxbuttoncreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
@@ -127,7 +127,7 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, O
wxe_util:call(?wxButton_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec () -> {W::integer(),H::integer()}
+%% @spec () -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbutton.html#wxbuttongetdefaultsize">external documentation</a>.
getDefaultSize() ->
wxe_util:call(?wxButton_GetDefaultSize,
diff --git a/lib/wx/src/gen/wxCalendarCtrl.erl b/lib/wx/src/gen/wxCalendarCtrl.erl
index 8ad4d5954b..1bb4ecb1fa 100644
--- a/lib/wx/src/gen/wxCalendarCtrl.erl
+++ b/lib/wx/src/gen/wxCalendarCtrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -93,7 +93,7 @@ new(Parent,Id)
new(Parent,Id, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxCalendarCtrl()
-%% Option = {date, wx:datetime()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {date, wx:datetime()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarctrl.html#wxcalendarctrlwxcalendarctrl">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
@@ -114,7 +114,7 @@ create(This,Parent,Id)
create(This,Parent,Id, []).
%% @spec (This::wxCalendarCtrl(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {date, wx:datetime()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {date, wx:datetime()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarctrl.html#wxcalendarctrlcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
@@ -297,7 +297,7 @@ resetAttr(#wx_ref{type=ThisT,ref=ThisRef},Day)
wxe_util:cast(?wxCalendarCtrl_ResetAttr,
<<ThisRef:32/?UI,Day:32/?UI>>).
-%% @spec (This::wxCalendarCtrl(), Pos::{X::integer(),Y::integer()}) -> {WxCalendarHitTestResult,Date::wx:datetime(),Wd::WeekDay}
+%% @spec (This::wxCalendarCtrl(), Pos::{X::integer(), Y::integer()}) -> {WxCalendarHitTestResult, Date::wx:datetime(), Wd::WeekDay}
%% WxCalendarHitTestResult = integer()
%% WeekDay = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarctrl.html#wxcalendarctrlhittest">external documentation</a>.
diff --git a/lib/wx/src/gen/wxCaret.erl b/lib/wx/src/gen/wxCaret.erl
index 3e1a3d544c..cbd868f388 100644
--- a/lib/wx/src/gen/wxCaret.erl
+++ b/lib/wx/src/gen/wxCaret.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -34,7 +34,7 @@
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Window::wxWindow:wxWindow(), Size::{W::integer(),H::integer()}) -> wxCaret()
+%% @spec (Window::wxWindow:wxWindow(), Size::{W::integer(), H::integer()}) -> wxCaret()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcaret.html#wxcaretwxcaret">external documentation</a>.
new(#wx_ref{type=WindowT,ref=WindowRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
@@ -50,7 +50,7 @@ new(#wx_ref{type=WindowT,ref=WindowRef},Width,Height)
wxe_util:construct(?wxCaret_new_3,
<<WindowRef:32/?UI,Width:32/?UI,Height:32/?UI>>).
-%% @spec (This::wxCaret(), Window::wxWindow:wxWindow(), Size::{W::integer(),H::integer()}) -> bool()
+%% @spec (This::wxCaret(), Window::wxWindow:wxWindow(), Size::{W::integer(), H::integer()}) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcaret.html#wxcaretcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
@@ -74,14 +74,14 @@ getBlinkTime() ->
wxe_util:call(?wxCaret_GetBlinkTime,
<<>>).
-%% @spec (This::wxCaret()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxCaret()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcaret.html#wxcaretgetposition">external documentation</a>.
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCaret),
wxe_util:call(?wxCaret_GetPosition,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCaret()) -> {W::integer(),H::integer()}
+%% @spec (This::wxCaret()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcaret.html#wxcaretgetsize">external documentation</a>.
getSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCaret),
@@ -116,7 +116,7 @@ isVisible(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxCaret_IsVisible,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCaret(), Pt::{X::integer(),Y::integer()}) -> ok
+%% @spec (This::wxCaret(), Pt::{X::integer(), Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcaret.html#wxcaretmove">external documentation</a>.
move(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
@@ -139,7 +139,7 @@ setBlinkTime(Milliseconds)
wxe_util:cast(?wxCaret_SetBlinkTime,
<<Milliseconds:32/?UI>>).
-%% @spec (This::wxCaret(), Size::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxCaret(), Size::{W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcaret.html#wxcaretsetsize">external documentation</a>.
setSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
diff --git a/lib/wx/src/gen/wxCheckBox.erl b/lib/wx/src/gen/wxCheckBox.erl
index c484483379..19f01645c1 100644
--- a/lib/wx/src/gen/wxCheckBox.erl
+++ b/lib/wx/src/gen/wxCheckBox.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -90,7 +90,7 @@ new(Parent,Id,Label)
new(Parent,Id,Label, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Label::string(), [Option]) -> wxCheckBox()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcheckbox.html#wxcheckboxwxcheckbox">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Label, Options)
when is_integer(Id),is_list(Label),is_list(Options) ->
@@ -112,7 +112,7 @@ create(This,Parent,Id,Label)
create(This,Parent,Id,Label, []).
%% @spec (This::wxCheckBox(), Parent::wxWindow:wxWindow(), Id::integer(), Label::string(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcheckbox.html#wxcheckboxcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Label, Options)
when is_integer(Id),is_list(Label),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxCheckListBox.erl b/lib/wx/src/gen/wxCheckListBox.erl
index c692997311..a1a07e1eec 100644
--- a/lib/wx/src/gen/wxCheckListBox.erl
+++ b/lib/wx/src/gen/wxCheckListBox.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -96,7 +96,7 @@ new(Parent,Id)
new(Parent,Id, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxCheckListBox()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {choices, [[string()]]} | {style, integer()} | {validator, wx:wx()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {choices, [[string()]]} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchecklistbox.html#wxchecklistboxwxchecklistbox">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxChoice.erl b/lib/wx/src/gen/wxChoice.erl
index eaf2f0352f..fa967d8487 100644
--- a/lib/wx/src/gen/wxChoice.erl
+++ b/lib/wx/src/gen/wxChoice.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -94,7 +94,7 @@ new(Parent,Id)
new(Parent,Id, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxChoice()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {choices, [[string()]]} | {style, integer()} | {validator, wx:wx()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {choices, [[string()]]} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoice.html#wxchoicewxchoice">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
@@ -109,13 +109,13 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
wxe_util:construct(?wxChoice_new_3,
<<ParentRef:32/?UI,Id:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxChoice(), Parent::wxWindow:wxWindow(), Id::integer(), Pos::{X::integer(),Y::integer()}, Size::{W::integer(),H::integer()}, Choices::[[string()]]) -> bool()
+%% @spec (This::wxChoice(), Parent::wxWindow:wxWindow(), Id::integer(), Pos::{X::integer(), Y::integer()}, Size::{W::integer(), H::integer()}, Choices::[[string()]]) -> bool()
%% @equiv create(This,Parent,Id,Pos,Size,Choices, [])
create(This,Parent,Id,Pos={PosX,PosY},Size={SizeW,SizeH},Choices)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id),is_integer(PosX),is_integer(PosY),is_integer(SizeW),is_integer(SizeH),is_list(Choices) ->
create(This,Parent,Id,Pos,Size,Choices, []).
-%% @spec (This::wxChoice(), Parent::wxWindow:wxWindow(), Id::integer(), Pos::{X::integer(),Y::integer()}, Size::{W::integer(),H::integer()}, Choices::[[string()]], [Option]) -> bool()
+%% @spec (This::wxChoice(), Parent::wxWindow:wxWindow(), Id::integer(), Pos::{X::integer(), Y::integer()}, Size::{W::integer(), H::integer()}, Choices::[[string()]], [Option]) -> bool()
%% Option = {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoice.html#wxchoicecreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,{PosX,PosY},{SizeW,SizeH},Choices, Options)
diff --git a/lib/wx/src/gen/wxChoicebook.erl b/lib/wx/src/gen/wxChoicebook.erl
index b724d0cad2..f37457f0ed 100644
--- a/lib/wx/src/gen/wxChoicebook.erl
+++ b/lib/wx/src/gen/wxChoicebook.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -93,7 +93,7 @@ new(Parent,Id)
new(Parent,Id, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxChoicebook()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebookwxchoicebook">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
@@ -160,7 +160,7 @@ create(This,Parent,Id)
create(This,Parent,Id, []).
%% @spec (This::wxChoicebook(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebookcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
@@ -249,7 +249,7 @@ getSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxChoicebook_GetSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxChoicebook(), Pt::{X::integer(),Y::integer()}) -> {integer(),Flags::integer()}
+%% @spec (This::wxChoicebook(), Pt::{X::integer(), Y::integer()}) -> {integer(), Flags::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebookhittest">external documentation</a>.
hitTest(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
@@ -286,7 +286,7 @@ setImageList(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ImageListT,ref=ImageLi
wxe_util:cast(?wxChoicebook_SetImageList,
<<ThisRef:32/?UI,ImageListRef:32/?UI>>).
-%% @spec (This::wxChoicebook(), Size::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxChoicebook(), Size::{W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebooksetpagesize">external documentation</a>.
setPageSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
diff --git a/lib/wx/src/gen/wxColourPickerCtrl.erl b/lib/wx/src/gen/wxColourPickerCtrl.erl
index 4f0816e1fd..60776925b9 100644
--- a/lib/wx/src/gen/wxColourPickerCtrl.erl
+++ b/lib/wx/src/gen/wxColourPickerCtrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -94,7 +94,7 @@ new(Parent,Id)
new(Parent,Id, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxColourPickerCtrl()
-%% Option = {col, wx:colour()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {col, wx:colour()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcolourpickerctrl.html#wxcolourpickerctrlwxcolourpickerctrl">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
@@ -116,7 +116,7 @@ create(This,Parent,Id)
create(This,Parent,Id, []).
%% @spec (This::wxColourPickerCtrl(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {col, wx:colour()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {col, wx:colour()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcolourpickerctrl.html#wxcolourpickerctrlcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxComboBox.erl b/lib/wx/src/gen/wxComboBox.erl
index 061e886734..f743df4e93 100644
--- a/lib/wx/src/gen/wxComboBox.erl
+++ b/lib/wx/src/gen/wxComboBox.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -96,7 +96,7 @@ new(Parent,Id)
new(Parent,Id, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxComboBox()
-%% Option = {value, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {choices, [[string()]]} | {style, integer()} | {validator, wx:wx()}
+%% Option = {value, string()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {choices, [[string()]]} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcombobox.html#wxcomboboxwxcombobox">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
@@ -112,13 +112,13 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
wxe_util:construct(?wxComboBox_new_3,
<<ParentRef:32/?UI,Id:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxComboBox(), Parent::wxWindow:wxWindow(), Id::integer(), Value::string(), Pos::{X::integer(),Y::integer()}, Size::{W::integer(),H::integer()}, Choices::[[string()]]) -> bool()
+%% @spec (This::wxComboBox(), Parent::wxWindow:wxWindow(), Id::integer(), Value::string(), Pos::{X::integer(), Y::integer()}, Size::{W::integer(), H::integer()}, Choices::[[string()]]) -> bool()
%% @equiv create(This,Parent,Id,Value,Pos,Size,Choices, [])
create(This,Parent,Id,Value,Pos={PosX,PosY},Size={SizeW,SizeH},Choices)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id),is_list(Value),is_integer(PosX),is_integer(PosY),is_integer(SizeW),is_integer(SizeH),is_list(Choices) ->
create(This,Parent,Id,Value,Pos,Size,Choices, []).
-%% @spec (This::wxComboBox(), Parent::wxWindow:wxWindow(), Id::integer(), Value::string(), Pos::{X::integer(),Y::integer()}, Size::{W::integer(),H::integer()}, Choices::[[string()]], [Option]) -> bool()
+%% @spec (This::wxComboBox(), Parent::wxWindow:wxWindow(), Id::integer(), Value::string(), Pos::{X::integer(), Y::integer()}, Size::{W::integer(), H::integer()}, Choices::[[string()]], [Option]) -> bool()
%% Option = {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcombobox.html#wxcomboboxcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Value,{PosX,PosY},{SizeW,SizeH},Choices, Options)
diff --git a/lib/wx/src/gen/wxContextMenuEvent.erl b/lib/wx/src/gen/wxContextMenuEvent.erl
index 56ed82f37c..0050b97b89 100644
--- a/lib/wx/src/gen/wxContextMenuEvent.erl
+++ b/lib/wx/src/gen/wxContextMenuEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -45,14 +45,14 @@ parent_class(wxCommandEvent) -> true;
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxContextMenuEvent()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxContextMenuEvent()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcontextmenuevent.html#wxcontextmenueventgetposition">external documentation</a>.
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxContextMenuEvent),
wxe_util:call(?wxContextMenuEvent_GetPosition,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxContextMenuEvent(), Pos::{X::integer(),Y::integer()}) -> ok
+%% @spec (This::wxContextMenuEvent(), Pos::{X::integer(), Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcontextmenuevent.html#wxcontextmenueventsetposition">external documentation</a>.
setPosition(#wx_ref{type=ThisT,ref=ThisRef},{PosX,PosY})
when is_integer(PosX),is_integer(PosY) ->
diff --git a/lib/wx/src/gen/wxDC.erl b/lib/wx/src/gen/wxDC.erl
index 9bce1249f8..ba498c651a 100644
--- a/lib/wx/src/gen/wxDC.erl
+++ b/lib/wx/src/gen/wxDC.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -52,14 +52,14 @@
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxDC(), DestPt::{X::integer(),Y::integer()}, Sz::{W::integer(),H::integer()}, Source::wxDC(), SrcPt::{X::integer(),Y::integer()}) -> bool()
+%% @spec (This::wxDC(), DestPt::{X::integer(), Y::integer()}, Sz::{W::integer(), H::integer()}, Source::wxDC(), SrcPt::{X::integer(), Y::integer()}) -> bool()
%% @equiv blit(This,DestPt,Sz,Source,SrcPt, [])
blit(This,DestPt={DestPtX,DestPtY},Sz={SzW,SzH},Source,SrcPt={SrcPtX,SrcPtY})
when is_record(This, wx_ref),is_integer(DestPtX),is_integer(DestPtY),is_integer(SzW),is_integer(SzH),is_record(Source, wx_ref),is_integer(SrcPtX),is_integer(SrcPtY) ->
blit(This,DestPt,Sz,Source,SrcPt, []).
-%% @spec (This::wxDC(), DestPt::{X::integer(),Y::integer()}, Sz::{W::integer(),H::integer()}, Source::wxDC(), SrcPt::{X::integer(),Y::integer()}, [Option]) -> bool()
-%% Option = {rop, integer()} | {useMask, bool()} | {srcPtMask, {X::integer(),Y::integer()}}
+%% @spec (This::wxDC(), DestPt::{X::integer(), Y::integer()}, Sz::{W::integer(), H::integer()}, Source::wxDC(), SrcPt::{X::integer(), Y::integer()}, [Option]) -> bool()
+%% Option = {rop, integer()} | {useMask, bool()} | {srcPtMask, {X::integer(), Y::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcblit">external documentation</a>.
blit(#wx_ref{type=ThisT,ref=ThisRef},{DestPtX,DestPtY},{SzW,SzH},#wx_ref{type=SourceT,ref=SourceRef},{SrcPtX,SrcPtY}, Options)
when is_integer(DestPtX),is_integer(DestPtY),is_integer(SzW),is_integer(SzH),is_integer(SrcPtX),is_integer(SrcPtY),is_list(Options) ->
@@ -95,7 +95,7 @@ computeScaleAndOrigin(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:cast(?wxDC_ComputeScaleAndOrigin,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC(), Pt::{X::integer(),Y::integer()}) -> ok
+%% @spec (This::wxDC(), Pt::{X::integer(), Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdccrosshair">external documentation</a>.
crossHair(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
@@ -142,7 +142,7 @@ deviceToLogicalYRel(#wx_ref{type=ThisT,ref=ThisRef},Y)
wxe_util:call(?wxDC_DeviceToLogicalYRel,
<<ThisRef:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxDC(), Pt1::{X::integer(),Y::integer()}, Pt2::{X::integer(),Y::integer()}, Centre::{X::integer(),Y::integer()}) -> ok
+%% @spec (This::wxDC(), Pt1::{X::integer(), Y::integer()}, Pt2::{X::integer(), Y::integer()}, Centre::{X::integer(), Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawarc">external documentation</a>.
drawArc(#wx_ref{type=ThisT,ref=ThisRef},{Pt1X,Pt1Y},{Pt2X,Pt2Y},{CentreX,CentreY})
when is_integer(Pt1X),is_integer(Pt1Y),is_integer(Pt2X),is_integer(Pt2Y),is_integer(CentreX),is_integer(CentreY) ->
@@ -150,13 +150,13 @@ drawArc(#wx_ref{type=ThisT,ref=ThisRef},{Pt1X,Pt1Y},{Pt2X,Pt2Y},{CentreX,CentreY
wxe_util:cast(?wxDC_DrawArc,
<<ThisRef:32/?UI,Pt1X:32/?UI,Pt1Y:32/?UI,Pt2X:32/?UI,Pt2Y:32/?UI,CentreX:32/?UI,CentreY:32/?UI>>).
-%% @spec (This::wxDC(), Bmp::wxBitmap:wxBitmap(), Pt::{X::integer(),Y::integer()}) -> ok
+%% @spec (This::wxDC(), Bmp::wxBitmap:wxBitmap(), Pt::{X::integer(), Y::integer()}) -> ok
%% @equiv drawBitmap(This,Bmp,Pt, [])
drawBitmap(This,Bmp,Pt={PtX,PtY})
when is_record(This, wx_ref),is_record(Bmp, wx_ref),is_integer(PtX),is_integer(PtY) ->
drawBitmap(This,Bmp,Pt, []).
-%% @spec (This::wxDC(), Bmp::wxBitmap:wxBitmap(), Pt::{X::integer(),Y::integer()}, [Option]) -> ok
+%% @spec (This::wxDC(), Bmp::wxBitmap:wxBitmap(), Pt::{X::integer(), Y::integer()}, [Option]) -> ok
%% Option = {useMask, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawbitmap">external documentation</a>.
drawBitmap(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BmpT,ref=BmpRef},{PtX,PtY}, Options)
@@ -169,7 +169,7 @@ drawBitmap(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BmpT,ref=BmpRef},{PtX,Pt
wxe_util:cast(?wxDC_DrawBitmap,
<<ThisRef:32/?UI,BmpRef:32/?UI,PtX:32/?UI,PtY:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxDC(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> ok
+%% @spec (This::wxDC(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawcheckmark">external documentation</a>.
drawCheckMark(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
@@ -177,7 +177,7 @@ drawCheckMark(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
wxe_util:cast(?wxDC_DrawCheckMark,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI>>).
-%% @spec (This::wxDC(), Pt::{X::integer(),Y::integer()}, Radius::integer()) -> ok
+%% @spec (This::wxDC(), Pt::{X::integer(), Y::integer()}, Radius::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawcircle">external documentation</a>.
drawCircle(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY},Radius)
when is_integer(PtX),is_integer(PtY),is_integer(Radius) ->
@@ -185,7 +185,7 @@ drawCircle(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY},Radius)
wxe_util:cast(?wxDC_DrawCircle,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI,Radius:32/?UI>>).
-%% @spec (This::wxDC(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> ok
+%% @spec (This::wxDC(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawellipse">external documentation</a>.
drawEllipse(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
@@ -193,7 +193,7 @@ drawEllipse(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
wxe_util:cast(?wxDC_DrawEllipse_1,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI>>).
-%% @spec (This::wxDC(), Pt::{X::integer(),Y::integer()}, Sz::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxDC(), Pt::{X::integer(), Y::integer()}, Sz::{W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawellipse">external documentation</a>.
drawEllipse(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY},{SzW,SzH})
when is_integer(PtX),is_integer(PtY),is_integer(SzW),is_integer(SzH) ->
@@ -201,7 +201,7 @@ drawEllipse(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY},{SzW,SzH})
wxe_util:cast(?wxDC_DrawEllipse_2,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI,SzW:32/?UI,SzH:32/?UI>>).
-%% @spec (This::wxDC(), Pt::{X::integer(),Y::integer()}, Sz::{W::integer(),H::integer()}, Sa::float(), Ea::float()) -> ok
+%% @spec (This::wxDC(), Pt::{X::integer(), Y::integer()}, Sz::{W::integer(), H::integer()}, Sa::float(), Ea::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawellipticarc">external documentation</a>.
drawEllipticArc(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY},{SzW,SzH},Sa,Ea)
when is_integer(PtX),is_integer(PtY),is_integer(SzW),is_integer(SzH),is_float(Sa),is_float(Ea) ->
@@ -209,7 +209,7 @@ drawEllipticArc(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY},{SzW,SzH},Sa,Ea)
wxe_util:cast(?wxDC_DrawEllipticArc,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI,SzW:32/?UI,SzH:32/?UI,0:32,Sa:64/?F,Ea:64/?F>>).
-%% @spec (This::wxDC(), Icon::wxIcon:wxIcon(), Pt::{X::integer(),Y::integer()}) -> ok
+%% @spec (This::wxDC(), Icon::wxIcon:wxIcon(), Pt::{X::integer(), Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawicon">external documentation</a>.
drawIcon(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=IconT,ref=IconRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
@@ -218,13 +218,13 @@ drawIcon(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=IconT,ref=IconRef},{PtX,Pt
wxe_util:cast(?wxDC_DrawIcon,
<<ThisRef:32/?UI,IconRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxDC(), Text::string(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> ok
+%% @spec (This::wxDC(), Text::string(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> ok
%% @equiv drawLabel(This,Text,Rect, [])
drawLabel(This,Text,Rect={RectX,RectY,RectW,RectH})
when is_record(This, wx_ref),is_list(Text),is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
drawLabel(This,Text,Rect, []).
-%% @spec (This::wxDC(), Text::string(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}, [Option]) -> ok
+%% @spec (This::wxDC(), Text::string(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}, [Option]) -> ok
%% Option = {alignment, integer()} | {indexAccel, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawlabel">external documentation</a>.
drawLabel(#wx_ref{type=ThisT,ref=ThisRef},Text,{RectX,RectY,RectW,RectH}, Options)
@@ -238,7 +238,7 @@ drawLabel(#wx_ref{type=ThisT,ref=ThisRef},Text,{RectX,RectY,RectW,RectH}, Option
wxe_util:cast(?wxDC_DrawLabel,
<<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxDC(), Pt1::{X::integer(),Y::integer()}, Pt2::{X::integer(),Y::integer()}) -> ok
+%% @spec (This::wxDC(), Pt1::{X::integer(), Y::integer()}, Pt2::{X::integer(), Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawline">external documentation</a>.
drawLine(#wx_ref{type=ThisT,ref=ThisRef},{Pt1X,Pt1Y},{Pt2X,Pt2Y})
when is_integer(Pt1X),is_integer(Pt1Y),is_integer(Pt2X),is_integer(Pt2Y) ->
@@ -246,13 +246,13 @@ drawLine(#wx_ref{type=ThisT,ref=ThisRef},{Pt1X,Pt1Y},{Pt2X,Pt2Y})
wxe_util:cast(?wxDC_DrawLine,
<<ThisRef:32/?UI,Pt1X:32/?UI,Pt1Y:32/?UI,Pt2X:32/?UI,Pt2Y:32/?UI>>).
-%% @spec (This::wxDC(), Points::[{X::integer(),Y::integer()}]) -> ok
+%% @spec (This::wxDC(), Points::[{X::integer(), Y::integer()}]) -> ok
%% @equiv drawLines(This,Points, [])
drawLines(This,Points)
when is_record(This, wx_ref),is_list(Points) ->
drawLines(This,Points, []).
-%% @spec (This::wxDC(), Points::[{X::integer(),Y::integer()}], [Option]) -> ok
+%% @spec (This::wxDC(), Points::[{X::integer(), Y::integer()}], [Option]) -> ok
%% Option = {xoffset, integer()} | {yoffset, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawlines">external documentation</a>.
drawLines(#wx_ref{type=ThisT,ref=ThisRef},Points, Options)
@@ -266,13 +266,13 @@ drawLines(#wx_ref{type=ThisT,ref=ThisRef},Points, Options)
<<ThisRef:32/?UI,(length(Points)):32/?UI,
(<< <<X:32/?I,Y:32/?I>> || {X,Y} <- Points>>)/binary, BinOpt/binary>>).
-%% @spec (This::wxDC(), Points::[{X::integer(),Y::integer()}]) -> ok
+%% @spec (This::wxDC(), Points::[{X::integer(), Y::integer()}]) -> ok
%% @equiv drawPolygon(This,Points, [])
drawPolygon(This,Points)
when is_record(This, wx_ref),is_list(Points) ->
drawPolygon(This,Points, []).
-%% @spec (This::wxDC(), Points::[{X::integer(),Y::integer()}], [Option]) -> ok
+%% @spec (This::wxDC(), Points::[{X::integer(), Y::integer()}], [Option]) -> ok
%% Option = {xoffset, integer()} | {yoffset, integer()} | {fillStyle, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawpolygon">external documentation</a>.
drawPolygon(#wx_ref{type=ThisT,ref=ThisRef},Points, Options)
@@ -287,7 +287,7 @@ drawPolygon(#wx_ref{type=ThisT,ref=ThisRef},Points, Options)
<<ThisRef:32/?UI,(length(Points)):32/?UI,
(<< <<X:32/?I,Y:32/?I>> || {X,Y} <- Points>>)/binary, BinOpt/binary>>).
-%% @spec (This::wxDC(), Pt::{X::integer(),Y::integer()}) -> ok
+%% @spec (This::wxDC(), Pt::{X::integer(), Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawpoint">external documentation</a>.
drawPoint(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
@@ -295,7 +295,7 @@ drawPoint(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
wxe_util:cast(?wxDC_DrawPoint,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxDC(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> ok
+%% @spec (This::wxDC(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawrectangle">external documentation</a>.
drawRectangle(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
@@ -303,7 +303,7 @@ drawRectangle(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
wxe_util:cast(?wxDC_DrawRectangle_1,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI>>).
-%% @spec (This::wxDC(), Pt::{X::integer(),Y::integer()}, Sz::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxDC(), Pt::{X::integer(), Y::integer()}, Sz::{W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawrectangle">external documentation</a>.
drawRectangle(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY},{SzW,SzH})
when is_integer(PtX),is_integer(PtY),is_integer(SzW),is_integer(SzH) ->
@@ -311,7 +311,7 @@ drawRectangle(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY},{SzW,SzH})
wxe_util:cast(?wxDC_DrawRectangle_2,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI,SzW:32/?UI,SzH:32/?UI>>).
-%% @spec (This::wxDC(), Text::string(), Pt::{X::integer(),Y::integer()}, Angle::float()) -> ok
+%% @spec (This::wxDC(), Text::string(), Pt::{X::integer(), Y::integer()}, Angle::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawrotatedtext">external documentation</a>.
drawRotatedText(#wx_ref{type=ThisT,ref=ThisRef},Text,{PtX,PtY},Angle)
when is_list(Text),is_integer(PtX),is_integer(PtY),is_float(Angle) ->
@@ -320,7 +320,7 @@ drawRotatedText(#wx_ref{type=ThisT,ref=ThisRef},Text,{PtX,PtY},Angle)
wxe_util:cast(?wxDC_DrawRotatedText,
<<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8,PtX:32/?UI,PtY:32/?UI,Angle:64/?F>>).
-%% @spec (This::wxDC(), R::{X::integer(),Y::integer(),W::integer(),H::integer()}, Radius::float()) -> ok
+%% @spec (This::wxDC(), R::{X::integer(), Y::integer(), W::integer(), H::integer()}, Radius::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawroundedrectangle">external documentation</a>.
drawRoundedRectangle(#wx_ref{type=ThisT,ref=ThisRef},{RX,RY,RW,RH},Radius)
when is_integer(RX),is_integer(RY),is_integer(RW),is_integer(RH),is_float(Radius) ->
@@ -328,7 +328,7 @@ drawRoundedRectangle(#wx_ref{type=ThisT,ref=ThisRef},{RX,RY,RW,RH},Radius)
wxe_util:cast(?wxDC_DrawRoundedRectangle_2,
<<ThisRef:32/?UI,RX:32/?UI,RY:32/?UI,RW:32/?UI,RH:32/?UI,0:32,Radius:64/?F>>).
-%% @spec (This::wxDC(), Pt::{X::integer(),Y::integer()}, Sz::{W::integer(),H::integer()}, Radius::float()) -> ok
+%% @spec (This::wxDC(), Pt::{X::integer(), Y::integer()}, Sz::{W::integer(), H::integer()}, Radius::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawroundedrectangle">external documentation</a>.
drawRoundedRectangle(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY},{SzW,SzH},Radius)
when is_integer(PtX),is_integer(PtY),is_integer(SzW),is_integer(SzH),is_float(Radius) ->
@@ -336,7 +336,7 @@ drawRoundedRectangle(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY},{SzW,SzH},Radius)
wxe_util:cast(?wxDC_DrawRoundedRectangle_3,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI,SzW:32/?UI,SzH:32/?UI,0:32,Radius:64/?F>>).
-%% @spec (This::wxDC(), Text::string(), Pt::{X::integer(),Y::integer()}) -> ok
+%% @spec (This::wxDC(), Text::string(), Pt::{X::integer(), Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawtext">external documentation</a>.
drawText(#wx_ref{type=ThisT,ref=ThisRef},Text,{PtX,PtY})
when is_list(Text),is_integer(PtX),is_integer(PtY) ->
@@ -359,13 +359,13 @@ endPage(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:cast(?wxDC_EndPage,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC(), Pt::{X::integer(),Y::integer()}, Col::wx:colour()) -> bool()
+%% @spec (This::wxDC(), Pt::{X::integer(), Y::integer()}, Col::wx:colour()) -> bool()
%% @equiv floodFill(This,Pt,Col, [])
floodFill(This,Pt={PtX,PtY},Col)
when is_record(This, wx_ref),is_integer(PtX),is_integer(PtY),tuple_size(Col) =:= 3; tuple_size(Col) =:= 4 ->
floodFill(This,Pt,Col, []).
-%% @spec (This::wxDC(), Pt::{X::integer(),Y::integer()}, Col::wx:colour(), [Option]) -> bool()
+%% @spec (This::wxDC(), Pt::{X::integer(), Y::integer()}, Col::wx:colour(), [Option]) -> bool()
%% Option = {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcfloodfill">external documentation</a>.
floodFill(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY},Col, Options)
@@ -412,7 +412,7 @@ getCharWidth(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxDC_GetCharWidth,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> ok
+%% @spec (This::wxDC(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetclippingbox">external documentation</a>.
getClippingBox(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
@@ -450,7 +450,7 @@ getMapMode(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxDC_GetMapMode,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC(), String::string()) -> {W::integer(),H::integer()}
+%% @spec (This::wxDC(), String::string()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetmultilinetextextent">external documentation</a>.
getMultiLineTextExtent(#wx_ref{type=ThisT,ref=ThisRef},String)
when is_list(String) ->
@@ -459,7 +459,7 @@ getMultiLineTextExtent(#wx_ref{type=ThisT,ref=ThisRef},String)
wxe_util:call(?wxDC_GetMultiLineTextExtent_1,
<<ThisRef:32/?UI,(byte_size(String_UC)):32/?UI,(String_UC)/binary, 0:(((8- ((0+byte_size(String_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxDC(), String::string(), [Option]) -> {Width::integer(),Height::integer(),HeightLine::integer()}
+%% @spec (This::wxDC(), String::string(), [Option]) -> {Width::integer(), Height::integer(), HeightLine::integer()}
%% Option = {font, wxFont:wxFont()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetmultilinetextextent">external documentation</a>.
getMultiLineTextExtent(#wx_ref{type=ThisT,ref=ThisRef},String, Options)
@@ -489,7 +489,7 @@ getPen(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxDC_GetPen,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC(), Pt::{X::integer(),Y::integer()}, Col::wx:colour()) -> bool()
+%% @spec (This::wxDC(), Pt::{X::integer(), Y::integer()}, Col::wx:colour()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetpixel">external documentation</a>.
getPixel(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY},Col)
when is_integer(PtX),is_integer(PtY),tuple_size(Col) =:= 3; tuple_size(Col) =:= 4 ->
@@ -497,21 +497,21 @@ getPixel(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY},Col)
wxe_util:call(?wxDC_GetPixel,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI,(wxe_util:colour_bin(Col)):16/binary>>).
-%% @spec (This::wxDC()) -> {W::integer(),H::integer()}
+%% @spec (This::wxDC()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetppi">external documentation</a>.
getPPI(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_GetPPI,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC()) -> {W::integer(),H::integer()}
+%% @spec (This::wxDC()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetsize">external documentation</a>.
getSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_GetSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC()) -> {W::integer(),H::integer()}
+%% @spec (This::wxDC()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetsizemm">external documentation</a>.
getSizeMM(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
@@ -525,7 +525,7 @@ getTextBackground(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxDC_GetTextBackground,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC(), String::string()) -> {W::integer(),H::integer()}
+%% @spec (This::wxDC(), String::string()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgettextextent">external documentation</a>.
getTextExtent(#wx_ref{type=ThisT,ref=ThisRef},String)
when is_list(String) ->
@@ -534,7 +534,7 @@ getTextExtent(#wx_ref{type=ThisT,ref=ThisRef},String)
wxe_util:call(?wxDC_GetTextExtent_1,
<<ThisRef:32/?UI,(byte_size(String_UC)):32/?UI,(String_UC)/binary, 0:(((8- ((0+byte_size(String_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxDC(), String::string(), [Option]) -> {X::integer(),Y::integer(),Descent::integer(),ExternalLeading::integer()}
+%% @spec (This::wxDC(), String::string(), [Option]) -> {X::integer(), Y::integer(), Descent::integer(), ExternalLeading::integer()}
%% Option = {theFont, wxFont:wxFont()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgettextextent">external documentation</a>.
getTextExtent(#wx_ref{type=ThisT,ref=ThisRef},String, Options)
@@ -554,14 +554,14 @@ getTextForeground(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxDC_GetTextForeground,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC()) -> {X::float(),Y::float()}
+%% @spec (This::wxDC()) -> {X::float(), Y::float()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetuserscale">external documentation</a>.
getUserScale(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_GetUserScale,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}, InitialColour::wx:colour(), DestColour::wx:colour()) -> ok
+%% @spec (This::wxDC(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}, InitialColour::wx:colour(), DestColour::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgradientfillconcentric">external documentation</a>.
gradientFillConcentric(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH},InitialColour,DestColour)
when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH),tuple_size(InitialColour) =:= 3; tuple_size(InitialColour) =:= 4,tuple_size(DestColour) =:= 3; tuple_size(DestColour) =:= 4 ->
@@ -569,7 +569,7 @@ gradientFillConcentric(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH}
wxe_util:cast(?wxDC_GradientFillConcentric_3,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI,(wxe_util:colour_bin(InitialColour)):16/binary,(wxe_util:colour_bin(DestColour)):16/binary>>).
-%% @spec (This::wxDC(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}, InitialColour::wx:colour(), DestColour::wx:colour(), CircleCenter::{X::integer(),Y::integer()}) -> ok
+%% @spec (This::wxDC(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}, InitialColour::wx:colour(), DestColour::wx:colour(), CircleCenter::{X::integer(), Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgradientfillconcentric">external documentation</a>.
gradientFillConcentric(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH},InitialColour,DestColour,{CircleCenterX,CircleCenterY})
when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH),tuple_size(InitialColour) =:= 3; tuple_size(InitialColour) =:= 4,tuple_size(DestColour) =:= 3; tuple_size(DestColour) =:= 4,is_integer(CircleCenterX),is_integer(CircleCenterY) ->
@@ -577,13 +577,13 @@ gradientFillConcentric(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH}
wxe_util:cast(?wxDC_GradientFillConcentric_4,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI,(wxe_util:colour_bin(InitialColour)):16/binary,(wxe_util:colour_bin(DestColour)):16/binary,CircleCenterX:32/?UI,CircleCenterY:32/?UI>>).
-%% @spec (This::wxDC(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}, InitialColour::wx:colour(), DestColour::wx:colour()) -> ok
+%% @spec (This::wxDC(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}, InitialColour::wx:colour(), DestColour::wx:colour()) -> ok
%% @equiv gradientFillLinear(This,Rect,InitialColour,DestColour, [])
gradientFillLinear(This,Rect={RectX,RectY,RectW,RectH},InitialColour,DestColour)
when is_record(This, wx_ref),is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH),tuple_size(InitialColour) =:= 3; tuple_size(InitialColour) =:= 4,tuple_size(DestColour) =:= 3; tuple_size(DestColour) =:= 4 ->
gradientFillLinear(This,Rect,InitialColour,DestColour, []).
-%% @spec (This::wxDC(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}, InitialColour::wx:colour(), DestColour::wx:colour(), [Option]) -> ok
+%% @spec (This::wxDC(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}, InitialColour::wx:colour(), DestColour::wx:colour(), [Option]) -> ok
%% Option = {nDirection, WxDirection}
%% WxDirection = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgradientfilllinear">external documentation</a>.
@@ -710,7 +710,7 @@ setBrush(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BrushT,ref=BrushRef}) ->
%% setClippingRegion(This::wxDC(), Region::wxRegion:wxRegion()) -> ok </c>
%% </p>
%% <p><c>
-%% setClippingRegion(This::wxDC(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> ok </c>
+%% setClippingRegion(This::wxDC(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> ok </c>
%% </p>
setClippingRegion(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=RegionT,ref=RegionRef}) ->
?CLASS(ThisT,wxDC),
@@ -723,7 +723,7 @@ setClippingRegion(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
wxe_util:cast(?wxDC_SetClippingRegion_1_1,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI>>).
-%% @spec (This::wxDC(), Pt::{X::integer(),Y::integer()}, Sz::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxDC(), Pt::{X::integer(), Y::integer()}, Sz::{W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcsetclippingregion">external documentation</a>.
setClippingRegion(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY},{SzW,SzH})
when is_integer(PtX),is_integer(PtY),is_integer(SzW),is_integer(SzH) ->
diff --git a/lib/wx/src/gen/wxDatePickerCtrl.erl b/lib/wx/src/gen/wxDatePickerCtrl.erl
index 2de51ce71d..8a1700e9cd 100644
--- a/lib/wx/src/gen/wxDatePickerCtrl.erl
+++ b/lib/wx/src/gen/wxDatePickerCtrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -94,7 +94,7 @@ new(Parent,Id)
new(Parent,Id, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxDatePickerCtrl()
-%% Option = {date, wx:datetime()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {date, wx:datetime()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdatepickerctrl.html#wxdatepickerctrlwxdatepickerctrl">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxDialog.erl b/lib/wx/src/gen/wxDialog.erl
index 8c0bd2cd76..514a62813e 100644
--- a/lib/wx/src/gen/wxDialog.erl
+++ b/lib/wx/src/gen/wxDialog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -95,7 +95,7 @@ new(Parent,Id,Title)
new(Parent,Id,Title, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), [Option]) -> wxDialog()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdialog.html#wxdialogwxdialog">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Title, Options)
when is_integer(Id),is_list(Title),is_list(Options) ->
@@ -116,7 +116,7 @@ create(This,Parent,Id,Title)
create(This,Parent,Id,Title, []).
%% @spec (This::wxDialog(), Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdialog.html#wxdialogcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Title, Options)
when is_integer(Id),is_list(Title),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxDirDialog.erl b/lib/wx/src/gen/wxDirDialog.erl
index 7849dce0a7..28db3daf1d 100644
--- a/lib/wx/src/gen/wxDirDialog.erl
+++ b/lib/wx/src/gen/wxDirDialog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -91,7 +91,7 @@ new(Parent)
new(Parent, []).
%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxDirDialog()
-%% Option = {title, string()} | {defaultPath, string()} | {style, integer()} | {pos, {X::integer(),Y::integer()}} | {sz, {W::integer(),H::integer()}}
+%% Option = {title, string()} | {defaultPath, string()} | {style, integer()} | {pos, {X::integer(), Y::integer()}} | {sz, {W::integer(), H::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdirdialog.html#wxdirdialogwxdirdialog">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
diff --git a/lib/wx/src/gen/wxDirPickerCtrl.erl b/lib/wx/src/gen/wxDirPickerCtrl.erl
index 7fb70b71e3..2b24bc4bb0 100644
--- a/lib/wx/src/gen/wxDirPickerCtrl.erl
+++ b/lib/wx/src/gen/wxDirPickerCtrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -94,7 +94,7 @@ new(Parent,Id)
new(Parent,Id, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxDirPickerCtrl()
-%% Option = {path, string()} | {message, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {path, string()} | {message, string()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdirpickerctrl.html#wxdirpickerctrlwxdirpickerctrl">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
@@ -117,7 +117,7 @@ create(This,Parent,Id)
create(This,Parent,Id, []).
%% @spec (This::wxDirPickerCtrl(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {path, string()} | {message, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {path, string()} | {message, string()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdirpickerctrl.html#wxdirpickerctrlcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxFileDialog.erl b/lib/wx/src/gen/wxFileDialog.erl
index cba9705335..c6779927e9 100644
--- a/lib/wx/src/gen/wxFileDialog.erl
+++ b/lib/wx/src/gen/wxFileDialog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -93,7 +93,7 @@ new(Parent)
new(Parent, []).
%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxFileDialog()
-%% Option = {message, string()} | {defaultDir, string()} | {defaultFile, string()} | {wildCard, string()} | {style, integer()} | {pos, {X::integer(),Y::integer()}} | {sz, {W::integer(),H::integer()}}
+%% Option = {message, string()} | {defaultDir, string()} | {defaultFile, string()} | {wildCard, string()} | {style, integer()} | {pos, {X::integer(), Y::integer()}} | {sz, {W::integer(), H::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfiledialog.html#wxfiledialogwxfiledialog">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
diff --git a/lib/wx/src/gen/wxFilePickerCtrl.erl b/lib/wx/src/gen/wxFilePickerCtrl.erl
index a3034aaa86..93bfa72380 100644
--- a/lib/wx/src/gen/wxFilePickerCtrl.erl
+++ b/lib/wx/src/gen/wxFilePickerCtrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -94,7 +94,7 @@ new(Parent,Id)
new(Parent,Id, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxFilePickerCtrl()
-%% Option = {path, string()} | {message, string()} | {wildcard, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {path, string()} | {message, string()} | {wildcard, string()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfilepickerctrl.html#wxfilepickerctrlwxfilepickerctrl">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
@@ -118,7 +118,7 @@ create(This,Parent,Id)
create(This,Parent,Id, []).
%% @spec (This::wxFilePickerCtrl(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {path, string()} | {message, string()} | {wildcard, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {path, string()} | {message, string()} | {wildcard, string()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfilepickerctrl.html#wxfilepickerctrlcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxFlexGridSizer.erl b/lib/wx/src/gen/wxFlexGridSizer.erl
index 9471cc8a01..910cc78894 100644
--- a/lib/wx/src/gen/wxFlexGridSizer.erl
+++ b/lib/wx/src/gen/wxFlexGridSizer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -222,7 +222,7 @@ prepend(This,Width,Height, Options) -> wxSizer:prepend(This,Width,Height, Option
%% @hidden
prepend(This,Width,Height) -> wxSizer:prepend(This,Width,Height).
%% @hidden
-prepend(This,Window) -> wxSizer:prepend(This,Window).
+prepend(This,Item) -> wxSizer:prepend(This,Item).
%% @hidden
layout(This) -> wxSizer:layout(This).
%% @hidden
@@ -238,7 +238,7 @@ insert(This,Index,Width,Height, Options) -> wxSizer:insert(This,Index,Width,Heig
%% @hidden
insert(This,Index,Width,Height) -> wxSizer:insert(This,Index,Width,Height).
%% @hidden
-insert(This,Index,Window) -> wxSizer:insert(This,Index,Window).
+insert(This,Index,Item) -> wxSizer:insert(This,Index,Item).
%% @hidden
hide(This,Window, Options) -> wxSizer:hide(This,Window, Options).
%% @hidden
diff --git a/lib/wx/src/gen/wxFontPickerCtrl.erl b/lib/wx/src/gen/wxFontPickerCtrl.erl
index 93d63cc930..3050011b60 100644
--- a/lib/wx/src/gen/wxFontPickerCtrl.erl
+++ b/lib/wx/src/gen/wxFontPickerCtrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -95,7 +95,7 @@ new(Parent,Id)
new(Parent,Id, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxFontPickerCtrl()
-%% Option = {initial, wxFont:wxFont()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {initial, wxFont:wxFont()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontpickerctrl.html#wxfontpickerctrlwxfontpickerctrl">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
@@ -117,7 +117,7 @@ create(This,Parent,Id)
create(This,Parent,Id, []).
%% @spec (This::wxFontPickerCtrl(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {initial, wxFont:wxFont()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {initial, wxFont:wxFont()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontpickerctrl.html#wxfontpickerctrlcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxFrame.erl b/lib/wx/src/gen/wxFrame.erl
index 5cd1e3dfd3..7e25bc8762 100644
--- a/lib/wx/src/gen/wxFrame.erl
+++ b/lib/wx/src/gen/wxFrame.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -97,7 +97,7 @@ new(Parent,Id,Title)
new(Parent,Id,Title, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), [Option]) -> wxFrame()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxframe.html#wxframewxframe">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Title, Options)
when is_integer(Id),is_list(Title),is_list(Options) ->
@@ -118,7 +118,7 @@ create(This,Parent,Id,Title)
create(This,Parent,Id,Title, []).
%% @spec (This::wxFrame(), Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxframe.html#wxframecreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Title, Options)
when is_integer(Id),is_list(Title),is_list(Options) ->
@@ -172,7 +172,7 @@ createToolBar(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxFrame_CreateToolBar,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxFrame()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxFrame()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxframe.html#wxframegetclientareaorigin">external documentation</a>.
getClientAreaOrigin(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFrame),
diff --git a/lib/wx/src/gen/wxGLCanvas.erl b/lib/wx/src/gen/wxGLCanvas.erl
index 032d42535d..a30d8cefd9 100644
--- a/lib/wx/src/gen/wxGLCanvas.erl
+++ b/lib/wx/src/gen/wxGLCanvas.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -86,7 +86,7 @@ new(Parent)
%% new(Parent::wxWindow:wxWindow(), Shared::wxGLContext:wxGLContext() | wxGLCanvas()) -> new(Parent,Shared, []) </c></p>
%% <p><c>
%% new(Parent::wxWindow:wxWindow(), [Option]) -> wxGLCanvas() </c>
-%%<br /> Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {name, string()} | {attribList, [integer()]} | {palette, wxPalette:wxPalette()}
+%%<br /> Option = {id, integer()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {name, string()} | {attribList, [integer()]} | {palette, wxPalette:wxPalette()}
%% </p>
new(Parent,Shared)
@@ -109,7 +109,7 @@ new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
<<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
%% @spec (Parent::wxWindow:wxWindow(), Shared::wxGLContext:wxGLContext() | wxGLCanvas(), [Option]) -> wxGLCanvas()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {name, string()} | {attribList, [integer()]} | {palette, wxPalette:wxPalette()}
+%% Option = {id, integer()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {name, string()} | {attribList, [integer()]} | {palette, wxPalette:wxPalette()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxglcanvas.html#wxglcanvaswxglcanvas">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},#wx_ref{type=SharedT,ref=SharedRef}, Options)
when is_list(Options) ->
diff --git a/lib/wx/src/gen/wxGauge.erl b/lib/wx/src/gen/wxGauge.erl
index 5028b29bba..484fd36936 100644
--- a/lib/wx/src/gen/wxGauge.erl
+++ b/lib/wx/src/gen/wxGauge.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -90,7 +90,7 @@ new(Parent,Id,Range)
new(Parent,Id,Range, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Range::integer(), [Option]) -> wxGauge()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgauge.html#wxgaugewxgauge">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Range, Options)
when is_integer(Id),is_integer(Range),is_list(Options) ->
@@ -111,7 +111,7 @@ create(This,Parent,Id,Range)
create(This,Parent,Id,Range, []).
%% @spec (This::wxGauge(), Parent::wxWindow:wxWindow(), Id::integer(), Range::integer(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgauge.html#wxgaugecreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Range, Options)
when is_integer(Id),is_integer(Range),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxGenericDirCtrl.erl b/lib/wx/src/gen/wxGenericDirCtrl.erl
index 97944710f0..626a454d2a 100644
--- a/lib/wx/src/gen/wxGenericDirCtrl.erl
+++ b/lib/wx/src/gen/wxGenericDirCtrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -91,7 +91,7 @@ new(Parent)
new(Parent, []).
%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxGenericDirCtrl()
-%% Option = {id, integer()} | {dir, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {filter, string()} | {defaultFilter, integer()}
+%% Option = {id, integer()} | {dir, string()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {filter, string()} | {defaultFilter, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgenericdirctrl.html#wxgenericdirctrlwxgenericdirctrl">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
@@ -115,7 +115,7 @@ create(This,Parent)
create(This,Parent, []).
%% @spec (This::wxGenericDirCtrl(), Parent::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {id, integer()} | {dir, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {filter, string()} | {defaultFilter, integer()}
+%% Option = {id, integer()} | {dir, string()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {filter, string()} | {defaultFilter, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgenericdirctrl.html#wxgenericdirctrlcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
diff --git a/lib/wx/src/gen/wxGraphicsContext.erl b/lib/wx/src/gen/wxGraphicsContext.erl
index 040867cb11..05c56dd4b2 100644
--- a/lib/wx/src/gen/wxGraphicsContext.erl
+++ b/lib/wx/src/gen/wxGraphicsContext.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -192,13 +192,13 @@ drawIcon(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=IconT,ref=IconRef},X,Y,W,H
wxe_util:cast(?wxGraphicsContext_DrawIcon,
<<ThisRef:32/?UI,IconRef:32/?UI,X:64/?F,Y:64/?F,W:64/?F,H:64/?F>>).
-%% @spec (This::wxGraphicsContext(), N::integer(), Points::{X::float(),Y::float()}) -> ok
+%% @spec (This::wxGraphicsContext(), N::integer(), Points::{X::float(), Y::float()}) -> ok
%% @equiv drawLines(This,N,Points, [])
drawLines(This,N,Points={PointsX,PointsY})
when is_record(This, wx_ref),is_integer(N),is_number(PointsX),is_number(PointsY) ->
drawLines(This,N,Points, []).
-%% @spec (This::wxGraphicsContext(), N::integer(), Points::{X::float(),Y::float()}, [Option]) -> ok
+%% @spec (This::wxGraphicsContext(), N::integer(), Points::{X::float(), Y::float()}, [Option]) -> ok
%% Option = {fillStyle, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextdrawlines">external documentation</a>.
drawLines(#wx_ref{type=ThisT,ref=ThisRef},N,{PointsX,PointsY}, Options)
@@ -331,7 +331,7 @@ getPartialTextExtents(#wx_ref{type=ThisT,ref=ThisRef},Text,Widths)
<<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8,(length(Widths)):32/?UI,
0:32, (<< <<C:64/float>> || C <- Widths>>)/binary>>).
-%% @spec (This::wxGraphicsContext(), Text::string()) -> {Width::float(),Height::float(),Descent::float(),ExternalLeading::float()}
+%% @spec (This::wxGraphicsContext(), Text::string()) -> {Width::float(), Height::float(), Descent::float(), ExternalLeading::float()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextgettextextent">external documentation</a>.
getTextExtent(#wx_ref{type=ThisT,ref=ThisRef},Text)
when is_list(Text) ->
@@ -438,7 +438,7 @@ strokeLine(#wx_ref{type=ThisT,ref=ThisRef},X1,Y1,X2,Y2)
wxe_util:cast(?wxGraphicsContext_StrokeLine,
<<ThisRef:32/?UI,0:32,X1:64/?F,Y1:64/?F,X2:64/?F,Y2:64/?F>>).
-%% @spec (This::wxGraphicsContext(), N::integer(), Points::{X::float(),Y::float()}) -> ok
+%% @spec (This::wxGraphicsContext(), N::integer(), Points::{X::float(), Y::float()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextstrokelines">external documentation</a>.
strokeLines(#wx_ref{type=ThisT,ref=ThisRef},N,{PointsX,PointsY})
when is_integer(N),is_number(PointsX),is_number(PointsY) ->
@@ -446,7 +446,7 @@ strokeLines(#wx_ref{type=ThisT,ref=ThisRef},N,{PointsX,PointsY})
wxe_util:cast(?wxGraphicsContext_StrokeLines_2,
<<ThisRef:32/?UI,N:32/?UI,PointsX:64/float,PointsY:64/float>>).
-%% @spec (This::wxGraphicsContext(), N::integer(), BeginPoints::{X::float(),Y::float()}, EndPoints::{X::float(),Y::float()}) -> ok
+%% @spec (This::wxGraphicsContext(), N::integer(), BeginPoints::{X::float(), Y::float()}, EndPoints::{X::float(), Y::float()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextstrokelines">external documentation</a>.
strokeLines(#wx_ref{type=ThisT,ref=ThisRef},N,{BeginPointsX,BeginPointsY},{EndPointsX,EndPointsY})
when is_integer(N),is_number(BeginPointsX),is_number(BeginPointsY),is_number(EndPointsX),is_number(EndPointsY) ->
diff --git a/lib/wx/src/gen/wxGraphicsMatrix.erl b/lib/wx/src/gen/wxGraphicsMatrix.erl
index 38ea007c58..635a2027b3 100644
--- a/lib/wx/src/gen/wxGraphicsMatrix.erl
+++ b/lib/wx/src/gen/wxGraphicsMatrix.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -45,7 +45,7 @@ concat(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=TT,ref=TRef}) ->
wxe_util:cast(?wxGraphicsMatrix_Concat,
<<ThisRef:32/?UI,TRef:32/?UI>>).
-%% @spec (This::wxGraphicsMatrix()) -> {A::float(),B::float(),C::float(),D::float(),Tx::float(),Ty::float()}
+%% @spec (This::wxGraphicsMatrix()) -> {A::float(), B::float(), C::float(), D::float(), Tx::float(), Ty::float()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsmatrix.html#wxgraphicsmatrixget">external documentation</a>.
get(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGraphicsMatrix),
@@ -128,14 +128,14 @@ set(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxGraphicsMatrix_Set,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGraphicsMatrix()) -> {X::float(),Y::float()}
+%% @spec (This::wxGraphicsMatrix()) -> {X::float(), Y::float()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsmatrix.html#wxgraphicsmatrixtransformpoint">external documentation</a>.
transformPoint(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGraphicsMatrix),
wxe_util:call(?wxGraphicsMatrix_TransformPoint,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGraphicsMatrix()) -> {Dx::float(),Dy::float()}
+%% @spec (This::wxGraphicsMatrix()) -> {Dx::float(), Dy::float()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsmatrix.html#wxgraphicsmatrixtransformdistance">external documentation</a>.
transformDistance(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGraphicsMatrix),
diff --git a/lib/wx/src/gen/wxGraphicsPath.erl b/lib/wx/src/gen/wxGraphicsPath.erl
index ff2dfb07a4..e41496c641 100644
--- a/lib/wx/src/gen/wxGraphicsPath.erl
+++ b/lib/wx/src/gen/wxGraphicsPath.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -40,7 +40,7 @@
parent_class(wxGraphicsObject) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxGraphicsPath(), P::{X::float(),Y::float()}) -> ok
+%% @spec (This::wxGraphicsPath(), P::{X::float(), Y::float()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathmovetopoint">external documentation</a>.
moveToPoint(#wx_ref{type=ThisT,ref=ThisRef},{PX,PY})
when is_number(PX),is_number(PY) ->
@@ -56,7 +56,7 @@ moveToPoint(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
wxe_util:cast(?wxGraphicsPath_MoveToPoint_2,
<<ThisRef:32/?UI,0:32,X:64/?F,Y:64/?F>>).
-%% @spec (This::wxGraphicsPath(), C::{X::float(),Y::float()}, R::float(), StartAngle::float(), EndAngle::float(), Clockwise::bool()) -> ok
+%% @spec (This::wxGraphicsPath(), C::{X::float(), Y::float()}, R::float(), StartAngle::float(), EndAngle::float(), Clockwise::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathaddarc">external documentation</a>.
addArc(#wx_ref{type=ThisT,ref=ThisRef},{CX,CY},R,StartAngle,EndAngle,Clockwise)
when is_number(CX),is_number(CY),is_float(R),is_float(StartAngle),is_float(EndAngle),is_boolean(Clockwise) ->
@@ -88,7 +88,7 @@ addCircle(#wx_ref{type=ThisT,ref=ThisRef},X,Y,R)
wxe_util:cast(?wxGraphicsPath_AddCircle,
<<ThisRef:32/?UI,0:32,X:64/?F,Y:64/?F,R:64/?F>>).
-%% @spec (This::wxGraphicsPath(), C1::{X::float(),Y::float()}, C2::{X::float(),Y::float()}, E::{X::float(),Y::float()}) -> ok
+%% @spec (This::wxGraphicsPath(), C1::{X::float(), Y::float()}, C2::{X::float(), Y::float()}, E::{X::float(), Y::float()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathaddcurvetopoint">external documentation</a>.
addCurveToPoint(#wx_ref{type=ThisT,ref=ThisRef},{C1X,C1Y},{C2X,C2Y},{EX,EY})
when is_number(C1X),is_number(C1Y),is_number(C2X),is_number(C2Y),is_number(EX),is_number(EY) ->
@@ -112,7 +112,7 @@ addEllipse(#wx_ref{type=ThisT,ref=ThisRef},X,Y,W,H)
wxe_util:cast(?wxGraphicsPath_AddEllipse,
<<ThisRef:32/?UI,0:32,X:64/?F,Y:64/?F,W:64/?F,H:64/?F>>).
-%% @spec (This::wxGraphicsPath(), P::{X::float(),Y::float()}) -> ok
+%% @spec (This::wxGraphicsPath(), P::{X::float(), Y::float()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathaddlinetopoint">external documentation</a>.
addLineToPoint(#wx_ref{type=ThisT,ref=ThisRef},{PX,PY})
when is_number(PX),is_number(PY) ->
@@ -167,7 +167,7 @@ closeSubpath(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:cast(?wxGraphicsPath_CloseSubpath,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGraphicsPath(), C::{X::float(),Y::float()}) -> bool()
+%% @spec (This::wxGraphicsPath(), C::{X::float(), Y::float()}) -> bool()
%% @equiv contains(This,C, [])
contains(This,C={CX,CY})
when is_record(This, wx_ref),is_number(CX),is_number(CY) ->
@@ -179,7 +179,7 @@ contains(This,C={CX,CY})
%% <p><c>
%% contains(This::wxGraphicsPath(), X::float(), Y::float()) -> contains(This,X,Y, []) </c></p>
%% <p><c>
-%% contains(This::wxGraphicsPath(), C::{X::float(),Y::float()}, [Option]) -> bool() </c>
+%% contains(This::wxGraphicsPath(), C::{X::float(), Y::float()}, [Option]) -> bool() </c>
%%<br /> Option = {fillStyle, integer()}
%% </p>
@@ -207,14 +207,14 @@ contains(#wx_ref{type=ThisT,ref=ThisRef},X,Y, Options)
wxe_util:call(?wxGraphicsPath_Contains_3,
<<ThisRef:32/?UI,0:32,X:64/?F,Y:64/?F, BinOpt/binary>>).
-%% @spec (This::wxGraphicsPath()) -> {X::float(),Y::float(),W::float(),H::float()}
+%% @spec (This::wxGraphicsPath()) -> {X::float(), Y::float(), W::float(), H::float()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathgetbox">external documentation</a>.
getBox(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGraphicsPath),
wxe_util:call(?wxGraphicsPath_GetBox,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGraphicsPath()) -> {X::float(),Y::float()}
+%% @spec (This::wxGraphicsPath()) -> {X::float(), Y::float()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathgetcurrentpoint">external documentation</a>.
getCurrentPoint(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGraphicsPath),
diff --git a/lib/wx/src/gen/wxGrid.erl b/lib/wx/src/gen/wxGrid.erl
index 7b62ec33a4..531fed05c1 100644
--- a/lib/wx/src/gen/wxGrid.erl
+++ b/lib/wx/src/gen/wxGrid.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -151,7 +151,7 @@ new(Parent,Id)
%% new(Parent::wxWindow:wxWindow(), X::integer(), Y::integer()) -> new(Parent,X,Y, []) </c></p>
%% <p><c>
%% new(Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxGrid() </c>
-%%<br /> Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%%<br /> Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% </p>
new(Parent,X,Y)
@@ -306,7 +306,7 @@ beginBatch(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:cast(?wxGrid_BeginBatch,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid(), TopLeft::{R::integer(),C::integer()}, BottomRight::{R::integer(),C::integer()}) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
+%% @spec (This::wxGrid(), TopLeft::{R::integer(), C::integer()}, BottomRight::{R::integer(), C::integer()}) -> {X::integer(), Y::integer(), W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridblocktodevicerect">external documentation</a>.
blockToDeviceRect(#wx_ref{type=ThisT,ref=ThisRef},{TopLeftR,TopLeftC},{BottomRightR,BottomRightC})
when is_integer(TopLeftR),is_integer(TopLeftC),is_integer(BottomRightR),is_integer(BottomRightC) ->
@@ -342,7 +342,7 @@ canEnableCellControl(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxGrid_CanEnableCellControl,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid(), Coords::{R::integer(),C::integer()}) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
+%% @spec (This::wxGrid(), Coords::{R::integer(), C::integer()}) -> {X::integer(), Y::integer(), W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridcelltorect">external documentation</a>.
cellToRect(#wx_ref{type=ThisT,ref=ThisRef},{CoordsR,CoordsC})
when is_integer(CoordsR),is_integer(CoordsC) ->
@@ -350,7 +350,7 @@ cellToRect(#wx_ref{type=ThisT,ref=ThisRef},{CoordsR,CoordsC})
wxe_util:call(?wxGrid_CellToRect_1,
<<ThisRef:32/?UI,CoordsR:32/?UI,CoordsC:32/?UI>>).
-%% @spec (This::wxGrid(), Row::integer(), Col::integer()) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
+%% @spec (This::wxGrid(), Row::integer(), Col::integer()) -> {X::integer(), Y::integer(), W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridcelltorect">external documentation</a>.
cellToRect(#wx_ref{type=ThisT,ref=ThisRef},Row,Col)
when is_integer(Row),is_integer(Col) ->
@@ -586,7 +586,7 @@ getBatchCount(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxGrid_GetBatchCount,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid(), Row::integer(), Col::integer()) -> {Horiz::integer(),Vert::integer()}
+%% @spec (This::wxGrid(), Row::integer(), Col::integer()) -> {Horiz::integer(), Vert::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetcellalignment">external documentation</a>.
getCellAlignment(#wx_ref{type=ThisT,ref=ThisRef},Row,Col)
when is_integer(Row),is_integer(Col) ->
@@ -634,7 +634,7 @@ getCellTextColour(#wx_ref{type=ThisT,ref=ThisRef},Row,Col)
wxe_util:call(?wxGrid_GetCellTextColour,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGrid(), Coords::{R::integer(),C::integer()}) -> string()
+%% @spec (This::wxGrid(), Coords::{R::integer(), C::integer()}) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetcellvalue">external documentation</a>.
getCellValue(#wx_ref{type=ThisT,ref=ThisRef},{CoordsR,CoordsC})
when is_integer(CoordsR),is_integer(CoordsC) ->
@@ -650,7 +650,7 @@ getCellValue(#wx_ref{type=ThisT,ref=ThisRef},Row,Col)
wxe_util:call(?wxGrid_GetCellValue_2,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGrid()) -> {Horiz::integer(),Vert::integer()}
+%% @spec (This::wxGrid()) -> {Horiz::integer(), Vert::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetcollabelalignment">external documentation</a>.
getColLabelAlignment(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
@@ -679,7 +679,7 @@ getColMinimalAcceptableWidth(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxGrid_GetColMinimalAcceptableWidth,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> {Horiz::integer(),Vert::integer()}
+%% @spec (This::wxGrid()) -> {Horiz::integer(), Vert::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetdefaultcellalignment">external documentation</a>.
getDefaultCellAlignment(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
@@ -728,7 +728,7 @@ getDefaultEditor(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxGrid_GetDefaultEditor,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid(), C::{R::integer(),C::integer()}) -> wxGridCellEditor:wxGridCellEditor()
+%% @spec (This::wxGrid(), C::{R::integer(), C::integer()}) -> wxGridCellEditor:wxGridCellEditor()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetdefaulteditorforcell">external documentation</a>.
getDefaultEditorForCell(#wx_ref{type=ThisT,ref=ThisRef},{CR,CC})
when is_integer(CR),is_integer(CC) ->
@@ -869,7 +869,7 @@ getRowMinimalAcceptableHeight(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxGrid_GetRowMinimalAcceptableHeight,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> {Horiz::integer(),Vert::integer()}
+%% @spec (This::wxGrid()) -> {Horiz::integer(), Vert::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetrowlabelalignment">external documentation</a>.
getRowLabelAlignment(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
@@ -913,7 +913,7 @@ getScrollLineY(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxGrid_GetScrollLineY,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> [{R::integer(),C::integer()}]
+%% @spec (This::wxGrid()) -> [{R::integer(), C::integer()}]
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetselectedcells">external documentation</a>.
getSelectedCells(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
@@ -941,14 +941,14 @@ getSelectionBackground(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxGrid_GetSelectionBackground,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> [{R::integer(),C::integer()}]
+%% @spec (This::wxGrid()) -> [{R::integer(), C::integer()}]
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetselectionblocktopleft">external documentation</a>.
getSelectionBlockTopLeft(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetSelectionBlockTopLeft,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> [{R::integer(),C::integer()}]
+%% @spec (This::wxGrid()) -> [{R::integer(), C::integer()}]
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetselectionblockbottomright">external documentation</a>.
getSelectionBlockBottomRight(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
@@ -1065,7 +1065,7 @@ isEditable(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxGrid_IsEditable,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid(), Coords::{R::integer(),C::integer()}) -> bool()
+%% @spec (This::wxGrid(), Coords::{R::integer(), C::integer()}) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridisinselection">external documentation</a>.
isInSelection(#wx_ref{type=ThisT,ref=ThisRef},{CoordsR,CoordsC})
when is_integer(CoordsR),is_integer(CoordsC) ->
@@ -1096,7 +1096,7 @@ isSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxGrid_IsSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid(), Coords::{R::integer(),C::integer()}) -> bool()
+%% @spec (This::wxGrid(), Coords::{R::integer(), C::integer()}) -> bool()
%% @equiv isVisible(This,Coords, [])
isVisible(This,Coords={CoordsR,CoordsC})
when is_record(This, wx_ref),is_integer(CoordsR),is_integer(CoordsC) ->
@@ -1108,7 +1108,7 @@ isVisible(This,Coords={CoordsR,CoordsC})
%% <p><c>
%% isVisible(This::wxGrid(), Row::integer(), Col::integer()) -> isVisible(This,Row,Col, []) </c></p>
%% <p><c>
-%% isVisible(This::wxGrid(), Coords::{R::integer(),C::integer()}, [Option]) -> bool() </c>
+%% isVisible(This::wxGrid(), Coords::{R::integer(), C::integer()}, [Option]) -> bool() </c>
%%<br /> Option = {wholeCellVisible, bool()}
%% </p>
@@ -1136,7 +1136,7 @@ isVisible(#wx_ref{type=ThisT,ref=ThisRef},Row,Col, Options)
wxe_util:call(?wxGrid_IsVisible_3,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGrid(), Coords::{R::integer(),C::integer()}) -> ok
+%% @spec (This::wxGrid(), Coords::{R::integer(), C::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridmakecellvisible">external documentation</a>.
makeCellVisible(#wx_ref{type=ThisT,ref=ThisRef},{CoordsR,CoordsC})
when is_integer(CoordsR),is_integer(CoordsC) ->
@@ -1255,13 +1255,13 @@ selectAll(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:cast(?wxGrid_SelectAll,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid(), TopLeft::{R::integer(),C::integer()}, BottomRight::{R::integer(),C::integer()}) -> ok
+%% @spec (This::wxGrid(), TopLeft::{R::integer(), C::integer()}, BottomRight::{R::integer(), C::integer()}) -> ok
%% @equiv selectBlock(This,TopLeft,BottomRight, [])
selectBlock(This,TopLeft={TopLeftR,TopLeftC},BottomRight={BottomRightR,BottomRightC})
when is_record(This, wx_ref),is_integer(TopLeftR),is_integer(TopLeftC),is_integer(BottomRightR),is_integer(BottomRightC) ->
selectBlock(This,TopLeft,BottomRight, []).
-%% @spec (This::wxGrid(), TopLeft::{R::integer(),C::integer()}, BottomRight::{R::integer(),C::integer()}, [Option]) -> ok
+%% @spec (This::wxGrid(), TopLeft::{R::integer(), C::integer()}, BottomRight::{R::integer(), C::integer()}, [Option]) -> ok
%% Option = {addToSelected, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridselectblock">external documentation</a>.
selectBlock(#wx_ref{type=ThisT,ref=ThisRef},{TopLeftR,TopLeftC},{BottomRightR,BottomRightC}, Options)
@@ -1434,7 +1434,7 @@ setCellTextColour(#wx_ref{type=ThisT,ref=ThisRef},Val,Row,Col)
wxe_util:cast(?wxGrid_SetCellTextColour_3_1,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Val)):16/binary,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGrid(), Coords::{R::integer(),C::integer()}, S::string()) -> ok
+%% @spec (This::wxGrid(), Coords::{R::integer(), C::integer()}, S::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetcellvalue">external documentation</a>.
setCellValue(#wx_ref{type=ThisT,ref=ThisRef},{CoordsR,CoordsC},S)
when is_integer(CoordsR),is_integer(CoordsC),is_list(S) ->
diff --git a/lib/wx/src/gen/wxGridBagSizer.erl b/lib/wx/src/gen/wxGridBagSizer.erl
index d8cc210d3b..d2b8a2b045 100644
--- a/lib/wx/src/gen/wxGridBagSizer.erl
+++ b/lib/wx/src/gen/wxGridBagSizer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -90,7 +90,7 @@ add(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ItemT,ref=ItemRef}) ->
%% <p><c>
%% add(This::wxGridBagSizer(), Width::integer(), Height::integer()) -> add(This,Width,Height, []) </c></p>
%% <p><c>
-%% add(This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer(), Pos::{R::integer(),C::integer()}) -> add(This,Window,Pos, []) </c></p>
+%% add(This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer(), Pos::{R::integer(), C::integer()}) -> add(This,Window,Pos, []) </c></p>
%% <p><c>
%% add(This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer(), [Option]) -> wxSizerItem:wxSizerItem() </c>
%%<br /> Option = {proportion, integer()} | {flag, integer()} | {border, integer()} | {userData, wx:wx()}
@@ -125,14 +125,14 @@ add(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef}, Options
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizeradd">external documentation</a>.
%% <br /> Alternatives:
%% <p><c>
-%% add(This::wxGridBagSizer(), Width::integer(), Height::integer(), Pos::{R::integer(),C::integer()}) -> add(This,Width,Height,Pos, []) </c></p>
+%% add(This::wxGridBagSizer(), Width::integer(), Height::integer(), Pos::{R::integer(), C::integer()}) -> add(This,Width,Height,Pos, []) </c></p>
%% <p><c>
%% add(This::wxGridBagSizer(), Width::integer(), Height::integer(), [Option]) -> wxSizerItem:wxSizerItem() </c>
%%<br /> Option = {proportion, integer()} | {flag, integer()} | {border, integer()} | {userData, wx:wx()}
%% </p>
%% <p><c>
-%% add(This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer(), Pos::{R::integer(),C::integer()}, [Option]) -> wxSizerItem:wxSizerItem() </c>
-%%<br /> Option = {span, {RS::integer(),CS::integer()}} | {flag, integer()} | {border, integer()} | {userData, wx:wx()}
+%% add(This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer(), Pos::{R::integer(), C::integer()}, [Option]) -> wxSizerItem:wxSizerItem() </c>
+%%<br /> Option = {span, {RS::integer(), CS::integer()}} | {flag, integer()} | {border, integer()} | {userData, wx:wx()}
%% </p>
add(This,Width,Height,Pos={PosR,PosC})
@@ -167,8 +167,8 @@ add(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef},{PosR,Po
wxe_util:call(WindowOP,
<<ThisRef:32/?UI,WindowRef:32/?UI,PosR:32/?UI,PosC:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxGridBagSizer(), Width::integer(), Height::integer(), Pos::{R::integer(),C::integer()}, [Option]) -> wxSizerItem:wxSizerItem()
-%% Option = {span, {RS::integer(),CS::integer()}} | {flag, integer()} | {border, integer()} | {userData, wx:wx()}
+%% @spec (This::wxGridBagSizer(), Width::integer(), Height::integer(), Pos::{R::integer(), C::integer()}, [Option]) -> wxSizerItem:wxSizerItem()
+%% Option = {span, {RS::integer(), CS::integer()}} | {flag, integer()} | {border, integer()} | {userData, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizeradd">external documentation</a>.
add(#wx_ref{type=ThisT,ref=ThisRef},Width,Height,{PosR,PosC}, Options)
when is_integer(Width),is_integer(Height),is_integer(PosR),is_integer(PosC),is_list(Options) ->
@@ -182,7 +182,7 @@ add(#wx_ref{type=ThisT,ref=ThisRef},Width,Height,{PosR,PosC}, Options)
wxe_util:call(?wxGridBagSizer_Add_4,
<<ThisRef:32/?UI,Width:32/?UI,Height:32/?UI,PosR:32/?UI,PosC:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGridBagSizer()) -> {W::integer(),H::integer()}
+%% @spec (This::wxGridBagSizer()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizercalcmin">external documentation</a>.
calcMin(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridBagSizer),
@@ -199,7 +199,7 @@ checkForIntersection(This,Item)
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizercheckforintersection">external documentation</a>.
%% <br /> Alternatives:
%% <p><c>
-%% checkForIntersection(This::wxGridBagSizer(), Pos::{R::integer(),C::integer()}, Span::{RS::integer(),CS::integer()}) -> checkForIntersection(This,Pos,Span, []) </c></p>
+%% checkForIntersection(This::wxGridBagSizer(), Pos::{R::integer(), C::integer()}, Span::{RS::integer(), CS::integer()}) -> checkForIntersection(This,Pos,Span, []) </c></p>
%% <p><c>
%% checkForIntersection(This::wxGridBagSizer(), Item::wxGBSizerItem:wxGBSizerItem(), [Option]) -> bool() </c>
%%<br /> Option = {excludeItem, wxGBSizerItem:wxGBSizerItem()}
@@ -218,7 +218,7 @@ checkForIntersection(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ItemT,ref=Item
wxe_util:call(?wxGridBagSizer_CheckForIntersection_2,
<<ThisRef:32/?UI,ItemRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxGridBagSizer(), Pos::{R::integer(),C::integer()}, Span::{RS::integer(),CS::integer()}, [Option]) -> bool()
+%% @spec (This::wxGridBagSizer(), Pos::{R::integer(), C::integer()}, Span::{RS::integer(), CS::integer()}, [Option]) -> bool()
%% Option = {excludeItem, wxGBSizerItem:wxGBSizerItem()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizercheckforintersection">external documentation</a>.
checkForIntersection(#wx_ref{type=ThisT,ref=ThisRef},{PosR,PosC},{SpanRS,SpanCS}, Options)
@@ -243,7 +243,7 @@ findItem(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef}) ->
wxe_util:call(WindowOP,
<<ThisRef:32/?UI,WindowRef:32/?UI>>).
-%% @spec (This::wxGridBagSizer(), Pt::{X::integer(),Y::integer()}) -> wxGBSizerItem:wxGBSizerItem()
+%% @spec (This::wxGridBagSizer(), Pt::{X::integer(), Y::integer()}) -> wxGBSizerItem:wxGBSizerItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizerfinditematpoint">external documentation</a>.
findItemAtPoint(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
@@ -251,7 +251,7 @@ findItemAtPoint(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
wxe_util:call(?wxGridBagSizer_FindItemAtPoint,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxGridBagSizer(), Pos::{R::integer(),C::integer()}) -> wxGBSizerItem:wxGBSizerItem()
+%% @spec (This::wxGridBagSizer(), Pos::{R::integer(), C::integer()}) -> wxGBSizerItem:wxGBSizerItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizerfinditematposition">external documentation</a>.
findItemAtPosition(#wx_ref{type=ThisT,ref=ThisRef},{PosR,PosC})
when is_integer(PosR),is_integer(PosC) ->
@@ -267,7 +267,7 @@ findItemWithData(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=UserDataT,ref=User
wxe_util:call(?wxGridBagSizer_FindItemWithData,
<<ThisRef:32/?UI,UserDataRef:32/?UI>>).
-%% @spec (This::wxGridBagSizer(), Row::integer(), Col::integer()) -> {W::integer(),H::integer()}
+%% @spec (This::wxGridBagSizer(), Row::integer(), Col::integer()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizergetcellsize">external documentation</a>.
getCellSize(#wx_ref{type=ThisT,ref=ThisRef},Row,Col)
when is_integer(Row),is_integer(Col) ->
@@ -275,21 +275,21 @@ getCellSize(#wx_ref{type=ThisT,ref=ThisRef},Row,Col)
wxe_util:call(?wxGridBagSizer_GetCellSize,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGridBagSizer()) -> {W::integer(),H::integer()}
+%% @spec (This::wxGridBagSizer()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizergetemptycellsize">external documentation</a>.
getEmptyCellSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridBagSizer),
wxe_util:call(?wxGridBagSizer_GetEmptyCellSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridBagSizer(),X::integer()|term()) -> {R::integer(),C::integer()}
+%% @spec (This::wxGridBagSizer(),X::integer()|term()) -> {R::integer(), C::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizergetitemposition">external documentation</a>.
%% <br /> Alternatives:
%% <p><c>
-%% getItemPosition(This::wxGridBagSizer(), Index::integer()) -> {R::integer(),C::integer()} </c>
+%% getItemPosition(This::wxGridBagSizer(), Index::integer()) -> {R::integer(), C::integer()} </c>
%% </p>
%% <p><c>
-%% getItemPosition(This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer()) -> {R::integer(),C::integer()} </c>
+%% getItemPosition(This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer()) -> {R::integer(), C::integer()} </c>
%% </p>
getItemPosition(#wx_ref{type=ThisT,ref=ThisRef},Index)
when is_integer(Index) ->
@@ -307,14 +307,14 @@ getItemPosition(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowR
wxe_util:call(WindowOP,
<<ThisRef:32/?UI,WindowRef:32/?UI>>).
-%% @spec (This::wxGridBagSizer(),X::integer()|term()) -> {RS::integer(),CS::integer()}
+%% @spec (This::wxGridBagSizer(),X::integer()|term()) -> {RS::integer(), CS::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizergetitemspan">external documentation</a>.
%% <br /> Alternatives:
%% <p><c>
-%% getItemSpan(This::wxGridBagSizer(), Index::integer()) -> {RS::integer(),CS::integer()} </c>
+%% getItemSpan(This::wxGridBagSizer(), Index::integer()) -> {RS::integer(), CS::integer()} </c>
%% </p>
%% <p><c>
-%% getItemSpan(This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer()) -> {RS::integer(),CS::integer()} </c>
+%% getItemSpan(This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer()) -> {RS::integer(), CS::integer()} </c>
%% </p>
getItemSpan(#wx_ref{type=ThisT,ref=ThisRef},Index)
when is_integer(Index) ->
@@ -332,7 +332,7 @@ getItemSpan(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef})
wxe_util:call(WindowOP,
<<ThisRef:32/?UI,WindowRef:32/?UI>>).
-%% @spec (This::wxGridBagSizer(), Sz::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxGridBagSizer(), Sz::{W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizersetemptycellsize">external documentation</a>.
setEmptyCellSize(#wx_ref{type=ThisT,ref=ThisRef},{SzW,SzH})
when is_integer(SzW),is_integer(SzH) ->
@@ -340,14 +340,14 @@ setEmptyCellSize(#wx_ref{type=ThisT,ref=ThisRef},{SzW,SzH})
wxe_util:cast(?wxGridBagSizer_SetEmptyCellSize,
<<ThisRef:32/?UI,SzW:32/?UI,SzH:32/?UI>>).
-%% @spec (This::wxGridBagSizer(),X::integer()|term(),Pos::{R::integer(),C::integer()}) -> bool()
+%% @spec (This::wxGridBagSizer(),X::integer()|term(),Pos::{R::integer(), C::integer()}) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizersetitemposition">external documentation</a>.
%% <br /> Alternatives:
%% <p><c>
-%% setItemPosition(This::wxGridBagSizer(), Index::integer(), Pos::{R::integer(),C::integer()}) -> bool() </c>
+%% setItemPosition(This::wxGridBagSizer(), Index::integer(), Pos::{R::integer(), C::integer()}) -> bool() </c>
%% </p>
%% <p><c>
-%% setItemPosition(This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer(), Pos::{R::integer(),C::integer()}) -> bool() </c>
+%% setItemPosition(This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer(), Pos::{R::integer(), C::integer()}) -> bool() </c>
%% </p>
setItemPosition(#wx_ref{type=ThisT,ref=ThisRef},Index,{PosR,PosC})
when is_integer(Index),is_integer(PosR),is_integer(PosC) ->
@@ -366,14 +366,14 @@ setItemPosition(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowR
wxe_util:call(WindowOP,
<<ThisRef:32/?UI,WindowRef:32/?UI,PosR:32/?UI,PosC:32/?UI>>).
-%% @spec (This::wxGridBagSizer(),X::integer()|term(),Span::{RS::integer(),CS::integer()}) -> bool()
+%% @spec (This::wxGridBagSizer(),X::integer()|term(),Span::{RS::integer(), CS::integer()}) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizersetitemspan">external documentation</a>.
%% <br /> Alternatives:
%% <p><c>
-%% setItemSpan(This::wxGridBagSizer(), Index::integer(), Span::{RS::integer(),CS::integer()}) -> bool() </c>
+%% setItemSpan(This::wxGridBagSizer(), Index::integer(), Span::{RS::integer(), CS::integer()}) -> bool() </c>
%% </p>
%% <p><c>
-%% setItemSpan(This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer(), Span::{RS::integer(),CS::integer()}) -> bool() </c>
+%% setItemSpan(This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer(), Span::{RS::integer(), CS::integer()}) -> bool() </c>
%% </p>
setItemSpan(#wx_ref{type=ThisT,ref=ThisRef},Index,{SpanRS,SpanCS})
when is_integer(Index),is_integer(SpanRS),is_integer(SpanCS) ->
@@ -474,7 +474,7 @@ prepend(This,Width,Height, Options) -> wxSizer:prepend(This,Width,Height, Option
%% @hidden
prepend(This,Width,Height) -> wxSizer:prepend(This,Width,Height).
%% @hidden
-prepend(This,Window) -> wxSizer:prepend(This,Window).
+prepend(This,Item) -> wxSizer:prepend(This,Item).
%% @hidden
layout(This) -> wxSizer:layout(This).
%% @hidden
@@ -490,7 +490,7 @@ insert(This,Index,Width,Height, Options) -> wxSizer:insert(This,Index,Width,Heig
%% @hidden
insert(This,Index,Width,Height) -> wxSizer:insert(This,Index,Width,Height).
%% @hidden
-insert(This,Index,Window) -> wxSizer:insert(This,Index,Window).
+insert(This,Index,Item) -> wxSizer:insert(This,Index,Item).
%% @hidden
hide(This,Window, Options) -> wxSizer:hide(This,Window, Options).
%% @hidden
diff --git a/lib/wx/src/gen/wxGridCellAttr.erl b/lib/wx/src/gen/wxGridCellAttr.erl
index 3d23c2acfc..a9a0c1fb79 100644
--- a/lib/wx/src/gen/wxGridCellAttr.erl
+++ b/lib/wx/src/gen/wxGridCellAttr.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -165,7 +165,7 @@ getFont(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxGridCellAttr_GetFont,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridCellAttr()) -> {HAlign::integer(),VAlign::integer()}
+%% @spec (This::wxGridCellAttr()) -> {HAlign::integer(), VAlign::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellattr.html#wxgridcellattrgetalignment">external documentation</a>.
getAlignment(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridCellAttr),
diff --git a/lib/wx/src/gen/wxGridCellEditor.erl b/lib/wx/src/gen/wxGridCellEditor.erl
index a27ba7bd0f..de1ebc5a4c 100644
--- a/lib/wx/src/gen/wxGridCellEditor.erl
+++ b/lib/wx/src/gen/wxGridCellEditor.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -50,7 +50,7 @@ isCreated(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxGridCellEditor_IsCreated,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridCellEditor(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> ok
+%% @spec (This::wxGridCellEditor(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcelleditor.html#wxgridcelleditorsetsize">external documentation</a>.
setSize(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
@@ -76,7 +76,7 @@ show(#wx_ref{type=ThisT,ref=ThisRef},Show, Options)
wxe_util:cast(?wxGridCellEditor_Show,
<<ThisRef:32/?UI,(wxe_util:from_bool(Show)):32/?UI, BinOpt/binary>>).
-%% @spec (This::wxGridCellEditor(), RectCell::{X::integer(),Y::integer(),W::integer(),H::integer()}, Attr::wxGridCellAttr:wxGridCellAttr()) -> ok
+%% @spec (This::wxGridCellEditor(), RectCell::{X::integer(), Y::integer(), W::integer(), H::integer()}, Attr::wxGridCellAttr:wxGridCellAttr()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcelleditor.html#wxgridcelleditorpaintbackground">external documentation</a>.
paintBackground(#wx_ref{type=ThisT,ref=ThisRef},{RectCellX,RectCellY,RectCellW,RectCellH},#wx_ref{type=AttrT,ref=AttrRef})
when is_integer(RectCellX),is_integer(RectCellY),is_integer(RectCellW),is_integer(RectCellH) ->
diff --git a/lib/wx/src/gen/wxGridCellRenderer.erl b/lib/wx/src/gen/wxGridCellRenderer.erl
index d9520c478f..765c116a48 100644
--- a/lib/wx/src/gen/wxGridCellRenderer.erl
+++ b/lib/wx/src/gen/wxGridCellRenderer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -32,7 +32,7 @@
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxGridCellRenderer(), Grid::wxGrid:wxGrid(), Attr::wxGridCellAttr:wxGridCellAttr(), Dc::wxDC:wxDC(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}, Row::integer(), Col::integer(), IsSelected::bool()) -> ok
+%% @spec (This::wxGridCellRenderer(), Grid::wxGrid:wxGrid(), Attr::wxGridCellAttr:wxGridCellAttr(), Dc::wxDC:wxDC(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}, Row::integer(), Col::integer(), IsSelected::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellrenderer.html#wxgridcellrendererdraw">external documentation</a>.
draw(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=GridT,ref=GridRef},#wx_ref{type=AttrT,ref=AttrRef},#wx_ref{type=DcT,ref=DcRef},{RectX,RectY,RectW,RectH},Row,Col,IsSelected)
when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH),is_integer(Row),is_integer(Col),is_boolean(IsSelected) ->
@@ -43,7 +43,7 @@ draw(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=GridT,ref=GridRef},#wx_ref{typ
wxe_util:cast(?wxGridCellRenderer_Draw,
<<ThisRef:32/?UI,GridRef:32/?UI,AttrRef:32/?UI,DcRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI,Row:32/?UI,Col:32/?UI,(wxe_util:from_bool(IsSelected)):32/?UI>>).
-%% @spec (This::wxGridCellRenderer(), Grid::wxGrid:wxGrid(), Attr::wxGridCellAttr:wxGridCellAttr(), Dc::wxDC:wxDC(), Row::integer(), Col::integer()) -> {W::integer(),H::integer()}
+%% @spec (This::wxGridCellRenderer(), Grid::wxGrid:wxGrid(), Attr::wxGridCellAttr:wxGridCellAttr(), Dc::wxDC:wxDC(), Row::integer(), Col::integer()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellrenderer.html#wxgridcellrenderergetbestsize">external documentation</a>.
getBestSize(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=GridT,ref=GridRef},#wx_ref{type=AttrT,ref=AttrRef},#wx_ref{type=DcT,ref=DcRef},Row,Col)
when is_integer(Row),is_integer(Col) ->
diff --git a/lib/wx/src/gen/wxGridEvent.erl b/lib/wx/src/gen/wxGridEvent.erl
index 9b7e0012ca..123088afb5 100644
--- a/lib/wx/src/gen/wxGridEvent.erl
+++ b/lib/wx/src/gen/wxGridEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -69,7 +69,7 @@ getCol(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxGridEvent_GetCol,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridEvent()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxGridEvent()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridevent.html#wxgrideventgetposition">external documentation</a>.
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridEvent),
diff --git a/lib/wx/src/gen/wxGridSizer.erl b/lib/wx/src/gen/wxGridSizer.erl
index 7b62774347..fd8580c70d 100644
--- a/lib/wx/src/gen/wxGridSizer.erl
+++ b/lib/wx/src/gen/wxGridSizer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -174,7 +174,7 @@ prepend(This,Width,Height, Options) -> wxSizer:prepend(This,Width,Height, Option
%% @hidden
prepend(This,Width,Height) -> wxSizer:prepend(This,Width,Height).
%% @hidden
-prepend(This,Window) -> wxSizer:prepend(This,Window).
+prepend(This,Item) -> wxSizer:prepend(This,Item).
%% @hidden
layout(This) -> wxSizer:layout(This).
%% @hidden
@@ -190,7 +190,7 @@ insert(This,Index,Width,Height, Options) -> wxSizer:insert(This,Index,Width,Heig
%% @hidden
insert(This,Index,Width,Height) -> wxSizer:insert(This,Index,Width,Height).
%% @hidden
-insert(This,Index,Window) -> wxSizer:insert(This,Index,Window).
+insert(This,Index,Item) -> wxSizer:insert(This,Index,Item).
%% @hidden
hide(This,Window, Options) -> wxSizer:hide(This,Window, Options).
%% @hidden
diff --git a/lib/wx/src/gen/wxHelpEvent.erl b/lib/wx/src/gen/wxHelpEvent.erl
index ef3c666ab7..b80903c314 100644
--- a/lib/wx/src/gen/wxHelpEvent.erl
+++ b/lib/wx/src/gen/wxHelpEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -50,7 +50,7 @@ getOrigin(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxHelpEvent_GetOrigin,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxHelpEvent()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxHelpEvent()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhelpevent.html#wxhelpeventgetposition">external documentation</a>.
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxHelpEvent),
@@ -67,7 +67,7 @@ setOrigin(#wx_ref{type=ThisT,ref=ThisRef},Origin)
wxe_util:cast(?wxHelpEvent_SetOrigin,
<<ThisRef:32/?UI,Origin:32/?UI>>).
-%% @spec (This::wxHelpEvent(), Pos::{X::integer(),Y::integer()}) -> ok
+%% @spec (This::wxHelpEvent(), Pos::{X::integer(), Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhelpevent.html#wxhelpeventsetposition">external documentation</a>.
setPosition(#wx_ref{type=ThisT,ref=ThisRef},{PosX,PosY})
when is_integer(PosX),is_integer(PosY) ->
diff --git a/lib/wx/src/gen/wxHtmlWindow.erl b/lib/wx/src/gen/wxHtmlWindow.erl
index ba8278ff56..891e5481fb 100644
--- a/lib/wx/src/gen/wxHtmlWindow.erl
+++ b/lib/wx/src/gen/wxHtmlWindow.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -99,7 +99,7 @@ new(Parent)
new(Parent, []).
%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxHtmlWindow()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {id, integer()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowwxhtmlwindow">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
@@ -217,7 +217,7 @@ selectionToText(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxHtmlWindow_SelectionToText,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxHtmlWindow(), Pos::{X::integer(),Y::integer()}) -> ok
+%% @spec (This::wxHtmlWindow(), Pos::{X::integer(), Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowselectline">external documentation</a>.
selectLine(#wx_ref{type=ThisT,ref=ThisRef},{PosX,PosY})
when is_integer(PosX),is_integer(PosY) ->
@@ -225,7 +225,7 @@ selectLine(#wx_ref{type=ThisT,ref=ThisRef},{PosX,PosY})
wxe_util:cast(?wxHtmlWindow_SelectLine,
<<ThisRef:32/?UI,PosX:32/?UI,PosY:32/?UI>>).
-%% @spec (This::wxHtmlWindow(), Pos::{X::integer(),Y::integer()}) -> ok
+%% @spec (This::wxHtmlWindow(), Pos::{X::integer(), Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowselectword">external documentation</a>.
selectWord(#wx_ref{type=ThisT,ref=ThisRef},{PosX,PosY})
when is_integer(PosX),is_integer(PosY) ->
diff --git a/lib/wx/src/gen/wxIconBundle.erl b/lib/wx/src/gen/wxIconBundle.erl
index ee133cbcb9..011b2dd1ac 100644
--- a/lib/wx/src/gen/wxIconBundle.erl
+++ b/lib/wx/src/gen/wxIconBundle.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -89,7 +89,7 @@ getIcon(This)
%%<br /> Option = {size, integer()}
%% </p>
%% <p><c>
-%% getIcon(This::wxIconBundle(), Size::{W::integer(),H::integer()}) -> wxIcon:wxIcon() </c>
+%% getIcon(This::wxIconBundle(), Size::{W::integer(), H::integer()}) -> wxIcon:wxIcon() </c>
%% </p>
getIcon(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
diff --git a/lib/wx/src/gen/wxImage.erl b/lib/wx/src/gen/wxImage.erl
index 5fe105fbb2..ea41a78a40 100644
--- a/lib/wx/src/gen/wxImage.erl
+++ b/lib/wx/src/gen/wxImage.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -303,13 +303,13 @@ create(#wx_ref{type=ThisT,ref=ThisRef},Width,Height,Data,Alpha, Options)
wxe_util:cast(?wxImage_Destroy,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxImage()) -> {bool(),R::integer(),G::integer(),B::integer()}
+%% @spec (This::wxImage()) -> {bool(), R::integer(), G::integer(), B::integer()}
%% @equiv findFirstUnusedColour(This, [])
findFirstUnusedColour(This)
when is_record(This, wx_ref) ->
findFirstUnusedColour(This, []).
-%% @spec (This::wxImage(), [Option]) -> {bool(),R::integer(),G::integer(),B::integer()}
+%% @spec (This::wxImage(), [Option]) -> {bool(), R::integer(), G::integer(), B::integer()}
%% Option = {startR, integer()} | {startG, integer()} | {startB, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagefindfirstunusedcolour">external documentation</a>.
findFirstUnusedColour(#wx_ref{type=ThisT,ref=ThisRef}, Options)
@@ -413,7 +413,7 @@ getMaskRed(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxImage_GetMaskRed,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxImage()) -> {bool(),R::integer(),G::integer(),B::integer()}
+%% @spec (This::wxImage()) -> {bool(), R::integer(), G::integer(), B::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagegetorfindmaskcolour">external documentation</a>.
getOrFindMaskColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxImage),
@@ -435,7 +435,7 @@ getRed(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
wxe_util:call(?wxImage_GetRed,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxImage(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> wxImage()
+%% @spec (This::wxImage(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> wxImage()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagegetsubimage">external documentation</a>.
getSubImage(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
@@ -615,13 +615,13 @@ rescale(#wx_ref{type=ThisT,ref=ThisRef},Width,Height, Options)
wxe_util:call(?wxImage_Rescale,
<<ThisRef:32/?UI,Width:32/?UI,Height:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxImage(), Size::{W::integer(),H::integer()}, Pos::{X::integer(),Y::integer()}) -> wxImage()
+%% @spec (This::wxImage(), Size::{W::integer(), H::integer()}, Pos::{X::integer(), Y::integer()}) -> wxImage()
%% @equiv resize(This,Size,Pos, [])
resize(This,Size={SizeW,SizeH},Pos={PosX,PosY})
when is_record(This, wx_ref),is_integer(SizeW),is_integer(SizeH),is_integer(PosX),is_integer(PosY) ->
resize(This,Size,Pos, []).
-%% @spec (This::wxImage(), Size::{W::integer(),H::integer()}, Pos::{X::integer(),Y::integer()}, [Option]) -> wxImage()
+%% @spec (This::wxImage(), Size::{W::integer(), H::integer()}, Pos::{X::integer(), Y::integer()}, [Option]) -> wxImage()
%% Option = {r, integer()} | {g, integer()} | {b, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximageresize">external documentation</a>.
resize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH},{PosX,PosY}, Options)
@@ -635,14 +635,14 @@ resize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH},{PosX,PosY}, Options)
wxe_util:call(?wxImage_Resize,
<<ThisRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI,PosX:32/?UI,PosY:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxImage(), Angle::float(), Centre_of_rotation::{X::integer(),Y::integer()}) -> wxImage()
+%% @spec (This::wxImage(), Angle::float(), Centre_of_rotation::{X::integer(), Y::integer()}) -> wxImage()
%% @equiv rotate(This,Angle,Centre_of_rotation, [])
rotate(This,Angle,Centre_of_rotation={Centre_of_rotationX,Centre_of_rotationY})
when is_record(This, wx_ref),is_float(Angle),is_integer(Centre_of_rotationX),is_integer(Centre_of_rotationY) ->
rotate(This,Angle,Centre_of_rotation, []).
-%% @spec (This::wxImage(), Angle::float(), Centre_of_rotation::{X::integer(),Y::integer()}, [Option]) -> wxImage()
-%% Option = {interpolating, bool()} | {offset_after_rotation, {X::integer(),Y::integer()}}
+%% @spec (This::wxImage(), Angle::float(), Centre_of_rotation::{X::integer(), Y::integer()}, [Option]) -> wxImage()
+%% Option = {interpolating, bool()} | {offset_after_rotation, {X::integer(), Y::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagerotate">external documentation</a>.
rotate(#wx_ref{type=ThisT,ref=ThisRef},Angle,{Centre_of_rotationX,Centre_of_rotationY}, Options)
when is_float(Angle),is_integer(Centre_of_rotationX),is_integer(Centre_of_rotationY),is_list(Options) ->
@@ -730,13 +730,13 @@ scale(#wx_ref{type=ThisT,ref=ThisRef},Width,Height, Options)
wxe_util:call(?wxImage_Scale,
<<ThisRef:32/?UI,Width:32/?UI,Height:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxImage(), Size::{W::integer(),H::integer()}, Pos::{X::integer(),Y::integer()}) -> wxImage()
+%% @spec (This::wxImage(), Size::{W::integer(), H::integer()}, Pos::{X::integer(), Y::integer()}) -> wxImage()
%% @equiv size(This,Size,Pos, [])
size(This,Size={SizeW,SizeH},Pos={PosX,PosY})
when is_record(This, wx_ref),is_integer(SizeW),is_integer(SizeH),is_integer(PosX),is_integer(PosY) ->
size(This,Size,Pos, []).
-%% @spec (This::wxImage(), Size::{W::integer(),H::integer()}, Pos::{X::integer(),Y::integer()}, [Option]) -> wxImage()
+%% @spec (This::wxImage(), Size::{W::integer(), H::integer()}, Pos::{X::integer(), Y::integer()}, [Option]) -> wxImage()
%% Option = {r, integer()} | {g, integer()} | {b, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagesize">external documentation</a>.
size(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH},{PosX,PosY}, Options)
@@ -881,7 +881,7 @@ setPalette(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PaletteT,ref=PaletteRef}
wxe_util:cast(?wxImage_SetPalette,
<<ThisRef:32/?UI,PaletteRef:32/?UI>>).
-%% @spec (This::wxImage(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}, R::integer(), G::integer(), B::integer()) -> ok
+%% @spec (This::wxImage(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}, R::integer(), G::integer(), B::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagesetrgb">external documentation</a>.
setRGB(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH},R,G,B)
when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH),is_integer(R),is_integer(G),is_integer(B) ->
diff --git a/lib/wx/src/gen/wxImageList.erl b/lib/wx/src/gen/wxImageList.erl
index dbd51bc47b..f805a234df 100644
--- a/lib/wx/src/gen/wxImageList.erl
+++ b/lib/wx/src/gen/wxImageList.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -150,7 +150,7 @@ getImageCount(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxImageList_GetImageCount,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxImageList(), Index::integer()) -> {bool(),Width::integer(),Height::integer()}
+%% @spec (This::wxImageList(), Index::integer()) -> {bool(), Width::integer(), Height::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximagelist.html#wximagelistgetsize">external documentation</a>.
getSize(#wx_ref{type=ThisT,ref=ThisRef},Index)
when is_integer(Index) ->
diff --git a/lib/wx/src/gen/wxJoystickEvent.erl b/lib/wx/src/gen/wxJoystickEvent.erl
index 2c2d7f3968..2f149a50f8 100644
--- a/lib/wx/src/gen/wxJoystickEvent.erl
+++ b/lib/wx/src/gen/wxJoystickEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -118,7 +118,7 @@ getJoystick(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxJoystickEvent_GetJoystick,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxJoystickEvent()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxJoystickEvent()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxjoystickevent.html#wxjoystickeventgetposition">external documentation</a>.
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxJoystickEvent),
diff --git a/lib/wx/src/gen/wxKeyEvent.erl b/lib/wx/src/gen/wxKeyEvent.erl
index 00d1e2033a..edda5ee0a6 100644
--- a/lib/wx/src/gen/wxKeyEvent.erl
+++ b/lib/wx/src/gen/wxKeyEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -78,7 +78,7 @@ getModifiers(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxKeyEvent_GetModifiers,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxKeyEvent()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxKeyEvent()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxkeyevent.html#wxkeyeventgetposition">external documentation</a>.
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxKeyEvent),
diff --git a/lib/wx/src/gen/wxLayoutAlgorithm.erl b/lib/wx/src/gen/wxLayoutAlgorithm.erl
index 402d116338..c17abeaed1 100644
--- a/lib/wx/src/gen/wxLayoutAlgorithm.erl
+++ b/lib/wx/src/gen/wxLayoutAlgorithm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -65,7 +65,7 @@ layoutMDIFrame(This,Frame)
layoutMDIFrame(This,Frame, []).
%% @spec (This::wxLayoutAlgorithm(), Frame::wxMDIParentFrame:wxMDIParentFrame(), [Option]) -> bool()
-%% Option = {rect, {X::integer(),Y::integer(),W::integer(),H::integer()}}
+%% Option = {rect, {X::integer(), Y::integer(), W::integer(), H::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlayoutalgorithm.html#wxlayoutalgorithmlayoutmdiframe">external documentation</a>.
layoutMDIFrame(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FrameT,ref=FrameRef}, Options)
when is_list(Options) ->
diff --git a/lib/wx/src/gen/wxListBox.erl b/lib/wx/src/gen/wxListBox.erl
index 731209c586..cc30bf95e4 100644
--- a/lib/wx/src/gen/wxListBox.erl
+++ b/lib/wx/src/gen/wxListBox.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -94,7 +94,7 @@ new(Parent,Id)
new(Parent,Id, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxListBox()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {choices, [[string()]]} | {style, integer()} | {validator, wx:wx()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {choices, [[string()]]} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbox.html#wxlistboxwxlistbox">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
@@ -109,13 +109,13 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
wxe_util:construct(?wxListBox_new_3,
<<ParentRef:32/?UI,Id:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxListBox(), Parent::wxWindow:wxWindow(), Id::integer(), Pos::{X::integer(),Y::integer()}, Size::{W::integer(),H::integer()}, Choices::[[string()]]) -> bool()
+%% @spec (This::wxListBox(), Parent::wxWindow:wxWindow(), Id::integer(), Pos::{X::integer(), Y::integer()}, Size::{W::integer(), H::integer()}, Choices::[[string()]]) -> bool()
%% @equiv create(This,Parent,Id,Pos,Size,Choices, [])
create(This,Parent,Id,Pos={PosX,PosY},Size={SizeW,SizeH},Choices)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id),is_integer(PosX),is_integer(PosY),is_integer(SizeW),is_integer(SizeH),is_list(Choices) ->
create(This,Parent,Id,Pos,Size,Choices, []).
-%% @spec (This::wxListBox(), Parent::wxWindow:wxWindow(), Id::integer(), Pos::{X::integer(),Y::integer()}, Size::{W::integer(),H::integer()}, Choices::[[string()]], [Option]) -> bool()
+%% @spec (This::wxListBox(), Parent::wxWindow:wxWindow(), Id::integer(), Pos::{X::integer(), Y::integer()}, Size::{W::integer(), H::integer()}, Choices::[[string()]], [Option]) -> bool()
%% Option = {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbox.html#wxlistboxcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,{PosX,PosY},{SizeW,SizeH},Choices, Options)
@@ -139,7 +139,7 @@ deselect(#wx_ref{type=ThisT,ref=ThisRef},N)
wxe_util:cast(?wxListBox_Deselect,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxListBox()) -> {integer(),ASelections::[integer()]}
+%% @spec (This::wxListBox()) -> {integer(), ASelections::[integer()]}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbox.html#wxlistboxgetselections">external documentation</a>.
getSelections(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListBox),
@@ -174,7 +174,7 @@ set(#wx_ref{type=ThisT,ref=ThisRef},Items)
wxe_util:cast(?wxListBox_Set,
<<ThisRef:32/?UI,(length(Items_UCA)):32/?UI, (<< <<(byte_size(UC_Str)):32/?UI, UC_Str/binary>>|| UC_Str <- Items_UCA>>)/binary, 0:(((8- ((0 + lists:sum([byte_size(S)+4||S<-Items_UCA])) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxListBox(), Point::{X::integer(),Y::integer()}) -> integer()
+%% @spec (This::wxListBox(), Point::{X::integer(), Y::integer()}) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbox.html#wxlistboxhittest">external documentation</a>.
hitTest(#wx_ref{type=ThisT,ref=ThisRef},{PointX,PointY})
when is_integer(PointX),is_integer(PointY) ->
diff --git a/lib/wx/src/gen/wxListCtrl.erl b/lib/wx/src/gen/wxListCtrl.erl
index 9c4ba1e5a3..fa99897171 100644
--- a/lib/wx/src/gen/wxListCtrl.erl
+++ b/lib/wx/src/gen/wxListCtrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -29,17 +29,17 @@
-module(wxListCtrl).
-include("wxe.hrl").
--export([ sortItems/2 ,arrange/1,arrange/2,assignImageList/3,clearAll/1,create/2,
- create/3,deleteAllItems/1,deleteColumn/2,deleteItem/2,destroy/1,editLabel/2,
- ensureVisible/2,findItem/3,findItem/4,getColumn/3,getColumnCount/1,
- getColumnWidth/2,getCountPerPage/1,getEditControl/1,getImageList/2,
- getItem/2,getItemBackgroundColour/2,getItemCount/1,getItemData/2,
- getItemFont/2,getItemPosition/3,getItemRect/3,getItemRect/4,getItemSpacing/1,
- getItemState/3,getItemText/2,getItemTextColour/2,getNextItem/2,getNextItem/3,
- getSelectedItemCount/1,getTextColour/1,getTopItem/1,getViewRect/1,
- hitTest/2,insertColumn/3,insertColumn/4,insertItem/2,insertItem/3,
- insertItem/4,new/0,new/1,new/2,refreshItem/2,refreshItems/3,scrollList/3,
- setBackgroundColour/2,setColumn/3,setColumnWidth/3,setImageList/3,
+-export([ create/2, create/3 , new/0, new/1, new/2 , sortItems/2 ,arrange/1,
+ arrange/2,assignImageList/3,clearAll/1,deleteAllItems/1,deleteColumn/2,
+ deleteItem/2,destroy/1,editLabel/2,ensureVisible/2,findItem/3,findItem/4,
+ getColumn/3,getColumnCount/1,getColumnWidth/2,getCountPerPage/1,getEditControl/1,
+ getImageList/2,getItem/2,getItemBackgroundColour/2,getItemCount/1,
+ getItemData/2,getItemFont/2,getItemPosition/3,getItemRect/3,getItemRect/4,
+ getItemSpacing/1,getItemState/3,getItemText/2,getItemTextColour/2,
+ getNextItem/2,getNextItem/3,getSelectedItemCount/1,getTextColour/1,
+ getTopItem/1,getViewRect/1,hitTest/2,insertColumn/3,insertColumn/4,
+ insertItem/2,insertItem/3,insertItem/4,refreshItem/2,refreshItems/3,
+ scrollList/3,setBackgroundColour/2,setColumn/3,setColumnWidth/3,setImageList/3,
setItem/2,setItem/4,setItem/5,setItemBackgroundColour/3,setItemColumnImage/4,
setItemCount/2,setItemData/3,setItemFont/3,setItemImage/3,setItemImage/4,
setItemPosition/3,setItemState/4,setItemText/3,setItemTextColour/3,
@@ -89,11 +89,11 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+
%% @spec () -> wxListCtrl()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlwxlistctrl">external documentation</a>.
new() ->
- wxe_util:construct(?wxListCtrl_new_0,
- <<>>).
+ wxe_util:construct(?wxListCtrl_new_0, <<>>).
%% @spec (Parent::wxWindow:wxWindow()) -> wxListCtrl()
%% @equiv new(Parent, [])
@@ -102,20 +102,44 @@ new(Parent)
new(Parent, []).
%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxListCtrl()
-%% Option = {winid, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {winid, integer()} |
+%% {pos, {X::integer(),Y::integer()}} |
+%% {size, {W::integer(),H::integer()}} |
+%% {style, integer()} |
+%% {validator, wx:wx()} |
+%% {onGetItemText, OnGetItemText} |
+%% {onGetItemAttr, OnGetItemAttr} |
+%% {onGetItemColumnImage, OnGetItemColumnImage}
+%%
+%% OnGetItemText = (This, Item, Column) -> wxString()
+%% OnGetItemAttr = (This, Item) -> wxListItemAttr()
+%% OnGetItemColumnImage = (This, Item, Column) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlwxlistctrl">external documentation</a>.
+
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
- when is_list(Options) ->
- ?CLASS(ParentT,wxWindow),
- MOpts = fun({winid, Winid}, Acc) -> [<<1:32/?UI,Winid:32/?UI>>|Acc];
- ({pos, {PosX,PosY}}, Acc) -> [<<2:32/?UI,PosX:32/?UI,PosY:32/?UI,0:32>>|Acc];
- ({size, {SizeW,SizeH}}, Acc) -> [<<3:32/?UI,SizeW:32/?UI,SizeH:32/?UI,0:32>>|Acc];
- ({style, Style}, Acc) -> [<<4:32/?UI,Style:32/?UI>>|Acc];
- ({validator, #wx_ref{type=ValidatorT,ref=ValidatorRef}}, Acc) -> ?CLASS(ValidatorT,wx),[<<5:32/?UI,ValidatorRef:32/?UI>>|Acc];
- (BadOpt, _) -> erlang:error({badoption, BadOpt}) end,
- BinOpt = list_to_binary(lists:foldl(MOpts, [<<0:32>>], Options)),
- wxe_util:construct(?wxListCtrl_new_2,
- <<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
+ when is_list(Options)->
+ ?CLASS(ParentT,wxWindow),
+ MOpts = fun({winid, Winid}, Acc) -> [<<1:32/?UI,Winid:32/?UI>>|Acc];
+ ({pos, {PosX,PosY}}, Acc) -> [<<2:32/?UI,PosX:32/?UI,PosY:32/?UI,0:32>>|Acc];
+ ({size, {SizeW,SizeH}}, Acc) -> [<<3:32/?UI,SizeW:32/?UI,SizeH:32/?UI,0:32>>|Acc];
+ ({style, Style}, Acc) -> [<<4:32/?UI,Style:32/?UI>>|Acc];
+ ({validator, #wx_ref{type=ValidatorT,ref=ValidatorRef}}, Acc) ->
+ ?CLASS(ValidatorT,wx),[<<5:32/?UI,ValidatorRef:32/?UI>>|Acc];
+ ({onGetItemText, F}, Acc) when is_function(F) ->
+ Fun = fun([This,Item,Col]) -> unicode:characters_to_binary([F(This,Item,Col),0]) end,
+ [<<6:32/?UI,(wxe_util:get_cbId(Fun)):32/?UI>>|Acc];
+ ({onGetItemAttr, F}, Acc) when is_function(F) ->
+ Fun = fun([This,Item]) ->
+ #wx_ref{type=wxListItemAttr,ref=ThisRef} = F(This,Item),
+ <<ThisRef:32/?UI>>
+ end,
+ [<<7:32/?UI,(wxe_util:get_cbId(Fun)):32/?UI>>|Acc];
+ ({onGetItemColumnImage, F}, Acc) when is_function(F) ->
+ Fun = fun([This,Item, Col]) -> <<(F(This,Item,Col)):32/?I>> end,
+ [<<8:32/?UI,(wxe_util:get_cbId(Fun)):32/?UI>>|Acc];
+ (BadOpt, _) -> erlang:error({badoption, BadOpt}) end,
+ BinOpt = list_to_binary(lists:foldl(MOpts, [<<0:32>>], Options)),
+ wxe_util:construct(?wxListCtrl_new_2, <<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
%% @spec (This::wxListCtrl()) -> bool()
%% @equiv arrange(This, [])
@@ -151,6 +175,7 @@ clearAll(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:cast(?wxListCtrl_ClearAll,
<<ThisRef:32/?UI>>).
+
%% @spec (This::wxListCtrl(), Parent::wxWindow:wxWindow()) -> bool()
%% @equiv create(This,Parent, [])
create(This,Parent)
@@ -158,7 +183,18 @@ create(This,Parent)
create(This,Parent, []).
%% @spec (This::wxListCtrl(), Parent::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {winid, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {winid, integer()} |
+%% {pos, {X::integer(),Y::integer()}} |
+%% {size, {W::integer(),H::integer()}} |
+%% {style, integer()} |
+%% {validator, wx:wx()} |
+%% {onGetItemText, OnGetItemText} |
+%% {onGetItemAttr, OnGetItemAttr} |
+%% {onGetItemColumnImage, OnGetItemColumnImage}
+%%
+%% OnGetItemText = (This, Item, Column) -> wxString()
+%% OnGetItemAttr = (This, Item) -> wxListItemAttr()
+%% OnGetItemColumnImage = (This, Item, Column) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
@@ -227,7 +263,7 @@ findItem(This,Start,Str)
%%<br /> Option = {partial, bool()}
%% </p>
%% <p><c>
-%% findItem(This::wxListCtrl(), Start::integer(), Pt::{X::integer(),Y::integer()}, Direction::integer()) -> integer() </c>
+%% findItem(This::wxListCtrl(), Start::integer(), Pt::{X::integer(), Y::integer()}, Direction::integer()) -> integer() </c>
%% </p>
findItem(#wx_ref{type=ThisT,ref=ThisRef},Start,Str, Options)
when is_integer(Start),is_list(Str),is_list(Options) ->
@@ -329,7 +365,7 @@ getItemFont(#wx_ref{type=ThisT,ref=ThisRef},Item)
wxe_util:call(?wxListCtrl_GetItemFont,
<<ThisRef:32/?UI,Item:32/?UI>>).
-%% @spec (This::wxListCtrl(), Item::integer(), Pos::{X::integer(),Y::integer()}) -> bool()
+%% @spec (This::wxListCtrl(), Item::integer(), Pos::{X::integer(), Y::integer()}) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgetitemposition">external documentation</a>.
getItemPosition(#wx_ref{type=ThisT,ref=ThisRef},Item,{PosX,PosY})
when is_integer(Item),is_integer(PosX),is_integer(PosY) ->
@@ -337,13 +373,13 @@ getItemPosition(#wx_ref{type=ThisT,ref=ThisRef},Item,{PosX,PosY})
wxe_util:call(?wxListCtrl_GetItemPosition,
<<ThisRef:32/?UI,Item:32/?UI,PosX:32/?UI,PosY:32/?UI>>).
-%% @spec (This::wxListCtrl(), Item::integer(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> bool()
+%% @spec (This::wxListCtrl(), Item::integer(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> bool()
%% @equiv getItemRect(This,Item,Rect, [])
getItemRect(This,Item,Rect={RectX,RectY,RectW,RectH})
when is_record(This, wx_ref),is_integer(Item),is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
getItemRect(This,Item,Rect, []).
-%% @spec (This::wxListCtrl(), Item::integer(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}, [Option]) -> bool()
+%% @spec (This::wxListCtrl(), Item::integer(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}, [Option]) -> bool()
%% Option = {code, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgetitemrect">external documentation</a>.
getItemRect(#wx_ref{type=ThisT,ref=ThisRef},Item,{RectX,RectY,RectW,RectH}, Options)
@@ -355,7 +391,7 @@ getItemRect(#wx_ref{type=ThisT,ref=ThisRef},Item,{RectX,RectY,RectW,RectH}, Opti
wxe_util:call(?wxListCtrl_GetItemRect,
<<ThisRef:32/?UI,Item:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxListCtrl()) -> {W::integer(),H::integer()}
+%% @spec (This::wxListCtrl()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgetitemspacing">external documentation</a>.
getItemSpacing(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListCtrl),
@@ -426,14 +462,14 @@ getTopItem(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxListCtrl_GetTopItem,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListCtrl()) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
+%% @spec (This::wxListCtrl()) -> {X::integer(), Y::integer(), W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgetviewrect">external documentation</a>.
getViewRect(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_GetViewRect,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListCtrl(), Point::{X::integer(),Y::integer()}) -> {integer(),Flags::integer()}
+%% @spec (This::wxListCtrl(), Point::{X::integer(), Y::integer()}) -> {integer(), Flags::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlhittest">external documentation</a>.
hitTest(#wx_ref{type=ThisT,ref=ThisRef},{PointX,PointY})
when is_integer(PointX),is_integer(PointY) ->
@@ -656,7 +692,7 @@ setItemColumnImage(#wx_ref{type=ThisT,ref=ThisRef},Item,Column,Image)
wxe_util:call(?wxListCtrl_SetItemColumnImage,
<<ThisRef:32/?UI,Item:32/?UI,Column:32/?UI,Image:32/?UI>>).
-%% @spec (This::wxListCtrl(), Item::integer(), Pos::{X::integer(),Y::integer()}) -> bool()
+%% @spec (This::wxListCtrl(), Item::integer(), Pos::{X::integer(), Y::integer()}) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlsetitemposition">external documentation</a>.
setItemPosition(#wx_ref{type=ThisT,ref=ThisRef},Item,{PosX,PosY})
when is_integer(Item),is_integer(PosX),is_integer(PosY) ->
@@ -726,12 +762,12 @@ setWindowStyleFlag(#wx_ref{type=ThisT,ref=ThisRef},Style)
%% @spec (This::wxListCtrl(), SortCallBack::function()) -> boolean()
%% @doc Sort the items in the list control<br />
-%% <pre>SortCalBack(Item1,Item2) -> integer()</pre>
+%% <pre>SortCallBack(Item1,Item2) -> integer()</pre>
%% <br /> SortCallBack receives the client data associated with two items
%% to compare, and should return 0 if the items are equal, a negative
%% value if the first item is less than the second one and a positive
%% value if the first item is greater than the second one.
-%% <br /> NOTE: The callback may not call other processes.
+%% <br /> NOTE: The callback may not call other (wx) processes.
sortItems(#wx_ref{type=ThisT,ref=ThisRef}, SortCallBack)
when is_function(SortCallBack, 2) ->
?CLASS(ThisT,wxListCtrl),
diff --git a/lib/wx/src/gen/wxListEvent.erl b/lib/wx/src/gen/wxListEvent.erl
index 74f9e6095c..f7d8658acc 100644
--- a/lib/wx/src/gen/wxListEvent.erl
+++ b/lib/wx/src/gen/wxListEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -83,7 +83,7 @@ getColumn(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxListEvent_GetColumn,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListEvent()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxListEvent()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistevent.html#wxlisteventgetpoint">external documentation</a>.
getPoint(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListEvent),
diff --git a/lib/wx/src/gen/wxListItemAttr.erl b/lib/wx/src/gen/wxListItemAttr.erl
new file mode 100644
index 0000000000..1a43c71854
--- /dev/null
+++ b/lib/wx/src/gen/wxListItemAttr.erl
@@ -0,0 +1,122 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%% This file is generated DO NOT EDIT
+
+%% @doc See external documentation: <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitemattr.html">wxListItemAttr</a>.
+%% @type wxListItemAttr(). 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(wxListItemAttr).
+-include("wxe.hrl").
+-export([destroy/1,getBackgroundColour/1,getFont/1,getTextColour/1,hasBackgroundColour/1,
+ hasFont/1,hasTextColour/1,new/0,new/3,setBackgroundColour/2,setFont/2,
+ setTextColour/2]).
+
+%% inherited exports
+-export([parent_class/1]).
+
+%% @hidden
+parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+
+%% @spec () -> wxListItemAttr()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitemattr.html#wxlistitemattrwxlistitemattr">external documentation</a>.
+new() ->
+ wxe_util:construct(?wxListItemAttr_new_0,
+ <<>>).
+
+%% @spec (ColText::wx:colour(), ColBack::wx:colour(), Font::wxFont:wxFont()) -> wxListItemAttr()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitemattr.html#wxlistitemattrwxlistitemattr">external documentation</a>.
+new(ColText,ColBack,#wx_ref{type=FontT,ref=FontRef})
+ when tuple_size(ColText) =:= 3; tuple_size(ColText) =:= 4,tuple_size(ColBack) =:= 3; tuple_size(ColBack) =:= 4 ->
+ ?CLASS(FontT,wxFont),
+ wxe_util:construct(?wxListItemAttr_new_3,
+ <<(wxe_util:colour_bin(ColText)):16/binary,(wxe_util:colour_bin(ColBack)):16/binary,FontRef:32/?UI>>).
+
+%% @spec (This::wxListItemAttr()) -> wx:colour()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitemattr.html#wxlistitemattrgetbackgroundcolour">external documentation</a>.
+getBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
+ ?CLASS(ThisT,wxListItemAttr),
+ wxe_util:call(?wxListItemAttr_GetBackgroundColour,
+ <<ThisRef:32/?UI>>).
+
+%% @spec (This::wxListItemAttr()) -> wxFont:wxFont()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitemattr.html#wxlistitemattrgetfont">external documentation</a>.
+getFont(#wx_ref{type=ThisT,ref=ThisRef}) ->
+ ?CLASS(ThisT,wxListItemAttr),
+ wxe_util:call(?wxListItemAttr_GetFont,
+ <<ThisRef:32/?UI>>).
+
+%% @spec (This::wxListItemAttr()) -> wx:colour()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitemattr.html#wxlistitemattrgettextcolour">external documentation</a>.
+getTextColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
+ ?CLASS(ThisT,wxListItemAttr),
+ wxe_util:call(?wxListItemAttr_GetTextColour,
+ <<ThisRef:32/?UI>>).
+
+%% @spec (This::wxListItemAttr()) -> bool()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitemattr.html#wxlistitemattrhasbackgroundcolour">external documentation</a>.
+hasBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
+ ?CLASS(ThisT,wxListItemAttr),
+ wxe_util:call(?wxListItemAttr_HasBackgroundColour,
+ <<ThisRef:32/?UI>>).
+
+%% @spec (This::wxListItemAttr()) -> bool()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitemattr.html#wxlistitemattrhasfont">external documentation</a>.
+hasFont(#wx_ref{type=ThisT,ref=ThisRef}) ->
+ ?CLASS(ThisT,wxListItemAttr),
+ wxe_util:call(?wxListItemAttr_HasFont,
+ <<ThisRef:32/?UI>>).
+
+%% @spec (This::wxListItemAttr()) -> bool()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitemattr.html#wxlistitemattrhastextcolour">external documentation</a>.
+hasTextColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
+ ?CLASS(ThisT,wxListItemAttr),
+ wxe_util:call(?wxListItemAttr_HasTextColour,
+ <<ThisRef:32/?UI>>).
+
+%% @spec (This::wxListItemAttr(), ColBack::wx:colour()) -> ok
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitemattr.html#wxlistitemattrsetbackgroundcolour">external documentation</a>.
+setBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef},ColBack)
+ when tuple_size(ColBack) =:= 3; tuple_size(ColBack) =:= 4 ->
+ ?CLASS(ThisT,wxListItemAttr),
+ wxe_util:cast(?wxListItemAttr_SetBackgroundColour,
+ <<ThisRef:32/?UI,(wxe_util:colour_bin(ColBack)):16/binary>>).
+
+%% @spec (This::wxListItemAttr(), Font::wxFont:wxFont()) -> ok
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitemattr.html#wxlistitemattrsetfont">external documentation</a>.
+setFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef}) ->
+ ?CLASS(ThisT,wxListItemAttr),
+ ?CLASS(FontT,wxFont),
+ wxe_util:cast(?wxListItemAttr_SetFont,
+ <<ThisRef:32/?UI,FontRef:32/?UI>>).
+
+%% @spec (This::wxListItemAttr(), ColText::wx:colour()) -> ok
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitemattr.html#wxlistitemattrsettextcolour">external documentation</a>.
+setTextColour(#wx_ref{type=ThisT,ref=ThisRef},ColText)
+ when tuple_size(ColText) =:= 3; tuple_size(ColText) =:= 4 ->
+ ?CLASS(ThisT,wxListItemAttr),
+ wxe_util:cast(?wxListItemAttr_SetTextColour,
+ <<ThisRef:32/?UI,(wxe_util:colour_bin(ColText)):16/binary>>).
+
+%% @spec (This::wxListItemAttr()) -> ok
+%% @doc Destroys this object, do not use object again
+destroy(Obj=#wx_ref{type=Type}) ->
+ ?CLASS(Type,wxListItemAttr),
+ wxe_util:destroy(?wxListItemAttr_destroy,Obj),
+ ok.
diff --git a/lib/wx/src/gen/wxListbook.erl b/lib/wx/src/gen/wxListbook.erl
index b1f0e3d9a4..c204dc87a1 100644
--- a/lib/wx/src/gen/wxListbook.erl
+++ b/lib/wx/src/gen/wxListbook.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -93,7 +93,7 @@ new(Parent,Id)
new(Parent,Id, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxListbook()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbookwxlistbook">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
@@ -160,7 +160,7 @@ create(This,Parent,Id)
create(This,Parent,Id, []).
%% @spec (This::wxListbook(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbookcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
@@ -249,7 +249,7 @@ getSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxListbook_GetSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListbook(), Pt::{X::integer(),Y::integer()}) -> {integer(),Flags::integer()}
+%% @spec (This::wxListbook(), Pt::{X::integer(), Y::integer()}) -> {integer(), Flags::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbookhittest">external documentation</a>.
hitTest(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
@@ -286,7 +286,7 @@ setImageList(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ImageListT,ref=ImageLi
wxe_util:cast(?wxListbook_SetImageList,
<<ThisRef:32/?UI,ImageListRef:32/?UI>>).
-%% @spec (This::wxListbook(), Size::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxListbook(), Size::{W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbooksetpagesize">external documentation</a>.
setPageSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
diff --git a/lib/wx/src/gen/wxMDIChildFrame.erl b/lib/wx/src/gen/wxMDIChildFrame.erl
index 34edac4213..d3e1edda55 100644
--- a/lib/wx/src/gen/wxMDIChildFrame.erl
+++ b/lib/wx/src/gen/wxMDIChildFrame.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -100,7 +100,7 @@ new(Parent,Id,Title)
new(Parent,Id,Title, []).
%% @spec (Parent::wxMDIParentFrame:wxMDIParentFrame(), Id::integer(), Title::string(), [Option]) -> wxMDIChildFrame()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmdichildframe.html#wxmdichildframewxmdichildframe">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Title, Options)
when is_integer(Id),is_list(Title),is_list(Options) ->
@@ -128,7 +128,7 @@ create(This,Parent,Id,Title)
create(This,Parent,Id,Title, []).
%% @spec (This::wxMDIChildFrame(), Parent::wxMDIParentFrame:wxMDIParentFrame(), Id::integer(), Title::string(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmdichildframe.html#wxmdichildframecreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Title, Options)
when is_integer(Id),is_list(Title),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxMDIParentFrame.erl b/lib/wx/src/gen/wxMDIParentFrame.erl
index db47e7ac74..7f8a305876 100644
--- a/lib/wx/src/gen/wxMDIParentFrame.erl
+++ b/lib/wx/src/gen/wxMDIParentFrame.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -102,7 +102,7 @@ new(Parent,Id,Title)
new(Parent,Id,Title, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), [Option]) -> wxMDIParentFrame()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmdiparentframe.html#wxmdiparentframewxmdiparentframe">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Title, Options)
when is_integer(Id),is_list(Title),is_list(Options) ->
@@ -151,7 +151,7 @@ create(This,Parent,Id,Title)
create(This,Parent,Id,Title, []).
%% @spec (This::wxMDIParentFrame(), Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmdiparentframe.html#wxmdiparentframecreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Title, Options)
when is_integer(Id),is_list(Title),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxMessageDialog.erl b/lib/wx/src/gen/wxMessageDialog.erl
index 916b201d3f..d13bb7cb6e 100644
--- a/lib/wx/src/gen/wxMessageDialog.erl
+++ b/lib/wx/src/gen/wxMessageDialog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -91,7 +91,7 @@ new(Parent,Message)
new(Parent,Message, []).
%% @spec (Parent::wxWindow:wxWindow(), Message::string(), [Option]) -> wxMessageDialog()
-%% Option = {caption, string()} | {style, integer()} | {pos, {X::integer(),Y::integer()}}
+%% Option = {caption, string()} | {style, integer()} | {pos, {X::integer(), Y::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmessagedialog.html#wxmessagedialogwxmessagedialog">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Message, Options)
when is_list(Message),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxMiniFrame.erl b/lib/wx/src/gen/wxMiniFrame.erl
index b86f1d7cfa..108ebcfb0e 100644
--- a/lib/wx/src/gen/wxMiniFrame.erl
+++ b/lib/wx/src/gen/wxMiniFrame.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -100,7 +100,7 @@ new(Parent,Id,Title)
new(Parent,Id,Title, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), [Option]) -> wxMiniFrame()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxminiframe.html#wxminiframewxminiframe">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Title, Options)
when is_integer(Id),is_list(Title),is_list(Options) ->
@@ -121,7 +121,7 @@ create(This,Parent,Id,Title)
create(This,Parent,Id,Title, []).
%% @spec (This::wxMiniFrame(), Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxminiframe.html#wxminiframecreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Title, Options)
when is_integer(Id),is_list(Title),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxMouseEvent.erl b/lib/wx/src/gen/wxMouseEvent.erl
index fed9a33db7..a91d2a2e99 100644
--- a/lib/wx/src/gen/wxMouseEvent.erl
+++ b/lib/wx/src/gen/wxMouseEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -151,14 +151,14 @@ getButton(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxMouseEvent_GetButton,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxMouseEvent()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventgetposition">external documentation</a>.
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_GetPosition,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent(), Dc::wxDC:wxDC()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxMouseEvent(), Dc::wxDC:wxDC()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventgetlogicalposition">external documentation</a>.
getLogicalPosition(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=DcT,ref=DcRef}) ->
?CLASS(ThisT,wxMouseEvent),
diff --git a/lib/wx/src/gen/wxMoveEvent.erl b/lib/wx/src/gen/wxMoveEvent.erl
index 80bf59074a..97cf803310 100644
--- a/lib/wx/src/gen/wxMoveEvent.erl
+++ b/lib/wx/src/gen/wxMoveEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -41,7 +41,7 @@
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxMoveEvent()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxMoveEvent()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmoveevent.html#wxmoveeventgetposition">external documentation</a>.
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMoveEvent),
diff --git a/lib/wx/src/gen/wxMultiChoiceDialog.erl b/lib/wx/src/gen/wxMultiChoiceDialog.erl
index e69889a1e0..6fae0c4860 100644
--- a/lib/wx/src/gen/wxMultiChoiceDialog.erl
+++ b/lib/wx/src/gen/wxMultiChoiceDialog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -97,7 +97,7 @@ new(Parent,Message,Caption,Choices)
new(Parent,Message,Caption,Choices, []).
%% @spec (Parent::wxWindow:wxWindow(), Message::string(), Caption::string(), Choices::[[string()]], [Option]) -> wxMultiChoiceDialog()
-%% Option = {style, integer()} | {pos, {X::integer(),Y::integer()}}
+%% Option = {style, integer()} | {pos, {X::integer(), Y::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmultichoicedialog.html#wxmultichoicedialogwxmultichoicedialog">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Message,Caption,Choices, Options)
when is_list(Message),is_list(Caption),is_list(Choices),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxNotebook.erl b/lib/wx/src/gen/wxNotebook.erl
index da543d7ac6..b918de5bb4 100644
--- a/lib/wx/src/gen/wxNotebook.erl
+++ b/lib/wx/src/gen/wxNotebook.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -93,7 +93,7 @@ new(Parent,Winid)
new(Parent,Winid, []).
%% @spec (Parent::wxWindow:wxWindow(), Winid::integer(), [Option]) -> wxNotebook()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebookwxnotebook">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Winid, Options)
when is_integer(Winid),is_list(Options) ->
@@ -160,7 +160,7 @@ create(This,Parent,Id)
create(This,Parent,Id, []).
%% @spec (This::wxNotebook(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebookcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
@@ -263,7 +263,7 @@ getThemeBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxNotebook_GetThemeBackgroundColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxNotebook(), Pt::{X::integer(),Y::integer()}) -> {integer(),Flags::integer()}
+%% @spec (This::wxNotebook(), Pt::{X::integer(), Y::integer()}) -> {integer(), Flags::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebookhittest">external documentation</a>.
hitTest(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
@@ -300,7 +300,7 @@ setImageList(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ImageListT,ref=ImageLi
wxe_util:cast(?wxNotebook_SetImageList,
<<ThisRef:32/?UI,ImageListRef:32/?UI>>).
-%% @spec (This::wxNotebook(), Padding::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxNotebook(), Padding::{W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebooksetpadding">external documentation</a>.
setPadding(#wx_ref{type=ThisT,ref=ThisRef},{PaddingW,PaddingH})
when is_integer(PaddingW),is_integer(PaddingH) ->
@@ -308,7 +308,7 @@ setPadding(#wx_ref{type=ThisT,ref=ThisRef},{PaddingW,PaddingH})
wxe_util:cast(?wxNotebook_SetPadding,
<<ThisRef:32/?UI,PaddingW:32/?UI,PaddingH:32/?UI>>).
-%% @spec (This::wxNotebook(), Size::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxNotebook(), Size::{W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebooksetpagesize">external documentation</a>.
setPageSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
diff --git a/lib/wx/src/gen/wxPageSetupDialogData.erl b/lib/wx/src/gen/wxPageSetupDialogData.erl
index 672ec7c083..00b4ca2a36 100644
--- a/lib/wx/src/gen/wxPageSetupDialogData.erl
+++ b/lib/wx/src/gen/wxPageSetupDialogData.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -146,28 +146,28 @@ getDefaultInfo(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxPageSetupDialogData_GetDefaultInfo,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxPageSetupDialogData()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatagetmargintopleft">external documentation</a>.
getMarginTopLeft(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:call(?wxPageSetupDialogData_GetMarginTopLeft,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxPageSetupDialogData()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatagetmarginbottomright">external documentation</a>.
getMarginBottomRight(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:call(?wxPageSetupDialogData_GetMarginBottomRight,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxPageSetupDialogData()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatagetminmargintopleft">external documentation</a>.
getMinMarginTopLeft(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:call(?wxPageSetupDialogData_GetMinMarginTopLeft,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxPageSetupDialogData()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatagetminmarginbottomright">external documentation</a>.
getMinMarginBottomRight(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPageSetupDialogData),
@@ -181,7 +181,7 @@ getPaperId(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxPageSetupDialogData_GetPaperId,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData()) -> {W::integer(),H::integer()}
+%% @spec (This::wxPageSetupDialogData()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatagetpapersize">external documentation</a>.
getPaperSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPageSetupDialogData),
@@ -218,7 +218,7 @@ setDefaultMinMargins(#wx_ref{type=ThisT,ref=ThisRef},Flag)
wxe_util:cast(?wxPageSetupDialogData_SetDefaultMinMargins,
<<ThisRef:32/?UI,(wxe_util:from_bool(Flag)):32/?UI>>).
-%% @spec (This::wxPageSetupDialogData(), Pt::{X::integer(),Y::integer()}) -> ok
+%% @spec (This::wxPageSetupDialogData(), Pt::{X::integer(), Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatasetmargintopleft">external documentation</a>.
setMarginTopLeft(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
@@ -226,7 +226,7 @@ setMarginTopLeft(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
wxe_util:cast(?wxPageSetupDialogData_SetMarginTopLeft,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData(), Pt::{X::integer(),Y::integer()}) -> ok
+%% @spec (This::wxPageSetupDialogData(), Pt::{X::integer(), Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatasetmarginbottomright">external documentation</a>.
setMarginBottomRight(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
@@ -234,7 +234,7 @@ setMarginBottomRight(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
wxe_util:cast(?wxPageSetupDialogData_SetMarginBottomRight,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData(), Pt::{X::integer(),Y::integer()}) -> ok
+%% @spec (This::wxPageSetupDialogData(), Pt::{X::integer(), Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatasetminmargintopleft">external documentation</a>.
setMinMarginTopLeft(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
@@ -242,7 +242,7 @@ setMinMarginTopLeft(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
wxe_util:cast(?wxPageSetupDialogData_SetMinMarginTopLeft,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData(), Pt::{X::integer(),Y::integer()}) -> ok
+%% @spec (This::wxPageSetupDialogData(), Pt::{X::integer(), Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatasetminmarginbottomright">external documentation</a>.
setMinMarginBottomRight(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
@@ -265,7 +265,7 @@ setPaperId(#wx_ref{type=ThisT,ref=ThisRef},Id)
%% setPaperSize(This::wxPageSetupDialogData(), Id::integer()) -> ok </c>
%% </p>
%% <p><c>
-%% setPaperSize(This::wxPageSetupDialogData(), Sz::{W::integer(),H::integer()}) -> ok </c>
+%% setPaperSize(This::wxPageSetupDialogData(), Sz::{W::integer(), H::integer()}) -> ok </c>
%% </p>
setPaperSize(#wx_ref{type=ThisT,ref=ThisRef},Id)
when is_integer(Id) ->
diff --git a/lib/wx/src/gen/wxPalette.erl b/lib/wx/src/gen/wxPalette.erl
index ee1fd0016d..3d8e811988 100644
--- a/lib/wx/src/gen/wxPalette.erl
+++ b/lib/wx/src/gen/wxPalette.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -75,7 +75,7 @@ getPixel(#wx_ref{type=ThisT,ref=ThisRef},Red,Green,Blue)
wxe_util:call(?wxPalette_GetPixel,
<<ThisRef:32/?UI,Red:32/?UI,Green:32/?UI,Blue:32/?UI>>).
-%% @spec (This::wxPalette(), Pixel::integer()) -> {bool(),Red::integer(),Green::integer(),Blue::integer()}
+%% @spec (This::wxPalette(), Pixel::integer()) -> {bool(), Red::integer(), Green::integer(), Blue::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpalette.html#wxpalettegetrgb">external documentation</a>.
getRGB(#wx_ref{type=ThisT,ref=ThisRef},Pixel)
when is_integer(Pixel) ->
diff --git a/lib/wx/src/gen/wxPanel.erl b/lib/wx/src/gen/wxPanel.erl
index 55eaa9f404..59fba03102 100644
--- a/lib/wx/src/gen/wxPanel.erl
+++ b/lib/wx/src/gen/wxPanel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -86,7 +86,7 @@ new(Parent)
new(Parent, []).
%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxPanel()
-%% Option = {winid, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {winid, integer()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpanel.html#wxpanelwxpanel">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
diff --git a/lib/wx/src/gen/wxPasswordEntryDialog.erl b/lib/wx/src/gen/wxPasswordEntryDialog.erl
index f79734ab46..07a0bcef56 100644
--- a/lib/wx/src/gen/wxPasswordEntryDialog.erl
+++ b/lib/wx/src/gen/wxPasswordEntryDialog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -94,7 +94,7 @@ new(Parent,Message)
new(Parent,Message, []).
%% @spec (Parent::wxWindow:wxWindow(), Message::string(), [Option]) -> wxPasswordEntryDialog()
-%% Option = {caption, string()} | {value, string()} | {style, integer()} | {pos, {X::integer(),Y::integer()}}
+%% Option = {caption, string()} | {value, string()} | {style, integer()} | {pos, {X::integer(), Y::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpasswordentrydialog.html#wxpasswordentrydialogwxpasswordentrydialog">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Message, Options)
when is_list(Message),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxPreviewControlBar.erl b/lib/wx/src/gen/wxPreviewControlBar.erl
index 78d46d1b95..e85af625e2 100644
--- a/lib/wx/src/gen/wxPreviewControlBar.erl
+++ b/lib/wx/src/gen/wxPreviewControlBar.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -83,7 +83,7 @@ new(Preview,Buttons,Parent)
new(Preview,Buttons,Parent, []).
%% @spec (Preview::wxPrintPreview:wxPrintPreview(), Buttons::integer(), Parent::wxWindow:wxWindow(), [Option]) -> wxPreviewControlBar()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpreviewcontrolbar.html#wxpreviewcontrolbarwxpreviewcontrolbar">external documentation</a>.
new(#wx_ref{type=PreviewT,ref=PreviewRef},Buttons,#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_integer(Buttons),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxPreviewFrame.erl b/lib/wx/src/gen/wxPreviewFrame.erl
index 91a32e9889..da43f86030 100644
--- a/lib/wx/src/gen/wxPreviewFrame.erl
+++ b/lib/wx/src/gen/wxPreviewFrame.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -95,7 +95,7 @@ new(Preview,Parent)
new(Preview,Parent, []).
%% @spec (Preview::wxPrintPreview:wxPrintPreview(), Parent::wxWindow:wxWindow(), [Option]) -> wxPreviewFrame()
-%% Option = {title, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {title, string()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpreviewframe.html#wxpreviewframewxpreviewframe">external documentation</a>.
new(#wx_ref{type=PreviewT,ref=PreviewRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
diff --git a/lib/wx/src/gen/wxPrintout.erl b/lib/wx/src/gen/wxPrintout.erl
index b5b93921e6..a34c030275 100644
--- a/lib/wx/src/gen/wxPrintout.erl
+++ b/lib/wx/src/gen/wxPrintout.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -125,35 +125,35 @@ getDC(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxPrintout_GetDC,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintout()) -> {W::integer(),H::integer()}
+%% @spec (This::wxPrintout()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutgetpagesizemm">external documentation</a>.
getPageSizeMM(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintout),
wxe_util:call(?wxPrintout_GetPageSizeMM,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintout()) -> {W::integer(),H::integer()}
+%% @spec (This::wxPrintout()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutgetpagesizepixels">external documentation</a>.
getPageSizePixels(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintout),
wxe_util:call(?wxPrintout_GetPageSizePixels,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintout()) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
+%% @spec (This::wxPrintout()) -> {X::integer(), Y::integer(), W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutgetpaperrectpixels">external documentation</a>.
getPaperRectPixels(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintout),
wxe_util:call(?wxPrintout_GetPaperRectPixels,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintout()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxPrintout()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutgetppiprinter">external documentation</a>.
getPPIPrinter(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintout),
wxe_util:call(?wxPrintout_GetPPIPrinter,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintout()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxPrintout()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutgetppiscreen">external documentation</a>.
getPPIScreen(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintout),
@@ -174,7 +174,7 @@ isPreview(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxPrintout_IsPreview,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintout(), ImageSize::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxPrintout(), ImageSize::{W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutfitthissizetopaper">external documentation</a>.
fitThisSizeToPaper(#wx_ref{type=ThisT,ref=ThisRef},{ImageSizeW,ImageSizeH})
when is_integer(ImageSizeW),is_integer(ImageSizeH) ->
@@ -182,7 +182,7 @@ fitThisSizeToPaper(#wx_ref{type=ThisT,ref=ThisRef},{ImageSizeW,ImageSizeH})
wxe_util:cast(?wxPrintout_FitThisSizeToPaper,
<<ThisRef:32/?UI,ImageSizeW:32/?UI,ImageSizeH:32/?UI>>).
-%% @spec (This::wxPrintout(), ImageSize::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxPrintout(), ImageSize::{W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutfitthissizetopage">external documentation</a>.
fitThisSizeToPage(#wx_ref{type=ThisT,ref=ThisRef},{ImageSizeW,ImageSizeH})
when is_integer(ImageSizeW),is_integer(ImageSizeH) ->
@@ -190,7 +190,7 @@ fitThisSizeToPage(#wx_ref{type=ThisT,ref=ThisRef},{ImageSizeW,ImageSizeH})
wxe_util:cast(?wxPrintout_FitThisSizeToPage,
<<ThisRef:32/?UI,ImageSizeW:32/?UI,ImageSizeH:32/?UI>>).
-%% @spec (This::wxPrintout(), ImageSize::{W::integer(),H::integer()}, PageSetupData::wxPageSetupDialogData:wxPageSetupDialogData()) -> ok
+%% @spec (This::wxPrintout(), ImageSize::{W::integer(), H::integer()}, PageSetupData::wxPageSetupDialogData:wxPageSetupDialogData()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutfitthissizetopagemargins">external documentation</a>.
fitThisSizeToPageMargins(#wx_ref{type=ThisT,ref=ThisRef},{ImageSizeW,ImageSizeH},#wx_ref{type=PageSetupDataT,ref=PageSetupDataRef})
when is_integer(ImageSizeW),is_integer(ImageSizeH) ->
@@ -228,21 +228,21 @@ mapScreenSizeToDevice(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:cast(?wxPrintout_MapScreenSizeToDevice,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintout()) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
+%% @spec (This::wxPrintout()) -> {X::integer(), Y::integer(), W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutgetlogicalpaperrect">external documentation</a>.
getLogicalPaperRect(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintout),
wxe_util:call(?wxPrintout_GetLogicalPaperRect,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintout()) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
+%% @spec (This::wxPrintout()) -> {X::integer(), Y::integer(), W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutgetlogicalpagerect">external documentation</a>.
getLogicalPageRect(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintout),
wxe_util:call(?wxPrintout_GetLogicalPageRect,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintout(), PageSetupData::wxPageSetupDialogData:wxPageSetupDialogData()) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
+%% @spec (This::wxPrintout(), PageSetupData::wxPageSetupDialogData:wxPageSetupDialogData()) -> {X::integer(), Y::integer(), W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutgetlogicalpagemarginsrect">external documentation</a>.
getLogicalPageMarginsRect(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PageSetupDataT,ref=PageSetupDataRef}) ->
?CLASS(ThisT,wxPrintout),
diff --git a/lib/wx/src/gen/wxRadioBox.erl b/lib/wx/src/gen/wxRadioBox.erl
index 06e8833972..766a691108 100644
--- a/lib/wx/src/gen/wxRadioBox.erl
+++ b/lib/wx/src/gen/wxRadioBox.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -78,13 +78,13 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), Pos::{X::integer(),Y::integer()}, Size::{W::integer(),H::integer()}, Choices::[[string()]]) -> wxRadioBox()
+%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), Pos::{X::integer(), Y::integer()}, Size::{W::integer(), H::integer()}, Choices::[[string()]]) -> wxRadioBox()
%% @equiv new(Parent,Id,Title,Pos,Size,Choices, [])
new(Parent,Id,Title,Pos={PosX,PosY},Size={SizeW,SizeH},Choices)
when is_record(Parent, wx_ref),is_integer(Id),is_list(Title),is_integer(PosX),is_integer(PosY),is_integer(SizeW),is_integer(SizeH),is_list(Choices) ->
new(Parent,Id,Title,Pos,Size,Choices, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), Pos::{X::integer(),Y::integer()}, Size::{W::integer(),H::integer()}, Choices::[[string()]], [Option]) -> wxRadioBox()
+%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), Pos::{X::integer(), Y::integer()}, Size::{W::integer(), H::integer()}, Choices::[[string()]], [Option]) -> wxRadioBox()
%% Option = {majorDim, integer()} | {style, integer()} | {val, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobox.html#wxradioboxwxradiobox">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Title,{PosX,PosY},{SizeW,SizeH},Choices, Options)
@@ -101,13 +101,13 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id,Title,{PosX,PosY},{SizeW,SizeH},Choic
wxe_util:construct(?wxRadioBox_new,
<<ParentRef:32/?UI,Id:32/?UI,(byte_size(Title_UC)):32/?UI,(Title_UC)/binary, 0:(((8- ((4+byte_size(Title_UC)) band 16#7)) band 16#7))/unit:8,PosX:32/?UI,PosY:32/?UI,SizeW:32/?UI,SizeH:32/?UI,(length(Choices_UCA)):32/?UI, (<< <<(byte_size(UC_Str)):32/?UI, UC_Str/binary>>|| UC_Str <- Choices_UCA>>)/binary, 0:(((8- ((4 + lists:sum([byte_size(S)+4||S<-Choices_UCA])) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxRadioBox(), Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), Pos::{X::integer(),Y::integer()}, Size::{W::integer(),H::integer()}, Choices::[[string()]]) -> bool()
+%% @spec (This::wxRadioBox(), Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), Pos::{X::integer(), Y::integer()}, Size::{W::integer(), H::integer()}, Choices::[[string()]]) -> bool()
%% @equiv create(This,Parent,Id,Title,Pos,Size,Choices, [])
create(This,Parent,Id,Title,Pos={PosX,PosY},Size={SizeW,SizeH},Choices)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id),is_list(Title),is_integer(PosX),is_integer(PosY),is_integer(SizeW),is_integer(SizeH),is_list(Choices) ->
create(This,Parent,Id,Title,Pos,Size,Choices, []).
-%% @spec (This::wxRadioBox(), Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), Pos::{X::integer(),Y::integer()}, Size::{W::integer(),H::integer()}, Choices::[[string()]], [Option]) -> bool()
+%% @spec (This::wxRadioBox(), Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), Pos::{X::integer(), Y::integer()}, Size::{W::integer(), H::integer()}, Choices::[[string()]], [Option]) -> bool()
%% Option = {majorDim, integer()} | {style, integer()} | {val, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobox.html#wxradioboxcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Title,{PosX,PosY},{SizeW,SizeH},Choices, Options)
@@ -251,7 +251,7 @@ getItemToolTip(#wx_ref{type=ThisT,ref=ThisRef},Item)
wxe_util:call(?wxRadioBox_GetItemToolTip,
<<ThisRef:32/?UI,Item:32/?UI>>).
-%% @spec (This::wxRadioBox(), Pt::{X::integer(),Y::integer()}) -> integer()
+%% @spec (This::wxRadioBox(), Pt::{X::integer(), Y::integer()}) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobox.html#wxradioboxgetitemfrompoint">external documentation</a>.
getItemFromPoint(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
diff --git a/lib/wx/src/gen/wxRadioButton.erl b/lib/wx/src/gen/wxRadioButton.erl
index c2c5a00be6..c4665837b5 100644
--- a/lib/wx/src/gen/wxRadioButton.erl
+++ b/lib/wx/src/gen/wxRadioButton.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -88,7 +88,7 @@ new(Parent,Id,Label)
new(Parent,Id,Label, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Label::string(), [Option]) -> wxRadioButton()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobutton.html#wxradiobuttonwxradiobutton">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Label, Options)
when is_integer(Id),is_list(Label),is_list(Options) ->
@@ -110,7 +110,7 @@ create(This,Parent,Id,Label)
create(This,Parent,Id,Label, []).
%% @spec (This::wxRadioButton(), Parent::wxWindow:wxWindow(), Id::integer(), Label::string(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobutton.html#wxradiobuttoncreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Label, Options)
when is_integer(Id),is_list(Label),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxRegion.erl b/lib/wx/src/gen/wxRegion.erl
index 0ceba1d203..9107a4d6b1 100644
--- a/lib/wx/src/gen/wxRegion.erl
+++ b/lib/wx/src/gen/wxRegion.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -48,7 +48,7 @@ new() ->
%% new(Bmp::wxBitmap:wxBitmap()) -> wxRegion() </c>
%% </p>
%% <p><c>
-%% new(Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> wxRegion() </c>
+%% new(Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> wxRegion() </c>
%% </p>
new(#wx_ref{type=BmpT,ref=BmpRef}) ->
?CLASS(BmpT,wxBitmap),
@@ -59,7 +59,7 @@ new({RectX,RectY,RectW,RectH})
wxe_util:construct(?wxRegion_new_1_1,
<<RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI>>).
-%% @spec (TopLeft::{X::integer(),Y::integer()}, BottomRight::{X::integer(),Y::integer()}) -> wxRegion()
+%% @spec (TopLeft::{X::integer(), Y::integer()}, BottomRight::{X::integer(), Y::integer()}) -> wxRegion()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregionwxregion">external documentation</a>.
new({TopLeftX,TopLeftY},{BottomRightX,BottomRightY})
when is_integer(TopLeftX),is_integer(TopLeftY),is_integer(BottomRightX),is_integer(BottomRightY) ->
@@ -84,12 +84,12 @@ clear(#wx_ref{type=ThisT,ref=ThisRef}) ->
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregioncontains">external documentation</a>.
%% <br /> Alternatives:
%% <p><c>
-%% contains(This::wxRegion(), Pt::{X::integer(),Y::integer()}) -> WxRegionContain </c>
+%% contains(This::wxRegion(), Pt::{X::integer(), Y::integer()}) -> WxRegionContain </c>
%%<br /> WxRegionContain = integer()
%%<br /> WxRegionContain is one of ?wxOutRegion | ?wxPartRegion | ?wxInRegion
%% </p>
%% <p><c>
-%% contains(This::wxRegion(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> WxRegionContain </c>
+%% contains(This::wxRegion(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> WxRegionContain </c>
%%<br /> WxRegionContain = integer()
%%<br /> WxRegionContain is one of ?wxOutRegion | ?wxPartRegion | ?wxInRegion
%% </p>
@@ -131,7 +131,7 @@ convertToBitmap(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxRegion_ConvertToBitmap,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxRegion()) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
+%% @spec (This::wxRegion()) -> {X::integer(), Y::integer(), W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregiongetbox">external documentation</a>.
getBox(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxRegion),
@@ -145,7 +145,7 @@ getBox(#wx_ref{type=ThisT,ref=ThisRef}) ->
%% intersect(This::wxRegion(), Region::wxRegion()) -> bool() </c>
%% </p>
%% <p><c>
-%% intersect(This::wxRegion(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> bool() </c>
+%% intersect(This::wxRegion(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> bool() </c>
%% </p>
intersect(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=RegionT,ref=RegionRef}) ->
?CLASS(ThisT,wxRegion),
@@ -180,7 +180,7 @@ isEmpty(#wx_ref{type=ThisT,ref=ThisRef}) ->
%% subtract(This::wxRegion(), Region::wxRegion()) -> bool() </c>
%% </p>
%% <p><c>
-%% subtract(This::wxRegion(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> bool() </c>
+%% subtract(This::wxRegion(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> bool() </c>
%% </p>
subtract(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=RegionT,ref=RegionRef}) ->
?CLASS(ThisT,wxRegion),
@@ -201,7 +201,7 @@ subtract(#wx_ref{type=ThisT,ref=ThisRef},X,Y,W,H)
wxe_util:call(?wxRegion_Subtract_4,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI,W:32/?UI,H:32/?UI>>).
-%% @spec (This::wxRegion(), Pt::{X::integer(),Y::integer()}) -> bool()
+%% @spec (This::wxRegion(), Pt::{X::integer(), Y::integer()}) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregionoffset">external documentation</a>.
offset(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
@@ -224,7 +224,7 @@ offset(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
%% union(This::wxRegion(), Region::wxRegion() | wxBitmap:wxBitmap()) -> bool() </c>
%% </p>
%% <p><c>
-%% union(This::wxRegion(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> bool() </c>
+%% union(This::wxRegion(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> bool() </c>
%% </p>
union(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=RegionT,ref=RegionRef}) ->
?CLASS(ThisT,wxRegion),
@@ -276,7 +276,7 @@ union(#wx_ref{type=ThisT,ref=ThisRef},X,Y,W,H)
%% 'Xor'(This::wxRegion(), Region::wxRegion()) -> bool() </c>
%% </p>
%% <p><c>
-%% 'Xor'(This::wxRegion(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> bool() </c>
+%% 'Xor'(This::wxRegion(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> bool() </c>
%% </p>
'Xor'(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=RegionT,ref=RegionRef}) ->
?CLASS(ThisT,wxRegion),
diff --git a/lib/wx/src/gen/wxSashEvent.erl b/lib/wx/src/gen/wxSashEvent.erl
index 480e241807..f9c58a04b1 100644
--- a/lib/wx/src/gen/wxSashEvent.erl
+++ b/lib/wx/src/gen/wxSashEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -54,7 +54,7 @@ getEdge(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxSashEvent_GetEdge,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSashEvent()) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
+%% @spec (This::wxSashEvent()) -> {X::integer(), Y::integer(), W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashevent.html#wxsasheventgetdragrect">external documentation</a>.
getDragRect(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSashEvent),
diff --git a/lib/wx/src/gen/wxSashLayoutWindow.erl b/lib/wx/src/gen/wxSashLayoutWindow.erl
index 9bc5a185ba..eb8eb38011 100644
--- a/lib/wx/src/gen/wxSashLayoutWindow.erl
+++ b/lib/wx/src/gen/wxSashLayoutWindow.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -93,7 +93,7 @@ new(Parent)
new(Parent, []).
%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxSashLayoutWindow()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {id, integer()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashlayoutwindow.html#wxsashlayoutwindowwxsashlayoutwindow">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
@@ -114,7 +114,7 @@ create(This,Parent)
create(This,Parent, []).
%% @spec (This::wxSashLayoutWindow(), Parent::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {id, integer()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashlayoutwindow.html#wxsashlayoutwindowcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
@@ -157,7 +157,7 @@ setAlignment(#wx_ref{type=ThisT,ref=ThisRef},Align)
wxe_util:cast(?wxSashLayoutWindow_SetAlignment,
<<ThisRef:32/?UI,Align:32/?UI>>).
-%% @spec (This::wxSashLayoutWindow(), Size::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxSashLayoutWindow(), Size::{W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashlayoutwindow.html#wxsashlayoutwindowsetdefaultsize">external documentation</a>.
setDefaultSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
diff --git a/lib/wx/src/gen/wxSashWindow.erl b/lib/wx/src/gen/wxSashWindow.erl
index 49fb82f828..698cfb8fb6 100644
--- a/lib/wx/src/gen/wxSashWindow.erl
+++ b/lib/wx/src/gen/wxSashWindow.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -88,7 +88,7 @@ new(Parent)
new(Parent, []).
%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxSashWindow()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {id, integer()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashwindow.html#wxsashwindowwxsashwindow">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
diff --git a/lib/wx/src/gen/wxScrollBar.erl b/lib/wx/src/gen/wxScrollBar.erl
index 41ca8d867f..5c7890009f 100644
--- a/lib/wx/src/gen/wxScrollBar.erl
+++ b/lib/wx/src/gen/wxScrollBar.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -89,7 +89,7 @@ new(Parent,Id)
new(Parent,Id, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxScrollBar()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrollbar.html#wxscrollbarwxscrollbar">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
@@ -110,7 +110,7 @@ create(This,Parent,Id)
create(This,Parent,Id, []).
%% @spec (This::wxScrollBar(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrollbar.html#wxscrollbarcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxScrolledWindow.erl b/lib/wx/src/gen/wxScrolledWindow.erl
index a6f813d1a2..0693a79760 100644
--- a/lib/wx/src/gen/wxScrolledWindow.erl
+++ b/lib/wx/src/gen/wxScrolledWindow.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -91,7 +91,7 @@ new(Parent)
new(Parent, []).
%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxScrolledWindow()
-%% Option = {winid, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {winid, integer()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrolledwindow.html#wxscrolledwindowwxscrolledwindow">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
@@ -105,7 +105,7 @@ new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
wxe_util:construct(?wxScrolledWindow_new_2,
<<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxScrolledWindow(), Pt::{X::integer(),Y::integer()}) -> {X::integer(),Y::integer()}
+%% @spec (This::wxScrolledWindow(), Pt::{X::integer(), Y::integer()}) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrolledwindow.html#wxscrolledwindowcalcscrolledposition">external documentation</a>.
calcScrolledPosition(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
@@ -113,7 +113,7 @@ calcScrolledPosition(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
wxe_util:call(?wxScrolledWindow_CalcScrolledPosition_1,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxScrolledWindow(), X::integer(), Y::integer()) -> {Xx::integer(),Yy::integer()}
+%% @spec (This::wxScrolledWindow(), X::integer(), Y::integer()) -> {Xx::integer(), Yy::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrolledwindow.html#wxscrolledwindowcalcscrolledposition">external documentation</a>.
calcScrolledPosition(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
@@ -121,7 +121,7 @@ calcScrolledPosition(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
wxe_util:call(?wxScrolledWindow_CalcScrolledPosition_4,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxScrolledWindow(), Pt::{X::integer(),Y::integer()}) -> {X::integer(),Y::integer()}
+%% @spec (This::wxScrolledWindow(), Pt::{X::integer(), Y::integer()}) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrolledwindow.html#wxscrolledwindowcalcunscrolledposition">external documentation</a>.
calcUnscrolledPosition(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
@@ -129,7 +129,7 @@ calcUnscrolledPosition(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
wxe_util:call(?wxScrolledWindow_CalcUnscrolledPosition_1,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxScrolledWindow(), X::integer(), Y::integer()) -> {Xx::integer(),Yy::integer()}
+%% @spec (This::wxScrolledWindow(), X::integer(), Y::integer()) -> {Xx::integer(), Yy::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrolledwindow.html#wxscrolledwindowcalcunscrolledposition">external documentation</a>.
calcUnscrolledPosition(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
@@ -145,14 +145,14 @@ enableScrolling(#wx_ref{type=ThisT,ref=ThisRef},X_scrolling,Y_scrolling)
wxe_util:cast(?wxScrolledWindow_EnableScrolling,
<<ThisRef:32/?UI,(wxe_util:from_bool(X_scrolling)):32/?UI,(wxe_util:from_bool(Y_scrolling)):32/?UI>>).
-%% @spec (This::wxScrolledWindow()) -> {PixelsPerUnitX::integer(),PixelsPerUnitY::integer()}
+%% @spec (This::wxScrolledWindow()) -> {PixelsPerUnitX::integer(), PixelsPerUnitY::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrolledwindow.html#wxscrolledwindowgetscrollpixelsperunit">external documentation</a>.
getScrollPixelsPerUnit(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxScrolledWindow),
wxe_util:call(?wxScrolledWindow_GetScrollPixelsPerUnit,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxScrolledWindow()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxScrolledWindow()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrolledwindow.html#wxscrolledwindowgetviewstart">external documentation</a>.
getViewStart(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxScrolledWindow),
diff --git a/lib/wx/src/gen/wxSingleChoiceDialog.erl b/lib/wx/src/gen/wxSingleChoiceDialog.erl
index 16e0c3d8ce..e2b835917e 100644
--- a/lib/wx/src/gen/wxSingleChoiceDialog.erl
+++ b/lib/wx/src/gen/wxSingleChoiceDialog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -97,7 +97,7 @@ new(Parent,Message,Caption,Choices)
new(Parent,Message,Caption,Choices, []).
%% @spec (Parent::wxWindow:wxWindow(), Message::string(), Caption::string(), Choices::[[string()]], [Option]) -> wxSingleChoiceDialog()
-%% Option = {style, integer()} | {pos, {X::integer(),Y::integer()}}
+%% Option = {style, integer()} | {pos, {X::integer(), Y::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsinglechoicedialog.html#wxsinglechoicedialogwxsinglechoicedialog">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Message,Caption,Choices, Options)
when is_list(Message),is_list(Caption),is_list(Choices),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxSizeEvent.erl b/lib/wx/src/gen/wxSizeEvent.erl
index 9e7619ebbd..0898f4aed9 100644
--- a/lib/wx/src/gen/wxSizeEvent.erl
+++ b/lib/wx/src/gen/wxSizeEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -41,7 +41,7 @@
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxSizeEvent()) -> {W::integer(),H::integer()}
+%% @spec (This::wxSizeEvent()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeevent.html#wxsizeeventgetsize">external documentation</a>.
getSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizeEvent),
diff --git a/lib/wx/src/gen/wxSizer.erl b/lib/wx/src/gen/wxSizer.erl
index 716b2224b5..0f1a92f379 100644
--- a/lib/wx/src/gen/wxSizer.erl
+++ b/lib/wx/src/gen/wxSizer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -132,7 +132,7 @@ addStretchSpacer(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxSizer_AddStretchSpacer,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxSizer()) -> {W::integer(),H::integer()}
+%% @spec (This::wxSizer()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizercalcmin">external documentation</a>.
calcMin(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizer),
@@ -182,7 +182,7 @@ detach(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef}) ->
wxe_util:call(WindowOP,
<<ThisRef:32/?UI,WindowRef:32/?UI>>).
-%% @spec (This::wxSizer(), Window::wxWindow:wxWindow()) -> {W::integer(),H::integer()}
+%% @spec (This::wxSizer(), Window::wxWindow:wxWindow()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizerfit">external documentation</a>.
fit(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef}) ->
?CLASS(ThisT,wxSizer),
@@ -241,21 +241,21 @@ getItem(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef}, Opt
wxe_util:call(WindowOP,
<<ThisRef:32/?UI,WindowRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxSizer()) -> {W::integer(),H::integer()}
+%% @spec (This::wxSizer()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizergetsize">external documentation</a>.
getSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizer),
wxe_util:call(?wxSizer_GetSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizer()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxSizer()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizergetposition">external documentation</a>.
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizer),
wxe_util:call(?wxSizer_GetPosition,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizer()) -> {W::integer(),H::integer()}
+%% @spec (This::wxSizer()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizergetminsize">external documentation</a>.
getMinSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizer),
@@ -298,18 +298,8 @@ hide(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef}, Option
wxe_util:call(WindowOP,
<<ThisRef:32/?UI,WindowRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxSizer(),Index::integer(),X::term()) -> wxSizerItem:wxSizerItem()
+%% @spec (This::wxSizer(), Index::integer(), Item::wxSizerItem:wxSizerItem()) -> wxSizerItem:wxSizerItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizerinsert">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% insert(This::wxSizer(), Index::integer(), Window::wxWindow:wxWindow() | wxSizer()) -> insert(This,Index,Window, []) </c></p>
-%% <p><c>
-%% insert(This::wxSizer(), Index::integer(), Item::wxSizerItem:wxSizerItem()) -> wxSizerItem:wxSizerItem() </c>
-%% </p>
-
-insert(This,Index,Window)
- when is_record(This, wx_ref),is_integer(Index),is_record(Window, wx_ref) ->
- insert(This,Index,Window, []);
insert(#wx_ref{type=ThisT,ref=ThisRef},Index,#wx_ref{type=ItemT,ref=ItemRef})
when is_integer(Index) ->
?CLASS(ThisT,wxSizer),
@@ -437,18 +427,8 @@ layout(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:cast(?wxSizer_Layout,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizer(),X::term()) -> wxSizerItem:wxSizerItem()
+%% @spec (This::wxSizer(), Item::wxSizerItem:wxSizerItem()) -> wxSizerItem:wxSizerItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizerprepend">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% prepend(This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer()) -> prepend(This,Window, []) </c></p>
-%% <p><c>
-%% prepend(This::wxSizer(), Item::wxSizerItem:wxSizerItem()) -> wxSizerItem:wxSizerItem() </c>
-%% </p>
-
-prepend(This,Window)
- when is_record(This, wx_ref),is_record(Window, wx_ref) ->
- prepend(This,Window, []);
prepend(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ItemT,ref=ItemRef}) ->
?CLASS(ThisT,wxSizer),
?CLASS(ItemT,wxSizerItem),
@@ -616,7 +596,7 @@ setDimension(#wx_ref{type=ThisT,ref=ThisRef},X,Y,Width,Height)
wxe_util:cast(?wxSizer_SetDimension,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI,Width:32/?UI,Height:32/?UI>>).
-%% @spec (This::wxSizer(), Size::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxSizer(), Size::{W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizersetminsize">external documentation</a>.
setMinSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
@@ -632,14 +612,14 @@ setMinSize(#wx_ref{type=ThisT,ref=ThisRef},Width,Height)
wxe_util:cast(?wxSizer_SetMinSize_2,
<<ThisRef:32/?UI,Width:32/?UI,Height:32/?UI>>).
-%% @spec (This::wxSizer(),X::integer()|term(),Size::{W::integer(),H::integer()}) -> bool()
+%% @spec (This::wxSizer(),X::integer()|term(),Size::{W::integer(), H::integer()}) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizersetitemminsize">external documentation</a>.
%% <br /> Alternatives:
%% <p><c>
-%% setItemMinSize(This::wxSizer(), Index::integer(), Size::{W::integer(),H::integer()}) -> bool() </c>
+%% setItemMinSize(This::wxSizer(), Index::integer(), Size::{W::integer(), H::integer()}) -> bool() </c>
%% </p>
%% <p><c>
-%% setItemMinSize(This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(), Size::{W::integer(),H::integer()}) -> bool() </c>
+%% setItemMinSize(This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(), Size::{W::integer(), H::integer()}) -> bool() </c>
%% </p>
setItemMinSize(#wx_ref{type=ThisT,ref=ThisRef},Index,{SizeW,SizeH})
when is_integer(Index),is_integer(SizeW),is_integer(SizeH) ->
diff --git a/lib/wx/src/gen/wxSizerItem.erl b/lib/wx/src/gen/wxSizerItem.erl
index 1e9f05d53c..41cb86eae2 100644
--- a/lib/wx/src/gen/wxSizerItem.erl
+++ b/lib/wx/src/gen/wxSizerItem.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -89,7 +89,7 @@ new(Width,Height,Proportion,Flag,Border,#wx_ref{type=UserDataT,ref=UserDataRef})
wxe_util:construct(?wxSizerItem_new_6,
<<Width:32/?UI,Height:32/?UI,Proportion:32/?UI,Flag:32/?UI,Border:32/?UI,UserDataRef:32/?UI>>).
-%% @spec (This::wxSizerItem()) -> {W::integer(),H::integer()}
+%% @spec (This::wxSizerItem()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemcalcmin">external documentation</a>.
calcMin(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerItem),
@@ -124,14 +124,14 @@ getFlag(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxSizerItem_GetFlag,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerItem()) -> {W::integer(),H::integer()}
+%% @spec (This::wxSizerItem()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemgetminsize">external documentation</a>.
getMinSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:call(?wxSizerItem_GetMinSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerItem()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxSizerItem()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemgetposition">external documentation</a>.
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerItem),
@@ -152,14 +152,14 @@ getRatio(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxSizerItem_GetRatio,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerItem()) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
+%% @spec (This::wxSizerItem()) -> {X::integer(), Y::integer(), W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemgetrect">external documentation</a>.
getRect(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:call(?wxSizerItem_GetRect,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerItem()) -> {W::integer(),H::integer()}
+%% @spec (This::wxSizerItem()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemgetsize">external documentation</a>.
getSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerItem),
@@ -173,7 +173,7 @@ getSizer(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxSizerItem_GetSizer,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerItem()) -> {W::integer(),H::integer()}
+%% @spec (This::wxSizerItem()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemgetspacer">external documentation</a>.
getSpacer(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerItem),
@@ -230,7 +230,7 @@ setBorder(#wx_ref{type=ThisT,ref=ThisRef},Border)
wxe_util:cast(?wxSizerItem_SetBorder,
<<ThisRef:32/?UI,Border:32/?UI>>).
-%% @spec (This::wxSizerItem(), Pos::{X::integer(),Y::integer()}, Size::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxSizerItem(), Pos::{X::integer(), Y::integer()}, Size::{W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemsetdimension">external documentation</a>.
setDimension(#wx_ref{type=ThisT,ref=ThisRef},{PosX,PosY},{SizeW,SizeH})
when is_integer(PosX),is_integer(PosY),is_integer(SizeW),is_integer(SizeH) ->
@@ -254,7 +254,7 @@ setInitSize(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
wxe_util:cast(?wxSizerItem_SetInitSize,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxSizerItem(), Size::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxSizerItem(), Size::{W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemsetminsize">external documentation</a>.
setMinSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
@@ -285,7 +285,7 @@ setProportion(#wx_ref{type=ThisT,ref=ThisRef},Proportion)
%% setRatio(This::wxSizerItem(), Ratio::float()) -> ok </c>
%% </p>
%% <p><c>
-%% setRatio(This::wxSizerItem(), Size::{W::integer(),H::integer()}) -> ok </c>
+%% setRatio(This::wxSizerItem(), Size::{W::integer(), H::integer()}) -> ok </c>
%% </p>
setRatio(#wx_ref{type=ThisT,ref=ThisRef},Ratio)
when is_float(Ratio) ->
@@ -314,7 +314,7 @@ setSizer(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=SizerT,ref=SizerRef}) ->
wxe_util:cast(?wxSizerItem_SetSizer,
<<ThisRef:32/?UI,SizerRef:32/?UI>>).
-%% @spec (This::wxSizerItem(), Size::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxSizerItem(), Size::{W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemsetspacer">external documentation</a>.
setSpacer(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
diff --git a/lib/wx/src/gen/wxSlider.erl b/lib/wx/src/gen/wxSlider.erl
index c70f127a5b..c7a3d6f5c0 100644
--- a/lib/wx/src/gen/wxSlider.erl
+++ b/lib/wx/src/gen/wxSlider.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -90,7 +90,7 @@ new(Parent,Id,Value,MinValue,MaxValue)
new(Parent,Id,Value,MinValue,MaxValue, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Value::integer(), MinValue::integer(), MaxValue::integer(), [Option]) -> wxSlider()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxslider.html#wxsliderwxslider">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Value,MinValue,MaxValue, Options)
when is_integer(Id),is_integer(Value),is_integer(MinValue),is_integer(MaxValue),is_list(Options) ->
@@ -111,7 +111,7 @@ create(This,Parent,Id,Value,MinValue,MaxValue)
create(This,Parent,Id,Value,MinValue,MaxValue, []).
%% @spec (This::wxSlider(), Parent::wxWindow:wxWindow(), Id::integer(), Value::integer(), MinValue::integer(), MaxValue::integer(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxslider.html#wxslidercreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Value,MinValue,MaxValue, Options)
when is_integer(Id),is_integer(Value),is_integer(MinValue),is_integer(MaxValue),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxSpinButton.erl b/lib/wx/src/gen/wxSpinButton.erl
index 027699e295..e269dbe329 100644
--- a/lib/wx/src/gen/wxSpinButton.erl
+++ b/lib/wx/src/gen/wxSpinButton.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -89,7 +89,7 @@ new(Parent)
new(Parent, []).
%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxSpinButton()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {id, integer()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxspinbutton.html#wxspinbuttonwxspinbutton">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
@@ -110,7 +110,7 @@ create(This,Parent)
create(This,Parent, []).
%% @spec (This::wxSpinButton(), Parent::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {id, integer()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxspinbutton.html#wxspinbuttoncreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
diff --git a/lib/wx/src/gen/wxSpinCtrl.erl b/lib/wx/src/gen/wxSpinCtrl.erl
index 6b77376b40..c6e8ad2238 100644
--- a/lib/wx/src/gen/wxSpinCtrl.erl
+++ b/lib/wx/src/gen/wxSpinCtrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -89,7 +89,7 @@ new(Parent)
new(Parent, []).
%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxSpinCtrl()
-%% Option = {id, integer()} | {value, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {min, integer()} | {max, integer()} | {initial, integer()}
+%% Option = {id, integer()} | {value, string()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {min, integer()} | {max, integer()} | {initial, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxspinctrl.html#wxspinctrlwxspinctrl">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
@@ -114,7 +114,7 @@ create(This,Parent)
create(This,Parent, []).
%% @spec (This::wxSpinCtrl(), Parent::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {id, integer()} | {value, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {min, integer()} | {max, integer()} | {initial, integer()}
+%% Option = {id, integer()} | {value, string()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {min, integer()} | {max, integer()} | {initial, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxspinctrl.html#wxspinctrlcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
diff --git a/lib/wx/src/gen/wxSplashScreen.erl b/lib/wx/src/gen/wxSplashScreen.erl
index 8806d07018..79ef8e413a 100644
--- a/lib/wx/src/gen/wxSplashScreen.erl
+++ b/lib/wx/src/gen/wxSplashScreen.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -100,7 +100,7 @@ new(Bitmap,SplashStyle,Milliseconds,Parent,Id)
new(Bitmap,SplashStyle,Milliseconds,Parent,Id, []).
%% @spec (Bitmap::wxBitmap:wxBitmap(), SplashStyle::integer(), Milliseconds::integer(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxSplashScreen()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplashscreen.html#wxsplashscreenwxsplashscreen">external documentation</a>.
new(#wx_ref{type=BitmapT,ref=BitmapRef},SplashStyle,Milliseconds,#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(SplashStyle),is_integer(Milliseconds),is_integer(Id),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxSplitterWindow.erl b/lib/wx/src/gen/wxSplitterWindow.erl
index 9e27be7475..b17fed3151 100644
--- a/lib/wx/src/gen/wxSplitterWindow.erl
+++ b/lib/wx/src/gen/wxSplitterWindow.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -91,7 +91,7 @@ new(Parent)
new(Parent, []).
%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxSplitterWindow()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {id, integer()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterwindow.html#wxsplitterwindowwxsplitterwindow">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
@@ -112,7 +112,7 @@ create(This,Parent)
create(This,Parent, []).
%% @spec (This::wxSplitterWindow(), Parent::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {id, integer()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterwindow.html#wxsplitterwindowcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
diff --git a/lib/wx/src/gen/wxStaticBitmap.erl b/lib/wx/src/gen/wxStaticBitmap.erl
index 6fbc59236d..31e39b3a6c 100644
--- a/lib/wx/src/gen/wxStaticBitmap.erl
+++ b/lib/wx/src/gen/wxStaticBitmap.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -88,7 +88,7 @@ new(Parent,Id,Label)
new(Parent,Id,Label, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Label::wxBitmap:wxBitmap(), [Option]) -> wxStaticBitmap()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstaticbitmap.html#wxstaticbitmapwxstaticbitmap">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,#wx_ref{type=LabelT,ref=LabelRef}, Options)
when is_integer(Id),is_list(Options) ->
@@ -109,7 +109,7 @@ create(This,Parent,Id,Label)
create(This,Parent,Id,Label, []).
%% @spec (This::wxStaticBitmap(), Parent::wxWindow:wxWindow(), Id::integer(), Label::wxBitmap:wxBitmap(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstaticbitmap.html#wxstaticbitmapcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,#wx_ref{type=LabelT,ref=LabelRef}, Options)
when is_integer(Id),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxStaticBox.erl b/lib/wx/src/gen/wxStaticBox.erl
index ad54184867..ec83ff5fd9 100644
--- a/lib/wx/src/gen/wxStaticBox.erl
+++ b/lib/wx/src/gen/wxStaticBox.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -88,7 +88,7 @@ new(Parent,Id,Label)
new(Parent,Id,Label, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Label::string(), [Option]) -> wxStaticBox()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstaticbox.html#wxstaticboxwxstaticbox">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Label, Options)
when is_integer(Id),is_list(Label),is_list(Options) ->
@@ -109,7 +109,7 @@ create(This,Parent,Id,Label)
create(This,Parent,Id,Label, []).
%% @spec (This::wxStaticBox(), Parent::wxWindow:wxWindow(), Id::integer(), Label::string(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstaticbox.html#wxstaticboxcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Label, Options)
when is_integer(Id),is_list(Label),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxStaticBoxSizer.erl b/lib/wx/src/gen/wxStaticBoxSizer.erl
index 5f346b7a1e..2cf9f64325 100644
--- a/lib/wx/src/gen/wxStaticBoxSizer.erl
+++ b/lib/wx/src/gen/wxStaticBoxSizer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -130,7 +130,7 @@ prepend(This,Width,Height, Options) -> wxSizer:prepend(This,Width,Height, Option
%% @hidden
prepend(This,Width,Height) -> wxSizer:prepend(This,Width,Height).
%% @hidden
-prepend(This,Window) -> wxSizer:prepend(This,Window).
+prepend(This,Item) -> wxSizer:prepend(This,Item).
%% @hidden
layout(This) -> wxSizer:layout(This).
%% @hidden
@@ -146,7 +146,7 @@ insert(This,Index,Width,Height, Options) -> wxSizer:insert(This,Index,Width,Heig
%% @hidden
insert(This,Index,Width,Height) -> wxSizer:insert(This,Index,Width,Height).
%% @hidden
-insert(This,Index,Window) -> wxSizer:insert(This,Index,Window).
+insert(This,Index,Item) -> wxSizer:insert(This,Index,Item).
%% @hidden
hide(This,Window, Options) -> wxSizer:hide(This,Window, Options).
%% @hidden
diff --git a/lib/wx/src/gen/wxStaticLine.erl b/lib/wx/src/gen/wxStaticLine.erl
index e3a1bedbdc..a850065ba0 100644
--- a/lib/wx/src/gen/wxStaticLine.erl
+++ b/lib/wx/src/gen/wxStaticLine.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -89,7 +89,7 @@ new(Parent)
new(Parent, []).
%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxStaticLine()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {id, integer()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstaticline.html#wxstaticlinewxstaticline">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
@@ -110,7 +110,7 @@ create(This,Parent)
create(This,Parent, []).
%% @spec (This::wxStaticLine(), Parent::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {id, integer()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstaticline.html#wxstaticlinecreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
diff --git a/lib/wx/src/gen/wxStaticText.erl b/lib/wx/src/gen/wxStaticText.erl
index 46c73a5998..301999d49a 100644
--- a/lib/wx/src/gen/wxStaticText.erl
+++ b/lib/wx/src/gen/wxStaticText.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -88,7 +88,7 @@ new(Parent,Id,Label)
new(Parent,Id,Label, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Label::string(), [Option]) -> wxStaticText()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstatictext.html#wxstatictextwxstatictext">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Label, Options)
when is_integer(Id),is_list(Label),is_list(Options) ->
@@ -109,7 +109,7 @@ create(This,Parent,Id,Label)
create(This,Parent,Id,Label, []).
%% @spec (This::wxStaticText(), Parent::wxWindow:wxWindow(), Id::integer(), Label::string(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstatictext.html#wxstatictextcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Label, Options)
when is_integer(Id),is_list(Label),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxStatusBar.erl b/lib/wx/src/gen/wxStatusBar.erl
index 52467117d7..6e77761f1d 100644
--- a/lib/wx/src/gen/wxStatusBar.erl
+++ b/lib/wx/src/gen/wxStatusBar.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -121,7 +121,7 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Opti
wxe_util:call(?wxStatusBar_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxStatusBar(), I::integer(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> bool()
+%% @spec (This::wxStatusBar(), I::integer(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstatusbar.html#wxstatusbargetfieldrect">external documentation</a>.
getFieldRect(#wx_ref{type=ThisT,ref=ThisRef},I,{RectX,RectY,RectW,RectH})
when is_integer(I),is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
diff --git a/lib/wx/src/gen/wxStdDialogButtonSizer.erl b/lib/wx/src/gen/wxStdDialogButtonSizer.erl
index b0052ca2e1..3d31907275 100644
--- a/lib/wx/src/gen/wxStdDialogButtonSizer.erl
+++ b/lib/wx/src/gen/wxStdDialogButtonSizer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -139,7 +139,7 @@ prepend(This,Width,Height, Options) -> wxSizer:prepend(This,Width,Height, Option
%% @hidden
prepend(This,Width,Height) -> wxSizer:prepend(This,Width,Height).
%% @hidden
-prepend(This,Window) -> wxSizer:prepend(This,Window).
+prepend(This,Item) -> wxSizer:prepend(This,Item).
%% @hidden
layout(This) -> wxSizer:layout(This).
%% @hidden
@@ -155,7 +155,7 @@ insert(This,Index,Width,Height, Options) -> wxSizer:insert(This,Index,Width,Heig
%% @hidden
insert(This,Index,Width,Height) -> wxSizer:insert(This,Index,Width,Height).
%% @hidden
-insert(This,Index,Window) -> wxSizer:insert(This,Index,Window).
+insert(This,Index,Item) -> wxSizer:insert(This,Index,Item).
%% @hidden
hide(This,Window, Options) -> wxSizer:hide(This,Window, Options).
%% @hidden
diff --git a/lib/wx/src/gen/wxStyledTextCtrl.erl b/lib/wx/src/gen/wxStyledTextCtrl.erl
index 71d1bd0d53..61f0e5afef 100644
--- a/lib/wx/src/gen/wxStyledTextCtrl.erl
+++ b/lib/wx/src/gen/wxStyledTextCtrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -190,7 +190,7 @@ new(Parent)
new(Parent, []).
%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxStyledTextCtrl()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {id, integer()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlwxstyledtextctrl">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
@@ -211,7 +211,7 @@ create(This,Parent)
create(This,Parent, []).
%% @spec (This::wxStyledTextCtrl(), Parent::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {id, integer()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
@@ -385,7 +385,7 @@ setViewWhiteSpace(#wx_ref{type=ThisT,ref=ThisRef},ViewWS)
wxe_util:cast(?wxStyledTextCtrl_SetViewWhiteSpace,
<<ThisRef:32/?UI,ViewWS:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Pt::{X::integer(),Y::integer()}) -> integer()
+%% @spec (This::wxStyledTextCtrl(), Pt::{X::integer(), Y::integer()}) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlpositionfrompoint">external documentation</a>.
positionFromPoint(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
@@ -425,7 +425,7 @@ setAnchor(#wx_ref{type=ThisT,ref=ThisRef},PosAnchor)
wxe_util:cast(?wxStyledTextCtrl_SetAnchor,
<<ThisRef:32/?UI,PosAnchor:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> {string(),LinePos::integer()}
+%% @spec (This::wxStyledTextCtrl()) -> {string(), LinePos::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetcurline">external documentation</a>.
getCurLine(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -1454,7 +1454,7 @@ findText(#wx_ref{type=ThisT,ref=ThisRef},MinPos,MaxPos,Text, Options)
wxe_util:call(?wxStyledTextCtrl_FindText,
<<ThisRef:32/?UI,MinPos:32/?UI,MaxPos:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxStyledTextCtrl(), DoDraw::bool(), StartPos::integer(), EndPos::integer(), Draw::wxDC:wxDC(), Target::wxDC:wxDC(), RenderRect::{X::integer(),Y::integer(),W::integer(),H::integer()}, PageRect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> integer()
+%% @spec (This::wxStyledTextCtrl(), DoDraw::bool(), StartPos::integer(), EndPos::integer(), Draw::wxDC:wxDC(), Target::wxDC:wxDC(), RenderRect::{X::integer(), Y::integer(), W::integer(), H::integer()}, PageRect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlformatrange">external documentation</a>.
formatRange(#wx_ref{type=ThisT,ref=ThisRef},DoDraw,StartPos,EndPos,#wx_ref{type=DrawT,ref=DrawRef},#wx_ref{type=TargetT,ref=TargetRef},{RenderRectX,RenderRectY,RenderRectW,RenderRectH},{PageRectX,PageRectY,PageRectW,PageRectH})
when is_boolean(DoDraw),is_integer(StartPos),is_integer(EndPos),is_integer(RenderRectX),is_integer(RenderRectY),is_integer(RenderRectW),is_integer(RenderRectH),is_integer(PageRectX),is_integer(PageRectY),is_integer(PageRectW),is_integer(PageRectH) ->
@@ -3417,14 +3417,14 @@ setMargins(#wx_ref{type=ThisT,ref=ThisRef},Left,Right)
wxe_util:cast(?wxStyledTextCtrl_SetMargins,
<<ThisRef:32/?UI,Left:32/?UI,Right:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> {StartPos::integer(),EndPos::integer()}
+%% @spec (This::wxStyledTextCtrl()) -> {StartPos::integer(), EndPos::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetselection">external documentation</a>.
getSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Pos::integer()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxStyledTextCtrl(), Pos::integer()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlpointfromposition">external documentation</a>.
pointFromPosition(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
@@ -3562,7 +3562,7 @@ insertTextRaw(#wx_ref{type=ThisT,ref=ThisRef},Pos,Text)
wxe_util:cast(?wxStyledTextCtrl_InsertTextRaw,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> {binary(),LinePos::integer()}
+%% @spec (This::wxStyledTextCtrl()) -> {binary(), LinePos::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetcurlineraw">external documentation</a>.
getCurLineRaw(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
diff --git a/lib/wx/src/gen/wxSystemOptions.erl b/lib/wx/src/gen/wxSystemOptions.erl
new file mode 100644
index 0000000000..d5e504632b
--- /dev/null
+++ b/lib/wx/src/gen/wxSystemOptions.erl
@@ -0,0 +1,87 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%% This file is generated DO NOT EDIT
+
+%% @doc See external documentation: <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsystemoptions.html">wxSystemOptions</a>.
+%% @type wxSystemOptions(). An object reference, The representation is internal
+%% and can be changed without notice. It can't be used for comparsion
+%% stored on disc or distributed for use on other nodes.
+
+-module(wxSystemOptions).
+-include("wxe.hrl").
+-export([getOption/1,getOptionInt/1,hasOption/1,isFalse/1,setOption/2]).
+
+%% inherited exports
+-export([parent_class/1]).
+
+%% @hidden
+parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+
+%% @spec (Name::string()) -> string()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsystemoptions.html#wxsystemoptionsgetoption">external documentation</a>.
+getOption(Name)
+ when is_list(Name) ->
+ Name_UC = unicode:characters_to_binary([Name,0]),
+ wxe_util:call(?wxSystemOptions_GetOption,
+ <<(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((4+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
+
+%% @spec (Name::string()) -> integer()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsystemoptions.html#wxsystemoptionsgetoptionint">external documentation</a>.
+getOptionInt(Name)
+ when is_list(Name) ->
+ Name_UC = unicode:characters_to_binary([Name,0]),
+ wxe_util:call(?wxSystemOptions_GetOptionInt,
+ <<(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((4+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
+
+%% @spec (Name::string()) -> bool()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsystemoptions.html#wxsystemoptionshasoption">external documentation</a>.
+hasOption(Name)
+ when is_list(Name) ->
+ Name_UC = unicode:characters_to_binary([Name,0]),
+ wxe_util:call(?wxSystemOptions_HasOption,
+ <<(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((4+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
+
+%% @spec (Name::string()) -> bool()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsystemoptions.html#wxsystemoptionsisfalse">external documentation</a>.
+isFalse(Name)
+ when is_list(Name) ->
+ Name_UC = unicode:characters_to_binary([Name,0]),
+ wxe_util:call(?wxSystemOptions_IsFalse,
+ <<(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((4+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
+
+%% @spec (Name::string(),X::integer()|string()) -> ok
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsystemoptions.html#wxsystemoptionssetoption">external documentation</a>.
+%% <br /> Alternatives:
+%% <p><c>
+%% setOption(Name::string(), Value::integer()) -> ok </c>
+%% </p>
+%% <p><c>
+%% setOption(Name::string(), Value::string()) -> ok </c>
+%% </p>
+setOption(Name,Value)
+ when is_list(Name),is_integer(Value) ->
+ Name_UC = unicode:characters_to_binary([Name,0]),
+ wxe_util:cast(?wxSystemOptions_SetOption_2_0,
+ <<(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((4+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8,Value:32/?UI>>);
+setOption(Name,Value)
+ when is_list(Name),is_list(Value) ->
+ Name_UC = unicode:characters_to_binary([Name,0]),
+ Value_UC = unicode:characters_to_binary([Value,0]),
+ wxe_util:cast(?wxSystemOptions_SetOption_2_1,
+ <<(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((4+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8,(byte_size(Value_UC)):32/?UI,(Value_UC)/binary, 0:(((8- ((4+byte_size(Value_UC)) band 16#7)) band 16#7))/unit:8>>).
+
diff --git a/lib/wx/src/gen/wxTextCtrl.erl b/lib/wx/src/gen/wxTextCtrl.erl
index b4af23bdd9..b32f45b83b 100644
--- a/lib/wx/src/gen/wxTextCtrl.erl
+++ b/lib/wx/src/gen/wxTextCtrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -96,7 +96,7 @@ new(Parent,Id)
new(Parent,Id, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxTextCtrl()
-%% Option = {value, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {value, string()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlwxtextctrl">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
@@ -176,7 +176,7 @@ create(This,Parent,Id)
create(This,Parent,Id, []).
%% @spec (This::wxTextCtrl(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {value, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {value, string()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
@@ -266,7 +266,7 @@ getRange(#wx_ref{type=ThisT,ref=ThisRef},From,To)
wxe_util:call(?wxTextCtrl_GetRange,
<<ThisRef:32/?UI,From:32/?UI,To:32/?UI>>).
-%% @spec (This::wxTextCtrl()) -> {From::integer(),To::integer()}
+%% @spec (This::wxTextCtrl()) -> {From::integer(), To::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlgetselection">external documentation</a>.
getSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
@@ -357,7 +357,7 @@ paste(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:cast(?wxTextCtrl_Paste,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl(), Pos::integer()) -> {bool(),X::integer(),Y::integer()}
+%% @spec (This::wxTextCtrl(), Pos::integer()) -> {bool(), X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlpositiontoxy">external documentation</a>.
positionToXY(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
diff --git a/lib/wx/src/gen/wxTextEntryDialog.erl b/lib/wx/src/gen/wxTextEntryDialog.erl
index a30c32dd53..53694a47e6 100644
--- a/lib/wx/src/gen/wxTextEntryDialog.erl
+++ b/lib/wx/src/gen/wxTextEntryDialog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -91,7 +91,7 @@ new(Parent,Message)
new(Parent,Message, []).
%% @spec (Parent::wxWindow:wxWindow(), Message::string(), [Option]) -> wxTextEntryDialog()
-%% Option = {caption, string()} | {value, string()} | {style, integer()} | {pos, {X::integer(),Y::integer()}}
+%% Option = {caption, string()} | {value, string()} | {style, integer()} | {pos, {X::integer(), Y::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextentrydialog.html#wxtextentrydialogwxtextentrydialog">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Message, Options)
when is_list(Message),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxToggleButton.erl b/lib/wx/src/gen/wxToggleButton.erl
index ab595c1906..d7755cc50b 100644
--- a/lib/wx/src/gen/wxToggleButton.erl
+++ b/lib/wx/src/gen/wxToggleButton.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -88,7 +88,7 @@ new(Parent,Id,Label)
new(Parent,Id,Label, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Label::string(), [Option]) -> wxToggleButton()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtogglebutton.html#wxtogglebuttonwxtogglebutton">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Label, Options)
when is_integer(Id),is_list(Label),is_list(Options) ->
@@ -110,7 +110,7 @@ create(This,Parent,Id,Label)
create(This,Parent,Id,Label, []).
%% @spec (This::wxToggleButton(), Parent::wxWindow:wxWindow(), Id::integer(), Label::string(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtogglebutton.html#wxtogglebuttoncreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Label, Options)
when is_integer(Id),is_list(Label),is_list(Options) ->
diff --git a/lib/wx/src/gen/wxToolBar.erl b/lib/wx/src/gen/wxToolBar.erl
index c68936d493..59369368f0 100644
--- a/lib/wx/src/gen/wxToolBar.erl
+++ b/lib/wx/src/gen/wxToolBar.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -327,21 +327,21 @@ findToolForPosition(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
wxe_util:call(?wxToolBar_FindToolForPosition,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxToolBar()) -> {W::integer(),H::integer()}
+%% @spec (This::wxToolBar()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbargettoolsize">external documentation</a>.
getToolSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxToolBar),
wxe_util:call(?wxToolBar_GetToolSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxToolBar()) -> {W::integer(),H::integer()}
+%% @spec (This::wxToolBar()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbargettoolbitmapsize">external documentation</a>.
getToolBitmapSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxToolBar),
wxe_util:call(?wxToolBar_GetToolBitmapSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxToolBar()) -> {W::integer(),H::integer()}
+%% @spec (This::wxToolBar()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbargetmargins">external documentation</a>.
getMargins(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxToolBar),
@@ -504,7 +504,7 @@ setMargins(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
wxe_util:cast(?wxToolBar_SetMargins,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxToolBar(), Size::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxToolBar(), Size::{W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbarsettoolbitmapsize">external documentation</a>.
setToolBitmapSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
diff --git a/lib/wx/src/gen/wxToolbook.erl b/lib/wx/src/gen/wxToolbook.erl
index 4d188e979d..764f66c2e5 100644
--- a/lib/wx/src/gen/wxToolbook.erl
+++ b/lib/wx/src/gen/wxToolbook.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -93,7 +93,7 @@ new(Parent,Id)
new(Parent,Id, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxToolbook()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbookwxtoolbook">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
@@ -160,7 +160,7 @@ create(This,Parent,Id)
create(This,Parent,Id, []).
%% @spec (This::wxToolbook(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbookcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
@@ -249,7 +249,7 @@ getSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxToolbook_GetSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxToolbook(), Pt::{X::integer(),Y::integer()}) -> {integer(),Flags::integer()}
+%% @spec (This::wxToolbook(), Pt::{X::integer(), Y::integer()}) -> {integer(), Flags::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbookhittest">external documentation</a>.
hitTest(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
@@ -286,7 +286,7 @@ setImageList(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ImageListT,ref=ImageLi
wxe_util:cast(?wxToolbook_SetImageList,
<<ThisRef:32/?UI,ImageListRef:32/?UI>>).
-%% @spec (This::wxToolbook(), Size::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxToolbook(), Size::{W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbooksetpagesize">external documentation</a>.
setPageSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
diff --git a/lib/wx/src/gen/wxTreeCtrl.erl b/lib/wx/src/gen/wxTreeCtrl.erl
index e3fe4c9612..77705ec76e 100644
--- a/lib/wx/src/gen/wxTreeCtrl.erl
+++ b/lib/wx/src/gen/wxTreeCtrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -108,7 +108,7 @@ new(Parent)
new(Parent, []).
%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxTreeCtrl()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {id, integer()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlwxtreectrl">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
@@ -204,7 +204,7 @@ create(This,Parent)
create(This,Parent, []).
%% @spec (This::wxTreeCtrl(), Parent::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {id, integer()} | {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
@@ -267,13 +267,13 @@ expand(#wx_ref{type=ThisT,ref=ThisRef},Item)
wxe_util:cast(?wxTreeCtrl_Expand,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> bool()
+%% @spec (This::wxTreeCtrl(), Item::integer(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> bool()
%% @equiv getBoundingRect(This,Item,Rect, [])
getBoundingRect(This,Item,Rect={RectX,RectY,RectW,RectH})
when is_record(This, wx_ref),is_integer(Item),is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
getBoundingRect(This,Item,Rect, []).
-%% @spec (This::wxTreeCtrl(), Item::integer(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}, [Option]) -> bool()
+%% @spec (This::wxTreeCtrl(), Item::integer(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}, [Option]) -> bool()
%% Option = {textOnly, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetboundingrect">external documentation</a>.
getBoundingRect(#wx_ref{type=ThisT,ref=ThisRef},Item,{RectX,RectY,RectW,RectH}, Options)
@@ -317,7 +317,7 @@ getEditControl(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxTreeCtrl_GetEditControl,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> {integer(),Cookie::integer()}
+%% @spec (This::wxTreeCtrl(), Item::integer()) -> {integer(), Cookie::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetfirstchild">external documentation</a>.
getFirstChild(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
@@ -325,7 +325,7 @@ getFirstChild(#wx_ref{type=ThisT,ref=ThisRef},Item)
wxe_util:call(?wxTreeCtrl_GetFirstChild,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer(), Cookie::integer()) -> {integer(),Cookie::integer()}
+%% @spec (This::wxTreeCtrl(), Item::integer(), Cookie::integer()) -> {integer(), Cookie::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetnextchild">external documentation</a>.
getNextChild(#wx_ref{type=ThisT,ref=ThisRef},Item,Cookie)
when is_integer(Item),is_integer(Cookie) ->
@@ -478,7 +478,7 @@ getSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxTreeCtrl_GetSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreeCtrl()) -> {integer(),Val::[integer()]}
+%% @spec (This::wxTreeCtrl()) -> {integer(), Val::[integer()]}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetselections">external documentation</a>.
getSelections(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreeCtrl),
@@ -492,7 +492,7 @@ getStateImageList(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxTreeCtrl_GetStateImageList,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreeCtrl(), Point::{X::integer(),Y::integer()}) -> integer()
+%% @spec (This::wxTreeCtrl(), Point::{X::integer(), Y::integer()}) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlhittest">external documentation</a>.
hitTest(#wx_ref{type=ThisT,ref=ThisRef},{PointX,PointY})
when is_integer(PointX),is_integer(PointY) ->
diff --git a/lib/wx/src/gen/wxTreeEvent.erl b/lib/wx/src/gen/wxTreeEvent.erl
index d5379b7abe..0264d43568 100644
--- a/lib/wx/src/gen/wxTreeEvent.erl
+++ b/lib/wx/src/gen/wxTreeEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -83,7 +83,7 @@ getOldItem(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxTreeEvent_GetOldItem,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreeEvent()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxTreeEvent()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreeevent.html#wxtreeeventgetpoint">external documentation</a>.
getPoint(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreeEvent),
diff --git a/lib/wx/src/gen/wxTreebook.erl b/lib/wx/src/gen/wxTreebook.erl
index a515ec9639..24f5d72c43 100644
--- a/lib/wx/src/gen/wxTreebook.erl
+++ b/lib/wx/src/gen/wxTreebook.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -94,7 +94,7 @@ new(Parent,Id)
new(Parent,Id, []).
%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxTreebook()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebookwxtreebook">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
@@ -161,7 +161,7 @@ create(This,Parent,Id)
create(This,Parent,Id, []).
%% @spec (This::wxTreebook(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebookcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
@@ -276,7 +276,7 @@ isNodeExpanded(#wx_ref{type=ThisT,ref=ThisRef},Pos)
wxe_util:call(?wxTreebook_IsNodeExpanded,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxTreebook(), Pt::{X::integer(),Y::integer()}) -> {integer(),Flags::integer()}
+%% @spec (This::wxTreebook(), Pt::{X::integer(), Y::integer()}) -> {integer(), Flags::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebookhittest">external documentation</a>.
hitTest(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
@@ -334,7 +334,7 @@ setImageList(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ImageListT,ref=ImageLi
wxe_util:cast(?wxTreebook_SetImageList,
<<ThisRef:32/?UI,ImageListRef:32/?UI>>).
-%% @spec (This::wxTreebook(), Size::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxTreebook(), Size::{W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebooksetpagesize">external documentation</a>.
setPageSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
diff --git a/lib/wx/src/gen/wxWindow.erl b/lib/wx/src/gen/wxWindow.erl
index 33665a0ad6..6b57cf508e 100644
--- a/lib/wx/src/gen/wxWindow.erl
+++ b/lib/wx/src/gen/wxWindow.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -86,7 +86,7 @@ new(Parent,Id)
new(Parent,Id, []).
%% @spec (Parent::wxWindow(), Id::integer(), [Option]) -> wxWindow()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
+%% Option = {pos, {X::integer(), Y::integer()}} | {size, {W::integer(), H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowwxwindow">external documentation</a>.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
@@ -99,7 +99,7 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
wxe_util:construct(?wxWindow_new_3,
<<ParentRef:32/?UI,Id:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxWindow(), Size::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxWindow(), Size::{W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowcachebestsize">external documentation</a>.
cacheBestSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
@@ -193,7 +193,7 @@ clearBackground(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:cast(?wxWindow_ClearBackground,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow(), Pt::{X::integer(),Y::integer()}) -> {X::integer(),Y::integer()}
+%% @spec (This::wxWindow(), Pt::{X::integer(), Y::integer()}) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowclienttoscreen">external documentation</a>.
clientToScreen(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
@@ -201,7 +201,7 @@ clientToScreen(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
wxe_util:call(?wxWindow_ClientToScreen_1,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxWindow(), X::integer(), Y::integer()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxWindow(), X::integer(), Y::integer()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowclienttoscreen">external documentation</a>.
clientToScreen(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
@@ -227,7 +227,7 @@ close(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxWindow_Close,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow(), Sz::{W::integer(),H::integer()}) -> {W::integer(),H::integer()}
+%% @spec (This::wxWindow(), Sz::{W::integer(), H::integer()}) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowconvertdialogtopixels">external documentation</a>.
convertDialogToPixels(#wx_ref{type=ThisT,ref=ThisRef},{SzW,SzH})
when is_integer(SzW),is_integer(SzH) ->
@@ -235,7 +235,7 @@ convertDialogToPixels(#wx_ref{type=ThisT,ref=ThisRef},{SzW,SzH})
wxe_util:call(?wxWindow_ConvertDialogToPixels,
<<ThisRef:32/?UI,SzW:32/?UI,SzH:32/?UI>>).
-%% @spec (This::wxWindow(), Sz::{W::integer(),H::integer()}) -> {W::integer(),H::integer()}
+%% @spec (This::wxWindow(), Sz::{W::integer(), H::integer()}) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowconvertpixelstodialog">external documentation</a>.
convertPixelsToDialog(#wx_ref{type=ThisT,ref=ThisRef},{SzW,SzH})
when is_integer(SzW),is_integer(SzH) ->
@@ -406,7 +406,7 @@ getBackgroundStyle(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxWindow_GetBackgroundStyle,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> {W::integer(),H::integer()}
+%% @spec (This::wxWindow()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetbestsize">external documentation</a>.
getBestSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
@@ -447,7 +447,7 @@ getChildren(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxWindow_GetChildren,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> {W::integer(),H::integer()}
+%% @spec (This::wxWindow()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetclientsize">external documentation</a>.
getClientSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
@@ -538,14 +538,14 @@ getLabel(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxWindow_GetLabel,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> {W::integer(),H::integer()}
+%% @spec (This::wxWindow()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetmaxsize">external documentation</a>.
getMaxSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetMaxSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> {W::integer(),H::integer()}
+%% @spec (This::wxWindow()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetminsize">external documentation</a>.
getMinSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
@@ -566,28 +566,28 @@ getParent(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxWindow_GetParent,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxWindow()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetposition">external documentation</a>.
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetPosition,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
+%% @spec (This::wxWindow()) -> {X::integer(), Y::integer(), W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetrect">external documentation</a>.
getRect(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetRect,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxWindow()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetscreenposition">external documentation</a>.
getScreenPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetScreenPosition,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
+%% @spec (This::wxWindow()) -> {X::integer(), Y::integer(), W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetscreenrect">external documentation</a>.
getScreenRect(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
@@ -618,7 +618,7 @@ getScrollThumb(#wx_ref{type=ThisT,ref=ThisRef},Orient)
wxe_util:call(?wxWindow_GetScrollThumb,
<<ThisRef:32/?UI,Orient:32/?UI>>).
-%% @spec (This::wxWindow()) -> {W::integer(),H::integer()}
+%% @spec (This::wxWindow()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetsize">external documentation</a>.
getSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
@@ -632,13 +632,13 @@ getSizer(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxWindow_GetSizer,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow(), String::string()) -> {X::integer(),Y::integer(),Descent::integer(),ExternalLeading::integer()}
+%% @spec (This::wxWindow(), String::string()) -> {X::integer(), Y::integer(), Descent::integer(), ExternalLeading::integer()}
%% @equiv getTextExtent(This,String, [])
getTextExtent(This,String)
when is_record(This, wx_ref),is_list(String) ->
getTextExtent(This,String, []).
-%% @spec (This::wxWindow(), String::string(), [Option]) -> {X::integer(),Y::integer(),Descent::integer(),ExternalLeading::integer()}
+%% @spec (This::wxWindow(), String::string(), [Option]) -> {X::integer(), Y::integer(), Descent::integer(), ExternalLeading::integer()}
%% Option = {theFont, wxFont:wxFont()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgettextextent">external documentation</a>.
getTextExtent(#wx_ref{type=ThisT,ref=ThisRef},String, Options)
@@ -665,7 +665,7 @@ getUpdateRegion(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:call(?wxWindow_GetUpdateRegion,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> {W::integer(),H::integer()}
+%% @spec (This::wxWindow()) -> {W::integer(), H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetvirtualsize">external documentation</a>.
getVirtualSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
@@ -749,10 +749,10 @@ isEnabled(#wx_ref{type=ThisT,ref=ThisRef}) ->
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowisexposed">external documentation</a>.
%% <br /> Alternatives:
%% <p><c>
-%% isExposed(This::wxWindow(), Pt::{X::integer(),Y::integer()}) -> bool() </c>
+%% isExposed(This::wxWindow(), Pt::{X::integer(), Y::integer()}) -> bool() </c>
%% </p>
%% <p><c>
-%% isExposed(This::wxWindow(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> bool() </c>
+%% isExposed(This::wxWindow(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> bool() </c>
%% </p>
isExposed(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
@@ -848,7 +848,7 @@ makeModal(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxWindow_MakeModal,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow(), Pt::{X::integer(),Y::integer()}) -> ok
+%% @spec (This::wxWindow(), Pt::{X::integer(), Y::integer()}) -> ok
%% @equiv move(This,Pt, [])
move(This,Pt={PtX,PtY})
when is_record(This, wx_ref),is_integer(PtX),is_integer(PtY) ->
@@ -860,7 +860,7 @@ move(This,Pt={PtX,PtY})
%% <p><c>
%% move(This::wxWindow(), X::integer(), Y::integer()) -> move(This,X,Y, []) </c></p>
%% <p><c>
-%% move(This::wxWindow(), Pt::{X::integer(),Y::integer()}, [Option]) -> ok </c>
+%% move(This::wxWindow(), Pt::{X::integer(), Y::integer()}, [Option]) -> ok </c>
%%<br /> Option = {flags, integer()}
%% </p>
@@ -961,7 +961,7 @@ popupMenu(This,Menu)
popupMenu(This,Menu, []).
%% @spec (This::wxWindow(), Menu::wxMenu:wxMenu(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}}
+%% Option = {pos, {X::integer(), Y::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowpopupmenu">external documentation</a>.
popupMenu(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=MenuT,ref=MenuRef}, Options)
when is_list(Options) ->
@@ -996,7 +996,7 @@ refresh(This)
refresh(This, []).
%% @spec (This::wxWindow(), [Option]) -> ok
-%% Option = {eraseBackground, bool()} | {rect, {X::integer(),Y::integer(),W::integer(),H::integer()}}
+%% Option = {eraseBackground, bool()} | {rect, {X::integer(), Y::integer(), W::integer(), H::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowrefresh">external documentation</a>.
refresh(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
@@ -1008,13 +1008,13 @@ refresh(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxWindow_Refresh,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> ok
+%% @spec (This::wxWindow(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> ok
%% @equiv refreshRect(This,Rect, [])
refreshRect(This,Rect={RectX,RectY,RectW,RectH})
when is_record(This, wx_ref),is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
refreshRect(This,Rect, []).
-%% @spec (This::wxWindow(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}, [Option]) -> ok
+%% @spec (This::wxWindow(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}, [Option]) -> ok
%% Option = {eraseBackground, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowrefreshrect">external documentation</a>.
refreshRect(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH}, Options)
@@ -1049,14 +1049,14 @@ reparent(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=NewParentT,ref=NewParentRe
wxe_util:call(?wxWindow_Reparent,
<<ThisRef:32/?UI,NewParentRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> {X::integer(),Y::integer()}
+%% @spec (This::wxWindow()) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowscreentoclient">external documentation</a>.
screenToClient(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_ScreenToClient_2,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow(), Pt::{X::integer(),Y::integer()}) -> {X::integer(),Y::integer()}
+%% @spec (This::wxWindow(), Pt::{X::integer(), Y::integer()}) -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowscreentoclient">external documentation</a>.
screenToClient(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
@@ -1087,7 +1087,7 @@ scrollWindow(This,Dx,Dy)
scrollWindow(This,Dx,Dy, []).
%% @spec (This::wxWindow(), Dx::integer(), Dy::integer(), [Option]) -> ok
-%% Option = {rect, {X::integer(),Y::integer(),W::integer(),H::integer()}}
+%% Option = {rect, {X::integer(), Y::integer(), W::integer(), H::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowscrollwindow">external documentation</a>.
scrollWindow(#wx_ref{type=ThisT,ref=ThisRef},Dx,Dy, Options)
when is_integer(Dx),is_integer(Dy),is_list(Options) ->
@@ -1144,10 +1144,10 @@ setCaret(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=CaretT,ref=CaretRef}) ->
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetclientsize">external documentation</a>.
%% <br /> Alternatives:
%% <p><c>
-%% setClientSize(This::wxWindow(), Size::{W::integer(),H::integer()}) -> ok </c>
+%% setClientSize(This::wxWindow(), Size::{W::integer(), H::integer()}) -> ok </c>
%% </p>
%% <p><c>
-%% setClientSize(This::wxWindow(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> ok </c>
+%% setClientSize(This::wxWindow(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> ok </c>
%% </p>
setClientSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
@@ -1184,7 +1184,7 @@ setCursor(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=CursorT,ref=CursorRef}) -
wxe_util:call(?wxWindow_SetCursor,
<<ThisRef:32/?UI,CursorRef:32/?UI>>).
-%% @spec (This::wxWindow(), MaxSize::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxWindow(), MaxSize::{W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetmaxsize">external documentation</a>.
setMaxSize(#wx_ref{type=ThisT,ref=ThisRef},{MaxSizeW,MaxSizeH})
when is_integer(MaxSizeW),is_integer(MaxSizeH) ->
@@ -1192,7 +1192,7 @@ setMaxSize(#wx_ref{type=ThisT,ref=ThisRef},{MaxSizeW,MaxSizeH})
wxe_util:cast(?wxWindow_SetMaxSize,
<<ThisRef:32/?UI,MaxSizeW:32/?UI,MaxSizeH:32/?UI>>).
-%% @spec (This::wxWindow(), MinSize::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxWindow(), MinSize::{W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetminsize">external documentation</a>.
setMinSize(#wx_ref{type=ThisT,ref=ThisRef},{MinSizeW,MinSizeH})
when is_integer(MinSizeW),is_integer(MinSizeH) ->
@@ -1353,9 +1353,9 @@ setScrollPos(#wx_ref{type=ThisT,ref=ThisRef},Orient,Pos, Options)
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetsize">external documentation</a>.
%% <br /> Alternatives:
%% <p><c>
-%% setSize(This::wxWindow(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> setSize(This,Rect, []) </c></p>
+%% setSize(This::wxWindow(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> setSize(This,Rect, []) </c></p>
%% <p><c>
-%% setSize(This::wxWindow(), Size::{W::integer(),H::integer()}) -> ok </c>
+%% setSize(This::wxWindow(), Size::{W::integer(), H::integer()}) -> ok </c>
%% </p>
setSize(This,Rect={RectX,RectY,RectW,RectH})
@@ -1374,7 +1374,7 @@ setSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
%% setSize(This::wxWindow(), Width::integer(), Height::integer()) -> ok </c>
%% </p>
%% <p><c>
-%% setSize(This::wxWindow(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}, [Option]) -> ok </c>
+%% setSize(This::wxWindow(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}, [Option]) -> ok </c>
%%<br /> Option = {sizeFlags, integer()}
%% </p>
setSize(#wx_ref{type=ThisT,ref=ThisRef},Width,Height)
@@ -1409,7 +1409,7 @@ setSize(#wx_ref{type=ThisT,ref=ThisRef},X,Y,Width,Height, Options)
wxe_util:cast(?wxWindow_SetSize_5,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI,Width:32/?UI,Height:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow(), MinSize::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxWindow(), MinSize::{W::integer(), H::integer()}) -> ok
%% @equiv setSizeHints(This,MinSize, [])
setSizeHints(This,MinSize={MinSizeW,MinSizeH})
when is_record(This, wx_ref),is_integer(MinSizeW),is_integer(MinSizeH) ->
@@ -1421,8 +1421,8 @@ setSizeHints(This,MinSize={MinSizeW,MinSizeH})
%% <p><c>
%% setSizeHints(This::wxWindow(), MinW::integer(), MinH::integer()) -> setSizeHints(This,MinW,MinH, []) </c></p>
%% <p><c>
-%% setSizeHints(This::wxWindow(), MinSize::{W::integer(),H::integer()}, [Option]) -> ok </c>
-%%<br /> Option = {maxSize, {W::integer(),H::integer()}} | {incSize, {W::integer(),H::integer()}}
+%% setSizeHints(This::wxWindow(), MinSize::{W::integer(), H::integer()}, [Option]) -> ok </c>
+%%<br /> Option = {maxSize, {W::integer(), H::integer()}} | {incSize, {W::integer(), H::integer()}}
%% </p>
setSizeHints(This,MinW,MinH)
@@ -1520,7 +1520,7 @@ setToolTip(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=TipT,ref=TipRef}) ->
wxe_util:cast(?wxWindow_SetToolTip_1_1,
<<ThisRef:32/?UI,TipRef:32/?UI>>).
-%% @spec (This::wxWindow(), Size::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxWindow(), Size::{W::integer(), H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetvirtualsize">external documentation</a>.
setVirtualSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
@@ -1536,7 +1536,7 @@ setVirtualSize(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
wxe_util:cast(?wxWindow_SetVirtualSize_2,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxWindow(), MinSize::{W::integer(),H::integer()}) -> ok
+%% @spec (This::wxWindow(), MinSize::{W::integer(), H::integer()}) -> ok
%% @equiv setVirtualSizeHints(This,MinSize, [])
setVirtualSizeHints(This,MinSize={MinSizeW,MinSizeH})
when is_record(This, wx_ref),is_integer(MinSizeW),is_integer(MinSizeH) ->
@@ -1548,8 +1548,8 @@ setVirtualSizeHints(This,MinSize={MinSizeW,MinSizeH})
%% <p><c>
%% setVirtualSizeHints(This::wxWindow(), MinW::integer(), MinH::integer()) -> setVirtualSizeHints(This,MinW,MinH, []) </c></p>
%% <p><c>
-%% setVirtualSizeHints(This::wxWindow(), MinSize::{W::integer(),H::integer()}, [Option]) -> ok </c>
-%%<br /> Option = {maxSize, {W::integer(),H::integer()}}
+%% setVirtualSizeHints(This::wxWindow(), MinSize::{W::integer(), H::integer()}, [Option]) -> ok </c>
+%%<br /> Option = {maxSize, {W::integer(), H::integer()}}
%% </p>
setVirtualSizeHints(This,MinW,MinH)
diff --git a/lib/wx/src/gen/wx_misc.erl b/lib/wx/src/gen/wx_misc.erl
index cf23d4cf8b..3382d898e4 100644
--- a/lib/wx/src/gen/wx_misc.erl
+++ b/lib/wx/src/gen/wx_misc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -39,7 +39,7 @@ getKeyState(Key)
wxe_util:call(?utils_wxGetKeyState,
<<Key:32/?UI>>).
-%% @spec () -> {X::integer(),Y::integer()}
+%% @spec () -> {X::integer(), Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxgetmouseposition">external documentation</a>.
getMousePosition() ->
wxe_util:call(?utils_wxGetMousePosition,
@@ -74,14 +74,14 @@ findMenuItemId(#wx_ref{type=FrameT,ref=FrameRef},MenuString,ItemString)
wxe_util:call(?utils_wxFindMenuItemId,
<<FrameRef:32/?UI,(byte_size(MenuString_UC)):32/?UI,(MenuString_UC)/binary, 0:(((8- ((0+byte_size(MenuString_UC)) band 16#7)) band 16#7))/unit:8,(byte_size(ItemString_UC)):32/?UI,(ItemString_UC)/binary, 0:(((8- ((4+byte_size(ItemString_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (Pt::{X::integer(),Y::integer()}) -> wxWindow:wxWindow()
+%% @spec (Pt::{X::integer(), Y::integer()}) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxgenericfindwindowatpoint">external documentation</a>.
genericFindWindowAtPoint({PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
wxe_util:call(?utils_wxGenericFindWindowAtPoint,
<<PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (Pt::{X::integer(),Y::integer()}) -> wxWindow:wxWindow()
+%% @spec (Pt::{X::integer(), Y::integer()}) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxfindwindowatpoint">external documentation</a>.
findWindowAtPoint({PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
diff --git a/lib/wx/src/gen/wxe_debug.hrl b/lib/wx/src/gen/wxe_debug.hrl
index 3edfa73599..4224c54200 100644
--- a/lib/wx/src/gen/wxe_debug.hrl
+++ b/lib/wx/src/gen/wxe_debug.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1603,1684 +1603,1702 @@ wxdebug_table() ->
{1754, {wxListItem, setText, 1}},
{1755, {wxListItem, setTextColour, 1}},
{1756, {wxListItem, setWidth, 1}},
- {1757, {wxImageList, new_0, 0}},
- {1758, {wxImageList, new_3, 3}},
- {1759, {wxImageList, add_1, 1}},
- {1760, {wxImageList, add_2_0, 2}},
- {1761, {wxImageList, add_2_1, 2}},
- {1762, {wxImageList, create, 3}},
- {1764, {wxImageList, draw, 5}},
- {1765, {wxImageList, getBitmap, 1}},
- {1766, {wxImageList, getIcon, 1}},
- {1767, {wxImageList, getImageCount, 0}},
- {1768, {wxImageList, getSize, 3}},
- {1769, {wxImageList, remove, 1}},
- {1770, {wxImageList, removeAll, 0}},
- {1771, {wxImageList, replace_2, 2}},
- {1772, {wxImageList, replace_3, 3}},
- {1773, {wxImageList, 'Destroy', undefined}},
- {1774, {wxTextAttr, new_0, 0}},
- {1775, {wxTextAttr, new_2, 2}},
- {1776, {wxTextAttr, getAlignment, 0}},
- {1777, {wxTextAttr, getBackgroundColour, 0}},
- {1778, {wxTextAttr, getFont, 0}},
- {1779, {wxTextAttr, getLeftIndent, 0}},
- {1780, {wxTextAttr, getLeftSubIndent, 0}},
- {1781, {wxTextAttr, getRightIndent, 0}},
- {1782, {wxTextAttr, getTabs, 0}},
- {1783, {wxTextAttr, getTextColour, 0}},
- {1784, {wxTextAttr, hasBackgroundColour, 0}},
- {1785, {wxTextAttr, hasFont, 0}},
- {1786, {wxTextAttr, hasTextColour, 0}},
- {1787, {wxTextAttr, getFlags, 0}},
- {1788, {wxTextAttr, isDefault, 0}},
- {1789, {wxTextAttr, setAlignment, 1}},
- {1790, {wxTextAttr, setBackgroundColour, 1}},
- {1791, {wxTextAttr, setFlags, 1}},
- {1792, {wxTextAttr, setFont, 2}},
- {1793, {wxTextAttr, setLeftIndent, 2}},
- {1794, {wxTextAttr, setRightIndent, 1}},
- {1795, {wxTextAttr, setTabs, 1}},
- {1796, {wxTextAttr, setTextColour, 1}},
- {1797, {wxTextAttr, 'Destroy', undefined}},
- {1799, {wxTextCtrl, new_3, 3}},
- {1800, {wxTextCtrl, new_0, 0}},
- {1802, {wxTextCtrl, destruct, 0}},
- {1803, {wxTextCtrl, appendText, 1}},
- {1804, {wxTextCtrl, canCopy, 0}},
- {1805, {wxTextCtrl, canCut, 0}},
- {1806, {wxTextCtrl, canPaste, 0}},
- {1807, {wxTextCtrl, canRedo, 0}},
- {1808, {wxTextCtrl, canUndo, 0}},
- {1809, {wxTextCtrl, clear, 0}},
- {1810, {wxTextCtrl, copy, 0}},
- {1811, {wxTextCtrl, create, 3}},
- {1812, {wxTextCtrl, cut, 0}},
- {1813, {wxTextCtrl, discardEdits, 0}},
- {1814, {wxTextCtrl, emulateKeyPress, 1}},
- {1815, {wxTextCtrl, getDefaultStyle, 0}},
- {1816, {wxTextCtrl, getInsertionPoint, 0}},
- {1817, {wxTextCtrl, getLastPosition, 0}},
- {1818, {wxTextCtrl, getLineLength, 1}},
- {1819, {wxTextCtrl, getLineText, 1}},
- {1820, {wxTextCtrl, getNumberOfLines, 0}},
- {1821, {wxTextCtrl, getRange, 2}},
- {1822, {wxTextCtrl, getSelection, 2}},
- {1823, {wxTextCtrl, getStringSelection, 0}},
- {1824, {wxTextCtrl, getStyle, 2}},
- {1825, {wxTextCtrl, getValue, 0}},
- {1826, {wxTextCtrl, isEditable, 0}},
- {1827, {wxTextCtrl, isModified, 0}},
- {1828, {wxTextCtrl, isMultiLine, 0}},
- {1829, {wxTextCtrl, isSingleLine, 0}},
- {1830, {wxTextCtrl, loadFile, 2}},
- {1831, {wxTextCtrl, markDirty, 0}},
- {1832, {wxTextCtrl, paste, 0}},
- {1833, {wxTextCtrl, positionToXY, 3}},
- {1834, {wxTextCtrl, redo, 0}},
- {1835, {wxTextCtrl, remove, 2}},
- {1836, {wxTextCtrl, replace, 3}},
- {1837, {wxTextCtrl, saveFile, 1}},
- {1838, {wxTextCtrl, setDefaultStyle, 1}},
- {1839, {wxTextCtrl, setEditable, 1}},
- {1840, {wxTextCtrl, setInsertionPoint, 1}},
- {1841, {wxTextCtrl, setInsertionPointEnd, 0}},
- {1843, {wxTextCtrl, setMaxLength, 1}},
- {1844, {wxTextCtrl, setSelection, 2}},
- {1845, {wxTextCtrl, setStyle, 3}},
- {1846, {wxTextCtrl, setValue, 1}},
- {1847, {wxTextCtrl, showPosition, 1}},
- {1848, {wxTextCtrl, undo, 0}},
- {1849, {wxTextCtrl, writeText, 1}},
- {1850, {wxTextCtrl, xYToPosition, 2}},
- {1853, {wxNotebook, new_0, 0}},
- {1854, {wxNotebook, new_3, 3}},
- {1855, {wxNotebook, destruct, 0}},
- {1856, {wxNotebook, addPage, 3}},
- {1857, {wxNotebook, advanceSelection, 1}},
- {1858, {wxNotebook, assignImageList, 1}},
- {1859, {wxNotebook, create, 3}},
- {1860, {wxNotebook, deleteAllPages, 0}},
- {1861, {wxNotebook, deletePage, 1}},
- {1862, {wxNotebook, removePage, 1}},
- {1863, {wxNotebook, getCurrentPage, 0}},
- {1864, {wxNotebook, getImageList, 0}},
- {1866, {wxNotebook, getPage, 1}},
- {1867, {wxNotebook, getPageCount, 0}},
- {1868, {wxNotebook, getPageImage, 1}},
- {1869, {wxNotebook, getPageText, 1}},
- {1870, {wxNotebook, getRowCount, 0}},
- {1871, {wxNotebook, getSelection, 0}},
- {1872, {wxNotebook, getThemeBackgroundColour, 0}},
- {1874, {wxNotebook, hitTest, 2}},
- {1876, {wxNotebook, insertPage, 4}},
- {1877, {wxNotebook, setImageList, 1}},
- {1878, {wxNotebook, setPadding, 1}},
- {1879, {wxNotebook, setPageSize, 1}},
- {1880, {wxNotebook, setPageImage, 2}},
- {1881, {wxNotebook, setPageText, 2}},
- {1882, {wxNotebook, setSelection, 1}},
- {1883, {wxNotebook, changeSelection, 1}},
- {1884, {wxChoicebook, new_0, 0}},
- {1885, {wxChoicebook, new_3, 3}},
- {1886, {wxChoicebook, addPage, 3}},
- {1887, {wxChoicebook, advanceSelection, 1}},
- {1888, {wxChoicebook, assignImageList, 1}},
- {1889, {wxChoicebook, create, 3}},
- {1890, {wxChoicebook, deleteAllPages, 0}},
- {1891, {wxChoicebook, deletePage, 1}},
- {1892, {wxChoicebook, removePage, 1}},
- {1893, {wxChoicebook, getCurrentPage, 0}},
- {1894, {wxChoicebook, getImageList, 0}},
- {1896, {wxChoicebook, getPage, 1}},
- {1897, {wxChoicebook, getPageCount, 0}},
- {1898, {wxChoicebook, getPageImage, 1}},
- {1899, {wxChoicebook, getPageText, 1}},
- {1900, {wxChoicebook, getSelection, 0}},
- {1901, {wxChoicebook, hitTest, 2}},
- {1902, {wxChoicebook, insertPage, 4}},
- {1903, {wxChoicebook, setImageList, 1}},
- {1904, {wxChoicebook, setPageSize, 1}},
- {1905, {wxChoicebook, setPageImage, 2}},
- {1906, {wxChoicebook, setPageText, 2}},
- {1907, {wxChoicebook, setSelection, 1}},
- {1908, {wxChoicebook, changeSelection, 1}},
- {1909, {wxChoicebook, 'Destroy', undefined}},
- {1910, {wxToolbook, new_0, 0}},
- {1911, {wxToolbook, new_3, 3}},
- {1912, {wxToolbook, addPage, 3}},
- {1913, {wxToolbook, advanceSelection, 1}},
- {1914, {wxToolbook, assignImageList, 1}},
- {1915, {wxToolbook, create, 3}},
- {1916, {wxToolbook, deleteAllPages, 0}},
- {1917, {wxToolbook, deletePage, 1}},
- {1918, {wxToolbook, removePage, 1}},
- {1919, {wxToolbook, getCurrentPage, 0}},
- {1920, {wxToolbook, getImageList, 0}},
- {1922, {wxToolbook, getPage, 1}},
- {1923, {wxToolbook, getPageCount, 0}},
- {1924, {wxToolbook, getPageImage, 1}},
- {1925, {wxToolbook, getPageText, 1}},
- {1926, {wxToolbook, getSelection, 0}},
- {1928, {wxToolbook, hitTest, 2}},
- {1929, {wxToolbook, insertPage, 4}},
- {1930, {wxToolbook, setImageList, 1}},
- {1931, {wxToolbook, setPageSize, 1}},
- {1932, {wxToolbook, setPageImage, 2}},
- {1933, {wxToolbook, setPageText, 2}},
- {1934, {wxToolbook, setSelection, 1}},
- {1935, {wxToolbook, changeSelection, 1}},
- {1936, {wxToolbook, 'Destroy', undefined}},
- {1937, {wxListbook, new_0, 0}},
- {1938, {wxListbook, new_3, 3}},
- {1939, {wxListbook, addPage, 3}},
- {1940, {wxListbook, advanceSelection, 1}},
- {1941, {wxListbook, assignImageList, 1}},
- {1942, {wxListbook, create, 3}},
- {1943, {wxListbook, deleteAllPages, 0}},
- {1944, {wxListbook, deletePage, 1}},
- {1945, {wxListbook, removePage, 1}},
- {1946, {wxListbook, getCurrentPage, 0}},
- {1947, {wxListbook, getImageList, 0}},
- {1949, {wxListbook, getPage, 1}},
- {1950, {wxListbook, getPageCount, 0}},
- {1951, {wxListbook, getPageImage, 1}},
- {1952, {wxListbook, getPageText, 1}},
- {1953, {wxListbook, getSelection, 0}},
- {1955, {wxListbook, hitTest, 2}},
- {1956, {wxListbook, insertPage, 4}},
- {1957, {wxListbook, setImageList, 1}},
- {1958, {wxListbook, setPageSize, 1}},
- {1959, {wxListbook, setPageImage, 2}},
- {1960, {wxListbook, setPageText, 2}},
- {1961, {wxListbook, setSelection, 1}},
- {1962, {wxListbook, changeSelection, 1}},
- {1963, {wxListbook, 'Destroy', undefined}},
- {1964, {wxTreebook, new_0, 0}},
- {1965, {wxTreebook, new_3, 3}},
- {1966, {wxTreebook, addPage, 3}},
- {1967, {wxTreebook, advanceSelection, 1}},
- {1968, {wxTreebook, assignImageList, 1}},
- {1969, {wxTreebook, create, 3}},
- {1970, {wxTreebook, deleteAllPages, 0}},
- {1971, {wxTreebook, deletePage, 1}},
- {1972, {wxTreebook, removePage, 1}},
- {1973, {wxTreebook, getCurrentPage, 0}},
- {1974, {wxTreebook, getImageList, 0}},
- {1976, {wxTreebook, getPage, 1}},
- {1977, {wxTreebook, getPageCount, 0}},
- {1978, {wxTreebook, getPageImage, 1}},
- {1979, {wxTreebook, getPageText, 1}},
- {1980, {wxTreebook, getSelection, 0}},
- {1981, {wxTreebook, expandNode, 2}},
- {1982, {wxTreebook, isNodeExpanded, 1}},
- {1984, {wxTreebook, hitTest, 2}},
- {1985, {wxTreebook, insertPage, 4}},
- {1986, {wxTreebook, insertSubPage, 4}},
- {1987, {wxTreebook, setImageList, 1}},
- {1988, {wxTreebook, setPageSize, 1}},
- {1989, {wxTreebook, setPageImage, 2}},
- {1990, {wxTreebook, setPageText, 2}},
- {1991, {wxTreebook, setSelection, 1}},
- {1992, {wxTreebook, changeSelection, 1}},
- {1993, {wxTreebook, 'Destroy', undefined}},
- {1996, {wxTreeCtrl, new_2, 2}},
- {1997, {wxTreeCtrl, new_0, 0}},
- {1999, {wxTreeCtrl, destruct, 0}},
- {2000, {wxTreeCtrl, addRoot, 2}},
- {2001, {wxTreeCtrl, appendItem, 3}},
- {2002, {wxTreeCtrl, assignImageList, 1}},
- {2003, {wxTreeCtrl, assignStateImageList, 1}},
- {2004, {wxTreeCtrl, collapse, 1}},
- {2005, {wxTreeCtrl, collapseAndReset, 1}},
- {2006, {wxTreeCtrl, create, 2}},
- {2007, {wxTreeCtrl, delete, 1}},
- {2008, {wxTreeCtrl, deleteAllItems, 0}},
- {2009, {wxTreeCtrl, deleteChildren, 1}},
- {2010, {wxTreeCtrl, editLabel, 1}},
- {2011, {wxTreeCtrl, ensureVisible, 1}},
- {2012, {wxTreeCtrl, expand, 1}},
- {2013, {wxTreeCtrl, getBoundingRect, 3}},
- {2015, {wxTreeCtrl, getChildrenCount, 2}},
- {2016, {wxTreeCtrl, getCount, 0}},
- {2017, {wxTreeCtrl, getEditControl, 0}},
- {2018, {wxTreeCtrl, getFirstChild, 2}},
- {2019, {wxTreeCtrl, getNextChild, 2}},
- {2020, {wxTreeCtrl, getFirstVisibleItem, 0}},
- {2021, {wxTreeCtrl, getImageList, 0}},
- {2022, {wxTreeCtrl, getIndent, 0}},
- {2023, {wxTreeCtrl, getItemBackgroundColour, 1}},
- {2024, {wxTreeCtrl, getItemData, 1}},
- {2025, {wxTreeCtrl, getItemFont, 1}},
- {2026, {wxTreeCtrl, getItemImage_1, 1}},
- {2027, {wxTreeCtrl, getItemImage_2, 2}},
- {2028, {wxTreeCtrl, getItemText, 1}},
- {2029, {wxTreeCtrl, getItemTextColour, 1}},
- {2030, {wxTreeCtrl, getLastChild, 1}},
- {2031, {wxTreeCtrl, getNextSibling, 1}},
- {2032, {wxTreeCtrl, getNextVisible, 1}},
- {2033, {wxTreeCtrl, getItemParent, 1}},
- {2034, {wxTreeCtrl, getPrevSibling, 1}},
- {2035, {wxTreeCtrl, getPrevVisible, 1}},
- {2036, {wxTreeCtrl, getRootItem, 0}},
- {2037, {wxTreeCtrl, getSelection, 0}},
- {2038, {wxTreeCtrl, getSelections, 1}},
- {2039, {wxTreeCtrl, getStateImageList, 0}},
- {2040, {wxTreeCtrl, hitTest, 1}},
- {2042, {wxTreeCtrl, insertItem, 4}},
- {2043, {wxTreeCtrl, isBold, 1}},
- {2044, {wxTreeCtrl, isExpanded, 1}},
- {2045, {wxTreeCtrl, isSelected, 1}},
- {2046, {wxTreeCtrl, isVisible, 1}},
- {2047, {wxTreeCtrl, itemHasChildren, 1}},
- {2048, {wxTreeCtrl, prependItem, 3}},
- {2049, {wxTreeCtrl, scrollTo, 1}},
- {2050, {wxTreeCtrl, selectItem_1, 1}},
- {2051, {wxTreeCtrl, selectItem_2, 2}},
- {2052, {wxTreeCtrl, setIndent, 1}},
- {2053, {wxTreeCtrl, setImageList, 1}},
- {2054, {wxTreeCtrl, setItemBackgroundColour, 2}},
- {2055, {wxTreeCtrl, setItemBold, 2}},
- {2056, {wxTreeCtrl, setItemData, 2}},
- {2057, {wxTreeCtrl, setItemDropHighlight, 2}},
- {2058, {wxTreeCtrl, setItemFont, 2}},
- {2059, {wxTreeCtrl, setItemHasChildren, 2}},
- {2060, {wxTreeCtrl, setItemImage_2, 2}},
- {2061, {wxTreeCtrl, setItemImage_3, 3}},
- {2062, {wxTreeCtrl, setItemText, 2}},
- {2063, {wxTreeCtrl, setItemTextColour, 2}},
- {2064, {wxTreeCtrl, setStateImageList, 1}},
- {2065, {wxTreeCtrl, setWindowStyle, 1}},
- {2066, {wxTreeCtrl, sortChildren, 1}},
- {2067, {wxTreeCtrl, toggle, 1}},
- {2068, {wxTreeCtrl, toggleItemSelection, 1}},
- {2069, {wxTreeCtrl, unselect, 0}},
- {2070, {wxTreeCtrl, unselectAll, 0}},
- {2071, {wxTreeCtrl, unselectItem, 1}},
- {2072, {wxScrollBar, new_0, 0}},
- {2073, {wxScrollBar, new_3, 3}},
- {2074, {wxScrollBar, destruct, 0}},
- {2075, {wxScrollBar, create, 3}},
- {2076, {wxScrollBar, getRange, 0}},
- {2077, {wxScrollBar, getPageSize, 0}},
- {2078, {wxScrollBar, getThumbPosition, 0}},
- {2079, {wxScrollBar, getThumbSize, 0}},
- {2080, {wxScrollBar, setThumbPosition, 1}},
- {2081, {wxScrollBar, setScrollbar, 5}},
- {2083, {wxSpinButton, new_2, 2}},
- {2084, {wxSpinButton, new_0, 0}},
- {2085, {wxSpinButton, create, 2}},
- {2086, {wxSpinButton, getMax, 0}},
- {2087, {wxSpinButton, getMin, 0}},
- {2088, {wxSpinButton, getValue, 0}},
- {2089, {wxSpinButton, setRange, 2}},
- {2090, {wxSpinButton, setValue, 1}},
- {2091, {wxSpinButton, 'Destroy', undefined}},
- {2092, {wxSpinCtrl, new_0, 0}},
- {2093, {wxSpinCtrl, new_2, 2}},
- {2095, {wxSpinCtrl, create, 2}},
- {2098, {wxSpinCtrl, setValue_1_1, 1}},
- {2099, {wxSpinCtrl, setValue_1_0, 1}},
- {2101, {wxSpinCtrl, getValue, 0}},
- {2103, {wxSpinCtrl, setRange, 2}},
- {2104, {wxSpinCtrl, setSelection, 2}},
- {2106, {wxSpinCtrl, getMin, 0}},
- {2108, {wxSpinCtrl, getMax, 0}},
- {2109, {wxSpinCtrl, 'Destroy', undefined}},
- {2110, {wxStaticText, new_0, 0}},
- {2111, {wxStaticText, new_4, 4}},
- {2112, {wxStaticText, create, 4}},
- {2113, {wxStaticText, getLabel, 0}},
- {2114, {wxStaticText, setLabel, 1}},
- {2115, {wxStaticText, wrap, 1}},
- {2116, {wxStaticText, 'Destroy', undefined}},
- {2117, {wxStaticBitmap, new_0, 0}},
- {2118, {wxStaticBitmap, new_4, 4}},
- {2119, {wxStaticBitmap, create, 4}},
- {2120, {wxStaticBitmap, getBitmap, 0}},
- {2121, {wxStaticBitmap, setBitmap, 1}},
- {2122, {wxStaticBitmap, 'Destroy', undefined}},
- {2123, {wxRadioBox, new, 7}},
- {2125, {wxRadioBox, destruct, 0}},
- {2126, {wxRadioBox, create, 7}},
- {2127, {wxRadioBox, enable_2, 2}},
- {2128, {wxRadioBox, enable_1, 1}},
- {2129, {wxRadioBox, getSelection, 0}},
- {2130, {wxRadioBox, getString, 1}},
- {2131, {wxRadioBox, setSelection, 1}},
- {2132, {wxRadioBox, show_2, 2}},
- {2133, {wxRadioBox, show_1, 1}},
- {2134, {wxRadioBox, getColumnCount, 0}},
- {2135, {wxRadioBox, getItemHelpText, 1}},
- {2136, {wxRadioBox, getItemToolTip, 1}},
- {2138, {wxRadioBox, getItemFromPoint, 1}},
- {2139, {wxRadioBox, getRowCount, 0}},
- {2140, {wxRadioBox, isItemEnabled, 1}},
- {2141, {wxRadioBox, isItemShown, 1}},
- {2142, {wxRadioBox, setItemHelpText, 2}},
- {2143, {wxRadioBox, setItemToolTip, 2}},
- {2144, {wxRadioButton, new_0, 0}},
- {2145, {wxRadioButton, new_4, 4}},
- {2146, {wxRadioButton, create, 4}},
- {2147, {wxRadioButton, getValue, 0}},
- {2148, {wxRadioButton, setValue, 1}},
- {2149, {wxRadioButton, 'Destroy', undefined}},
- {2151, {wxSlider, new_6, 6}},
- {2152, {wxSlider, new_0, 0}},
- {2153, {wxSlider, create, 6}},
- {2154, {wxSlider, getLineSize, 0}},
- {2155, {wxSlider, getMax, 0}},
- {2156, {wxSlider, getMin, 0}},
- {2157, {wxSlider, getPageSize, 0}},
- {2158, {wxSlider, getThumbLength, 0}},
- {2159, {wxSlider, getValue, 0}},
- {2160, {wxSlider, setLineSize, 1}},
- {2161, {wxSlider, setPageSize, 1}},
- {2162, {wxSlider, setRange, 2}},
- {2163, {wxSlider, setThumbLength, 1}},
- {2164, {wxSlider, setValue, 1}},
- {2165, {wxSlider, 'Destroy', undefined}},
- {2167, {wxDialog, new_4, 4}},
- {2168, {wxDialog, new_0, 0}},
- {2170, {wxDialog, destruct, 0}},
- {2171, {wxDialog, create, 4}},
- {2172, {wxDialog, createButtonSizer, 1}},
- {2173, {wxDialog, createStdDialogButtonSizer, 1}},
- {2174, {wxDialog, endModal, 1}},
- {2175, {wxDialog, getAffirmativeId, 0}},
- {2176, {wxDialog, getReturnCode, 0}},
- {2177, {wxDialog, isModal, 0}},
- {2178, {wxDialog, setAffirmativeId, 1}},
- {2179, {wxDialog, setReturnCode, 1}},
- {2180, {wxDialog, show, 1}},
- {2181, {wxDialog, showModal, 0}},
- {2182, {wxColourDialog, new_0, 0}},
- {2183, {wxColourDialog, new_2, 2}},
- {2184, {wxColourDialog, destruct, 0}},
- {2185, {wxColourDialog, create, 2}},
- {2186, {wxColourDialog, getColourData, 0}},
- {2187, {wxColourData, new_0, 0}},
- {2188, {wxColourData, new_1, 1}},
- {2189, {wxColourData, destruct, 0}},
- {2190, {wxColourData, getChooseFull, 0}},
- {2191, {wxColourData, getColour, 0}},
- {2193, {wxColourData, getCustomColour, 1}},
- {2194, {wxColourData, setChooseFull, 1}},
- {2195, {wxColourData, setColour, 1}},
- {2196, {wxColourData, setCustomColour, 2}},
- {2197, {wxPalette, new_0, 0}},
- {2198, {wxPalette, new_4, 4}},
- {2200, {wxPalette, destruct, 0}},
- {2201, {wxPalette, create, 4}},
- {2202, {wxPalette, getColoursCount, 0}},
- {2203, {wxPalette, getPixel, 3}},
- {2204, {wxPalette, getRGB, 4}},
- {2205, {wxPalette, isOk, 0}},
- {2209, {wxDirDialog, new, 2}},
- {2210, {wxDirDialog, destruct, 0}},
- {2211, {wxDirDialog, getPath, 0}},
- {2212, {wxDirDialog, getMessage, 0}},
- {2213, {wxDirDialog, setMessage, 1}},
- {2214, {wxDirDialog, setPath, 1}},
- {2218, {wxFileDialog, new, 2}},
- {2219, {wxFileDialog, destruct, 0}},
- {2220, {wxFileDialog, getDirectory, 0}},
- {2221, {wxFileDialog, getFilename, 0}},
- {2222, {wxFileDialog, getFilenames, 1}},
- {2223, {wxFileDialog, getFilterIndex, 0}},
- {2224, {wxFileDialog, getMessage, 0}},
- {2225, {wxFileDialog, getPath, 0}},
- {2226, {wxFileDialog, getPaths, 1}},
- {2227, {wxFileDialog, getWildcard, 0}},
- {2228, {wxFileDialog, setDirectory, 1}},
- {2229, {wxFileDialog, setFilename, 1}},
- {2230, {wxFileDialog, setFilterIndex, 1}},
- {2231, {wxFileDialog, setMessage, 1}},
- {2232, {wxFileDialog, setPath, 1}},
- {2233, {wxFileDialog, setWildcard, 1}},
- {2234, {wxPickerBase, setInternalMargin, 1}},
- {2235, {wxPickerBase, getInternalMargin, 0}},
- {2236, {wxPickerBase, setTextCtrlProportion, 1}},
- {2237, {wxPickerBase, setPickerCtrlProportion, 1}},
- {2238, {wxPickerBase, getTextCtrlProportion, 0}},
- {2239, {wxPickerBase, getPickerCtrlProportion, 0}},
- {2240, {wxPickerBase, hasTextCtrl, 0}},
- {2241, {wxPickerBase, getTextCtrl, 0}},
- {2242, {wxPickerBase, isTextCtrlGrowable, 0}},
- {2243, {wxPickerBase, setPickerCtrlGrowable, 1}},
- {2244, {wxPickerBase, setTextCtrlGrowable, 1}},
- {2245, {wxPickerBase, isPickerCtrlGrowable, 0}},
- {2246, {wxFilePickerCtrl, new_0, 0}},
- {2247, {wxFilePickerCtrl, new_3, 3}},
- {2248, {wxFilePickerCtrl, create, 3}},
- {2249, {wxFilePickerCtrl, getPath, 0}},
- {2250, {wxFilePickerCtrl, setPath, 1}},
- {2251, {wxFilePickerCtrl, 'Destroy', undefined}},
- {2252, {wxDirPickerCtrl, new_0, 0}},
- {2253, {wxDirPickerCtrl, new_3, 3}},
- {2254, {wxDirPickerCtrl, create, 3}},
- {2255, {wxDirPickerCtrl, getPath, 0}},
- {2256, {wxDirPickerCtrl, setPath, 1}},
- {2257, {wxDirPickerCtrl, 'Destroy', undefined}},
- {2258, {wxColourPickerCtrl, new_0, 0}},
- {2259, {wxColourPickerCtrl, new_3, 3}},
- {2260, {wxColourPickerCtrl, create, 3}},
- {2261, {wxColourPickerCtrl, getColour, 0}},
- {2262, {wxColourPickerCtrl, setColour_1_1, 1}},
- {2263, {wxColourPickerCtrl, setColour_1_0, 1}},
- {2264, {wxColourPickerCtrl, 'Destroy', undefined}},
- {2265, {wxDatePickerCtrl, new_0, 0}},
- {2266, {wxDatePickerCtrl, new_3, 3}},
- {2267, {wxDatePickerCtrl, getRange, 2}},
- {2268, {wxDatePickerCtrl, getValue, 0}},
- {2269, {wxDatePickerCtrl, setRange, 2}},
- {2270, {wxDatePickerCtrl, setValue, 1}},
- {2271, {wxDatePickerCtrl, 'Destroy', undefined}},
- {2272, {wxFontPickerCtrl, new_0, 0}},
- {2273, {wxFontPickerCtrl, new_3, 3}},
- {2274, {wxFontPickerCtrl, create, 3}},
- {2275, {wxFontPickerCtrl, getSelectedFont, 0}},
- {2276, {wxFontPickerCtrl, setSelectedFont, 1}},
- {2277, {wxFontPickerCtrl, getMaxPointSize, 0}},
- {2278, {wxFontPickerCtrl, setMaxPointSize, 1}},
- {2279, {wxFontPickerCtrl, 'Destroy', undefined}},
- {2282, {wxFindReplaceDialog, new_0, 0}},
- {2283, {wxFindReplaceDialog, new_4, 4}},
- {2284, {wxFindReplaceDialog, destruct, 0}},
- {2285, {wxFindReplaceDialog, create, 4}},
- {2286, {wxFindReplaceDialog, getData, 0}},
- {2287, {wxFindReplaceData, new_0, 0}},
- {2288, {wxFindReplaceData, new_1, 1}},
- {2289, {wxFindReplaceData, getFindString, 0}},
- {2290, {wxFindReplaceData, getReplaceString, 0}},
- {2291, {wxFindReplaceData, getFlags, 0}},
- {2292, {wxFindReplaceData, setFlags, 1}},
- {2293, {wxFindReplaceData, setFindString, 1}},
- {2294, {wxFindReplaceData, setReplaceString, 1}},
- {2295, {wxFindReplaceData, 'Destroy', undefined}},
- {2296, {wxMultiChoiceDialog, new_0, 0}},
- {2298, {wxMultiChoiceDialog, new_5, 5}},
- {2299, {wxMultiChoiceDialog, getSelections, 0}},
- {2300, {wxMultiChoiceDialog, setSelections, 1}},
- {2301, {wxMultiChoiceDialog, 'Destroy', undefined}},
- {2302, {wxSingleChoiceDialog, new_0, 0}},
- {2304, {wxSingleChoiceDialog, new_5, 5}},
- {2305, {wxSingleChoiceDialog, getSelection, 0}},
- {2306, {wxSingleChoiceDialog, getStringSelection, 0}},
- {2307, {wxSingleChoiceDialog, setSelection, 1}},
- {2308, {wxSingleChoiceDialog, 'Destroy', undefined}},
- {2309, {wxTextEntryDialog, new, 3}},
- {2310, {wxTextEntryDialog, getValue, 0}},
- {2311, {wxTextEntryDialog, setValue, 1}},
- {2312, {wxTextEntryDialog, 'Destroy', undefined}},
- {2313, {wxPasswordEntryDialog, new, 3}},
- {2314, {wxPasswordEntryDialog, 'Destroy', undefined}},
- {2315, {wxFontData, new_0, 0}},
- {2316, {wxFontData, new_1, 1}},
- {2317, {wxFontData, destruct, 0}},
- {2318, {wxFontData, enableEffects, 1}},
- {2319, {wxFontData, getAllowSymbols, 0}},
- {2320, {wxFontData, getColour, 0}},
- {2321, {wxFontData, getChosenFont, 0}},
- {2322, {wxFontData, getEnableEffects, 0}},
- {2323, {wxFontData, getInitialFont, 0}},
- {2324, {wxFontData, getShowHelp, 0}},
- {2325, {wxFontData, setAllowSymbols, 1}},
- {2326, {wxFontData, setChosenFont, 1}},
- {2327, {wxFontData, setColour, 1}},
- {2328, {wxFontData, setInitialFont, 1}},
- {2329, {wxFontData, setRange, 2}},
- {2330, {wxFontData, setShowHelp, 1}},
- {2334, {wxFontDialog, new_0, 0}},
- {2336, {wxFontDialog, new_2, 2}},
- {2338, {wxFontDialog, create, 2}},
- {2339, {wxFontDialog, getFontData, 0}},
- {2341, {wxFontDialog, 'Destroy', undefined}},
- {2342, {wxProgressDialog, new, 3}},
- {2343, {wxProgressDialog, destruct, 0}},
- {2344, {wxProgressDialog, resume, 0}},
- {2345, {wxProgressDialog, update_2, 2}},
- {2346, {wxProgressDialog, update_0, 0}},
- {2347, {wxMessageDialog, new, 3}},
- {2348, {wxMessageDialog, destruct, 0}},
- {2349, {wxPageSetupDialog, new, 2}},
- {2350, {wxPageSetupDialog, destruct, 0}},
- {2351, {wxPageSetupDialog, getPageSetupData, 0}},
- {2352, {wxPageSetupDialog, showModal, 0}},
- {2353, {wxPageSetupDialogData, new_0, 0}},
- {2354, {wxPageSetupDialogData, new_1_0, 1}},
- {2355, {wxPageSetupDialogData, new_1_1, 1}},
- {2356, {wxPageSetupDialogData, destruct, 0}},
- {2357, {wxPageSetupDialogData, enableHelp, 1}},
- {2358, {wxPageSetupDialogData, enableMargins, 1}},
- {2359, {wxPageSetupDialogData, enableOrientation, 1}},
- {2360, {wxPageSetupDialogData, enablePaper, 1}},
- {2361, {wxPageSetupDialogData, enablePrinter, 1}},
- {2362, {wxPageSetupDialogData, getDefaultMinMargins, 0}},
- {2363, {wxPageSetupDialogData, getEnableMargins, 0}},
- {2364, {wxPageSetupDialogData, getEnableOrientation, 0}},
- {2365, {wxPageSetupDialogData, getEnablePaper, 0}},
- {2366, {wxPageSetupDialogData, getEnablePrinter, 0}},
- {2367, {wxPageSetupDialogData, getEnableHelp, 0}},
- {2368, {wxPageSetupDialogData, getDefaultInfo, 0}},
- {2369, {wxPageSetupDialogData, getMarginTopLeft, 0}},
- {2370, {wxPageSetupDialogData, getMarginBottomRight, 0}},
- {2371, {wxPageSetupDialogData, getMinMarginTopLeft, 0}},
- {2372, {wxPageSetupDialogData, getMinMarginBottomRight, 0}},
- {2373, {wxPageSetupDialogData, getPaperId, 0}},
- {2374, {wxPageSetupDialogData, getPaperSize, 0}},
- {2376, {wxPageSetupDialogData, getPrintData, 0}},
- {2377, {wxPageSetupDialogData, isOk, 0}},
- {2378, {wxPageSetupDialogData, setDefaultInfo, 1}},
- {2379, {wxPageSetupDialogData, setDefaultMinMargins, 1}},
- {2380, {wxPageSetupDialogData, setMarginTopLeft, 1}},
- {2381, {wxPageSetupDialogData, setMarginBottomRight, 1}},
- {2382, {wxPageSetupDialogData, setMinMarginTopLeft, 1}},
- {2383, {wxPageSetupDialogData, setMinMarginBottomRight, 1}},
- {2384, {wxPageSetupDialogData, setPaperId, 1}},
- {2385, {wxPageSetupDialogData, setPaperSize_1_1, 1}},
- {2386, {wxPageSetupDialogData, setPaperSize_1_0, 1}},
- {2387, {wxPageSetupDialogData, setPrintData, 1}},
- {2388, {wxPrintDialog, new_2_0, 2}},
- {2389, {wxPrintDialog, new_2_1, 2}},
- {2390, {wxPrintDialog, destruct, 0}},
- {2391, {wxPrintDialog, getPrintDialogData, 0}},
- {2392, {wxPrintDialog, getPrintDC, 0}},
- {2393, {wxPrintDialogData, new_0, 0}},
- {2394, {wxPrintDialogData, new_1_1, 1}},
- {2395, {wxPrintDialogData, new_1_0, 1}},
- {2396, {wxPrintDialogData, destruct, 0}},
- {2397, {wxPrintDialogData, enableHelp, 1}},
- {2398, {wxPrintDialogData, enablePageNumbers, 1}},
- {2399, {wxPrintDialogData, enablePrintToFile, 1}},
- {2400, {wxPrintDialogData, enableSelection, 1}},
- {2401, {wxPrintDialogData, getAllPages, 0}},
- {2402, {wxPrintDialogData, getCollate, 0}},
- {2403, {wxPrintDialogData, getFromPage, 0}},
- {2404, {wxPrintDialogData, getMaxPage, 0}},
- {2405, {wxPrintDialogData, getMinPage, 0}},
- {2406, {wxPrintDialogData, getNoCopies, 0}},
- {2407, {wxPrintDialogData, getPrintData, 0}},
- {2408, {wxPrintDialogData, getPrintToFile, 0}},
- {2409, {wxPrintDialogData, getSelection, 0}},
- {2410, {wxPrintDialogData, getToPage, 0}},
- {2411, {wxPrintDialogData, isOk, 0}},
- {2412, {wxPrintDialogData, setCollate, 1}},
- {2413, {wxPrintDialogData, setFromPage, 1}},
- {2414, {wxPrintDialogData, setMaxPage, 1}},
- {2415, {wxPrintDialogData, setMinPage, 1}},
- {2416, {wxPrintDialogData, setNoCopies, 1}},
- {2417, {wxPrintDialogData, setPrintData, 1}},
- {2418, {wxPrintDialogData, setPrintToFile, 1}},
- {2419, {wxPrintDialogData, setSelection, 1}},
- {2420, {wxPrintDialogData, setToPage, 1}},
- {2421, {wxPrintData, new_0, 0}},
- {2422, {wxPrintData, new_1, 1}},
- {2423, {wxPrintData, destruct, 0}},
- {2424, {wxPrintData, getCollate, 0}},
- {2425, {wxPrintData, getBin, 0}},
- {2426, {wxPrintData, getColour, 0}},
- {2427, {wxPrintData, getDuplex, 0}},
- {2428, {wxPrintData, getNoCopies, 0}},
- {2429, {wxPrintData, getOrientation, 0}},
- {2430, {wxPrintData, getPaperId, 0}},
- {2431, {wxPrintData, getPrinterName, 0}},
- {2432, {wxPrintData, getQuality, 0}},
- {2433, {wxPrintData, isOk, 0}},
- {2434, {wxPrintData, setBin, 1}},
- {2435, {wxPrintData, setCollate, 1}},
- {2436, {wxPrintData, setColour, 1}},
- {2437, {wxPrintData, setDuplex, 1}},
- {2438, {wxPrintData, setNoCopies, 1}},
- {2439, {wxPrintData, setOrientation, 1}},
- {2440, {wxPrintData, setPaperId, 1}},
- {2441, {wxPrintData, setPrinterName, 1}},
- {2442, {wxPrintData, setQuality, 1}},
- {2445, {wxPrintPreview, new_2, 2}},
- {2446, {wxPrintPreview, new_3, 3}},
- {2448, {wxPrintPreview, destruct, 0}},
- {2449, {wxPrintPreview, getCanvas, 0}},
- {2450, {wxPrintPreview, getCurrentPage, 0}},
- {2451, {wxPrintPreview, getFrame, 0}},
- {2452, {wxPrintPreview, getMaxPage, 0}},
- {2453, {wxPrintPreview, getMinPage, 0}},
- {2454, {wxPrintPreview, getPrintout, 0}},
- {2455, {wxPrintPreview, getPrintoutForPrinting, 0}},
- {2456, {wxPrintPreview, isOk, 0}},
- {2457, {wxPrintPreview, paintPage, 2}},
- {2458, {wxPrintPreview, print, 1}},
- {2459, {wxPrintPreview, renderPage, 1}},
- {2460, {wxPrintPreview, setCanvas, 1}},
- {2461, {wxPrintPreview, setCurrentPage, 1}},
- {2462, {wxPrintPreview, setFrame, 1}},
- {2463, {wxPrintPreview, setPrintout, 1}},
- {2464, {wxPrintPreview, setZoom, 1}},
- {2465, {wxPreviewFrame, new, 3}},
- {2466, {wxPreviewFrame, destruct, 0}},
- {2467, {wxPreviewFrame, createControlBar, 0}},
- {2468, {wxPreviewFrame, createCanvas, 0}},
- {2469, {wxPreviewFrame, initialize, 0}},
- {2470, {wxPreviewFrame, onCloseWindow, 1}},
- {2471, {wxPreviewControlBar, new, 4}},
- {2472, {wxPreviewControlBar, destruct, 0}},
- {2473, {wxPreviewControlBar, createButtons, 0}},
- {2474, {wxPreviewControlBar, getPrintPreview, 0}},
- {2475, {wxPreviewControlBar, getZoomControl, 0}},
- {2476, {wxPreviewControlBar, setZoomControl, 1}},
- {2478, {wxPrinter, new, 1}},
- {2479, {wxPrinter, createAbortWindow, 2}},
- {2480, {wxPrinter, getAbort, 0}},
- {2481, {wxPrinter, getLastError, 0}},
- {2482, {wxPrinter, getPrintDialogData, 0}},
- {2483, {wxPrinter, print, 3}},
- {2484, {wxPrinter, printDialog, 1}},
- {2485, {wxPrinter, reportError, 3}},
- {2486, {wxPrinter, setup, 1}},
- {2487, {wxPrinter, 'Destroy', undefined}},
- {2488, {wxXmlResource, new_1, 1}},
- {2489, {wxXmlResource, new_2, 2}},
- {2490, {wxXmlResource, destruct, 0}},
- {2491, {wxXmlResource, attachUnknownControl, 3}},
- {2492, {wxXmlResource, clearHandlers, 0}},
- {2493, {wxXmlResource, compareVersion, 4}},
- {2494, {wxXmlResource, get, 0}},
- {2495, {wxXmlResource, getFlags, 0}},
- {2496, {wxXmlResource, getVersion, 0}},
- {2497, {wxXmlResource, getXRCID, 2}},
- {2498, {wxXmlResource, initAllHandlers, 0}},
- {2499, {wxXmlResource, load, 1}},
- {2500, {wxXmlResource, loadBitmap, 1}},
- {2501, {wxXmlResource, loadDialog_2, 2}},
- {2502, {wxXmlResource, loadDialog_3, 3}},
- {2503, {wxXmlResource, loadFrame_2, 2}},
- {2504, {wxXmlResource, loadFrame_3, 3}},
- {2505, {wxXmlResource, loadIcon, 1}},
- {2506, {wxXmlResource, loadMenu, 1}},
- {2507, {wxXmlResource, loadMenuBar_2, 2}},
- {2508, {wxXmlResource, loadMenuBar_1, 1}},
- {2509, {wxXmlResource, loadPanel_2, 2}},
- {2510, {wxXmlResource, loadPanel_3, 3}},
- {2511, {wxXmlResource, loadToolBar, 2}},
- {2512, {wxXmlResource, set, 1}},
- {2513, {wxXmlResource, setFlags, 1}},
- {2514, {wxXmlResource, unload, 1}},
- {2515, {wxXmlResource, xrcctrl, 3}},
- {2516, {wxHtmlEasyPrinting, new, 1}},
- {2517, {wxHtmlEasyPrinting, destruct, 0}},
- {2518, {wxHtmlEasyPrinting, getPrintData, 0}},
- {2519, {wxHtmlEasyPrinting, getPageSetupData, 0}},
- {2520, {wxHtmlEasyPrinting, previewFile, 1}},
- {2521, {wxHtmlEasyPrinting, previewText, 2}},
- {2522, {wxHtmlEasyPrinting, printFile, 1}},
- {2523, {wxHtmlEasyPrinting, printText, 2}},
- {2524, {wxHtmlEasyPrinting, pageSetup, 0}},
- {2525, {wxHtmlEasyPrinting, setFonts, 3}},
- {2526, {wxHtmlEasyPrinting, setHeader, 2}},
- {2527, {wxHtmlEasyPrinting, setFooter, 2}},
- {2529, {wxGLCanvas, new_2, 2}},
- {2530, {wxGLCanvas, new_3_1, 3}},
- {2531, {wxGLCanvas, new_3_0, 3}},
- {2532, {wxGLCanvas, getContext, 0}},
- {2534, {wxGLCanvas, setCurrent, 0}},
- {2535, {wxGLCanvas, swapBuffers, 0}},
- {2536, {wxGLCanvas, 'Destroy', undefined}},
- {2537, {wxAuiManager, new, 1}},
- {2538, {wxAuiManager, destruct, 0}},
- {2539, {wxAuiManager, addPane_2_1, 2}},
- {2540, {wxAuiManager, addPane_3, 3}},
- {2541, {wxAuiManager, addPane_2_0, 2}},
- {2542, {wxAuiManager, detachPane, 1}},
- {2543, {wxAuiManager, getAllPanes, 0}},
- {2544, {wxAuiManager, getArtProvider, 0}},
- {2545, {wxAuiManager, getDockSizeConstraint, 2}},
- {2546, {wxAuiManager, getFlags, 0}},
- {2547, {wxAuiManager, getManagedWindow, 0}},
- {2548, {wxAuiManager, getManager, 1}},
- {2549, {wxAuiManager, getPane_1_1, 1}},
- {2550, {wxAuiManager, getPane_1_0, 1}},
- {2551, {wxAuiManager, hideHint, 0}},
- {2552, {wxAuiManager, insertPane, 3}},
- {2553, {wxAuiManager, loadPaneInfo, 2}},
- {2554, {wxAuiManager, loadPerspective, 2}},
- {2555, {wxAuiManager, savePaneInfo, 1}},
- {2556, {wxAuiManager, savePerspective, 0}},
- {2557, {wxAuiManager, setArtProvider, 1}},
- {2558, {wxAuiManager, setDockSizeConstraint, 2}},
- {2559, {wxAuiManager, setFlags, 1}},
- {2560, {wxAuiManager, setManagedWindow, 1}},
- {2561, {wxAuiManager, showHint, 1}},
- {2562, {wxAuiManager, unInit, 0}},
- {2563, {wxAuiManager, update, 0}},
- {2564, {wxAuiPaneInfo, new_0, 0}},
- {2565, {wxAuiPaneInfo, new_1, 1}},
- {2566, {wxAuiPaneInfo, destruct, 0}},
- {2567, {wxAuiPaneInfo, bestSize_1, 1}},
- {2568, {wxAuiPaneInfo, bestSize_2, 2}},
- {2569, {wxAuiPaneInfo, bottom, 0}},
- {2570, {wxAuiPaneInfo, bottomDockable, 1}},
- {2571, {wxAuiPaneInfo, caption, 1}},
- {2572, {wxAuiPaneInfo, captionVisible, 1}},
- {2573, {wxAuiPaneInfo, centre, 0}},
- {2574, {wxAuiPaneInfo, centrePane, 0}},
- {2575, {wxAuiPaneInfo, closeButton, 1}},
- {2576, {wxAuiPaneInfo, defaultPane, 0}},
- {2577, {wxAuiPaneInfo, destroyOnClose, 1}},
- {2578, {wxAuiPaneInfo, direction, 1}},
- {2579, {wxAuiPaneInfo, dock, 0}},
- {2580, {wxAuiPaneInfo, dockable, 1}},
- {2581, {wxAuiPaneInfo, fixed, 0}},
- {2582, {wxAuiPaneInfo, float, 0}},
- {2583, {wxAuiPaneInfo, floatable, 1}},
- {2584, {wxAuiPaneInfo, floatingPosition_1, 1}},
- {2585, {wxAuiPaneInfo, floatingPosition_2, 2}},
- {2586, {wxAuiPaneInfo, floatingSize_1, 1}},
- {2587, {wxAuiPaneInfo, floatingSize_2, 2}},
- {2588, {wxAuiPaneInfo, gripper, 1}},
- {2589, {wxAuiPaneInfo, gripperTop, 1}},
- {2590, {wxAuiPaneInfo, hasBorder, 0}},
- {2591, {wxAuiPaneInfo, hasCaption, 0}},
- {2592, {wxAuiPaneInfo, hasCloseButton, 0}},
- {2593, {wxAuiPaneInfo, hasFlag, 1}},
- {2594, {wxAuiPaneInfo, hasGripper, 0}},
- {2595, {wxAuiPaneInfo, hasGripperTop, 0}},
- {2596, {wxAuiPaneInfo, hasMaximizeButton, 0}},
- {2597, {wxAuiPaneInfo, hasMinimizeButton, 0}},
- {2598, {wxAuiPaneInfo, hasPinButton, 0}},
- {2599, {wxAuiPaneInfo, hide, 0}},
- {2600, {wxAuiPaneInfo, isBottomDockable, 0}},
- {2601, {wxAuiPaneInfo, isDocked, 0}},
- {2602, {wxAuiPaneInfo, isFixed, 0}},
- {2603, {wxAuiPaneInfo, isFloatable, 0}},
- {2604, {wxAuiPaneInfo, isFloating, 0}},
- {2605, {wxAuiPaneInfo, isLeftDockable, 0}},
- {2606, {wxAuiPaneInfo, isMovable, 0}},
- {2607, {wxAuiPaneInfo, isOk, 0}},
- {2608, {wxAuiPaneInfo, isResizable, 0}},
- {2609, {wxAuiPaneInfo, isRightDockable, 0}},
- {2610, {wxAuiPaneInfo, isShown, 0}},
- {2611, {wxAuiPaneInfo, isToolbar, 0}},
- {2612, {wxAuiPaneInfo, isTopDockable, 0}},
- {2613, {wxAuiPaneInfo, layer, 1}},
- {2614, {wxAuiPaneInfo, left, 0}},
- {2615, {wxAuiPaneInfo, leftDockable, 1}},
- {2616, {wxAuiPaneInfo, maxSize_1, 1}},
- {2617, {wxAuiPaneInfo, maxSize_2, 2}},
- {2618, {wxAuiPaneInfo, maximizeButton, 1}},
- {2619, {wxAuiPaneInfo, minSize_1, 1}},
- {2620, {wxAuiPaneInfo, minSize_2, 2}},
- {2621, {wxAuiPaneInfo, minimizeButton, 1}},
- {2622, {wxAuiPaneInfo, movable, 1}},
- {2623, {wxAuiPaneInfo, name, 1}},
- {2624, {wxAuiPaneInfo, paneBorder, 1}},
- {2625, {wxAuiPaneInfo, pinButton, 1}},
- {2626, {wxAuiPaneInfo, position, 1}},
- {2627, {wxAuiPaneInfo, resizable, 1}},
- {2628, {wxAuiPaneInfo, right, 0}},
- {2629, {wxAuiPaneInfo, rightDockable, 1}},
- {2630, {wxAuiPaneInfo, row, 1}},
- {2631, {wxAuiPaneInfo, safeSet, 1}},
- {2632, {wxAuiPaneInfo, setFlag, 2}},
- {2633, {wxAuiPaneInfo, show, 1}},
- {2634, {wxAuiPaneInfo, toolbarPane, 0}},
- {2635, {wxAuiPaneInfo, top, 0}},
- {2636, {wxAuiPaneInfo, topDockable, 1}},
- {2637, {wxAuiPaneInfo, window, 1}},
- {2638, {wxAuiNotebook, new_0, 0}},
- {2639, {wxAuiNotebook, new_2, 2}},
- {2640, {wxAuiNotebook, addPage, 3}},
- {2641, {wxAuiNotebook, create, 2}},
- {2642, {wxAuiNotebook, deletePage, 1}},
- {2643, {wxAuiNotebook, getArtProvider, 0}},
- {2644, {wxAuiNotebook, getPage, 1}},
- {2645, {wxAuiNotebook, getPageBitmap, 1}},
- {2646, {wxAuiNotebook, getPageCount, 0}},
- {2647, {wxAuiNotebook, getPageIndex, 1}},
- {2648, {wxAuiNotebook, getPageText, 1}},
- {2649, {wxAuiNotebook, getSelection, 0}},
- {2650, {wxAuiNotebook, insertPage, 4}},
- {2651, {wxAuiNotebook, removePage, 1}},
- {2652, {wxAuiNotebook, setArtProvider, 1}},
- {2653, {wxAuiNotebook, setFont, 1}},
- {2654, {wxAuiNotebook, setPageBitmap, 2}},
- {2655, {wxAuiNotebook, setPageText, 2}},
- {2656, {wxAuiNotebook, setSelection, 1}},
- {2657, {wxAuiNotebook, setTabCtrlHeight, 1}},
- {2658, {wxAuiNotebook, setUniformBitmapSize, 1}},
- {2659, {wxAuiNotebook, 'Destroy', undefined}},
- {2660, {wxMDIParentFrame, new_0, 0}},
- {2661, {wxMDIParentFrame, new_4, 4}},
- {2662, {wxMDIParentFrame, destruct, 0}},
- {2663, {wxMDIParentFrame, activateNext, 0}},
- {2664, {wxMDIParentFrame, activatePrevious, 0}},
- {2665, {wxMDIParentFrame, arrangeIcons, 0}},
- {2666, {wxMDIParentFrame, cascade, 0}},
- {2667, {wxMDIParentFrame, create, 4}},
- {2668, {wxMDIParentFrame, getActiveChild, 0}},
- {2669, {wxMDIParentFrame, getClientWindow, 0}},
- {2670, {wxMDIParentFrame, tile, 1}},
- {2671, {wxMDIChildFrame, new_0, 0}},
- {2672, {wxMDIChildFrame, new_4, 4}},
- {2673, {wxMDIChildFrame, destruct, 0}},
- {2674, {wxMDIChildFrame, activate, 0}},
- {2675, {wxMDIChildFrame, create, 4}},
- {2676, {wxMDIChildFrame, maximize, 1}},
- {2677, {wxMDIChildFrame, restore, 0}},
- {2678, {wxMDIClientWindow, new_0, 0}},
- {2679, {wxMDIClientWindow, new_2, 2}},
- {2680, {wxMDIClientWindow, destruct, 0}},
- {2681, {wxMDIClientWindow, createClient, 2}},
- {2682, {wxLayoutAlgorithm, new, 0}},
- {2683, {wxLayoutAlgorithm, layoutFrame, 2}},
- {2684, {wxLayoutAlgorithm, layoutMDIFrame, 2}},
- {2685, {wxLayoutAlgorithm, layoutWindow, 2}},
- {2686, {wxLayoutAlgorithm, 'Destroy', undefined}},
- {2687, {wxEvent, getId, 0}},
- {2688, {wxEvent, getSkipped, 0}},
- {2689, {wxEvent, getTimestamp, 0}},
- {2690, {wxEvent, isCommandEvent, 0}},
- {2691, {wxEvent, resumePropagation, 1}},
- {2692, {wxEvent, shouldPropagate, 0}},
- {2693, {wxEvent, skip, 1}},
- {2694, {wxEvent, stopPropagation, 0}},
- {2695, {wxCommandEvent, getClientData, 0}},
- {2696, {wxCommandEvent, getExtraLong, 0}},
- {2697, {wxCommandEvent, getInt, 0}},
- {2698, {wxCommandEvent, getSelection, 0}},
- {2699, {wxCommandEvent, getString, 0}},
- {2700, {wxCommandEvent, isChecked, 0}},
- {2701, {wxCommandEvent, isSelection, 0}},
- {2702, {wxCommandEvent, setInt, 1}},
- {2703, {wxCommandEvent, setString, 1}},
- {2704, {wxScrollEvent, getOrientation, 0}},
- {2705, {wxScrollEvent, getPosition, 0}},
- {2706, {wxScrollWinEvent, getOrientation, 0}},
- {2707, {wxScrollWinEvent, getPosition, 0}},
- {2708, {wxMouseEvent, altDown, 0}},
- {2709, {wxMouseEvent, button, 1}},
- {2710, {wxMouseEvent, buttonDClick, 1}},
- {2711, {wxMouseEvent, buttonDown, 1}},
- {2712, {wxMouseEvent, buttonUp, 1}},
- {2713, {wxMouseEvent, cmdDown, 0}},
- {2714, {wxMouseEvent, controlDown, 0}},
- {2715, {wxMouseEvent, dragging, 0}},
- {2716, {wxMouseEvent, entering, 0}},
- {2717, {wxMouseEvent, getButton, 0}},
- {2720, {wxMouseEvent, getPosition, 0}},
- {2721, {wxMouseEvent, getLogicalPosition, 1}},
- {2722, {wxMouseEvent, getLinesPerAction, 0}},
- {2723, {wxMouseEvent, getWheelRotation, 0}},
- {2724, {wxMouseEvent, getWheelDelta, 0}},
- {2725, {wxMouseEvent, getX, 0}},
- {2726, {wxMouseEvent, getY, 0}},
- {2727, {wxMouseEvent, isButton, 0}},
- {2728, {wxMouseEvent, isPageScroll, 0}},
- {2729, {wxMouseEvent, leaving, 0}},
- {2730, {wxMouseEvent, leftDClick, 0}},
- {2731, {wxMouseEvent, leftDown, 0}},
- {2732, {wxMouseEvent, leftIsDown, 0}},
- {2733, {wxMouseEvent, leftUp, 0}},
- {2734, {wxMouseEvent, metaDown, 0}},
- {2735, {wxMouseEvent, middleDClick, 0}},
- {2736, {wxMouseEvent, middleDown, 0}},
- {2737, {wxMouseEvent, middleIsDown, 0}},
- {2738, {wxMouseEvent, middleUp, 0}},
- {2739, {wxMouseEvent, moving, 0}},
- {2740, {wxMouseEvent, rightDClick, 0}},
- {2741, {wxMouseEvent, rightDown, 0}},
- {2742, {wxMouseEvent, rightIsDown, 0}},
- {2743, {wxMouseEvent, rightUp, 0}},
- {2744, {wxMouseEvent, shiftDown, 0}},
- {2745, {wxSetCursorEvent, getCursor, 0}},
- {2746, {wxSetCursorEvent, getX, 0}},
- {2747, {wxSetCursorEvent, getY, 0}},
- {2748, {wxSetCursorEvent, hasCursor, 0}},
- {2749, {wxSetCursorEvent, setCursor, 1}},
- {2750, {wxKeyEvent, altDown, 0}},
- {2751, {wxKeyEvent, cmdDown, 0}},
- {2752, {wxKeyEvent, controlDown, 0}},
- {2753, {wxKeyEvent, getKeyCode, 0}},
- {2754, {wxKeyEvent, getModifiers, 0}},
- {2757, {wxKeyEvent, getPosition, 0}},
- {2758, {wxKeyEvent, getRawKeyCode, 0}},
- {2759, {wxKeyEvent, getRawKeyFlags, 0}},
- {2760, {wxKeyEvent, getUnicodeKey, 0}},
- {2761, {wxKeyEvent, getX, 0}},
- {2762, {wxKeyEvent, getY, 0}},
- {2763, {wxKeyEvent, hasModifiers, 0}},
- {2764, {wxKeyEvent, metaDown, 0}},
- {2765, {wxKeyEvent, shiftDown, 0}},
- {2766, {wxSizeEvent, getSize, 0}},
- {2767, {wxMoveEvent, getPosition, 0}},
- {2768, {wxEraseEvent, getDC, 0}},
- {2769, {wxFocusEvent, getWindow, 0}},
- {2770, {wxChildFocusEvent, getWindow, 0}},
- {2771, {wxMenuEvent, getMenu, 0}},
- {2772, {wxMenuEvent, getMenuId, 0}},
- {2773, {wxMenuEvent, isPopup, 0}},
- {2774, {wxCloseEvent, canVeto, 0}},
- {2775, {wxCloseEvent, getLoggingOff, 0}},
- {2776, {wxCloseEvent, setCanVeto, 1}},
- {2777, {wxCloseEvent, setLoggingOff, 1}},
- {2778, {wxCloseEvent, veto, 1}},
- {2779, {wxShowEvent, setShow, 1}},
- {2780, {wxShowEvent, getShow, 0}},
- {2781, {wxIconizeEvent, iconized, 0}},
- {2782, {wxJoystickEvent, buttonDown, 1}},
- {2783, {wxJoystickEvent, buttonIsDown, 1}},
- {2784, {wxJoystickEvent, buttonUp, 1}},
- {2785, {wxJoystickEvent, getButtonChange, 0}},
- {2786, {wxJoystickEvent, getButtonState, 0}},
- {2787, {wxJoystickEvent, getJoystick, 0}},
- {2788, {wxJoystickEvent, getPosition, 0}},
- {2789, {wxJoystickEvent, getZPosition, 0}},
- {2790, {wxJoystickEvent, isButton, 0}},
- {2791, {wxJoystickEvent, isMove, 0}},
- {2792, {wxJoystickEvent, isZMove, 0}},
- {2793, {wxUpdateUIEvent, canUpdate, 1}},
- {2794, {wxUpdateUIEvent, check, 1}},
- {2795, {wxUpdateUIEvent, enable, 1}},
- {2796, {wxUpdateUIEvent, show, 1}},
- {2797, {wxUpdateUIEvent, getChecked, 0}},
- {2798, {wxUpdateUIEvent, getEnabled, 0}},
- {2799, {wxUpdateUIEvent, getShown, 0}},
- {2800, {wxUpdateUIEvent, getSetChecked, 0}},
- {2801, {wxUpdateUIEvent, getSetEnabled, 0}},
- {2802, {wxUpdateUIEvent, getSetShown, 0}},
- {2803, {wxUpdateUIEvent, getSetText, 0}},
- {2804, {wxUpdateUIEvent, getText, 0}},
- {2805, {wxUpdateUIEvent, getMode, 0}},
- {2806, {wxUpdateUIEvent, getUpdateInterval, 0}},
- {2807, {wxUpdateUIEvent, resetUpdateTime, 0}},
- {2808, {wxUpdateUIEvent, setMode, 1}},
- {2809, {wxUpdateUIEvent, setText, 1}},
- {2810, {wxUpdateUIEvent, setUpdateInterval, 1}},
- {2811, {wxMouseCaptureChangedEvent, getCapturedWindow, 0}},
- {2812, {wxPaletteChangedEvent, setChangedWindow, 1}},
- {2813, {wxPaletteChangedEvent, getChangedWindow, 0}},
- {2814, {wxQueryNewPaletteEvent, setPaletteRealized, 1}},
- {2815, {wxQueryNewPaletteEvent, getPaletteRealized, 0}},
- {2816, {wxNavigationKeyEvent, getDirection, 0}},
- {2817, {wxNavigationKeyEvent, setDirection, 1}},
- {2818, {wxNavigationKeyEvent, isWindowChange, 0}},
- {2819, {wxNavigationKeyEvent, setWindowChange, 1}},
- {2820, {wxNavigationKeyEvent, isFromTab, 0}},
- {2821, {wxNavigationKeyEvent, setFromTab, 1}},
- {2822, {wxNavigationKeyEvent, getCurrentFocus, 0}},
- {2823, {wxNavigationKeyEvent, setCurrentFocus, 1}},
- {2824, {wxHelpEvent, getOrigin, 0}},
- {2825, {wxHelpEvent, getPosition, 0}},
- {2826, {wxHelpEvent, setOrigin, 1}},
- {2827, {wxHelpEvent, setPosition, 1}},
- {2828, {wxContextMenuEvent, getPosition, 0}},
- {2829, {wxContextMenuEvent, setPosition, 1}},
- {2830, {wxIdleEvent, canSend, 1}},
- {2831, {wxIdleEvent, getMode, 0}},
- {2832, {wxIdleEvent, requestMore, 1}},
- {2833, {wxIdleEvent, moreRequested, 0}},
- {2834, {wxIdleEvent, setMode, 1}},
- {2835, {wxGridEvent, altDown, 0}},
- {2836, {wxGridEvent, controlDown, 0}},
- {2837, {wxGridEvent, getCol, 0}},
- {2838, {wxGridEvent, getPosition, 0}},
- {2839, {wxGridEvent, getRow, 0}},
- {2840, {wxGridEvent, metaDown, 0}},
- {2841, {wxGridEvent, selecting, 0}},
- {2842, {wxGridEvent, shiftDown, 0}},
- {2843, {wxNotifyEvent, allow, 0}},
- {2844, {wxNotifyEvent, isAllowed, 0}},
- {2845, {wxNotifyEvent, veto, 0}},
- {2846, {wxSashEvent, getEdge, 0}},
- {2847, {wxSashEvent, getDragRect, 0}},
- {2848, {wxSashEvent, getDragStatus, 0}},
- {2849, {wxListEvent, getCacheFrom, 0}},
- {2850, {wxListEvent, getCacheTo, 0}},
- {2851, {wxListEvent, getKeyCode, 0}},
- {2852, {wxListEvent, getIndex, 0}},
- {2853, {wxListEvent, getColumn, 0}},
- {2854, {wxListEvent, getPoint, 0}},
- {2855, {wxListEvent, getLabel, 0}},
- {2856, {wxListEvent, getText, 0}},
- {2857, {wxListEvent, getImage, 0}},
- {2858, {wxListEvent, getData, 0}},
- {2859, {wxListEvent, getMask, 0}},
- {2860, {wxListEvent, getItem, 0}},
- {2861, {wxListEvent, isEditCancelled, 0}},
- {2862, {wxDateEvent, getDate, 0}},
- {2863, {wxCalendarEvent, getWeekDay, 0}},
- {2864, {wxFileDirPickerEvent, getPath, 0}},
- {2865, {wxColourPickerEvent, getColour, 0}},
- {2866, {wxFontPickerEvent, getFont, 0}},
- {2867, {wxStyledTextEvent, getPosition, 0}},
- {2868, {wxStyledTextEvent, getKey, 0}},
- {2869, {wxStyledTextEvent, getModifiers, 0}},
- {2870, {wxStyledTextEvent, getModificationType, 0}},
- {2871, {wxStyledTextEvent, getText, 0}},
- {2872, {wxStyledTextEvent, getLength, 0}},
- {2873, {wxStyledTextEvent, getLinesAdded, 0}},
- {2874, {wxStyledTextEvent, getLine, 0}},
- {2875, {wxStyledTextEvent, getFoldLevelNow, 0}},
- {2876, {wxStyledTextEvent, getFoldLevelPrev, 0}},
- {2877, {wxStyledTextEvent, getMargin, 0}},
- {2878, {wxStyledTextEvent, getMessage, 0}},
- {2879, {wxStyledTextEvent, getWParam, 0}},
- {2880, {wxStyledTextEvent, getLParam, 0}},
- {2881, {wxStyledTextEvent, getListType, 0}},
- {2882, {wxStyledTextEvent, getX, 0}},
- {2883, {wxStyledTextEvent, getY, 0}},
- {2884, {wxStyledTextEvent, getDragText, 0}},
- {2885, {wxStyledTextEvent, getDragAllowMove, 0}},
- {2886, {wxStyledTextEvent, getDragResult, 0}},
- {2887, {wxStyledTextEvent, getShift, 0}},
- {2888, {wxStyledTextEvent, getControl, 0}},
- {2889, {wxStyledTextEvent, getAlt, 0}},
- {2890, {utils, getKeyState, 1}},
- {2891, {utils, getMousePosition, 2}},
- {2892, {utils, getMouseState, 0}},
- {2893, {utils, setDetectableAutoRepeat, 1}},
- {2894, {utils, bell, 0}},
- {2895, {utils, findMenuItemId, 3}},
- {2896, {utils, genericFindWindowAtPoint, 1}},
- {2897, {utils, findWindowAtPoint, 1}},
- {2898, {utils, beginBusyCursor, 1}},
- {2899, {utils, endBusyCursor, 0}},
- {2900, {utils, isBusy, 0}},
- {2901, {utils, shutdown, 1}},
- {2902, {utils, shell, 1}},
- {2903, {utils, launchDefaultBrowser, 2}},
- {2904, {utils, getEmailAddress, 0}},
- {2905, {utils, getUserId, 0}},
- {2906, {utils, getHomeDir, 0}},
- {2907, {utils, newId, 0}},
- {2908, {utils, registerId, 1}},
- {2909, {utils, getCurrentId, 0}},
- {2910, {utils, getOsDescription, 0}},
- {2911, {utils, isPlatformLittleEndian, 0}},
- {2912, {utils, isPlatform64Bit, 0}},
- {2913, {wxPrintout, new, 1}},
- {2914, {wxPrintout, destruct, 0}},
- {2915, {wxPrintout, getDC, 0}},
- {2916, {wxPrintout, getPageSizeMM, 2}},
- {2917, {wxPrintout, getPageSizePixels, 2}},
- {2918, {wxPrintout, getPaperRectPixels, 0}},
- {2919, {wxPrintout, getPPIPrinter, 2}},
- {2920, {wxPrintout, getPPIScreen, 2}},
- {2921, {wxPrintout, getTitle, 0}},
- {2922, {wxPrintout, isPreview, 0}},
- {2923, {wxPrintout, fitThisSizeToPaper, 1}},
- {2924, {wxPrintout, fitThisSizeToPage, 1}},
- {2925, {wxPrintout, fitThisSizeToPageMargins, 2}},
- {2926, {wxPrintout, mapScreenSizeToPaper, 0}},
- {2927, {wxPrintout, mapScreenSizeToPage, 0}},
- {2928, {wxPrintout, mapScreenSizeToPageMargins, 1}},
- {2929, {wxPrintout, mapScreenSizeToDevice, 0}},
- {2930, {wxPrintout, getLogicalPaperRect, 0}},
- {2931, {wxPrintout, getLogicalPageRect, 0}},
- {2932, {wxPrintout, getLogicalPageMarginsRect, 1}},
- {2933, {wxPrintout, setLogicalOrigin, 2}},
- {2934, {wxPrintout, offsetLogicalOrigin, 2}},
- {2935, {wxStyledTextCtrl, new_2, 2}},
- {2936, {wxStyledTextCtrl, new_0, 0}},
- {2937, {wxStyledTextCtrl, destruct, 0}},
- {2938, {wxStyledTextCtrl, create, 2}},
- {2939, {wxStyledTextCtrl, addText, 1}},
- {2940, {wxStyledTextCtrl, addStyledText, 1}},
- {2941, {wxStyledTextCtrl, insertText, 2}},
- {2942, {wxStyledTextCtrl, clearAll, 0}},
- {2943, {wxStyledTextCtrl, clearDocumentStyle, 0}},
- {2944, {wxStyledTextCtrl, getLength, 0}},
- {2945, {wxStyledTextCtrl, getCharAt, 1}},
- {2946, {wxStyledTextCtrl, getCurrentPos, 0}},
- {2947, {wxStyledTextCtrl, getAnchor, 0}},
- {2948, {wxStyledTextCtrl, getStyleAt, 1}},
- {2949, {wxStyledTextCtrl, redo, 0}},
- {2950, {wxStyledTextCtrl, setUndoCollection, 1}},
- {2951, {wxStyledTextCtrl, selectAll, 0}},
- {2952, {wxStyledTextCtrl, setSavePoint, 0}},
- {2953, {wxStyledTextCtrl, getStyledText, 2}},
- {2954, {wxStyledTextCtrl, canRedo, 0}},
- {2955, {wxStyledTextCtrl, markerLineFromHandle, 1}},
- {2956, {wxStyledTextCtrl, markerDeleteHandle, 1}},
- {2957, {wxStyledTextCtrl, getUndoCollection, 0}},
- {2958, {wxStyledTextCtrl, getViewWhiteSpace, 0}},
- {2959, {wxStyledTextCtrl, setViewWhiteSpace, 1}},
- {2960, {wxStyledTextCtrl, positionFromPoint, 1}},
- {2961, {wxStyledTextCtrl, positionFromPointClose, 2}},
- {2962, {wxStyledTextCtrl, gotoLine, 1}},
- {2963, {wxStyledTextCtrl, gotoPos, 1}},
- {2964, {wxStyledTextCtrl, setAnchor, 1}},
- {2965, {wxStyledTextCtrl, getCurLine, 1}},
- {2966, {wxStyledTextCtrl, getEndStyled, 0}},
- {2967, {wxStyledTextCtrl, convertEOLs, 1}},
- {2968, {wxStyledTextCtrl, getEOLMode, 0}},
- {2969, {wxStyledTextCtrl, setEOLMode, 1}},
- {2970, {wxStyledTextCtrl, startStyling, 2}},
- {2971, {wxStyledTextCtrl, setStyling, 2}},
- {2972, {wxStyledTextCtrl, getBufferedDraw, 0}},
- {2973, {wxStyledTextCtrl, setBufferedDraw, 1}},
- {2974, {wxStyledTextCtrl, setTabWidth, 1}},
- {2975, {wxStyledTextCtrl, getTabWidth, 0}},
- {2976, {wxStyledTextCtrl, setCodePage, 1}},
- {2977, {wxStyledTextCtrl, markerDefine, 3}},
- {2978, {wxStyledTextCtrl, markerSetForeground, 2}},
- {2979, {wxStyledTextCtrl, markerSetBackground, 2}},
- {2980, {wxStyledTextCtrl, markerAdd, 2}},
- {2981, {wxStyledTextCtrl, markerDelete, 2}},
- {2982, {wxStyledTextCtrl, markerDeleteAll, 1}},
- {2983, {wxStyledTextCtrl, markerGet, 1}},
- {2984, {wxStyledTextCtrl, markerNext, 2}},
- {2985, {wxStyledTextCtrl, markerPrevious, 2}},
- {2986, {wxStyledTextCtrl, markerDefineBitmap, 2}},
- {2987, {wxStyledTextCtrl, markerAddSet, 2}},
- {2988, {wxStyledTextCtrl, markerSetAlpha, 2}},
- {2989, {wxStyledTextCtrl, setMarginType, 2}},
- {2990, {wxStyledTextCtrl, getMarginType, 1}},
- {2991, {wxStyledTextCtrl, setMarginWidth, 2}},
- {2992, {wxStyledTextCtrl, getMarginWidth, 1}},
- {2993, {wxStyledTextCtrl, setMarginMask, 2}},
- {2994, {wxStyledTextCtrl, getMarginMask, 1}},
- {2995, {wxStyledTextCtrl, setMarginSensitive, 2}},
- {2996, {wxStyledTextCtrl, getMarginSensitive, 1}},
- {2997, {wxStyledTextCtrl, styleClearAll, 0}},
- {2998, {wxStyledTextCtrl, styleSetForeground, 2}},
- {2999, {wxStyledTextCtrl, styleSetBackground, 2}},
- {3000, {wxStyledTextCtrl, styleSetBold, 2}},
- {3001, {wxStyledTextCtrl, styleSetItalic, 2}},
- {3002, {wxStyledTextCtrl, styleSetSize, 2}},
- {3003, {wxStyledTextCtrl, styleSetFaceName, 2}},
- {3004, {wxStyledTextCtrl, styleSetEOLFilled, 2}},
- {3005, {wxStyledTextCtrl, styleResetDefault, 0}},
- {3006, {wxStyledTextCtrl, styleSetUnderline, 2}},
- {3007, {wxStyledTextCtrl, styleSetCase, 2}},
- {3008, {wxStyledTextCtrl, styleSetHotSpot, 2}},
- {3009, {wxStyledTextCtrl, setSelForeground, 2}},
- {3010, {wxStyledTextCtrl, setSelBackground, 2}},
- {3011, {wxStyledTextCtrl, getSelAlpha, 0}},
- {3012, {wxStyledTextCtrl, setSelAlpha, 1}},
- {3013, {wxStyledTextCtrl, setCaretForeground, 1}},
- {3014, {wxStyledTextCtrl, cmdKeyAssign, 3}},
- {3015, {wxStyledTextCtrl, cmdKeyClear, 2}},
- {3016, {wxStyledTextCtrl, cmdKeyClearAll, 0}},
- {3017, {wxStyledTextCtrl, setStyleBytes, 2}},
- {3018, {wxStyledTextCtrl, styleSetVisible, 2}},
- {3019, {wxStyledTextCtrl, getCaretPeriod, 0}},
- {3020, {wxStyledTextCtrl, setCaretPeriod, 1}},
- {3021, {wxStyledTextCtrl, setWordChars, 1}},
- {3022, {wxStyledTextCtrl, beginUndoAction, 0}},
- {3023, {wxStyledTextCtrl, endUndoAction, 0}},
- {3024, {wxStyledTextCtrl, indicatorSetStyle, 2}},
- {3025, {wxStyledTextCtrl, indicatorGetStyle, 1}},
- {3026, {wxStyledTextCtrl, indicatorSetForeground, 2}},
- {3027, {wxStyledTextCtrl, indicatorGetForeground, 1}},
- {3028, {wxStyledTextCtrl, setWhitespaceForeground, 2}},
- {3029, {wxStyledTextCtrl, setWhitespaceBackground, 2}},
- {3030, {wxStyledTextCtrl, getStyleBits, 0}},
- {3031, {wxStyledTextCtrl, setLineState, 2}},
- {3032, {wxStyledTextCtrl, getLineState, 1}},
- {3033, {wxStyledTextCtrl, getMaxLineState, 0}},
- {3034, {wxStyledTextCtrl, getCaretLineVisible, 0}},
- {3035, {wxStyledTextCtrl, setCaretLineVisible, 1}},
- {3036, {wxStyledTextCtrl, getCaretLineBackground, 0}},
- {3037, {wxStyledTextCtrl, setCaretLineBackground, 1}},
- {3038, {wxStyledTextCtrl, autoCompShow, 2}},
- {3039, {wxStyledTextCtrl, autoCompCancel, 0}},
- {3040, {wxStyledTextCtrl, autoCompActive, 0}},
- {3041, {wxStyledTextCtrl, autoCompPosStart, 0}},
- {3042, {wxStyledTextCtrl, autoCompComplete, 0}},
- {3043, {wxStyledTextCtrl, autoCompStops, 1}},
- {3044, {wxStyledTextCtrl, autoCompSetSeparator, 1}},
- {3045, {wxStyledTextCtrl, autoCompGetSeparator, 0}},
- {3046, {wxStyledTextCtrl, autoCompSelect, 1}},
- {3047, {wxStyledTextCtrl, autoCompSetCancelAtStart, 1}},
- {3048, {wxStyledTextCtrl, autoCompGetCancelAtStart, 0}},
- {3049, {wxStyledTextCtrl, autoCompSetFillUps, 1}},
- {3050, {wxStyledTextCtrl, autoCompSetChooseSingle, 1}},
- {3051, {wxStyledTextCtrl, autoCompGetChooseSingle, 0}},
- {3052, {wxStyledTextCtrl, autoCompSetIgnoreCase, 1}},
- {3053, {wxStyledTextCtrl, autoCompGetIgnoreCase, 0}},
- {3054, {wxStyledTextCtrl, userListShow, 2}},
- {3055, {wxStyledTextCtrl, autoCompSetAutoHide, 1}},
- {3056, {wxStyledTextCtrl, autoCompGetAutoHide, 0}},
- {3057, {wxStyledTextCtrl, autoCompSetDropRestOfWord, 1}},
- {3058, {wxStyledTextCtrl, autoCompGetDropRestOfWord, 0}},
- {3059, {wxStyledTextCtrl, registerImage, 2}},
- {3060, {wxStyledTextCtrl, clearRegisteredImages, 0}},
- {3061, {wxStyledTextCtrl, autoCompGetTypeSeparator, 0}},
- {3062, {wxStyledTextCtrl, autoCompSetTypeSeparator, 1}},
- {3063, {wxStyledTextCtrl, autoCompSetMaxWidth, 1}},
- {3064, {wxStyledTextCtrl, autoCompGetMaxWidth, 0}},
- {3065, {wxStyledTextCtrl, autoCompSetMaxHeight, 1}},
- {3066, {wxStyledTextCtrl, autoCompGetMaxHeight, 0}},
- {3067, {wxStyledTextCtrl, setIndent, 1}},
- {3068, {wxStyledTextCtrl, getIndent, 0}},
- {3069, {wxStyledTextCtrl, setUseTabs, 1}},
- {3070, {wxStyledTextCtrl, getUseTabs, 0}},
- {3071, {wxStyledTextCtrl, setLineIndentation, 2}},
- {3072, {wxStyledTextCtrl, getLineIndentation, 1}},
- {3073, {wxStyledTextCtrl, getLineIndentPosition, 1}},
- {3074, {wxStyledTextCtrl, getColumn, 1}},
- {3075, {wxStyledTextCtrl, setUseHorizontalScrollBar, 1}},
- {3076, {wxStyledTextCtrl, getUseHorizontalScrollBar, 0}},
- {3077, {wxStyledTextCtrl, setIndentationGuides, 1}},
- {3078, {wxStyledTextCtrl, getIndentationGuides, 0}},
- {3079, {wxStyledTextCtrl, setHighlightGuide, 1}},
- {3080, {wxStyledTextCtrl, getHighlightGuide, 0}},
- {3081, {wxStyledTextCtrl, getLineEndPosition, 1}},
- {3082, {wxStyledTextCtrl, getCodePage, 0}},
- {3083, {wxStyledTextCtrl, getCaretForeground, 0}},
- {3084, {wxStyledTextCtrl, getReadOnly, 0}},
- {3085, {wxStyledTextCtrl, setCurrentPos, 1}},
- {3086, {wxStyledTextCtrl, setSelectionStart, 1}},
- {3087, {wxStyledTextCtrl, getSelectionStart, 0}},
- {3088, {wxStyledTextCtrl, setSelectionEnd, 1}},
- {3089, {wxStyledTextCtrl, getSelectionEnd, 0}},
- {3090, {wxStyledTextCtrl, setPrintMagnification, 1}},
- {3091, {wxStyledTextCtrl, getPrintMagnification, 0}},
- {3092, {wxStyledTextCtrl, setPrintColourMode, 1}},
- {3093, {wxStyledTextCtrl, getPrintColourMode, 0}},
- {3094, {wxStyledTextCtrl, findText, 4}},
- {3095, {wxStyledTextCtrl, formatRange, 7}},
- {3096, {wxStyledTextCtrl, getFirstVisibleLine, 0}},
- {3097, {wxStyledTextCtrl, getLine, 1}},
- {3098, {wxStyledTextCtrl, getLineCount, 0}},
- {3099, {wxStyledTextCtrl, setMarginLeft, 1}},
- {3100, {wxStyledTextCtrl, getMarginLeft, 0}},
- {3101, {wxStyledTextCtrl, setMarginRight, 1}},
- {3102, {wxStyledTextCtrl, getMarginRight, 0}},
- {3103, {wxStyledTextCtrl, getModify, 0}},
- {3104, {wxStyledTextCtrl, setSelection, 2}},
- {3105, {wxStyledTextCtrl, getSelectedText, 0}},
- {3106, {wxStyledTextCtrl, getTextRange, 2}},
- {3107, {wxStyledTextCtrl, hideSelection, 1}},
- {3108, {wxStyledTextCtrl, lineFromPosition, 1}},
- {3109, {wxStyledTextCtrl, positionFromLine, 1}},
- {3110, {wxStyledTextCtrl, lineScroll, 2}},
- {3111, {wxStyledTextCtrl, ensureCaretVisible, 0}},
- {3112, {wxStyledTextCtrl, replaceSelection, 1}},
- {3113, {wxStyledTextCtrl, setReadOnly, 1}},
- {3114, {wxStyledTextCtrl, canPaste, 0}},
- {3115, {wxStyledTextCtrl, canUndo, 0}},
- {3116, {wxStyledTextCtrl, emptyUndoBuffer, 0}},
- {3117, {wxStyledTextCtrl, undo, 0}},
- {3118, {wxStyledTextCtrl, cut, 0}},
- {3119, {wxStyledTextCtrl, copy, 0}},
- {3120, {wxStyledTextCtrl, paste, 0}},
- {3121, {wxStyledTextCtrl, clear, 0}},
- {3122, {wxStyledTextCtrl, setText, 1}},
- {3123, {wxStyledTextCtrl, getText, 0}},
- {3124, {wxStyledTextCtrl, getTextLength, 0}},
- {3125, {wxStyledTextCtrl, getOvertype, 0}},
- {3126, {wxStyledTextCtrl, setCaretWidth, 1}},
- {3127, {wxStyledTextCtrl, getCaretWidth, 0}},
- {3128, {wxStyledTextCtrl, setTargetStart, 1}},
- {3129, {wxStyledTextCtrl, getTargetStart, 0}},
- {3130, {wxStyledTextCtrl, setTargetEnd, 1}},
- {3131, {wxStyledTextCtrl, getTargetEnd, 0}},
- {3132, {wxStyledTextCtrl, replaceTarget, 1}},
- {3133, {wxStyledTextCtrl, searchInTarget, 1}},
- {3134, {wxStyledTextCtrl, setSearchFlags, 1}},
- {3135, {wxStyledTextCtrl, getSearchFlags, 0}},
- {3136, {wxStyledTextCtrl, callTipShow, 2}},
- {3137, {wxStyledTextCtrl, callTipCancel, 0}},
- {3138, {wxStyledTextCtrl, callTipActive, 0}},
- {3139, {wxStyledTextCtrl, callTipPosAtStart, 0}},
- {3140, {wxStyledTextCtrl, callTipSetHighlight, 2}},
- {3141, {wxStyledTextCtrl, callTipSetBackground, 1}},
- {3142, {wxStyledTextCtrl, callTipSetForeground, 1}},
- {3143, {wxStyledTextCtrl, callTipSetForegroundHighlight, 1}},
- {3144, {wxStyledTextCtrl, callTipUseStyle, 1}},
- {3145, {wxStyledTextCtrl, visibleFromDocLine, 1}},
- {3146, {wxStyledTextCtrl, docLineFromVisible, 1}},
- {3147, {wxStyledTextCtrl, wrapCount, 1}},
- {3148, {wxStyledTextCtrl, setFoldLevel, 2}},
- {3149, {wxStyledTextCtrl, getFoldLevel, 1}},
- {3150, {wxStyledTextCtrl, getLastChild, 2}},
- {3151, {wxStyledTextCtrl, getFoldParent, 1}},
- {3152, {wxStyledTextCtrl, showLines, 2}},
- {3153, {wxStyledTextCtrl, hideLines, 2}},
- {3154, {wxStyledTextCtrl, getLineVisible, 1}},
- {3155, {wxStyledTextCtrl, setFoldExpanded, 2}},
- {3156, {wxStyledTextCtrl, getFoldExpanded, 1}},
- {3157, {wxStyledTextCtrl, toggleFold, 1}},
- {3158, {wxStyledTextCtrl, ensureVisible, 1}},
- {3159, {wxStyledTextCtrl, setFoldFlags, 1}},
- {3160, {wxStyledTextCtrl, ensureVisibleEnforcePolicy, 1}},
- {3161, {wxStyledTextCtrl, setTabIndents, 1}},
- {3162, {wxStyledTextCtrl, getTabIndents, 0}},
- {3163, {wxStyledTextCtrl, setBackSpaceUnIndents, 1}},
- {3164, {wxStyledTextCtrl, getBackSpaceUnIndents, 0}},
- {3165, {wxStyledTextCtrl, setMouseDwellTime, 1}},
- {3166, {wxStyledTextCtrl, getMouseDwellTime, 0}},
- {3167, {wxStyledTextCtrl, wordStartPosition, 2}},
- {3168, {wxStyledTextCtrl, wordEndPosition, 2}},
- {3169, {wxStyledTextCtrl, setWrapMode, 1}},
- {3170, {wxStyledTextCtrl, getWrapMode, 0}},
- {3171, {wxStyledTextCtrl, setWrapVisualFlags, 1}},
- {3172, {wxStyledTextCtrl, getWrapVisualFlags, 0}},
- {3173, {wxStyledTextCtrl, setWrapVisualFlagsLocation, 1}},
- {3174, {wxStyledTextCtrl, getWrapVisualFlagsLocation, 0}},
- {3175, {wxStyledTextCtrl, setWrapStartIndent, 1}},
- {3176, {wxStyledTextCtrl, getWrapStartIndent, 0}},
- {3177, {wxStyledTextCtrl, setLayoutCache, 1}},
- {3178, {wxStyledTextCtrl, getLayoutCache, 0}},
- {3179, {wxStyledTextCtrl, setScrollWidth, 1}},
- {3180, {wxStyledTextCtrl, getScrollWidth, 0}},
- {3181, {wxStyledTextCtrl, textWidth, 2}},
- {3182, {wxStyledTextCtrl, getEndAtLastLine, 0}},
- {3183, {wxStyledTextCtrl, textHeight, 1}},
- {3184, {wxStyledTextCtrl, setUseVerticalScrollBar, 1}},
- {3185, {wxStyledTextCtrl, getUseVerticalScrollBar, 0}},
- {3186, {wxStyledTextCtrl, appendText, 1}},
- {3187, {wxStyledTextCtrl, getTwoPhaseDraw, 0}},
- {3188, {wxStyledTextCtrl, setTwoPhaseDraw, 1}},
- {3189, {wxStyledTextCtrl, targetFromSelection, 0}},
- {3190, {wxStyledTextCtrl, linesJoin, 0}},
- {3191, {wxStyledTextCtrl, linesSplit, 1}},
- {3192, {wxStyledTextCtrl, setFoldMarginColour, 2}},
- {3193, {wxStyledTextCtrl, setFoldMarginHiColour, 2}},
- {3194, {wxStyledTextCtrl, lineDown, 0}},
- {3195, {wxStyledTextCtrl, lineDownExtend, 0}},
- {3196, {wxStyledTextCtrl, lineUp, 0}},
- {3197, {wxStyledTextCtrl, lineUpExtend, 0}},
- {3198, {wxStyledTextCtrl, charLeft, 0}},
- {3199, {wxStyledTextCtrl, charLeftExtend, 0}},
- {3200, {wxStyledTextCtrl, charRight, 0}},
- {3201, {wxStyledTextCtrl, charRightExtend, 0}},
- {3202, {wxStyledTextCtrl, wordLeft, 0}},
- {3203, {wxStyledTextCtrl, wordLeftExtend, 0}},
- {3204, {wxStyledTextCtrl, wordRight, 0}},
- {3205, {wxStyledTextCtrl, wordRightExtend, 0}},
- {3206, {wxStyledTextCtrl, home, 0}},
- {3207, {wxStyledTextCtrl, homeExtend, 0}},
- {3208, {wxStyledTextCtrl, lineEnd, 0}},
- {3209, {wxStyledTextCtrl, lineEndExtend, 0}},
- {3210, {wxStyledTextCtrl, documentStart, 0}},
- {3211, {wxStyledTextCtrl, documentStartExtend, 0}},
- {3212, {wxStyledTextCtrl, documentEnd, 0}},
- {3213, {wxStyledTextCtrl, documentEndExtend, 0}},
- {3214, {wxStyledTextCtrl, pageUp, 0}},
- {3215, {wxStyledTextCtrl, pageUpExtend, 0}},
- {3216, {wxStyledTextCtrl, pageDown, 0}},
- {3217, {wxStyledTextCtrl, pageDownExtend, 0}},
- {3218, {wxStyledTextCtrl, editToggleOvertype, 0}},
- {3219, {wxStyledTextCtrl, cancel, 0}},
- {3220, {wxStyledTextCtrl, deleteBack, 0}},
- {3221, {wxStyledTextCtrl, tab, 0}},
- {3222, {wxStyledTextCtrl, backTab, 0}},
- {3223, {wxStyledTextCtrl, newLine, 0}},
- {3224, {wxStyledTextCtrl, formFeed, 0}},
- {3225, {wxStyledTextCtrl, vCHome, 0}},
- {3226, {wxStyledTextCtrl, vCHomeExtend, 0}},
- {3227, {wxStyledTextCtrl, zoomIn, 0}},
- {3228, {wxStyledTextCtrl, zoomOut, 0}},
- {3229, {wxStyledTextCtrl, delWordLeft, 0}},
- {3230, {wxStyledTextCtrl, delWordRight, 0}},
- {3231, {wxStyledTextCtrl, lineCut, 0}},
- {3232, {wxStyledTextCtrl, lineDelete, 0}},
- {3233, {wxStyledTextCtrl, lineTranspose, 0}},
- {3234, {wxStyledTextCtrl, lineDuplicate, 0}},
- {3235, {wxStyledTextCtrl, lowerCase, 0}},
- {3236, {wxStyledTextCtrl, upperCase, 0}},
- {3237, {wxStyledTextCtrl, lineScrollDown, 0}},
- {3238, {wxStyledTextCtrl, lineScrollUp, 0}},
- {3239, {wxStyledTextCtrl, deleteBackNotLine, 0}},
- {3240, {wxStyledTextCtrl, homeDisplay, 0}},
- {3241, {wxStyledTextCtrl, homeDisplayExtend, 0}},
- {3242, {wxStyledTextCtrl, lineEndDisplay, 0}},
- {3243, {wxStyledTextCtrl, lineEndDisplayExtend, 0}},
- {3244, {wxStyledTextCtrl, homeWrapExtend, 0}},
- {3245, {wxStyledTextCtrl, lineEndWrap, 0}},
- {3246, {wxStyledTextCtrl, lineEndWrapExtend, 0}},
- {3247, {wxStyledTextCtrl, vCHomeWrap, 0}},
- {3248, {wxStyledTextCtrl, vCHomeWrapExtend, 0}},
- {3249, {wxStyledTextCtrl, lineCopy, 0}},
- {3250, {wxStyledTextCtrl, moveCaretInsideView, 0}},
- {3251, {wxStyledTextCtrl, lineLength, 1}},
- {3252, {wxStyledTextCtrl, braceHighlight, 2}},
- {3253, {wxStyledTextCtrl, braceBadLight, 1}},
- {3254, {wxStyledTextCtrl, braceMatch, 1}},
- {3255, {wxStyledTextCtrl, getViewEOL, 0}},
- {3256, {wxStyledTextCtrl, setViewEOL, 1}},
- {3257, {wxStyledTextCtrl, setModEventMask, 1}},
- {3258, {wxStyledTextCtrl, getEdgeColumn, 0}},
- {3259, {wxStyledTextCtrl, setEdgeColumn, 1}},
- {3260, {wxStyledTextCtrl, getEdgeMode, 0}},
- {3261, {wxStyledTextCtrl, getEdgeColour, 0}},
- {3262, {wxStyledTextCtrl, setEdgeColour, 1}},
- {3263, {wxStyledTextCtrl, searchAnchor, 0}},
- {3264, {wxStyledTextCtrl, searchNext, 2}},
- {3265, {wxStyledTextCtrl, searchPrev, 2}},
- {3266, {wxStyledTextCtrl, linesOnScreen, 0}},
- {3267, {wxStyledTextCtrl, usePopUp, 1}},
- {3268, {wxStyledTextCtrl, selectionIsRectangle, 0}},
- {3269, {wxStyledTextCtrl, setZoom, 1}},
- {3270, {wxStyledTextCtrl, getZoom, 0}},
- {3271, {wxStyledTextCtrl, getModEventMask, 0}},
- {3272, {wxStyledTextCtrl, setSTCFocus, 1}},
- {3273, {wxStyledTextCtrl, getSTCFocus, 0}},
- {3274, {wxStyledTextCtrl, setStatus, 1}},
- {3275, {wxStyledTextCtrl, getStatus, 0}},
- {3276, {wxStyledTextCtrl, setMouseDownCaptures, 1}},
- {3277, {wxStyledTextCtrl, getMouseDownCaptures, 0}},
- {3278, {wxStyledTextCtrl, setSTCCursor, 1}},
- {3279, {wxStyledTextCtrl, getSTCCursor, 0}},
- {3280, {wxStyledTextCtrl, setControlCharSymbol, 1}},
- {3281, {wxStyledTextCtrl, getControlCharSymbol, 0}},
- {3282, {wxStyledTextCtrl, wordPartLeft, 0}},
- {3283, {wxStyledTextCtrl, wordPartLeftExtend, 0}},
- {3284, {wxStyledTextCtrl, wordPartRight, 0}},
- {3285, {wxStyledTextCtrl, wordPartRightExtend, 0}},
- {3286, {wxStyledTextCtrl, setVisiblePolicy, 2}},
- {3287, {wxStyledTextCtrl, delLineLeft, 0}},
- {3288, {wxStyledTextCtrl, delLineRight, 0}},
- {3289, {wxStyledTextCtrl, getXOffset, 0}},
- {3290, {wxStyledTextCtrl, chooseCaretX, 0}},
- {3291, {wxStyledTextCtrl, setXCaretPolicy, 2}},
- {3292, {wxStyledTextCtrl, setYCaretPolicy, 2}},
- {3293, {wxStyledTextCtrl, getPrintWrapMode, 0}},
- {3294, {wxStyledTextCtrl, setHotspotActiveForeground, 2}},
- {3295, {wxStyledTextCtrl, setHotspotActiveBackground, 2}},
- {3296, {wxStyledTextCtrl, setHotspotActiveUnderline, 1}},
- {3297, {wxStyledTextCtrl, setHotspotSingleLine, 1}},
- {3298, {wxStyledTextCtrl, paraDownExtend, 0}},
- {3299, {wxStyledTextCtrl, paraUp, 0}},
- {3300, {wxStyledTextCtrl, paraUpExtend, 0}},
- {3301, {wxStyledTextCtrl, positionBefore, 1}},
- {3302, {wxStyledTextCtrl, positionAfter, 1}},
- {3303, {wxStyledTextCtrl, copyRange, 2}},
- {3304, {wxStyledTextCtrl, copyText, 2}},
- {3305, {wxStyledTextCtrl, setSelectionMode, 1}},
- {3306, {wxStyledTextCtrl, getSelectionMode, 0}},
- {3307, {wxStyledTextCtrl, lineDownRectExtend, 0}},
- {3308, {wxStyledTextCtrl, lineUpRectExtend, 0}},
- {3309, {wxStyledTextCtrl, charLeftRectExtend, 0}},
- {3310, {wxStyledTextCtrl, charRightRectExtend, 0}},
- {3311, {wxStyledTextCtrl, homeRectExtend, 0}},
- {3312, {wxStyledTextCtrl, vCHomeRectExtend, 0}},
- {3313, {wxStyledTextCtrl, lineEndRectExtend, 0}},
- {3314, {wxStyledTextCtrl, pageUpRectExtend, 0}},
- {3315, {wxStyledTextCtrl, pageDownRectExtend, 0}},
- {3316, {wxStyledTextCtrl, stutteredPageUp, 0}},
- {3317, {wxStyledTextCtrl, stutteredPageUpExtend, 0}},
- {3318, {wxStyledTextCtrl, stutteredPageDown, 0}},
- {3319, {wxStyledTextCtrl, stutteredPageDownExtend, 0}},
- {3320, {wxStyledTextCtrl, wordLeftEnd, 0}},
- {3321, {wxStyledTextCtrl, wordLeftEndExtend, 0}},
- {3322, {wxStyledTextCtrl, wordRightEnd, 0}},
- {3323, {wxStyledTextCtrl, wordRightEndExtend, 0}},
- {3324, {wxStyledTextCtrl, setWhitespaceChars, 1}},
- {3325, {wxStyledTextCtrl, setCharsDefault, 0}},
- {3326, {wxStyledTextCtrl, autoCompGetCurrent, 0}},
- {3327, {wxStyledTextCtrl, allocate, 1}},
- {3328, {wxStyledTextCtrl, findColumn, 2}},
- {3329, {wxStyledTextCtrl, getCaretSticky, 0}},
- {3330, {wxStyledTextCtrl, setCaretSticky, 1}},
- {3331, {wxStyledTextCtrl, toggleCaretSticky, 0}},
- {3332, {wxStyledTextCtrl, setPasteConvertEndings, 1}},
- {3333, {wxStyledTextCtrl, getPasteConvertEndings, 0}},
- {3334, {wxStyledTextCtrl, selectionDuplicate, 0}},
- {3335, {wxStyledTextCtrl, setCaretLineBackAlpha, 1}},
- {3336, {wxStyledTextCtrl, getCaretLineBackAlpha, 0}},
- {3337, {wxStyledTextCtrl, startRecord, 0}},
- {3338, {wxStyledTextCtrl, stopRecord, 0}},
- {3339, {wxStyledTextCtrl, setLexer, 1}},
- {3340, {wxStyledTextCtrl, getLexer, 0}},
- {3341, {wxStyledTextCtrl, colourise, 2}},
- {3342, {wxStyledTextCtrl, setProperty, 2}},
- {3343, {wxStyledTextCtrl, setKeyWords, 2}},
- {3344, {wxStyledTextCtrl, setLexerLanguage, 1}},
- {3345, {wxStyledTextCtrl, getProperty, 1}},
- {3346, {wxStyledTextCtrl, getStyleBitsNeeded, 0}},
- {3347, {wxStyledTextCtrl, getCurrentLine, 0}},
- {3348, {wxStyledTextCtrl, styleSetSpec, 2}},
- {3349, {wxStyledTextCtrl, styleSetFont, 2}},
- {3350, {wxStyledTextCtrl, styleSetFontAttr, 7}},
- {3351, {wxStyledTextCtrl, styleSetCharacterSet, 2}},
- {3352, {wxStyledTextCtrl, styleSetFontEncoding, 2}},
- {3353, {wxStyledTextCtrl, cmdKeyExecute, 1}},
- {3354, {wxStyledTextCtrl, setMargins, 2}},
- {3355, {wxStyledTextCtrl, getSelection, 2}},
- {3356, {wxStyledTextCtrl, pointFromPosition, 1}},
- {3357, {wxStyledTextCtrl, scrollToLine, 1}},
- {3358, {wxStyledTextCtrl, scrollToColumn, 1}},
- {3359, {wxStyledTextCtrl, sendMsg, 2}},
- {3360, {wxStyledTextCtrl, setVScrollBar, 1}},
- {3361, {wxStyledTextCtrl, setHScrollBar, 1}},
- {3362, {wxStyledTextCtrl, getLastKeydownProcessed, 0}},
- {3363, {wxStyledTextCtrl, setLastKeydownProcessed, 1}},
- {3364, {wxStyledTextCtrl, saveFile, 1}},
- {3365, {wxStyledTextCtrl, loadFile, 1}},
- {3366, {wxStyledTextCtrl, doDragOver, 3}},
- {3367, {wxStyledTextCtrl, doDropText, 3}},
- {3368, {wxStyledTextCtrl, getUseAntiAliasing, 0}},
- {3369, {wxStyledTextCtrl, addTextRaw, 1}},
- {3370, {wxStyledTextCtrl, insertTextRaw, 2}},
- {3371, {wxStyledTextCtrl, getCurLineRaw, 1}},
- {3372, {wxStyledTextCtrl, getLineRaw, 1}},
- {3373, {wxStyledTextCtrl, getSelectedTextRaw, 0}},
- {3374, {wxStyledTextCtrl, getTextRangeRaw, 2}},
- {3375, {wxStyledTextCtrl, setTextRaw, 1}},
- {3376, {wxStyledTextCtrl, getTextRaw, 0}},
- {3377, {wxStyledTextCtrl, appendTextRaw, 1}},
- {3378, {wxArtProvider, getBitmap, 2}},
- {3379, {wxArtProvider, getIcon, 2}},
- {3380, {wxTreeEvent, getKeyCode, 0}},
- {3381, {wxTreeEvent, getItem, 0}},
- {3382, {wxTreeEvent, getKeyEvent, 0}},
- {3383, {wxTreeEvent, getLabel, 0}},
- {3384, {wxTreeEvent, getOldItem, 0}},
- {3385, {wxTreeEvent, getPoint, 0}},
- {3386, {wxTreeEvent, isEditCancelled, 0}},
- {3387, {wxTreeEvent, setToolTip, 1}},
- {3388, {wxNotebookEvent, getOldSelection, 0}},
- {3389, {wxNotebookEvent, getSelection, 0}},
- {3390, {wxNotebookEvent, setOldSelection, 1}},
- {3391, {wxNotebookEvent, setSelection, 1}},
- {3392, {wxFileDataObject, new, 0}},
- {3393, {wxFileDataObject, addFile, 1}},
- {3394, {wxFileDataObject, getFilenames, 0}},
- {3395, {wxFileDataObject, 'Destroy', undefined}},
- {3396, {wxTextDataObject, new, 1}},
- {3397, {wxTextDataObject, getTextLength, 0}},
- {3398, {wxTextDataObject, getText, 0}},
- {3399, {wxTextDataObject, setText, 1}},
- {3400, {wxTextDataObject, 'Destroy', undefined}},
- {3401, {wxBitmapDataObject, new_1_1, 1}},
- {3402, {wxBitmapDataObject, new_1_0, 1}},
- {3403, {wxBitmapDataObject, getBitmap, 0}},
- {3404, {wxBitmapDataObject, setBitmap, 1}},
- {3405, {wxBitmapDataObject, 'Destroy', undefined}},
- {3407, {wxClipboard, new, 0}},
- {3408, {wxClipboard, destruct, 0}},
- {3409, {wxClipboard, addData, 1}},
- {3410, {wxClipboard, clear, 0}},
- {3411, {wxClipboard, close, 0}},
- {3412, {wxClipboard, flush, 0}},
- {3413, {wxClipboard, getData, 1}},
- {3414, {wxClipboard, isOpened, 0}},
- {3415, {wxClipboard, open, 0}},
- {3416, {wxClipboard, setData, 1}},
- {3418, {wxClipboard, usePrimarySelection, 1}},
- {3419, {wxClipboard, isSupported, 1}},
- {3420, {wxClipboard, get, 0}},
- {3421, {wxSpinEvent, getPosition, 0}},
- {3422, {wxSpinEvent, setPosition, 1}},
- {3423, {wxSplitterWindow, new_0, 0}},
- {3424, {wxSplitterWindow, new_2, 2}},
- {3425, {wxSplitterWindow, destruct, 0}},
- {3426, {wxSplitterWindow, create, 2}},
- {3427, {wxSplitterWindow, getMinimumPaneSize, 0}},
- {3428, {wxSplitterWindow, getSashGravity, 0}},
- {3429, {wxSplitterWindow, getSashPosition, 0}},
- {3430, {wxSplitterWindow, getSplitMode, 0}},
- {3431, {wxSplitterWindow, getWindow1, 0}},
- {3432, {wxSplitterWindow, getWindow2, 0}},
- {3433, {wxSplitterWindow, initialize, 1}},
- {3434, {wxSplitterWindow, isSplit, 0}},
- {3435, {wxSplitterWindow, replaceWindow, 2}},
- {3436, {wxSplitterWindow, setSashGravity, 1}},
- {3437, {wxSplitterWindow, setSashPosition, 2}},
- {3438, {wxSplitterWindow, setSashSize, 1}},
- {3439, {wxSplitterWindow, setMinimumPaneSize, 1}},
- {3440, {wxSplitterWindow, setSplitMode, 1}},
- {3441, {wxSplitterWindow, splitHorizontally, 3}},
- {3442, {wxSplitterWindow, splitVertically, 3}},
- {3443, {wxSplitterWindow, unsplit, 1}},
- {3444, {wxSplitterWindow, updateSize, 0}},
- {3445, {wxSplitterEvent, getSashPosition, 0}},
- {3446, {wxSplitterEvent, getX, 0}},
- {3447, {wxSplitterEvent, getY, 0}},
- {3448, {wxSplitterEvent, getWindowBeingRemoved, 0}},
- {3449, {wxSplitterEvent, setSashPosition, 1}},
- {3450, {wxHtmlWindow, new_0, 0}},
- {3451, {wxHtmlWindow, new_2, 2}},
- {3452, {wxHtmlWindow, appendToPage, 1}},
- {3453, {wxHtmlWindow, getOpenedAnchor, 0}},
- {3454, {wxHtmlWindow, getOpenedPage, 0}},
- {3455, {wxHtmlWindow, getOpenedPageTitle, 0}},
- {3456, {wxHtmlWindow, getRelatedFrame, 0}},
- {3457, {wxHtmlWindow, historyBack, 0}},
- {3458, {wxHtmlWindow, historyCanBack, 0}},
- {3459, {wxHtmlWindow, historyCanForward, 0}},
- {3460, {wxHtmlWindow, historyClear, 0}},
- {3461, {wxHtmlWindow, historyForward, 0}},
- {3462, {wxHtmlWindow, loadFile, 1}},
- {3463, {wxHtmlWindow, loadPage, 1}},
- {3464, {wxHtmlWindow, selectAll, 0}},
- {3465, {wxHtmlWindow, selectionToText, 0}},
- {3466, {wxHtmlWindow, selectLine, 1}},
- {3467, {wxHtmlWindow, selectWord, 1}},
- {3468, {wxHtmlWindow, setBorders, 1}},
- {3469, {wxHtmlWindow, setFonts, 3}},
- {3470, {wxHtmlWindow, setPage, 1}},
- {3471, {wxHtmlWindow, setRelatedFrame, 2}},
- {3472, {wxHtmlWindow, setRelatedStatusBar, 1}},
- {3473, {wxHtmlWindow, toText, 0}},
- {3474, {wxHtmlWindow, 'Destroy', undefined}},
- {3475, {wxHtmlLinkEvent, getLinkInfo, 0}},
- {3476, {wxSystemSettings, getColour, 1}},
- {3477, {wxSystemSettings, getFont, 1}},
- {3478, {wxSystemSettings, getMetric, 2}},
- {3479, {wxSystemSettings, getScreenType, 0}},
- {3480, {wxAuiNotebookEvent, setSelection, 1}},
- {3481, {wxAuiNotebookEvent, getSelection, 0}},
- {3482, {wxAuiNotebookEvent, setOldSelection, 1}},
- {3483, {wxAuiNotebookEvent, getOldSelection, 0}},
- {3484, {wxAuiNotebookEvent, setDragSource, 1}},
- {3485, {wxAuiNotebookEvent, getDragSource, 0}},
- {3486, {wxAuiManagerEvent, setManager, 1}},
- {3487, {wxAuiManagerEvent, getManager, 0}},
- {3488, {wxAuiManagerEvent, setPane, 1}},
- {3489, {wxAuiManagerEvent, getPane, 0}},
- {3490, {wxAuiManagerEvent, setButton, 1}},
- {3491, {wxAuiManagerEvent, getButton, 0}},
- {3492, {wxAuiManagerEvent, setDC, 1}},
- {3493, {wxAuiManagerEvent, getDC, 0}},
- {3494, {wxAuiManagerEvent, veto, 1}},
- {3495, {wxAuiManagerEvent, getVeto, 0}},
- {3496, {wxAuiManagerEvent, setCanVeto, 1}},
- {3497, {wxAuiManagerEvent, canVeto, 0}},
- {3498, {wxLogNull, new, 0}},
- {3499, {wxLogNull, 'Destroy', undefined}},
+ {1757, {wxListItemAttr, new_0, 0}},
+ {1758, {wxListItemAttr, new_3, 3}},
+ {1759, {wxListItemAttr, getBackgroundColour, 0}},
+ {1760, {wxListItemAttr, getFont, 0}},
+ {1761, {wxListItemAttr, getTextColour, 0}},
+ {1762, {wxListItemAttr, hasBackgroundColour, 0}},
+ {1763, {wxListItemAttr, hasFont, 0}},
+ {1764, {wxListItemAttr, hasTextColour, 0}},
+ {1765, {wxListItemAttr, setBackgroundColour, 1}},
+ {1766, {wxListItemAttr, setFont, 1}},
+ {1767, {wxListItemAttr, setTextColour, 1}},
+ {1768, {wxListItemAttr, 'Destroy', undefined}},
+ {1769, {wxImageList, new_0, 0}},
+ {1770, {wxImageList, new_3, 3}},
+ {1771, {wxImageList, add_1, 1}},
+ {1772, {wxImageList, add_2_0, 2}},
+ {1773, {wxImageList, add_2_1, 2}},
+ {1774, {wxImageList, create, 3}},
+ {1776, {wxImageList, draw, 5}},
+ {1777, {wxImageList, getBitmap, 1}},
+ {1778, {wxImageList, getIcon, 1}},
+ {1779, {wxImageList, getImageCount, 0}},
+ {1780, {wxImageList, getSize, 3}},
+ {1781, {wxImageList, remove, 1}},
+ {1782, {wxImageList, removeAll, 0}},
+ {1783, {wxImageList, replace_2, 2}},
+ {1784, {wxImageList, replace_3, 3}},
+ {1785, {wxImageList, 'Destroy', undefined}},
+ {1786, {wxTextAttr, new_0, 0}},
+ {1787, {wxTextAttr, new_2, 2}},
+ {1788, {wxTextAttr, getAlignment, 0}},
+ {1789, {wxTextAttr, getBackgroundColour, 0}},
+ {1790, {wxTextAttr, getFont, 0}},
+ {1791, {wxTextAttr, getLeftIndent, 0}},
+ {1792, {wxTextAttr, getLeftSubIndent, 0}},
+ {1793, {wxTextAttr, getRightIndent, 0}},
+ {1794, {wxTextAttr, getTabs, 0}},
+ {1795, {wxTextAttr, getTextColour, 0}},
+ {1796, {wxTextAttr, hasBackgroundColour, 0}},
+ {1797, {wxTextAttr, hasFont, 0}},
+ {1798, {wxTextAttr, hasTextColour, 0}},
+ {1799, {wxTextAttr, getFlags, 0}},
+ {1800, {wxTextAttr, isDefault, 0}},
+ {1801, {wxTextAttr, setAlignment, 1}},
+ {1802, {wxTextAttr, setBackgroundColour, 1}},
+ {1803, {wxTextAttr, setFlags, 1}},
+ {1804, {wxTextAttr, setFont, 2}},
+ {1805, {wxTextAttr, setLeftIndent, 2}},
+ {1806, {wxTextAttr, setRightIndent, 1}},
+ {1807, {wxTextAttr, setTabs, 1}},
+ {1808, {wxTextAttr, setTextColour, 1}},
+ {1809, {wxTextAttr, 'Destroy', undefined}},
+ {1811, {wxTextCtrl, new_3, 3}},
+ {1812, {wxTextCtrl, new_0, 0}},
+ {1814, {wxTextCtrl, destruct, 0}},
+ {1815, {wxTextCtrl, appendText, 1}},
+ {1816, {wxTextCtrl, canCopy, 0}},
+ {1817, {wxTextCtrl, canCut, 0}},
+ {1818, {wxTextCtrl, canPaste, 0}},
+ {1819, {wxTextCtrl, canRedo, 0}},
+ {1820, {wxTextCtrl, canUndo, 0}},
+ {1821, {wxTextCtrl, clear, 0}},
+ {1822, {wxTextCtrl, copy, 0}},
+ {1823, {wxTextCtrl, create, 3}},
+ {1824, {wxTextCtrl, cut, 0}},
+ {1825, {wxTextCtrl, discardEdits, 0}},
+ {1826, {wxTextCtrl, emulateKeyPress, 1}},
+ {1827, {wxTextCtrl, getDefaultStyle, 0}},
+ {1828, {wxTextCtrl, getInsertionPoint, 0}},
+ {1829, {wxTextCtrl, getLastPosition, 0}},
+ {1830, {wxTextCtrl, getLineLength, 1}},
+ {1831, {wxTextCtrl, getLineText, 1}},
+ {1832, {wxTextCtrl, getNumberOfLines, 0}},
+ {1833, {wxTextCtrl, getRange, 2}},
+ {1834, {wxTextCtrl, getSelection, 2}},
+ {1835, {wxTextCtrl, getStringSelection, 0}},
+ {1836, {wxTextCtrl, getStyle, 2}},
+ {1837, {wxTextCtrl, getValue, 0}},
+ {1838, {wxTextCtrl, isEditable, 0}},
+ {1839, {wxTextCtrl, isModified, 0}},
+ {1840, {wxTextCtrl, isMultiLine, 0}},
+ {1841, {wxTextCtrl, isSingleLine, 0}},
+ {1842, {wxTextCtrl, loadFile, 2}},
+ {1843, {wxTextCtrl, markDirty, 0}},
+ {1844, {wxTextCtrl, paste, 0}},
+ {1845, {wxTextCtrl, positionToXY, 3}},
+ {1846, {wxTextCtrl, redo, 0}},
+ {1847, {wxTextCtrl, remove, 2}},
+ {1848, {wxTextCtrl, replace, 3}},
+ {1849, {wxTextCtrl, saveFile, 1}},
+ {1850, {wxTextCtrl, setDefaultStyle, 1}},
+ {1851, {wxTextCtrl, setEditable, 1}},
+ {1852, {wxTextCtrl, setInsertionPoint, 1}},
+ {1853, {wxTextCtrl, setInsertionPointEnd, 0}},
+ {1855, {wxTextCtrl, setMaxLength, 1}},
+ {1856, {wxTextCtrl, setSelection, 2}},
+ {1857, {wxTextCtrl, setStyle, 3}},
+ {1858, {wxTextCtrl, setValue, 1}},
+ {1859, {wxTextCtrl, showPosition, 1}},
+ {1860, {wxTextCtrl, undo, 0}},
+ {1861, {wxTextCtrl, writeText, 1}},
+ {1862, {wxTextCtrl, xYToPosition, 2}},
+ {1865, {wxNotebook, new_0, 0}},
+ {1866, {wxNotebook, new_3, 3}},
+ {1867, {wxNotebook, destruct, 0}},
+ {1868, {wxNotebook, addPage, 3}},
+ {1869, {wxNotebook, advanceSelection, 1}},
+ {1870, {wxNotebook, assignImageList, 1}},
+ {1871, {wxNotebook, create, 3}},
+ {1872, {wxNotebook, deleteAllPages, 0}},
+ {1873, {wxNotebook, deletePage, 1}},
+ {1874, {wxNotebook, removePage, 1}},
+ {1875, {wxNotebook, getCurrentPage, 0}},
+ {1876, {wxNotebook, getImageList, 0}},
+ {1878, {wxNotebook, getPage, 1}},
+ {1879, {wxNotebook, getPageCount, 0}},
+ {1880, {wxNotebook, getPageImage, 1}},
+ {1881, {wxNotebook, getPageText, 1}},
+ {1882, {wxNotebook, getRowCount, 0}},
+ {1883, {wxNotebook, getSelection, 0}},
+ {1884, {wxNotebook, getThemeBackgroundColour, 0}},
+ {1886, {wxNotebook, hitTest, 2}},
+ {1888, {wxNotebook, insertPage, 4}},
+ {1889, {wxNotebook, setImageList, 1}},
+ {1890, {wxNotebook, setPadding, 1}},
+ {1891, {wxNotebook, setPageSize, 1}},
+ {1892, {wxNotebook, setPageImage, 2}},
+ {1893, {wxNotebook, setPageText, 2}},
+ {1894, {wxNotebook, setSelection, 1}},
+ {1895, {wxNotebook, changeSelection, 1}},
+ {1896, {wxChoicebook, new_0, 0}},
+ {1897, {wxChoicebook, new_3, 3}},
+ {1898, {wxChoicebook, addPage, 3}},
+ {1899, {wxChoicebook, advanceSelection, 1}},
+ {1900, {wxChoicebook, assignImageList, 1}},
+ {1901, {wxChoicebook, create, 3}},
+ {1902, {wxChoicebook, deleteAllPages, 0}},
+ {1903, {wxChoicebook, deletePage, 1}},
+ {1904, {wxChoicebook, removePage, 1}},
+ {1905, {wxChoicebook, getCurrentPage, 0}},
+ {1906, {wxChoicebook, getImageList, 0}},
+ {1908, {wxChoicebook, getPage, 1}},
+ {1909, {wxChoicebook, getPageCount, 0}},
+ {1910, {wxChoicebook, getPageImage, 1}},
+ {1911, {wxChoicebook, getPageText, 1}},
+ {1912, {wxChoicebook, getSelection, 0}},
+ {1913, {wxChoicebook, hitTest, 2}},
+ {1914, {wxChoicebook, insertPage, 4}},
+ {1915, {wxChoicebook, setImageList, 1}},
+ {1916, {wxChoicebook, setPageSize, 1}},
+ {1917, {wxChoicebook, setPageImage, 2}},
+ {1918, {wxChoicebook, setPageText, 2}},
+ {1919, {wxChoicebook, setSelection, 1}},
+ {1920, {wxChoicebook, changeSelection, 1}},
+ {1921, {wxChoicebook, 'Destroy', undefined}},
+ {1922, {wxToolbook, new_0, 0}},
+ {1923, {wxToolbook, new_3, 3}},
+ {1924, {wxToolbook, addPage, 3}},
+ {1925, {wxToolbook, advanceSelection, 1}},
+ {1926, {wxToolbook, assignImageList, 1}},
+ {1927, {wxToolbook, create, 3}},
+ {1928, {wxToolbook, deleteAllPages, 0}},
+ {1929, {wxToolbook, deletePage, 1}},
+ {1930, {wxToolbook, removePage, 1}},
+ {1931, {wxToolbook, getCurrentPage, 0}},
+ {1932, {wxToolbook, getImageList, 0}},
+ {1934, {wxToolbook, getPage, 1}},
+ {1935, {wxToolbook, getPageCount, 0}},
+ {1936, {wxToolbook, getPageImage, 1}},
+ {1937, {wxToolbook, getPageText, 1}},
+ {1938, {wxToolbook, getSelection, 0}},
+ {1940, {wxToolbook, hitTest, 2}},
+ {1941, {wxToolbook, insertPage, 4}},
+ {1942, {wxToolbook, setImageList, 1}},
+ {1943, {wxToolbook, setPageSize, 1}},
+ {1944, {wxToolbook, setPageImage, 2}},
+ {1945, {wxToolbook, setPageText, 2}},
+ {1946, {wxToolbook, setSelection, 1}},
+ {1947, {wxToolbook, changeSelection, 1}},
+ {1948, {wxToolbook, 'Destroy', undefined}},
+ {1949, {wxListbook, new_0, 0}},
+ {1950, {wxListbook, new_3, 3}},
+ {1951, {wxListbook, addPage, 3}},
+ {1952, {wxListbook, advanceSelection, 1}},
+ {1953, {wxListbook, assignImageList, 1}},
+ {1954, {wxListbook, create, 3}},
+ {1955, {wxListbook, deleteAllPages, 0}},
+ {1956, {wxListbook, deletePage, 1}},
+ {1957, {wxListbook, removePage, 1}},
+ {1958, {wxListbook, getCurrentPage, 0}},
+ {1959, {wxListbook, getImageList, 0}},
+ {1961, {wxListbook, getPage, 1}},
+ {1962, {wxListbook, getPageCount, 0}},
+ {1963, {wxListbook, getPageImage, 1}},
+ {1964, {wxListbook, getPageText, 1}},
+ {1965, {wxListbook, getSelection, 0}},
+ {1967, {wxListbook, hitTest, 2}},
+ {1968, {wxListbook, insertPage, 4}},
+ {1969, {wxListbook, setImageList, 1}},
+ {1970, {wxListbook, setPageSize, 1}},
+ {1971, {wxListbook, setPageImage, 2}},
+ {1972, {wxListbook, setPageText, 2}},
+ {1973, {wxListbook, setSelection, 1}},
+ {1974, {wxListbook, changeSelection, 1}},
+ {1975, {wxListbook, 'Destroy', undefined}},
+ {1976, {wxTreebook, new_0, 0}},
+ {1977, {wxTreebook, new_3, 3}},
+ {1978, {wxTreebook, addPage, 3}},
+ {1979, {wxTreebook, advanceSelection, 1}},
+ {1980, {wxTreebook, assignImageList, 1}},
+ {1981, {wxTreebook, create, 3}},
+ {1982, {wxTreebook, deleteAllPages, 0}},
+ {1983, {wxTreebook, deletePage, 1}},
+ {1984, {wxTreebook, removePage, 1}},
+ {1985, {wxTreebook, getCurrentPage, 0}},
+ {1986, {wxTreebook, getImageList, 0}},
+ {1988, {wxTreebook, getPage, 1}},
+ {1989, {wxTreebook, getPageCount, 0}},
+ {1990, {wxTreebook, getPageImage, 1}},
+ {1991, {wxTreebook, getPageText, 1}},
+ {1992, {wxTreebook, getSelection, 0}},
+ {1993, {wxTreebook, expandNode, 2}},
+ {1994, {wxTreebook, isNodeExpanded, 1}},
+ {1996, {wxTreebook, hitTest, 2}},
+ {1997, {wxTreebook, insertPage, 4}},
+ {1998, {wxTreebook, insertSubPage, 4}},
+ {1999, {wxTreebook, setImageList, 1}},
+ {2000, {wxTreebook, setPageSize, 1}},
+ {2001, {wxTreebook, setPageImage, 2}},
+ {2002, {wxTreebook, setPageText, 2}},
+ {2003, {wxTreebook, setSelection, 1}},
+ {2004, {wxTreebook, changeSelection, 1}},
+ {2005, {wxTreebook, 'Destroy', undefined}},
+ {2008, {wxTreeCtrl, new_2, 2}},
+ {2009, {wxTreeCtrl, new_0, 0}},
+ {2011, {wxTreeCtrl, destruct, 0}},
+ {2012, {wxTreeCtrl, addRoot, 2}},
+ {2013, {wxTreeCtrl, appendItem, 3}},
+ {2014, {wxTreeCtrl, assignImageList, 1}},
+ {2015, {wxTreeCtrl, assignStateImageList, 1}},
+ {2016, {wxTreeCtrl, collapse, 1}},
+ {2017, {wxTreeCtrl, collapseAndReset, 1}},
+ {2018, {wxTreeCtrl, create, 2}},
+ {2019, {wxTreeCtrl, delete, 1}},
+ {2020, {wxTreeCtrl, deleteAllItems, 0}},
+ {2021, {wxTreeCtrl, deleteChildren, 1}},
+ {2022, {wxTreeCtrl, editLabel, 1}},
+ {2023, {wxTreeCtrl, ensureVisible, 1}},
+ {2024, {wxTreeCtrl, expand, 1}},
+ {2025, {wxTreeCtrl, getBoundingRect, 3}},
+ {2027, {wxTreeCtrl, getChildrenCount, 2}},
+ {2028, {wxTreeCtrl, getCount, 0}},
+ {2029, {wxTreeCtrl, getEditControl, 0}},
+ {2030, {wxTreeCtrl, getFirstChild, 2}},
+ {2031, {wxTreeCtrl, getNextChild, 2}},
+ {2032, {wxTreeCtrl, getFirstVisibleItem, 0}},
+ {2033, {wxTreeCtrl, getImageList, 0}},
+ {2034, {wxTreeCtrl, getIndent, 0}},
+ {2035, {wxTreeCtrl, getItemBackgroundColour, 1}},
+ {2036, {wxTreeCtrl, getItemData, 1}},
+ {2037, {wxTreeCtrl, getItemFont, 1}},
+ {2038, {wxTreeCtrl, getItemImage_1, 1}},
+ {2039, {wxTreeCtrl, getItemImage_2, 2}},
+ {2040, {wxTreeCtrl, getItemText, 1}},
+ {2041, {wxTreeCtrl, getItemTextColour, 1}},
+ {2042, {wxTreeCtrl, getLastChild, 1}},
+ {2043, {wxTreeCtrl, getNextSibling, 1}},
+ {2044, {wxTreeCtrl, getNextVisible, 1}},
+ {2045, {wxTreeCtrl, getItemParent, 1}},
+ {2046, {wxTreeCtrl, getPrevSibling, 1}},
+ {2047, {wxTreeCtrl, getPrevVisible, 1}},
+ {2048, {wxTreeCtrl, getRootItem, 0}},
+ {2049, {wxTreeCtrl, getSelection, 0}},
+ {2050, {wxTreeCtrl, getSelections, 1}},
+ {2051, {wxTreeCtrl, getStateImageList, 0}},
+ {2052, {wxTreeCtrl, hitTest, 1}},
+ {2054, {wxTreeCtrl, insertItem, 4}},
+ {2055, {wxTreeCtrl, isBold, 1}},
+ {2056, {wxTreeCtrl, isExpanded, 1}},
+ {2057, {wxTreeCtrl, isSelected, 1}},
+ {2058, {wxTreeCtrl, isVisible, 1}},
+ {2059, {wxTreeCtrl, itemHasChildren, 1}},
+ {2060, {wxTreeCtrl, prependItem, 3}},
+ {2061, {wxTreeCtrl, scrollTo, 1}},
+ {2062, {wxTreeCtrl, selectItem_1, 1}},
+ {2063, {wxTreeCtrl, selectItem_2, 2}},
+ {2064, {wxTreeCtrl, setIndent, 1}},
+ {2065, {wxTreeCtrl, setImageList, 1}},
+ {2066, {wxTreeCtrl, setItemBackgroundColour, 2}},
+ {2067, {wxTreeCtrl, setItemBold, 2}},
+ {2068, {wxTreeCtrl, setItemData, 2}},
+ {2069, {wxTreeCtrl, setItemDropHighlight, 2}},
+ {2070, {wxTreeCtrl, setItemFont, 2}},
+ {2071, {wxTreeCtrl, setItemHasChildren, 2}},
+ {2072, {wxTreeCtrl, setItemImage_2, 2}},
+ {2073, {wxTreeCtrl, setItemImage_3, 3}},
+ {2074, {wxTreeCtrl, setItemText, 2}},
+ {2075, {wxTreeCtrl, setItemTextColour, 2}},
+ {2076, {wxTreeCtrl, setStateImageList, 1}},
+ {2077, {wxTreeCtrl, setWindowStyle, 1}},
+ {2078, {wxTreeCtrl, sortChildren, 1}},
+ {2079, {wxTreeCtrl, toggle, 1}},
+ {2080, {wxTreeCtrl, toggleItemSelection, 1}},
+ {2081, {wxTreeCtrl, unselect, 0}},
+ {2082, {wxTreeCtrl, unselectAll, 0}},
+ {2083, {wxTreeCtrl, unselectItem, 1}},
+ {2084, {wxScrollBar, new_0, 0}},
+ {2085, {wxScrollBar, new_3, 3}},
+ {2086, {wxScrollBar, destruct, 0}},
+ {2087, {wxScrollBar, create, 3}},
+ {2088, {wxScrollBar, getRange, 0}},
+ {2089, {wxScrollBar, getPageSize, 0}},
+ {2090, {wxScrollBar, getThumbPosition, 0}},
+ {2091, {wxScrollBar, getThumbSize, 0}},
+ {2092, {wxScrollBar, setThumbPosition, 1}},
+ {2093, {wxScrollBar, setScrollbar, 5}},
+ {2095, {wxSpinButton, new_2, 2}},
+ {2096, {wxSpinButton, new_0, 0}},
+ {2097, {wxSpinButton, create, 2}},
+ {2098, {wxSpinButton, getMax, 0}},
+ {2099, {wxSpinButton, getMin, 0}},
+ {2100, {wxSpinButton, getValue, 0}},
+ {2101, {wxSpinButton, setRange, 2}},
+ {2102, {wxSpinButton, setValue, 1}},
+ {2103, {wxSpinButton, 'Destroy', undefined}},
+ {2104, {wxSpinCtrl, new_0, 0}},
+ {2105, {wxSpinCtrl, new_2, 2}},
+ {2107, {wxSpinCtrl, create, 2}},
+ {2110, {wxSpinCtrl, setValue_1_1, 1}},
+ {2111, {wxSpinCtrl, setValue_1_0, 1}},
+ {2113, {wxSpinCtrl, getValue, 0}},
+ {2115, {wxSpinCtrl, setRange, 2}},
+ {2116, {wxSpinCtrl, setSelection, 2}},
+ {2118, {wxSpinCtrl, getMin, 0}},
+ {2120, {wxSpinCtrl, getMax, 0}},
+ {2121, {wxSpinCtrl, 'Destroy', undefined}},
+ {2122, {wxStaticText, new_0, 0}},
+ {2123, {wxStaticText, new_4, 4}},
+ {2124, {wxStaticText, create, 4}},
+ {2125, {wxStaticText, getLabel, 0}},
+ {2126, {wxStaticText, setLabel, 1}},
+ {2127, {wxStaticText, wrap, 1}},
+ {2128, {wxStaticText, 'Destroy', undefined}},
+ {2129, {wxStaticBitmap, new_0, 0}},
+ {2130, {wxStaticBitmap, new_4, 4}},
+ {2131, {wxStaticBitmap, create, 4}},
+ {2132, {wxStaticBitmap, getBitmap, 0}},
+ {2133, {wxStaticBitmap, setBitmap, 1}},
+ {2134, {wxStaticBitmap, 'Destroy', undefined}},
+ {2135, {wxRadioBox, new, 7}},
+ {2137, {wxRadioBox, destruct, 0}},
+ {2138, {wxRadioBox, create, 7}},
+ {2139, {wxRadioBox, enable_2, 2}},
+ {2140, {wxRadioBox, enable_1, 1}},
+ {2141, {wxRadioBox, getSelection, 0}},
+ {2142, {wxRadioBox, getString, 1}},
+ {2143, {wxRadioBox, setSelection, 1}},
+ {2144, {wxRadioBox, show_2, 2}},
+ {2145, {wxRadioBox, show_1, 1}},
+ {2146, {wxRadioBox, getColumnCount, 0}},
+ {2147, {wxRadioBox, getItemHelpText, 1}},
+ {2148, {wxRadioBox, getItemToolTip, 1}},
+ {2150, {wxRadioBox, getItemFromPoint, 1}},
+ {2151, {wxRadioBox, getRowCount, 0}},
+ {2152, {wxRadioBox, isItemEnabled, 1}},
+ {2153, {wxRadioBox, isItemShown, 1}},
+ {2154, {wxRadioBox, setItemHelpText, 2}},
+ {2155, {wxRadioBox, setItemToolTip, 2}},
+ {2156, {wxRadioButton, new_0, 0}},
+ {2157, {wxRadioButton, new_4, 4}},
+ {2158, {wxRadioButton, create, 4}},
+ {2159, {wxRadioButton, getValue, 0}},
+ {2160, {wxRadioButton, setValue, 1}},
+ {2161, {wxRadioButton, 'Destroy', undefined}},
+ {2163, {wxSlider, new_6, 6}},
+ {2164, {wxSlider, new_0, 0}},
+ {2165, {wxSlider, create, 6}},
+ {2166, {wxSlider, getLineSize, 0}},
+ {2167, {wxSlider, getMax, 0}},
+ {2168, {wxSlider, getMin, 0}},
+ {2169, {wxSlider, getPageSize, 0}},
+ {2170, {wxSlider, getThumbLength, 0}},
+ {2171, {wxSlider, getValue, 0}},
+ {2172, {wxSlider, setLineSize, 1}},
+ {2173, {wxSlider, setPageSize, 1}},
+ {2174, {wxSlider, setRange, 2}},
+ {2175, {wxSlider, setThumbLength, 1}},
+ {2176, {wxSlider, setValue, 1}},
+ {2177, {wxSlider, 'Destroy', undefined}},
+ {2179, {wxDialog, new_4, 4}},
+ {2180, {wxDialog, new_0, 0}},
+ {2182, {wxDialog, destruct, 0}},
+ {2183, {wxDialog, create, 4}},
+ {2184, {wxDialog, createButtonSizer, 1}},
+ {2185, {wxDialog, createStdDialogButtonSizer, 1}},
+ {2186, {wxDialog, endModal, 1}},
+ {2187, {wxDialog, getAffirmativeId, 0}},
+ {2188, {wxDialog, getReturnCode, 0}},
+ {2189, {wxDialog, isModal, 0}},
+ {2190, {wxDialog, setAffirmativeId, 1}},
+ {2191, {wxDialog, setReturnCode, 1}},
+ {2192, {wxDialog, show, 1}},
+ {2193, {wxDialog, showModal, 0}},
+ {2194, {wxColourDialog, new_0, 0}},
+ {2195, {wxColourDialog, new_2, 2}},
+ {2196, {wxColourDialog, destruct, 0}},
+ {2197, {wxColourDialog, create, 2}},
+ {2198, {wxColourDialog, getColourData, 0}},
+ {2199, {wxColourData, new_0, 0}},
+ {2200, {wxColourData, new_1, 1}},
+ {2201, {wxColourData, destruct, 0}},
+ {2202, {wxColourData, getChooseFull, 0}},
+ {2203, {wxColourData, getColour, 0}},
+ {2205, {wxColourData, getCustomColour, 1}},
+ {2206, {wxColourData, setChooseFull, 1}},
+ {2207, {wxColourData, setColour, 1}},
+ {2208, {wxColourData, setCustomColour, 2}},
+ {2209, {wxPalette, new_0, 0}},
+ {2210, {wxPalette, new_4, 4}},
+ {2212, {wxPalette, destruct, 0}},
+ {2213, {wxPalette, create, 4}},
+ {2214, {wxPalette, getColoursCount, 0}},
+ {2215, {wxPalette, getPixel, 3}},
+ {2216, {wxPalette, getRGB, 4}},
+ {2217, {wxPalette, isOk, 0}},
+ {2221, {wxDirDialog, new, 2}},
+ {2222, {wxDirDialog, destruct, 0}},
+ {2223, {wxDirDialog, getPath, 0}},
+ {2224, {wxDirDialog, getMessage, 0}},
+ {2225, {wxDirDialog, setMessage, 1}},
+ {2226, {wxDirDialog, setPath, 1}},
+ {2230, {wxFileDialog, new, 2}},
+ {2231, {wxFileDialog, destruct, 0}},
+ {2232, {wxFileDialog, getDirectory, 0}},
+ {2233, {wxFileDialog, getFilename, 0}},
+ {2234, {wxFileDialog, getFilenames, 1}},
+ {2235, {wxFileDialog, getFilterIndex, 0}},
+ {2236, {wxFileDialog, getMessage, 0}},
+ {2237, {wxFileDialog, getPath, 0}},
+ {2238, {wxFileDialog, getPaths, 1}},
+ {2239, {wxFileDialog, getWildcard, 0}},
+ {2240, {wxFileDialog, setDirectory, 1}},
+ {2241, {wxFileDialog, setFilename, 1}},
+ {2242, {wxFileDialog, setFilterIndex, 1}},
+ {2243, {wxFileDialog, setMessage, 1}},
+ {2244, {wxFileDialog, setPath, 1}},
+ {2245, {wxFileDialog, setWildcard, 1}},
+ {2246, {wxPickerBase, setInternalMargin, 1}},
+ {2247, {wxPickerBase, getInternalMargin, 0}},
+ {2248, {wxPickerBase, setTextCtrlProportion, 1}},
+ {2249, {wxPickerBase, setPickerCtrlProportion, 1}},
+ {2250, {wxPickerBase, getTextCtrlProportion, 0}},
+ {2251, {wxPickerBase, getPickerCtrlProportion, 0}},
+ {2252, {wxPickerBase, hasTextCtrl, 0}},
+ {2253, {wxPickerBase, getTextCtrl, 0}},
+ {2254, {wxPickerBase, isTextCtrlGrowable, 0}},
+ {2255, {wxPickerBase, setPickerCtrlGrowable, 1}},
+ {2256, {wxPickerBase, setTextCtrlGrowable, 1}},
+ {2257, {wxPickerBase, isPickerCtrlGrowable, 0}},
+ {2258, {wxFilePickerCtrl, new_0, 0}},
+ {2259, {wxFilePickerCtrl, new_3, 3}},
+ {2260, {wxFilePickerCtrl, create, 3}},
+ {2261, {wxFilePickerCtrl, getPath, 0}},
+ {2262, {wxFilePickerCtrl, setPath, 1}},
+ {2263, {wxFilePickerCtrl, 'Destroy', undefined}},
+ {2264, {wxDirPickerCtrl, new_0, 0}},
+ {2265, {wxDirPickerCtrl, new_3, 3}},
+ {2266, {wxDirPickerCtrl, create, 3}},
+ {2267, {wxDirPickerCtrl, getPath, 0}},
+ {2268, {wxDirPickerCtrl, setPath, 1}},
+ {2269, {wxDirPickerCtrl, 'Destroy', undefined}},
+ {2270, {wxColourPickerCtrl, new_0, 0}},
+ {2271, {wxColourPickerCtrl, new_3, 3}},
+ {2272, {wxColourPickerCtrl, create, 3}},
+ {2273, {wxColourPickerCtrl, getColour, 0}},
+ {2274, {wxColourPickerCtrl, setColour_1_1, 1}},
+ {2275, {wxColourPickerCtrl, setColour_1_0, 1}},
+ {2276, {wxColourPickerCtrl, 'Destroy', undefined}},
+ {2277, {wxDatePickerCtrl, new_0, 0}},
+ {2278, {wxDatePickerCtrl, new_3, 3}},
+ {2279, {wxDatePickerCtrl, getRange, 2}},
+ {2280, {wxDatePickerCtrl, getValue, 0}},
+ {2281, {wxDatePickerCtrl, setRange, 2}},
+ {2282, {wxDatePickerCtrl, setValue, 1}},
+ {2283, {wxDatePickerCtrl, 'Destroy', undefined}},
+ {2284, {wxFontPickerCtrl, new_0, 0}},
+ {2285, {wxFontPickerCtrl, new_3, 3}},
+ {2286, {wxFontPickerCtrl, create, 3}},
+ {2287, {wxFontPickerCtrl, getSelectedFont, 0}},
+ {2288, {wxFontPickerCtrl, setSelectedFont, 1}},
+ {2289, {wxFontPickerCtrl, getMaxPointSize, 0}},
+ {2290, {wxFontPickerCtrl, setMaxPointSize, 1}},
+ {2291, {wxFontPickerCtrl, 'Destroy', undefined}},
+ {2294, {wxFindReplaceDialog, new_0, 0}},
+ {2295, {wxFindReplaceDialog, new_4, 4}},
+ {2296, {wxFindReplaceDialog, destruct, 0}},
+ {2297, {wxFindReplaceDialog, create, 4}},
+ {2298, {wxFindReplaceDialog, getData, 0}},
+ {2299, {wxFindReplaceData, new_0, 0}},
+ {2300, {wxFindReplaceData, new_1, 1}},
+ {2301, {wxFindReplaceData, getFindString, 0}},
+ {2302, {wxFindReplaceData, getReplaceString, 0}},
+ {2303, {wxFindReplaceData, getFlags, 0}},
+ {2304, {wxFindReplaceData, setFlags, 1}},
+ {2305, {wxFindReplaceData, setFindString, 1}},
+ {2306, {wxFindReplaceData, setReplaceString, 1}},
+ {2307, {wxFindReplaceData, 'Destroy', undefined}},
+ {2308, {wxMultiChoiceDialog, new_0, 0}},
+ {2310, {wxMultiChoiceDialog, new_5, 5}},
+ {2311, {wxMultiChoiceDialog, getSelections, 0}},
+ {2312, {wxMultiChoiceDialog, setSelections, 1}},
+ {2313, {wxMultiChoiceDialog, 'Destroy', undefined}},
+ {2314, {wxSingleChoiceDialog, new_0, 0}},
+ {2316, {wxSingleChoiceDialog, new_5, 5}},
+ {2317, {wxSingleChoiceDialog, getSelection, 0}},
+ {2318, {wxSingleChoiceDialog, getStringSelection, 0}},
+ {2319, {wxSingleChoiceDialog, setSelection, 1}},
+ {2320, {wxSingleChoiceDialog, 'Destroy', undefined}},
+ {2321, {wxTextEntryDialog, new, 3}},
+ {2322, {wxTextEntryDialog, getValue, 0}},
+ {2323, {wxTextEntryDialog, setValue, 1}},
+ {2324, {wxTextEntryDialog, 'Destroy', undefined}},
+ {2325, {wxPasswordEntryDialog, new, 3}},
+ {2326, {wxPasswordEntryDialog, 'Destroy', undefined}},
+ {2327, {wxFontData, new_0, 0}},
+ {2328, {wxFontData, new_1, 1}},
+ {2329, {wxFontData, destruct, 0}},
+ {2330, {wxFontData, enableEffects, 1}},
+ {2331, {wxFontData, getAllowSymbols, 0}},
+ {2332, {wxFontData, getColour, 0}},
+ {2333, {wxFontData, getChosenFont, 0}},
+ {2334, {wxFontData, getEnableEffects, 0}},
+ {2335, {wxFontData, getInitialFont, 0}},
+ {2336, {wxFontData, getShowHelp, 0}},
+ {2337, {wxFontData, setAllowSymbols, 1}},
+ {2338, {wxFontData, setChosenFont, 1}},
+ {2339, {wxFontData, setColour, 1}},
+ {2340, {wxFontData, setInitialFont, 1}},
+ {2341, {wxFontData, setRange, 2}},
+ {2342, {wxFontData, setShowHelp, 1}},
+ {2346, {wxFontDialog, new_0, 0}},
+ {2348, {wxFontDialog, new_2, 2}},
+ {2350, {wxFontDialog, create, 2}},
+ {2351, {wxFontDialog, getFontData, 0}},
+ {2353, {wxFontDialog, 'Destroy', undefined}},
+ {2354, {wxProgressDialog, new, 3}},
+ {2355, {wxProgressDialog, destruct, 0}},
+ {2356, {wxProgressDialog, resume, 0}},
+ {2357, {wxProgressDialog, update_2, 2}},
+ {2358, {wxProgressDialog, update_0, 0}},
+ {2359, {wxMessageDialog, new, 3}},
+ {2360, {wxMessageDialog, destruct, 0}},
+ {2361, {wxPageSetupDialog, new, 2}},
+ {2362, {wxPageSetupDialog, destruct, 0}},
+ {2363, {wxPageSetupDialog, getPageSetupData, 0}},
+ {2364, {wxPageSetupDialog, showModal, 0}},
+ {2365, {wxPageSetupDialogData, new_0, 0}},
+ {2366, {wxPageSetupDialogData, new_1_0, 1}},
+ {2367, {wxPageSetupDialogData, new_1_1, 1}},
+ {2368, {wxPageSetupDialogData, destruct, 0}},
+ {2369, {wxPageSetupDialogData, enableHelp, 1}},
+ {2370, {wxPageSetupDialogData, enableMargins, 1}},
+ {2371, {wxPageSetupDialogData, enableOrientation, 1}},
+ {2372, {wxPageSetupDialogData, enablePaper, 1}},
+ {2373, {wxPageSetupDialogData, enablePrinter, 1}},
+ {2374, {wxPageSetupDialogData, getDefaultMinMargins, 0}},
+ {2375, {wxPageSetupDialogData, getEnableMargins, 0}},
+ {2376, {wxPageSetupDialogData, getEnableOrientation, 0}},
+ {2377, {wxPageSetupDialogData, getEnablePaper, 0}},
+ {2378, {wxPageSetupDialogData, getEnablePrinter, 0}},
+ {2379, {wxPageSetupDialogData, getEnableHelp, 0}},
+ {2380, {wxPageSetupDialogData, getDefaultInfo, 0}},
+ {2381, {wxPageSetupDialogData, getMarginTopLeft, 0}},
+ {2382, {wxPageSetupDialogData, getMarginBottomRight, 0}},
+ {2383, {wxPageSetupDialogData, getMinMarginTopLeft, 0}},
+ {2384, {wxPageSetupDialogData, getMinMarginBottomRight, 0}},
+ {2385, {wxPageSetupDialogData, getPaperId, 0}},
+ {2386, {wxPageSetupDialogData, getPaperSize, 0}},
+ {2388, {wxPageSetupDialogData, getPrintData, 0}},
+ {2389, {wxPageSetupDialogData, isOk, 0}},
+ {2390, {wxPageSetupDialogData, setDefaultInfo, 1}},
+ {2391, {wxPageSetupDialogData, setDefaultMinMargins, 1}},
+ {2392, {wxPageSetupDialogData, setMarginTopLeft, 1}},
+ {2393, {wxPageSetupDialogData, setMarginBottomRight, 1}},
+ {2394, {wxPageSetupDialogData, setMinMarginTopLeft, 1}},
+ {2395, {wxPageSetupDialogData, setMinMarginBottomRight, 1}},
+ {2396, {wxPageSetupDialogData, setPaperId, 1}},
+ {2397, {wxPageSetupDialogData, setPaperSize_1_1, 1}},
+ {2398, {wxPageSetupDialogData, setPaperSize_1_0, 1}},
+ {2399, {wxPageSetupDialogData, setPrintData, 1}},
+ {2400, {wxPrintDialog, new_2_0, 2}},
+ {2401, {wxPrintDialog, new_2_1, 2}},
+ {2402, {wxPrintDialog, destruct, 0}},
+ {2403, {wxPrintDialog, getPrintDialogData, 0}},
+ {2404, {wxPrintDialog, getPrintDC, 0}},
+ {2405, {wxPrintDialogData, new_0, 0}},
+ {2406, {wxPrintDialogData, new_1_1, 1}},
+ {2407, {wxPrintDialogData, new_1_0, 1}},
+ {2408, {wxPrintDialogData, destruct, 0}},
+ {2409, {wxPrintDialogData, enableHelp, 1}},
+ {2410, {wxPrintDialogData, enablePageNumbers, 1}},
+ {2411, {wxPrintDialogData, enablePrintToFile, 1}},
+ {2412, {wxPrintDialogData, enableSelection, 1}},
+ {2413, {wxPrintDialogData, getAllPages, 0}},
+ {2414, {wxPrintDialogData, getCollate, 0}},
+ {2415, {wxPrintDialogData, getFromPage, 0}},
+ {2416, {wxPrintDialogData, getMaxPage, 0}},
+ {2417, {wxPrintDialogData, getMinPage, 0}},
+ {2418, {wxPrintDialogData, getNoCopies, 0}},
+ {2419, {wxPrintDialogData, getPrintData, 0}},
+ {2420, {wxPrintDialogData, getPrintToFile, 0}},
+ {2421, {wxPrintDialogData, getSelection, 0}},
+ {2422, {wxPrintDialogData, getToPage, 0}},
+ {2423, {wxPrintDialogData, isOk, 0}},
+ {2424, {wxPrintDialogData, setCollate, 1}},
+ {2425, {wxPrintDialogData, setFromPage, 1}},
+ {2426, {wxPrintDialogData, setMaxPage, 1}},
+ {2427, {wxPrintDialogData, setMinPage, 1}},
+ {2428, {wxPrintDialogData, setNoCopies, 1}},
+ {2429, {wxPrintDialogData, setPrintData, 1}},
+ {2430, {wxPrintDialogData, setPrintToFile, 1}},
+ {2431, {wxPrintDialogData, setSelection, 1}},
+ {2432, {wxPrintDialogData, setToPage, 1}},
+ {2433, {wxPrintData, new_0, 0}},
+ {2434, {wxPrintData, new_1, 1}},
+ {2435, {wxPrintData, destruct, 0}},
+ {2436, {wxPrintData, getCollate, 0}},
+ {2437, {wxPrintData, getBin, 0}},
+ {2438, {wxPrintData, getColour, 0}},
+ {2439, {wxPrintData, getDuplex, 0}},
+ {2440, {wxPrintData, getNoCopies, 0}},
+ {2441, {wxPrintData, getOrientation, 0}},
+ {2442, {wxPrintData, getPaperId, 0}},
+ {2443, {wxPrintData, getPrinterName, 0}},
+ {2444, {wxPrintData, getQuality, 0}},
+ {2445, {wxPrintData, isOk, 0}},
+ {2446, {wxPrintData, setBin, 1}},
+ {2447, {wxPrintData, setCollate, 1}},
+ {2448, {wxPrintData, setColour, 1}},
+ {2449, {wxPrintData, setDuplex, 1}},
+ {2450, {wxPrintData, setNoCopies, 1}},
+ {2451, {wxPrintData, setOrientation, 1}},
+ {2452, {wxPrintData, setPaperId, 1}},
+ {2453, {wxPrintData, setPrinterName, 1}},
+ {2454, {wxPrintData, setQuality, 1}},
+ {2457, {wxPrintPreview, new_2, 2}},
+ {2458, {wxPrintPreview, new_3, 3}},
+ {2460, {wxPrintPreview, destruct, 0}},
+ {2461, {wxPrintPreview, getCanvas, 0}},
+ {2462, {wxPrintPreview, getCurrentPage, 0}},
+ {2463, {wxPrintPreview, getFrame, 0}},
+ {2464, {wxPrintPreview, getMaxPage, 0}},
+ {2465, {wxPrintPreview, getMinPage, 0}},
+ {2466, {wxPrintPreview, getPrintout, 0}},
+ {2467, {wxPrintPreview, getPrintoutForPrinting, 0}},
+ {2468, {wxPrintPreview, isOk, 0}},
+ {2469, {wxPrintPreview, paintPage, 2}},
+ {2470, {wxPrintPreview, print, 1}},
+ {2471, {wxPrintPreview, renderPage, 1}},
+ {2472, {wxPrintPreview, setCanvas, 1}},
+ {2473, {wxPrintPreview, setCurrentPage, 1}},
+ {2474, {wxPrintPreview, setFrame, 1}},
+ {2475, {wxPrintPreview, setPrintout, 1}},
+ {2476, {wxPrintPreview, setZoom, 1}},
+ {2477, {wxPreviewFrame, new, 3}},
+ {2478, {wxPreviewFrame, destruct, 0}},
+ {2479, {wxPreviewFrame, createControlBar, 0}},
+ {2480, {wxPreviewFrame, createCanvas, 0}},
+ {2481, {wxPreviewFrame, initialize, 0}},
+ {2482, {wxPreviewFrame, onCloseWindow, 1}},
+ {2483, {wxPreviewControlBar, new, 4}},
+ {2484, {wxPreviewControlBar, destruct, 0}},
+ {2485, {wxPreviewControlBar, createButtons, 0}},
+ {2486, {wxPreviewControlBar, getPrintPreview, 0}},
+ {2487, {wxPreviewControlBar, getZoomControl, 0}},
+ {2488, {wxPreviewControlBar, setZoomControl, 1}},
+ {2490, {wxPrinter, new, 1}},
+ {2491, {wxPrinter, createAbortWindow, 2}},
+ {2492, {wxPrinter, getAbort, 0}},
+ {2493, {wxPrinter, getLastError, 0}},
+ {2494, {wxPrinter, getPrintDialogData, 0}},
+ {2495, {wxPrinter, print, 3}},
+ {2496, {wxPrinter, printDialog, 1}},
+ {2497, {wxPrinter, reportError, 3}},
+ {2498, {wxPrinter, setup, 1}},
+ {2499, {wxPrinter, 'Destroy', undefined}},
+ {2500, {wxXmlResource, new_1, 1}},
+ {2501, {wxXmlResource, new_2, 2}},
+ {2502, {wxXmlResource, destruct, 0}},
+ {2503, {wxXmlResource, attachUnknownControl, 3}},
+ {2504, {wxXmlResource, clearHandlers, 0}},
+ {2505, {wxXmlResource, compareVersion, 4}},
+ {2506, {wxXmlResource, get, 0}},
+ {2507, {wxXmlResource, getFlags, 0}},
+ {2508, {wxXmlResource, getVersion, 0}},
+ {2509, {wxXmlResource, getXRCID, 2}},
+ {2510, {wxXmlResource, initAllHandlers, 0}},
+ {2511, {wxXmlResource, load, 1}},
+ {2512, {wxXmlResource, loadBitmap, 1}},
+ {2513, {wxXmlResource, loadDialog_2, 2}},
+ {2514, {wxXmlResource, loadDialog_3, 3}},
+ {2515, {wxXmlResource, loadFrame_2, 2}},
+ {2516, {wxXmlResource, loadFrame_3, 3}},
+ {2517, {wxXmlResource, loadIcon, 1}},
+ {2518, {wxXmlResource, loadMenu, 1}},
+ {2519, {wxXmlResource, loadMenuBar_2, 2}},
+ {2520, {wxXmlResource, loadMenuBar_1, 1}},
+ {2521, {wxXmlResource, loadPanel_2, 2}},
+ {2522, {wxXmlResource, loadPanel_3, 3}},
+ {2523, {wxXmlResource, loadToolBar, 2}},
+ {2524, {wxXmlResource, set, 1}},
+ {2525, {wxXmlResource, setFlags, 1}},
+ {2526, {wxXmlResource, unload, 1}},
+ {2527, {wxXmlResource, xrcctrl, 3}},
+ {2528, {wxHtmlEasyPrinting, new, 1}},
+ {2529, {wxHtmlEasyPrinting, destruct, 0}},
+ {2530, {wxHtmlEasyPrinting, getPrintData, 0}},
+ {2531, {wxHtmlEasyPrinting, getPageSetupData, 0}},
+ {2532, {wxHtmlEasyPrinting, previewFile, 1}},
+ {2533, {wxHtmlEasyPrinting, previewText, 2}},
+ {2534, {wxHtmlEasyPrinting, printFile, 1}},
+ {2535, {wxHtmlEasyPrinting, printText, 2}},
+ {2536, {wxHtmlEasyPrinting, pageSetup, 0}},
+ {2537, {wxHtmlEasyPrinting, setFonts, 3}},
+ {2538, {wxHtmlEasyPrinting, setHeader, 2}},
+ {2539, {wxHtmlEasyPrinting, setFooter, 2}},
+ {2541, {wxGLCanvas, new_2, 2}},
+ {2542, {wxGLCanvas, new_3_1, 3}},
+ {2543, {wxGLCanvas, new_3_0, 3}},
+ {2544, {wxGLCanvas, getContext, 0}},
+ {2546, {wxGLCanvas, setCurrent, 0}},
+ {2547, {wxGLCanvas, swapBuffers, 0}},
+ {2548, {wxGLCanvas, 'Destroy', undefined}},
+ {2549, {wxAuiManager, new, 1}},
+ {2550, {wxAuiManager, destruct, 0}},
+ {2551, {wxAuiManager, addPane_2_1, 2}},
+ {2552, {wxAuiManager, addPane_3, 3}},
+ {2553, {wxAuiManager, addPane_2_0, 2}},
+ {2554, {wxAuiManager, detachPane, 1}},
+ {2555, {wxAuiManager, getAllPanes, 0}},
+ {2556, {wxAuiManager, getArtProvider, 0}},
+ {2557, {wxAuiManager, getDockSizeConstraint, 2}},
+ {2558, {wxAuiManager, getFlags, 0}},
+ {2559, {wxAuiManager, getManagedWindow, 0}},
+ {2560, {wxAuiManager, getManager, 1}},
+ {2561, {wxAuiManager, getPane_1_1, 1}},
+ {2562, {wxAuiManager, getPane_1_0, 1}},
+ {2563, {wxAuiManager, hideHint, 0}},
+ {2564, {wxAuiManager, insertPane, 3}},
+ {2565, {wxAuiManager, loadPaneInfo, 2}},
+ {2566, {wxAuiManager, loadPerspective, 2}},
+ {2567, {wxAuiManager, savePaneInfo, 1}},
+ {2568, {wxAuiManager, savePerspective, 0}},
+ {2569, {wxAuiManager, setArtProvider, 1}},
+ {2570, {wxAuiManager, setDockSizeConstraint, 2}},
+ {2571, {wxAuiManager, setFlags, 1}},
+ {2572, {wxAuiManager, setManagedWindow, 1}},
+ {2573, {wxAuiManager, showHint, 1}},
+ {2574, {wxAuiManager, unInit, 0}},
+ {2575, {wxAuiManager, update, 0}},
+ {2576, {wxAuiPaneInfo, new_0, 0}},
+ {2577, {wxAuiPaneInfo, new_1, 1}},
+ {2578, {wxAuiPaneInfo, destruct, 0}},
+ {2579, {wxAuiPaneInfo, bestSize_1, 1}},
+ {2580, {wxAuiPaneInfo, bestSize_2, 2}},
+ {2581, {wxAuiPaneInfo, bottom, 0}},
+ {2582, {wxAuiPaneInfo, bottomDockable, 1}},
+ {2583, {wxAuiPaneInfo, caption, 1}},
+ {2584, {wxAuiPaneInfo, captionVisible, 1}},
+ {2585, {wxAuiPaneInfo, centre, 0}},
+ {2586, {wxAuiPaneInfo, centrePane, 0}},
+ {2587, {wxAuiPaneInfo, closeButton, 1}},
+ {2588, {wxAuiPaneInfo, defaultPane, 0}},
+ {2589, {wxAuiPaneInfo, destroyOnClose, 1}},
+ {2590, {wxAuiPaneInfo, direction, 1}},
+ {2591, {wxAuiPaneInfo, dock, 0}},
+ {2592, {wxAuiPaneInfo, dockable, 1}},
+ {2593, {wxAuiPaneInfo, fixed, 0}},
+ {2594, {wxAuiPaneInfo, float, 0}},
+ {2595, {wxAuiPaneInfo, floatable, 1}},
+ {2596, {wxAuiPaneInfo, floatingPosition_1, 1}},
+ {2597, {wxAuiPaneInfo, floatingPosition_2, 2}},
+ {2598, {wxAuiPaneInfo, floatingSize_1, 1}},
+ {2599, {wxAuiPaneInfo, floatingSize_2, 2}},
+ {2600, {wxAuiPaneInfo, gripper, 1}},
+ {2601, {wxAuiPaneInfo, gripperTop, 1}},
+ {2602, {wxAuiPaneInfo, hasBorder, 0}},
+ {2603, {wxAuiPaneInfo, hasCaption, 0}},
+ {2604, {wxAuiPaneInfo, hasCloseButton, 0}},
+ {2605, {wxAuiPaneInfo, hasFlag, 1}},
+ {2606, {wxAuiPaneInfo, hasGripper, 0}},
+ {2607, {wxAuiPaneInfo, hasGripperTop, 0}},
+ {2608, {wxAuiPaneInfo, hasMaximizeButton, 0}},
+ {2609, {wxAuiPaneInfo, hasMinimizeButton, 0}},
+ {2610, {wxAuiPaneInfo, hasPinButton, 0}},
+ {2611, {wxAuiPaneInfo, hide, 0}},
+ {2612, {wxAuiPaneInfo, isBottomDockable, 0}},
+ {2613, {wxAuiPaneInfo, isDocked, 0}},
+ {2614, {wxAuiPaneInfo, isFixed, 0}},
+ {2615, {wxAuiPaneInfo, isFloatable, 0}},
+ {2616, {wxAuiPaneInfo, isFloating, 0}},
+ {2617, {wxAuiPaneInfo, isLeftDockable, 0}},
+ {2618, {wxAuiPaneInfo, isMovable, 0}},
+ {2619, {wxAuiPaneInfo, isOk, 0}},
+ {2620, {wxAuiPaneInfo, isResizable, 0}},
+ {2621, {wxAuiPaneInfo, isRightDockable, 0}},
+ {2622, {wxAuiPaneInfo, isShown, 0}},
+ {2623, {wxAuiPaneInfo, isToolbar, 0}},
+ {2624, {wxAuiPaneInfo, isTopDockable, 0}},
+ {2625, {wxAuiPaneInfo, layer, 1}},
+ {2626, {wxAuiPaneInfo, left, 0}},
+ {2627, {wxAuiPaneInfo, leftDockable, 1}},
+ {2628, {wxAuiPaneInfo, maxSize_1, 1}},
+ {2629, {wxAuiPaneInfo, maxSize_2, 2}},
+ {2630, {wxAuiPaneInfo, maximizeButton, 1}},
+ {2631, {wxAuiPaneInfo, minSize_1, 1}},
+ {2632, {wxAuiPaneInfo, minSize_2, 2}},
+ {2633, {wxAuiPaneInfo, minimizeButton, 1}},
+ {2634, {wxAuiPaneInfo, movable, 1}},
+ {2635, {wxAuiPaneInfo, name, 1}},
+ {2636, {wxAuiPaneInfo, paneBorder, 1}},
+ {2637, {wxAuiPaneInfo, pinButton, 1}},
+ {2638, {wxAuiPaneInfo, position, 1}},
+ {2639, {wxAuiPaneInfo, resizable, 1}},
+ {2640, {wxAuiPaneInfo, right, 0}},
+ {2641, {wxAuiPaneInfo, rightDockable, 1}},
+ {2642, {wxAuiPaneInfo, row, 1}},
+ {2643, {wxAuiPaneInfo, safeSet, 1}},
+ {2644, {wxAuiPaneInfo, setFlag, 2}},
+ {2645, {wxAuiPaneInfo, show, 1}},
+ {2646, {wxAuiPaneInfo, toolbarPane, 0}},
+ {2647, {wxAuiPaneInfo, top, 0}},
+ {2648, {wxAuiPaneInfo, topDockable, 1}},
+ {2649, {wxAuiPaneInfo, window, 1}},
+ {2650, {wxAuiNotebook, new_0, 0}},
+ {2651, {wxAuiNotebook, new_2, 2}},
+ {2652, {wxAuiNotebook, addPage, 3}},
+ {2653, {wxAuiNotebook, create, 2}},
+ {2654, {wxAuiNotebook, deletePage, 1}},
+ {2655, {wxAuiNotebook, getArtProvider, 0}},
+ {2656, {wxAuiNotebook, getPage, 1}},
+ {2657, {wxAuiNotebook, getPageBitmap, 1}},
+ {2658, {wxAuiNotebook, getPageCount, 0}},
+ {2659, {wxAuiNotebook, getPageIndex, 1}},
+ {2660, {wxAuiNotebook, getPageText, 1}},
+ {2661, {wxAuiNotebook, getSelection, 0}},
+ {2662, {wxAuiNotebook, insertPage, 4}},
+ {2663, {wxAuiNotebook, removePage, 1}},
+ {2664, {wxAuiNotebook, setArtProvider, 1}},
+ {2665, {wxAuiNotebook, setFont, 1}},
+ {2666, {wxAuiNotebook, setPageBitmap, 2}},
+ {2667, {wxAuiNotebook, setPageText, 2}},
+ {2668, {wxAuiNotebook, setSelection, 1}},
+ {2669, {wxAuiNotebook, setTabCtrlHeight, 1}},
+ {2670, {wxAuiNotebook, setUniformBitmapSize, 1}},
+ {2671, {wxAuiNotebook, 'Destroy', undefined}},
+ {2672, {wxMDIParentFrame, new_0, 0}},
+ {2673, {wxMDIParentFrame, new_4, 4}},
+ {2674, {wxMDIParentFrame, destruct, 0}},
+ {2675, {wxMDIParentFrame, activateNext, 0}},
+ {2676, {wxMDIParentFrame, activatePrevious, 0}},
+ {2677, {wxMDIParentFrame, arrangeIcons, 0}},
+ {2678, {wxMDIParentFrame, cascade, 0}},
+ {2679, {wxMDIParentFrame, create, 4}},
+ {2680, {wxMDIParentFrame, getActiveChild, 0}},
+ {2681, {wxMDIParentFrame, getClientWindow, 0}},
+ {2682, {wxMDIParentFrame, tile, 1}},
+ {2683, {wxMDIChildFrame, new_0, 0}},
+ {2684, {wxMDIChildFrame, new_4, 4}},
+ {2685, {wxMDIChildFrame, destruct, 0}},
+ {2686, {wxMDIChildFrame, activate, 0}},
+ {2687, {wxMDIChildFrame, create, 4}},
+ {2688, {wxMDIChildFrame, maximize, 1}},
+ {2689, {wxMDIChildFrame, restore, 0}},
+ {2690, {wxMDIClientWindow, new_0, 0}},
+ {2691, {wxMDIClientWindow, new_2, 2}},
+ {2692, {wxMDIClientWindow, destruct, 0}},
+ {2693, {wxMDIClientWindow, createClient, 2}},
+ {2694, {wxLayoutAlgorithm, new, 0}},
+ {2695, {wxLayoutAlgorithm, layoutFrame, 2}},
+ {2696, {wxLayoutAlgorithm, layoutMDIFrame, 2}},
+ {2697, {wxLayoutAlgorithm, layoutWindow, 2}},
+ {2698, {wxLayoutAlgorithm, 'Destroy', undefined}},
+ {2699, {wxEvent, getId, 0}},
+ {2700, {wxEvent, getSkipped, 0}},
+ {2701, {wxEvent, getTimestamp, 0}},
+ {2702, {wxEvent, isCommandEvent, 0}},
+ {2703, {wxEvent, resumePropagation, 1}},
+ {2704, {wxEvent, shouldPropagate, 0}},
+ {2705, {wxEvent, skip, 1}},
+ {2706, {wxEvent, stopPropagation, 0}},
+ {2707, {wxCommandEvent, getClientData, 0}},
+ {2708, {wxCommandEvent, getExtraLong, 0}},
+ {2709, {wxCommandEvent, getInt, 0}},
+ {2710, {wxCommandEvent, getSelection, 0}},
+ {2711, {wxCommandEvent, getString, 0}},
+ {2712, {wxCommandEvent, isChecked, 0}},
+ {2713, {wxCommandEvent, isSelection, 0}},
+ {2714, {wxCommandEvent, setInt, 1}},
+ {2715, {wxCommandEvent, setString, 1}},
+ {2716, {wxScrollEvent, getOrientation, 0}},
+ {2717, {wxScrollEvent, getPosition, 0}},
+ {2718, {wxScrollWinEvent, getOrientation, 0}},
+ {2719, {wxScrollWinEvent, getPosition, 0}},
+ {2720, {wxMouseEvent, altDown, 0}},
+ {2721, {wxMouseEvent, button, 1}},
+ {2722, {wxMouseEvent, buttonDClick, 1}},
+ {2723, {wxMouseEvent, buttonDown, 1}},
+ {2724, {wxMouseEvent, buttonUp, 1}},
+ {2725, {wxMouseEvent, cmdDown, 0}},
+ {2726, {wxMouseEvent, controlDown, 0}},
+ {2727, {wxMouseEvent, dragging, 0}},
+ {2728, {wxMouseEvent, entering, 0}},
+ {2729, {wxMouseEvent, getButton, 0}},
+ {2732, {wxMouseEvent, getPosition, 0}},
+ {2733, {wxMouseEvent, getLogicalPosition, 1}},
+ {2734, {wxMouseEvent, getLinesPerAction, 0}},
+ {2735, {wxMouseEvent, getWheelRotation, 0}},
+ {2736, {wxMouseEvent, getWheelDelta, 0}},
+ {2737, {wxMouseEvent, getX, 0}},
+ {2738, {wxMouseEvent, getY, 0}},
+ {2739, {wxMouseEvent, isButton, 0}},
+ {2740, {wxMouseEvent, isPageScroll, 0}},
+ {2741, {wxMouseEvent, leaving, 0}},
+ {2742, {wxMouseEvent, leftDClick, 0}},
+ {2743, {wxMouseEvent, leftDown, 0}},
+ {2744, {wxMouseEvent, leftIsDown, 0}},
+ {2745, {wxMouseEvent, leftUp, 0}},
+ {2746, {wxMouseEvent, metaDown, 0}},
+ {2747, {wxMouseEvent, middleDClick, 0}},
+ {2748, {wxMouseEvent, middleDown, 0}},
+ {2749, {wxMouseEvent, middleIsDown, 0}},
+ {2750, {wxMouseEvent, middleUp, 0}},
+ {2751, {wxMouseEvent, moving, 0}},
+ {2752, {wxMouseEvent, rightDClick, 0}},
+ {2753, {wxMouseEvent, rightDown, 0}},
+ {2754, {wxMouseEvent, rightIsDown, 0}},
+ {2755, {wxMouseEvent, rightUp, 0}},
+ {2756, {wxMouseEvent, shiftDown, 0}},
+ {2757, {wxSetCursorEvent, getCursor, 0}},
+ {2758, {wxSetCursorEvent, getX, 0}},
+ {2759, {wxSetCursorEvent, getY, 0}},
+ {2760, {wxSetCursorEvent, hasCursor, 0}},
+ {2761, {wxSetCursorEvent, setCursor, 1}},
+ {2762, {wxKeyEvent, altDown, 0}},
+ {2763, {wxKeyEvent, cmdDown, 0}},
+ {2764, {wxKeyEvent, controlDown, 0}},
+ {2765, {wxKeyEvent, getKeyCode, 0}},
+ {2766, {wxKeyEvent, getModifiers, 0}},
+ {2769, {wxKeyEvent, getPosition, 0}},
+ {2770, {wxKeyEvent, getRawKeyCode, 0}},
+ {2771, {wxKeyEvent, getRawKeyFlags, 0}},
+ {2772, {wxKeyEvent, getUnicodeKey, 0}},
+ {2773, {wxKeyEvent, getX, 0}},
+ {2774, {wxKeyEvent, getY, 0}},
+ {2775, {wxKeyEvent, hasModifiers, 0}},
+ {2776, {wxKeyEvent, metaDown, 0}},
+ {2777, {wxKeyEvent, shiftDown, 0}},
+ {2778, {wxSizeEvent, getSize, 0}},
+ {2779, {wxMoveEvent, getPosition, 0}},
+ {2780, {wxEraseEvent, getDC, 0}},
+ {2781, {wxFocusEvent, getWindow, 0}},
+ {2782, {wxChildFocusEvent, getWindow, 0}},
+ {2783, {wxMenuEvent, getMenu, 0}},
+ {2784, {wxMenuEvent, getMenuId, 0}},
+ {2785, {wxMenuEvent, isPopup, 0}},
+ {2786, {wxCloseEvent, canVeto, 0}},
+ {2787, {wxCloseEvent, getLoggingOff, 0}},
+ {2788, {wxCloseEvent, setCanVeto, 1}},
+ {2789, {wxCloseEvent, setLoggingOff, 1}},
+ {2790, {wxCloseEvent, veto, 1}},
+ {2791, {wxShowEvent, setShow, 1}},
+ {2792, {wxShowEvent, getShow, 0}},
+ {2793, {wxIconizeEvent, iconized, 0}},
+ {2794, {wxJoystickEvent, buttonDown, 1}},
+ {2795, {wxJoystickEvent, buttonIsDown, 1}},
+ {2796, {wxJoystickEvent, buttonUp, 1}},
+ {2797, {wxJoystickEvent, getButtonChange, 0}},
+ {2798, {wxJoystickEvent, getButtonState, 0}},
+ {2799, {wxJoystickEvent, getJoystick, 0}},
+ {2800, {wxJoystickEvent, getPosition, 0}},
+ {2801, {wxJoystickEvent, getZPosition, 0}},
+ {2802, {wxJoystickEvent, isButton, 0}},
+ {2803, {wxJoystickEvent, isMove, 0}},
+ {2804, {wxJoystickEvent, isZMove, 0}},
+ {2805, {wxUpdateUIEvent, canUpdate, 1}},
+ {2806, {wxUpdateUIEvent, check, 1}},
+ {2807, {wxUpdateUIEvent, enable, 1}},
+ {2808, {wxUpdateUIEvent, show, 1}},
+ {2809, {wxUpdateUIEvent, getChecked, 0}},
+ {2810, {wxUpdateUIEvent, getEnabled, 0}},
+ {2811, {wxUpdateUIEvent, getShown, 0}},
+ {2812, {wxUpdateUIEvent, getSetChecked, 0}},
+ {2813, {wxUpdateUIEvent, getSetEnabled, 0}},
+ {2814, {wxUpdateUIEvent, getSetShown, 0}},
+ {2815, {wxUpdateUIEvent, getSetText, 0}},
+ {2816, {wxUpdateUIEvent, getText, 0}},
+ {2817, {wxUpdateUIEvent, getMode, 0}},
+ {2818, {wxUpdateUIEvent, getUpdateInterval, 0}},
+ {2819, {wxUpdateUIEvent, resetUpdateTime, 0}},
+ {2820, {wxUpdateUIEvent, setMode, 1}},
+ {2821, {wxUpdateUIEvent, setText, 1}},
+ {2822, {wxUpdateUIEvent, setUpdateInterval, 1}},
+ {2823, {wxMouseCaptureChangedEvent, getCapturedWindow, 0}},
+ {2824, {wxPaletteChangedEvent, setChangedWindow, 1}},
+ {2825, {wxPaletteChangedEvent, getChangedWindow, 0}},
+ {2826, {wxQueryNewPaletteEvent, setPaletteRealized, 1}},
+ {2827, {wxQueryNewPaletteEvent, getPaletteRealized, 0}},
+ {2828, {wxNavigationKeyEvent, getDirection, 0}},
+ {2829, {wxNavigationKeyEvent, setDirection, 1}},
+ {2830, {wxNavigationKeyEvent, isWindowChange, 0}},
+ {2831, {wxNavigationKeyEvent, setWindowChange, 1}},
+ {2832, {wxNavigationKeyEvent, isFromTab, 0}},
+ {2833, {wxNavigationKeyEvent, setFromTab, 1}},
+ {2834, {wxNavigationKeyEvent, getCurrentFocus, 0}},
+ {2835, {wxNavigationKeyEvent, setCurrentFocus, 1}},
+ {2836, {wxHelpEvent, getOrigin, 0}},
+ {2837, {wxHelpEvent, getPosition, 0}},
+ {2838, {wxHelpEvent, setOrigin, 1}},
+ {2839, {wxHelpEvent, setPosition, 1}},
+ {2840, {wxContextMenuEvent, getPosition, 0}},
+ {2841, {wxContextMenuEvent, setPosition, 1}},
+ {2842, {wxIdleEvent, canSend, 1}},
+ {2843, {wxIdleEvent, getMode, 0}},
+ {2844, {wxIdleEvent, requestMore, 1}},
+ {2845, {wxIdleEvent, moreRequested, 0}},
+ {2846, {wxIdleEvent, setMode, 1}},
+ {2847, {wxGridEvent, altDown, 0}},
+ {2848, {wxGridEvent, controlDown, 0}},
+ {2849, {wxGridEvent, getCol, 0}},
+ {2850, {wxGridEvent, getPosition, 0}},
+ {2851, {wxGridEvent, getRow, 0}},
+ {2852, {wxGridEvent, metaDown, 0}},
+ {2853, {wxGridEvent, selecting, 0}},
+ {2854, {wxGridEvent, shiftDown, 0}},
+ {2855, {wxNotifyEvent, allow, 0}},
+ {2856, {wxNotifyEvent, isAllowed, 0}},
+ {2857, {wxNotifyEvent, veto, 0}},
+ {2858, {wxSashEvent, getEdge, 0}},
+ {2859, {wxSashEvent, getDragRect, 0}},
+ {2860, {wxSashEvent, getDragStatus, 0}},
+ {2861, {wxListEvent, getCacheFrom, 0}},
+ {2862, {wxListEvent, getCacheTo, 0}},
+ {2863, {wxListEvent, getKeyCode, 0}},
+ {2864, {wxListEvent, getIndex, 0}},
+ {2865, {wxListEvent, getColumn, 0}},
+ {2866, {wxListEvent, getPoint, 0}},
+ {2867, {wxListEvent, getLabel, 0}},
+ {2868, {wxListEvent, getText, 0}},
+ {2869, {wxListEvent, getImage, 0}},
+ {2870, {wxListEvent, getData, 0}},
+ {2871, {wxListEvent, getMask, 0}},
+ {2872, {wxListEvent, getItem, 0}},
+ {2873, {wxListEvent, isEditCancelled, 0}},
+ {2874, {wxDateEvent, getDate, 0}},
+ {2875, {wxCalendarEvent, getWeekDay, 0}},
+ {2876, {wxFileDirPickerEvent, getPath, 0}},
+ {2877, {wxColourPickerEvent, getColour, 0}},
+ {2878, {wxFontPickerEvent, getFont, 0}},
+ {2879, {wxStyledTextEvent, getPosition, 0}},
+ {2880, {wxStyledTextEvent, getKey, 0}},
+ {2881, {wxStyledTextEvent, getModifiers, 0}},
+ {2882, {wxStyledTextEvent, getModificationType, 0}},
+ {2883, {wxStyledTextEvent, getText, 0}},
+ {2884, {wxStyledTextEvent, getLength, 0}},
+ {2885, {wxStyledTextEvent, getLinesAdded, 0}},
+ {2886, {wxStyledTextEvent, getLine, 0}},
+ {2887, {wxStyledTextEvent, getFoldLevelNow, 0}},
+ {2888, {wxStyledTextEvent, getFoldLevelPrev, 0}},
+ {2889, {wxStyledTextEvent, getMargin, 0}},
+ {2890, {wxStyledTextEvent, getMessage, 0}},
+ {2891, {wxStyledTextEvent, getWParam, 0}},
+ {2892, {wxStyledTextEvent, getLParam, 0}},
+ {2893, {wxStyledTextEvent, getListType, 0}},
+ {2894, {wxStyledTextEvent, getX, 0}},
+ {2895, {wxStyledTextEvent, getY, 0}},
+ {2896, {wxStyledTextEvent, getDragText, 0}},
+ {2897, {wxStyledTextEvent, getDragAllowMove, 0}},
+ {2898, {wxStyledTextEvent, getDragResult, 0}},
+ {2899, {wxStyledTextEvent, getShift, 0}},
+ {2900, {wxStyledTextEvent, getControl, 0}},
+ {2901, {wxStyledTextEvent, getAlt, 0}},
+ {2902, {utils, getKeyState, 1}},
+ {2903, {utils, getMousePosition, 2}},
+ {2904, {utils, getMouseState, 0}},
+ {2905, {utils, setDetectableAutoRepeat, 1}},
+ {2906, {utils, bell, 0}},
+ {2907, {utils, findMenuItemId, 3}},
+ {2908, {utils, genericFindWindowAtPoint, 1}},
+ {2909, {utils, findWindowAtPoint, 1}},
+ {2910, {utils, beginBusyCursor, 1}},
+ {2911, {utils, endBusyCursor, 0}},
+ {2912, {utils, isBusy, 0}},
+ {2913, {utils, shutdown, 1}},
+ {2914, {utils, shell, 1}},
+ {2915, {utils, launchDefaultBrowser, 2}},
+ {2916, {utils, getEmailAddress, 0}},
+ {2917, {utils, getUserId, 0}},
+ {2918, {utils, getHomeDir, 0}},
+ {2919, {utils, newId, 0}},
+ {2920, {utils, registerId, 1}},
+ {2921, {utils, getCurrentId, 0}},
+ {2922, {utils, getOsDescription, 0}},
+ {2923, {utils, isPlatformLittleEndian, 0}},
+ {2924, {utils, isPlatform64Bit, 0}},
+ {2925, {wxPrintout, new, 1}},
+ {2926, {wxPrintout, destruct, 0}},
+ {2927, {wxPrintout, getDC, 0}},
+ {2928, {wxPrintout, getPageSizeMM, 2}},
+ {2929, {wxPrintout, getPageSizePixels, 2}},
+ {2930, {wxPrintout, getPaperRectPixels, 0}},
+ {2931, {wxPrintout, getPPIPrinter, 2}},
+ {2932, {wxPrintout, getPPIScreen, 2}},
+ {2933, {wxPrintout, getTitle, 0}},
+ {2934, {wxPrintout, isPreview, 0}},
+ {2935, {wxPrintout, fitThisSizeToPaper, 1}},
+ {2936, {wxPrintout, fitThisSizeToPage, 1}},
+ {2937, {wxPrintout, fitThisSizeToPageMargins, 2}},
+ {2938, {wxPrintout, mapScreenSizeToPaper, 0}},
+ {2939, {wxPrintout, mapScreenSizeToPage, 0}},
+ {2940, {wxPrintout, mapScreenSizeToPageMargins, 1}},
+ {2941, {wxPrintout, mapScreenSizeToDevice, 0}},
+ {2942, {wxPrintout, getLogicalPaperRect, 0}},
+ {2943, {wxPrintout, getLogicalPageRect, 0}},
+ {2944, {wxPrintout, getLogicalPageMarginsRect, 1}},
+ {2945, {wxPrintout, setLogicalOrigin, 2}},
+ {2946, {wxPrintout, offsetLogicalOrigin, 2}},
+ {2947, {wxStyledTextCtrl, new_2, 2}},
+ {2948, {wxStyledTextCtrl, new_0, 0}},
+ {2949, {wxStyledTextCtrl, destruct, 0}},
+ {2950, {wxStyledTextCtrl, create, 2}},
+ {2951, {wxStyledTextCtrl, addText, 1}},
+ {2952, {wxStyledTextCtrl, addStyledText, 1}},
+ {2953, {wxStyledTextCtrl, insertText, 2}},
+ {2954, {wxStyledTextCtrl, clearAll, 0}},
+ {2955, {wxStyledTextCtrl, clearDocumentStyle, 0}},
+ {2956, {wxStyledTextCtrl, getLength, 0}},
+ {2957, {wxStyledTextCtrl, getCharAt, 1}},
+ {2958, {wxStyledTextCtrl, getCurrentPos, 0}},
+ {2959, {wxStyledTextCtrl, getAnchor, 0}},
+ {2960, {wxStyledTextCtrl, getStyleAt, 1}},
+ {2961, {wxStyledTextCtrl, redo, 0}},
+ {2962, {wxStyledTextCtrl, setUndoCollection, 1}},
+ {2963, {wxStyledTextCtrl, selectAll, 0}},
+ {2964, {wxStyledTextCtrl, setSavePoint, 0}},
+ {2965, {wxStyledTextCtrl, getStyledText, 2}},
+ {2966, {wxStyledTextCtrl, canRedo, 0}},
+ {2967, {wxStyledTextCtrl, markerLineFromHandle, 1}},
+ {2968, {wxStyledTextCtrl, markerDeleteHandle, 1}},
+ {2969, {wxStyledTextCtrl, getUndoCollection, 0}},
+ {2970, {wxStyledTextCtrl, getViewWhiteSpace, 0}},
+ {2971, {wxStyledTextCtrl, setViewWhiteSpace, 1}},
+ {2972, {wxStyledTextCtrl, positionFromPoint, 1}},
+ {2973, {wxStyledTextCtrl, positionFromPointClose, 2}},
+ {2974, {wxStyledTextCtrl, gotoLine, 1}},
+ {2975, {wxStyledTextCtrl, gotoPos, 1}},
+ {2976, {wxStyledTextCtrl, setAnchor, 1}},
+ {2977, {wxStyledTextCtrl, getCurLine, 1}},
+ {2978, {wxStyledTextCtrl, getEndStyled, 0}},
+ {2979, {wxStyledTextCtrl, convertEOLs, 1}},
+ {2980, {wxStyledTextCtrl, getEOLMode, 0}},
+ {2981, {wxStyledTextCtrl, setEOLMode, 1}},
+ {2982, {wxStyledTextCtrl, startStyling, 2}},
+ {2983, {wxStyledTextCtrl, setStyling, 2}},
+ {2984, {wxStyledTextCtrl, getBufferedDraw, 0}},
+ {2985, {wxStyledTextCtrl, setBufferedDraw, 1}},
+ {2986, {wxStyledTextCtrl, setTabWidth, 1}},
+ {2987, {wxStyledTextCtrl, getTabWidth, 0}},
+ {2988, {wxStyledTextCtrl, setCodePage, 1}},
+ {2989, {wxStyledTextCtrl, markerDefine, 3}},
+ {2990, {wxStyledTextCtrl, markerSetForeground, 2}},
+ {2991, {wxStyledTextCtrl, markerSetBackground, 2}},
+ {2992, {wxStyledTextCtrl, markerAdd, 2}},
+ {2993, {wxStyledTextCtrl, markerDelete, 2}},
+ {2994, {wxStyledTextCtrl, markerDeleteAll, 1}},
+ {2995, {wxStyledTextCtrl, markerGet, 1}},
+ {2996, {wxStyledTextCtrl, markerNext, 2}},
+ {2997, {wxStyledTextCtrl, markerPrevious, 2}},
+ {2998, {wxStyledTextCtrl, markerDefineBitmap, 2}},
+ {2999, {wxStyledTextCtrl, markerAddSet, 2}},
+ {3000, {wxStyledTextCtrl, markerSetAlpha, 2}},
+ {3001, {wxStyledTextCtrl, setMarginType, 2}},
+ {3002, {wxStyledTextCtrl, getMarginType, 1}},
+ {3003, {wxStyledTextCtrl, setMarginWidth, 2}},
+ {3004, {wxStyledTextCtrl, getMarginWidth, 1}},
+ {3005, {wxStyledTextCtrl, setMarginMask, 2}},
+ {3006, {wxStyledTextCtrl, getMarginMask, 1}},
+ {3007, {wxStyledTextCtrl, setMarginSensitive, 2}},
+ {3008, {wxStyledTextCtrl, getMarginSensitive, 1}},
+ {3009, {wxStyledTextCtrl, styleClearAll, 0}},
+ {3010, {wxStyledTextCtrl, styleSetForeground, 2}},
+ {3011, {wxStyledTextCtrl, styleSetBackground, 2}},
+ {3012, {wxStyledTextCtrl, styleSetBold, 2}},
+ {3013, {wxStyledTextCtrl, styleSetItalic, 2}},
+ {3014, {wxStyledTextCtrl, styleSetSize, 2}},
+ {3015, {wxStyledTextCtrl, styleSetFaceName, 2}},
+ {3016, {wxStyledTextCtrl, styleSetEOLFilled, 2}},
+ {3017, {wxStyledTextCtrl, styleResetDefault, 0}},
+ {3018, {wxStyledTextCtrl, styleSetUnderline, 2}},
+ {3019, {wxStyledTextCtrl, styleSetCase, 2}},
+ {3020, {wxStyledTextCtrl, styleSetHotSpot, 2}},
+ {3021, {wxStyledTextCtrl, setSelForeground, 2}},
+ {3022, {wxStyledTextCtrl, setSelBackground, 2}},
+ {3023, {wxStyledTextCtrl, getSelAlpha, 0}},
+ {3024, {wxStyledTextCtrl, setSelAlpha, 1}},
+ {3025, {wxStyledTextCtrl, setCaretForeground, 1}},
+ {3026, {wxStyledTextCtrl, cmdKeyAssign, 3}},
+ {3027, {wxStyledTextCtrl, cmdKeyClear, 2}},
+ {3028, {wxStyledTextCtrl, cmdKeyClearAll, 0}},
+ {3029, {wxStyledTextCtrl, setStyleBytes, 2}},
+ {3030, {wxStyledTextCtrl, styleSetVisible, 2}},
+ {3031, {wxStyledTextCtrl, getCaretPeriod, 0}},
+ {3032, {wxStyledTextCtrl, setCaretPeriod, 1}},
+ {3033, {wxStyledTextCtrl, setWordChars, 1}},
+ {3034, {wxStyledTextCtrl, beginUndoAction, 0}},
+ {3035, {wxStyledTextCtrl, endUndoAction, 0}},
+ {3036, {wxStyledTextCtrl, indicatorSetStyle, 2}},
+ {3037, {wxStyledTextCtrl, indicatorGetStyle, 1}},
+ {3038, {wxStyledTextCtrl, indicatorSetForeground, 2}},
+ {3039, {wxStyledTextCtrl, indicatorGetForeground, 1}},
+ {3040, {wxStyledTextCtrl, setWhitespaceForeground, 2}},
+ {3041, {wxStyledTextCtrl, setWhitespaceBackground, 2}},
+ {3042, {wxStyledTextCtrl, getStyleBits, 0}},
+ {3043, {wxStyledTextCtrl, setLineState, 2}},
+ {3044, {wxStyledTextCtrl, getLineState, 1}},
+ {3045, {wxStyledTextCtrl, getMaxLineState, 0}},
+ {3046, {wxStyledTextCtrl, getCaretLineVisible, 0}},
+ {3047, {wxStyledTextCtrl, setCaretLineVisible, 1}},
+ {3048, {wxStyledTextCtrl, getCaretLineBackground, 0}},
+ {3049, {wxStyledTextCtrl, setCaretLineBackground, 1}},
+ {3050, {wxStyledTextCtrl, autoCompShow, 2}},
+ {3051, {wxStyledTextCtrl, autoCompCancel, 0}},
+ {3052, {wxStyledTextCtrl, autoCompActive, 0}},
+ {3053, {wxStyledTextCtrl, autoCompPosStart, 0}},
+ {3054, {wxStyledTextCtrl, autoCompComplete, 0}},
+ {3055, {wxStyledTextCtrl, autoCompStops, 1}},
+ {3056, {wxStyledTextCtrl, autoCompSetSeparator, 1}},
+ {3057, {wxStyledTextCtrl, autoCompGetSeparator, 0}},
+ {3058, {wxStyledTextCtrl, autoCompSelect, 1}},
+ {3059, {wxStyledTextCtrl, autoCompSetCancelAtStart, 1}},
+ {3060, {wxStyledTextCtrl, autoCompGetCancelAtStart, 0}},
+ {3061, {wxStyledTextCtrl, autoCompSetFillUps, 1}},
+ {3062, {wxStyledTextCtrl, autoCompSetChooseSingle, 1}},
+ {3063, {wxStyledTextCtrl, autoCompGetChooseSingle, 0}},
+ {3064, {wxStyledTextCtrl, autoCompSetIgnoreCase, 1}},
+ {3065, {wxStyledTextCtrl, autoCompGetIgnoreCase, 0}},
+ {3066, {wxStyledTextCtrl, userListShow, 2}},
+ {3067, {wxStyledTextCtrl, autoCompSetAutoHide, 1}},
+ {3068, {wxStyledTextCtrl, autoCompGetAutoHide, 0}},
+ {3069, {wxStyledTextCtrl, autoCompSetDropRestOfWord, 1}},
+ {3070, {wxStyledTextCtrl, autoCompGetDropRestOfWord, 0}},
+ {3071, {wxStyledTextCtrl, registerImage, 2}},
+ {3072, {wxStyledTextCtrl, clearRegisteredImages, 0}},
+ {3073, {wxStyledTextCtrl, autoCompGetTypeSeparator, 0}},
+ {3074, {wxStyledTextCtrl, autoCompSetTypeSeparator, 1}},
+ {3075, {wxStyledTextCtrl, autoCompSetMaxWidth, 1}},
+ {3076, {wxStyledTextCtrl, autoCompGetMaxWidth, 0}},
+ {3077, {wxStyledTextCtrl, autoCompSetMaxHeight, 1}},
+ {3078, {wxStyledTextCtrl, autoCompGetMaxHeight, 0}},
+ {3079, {wxStyledTextCtrl, setIndent, 1}},
+ {3080, {wxStyledTextCtrl, getIndent, 0}},
+ {3081, {wxStyledTextCtrl, setUseTabs, 1}},
+ {3082, {wxStyledTextCtrl, getUseTabs, 0}},
+ {3083, {wxStyledTextCtrl, setLineIndentation, 2}},
+ {3084, {wxStyledTextCtrl, getLineIndentation, 1}},
+ {3085, {wxStyledTextCtrl, getLineIndentPosition, 1}},
+ {3086, {wxStyledTextCtrl, getColumn, 1}},
+ {3087, {wxStyledTextCtrl, setUseHorizontalScrollBar, 1}},
+ {3088, {wxStyledTextCtrl, getUseHorizontalScrollBar, 0}},
+ {3089, {wxStyledTextCtrl, setIndentationGuides, 1}},
+ {3090, {wxStyledTextCtrl, getIndentationGuides, 0}},
+ {3091, {wxStyledTextCtrl, setHighlightGuide, 1}},
+ {3092, {wxStyledTextCtrl, getHighlightGuide, 0}},
+ {3093, {wxStyledTextCtrl, getLineEndPosition, 1}},
+ {3094, {wxStyledTextCtrl, getCodePage, 0}},
+ {3095, {wxStyledTextCtrl, getCaretForeground, 0}},
+ {3096, {wxStyledTextCtrl, getReadOnly, 0}},
+ {3097, {wxStyledTextCtrl, setCurrentPos, 1}},
+ {3098, {wxStyledTextCtrl, setSelectionStart, 1}},
+ {3099, {wxStyledTextCtrl, getSelectionStart, 0}},
+ {3100, {wxStyledTextCtrl, setSelectionEnd, 1}},
+ {3101, {wxStyledTextCtrl, getSelectionEnd, 0}},
+ {3102, {wxStyledTextCtrl, setPrintMagnification, 1}},
+ {3103, {wxStyledTextCtrl, getPrintMagnification, 0}},
+ {3104, {wxStyledTextCtrl, setPrintColourMode, 1}},
+ {3105, {wxStyledTextCtrl, getPrintColourMode, 0}},
+ {3106, {wxStyledTextCtrl, findText, 4}},
+ {3107, {wxStyledTextCtrl, formatRange, 7}},
+ {3108, {wxStyledTextCtrl, getFirstVisibleLine, 0}},
+ {3109, {wxStyledTextCtrl, getLine, 1}},
+ {3110, {wxStyledTextCtrl, getLineCount, 0}},
+ {3111, {wxStyledTextCtrl, setMarginLeft, 1}},
+ {3112, {wxStyledTextCtrl, getMarginLeft, 0}},
+ {3113, {wxStyledTextCtrl, setMarginRight, 1}},
+ {3114, {wxStyledTextCtrl, getMarginRight, 0}},
+ {3115, {wxStyledTextCtrl, getModify, 0}},
+ {3116, {wxStyledTextCtrl, setSelection, 2}},
+ {3117, {wxStyledTextCtrl, getSelectedText, 0}},
+ {3118, {wxStyledTextCtrl, getTextRange, 2}},
+ {3119, {wxStyledTextCtrl, hideSelection, 1}},
+ {3120, {wxStyledTextCtrl, lineFromPosition, 1}},
+ {3121, {wxStyledTextCtrl, positionFromLine, 1}},
+ {3122, {wxStyledTextCtrl, lineScroll, 2}},
+ {3123, {wxStyledTextCtrl, ensureCaretVisible, 0}},
+ {3124, {wxStyledTextCtrl, replaceSelection, 1}},
+ {3125, {wxStyledTextCtrl, setReadOnly, 1}},
+ {3126, {wxStyledTextCtrl, canPaste, 0}},
+ {3127, {wxStyledTextCtrl, canUndo, 0}},
+ {3128, {wxStyledTextCtrl, emptyUndoBuffer, 0}},
+ {3129, {wxStyledTextCtrl, undo, 0}},
+ {3130, {wxStyledTextCtrl, cut, 0}},
+ {3131, {wxStyledTextCtrl, copy, 0}},
+ {3132, {wxStyledTextCtrl, paste, 0}},
+ {3133, {wxStyledTextCtrl, clear, 0}},
+ {3134, {wxStyledTextCtrl, setText, 1}},
+ {3135, {wxStyledTextCtrl, getText, 0}},
+ {3136, {wxStyledTextCtrl, getTextLength, 0}},
+ {3137, {wxStyledTextCtrl, getOvertype, 0}},
+ {3138, {wxStyledTextCtrl, setCaretWidth, 1}},
+ {3139, {wxStyledTextCtrl, getCaretWidth, 0}},
+ {3140, {wxStyledTextCtrl, setTargetStart, 1}},
+ {3141, {wxStyledTextCtrl, getTargetStart, 0}},
+ {3142, {wxStyledTextCtrl, setTargetEnd, 1}},
+ {3143, {wxStyledTextCtrl, getTargetEnd, 0}},
+ {3144, {wxStyledTextCtrl, replaceTarget, 1}},
+ {3145, {wxStyledTextCtrl, searchInTarget, 1}},
+ {3146, {wxStyledTextCtrl, setSearchFlags, 1}},
+ {3147, {wxStyledTextCtrl, getSearchFlags, 0}},
+ {3148, {wxStyledTextCtrl, callTipShow, 2}},
+ {3149, {wxStyledTextCtrl, callTipCancel, 0}},
+ {3150, {wxStyledTextCtrl, callTipActive, 0}},
+ {3151, {wxStyledTextCtrl, callTipPosAtStart, 0}},
+ {3152, {wxStyledTextCtrl, callTipSetHighlight, 2}},
+ {3153, {wxStyledTextCtrl, callTipSetBackground, 1}},
+ {3154, {wxStyledTextCtrl, callTipSetForeground, 1}},
+ {3155, {wxStyledTextCtrl, callTipSetForegroundHighlight, 1}},
+ {3156, {wxStyledTextCtrl, callTipUseStyle, 1}},
+ {3157, {wxStyledTextCtrl, visibleFromDocLine, 1}},
+ {3158, {wxStyledTextCtrl, docLineFromVisible, 1}},
+ {3159, {wxStyledTextCtrl, wrapCount, 1}},
+ {3160, {wxStyledTextCtrl, setFoldLevel, 2}},
+ {3161, {wxStyledTextCtrl, getFoldLevel, 1}},
+ {3162, {wxStyledTextCtrl, getLastChild, 2}},
+ {3163, {wxStyledTextCtrl, getFoldParent, 1}},
+ {3164, {wxStyledTextCtrl, showLines, 2}},
+ {3165, {wxStyledTextCtrl, hideLines, 2}},
+ {3166, {wxStyledTextCtrl, getLineVisible, 1}},
+ {3167, {wxStyledTextCtrl, setFoldExpanded, 2}},
+ {3168, {wxStyledTextCtrl, getFoldExpanded, 1}},
+ {3169, {wxStyledTextCtrl, toggleFold, 1}},
+ {3170, {wxStyledTextCtrl, ensureVisible, 1}},
+ {3171, {wxStyledTextCtrl, setFoldFlags, 1}},
+ {3172, {wxStyledTextCtrl, ensureVisibleEnforcePolicy, 1}},
+ {3173, {wxStyledTextCtrl, setTabIndents, 1}},
+ {3174, {wxStyledTextCtrl, getTabIndents, 0}},
+ {3175, {wxStyledTextCtrl, setBackSpaceUnIndents, 1}},
+ {3176, {wxStyledTextCtrl, getBackSpaceUnIndents, 0}},
+ {3177, {wxStyledTextCtrl, setMouseDwellTime, 1}},
+ {3178, {wxStyledTextCtrl, getMouseDwellTime, 0}},
+ {3179, {wxStyledTextCtrl, wordStartPosition, 2}},
+ {3180, {wxStyledTextCtrl, wordEndPosition, 2}},
+ {3181, {wxStyledTextCtrl, setWrapMode, 1}},
+ {3182, {wxStyledTextCtrl, getWrapMode, 0}},
+ {3183, {wxStyledTextCtrl, setWrapVisualFlags, 1}},
+ {3184, {wxStyledTextCtrl, getWrapVisualFlags, 0}},
+ {3185, {wxStyledTextCtrl, setWrapVisualFlagsLocation, 1}},
+ {3186, {wxStyledTextCtrl, getWrapVisualFlagsLocation, 0}},
+ {3187, {wxStyledTextCtrl, setWrapStartIndent, 1}},
+ {3188, {wxStyledTextCtrl, getWrapStartIndent, 0}},
+ {3189, {wxStyledTextCtrl, setLayoutCache, 1}},
+ {3190, {wxStyledTextCtrl, getLayoutCache, 0}},
+ {3191, {wxStyledTextCtrl, setScrollWidth, 1}},
+ {3192, {wxStyledTextCtrl, getScrollWidth, 0}},
+ {3193, {wxStyledTextCtrl, textWidth, 2}},
+ {3194, {wxStyledTextCtrl, getEndAtLastLine, 0}},
+ {3195, {wxStyledTextCtrl, textHeight, 1}},
+ {3196, {wxStyledTextCtrl, setUseVerticalScrollBar, 1}},
+ {3197, {wxStyledTextCtrl, getUseVerticalScrollBar, 0}},
+ {3198, {wxStyledTextCtrl, appendText, 1}},
+ {3199, {wxStyledTextCtrl, getTwoPhaseDraw, 0}},
+ {3200, {wxStyledTextCtrl, setTwoPhaseDraw, 1}},
+ {3201, {wxStyledTextCtrl, targetFromSelection, 0}},
+ {3202, {wxStyledTextCtrl, linesJoin, 0}},
+ {3203, {wxStyledTextCtrl, linesSplit, 1}},
+ {3204, {wxStyledTextCtrl, setFoldMarginColour, 2}},
+ {3205, {wxStyledTextCtrl, setFoldMarginHiColour, 2}},
+ {3206, {wxStyledTextCtrl, lineDown, 0}},
+ {3207, {wxStyledTextCtrl, lineDownExtend, 0}},
+ {3208, {wxStyledTextCtrl, lineUp, 0}},
+ {3209, {wxStyledTextCtrl, lineUpExtend, 0}},
+ {3210, {wxStyledTextCtrl, charLeft, 0}},
+ {3211, {wxStyledTextCtrl, charLeftExtend, 0}},
+ {3212, {wxStyledTextCtrl, charRight, 0}},
+ {3213, {wxStyledTextCtrl, charRightExtend, 0}},
+ {3214, {wxStyledTextCtrl, wordLeft, 0}},
+ {3215, {wxStyledTextCtrl, wordLeftExtend, 0}},
+ {3216, {wxStyledTextCtrl, wordRight, 0}},
+ {3217, {wxStyledTextCtrl, wordRightExtend, 0}},
+ {3218, {wxStyledTextCtrl, home, 0}},
+ {3219, {wxStyledTextCtrl, homeExtend, 0}},
+ {3220, {wxStyledTextCtrl, lineEnd, 0}},
+ {3221, {wxStyledTextCtrl, lineEndExtend, 0}},
+ {3222, {wxStyledTextCtrl, documentStart, 0}},
+ {3223, {wxStyledTextCtrl, documentStartExtend, 0}},
+ {3224, {wxStyledTextCtrl, documentEnd, 0}},
+ {3225, {wxStyledTextCtrl, documentEndExtend, 0}},
+ {3226, {wxStyledTextCtrl, pageUp, 0}},
+ {3227, {wxStyledTextCtrl, pageUpExtend, 0}},
+ {3228, {wxStyledTextCtrl, pageDown, 0}},
+ {3229, {wxStyledTextCtrl, pageDownExtend, 0}},
+ {3230, {wxStyledTextCtrl, editToggleOvertype, 0}},
+ {3231, {wxStyledTextCtrl, cancel, 0}},
+ {3232, {wxStyledTextCtrl, deleteBack, 0}},
+ {3233, {wxStyledTextCtrl, tab, 0}},
+ {3234, {wxStyledTextCtrl, backTab, 0}},
+ {3235, {wxStyledTextCtrl, newLine, 0}},
+ {3236, {wxStyledTextCtrl, formFeed, 0}},
+ {3237, {wxStyledTextCtrl, vCHome, 0}},
+ {3238, {wxStyledTextCtrl, vCHomeExtend, 0}},
+ {3239, {wxStyledTextCtrl, zoomIn, 0}},
+ {3240, {wxStyledTextCtrl, zoomOut, 0}},
+ {3241, {wxStyledTextCtrl, delWordLeft, 0}},
+ {3242, {wxStyledTextCtrl, delWordRight, 0}},
+ {3243, {wxStyledTextCtrl, lineCut, 0}},
+ {3244, {wxStyledTextCtrl, lineDelete, 0}},
+ {3245, {wxStyledTextCtrl, lineTranspose, 0}},
+ {3246, {wxStyledTextCtrl, lineDuplicate, 0}},
+ {3247, {wxStyledTextCtrl, lowerCase, 0}},
+ {3248, {wxStyledTextCtrl, upperCase, 0}},
+ {3249, {wxStyledTextCtrl, lineScrollDown, 0}},
+ {3250, {wxStyledTextCtrl, lineScrollUp, 0}},
+ {3251, {wxStyledTextCtrl, deleteBackNotLine, 0}},
+ {3252, {wxStyledTextCtrl, homeDisplay, 0}},
+ {3253, {wxStyledTextCtrl, homeDisplayExtend, 0}},
+ {3254, {wxStyledTextCtrl, lineEndDisplay, 0}},
+ {3255, {wxStyledTextCtrl, lineEndDisplayExtend, 0}},
+ {3256, {wxStyledTextCtrl, homeWrapExtend, 0}},
+ {3257, {wxStyledTextCtrl, lineEndWrap, 0}},
+ {3258, {wxStyledTextCtrl, lineEndWrapExtend, 0}},
+ {3259, {wxStyledTextCtrl, vCHomeWrap, 0}},
+ {3260, {wxStyledTextCtrl, vCHomeWrapExtend, 0}},
+ {3261, {wxStyledTextCtrl, lineCopy, 0}},
+ {3262, {wxStyledTextCtrl, moveCaretInsideView, 0}},
+ {3263, {wxStyledTextCtrl, lineLength, 1}},
+ {3264, {wxStyledTextCtrl, braceHighlight, 2}},
+ {3265, {wxStyledTextCtrl, braceBadLight, 1}},
+ {3266, {wxStyledTextCtrl, braceMatch, 1}},
+ {3267, {wxStyledTextCtrl, getViewEOL, 0}},
+ {3268, {wxStyledTextCtrl, setViewEOL, 1}},
+ {3269, {wxStyledTextCtrl, setModEventMask, 1}},
+ {3270, {wxStyledTextCtrl, getEdgeColumn, 0}},
+ {3271, {wxStyledTextCtrl, setEdgeColumn, 1}},
+ {3272, {wxStyledTextCtrl, getEdgeMode, 0}},
+ {3273, {wxStyledTextCtrl, getEdgeColour, 0}},
+ {3274, {wxStyledTextCtrl, setEdgeColour, 1}},
+ {3275, {wxStyledTextCtrl, searchAnchor, 0}},
+ {3276, {wxStyledTextCtrl, searchNext, 2}},
+ {3277, {wxStyledTextCtrl, searchPrev, 2}},
+ {3278, {wxStyledTextCtrl, linesOnScreen, 0}},
+ {3279, {wxStyledTextCtrl, usePopUp, 1}},
+ {3280, {wxStyledTextCtrl, selectionIsRectangle, 0}},
+ {3281, {wxStyledTextCtrl, setZoom, 1}},
+ {3282, {wxStyledTextCtrl, getZoom, 0}},
+ {3283, {wxStyledTextCtrl, getModEventMask, 0}},
+ {3284, {wxStyledTextCtrl, setSTCFocus, 1}},
+ {3285, {wxStyledTextCtrl, getSTCFocus, 0}},
+ {3286, {wxStyledTextCtrl, setStatus, 1}},
+ {3287, {wxStyledTextCtrl, getStatus, 0}},
+ {3288, {wxStyledTextCtrl, setMouseDownCaptures, 1}},
+ {3289, {wxStyledTextCtrl, getMouseDownCaptures, 0}},
+ {3290, {wxStyledTextCtrl, setSTCCursor, 1}},
+ {3291, {wxStyledTextCtrl, getSTCCursor, 0}},
+ {3292, {wxStyledTextCtrl, setControlCharSymbol, 1}},
+ {3293, {wxStyledTextCtrl, getControlCharSymbol, 0}},
+ {3294, {wxStyledTextCtrl, wordPartLeft, 0}},
+ {3295, {wxStyledTextCtrl, wordPartLeftExtend, 0}},
+ {3296, {wxStyledTextCtrl, wordPartRight, 0}},
+ {3297, {wxStyledTextCtrl, wordPartRightExtend, 0}},
+ {3298, {wxStyledTextCtrl, setVisiblePolicy, 2}},
+ {3299, {wxStyledTextCtrl, delLineLeft, 0}},
+ {3300, {wxStyledTextCtrl, delLineRight, 0}},
+ {3301, {wxStyledTextCtrl, getXOffset, 0}},
+ {3302, {wxStyledTextCtrl, chooseCaretX, 0}},
+ {3303, {wxStyledTextCtrl, setXCaretPolicy, 2}},
+ {3304, {wxStyledTextCtrl, setYCaretPolicy, 2}},
+ {3305, {wxStyledTextCtrl, getPrintWrapMode, 0}},
+ {3306, {wxStyledTextCtrl, setHotspotActiveForeground, 2}},
+ {3307, {wxStyledTextCtrl, setHotspotActiveBackground, 2}},
+ {3308, {wxStyledTextCtrl, setHotspotActiveUnderline, 1}},
+ {3309, {wxStyledTextCtrl, setHotspotSingleLine, 1}},
+ {3310, {wxStyledTextCtrl, paraDownExtend, 0}},
+ {3311, {wxStyledTextCtrl, paraUp, 0}},
+ {3312, {wxStyledTextCtrl, paraUpExtend, 0}},
+ {3313, {wxStyledTextCtrl, positionBefore, 1}},
+ {3314, {wxStyledTextCtrl, positionAfter, 1}},
+ {3315, {wxStyledTextCtrl, copyRange, 2}},
+ {3316, {wxStyledTextCtrl, copyText, 2}},
+ {3317, {wxStyledTextCtrl, setSelectionMode, 1}},
+ {3318, {wxStyledTextCtrl, getSelectionMode, 0}},
+ {3319, {wxStyledTextCtrl, lineDownRectExtend, 0}},
+ {3320, {wxStyledTextCtrl, lineUpRectExtend, 0}},
+ {3321, {wxStyledTextCtrl, charLeftRectExtend, 0}},
+ {3322, {wxStyledTextCtrl, charRightRectExtend, 0}},
+ {3323, {wxStyledTextCtrl, homeRectExtend, 0}},
+ {3324, {wxStyledTextCtrl, vCHomeRectExtend, 0}},
+ {3325, {wxStyledTextCtrl, lineEndRectExtend, 0}},
+ {3326, {wxStyledTextCtrl, pageUpRectExtend, 0}},
+ {3327, {wxStyledTextCtrl, pageDownRectExtend, 0}},
+ {3328, {wxStyledTextCtrl, stutteredPageUp, 0}},
+ {3329, {wxStyledTextCtrl, stutteredPageUpExtend, 0}},
+ {3330, {wxStyledTextCtrl, stutteredPageDown, 0}},
+ {3331, {wxStyledTextCtrl, stutteredPageDownExtend, 0}},
+ {3332, {wxStyledTextCtrl, wordLeftEnd, 0}},
+ {3333, {wxStyledTextCtrl, wordLeftEndExtend, 0}},
+ {3334, {wxStyledTextCtrl, wordRightEnd, 0}},
+ {3335, {wxStyledTextCtrl, wordRightEndExtend, 0}},
+ {3336, {wxStyledTextCtrl, setWhitespaceChars, 1}},
+ {3337, {wxStyledTextCtrl, setCharsDefault, 0}},
+ {3338, {wxStyledTextCtrl, autoCompGetCurrent, 0}},
+ {3339, {wxStyledTextCtrl, allocate, 1}},
+ {3340, {wxStyledTextCtrl, findColumn, 2}},
+ {3341, {wxStyledTextCtrl, getCaretSticky, 0}},
+ {3342, {wxStyledTextCtrl, setCaretSticky, 1}},
+ {3343, {wxStyledTextCtrl, toggleCaretSticky, 0}},
+ {3344, {wxStyledTextCtrl, setPasteConvertEndings, 1}},
+ {3345, {wxStyledTextCtrl, getPasteConvertEndings, 0}},
+ {3346, {wxStyledTextCtrl, selectionDuplicate, 0}},
+ {3347, {wxStyledTextCtrl, setCaretLineBackAlpha, 1}},
+ {3348, {wxStyledTextCtrl, getCaretLineBackAlpha, 0}},
+ {3349, {wxStyledTextCtrl, startRecord, 0}},
+ {3350, {wxStyledTextCtrl, stopRecord, 0}},
+ {3351, {wxStyledTextCtrl, setLexer, 1}},
+ {3352, {wxStyledTextCtrl, getLexer, 0}},
+ {3353, {wxStyledTextCtrl, colourise, 2}},
+ {3354, {wxStyledTextCtrl, setProperty, 2}},
+ {3355, {wxStyledTextCtrl, setKeyWords, 2}},
+ {3356, {wxStyledTextCtrl, setLexerLanguage, 1}},
+ {3357, {wxStyledTextCtrl, getProperty, 1}},
+ {3358, {wxStyledTextCtrl, getStyleBitsNeeded, 0}},
+ {3359, {wxStyledTextCtrl, getCurrentLine, 0}},
+ {3360, {wxStyledTextCtrl, styleSetSpec, 2}},
+ {3361, {wxStyledTextCtrl, styleSetFont, 2}},
+ {3362, {wxStyledTextCtrl, styleSetFontAttr, 7}},
+ {3363, {wxStyledTextCtrl, styleSetCharacterSet, 2}},
+ {3364, {wxStyledTextCtrl, styleSetFontEncoding, 2}},
+ {3365, {wxStyledTextCtrl, cmdKeyExecute, 1}},
+ {3366, {wxStyledTextCtrl, setMargins, 2}},
+ {3367, {wxStyledTextCtrl, getSelection, 2}},
+ {3368, {wxStyledTextCtrl, pointFromPosition, 1}},
+ {3369, {wxStyledTextCtrl, scrollToLine, 1}},
+ {3370, {wxStyledTextCtrl, scrollToColumn, 1}},
+ {3371, {wxStyledTextCtrl, sendMsg, 2}},
+ {3372, {wxStyledTextCtrl, setVScrollBar, 1}},
+ {3373, {wxStyledTextCtrl, setHScrollBar, 1}},
+ {3374, {wxStyledTextCtrl, getLastKeydownProcessed, 0}},
+ {3375, {wxStyledTextCtrl, setLastKeydownProcessed, 1}},
+ {3376, {wxStyledTextCtrl, saveFile, 1}},
+ {3377, {wxStyledTextCtrl, loadFile, 1}},
+ {3378, {wxStyledTextCtrl, doDragOver, 3}},
+ {3379, {wxStyledTextCtrl, doDropText, 3}},
+ {3380, {wxStyledTextCtrl, getUseAntiAliasing, 0}},
+ {3381, {wxStyledTextCtrl, addTextRaw, 1}},
+ {3382, {wxStyledTextCtrl, insertTextRaw, 2}},
+ {3383, {wxStyledTextCtrl, getCurLineRaw, 1}},
+ {3384, {wxStyledTextCtrl, getLineRaw, 1}},
+ {3385, {wxStyledTextCtrl, getSelectedTextRaw, 0}},
+ {3386, {wxStyledTextCtrl, getTextRangeRaw, 2}},
+ {3387, {wxStyledTextCtrl, setTextRaw, 1}},
+ {3388, {wxStyledTextCtrl, getTextRaw, 0}},
+ {3389, {wxStyledTextCtrl, appendTextRaw, 1}},
+ {3390, {wxArtProvider, getBitmap, 2}},
+ {3391, {wxArtProvider, getIcon, 2}},
+ {3392, {wxTreeEvent, getKeyCode, 0}},
+ {3393, {wxTreeEvent, getItem, 0}},
+ {3394, {wxTreeEvent, getKeyEvent, 0}},
+ {3395, {wxTreeEvent, getLabel, 0}},
+ {3396, {wxTreeEvent, getOldItem, 0}},
+ {3397, {wxTreeEvent, getPoint, 0}},
+ {3398, {wxTreeEvent, isEditCancelled, 0}},
+ {3399, {wxTreeEvent, setToolTip, 1}},
+ {3400, {wxNotebookEvent, getOldSelection, 0}},
+ {3401, {wxNotebookEvent, getSelection, 0}},
+ {3402, {wxNotebookEvent, setOldSelection, 1}},
+ {3403, {wxNotebookEvent, setSelection, 1}},
+ {3404, {wxFileDataObject, new, 0}},
+ {3405, {wxFileDataObject, addFile, 1}},
+ {3406, {wxFileDataObject, getFilenames, 0}},
+ {3407, {wxFileDataObject, 'Destroy', undefined}},
+ {3408, {wxTextDataObject, new, 1}},
+ {3409, {wxTextDataObject, getTextLength, 0}},
+ {3410, {wxTextDataObject, getText, 0}},
+ {3411, {wxTextDataObject, setText, 1}},
+ {3412, {wxTextDataObject, 'Destroy', undefined}},
+ {3413, {wxBitmapDataObject, new_1_1, 1}},
+ {3414, {wxBitmapDataObject, new_1_0, 1}},
+ {3415, {wxBitmapDataObject, getBitmap, 0}},
+ {3416, {wxBitmapDataObject, setBitmap, 1}},
+ {3417, {wxBitmapDataObject, 'Destroy', undefined}},
+ {3419, {wxClipboard, new, 0}},
+ {3420, {wxClipboard, destruct, 0}},
+ {3421, {wxClipboard, addData, 1}},
+ {3422, {wxClipboard, clear, 0}},
+ {3423, {wxClipboard, close, 0}},
+ {3424, {wxClipboard, flush, 0}},
+ {3425, {wxClipboard, getData, 1}},
+ {3426, {wxClipboard, isOpened, 0}},
+ {3427, {wxClipboard, open, 0}},
+ {3428, {wxClipboard, setData, 1}},
+ {3430, {wxClipboard, usePrimarySelection, 1}},
+ {3431, {wxClipboard, isSupported, 1}},
+ {3432, {wxClipboard, get, 0}},
+ {3433, {wxSpinEvent, getPosition, 0}},
+ {3434, {wxSpinEvent, setPosition, 1}},
+ {3435, {wxSplitterWindow, new_0, 0}},
+ {3436, {wxSplitterWindow, new_2, 2}},
+ {3437, {wxSplitterWindow, destruct, 0}},
+ {3438, {wxSplitterWindow, create, 2}},
+ {3439, {wxSplitterWindow, getMinimumPaneSize, 0}},
+ {3440, {wxSplitterWindow, getSashGravity, 0}},
+ {3441, {wxSplitterWindow, getSashPosition, 0}},
+ {3442, {wxSplitterWindow, getSplitMode, 0}},
+ {3443, {wxSplitterWindow, getWindow1, 0}},
+ {3444, {wxSplitterWindow, getWindow2, 0}},
+ {3445, {wxSplitterWindow, initialize, 1}},
+ {3446, {wxSplitterWindow, isSplit, 0}},
+ {3447, {wxSplitterWindow, replaceWindow, 2}},
+ {3448, {wxSplitterWindow, setSashGravity, 1}},
+ {3449, {wxSplitterWindow, setSashPosition, 2}},
+ {3450, {wxSplitterWindow, setSashSize, 1}},
+ {3451, {wxSplitterWindow, setMinimumPaneSize, 1}},
+ {3452, {wxSplitterWindow, setSplitMode, 1}},
+ {3453, {wxSplitterWindow, splitHorizontally, 3}},
+ {3454, {wxSplitterWindow, splitVertically, 3}},
+ {3455, {wxSplitterWindow, unsplit, 1}},
+ {3456, {wxSplitterWindow, updateSize, 0}},
+ {3457, {wxSplitterEvent, getSashPosition, 0}},
+ {3458, {wxSplitterEvent, getX, 0}},
+ {3459, {wxSplitterEvent, getY, 0}},
+ {3460, {wxSplitterEvent, getWindowBeingRemoved, 0}},
+ {3461, {wxSplitterEvent, setSashPosition, 1}},
+ {3462, {wxHtmlWindow, new_0, 0}},
+ {3463, {wxHtmlWindow, new_2, 2}},
+ {3464, {wxHtmlWindow, appendToPage, 1}},
+ {3465, {wxHtmlWindow, getOpenedAnchor, 0}},
+ {3466, {wxHtmlWindow, getOpenedPage, 0}},
+ {3467, {wxHtmlWindow, getOpenedPageTitle, 0}},
+ {3468, {wxHtmlWindow, getRelatedFrame, 0}},
+ {3469, {wxHtmlWindow, historyBack, 0}},
+ {3470, {wxHtmlWindow, historyCanBack, 0}},
+ {3471, {wxHtmlWindow, historyCanForward, 0}},
+ {3472, {wxHtmlWindow, historyClear, 0}},
+ {3473, {wxHtmlWindow, historyForward, 0}},
+ {3474, {wxHtmlWindow, loadFile, 1}},
+ {3475, {wxHtmlWindow, loadPage, 1}},
+ {3476, {wxHtmlWindow, selectAll, 0}},
+ {3477, {wxHtmlWindow, selectionToText, 0}},
+ {3478, {wxHtmlWindow, selectLine, 1}},
+ {3479, {wxHtmlWindow, selectWord, 1}},
+ {3480, {wxHtmlWindow, setBorders, 1}},
+ {3481, {wxHtmlWindow, setFonts, 3}},
+ {3482, {wxHtmlWindow, setPage, 1}},
+ {3483, {wxHtmlWindow, setRelatedFrame, 2}},
+ {3484, {wxHtmlWindow, setRelatedStatusBar, 1}},
+ {3485, {wxHtmlWindow, toText, 0}},
+ {3486, {wxHtmlWindow, 'Destroy', undefined}},
+ {3487, {wxHtmlLinkEvent, getLinkInfo, 0}},
+ {3488, {wxSystemSettings, getColour, 1}},
+ {3489, {wxSystemSettings, getFont, 1}},
+ {3490, {wxSystemSettings, getMetric, 2}},
+ {3491, {wxSystemSettings, getScreenType, 0}},
+ {3492, {wxSystemOptions, getOption, 1}},
+ {3493, {wxSystemOptions, getOptionInt, 1}},
+ {3494, {wxSystemOptions, hasOption, 1}},
+ {3495, {wxSystemOptions, isFalse, 1}},
+ {3496, {wxSystemOptions, setOption_2_1, 2}},
+ {3497, {wxSystemOptions, setOption_2_0, 2}},
+ {3498, {wxAuiNotebookEvent, setSelection, 1}},
+ {3499, {wxAuiNotebookEvent, getSelection, 0}},
+ {3500, {wxAuiNotebookEvent, setOldSelection, 1}},
+ {3501, {wxAuiNotebookEvent, getOldSelection, 0}},
+ {3502, {wxAuiNotebookEvent, setDragSource, 1}},
+ {3503, {wxAuiNotebookEvent, getDragSource, 0}},
+ {3504, {wxAuiManagerEvent, setManager, 1}},
+ {3505, {wxAuiManagerEvent, getManager, 0}},
+ {3506, {wxAuiManagerEvent, setPane, 1}},
+ {3507, {wxAuiManagerEvent, getPane, 0}},
+ {3508, {wxAuiManagerEvent, setButton, 1}},
+ {3509, {wxAuiManagerEvent, getButton, 0}},
+ {3510, {wxAuiManagerEvent, setDC, 1}},
+ {3511, {wxAuiManagerEvent, getDC, 0}},
+ {3512, {wxAuiManagerEvent, veto, 1}},
+ {3513, {wxAuiManagerEvent, getVeto, 0}},
+ {3514, {wxAuiManagerEvent, setCanVeto, 1}},
+ {3515, {wxAuiManagerEvent, canVeto, 0}},
+ {3516, {wxLogNull, new, 0}},
+ {3517, {wxLogNull, 'Destroy', undefined}},
{-1, {mod, func, -1}}
].
diff --git a/lib/wx/src/gen/wxe_funcs.hrl b/lib/wx/src/gen/wxe_funcs.hrl
index cf672644c6..55cbee5572 100644
--- a/lib/wx/src/gen/wxe_funcs.hrl
+++ b/lib/wx/src/gen/wxe_funcs.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1600,1681 +1600,1699 @@
-define(wxListItem_SetText, 1754).
-define(wxListItem_SetTextColour, 1755).
-define(wxListItem_SetWidth, 1756).
--define(wxImageList_new_0, 1757).
--define(wxImageList_new_3, 1758).
--define(wxImageList_Add_1, 1759).
--define(wxImageList_Add_2_0, 1760).
--define(wxImageList_Add_2_1, 1761).
--define(wxImageList_Create, 1762).
--define(wxImageList_Draw, 1764).
--define(wxImageList_GetBitmap, 1765).
--define(wxImageList_GetIcon, 1766).
--define(wxImageList_GetImageCount, 1767).
--define(wxImageList_GetSize, 1768).
--define(wxImageList_Remove, 1769).
--define(wxImageList_RemoveAll, 1770).
--define(wxImageList_Replace_2, 1771).
--define(wxImageList_Replace_3, 1772).
--define(wxImageList_destroy, 1773).
--define(wxTextAttr_new_0, 1774).
--define(wxTextAttr_new_2, 1775).
--define(wxTextAttr_GetAlignment, 1776).
--define(wxTextAttr_GetBackgroundColour, 1777).
--define(wxTextAttr_GetFont, 1778).
--define(wxTextAttr_GetLeftIndent, 1779).
--define(wxTextAttr_GetLeftSubIndent, 1780).
--define(wxTextAttr_GetRightIndent, 1781).
--define(wxTextAttr_GetTabs, 1782).
--define(wxTextAttr_GetTextColour, 1783).
--define(wxTextAttr_HasBackgroundColour, 1784).
--define(wxTextAttr_HasFont, 1785).
--define(wxTextAttr_HasTextColour, 1786).
--define(wxTextAttr_GetFlags, 1787).
--define(wxTextAttr_IsDefault, 1788).
--define(wxTextAttr_SetAlignment, 1789).
--define(wxTextAttr_SetBackgroundColour, 1790).
--define(wxTextAttr_SetFlags, 1791).
--define(wxTextAttr_SetFont, 1792).
--define(wxTextAttr_SetLeftIndent, 1793).
--define(wxTextAttr_SetRightIndent, 1794).
--define(wxTextAttr_SetTabs, 1795).
--define(wxTextAttr_SetTextColour, 1796).
--define(wxTextAttr_destroy, 1797).
--define(wxTextCtrl_new_3, 1799).
--define(wxTextCtrl_new_0, 1800).
--define(wxTextCtrl_destruct, 1802).
--define(wxTextCtrl_AppendText, 1803).
--define(wxTextCtrl_CanCopy, 1804).
--define(wxTextCtrl_CanCut, 1805).
--define(wxTextCtrl_CanPaste, 1806).
--define(wxTextCtrl_CanRedo, 1807).
--define(wxTextCtrl_CanUndo, 1808).
--define(wxTextCtrl_Clear, 1809).
--define(wxTextCtrl_Copy, 1810).
--define(wxTextCtrl_Create, 1811).
--define(wxTextCtrl_Cut, 1812).
--define(wxTextCtrl_DiscardEdits, 1813).
--define(wxTextCtrl_EmulateKeyPress, 1814).
--define(wxTextCtrl_GetDefaultStyle, 1815).
--define(wxTextCtrl_GetInsertionPoint, 1816).
--define(wxTextCtrl_GetLastPosition, 1817).
--define(wxTextCtrl_GetLineLength, 1818).
--define(wxTextCtrl_GetLineText, 1819).
--define(wxTextCtrl_GetNumberOfLines, 1820).
--define(wxTextCtrl_GetRange, 1821).
--define(wxTextCtrl_GetSelection, 1822).
--define(wxTextCtrl_GetStringSelection, 1823).
--define(wxTextCtrl_GetStyle, 1824).
--define(wxTextCtrl_GetValue, 1825).
--define(wxTextCtrl_IsEditable, 1826).
--define(wxTextCtrl_IsModified, 1827).
--define(wxTextCtrl_IsMultiLine, 1828).
--define(wxTextCtrl_IsSingleLine, 1829).
--define(wxTextCtrl_LoadFile, 1830).
--define(wxTextCtrl_MarkDirty, 1831).
--define(wxTextCtrl_Paste, 1832).
--define(wxTextCtrl_PositionToXY, 1833).
--define(wxTextCtrl_Redo, 1834).
--define(wxTextCtrl_Remove, 1835).
--define(wxTextCtrl_Replace, 1836).
--define(wxTextCtrl_SaveFile, 1837).
--define(wxTextCtrl_SetDefaultStyle, 1838).
--define(wxTextCtrl_SetEditable, 1839).
--define(wxTextCtrl_SetInsertionPoint, 1840).
--define(wxTextCtrl_SetInsertionPointEnd, 1841).
--define(wxTextCtrl_SetMaxLength, 1843).
--define(wxTextCtrl_SetSelection, 1844).
--define(wxTextCtrl_SetStyle, 1845).
--define(wxTextCtrl_SetValue, 1846).
--define(wxTextCtrl_ShowPosition, 1847).
--define(wxTextCtrl_Undo, 1848).
--define(wxTextCtrl_WriteText, 1849).
--define(wxTextCtrl_XYToPosition, 1850).
--define(wxNotebook_new_0, 1853).
--define(wxNotebook_new_3, 1854).
--define(wxNotebook_destruct, 1855).
--define(wxNotebook_AddPage, 1856).
--define(wxNotebook_AdvanceSelection, 1857).
--define(wxNotebook_AssignImageList, 1858).
--define(wxNotebook_Create, 1859).
--define(wxNotebook_DeleteAllPages, 1860).
--define(wxNotebook_DeletePage, 1861).
--define(wxNotebook_RemovePage, 1862).
--define(wxNotebook_GetCurrentPage, 1863).
--define(wxNotebook_GetImageList, 1864).
--define(wxNotebook_GetPage, 1866).
--define(wxNotebook_GetPageCount, 1867).
--define(wxNotebook_GetPageImage, 1868).
--define(wxNotebook_GetPageText, 1869).
--define(wxNotebook_GetRowCount, 1870).
--define(wxNotebook_GetSelection, 1871).
--define(wxNotebook_GetThemeBackgroundColour, 1872).
--define(wxNotebook_HitTest, 1874).
--define(wxNotebook_InsertPage, 1876).
--define(wxNotebook_SetImageList, 1877).
--define(wxNotebook_SetPadding, 1878).
--define(wxNotebook_SetPageSize, 1879).
--define(wxNotebook_SetPageImage, 1880).
--define(wxNotebook_SetPageText, 1881).
--define(wxNotebook_SetSelection, 1882).
--define(wxNotebook_ChangeSelection, 1883).
--define(wxChoicebook_new_0, 1884).
--define(wxChoicebook_new_3, 1885).
--define(wxChoicebook_AddPage, 1886).
--define(wxChoicebook_AdvanceSelection, 1887).
--define(wxChoicebook_AssignImageList, 1888).
--define(wxChoicebook_Create, 1889).
--define(wxChoicebook_DeleteAllPages, 1890).
--define(wxChoicebook_DeletePage, 1891).
--define(wxChoicebook_RemovePage, 1892).
--define(wxChoicebook_GetCurrentPage, 1893).
--define(wxChoicebook_GetImageList, 1894).
--define(wxChoicebook_GetPage, 1896).
--define(wxChoicebook_GetPageCount, 1897).
--define(wxChoicebook_GetPageImage, 1898).
--define(wxChoicebook_GetPageText, 1899).
--define(wxChoicebook_GetSelection, 1900).
--define(wxChoicebook_HitTest, 1901).
--define(wxChoicebook_InsertPage, 1902).
--define(wxChoicebook_SetImageList, 1903).
--define(wxChoicebook_SetPageSize, 1904).
--define(wxChoicebook_SetPageImage, 1905).
--define(wxChoicebook_SetPageText, 1906).
--define(wxChoicebook_SetSelection, 1907).
--define(wxChoicebook_ChangeSelection, 1908).
--define(wxChoicebook_destroy, 1909).
--define(wxToolbook_new_0, 1910).
--define(wxToolbook_new_3, 1911).
--define(wxToolbook_AddPage, 1912).
--define(wxToolbook_AdvanceSelection, 1913).
--define(wxToolbook_AssignImageList, 1914).
--define(wxToolbook_Create, 1915).
--define(wxToolbook_DeleteAllPages, 1916).
--define(wxToolbook_DeletePage, 1917).
--define(wxToolbook_RemovePage, 1918).
--define(wxToolbook_GetCurrentPage, 1919).
--define(wxToolbook_GetImageList, 1920).
--define(wxToolbook_GetPage, 1922).
--define(wxToolbook_GetPageCount, 1923).
--define(wxToolbook_GetPageImage, 1924).
--define(wxToolbook_GetPageText, 1925).
--define(wxToolbook_GetSelection, 1926).
--define(wxToolbook_HitTest, 1928).
--define(wxToolbook_InsertPage, 1929).
--define(wxToolbook_SetImageList, 1930).
--define(wxToolbook_SetPageSize, 1931).
--define(wxToolbook_SetPageImage, 1932).
--define(wxToolbook_SetPageText, 1933).
--define(wxToolbook_SetSelection, 1934).
--define(wxToolbook_ChangeSelection, 1935).
--define(wxToolbook_destroy, 1936).
--define(wxListbook_new_0, 1937).
--define(wxListbook_new_3, 1938).
--define(wxListbook_AddPage, 1939).
--define(wxListbook_AdvanceSelection, 1940).
--define(wxListbook_AssignImageList, 1941).
--define(wxListbook_Create, 1942).
--define(wxListbook_DeleteAllPages, 1943).
--define(wxListbook_DeletePage, 1944).
--define(wxListbook_RemovePage, 1945).
--define(wxListbook_GetCurrentPage, 1946).
--define(wxListbook_GetImageList, 1947).
--define(wxListbook_GetPage, 1949).
--define(wxListbook_GetPageCount, 1950).
--define(wxListbook_GetPageImage, 1951).
--define(wxListbook_GetPageText, 1952).
--define(wxListbook_GetSelection, 1953).
--define(wxListbook_HitTest, 1955).
--define(wxListbook_InsertPage, 1956).
--define(wxListbook_SetImageList, 1957).
--define(wxListbook_SetPageSize, 1958).
--define(wxListbook_SetPageImage, 1959).
--define(wxListbook_SetPageText, 1960).
--define(wxListbook_SetSelection, 1961).
--define(wxListbook_ChangeSelection, 1962).
--define(wxListbook_destroy, 1963).
--define(wxTreebook_new_0, 1964).
--define(wxTreebook_new_3, 1965).
--define(wxTreebook_AddPage, 1966).
--define(wxTreebook_AdvanceSelection, 1967).
--define(wxTreebook_AssignImageList, 1968).
--define(wxTreebook_Create, 1969).
--define(wxTreebook_DeleteAllPages, 1970).
--define(wxTreebook_DeletePage, 1971).
--define(wxTreebook_RemovePage, 1972).
--define(wxTreebook_GetCurrentPage, 1973).
--define(wxTreebook_GetImageList, 1974).
--define(wxTreebook_GetPage, 1976).
--define(wxTreebook_GetPageCount, 1977).
--define(wxTreebook_GetPageImage, 1978).
--define(wxTreebook_GetPageText, 1979).
--define(wxTreebook_GetSelection, 1980).
--define(wxTreebook_ExpandNode, 1981).
--define(wxTreebook_IsNodeExpanded, 1982).
--define(wxTreebook_HitTest, 1984).
--define(wxTreebook_InsertPage, 1985).
--define(wxTreebook_InsertSubPage, 1986).
--define(wxTreebook_SetImageList, 1987).
--define(wxTreebook_SetPageSize, 1988).
--define(wxTreebook_SetPageImage, 1989).
--define(wxTreebook_SetPageText, 1990).
--define(wxTreebook_SetSelection, 1991).
--define(wxTreebook_ChangeSelection, 1992).
--define(wxTreebook_destroy, 1993).
--define(wxTreeCtrl_new_2, 1996).
--define(wxTreeCtrl_new_0, 1997).
--define(wxTreeCtrl_destruct, 1999).
--define(wxTreeCtrl_AddRoot, 2000).
--define(wxTreeCtrl_AppendItem, 2001).
--define(wxTreeCtrl_AssignImageList, 2002).
--define(wxTreeCtrl_AssignStateImageList, 2003).
--define(wxTreeCtrl_Collapse, 2004).
--define(wxTreeCtrl_CollapseAndReset, 2005).
--define(wxTreeCtrl_Create, 2006).
--define(wxTreeCtrl_Delete, 2007).
--define(wxTreeCtrl_DeleteAllItems, 2008).
--define(wxTreeCtrl_DeleteChildren, 2009).
--define(wxTreeCtrl_EditLabel, 2010).
--define(wxTreeCtrl_EnsureVisible, 2011).
--define(wxTreeCtrl_Expand, 2012).
--define(wxTreeCtrl_GetBoundingRect, 2013).
--define(wxTreeCtrl_GetChildrenCount, 2015).
--define(wxTreeCtrl_GetCount, 2016).
--define(wxTreeCtrl_GetEditControl, 2017).
--define(wxTreeCtrl_GetFirstChild, 2018).
--define(wxTreeCtrl_GetNextChild, 2019).
--define(wxTreeCtrl_GetFirstVisibleItem, 2020).
--define(wxTreeCtrl_GetImageList, 2021).
--define(wxTreeCtrl_GetIndent, 2022).
--define(wxTreeCtrl_GetItemBackgroundColour, 2023).
--define(wxTreeCtrl_GetItemData, 2024).
--define(wxTreeCtrl_GetItemFont, 2025).
--define(wxTreeCtrl_GetItemImage_1, 2026).
--define(wxTreeCtrl_GetItemImage_2, 2027).
--define(wxTreeCtrl_GetItemText, 2028).
--define(wxTreeCtrl_GetItemTextColour, 2029).
--define(wxTreeCtrl_GetLastChild, 2030).
--define(wxTreeCtrl_GetNextSibling, 2031).
--define(wxTreeCtrl_GetNextVisible, 2032).
--define(wxTreeCtrl_GetItemParent, 2033).
--define(wxTreeCtrl_GetPrevSibling, 2034).
--define(wxTreeCtrl_GetPrevVisible, 2035).
--define(wxTreeCtrl_GetRootItem, 2036).
--define(wxTreeCtrl_GetSelection, 2037).
--define(wxTreeCtrl_GetSelections, 2038).
--define(wxTreeCtrl_GetStateImageList, 2039).
--define(wxTreeCtrl_HitTest, 2040).
--define(wxTreeCtrl_InsertItem, 2042).
--define(wxTreeCtrl_IsBold, 2043).
--define(wxTreeCtrl_IsExpanded, 2044).
--define(wxTreeCtrl_IsSelected, 2045).
--define(wxTreeCtrl_IsVisible, 2046).
--define(wxTreeCtrl_ItemHasChildren, 2047).
--define(wxTreeCtrl_PrependItem, 2048).
--define(wxTreeCtrl_ScrollTo, 2049).
--define(wxTreeCtrl_SelectItem_1, 2050).
--define(wxTreeCtrl_SelectItem_2, 2051).
--define(wxTreeCtrl_SetIndent, 2052).
--define(wxTreeCtrl_SetImageList, 2053).
--define(wxTreeCtrl_SetItemBackgroundColour, 2054).
--define(wxTreeCtrl_SetItemBold, 2055).
--define(wxTreeCtrl_SetItemData, 2056).
--define(wxTreeCtrl_SetItemDropHighlight, 2057).
--define(wxTreeCtrl_SetItemFont, 2058).
--define(wxTreeCtrl_SetItemHasChildren, 2059).
--define(wxTreeCtrl_SetItemImage_2, 2060).
--define(wxTreeCtrl_SetItemImage_3, 2061).
--define(wxTreeCtrl_SetItemText, 2062).
--define(wxTreeCtrl_SetItemTextColour, 2063).
--define(wxTreeCtrl_SetStateImageList, 2064).
--define(wxTreeCtrl_SetWindowStyle, 2065).
--define(wxTreeCtrl_SortChildren, 2066).
--define(wxTreeCtrl_Toggle, 2067).
--define(wxTreeCtrl_ToggleItemSelection, 2068).
--define(wxTreeCtrl_Unselect, 2069).
--define(wxTreeCtrl_UnselectAll, 2070).
--define(wxTreeCtrl_UnselectItem, 2071).
--define(wxScrollBar_new_0, 2072).
--define(wxScrollBar_new_3, 2073).
--define(wxScrollBar_destruct, 2074).
--define(wxScrollBar_Create, 2075).
--define(wxScrollBar_GetRange, 2076).
--define(wxScrollBar_GetPageSize, 2077).
--define(wxScrollBar_GetThumbPosition, 2078).
--define(wxScrollBar_GetThumbSize, 2079).
--define(wxScrollBar_SetThumbPosition, 2080).
--define(wxScrollBar_SetScrollbar, 2081).
--define(wxSpinButton_new_2, 2083).
--define(wxSpinButton_new_0, 2084).
--define(wxSpinButton_Create, 2085).
--define(wxSpinButton_GetMax, 2086).
--define(wxSpinButton_GetMin, 2087).
--define(wxSpinButton_GetValue, 2088).
--define(wxSpinButton_SetRange, 2089).
--define(wxSpinButton_SetValue, 2090).
--define(wxSpinButton_destroy, 2091).
--define(wxSpinCtrl_new_0, 2092).
--define(wxSpinCtrl_new_2, 2093).
--define(wxSpinCtrl_Create, 2095).
--define(wxSpinCtrl_SetValue_1_1, 2098).
--define(wxSpinCtrl_SetValue_1_0, 2099).
--define(wxSpinCtrl_GetValue, 2101).
--define(wxSpinCtrl_SetRange, 2103).
--define(wxSpinCtrl_SetSelection, 2104).
--define(wxSpinCtrl_GetMin, 2106).
--define(wxSpinCtrl_GetMax, 2108).
--define(wxSpinCtrl_destroy, 2109).
--define(wxStaticText_new_0, 2110).
--define(wxStaticText_new_4, 2111).
--define(wxStaticText_Create, 2112).
--define(wxStaticText_GetLabel, 2113).
--define(wxStaticText_SetLabel, 2114).
--define(wxStaticText_Wrap, 2115).
--define(wxStaticText_destroy, 2116).
--define(wxStaticBitmap_new_0, 2117).
--define(wxStaticBitmap_new_4, 2118).
--define(wxStaticBitmap_Create, 2119).
--define(wxStaticBitmap_GetBitmap, 2120).
--define(wxStaticBitmap_SetBitmap, 2121).
--define(wxStaticBitmap_destroy, 2122).
--define(wxRadioBox_new, 2123).
--define(wxRadioBox_destruct, 2125).
--define(wxRadioBox_Create, 2126).
--define(wxRadioBox_Enable_2, 2127).
--define(wxRadioBox_Enable_1, 2128).
--define(wxRadioBox_GetSelection, 2129).
--define(wxRadioBox_GetString, 2130).
--define(wxRadioBox_SetSelection, 2131).
--define(wxRadioBox_Show_2, 2132).
--define(wxRadioBox_Show_1, 2133).
--define(wxRadioBox_GetColumnCount, 2134).
--define(wxRadioBox_GetItemHelpText, 2135).
--define(wxRadioBox_GetItemToolTip, 2136).
--define(wxRadioBox_GetItemFromPoint, 2138).
--define(wxRadioBox_GetRowCount, 2139).
--define(wxRadioBox_IsItemEnabled, 2140).
--define(wxRadioBox_IsItemShown, 2141).
--define(wxRadioBox_SetItemHelpText, 2142).
--define(wxRadioBox_SetItemToolTip, 2143).
--define(wxRadioButton_new_0, 2144).
--define(wxRadioButton_new_4, 2145).
--define(wxRadioButton_Create, 2146).
--define(wxRadioButton_GetValue, 2147).
--define(wxRadioButton_SetValue, 2148).
--define(wxRadioButton_destroy, 2149).
--define(wxSlider_new_6, 2151).
--define(wxSlider_new_0, 2152).
--define(wxSlider_Create, 2153).
--define(wxSlider_GetLineSize, 2154).
--define(wxSlider_GetMax, 2155).
--define(wxSlider_GetMin, 2156).
--define(wxSlider_GetPageSize, 2157).
--define(wxSlider_GetThumbLength, 2158).
--define(wxSlider_GetValue, 2159).
--define(wxSlider_SetLineSize, 2160).
--define(wxSlider_SetPageSize, 2161).
--define(wxSlider_SetRange, 2162).
--define(wxSlider_SetThumbLength, 2163).
--define(wxSlider_SetValue, 2164).
--define(wxSlider_destroy, 2165).
--define(wxDialog_new_4, 2167).
--define(wxDialog_new_0, 2168).
--define(wxDialog_destruct, 2170).
--define(wxDialog_Create, 2171).
--define(wxDialog_CreateButtonSizer, 2172).
--define(wxDialog_CreateStdDialogButtonSizer, 2173).
--define(wxDialog_EndModal, 2174).
--define(wxDialog_GetAffirmativeId, 2175).
--define(wxDialog_GetReturnCode, 2176).
--define(wxDialog_IsModal, 2177).
--define(wxDialog_SetAffirmativeId, 2178).
--define(wxDialog_SetReturnCode, 2179).
--define(wxDialog_Show, 2180).
--define(wxDialog_ShowModal, 2181).
--define(wxColourDialog_new_0, 2182).
--define(wxColourDialog_new_2, 2183).
--define(wxColourDialog_destruct, 2184).
--define(wxColourDialog_Create, 2185).
--define(wxColourDialog_GetColourData, 2186).
--define(wxColourData_new_0, 2187).
--define(wxColourData_new_1, 2188).
--define(wxColourData_destruct, 2189).
--define(wxColourData_GetChooseFull, 2190).
--define(wxColourData_GetColour, 2191).
--define(wxColourData_GetCustomColour, 2193).
--define(wxColourData_SetChooseFull, 2194).
--define(wxColourData_SetColour, 2195).
--define(wxColourData_SetCustomColour, 2196).
--define(wxPalette_new_0, 2197).
--define(wxPalette_new_4, 2198).
--define(wxPalette_destruct, 2200).
--define(wxPalette_Create, 2201).
--define(wxPalette_GetColoursCount, 2202).
--define(wxPalette_GetPixel, 2203).
--define(wxPalette_GetRGB, 2204).
--define(wxPalette_IsOk, 2205).
--define(wxDirDialog_new, 2209).
--define(wxDirDialog_destruct, 2210).
--define(wxDirDialog_GetPath, 2211).
--define(wxDirDialog_GetMessage, 2212).
--define(wxDirDialog_SetMessage, 2213).
--define(wxDirDialog_SetPath, 2214).
--define(wxFileDialog_new, 2218).
--define(wxFileDialog_destruct, 2219).
--define(wxFileDialog_GetDirectory, 2220).
--define(wxFileDialog_GetFilename, 2221).
--define(wxFileDialog_GetFilenames, 2222).
--define(wxFileDialog_GetFilterIndex, 2223).
--define(wxFileDialog_GetMessage, 2224).
--define(wxFileDialog_GetPath, 2225).
--define(wxFileDialog_GetPaths, 2226).
--define(wxFileDialog_GetWildcard, 2227).
--define(wxFileDialog_SetDirectory, 2228).
--define(wxFileDialog_SetFilename, 2229).
--define(wxFileDialog_SetFilterIndex, 2230).
--define(wxFileDialog_SetMessage, 2231).
--define(wxFileDialog_SetPath, 2232).
--define(wxFileDialog_SetWildcard, 2233).
--define(wxPickerBase_SetInternalMargin, 2234).
--define(wxPickerBase_GetInternalMargin, 2235).
--define(wxPickerBase_SetTextCtrlProportion, 2236).
--define(wxPickerBase_SetPickerCtrlProportion, 2237).
--define(wxPickerBase_GetTextCtrlProportion, 2238).
--define(wxPickerBase_GetPickerCtrlProportion, 2239).
--define(wxPickerBase_HasTextCtrl, 2240).
--define(wxPickerBase_GetTextCtrl, 2241).
--define(wxPickerBase_IsTextCtrlGrowable, 2242).
--define(wxPickerBase_SetPickerCtrlGrowable, 2243).
--define(wxPickerBase_SetTextCtrlGrowable, 2244).
--define(wxPickerBase_IsPickerCtrlGrowable, 2245).
--define(wxFilePickerCtrl_new_0, 2246).
--define(wxFilePickerCtrl_new_3, 2247).
--define(wxFilePickerCtrl_Create, 2248).
--define(wxFilePickerCtrl_GetPath, 2249).
--define(wxFilePickerCtrl_SetPath, 2250).
--define(wxFilePickerCtrl_destroy, 2251).
--define(wxDirPickerCtrl_new_0, 2252).
--define(wxDirPickerCtrl_new_3, 2253).
--define(wxDirPickerCtrl_Create, 2254).
--define(wxDirPickerCtrl_GetPath, 2255).
--define(wxDirPickerCtrl_SetPath, 2256).
--define(wxDirPickerCtrl_destroy, 2257).
--define(wxColourPickerCtrl_new_0, 2258).
--define(wxColourPickerCtrl_new_3, 2259).
--define(wxColourPickerCtrl_Create, 2260).
--define(wxColourPickerCtrl_GetColour, 2261).
--define(wxColourPickerCtrl_SetColour_1_1, 2262).
--define(wxColourPickerCtrl_SetColour_1_0, 2263).
--define(wxColourPickerCtrl_destroy, 2264).
--define(wxDatePickerCtrl_new_0, 2265).
--define(wxDatePickerCtrl_new_3, 2266).
--define(wxDatePickerCtrl_GetRange, 2267).
--define(wxDatePickerCtrl_GetValue, 2268).
--define(wxDatePickerCtrl_SetRange, 2269).
--define(wxDatePickerCtrl_SetValue, 2270).
--define(wxDatePickerCtrl_destroy, 2271).
--define(wxFontPickerCtrl_new_0, 2272).
--define(wxFontPickerCtrl_new_3, 2273).
--define(wxFontPickerCtrl_Create, 2274).
--define(wxFontPickerCtrl_GetSelectedFont, 2275).
--define(wxFontPickerCtrl_SetSelectedFont, 2276).
--define(wxFontPickerCtrl_GetMaxPointSize, 2277).
--define(wxFontPickerCtrl_SetMaxPointSize, 2278).
--define(wxFontPickerCtrl_destroy, 2279).
--define(wxFindReplaceDialog_new_0, 2282).
--define(wxFindReplaceDialog_new_4, 2283).
--define(wxFindReplaceDialog_destruct, 2284).
--define(wxFindReplaceDialog_Create, 2285).
--define(wxFindReplaceDialog_GetData, 2286).
--define(wxFindReplaceData_new_0, 2287).
--define(wxFindReplaceData_new_1, 2288).
--define(wxFindReplaceData_GetFindString, 2289).
--define(wxFindReplaceData_GetReplaceString, 2290).
--define(wxFindReplaceData_GetFlags, 2291).
--define(wxFindReplaceData_SetFlags, 2292).
--define(wxFindReplaceData_SetFindString, 2293).
--define(wxFindReplaceData_SetReplaceString, 2294).
--define(wxFindReplaceData_destroy, 2295).
--define(wxMultiChoiceDialog_new_0, 2296).
--define(wxMultiChoiceDialog_new_5, 2298).
--define(wxMultiChoiceDialog_GetSelections, 2299).
--define(wxMultiChoiceDialog_SetSelections, 2300).
--define(wxMultiChoiceDialog_destroy, 2301).
--define(wxSingleChoiceDialog_new_0, 2302).
--define(wxSingleChoiceDialog_new_5, 2304).
--define(wxSingleChoiceDialog_GetSelection, 2305).
--define(wxSingleChoiceDialog_GetStringSelection, 2306).
--define(wxSingleChoiceDialog_SetSelection, 2307).
--define(wxSingleChoiceDialog_destroy, 2308).
--define(wxTextEntryDialog_new, 2309).
--define(wxTextEntryDialog_GetValue, 2310).
--define(wxTextEntryDialog_SetValue, 2311).
--define(wxTextEntryDialog_destroy, 2312).
--define(wxPasswordEntryDialog_new, 2313).
--define(wxPasswordEntryDialog_destroy, 2314).
--define(wxFontData_new_0, 2315).
--define(wxFontData_new_1, 2316).
--define(wxFontData_destruct, 2317).
--define(wxFontData_EnableEffects, 2318).
--define(wxFontData_GetAllowSymbols, 2319).
--define(wxFontData_GetColour, 2320).
--define(wxFontData_GetChosenFont, 2321).
--define(wxFontData_GetEnableEffects, 2322).
--define(wxFontData_GetInitialFont, 2323).
--define(wxFontData_GetShowHelp, 2324).
--define(wxFontData_SetAllowSymbols, 2325).
--define(wxFontData_SetChosenFont, 2326).
--define(wxFontData_SetColour, 2327).
--define(wxFontData_SetInitialFont, 2328).
--define(wxFontData_SetRange, 2329).
--define(wxFontData_SetShowHelp, 2330).
--define(wxFontDialog_new_0, 2334).
--define(wxFontDialog_new_2, 2336).
--define(wxFontDialog_Create, 2338).
--define(wxFontDialog_GetFontData, 2339).
--define(wxFontDialog_destroy, 2341).
--define(wxProgressDialog_new, 2342).
--define(wxProgressDialog_destruct, 2343).
--define(wxProgressDialog_Resume, 2344).
--define(wxProgressDialog_Update_2, 2345).
--define(wxProgressDialog_Update_0, 2346).
--define(wxMessageDialog_new, 2347).
--define(wxMessageDialog_destruct, 2348).
--define(wxPageSetupDialog_new, 2349).
--define(wxPageSetupDialog_destruct, 2350).
--define(wxPageSetupDialog_GetPageSetupData, 2351).
--define(wxPageSetupDialog_ShowModal, 2352).
--define(wxPageSetupDialogData_new_0, 2353).
--define(wxPageSetupDialogData_new_1_0, 2354).
--define(wxPageSetupDialogData_new_1_1, 2355).
--define(wxPageSetupDialogData_destruct, 2356).
--define(wxPageSetupDialogData_EnableHelp, 2357).
--define(wxPageSetupDialogData_EnableMargins, 2358).
--define(wxPageSetupDialogData_EnableOrientation, 2359).
--define(wxPageSetupDialogData_EnablePaper, 2360).
--define(wxPageSetupDialogData_EnablePrinter, 2361).
--define(wxPageSetupDialogData_GetDefaultMinMargins, 2362).
--define(wxPageSetupDialogData_GetEnableMargins, 2363).
--define(wxPageSetupDialogData_GetEnableOrientation, 2364).
--define(wxPageSetupDialogData_GetEnablePaper, 2365).
--define(wxPageSetupDialogData_GetEnablePrinter, 2366).
--define(wxPageSetupDialogData_GetEnableHelp, 2367).
--define(wxPageSetupDialogData_GetDefaultInfo, 2368).
--define(wxPageSetupDialogData_GetMarginTopLeft, 2369).
--define(wxPageSetupDialogData_GetMarginBottomRight, 2370).
--define(wxPageSetupDialogData_GetMinMarginTopLeft, 2371).
--define(wxPageSetupDialogData_GetMinMarginBottomRight, 2372).
--define(wxPageSetupDialogData_GetPaperId, 2373).
--define(wxPageSetupDialogData_GetPaperSize, 2374).
--define(wxPageSetupDialogData_GetPrintData, 2376).
--define(wxPageSetupDialogData_IsOk, 2377).
--define(wxPageSetupDialogData_SetDefaultInfo, 2378).
--define(wxPageSetupDialogData_SetDefaultMinMargins, 2379).
--define(wxPageSetupDialogData_SetMarginTopLeft, 2380).
--define(wxPageSetupDialogData_SetMarginBottomRight, 2381).
--define(wxPageSetupDialogData_SetMinMarginTopLeft, 2382).
--define(wxPageSetupDialogData_SetMinMarginBottomRight, 2383).
--define(wxPageSetupDialogData_SetPaperId, 2384).
--define(wxPageSetupDialogData_SetPaperSize_1_1, 2385).
--define(wxPageSetupDialogData_SetPaperSize_1_0, 2386).
--define(wxPageSetupDialogData_SetPrintData, 2387).
--define(wxPrintDialog_new_2_0, 2388).
--define(wxPrintDialog_new_2_1, 2389).
--define(wxPrintDialog_destruct, 2390).
--define(wxPrintDialog_GetPrintDialogData, 2391).
--define(wxPrintDialog_GetPrintDC, 2392).
--define(wxPrintDialogData_new_0, 2393).
--define(wxPrintDialogData_new_1_1, 2394).
--define(wxPrintDialogData_new_1_0, 2395).
--define(wxPrintDialogData_destruct, 2396).
--define(wxPrintDialogData_EnableHelp, 2397).
--define(wxPrintDialogData_EnablePageNumbers, 2398).
--define(wxPrintDialogData_EnablePrintToFile, 2399).
--define(wxPrintDialogData_EnableSelection, 2400).
--define(wxPrintDialogData_GetAllPages, 2401).
--define(wxPrintDialogData_GetCollate, 2402).
--define(wxPrintDialogData_GetFromPage, 2403).
--define(wxPrintDialogData_GetMaxPage, 2404).
--define(wxPrintDialogData_GetMinPage, 2405).
--define(wxPrintDialogData_GetNoCopies, 2406).
--define(wxPrintDialogData_GetPrintData, 2407).
--define(wxPrintDialogData_GetPrintToFile, 2408).
--define(wxPrintDialogData_GetSelection, 2409).
--define(wxPrintDialogData_GetToPage, 2410).
--define(wxPrintDialogData_IsOk, 2411).
--define(wxPrintDialogData_SetCollate, 2412).
--define(wxPrintDialogData_SetFromPage, 2413).
--define(wxPrintDialogData_SetMaxPage, 2414).
--define(wxPrintDialogData_SetMinPage, 2415).
--define(wxPrintDialogData_SetNoCopies, 2416).
--define(wxPrintDialogData_SetPrintData, 2417).
--define(wxPrintDialogData_SetPrintToFile, 2418).
--define(wxPrintDialogData_SetSelection, 2419).
--define(wxPrintDialogData_SetToPage, 2420).
--define(wxPrintData_new_0, 2421).
--define(wxPrintData_new_1, 2422).
--define(wxPrintData_destruct, 2423).
--define(wxPrintData_GetCollate, 2424).
--define(wxPrintData_GetBin, 2425).
--define(wxPrintData_GetColour, 2426).
--define(wxPrintData_GetDuplex, 2427).
--define(wxPrintData_GetNoCopies, 2428).
--define(wxPrintData_GetOrientation, 2429).
--define(wxPrintData_GetPaperId, 2430).
--define(wxPrintData_GetPrinterName, 2431).
--define(wxPrintData_GetQuality, 2432).
--define(wxPrintData_IsOk, 2433).
--define(wxPrintData_SetBin, 2434).
--define(wxPrintData_SetCollate, 2435).
--define(wxPrintData_SetColour, 2436).
--define(wxPrintData_SetDuplex, 2437).
--define(wxPrintData_SetNoCopies, 2438).
--define(wxPrintData_SetOrientation, 2439).
--define(wxPrintData_SetPaperId, 2440).
--define(wxPrintData_SetPrinterName, 2441).
--define(wxPrintData_SetQuality, 2442).
--define(wxPrintPreview_new_2, 2445).
--define(wxPrintPreview_new_3, 2446).
--define(wxPrintPreview_destruct, 2448).
--define(wxPrintPreview_GetCanvas, 2449).
--define(wxPrintPreview_GetCurrentPage, 2450).
--define(wxPrintPreview_GetFrame, 2451).
--define(wxPrintPreview_GetMaxPage, 2452).
--define(wxPrintPreview_GetMinPage, 2453).
--define(wxPrintPreview_GetPrintout, 2454).
--define(wxPrintPreview_GetPrintoutForPrinting, 2455).
--define(wxPrintPreview_IsOk, 2456).
--define(wxPrintPreview_PaintPage, 2457).
--define(wxPrintPreview_Print, 2458).
--define(wxPrintPreview_RenderPage, 2459).
--define(wxPrintPreview_SetCanvas, 2460).
--define(wxPrintPreview_SetCurrentPage, 2461).
--define(wxPrintPreview_SetFrame, 2462).
--define(wxPrintPreview_SetPrintout, 2463).
--define(wxPrintPreview_SetZoom, 2464).
--define(wxPreviewFrame_new, 2465).
--define(wxPreviewFrame_destruct, 2466).
--define(wxPreviewFrame_CreateControlBar, 2467).
--define(wxPreviewFrame_CreateCanvas, 2468).
--define(wxPreviewFrame_Initialize, 2469).
--define(wxPreviewFrame_OnCloseWindow, 2470).
--define(wxPreviewControlBar_new, 2471).
--define(wxPreviewControlBar_destruct, 2472).
--define(wxPreviewControlBar_CreateButtons, 2473).
--define(wxPreviewControlBar_GetPrintPreview, 2474).
--define(wxPreviewControlBar_GetZoomControl, 2475).
--define(wxPreviewControlBar_SetZoomControl, 2476).
--define(wxPrinter_new, 2478).
--define(wxPrinter_CreateAbortWindow, 2479).
--define(wxPrinter_GetAbort, 2480).
--define(wxPrinter_GetLastError, 2481).
--define(wxPrinter_GetPrintDialogData, 2482).
--define(wxPrinter_Print, 2483).
--define(wxPrinter_PrintDialog, 2484).
--define(wxPrinter_ReportError, 2485).
--define(wxPrinter_Setup, 2486).
--define(wxPrinter_destroy, 2487).
--define(wxXmlResource_new_1, 2488).
--define(wxXmlResource_new_2, 2489).
--define(wxXmlResource_destruct, 2490).
--define(wxXmlResource_AttachUnknownControl, 2491).
--define(wxXmlResource_ClearHandlers, 2492).
--define(wxXmlResource_CompareVersion, 2493).
--define(wxXmlResource_Get, 2494).
--define(wxXmlResource_GetFlags, 2495).
--define(wxXmlResource_GetVersion, 2496).
--define(wxXmlResource_GetXRCID, 2497).
--define(wxXmlResource_InitAllHandlers, 2498).
--define(wxXmlResource_Load, 2499).
--define(wxXmlResource_LoadBitmap, 2500).
--define(wxXmlResource_LoadDialog_2, 2501).
--define(wxXmlResource_LoadDialog_3, 2502).
--define(wxXmlResource_LoadFrame_2, 2503).
--define(wxXmlResource_LoadFrame_3, 2504).
--define(wxXmlResource_LoadIcon, 2505).
--define(wxXmlResource_LoadMenu, 2506).
--define(wxXmlResource_LoadMenuBar_2, 2507).
--define(wxXmlResource_LoadMenuBar_1, 2508).
--define(wxXmlResource_LoadPanel_2, 2509).
--define(wxXmlResource_LoadPanel_3, 2510).
--define(wxXmlResource_LoadToolBar, 2511).
--define(wxXmlResource_Set, 2512).
--define(wxXmlResource_SetFlags, 2513).
--define(wxXmlResource_Unload, 2514).
--define(wxXmlResource_xrcctrl, 2515).
--define(wxHtmlEasyPrinting_new, 2516).
--define(wxHtmlEasyPrinting_destruct, 2517).
--define(wxHtmlEasyPrinting_GetPrintData, 2518).
--define(wxHtmlEasyPrinting_GetPageSetupData, 2519).
--define(wxHtmlEasyPrinting_PreviewFile, 2520).
--define(wxHtmlEasyPrinting_PreviewText, 2521).
--define(wxHtmlEasyPrinting_PrintFile, 2522).
--define(wxHtmlEasyPrinting_PrintText, 2523).
--define(wxHtmlEasyPrinting_PageSetup, 2524).
--define(wxHtmlEasyPrinting_SetFonts, 2525).
--define(wxHtmlEasyPrinting_SetHeader, 2526).
--define(wxHtmlEasyPrinting_SetFooter, 2527).
--define(wxGLCanvas_new_2, 2529).
--define(wxGLCanvas_new_3_1, 2530).
--define(wxGLCanvas_new_3_0, 2531).
--define(wxGLCanvas_GetContext, 2532).
--define(wxGLCanvas_SetCurrent, 2534).
--define(wxGLCanvas_SwapBuffers, 2535).
--define(wxGLCanvas_destroy, 2536).
--define(wxAuiManager_new, 2537).
--define(wxAuiManager_destruct, 2538).
--define(wxAuiManager_AddPane_2_1, 2539).
--define(wxAuiManager_AddPane_3, 2540).
--define(wxAuiManager_AddPane_2_0, 2541).
--define(wxAuiManager_DetachPane, 2542).
--define(wxAuiManager_GetAllPanes, 2543).
--define(wxAuiManager_GetArtProvider, 2544).
--define(wxAuiManager_GetDockSizeConstraint, 2545).
--define(wxAuiManager_GetFlags, 2546).
--define(wxAuiManager_GetManagedWindow, 2547).
--define(wxAuiManager_GetManager, 2548).
--define(wxAuiManager_GetPane_1_1, 2549).
--define(wxAuiManager_GetPane_1_0, 2550).
--define(wxAuiManager_HideHint, 2551).
--define(wxAuiManager_InsertPane, 2552).
--define(wxAuiManager_LoadPaneInfo, 2553).
--define(wxAuiManager_LoadPerspective, 2554).
--define(wxAuiManager_SavePaneInfo, 2555).
--define(wxAuiManager_SavePerspective, 2556).
--define(wxAuiManager_SetArtProvider, 2557).
--define(wxAuiManager_SetDockSizeConstraint, 2558).
--define(wxAuiManager_SetFlags, 2559).
--define(wxAuiManager_SetManagedWindow, 2560).
--define(wxAuiManager_ShowHint, 2561).
--define(wxAuiManager_UnInit, 2562).
--define(wxAuiManager_Update, 2563).
--define(wxAuiPaneInfo_new_0, 2564).
--define(wxAuiPaneInfo_new_1, 2565).
--define(wxAuiPaneInfo_destruct, 2566).
--define(wxAuiPaneInfo_BestSize_1, 2567).
--define(wxAuiPaneInfo_BestSize_2, 2568).
--define(wxAuiPaneInfo_Bottom, 2569).
--define(wxAuiPaneInfo_BottomDockable, 2570).
--define(wxAuiPaneInfo_Caption, 2571).
--define(wxAuiPaneInfo_CaptionVisible, 2572).
--define(wxAuiPaneInfo_Centre, 2573).
--define(wxAuiPaneInfo_CentrePane, 2574).
--define(wxAuiPaneInfo_CloseButton, 2575).
--define(wxAuiPaneInfo_DefaultPane, 2576).
--define(wxAuiPaneInfo_DestroyOnClose, 2577).
--define(wxAuiPaneInfo_Direction, 2578).
--define(wxAuiPaneInfo_Dock, 2579).
--define(wxAuiPaneInfo_Dockable, 2580).
--define(wxAuiPaneInfo_Fixed, 2581).
--define(wxAuiPaneInfo_Float, 2582).
--define(wxAuiPaneInfo_Floatable, 2583).
--define(wxAuiPaneInfo_FloatingPosition_1, 2584).
--define(wxAuiPaneInfo_FloatingPosition_2, 2585).
--define(wxAuiPaneInfo_FloatingSize_1, 2586).
--define(wxAuiPaneInfo_FloatingSize_2, 2587).
--define(wxAuiPaneInfo_Gripper, 2588).
--define(wxAuiPaneInfo_GripperTop, 2589).
--define(wxAuiPaneInfo_HasBorder, 2590).
--define(wxAuiPaneInfo_HasCaption, 2591).
--define(wxAuiPaneInfo_HasCloseButton, 2592).
--define(wxAuiPaneInfo_HasFlag, 2593).
--define(wxAuiPaneInfo_HasGripper, 2594).
--define(wxAuiPaneInfo_HasGripperTop, 2595).
--define(wxAuiPaneInfo_HasMaximizeButton, 2596).
--define(wxAuiPaneInfo_HasMinimizeButton, 2597).
--define(wxAuiPaneInfo_HasPinButton, 2598).
--define(wxAuiPaneInfo_Hide, 2599).
--define(wxAuiPaneInfo_IsBottomDockable, 2600).
--define(wxAuiPaneInfo_IsDocked, 2601).
--define(wxAuiPaneInfo_IsFixed, 2602).
--define(wxAuiPaneInfo_IsFloatable, 2603).
--define(wxAuiPaneInfo_IsFloating, 2604).
--define(wxAuiPaneInfo_IsLeftDockable, 2605).
--define(wxAuiPaneInfo_IsMovable, 2606).
--define(wxAuiPaneInfo_IsOk, 2607).
--define(wxAuiPaneInfo_IsResizable, 2608).
--define(wxAuiPaneInfo_IsRightDockable, 2609).
--define(wxAuiPaneInfo_IsShown, 2610).
--define(wxAuiPaneInfo_IsToolbar, 2611).
--define(wxAuiPaneInfo_IsTopDockable, 2612).
--define(wxAuiPaneInfo_Layer, 2613).
--define(wxAuiPaneInfo_Left, 2614).
--define(wxAuiPaneInfo_LeftDockable, 2615).
--define(wxAuiPaneInfo_MaxSize_1, 2616).
--define(wxAuiPaneInfo_MaxSize_2, 2617).
--define(wxAuiPaneInfo_MaximizeButton, 2618).
--define(wxAuiPaneInfo_MinSize_1, 2619).
--define(wxAuiPaneInfo_MinSize_2, 2620).
--define(wxAuiPaneInfo_MinimizeButton, 2621).
--define(wxAuiPaneInfo_Movable, 2622).
--define(wxAuiPaneInfo_Name, 2623).
--define(wxAuiPaneInfo_PaneBorder, 2624).
--define(wxAuiPaneInfo_PinButton, 2625).
--define(wxAuiPaneInfo_Position, 2626).
--define(wxAuiPaneInfo_Resizable, 2627).
--define(wxAuiPaneInfo_Right, 2628).
--define(wxAuiPaneInfo_RightDockable, 2629).
--define(wxAuiPaneInfo_Row, 2630).
--define(wxAuiPaneInfo_SafeSet, 2631).
--define(wxAuiPaneInfo_SetFlag, 2632).
--define(wxAuiPaneInfo_Show, 2633).
--define(wxAuiPaneInfo_ToolbarPane, 2634).
--define(wxAuiPaneInfo_Top, 2635).
--define(wxAuiPaneInfo_TopDockable, 2636).
--define(wxAuiPaneInfo_Window, 2637).
--define(wxAuiNotebook_new_0, 2638).
--define(wxAuiNotebook_new_2, 2639).
--define(wxAuiNotebook_AddPage, 2640).
--define(wxAuiNotebook_Create, 2641).
--define(wxAuiNotebook_DeletePage, 2642).
--define(wxAuiNotebook_GetArtProvider, 2643).
--define(wxAuiNotebook_GetPage, 2644).
--define(wxAuiNotebook_GetPageBitmap, 2645).
--define(wxAuiNotebook_GetPageCount, 2646).
--define(wxAuiNotebook_GetPageIndex, 2647).
--define(wxAuiNotebook_GetPageText, 2648).
--define(wxAuiNotebook_GetSelection, 2649).
--define(wxAuiNotebook_InsertPage, 2650).
--define(wxAuiNotebook_RemovePage, 2651).
--define(wxAuiNotebook_SetArtProvider, 2652).
--define(wxAuiNotebook_SetFont, 2653).
--define(wxAuiNotebook_SetPageBitmap, 2654).
--define(wxAuiNotebook_SetPageText, 2655).
--define(wxAuiNotebook_SetSelection, 2656).
--define(wxAuiNotebook_SetTabCtrlHeight, 2657).
--define(wxAuiNotebook_SetUniformBitmapSize, 2658).
--define(wxAuiNotebook_destroy, 2659).
--define(wxMDIParentFrame_new_0, 2660).
--define(wxMDIParentFrame_new_4, 2661).
--define(wxMDIParentFrame_destruct, 2662).
--define(wxMDIParentFrame_ActivateNext, 2663).
--define(wxMDIParentFrame_ActivatePrevious, 2664).
--define(wxMDIParentFrame_ArrangeIcons, 2665).
--define(wxMDIParentFrame_Cascade, 2666).
--define(wxMDIParentFrame_Create, 2667).
--define(wxMDIParentFrame_GetActiveChild, 2668).
--define(wxMDIParentFrame_GetClientWindow, 2669).
--define(wxMDIParentFrame_Tile, 2670).
--define(wxMDIChildFrame_new_0, 2671).
--define(wxMDIChildFrame_new_4, 2672).
--define(wxMDIChildFrame_destruct, 2673).
--define(wxMDIChildFrame_Activate, 2674).
--define(wxMDIChildFrame_Create, 2675).
--define(wxMDIChildFrame_Maximize, 2676).
--define(wxMDIChildFrame_Restore, 2677).
--define(wxMDIClientWindow_new_0, 2678).
--define(wxMDIClientWindow_new_2, 2679).
--define(wxMDIClientWindow_destruct, 2680).
--define(wxMDIClientWindow_CreateClient, 2681).
--define(wxLayoutAlgorithm_new, 2682).
--define(wxLayoutAlgorithm_LayoutFrame, 2683).
--define(wxLayoutAlgorithm_LayoutMDIFrame, 2684).
--define(wxLayoutAlgorithm_LayoutWindow, 2685).
--define(wxLayoutAlgorithm_destroy, 2686).
--define(wxEvent_GetId, 2687).
--define(wxEvent_GetSkipped, 2688).
--define(wxEvent_GetTimestamp, 2689).
--define(wxEvent_IsCommandEvent, 2690).
--define(wxEvent_ResumePropagation, 2691).
--define(wxEvent_ShouldPropagate, 2692).
--define(wxEvent_Skip, 2693).
--define(wxEvent_StopPropagation, 2694).
--define(wxCommandEvent_getClientData, 2695).
--define(wxCommandEvent_GetExtraLong, 2696).
--define(wxCommandEvent_GetInt, 2697).
--define(wxCommandEvent_GetSelection, 2698).
--define(wxCommandEvent_GetString, 2699).
--define(wxCommandEvent_IsChecked, 2700).
--define(wxCommandEvent_IsSelection, 2701).
--define(wxCommandEvent_SetInt, 2702).
--define(wxCommandEvent_SetString, 2703).
--define(wxScrollEvent_GetOrientation, 2704).
--define(wxScrollEvent_GetPosition, 2705).
--define(wxScrollWinEvent_GetOrientation, 2706).
--define(wxScrollWinEvent_GetPosition, 2707).
--define(wxMouseEvent_AltDown, 2708).
--define(wxMouseEvent_Button, 2709).
--define(wxMouseEvent_ButtonDClick, 2710).
--define(wxMouseEvent_ButtonDown, 2711).
--define(wxMouseEvent_ButtonUp, 2712).
--define(wxMouseEvent_CmdDown, 2713).
--define(wxMouseEvent_ControlDown, 2714).
--define(wxMouseEvent_Dragging, 2715).
--define(wxMouseEvent_Entering, 2716).
--define(wxMouseEvent_GetButton, 2717).
--define(wxMouseEvent_GetPosition, 2720).
--define(wxMouseEvent_GetLogicalPosition, 2721).
--define(wxMouseEvent_GetLinesPerAction, 2722).
--define(wxMouseEvent_GetWheelRotation, 2723).
--define(wxMouseEvent_GetWheelDelta, 2724).
--define(wxMouseEvent_GetX, 2725).
--define(wxMouseEvent_GetY, 2726).
--define(wxMouseEvent_IsButton, 2727).
--define(wxMouseEvent_IsPageScroll, 2728).
--define(wxMouseEvent_Leaving, 2729).
--define(wxMouseEvent_LeftDClick, 2730).
--define(wxMouseEvent_LeftDown, 2731).
--define(wxMouseEvent_LeftIsDown, 2732).
--define(wxMouseEvent_LeftUp, 2733).
--define(wxMouseEvent_MetaDown, 2734).
--define(wxMouseEvent_MiddleDClick, 2735).
--define(wxMouseEvent_MiddleDown, 2736).
--define(wxMouseEvent_MiddleIsDown, 2737).
--define(wxMouseEvent_MiddleUp, 2738).
--define(wxMouseEvent_Moving, 2739).
--define(wxMouseEvent_RightDClick, 2740).
--define(wxMouseEvent_RightDown, 2741).
--define(wxMouseEvent_RightIsDown, 2742).
--define(wxMouseEvent_RightUp, 2743).
--define(wxMouseEvent_ShiftDown, 2744).
--define(wxSetCursorEvent_GetCursor, 2745).
--define(wxSetCursorEvent_GetX, 2746).
--define(wxSetCursorEvent_GetY, 2747).
--define(wxSetCursorEvent_HasCursor, 2748).
--define(wxSetCursorEvent_SetCursor, 2749).
--define(wxKeyEvent_AltDown, 2750).
--define(wxKeyEvent_CmdDown, 2751).
--define(wxKeyEvent_ControlDown, 2752).
--define(wxKeyEvent_GetKeyCode, 2753).
--define(wxKeyEvent_GetModifiers, 2754).
--define(wxKeyEvent_GetPosition, 2757).
--define(wxKeyEvent_GetRawKeyCode, 2758).
--define(wxKeyEvent_GetRawKeyFlags, 2759).
--define(wxKeyEvent_GetUnicodeKey, 2760).
--define(wxKeyEvent_GetX, 2761).
--define(wxKeyEvent_GetY, 2762).
--define(wxKeyEvent_HasModifiers, 2763).
--define(wxKeyEvent_MetaDown, 2764).
--define(wxKeyEvent_ShiftDown, 2765).
--define(wxSizeEvent_GetSize, 2766).
--define(wxMoveEvent_GetPosition, 2767).
--define(wxEraseEvent_GetDC, 2768).
--define(wxFocusEvent_GetWindow, 2769).
--define(wxChildFocusEvent_GetWindow, 2770).
--define(wxMenuEvent_GetMenu, 2771).
--define(wxMenuEvent_GetMenuId, 2772).
--define(wxMenuEvent_IsPopup, 2773).
--define(wxCloseEvent_CanVeto, 2774).
--define(wxCloseEvent_GetLoggingOff, 2775).
--define(wxCloseEvent_SetCanVeto, 2776).
--define(wxCloseEvent_SetLoggingOff, 2777).
--define(wxCloseEvent_Veto, 2778).
--define(wxShowEvent_SetShow, 2779).
--define(wxShowEvent_GetShow, 2780).
--define(wxIconizeEvent_Iconized, 2781).
--define(wxJoystickEvent_ButtonDown, 2782).
--define(wxJoystickEvent_ButtonIsDown, 2783).
--define(wxJoystickEvent_ButtonUp, 2784).
--define(wxJoystickEvent_GetButtonChange, 2785).
--define(wxJoystickEvent_GetButtonState, 2786).
--define(wxJoystickEvent_GetJoystick, 2787).
--define(wxJoystickEvent_GetPosition, 2788).
--define(wxJoystickEvent_GetZPosition, 2789).
--define(wxJoystickEvent_IsButton, 2790).
--define(wxJoystickEvent_IsMove, 2791).
--define(wxJoystickEvent_IsZMove, 2792).
--define(wxUpdateUIEvent_CanUpdate, 2793).
--define(wxUpdateUIEvent_Check, 2794).
--define(wxUpdateUIEvent_Enable, 2795).
--define(wxUpdateUIEvent_Show, 2796).
--define(wxUpdateUIEvent_GetChecked, 2797).
--define(wxUpdateUIEvent_GetEnabled, 2798).
--define(wxUpdateUIEvent_GetShown, 2799).
--define(wxUpdateUIEvent_GetSetChecked, 2800).
--define(wxUpdateUIEvent_GetSetEnabled, 2801).
--define(wxUpdateUIEvent_GetSetShown, 2802).
--define(wxUpdateUIEvent_GetSetText, 2803).
--define(wxUpdateUIEvent_GetText, 2804).
--define(wxUpdateUIEvent_GetMode, 2805).
--define(wxUpdateUIEvent_GetUpdateInterval, 2806).
--define(wxUpdateUIEvent_ResetUpdateTime, 2807).
--define(wxUpdateUIEvent_SetMode, 2808).
--define(wxUpdateUIEvent_SetText, 2809).
--define(wxUpdateUIEvent_SetUpdateInterval, 2810).
--define(wxMouseCaptureChangedEvent_GetCapturedWindow, 2811).
--define(wxPaletteChangedEvent_SetChangedWindow, 2812).
--define(wxPaletteChangedEvent_GetChangedWindow, 2813).
--define(wxQueryNewPaletteEvent_SetPaletteRealized, 2814).
--define(wxQueryNewPaletteEvent_GetPaletteRealized, 2815).
--define(wxNavigationKeyEvent_GetDirection, 2816).
--define(wxNavigationKeyEvent_SetDirection, 2817).
--define(wxNavigationKeyEvent_IsWindowChange, 2818).
--define(wxNavigationKeyEvent_SetWindowChange, 2819).
--define(wxNavigationKeyEvent_IsFromTab, 2820).
--define(wxNavigationKeyEvent_SetFromTab, 2821).
--define(wxNavigationKeyEvent_GetCurrentFocus, 2822).
--define(wxNavigationKeyEvent_SetCurrentFocus, 2823).
--define(wxHelpEvent_GetOrigin, 2824).
--define(wxHelpEvent_GetPosition, 2825).
--define(wxHelpEvent_SetOrigin, 2826).
--define(wxHelpEvent_SetPosition, 2827).
--define(wxContextMenuEvent_GetPosition, 2828).
--define(wxContextMenuEvent_SetPosition, 2829).
--define(wxIdleEvent_CanSend, 2830).
--define(wxIdleEvent_GetMode, 2831).
--define(wxIdleEvent_RequestMore, 2832).
--define(wxIdleEvent_MoreRequested, 2833).
--define(wxIdleEvent_SetMode, 2834).
--define(wxGridEvent_AltDown, 2835).
--define(wxGridEvent_ControlDown, 2836).
--define(wxGridEvent_GetCol, 2837).
--define(wxGridEvent_GetPosition, 2838).
--define(wxGridEvent_GetRow, 2839).
--define(wxGridEvent_MetaDown, 2840).
--define(wxGridEvent_Selecting, 2841).
--define(wxGridEvent_ShiftDown, 2842).
--define(wxNotifyEvent_Allow, 2843).
--define(wxNotifyEvent_IsAllowed, 2844).
--define(wxNotifyEvent_Veto, 2845).
--define(wxSashEvent_GetEdge, 2846).
--define(wxSashEvent_GetDragRect, 2847).
--define(wxSashEvent_GetDragStatus, 2848).
--define(wxListEvent_GetCacheFrom, 2849).
--define(wxListEvent_GetCacheTo, 2850).
--define(wxListEvent_GetKeyCode, 2851).
--define(wxListEvent_GetIndex, 2852).
--define(wxListEvent_GetColumn, 2853).
--define(wxListEvent_GetPoint, 2854).
--define(wxListEvent_GetLabel, 2855).
--define(wxListEvent_GetText, 2856).
--define(wxListEvent_GetImage, 2857).
--define(wxListEvent_GetData, 2858).
--define(wxListEvent_GetMask, 2859).
--define(wxListEvent_GetItem, 2860).
--define(wxListEvent_IsEditCancelled, 2861).
--define(wxDateEvent_GetDate, 2862).
--define(wxCalendarEvent_GetWeekDay, 2863).
--define(wxFileDirPickerEvent_GetPath, 2864).
--define(wxColourPickerEvent_GetColour, 2865).
--define(wxFontPickerEvent_GetFont, 2866).
--define(wxStyledTextEvent_GetPosition, 2867).
--define(wxStyledTextEvent_GetKey, 2868).
--define(wxStyledTextEvent_GetModifiers, 2869).
--define(wxStyledTextEvent_GetModificationType, 2870).
--define(wxStyledTextEvent_GetText, 2871).
--define(wxStyledTextEvent_GetLength, 2872).
--define(wxStyledTextEvent_GetLinesAdded, 2873).
--define(wxStyledTextEvent_GetLine, 2874).
--define(wxStyledTextEvent_GetFoldLevelNow, 2875).
--define(wxStyledTextEvent_GetFoldLevelPrev, 2876).
--define(wxStyledTextEvent_GetMargin, 2877).
--define(wxStyledTextEvent_GetMessage, 2878).
--define(wxStyledTextEvent_GetWParam, 2879).
--define(wxStyledTextEvent_GetLParam, 2880).
--define(wxStyledTextEvent_GetListType, 2881).
--define(wxStyledTextEvent_GetX, 2882).
--define(wxStyledTextEvent_GetY, 2883).
--define(wxStyledTextEvent_GetDragText, 2884).
--define(wxStyledTextEvent_GetDragAllowMove, 2885).
--define(wxStyledTextEvent_GetDragResult, 2886).
--define(wxStyledTextEvent_GetShift, 2887).
--define(wxStyledTextEvent_GetControl, 2888).
--define(wxStyledTextEvent_GetAlt, 2889).
--define(utils_wxGetKeyState, 2890).
--define(utils_wxGetMousePosition, 2891).
--define(utils_wxGetMouseState, 2892).
--define(utils_wxSetDetectableAutoRepeat, 2893).
--define(utils_wxBell, 2894).
--define(utils_wxFindMenuItemId, 2895).
--define(utils_wxGenericFindWindowAtPoint, 2896).
--define(utils_wxFindWindowAtPoint, 2897).
--define(utils_wxBeginBusyCursor, 2898).
--define(utils_wxEndBusyCursor, 2899).
--define(utils_wxIsBusy, 2900).
--define(utils_wxShutdown, 2901).
--define(utils_wxShell, 2902).
--define(utils_wxLaunchDefaultBrowser, 2903).
--define(utils_wxGetEmailAddress, 2904).
--define(utils_wxGetUserId, 2905).
--define(utils_wxGetHomeDir, 2906).
--define(utils_wxNewId, 2907).
--define(utils_wxRegisterId, 2908).
--define(utils_wxGetCurrentId, 2909).
--define(utils_wxGetOsDescription, 2910).
--define(utils_wxIsPlatformLittleEndian, 2911).
--define(utils_wxIsPlatform64Bit, 2912).
--define(wxPrintout_new, 2913).
--define(wxPrintout_destruct, 2914).
--define(wxPrintout_GetDC, 2915).
--define(wxPrintout_GetPageSizeMM, 2916).
--define(wxPrintout_GetPageSizePixels, 2917).
--define(wxPrintout_GetPaperRectPixels, 2918).
--define(wxPrintout_GetPPIPrinter, 2919).
--define(wxPrintout_GetPPIScreen, 2920).
--define(wxPrintout_GetTitle, 2921).
--define(wxPrintout_IsPreview, 2922).
--define(wxPrintout_FitThisSizeToPaper, 2923).
--define(wxPrintout_FitThisSizeToPage, 2924).
--define(wxPrintout_FitThisSizeToPageMargins, 2925).
--define(wxPrintout_MapScreenSizeToPaper, 2926).
--define(wxPrintout_MapScreenSizeToPage, 2927).
--define(wxPrintout_MapScreenSizeToPageMargins, 2928).
--define(wxPrintout_MapScreenSizeToDevice, 2929).
--define(wxPrintout_GetLogicalPaperRect, 2930).
--define(wxPrintout_GetLogicalPageRect, 2931).
--define(wxPrintout_GetLogicalPageMarginsRect, 2932).
--define(wxPrintout_SetLogicalOrigin, 2933).
--define(wxPrintout_OffsetLogicalOrigin, 2934).
--define(wxStyledTextCtrl_new_2, 2935).
--define(wxStyledTextCtrl_new_0, 2936).
--define(wxStyledTextCtrl_destruct, 2937).
--define(wxStyledTextCtrl_Create, 2938).
--define(wxStyledTextCtrl_AddText, 2939).
--define(wxStyledTextCtrl_AddStyledText, 2940).
--define(wxStyledTextCtrl_InsertText, 2941).
--define(wxStyledTextCtrl_ClearAll, 2942).
--define(wxStyledTextCtrl_ClearDocumentStyle, 2943).
--define(wxStyledTextCtrl_GetLength, 2944).
--define(wxStyledTextCtrl_GetCharAt, 2945).
--define(wxStyledTextCtrl_GetCurrentPos, 2946).
--define(wxStyledTextCtrl_GetAnchor, 2947).
--define(wxStyledTextCtrl_GetStyleAt, 2948).
--define(wxStyledTextCtrl_Redo, 2949).
--define(wxStyledTextCtrl_SetUndoCollection, 2950).
--define(wxStyledTextCtrl_SelectAll, 2951).
--define(wxStyledTextCtrl_SetSavePoint, 2952).
--define(wxStyledTextCtrl_GetStyledText, 2953).
--define(wxStyledTextCtrl_CanRedo, 2954).
--define(wxStyledTextCtrl_MarkerLineFromHandle, 2955).
--define(wxStyledTextCtrl_MarkerDeleteHandle, 2956).
--define(wxStyledTextCtrl_GetUndoCollection, 2957).
--define(wxStyledTextCtrl_GetViewWhiteSpace, 2958).
--define(wxStyledTextCtrl_SetViewWhiteSpace, 2959).
--define(wxStyledTextCtrl_PositionFromPoint, 2960).
--define(wxStyledTextCtrl_PositionFromPointClose, 2961).
--define(wxStyledTextCtrl_GotoLine, 2962).
--define(wxStyledTextCtrl_GotoPos, 2963).
--define(wxStyledTextCtrl_SetAnchor, 2964).
--define(wxStyledTextCtrl_GetCurLine, 2965).
--define(wxStyledTextCtrl_GetEndStyled, 2966).
--define(wxStyledTextCtrl_ConvertEOLs, 2967).
--define(wxStyledTextCtrl_GetEOLMode, 2968).
--define(wxStyledTextCtrl_SetEOLMode, 2969).
--define(wxStyledTextCtrl_StartStyling, 2970).
--define(wxStyledTextCtrl_SetStyling, 2971).
--define(wxStyledTextCtrl_GetBufferedDraw, 2972).
--define(wxStyledTextCtrl_SetBufferedDraw, 2973).
--define(wxStyledTextCtrl_SetTabWidth, 2974).
--define(wxStyledTextCtrl_GetTabWidth, 2975).
--define(wxStyledTextCtrl_SetCodePage, 2976).
--define(wxStyledTextCtrl_MarkerDefine, 2977).
--define(wxStyledTextCtrl_MarkerSetForeground, 2978).
--define(wxStyledTextCtrl_MarkerSetBackground, 2979).
--define(wxStyledTextCtrl_MarkerAdd, 2980).
--define(wxStyledTextCtrl_MarkerDelete, 2981).
--define(wxStyledTextCtrl_MarkerDeleteAll, 2982).
--define(wxStyledTextCtrl_MarkerGet, 2983).
--define(wxStyledTextCtrl_MarkerNext, 2984).
--define(wxStyledTextCtrl_MarkerPrevious, 2985).
--define(wxStyledTextCtrl_MarkerDefineBitmap, 2986).
--define(wxStyledTextCtrl_MarkerAddSet, 2987).
--define(wxStyledTextCtrl_MarkerSetAlpha, 2988).
--define(wxStyledTextCtrl_SetMarginType, 2989).
--define(wxStyledTextCtrl_GetMarginType, 2990).
--define(wxStyledTextCtrl_SetMarginWidth, 2991).
--define(wxStyledTextCtrl_GetMarginWidth, 2992).
--define(wxStyledTextCtrl_SetMarginMask, 2993).
--define(wxStyledTextCtrl_GetMarginMask, 2994).
--define(wxStyledTextCtrl_SetMarginSensitive, 2995).
--define(wxStyledTextCtrl_GetMarginSensitive, 2996).
--define(wxStyledTextCtrl_StyleClearAll, 2997).
--define(wxStyledTextCtrl_StyleSetForeground, 2998).
--define(wxStyledTextCtrl_StyleSetBackground, 2999).
--define(wxStyledTextCtrl_StyleSetBold, 3000).
--define(wxStyledTextCtrl_StyleSetItalic, 3001).
--define(wxStyledTextCtrl_StyleSetSize, 3002).
--define(wxStyledTextCtrl_StyleSetFaceName, 3003).
--define(wxStyledTextCtrl_StyleSetEOLFilled, 3004).
--define(wxStyledTextCtrl_StyleResetDefault, 3005).
--define(wxStyledTextCtrl_StyleSetUnderline, 3006).
--define(wxStyledTextCtrl_StyleSetCase, 3007).
--define(wxStyledTextCtrl_StyleSetHotSpot, 3008).
--define(wxStyledTextCtrl_SetSelForeground, 3009).
--define(wxStyledTextCtrl_SetSelBackground, 3010).
--define(wxStyledTextCtrl_GetSelAlpha, 3011).
--define(wxStyledTextCtrl_SetSelAlpha, 3012).
--define(wxStyledTextCtrl_SetCaretForeground, 3013).
--define(wxStyledTextCtrl_CmdKeyAssign, 3014).
--define(wxStyledTextCtrl_CmdKeyClear, 3015).
--define(wxStyledTextCtrl_CmdKeyClearAll, 3016).
--define(wxStyledTextCtrl_SetStyleBytes, 3017).
--define(wxStyledTextCtrl_StyleSetVisible, 3018).
--define(wxStyledTextCtrl_GetCaretPeriod, 3019).
--define(wxStyledTextCtrl_SetCaretPeriod, 3020).
--define(wxStyledTextCtrl_SetWordChars, 3021).
--define(wxStyledTextCtrl_BeginUndoAction, 3022).
--define(wxStyledTextCtrl_EndUndoAction, 3023).
--define(wxStyledTextCtrl_IndicatorSetStyle, 3024).
--define(wxStyledTextCtrl_IndicatorGetStyle, 3025).
--define(wxStyledTextCtrl_IndicatorSetForeground, 3026).
--define(wxStyledTextCtrl_IndicatorGetForeground, 3027).
--define(wxStyledTextCtrl_SetWhitespaceForeground, 3028).
--define(wxStyledTextCtrl_SetWhitespaceBackground, 3029).
--define(wxStyledTextCtrl_GetStyleBits, 3030).
--define(wxStyledTextCtrl_SetLineState, 3031).
--define(wxStyledTextCtrl_GetLineState, 3032).
--define(wxStyledTextCtrl_GetMaxLineState, 3033).
--define(wxStyledTextCtrl_GetCaretLineVisible, 3034).
--define(wxStyledTextCtrl_SetCaretLineVisible, 3035).
--define(wxStyledTextCtrl_GetCaretLineBackground, 3036).
--define(wxStyledTextCtrl_SetCaretLineBackground, 3037).
--define(wxStyledTextCtrl_AutoCompShow, 3038).
--define(wxStyledTextCtrl_AutoCompCancel, 3039).
--define(wxStyledTextCtrl_AutoCompActive, 3040).
--define(wxStyledTextCtrl_AutoCompPosStart, 3041).
--define(wxStyledTextCtrl_AutoCompComplete, 3042).
--define(wxStyledTextCtrl_AutoCompStops, 3043).
--define(wxStyledTextCtrl_AutoCompSetSeparator, 3044).
--define(wxStyledTextCtrl_AutoCompGetSeparator, 3045).
--define(wxStyledTextCtrl_AutoCompSelect, 3046).
--define(wxStyledTextCtrl_AutoCompSetCancelAtStart, 3047).
--define(wxStyledTextCtrl_AutoCompGetCancelAtStart, 3048).
--define(wxStyledTextCtrl_AutoCompSetFillUps, 3049).
--define(wxStyledTextCtrl_AutoCompSetChooseSingle, 3050).
--define(wxStyledTextCtrl_AutoCompGetChooseSingle, 3051).
--define(wxStyledTextCtrl_AutoCompSetIgnoreCase, 3052).
--define(wxStyledTextCtrl_AutoCompGetIgnoreCase, 3053).
--define(wxStyledTextCtrl_UserListShow, 3054).
--define(wxStyledTextCtrl_AutoCompSetAutoHide, 3055).
--define(wxStyledTextCtrl_AutoCompGetAutoHide, 3056).
--define(wxStyledTextCtrl_AutoCompSetDropRestOfWord, 3057).
--define(wxStyledTextCtrl_AutoCompGetDropRestOfWord, 3058).
--define(wxStyledTextCtrl_RegisterImage, 3059).
--define(wxStyledTextCtrl_ClearRegisteredImages, 3060).
--define(wxStyledTextCtrl_AutoCompGetTypeSeparator, 3061).
--define(wxStyledTextCtrl_AutoCompSetTypeSeparator, 3062).
--define(wxStyledTextCtrl_AutoCompSetMaxWidth, 3063).
--define(wxStyledTextCtrl_AutoCompGetMaxWidth, 3064).
--define(wxStyledTextCtrl_AutoCompSetMaxHeight, 3065).
--define(wxStyledTextCtrl_AutoCompGetMaxHeight, 3066).
--define(wxStyledTextCtrl_SetIndent, 3067).
--define(wxStyledTextCtrl_GetIndent, 3068).
--define(wxStyledTextCtrl_SetUseTabs, 3069).
--define(wxStyledTextCtrl_GetUseTabs, 3070).
--define(wxStyledTextCtrl_SetLineIndentation, 3071).
--define(wxStyledTextCtrl_GetLineIndentation, 3072).
--define(wxStyledTextCtrl_GetLineIndentPosition, 3073).
--define(wxStyledTextCtrl_GetColumn, 3074).
--define(wxStyledTextCtrl_SetUseHorizontalScrollBar, 3075).
--define(wxStyledTextCtrl_GetUseHorizontalScrollBar, 3076).
--define(wxStyledTextCtrl_SetIndentationGuides, 3077).
--define(wxStyledTextCtrl_GetIndentationGuides, 3078).
--define(wxStyledTextCtrl_SetHighlightGuide, 3079).
--define(wxStyledTextCtrl_GetHighlightGuide, 3080).
--define(wxStyledTextCtrl_GetLineEndPosition, 3081).
--define(wxStyledTextCtrl_GetCodePage, 3082).
--define(wxStyledTextCtrl_GetCaretForeground, 3083).
--define(wxStyledTextCtrl_GetReadOnly, 3084).
--define(wxStyledTextCtrl_SetCurrentPos, 3085).
--define(wxStyledTextCtrl_SetSelectionStart, 3086).
--define(wxStyledTextCtrl_GetSelectionStart, 3087).
--define(wxStyledTextCtrl_SetSelectionEnd, 3088).
--define(wxStyledTextCtrl_GetSelectionEnd, 3089).
--define(wxStyledTextCtrl_SetPrintMagnification, 3090).
--define(wxStyledTextCtrl_GetPrintMagnification, 3091).
--define(wxStyledTextCtrl_SetPrintColourMode, 3092).
--define(wxStyledTextCtrl_GetPrintColourMode, 3093).
--define(wxStyledTextCtrl_FindText, 3094).
--define(wxStyledTextCtrl_FormatRange, 3095).
--define(wxStyledTextCtrl_GetFirstVisibleLine, 3096).
--define(wxStyledTextCtrl_GetLine, 3097).
--define(wxStyledTextCtrl_GetLineCount, 3098).
--define(wxStyledTextCtrl_SetMarginLeft, 3099).
--define(wxStyledTextCtrl_GetMarginLeft, 3100).
--define(wxStyledTextCtrl_SetMarginRight, 3101).
--define(wxStyledTextCtrl_GetMarginRight, 3102).
--define(wxStyledTextCtrl_GetModify, 3103).
--define(wxStyledTextCtrl_SetSelection, 3104).
--define(wxStyledTextCtrl_GetSelectedText, 3105).
--define(wxStyledTextCtrl_GetTextRange, 3106).
--define(wxStyledTextCtrl_HideSelection, 3107).
--define(wxStyledTextCtrl_LineFromPosition, 3108).
--define(wxStyledTextCtrl_PositionFromLine, 3109).
--define(wxStyledTextCtrl_LineScroll, 3110).
--define(wxStyledTextCtrl_EnsureCaretVisible, 3111).
--define(wxStyledTextCtrl_ReplaceSelection, 3112).
--define(wxStyledTextCtrl_SetReadOnly, 3113).
--define(wxStyledTextCtrl_CanPaste, 3114).
--define(wxStyledTextCtrl_CanUndo, 3115).
--define(wxStyledTextCtrl_EmptyUndoBuffer, 3116).
--define(wxStyledTextCtrl_Undo, 3117).
--define(wxStyledTextCtrl_Cut, 3118).
--define(wxStyledTextCtrl_Copy, 3119).
--define(wxStyledTextCtrl_Paste, 3120).
--define(wxStyledTextCtrl_Clear, 3121).
--define(wxStyledTextCtrl_SetText, 3122).
--define(wxStyledTextCtrl_GetText, 3123).
--define(wxStyledTextCtrl_GetTextLength, 3124).
--define(wxStyledTextCtrl_GetOvertype, 3125).
--define(wxStyledTextCtrl_SetCaretWidth, 3126).
--define(wxStyledTextCtrl_GetCaretWidth, 3127).
--define(wxStyledTextCtrl_SetTargetStart, 3128).
--define(wxStyledTextCtrl_GetTargetStart, 3129).
--define(wxStyledTextCtrl_SetTargetEnd, 3130).
--define(wxStyledTextCtrl_GetTargetEnd, 3131).
--define(wxStyledTextCtrl_ReplaceTarget, 3132).
--define(wxStyledTextCtrl_SearchInTarget, 3133).
--define(wxStyledTextCtrl_SetSearchFlags, 3134).
--define(wxStyledTextCtrl_GetSearchFlags, 3135).
--define(wxStyledTextCtrl_CallTipShow, 3136).
--define(wxStyledTextCtrl_CallTipCancel, 3137).
--define(wxStyledTextCtrl_CallTipActive, 3138).
--define(wxStyledTextCtrl_CallTipPosAtStart, 3139).
--define(wxStyledTextCtrl_CallTipSetHighlight, 3140).
--define(wxStyledTextCtrl_CallTipSetBackground, 3141).
--define(wxStyledTextCtrl_CallTipSetForeground, 3142).
--define(wxStyledTextCtrl_CallTipSetForegroundHighlight, 3143).
--define(wxStyledTextCtrl_CallTipUseStyle, 3144).
--define(wxStyledTextCtrl_VisibleFromDocLine, 3145).
--define(wxStyledTextCtrl_DocLineFromVisible, 3146).
--define(wxStyledTextCtrl_WrapCount, 3147).
--define(wxStyledTextCtrl_SetFoldLevel, 3148).
--define(wxStyledTextCtrl_GetFoldLevel, 3149).
--define(wxStyledTextCtrl_GetLastChild, 3150).
--define(wxStyledTextCtrl_GetFoldParent, 3151).
--define(wxStyledTextCtrl_ShowLines, 3152).
--define(wxStyledTextCtrl_HideLines, 3153).
--define(wxStyledTextCtrl_GetLineVisible, 3154).
--define(wxStyledTextCtrl_SetFoldExpanded, 3155).
--define(wxStyledTextCtrl_GetFoldExpanded, 3156).
--define(wxStyledTextCtrl_ToggleFold, 3157).
--define(wxStyledTextCtrl_EnsureVisible, 3158).
--define(wxStyledTextCtrl_SetFoldFlags, 3159).
--define(wxStyledTextCtrl_EnsureVisibleEnforcePolicy, 3160).
--define(wxStyledTextCtrl_SetTabIndents, 3161).
--define(wxStyledTextCtrl_GetTabIndents, 3162).
--define(wxStyledTextCtrl_SetBackSpaceUnIndents, 3163).
--define(wxStyledTextCtrl_GetBackSpaceUnIndents, 3164).
--define(wxStyledTextCtrl_SetMouseDwellTime, 3165).
--define(wxStyledTextCtrl_GetMouseDwellTime, 3166).
--define(wxStyledTextCtrl_WordStartPosition, 3167).
--define(wxStyledTextCtrl_WordEndPosition, 3168).
--define(wxStyledTextCtrl_SetWrapMode, 3169).
--define(wxStyledTextCtrl_GetWrapMode, 3170).
--define(wxStyledTextCtrl_SetWrapVisualFlags, 3171).
--define(wxStyledTextCtrl_GetWrapVisualFlags, 3172).
--define(wxStyledTextCtrl_SetWrapVisualFlagsLocation, 3173).
--define(wxStyledTextCtrl_GetWrapVisualFlagsLocation, 3174).
--define(wxStyledTextCtrl_SetWrapStartIndent, 3175).
--define(wxStyledTextCtrl_GetWrapStartIndent, 3176).
--define(wxStyledTextCtrl_SetLayoutCache, 3177).
--define(wxStyledTextCtrl_GetLayoutCache, 3178).
--define(wxStyledTextCtrl_SetScrollWidth, 3179).
--define(wxStyledTextCtrl_GetScrollWidth, 3180).
--define(wxStyledTextCtrl_TextWidth, 3181).
--define(wxStyledTextCtrl_GetEndAtLastLine, 3182).
--define(wxStyledTextCtrl_TextHeight, 3183).
--define(wxStyledTextCtrl_SetUseVerticalScrollBar, 3184).
--define(wxStyledTextCtrl_GetUseVerticalScrollBar, 3185).
--define(wxStyledTextCtrl_AppendText, 3186).
--define(wxStyledTextCtrl_GetTwoPhaseDraw, 3187).
--define(wxStyledTextCtrl_SetTwoPhaseDraw, 3188).
--define(wxStyledTextCtrl_TargetFromSelection, 3189).
--define(wxStyledTextCtrl_LinesJoin, 3190).
--define(wxStyledTextCtrl_LinesSplit, 3191).
--define(wxStyledTextCtrl_SetFoldMarginColour, 3192).
--define(wxStyledTextCtrl_SetFoldMarginHiColour, 3193).
--define(wxStyledTextCtrl_LineDown, 3194).
--define(wxStyledTextCtrl_LineDownExtend, 3195).
--define(wxStyledTextCtrl_LineUp, 3196).
--define(wxStyledTextCtrl_LineUpExtend, 3197).
--define(wxStyledTextCtrl_CharLeft, 3198).
--define(wxStyledTextCtrl_CharLeftExtend, 3199).
--define(wxStyledTextCtrl_CharRight, 3200).
--define(wxStyledTextCtrl_CharRightExtend, 3201).
--define(wxStyledTextCtrl_WordLeft, 3202).
--define(wxStyledTextCtrl_WordLeftExtend, 3203).
--define(wxStyledTextCtrl_WordRight, 3204).
--define(wxStyledTextCtrl_WordRightExtend, 3205).
--define(wxStyledTextCtrl_Home, 3206).
--define(wxStyledTextCtrl_HomeExtend, 3207).
--define(wxStyledTextCtrl_LineEnd, 3208).
--define(wxStyledTextCtrl_LineEndExtend, 3209).
--define(wxStyledTextCtrl_DocumentStart, 3210).
--define(wxStyledTextCtrl_DocumentStartExtend, 3211).
--define(wxStyledTextCtrl_DocumentEnd, 3212).
--define(wxStyledTextCtrl_DocumentEndExtend, 3213).
--define(wxStyledTextCtrl_PageUp, 3214).
--define(wxStyledTextCtrl_PageUpExtend, 3215).
--define(wxStyledTextCtrl_PageDown, 3216).
--define(wxStyledTextCtrl_PageDownExtend, 3217).
--define(wxStyledTextCtrl_EditToggleOvertype, 3218).
--define(wxStyledTextCtrl_Cancel, 3219).
--define(wxStyledTextCtrl_DeleteBack, 3220).
--define(wxStyledTextCtrl_Tab, 3221).
--define(wxStyledTextCtrl_BackTab, 3222).
--define(wxStyledTextCtrl_NewLine, 3223).
--define(wxStyledTextCtrl_FormFeed, 3224).
--define(wxStyledTextCtrl_VCHome, 3225).
--define(wxStyledTextCtrl_VCHomeExtend, 3226).
--define(wxStyledTextCtrl_ZoomIn, 3227).
--define(wxStyledTextCtrl_ZoomOut, 3228).
--define(wxStyledTextCtrl_DelWordLeft, 3229).
--define(wxStyledTextCtrl_DelWordRight, 3230).
--define(wxStyledTextCtrl_LineCut, 3231).
--define(wxStyledTextCtrl_LineDelete, 3232).
--define(wxStyledTextCtrl_LineTranspose, 3233).
--define(wxStyledTextCtrl_LineDuplicate, 3234).
--define(wxStyledTextCtrl_LowerCase, 3235).
--define(wxStyledTextCtrl_UpperCase, 3236).
--define(wxStyledTextCtrl_LineScrollDown, 3237).
--define(wxStyledTextCtrl_LineScrollUp, 3238).
--define(wxStyledTextCtrl_DeleteBackNotLine, 3239).
--define(wxStyledTextCtrl_HomeDisplay, 3240).
--define(wxStyledTextCtrl_HomeDisplayExtend, 3241).
--define(wxStyledTextCtrl_LineEndDisplay, 3242).
--define(wxStyledTextCtrl_LineEndDisplayExtend, 3243).
--define(wxStyledTextCtrl_HomeWrapExtend, 3244).
--define(wxStyledTextCtrl_LineEndWrap, 3245).
--define(wxStyledTextCtrl_LineEndWrapExtend, 3246).
--define(wxStyledTextCtrl_VCHomeWrap, 3247).
--define(wxStyledTextCtrl_VCHomeWrapExtend, 3248).
--define(wxStyledTextCtrl_LineCopy, 3249).
--define(wxStyledTextCtrl_MoveCaretInsideView, 3250).
--define(wxStyledTextCtrl_LineLength, 3251).
--define(wxStyledTextCtrl_BraceHighlight, 3252).
--define(wxStyledTextCtrl_BraceBadLight, 3253).
--define(wxStyledTextCtrl_BraceMatch, 3254).
--define(wxStyledTextCtrl_GetViewEOL, 3255).
--define(wxStyledTextCtrl_SetViewEOL, 3256).
--define(wxStyledTextCtrl_SetModEventMask, 3257).
--define(wxStyledTextCtrl_GetEdgeColumn, 3258).
--define(wxStyledTextCtrl_SetEdgeColumn, 3259).
--define(wxStyledTextCtrl_GetEdgeMode, 3260).
--define(wxStyledTextCtrl_GetEdgeColour, 3261).
--define(wxStyledTextCtrl_SetEdgeColour, 3262).
--define(wxStyledTextCtrl_SearchAnchor, 3263).
--define(wxStyledTextCtrl_SearchNext, 3264).
--define(wxStyledTextCtrl_SearchPrev, 3265).
--define(wxStyledTextCtrl_LinesOnScreen, 3266).
--define(wxStyledTextCtrl_UsePopUp, 3267).
--define(wxStyledTextCtrl_SelectionIsRectangle, 3268).
--define(wxStyledTextCtrl_SetZoom, 3269).
--define(wxStyledTextCtrl_GetZoom, 3270).
--define(wxStyledTextCtrl_GetModEventMask, 3271).
--define(wxStyledTextCtrl_SetSTCFocus, 3272).
--define(wxStyledTextCtrl_GetSTCFocus, 3273).
--define(wxStyledTextCtrl_SetStatus, 3274).
--define(wxStyledTextCtrl_GetStatus, 3275).
--define(wxStyledTextCtrl_SetMouseDownCaptures, 3276).
--define(wxStyledTextCtrl_GetMouseDownCaptures, 3277).
--define(wxStyledTextCtrl_SetSTCCursor, 3278).
--define(wxStyledTextCtrl_GetSTCCursor, 3279).
--define(wxStyledTextCtrl_SetControlCharSymbol, 3280).
--define(wxStyledTextCtrl_GetControlCharSymbol, 3281).
--define(wxStyledTextCtrl_WordPartLeft, 3282).
--define(wxStyledTextCtrl_WordPartLeftExtend, 3283).
--define(wxStyledTextCtrl_WordPartRight, 3284).
--define(wxStyledTextCtrl_WordPartRightExtend, 3285).
--define(wxStyledTextCtrl_SetVisiblePolicy, 3286).
--define(wxStyledTextCtrl_DelLineLeft, 3287).
--define(wxStyledTextCtrl_DelLineRight, 3288).
--define(wxStyledTextCtrl_GetXOffset, 3289).
--define(wxStyledTextCtrl_ChooseCaretX, 3290).
--define(wxStyledTextCtrl_SetXCaretPolicy, 3291).
--define(wxStyledTextCtrl_SetYCaretPolicy, 3292).
--define(wxStyledTextCtrl_GetPrintWrapMode, 3293).
--define(wxStyledTextCtrl_SetHotspotActiveForeground, 3294).
--define(wxStyledTextCtrl_SetHotspotActiveBackground, 3295).
--define(wxStyledTextCtrl_SetHotspotActiveUnderline, 3296).
--define(wxStyledTextCtrl_SetHotspotSingleLine, 3297).
--define(wxStyledTextCtrl_ParaDownExtend, 3298).
--define(wxStyledTextCtrl_ParaUp, 3299).
--define(wxStyledTextCtrl_ParaUpExtend, 3300).
--define(wxStyledTextCtrl_PositionBefore, 3301).
--define(wxStyledTextCtrl_PositionAfter, 3302).
--define(wxStyledTextCtrl_CopyRange, 3303).
--define(wxStyledTextCtrl_CopyText, 3304).
--define(wxStyledTextCtrl_SetSelectionMode, 3305).
--define(wxStyledTextCtrl_GetSelectionMode, 3306).
--define(wxStyledTextCtrl_LineDownRectExtend, 3307).
--define(wxStyledTextCtrl_LineUpRectExtend, 3308).
--define(wxStyledTextCtrl_CharLeftRectExtend, 3309).
--define(wxStyledTextCtrl_CharRightRectExtend, 3310).
--define(wxStyledTextCtrl_HomeRectExtend, 3311).
--define(wxStyledTextCtrl_VCHomeRectExtend, 3312).
--define(wxStyledTextCtrl_LineEndRectExtend, 3313).
--define(wxStyledTextCtrl_PageUpRectExtend, 3314).
--define(wxStyledTextCtrl_PageDownRectExtend, 3315).
--define(wxStyledTextCtrl_StutteredPageUp, 3316).
--define(wxStyledTextCtrl_StutteredPageUpExtend, 3317).
--define(wxStyledTextCtrl_StutteredPageDown, 3318).
--define(wxStyledTextCtrl_StutteredPageDownExtend, 3319).
--define(wxStyledTextCtrl_WordLeftEnd, 3320).
--define(wxStyledTextCtrl_WordLeftEndExtend, 3321).
--define(wxStyledTextCtrl_WordRightEnd, 3322).
--define(wxStyledTextCtrl_WordRightEndExtend, 3323).
--define(wxStyledTextCtrl_SetWhitespaceChars, 3324).
--define(wxStyledTextCtrl_SetCharsDefault, 3325).
--define(wxStyledTextCtrl_AutoCompGetCurrent, 3326).
--define(wxStyledTextCtrl_Allocate, 3327).
--define(wxStyledTextCtrl_FindColumn, 3328).
--define(wxStyledTextCtrl_GetCaretSticky, 3329).
--define(wxStyledTextCtrl_SetCaretSticky, 3330).
--define(wxStyledTextCtrl_ToggleCaretSticky, 3331).
--define(wxStyledTextCtrl_SetPasteConvertEndings, 3332).
--define(wxStyledTextCtrl_GetPasteConvertEndings, 3333).
--define(wxStyledTextCtrl_SelectionDuplicate, 3334).
--define(wxStyledTextCtrl_SetCaretLineBackAlpha, 3335).
--define(wxStyledTextCtrl_GetCaretLineBackAlpha, 3336).
--define(wxStyledTextCtrl_StartRecord, 3337).
--define(wxStyledTextCtrl_StopRecord, 3338).
--define(wxStyledTextCtrl_SetLexer, 3339).
--define(wxStyledTextCtrl_GetLexer, 3340).
--define(wxStyledTextCtrl_Colourise, 3341).
--define(wxStyledTextCtrl_SetProperty, 3342).
--define(wxStyledTextCtrl_SetKeyWords, 3343).
--define(wxStyledTextCtrl_SetLexerLanguage, 3344).
--define(wxStyledTextCtrl_GetProperty, 3345).
--define(wxStyledTextCtrl_GetStyleBitsNeeded, 3346).
--define(wxStyledTextCtrl_GetCurrentLine, 3347).
--define(wxStyledTextCtrl_StyleSetSpec, 3348).
--define(wxStyledTextCtrl_StyleSetFont, 3349).
--define(wxStyledTextCtrl_StyleSetFontAttr, 3350).
--define(wxStyledTextCtrl_StyleSetCharacterSet, 3351).
--define(wxStyledTextCtrl_StyleSetFontEncoding, 3352).
--define(wxStyledTextCtrl_CmdKeyExecute, 3353).
--define(wxStyledTextCtrl_SetMargins, 3354).
--define(wxStyledTextCtrl_GetSelection, 3355).
--define(wxStyledTextCtrl_PointFromPosition, 3356).
--define(wxStyledTextCtrl_ScrollToLine, 3357).
--define(wxStyledTextCtrl_ScrollToColumn, 3358).
--define(wxStyledTextCtrl_SendMsg, 3359).
--define(wxStyledTextCtrl_SetVScrollBar, 3360).
--define(wxStyledTextCtrl_SetHScrollBar, 3361).
--define(wxStyledTextCtrl_GetLastKeydownProcessed, 3362).
--define(wxStyledTextCtrl_SetLastKeydownProcessed, 3363).
--define(wxStyledTextCtrl_SaveFile, 3364).
--define(wxStyledTextCtrl_LoadFile, 3365).
--define(wxStyledTextCtrl_DoDragOver, 3366).
--define(wxStyledTextCtrl_DoDropText, 3367).
--define(wxStyledTextCtrl_GetUseAntiAliasing, 3368).
--define(wxStyledTextCtrl_AddTextRaw, 3369).
--define(wxStyledTextCtrl_InsertTextRaw, 3370).
--define(wxStyledTextCtrl_GetCurLineRaw, 3371).
--define(wxStyledTextCtrl_GetLineRaw, 3372).
--define(wxStyledTextCtrl_GetSelectedTextRaw, 3373).
--define(wxStyledTextCtrl_GetTextRangeRaw, 3374).
--define(wxStyledTextCtrl_SetTextRaw, 3375).
--define(wxStyledTextCtrl_GetTextRaw, 3376).
--define(wxStyledTextCtrl_AppendTextRaw, 3377).
--define(wxArtProvider_GetBitmap, 3378).
--define(wxArtProvider_GetIcon, 3379).
--define(wxTreeEvent_GetKeyCode, 3380).
--define(wxTreeEvent_GetItem, 3381).
--define(wxTreeEvent_GetKeyEvent, 3382).
--define(wxTreeEvent_GetLabel, 3383).
--define(wxTreeEvent_GetOldItem, 3384).
--define(wxTreeEvent_GetPoint, 3385).
--define(wxTreeEvent_IsEditCancelled, 3386).
--define(wxTreeEvent_SetToolTip, 3387).
--define(wxNotebookEvent_GetOldSelection, 3388).
--define(wxNotebookEvent_GetSelection, 3389).
--define(wxNotebookEvent_SetOldSelection, 3390).
--define(wxNotebookEvent_SetSelection, 3391).
--define(wxFileDataObject_new, 3392).
--define(wxFileDataObject_AddFile, 3393).
--define(wxFileDataObject_GetFilenames, 3394).
--define(wxFileDataObject_destroy, 3395).
--define(wxTextDataObject_new, 3396).
--define(wxTextDataObject_GetTextLength, 3397).
--define(wxTextDataObject_GetText, 3398).
--define(wxTextDataObject_SetText, 3399).
--define(wxTextDataObject_destroy, 3400).
--define(wxBitmapDataObject_new_1_1, 3401).
--define(wxBitmapDataObject_new_1_0, 3402).
--define(wxBitmapDataObject_GetBitmap, 3403).
--define(wxBitmapDataObject_SetBitmap, 3404).
--define(wxBitmapDataObject_destroy, 3405).
--define(wxClipboard_new, 3407).
--define(wxClipboard_destruct, 3408).
--define(wxClipboard_AddData, 3409).
--define(wxClipboard_Clear, 3410).
--define(wxClipboard_Close, 3411).
--define(wxClipboard_Flush, 3412).
--define(wxClipboard_GetData, 3413).
--define(wxClipboard_IsOpened, 3414).
--define(wxClipboard_Open, 3415).
--define(wxClipboard_SetData, 3416).
--define(wxClipboard_UsePrimarySelection, 3418).
--define(wxClipboard_IsSupported, 3419).
--define(wxClipboard_Get, 3420).
--define(wxSpinEvent_GetPosition, 3421).
--define(wxSpinEvent_SetPosition, 3422).
--define(wxSplitterWindow_new_0, 3423).
--define(wxSplitterWindow_new_2, 3424).
--define(wxSplitterWindow_destruct, 3425).
--define(wxSplitterWindow_Create, 3426).
--define(wxSplitterWindow_GetMinimumPaneSize, 3427).
--define(wxSplitterWindow_GetSashGravity, 3428).
--define(wxSplitterWindow_GetSashPosition, 3429).
--define(wxSplitterWindow_GetSplitMode, 3430).
--define(wxSplitterWindow_GetWindow1, 3431).
--define(wxSplitterWindow_GetWindow2, 3432).
--define(wxSplitterWindow_Initialize, 3433).
--define(wxSplitterWindow_IsSplit, 3434).
--define(wxSplitterWindow_ReplaceWindow, 3435).
--define(wxSplitterWindow_SetSashGravity, 3436).
--define(wxSplitterWindow_SetSashPosition, 3437).
--define(wxSplitterWindow_SetSashSize, 3438).
--define(wxSplitterWindow_SetMinimumPaneSize, 3439).
--define(wxSplitterWindow_SetSplitMode, 3440).
--define(wxSplitterWindow_SplitHorizontally, 3441).
--define(wxSplitterWindow_SplitVertically, 3442).
--define(wxSplitterWindow_Unsplit, 3443).
--define(wxSplitterWindow_UpdateSize, 3444).
--define(wxSplitterEvent_GetSashPosition, 3445).
--define(wxSplitterEvent_GetX, 3446).
--define(wxSplitterEvent_GetY, 3447).
--define(wxSplitterEvent_GetWindowBeingRemoved, 3448).
--define(wxSplitterEvent_SetSashPosition, 3449).
--define(wxHtmlWindow_new_0, 3450).
--define(wxHtmlWindow_new_2, 3451).
--define(wxHtmlWindow_AppendToPage, 3452).
--define(wxHtmlWindow_GetOpenedAnchor, 3453).
--define(wxHtmlWindow_GetOpenedPage, 3454).
--define(wxHtmlWindow_GetOpenedPageTitle, 3455).
--define(wxHtmlWindow_GetRelatedFrame, 3456).
--define(wxHtmlWindow_HistoryBack, 3457).
--define(wxHtmlWindow_HistoryCanBack, 3458).
--define(wxHtmlWindow_HistoryCanForward, 3459).
--define(wxHtmlWindow_HistoryClear, 3460).
--define(wxHtmlWindow_HistoryForward, 3461).
--define(wxHtmlWindow_LoadFile, 3462).
--define(wxHtmlWindow_LoadPage, 3463).
--define(wxHtmlWindow_SelectAll, 3464).
--define(wxHtmlWindow_SelectionToText, 3465).
--define(wxHtmlWindow_SelectLine, 3466).
--define(wxHtmlWindow_SelectWord, 3467).
--define(wxHtmlWindow_SetBorders, 3468).
--define(wxHtmlWindow_SetFonts, 3469).
--define(wxHtmlWindow_SetPage, 3470).
--define(wxHtmlWindow_SetRelatedFrame, 3471).
--define(wxHtmlWindow_SetRelatedStatusBar, 3472).
--define(wxHtmlWindow_ToText, 3473).
--define(wxHtmlWindow_destroy, 3474).
--define(wxHtmlLinkEvent_GetLinkInfo, 3475).
--define(wxSystemSettings_GetColour, 3476).
--define(wxSystemSettings_GetFont, 3477).
--define(wxSystemSettings_GetMetric, 3478).
--define(wxSystemSettings_GetScreenType, 3479).
--define(wxAuiNotebookEvent_SetSelection, 3480).
--define(wxAuiNotebookEvent_GetSelection, 3481).
--define(wxAuiNotebookEvent_SetOldSelection, 3482).
--define(wxAuiNotebookEvent_GetOldSelection, 3483).
--define(wxAuiNotebookEvent_SetDragSource, 3484).
--define(wxAuiNotebookEvent_GetDragSource, 3485).
--define(wxAuiManagerEvent_SetManager, 3486).
--define(wxAuiManagerEvent_GetManager, 3487).
--define(wxAuiManagerEvent_SetPane, 3488).
--define(wxAuiManagerEvent_GetPane, 3489).
--define(wxAuiManagerEvent_SetButton, 3490).
--define(wxAuiManagerEvent_GetButton, 3491).
--define(wxAuiManagerEvent_SetDC, 3492).
--define(wxAuiManagerEvent_GetDC, 3493).
--define(wxAuiManagerEvent_Veto, 3494).
--define(wxAuiManagerEvent_GetVeto, 3495).
--define(wxAuiManagerEvent_SetCanVeto, 3496).
--define(wxAuiManagerEvent_CanVeto, 3497).
--define(wxLogNull_new, 3498).
--define(wxLogNull_destroy, 3499).
+-define(wxListItemAttr_new_0, 1757).
+-define(wxListItemAttr_new_3, 1758).
+-define(wxListItemAttr_GetBackgroundColour, 1759).
+-define(wxListItemAttr_GetFont, 1760).
+-define(wxListItemAttr_GetTextColour, 1761).
+-define(wxListItemAttr_HasBackgroundColour, 1762).
+-define(wxListItemAttr_HasFont, 1763).
+-define(wxListItemAttr_HasTextColour, 1764).
+-define(wxListItemAttr_SetBackgroundColour, 1765).
+-define(wxListItemAttr_SetFont, 1766).
+-define(wxListItemAttr_SetTextColour, 1767).
+-define(wxListItemAttr_destroy, 1768).
+-define(wxImageList_new_0, 1769).
+-define(wxImageList_new_3, 1770).
+-define(wxImageList_Add_1, 1771).
+-define(wxImageList_Add_2_0, 1772).
+-define(wxImageList_Add_2_1, 1773).
+-define(wxImageList_Create, 1774).
+-define(wxImageList_Draw, 1776).
+-define(wxImageList_GetBitmap, 1777).
+-define(wxImageList_GetIcon, 1778).
+-define(wxImageList_GetImageCount, 1779).
+-define(wxImageList_GetSize, 1780).
+-define(wxImageList_Remove, 1781).
+-define(wxImageList_RemoveAll, 1782).
+-define(wxImageList_Replace_2, 1783).
+-define(wxImageList_Replace_3, 1784).
+-define(wxImageList_destroy, 1785).
+-define(wxTextAttr_new_0, 1786).
+-define(wxTextAttr_new_2, 1787).
+-define(wxTextAttr_GetAlignment, 1788).
+-define(wxTextAttr_GetBackgroundColour, 1789).
+-define(wxTextAttr_GetFont, 1790).
+-define(wxTextAttr_GetLeftIndent, 1791).
+-define(wxTextAttr_GetLeftSubIndent, 1792).
+-define(wxTextAttr_GetRightIndent, 1793).
+-define(wxTextAttr_GetTabs, 1794).
+-define(wxTextAttr_GetTextColour, 1795).
+-define(wxTextAttr_HasBackgroundColour, 1796).
+-define(wxTextAttr_HasFont, 1797).
+-define(wxTextAttr_HasTextColour, 1798).
+-define(wxTextAttr_GetFlags, 1799).
+-define(wxTextAttr_IsDefault, 1800).
+-define(wxTextAttr_SetAlignment, 1801).
+-define(wxTextAttr_SetBackgroundColour, 1802).
+-define(wxTextAttr_SetFlags, 1803).
+-define(wxTextAttr_SetFont, 1804).
+-define(wxTextAttr_SetLeftIndent, 1805).
+-define(wxTextAttr_SetRightIndent, 1806).
+-define(wxTextAttr_SetTabs, 1807).
+-define(wxTextAttr_SetTextColour, 1808).
+-define(wxTextAttr_destroy, 1809).
+-define(wxTextCtrl_new_3, 1811).
+-define(wxTextCtrl_new_0, 1812).
+-define(wxTextCtrl_destruct, 1814).
+-define(wxTextCtrl_AppendText, 1815).
+-define(wxTextCtrl_CanCopy, 1816).
+-define(wxTextCtrl_CanCut, 1817).
+-define(wxTextCtrl_CanPaste, 1818).
+-define(wxTextCtrl_CanRedo, 1819).
+-define(wxTextCtrl_CanUndo, 1820).
+-define(wxTextCtrl_Clear, 1821).
+-define(wxTextCtrl_Copy, 1822).
+-define(wxTextCtrl_Create, 1823).
+-define(wxTextCtrl_Cut, 1824).
+-define(wxTextCtrl_DiscardEdits, 1825).
+-define(wxTextCtrl_EmulateKeyPress, 1826).
+-define(wxTextCtrl_GetDefaultStyle, 1827).
+-define(wxTextCtrl_GetInsertionPoint, 1828).
+-define(wxTextCtrl_GetLastPosition, 1829).
+-define(wxTextCtrl_GetLineLength, 1830).
+-define(wxTextCtrl_GetLineText, 1831).
+-define(wxTextCtrl_GetNumberOfLines, 1832).
+-define(wxTextCtrl_GetRange, 1833).
+-define(wxTextCtrl_GetSelection, 1834).
+-define(wxTextCtrl_GetStringSelection, 1835).
+-define(wxTextCtrl_GetStyle, 1836).
+-define(wxTextCtrl_GetValue, 1837).
+-define(wxTextCtrl_IsEditable, 1838).
+-define(wxTextCtrl_IsModified, 1839).
+-define(wxTextCtrl_IsMultiLine, 1840).
+-define(wxTextCtrl_IsSingleLine, 1841).
+-define(wxTextCtrl_LoadFile, 1842).
+-define(wxTextCtrl_MarkDirty, 1843).
+-define(wxTextCtrl_Paste, 1844).
+-define(wxTextCtrl_PositionToXY, 1845).
+-define(wxTextCtrl_Redo, 1846).
+-define(wxTextCtrl_Remove, 1847).
+-define(wxTextCtrl_Replace, 1848).
+-define(wxTextCtrl_SaveFile, 1849).
+-define(wxTextCtrl_SetDefaultStyle, 1850).
+-define(wxTextCtrl_SetEditable, 1851).
+-define(wxTextCtrl_SetInsertionPoint, 1852).
+-define(wxTextCtrl_SetInsertionPointEnd, 1853).
+-define(wxTextCtrl_SetMaxLength, 1855).
+-define(wxTextCtrl_SetSelection, 1856).
+-define(wxTextCtrl_SetStyle, 1857).
+-define(wxTextCtrl_SetValue, 1858).
+-define(wxTextCtrl_ShowPosition, 1859).
+-define(wxTextCtrl_Undo, 1860).
+-define(wxTextCtrl_WriteText, 1861).
+-define(wxTextCtrl_XYToPosition, 1862).
+-define(wxNotebook_new_0, 1865).
+-define(wxNotebook_new_3, 1866).
+-define(wxNotebook_destruct, 1867).
+-define(wxNotebook_AddPage, 1868).
+-define(wxNotebook_AdvanceSelection, 1869).
+-define(wxNotebook_AssignImageList, 1870).
+-define(wxNotebook_Create, 1871).
+-define(wxNotebook_DeleteAllPages, 1872).
+-define(wxNotebook_DeletePage, 1873).
+-define(wxNotebook_RemovePage, 1874).
+-define(wxNotebook_GetCurrentPage, 1875).
+-define(wxNotebook_GetImageList, 1876).
+-define(wxNotebook_GetPage, 1878).
+-define(wxNotebook_GetPageCount, 1879).
+-define(wxNotebook_GetPageImage, 1880).
+-define(wxNotebook_GetPageText, 1881).
+-define(wxNotebook_GetRowCount, 1882).
+-define(wxNotebook_GetSelection, 1883).
+-define(wxNotebook_GetThemeBackgroundColour, 1884).
+-define(wxNotebook_HitTest, 1886).
+-define(wxNotebook_InsertPage, 1888).
+-define(wxNotebook_SetImageList, 1889).
+-define(wxNotebook_SetPadding, 1890).
+-define(wxNotebook_SetPageSize, 1891).
+-define(wxNotebook_SetPageImage, 1892).
+-define(wxNotebook_SetPageText, 1893).
+-define(wxNotebook_SetSelection, 1894).
+-define(wxNotebook_ChangeSelection, 1895).
+-define(wxChoicebook_new_0, 1896).
+-define(wxChoicebook_new_3, 1897).
+-define(wxChoicebook_AddPage, 1898).
+-define(wxChoicebook_AdvanceSelection, 1899).
+-define(wxChoicebook_AssignImageList, 1900).
+-define(wxChoicebook_Create, 1901).
+-define(wxChoicebook_DeleteAllPages, 1902).
+-define(wxChoicebook_DeletePage, 1903).
+-define(wxChoicebook_RemovePage, 1904).
+-define(wxChoicebook_GetCurrentPage, 1905).
+-define(wxChoicebook_GetImageList, 1906).
+-define(wxChoicebook_GetPage, 1908).
+-define(wxChoicebook_GetPageCount, 1909).
+-define(wxChoicebook_GetPageImage, 1910).
+-define(wxChoicebook_GetPageText, 1911).
+-define(wxChoicebook_GetSelection, 1912).
+-define(wxChoicebook_HitTest, 1913).
+-define(wxChoicebook_InsertPage, 1914).
+-define(wxChoicebook_SetImageList, 1915).
+-define(wxChoicebook_SetPageSize, 1916).
+-define(wxChoicebook_SetPageImage, 1917).
+-define(wxChoicebook_SetPageText, 1918).
+-define(wxChoicebook_SetSelection, 1919).
+-define(wxChoicebook_ChangeSelection, 1920).
+-define(wxChoicebook_destroy, 1921).
+-define(wxToolbook_new_0, 1922).
+-define(wxToolbook_new_3, 1923).
+-define(wxToolbook_AddPage, 1924).
+-define(wxToolbook_AdvanceSelection, 1925).
+-define(wxToolbook_AssignImageList, 1926).
+-define(wxToolbook_Create, 1927).
+-define(wxToolbook_DeleteAllPages, 1928).
+-define(wxToolbook_DeletePage, 1929).
+-define(wxToolbook_RemovePage, 1930).
+-define(wxToolbook_GetCurrentPage, 1931).
+-define(wxToolbook_GetImageList, 1932).
+-define(wxToolbook_GetPage, 1934).
+-define(wxToolbook_GetPageCount, 1935).
+-define(wxToolbook_GetPageImage, 1936).
+-define(wxToolbook_GetPageText, 1937).
+-define(wxToolbook_GetSelection, 1938).
+-define(wxToolbook_HitTest, 1940).
+-define(wxToolbook_InsertPage, 1941).
+-define(wxToolbook_SetImageList, 1942).
+-define(wxToolbook_SetPageSize, 1943).
+-define(wxToolbook_SetPageImage, 1944).
+-define(wxToolbook_SetPageText, 1945).
+-define(wxToolbook_SetSelection, 1946).
+-define(wxToolbook_ChangeSelection, 1947).
+-define(wxToolbook_destroy, 1948).
+-define(wxListbook_new_0, 1949).
+-define(wxListbook_new_3, 1950).
+-define(wxListbook_AddPage, 1951).
+-define(wxListbook_AdvanceSelection, 1952).
+-define(wxListbook_AssignImageList, 1953).
+-define(wxListbook_Create, 1954).
+-define(wxListbook_DeleteAllPages, 1955).
+-define(wxListbook_DeletePage, 1956).
+-define(wxListbook_RemovePage, 1957).
+-define(wxListbook_GetCurrentPage, 1958).
+-define(wxListbook_GetImageList, 1959).
+-define(wxListbook_GetPage, 1961).
+-define(wxListbook_GetPageCount, 1962).
+-define(wxListbook_GetPageImage, 1963).
+-define(wxListbook_GetPageText, 1964).
+-define(wxListbook_GetSelection, 1965).
+-define(wxListbook_HitTest, 1967).
+-define(wxListbook_InsertPage, 1968).
+-define(wxListbook_SetImageList, 1969).
+-define(wxListbook_SetPageSize, 1970).
+-define(wxListbook_SetPageImage, 1971).
+-define(wxListbook_SetPageText, 1972).
+-define(wxListbook_SetSelection, 1973).
+-define(wxListbook_ChangeSelection, 1974).
+-define(wxListbook_destroy, 1975).
+-define(wxTreebook_new_0, 1976).
+-define(wxTreebook_new_3, 1977).
+-define(wxTreebook_AddPage, 1978).
+-define(wxTreebook_AdvanceSelection, 1979).
+-define(wxTreebook_AssignImageList, 1980).
+-define(wxTreebook_Create, 1981).
+-define(wxTreebook_DeleteAllPages, 1982).
+-define(wxTreebook_DeletePage, 1983).
+-define(wxTreebook_RemovePage, 1984).
+-define(wxTreebook_GetCurrentPage, 1985).
+-define(wxTreebook_GetImageList, 1986).
+-define(wxTreebook_GetPage, 1988).
+-define(wxTreebook_GetPageCount, 1989).
+-define(wxTreebook_GetPageImage, 1990).
+-define(wxTreebook_GetPageText, 1991).
+-define(wxTreebook_GetSelection, 1992).
+-define(wxTreebook_ExpandNode, 1993).
+-define(wxTreebook_IsNodeExpanded, 1994).
+-define(wxTreebook_HitTest, 1996).
+-define(wxTreebook_InsertPage, 1997).
+-define(wxTreebook_InsertSubPage, 1998).
+-define(wxTreebook_SetImageList, 1999).
+-define(wxTreebook_SetPageSize, 2000).
+-define(wxTreebook_SetPageImage, 2001).
+-define(wxTreebook_SetPageText, 2002).
+-define(wxTreebook_SetSelection, 2003).
+-define(wxTreebook_ChangeSelection, 2004).
+-define(wxTreebook_destroy, 2005).
+-define(wxTreeCtrl_new_2, 2008).
+-define(wxTreeCtrl_new_0, 2009).
+-define(wxTreeCtrl_destruct, 2011).
+-define(wxTreeCtrl_AddRoot, 2012).
+-define(wxTreeCtrl_AppendItem, 2013).
+-define(wxTreeCtrl_AssignImageList, 2014).
+-define(wxTreeCtrl_AssignStateImageList, 2015).
+-define(wxTreeCtrl_Collapse, 2016).
+-define(wxTreeCtrl_CollapseAndReset, 2017).
+-define(wxTreeCtrl_Create, 2018).
+-define(wxTreeCtrl_Delete, 2019).
+-define(wxTreeCtrl_DeleteAllItems, 2020).
+-define(wxTreeCtrl_DeleteChildren, 2021).
+-define(wxTreeCtrl_EditLabel, 2022).
+-define(wxTreeCtrl_EnsureVisible, 2023).
+-define(wxTreeCtrl_Expand, 2024).
+-define(wxTreeCtrl_GetBoundingRect, 2025).
+-define(wxTreeCtrl_GetChildrenCount, 2027).
+-define(wxTreeCtrl_GetCount, 2028).
+-define(wxTreeCtrl_GetEditControl, 2029).
+-define(wxTreeCtrl_GetFirstChild, 2030).
+-define(wxTreeCtrl_GetNextChild, 2031).
+-define(wxTreeCtrl_GetFirstVisibleItem, 2032).
+-define(wxTreeCtrl_GetImageList, 2033).
+-define(wxTreeCtrl_GetIndent, 2034).
+-define(wxTreeCtrl_GetItemBackgroundColour, 2035).
+-define(wxTreeCtrl_GetItemData, 2036).
+-define(wxTreeCtrl_GetItemFont, 2037).
+-define(wxTreeCtrl_GetItemImage_1, 2038).
+-define(wxTreeCtrl_GetItemImage_2, 2039).
+-define(wxTreeCtrl_GetItemText, 2040).
+-define(wxTreeCtrl_GetItemTextColour, 2041).
+-define(wxTreeCtrl_GetLastChild, 2042).
+-define(wxTreeCtrl_GetNextSibling, 2043).
+-define(wxTreeCtrl_GetNextVisible, 2044).
+-define(wxTreeCtrl_GetItemParent, 2045).
+-define(wxTreeCtrl_GetPrevSibling, 2046).
+-define(wxTreeCtrl_GetPrevVisible, 2047).
+-define(wxTreeCtrl_GetRootItem, 2048).
+-define(wxTreeCtrl_GetSelection, 2049).
+-define(wxTreeCtrl_GetSelections, 2050).
+-define(wxTreeCtrl_GetStateImageList, 2051).
+-define(wxTreeCtrl_HitTest, 2052).
+-define(wxTreeCtrl_InsertItem, 2054).
+-define(wxTreeCtrl_IsBold, 2055).
+-define(wxTreeCtrl_IsExpanded, 2056).
+-define(wxTreeCtrl_IsSelected, 2057).
+-define(wxTreeCtrl_IsVisible, 2058).
+-define(wxTreeCtrl_ItemHasChildren, 2059).
+-define(wxTreeCtrl_PrependItem, 2060).
+-define(wxTreeCtrl_ScrollTo, 2061).
+-define(wxTreeCtrl_SelectItem_1, 2062).
+-define(wxTreeCtrl_SelectItem_2, 2063).
+-define(wxTreeCtrl_SetIndent, 2064).
+-define(wxTreeCtrl_SetImageList, 2065).
+-define(wxTreeCtrl_SetItemBackgroundColour, 2066).
+-define(wxTreeCtrl_SetItemBold, 2067).
+-define(wxTreeCtrl_SetItemData, 2068).
+-define(wxTreeCtrl_SetItemDropHighlight, 2069).
+-define(wxTreeCtrl_SetItemFont, 2070).
+-define(wxTreeCtrl_SetItemHasChildren, 2071).
+-define(wxTreeCtrl_SetItemImage_2, 2072).
+-define(wxTreeCtrl_SetItemImage_3, 2073).
+-define(wxTreeCtrl_SetItemText, 2074).
+-define(wxTreeCtrl_SetItemTextColour, 2075).
+-define(wxTreeCtrl_SetStateImageList, 2076).
+-define(wxTreeCtrl_SetWindowStyle, 2077).
+-define(wxTreeCtrl_SortChildren, 2078).
+-define(wxTreeCtrl_Toggle, 2079).
+-define(wxTreeCtrl_ToggleItemSelection, 2080).
+-define(wxTreeCtrl_Unselect, 2081).
+-define(wxTreeCtrl_UnselectAll, 2082).
+-define(wxTreeCtrl_UnselectItem, 2083).
+-define(wxScrollBar_new_0, 2084).
+-define(wxScrollBar_new_3, 2085).
+-define(wxScrollBar_destruct, 2086).
+-define(wxScrollBar_Create, 2087).
+-define(wxScrollBar_GetRange, 2088).
+-define(wxScrollBar_GetPageSize, 2089).
+-define(wxScrollBar_GetThumbPosition, 2090).
+-define(wxScrollBar_GetThumbSize, 2091).
+-define(wxScrollBar_SetThumbPosition, 2092).
+-define(wxScrollBar_SetScrollbar, 2093).
+-define(wxSpinButton_new_2, 2095).
+-define(wxSpinButton_new_0, 2096).
+-define(wxSpinButton_Create, 2097).
+-define(wxSpinButton_GetMax, 2098).
+-define(wxSpinButton_GetMin, 2099).
+-define(wxSpinButton_GetValue, 2100).
+-define(wxSpinButton_SetRange, 2101).
+-define(wxSpinButton_SetValue, 2102).
+-define(wxSpinButton_destroy, 2103).
+-define(wxSpinCtrl_new_0, 2104).
+-define(wxSpinCtrl_new_2, 2105).
+-define(wxSpinCtrl_Create, 2107).
+-define(wxSpinCtrl_SetValue_1_1, 2110).
+-define(wxSpinCtrl_SetValue_1_0, 2111).
+-define(wxSpinCtrl_GetValue, 2113).
+-define(wxSpinCtrl_SetRange, 2115).
+-define(wxSpinCtrl_SetSelection, 2116).
+-define(wxSpinCtrl_GetMin, 2118).
+-define(wxSpinCtrl_GetMax, 2120).
+-define(wxSpinCtrl_destroy, 2121).
+-define(wxStaticText_new_0, 2122).
+-define(wxStaticText_new_4, 2123).
+-define(wxStaticText_Create, 2124).
+-define(wxStaticText_GetLabel, 2125).
+-define(wxStaticText_SetLabel, 2126).
+-define(wxStaticText_Wrap, 2127).
+-define(wxStaticText_destroy, 2128).
+-define(wxStaticBitmap_new_0, 2129).
+-define(wxStaticBitmap_new_4, 2130).
+-define(wxStaticBitmap_Create, 2131).
+-define(wxStaticBitmap_GetBitmap, 2132).
+-define(wxStaticBitmap_SetBitmap, 2133).
+-define(wxStaticBitmap_destroy, 2134).
+-define(wxRadioBox_new, 2135).
+-define(wxRadioBox_destruct, 2137).
+-define(wxRadioBox_Create, 2138).
+-define(wxRadioBox_Enable_2, 2139).
+-define(wxRadioBox_Enable_1, 2140).
+-define(wxRadioBox_GetSelection, 2141).
+-define(wxRadioBox_GetString, 2142).
+-define(wxRadioBox_SetSelection, 2143).
+-define(wxRadioBox_Show_2, 2144).
+-define(wxRadioBox_Show_1, 2145).
+-define(wxRadioBox_GetColumnCount, 2146).
+-define(wxRadioBox_GetItemHelpText, 2147).
+-define(wxRadioBox_GetItemToolTip, 2148).
+-define(wxRadioBox_GetItemFromPoint, 2150).
+-define(wxRadioBox_GetRowCount, 2151).
+-define(wxRadioBox_IsItemEnabled, 2152).
+-define(wxRadioBox_IsItemShown, 2153).
+-define(wxRadioBox_SetItemHelpText, 2154).
+-define(wxRadioBox_SetItemToolTip, 2155).
+-define(wxRadioButton_new_0, 2156).
+-define(wxRadioButton_new_4, 2157).
+-define(wxRadioButton_Create, 2158).
+-define(wxRadioButton_GetValue, 2159).
+-define(wxRadioButton_SetValue, 2160).
+-define(wxRadioButton_destroy, 2161).
+-define(wxSlider_new_6, 2163).
+-define(wxSlider_new_0, 2164).
+-define(wxSlider_Create, 2165).
+-define(wxSlider_GetLineSize, 2166).
+-define(wxSlider_GetMax, 2167).
+-define(wxSlider_GetMin, 2168).
+-define(wxSlider_GetPageSize, 2169).
+-define(wxSlider_GetThumbLength, 2170).
+-define(wxSlider_GetValue, 2171).
+-define(wxSlider_SetLineSize, 2172).
+-define(wxSlider_SetPageSize, 2173).
+-define(wxSlider_SetRange, 2174).
+-define(wxSlider_SetThumbLength, 2175).
+-define(wxSlider_SetValue, 2176).
+-define(wxSlider_destroy, 2177).
+-define(wxDialog_new_4, 2179).
+-define(wxDialog_new_0, 2180).
+-define(wxDialog_destruct, 2182).
+-define(wxDialog_Create, 2183).
+-define(wxDialog_CreateButtonSizer, 2184).
+-define(wxDialog_CreateStdDialogButtonSizer, 2185).
+-define(wxDialog_EndModal, 2186).
+-define(wxDialog_GetAffirmativeId, 2187).
+-define(wxDialog_GetReturnCode, 2188).
+-define(wxDialog_IsModal, 2189).
+-define(wxDialog_SetAffirmativeId, 2190).
+-define(wxDialog_SetReturnCode, 2191).
+-define(wxDialog_Show, 2192).
+-define(wxDialog_ShowModal, 2193).
+-define(wxColourDialog_new_0, 2194).
+-define(wxColourDialog_new_2, 2195).
+-define(wxColourDialog_destruct, 2196).
+-define(wxColourDialog_Create, 2197).
+-define(wxColourDialog_GetColourData, 2198).
+-define(wxColourData_new_0, 2199).
+-define(wxColourData_new_1, 2200).
+-define(wxColourData_destruct, 2201).
+-define(wxColourData_GetChooseFull, 2202).
+-define(wxColourData_GetColour, 2203).
+-define(wxColourData_GetCustomColour, 2205).
+-define(wxColourData_SetChooseFull, 2206).
+-define(wxColourData_SetColour, 2207).
+-define(wxColourData_SetCustomColour, 2208).
+-define(wxPalette_new_0, 2209).
+-define(wxPalette_new_4, 2210).
+-define(wxPalette_destruct, 2212).
+-define(wxPalette_Create, 2213).
+-define(wxPalette_GetColoursCount, 2214).
+-define(wxPalette_GetPixel, 2215).
+-define(wxPalette_GetRGB, 2216).
+-define(wxPalette_IsOk, 2217).
+-define(wxDirDialog_new, 2221).
+-define(wxDirDialog_destruct, 2222).
+-define(wxDirDialog_GetPath, 2223).
+-define(wxDirDialog_GetMessage, 2224).
+-define(wxDirDialog_SetMessage, 2225).
+-define(wxDirDialog_SetPath, 2226).
+-define(wxFileDialog_new, 2230).
+-define(wxFileDialog_destruct, 2231).
+-define(wxFileDialog_GetDirectory, 2232).
+-define(wxFileDialog_GetFilename, 2233).
+-define(wxFileDialog_GetFilenames, 2234).
+-define(wxFileDialog_GetFilterIndex, 2235).
+-define(wxFileDialog_GetMessage, 2236).
+-define(wxFileDialog_GetPath, 2237).
+-define(wxFileDialog_GetPaths, 2238).
+-define(wxFileDialog_GetWildcard, 2239).
+-define(wxFileDialog_SetDirectory, 2240).
+-define(wxFileDialog_SetFilename, 2241).
+-define(wxFileDialog_SetFilterIndex, 2242).
+-define(wxFileDialog_SetMessage, 2243).
+-define(wxFileDialog_SetPath, 2244).
+-define(wxFileDialog_SetWildcard, 2245).
+-define(wxPickerBase_SetInternalMargin, 2246).
+-define(wxPickerBase_GetInternalMargin, 2247).
+-define(wxPickerBase_SetTextCtrlProportion, 2248).
+-define(wxPickerBase_SetPickerCtrlProportion, 2249).
+-define(wxPickerBase_GetTextCtrlProportion, 2250).
+-define(wxPickerBase_GetPickerCtrlProportion, 2251).
+-define(wxPickerBase_HasTextCtrl, 2252).
+-define(wxPickerBase_GetTextCtrl, 2253).
+-define(wxPickerBase_IsTextCtrlGrowable, 2254).
+-define(wxPickerBase_SetPickerCtrlGrowable, 2255).
+-define(wxPickerBase_SetTextCtrlGrowable, 2256).
+-define(wxPickerBase_IsPickerCtrlGrowable, 2257).
+-define(wxFilePickerCtrl_new_0, 2258).
+-define(wxFilePickerCtrl_new_3, 2259).
+-define(wxFilePickerCtrl_Create, 2260).
+-define(wxFilePickerCtrl_GetPath, 2261).
+-define(wxFilePickerCtrl_SetPath, 2262).
+-define(wxFilePickerCtrl_destroy, 2263).
+-define(wxDirPickerCtrl_new_0, 2264).
+-define(wxDirPickerCtrl_new_3, 2265).
+-define(wxDirPickerCtrl_Create, 2266).
+-define(wxDirPickerCtrl_GetPath, 2267).
+-define(wxDirPickerCtrl_SetPath, 2268).
+-define(wxDirPickerCtrl_destroy, 2269).
+-define(wxColourPickerCtrl_new_0, 2270).
+-define(wxColourPickerCtrl_new_3, 2271).
+-define(wxColourPickerCtrl_Create, 2272).
+-define(wxColourPickerCtrl_GetColour, 2273).
+-define(wxColourPickerCtrl_SetColour_1_1, 2274).
+-define(wxColourPickerCtrl_SetColour_1_0, 2275).
+-define(wxColourPickerCtrl_destroy, 2276).
+-define(wxDatePickerCtrl_new_0, 2277).
+-define(wxDatePickerCtrl_new_3, 2278).
+-define(wxDatePickerCtrl_GetRange, 2279).
+-define(wxDatePickerCtrl_GetValue, 2280).
+-define(wxDatePickerCtrl_SetRange, 2281).
+-define(wxDatePickerCtrl_SetValue, 2282).
+-define(wxDatePickerCtrl_destroy, 2283).
+-define(wxFontPickerCtrl_new_0, 2284).
+-define(wxFontPickerCtrl_new_3, 2285).
+-define(wxFontPickerCtrl_Create, 2286).
+-define(wxFontPickerCtrl_GetSelectedFont, 2287).
+-define(wxFontPickerCtrl_SetSelectedFont, 2288).
+-define(wxFontPickerCtrl_GetMaxPointSize, 2289).
+-define(wxFontPickerCtrl_SetMaxPointSize, 2290).
+-define(wxFontPickerCtrl_destroy, 2291).
+-define(wxFindReplaceDialog_new_0, 2294).
+-define(wxFindReplaceDialog_new_4, 2295).
+-define(wxFindReplaceDialog_destruct, 2296).
+-define(wxFindReplaceDialog_Create, 2297).
+-define(wxFindReplaceDialog_GetData, 2298).
+-define(wxFindReplaceData_new_0, 2299).
+-define(wxFindReplaceData_new_1, 2300).
+-define(wxFindReplaceData_GetFindString, 2301).
+-define(wxFindReplaceData_GetReplaceString, 2302).
+-define(wxFindReplaceData_GetFlags, 2303).
+-define(wxFindReplaceData_SetFlags, 2304).
+-define(wxFindReplaceData_SetFindString, 2305).
+-define(wxFindReplaceData_SetReplaceString, 2306).
+-define(wxFindReplaceData_destroy, 2307).
+-define(wxMultiChoiceDialog_new_0, 2308).
+-define(wxMultiChoiceDialog_new_5, 2310).
+-define(wxMultiChoiceDialog_GetSelections, 2311).
+-define(wxMultiChoiceDialog_SetSelections, 2312).
+-define(wxMultiChoiceDialog_destroy, 2313).
+-define(wxSingleChoiceDialog_new_0, 2314).
+-define(wxSingleChoiceDialog_new_5, 2316).
+-define(wxSingleChoiceDialog_GetSelection, 2317).
+-define(wxSingleChoiceDialog_GetStringSelection, 2318).
+-define(wxSingleChoiceDialog_SetSelection, 2319).
+-define(wxSingleChoiceDialog_destroy, 2320).
+-define(wxTextEntryDialog_new, 2321).
+-define(wxTextEntryDialog_GetValue, 2322).
+-define(wxTextEntryDialog_SetValue, 2323).
+-define(wxTextEntryDialog_destroy, 2324).
+-define(wxPasswordEntryDialog_new, 2325).
+-define(wxPasswordEntryDialog_destroy, 2326).
+-define(wxFontData_new_0, 2327).
+-define(wxFontData_new_1, 2328).
+-define(wxFontData_destruct, 2329).
+-define(wxFontData_EnableEffects, 2330).
+-define(wxFontData_GetAllowSymbols, 2331).
+-define(wxFontData_GetColour, 2332).
+-define(wxFontData_GetChosenFont, 2333).
+-define(wxFontData_GetEnableEffects, 2334).
+-define(wxFontData_GetInitialFont, 2335).
+-define(wxFontData_GetShowHelp, 2336).
+-define(wxFontData_SetAllowSymbols, 2337).
+-define(wxFontData_SetChosenFont, 2338).
+-define(wxFontData_SetColour, 2339).
+-define(wxFontData_SetInitialFont, 2340).
+-define(wxFontData_SetRange, 2341).
+-define(wxFontData_SetShowHelp, 2342).
+-define(wxFontDialog_new_0, 2346).
+-define(wxFontDialog_new_2, 2348).
+-define(wxFontDialog_Create, 2350).
+-define(wxFontDialog_GetFontData, 2351).
+-define(wxFontDialog_destroy, 2353).
+-define(wxProgressDialog_new, 2354).
+-define(wxProgressDialog_destruct, 2355).
+-define(wxProgressDialog_Resume, 2356).
+-define(wxProgressDialog_Update_2, 2357).
+-define(wxProgressDialog_Update_0, 2358).
+-define(wxMessageDialog_new, 2359).
+-define(wxMessageDialog_destruct, 2360).
+-define(wxPageSetupDialog_new, 2361).
+-define(wxPageSetupDialog_destruct, 2362).
+-define(wxPageSetupDialog_GetPageSetupData, 2363).
+-define(wxPageSetupDialog_ShowModal, 2364).
+-define(wxPageSetupDialogData_new_0, 2365).
+-define(wxPageSetupDialogData_new_1_0, 2366).
+-define(wxPageSetupDialogData_new_1_1, 2367).
+-define(wxPageSetupDialogData_destruct, 2368).
+-define(wxPageSetupDialogData_EnableHelp, 2369).
+-define(wxPageSetupDialogData_EnableMargins, 2370).
+-define(wxPageSetupDialogData_EnableOrientation, 2371).
+-define(wxPageSetupDialogData_EnablePaper, 2372).
+-define(wxPageSetupDialogData_EnablePrinter, 2373).
+-define(wxPageSetupDialogData_GetDefaultMinMargins, 2374).
+-define(wxPageSetupDialogData_GetEnableMargins, 2375).
+-define(wxPageSetupDialogData_GetEnableOrientation, 2376).
+-define(wxPageSetupDialogData_GetEnablePaper, 2377).
+-define(wxPageSetupDialogData_GetEnablePrinter, 2378).
+-define(wxPageSetupDialogData_GetEnableHelp, 2379).
+-define(wxPageSetupDialogData_GetDefaultInfo, 2380).
+-define(wxPageSetupDialogData_GetMarginTopLeft, 2381).
+-define(wxPageSetupDialogData_GetMarginBottomRight, 2382).
+-define(wxPageSetupDialogData_GetMinMarginTopLeft, 2383).
+-define(wxPageSetupDialogData_GetMinMarginBottomRight, 2384).
+-define(wxPageSetupDialogData_GetPaperId, 2385).
+-define(wxPageSetupDialogData_GetPaperSize, 2386).
+-define(wxPageSetupDialogData_GetPrintData, 2388).
+-define(wxPageSetupDialogData_IsOk, 2389).
+-define(wxPageSetupDialogData_SetDefaultInfo, 2390).
+-define(wxPageSetupDialogData_SetDefaultMinMargins, 2391).
+-define(wxPageSetupDialogData_SetMarginTopLeft, 2392).
+-define(wxPageSetupDialogData_SetMarginBottomRight, 2393).
+-define(wxPageSetupDialogData_SetMinMarginTopLeft, 2394).
+-define(wxPageSetupDialogData_SetMinMarginBottomRight, 2395).
+-define(wxPageSetupDialogData_SetPaperId, 2396).
+-define(wxPageSetupDialogData_SetPaperSize_1_1, 2397).
+-define(wxPageSetupDialogData_SetPaperSize_1_0, 2398).
+-define(wxPageSetupDialogData_SetPrintData, 2399).
+-define(wxPrintDialog_new_2_0, 2400).
+-define(wxPrintDialog_new_2_1, 2401).
+-define(wxPrintDialog_destruct, 2402).
+-define(wxPrintDialog_GetPrintDialogData, 2403).
+-define(wxPrintDialog_GetPrintDC, 2404).
+-define(wxPrintDialogData_new_0, 2405).
+-define(wxPrintDialogData_new_1_1, 2406).
+-define(wxPrintDialogData_new_1_0, 2407).
+-define(wxPrintDialogData_destruct, 2408).
+-define(wxPrintDialogData_EnableHelp, 2409).
+-define(wxPrintDialogData_EnablePageNumbers, 2410).
+-define(wxPrintDialogData_EnablePrintToFile, 2411).
+-define(wxPrintDialogData_EnableSelection, 2412).
+-define(wxPrintDialogData_GetAllPages, 2413).
+-define(wxPrintDialogData_GetCollate, 2414).
+-define(wxPrintDialogData_GetFromPage, 2415).
+-define(wxPrintDialogData_GetMaxPage, 2416).
+-define(wxPrintDialogData_GetMinPage, 2417).
+-define(wxPrintDialogData_GetNoCopies, 2418).
+-define(wxPrintDialogData_GetPrintData, 2419).
+-define(wxPrintDialogData_GetPrintToFile, 2420).
+-define(wxPrintDialogData_GetSelection, 2421).
+-define(wxPrintDialogData_GetToPage, 2422).
+-define(wxPrintDialogData_IsOk, 2423).
+-define(wxPrintDialogData_SetCollate, 2424).
+-define(wxPrintDialogData_SetFromPage, 2425).
+-define(wxPrintDialogData_SetMaxPage, 2426).
+-define(wxPrintDialogData_SetMinPage, 2427).
+-define(wxPrintDialogData_SetNoCopies, 2428).
+-define(wxPrintDialogData_SetPrintData, 2429).
+-define(wxPrintDialogData_SetPrintToFile, 2430).
+-define(wxPrintDialogData_SetSelection, 2431).
+-define(wxPrintDialogData_SetToPage, 2432).
+-define(wxPrintData_new_0, 2433).
+-define(wxPrintData_new_1, 2434).
+-define(wxPrintData_destruct, 2435).
+-define(wxPrintData_GetCollate, 2436).
+-define(wxPrintData_GetBin, 2437).
+-define(wxPrintData_GetColour, 2438).
+-define(wxPrintData_GetDuplex, 2439).
+-define(wxPrintData_GetNoCopies, 2440).
+-define(wxPrintData_GetOrientation, 2441).
+-define(wxPrintData_GetPaperId, 2442).
+-define(wxPrintData_GetPrinterName, 2443).
+-define(wxPrintData_GetQuality, 2444).
+-define(wxPrintData_IsOk, 2445).
+-define(wxPrintData_SetBin, 2446).
+-define(wxPrintData_SetCollate, 2447).
+-define(wxPrintData_SetColour, 2448).
+-define(wxPrintData_SetDuplex, 2449).
+-define(wxPrintData_SetNoCopies, 2450).
+-define(wxPrintData_SetOrientation, 2451).
+-define(wxPrintData_SetPaperId, 2452).
+-define(wxPrintData_SetPrinterName, 2453).
+-define(wxPrintData_SetQuality, 2454).
+-define(wxPrintPreview_new_2, 2457).
+-define(wxPrintPreview_new_3, 2458).
+-define(wxPrintPreview_destruct, 2460).
+-define(wxPrintPreview_GetCanvas, 2461).
+-define(wxPrintPreview_GetCurrentPage, 2462).
+-define(wxPrintPreview_GetFrame, 2463).
+-define(wxPrintPreview_GetMaxPage, 2464).
+-define(wxPrintPreview_GetMinPage, 2465).
+-define(wxPrintPreview_GetPrintout, 2466).
+-define(wxPrintPreview_GetPrintoutForPrinting, 2467).
+-define(wxPrintPreview_IsOk, 2468).
+-define(wxPrintPreview_PaintPage, 2469).
+-define(wxPrintPreview_Print, 2470).
+-define(wxPrintPreview_RenderPage, 2471).
+-define(wxPrintPreview_SetCanvas, 2472).
+-define(wxPrintPreview_SetCurrentPage, 2473).
+-define(wxPrintPreview_SetFrame, 2474).
+-define(wxPrintPreview_SetPrintout, 2475).
+-define(wxPrintPreview_SetZoom, 2476).
+-define(wxPreviewFrame_new, 2477).
+-define(wxPreviewFrame_destruct, 2478).
+-define(wxPreviewFrame_CreateControlBar, 2479).
+-define(wxPreviewFrame_CreateCanvas, 2480).
+-define(wxPreviewFrame_Initialize, 2481).
+-define(wxPreviewFrame_OnCloseWindow, 2482).
+-define(wxPreviewControlBar_new, 2483).
+-define(wxPreviewControlBar_destruct, 2484).
+-define(wxPreviewControlBar_CreateButtons, 2485).
+-define(wxPreviewControlBar_GetPrintPreview, 2486).
+-define(wxPreviewControlBar_GetZoomControl, 2487).
+-define(wxPreviewControlBar_SetZoomControl, 2488).
+-define(wxPrinter_new, 2490).
+-define(wxPrinter_CreateAbortWindow, 2491).
+-define(wxPrinter_GetAbort, 2492).
+-define(wxPrinter_GetLastError, 2493).
+-define(wxPrinter_GetPrintDialogData, 2494).
+-define(wxPrinter_Print, 2495).
+-define(wxPrinter_PrintDialog, 2496).
+-define(wxPrinter_ReportError, 2497).
+-define(wxPrinter_Setup, 2498).
+-define(wxPrinter_destroy, 2499).
+-define(wxXmlResource_new_1, 2500).
+-define(wxXmlResource_new_2, 2501).
+-define(wxXmlResource_destruct, 2502).
+-define(wxXmlResource_AttachUnknownControl, 2503).
+-define(wxXmlResource_ClearHandlers, 2504).
+-define(wxXmlResource_CompareVersion, 2505).
+-define(wxXmlResource_Get, 2506).
+-define(wxXmlResource_GetFlags, 2507).
+-define(wxXmlResource_GetVersion, 2508).
+-define(wxXmlResource_GetXRCID, 2509).
+-define(wxXmlResource_InitAllHandlers, 2510).
+-define(wxXmlResource_Load, 2511).
+-define(wxXmlResource_LoadBitmap, 2512).
+-define(wxXmlResource_LoadDialog_2, 2513).
+-define(wxXmlResource_LoadDialog_3, 2514).
+-define(wxXmlResource_LoadFrame_2, 2515).
+-define(wxXmlResource_LoadFrame_3, 2516).
+-define(wxXmlResource_LoadIcon, 2517).
+-define(wxXmlResource_LoadMenu, 2518).
+-define(wxXmlResource_LoadMenuBar_2, 2519).
+-define(wxXmlResource_LoadMenuBar_1, 2520).
+-define(wxXmlResource_LoadPanel_2, 2521).
+-define(wxXmlResource_LoadPanel_3, 2522).
+-define(wxXmlResource_LoadToolBar, 2523).
+-define(wxXmlResource_Set, 2524).
+-define(wxXmlResource_SetFlags, 2525).
+-define(wxXmlResource_Unload, 2526).
+-define(wxXmlResource_xrcctrl, 2527).
+-define(wxHtmlEasyPrinting_new, 2528).
+-define(wxHtmlEasyPrinting_destruct, 2529).
+-define(wxHtmlEasyPrinting_GetPrintData, 2530).
+-define(wxHtmlEasyPrinting_GetPageSetupData, 2531).
+-define(wxHtmlEasyPrinting_PreviewFile, 2532).
+-define(wxHtmlEasyPrinting_PreviewText, 2533).
+-define(wxHtmlEasyPrinting_PrintFile, 2534).
+-define(wxHtmlEasyPrinting_PrintText, 2535).
+-define(wxHtmlEasyPrinting_PageSetup, 2536).
+-define(wxHtmlEasyPrinting_SetFonts, 2537).
+-define(wxHtmlEasyPrinting_SetHeader, 2538).
+-define(wxHtmlEasyPrinting_SetFooter, 2539).
+-define(wxGLCanvas_new_2, 2541).
+-define(wxGLCanvas_new_3_1, 2542).
+-define(wxGLCanvas_new_3_0, 2543).
+-define(wxGLCanvas_GetContext, 2544).
+-define(wxGLCanvas_SetCurrent, 2546).
+-define(wxGLCanvas_SwapBuffers, 2547).
+-define(wxGLCanvas_destroy, 2548).
+-define(wxAuiManager_new, 2549).
+-define(wxAuiManager_destruct, 2550).
+-define(wxAuiManager_AddPane_2_1, 2551).
+-define(wxAuiManager_AddPane_3, 2552).
+-define(wxAuiManager_AddPane_2_0, 2553).
+-define(wxAuiManager_DetachPane, 2554).
+-define(wxAuiManager_GetAllPanes, 2555).
+-define(wxAuiManager_GetArtProvider, 2556).
+-define(wxAuiManager_GetDockSizeConstraint, 2557).
+-define(wxAuiManager_GetFlags, 2558).
+-define(wxAuiManager_GetManagedWindow, 2559).
+-define(wxAuiManager_GetManager, 2560).
+-define(wxAuiManager_GetPane_1_1, 2561).
+-define(wxAuiManager_GetPane_1_0, 2562).
+-define(wxAuiManager_HideHint, 2563).
+-define(wxAuiManager_InsertPane, 2564).
+-define(wxAuiManager_LoadPaneInfo, 2565).
+-define(wxAuiManager_LoadPerspective, 2566).
+-define(wxAuiManager_SavePaneInfo, 2567).
+-define(wxAuiManager_SavePerspective, 2568).
+-define(wxAuiManager_SetArtProvider, 2569).
+-define(wxAuiManager_SetDockSizeConstraint, 2570).
+-define(wxAuiManager_SetFlags, 2571).
+-define(wxAuiManager_SetManagedWindow, 2572).
+-define(wxAuiManager_ShowHint, 2573).
+-define(wxAuiManager_UnInit, 2574).
+-define(wxAuiManager_Update, 2575).
+-define(wxAuiPaneInfo_new_0, 2576).
+-define(wxAuiPaneInfo_new_1, 2577).
+-define(wxAuiPaneInfo_destruct, 2578).
+-define(wxAuiPaneInfo_BestSize_1, 2579).
+-define(wxAuiPaneInfo_BestSize_2, 2580).
+-define(wxAuiPaneInfo_Bottom, 2581).
+-define(wxAuiPaneInfo_BottomDockable, 2582).
+-define(wxAuiPaneInfo_Caption, 2583).
+-define(wxAuiPaneInfo_CaptionVisible, 2584).
+-define(wxAuiPaneInfo_Centre, 2585).
+-define(wxAuiPaneInfo_CentrePane, 2586).
+-define(wxAuiPaneInfo_CloseButton, 2587).
+-define(wxAuiPaneInfo_DefaultPane, 2588).
+-define(wxAuiPaneInfo_DestroyOnClose, 2589).
+-define(wxAuiPaneInfo_Direction, 2590).
+-define(wxAuiPaneInfo_Dock, 2591).
+-define(wxAuiPaneInfo_Dockable, 2592).
+-define(wxAuiPaneInfo_Fixed, 2593).
+-define(wxAuiPaneInfo_Float, 2594).
+-define(wxAuiPaneInfo_Floatable, 2595).
+-define(wxAuiPaneInfo_FloatingPosition_1, 2596).
+-define(wxAuiPaneInfo_FloatingPosition_2, 2597).
+-define(wxAuiPaneInfo_FloatingSize_1, 2598).
+-define(wxAuiPaneInfo_FloatingSize_2, 2599).
+-define(wxAuiPaneInfo_Gripper, 2600).
+-define(wxAuiPaneInfo_GripperTop, 2601).
+-define(wxAuiPaneInfo_HasBorder, 2602).
+-define(wxAuiPaneInfo_HasCaption, 2603).
+-define(wxAuiPaneInfo_HasCloseButton, 2604).
+-define(wxAuiPaneInfo_HasFlag, 2605).
+-define(wxAuiPaneInfo_HasGripper, 2606).
+-define(wxAuiPaneInfo_HasGripperTop, 2607).
+-define(wxAuiPaneInfo_HasMaximizeButton, 2608).
+-define(wxAuiPaneInfo_HasMinimizeButton, 2609).
+-define(wxAuiPaneInfo_HasPinButton, 2610).
+-define(wxAuiPaneInfo_Hide, 2611).
+-define(wxAuiPaneInfo_IsBottomDockable, 2612).
+-define(wxAuiPaneInfo_IsDocked, 2613).
+-define(wxAuiPaneInfo_IsFixed, 2614).
+-define(wxAuiPaneInfo_IsFloatable, 2615).
+-define(wxAuiPaneInfo_IsFloating, 2616).
+-define(wxAuiPaneInfo_IsLeftDockable, 2617).
+-define(wxAuiPaneInfo_IsMovable, 2618).
+-define(wxAuiPaneInfo_IsOk, 2619).
+-define(wxAuiPaneInfo_IsResizable, 2620).
+-define(wxAuiPaneInfo_IsRightDockable, 2621).
+-define(wxAuiPaneInfo_IsShown, 2622).
+-define(wxAuiPaneInfo_IsToolbar, 2623).
+-define(wxAuiPaneInfo_IsTopDockable, 2624).
+-define(wxAuiPaneInfo_Layer, 2625).
+-define(wxAuiPaneInfo_Left, 2626).
+-define(wxAuiPaneInfo_LeftDockable, 2627).
+-define(wxAuiPaneInfo_MaxSize_1, 2628).
+-define(wxAuiPaneInfo_MaxSize_2, 2629).
+-define(wxAuiPaneInfo_MaximizeButton, 2630).
+-define(wxAuiPaneInfo_MinSize_1, 2631).
+-define(wxAuiPaneInfo_MinSize_2, 2632).
+-define(wxAuiPaneInfo_MinimizeButton, 2633).
+-define(wxAuiPaneInfo_Movable, 2634).
+-define(wxAuiPaneInfo_Name, 2635).
+-define(wxAuiPaneInfo_PaneBorder, 2636).
+-define(wxAuiPaneInfo_PinButton, 2637).
+-define(wxAuiPaneInfo_Position, 2638).
+-define(wxAuiPaneInfo_Resizable, 2639).
+-define(wxAuiPaneInfo_Right, 2640).
+-define(wxAuiPaneInfo_RightDockable, 2641).
+-define(wxAuiPaneInfo_Row, 2642).
+-define(wxAuiPaneInfo_SafeSet, 2643).
+-define(wxAuiPaneInfo_SetFlag, 2644).
+-define(wxAuiPaneInfo_Show, 2645).
+-define(wxAuiPaneInfo_ToolbarPane, 2646).
+-define(wxAuiPaneInfo_Top, 2647).
+-define(wxAuiPaneInfo_TopDockable, 2648).
+-define(wxAuiPaneInfo_Window, 2649).
+-define(wxAuiNotebook_new_0, 2650).
+-define(wxAuiNotebook_new_2, 2651).
+-define(wxAuiNotebook_AddPage, 2652).
+-define(wxAuiNotebook_Create, 2653).
+-define(wxAuiNotebook_DeletePage, 2654).
+-define(wxAuiNotebook_GetArtProvider, 2655).
+-define(wxAuiNotebook_GetPage, 2656).
+-define(wxAuiNotebook_GetPageBitmap, 2657).
+-define(wxAuiNotebook_GetPageCount, 2658).
+-define(wxAuiNotebook_GetPageIndex, 2659).
+-define(wxAuiNotebook_GetPageText, 2660).
+-define(wxAuiNotebook_GetSelection, 2661).
+-define(wxAuiNotebook_InsertPage, 2662).
+-define(wxAuiNotebook_RemovePage, 2663).
+-define(wxAuiNotebook_SetArtProvider, 2664).
+-define(wxAuiNotebook_SetFont, 2665).
+-define(wxAuiNotebook_SetPageBitmap, 2666).
+-define(wxAuiNotebook_SetPageText, 2667).
+-define(wxAuiNotebook_SetSelection, 2668).
+-define(wxAuiNotebook_SetTabCtrlHeight, 2669).
+-define(wxAuiNotebook_SetUniformBitmapSize, 2670).
+-define(wxAuiNotebook_destroy, 2671).
+-define(wxMDIParentFrame_new_0, 2672).
+-define(wxMDIParentFrame_new_4, 2673).
+-define(wxMDIParentFrame_destruct, 2674).
+-define(wxMDIParentFrame_ActivateNext, 2675).
+-define(wxMDIParentFrame_ActivatePrevious, 2676).
+-define(wxMDIParentFrame_ArrangeIcons, 2677).
+-define(wxMDIParentFrame_Cascade, 2678).
+-define(wxMDIParentFrame_Create, 2679).
+-define(wxMDIParentFrame_GetActiveChild, 2680).
+-define(wxMDIParentFrame_GetClientWindow, 2681).
+-define(wxMDIParentFrame_Tile, 2682).
+-define(wxMDIChildFrame_new_0, 2683).
+-define(wxMDIChildFrame_new_4, 2684).
+-define(wxMDIChildFrame_destruct, 2685).
+-define(wxMDIChildFrame_Activate, 2686).
+-define(wxMDIChildFrame_Create, 2687).
+-define(wxMDIChildFrame_Maximize, 2688).
+-define(wxMDIChildFrame_Restore, 2689).
+-define(wxMDIClientWindow_new_0, 2690).
+-define(wxMDIClientWindow_new_2, 2691).
+-define(wxMDIClientWindow_destruct, 2692).
+-define(wxMDIClientWindow_CreateClient, 2693).
+-define(wxLayoutAlgorithm_new, 2694).
+-define(wxLayoutAlgorithm_LayoutFrame, 2695).
+-define(wxLayoutAlgorithm_LayoutMDIFrame, 2696).
+-define(wxLayoutAlgorithm_LayoutWindow, 2697).
+-define(wxLayoutAlgorithm_destroy, 2698).
+-define(wxEvent_GetId, 2699).
+-define(wxEvent_GetSkipped, 2700).
+-define(wxEvent_GetTimestamp, 2701).
+-define(wxEvent_IsCommandEvent, 2702).
+-define(wxEvent_ResumePropagation, 2703).
+-define(wxEvent_ShouldPropagate, 2704).
+-define(wxEvent_Skip, 2705).
+-define(wxEvent_StopPropagation, 2706).
+-define(wxCommandEvent_getClientData, 2707).
+-define(wxCommandEvent_GetExtraLong, 2708).
+-define(wxCommandEvent_GetInt, 2709).
+-define(wxCommandEvent_GetSelection, 2710).
+-define(wxCommandEvent_GetString, 2711).
+-define(wxCommandEvent_IsChecked, 2712).
+-define(wxCommandEvent_IsSelection, 2713).
+-define(wxCommandEvent_SetInt, 2714).
+-define(wxCommandEvent_SetString, 2715).
+-define(wxScrollEvent_GetOrientation, 2716).
+-define(wxScrollEvent_GetPosition, 2717).
+-define(wxScrollWinEvent_GetOrientation, 2718).
+-define(wxScrollWinEvent_GetPosition, 2719).
+-define(wxMouseEvent_AltDown, 2720).
+-define(wxMouseEvent_Button, 2721).
+-define(wxMouseEvent_ButtonDClick, 2722).
+-define(wxMouseEvent_ButtonDown, 2723).
+-define(wxMouseEvent_ButtonUp, 2724).
+-define(wxMouseEvent_CmdDown, 2725).
+-define(wxMouseEvent_ControlDown, 2726).
+-define(wxMouseEvent_Dragging, 2727).
+-define(wxMouseEvent_Entering, 2728).
+-define(wxMouseEvent_GetButton, 2729).
+-define(wxMouseEvent_GetPosition, 2732).
+-define(wxMouseEvent_GetLogicalPosition, 2733).
+-define(wxMouseEvent_GetLinesPerAction, 2734).
+-define(wxMouseEvent_GetWheelRotation, 2735).
+-define(wxMouseEvent_GetWheelDelta, 2736).
+-define(wxMouseEvent_GetX, 2737).
+-define(wxMouseEvent_GetY, 2738).
+-define(wxMouseEvent_IsButton, 2739).
+-define(wxMouseEvent_IsPageScroll, 2740).
+-define(wxMouseEvent_Leaving, 2741).
+-define(wxMouseEvent_LeftDClick, 2742).
+-define(wxMouseEvent_LeftDown, 2743).
+-define(wxMouseEvent_LeftIsDown, 2744).
+-define(wxMouseEvent_LeftUp, 2745).
+-define(wxMouseEvent_MetaDown, 2746).
+-define(wxMouseEvent_MiddleDClick, 2747).
+-define(wxMouseEvent_MiddleDown, 2748).
+-define(wxMouseEvent_MiddleIsDown, 2749).
+-define(wxMouseEvent_MiddleUp, 2750).
+-define(wxMouseEvent_Moving, 2751).
+-define(wxMouseEvent_RightDClick, 2752).
+-define(wxMouseEvent_RightDown, 2753).
+-define(wxMouseEvent_RightIsDown, 2754).
+-define(wxMouseEvent_RightUp, 2755).
+-define(wxMouseEvent_ShiftDown, 2756).
+-define(wxSetCursorEvent_GetCursor, 2757).
+-define(wxSetCursorEvent_GetX, 2758).
+-define(wxSetCursorEvent_GetY, 2759).
+-define(wxSetCursorEvent_HasCursor, 2760).
+-define(wxSetCursorEvent_SetCursor, 2761).
+-define(wxKeyEvent_AltDown, 2762).
+-define(wxKeyEvent_CmdDown, 2763).
+-define(wxKeyEvent_ControlDown, 2764).
+-define(wxKeyEvent_GetKeyCode, 2765).
+-define(wxKeyEvent_GetModifiers, 2766).
+-define(wxKeyEvent_GetPosition, 2769).
+-define(wxKeyEvent_GetRawKeyCode, 2770).
+-define(wxKeyEvent_GetRawKeyFlags, 2771).
+-define(wxKeyEvent_GetUnicodeKey, 2772).
+-define(wxKeyEvent_GetX, 2773).
+-define(wxKeyEvent_GetY, 2774).
+-define(wxKeyEvent_HasModifiers, 2775).
+-define(wxKeyEvent_MetaDown, 2776).
+-define(wxKeyEvent_ShiftDown, 2777).
+-define(wxSizeEvent_GetSize, 2778).
+-define(wxMoveEvent_GetPosition, 2779).
+-define(wxEraseEvent_GetDC, 2780).
+-define(wxFocusEvent_GetWindow, 2781).
+-define(wxChildFocusEvent_GetWindow, 2782).
+-define(wxMenuEvent_GetMenu, 2783).
+-define(wxMenuEvent_GetMenuId, 2784).
+-define(wxMenuEvent_IsPopup, 2785).
+-define(wxCloseEvent_CanVeto, 2786).
+-define(wxCloseEvent_GetLoggingOff, 2787).
+-define(wxCloseEvent_SetCanVeto, 2788).
+-define(wxCloseEvent_SetLoggingOff, 2789).
+-define(wxCloseEvent_Veto, 2790).
+-define(wxShowEvent_SetShow, 2791).
+-define(wxShowEvent_GetShow, 2792).
+-define(wxIconizeEvent_Iconized, 2793).
+-define(wxJoystickEvent_ButtonDown, 2794).
+-define(wxJoystickEvent_ButtonIsDown, 2795).
+-define(wxJoystickEvent_ButtonUp, 2796).
+-define(wxJoystickEvent_GetButtonChange, 2797).
+-define(wxJoystickEvent_GetButtonState, 2798).
+-define(wxJoystickEvent_GetJoystick, 2799).
+-define(wxJoystickEvent_GetPosition, 2800).
+-define(wxJoystickEvent_GetZPosition, 2801).
+-define(wxJoystickEvent_IsButton, 2802).
+-define(wxJoystickEvent_IsMove, 2803).
+-define(wxJoystickEvent_IsZMove, 2804).
+-define(wxUpdateUIEvent_CanUpdate, 2805).
+-define(wxUpdateUIEvent_Check, 2806).
+-define(wxUpdateUIEvent_Enable, 2807).
+-define(wxUpdateUIEvent_Show, 2808).
+-define(wxUpdateUIEvent_GetChecked, 2809).
+-define(wxUpdateUIEvent_GetEnabled, 2810).
+-define(wxUpdateUIEvent_GetShown, 2811).
+-define(wxUpdateUIEvent_GetSetChecked, 2812).
+-define(wxUpdateUIEvent_GetSetEnabled, 2813).
+-define(wxUpdateUIEvent_GetSetShown, 2814).
+-define(wxUpdateUIEvent_GetSetText, 2815).
+-define(wxUpdateUIEvent_GetText, 2816).
+-define(wxUpdateUIEvent_GetMode, 2817).
+-define(wxUpdateUIEvent_GetUpdateInterval, 2818).
+-define(wxUpdateUIEvent_ResetUpdateTime, 2819).
+-define(wxUpdateUIEvent_SetMode, 2820).
+-define(wxUpdateUIEvent_SetText, 2821).
+-define(wxUpdateUIEvent_SetUpdateInterval, 2822).
+-define(wxMouseCaptureChangedEvent_GetCapturedWindow, 2823).
+-define(wxPaletteChangedEvent_SetChangedWindow, 2824).
+-define(wxPaletteChangedEvent_GetChangedWindow, 2825).
+-define(wxQueryNewPaletteEvent_SetPaletteRealized, 2826).
+-define(wxQueryNewPaletteEvent_GetPaletteRealized, 2827).
+-define(wxNavigationKeyEvent_GetDirection, 2828).
+-define(wxNavigationKeyEvent_SetDirection, 2829).
+-define(wxNavigationKeyEvent_IsWindowChange, 2830).
+-define(wxNavigationKeyEvent_SetWindowChange, 2831).
+-define(wxNavigationKeyEvent_IsFromTab, 2832).
+-define(wxNavigationKeyEvent_SetFromTab, 2833).
+-define(wxNavigationKeyEvent_GetCurrentFocus, 2834).
+-define(wxNavigationKeyEvent_SetCurrentFocus, 2835).
+-define(wxHelpEvent_GetOrigin, 2836).
+-define(wxHelpEvent_GetPosition, 2837).
+-define(wxHelpEvent_SetOrigin, 2838).
+-define(wxHelpEvent_SetPosition, 2839).
+-define(wxContextMenuEvent_GetPosition, 2840).
+-define(wxContextMenuEvent_SetPosition, 2841).
+-define(wxIdleEvent_CanSend, 2842).
+-define(wxIdleEvent_GetMode, 2843).
+-define(wxIdleEvent_RequestMore, 2844).
+-define(wxIdleEvent_MoreRequested, 2845).
+-define(wxIdleEvent_SetMode, 2846).
+-define(wxGridEvent_AltDown, 2847).
+-define(wxGridEvent_ControlDown, 2848).
+-define(wxGridEvent_GetCol, 2849).
+-define(wxGridEvent_GetPosition, 2850).
+-define(wxGridEvent_GetRow, 2851).
+-define(wxGridEvent_MetaDown, 2852).
+-define(wxGridEvent_Selecting, 2853).
+-define(wxGridEvent_ShiftDown, 2854).
+-define(wxNotifyEvent_Allow, 2855).
+-define(wxNotifyEvent_IsAllowed, 2856).
+-define(wxNotifyEvent_Veto, 2857).
+-define(wxSashEvent_GetEdge, 2858).
+-define(wxSashEvent_GetDragRect, 2859).
+-define(wxSashEvent_GetDragStatus, 2860).
+-define(wxListEvent_GetCacheFrom, 2861).
+-define(wxListEvent_GetCacheTo, 2862).
+-define(wxListEvent_GetKeyCode, 2863).
+-define(wxListEvent_GetIndex, 2864).
+-define(wxListEvent_GetColumn, 2865).
+-define(wxListEvent_GetPoint, 2866).
+-define(wxListEvent_GetLabel, 2867).
+-define(wxListEvent_GetText, 2868).
+-define(wxListEvent_GetImage, 2869).
+-define(wxListEvent_GetData, 2870).
+-define(wxListEvent_GetMask, 2871).
+-define(wxListEvent_GetItem, 2872).
+-define(wxListEvent_IsEditCancelled, 2873).
+-define(wxDateEvent_GetDate, 2874).
+-define(wxCalendarEvent_GetWeekDay, 2875).
+-define(wxFileDirPickerEvent_GetPath, 2876).
+-define(wxColourPickerEvent_GetColour, 2877).
+-define(wxFontPickerEvent_GetFont, 2878).
+-define(wxStyledTextEvent_GetPosition, 2879).
+-define(wxStyledTextEvent_GetKey, 2880).
+-define(wxStyledTextEvent_GetModifiers, 2881).
+-define(wxStyledTextEvent_GetModificationType, 2882).
+-define(wxStyledTextEvent_GetText, 2883).
+-define(wxStyledTextEvent_GetLength, 2884).
+-define(wxStyledTextEvent_GetLinesAdded, 2885).
+-define(wxStyledTextEvent_GetLine, 2886).
+-define(wxStyledTextEvent_GetFoldLevelNow, 2887).
+-define(wxStyledTextEvent_GetFoldLevelPrev, 2888).
+-define(wxStyledTextEvent_GetMargin, 2889).
+-define(wxStyledTextEvent_GetMessage, 2890).
+-define(wxStyledTextEvent_GetWParam, 2891).
+-define(wxStyledTextEvent_GetLParam, 2892).
+-define(wxStyledTextEvent_GetListType, 2893).
+-define(wxStyledTextEvent_GetX, 2894).
+-define(wxStyledTextEvent_GetY, 2895).
+-define(wxStyledTextEvent_GetDragText, 2896).
+-define(wxStyledTextEvent_GetDragAllowMove, 2897).
+-define(wxStyledTextEvent_GetDragResult, 2898).
+-define(wxStyledTextEvent_GetShift, 2899).
+-define(wxStyledTextEvent_GetControl, 2900).
+-define(wxStyledTextEvent_GetAlt, 2901).
+-define(utils_wxGetKeyState, 2902).
+-define(utils_wxGetMousePosition, 2903).
+-define(utils_wxGetMouseState, 2904).
+-define(utils_wxSetDetectableAutoRepeat, 2905).
+-define(utils_wxBell, 2906).
+-define(utils_wxFindMenuItemId, 2907).
+-define(utils_wxGenericFindWindowAtPoint, 2908).
+-define(utils_wxFindWindowAtPoint, 2909).
+-define(utils_wxBeginBusyCursor, 2910).
+-define(utils_wxEndBusyCursor, 2911).
+-define(utils_wxIsBusy, 2912).
+-define(utils_wxShutdown, 2913).
+-define(utils_wxShell, 2914).
+-define(utils_wxLaunchDefaultBrowser, 2915).
+-define(utils_wxGetEmailAddress, 2916).
+-define(utils_wxGetUserId, 2917).
+-define(utils_wxGetHomeDir, 2918).
+-define(utils_wxNewId, 2919).
+-define(utils_wxRegisterId, 2920).
+-define(utils_wxGetCurrentId, 2921).
+-define(utils_wxGetOsDescription, 2922).
+-define(utils_wxIsPlatformLittleEndian, 2923).
+-define(utils_wxIsPlatform64Bit, 2924).
+-define(wxPrintout_new, 2925).
+-define(wxPrintout_destruct, 2926).
+-define(wxPrintout_GetDC, 2927).
+-define(wxPrintout_GetPageSizeMM, 2928).
+-define(wxPrintout_GetPageSizePixels, 2929).
+-define(wxPrintout_GetPaperRectPixels, 2930).
+-define(wxPrintout_GetPPIPrinter, 2931).
+-define(wxPrintout_GetPPIScreen, 2932).
+-define(wxPrintout_GetTitle, 2933).
+-define(wxPrintout_IsPreview, 2934).
+-define(wxPrintout_FitThisSizeToPaper, 2935).
+-define(wxPrintout_FitThisSizeToPage, 2936).
+-define(wxPrintout_FitThisSizeToPageMargins, 2937).
+-define(wxPrintout_MapScreenSizeToPaper, 2938).
+-define(wxPrintout_MapScreenSizeToPage, 2939).
+-define(wxPrintout_MapScreenSizeToPageMargins, 2940).
+-define(wxPrintout_MapScreenSizeToDevice, 2941).
+-define(wxPrintout_GetLogicalPaperRect, 2942).
+-define(wxPrintout_GetLogicalPageRect, 2943).
+-define(wxPrintout_GetLogicalPageMarginsRect, 2944).
+-define(wxPrintout_SetLogicalOrigin, 2945).
+-define(wxPrintout_OffsetLogicalOrigin, 2946).
+-define(wxStyledTextCtrl_new_2, 2947).
+-define(wxStyledTextCtrl_new_0, 2948).
+-define(wxStyledTextCtrl_destruct, 2949).
+-define(wxStyledTextCtrl_Create, 2950).
+-define(wxStyledTextCtrl_AddText, 2951).
+-define(wxStyledTextCtrl_AddStyledText, 2952).
+-define(wxStyledTextCtrl_InsertText, 2953).
+-define(wxStyledTextCtrl_ClearAll, 2954).
+-define(wxStyledTextCtrl_ClearDocumentStyle, 2955).
+-define(wxStyledTextCtrl_GetLength, 2956).
+-define(wxStyledTextCtrl_GetCharAt, 2957).
+-define(wxStyledTextCtrl_GetCurrentPos, 2958).
+-define(wxStyledTextCtrl_GetAnchor, 2959).
+-define(wxStyledTextCtrl_GetStyleAt, 2960).
+-define(wxStyledTextCtrl_Redo, 2961).
+-define(wxStyledTextCtrl_SetUndoCollection, 2962).
+-define(wxStyledTextCtrl_SelectAll, 2963).
+-define(wxStyledTextCtrl_SetSavePoint, 2964).
+-define(wxStyledTextCtrl_GetStyledText, 2965).
+-define(wxStyledTextCtrl_CanRedo, 2966).
+-define(wxStyledTextCtrl_MarkerLineFromHandle, 2967).
+-define(wxStyledTextCtrl_MarkerDeleteHandle, 2968).
+-define(wxStyledTextCtrl_GetUndoCollection, 2969).
+-define(wxStyledTextCtrl_GetViewWhiteSpace, 2970).
+-define(wxStyledTextCtrl_SetViewWhiteSpace, 2971).
+-define(wxStyledTextCtrl_PositionFromPoint, 2972).
+-define(wxStyledTextCtrl_PositionFromPointClose, 2973).
+-define(wxStyledTextCtrl_GotoLine, 2974).
+-define(wxStyledTextCtrl_GotoPos, 2975).
+-define(wxStyledTextCtrl_SetAnchor, 2976).
+-define(wxStyledTextCtrl_GetCurLine, 2977).
+-define(wxStyledTextCtrl_GetEndStyled, 2978).
+-define(wxStyledTextCtrl_ConvertEOLs, 2979).
+-define(wxStyledTextCtrl_GetEOLMode, 2980).
+-define(wxStyledTextCtrl_SetEOLMode, 2981).
+-define(wxStyledTextCtrl_StartStyling, 2982).
+-define(wxStyledTextCtrl_SetStyling, 2983).
+-define(wxStyledTextCtrl_GetBufferedDraw, 2984).
+-define(wxStyledTextCtrl_SetBufferedDraw, 2985).
+-define(wxStyledTextCtrl_SetTabWidth, 2986).
+-define(wxStyledTextCtrl_GetTabWidth, 2987).
+-define(wxStyledTextCtrl_SetCodePage, 2988).
+-define(wxStyledTextCtrl_MarkerDefine, 2989).
+-define(wxStyledTextCtrl_MarkerSetForeground, 2990).
+-define(wxStyledTextCtrl_MarkerSetBackground, 2991).
+-define(wxStyledTextCtrl_MarkerAdd, 2992).
+-define(wxStyledTextCtrl_MarkerDelete, 2993).
+-define(wxStyledTextCtrl_MarkerDeleteAll, 2994).
+-define(wxStyledTextCtrl_MarkerGet, 2995).
+-define(wxStyledTextCtrl_MarkerNext, 2996).
+-define(wxStyledTextCtrl_MarkerPrevious, 2997).
+-define(wxStyledTextCtrl_MarkerDefineBitmap, 2998).
+-define(wxStyledTextCtrl_MarkerAddSet, 2999).
+-define(wxStyledTextCtrl_MarkerSetAlpha, 3000).
+-define(wxStyledTextCtrl_SetMarginType, 3001).
+-define(wxStyledTextCtrl_GetMarginType, 3002).
+-define(wxStyledTextCtrl_SetMarginWidth, 3003).
+-define(wxStyledTextCtrl_GetMarginWidth, 3004).
+-define(wxStyledTextCtrl_SetMarginMask, 3005).
+-define(wxStyledTextCtrl_GetMarginMask, 3006).
+-define(wxStyledTextCtrl_SetMarginSensitive, 3007).
+-define(wxStyledTextCtrl_GetMarginSensitive, 3008).
+-define(wxStyledTextCtrl_StyleClearAll, 3009).
+-define(wxStyledTextCtrl_StyleSetForeground, 3010).
+-define(wxStyledTextCtrl_StyleSetBackground, 3011).
+-define(wxStyledTextCtrl_StyleSetBold, 3012).
+-define(wxStyledTextCtrl_StyleSetItalic, 3013).
+-define(wxStyledTextCtrl_StyleSetSize, 3014).
+-define(wxStyledTextCtrl_StyleSetFaceName, 3015).
+-define(wxStyledTextCtrl_StyleSetEOLFilled, 3016).
+-define(wxStyledTextCtrl_StyleResetDefault, 3017).
+-define(wxStyledTextCtrl_StyleSetUnderline, 3018).
+-define(wxStyledTextCtrl_StyleSetCase, 3019).
+-define(wxStyledTextCtrl_StyleSetHotSpot, 3020).
+-define(wxStyledTextCtrl_SetSelForeground, 3021).
+-define(wxStyledTextCtrl_SetSelBackground, 3022).
+-define(wxStyledTextCtrl_GetSelAlpha, 3023).
+-define(wxStyledTextCtrl_SetSelAlpha, 3024).
+-define(wxStyledTextCtrl_SetCaretForeground, 3025).
+-define(wxStyledTextCtrl_CmdKeyAssign, 3026).
+-define(wxStyledTextCtrl_CmdKeyClear, 3027).
+-define(wxStyledTextCtrl_CmdKeyClearAll, 3028).
+-define(wxStyledTextCtrl_SetStyleBytes, 3029).
+-define(wxStyledTextCtrl_StyleSetVisible, 3030).
+-define(wxStyledTextCtrl_GetCaretPeriod, 3031).
+-define(wxStyledTextCtrl_SetCaretPeriod, 3032).
+-define(wxStyledTextCtrl_SetWordChars, 3033).
+-define(wxStyledTextCtrl_BeginUndoAction, 3034).
+-define(wxStyledTextCtrl_EndUndoAction, 3035).
+-define(wxStyledTextCtrl_IndicatorSetStyle, 3036).
+-define(wxStyledTextCtrl_IndicatorGetStyle, 3037).
+-define(wxStyledTextCtrl_IndicatorSetForeground, 3038).
+-define(wxStyledTextCtrl_IndicatorGetForeground, 3039).
+-define(wxStyledTextCtrl_SetWhitespaceForeground, 3040).
+-define(wxStyledTextCtrl_SetWhitespaceBackground, 3041).
+-define(wxStyledTextCtrl_GetStyleBits, 3042).
+-define(wxStyledTextCtrl_SetLineState, 3043).
+-define(wxStyledTextCtrl_GetLineState, 3044).
+-define(wxStyledTextCtrl_GetMaxLineState, 3045).
+-define(wxStyledTextCtrl_GetCaretLineVisible, 3046).
+-define(wxStyledTextCtrl_SetCaretLineVisible, 3047).
+-define(wxStyledTextCtrl_GetCaretLineBackground, 3048).
+-define(wxStyledTextCtrl_SetCaretLineBackground, 3049).
+-define(wxStyledTextCtrl_AutoCompShow, 3050).
+-define(wxStyledTextCtrl_AutoCompCancel, 3051).
+-define(wxStyledTextCtrl_AutoCompActive, 3052).
+-define(wxStyledTextCtrl_AutoCompPosStart, 3053).
+-define(wxStyledTextCtrl_AutoCompComplete, 3054).
+-define(wxStyledTextCtrl_AutoCompStops, 3055).
+-define(wxStyledTextCtrl_AutoCompSetSeparator, 3056).
+-define(wxStyledTextCtrl_AutoCompGetSeparator, 3057).
+-define(wxStyledTextCtrl_AutoCompSelect, 3058).
+-define(wxStyledTextCtrl_AutoCompSetCancelAtStart, 3059).
+-define(wxStyledTextCtrl_AutoCompGetCancelAtStart, 3060).
+-define(wxStyledTextCtrl_AutoCompSetFillUps, 3061).
+-define(wxStyledTextCtrl_AutoCompSetChooseSingle, 3062).
+-define(wxStyledTextCtrl_AutoCompGetChooseSingle, 3063).
+-define(wxStyledTextCtrl_AutoCompSetIgnoreCase, 3064).
+-define(wxStyledTextCtrl_AutoCompGetIgnoreCase, 3065).
+-define(wxStyledTextCtrl_UserListShow, 3066).
+-define(wxStyledTextCtrl_AutoCompSetAutoHide, 3067).
+-define(wxStyledTextCtrl_AutoCompGetAutoHide, 3068).
+-define(wxStyledTextCtrl_AutoCompSetDropRestOfWord, 3069).
+-define(wxStyledTextCtrl_AutoCompGetDropRestOfWord, 3070).
+-define(wxStyledTextCtrl_RegisterImage, 3071).
+-define(wxStyledTextCtrl_ClearRegisteredImages, 3072).
+-define(wxStyledTextCtrl_AutoCompGetTypeSeparator, 3073).
+-define(wxStyledTextCtrl_AutoCompSetTypeSeparator, 3074).
+-define(wxStyledTextCtrl_AutoCompSetMaxWidth, 3075).
+-define(wxStyledTextCtrl_AutoCompGetMaxWidth, 3076).
+-define(wxStyledTextCtrl_AutoCompSetMaxHeight, 3077).
+-define(wxStyledTextCtrl_AutoCompGetMaxHeight, 3078).
+-define(wxStyledTextCtrl_SetIndent, 3079).
+-define(wxStyledTextCtrl_GetIndent, 3080).
+-define(wxStyledTextCtrl_SetUseTabs, 3081).
+-define(wxStyledTextCtrl_GetUseTabs, 3082).
+-define(wxStyledTextCtrl_SetLineIndentation, 3083).
+-define(wxStyledTextCtrl_GetLineIndentation, 3084).
+-define(wxStyledTextCtrl_GetLineIndentPosition, 3085).
+-define(wxStyledTextCtrl_GetColumn, 3086).
+-define(wxStyledTextCtrl_SetUseHorizontalScrollBar, 3087).
+-define(wxStyledTextCtrl_GetUseHorizontalScrollBar, 3088).
+-define(wxStyledTextCtrl_SetIndentationGuides, 3089).
+-define(wxStyledTextCtrl_GetIndentationGuides, 3090).
+-define(wxStyledTextCtrl_SetHighlightGuide, 3091).
+-define(wxStyledTextCtrl_GetHighlightGuide, 3092).
+-define(wxStyledTextCtrl_GetLineEndPosition, 3093).
+-define(wxStyledTextCtrl_GetCodePage, 3094).
+-define(wxStyledTextCtrl_GetCaretForeground, 3095).
+-define(wxStyledTextCtrl_GetReadOnly, 3096).
+-define(wxStyledTextCtrl_SetCurrentPos, 3097).
+-define(wxStyledTextCtrl_SetSelectionStart, 3098).
+-define(wxStyledTextCtrl_GetSelectionStart, 3099).
+-define(wxStyledTextCtrl_SetSelectionEnd, 3100).
+-define(wxStyledTextCtrl_GetSelectionEnd, 3101).
+-define(wxStyledTextCtrl_SetPrintMagnification, 3102).
+-define(wxStyledTextCtrl_GetPrintMagnification, 3103).
+-define(wxStyledTextCtrl_SetPrintColourMode, 3104).
+-define(wxStyledTextCtrl_GetPrintColourMode, 3105).
+-define(wxStyledTextCtrl_FindText, 3106).
+-define(wxStyledTextCtrl_FormatRange, 3107).
+-define(wxStyledTextCtrl_GetFirstVisibleLine, 3108).
+-define(wxStyledTextCtrl_GetLine, 3109).
+-define(wxStyledTextCtrl_GetLineCount, 3110).
+-define(wxStyledTextCtrl_SetMarginLeft, 3111).
+-define(wxStyledTextCtrl_GetMarginLeft, 3112).
+-define(wxStyledTextCtrl_SetMarginRight, 3113).
+-define(wxStyledTextCtrl_GetMarginRight, 3114).
+-define(wxStyledTextCtrl_GetModify, 3115).
+-define(wxStyledTextCtrl_SetSelection, 3116).
+-define(wxStyledTextCtrl_GetSelectedText, 3117).
+-define(wxStyledTextCtrl_GetTextRange, 3118).
+-define(wxStyledTextCtrl_HideSelection, 3119).
+-define(wxStyledTextCtrl_LineFromPosition, 3120).
+-define(wxStyledTextCtrl_PositionFromLine, 3121).
+-define(wxStyledTextCtrl_LineScroll, 3122).
+-define(wxStyledTextCtrl_EnsureCaretVisible, 3123).
+-define(wxStyledTextCtrl_ReplaceSelection, 3124).
+-define(wxStyledTextCtrl_SetReadOnly, 3125).
+-define(wxStyledTextCtrl_CanPaste, 3126).
+-define(wxStyledTextCtrl_CanUndo, 3127).
+-define(wxStyledTextCtrl_EmptyUndoBuffer, 3128).
+-define(wxStyledTextCtrl_Undo, 3129).
+-define(wxStyledTextCtrl_Cut, 3130).
+-define(wxStyledTextCtrl_Copy, 3131).
+-define(wxStyledTextCtrl_Paste, 3132).
+-define(wxStyledTextCtrl_Clear, 3133).
+-define(wxStyledTextCtrl_SetText, 3134).
+-define(wxStyledTextCtrl_GetText, 3135).
+-define(wxStyledTextCtrl_GetTextLength, 3136).
+-define(wxStyledTextCtrl_GetOvertype, 3137).
+-define(wxStyledTextCtrl_SetCaretWidth, 3138).
+-define(wxStyledTextCtrl_GetCaretWidth, 3139).
+-define(wxStyledTextCtrl_SetTargetStart, 3140).
+-define(wxStyledTextCtrl_GetTargetStart, 3141).
+-define(wxStyledTextCtrl_SetTargetEnd, 3142).
+-define(wxStyledTextCtrl_GetTargetEnd, 3143).
+-define(wxStyledTextCtrl_ReplaceTarget, 3144).
+-define(wxStyledTextCtrl_SearchInTarget, 3145).
+-define(wxStyledTextCtrl_SetSearchFlags, 3146).
+-define(wxStyledTextCtrl_GetSearchFlags, 3147).
+-define(wxStyledTextCtrl_CallTipShow, 3148).
+-define(wxStyledTextCtrl_CallTipCancel, 3149).
+-define(wxStyledTextCtrl_CallTipActive, 3150).
+-define(wxStyledTextCtrl_CallTipPosAtStart, 3151).
+-define(wxStyledTextCtrl_CallTipSetHighlight, 3152).
+-define(wxStyledTextCtrl_CallTipSetBackground, 3153).
+-define(wxStyledTextCtrl_CallTipSetForeground, 3154).
+-define(wxStyledTextCtrl_CallTipSetForegroundHighlight, 3155).
+-define(wxStyledTextCtrl_CallTipUseStyle, 3156).
+-define(wxStyledTextCtrl_VisibleFromDocLine, 3157).
+-define(wxStyledTextCtrl_DocLineFromVisible, 3158).
+-define(wxStyledTextCtrl_WrapCount, 3159).
+-define(wxStyledTextCtrl_SetFoldLevel, 3160).
+-define(wxStyledTextCtrl_GetFoldLevel, 3161).
+-define(wxStyledTextCtrl_GetLastChild, 3162).
+-define(wxStyledTextCtrl_GetFoldParent, 3163).
+-define(wxStyledTextCtrl_ShowLines, 3164).
+-define(wxStyledTextCtrl_HideLines, 3165).
+-define(wxStyledTextCtrl_GetLineVisible, 3166).
+-define(wxStyledTextCtrl_SetFoldExpanded, 3167).
+-define(wxStyledTextCtrl_GetFoldExpanded, 3168).
+-define(wxStyledTextCtrl_ToggleFold, 3169).
+-define(wxStyledTextCtrl_EnsureVisible, 3170).
+-define(wxStyledTextCtrl_SetFoldFlags, 3171).
+-define(wxStyledTextCtrl_EnsureVisibleEnforcePolicy, 3172).
+-define(wxStyledTextCtrl_SetTabIndents, 3173).
+-define(wxStyledTextCtrl_GetTabIndents, 3174).
+-define(wxStyledTextCtrl_SetBackSpaceUnIndents, 3175).
+-define(wxStyledTextCtrl_GetBackSpaceUnIndents, 3176).
+-define(wxStyledTextCtrl_SetMouseDwellTime, 3177).
+-define(wxStyledTextCtrl_GetMouseDwellTime, 3178).
+-define(wxStyledTextCtrl_WordStartPosition, 3179).
+-define(wxStyledTextCtrl_WordEndPosition, 3180).
+-define(wxStyledTextCtrl_SetWrapMode, 3181).
+-define(wxStyledTextCtrl_GetWrapMode, 3182).
+-define(wxStyledTextCtrl_SetWrapVisualFlags, 3183).
+-define(wxStyledTextCtrl_GetWrapVisualFlags, 3184).
+-define(wxStyledTextCtrl_SetWrapVisualFlagsLocation, 3185).
+-define(wxStyledTextCtrl_GetWrapVisualFlagsLocation, 3186).
+-define(wxStyledTextCtrl_SetWrapStartIndent, 3187).
+-define(wxStyledTextCtrl_GetWrapStartIndent, 3188).
+-define(wxStyledTextCtrl_SetLayoutCache, 3189).
+-define(wxStyledTextCtrl_GetLayoutCache, 3190).
+-define(wxStyledTextCtrl_SetScrollWidth, 3191).
+-define(wxStyledTextCtrl_GetScrollWidth, 3192).
+-define(wxStyledTextCtrl_TextWidth, 3193).
+-define(wxStyledTextCtrl_GetEndAtLastLine, 3194).
+-define(wxStyledTextCtrl_TextHeight, 3195).
+-define(wxStyledTextCtrl_SetUseVerticalScrollBar, 3196).
+-define(wxStyledTextCtrl_GetUseVerticalScrollBar, 3197).
+-define(wxStyledTextCtrl_AppendText, 3198).
+-define(wxStyledTextCtrl_GetTwoPhaseDraw, 3199).
+-define(wxStyledTextCtrl_SetTwoPhaseDraw, 3200).
+-define(wxStyledTextCtrl_TargetFromSelection, 3201).
+-define(wxStyledTextCtrl_LinesJoin, 3202).
+-define(wxStyledTextCtrl_LinesSplit, 3203).
+-define(wxStyledTextCtrl_SetFoldMarginColour, 3204).
+-define(wxStyledTextCtrl_SetFoldMarginHiColour, 3205).
+-define(wxStyledTextCtrl_LineDown, 3206).
+-define(wxStyledTextCtrl_LineDownExtend, 3207).
+-define(wxStyledTextCtrl_LineUp, 3208).
+-define(wxStyledTextCtrl_LineUpExtend, 3209).
+-define(wxStyledTextCtrl_CharLeft, 3210).
+-define(wxStyledTextCtrl_CharLeftExtend, 3211).
+-define(wxStyledTextCtrl_CharRight, 3212).
+-define(wxStyledTextCtrl_CharRightExtend, 3213).
+-define(wxStyledTextCtrl_WordLeft, 3214).
+-define(wxStyledTextCtrl_WordLeftExtend, 3215).
+-define(wxStyledTextCtrl_WordRight, 3216).
+-define(wxStyledTextCtrl_WordRightExtend, 3217).
+-define(wxStyledTextCtrl_Home, 3218).
+-define(wxStyledTextCtrl_HomeExtend, 3219).
+-define(wxStyledTextCtrl_LineEnd, 3220).
+-define(wxStyledTextCtrl_LineEndExtend, 3221).
+-define(wxStyledTextCtrl_DocumentStart, 3222).
+-define(wxStyledTextCtrl_DocumentStartExtend, 3223).
+-define(wxStyledTextCtrl_DocumentEnd, 3224).
+-define(wxStyledTextCtrl_DocumentEndExtend, 3225).
+-define(wxStyledTextCtrl_PageUp, 3226).
+-define(wxStyledTextCtrl_PageUpExtend, 3227).
+-define(wxStyledTextCtrl_PageDown, 3228).
+-define(wxStyledTextCtrl_PageDownExtend, 3229).
+-define(wxStyledTextCtrl_EditToggleOvertype, 3230).
+-define(wxStyledTextCtrl_Cancel, 3231).
+-define(wxStyledTextCtrl_DeleteBack, 3232).
+-define(wxStyledTextCtrl_Tab, 3233).
+-define(wxStyledTextCtrl_BackTab, 3234).
+-define(wxStyledTextCtrl_NewLine, 3235).
+-define(wxStyledTextCtrl_FormFeed, 3236).
+-define(wxStyledTextCtrl_VCHome, 3237).
+-define(wxStyledTextCtrl_VCHomeExtend, 3238).
+-define(wxStyledTextCtrl_ZoomIn, 3239).
+-define(wxStyledTextCtrl_ZoomOut, 3240).
+-define(wxStyledTextCtrl_DelWordLeft, 3241).
+-define(wxStyledTextCtrl_DelWordRight, 3242).
+-define(wxStyledTextCtrl_LineCut, 3243).
+-define(wxStyledTextCtrl_LineDelete, 3244).
+-define(wxStyledTextCtrl_LineTranspose, 3245).
+-define(wxStyledTextCtrl_LineDuplicate, 3246).
+-define(wxStyledTextCtrl_LowerCase, 3247).
+-define(wxStyledTextCtrl_UpperCase, 3248).
+-define(wxStyledTextCtrl_LineScrollDown, 3249).
+-define(wxStyledTextCtrl_LineScrollUp, 3250).
+-define(wxStyledTextCtrl_DeleteBackNotLine, 3251).
+-define(wxStyledTextCtrl_HomeDisplay, 3252).
+-define(wxStyledTextCtrl_HomeDisplayExtend, 3253).
+-define(wxStyledTextCtrl_LineEndDisplay, 3254).
+-define(wxStyledTextCtrl_LineEndDisplayExtend, 3255).
+-define(wxStyledTextCtrl_HomeWrapExtend, 3256).
+-define(wxStyledTextCtrl_LineEndWrap, 3257).
+-define(wxStyledTextCtrl_LineEndWrapExtend, 3258).
+-define(wxStyledTextCtrl_VCHomeWrap, 3259).
+-define(wxStyledTextCtrl_VCHomeWrapExtend, 3260).
+-define(wxStyledTextCtrl_LineCopy, 3261).
+-define(wxStyledTextCtrl_MoveCaretInsideView, 3262).
+-define(wxStyledTextCtrl_LineLength, 3263).
+-define(wxStyledTextCtrl_BraceHighlight, 3264).
+-define(wxStyledTextCtrl_BraceBadLight, 3265).
+-define(wxStyledTextCtrl_BraceMatch, 3266).
+-define(wxStyledTextCtrl_GetViewEOL, 3267).
+-define(wxStyledTextCtrl_SetViewEOL, 3268).
+-define(wxStyledTextCtrl_SetModEventMask, 3269).
+-define(wxStyledTextCtrl_GetEdgeColumn, 3270).
+-define(wxStyledTextCtrl_SetEdgeColumn, 3271).
+-define(wxStyledTextCtrl_GetEdgeMode, 3272).
+-define(wxStyledTextCtrl_GetEdgeColour, 3273).
+-define(wxStyledTextCtrl_SetEdgeColour, 3274).
+-define(wxStyledTextCtrl_SearchAnchor, 3275).
+-define(wxStyledTextCtrl_SearchNext, 3276).
+-define(wxStyledTextCtrl_SearchPrev, 3277).
+-define(wxStyledTextCtrl_LinesOnScreen, 3278).
+-define(wxStyledTextCtrl_UsePopUp, 3279).
+-define(wxStyledTextCtrl_SelectionIsRectangle, 3280).
+-define(wxStyledTextCtrl_SetZoom, 3281).
+-define(wxStyledTextCtrl_GetZoom, 3282).
+-define(wxStyledTextCtrl_GetModEventMask, 3283).
+-define(wxStyledTextCtrl_SetSTCFocus, 3284).
+-define(wxStyledTextCtrl_GetSTCFocus, 3285).
+-define(wxStyledTextCtrl_SetStatus, 3286).
+-define(wxStyledTextCtrl_GetStatus, 3287).
+-define(wxStyledTextCtrl_SetMouseDownCaptures, 3288).
+-define(wxStyledTextCtrl_GetMouseDownCaptures, 3289).
+-define(wxStyledTextCtrl_SetSTCCursor, 3290).
+-define(wxStyledTextCtrl_GetSTCCursor, 3291).
+-define(wxStyledTextCtrl_SetControlCharSymbol, 3292).
+-define(wxStyledTextCtrl_GetControlCharSymbol, 3293).
+-define(wxStyledTextCtrl_WordPartLeft, 3294).
+-define(wxStyledTextCtrl_WordPartLeftExtend, 3295).
+-define(wxStyledTextCtrl_WordPartRight, 3296).
+-define(wxStyledTextCtrl_WordPartRightExtend, 3297).
+-define(wxStyledTextCtrl_SetVisiblePolicy, 3298).
+-define(wxStyledTextCtrl_DelLineLeft, 3299).
+-define(wxStyledTextCtrl_DelLineRight, 3300).
+-define(wxStyledTextCtrl_GetXOffset, 3301).
+-define(wxStyledTextCtrl_ChooseCaretX, 3302).
+-define(wxStyledTextCtrl_SetXCaretPolicy, 3303).
+-define(wxStyledTextCtrl_SetYCaretPolicy, 3304).
+-define(wxStyledTextCtrl_GetPrintWrapMode, 3305).
+-define(wxStyledTextCtrl_SetHotspotActiveForeground, 3306).
+-define(wxStyledTextCtrl_SetHotspotActiveBackground, 3307).
+-define(wxStyledTextCtrl_SetHotspotActiveUnderline, 3308).
+-define(wxStyledTextCtrl_SetHotspotSingleLine, 3309).
+-define(wxStyledTextCtrl_ParaDownExtend, 3310).
+-define(wxStyledTextCtrl_ParaUp, 3311).
+-define(wxStyledTextCtrl_ParaUpExtend, 3312).
+-define(wxStyledTextCtrl_PositionBefore, 3313).
+-define(wxStyledTextCtrl_PositionAfter, 3314).
+-define(wxStyledTextCtrl_CopyRange, 3315).
+-define(wxStyledTextCtrl_CopyText, 3316).
+-define(wxStyledTextCtrl_SetSelectionMode, 3317).
+-define(wxStyledTextCtrl_GetSelectionMode, 3318).
+-define(wxStyledTextCtrl_LineDownRectExtend, 3319).
+-define(wxStyledTextCtrl_LineUpRectExtend, 3320).
+-define(wxStyledTextCtrl_CharLeftRectExtend, 3321).
+-define(wxStyledTextCtrl_CharRightRectExtend, 3322).
+-define(wxStyledTextCtrl_HomeRectExtend, 3323).
+-define(wxStyledTextCtrl_VCHomeRectExtend, 3324).
+-define(wxStyledTextCtrl_LineEndRectExtend, 3325).
+-define(wxStyledTextCtrl_PageUpRectExtend, 3326).
+-define(wxStyledTextCtrl_PageDownRectExtend, 3327).
+-define(wxStyledTextCtrl_StutteredPageUp, 3328).
+-define(wxStyledTextCtrl_StutteredPageUpExtend, 3329).
+-define(wxStyledTextCtrl_StutteredPageDown, 3330).
+-define(wxStyledTextCtrl_StutteredPageDownExtend, 3331).
+-define(wxStyledTextCtrl_WordLeftEnd, 3332).
+-define(wxStyledTextCtrl_WordLeftEndExtend, 3333).
+-define(wxStyledTextCtrl_WordRightEnd, 3334).
+-define(wxStyledTextCtrl_WordRightEndExtend, 3335).
+-define(wxStyledTextCtrl_SetWhitespaceChars, 3336).
+-define(wxStyledTextCtrl_SetCharsDefault, 3337).
+-define(wxStyledTextCtrl_AutoCompGetCurrent, 3338).
+-define(wxStyledTextCtrl_Allocate, 3339).
+-define(wxStyledTextCtrl_FindColumn, 3340).
+-define(wxStyledTextCtrl_GetCaretSticky, 3341).
+-define(wxStyledTextCtrl_SetCaretSticky, 3342).
+-define(wxStyledTextCtrl_ToggleCaretSticky, 3343).
+-define(wxStyledTextCtrl_SetPasteConvertEndings, 3344).
+-define(wxStyledTextCtrl_GetPasteConvertEndings, 3345).
+-define(wxStyledTextCtrl_SelectionDuplicate, 3346).
+-define(wxStyledTextCtrl_SetCaretLineBackAlpha, 3347).
+-define(wxStyledTextCtrl_GetCaretLineBackAlpha, 3348).
+-define(wxStyledTextCtrl_StartRecord, 3349).
+-define(wxStyledTextCtrl_StopRecord, 3350).
+-define(wxStyledTextCtrl_SetLexer, 3351).
+-define(wxStyledTextCtrl_GetLexer, 3352).
+-define(wxStyledTextCtrl_Colourise, 3353).
+-define(wxStyledTextCtrl_SetProperty, 3354).
+-define(wxStyledTextCtrl_SetKeyWords, 3355).
+-define(wxStyledTextCtrl_SetLexerLanguage, 3356).
+-define(wxStyledTextCtrl_GetProperty, 3357).
+-define(wxStyledTextCtrl_GetStyleBitsNeeded, 3358).
+-define(wxStyledTextCtrl_GetCurrentLine, 3359).
+-define(wxStyledTextCtrl_StyleSetSpec, 3360).
+-define(wxStyledTextCtrl_StyleSetFont, 3361).
+-define(wxStyledTextCtrl_StyleSetFontAttr, 3362).
+-define(wxStyledTextCtrl_StyleSetCharacterSet, 3363).
+-define(wxStyledTextCtrl_StyleSetFontEncoding, 3364).
+-define(wxStyledTextCtrl_CmdKeyExecute, 3365).
+-define(wxStyledTextCtrl_SetMargins, 3366).
+-define(wxStyledTextCtrl_GetSelection, 3367).
+-define(wxStyledTextCtrl_PointFromPosition, 3368).
+-define(wxStyledTextCtrl_ScrollToLine, 3369).
+-define(wxStyledTextCtrl_ScrollToColumn, 3370).
+-define(wxStyledTextCtrl_SendMsg, 3371).
+-define(wxStyledTextCtrl_SetVScrollBar, 3372).
+-define(wxStyledTextCtrl_SetHScrollBar, 3373).
+-define(wxStyledTextCtrl_GetLastKeydownProcessed, 3374).
+-define(wxStyledTextCtrl_SetLastKeydownProcessed, 3375).
+-define(wxStyledTextCtrl_SaveFile, 3376).
+-define(wxStyledTextCtrl_LoadFile, 3377).
+-define(wxStyledTextCtrl_DoDragOver, 3378).
+-define(wxStyledTextCtrl_DoDropText, 3379).
+-define(wxStyledTextCtrl_GetUseAntiAliasing, 3380).
+-define(wxStyledTextCtrl_AddTextRaw, 3381).
+-define(wxStyledTextCtrl_InsertTextRaw, 3382).
+-define(wxStyledTextCtrl_GetCurLineRaw, 3383).
+-define(wxStyledTextCtrl_GetLineRaw, 3384).
+-define(wxStyledTextCtrl_GetSelectedTextRaw, 3385).
+-define(wxStyledTextCtrl_GetTextRangeRaw, 3386).
+-define(wxStyledTextCtrl_SetTextRaw, 3387).
+-define(wxStyledTextCtrl_GetTextRaw, 3388).
+-define(wxStyledTextCtrl_AppendTextRaw, 3389).
+-define(wxArtProvider_GetBitmap, 3390).
+-define(wxArtProvider_GetIcon, 3391).
+-define(wxTreeEvent_GetKeyCode, 3392).
+-define(wxTreeEvent_GetItem, 3393).
+-define(wxTreeEvent_GetKeyEvent, 3394).
+-define(wxTreeEvent_GetLabel, 3395).
+-define(wxTreeEvent_GetOldItem, 3396).
+-define(wxTreeEvent_GetPoint, 3397).
+-define(wxTreeEvent_IsEditCancelled, 3398).
+-define(wxTreeEvent_SetToolTip, 3399).
+-define(wxNotebookEvent_GetOldSelection, 3400).
+-define(wxNotebookEvent_GetSelection, 3401).
+-define(wxNotebookEvent_SetOldSelection, 3402).
+-define(wxNotebookEvent_SetSelection, 3403).
+-define(wxFileDataObject_new, 3404).
+-define(wxFileDataObject_AddFile, 3405).
+-define(wxFileDataObject_GetFilenames, 3406).
+-define(wxFileDataObject_destroy, 3407).
+-define(wxTextDataObject_new, 3408).
+-define(wxTextDataObject_GetTextLength, 3409).
+-define(wxTextDataObject_GetText, 3410).
+-define(wxTextDataObject_SetText, 3411).
+-define(wxTextDataObject_destroy, 3412).
+-define(wxBitmapDataObject_new_1_1, 3413).
+-define(wxBitmapDataObject_new_1_0, 3414).
+-define(wxBitmapDataObject_GetBitmap, 3415).
+-define(wxBitmapDataObject_SetBitmap, 3416).
+-define(wxBitmapDataObject_destroy, 3417).
+-define(wxClipboard_new, 3419).
+-define(wxClipboard_destruct, 3420).
+-define(wxClipboard_AddData, 3421).
+-define(wxClipboard_Clear, 3422).
+-define(wxClipboard_Close, 3423).
+-define(wxClipboard_Flush, 3424).
+-define(wxClipboard_GetData, 3425).
+-define(wxClipboard_IsOpened, 3426).
+-define(wxClipboard_Open, 3427).
+-define(wxClipboard_SetData, 3428).
+-define(wxClipboard_UsePrimarySelection, 3430).
+-define(wxClipboard_IsSupported, 3431).
+-define(wxClipboard_Get, 3432).
+-define(wxSpinEvent_GetPosition, 3433).
+-define(wxSpinEvent_SetPosition, 3434).
+-define(wxSplitterWindow_new_0, 3435).
+-define(wxSplitterWindow_new_2, 3436).
+-define(wxSplitterWindow_destruct, 3437).
+-define(wxSplitterWindow_Create, 3438).
+-define(wxSplitterWindow_GetMinimumPaneSize, 3439).
+-define(wxSplitterWindow_GetSashGravity, 3440).
+-define(wxSplitterWindow_GetSashPosition, 3441).
+-define(wxSplitterWindow_GetSplitMode, 3442).
+-define(wxSplitterWindow_GetWindow1, 3443).
+-define(wxSplitterWindow_GetWindow2, 3444).
+-define(wxSplitterWindow_Initialize, 3445).
+-define(wxSplitterWindow_IsSplit, 3446).
+-define(wxSplitterWindow_ReplaceWindow, 3447).
+-define(wxSplitterWindow_SetSashGravity, 3448).
+-define(wxSplitterWindow_SetSashPosition, 3449).
+-define(wxSplitterWindow_SetSashSize, 3450).
+-define(wxSplitterWindow_SetMinimumPaneSize, 3451).
+-define(wxSplitterWindow_SetSplitMode, 3452).
+-define(wxSplitterWindow_SplitHorizontally, 3453).
+-define(wxSplitterWindow_SplitVertically, 3454).
+-define(wxSplitterWindow_Unsplit, 3455).
+-define(wxSplitterWindow_UpdateSize, 3456).
+-define(wxSplitterEvent_GetSashPosition, 3457).
+-define(wxSplitterEvent_GetX, 3458).
+-define(wxSplitterEvent_GetY, 3459).
+-define(wxSplitterEvent_GetWindowBeingRemoved, 3460).
+-define(wxSplitterEvent_SetSashPosition, 3461).
+-define(wxHtmlWindow_new_0, 3462).
+-define(wxHtmlWindow_new_2, 3463).
+-define(wxHtmlWindow_AppendToPage, 3464).
+-define(wxHtmlWindow_GetOpenedAnchor, 3465).
+-define(wxHtmlWindow_GetOpenedPage, 3466).
+-define(wxHtmlWindow_GetOpenedPageTitle, 3467).
+-define(wxHtmlWindow_GetRelatedFrame, 3468).
+-define(wxHtmlWindow_HistoryBack, 3469).
+-define(wxHtmlWindow_HistoryCanBack, 3470).
+-define(wxHtmlWindow_HistoryCanForward, 3471).
+-define(wxHtmlWindow_HistoryClear, 3472).
+-define(wxHtmlWindow_HistoryForward, 3473).
+-define(wxHtmlWindow_LoadFile, 3474).
+-define(wxHtmlWindow_LoadPage, 3475).
+-define(wxHtmlWindow_SelectAll, 3476).
+-define(wxHtmlWindow_SelectionToText, 3477).
+-define(wxHtmlWindow_SelectLine, 3478).
+-define(wxHtmlWindow_SelectWord, 3479).
+-define(wxHtmlWindow_SetBorders, 3480).
+-define(wxHtmlWindow_SetFonts, 3481).
+-define(wxHtmlWindow_SetPage, 3482).
+-define(wxHtmlWindow_SetRelatedFrame, 3483).
+-define(wxHtmlWindow_SetRelatedStatusBar, 3484).
+-define(wxHtmlWindow_ToText, 3485).
+-define(wxHtmlWindow_destroy, 3486).
+-define(wxHtmlLinkEvent_GetLinkInfo, 3487).
+-define(wxSystemSettings_GetColour, 3488).
+-define(wxSystemSettings_GetFont, 3489).
+-define(wxSystemSettings_GetMetric, 3490).
+-define(wxSystemSettings_GetScreenType, 3491).
+-define(wxSystemOptions_GetOption, 3492).
+-define(wxSystemOptions_GetOptionInt, 3493).
+-define(wxSystemOptions_HasOption, 3494).
+-define(wxSystemOptions_IsFalse, 3495).
+-define(wxSystemOptions_SetOption_2_1, 3496).
+-define(wxSystemOptions_SetOption_2_0, 3497).
+-define(wxAuiNotebookEvent_SetSelection, 3498).
+-define(wxAuiNotebookEvent_GetSelection, 3499).
+-define(wxAuiNotebookEvent_SetOldSelection, 3500).
+-define(wxAuiNotebookEvent_GetOldSelection, 3501).
+-define(wxAuiNotebookEvent_SetDragSource, 3502).
+-define(wxAuiNotebookEvent_GetDragSource, 3503).
+-define(wxAuiManagerEvent_SetManager, 3504).
+-define(wxAuiManagerEvent_GetManager, 3505).
+-define(wxAuiManagerEvent_SetPane, 3506).
+-define(wxAuiManagerEvent_GetPane, 3507).
+-define(wxAuiManagerEvent_SetButton, 3508).
+-define(wxAuiManagerEvent_GetButton, 3509).
+-define(wxAuiManagerEvent_SetDC, 3510).
+-define(wxAuiManagerEvent_GetDC, 3511).
+-define(wxAuiManagerEvent_Veto, 3512).
+-define(wxAuiManagerEvent_GetVeto, 3513).
+-define(wxAuiManagerEvent_SetCanVeto, 3514).
+-define(wxAuiManagerEvent_CanVeto, 3515).
+-define(wxLogNull_new, 3516).
+-define(wxLogNull_destroy, 3517).
diff --git a/lib/wx/src/wx_object.erl b/lib/wx/src/wx_object.erl
index bfd38960dd..82c4cfbad5 100644
--- a/lib/wx/src/wx_object.erl
+++ b/lib/wx/src/wx_object.erl
@@ -537,16 +537,16 @@ error_info(_Reason, application_controller, _Msg, _State, _Debug) ->
error_info(Reason, Name, Msg, State, Debug) ->
Reason1 =
case Reason of
- {undef,[{M,F,A}|MFAs]} ->
+ {undef,[{M,F,A,L}|MFAs]} ->
case code:is_loaded(M) of
false ->
- {'module could not be loaded',[{M,F,A}|MFAs]};
+ {'module could not be loaded',[{M,F,A,L}|MFAs]};
_ ->
case erlang:function_exported(M, F, length(A)) of
true ->
Reason;
false ->
- {'function not exported',[{M,F,A}|MFAs]}
+ {'function not exported',[{M,F,A,L}|MFAs]}
end
end;
_ ->
diff --git a/lib/wx/src/wxe_server.erl b/lib/wx/src/wxe_server.erl
index 40412987a5..69e2189fac 100644
--- a/lib/wx/src/wxe_server.erl
+++ b/lib/wx/src/wxe_server.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%%-------------------------------------------------------------------
%%% File : wxe_server.erl
@@ -24,7 +24,7 @@
%%% Created : 17 Jan 2007 by Dan Gudmundsson <[email protected]>
%%%-------------------------------------------------------------------
-%% @hidden
+%% @hidden
-module(wxe_server).
-behaviour(gen_server).
@@ -65,7 +65,7 @@ start() ->
end;
Env = #wx_env{sv=Pid} ->
case erlang:is_process_alive(Pid) of
- true ->
+ true ->
Env;
false -> %% Ok we got an old wx env, someone forgot
erase(?WXE_IDENTIFIER), %% to call wx:destroy()
@@ -94,7 +94,7 @@ init([]) ->
{ok,#state{port=Port, cb_port=CBPort,
users=gb_trees:empty(), cb=gb_trees:empty(), cb_cnt=1}}.
-%% Register process
+%% Register process
handle_call(register_me, {From,_}, State=#state{users=Users}) ->
erlang:monitor(process, From),
case gb_trees:is_defined(From, Users) of
@@ -147,7 +147,7 @@ handle_cast({debug, Level}, State) ->
put(?WXE_IDENTIFIER, Env#wx_env{debug=Level}),
{noreply, State};
-handle_cast(_Msg, State) ->
+handle_cast(_Msg, State) ->
?log("Unknown message ~p sent to ~p~n",[_Msg, ?MODULE]),
{noreply, State}.
@@ -156,7 +156,7 @@ handle_cast(_Msg, State) ->
%% Callback request from driver
handle_info(Cb = {_, _, '_wx_invoke_cb_'}, State) ->
invoke_cb(Cb, State),
- {noreply, State};
+ {noreply, State};
handle_info({wx_delete_cb, FunId}, State0 = #state{cb=CB}) when is_integer(FunId) ->
case get(FunId) of
undefined ->
@@ -166,7 +166,7 @@ handle_info({wx_delete_cb, FunId}, State0 = #state{cb=CB}) when is_integer(FunId
{noreply, State0#state{cb=gb_trees:delete(Fun, CB)}}
end;
handle_info({'DOWN',_,process,Pid,_}, State=#state{users=Users0,cleaners=Cs}) ->
- try
+ try
User = gb_trees:get(Pid,Users0),
Users = gb_trees:delete(Pid,Users0),
Env = wx:get_env(),
@@ -210,7 +210,7 @@ handle_connect(Object, EvData, From, State0 = #state{users=Users}) ->
case Handler0 of
#wx_ref{} when Callback =:= 0 ->
CBHandler = Handler0,
- Handler = Handler0;
+ Handler = Handler0;
undefined when Callback =:= 0 ->
Handler = new_evt_listener(State0),
CBHandler = Handler;
@@ -225,7 +225,7 @@ handle_connect(Object, EvData, From, State0 = #state{users=Users}) ->
{FunId, State} = attach_fun(Callback,State1),
Res = wxEvtHandler:connect_impl(CBHandler,Object,
wxEvtHandler:replace_fun_with_id(EvData,FunId)),
- case Res of
+ case Res of
ok -> {reply,Res,State};
_Error -> {reply,Res,State0}
end;
@@ -238,11 +238,7 @@ invoke_cb({{Ev=#wx{}, Ref=#wx_ref{}}, FunId,_}, _S) ->
%% Event callbacks
case get(FunId) of
Fun when is_function(Fun) ->
- invoke_callback(fun() ->
- wxe_util:cast(?WXE_CB_START, <<>>),
- Fun(Ev, Ref),
- <<>>
- end);
+ invoke_callback(fun() -> Fun(Ev, Ref), <<>> end);
Err ->
?log("Internal Error ~p~n",[Err])
end;
@@ -254,12 +250,14 @@ invoke_cb({FunId, Args, _}, _S) when is_list(Args), is_integer(FunId) ->
Err ->
?log("Internal Error ~p ~p ~p~n",[Err, FunId, Args])
end.
-
+
invoke_callback(Fun) ->
Env = get(?WXE_IDENTIFIER),
CB = fun() ->
wx:set_env(Env),
- Res = try Return = Fun(),
+ wxe_util:cast(?WXE_CB_START, <<>>),
+ Res = try
+ Return = Fun(),
true = is_binary(Return),
Return
catch _:Reason ->
@@ -278,9 +276,9 @@ new_evt_listener(State) ->
get_result(State).
get_result(_State) ->
- receive
+ receive
{'_wxe_result_', Res} -> Res;
- {'_wxe_error_', Op, Error} ->
+ {'_wxe_error_', Op, Error} ->
erlang:error({Error, {wxEvtHandler, {internal_installer, Op}}})
end.
@@ -289,7 +287,7 @@ attach_fun(Fun, S = #state{cb=CB,cb_cnt=Next}) ->
{value, ID} ->
{ID,S};
none ->
- put(Next,Fun),
+ put(Next,Fun),
{Next,S#state{cb=gb_trees:insert(Fun,Next,CB),cb_cnt=Next+1}}
end.
@@ -297,7 +295,7 @@ handle_disconnect(Object, Evh, From, State0 = #state{users=Users0}) ->
User0 = #user{events=Evs0, evt_handler=PidH} = gb_trees:get(From, Users0),
Fun = wxEvtHandler:get_callback(Evh),
case find_handler(Evs0, Object, Fun) of
- [] ->
+ [] ->
{reply, false, State0};
Handlers ->
case disconnect(Object,Evh, Handlers) of
@@ -310,7 +308,7 @@ handle_disconnect(Object, Evh, From, State0 = #state{users=Users0}) ->
[] when PidH =/= undefined ->
wxEvtHandler:destroy_evt_listener(PidH),
User0#user{events=[], evt_handler=undefined};
- Evs ->
+ Evs ->
User0#user{events=Evs}
end,
{reply, true, State0#state{users=gb_trees:update(From,User,Users0)}};
@@ -345,7 +343,7 @@ find_handler([],_Object,_Fun,Res) ->
%% Cleanup
-%% The server handles callbacks from driver so every other wx call must
+%% The server handles callbacks from driver so every other wx call must
%% be called from another process, therefore the cleaning must be spawned.
%%
cleanup(Env, _Pid, Data) ->
@@ -358,7 +356,7 @@ cleanup(#user{objects=_Os,events=Evs, evt_handler=Handler}) ->
lists:foreach(fun(#event{object=_O, callback=CB, cb_handler=CbH}) ->
%%catch wxEvtHandler:disconnect_impl(CbH,O),
case is_function(CB) of
- true ->
+ true ->
wxEvtHandler:destroy_evt_listener(CbH);
false ->
ignore
diff --git a/lib/wx/test/wx_class_SUITE.erl b/lib/wx/test/wx_class_SUITE.erl
index 79e6833e9b..b75b0cc74e 100644
--- a/lib/wx/test/wx_class_SUITE.erl
+++ b/lib/wx/test/wx_class_SUITE.erl
@@ -18,14 +18,14 @@
%%%-------------------------------------------------------------------
%%% File : wx_class_SUITE.erl
%%% Author : Dan Gudmundsson <[email protected]>
-%%% Description :
+%%% Description :
%%%
%%% Created : 13 Nov 2008 by Dan Gudmundsson <[email protected]>
%%%-------------------------------------------------------------------
-module(wx_class_SUITE).
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
- init_per_suite/1, end_per_suite/1,
+-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
+ init_per_suite/1, end_per_suite/1,
init_per_testcase/2, end_per_testcase/2]).
-compile(export_all).
@@ -41,18 +41,18 @@ end_per_suite(Config) ->
init_per_testcase(Func,Config) ->
wx_test_lib:init_per_testcase(Func,Config).
-end_per_testcase(Func,Config) ->
+end_per_testcase(Func,Config) ->
wx_test_lib:end_per_testcase(Func,Config).
%% SUITE specification
suite() -> [{ct_hooks,[ts_install_cth]}].
-all() ->
+all() ->
[calendarCtrl, treeCtrl, notebook, staticBoxSizer,
- clipboard, helpFrame, htmlWindow, listCtrlSort,
+ clipboard, helpFrame, htmlWindow, listCtrlSort, listCtrlVirtual,
radioBox, systemSettings].
-groups() ->
+groups() ->
[].
init_per_group(_GroupName, Config) ->
@@ -70,9 +70,9 @@ calendarCtrl(Config) ->
Frame = ?mt(wxFrame, wxFrame:new(Wx, 1, "Calendar", [])),
Panel = wxPanel:new(Frame),
Sz = wxBoxSizer:new(?wxVERTICAL),
-
+
{YMD={_,_,Day},_} = DateTime = calendar:now_to_datetime(erlang:now()),
- Cal = ?mt(wxCalendarCtrl, wxCalendarCtrl:new(Panel, ?wxID_ANY,
+ Cal = ?mt(wxCalendarCtrl, wxCalendarCtrl:new(Panel, ?wxID_ANY,
[{date,DateTime}
])),
wxSizer:add(Sz,Cal),
@@ -91,25 +91,25 @@ calendarCtrl(Config) ->
?m({0,243,0,255}, wxCalendarDateAttr:getBackgroundColour(DateAttr1)),
?m({YMD, _},wxCalendarCtrl:getDate(Cal)),
-
- wxCalendarCtrl:connect(Cal, calendar_weekday_clicked),
- wxCalendarCtrl:connect(Cal, calendar_day_changed),
- wxCalendarCtrl:connect(Cal, calendar_month_changed),
+
+ wxCalendarCtrl:connect(Cal, calendar_weekday_clicked),
+ wxCalendarCtrl:connect(Cal, calendar_day_changed),
+ wxCalendarCtrl:connect(Cal, calendar_month_changed),
wxCalendarCtrl:connect(Cal, calendar_year_changed),
- wxCalendarCtrl:connect(Cal, calendar_doubleclicked),
+ wxCalendarCtrl:connect(Cal, calendar_doubleclicked),
wxCalendarCtrl:connect(Cal, calendar_sel_changed),
-
+
wxWindow:setSizer(Panel,Sz),
wxSizer:setSizeHints(Sz,Frame),
- wxWindow:show(Frame),
-
+ wxWindow:show(Frame),
+
wx_test_lib:wx_destroy(Frame,Config).
treeCtrl(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo);
treeCtrl(Config) ->
Wx = wx:new(),
-
+
Frame = wxFrame:new(Wx, ?wxID_ANY, "Frame"),
Panel = wxPanel:new(Frame, []),
Tree = ?mt(wxTreeCtrl,wxTreeCtrl:new(Panel, [{style , ?wxTR_HAS_BUTTONS}])),
@@ -122,25 +122,25 @@ treeCtrl(Config) ->
?m(ok, wxTreeCtrl:setItemData(Tree, Item2, {data, item2})),
Item3 = wxTreeCtrl:appendItem(Tree, Root, "Item3", []),
?m(ok, wxTreeCtrl:setItemData(Tree, Item3, {data, item3})),
-
+
Sizer = wxBoxSizer:new(?wxVERTICAL),
wxSizer:add(Sizer, Tree, [{flag, ?wxEXPAND}, {proportion, 1}]),
wxWindow:setSizerAndFit(Panel, Sizer),
wxFrame:show(Frame),
-
+
?m([], wxTreeCtrl:getItemData(Tree, Root)),
?m({data,item1}, wxTreeCtrl:getItemData(Tree, Item1)),
?m({data,item2}, wxTreeCtrl:getItemData(Tree, Item2)),
?m({data,item3}, wxTreeCtrl:getItemData(Tree, Item3)),
-
+
wxFrame:connect(Tree, command_tree_item_expanded),
wxFrame:connect(Tree, command_tree_item_collapsed),
wxFrame:connect(Frame, close_window),
wxTreeCtrl:editLabel(Tree, Root),
-
+
wx_test_lib:wx_destroy(Frame,Config).
notebook(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo);
@@ -210,13 +210,13 @@ staticBoxSizer(Config) ->
Frame = wxFrame:new(Wx, ?wxID_ANY, "Frame"),
Panel = wxPanel:new(Frame, []),
InclSizer = ?mt(wxStaticBoxSizer,
- wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ wxStaticBoxSizer:new(?wxVERTICAL, Panel,
[{label, "Module inclusion policy"}])),
Sizer = wxBoxSizer:new(?wxVERTICAL),
wxSizer:add(Sizer, InclSizer,
[{border, 2}, {flag, ?wxALL bor ?wxEXPAND}, {proportion, 1}]),
- wxWindow:setSizerAndFit(Panel, Sizer),
-
+ wxWindow:setSizerAndFit(Panel, Sizer),
+
wxWindow:show(Frame),
wx_test_lib:wx_destroy(Frame,Config).
@@ -263,13 +263,13 @@ clipboard(_Config) ->
wxClipboard:flush(CB),
?log("Stopping ~n",[]),
ok.
-
+
helpFrame(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo);
helpFrame(Config) ->
Wx = wx:new(),
MFrame = wx:batch(fun() ->
MFrame = wxFrame:new(Wx, ?wxID_ANY, "Main Frame"),
- wxPanel:new(MFrame, [{size, {600,400}}]),
+ wxPanel:new(MFrame, [{size, {600,400}}]),
wxWindow:show(MFrame),
MFrame
end),
@@ -279,11 +279,11 @@ helpFrame(Config) ->
{X, Y, W,H} = wxWindow:getScreenRect(MFrame),
io:format("Pos0: ~p ~p ~p Pos: ~p:~p Size: ~p:~p ~n",
[X0,Y0, wxWindow:clientToScreen(MFrame, {0,0}), X,Y,W,H]),
-
+
Pos = {X+5, Y+(H div 2)},
Size = {W-10, (H div 2) - 5},
- Comp = wxFrame:new(MFrame, ?wxID_ANY, "Completion Window",
+ Comp = wxFrame:new(MFrame, ?wxID_ANY, "Completion Window",
[{pos, Pos}, {size, Size},
{style, ?wxFRAME_FLOAT_ON_PARENT}]),
LB = wxListBox:new(Comp, 42, [{style, ?wxLB_SINGLE},
@@ -301,7 +301,7 @@ htmlWindow(Config) ->
{MFrame,HPanel} =
wx:batch(fun() ->
MFrame = wxFrame:new(Wx, ?wxID_ANY, "Main Frame"),
- HPanel = wxHtmlWindow:new(MFrame, [{size, {600,400}}]),
+ HPanel = wxHtmlWindow:new(MFrame, [{size, {600,400}}]),
wxWindow:show(MFrame),
{MFrame, HPanel}
end),
@@ -310,7 +310,7 @@ htmlWindow(Config) ->
WxMod = code:which(wx),
WxDir = filename:split(filename:dirname(WxMod)) -- ["ebin"],
Html = filename:join(filename:join(WxDir),filename:join("doc", "html")),
-
+
Index = filename:join(Html, "wx.html"),
?m(ok, wxHtmlWindow:connect(HPanel, command_html_link_clicked,
@@ -318,7 +318,7 @@ htmlWindow(Config) ->
fun(Ev,_) ->
io:format("Link clicked: ~p~n",[Ev])
end}])),
-
+
case filelib:is_file(Index) of
true ->
?m(true, wxHtmlWindow:loadFile(HPanel, Index)),
@@ -326,7 +326,7 @@ htmlWindow(Config) ->
false ->
ok
end,
-
+
wx_test_lib:wx_destroy(MFrame,Config).
@@ -334,18 +334,18 @@ listCtrlSort(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo);
listCtrlSort(Config) ->
Wx = wx:new(),
Frame = wxFrame:new(Wx, ?wxID_ANY, "Frame"),
-
+
LC = wxListCtrl:new(Frame, [{style, ?wxLC_REPORT bor ?wxLC_SORT_ASCENDING}]),
%% must be done crashes in wxwidgets otherwise.
wxListCtrl:insertColumn(LC, 0, "Column"),
-
- Add = fun(Int) ->
+
+ Add = fun(Int) ->
wxListCtrl:insertItem(LC, Int, integer_to_list(Int)),
%% ItemData Can only be integers currently
wxListCtrl:setItemData(LC, Int, abs(2500-Int))
end,
-
+
wx:foreach(Add, lists:seq(0,5000)),
wxWindow:show(Frame),
@@ -360,10 +360,10 @@ listCtrlSort(Config) ->
end
end)
end,
-
+
Time = timer:tc(erlang, apply, [Sort,[]]),
io:format("Sorted ~p ~n",[Time]),
-
+
Item = wxListItem:new(),
_List = wx:map(fun(Int) ->
wxListItem:setId(Item, Int),
@@ -374,6 +374,48 @@ listCtrlSort(Config) ->
wx_test_lib:wx_destroy(Frame,Config).
+listCtrlVirtual(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo);
+listCtrlVirtual(Config) ->
+ Wx = wx:new(),
+ Frame = wxFrame:new(Wx, ?wxID_ANY, "Frame"),
+ IA = wxListItemAttr:new(),
+ wxListItemAttr:setTextColour(IA, {190, 25, 25}),
+ LC = wxListCtrl:new(Frame,
+ [{style, ?wxLC_REPORT bor ?wxLC_VIRTUAL},
+ {onGetItemText, fun(_This, Item, 0) ->
+ "Row " ++ integer_to_list(Item);
+ (_, Item, 1) when Item rem 5 == 0 ->
+ "Column 2";
+ (_, _, _) -> ""
+ end},
+ {onGetItemAttr, fun(_This, Item) when Item rem 3 == 0 ->
+ IA;
+ (_This, _Item) ->
+ wx:typeCast(wx:null(), wxListItemAttr)
+ end},
+ {onGetItemColumnImage, fun(_This, Item, 1) ->
+ Item rem 4;
+ (_, _, _) ->
+ -1
+ end}
+ ]),
+
+ IL = wxImageList:new(16,16),
+ wxImageList:add(IL, wxArtProvider:getBitmap("wxART_COPY", [{size, {16,16}}])),
+ wxImageList:add(IL, wxArtProvider:getBitmap("wxART_MISSING_IMAGE", [{size, {16,16}}])),
+ wxImageList:add(IL, wxArtProvider:getBitmap("wxART_TICK_MARK", [{size, {16,16}}])),
+ wxImageList:add(IL, wxArtProvider:getBitmap("wxART_CROSS_MARK", [{size, {16,16}}])),
+ wxListCtrl:assignImageList(LC, IL, ?wxIMAGE_LIST_SMALL),
+
+ wxListCtrl:insertColumn(LC, 0, "Column 1"),
+ wxListCtrl:insertColumn(LC, 1, "Column 2"),
+ wxListCtrl:setColumnWidth(LC, 0, 200),
+ wxListCtrl:setColumnWidth(LC, 1, 200),
+ wxListCtrl:setItemCount(LC, 1000000),
+
+ wxWindow:show(Frame),
+ wx_test_lib:wx_destroy(Frame,Config).
+
radioBox(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo);
radioBox(Config) ->
@@ -382,7 +424,7 @@ radioBox(Config) ->
TrSortRadioBox = wxRadioBox:new(Frame, ?wxID_ANY, "Sort by:",
{100, 100},{100, 100}, ["Timestamp"]),
-
+
io:format("TrSortRadioBox ~p ~n", [TrSortRadioBox]),
%% If I uncomment any of these lines, it will crash
@@ -398,7 +440,7 @@ systemSettings(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo)
systemSettings(Config) ->
Wx = wx:new(),
Frame = wxFrame:new(Wx, ?wxID_ANY, "Frame"),
-
+
?m({_,_,_,_}, wxSystemSettings:getColour(?wxSYS_COLOUR_DESKTOP)),
?mt(wxFont, wxSystemSettings:getFont(?wxSYS_SYSTEM_FONT)),
?m(true, is_integer(wxSystemSettings:getMetric(?wxSYS_MOUSE_BUTTONS))),
@@ -406,3 +448,25 @@ systemSettings(Config) ->
wxWindow:show(Frame),
wx_test_lib:wx_destroy(Frame,Config).
+
+
+textCtrl(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo);
+textCtrl(Config) ->
+ Wx = wx:new(),
+ Frame = wxFrame:new(Wx, ?wxID_ANY, "Frame"),
+
+ TC = ?mt(wxTextCtrl, wxTextCtrl:new(Frame, ?wxID_ANY, [{style, ?wxTE_MULTILINE bor ?wxTE_RICH2}])),
+ wxTextCtrl:appendText(TC, "This line is in default color\n"),
+ Attr = ?mt(wxTextAttr, wxTextAttr:new(?wxRED)),
+ wxTextCtrl:setDefaultStyle(TC, Attr),
+ wxTextCtrl:appendText(TC, "This line is in ?wxRED color\n"),
+ wxTextAttr:setTextColour(Attr, ?wxBLACK),
+ wxTextCtrl:setDefaultStyle(TC, Attr),
+ wxTextCtrl:appendText(TC, "This line is in ?wxBLACK color\n"),
+ Default = wxSystemSettings:getColour(?wxSYS_COLOUR_WINDOWTEXT),
+ wxTextAttr:setTextColour(Attr, Default),
+ wxTextCtrl:setDefaultStyle(TC, Attr),
+ wxTextCtrl:appendText(TC, "This line is in default color\n"),
+ wxTextAttr:destroy(Attr),
+ wxWindow:show(Frame),
+ wx_test_lib:wx_destroy(Frame,Config).
diff --git a/lib/wx/test/wx_event_SUITE.erl b/lib/wx/test/wx_event_SUITE.erl
index 0d8dd4852e..8f364049b4 100644
--- a/lib/wx/test/wx_event_SUITE.erl
+++ b/lib/wx/test/wx_event_SUITE.erl
@@ -47,7 +47,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[connect, disconnect, connect_msg_20, connect_cb_20,
- mouse_on_grid, spin_event, connect_in_callback].
+ mouse_on_grid, spin_event, connect_in_callback, recursive].
groups() ->
[].
@@ -331,3 +331,35 @@ connect_in_callback(Config) ->
wx_test_lib:flush(),
wx_test_lib:wx_destroy(Frame, Config).
+
+%% Test that event callback which triggers another callback works
+%% i.e. the callback invoker in driver will recurse
+recursive(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo);
+recursive(Config) ->
+ Wx = wx:new(),
+ Frame = wxFrame:new(Wx, ?wxID_ANY, "Connect in callback"),
+ Panel = wxPanel:new(Frame, []),
+ Sz = wxBoxSizer:new(?wxVERTICAL),
+ ListBox = wxListBox:new(Panel, ?wxID_ANY, [{choices, ["foo", "bar", "baz"]}]),
+ wxSizer:add(Sz, ListBox, [{proportion, 1},{flag, ?wxEXPAND}]),
+ wxWindow:setSizer(Panel, Sz),
+ wxListBox:connect(ListBox, command_listbox_selected,
+ [{callback,
+ fun(#wx{event=#wxCommand{commandInt=Id}}, _) ->
+ io:format("Selected ~p~n",[Id])
+ end}]),
+ wxListBox:setSelection(ListBox, 0),
+ wxListBox:connect(ListBox, size,
+ [{callback,
+ fun(#wx{event=#wxSize{}}, _) ->
+ io:format("Size init ~n",[]),
+ case wxListBox:getCount(ListBox) > 0 of
+ true -> wxListBox:delete(ListBox, 0);
+ false -> ok
+ end,
+ io:format("Size done ~n",[])
+ end}]),
+ wxFrame:show(Frame),
+ wx_test_lib:flush(),
+
+ wx_test_lib:wx_destroy(Frame, Config).
diff --git a/lib/wx/test/wxt.erl b/lib/wx/test/wxt.erl
index 1f5b1cc3b1..c14d3f8647 100644
--- a/lib/wx/test/wxt.erl
+++ b/lib/wx/test/wxt.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -72,7 +72,7 @@ resolve({Suite0, Case}) when is_atom(Suite0), is_atom(Case) ->
{Suite, Case2} ->
{Suite, Case2}
end;
-resolve(List) when list(List) ->
+resolve(List) when is_list(List) ->
[resolve(Case) || Case <- List].
alias(Suite) when is_atom(Suite) ->
@@ -104,7 +104,7 @@ read_config() ->
end.
%% Write new default config file
-write_config(Config) when list(Config) ->
+write_config(Config) when is_list(Config) ->
Fname = config_fname(),
{ok, Fd} = file:open(Fname, write),
write_list(Fd, Config),
diff --git a/lib/wx/vsn.mk b/lib/wx/vsn.mk
index 02899f4115..8685c633d4 100644
--- a/lib/wx/vsn.mk
+++ b/lib/wx/vsn.mk
@@ -1 +1 @@
-WX_VSN = 0.98.10
+WX_VSN = 0.99
diff --git a/lib/xmerl/doc/examples/test_html.erl b/lib/xmerl/doc/examples/test_html.erl
index 3ca15f30f8..3ca15f30f8 100755..100644
--- a/lib/xmerl/doc/examples/test_html.erl
+++ b/lib/xmerl/doc/examples/test_html.erl
diff --git a/lib/xmerl/doc/examples/xml/test.xml b/lib/xmerl/doc/examples/xml/test.xml
index e803a83560..e803a83560 100755..100644
--- a/lib/xmerl/doc/examples/xml/test.xml
+++ b/lib/xmerl/doc/examples/xml/test.xml
diff --git a/lib/xmerl/doc/examples/xml/test2.xml b/lib/xmerl/doc/examples/xml/test2.xml
index 0cb11194fc..0cb11194fc 100755..100644
--- a/lib/xmerl/doc/examples/xml/test2.xml
+++ b/lib/xmerl/doc/examples/xml/test2.xml
diff --git a/lib/xmerl/doc/examples/xml/test3.xml b/lib/xmerl/doc/examples/xml/test3.xml
index dbdc1e62c2..dbdc1e62c2 100755..100644
--- a/lib/xmerl/doc/examples/xml/test3.xml
+++ b/lib/xmerl/doc/examples/xml/test3.xml
diff --git a/lib/xmerl/doc/examples/xml/test4.xml b/lib/xmerl/doc/examples/xml/test4.xml
index e9d85b8d8f..e9d85b8d8f 100755..100644
--- a/lib/xmerl/doc/examples/xml/test4.xml
+++ b/lib/xmerl/doc/examples/xml/test4.xml
diff --git a/lib/xmerl/doc/examples/xml/test5.xml b/lib/xmerl/doc/examples/xml/test5.xml
index e9d85b8d8f..e9d85b8d8f 100755..100644
--- a/lib/xmerl/doc/examples/xml/test5.xml
+++ b/lib/xmerl/doc/examples/xml/test5.xml
diff --git a/lib/xmerl/doc/examples/xml/testdtd.dtd b/lib/xmerl/doc/examples/xml/testdtd.dtd
index 2ce1c513a6..2ce1c513a6 100755..100644
--- a/lib/xmerl/doc/examples/xml/testdtd.dtd
+++ b/lib/xmerl/doc/examples/xml/testdtd.dtd
diff --git a/lib/xmerl/doc/examples/xml/xmerl.xml b/lib/xmerl/doc/examples/xml/xmerl.xml
index f02282dbef..f02282dbef 100755..100644
--- a/lib/xmerl/doc/examples/xml/xmerl.xml
+++ b/lib/xmerl/doc/examples/xml/xmerl.xml
diff --git a/lib/xmerl/doc/src/make.dep b/lib/xmerl/doc/src/make.dep
deleted file mode 100644
index 9c303fc41c..0000000000
--- a/lib/xmerl/doc/src/make.dep
+++ /dev/null
@@ -1,24 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex part.tex ref_man.tex xmerl.tex xmerl_eventp.tex \
- xmerl_scan.tex xmerl_ug.tex xmerl_xpath.tex \
- xmerl_xs.tex xmerl_xsd.tex xmerl_sax_parser.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-xmerl_ug.tex: motorcycles.txt motorcycles2html.erl motorcycles_dtd.txt \
- new_motorcycles.txt new_motorcycles2.txt
-
diff --git a/lib/xmerl/doc/src/notes.xml b/lib/xmerl/doc/src/notes.xml
index 697823eee2..15c42d6f6a 100644
--- a/lib/xmerl/doc/src/notes.xml
+++ b/lib/xmerl/doc/src/notes.xml
@@ -31,6 +31,63 @@
<p>This document describes the changes made to the Xmerl application.</p>
+<section><title>Xmerl 1.2.10</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fixed a schema search bug in xmerl_xsd. </p> <p> A
+ new flag was needed in the xsd_state record so if the
+ state is saved there is an incompatibility and a state
+ conversion is needed. </p>
+ <p>
+ *** INCOMPATIBILITY with R14B03 ***</p>
+ <p>
+ Own Id: OTP-9410</p>
+ </item>
+ <item>
+ <p> Fixed xmerl_scan problems with entities in attribute
+ values. </p>
+ <p>
+ Own Id: OTP-9411</p>
+ </item>
+ <item>
+ <p> Streaming bug in xmerl_scan. </p> <p> If the
+ continuation_fun runs out of input at the end of an
+ attribute value then it crashed. (Thanks to Simon
+ Cornish) </p>
+ <p>
+ Own Id: OTP-9457</p>
+ </item>
+ <item>
+ <p>
+ Fixed xmerl_ucs UCS2 little endian en/decoding</p>
+ <p>
+ Corrected number of shift bytes in
+ xmerl_ucs:char_to_ucs2le and recursive call from
+ from_ucs2le to from_ucs4le. (Thanks to Michal Ptaszek)</p>
+ <p>
+ Own Id: OTP-9548</p>
+ </item>
+ <item>
+ <p>
+ Add latin9 (iso-8859-15) support in xmerl_ucs (Thanks to
+ David Julien)</p>
+ <p>
+ Own Id: OTP-9552</p>
+ </item>
+ <item>
+ <p>
+ Improve spelling throughout documentation, code comments
+ and error messages</p>
+ <p>
+ Own Id: OTP-9555</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Xmerl 1.2.9</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/xmerl/doc/src/part_notes.xml b/lib/xmerl/doc/src/part_notes.xml
index 827ffd90e9..827ffd90e9 100755..100644
--- a/lib/xmerl/doc/src/part_notes.xml
+++ b/lib/xmerl/doc/src/part_notes.xml
diff --git a/lib/xmerl/include/xmerl.hrl b/lib/xmerl/include/xmerl.hrl
index 7bb3f4de9b..3760a5cce0 100755..100644
--- a/lib/xmerl/include/xmerl.hrl
+++ b/lib/xmerl/include/xmerl.hrl
@@ -61,10 +61,11 @@
}).
%% namespace node - i.e. a {Prefix, URI} pair
-%% TODO: these are not currently used?? /RC
-record(xmlNsNode,{
- prefix,
- uri = []
+ parents = [], % [{atom(),integer()}]
+ pos, % integer()
+ prefix, % string()
+ uri = [] % [] | atom()
}).
%% XML Element
@@ -103,9 +104,10 @@
%% processing instruction
-record(xmlPI,{
- name, % atom()
- pos, % integer()
- value % IOlist()
+ name, % atom()
+ parents = [], % [{atom(),integer()}]
+ pos, % integer()
+ value % IOlist()
}).
-record(xmlDocument,{
@@ -154,6 +156,9 @@
declarations = [], % [{Name, Attrs}]
doctype_name,
doctype_DTD = internal, % internal | DTDId
+ comments = true,
+ document = false,
+ default_attrs = false,
rules,
keep_rules = false, % delete (ets) tab if false
namespace_conformant = false, % true | false
diff --git a/lib/xmerl/include/xmerl_xlink.hrl b/lib/xmerl/include/xmerl_xlink.hrl
index 375e244c23..375e244c23 100755..100644
--- a/lib/xmerl/include/xmerl_xlink.hrl
+++ b/lib/xmerl/include/xmerl_xlink.hrl
diff --git a/lib/xmerl/include/xmerl_xsd.hrl b/lib/xmerl/include/xmerl_xsd.hrl
index b527accc8c..6dad7d8ff0 100644
--- a/lib/xmerl/include/xmerl_xsd.hrl
+++ b/lib/xmerl/include/xmerl_xsd.hrl
@@ -36,6 +36,7 @@
schema_name,
vsn,
schema_preprocessed=false,
+ external_xsd_base=false,
xsd_base,
xml_options=[],
scope=[],
diff --git a/lib/xmerl/src/xmerl.erl b/lib/xmerl/src/xmerl.erl
index cf78f7bdf7..2332517988 100644
--- a/lib/xmerl/src/xmerl.erl
+++ b/lib/xmerl/src/xmerl.erl
@@ -307,7 +307,7 @@ apply_cb(Ms, F, Df, Args) ->
apply_cb([M|Ms], F, Df, Args, Ms0) ->
case catch apply(M, F, Args) of
- {'EXIT', {undef,[{M,F,_}|_]}} ->
+ {'EXIT', {undef,[{M,F,_,_}|_]}} ->
apply_cb(Ms, F, Df, Args, Ms0);
{'EXIT', Reason} ->
exit(Reason);
diff --git a/lib/xmerl/src/xmerl_lib.erl b/lib/xmerl/src/xmerl_lib.erl
index 6402f1cbeb..aeb821f411 100644
--- a/lib/xmerl/src/xmerl_lib.erl
+++ b/lib/xmerl/src/xmerl_lib.erl
@@ -160,8 +160,9 @@ expand_element(E = #xmlText{}, Pos, Parents, Norm) ->
E#xmlText{pos = Pos,
parents = Parents,
value = expand_text(E#xmlText.value, Norm)};
-expand_element(E = #xmlPI{}, Pos, _Parents, Norm) ->
+expand_element(E = #xmlPI{}, Pos, Parents, Norm) ->
E#xmlPI{pos = Pos,
+ parents = Parents,
value = expand_text(E#xmlPI.value, Norm)};
expand_element(E = #xmlComment{}, Pos, Parents, Norm) ->
E#xmlComment{pos = Pos,
diff --git a/lib/xmerl/src/xmerl_sax_parser_base.erlsrc b/lib/xmerl/src/xmerl_sax_parser_base.erlsrc
index 3b9eaa309c..ec9178ea25 100644
--- a/lib/xmerl/src/xmerl_sax_parser_base.erlsrc
+++ b/lib/xmerl/src/xmerl_sax_parser_base.erlsrc
@@ -944,14 +944,19 @@ parse_att_value(?STRING_REST("&", Rest), State, Stop, Acc) ->
{unparsed, Name, _} ->
?fatal_error(State1, "Unparsed entity reference in attribute value: " ++ Name)
end;
-parse_att_value(?STRING_UNBOUND_REST(Stop, Rest), State, Stop, Acc) ->
+parse_att_value(?STRING_UNBOUND_REST(Stop, Rest), State, Stop, Acc) ->
{lists:reverse(Acc), Rest, State};
-parse_att_value(?STRING_UNBOUND_REST($<, _Rest), State, _Stop, _Acc) ->
+parse_att_value(?STRING_UNBOUND_REST($<, _Rest), State, _Stop, _Acc) ->
?fatal_error(State, "< not allowed in attribute value");
-parse_att_value(?STRING_UNBOUND_REST(C, Rest), State, Stop, Acc) ->
- parse_att_value(Rest, State, Stop, [C|Acc]);
-parse_att_value(Bytes, State, Stop, Acc) ->
- unicode_incomplete_check([Bytes, State, Stop, Acc, fun parse_att_value/4],
+parse_att_value(?STRING_UNBOUND_REST(C, Rest), State, Stop, Acc) ->
+ if
+ ?is_char(C) ->
+ parse_att_value(Rest, State, Stop, [C|Acc]);
+ true ->
+ ?fatal_error(State, lists:flatten(io_lib:format("Bad character in attribute value: ~p", [C])))
+ end;
+parse_att_value(Bytes, State, Stop, Acc) ->
+ unicode_incomplete_check([Bytes, State, Stop, Acc, fun parse_att_value/4],
undefined).
@@ -1120,10 +1125,10 @@ parse_content(?STRING_UNBOUND_REST(C, Rest), State, Acc, _IgnorableWS) ->
?is_char(C) ->
parse_content(Rest, State, [C|Acc], false);
true ->
- ?fatal_error(State, "Bad character in content: " ++ C)
- end;
-parse_content(Bytes, State, Acc, IgnorableWS) ->
- unicode_incomplete_check([Bytes, State, Acc, IgnorableWS, fun parse_content/4],
+ ?fatal_error(State, lists:flatten(io_lib:format("Bad character in content: ~p", [C])))
+ end;
+parse_content(Bytes, State, Acc, IgnorableWS) ->
+ unicode_incomplete_check([Bytes, State, Acc, IgnorableWS, fun parse_content/4],
undefined).
@@ -2522,11 +2527,16 @@ parse_entity_value(?STRING_REST("%", Rest), #xmerl_sax_parser_state{file_type=Ty
end
end;
-parse_entity_value(?STRING_UNBOUND_REST(Stop, Rest), State, Stop, Acc) ->
+parse_entity_value(?STRING_UNBOUND_REST(Stop, Rest), State, Stop, Acc) ->
{lists:reverse(Acc), Rest, State};
-parse_entity_value(?STRING_UNBOUND_REST(C, Rest), State, Stop, Acc) ->
- parse_entity_value(Rest, State, Stop, [C|Acc]);
-parse_entity_value(Bytes, State, Stop, Acc) ->
+parse_entity_value(?STRING_UNBOUND_REST(C, Rest), State, Stop, Acc) ->
+ if
+ ?is_char(C) ->
+ parse_entity_value(Rest, State, Stop, [C|Acc]);
+ true ->
+ ?fatal_error(State, lists:flatten(io_lib:format("Bad character in entity value: ~p", [C])))
+ end;
+parse_entity_value(Bytes, State, Stop, Acc) ->
unicode_incomplete_check([Bytes, State, Stop, Acc, fun parse_entity_value/4],
undefined).
diff --git a/lib/xmerl/src/xmerl_scan.erl b/lib/xmerl/src/xmerl_scan.erl
index 059c8f21b6..ec7ea534d6 100644
--- a/lib/xmerl/src/xmerl_scan.erl
+++ b/lib/xmerl/src/xmerl_scan.erl
@@ -100,7 +100,21 @@
%% <dd>Set default character set used (default UTF-8).
%% This character set is used only if not explicitly given by the XML
%% declaration. </dd>
+%% <dt><code>{document, Flag}</code></dt>
+%% <dd>Set to 'true' if xmerl should return a complete XML document
+%% as an xmlDocument record (default 'false').</dd>
+%% <dt><code>{comments, Flag}</code></dt>
+%% <dd>Set to 'false' if xmerl should skip comments otherwise they will
+%% be returned as xmlComment records (default 'true').</dd>
+%% <dt><code>{default_attrs, Flag}</code></dt>
+%% <dd>Set to 'true' if xmerl should add to elements missing attributes
+%% with a defined default value (default 'false').</dd>
%% </dl>
+%% @type document() = xmlElement() | xmlDocument(). <p>
+%% The document returned by <tt>xmerl_scan:string/[1,2]</tt> and
+%% <tt>xmerl_scan:file/[1,2]</tt>. The type of the returned record depends on
+%% the value of the document option passed to the function.
+%% </p>
-module(xmerl_scan).
@@ -224,7 +238,7 @@ cont_state(X, S=#xmerl_scanner{fun_states = FS}) ->
file(F) ->
file(F, []).
-%% @spec file(Filename::string(), Options::option_list()) -> {xmlElement(),Rest}
+%% @spec file(Filename::string(), Options::option_list()) -> {document(),Rest}
%% Rest = list()
%%% @doc Parse file containing an XML document
file(F, Options) ->
@@ -264,7 +278,7 @@ int_file_decl(F, Options,_ExtCharset) ->
string(Str) ->
string(Str, []).
-%% @spec string(Text::list(),Options::option_list()) -> {xmlElement(),Rest}
+%% @spec string(Text::list(),Options::option_list()) -> {document(),Rest}
%% Rest = list()
%%% @doc Parse string containing an XML document
string(Str, Options) ->
@@ -381,6 +395,12 @@ initial_state([{quiet, F}|T], S) when F==true; F==false ->
initial_state(T, S#xmerl_scanner{quiet = F});
initial_state([{doctype_DTD,DTD}|T], S) ->
initial_state(T,S#xmerl_scanner{doctype_DTD = DTD});
+initial_state([{document, F}|T], S) when is_boolean(F) ->
+ initial_state(T,S#xmerl_scanner{document = F});
+initial_state([{comments, F}|T], S) when is_boolean(F) ->
+ initial_state(T,S#xmerl_scanner{comments = F});
+initial_state([{default_attrs, F}|T], S) when is_boolean(F) ->
+ initial_state(T,S#xmerl_scanner{default_attrs = F});
initial_state([{text_decl,Bool}|T], S) ->
initial_state(T,S#xmerl_scanner{text_decl=Bool});
initial_state([{environment,Env}|T], S) ->
@@ -518,6 +538,7 @@ scan_document(Str0, S=#xmerl_scanner{event_fun = Event,
line = L, col = C,
environment=Env,
encoding=Charset,
+ document=Document,
validation=ValidateResult}) ->
S1 = Event(#xmerl_event{event = started,
line = L,
@@ -530,8 +551,8 @@ scan_document(Str0, S=#xmerl_scanner{event_fun = Event,
Str=if
Charset == "utf-8" ->
Str0;
- Charset=/=undefined -> % Default character set is UTF-8
- xmerl_ucs:to_unicode(Str0,list_to_atom(Charset));
+ Charset =/= undefined -> % Default character set is UTF-8
+ xmerl_ucs:to_unicode(Str0, list_to_atom(Charset));
true -> %% Charset is undefined if no external input is
%% given, and no auto detection of character
%% encoding was made.
@@ -539,17 +560,17 @@ scan_document(Str0, S=#xmerl_scanner{event_fun = Event,
end,
%% M1 = erlang:memory(),
%% io:format("Memory status before prolog: ~p~n",[M1]),
- {T1, S2} = scan_prolog(Str, S1, _StartPos = 1),
+ {Prolog, Pos, T1, S2} = scan_prolog(Str, S1, _StartPos = 1),
%% M2 = erlang:memory(),
%% io:format("Memory status after prolog: ~p~n",[M2]),
%%io:format("scan_document 2, prolog parsed~n",[]),
- T2 = scan_mandatory("<",T1,1,S2,expected_element_start_tag),
+ T2 = scan_mandatory("<", T1, 1, S2, expected_element_start_tag),
%% M3 = erlang:memory(),
%% io:format("Memory status before element: ~p~n",[M3]),
- {Res, T3, S3} =scan_element(T2,S2,_StartPos = 1),
+ {Res, T3, S3} = scan_element(T2,S2,Pos),
%% M4 = erlang:memory(),
%% io:format("Memory status after element: ~p~n",[M4]),
- {Tail, S4}=scan_misc(T3, S3, _StartPos = 1),
+ {Misc, _Pos1, Tail, S4}=scan_misc(T3, S3, Pos + 1),
%% M5 = erlang:memory(),
%% io:format("Memory status after misc: ~p~n",[M5]),
@@ -558,44 +579,52 @@ scan_document(Str0, S=#xmerl_scanner{event_fun = Event,
col = S4#xmerl_scanner.col,
data = document}, S4),
- {Res2,S6} = case validation_mode(ValidateResult) of
+ {Res2, S6} = case validation_mode(ValidateResult) of
off ->
- {Res,cleanup(S5)};
+ {Res, cleanup(S5)};
dtd when Env == element; Env == prolog ->
check_decl2(S5),
- case xmerl_validate:validate(S5,Res) of
- {'EXIT',{error,Reason}} ->
- S5b=cleanup(S5),
- ?fatal({failed_validation,Reason}, S5b);
- {'EXIT',Reason} ->
- S5b=cleanup(S5),
- ?fatal({failed_validation,Reason}, S5b);
- {error,Reason} ->
- S5b=cleanup(S5),
- ?fatal({failed_validation,Reason}, S5b);
- {error,Reason,_Next} ->
- S5b=cleanup(S5),
- ?fatal({failed_validation,Reason}, S5b);
+ case xmerl_validate:validate(S5, Res) of
+ {'EXIT', {error, Reason}} ->
+ S5b = cleanup(S5),
+ ?fatal({failed_validation, Reason}, S5b);
+ {'EXIT', Reason} ->
+ S5b = cleanup(S5),
+ ?fatal({failed_validation, Reason}, S5b);
+ {error, Reason} ->
+ S5b = cleanup(S5),
+ ?fatal({failed_validation, Reason}, S5b);
+ {error, Reason, _Next} ->
+ S5b = cleanup(S5),
+ ?fatal({failed_validation, Reason}, S5b);
_XML ->
- {Res,cleanup(S5)}
+ {Res, cleanup(S5)}
end;
schema ->
- case schemaLocations(Res,S5) of
- {ok,Schemas} ->
+ case schemaLocations(Res, S5) of
+ {ok, Schemas} ->
cleanup(S5),
%%io:format("Schemas: ~p~nRes: ~p~ninhertih_options(S): ~p~n",
%% [Schemas,Res,inherit_options(S5)]),
- XSDRes = xmerl_xsd:process_validate(Schemas,Res,
+ XSDRes = xmerl_xsd:process_validate(Schemas, Res,
inherit_options(S5)),
- handle_schema_result(XSDRes,S5);
+ handle_schema_result(XSDRes, S5);
_ ->
- {Res,cleanup(S5)}
+ {Res, cleanup(S5)}
end;
_ ->
- {Res,cleanup(S5)}
+ {Res, cleanup(S5)}
end,
- {Res2, Tail, S6}.
+ Res3 =
+ case Document of
+ true ->
+ Content = lists:reverse(Prolog, [Res2 | lists:reverse(Misc)]),
+ #xmlDocument{content = Content};
+ false ->
+ Res2
+ end,
+ {Res3, Tail, S6}.
scan_decl(Str, S=#xmerl_scanner{event_fun = Event,
@@ -609,11 +638,11 @@ scan_decl(Str, S=#xmerl_scanner{event_fun = Event,
data = document}, S),
case scan_prolog(Str, S1, _StartPos = 1) of
- {T2="<"++_, S2} ->
+ {_,_,T2="<"++_, S2} ->
{{S2#xmerl_scanner.user_state,T2},[],S2};
- {[], S2}->
+ {_,_,[], S2}->
{[],[],S2};
- {T2, S2} ->
+ {_,_,T2, S2} ->
{_,_,S3} = scan_content(T2,S2,[],_Attrs=[],S2#xmerl_scanner.space,
_Lang=[],_Parents=[],#xmlNamespace{}),
{T2,[],S3}
@@ -624,14 +653,17 @@ scan_decl(Str, S=#xmerl_scanner{event_fun = Event,
%%% prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
%%%
%% empty text declarations are handled by the first function clause.
-scan_prolog([], S=#xmerl_scanner{continuation_fun = F}, Pos) ->
+scan_prolog(T, S, Pos) ->
+ scan_prolog(T, S, Pos, []).
+scan_prolog([], S=#xmerl_scanner{continuation_fun = F}, Pos, Acc) ->
?dbg("cont()...~n", []),
- F(fun(MoreBytes, S1) -> scan_prolog(MoreBytes, S1, Pos) end,
- fun(S1) -> {[], S1} end,
+ F(fun(MoreBytes, S1) -> scan_prolog(MoreBytes, S1, Pos, Acc) end,
+ fun(S1) -> {Acc, Pos, [], S1} end,
S);
-scan_prolog("<?xml"++T,S0=#xmerl_scanner{encoding=Charset0,col=Col,line=L},Pos)
- when ?whitespace(hd(T)) ->
- {Charset,T3, S3}=
+scan_prolog("<?xml"++T,
+ S0=#xmerl_scanner{encoding=Charset0,col=Col,line=L},
+ Pos,Acc) when ?whitespace(hd(T)) ->
+ {Charset, T3, S3} =
if
Col==1,L==1,S0#xmerl_scanner.text_decl==true ->
?dbg("prolog(\"<?xml\")~n", []),
@@ -639,13 +671,13 @@ scan_prolog("<?xml"++T,S0=#xmerl_scanner{encoding=Charset0,col=Col,line=L},Pos)
{_,T1,S1} = mandatory_strip(T,S),
{Decl,T2, S2}=scan_text_decl(T1,S1),
Encoding=Decl#xmlDecl.encoding,
- {Encoding,T2, S2#xmerl_scanner{encoding=Encoding}};
+ {Encoding, T2, S2#xmerl_scanner{encoding=Encoding}};
Col==1,L==1 ->
?dbg("prolog(\"<?xml\")~n", []),
?bump_col(5),
{Decl,T2, S2}=scan_xml_decl(T, S),
Encoding=Decl#xmlDecl.encoding,
- {Encoding,T2, S2#xmerl_scanner{encoding=Encoding}};
+ {Encoding, T2, S2#xmerl_scanner{encoding=Encoding}};
true ->
?fatal({xml_declaration_must_be_first_in_doc,Col,L},S0)
end,
@@ -659,7 +691,7 @@ scan_prolog("<?xml"++T,S0=#xmerl_scanner{encoding=Charset0,col=Col,line=L},Pos)
%% Now transform to declared character set.
if
Charset==Charset0 -> % Document already transformed to this charset!
- scan_prolog(T3, S3, Pos);
+ scan_prolog(T3, S3, Pos, Acc);
Charset0=/=undefined ->
%% For example may an external entity
%% have the BOM for utf-16 and the internal
@@ -668,17 +700,18 @@ scan_prolog("<?xml"++T,S0=#xmerl_scanner{encoding=Charset0,col=Col,line=L},Pos)
%% 'iso-10646-utf-1', and Charset will be 'utf-16', all
%% legal.
%%
- scan_prolog(T3,S3#xmerl_scanner{encoding=Charset0},Pos);
+ scan_prolog(T3,S3#xmerl_scanner{encoding=Charset0},Pos,Acc);
Charset == "utf-8" ->
- scan_prolog(T3, S3, Pos);
+ scan_prolog(T3, S3, Pos, Acc);
Charset=/=undefined -> % Document not previously transformed
T4=xmerl_ucs:to_unicode(T3,list_to_atom(Charset)),
- scan_prolog(T4, S3, Pos);
+ scan_prolog(T4, S3, Pos, Acc);
true -> % No encoding info given
- scan_prolog(T3, S3, Pos)
+ scan_prolog(T3, S3, Pos, Acc)
end;
-scan_prolog("<!DOCTYPE" ++ T, S0=#xmerl_scanner{environment=prolog,
- encoding=_Charset}, Pos) ->
+scan_prolog("<!DOCTYPE" ++ T,
+ S0=#xmerl_scanner{environment=prolog,encoding=_Charset},
+ Pos, Acc) ->
?dbg("prolog(\"<!DOCTYPE\")~n", []),
?bump_col(9),
%% If no known character set assume it is UTF-8
@@ -687,10 +720,13 @@ scan_prolog("<!DOCTYPE" ++ T, S0=#xmerl_scanner{environment=prolog,
true -> T
end,
{T2, S1} = scan_doctype(T1, S),
- scan_misc(T2, S1, Pos);
-scan_prolog(Str="%"++_T,S=#xmerl_scanner{environment={external,_}},_Pos) ->
- scan_ext_subset(Str,S);
-scan_prolog(Str, S0 = #xmerl_scanner{user_state=_US,encoding=_Charset},Pos) ->
+ scan_misc(T2, S1, Pos, Acc);
+scan_prolog(Str="%"++_T,S=#xmerl_scanner{environment={external,_}},
+ Pos,Acc) ->
+ {T, S1} = scan_ext_subset(Str,S),
+ {Acc, Pos, T, S1};
+scan_prolog(Str, S0 = #xmerl_scanner{user_state=_US,encoding=_Charset},
+ Pos,Acc) ->
?dbg("prolog(\"<\")~n", []),
%% Check for Comments, PI before possible DOCTYPE declaration
@@ -700,26 +736,28 @@ scan_prolog(Str, S0 = #xmerl_scanner{user_state=_US,encoding=_Charset},Pos) ->
%% Charset==undefined -> xmerl_ucs:to_unicode(Str,'utf-8');
true -> Str
end,
- {T1, S1}=scan_misc(T, S, Pos),
- scan_prolog2(T1,S1,Pos).
+ {Acc1, Pos1, T1, S1}=scan_misc(T, S, Pos, Acc),
+ scan_prolog2(T1,S1,Pos1,Acc1).
-scan_prolog2([], S=#xmerl_scanner{continuation_fun = F}, Pos) ->
+scan_prolog2([], S=#xmerl_scanner{continuation_fun = F}, Pos, Acc) ->
?dbg("cont()...~n", []),
- F(fun(MoreBytes, S1) -> scan_prolog2(MoreBytes, S1, Pos) end,
- fun(S1) -> {[], S1} end,
+ F(fun(MoreBytes, S1) -> scan_prolog2(MoreBytes, S1, Pos, Acc) end,
+ fun(S1) -> {Acc, Pos, [], S1} end,
S);
-scan_prolog2("<!DOCTYPE" ++ T, S0=#xmerl_scanner{environment=prolog}, Pos) ->
+scan_prolog2("<!DOCTYPE" ++ T, S0=#xmerl_scanner{environment=prolog},
+ Pos, Acc) ->
?dbg("prolog(\"<!DOCTYPE\")~n", []),
?bump_col(9),
{T1, S1} = scan_doctype(T, S),
- scan_misc(T1, S1, Pos);
-scan_prolog2(Str = "<!" ++ _, S, _Pos) ->
+ scan_misc(T1, S1, Pos, Acc);
+scan_prolog2(Str = "<!" ++ _, S, Pos, Acc) ->
?dbg("prolog(\"<!\")~n", []),
%% In e.g. a DTD, we jump directly to markup declarations
- scan_ext_subset(Str, S);
-scan_prolog2(Str, S0 = #xmerl_scanner{user_state=_US},Pos) ->
+ {T, S1} = scan_ext_subset(Str, S),
+ {Acc, Pos, T, S1};
+scan_prolog2(Str, S0 = #xmerl_scanner{user_state=_US},Pos,Acc) ->
?dbg("prolog(\"<\")~n", []),
%% Here we consider the DTD provided by doctype_DTD option,
@@ -733,7 +771,7 @@ scan_prolog2(Str, S0 = #xmerl_scanner{user_state=_US},Pos) ->
end,
%% Check for more Comments and PI after DOCTYPE declaration
% ?bump_col(1),
- scan_misc(Str, S1, Pos).
+ scan_misc(Str, S1, Pos, Acc).
@@ -743,26 +781,46 @@ scan_prolog2(Str, S0 = #xmerl_scanner{user_state=_US},Pos) ->
%% - Neither of Comment and PI are returned in the resulting parsed
%% structure.
%% - scan_misc/3 implements Misc* as that is how the rule is always used
-scan_misc([], S=#xmerl_scanner{continuation_fun = F}, Pos) ->
+scan_misc(T, S, Pos) ->
+ scan_misc(T, S, Pos, []).
+scan_misc([], S=#xmerl_scanner{continuation_fun = F}, Pos, Acc) ->
?dbg("cont()...~n", []),
- F(fun(MoreBytes, S1) -> scan_misc(MoreBytes, S1, Pos) end,
- fun(S1) -> {[], S1} end,
+ F(fun(MoreBytes, S1) -> scan_misc(MoreBytes, S1, Pos, Acc) end,
+ fun(S1) -> {Acc, Pos, [], S1} end,
S);
-scan_misc("<!--" ++ T, S0, Pos) -> % Comment
+scan_misc("<!--" ++ T, S0=#xmerl_scanner{acc_fun = F, comments=CF}, Pos, Acc) -> % Comment
?bump_col(4),
- {_, T1, S1} = scan_comment(T, S, Pos, _Parents = [], _Lang = []),
- scan_misc(T1,S1,Pos);
-scan_misc("<?" ++ T, S0, Pos) -> % PI
+ {C, T1, S1} = scan_comment(T, S, Pos, _Parents = [], _Lang = []),
+ case CF of
+ true ->
+ {Acc2, Pos2, S3} =
+ case F(C, Acc, S1) of
+ {Acc1, S2} ->
+ {Acc1, Pos + 1, S2};
+ {Acc1, Pos1, S2} ->
+ {Acc1, Pos1, S2}
+ end,
+ scan_misc(T1, S3, Pos2, Acc2);
+ false ->
+ scan_misc(T1, S1, Pos, Acc)
+ end;
+scan_misc("<?" ++ T, S0=#xmerl_scanner{acc_fun = F}, Pos, Acc) -> % PI
?dbg("prolog(\"<?\")~n", []),
?bump_col(2),
- {_PI, T1, S1} = scan_pi(T, S, Pos),
- scan_misc(T1,S1,Pos);
-scan_misc(T=[H|_T], S, Pos) when ?whitespace(H) ->
+ {PI, T1, S1} = scan_pi(T, S, Pos, []),
+ {Acc2, Pos2, S3} = case F(PI, Acc, S1) of
+ {Acc1, S2} ->
+ {Acc1, Pos + 1, S2};
+ {Acc1, Pos1, S2} ->
+ {Acc1, Pos1, S2}
+ end,
+ scan_misc(T1,S3,Pos2,Acc2);
+scan_misc(T=[H|_T], S, Pos, Acc) when ?whitespace(H) ->
?dbg("prolog(whitespace)~n", []),
{_,T1,S1}=strip(T,S),
- scan_misc(T1,S1,Pos);
-scan_misc(T,S,_Pos) ->
- {T,S}.
+ scan_misc(T1,S1,Pos,Acc);
+scan_misc(T,S,Pos,Acc) ->
+ {Acc,Pos,T,S}.
cleanup(S=#xmerl_scanner{keep_rules = false,
@@ -789,7 +847,8 @@ scan_xml_decl(T, S) ->
Attr = #xmlAttribute{name = version,
parents = [{xml, _XMLPos = 1}],
value = Vsn},
- scan_xml_decl(T4, S4, #xmlDecl{attributes = [Attr]}).
+ scan_xml_decl(T4, S4, #xmlDecl{vsn = Vsn,
+ attributes = [Attr]}).
scan_xml_decl([], S=#xmerl_scanner{continuation_fun = F}, Decl) ->
?dbg("cont()...~n", []),
@@ -1025,50 +1084,53 @@ xml_vsn([H|T], S=#xmerl_scanner{col = C}, Delim, Acc) ->
%%%%%%% [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
-scan_pi([], S=#xmerl_scanner{continuation_fun = F}, Pos) ->
+scan_pi([], S=#xmerl_scanner{continuation_fun = F}, Pos, Ps) ->
?dbg("cont()...~n", []),
- F(fun(MoreBytes, S1) -> scan_pi(MoreBytes, S1, Pos) end,
+ F(fun(MoreBytes, S1) -> scan_pi(MoreBytes, S1, Pos, Ps) end,
fun(S1) -> ?fatal(unexpected_end, S1) end,
S);
-scan_pi(Str = [H1,H2,H3 | T],S0=#xmerl_scanner{line = L, col = C}, Pos)
+scan_pi(Str = [H1,H2,H3 | T],S0=#xmerl_scanner{line = L, col = C}, Pos, Ps)
when H1==$x;H1==$X ->
%% names beginning with [xX][mM][lL] are reserved for future use.
?bump_col(3),
if
((H2==$m) or (H2==$M)) and
((H3==$l) or (H3==$L)) ->
- scan_wellknown_pi(T,S,Pos);
+ scan_wellknown_pi(T,S,Pos,Ps);
true ->
{Target, _NamespaceInfo, T1, S1} = scan_name(Str, S),
- scan_pi(T1, S1, Target, L, C, Pos, [])
+ scan_pi(T1, S1, Target, L, C, Pos, Ps, [])
end;
-scan_pi(Str, S=#xmerl_scanner{line = L, col = C}, Pos) ->
+scan_pi(Str, S=#xmerl_scanner{line = L, col = C}, Pos, Ps) ->
{Target, _NamespaceInfo, T1, S1} = scan_name(Str, S),
- scan_pi(T1, S1, Target, L, C, Pos,[]).
+ scan_pi(T1, S1, Target, L, C, Pos, Ps, []).
%%% More info on xml-stylesheet can be found at:
%%% "Associating Style Sheets with XML documents", Version 1.0,
%%% W3C Recommendation 29 June 1999 (http://www.w3.org/TR/xml-stylesheet/)
-scan_wellknown_pi("-stylesheet"++T, S0=#xmerl_scanner{line=L,col=C},Pos) ->
+scan_wellknown_pi("-stylesheet"++T, S0=#xmerl_scanner{line=L,col=C},Pos,Ps) ->
?dbg("prolog(\"<?xml-stylesheet\")~n", []),
?bump_col(16),
- scan_pi(T, S, "xml-stylesheet",L,C,Pos,[]);
-scan_wellknown_pi(Str,S,_Pos) ->
+ scan_pi(T, S, "xml-stylesheet",L,C,Pos,Ps,[]);
+scan_wellknown_pi(Str,S,_Pos,_Ps) ->
?fatal({invalid_target_name, lists:sublist(Str, 1, 10)}, S).
-scan_pi([], S=#xmerl_scanner{continuation_fun = F}, Target,L, C, Pos, Acc) ->
+scan_pi([], S=#xmerl_scanner{continuation_fun = F}, Target,
+ L, C, Pos, Ps, Acc) ->
?dbg("cont()...~n", []),
- F(fun(MoreBytes, S1) -> scan_pi(MoreBytes, S1, Target, L, C, Pos, Acc) end,
+ F(fun(MoreBytes, S1) -> scan_pi(MoreBytes, S1, Target,
+ L, C, Pos, Ps, Acc) end,
fun(S1) -> ?fatal(unexpected_end, S1) end,
S);
scan_pi("?>" ++ T, S0 = #xmerl_scanner{hook_fun = Hook,
event_fun = Event},
- Target, L, C, Pos, Acc) ->
+ Target, L, C, Pos, Ps, Acc) ->
?bump_col(2),
PI = #xmlPI{name = Target,
+ parents = Ps,
pos = Pos,
value = lists:reverse(Acc)},
S1 = #xmerl_scanner{} = Event(#xmerl_event{event = ended,
@@ -1077,22 +1139,25 @@ scan_pi("?>" ++ T, S0 = #xmerl_scanner{hook_fun = Hook,
data = PI}, S),
{Ret, S2} = Hook(PI, S1),
{Ret, T, S2};
-scan_pi([H|T], S, Target, L, C, Pos, Acc) when ?whitespace(H) ->
+scan_pi([H|T], S, Target, L, C, Pos, Ps, Acc) when ?whitespace(H) ->
?strip1,
- scan_pi2(T1, S1, Target, L, C, Pos, Acc);
-scan_pi([H|_T],S,_Target, _L, _C, _Pos, _Acc) ->
+ scan_pi2(T1, S1, Target, L, C, Pos, Ps, Acc);
+scan_pi([H|_T],S,_Target, _L, _C, _Pos, _Ps, _Acc) ->
?fatal({expected_whitespace_OR_end_of_PI,{char,H}}, S).
-scan_pi2([], S=#xmerl_scanner{continuation_fun = F}, Target,L, C, Pos, Acc) ->
+scan_pi2([], S=#xmerl_scanner{continuation_fun = F}, Target,
+ L, C, Pos, Ps, Acc) ->
?dbg("cont()...~n", []),
- F(fun(MoreBytes, S1) -> scan_pi2(MoreBytes, S1, Target, L, C, Pos, Acc) end,
+ F(fun(MoreBytes, S1) -> scan_pi2(MoreBytes, S1, Target,
+ L, C, Pos, Ps, Acc) end,
fun(S1) -> ?fatal(unexpected_end, S1) end,
S);
scan_pi2("?>" ++ T, S0 = #xmerl_scanner{hook_fun = Hook,
event_fun = Event},
- Target, L, C, Pos, Acc) ->
+ Target, L, C, Pos, Ps, Acc) ->
?bump_col(2),
PI = #xmlPI{name = Target,
+ parents = Ps,
pos = Pos,
value = lists:reverse(Acc)},
S1 = #xmerl_scanner{} = Event(#xmerl_event{event = ended,
@@ -1101,10 +1166,10 @@ scan_pi2("?>" ++ T, S0 = #xmerl_scanner{hook_fun = Hook,
data = PI}, S),
{Ret, S2} = Hook(PI, S1),
{Ret, T, S2};
-scan_pi2(Str, S0, Target, L, C, Pos, Acc) ->
+scan_pi2(Str, S0, Target, L, C, Pos, Ps, Acc) ->
?bump_col(1),
{Ch,T} = wfc_legal_char(Str,S),
- scan_pi2(T, S, Target, L, C, Pos, [Ch|Acc]).
+ scan_pi2(T, S, Target, L, C, Pos, Ps, [Ch|Acc]).
@@ -1575,7 +1640,7 @@ scan_markup_decl("<!--" ++ T, S0) ->
scan_comment(T, S);
scan_markup_decl("<?" ++ T, S0) ->
?bump_col(2),
- {_PI, T1, S1} = scan_pi(T, S,_Pos=markup),
+ {_PI, T1, S1} = scan_pi(T, S,_Pos=markup,[]),
strip(T1, S1);
scan_markup_decl("<!ELEMENT" ++ T,
#xmerl_scanner{rules_read_fun = Read,
@@ -1981,7 +2046,7 @@ scan_element(T, S, Pos) ->
scan_element(T, S=#xmerl_scanner{line=L,col=C},
Pos, SpaceDefault,Lang, Parents, NS) ->
{Name, NamespaceInfo, T1, S1} = scan_name(T, S),
- vc_Element_valid(Name,S),
+ vc_Element_valid(Name,NamespaceInfo,S),
?strip2,
scan_element(T2, S2, Pos, Name, L, C, _Attrs = [],
Lang, Parents, NamespaceInfo, NS,
@@ -2016,7 +2081,8 @@ scan_element("/>" ++ T, S0 = #xmerl_scanner{hook_fun = Hook,
Attrs = lists:reverse(Attrs0),
E=processed_whole_element(S, Pos, Name, Attrs, Lang, Parents,NSI,Namespace),
- wfc_unique_att_spec(Attrs,S),
+ #xmlElement{attributes = Attrs1} = E,
+ wfc_unique_att_spec(Attrs1,S),
S1 = #xmerl_scanner{} = Event(#xmerl_event{event = ended,
line = L,
col = C,
@@ -2074,10 +2140,10 @@ scan_element(T, S, Pos, Name, StartL, StartC, Attrs, Lang, Parents,
{AttName, NamespaceInfo, T1, S1} = scan_name(T, S),
{T2, S2} = scan_eq(T1, S1),
{AttType,_DefaultDecl} = get_att_type(S2,AttName,Name),
- {AttValue, T3, S3,IsNorm} = scan_att_value(T2, S2, AttType),
+ {AttValue, T3a, S3a,IsNorm} = scan_att_value(T2, S2, AttType),
%% check_default_value(S3,DefaultDecl,AttValue),
NewNS = check_namespace(AttName, NamespaceInfo, AttValue, NS),
- wfc_whitespace_betw_attrs(hd(T3),S3),
+ {T3,S3} = wfc_whitespace_betw_attrs(T3a,S3a),
?strip4,
AttrPos = case Attrs of
[] ->
@@ -2086,9 +2152,10 @@ scan_element(T, S, Pos, Name, StartL, StartC, Attrs, Lang, Parents,
P+1
end,
Attr = #xmlAttribute{name = AttName,
+ parents = [{Name, Pos}|Parents],
pos = AttrPos,
language = Lang,
- namespace = NamespaceInfo,
+ nsinfo = NamespaceInfo,
value = AttValue,
normalized = IsNorm},
XMLBase=if
@@ -2110,6 +2177,14 @@ scan_element(T, S, Pos, Name, StartL, StartC, Attrs, Lang, Parents,
scan_element(T4, S5, Pos, Name, StartL, StartC, [Attr|Attrs],
Lang, Parents, NSI, NewNS, SpaceDefault).
+get_default_attrs(S = #xmerl_scanner{rules_read_fun = Read}, ElemName) ->
+ case Read(elem_def, ElemName, S) of
+ #xmlElement{attributes = Attrs} ->
+ [ {AttName, AttValue} ||
+ {AttName, _, AttValue, _, _} <- Attrs, AttValue =/= no_value ];
+ _ -> []
+ end.
+
get_att_type(S=#xmerl_scanner{rules_read_fun=Read},AttName,ElemName) ->
case Read(elem_def,ElemName,S) of
#xmlElement{attributes = Attrs} ->
@@ -2139,6 +2214,23 @@ processed_whole_element(S=#xmerl_scanner{hook_fun = _Hook,
Pos, Name, Attrs, Lang, Parents, NSI, Namespace) ->
Language = check_language(Attrs, Lang),
+ AllAttrs =
+ case S#xmerl_scanner.default_attrs of
+ true ->
+ [ #xmlAttribute{name = AttName,
+ parents = [{Name, Pos} | Parents],
+ language = Lang,
+ nsinfo = NSI,
+ namespace = Namespace,
+ value = AttValue,
+ normalized = true} ||
+ {AttName, AttValue} <- get_default_attrs(S, Name),
+ AttValue =/= no_value,
+ not lists:keymember(AttName, #xmlAttribute.name, Attrs) ];
+ false ->
+ Attrs
+ end,
+
{ExpName, ExpAttrs} =
case S#xmerl_scanner.namespace_conformant of
true ->
@@ -2153,14 +2245,15 @@ processed_whole_element(S=#xmerl_scanner{hook_fun = _Hook,
TempNamespace = Namespace#xmlNamespace{default = []},
ExpAttrsX =
[A#xmlAttribute{
+ namespace=Namespace,
expanded_name=expanded_name(
A#xmlAttribute.name,
- A#xmlAttribute.namespace,
+ A#xmlAttribute.nsinfo,
% NSI,
- TempNamespace, S)} || A <- Attrs],
+ TempNamespace, S)} || A <- AllAttrs],
{expanded_name(Name, NSI, Namespace, S), ExpAttrsX};
false ->
- {Name, Attrs}
+ {Name, AllAttrs}
end,
#xmlElement{name = Name,
@@ -2194,10 +2287,32 @@ check_namespace(_, _, _, NS) ->
expanded_name(Name, [], #xmlNamespace{default = []}, _S) ->
Name;
-expanded_name(Name, [], #xmlNamespace{default = URI}, _S) ->
- {URI, Name};
-expanded_name(_Name, {"xmlns", Local}, _NS, _S) -> % CHECK THIS /JB
- {"xmlns",Local};
+expanded_name(Name, [], #xmlNamespace{default = URI}, S) ->
+ case URI of
+ 'http://www.w3.org/XML/1998/namespace' ->
+ ?fatal(cannot_bind_default_namespace_to_xml_namespace_name, S);
+ 'http://www.w3.org/2000/xmlns/' ->
+ ?fatal(cannot_bind_default_namespace_to_xmlns_namespace_name, S);
+ _ ->
+ {URI, Name}
+ end;
+expanded_name(Name, N = {"xmlns", Local}, #xmlNamespace{nodes = Ns}, S) ->
+ {_, Value} = lists:keyfind(Local, 1, Ns),
+ case Name of
+ 'xmlns:xml' when Value =/= 'http://www.w3.org/XML/1998/namespace' ->
+ ?fatal({xml_prefix_cannot_be_redeclared, Value}, S);
+ 'xmlns:xmlns' ->
+ ?fatal({xmlns_prefix_cannot_be_declared, Value}, S);
+ _ ->
+ case Value of
+ 'http://www.w3.org/XML/1998/namespace' ->
+ ?fatal({cannot_bind_prefix_to_xml_namespace, Local}, S);
+ 'http://www.w3.org/2000/xmlns/' ->
+ ?fatal({cannot_bind_prefix_to_xmlns_namespace, Local}, S);
+ _ ->
+ N
+ end
+ end;
expanded_name(_Name, {Prefix, Local}, #xmlNamespace{nodes = Ns}, S) ->
case lists:keysearch(Prefix, 1, Ns) of
{value, {_, URI}} ->
@@ -2276,7 +2391,7 @@ scan_att_chars([H|T], S0, H, Acc, TmpAcc,AttType,IsNorm) -> % End quote
true ->
normalize(Acc,S,IsNorm)
end,
- {lists:reverse(Acc2), T, S2,IsNorm2};
+ {lists:flatten(lists:reverse(Acc2)), T, S2,IsNorm2};
scan_att_chars("&" ++ T, S0, Delim, Acc, TmpAcc,AT,IsNorm) -> % Reference
?bump_col(1),
{ExpRef, T1, S1} = scan_reference(T, S),
@@ -2449,9 +2564,23 @@ scan_content("&" ++ T, S0, Pos, Name, Attrs, Space, Lang, Parents, NS, Acc,[]) -
_ ->
scan_content(string_to_char_set(S1#xmerl_scanner.encoding,ExpRef)++T1,S1,Pos,Name,Attrs,Space,Lang,Parents,NS,Acc,[])
end;
-scan_content("<!--" ++ T, S, Pos, Name, Attrs, Space, Lang, Parents, NS, Acc,[]) ->
- {_, T1, S1} = scan_comment(T, S, Pos, Parents, Lang),
- scan_content(T1, S1, Pos+1, Name, Attrs, Space, Lang, Parents, NS, Acc,[]);
+scan_content("<!--" ++ T, S0=#xmerl_scanner{acc_fun = F, comments=CF}, Pos, Name, Attrs, Space,
+ Lang, Parents, NS, Acc,[]) ->
+ ?bump_col(4),
+ {C, T1, S1} = scan_comment(T, S, Pos, Parents, Lang),
+ case CF of
+ true ->
+ {Acc2, Pos2, S3} =
+ case F(C, Acc, S1) of
+ {Acc1, S2} ->
+ {Acc1, Pos + 1, S2};
+ {Acc1, Pos1, S2} ->
+ {Acc1, Pos1, S2}
+ end,
+ scan_content(T1, S3, Pos2, Name, Attrs, Space, Lang, Parents, NS, Acc2,[]);
+ false ->
+ scan_content(T1, S1, Pos, Name, Attrs, Space, Lang, Parents, NS, Acc,[])
+ end;
scan_content("<" ++ T, S0, Pos, Name, Attrs, Space, Lang, Parents, NS, Acc,[]) ->
?bump_col(1),
{Markup, T1, S1} =
@@ -2508,9 +2637,9 @@ scan_content_markup("![CDATA[" ++ T, S0, Pos, _Name, _Attrs,
_Space, _Lang, Parents, _NS) ->
?bump_col(8),
scan_cdata(T, S, Pos, Parents);
-scan_content_markup("?"++T,S0,Pos,_Name,_Attrs,_Space,_Lang,_Parents,_NS) ->
+scan_content_markup("?"++T,S0,Pos,_Name,_Attrs,_Space,_Lang,Parents,_NS) ->
?bump_col(1),
- scan_pi(T, S, Pos);
+ scan_pi(T, S, Pos, Parents);
scan_content_markup(T, S, Pos, _Name, _Attrs, Space, Lang, Parents, NS) ->
scan_element(T, S, Pos, Space, Lang, Parents, NS).
@@ -3259,12 +3388,18 @@ mandatory_delimeter_wfc(T,S) ->
wfc_unique_att_spec([],_S) ->
ok;
-wfc_unique_att_spec([#xmlAttribute{name=N}|Atts],S) ->
+wfc_unique_att_spec([#xmlAttribute{name=N,expanded_name=EN}|Atts],S) ->
case lists:keymember(N,#xmlAttribute.name,Atts) of
true ->
?fatal({error,{unique_att_spec_required,N}},S);
_ ->
- wfc_unique_att_spec(Atts,S)
+ case S#xmerl_scanner.namespace_conformant andalso
+ lists:keymember(EN, #xmlAttribute.expanded_name, Atts) of
+ true ->
+ ?fatal({error,{unique_att_spec_required,EN}},S);
+ _ ->
+ wfc_unique_att_spec(Atts,S)
+ end
end.
wfc_legal_char(Chars,S) when is_list(Chars)->
@@ -3284,12 +3419,17 @@ wfc_legal_char(Ch,S) ->
end.
-wfc_whitespace_betw_attrs(WS,_S) when ?whitespace(WS) ->
- ok;
-wfc_whitespace_betw_attrs($/,_S) ->
- ok;
-wfc_whitespace_betw_attrs($>,_S) ->
- ok;
+wfc_whitespace_betw_attrs([WS |_]=L,S) when ?whitespace(WS) ->
+ {L,S};
+wfc_whitespace_betw_attrs([$/ |_]=L,S) ->
+ {L,S};
+wfc_whitespace_betw_attrs([$> |_]=L,S) ->
+ {L,S};
+wfc_whitespace_betw_attrs([],S=#xmerl_scanner{continuation_fun = F}) ->
+ ?dbg("cont()...~n", []),
+ F(fun(MoreBytes, S1) -> wfc_whitespace_betw_attrs(MoreBytes, S1) end,
+ fun(S1) -> ?fatal(unexpected_end, S1) end,
+ S);
wfc_whitespace_betw_attrs(_,S) ->
?fatal({whitespace_required_between_attributes},S).
@@ -3308,6 +3448,11 @@ wfc_Internal_parsed_entity(internal,Value,S) ->
wfc_Internal_parsed_entity(_,_,_) ->
ok.
+vc_Element_valid(_Name, {"xmlns", _},
+ S = #xmerl_scanner{namespace_conformant = true}) ->
+ ?fatal({error,{illegal_element_prefix,xmlns}},S);
+vc_Element_valid(Name, _, S) ->
+ vc_Element_valid(Name, S).
vc_Element_valid(_Name,#xmerl_scanner{environment=internal_parsed_entity}) ->
ok;
@@ -3912,7 +4057,7 @@ schemaLocations(El,#xmerl_scanner{schemaLocation=SL}) ->
schemaLocations(#xmlElement{attributes=Atts,xmlbase=_Base}) ->
Pred = fun(#xmlAttribute{name=schemaLocation}) -> false;
- (#xmlAttribute{namespace={_,"schemaLocation"}}) -> false;
+ (#xmlAttribute{nsinfo={_,"schemaLocation"}}) -> false;
(_) -> true
end,
case lists:dropwhile(Pred,Atts) of
diff --git a/lib/xmerl/src/xmerl_ucs.erl b/lib/xmerl/src/xmerl_ucs.erl
index 7c45c838ab..6550a9d954 100644
--- a/lib/xmerl/src/xmerl_ucs.erl
+++ b/lib/xmerl/src/xmerl_ucs.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -43,6 +43,7 @@
-export([to_utf16be/1, from_utf16be/1, from_utf16be/2]).
-export([to_utf16le/1, from_utf16le/1, from_utf16le/2]).
-export([to_utf8/1, from_utf8/1]).
+-export([from_latin9/1]).
%%% NB: Non-canonical UTF-8 encodings and incorrectly used
%%% surrogate-pair codes are disallowed by this code. There are
@@ -177,13 +178,27 @@ to_utf8(List) when is_list(List) -> lists:flatmap(fun to_utf8/1, List);
to_utf8(Ch) -> char_to_utf8(Ch).
from_utf8(Bin) when is_binary(Bin) -> from_utf8(binary_to_list(Bin));
-from_utf8(List) ->
+from_utf8(List) ->
case expand_utf8(List) of
{Result,0} -> Result;
{_Res,_NumBadChar} ->
exit({ucs,{bad_utf8_character_code}})
end.
+%%% Latin9 support
+from_latin9(Bin) when is_binary(Bin) -> from_latin9(binary_to_list(Bin));
+from_latin9(List) ->
+ [ latin9_to_ucs4(Char) || Char <- List].
+
+latin9_to_ucs4(16#A4) -> 16#20AC;
+latin9_to_ucs4(16#A6) -> 16#160;
+latin9_to_ucs4(16#A8) -> 16#161;
+latin9_to_ucs4(16#B4) -> 16#17D;
+latin9_to_ucs4(16#B8) -> 16#17E;
+latin9_to_ucs4(16#BC) -> 16#152;
+latin9_to_ucs4(16#BD) -> 16#153;
+latin9_to_ucs4(16#BE) -> 16#178;
+latin9_to_ucs4(Other) -> Other.
@@ -238,7 +253,7 @@ from_ucs4le(Bin,Acc,Tail) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% UCS-2 support
-%%% FIXME! Don't know how to encode UCS-2!!
+%%% FIXME! Don't know how to encode UCS-2!!
%%% Currently I just encode as UCS-4, but strips the 16 higher bits.
char_to_ucs2be(Ch) ->
true = is_iso10646(Ch),
@@ -259,15 +274,15 @@ from_ucs2be(Bin,Acc,Tail) ->
char_to_ucs2le(Ch) ->
true = is_iso10646(Ch),
- [(Ch bsr 16) band 16#FF,
- (Ch bsr 24)].
+ [Ch band 16#FF,
+ (Ch bsr 8) band 16#FF].
from_ucs2le(<<Ch:16/little-signed-integer, Rest/binary>>,Acc,Tail) ->
if Ch < 0; Ch >= 16#D800, Ch < 16#E000; Ch =:= 16#FFFE; Ch =:= 16#FFFF ->
exit({bad_character_code,Ch});
true ->
- from_ucs4le(Rest,[Ch|Acc],Tail)
+ from_ucs2le(Rest,[Ch|Acc],Tail)
end;
from_ucs2le(<<>>,Acc,Tail) ->
lists:reverse(Acc,Tail);
@@ -476,6 +491,8 @@ to_unicode(Input,Cs) when Cs=='iso_8859-1:1987';Cs=='iso-ir-100';
Cs=='l1';Cs=='ibm819';
Cs=='cp819';Cs=='csisolatin1' ->
Input;
+to_unicode(Input,Cs) when Cs=='iso_8859-15';Cs=='iso-8859-15';Cs=='latin9' ->
+ from_latin9(Input);
% to_unicode(Input,Cs) when Cs=='mnemonic';Cs=='"mnemonic+ascii+38';
% Cs=='mnem';Cs=='"mnemonic+ascii+8200' ->
% from_mnemonic(Input);
diff --git a/lib/xmerl/src/xmerl_validate.erl b/lib/xmerl/src/xmerl_validate.erl
index 893e23ca34..4028fef2b9 100644
--- a/lib/xmerl/src/xmerl_validate.erl
+++ b/lib/xmerl/src/xmerl_validate.erl
@@ -399,25 +399,28 @@ test_attribute_value(_Rule,Attr,_,_) ->
%% +type valid_contents([rule()],[xmlElement()])->
%% [xmlElement() | {error,???}.
-valid_contents(Rule,XMLS,Rules,S,WSActionMode)->
- case parse(Rule,XMLS,Rules,WSActionMode,S) of
- {XML_N,[]}->
- lists:flatten(XML_N);
- {_,[#xmlElement{name=Name}|_T]} ->
- exit({error,{element,Name,isnt_comprise_in_the_rule,Rule}});
- {_,[#xmlText{}=Txt|_T]} ->
- exit({error,{element,text,Txt,isnt_comprise_in_the_rule,Rule}});
- {error,Reason} ->
- {error,Reason};
- {error,Reason,N} ->
- {error,Reason,N}
+valid_contents(Rule, XMLS, Rules, S, WSActionMode)->
+ case parse(Rule, XMLS, Rules, WSActionMode, S) of
+ {error, Reason} ->
+ {error, Reason};
+ {error, Reason, N} ->
+ {error, Reason, N};
+ {XML_N, Rest} -> %The list may consist of xmlComment{} records
+ case lists:dropwhile(fun(X) when is_record(X, xmlComment) -> true; (_) -> false end, Rest) of
+ [] ->
+ lists:flatten(XML_N);
+ [#xmlElement{name=Name} |_T] ->
+ exit({error, {element, Name, isnt_comprise_in_the_rule, Rule}});
+ [#xmlText{} = Txt |_T] ->
+ exit({error, {element, text, Txt, isnt_comprise_in_the_rule, Rule}})
+ end
end.
-parse({'*',SubRule},XMLS,Rules,WSaction,S)->
- star(SubRule,XMLS,Rules,WSaction,[],S);
-parse({'+',SubRule},XMLS,Rules,WSaction,S) ->
- plus(SubRule,XMLS,Rules,WSaction,S);
-parse({choice,CHOICE},XMLS,Rules,WSaction,S)->
+parse({'*', SubRule}, XMLS, Rules, WSaction, S)->
+ star(SubRule, XMLS, Rules, WSaction, [], S);
+parse({'+',SubRule}, XMLS, Rules, WSaction, S) ->
+ plus(SubRule, XMLS, Rules, WSaction, S);
+parse({choice,CHOICE}, XMLS, Rules, WSaction, S)->
% case XMLS of
% [] ->
% io:format("~p~n",[{choice,CHOICE,[]}]);
@@ -426,47 +429,49 @@ parse({choice,CHOICE},XMLS,Rules,WSaction,S)->
% [#xmlText{value=V}|_] ->
% io:format("~p~n",[{choice,CHOICE,{text,V}}])
% end,
- choice(CHOICE,XMLS,Rules,WSaction,S);
-parse(empty,[],_Rules,_WSaction,_S) ->
- {[],[]};
-parse({'?',SubRule},XMLS,Rules,_WSaction,S)->
- question(SubRule,XMLS,Rules,S);
-parse({seq,List},XMLS,Rules,WSaction,S) ->
- seq(List,XMLS,Rules,WSaction,S);
-parse(El_Name,[#xmlElement{name=El_Name}=XML|T],Rules,_WSaction,S)
+ choice(CHOICE, XMLS, Rules, WSaction, S);
+parse(empty, [], _Rules, _WSaction, _S) ->
+ {[], []};
+parse({'?', SubRule}, XMLS, Rules, _WSaction, S)->
+ question(SubRule, XMLS, Rules, S);
+parse({seq,List}, XMLS, Rules, WSaction, S) ->
+ seq(List, XMLS, Rules, WSaction, S);
+parse(El_Name, [#xmlElement{name=El_Name} = XML |T], Rules, _WSaction, S)
when is_atom(El_Name)->
- case do_validation(read_rules(Rules,El_Name),XML,Rules,S) of
- {error,R} ->
+ case do_validation(read_rules(Rules, El_Name), XML, Rules, S) of
+ {error, R} ->
% {error,R};
exit(R);
- {error,R,_N}->
+ {error, R, _N}->
% {error,R,N};
exit(R);
XML_->
- {[XML_],T}
+ {[XML_], T}
end;
-parse(any,Cont,Rules,_WSaction,S) ->
- case catch parse_any(Cont,Rules,S) of
- Err = {error,_} -> Err;
- ValidContents -> {ValidContents,[]}
+parse(any, Cont, Rules, _WSaction, S) ->
+ case catch parse_any(Cont, Rules, S) of
+ Err = {error, _} -> Err;
+ ValidContents -> {ValidContents, []}
end;
-parse(El_Name,[#xmlElement{name=Name}|_T]=S,_Rules,_WSa,_S) when is_atom(El_Name)->
+parse(El_Name, [#xmlElement{name=Name} |_T] = XMLS, _Rules, _WSa, _S) when is_atom(El_Name) ->
{error,
- {element_seq_not_conform,{wait,El_Name},{is,Name}},
- {{next,S},{act,[]}} };
-parse(_El_Name,[#xmlPI{}=H|T],_Rules,_WSa,_S) ->
- {[H],T};
-parse('#PCDATA',XML,_Rules,_WSa,_S)->
+ {element_seq_not_conform,{wait, El_Name}, {is, Name}},
+ {{next, XMLS}, {act, []}}};
+parse(El_Name, [#xmlComment{} |T], Rules, WSa, S) ->
+ parse(El_Name, T, Rules, WSa, S);
+parse(_El_Name, [#xmlPI{} = H |T], _Rules, _WSa, _S) ->
+ {[H], T};
+parse('#PCDATA', XMLS, _Rules, _WSa, _S)->
%%% PCDATA it is 0 , 1 or more #xmlText{}.
- parse_pcdata(XML);
-parse(El_Name,[#xmlText{}|_T]=S,_Rules,_WSa,_S)->
+ parse_pcdata(XMLS);
+parse(El_Name, [#xmlText{}|_T] = XMLS, _Rules, _WSa, _S)->
{error,
- {text_in_place_of,El_Name},
- {{next,S},{act,[]}}};
-parse([],_,_,_,_) ->
- {error,no_rule};
-parse(Rule,[],_,_,_) ->
- {error,{no_xml_element,Rule}}.
+ {text_in_place_of, El_Name},
+ {{next, XMLS}, {act, []}}};
+parse([], _, _, _, _) ->
+ {error, no_rule};
+parse(Rule, [], _, _, _) ->
+ {error, {no_xml_element, Rule}}.
parse_any([],_Rules,_S) ->
[];
@@ -618,11 +623,15 @@ el_name(#xmlElement{name=Name})->
parse_pcdata([#xmlText{}=H|T])->
parse_pcdata(T,[H]);
+parse_pcdata([#xmlComment{}|T])->
+ parse_pcdata(T,[]);
parse_pcdata(H) ->
{[],H}.
parse_pcdata([#xmlText{}=H|T],Acc)->
parse_pcdata(T,Acc++[H]);
+parse_pcdata([#xmlComment{}|T],Acc)->
+ parse_pcdata(T,Acc);
parse_pcdata(H,Acc) ->
{Acc,H}.
diff --git a/lib/xmerl/src/xmerl_xpath.erl b/lib/xmerl/src/xmerl_xpath.erl
index db3d3ac2d6..b3301f2faf 100644
--- a/lib/xmerl/src/xmerl_xpath.erl
+++ b/lib/xmerl/src/xmerl_xpath.erl
@@ -41,18 +41,13 @@
% xmerl_xpath_parse:parse(xmerl_xpath_scan:tokens("parent::processing-instruction('foo')")).
%% </pre>
%%
-%% @type docEntity() =
+%% @type nodeEntity() =
%% xmlElement()
%% | xmlAttribute()
%% | xmlText()
%% | xmlPI()
%% | xmlComment()
-%% @type nodeEntity() =
-%% xmlElement()
-%% | xmlAttribute()
-%% | xmlText()
-%% | xmlPI()
-%% | xmlNamespace()
+%% | xmlNsNode()
%% | xmlDocument()
%% @type option_list(). <p>Options allows to customize the behaviour of the
%% XPath scanner.
@@ -303,6 +298,17 @@ write_node(#xmlNode{pos = Pos,
node = #xmlText{value = Txt,
parents = Ps}}) ->
{text, Pos, Txt, Ps};
+write_node(#xmlNode{pos = Pos,
+ node = #xmlComment{parents = Ps}}) ->
+ {comment, Pos, '', Ps};
+write_node(#xmlNode{pos = Pos,
+ node = #xmlPI{name = Name,
+ parents = Ps}}) ->
+ {processing_instruction, Pos, Name, Ps};
+write_node(#xmlNode{pos = Pos,
+ node = #xmlNsNode{parents = Ps,
+ prefix = Prefix}}) ->
+ {namespace, Pos, Prefix, Ps};
write_node(_) ->
other.
@@ -330,18 +336,16 @@ eval_path(rel, PathExpr, C = #xmlContext{}) ->
Context = C#xmlContext{nodeset = NodeSet},
S = #state{context = Context},
path_expr(PathExpr, S);
-eval_path(filter, {PathExpr, PredExpr}, C = #xmlContext{}) ->
+eval_path(filter, {PathExpr, {pred, Pred}}, C = #xmlContext{}) ->
S = #state{context = C},
- S1 = path_expr(PathExpr, S),
- pred_expr(PredExpr, S1).
+ S1 = match_expr(PathExpr, S),
+ eval_pred(Pred, S1).
-eval_primary_expr(FC = {function_call,_,_},S = #state{context = Context}) ->
+eval_primary_expr(PrimExpr, S = #state{context = Context}) ->
%% NewNodeSet = xmerl_xpath_pred:eval(FC, Context),
- NewNodeSet = xmerl_xpath_lib:eval(primary_expr, FC, Context),
+ NewNodeSet = xmerl_xpath_lib:eval(primary_expr, PrimExpr, Context),
NewContext = Context#xmlContext{nodeset = NewNodeSet},
- S#state{context = NewContext};
-eval_primary_expr(PrimExpr,_S) ->
- exit({primary_expression,{not_implemented, PrimExpr}}).
+ S#state{context = NewContext}.
%% axis(Axis,NodeTest,Context::xmlContext()) -> xmlContext()
@@ -384,8 +388,8 @@ axis1(preceding, Tok, N, Acc, Context) ->
match_preceding(Tok, N, Acc, Context);
axis1(attribute, Tok, N, Acc, Context) ->
match_attribute(Tok, N, Acc, Context);
-%axis1(namespace, Tok, N, Acc, Context) ->
-% match_namespace(Tok, N, Acc, Context);
+axis1(namespace, Tok, N, Acc, Context) ->
+ match_namespace(Tok, N, Acc, Context);
axis1(ancestor_or_self, Tok, N, Acc, Context) ->
match_ancestor_or_self(Tok, N, Acc, Context);
axis1(descendant_or_self, Tok, N, Acc, Context) ->
@@ -627,14 +631,58 @@ node_type(#xmlAttribute{}) -> attribute;
node_type(#xmlElement{}) -> element;
node_type(#xmlText{}) -> text;
node_type(#xmlPI{}) -> processing_instruction;
-node_type(#xmlNamespace{}) -> namespace;
+node_type(#xmlNsNode{}) -> namespace;
+node_type(#xmlComment{}) -> comment;
node_type(#xmlDocument{}) -> root_node.
%% "The namespace axis contains the namespace nodes of the context node;
%% the axis will be empty unless the context node is an element."
-%match_namespace(_Tok, _N, _Acc, _Context) ->
- %% TODO: IMPLEMENT NAMESPACE AXIS
-% erlang:fault(not_yet_implemented).
+match_namespace(Tok, N, Acc, Context) ->
+ case N#xmlNode.type of
+ element ->
+ #xmlNode{parents = Ps, node = E} = N,
+ #xmlElement{name = Name,
+ namespace = NS,
+ parents = EPs,
+ pos = Pos} = E,
+ #xmlNamespace{default = Default, nodes = NSPairs} = NS,
+ ThisEPs = [{Name, Pos}|EPs],
+ ThisPs = [N|Ps],
+ Acc0 =
+ case Default of
+ D when D =:= []; D =:= '' ->
+ {[], 1};
+ URI ->
+ DefaultNSNode = #xmlNsNode{parents = ThisEPs,
+ pos = 1,
+ prefix = [],
+ uri = URI},
+ Node = #xmlNode{type = namespace,
+ node = DefaultNSNode,
+ parents = ThisPs},
+ {[Node], 2}
+ end,
+ {Nodes, _I} =
+ lists:foldr(
+ fun ({Prefix, URI}, {AccX, I}) ->
+ NSNode = #xmlNsNode{parents = ThisEPs,
+ pos = I,
+ prefix = Prefix,
+ uri = URI},
+ ThisN = #xmlNode{pos = I,
+ type = namespace,
+ node = NSNode,
+ parents = ThisPs},
+ {[ThisN | AccX], I + 1}
+ end, Acc0, NSPairs),
+ lists:foldr(
+ fun (ThisN, AccX) ->
+ match_self(Tok, ThisN, AccX, Context)
+ end, Acc, Nodes);
+ _Other ->
+ %%[]
+ Acc
+ end.
update_nodeset(Context = #xmlContext{axis_type = AxisType}, NodeSet) ->
@@ -655,8 +703,15 @@ update_nodeset(Context = #xmlContext{axis_type = AxisType}, NodeSet) ->
node_test(F, N, Context) when is_function(F) ->
F(N, Context);
+node_test(_Test, #xmlNode{type=attribute,node=#xmlAttribute{name=xmlns}},
+ _Context) ->
+ false;
+node_test(_Test,
+ #xmlNode{type=attribute,node=#xmlAttribute{nsinfo={"xmlns",_Local}}},
+ _Context) ->
+ false;
node_test({wildcard, _}, #xmlNode{type=ElAt}, _Context)
- when ElAt==element; ElAt==attribute ->
+ when ElAt==element; ElAt==attribute; ElAt==namespace ->
true;
node_test({prefix_test, Prefix}, #xmlNode{node = N}, _Context) ->
case N of
@@ -720,6 +775,9 @@ node_test({name, {_Tag, Prefix, Local}},
[{_Tag, Prefix, Local}, write_node(NSNodes)]),
false
end;
+node_test({name, {_Tag, [], Local}},
+ #xmlNode{node = #xmlNsNode{prefix = Local}}, _Context) ->
+ true;
node_test({node_type, NT}, #xmlNode{node = N}, _Context) ->
case {NT, N} of
{text, #xmlText{}} ->
@@ -728,14 +786,18 @@ node_test({node_type, NT}, #xmlNode{node = N}, _Context) ->
true;
{attribute, #xmlAttribute{}} ->
true;
- {namespace, #xmlNamespace{}} ->
+ {namespace, #xmlNsNode{}} ->
+ true;
+ {comment, #xmlComment{}} ->
+ true;
+ {processing_instruction, #xmlPI{}} ->
true;
_ ->
false
end;
-node_test({processing_instruction, {literal, _, Name}},
- #xmlNode{node = {processing_instruction, Name, _Data}}, _Context) ->
- true;
+node_test({processing_instruction, Name1},
+ #xmlNode{node = #xmlPI{name = Name2}}, _Context) ->
+ Name1 == atom_to_list(Name2);
node_test(_Other, _N, _Context) ->
%io:format("node_test(~p, ~p) -> false.~n", [_Other, write_node(_N)]),
false.
diff --git a/lib/xmerl/src/xmerl_xpath_lib.erl b/lib/xmerl/src/xmerl_xpath_lib.erl
index cfd0e36667..096f54ec30 100644
--- a/lib/xmerl/src/xmerl_xpath_lib.erl
+++ b/lib/xmerl/src/xmerl_xpath_lib.erl
@@ -49,5 +49,7 @@ primary_expr({function_call, F, Args}, C) ->
%% here, we should look up the function in the context provided
%% by the caller, but we haven't figured this out yet.
exit({not_a_core_function, F})
- end.
+ end;
+primary_expr(PrimExpr, _C) ->
+ exit({primary_expression, {not_implemented, PrimExpr}}).
diff --git a/lib/xmerl/src/xmerl_xpath_parse.yrl b/lib/xmerl/src/xmerl_xpath_parse.yrl
index 37576b9e61..f60cea0a2e 100644
--- a/lib/xmerl/src/xmerl_xpath_parse.yrl
+++ b/lib/xmerl/src/xmerl_xpath_parse.yrl
@@ -144,6 +144,7 @@ Expect 2.
%% [7]
'NodeTest' -> 'NameTest' : '$1' .
'NodeTest' -> 'node_type' '(' ')' : {node_type, value('$1')} .
+'NodeTest' -> 'processing-instruction' '(' ')' : {node_type, value('$1')} .
'NodeTest' -> 'processing-instruction' '(' 'literal' ')'
: {processing_instruction, value('$3')} .
diff --git a/lib/xmerl/src/xmerl_xpath_pred.erl b/lib/xmerl/src/xmerl_xpath_pred.erl
index 451a09bee3..855b8599fe 100644
--- a/lib/xmerl/src/xmerl_xpath_pred.erl
+++ b/lib/xmerl/src/xmerl_xpath_pred.erl
@@ -337,6 +337,9 @@ local_name1([#xmlNode{type=element,node=El}|_]) ->
local_name1([#xmlNode{type=attribute,node=Att}|_]) ->
#xmlAttribute{name=Name,nsinfo=NSI} = Att,
local_name2(Name,NSI);
+local_name1([#xmlNode{type=namespace,node=N}|_]) ->
+ #xmlNsNode{prefix=Prefix} = N,
+ ?string(Prefix);
local_name1([#xmlElement{name = Name, nsinfo = NSI}|_]) ->
local_name2(Name,NSI).
local_name2(Name, NSI) ->
@@ -431,6 +434,9 @@ string_value(N=#xmlObj{}) ->
string_value(A=#xmlNode{type=attribute}) ->
#xmlAttribute{value=AttVal}=A#xmlNode.node,
?string(AttVal);
+string_value(N=#xmlNode{type=namespace}) ->
+ #xmlNsNode{uri=URI}=N#xmlNode.node,
+ ?string(atom_to_list(URI));
string_value(El=#xmlNode{type=element}) ->
#xmlElement{content=C} = El#xmlNode.node,
TextValue = fun(#xmlText{value=T},_Fun) -> T;
@@ -442,6 +448,9 @@ string_value(El=#xmlNode{type=element}) ->
string_value(T=#xmlNode{type=text}) ->
#xmlText{value=Txt} = T#xmlNode.node,
?string(Txt);
+string_value(T=#xmlNode{type=comment}) ->
+ #xmlComment{value=Txt} = T#xmlNode.node,
+ ?string(Txt);
string_value(infinity) -> ?string("Infinity");
string_value(neg_infinity) -> ?string("-Infinity");
string_value(A) when is_atom(A) ->
diff --git a/lib/xmerl/src/xmerl_xsd.erl b/lib/xmerl/src/xmerl_xsd.erl
index e56f1470c0..ed0890f0d0 100644
--- a/lib/xmerl/src/xmerl_xsd.erl
+++ b/lib/xmerl/src/xmerl_xsd.erl
@@ -245,21 +245,27 @@ process_validate2({SE,_},Schema,Xml,Opts) ->
S4 = validation_options(S3,Opts),
validate3(Schema,Xml,S4).
-validate3(Schema,Xml,S=#xsd_state{errors=[]}) ->
- Ret = {_,S2} =
- case catch validate_xml(Xml,S) of
- {[XML2],[],Sx} ->
- {XML2,Sx};
- {XML2,[],Sx} ->
- {XML2,Sx};
- {_,UnValidated,Sx} ->
- {Xml,acc_errs(Sx,{error_path(UnValidated,Xml#xmlElement.name),?MODULE,
- {unvalidated_rest,UnValidated}})};
- _Err = {error,Reason} ->
- {Xml,acc_errs(S,Reason)};
- {'EXIT',Reason} ->
- {Xml,acc_errs(S,{error_path(Xml,Xml#xmlElement.name),?MODULE,
- {undefined,{internal_error,Reason}}})}
+validate3(Schema, Xml,S =#xsd_state{errors=[]}) ->
+ Ret = {_, S2} =
+ case catch validate_xml(Xml, S) of
+ _Err = {error, Reason} ->
+ {Xml, acc_errs(S, Reason)};
+ {'EXIT', Reason} ->
+ {Xml, acc_errs(S, {error_path(Xml, Xml#xmlElement.name), ?MODULE,
+ {undefined, {internal_error, Reason}}})};
+ {XML2, Rest, Sx} ->
+ case lists:dropwhile(fun(X) when is_record(X, xmlComment) -> true; (_) -> false end, Rest) of
+ [] ->
+ case XML2 of
+ [XML3] ->
+ {XML3,Sx};
+ XML3 ->
+ {XML3,Sx}
+ end;
+ UnValidated ->
+ {Xml,acc_errs(Sx,{error_path(UnValidated,Xml#xmlElement.name),?MODULE,
+ {unvalidated_rest,UnValidated}})}
+ end
end,
save_to_file(S2,filename:rootname(Schema)++".tab2"),
case S2#xsd_state.errors of
@@ -287,10 +293,19 @@ process_schema(Schema) ->
%% error reason. The error reason may be a list of several errors
%% or a single error encountered during the processing.
process_schema(Schema,Options) when is_list(Options) ->
- S = initiate_state(Options,Schema),
- process_schema2(xmerl_scan:file(filename:join(S#xsd_state.xsd_base, Schema)),S,Schema);
-process_schema(Schema,State) when is_record(State,xsd_state) ->
- process_schema2(xmerl_scan:file(filename:join(State#xsd_state.xsd_base, Schema)),State,Schema).
+ State = initiate_state(Options,Schema),
+ process_schema(Schema, State);
+process_schema(Schema, State=#xsd_state{fetch_fun=Fetch})->
+ case Fetch(Schema, State) of
+ {ok,{file,File},_} ->
+ process_schema2(xmerl_scan:file(File), State, Schema);
+ {ok,{string,Str},_} ->
+ process_schema2(xmerl_scan:string(Str), State, Schema);
+ {ok,[],_} ->
+ {error,enoent};
+ Err ->
+ Err
+ end.
process_schema2(Err={error,_},_,_) ->
Err;
@@ -319,12 +334,9 @@ process_schemas(Schemas) ->
%% error reason. The error reason may be a list of several errors
%% or a single error encountered during the processing.
process_schemas(Schemas=[{_,Schema}|_],Options) when is_list(Options) ->
- process_schemas(Schemas,initiate_state(Options,Schema));
+ State = initiate_state(Options,Schema),
+ process_schemas(Schemas, State);
process_schemas([{_NS,Schema}|Rest],State=#xsd_state{fetch_fun=Fetch}) ->
-%% case process_external_schema_once(Schema,if_list_to_atom(NS),State) of
-%% S when is_record(S,xsd_state) ->
-%% case process_schema(filename:join([State#xsd_state.xsd_base,Schema]),State) of
-%% {ok,S} ->
Res=
case Fetch(Schema,State) of
{ok,{file,File},_} ->
@@ -345,20 +357,20 @@ process_schemas([{_NS,Schema}|Rest],State=#xsd_state{fetch_fun=Fetch}) ->
process_schemas([],S) when is_record(S,xsd_state) ->
{ok,S}.
-
initiate_state(Opts,Schema) ->
XSDBase = filename:dirname(Schema),
{{state,S},RestOpts}=new_state(Opts),
S2 = create_tables(S),
- initiate_state2(S2#xsd_state{schema_name = Schema,
- xsd_base = XSDBase,
- fetch_fun = fun fetch/2},RestOpts).
+ initiate_state2(S2#xsd_state{schema_name = Schema, xsd_base=XSDBase,
+ fetch_fun = fun fetch/2},
+ RestOpts).
+
initiate_state2(S,[]) ->
S;
initiate_state2(S,[{tab2file,Bool}|T]) ->
initiate_state2(S#xsd_state{tab2file=Bool},T);
-initiate_state2(S,[{xsdbase,XSDBase}|T]) ->
- initiate_state2(S#xsd_state{xsd_base=XSDBase},T);
+initiate_state2(S,[{xsdbase, XSDBase}|T]) ->
+ initiate_state2(S#xsd_state{xsd_base=XSDBase, external_xsd_base=true},T);
initiate_state2(S,[{fetch_fun,FetchFun}|T]) ->
initiate_state2(S#xsd_state{fetch_fun=FetchFun},T);
initiate_state2(S,[{fetch_path,FetchPath}|T]) ->
@@ -736,7 +748,7 @@ element_content({IDC,S},El,Env)
{{IDC,IDConstr},S3};
Err ->
S3 = acc_errs(S2,{error_path(El,El#xmlElement.name),?MODULE,
- {erronous_content_in_identity_constraint,IDC,Err}}),
+ {erroneous_content_in_identity_constraint,IDC,Err}}),
{{IDC,[]},S3}
end;
element_content({selector,S},Sel,_Env) ->
@@ -1944,7 +1956,7 @@ fetch_external_schema(Path,S) when is_list(Path) ->
{EXSD,S#xsd_state{schema_name=File}}
end;
{_,{string,String},_} -> %% this is for a user defined fetch fun that returns an xml document on string format.
- ?debug("scanning string: ~p~n",[File]),
+ ?debug("scanning string: ~p~n",[String]),
case xmerl_scan:string(String,S#xsd_state.xml_options) of
{error,Reason} ->
{error,acc_errs(S,{[],?MODULE,{parsing_external_schema_failed,Path,Reason}})};
@@ -2514,9 +2526,9 @@ check_element_type([],#schema_complex_type{name=_Name,block=_Bl,content=C},
{error,{error_path(Checked,undefined),?MODULE,
{empty_content_not_allowed,C}}}
end;
-check_element_type(C,{anyType,_},_Env,_Block,S,_Checked) ->
+check_element_type(C, {anyType, _}, _Env, _Block, S, _Checked) ->
%% permitt anything
- {C,[],S};
+ {lists:reverse(C), [], S};
check_element_type(XML=[#xmlText{}|_],Type=#schema_simple_type{},
_Env,_Block,S,_Checked) ->
@@ -2579,7 +2591,7 @@ check_element_type(XML=[XMLEl=#xmlElement{name=Name}|RestXML],
S6 = check_form(ElName,Name,XMLEl,
actual_form_value(CMEl#schema_element.form,
S5#xsd_state.elementFormDefault),
- S5),
+ S5),
%Step into content of XML element.
{Content,_,S7} =
case
@@ -2599,12 +2611,12 @@ check_element_type(XML=[XMLEl=#xmlElement{name=Name}|RestXML],
RestXML,
set_scope(S5#xsd_state.scope,set_num_el(S7,S6))};
true ->
- {error,{error_path(XMLEl,Name),?MODULE,
- {element_not_suitable_with_schema,ElName,S}}};
+ {error,{error_path(XMLEl, Name), ?MODULE,
+ {element_not_suitable_with_schema, ElName, S}}};
_ when S#xsd_state.num_el >= Min ->
%% it may be a match error or an optional element not
%% present
- {[],XML,S#xsd_state{num_el=0}};
+ {[], XML, S#xsd_state{num_el=0}};
_ ->
{error,{error_path(XMLEl,Name),?MODULE,
{element_not_suitable_with_schema,ElName,CMName,CMEl,S}}}
@@ -2639,7 +2651,7 @@ check_element_type(XML=[#xmlElement{}|_Rest],
check_element_type(XML=[E=#xmlElement{name=Name}|Rest],
Any={any,{Namespace,_Occ={Min,_},ProcessorContents}},Env,
_Block,S,_Checked) ->
- ?debug("check any: {any,{~p,~p,~p}}~n",[Namespace,Occ,ProcessorContents]),
+ ?debug("check any: {any,{~p,~p,~p}}~n",[Namespace,_Occ,ProcessorContents]),
%% ProcessorContents any of lax | strict | skip
%% lax: may validate if schema is found
%% strict: must validate
@@ -2704,8 +2716,11 @@ check_element_type([],CM,_Env,_Block,S,Checked) ->
{error,{error_path(Checked,undefined),?MODULE,
{empty_content_not_allowed,CM}}}
end;
+check_element_type([C = #xmlComment{} |Rest],CM,Env,Block,S,Checked) ->
+ check_element_type(Rest,CM,Env,Block,S,[C |Checked]);
check_element_type(XML,CM,_Env,_Block,S,_Checked) ->
{error,{error_path(XML,undefined),?MODULE,{match_failure,XML,CM,S}}}.
+
%% single xml content object and single schema object
check_text_type(XML=[#xmlText{}|_],optional_text,S) ->
% {XMLTxt,optional_text};
@@ -2724,7 +2739,7 @@ check_text_type([XMLTxt=#xmlText{}|_],CMEl,_S) ->
{cannot_contain_text,XMLTxt,CMEl}}}.
split_xmlText(XML) ->
- splitwith(fun(#xmlText{}) -> true;(_) -> false end,XML).
+ splitwith(fun(#xmlText{}) -> true;(#xmlComment{}) -> true;(_) -> false end,XML).
%% Sequence
check_sequence([T=#xmlText{}|Rest],Els,Occ,Env,S,Checked) ->
@@ -2767,6 +2782,8 @@ check_sequence(Seq=[_InstEl=#xmlElement{}|_],[El|Els],Occ={_Min,_Max},Env,S,Chec
count_num_el(set_num_el(S3,S2)),
Ret++Checked)
end;
+check_sequence([C = #xmlComment{} |Rest], Els, Occ, Env, S, Checked) ->
+ check_sequence(Rest,Els,Occ,Env,S,[C |Checked]);
check_sequence(Rest,[],_Occ,_Env,S,Checked) ->
{Checked,Rest,set_num_el(S,0)};
check_sequence([],Els,_Occ,_Env,S,Checked) ->
@@ -2863,6 +2880,8 @@ check_all(XML=[E=#xmlElement{name=Name}|RestXML],CM,Occ,Env,S,
{element_not_in_all,ElName,E,CM}},
check_all(RestXML,CM,Occ,Env,acc_errs(S,Err),[E|Checked],PrevXML)
end;
+check_all([C=#xmlComment{} |RestXML], CM, Occ, Env, S, Checked, XML) ->
+ check_all(RestXML, CM, Occ, Env, S, [C |Checked], XML);
check_all(XML,[],_,_,S,Checked,_) ->
{Checked,XML,S};
check_all([],CM,_Occ,_,S,Checked,_PrevXML) ->
@@ -2914,7 +2933,7 @@ check_target_namespace(XMLEl,S) ->
schemaLocations(El=#xmlElement{attributes=Atts},S) ->
Pred = fun(#xmlAttribute{name=schemaLocation}) -> false;
- (#xmlAttribute{namespace={_,"schemaLocation"}}) -> false;
+ (#xmlAttribute{nsinfo={_,"schemaLocation"}}) -> false;
(_) -> true
end,
case lists:dropwhile(Pred,Atts) of
@@ -5232,7 +5251,12 @@ fetch(URI,S) ->
[] -> %% empty systemliteral
[];
_ ->
- filename:join(S#xsd_state.xsd_base, URI)
+ case S#xsd_state.external_xsd_base of
+ true ->
+ filename:join(S#xsd_state.xsd_base, URI);
+ false ->
+ filename:join(S#xsd_state.xsd_base, filename:basename(URI))
+ end
end,
Path = path_locate(S#xsd_state.fetch_path, Filename, Fullname),
?dbg("fetch(~p) -> {file, ~p}.~n", [URI, Path]),
@@ -5560,7 +5584,7 @@ format_error({incomplete_file,_FileName,_Other}) ->
"Schema: The file containing a schema state must be produced by xmerl_xsd:state2file/[1,2].";
format_error({unexpected_content_in_any,A}) ->
io_lib:format("Schema: The any type is considered to have no content besides annotation. ~p was found.",[A]);
-format_error({erronous_content_in_identity_constraint,IDC,Err}) ->
+format_error({erroneous_content_in_identity_constraint,IDC,Err}) ->
io_lib:format("Schema: An ~p identity constraint must have one selector and one or more field in content. This case ~p",[IDC,Err]);
format_error({missing_xpath_attribute,IDCContent}) ->
io_lib:format("Schema: A ~p in a identity constraint must have a xpath attribute.",[IDCContent]);
diff --git a/lib/xmerl/test/Makefile b/lib/xmerl/test/Makefile
index 9715aa054a..5a2a585841 100644
--- a/lib/xmerl/test/Makefile
+++ b/lib/xmerl/test/Makefile
@@ -124,4 +124,4 @@ release_tests_spec: opt
@tar cfh - xmerl_xsd_MS2002-01-16_SUITE_data | (cd $(RELSYSDIR); tar xf -)
@tar cfh - xmerl_xsd_NIST2002-01-16_SUITE_data | (cd $(RELSYSDIR); tar xf -)
@tar cfh - xmerl_xsd_Sun2002-01-16_SUITE_data | (cd $(RELSYSDIR); tar xf -)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
diff --git a/lib/xmerl/test/xmerl_SUITE.erl b/lib/xmerl/test/xmerl_SUITE.erl
index 392b2522e8..55b6d1844c 100644
--- a/lib/xmerl/test/xmerl_SUITE.erl
+++ b/lib/xmerl/test/xmerl_SUITE.erl
@@ -57,7 +57,8 @@ groups() ->
{eventp_tests, [], [sax_parse_and_export]},
{ticket_tests, [],
[ticket_5998, ticket_7211, ticket_7214, ticket_7430,
- ticket_6873, ticket_7496, ticket_8156, ticket_8697]},
+ ticket_6873, ticket_7496, ticket_8156, ticket_8697,
+ ticket_9411, ticket_9457, ticket_9664_schema, ticket_9664_dtd]},
{app_test, [], [{xmerl_app_test, all}]},
{appup_test, [], [{xmerl_appup_test, all}]}].
@@ -283,7 +284,7 @@ export(Config) ->
?line {E,_} = xmerl_scan:file(TestFile),
?line Exported = xmerl:export([E],xmerl_xml,[{prolog,Prolog}]),
B = list_to_binary(Exported++"\n"),
- ?line {ok,B} = file:read_file(TestFile),
+ ?line {ok, B} = file:read_file(TestFile),
ok.
%%----------------------------------------------------------------------
@@ -575,8 +576,69 @@ ticket_8697(Config) ->
?line [16#545C] = HexEntityText,
ok.
+ticket_9411(suite) -> [];
+ticket_9411(doc) ->
+ ["Test that xmerl_scan handles attribute that contains for example &quot"];
+ticket_9411(Config) ->
+ DataDir = ?config(data_dir,Config),
+
+ ?line {ok, Schema} = xmerl_xsd:process_schema(filename:join([DataDir,"misc/ticket_9411.xsd"])),
+ ?line {ok, Bin} = file:read_file(filename:join([DataDir,"misc/ticket_9411.xml"])),
+ ?line Xml = erlang:binary_to_list(Bin),
+ ?line {E, _} = xmerl_scan:string(Xml),
+ ?line {E, _} = xmerl_xsd:validate(E, Schema).
+
+ticket_9457(suite) -> [];
+ticket_9457(doc) ->
+ ["Test that xmerl_scan handles continuation correct when current input runs out at the end of an attribute value"];
+ticket_9457(Config) ->
+ Opts = [{continuation_fun, fun ticket_9457_cont/3, start}, {space, normalize}],
+ ?line {E, _} = xmerl_scan:string([], Opts).
+
+ticket_9457_cont(Continue, Exception, GlobalState) ->
+ case xmerl_scan:cont_state(GlobalState) of
+ start ->
+ G1 = xmerl_scan:cont_state(next, GlobalState),
+ Bytes = "<?xml version=\"1.0\" ?>\r\n<item a=\"b\"",
+ Continue(Bytes, G1);
+ next ->
+ G1 = xmerl_scan:cont_state(last, GlobalState),
+ Bytes = ">blah</item>\r\n",
+ Continue(Bytes, G1);
+ _ ->
+ Exception(GlobalState)
+ end.
+
+ticket_9664_schema(suite) -> [];
+ticket_9664_schema(doc) ->
+ ["Test that comments are handled correct whith"];
+ticket_9664_schema(Config) ->
+ ?line {E, _} = xmerl_scan:file(filename:join([?config(data_dir, Config), misc,
+ "ticket_9664_schema.xml"]),[]),
+ ?line {ok, S} = xmerl_xsd:process_schema(filename:join([?config(data_dir, Config), misc,
+ "motorcycles.xsd"])),
+ ?line {E1, _} = xmerl_xsd:validate(E, S),
+
+ ?line {E1,_} = xmerl_xsd:process_validate(filename:join([?config(data_dir,Config), misc,
+ "motorcycles.xsd"]),E,[]),
+
+ ?line {E1,_} = xmerl_scan:file(filename:join([?config(data_dir,Config), misc,
+ "ticket_9664_schema.xml"]),
+ [{schemaLocation, [{"mc", "motorcycles.xsd"}]},
+ {validation, schema}]),
+ ok.
+
+ticket_9664_dtd(suite) -> [];
+ticket_9664_dtd(doc) ->
+ ["Test that comments are handled correct whith"];
+ticket_9664_dtd(Config) ->
+ ?line {E, _} = xmerl_scan:file(filename:join([?config(data_dir, Config), misc,
+ "ticket_9664_dtd.xml"]),[]),
+ ?line {E, _} = xmerl_scan:file(filename:join([?config(data_dir, Config), misc,
+ "ticket_9664_dtd.xml"]),[{validation, true}]),
+ ok.
%%======================================================================
diff --git a/lib/xmerl/test/xmerl_SUITE_data/misc.tar.gz b/lib/xmerl/test/xmerl_SUITE_data/misc.tar.gz
index c48a6f897b..ffc1d327a5 100644
--- a/lib/xmerl/test/xmerl_SUITE_data/misc.tar.gz
+++ b/lib/xmerl/test/xmerl_SUITE_data/misc.tar.gz
Binary files differ
diff --git a/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_abbrev.erl b/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_abbrev.erl
index 850b7f8135..7b6f1e95b3 100644
--- a/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_abbrev.erl
+++ b/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_abbrev.erl
@@ -210,7 +210,7 @@ ticket_7496() ->
?line {Doc3,_} = xmerl_scan:file("documentRoot.xml"),
?line ok = Test(Doc3,"//child",[child,child,child]),
?line ok = Test(Doc3,"//child[@name='beta']",[child]),
- ?line [{xmlAttribute,id,[],[],[],[],1,[],"2",false}] =
+ ?line [{xmlAttribute,id,[],[],[],_,1,[],"2",false}] =
xmerl_xpath:string("/documentRoot/parent/child[@name='beta']/@id",Doc3),
?line ok = Test(Doc3,"/documentRoot/parent/child|/documentRoot/parent/pet",
[child,child,child,pet,pet]),
diff --git a/lib/xmerl/test/xmerl_test_lib.erl b/lib/xmerl/test/xmerl_test_lib.erl
index a83956c076..e82ad283b2 100644
--- a/lib/xmerl/test/xmerl_test_lib.erl
+++ b/lib/xmerl/test/xmerl_test_lib.erl
@@ -87,6 +87,6 @@ keysearch_delete(Key,N,List) ->
%% the original data directory.
get_data_dir(Config) ->
- Data0 = ?config(data_dir, Config),
- {ok,Data,_} = regexp:sub(Data0, "xmerl_sax_std_SUITE", "xmerl_std_SUITE"),
- Data.
+ Data = ?config(data_dir, Config),
+ Opts = [{return,list}],
+ re:replace(Data, "xmerl_sax_std_SUITE", "xmerl_std_SUITE", Opts).
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE.erl b/lib/xmerl/test/xmerl_xsd_SUITE.erl
index a0d3b1e667..421fa48054 100644
--- a/lib/xmerl/test/xmerl_xsd_SUITE.erl
+++ b/lib/xmerl/test/xmerl_xsd_SUITE.erl
@@ -62,7 +62,7 @@ groups() ->
sis2, state2file_file2state, union]},
{ticket_tests, [],
[ticket_6910, ticket_7165, ticket_7190, ticket_7288,
- ticket_7736, ticket_8599]},
+ ticket_7736, ticket_8599, ticket_9410]},
{facets, [],
[length, minLength, maxLength, pattern, enumeration,
whiteSpace, maxInclusive, maxExclusive, minExclusive,
@@ -1146,3 +1146,8 @@ ticket_8599(Config) ->
?line {{xmlElement,persons,persons,_,_,_,_,_,_,_,_,_},_GlobalState} = xmerl_xsd:validate(E, S).
+
+ticket_9410(suite) -> [];
+ticket_9410(Config) ->
+ file:set_cwd(filename:join([?config(data_dir,Config),".."])),
+ ?line {ok, _S} = xmerl_xsd:process_schema("xmerl_xsd_SUITE_data/small.xsd").
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/mim.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/mim.xsd
index 057344cde8..057344cde8 100755..100644
--- a/lib/xmerl/test/xmerl_xsd_SUITE_data/mim.xsd
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/mim.xsd
diff --git a/lib/xmerl/vsn.mk b/lib/xmerl/vsn.mk
index 965a0ae7b4..de47e3418b 100644
--- a/lib/xmerl/vsn.mk
+++ b/lib/xmerl/vsn.mk
@@ -1 +1 @@
-XMERL_VSN = 1.2.9
+XMERL_VSN = 1.3
diff --git a/lib/xmerl/xmerl.pub b/lib/xmerl/xmerl.pub
index 29a81bbde2..29a81bbde2 100755..100644
--- a/lib/xmerl/xmerl.pub
+++ b/lib/xmerl/xmerl.pub
diff --git a/make/otp.mk.in b/make/otp.mk.in
index a4e9dad46f..b138dd7d8e 100644
--- a/make/otp.mk.in
+++ b/make/otp.mk.in
@@ -190,8 +190,6 @@ EMACS_COMPILE_OPTIONS=-q --no-site-file -batch -f batch-byte-compile
# ----------------------------------------------------
export VSN
-DOCSUPPORT = 1
-
TOPDOCDIR=../../../../doc
DOCDIR = ..
@@ -239,7 +237,9 @@ FOP = @FOP@
DOCGEN=$(ERL_TOP)/lib/erl_docgen
+ifneq (,$(findstring $(origin SPECS_ESRC),$(DUBIOUS_ORIGINS)))
SPECS_ESRC = ../../src
+endif
SPECS_EXTRACTOR=$(DOCGEN)/priv/bin/specs_gen.escript
# Extract specifications and types from Erlang source files (-spec, -type)
$(SPECDIR)/specs_%.xml: $(SPECS_ESRC)/%.erl
@@ -267,7 +267,7 @@ $(MAN3DIR)/%.3: %.xml
xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude -path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_man_entities $(DOCGEN)/priv/xsl/db_man.xsl $<
endif
-# left for compatability
+# left for compatibility
$(MAN4DIR)/%.4: %.xml
date=`date +"%B %e %Y"`; \
xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude -path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_man_entities $(DOCGEN)/priv/xsl/db_man.xsl $<
@@ -276,7 +276,7 @@ $(MAN4DIR)/%.5: %.xml
date=`date +"%B %e %Y"`; \
xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude -path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_man_entities $(DOCGEN)/priv/xsl/db_man.xsl $<
-# left for compatability
+# left for compatibility
$(MAN6DIR)/%.6: %_app.xml
date=`date +"%B %e %Y"`; \
xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude -path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_man_entities $(DOCGEN)/priv/xsl/db_man.xsl $<
diff --git a/make/otp_release_targets.mk b/make/otp_release_targets.mk
index 8058e634d4..7cd827b5af 100644
--- a/make/otp_release_targets.mk
+++ b/make/otp_release_targets.mk
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2010. All Rights Reserved.
+# Copyright Ericsson AB 1997-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -74,10 +74,10 @@ ifneq ($(XML_FILES),)
# ----------------------------------------------------
# Generation of application index data
# ----------------------------------------------------
-$(HTMLDIR)/$(APPLICATION).eix: $(XML_FILES)
+$(HTMLDIR)/$(APPLICATION).eix: $(XML_FILES) $(SPECS_FILES)
date=`date +"%B %e %Y"`; \
$(XSLTPROC) --stringparam docgen "$(DOCGEN)" \
- --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude \
+ --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude $(TOP_SPECS_PARAM) \
-path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_html_entities $(DOCGEN)/priv/xsl/db_eix.xsl book.xml > $@
docs: $(HTMLDIR)/$(APPLICATION).eix
diff --git a/make/otp_subdir.mk b/make/otp_subdir.mk
index bfbd9997a1..919eee52fc 100644
--- a/make/otp_subdir.mk
+++ b/make/otp_subdir.mk
@@ -30,7 +30,6 @@ opt debug release docs release_docs tests release_tests clean depend valgrind:
if test -f vsn.mk; then \
echo "=== Entering application" `basename $$app_pwd` ; \
fi ; \
- case "$(MAKE)" in *clearmake*) tflag="-T";; *) tflag="";; esac; \
for d in $(SUB_DIRECTORIES); do \
if test -f $$d/SKIP ; then \
echo "=== Skipping subdir $$d, reason:" ; \
@@ -40,11 +39,7 @@ opt debug release docs release_docs tests release_tests clean depend valgrind:
if test ! -d $$d ; then \
echo "=== Skipping subdir $$d, it is missing" ; \
else \
- xflag="" ; \
- if test -f $$d/ignore_config_record.inf; then \
- xflag=$$tflag ; \
- fi ; \
- (cd $$d && $(MAKE) $$xflag $@) || exit $$? ; \
+ (cd $$d && $(MAKE) $@) || exit $$? ; \
fi ; \
fi ; \
done ; \
diff --git a/make/target.mk b/make/target.mk
index 06e895df90..a6493e09a5 100644
--- a/make/target.mk
+++ b/make/target.mk
@@ -1,3 +1,24 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1998-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+
+# Ensure that the make variable TARGET is set
+#
+
ifeq ($(OVERRIDE_TARGET),)
ifeq ($(TARGET),)
@@ -31,3 +52,18 @@ endif
endif
+ifneq ($(TARGET),)
+ifneq ($(TARGET),win32)
+ifneq ($(TARGET),vxworks)
+override TARGET := $(shell $(ERL_TOP)/erts/autoconf/config.sub $(TARGET))
+else
+endif
+else
+endif
+else
+endif
+
+ifeq ($(TARGET),)
+$(error Neither TARGET nor OVERRIDE_TARGET can be determined!)
+else
+endif
diff --git a/otp_build b/otp_build
index ed4609435f..76f1d20ff7 100755
--- a/otp_build
+++ b/otp_build
@@ -186,15 +186,15 @@ set_config_flags ()
if target_contains free_source; then
CONFIG_FLAGS="$CONFIG_FLAGS --host=$TARGET"
fi
- # Link SSL static for all binary distributions if not overridden
- # Even for win32 starting with R14B03
- XX=`echo $* | grep -v dynamic-ssl-lib`
- if [ "$*" = "$XX" ]; then
- CONFIG_FLAGS="--disable-dynamic-ssl-lib $CONFIG_FLAGS"
- fi
+ # Link SSL static for win32 binary distributions if not overridden
if target_contains win32; then
+ XX=`echo $* | grep -v dynamic-ssl-lib`
+ if [ "$*" = "$XX" ]; then
+ CONFIG_FLAGS="--disable-dynamic-ssl-lib $CONFIG_FLAGS"
+ fi
CONFIG_FLAGS="--build=$BUILDSYS build_alias=win32 --host=win32 --target=win32 $CONFIG_FLAGS"
fi
+
if [ "x$OVERRIDE_CONFIG_CACHE" = "x" ]; then
CONFIG_FLAGS="$CONFIG_FLAGS --cache-file=/dev/null"
@@ -324,16 +324,6 @@ do_autoconf ()
fi
}
-mk_targetdir ()
-{
- if [ ! -d $ERL_TOP/$TARGET ]; then
- echo "creating $ERL_TOP/$TARGET"
- mkdir $ERL_TOP/$TARGET
- else
- echo "existing $ERL_TOP/$TARGET is used"
- fi
-}
-
run_configure ()
{
cdir="$ERL_TOP"
@@ -499,7 +489,6 @@ maybe_copy_static_cache ()
do_configure ()
{
setup_make
- mk_targetdir
# Get `erl_build_tool_vars'
. "$ERL_TOP/erl-build-tool-vars.sh" || exit 1
@@ -513,7 +502,6 @@ do_configure ()
hide_vars OVERRIDE_TARGET TARGET
TARGET=$BUILDSYS
export TARGET
- mk_targetdir
set_config_flags "$@"
run_configure "$@"
restore_vars OVERRIDE_TARGET TARGET;;
@@ -878,8 +866,10 @@ do_primary_git ()
git add -A bootstrap/lib/kernel \
bootstrap/lib/stdlib \
bootstrap/lib/compiler \
- bootstrap/lib/orber/include \
bootstrap/bin
+ find bootstrap -name egen -o -name '*.script' -o \
+ -name '*.app' -o -name '*.appup' |
+ xargs git reset HEAD
git commit --no-verify -m 'Update primary bootstrap'
}
@@ -1001,24 +991,17 @@ do_copy_primary_bootstrap ()
test -d $bootstrap/lib/kernel/ebin || mkdir -p $bootstrap/lib/kernel/ebin
test -d $bootstrap/lib/kernel/include || mkdir -p $bootstrap/lib/kernel/include
cp -f $lib_src/kernel/ebin/*.beam $bootstrap/lib/kernel/ebin
- cp -f $lib_src/kernel/ebin/*.app* $bootstrap/lib/kernel/ebin
cp -f $lib_src/kernel/include/*.hrl $bootstrap/lib/kernel/include
# stdlib
test -d $bootstrap/lib/stdlib/ebin || mkdir -p $bootstrap/lib/stdlib/ebin
test -d $bootstrap/lib/stdlib/include || mkdir -p $bootstrap/lib/stdlib/include
cp -f $lib_src/stdlib/ebin/*.beam $bootstrap/lib/stdlib/ebin
- cp -f $lib_src/stdlib/ebin/*.app* $bootstrap/lib/stdlib/ebin
cp -f $lib_src/stdlib/include/*.hrl $bootstrap/lib/stdlib/include
# compiler
test -d $bootstrap/lib/compiler/ebin || mkdir -p $bootstrap/lib/compiler/ebin
cp -f $lib_src/compiler/ebin/*.beam $bootstrap/lib/compiler/ebin
- cp -f $lib_src/compiler/ebin/*.app* $bootstrap/lib/compiler/ebin
-
- # orber include
- test -d $bootstrap/lib/orber/include || mkdir -p $bootstrap/lib/orber/include
- cp -f $lib_src/orber/include/* $bootstrap/lib/orber/include
# bootstrap bin
if [ $bootstrap_src_top != $ERL_TOP ]; then
diff --git a/system/doc/design_principles/Makefile b/system/doc/design_principles/Makefile
index b3fe136644..ae951ba8d4 100644
--- a/system/doc/design_principles/Makefile
+++ b/system/doc/design_principles/Makefile
@@ -79,6 +79,8 @@ DVIPS_FLAGS +=
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
+_create_dirs := $(shell mkdir -p $(HTMLDIR))
+
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
diff --git a/system/doc/design_principles/make.dep b/system/doc/design_principles/make.dep
deleted file mode 100644
index 05dd2333fb..0000000000
--- a/system/doc/design_principles/make.dep
+++ /dev/null
@@ -1,31 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/gandalf/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: applications.tex appup_cookbook.tex book.tex \
- des_princ.tex distributed_applications.tex \
- events.tex fsm.tex gen_server_concepts.tex \
- included_applications.tex part.tex release_handling.tex \
- release_structure.tex spec_proc.tex sup_princ.tex
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: sup6.ps
-
-book.dvi: dist1.ps dist2.ps dist3.ps dist4.ps dist5.ps
-
-book.dvi: clientserver.ps
-
-book.dvi: inclappls.ps
-
-book.dvi: sup4.ps sup5.ps
-
diff --git a/system/doc/design_principles/spec_proc.xml b/system/doc/design_principles/spec_proc.xml
index f0f62891b6..a1c862e004 100644
--- a/system/doc/design_principles/spec_proc.xml
+++ b/system/doc/design_principles/spec_proc.xml
@@ -411,30 +411,48 @@ loop(...) ->
<p>To implement a user-defined behaviour, write code similar to
code for a special process but calling functions in a callback
module for handling specific tasks.</p>
- <p>If it is desired that the compiler should warn for missing
- callback functions, as it does for the OTP behaviours, implement
- and export the function:</p>
+ <p>If it is desired that the compiler should warn for missing callback
+ functions, as it does for the OTP behaviours, add callback attributes in the
+ behaviour module to describe the expected callbacks:</p>
+ <code type="none">
+-callback Name1(Arg1_1, Arg1_2, ..., Arg1_N1) -> Res1.
+-callback Name2(Arg2_1, Arg2_2, ..., Arg2_N2) -> Res2.
+...
+-callback NameM(ArgM_1, ArgM_2, ..., ArgM_NM) -> ResM.</code>
+ <p>where <c>NameX</c> are the names of the expected callbacks and
+ <c>ArgX_Y</c>, <c>ResX</c> are types as they are described in Specifications
+ for functions in <seealso marker="../reference_manual/typespec">Types and
+ Function Specifications</seealso>. The whole syntax of spec attributes is
+ supported by callback attributes.</p>
+ <p>Alternatively you may directly implement and export the function:</p>
<code type="none">
behaviour_info(callbacks) ->
[{Name1,Arity1},...,{NameN,ArityN}].</code>
- <p>where each <c>{Name,Arity}</c> specifies the name and arity of
- a callback function.</p>
+ <p>where each <c>{Name,Arity}</c> specifies the name and arity of a callback
+ function. This function is otherwise automatically generated by the compiler
+ using the callback attributes.</p>
<p>When the compiler encounters the module attribute
- <c>-behaviour(Behaviour).</c> in a module <c>Mod</c>, it will call
- <c>Behaviour:behaviour_info(callbacks)</c> and compare the result
- with the set of functions actually exported from <c>Mod</c>, and
- issue a warning if any callback function is missing.</p>
+ <c>-behaviour(Behaviour).</c> in a module <c>Mod</c>, it will call
+ <c>Behaviour:behaviour_info(callbacks)</c> and compare the result with the
+ set of functions actually exported from <c>Mod</c>, and issue a warning if
+ any callback function is missing.</p>
<p>Example:</p>
<code type="none">
%% User-defined behaviour module
-module(simple_server).
-export([start_link/2,...]).
--export([behaviour_info/1]).
-behaviour_info(callbacks) ->
- [{init,1},
- {handle_req,1},
- {terminate,0}].
+-callback init(State :: term()) -> 'ok'.
+-callback handle_req(Req :: term(), State :: term()) -> {'ok', Reply :: term()}.
+-callback terminate() -> 'ok'.
+
+%% Alternatively you may define:
+%%
+%% -export([behaviour_info/1]).
+%% behaviour_info(callbacks) ->
+%% [{init,1},
+%% {handle_req,2},
+%% {terminate,0}].
start_link(Name, Module) ->
proc_lib:start_link(?MODULE, init, [self(), Name, Module]).
@@ -452,7 +470,7 @@ init(Parent, Name, Module) ->
-module(db).
-behaviour(simple_server).
--export([init/0, handle_req/1, terminate/0]).
+-export([init/0, handle_req/2, terminate/0]).
...</code>
</section>
diff --git a/system/doc/design_principles/sup_princ.xml b/system/doc/design_principles/sup_princ.xml
index 2748f21bbe..5b8fd604c8 100644
--- a/system/doc/design_principles/sup_princ.xml
+++ b/system/doc/design_principles/sup_princ.xml
@@ -160,10 +160,13 @@ init(...) ->
be restarted.</p>
<list type="bulleted">
<item>A <c>permanent</c> child process is always restarted.</item>
- <item>A <c>temporary</c> child process is never restarted.</item>
+ <item>A <c>temporary</c> child process is never restarted
+ (not even when the supervisor's restart strategy
+ is <c>rest_for_one</c> or <c>one_for_all</c> and a sibling's
+ death causes the temporary process to be terminated).</item>
<item>A <c>transient</c> child process is restarted only if it
terminates abnormally, i.e. with another exit reason than
- <c>normal</c>.</item>
+ <c>normal</c>, <c>shutdown</c> or <c>{shutdown,Term}</c>.</item>
</list>
</item>
<item>
@@ -181,8 +184,16 @@ init(...) ->
terminated using <c>exit(Child, kill)</c>.</item>
<item>If the child process is another supervisor, it should be
set to <c>infinity</c> to give the subtree enough time to
- shutdown.</item>
+ shutdown. It is also allowed to set it to <c>infinity</c>, if the
+ child process is a worker.</item>
</list>
+ <warning>
+ <p>Be careful by setting the <c>Shutdown</c> strategy to
+ <c>infinity</c> when the child process is a worker. Because, in this
+ situation, the termination of the supervision tree depends on the
+ child process, it must be implemented in a safe way and its cleanup
+ procedure must always return.</p>
+ </warning>
</item>
<item>
<p><c>Type</c> specifies if the child process is a supervisor or
@@ -341,6 +352,10 @@ call:start_link(id1)</code>
supervisor:terminate_child(Sup, Pid)</code>
<p>where <c>Sup</c> is the pid, or name, of the supervisor and
<c>Pid</c> is the pid of the child.</p>
+ <p>Because a <c>simple_one_for_one</c> supervisor could have many children,
+ it shuts them all down at same time. So, order in which they are stopped is
+ not defined. For the same reason, it could have an overhead with regards to
+ the <c>Shutdown</c> strategy.</p>
</section>
<section>
diff --git a/system/doc/efficiency_guide/Makefile b/system/doc/efficiency_guide/Makefile
index f51313de84..2629285b42 100644
--- a/system/doc/efficiency_guide/Makefile
+++ b/system/doc/efficiency_guide/Makefile
@@ -85,6 +85,8 @@ DVIPS_FLAGS +=
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
+_create_dirs := $(shell mkdir -p $(HTMLDIR))
+
docs: html
local_docs: PDFDIR=../../pdf
diff --git a/system/doc/efficiency_guide/make.dep b/system/doc/efficiency_guide/make.dep
deleted file mode 100644
index afa3bd0516..0000000000
--- a/system/doc/efficiency_guide/make.dep
+++ /dev/null
@@ -1,16 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: advanced.tex binaryhandling.tex book.tex commoncaveats.tex \
- drivers.tex functions.tex introduction.tex listhandling.tex \
- myths.tex part.tex processes.tex profiling.tex \
- tablesDatabases.tex
-
diff --git a/system/doc/efficiency_guide/profiling.xml b/system/doc/efficiency_guide/profiling.xml
index 13165a0ede..65ba4b3369 100644
--- a/system/doc/efficiency_guide/profiling.xml
+++ b/system/doc/efficiency_guide/profiling.xml
@@ -40,9 +40,13 @@
<p>Erlang/OTP contains several tools to help finding bottlenecks.</p>
- <p><c>fprof</c> and <c>eprof</c> provide the most detailed information
- about where the time is spent, but they significantly slow downs the
- programs they profile.</p>
+ <p><c>fprof</c> provide the most detailed information
+ about where the time is spent, but it significantly slows down the
+ program it profiles.</p>
+
+ <p><c>eprof</c> provides time information of each function used
+ in the program. No callgraph is produced but <c>eprof</c> has
+ considerable less impact on the program profiled.</p>
<p>If the program is too big to be profiled by <c>fprof</c> or <c>eprof</c>,
<c>cover</c> and <c>cprof</c> could be used to locate parts of the
@@ -50,7 +54,7 @@
<c>eprof</c>.</p>
<p><c>cover</c> provides execution counts per line per process,
- with less overhead than <c>fprof/eprof</c>. Execution counts can
+ with less overhead than <c>fprof</c>. Execution counts can
with some caution be used to locate potential performance bottlenecks.
The most lightweight tool is <c>cprof</c>, but it only provides execution
counts on a function basis (for all processes, not per process).</p>
@@ -102,35 +106,45 @@
<section>
<title>fprof</title>
- <p><c>fprof</c> measures the execution time for each function,
+ <p>
+ <c>fprof</c> measures the execution time for each function,
both own time i.e how much time a function has used for its
own execution, and accumulated time i.e. including called
functions. The values are displayed per process. You also get
to know how many times each function has been
called. <c>fprof</c> is based on trace to file in order to
minimize runtime performance impact. Using fprof is just a
- matter of calling a few library functions, see fprof manual
- page under the application tools.</p>
- <p><c>fprof</c> was introduced in version R8 of Erlang/OTP. Its
- predecessor <c>eprof</c> that is based on the Erlang trace BIFs,
- is still available, see eprof manual page under the
- application tools. Eprof shows how much time has been used by
- each process, and in which function calls this time has been
- spent. Time is shown as percentage of total time, not as
- absolute time.</p>
+ matter of calling a few library functions, see
+ <seealso marker="tools:fprof">fprof</seealso>
+ manual page under the application tools.<c>fprof</c> was introduced in
+ version R8 of Erlang/OTP.
+ </p>
</section>
+ <section>
+ <title>eprof</title>
+ <p>
+ <c>eprof</c> is based on the Erlang trace_info BIFs. Eprof shows how much time has been used by
+ each process, and in which function calls this time has been
+ spent. Time is shown as percentage of total time and absolute time.
+ See <seealso marker="tools:eprof">eprof</seealso> for
+ additional information.
+ </p>
+ </section>
+
<section>
<title>cover</title>
- <p><c>cover</c>'s primary use is coverage analysis to verify
+ <p>
+ <c>cover</c>'s primary use is coverage analysis to verify
test cases, making sure all relevant code is covered.
<c>cover</c> counts how many times each executable line of
code is executed when a program is run. This is done on a per
module basis. Of course this information can be used to
determine what code is run very frequently and could therefore
be subject for optimization. Using cover is just a matter of
- calling a few library functions, see cover manual
- page under the application tools.</p>
+ calling a few library functions, see
+ <seealso marker="tools:cover">cover</seealso>
+ manual page under the application tools.</p>
</section>
<section>
@@ -139,8 +153,11 @@
<c>cover</c> regarding features. It counts how many times each
function is called when the program is run, on a per module
basis. <c>cprof</c> has a low performance degradation effect (versus
- <c>fprof</c> and <c>eprof</c>) and does not need to recompile
- any modules to profile (versus <c>cover</c>).</p>
+ <c>fprof</c>) and does not need to recompile
+ any modules to profile (versus <c>cover</c>).
+ See <seealso marker="tools:cprof">cprof</seealso> manual page for additional
+ information.
+ </p>
</section>
<section>
@@ -170,7 +187,7 @@
<cell align="left" valign="middle"><c>eprof </c></cell>
<cell align="left" valign="middle">per process/function to screen/file </cell>
<cell align="left" valign="middle">medium </cell>
- <cell align="left" valign="middle">significant slowdown </cell>
+ <cell align="left" valign="middle">small slowdown </cell>
<cell align="left" valign="middle">yes </cell>
<cell align="left" valign="middle">only total </cell>
<cell align="left" valign="middle">no </cell>
diff --git a/system/doc/embedded/Makefile b/system/doc/embedded/Makefile
index 5e68917fc2..70357efb1f 100644
--- a/system/doc/embedded/Makefile
+++ b/system/doc/embedded/Makefile
@@ -73,6 +73,8 @@ DVIPS_FLAGS +=
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
+_create_dirs := $(shell mkdir -p $(HTMLDIR))
+
docs: html
local_docs: PDFDIR=../../pdf
diff --git a/system/doc/embedded/make.dep b/system/doc/embedded/make.dep
deleted file mode 100644
index 9949a3ac96..0000000000
--- a/system/doc/embedded/make.dep
+++ /dev/null
@@ -1,14 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex embedded_nt.tex embedded_solaris.tex \
- part.tex vxworks.tex
-
diff --git a/system/doc/getting_started/Makefile b/system/doc/getting_started/Makefile
index 5ca885d56e..5d85ca2adc 100644
--- a/system/doc/getting_started/Makefile
+++ b/system/doc/getting_started/Makefile
@@ -72,6 +72,8 @@ DVIPS_FLAGS +=
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
+_create_dirs := $(shell mkdir -p $(HTMLDIR))
+
docs: html
local_docs: PDFDIR=../../pdf
diff --git a/system/doc/getting_started/make.dep b/system/doc/getting_started/make.dep
deleted file mode 100644
index 69b177f77c..0000000000
--- a/system/doc/getting_started/make.dep
+++ /dev/null
@@ -1,14 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex conc_prog.tex intro.tex part.tex \
- records_macros.tex robustness.tex seq_prog.tex
-
diff --git a/system/doc/getting_started/seq_prog.xml b/system/doc/getting_started/seq_prog.xml
index bc1758d855..96876ea513 100644
--- a/system/doc/getting_started/seq_prog.xml
+++ b/system/doc/getting_started/seq_prog.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2009</year>
+ <year>2003</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -41,9 +41,9 @@
<c>erl</c>, you will see something like this.</p>
<pre>
% <input>erl</input>
-Erlang (BEAM) emulator version 5.2 [source] [hipe]
+Erlang R15B (erts-5.9.1) [source] [smp:8:8] [rq:8] [async-threads:0] [hipe] [kernel-poll:false]
-Eshell V5.2 (abort with ^G)
+Eshell V5.9.1 (abort with ^G)
1></pre>
<p>Now type in "2 + 5." as shown below.</p>
<pre>
@@ -245,7 +245,7 @@ convert(N, centimeter) ->
inch in the convert function:</p>
<pre>
12> <input>tut2:convert(3, miles).</input>
-** exception error: no function clause matching tut2:convert(3,miles)</pre>
+** exception error: no function clause matching tut2:convert(3,miles) (tut2.erl, line 4)</pre>
<p>The two parts of the <c>convert</c> function are called its
clauses. Here we see that "miles" is not part of either of
the clauses. The Erlang system can't <em>match</em> either of
@@ -255,11 +255,13 @@ convert(N, centimeter) ->
command <c>v/1</c>:</p>
<pre>
13> <input>v(12).</input>
-{'EXIT',{function_clause,[{tut2,convert,[3,miles]},
- {erl_eval,do_apply,5},
- {shell,exprs,6},
- {shell,eval_exprs,6},
- {shell,eval_loop,3}]}}</pre>
+{'EXIT',{function_clause,[{tut2,convert,
+ [3,miles],
+ [{file,"tut2.erl"},{line,4}]},
+ {erl_eval,do_apply,5,[{file,"erl_eval.erl"},{line,482}]},
+ {shell,exprs,7,[{file,"shell.erl"},{line,666}]},
+ {shell,eval_exprs,7,[{file,"shell.erl"},{line,621}]},
+ {shell,eval_loop,3,[{file,"shell.erl"},{line,606}]}]}}</pre>
</section>
@@ -943,7 +945,7 @@ A == 1 ; B == 7
a_equals_1_or_b_equals_7
66> <input>tut9:test_if(33, 33).</input>
** exception error: no true branch found when evaluating an if expression
- in function tut9:test_if/2</pre>
+ in function tut9:test_if/2 (tut9.erl, line 5)</pre>
<p>Notice that <c>tut9:test_if(33,33)</c> did not cause any
condition to succeed so we got the run time error
<c>if_clause</c>, here nicely formatted by the shell. See the chapter
diff --git a/system/doc/installation_guide/make.dep b/system/doc/installation_guide/make.dep
deleted file mode 100644
index 3878f4ac9d..0000000000
--- a/system/doc/installation_guide/make.dep
+++ /dev/null
@@ -1,13 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex install-binary.tex part.tex verification.tex
-
diff --git a/system/doc/oam/Makefile b/system/doc/oam/Makefile
index e3288c9182..7732426ce6 100644
--- a/system/doc/oam/Makefile
+++ b/system/doc/oam/Makefile
@@ -69,6 +69,8 @@ DVIPS_FLAGS +=
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
+_create_dirs := $(shell mkdir -p $(HTMLDIR))
+
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
diff --git a/system/doc/oam/make.dep b/system/doc/oam/make.dep
deleted file mode 100644
index 3694df9f1b..0000000000
--- a/system/doc/oam/make.dep
+++ /dev/null
@@ -1,26 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex oam_intro.tex part.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-oam_intro.tex: ../../../system/doc/definitions/term.defs
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: snmp_model_1.ps snmp_model_2.ps snmp_model_3.ps \
- terminology.ps
-
diff --git a/system/doc/programming_examples/Makefile b/system/doc/programming_examples/Makefile
index 73512c9654..8aeead9f6a 100644
--- a/system/doc/programming_examples/Makefile
+++ b/system/doc/programming_examples/Makefile
@@ -70,6 +70,8 @@ DVIPS_FLAGS +=
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
+_create_dirs := $(shell mkdir -p $(HTMLDIR))
+
docs: html
local_docs: PDFDIR=../../pdf
diff --git a/system/doc/programming_examples/make.dep b/system/doc/programming_examples/make.dep
deleted file mode 100644
index b0655f56b3..0000000000
--- a/system/doc/programming_examples/make.dep
+++ /dev/null
@@ -1,20 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: bit_syntax.tex book.tex funs.tex list_comprehensions.tex \
- part.tex records.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-funs.tex: fun_test.erl funparse.erl funs1.erl
-
diff --git a/system/doc/reference_manual/Makefile b/system/doc/reference_manual/Makefile
index 34e5b7f555..2e1f8e71cb 100644
--- a/system/doc/reference_manual/Makefile
+++ b/system/doc/reference_manual/Makefile
@@ -82,6 +82,8 @@ DVIPS_FLAGS +=
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
+_create_dirs := $(shell mkdir -p $(HTMLDIR))
+
docs: html
local_docs: PDFDIR=../../pdf
diff --git a/system/doc/reference_manual/code_loading.xml b/system/doc/reference_manual/code_loading.xml
index f56e1ff408..3ea72a4057 100644
--- a/system/doc/reference_manual/code_loading.xml
+++ b/system/doc/reference_manual/code_loading.xml
@@ -112,8 +112,8 @@ loop() ->
<c>code_switch</c> to it. The process then will make a fully
qualified call to <c>m:loop()</c> and change to current code.
Note that <c>m:loop/0</c> must be exported.</p>
- <p>For code replacement of funs to work, the tuple syntax
- <c>{Module,FunctionName}</c> must be used to represent the fun.</p>
+ <p>For code replacement of funs to work, the syntax
+ <c>fun Module:FunctionName/Arity</c> should be used.</p>
</section>
<section>
diff --git a/system/doc/reference_manual/distributed.xml b/system/doc/reference_manual/distributed.xml
index 52222c6d9d..bc55d14c90 100644
--- a/system/doc/reference_manual/distributed.xml
+++ b/system/doc/reference_manual/distributed.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2009</year>
+ <year>2003</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -78,7 +78,7 @@ dilbert@uab</pre>
using the command line flag <c>-connect_all false</c>, see
<c>erl(1)</c>.</p>
<p>If a node goes down, all connections to that node are removed.
- Calling <c>erlang:disconnect(Node)</c> will force disconnection
+ Calling <c>erlang:disconnect_node(Node)</c> will force disconnection
of a node.</p>
<p>The list of (visible) nodes currently connected to is returned by
<c>nodes()</c>.</p>
@@ -176,11 +176,11 @@ dilbert@uab</pre>
</row>
<row>
<cell align="left" valign="middle"><c>is_alive()</c></cell>
- <cell align="left" valign="middle">Returns <c>true</c>if the runtime system is a node and can connect to other nodes, <c>false</c>otherwise.</cell>
+ <cell align="left" valign="middle">Returns <c>true</c> if the runtime system is a node and can connect to other nodes, <c>false</c> otherwise.</cell>
</row>
<row>
<cell align="left" valign="middle"><c>monitor_node(Node, true|false)</c></cell>
- <cell align="left" valign="middle">Monitor the status of <c>Node</c>. A message<c>{nodedown, Node}</c>is received if the connection to it is lost.</cell>
+ <cell align="left" valign="middle">Monitor the status of <c>Node</c>. A message<c>{nodedown, Node}</c> is received if the connection to it is lost.</cell>
</row>
<row>
<cell align="left" valign="middle"><c>node()</c></cell>
@@ -200,7 +200,7 @@ dilbert@uab</pre>
</row>
<row>
<cell align="left" valign="middle"><c>set_cookie(Node, Cookie)</c></cell>
- <cell align="left" valign="middle">Sets the magic cookie used when connecting to <c>Node</c>. If <c>Node</c>is the current node, <c>Cookie</c>will be used when connecting to all new nodes.</cell>
+ <cell align="left" valign="middle">Sets the magic cookie used when connecting to <c>Node</c>. If <c>Node</c> is the current node, <c>Cookie</c> will be used when connecting to all new nodes.</cell>
</row>
<row>
<cell align="left" valign="middle"><c>spawn[_link|_opt](Node, Fun)</c></cell>
diff --git a/system/doc/reference_manual/expressions.xml b/system/doc/reference_manual/expressions.xml
index 497d7eb464..43d46d87cc 100644
--- a/system/doc/reference_manual/expressions.xml
+++ b/system/doc/reference_manual/expressions.xml
@@ -561,11 +561,15 @@ number &lt; atom &lt; reference &lt; fun &lt; port &lt; pid &lt; tuple &lt; list
<p>Lists are compared element by element. Tuples are ordered by
size, two tuples with the same size are compared element by
element.</p>
- <p>If one of the compared terms is an integer and the other a
- float, the integer is first converted into a float, unless the
- operator is one of =:= and =/=. If the integer is too big to fit
- in a float no conversion is done, but the order is determined by
- inspecting the sign of the numbers.</p>
+ <p>When comparing an integer to a float, the term with the lesser
+ precision will be converted into the other term's type, unless the
+ operator is one of =:= and =/=. A float is more precise than
+ an integer until all significant figures of the float are to the left of
+ the decimal point. This happens when the float is larger/smaller then
+ +/-9007199254740992.0. The conversion strategy is changed
+ depending on the size of the float because otherwise comparison of large
+ floats and integers would loose their transitivity.</p>
+
<p>Returns the Boolean value of the expression, <c>true</c> or
<c>false</c>.</p>
<p>Examples:</p>
@@ -879,9 +883,8 @@ Ei = Value |
and UTF-32, respectively.</p>
<p>When constructing a segment of a <c>utf</c> type, <c>Value</c>
- must be an integer in one of the ranges 0..16#D7FF,
- 16#E000..16#FFFD, or 16#10000..16#10FFFF
- (i.e. a valid Unicode code point). Construction
+ must be an integer in the range 0..16#D7FF or
+ 16#E000....16#10FFFF. Construction
will fail with a <c>badarg</c> exception if <c>Value</c> is
outside the allowed ranges. The size of the resulting binary
segment depends on the type and/or <c>Value</c>. For <c>utf8</c>,
@@ -896,14 +899,13 @@ Ei = Value |
<c><![CDATA[<<$a/utf8,$b/utf8,$c/utf8>>]]></c>.</p>
<p>A successful match of a segment of a <c>utf</c> type results
- in an integer in one of the ranges 0..16#D7FF, 16#E000..16#FFFD,
- or 16#10000..16#10FFFF
- (i.e. a valid Unicode code point). The match will fail if returned value
+ in an integer in the range 0..16#D7FF or 16#E000..16#10FFFF.
+ The match will fail if returned value
would fall outside those ranges.</p>
<p>A segment of type <c>utf8</c> will match 1 to 4 bytes in the binary,
if the binary at the match position contains a valid UTF-8 sequence.
- (See RFC-2279 or the Unicode standard.)</p>
+ (See RFC-3629 or the Unicode standard.)</p>
<p>A segment of type <c>utf16</c> may match 2 or 4 bytes in the binary.
The match will fail if the binary at the match position does not contain
@@ -991,15 +993,19 @@ fun Module:Name/Arity</pre>
<pre>
fun (Arg1,...,ArgN) -> Name(Arg1,...,ArgN) end</pre>
<p>In <c>Module:Name/Arity</c>, <c>Module</c> and <c>Name</c> are atoms
- and <c>Arity</c> is an integer.
+ and <c>Arity</c> is an integer. Starting from the R15 release,
+ <c>Module</c>, <c>Name</c>, and <c>Arity</c> may also be variables.
A fun defined in this way will refer to the function <c>Name</c>
- with arity <c>Arity</c> in the <em>latest</em> version of module <c>Module</c>.
+ with arity <c>Arity</c> in the <em>latest</em> version of module
+ <c>Module</c>. A fun defined in this way will not be dependent on
+ the code for module in which it is defined.
</p>
<p>When applied to a number N of arguments, a tuple
<c>{Module,FunctionName}</c> is interpreted as a fun, referring
to the function <c>FunctionName</c> with arity N in the module
<c>Module</c>. The function must be exported.
- <em>This usage is deprecated.</em>
+ <em>This usage is deprecated.</em> Use <c>fun Module:Name/Arity</c>
+ instead.
See <seealso marker="#calls">Function Calls</seealso> for an example.</p>
<p>More examples can be found in <em>Programming Examples</em>.</p>
</section>
diff --git a/system/doc/reference_manual/macros.xml b/system/doc/reference_manual/macros.xml
index 9dd5fc79bd..bfac7f8d79 100644
--- a/system/doc/reference_manual/macros.xml
+++ b/system/doc/reference_manual/macros.xml
@@ -234,7 +234,7 @@ or
?TESTCALL(you:function(2,1)).</code>
<p>results in</p>
<code type="none">
-io:format("Call ~s: ~w~n",["myfunction ( 1 , 2 )",m:myfunction(1,2)]),
+io:format("Call ~s: ~w~n",["myfunction ( 1 , 2 )",myfunction(1,2)]),
io:format("Call ~s: ~w~n",["you : function ( 2 , 1 )",you:function(2,1)]).</code>
<p>That is, a trace output with both the function called and
the resulting value.</p>
diff --git a/system/doc/reference_manual/make.dep b/system/doc/reference_manual/make.dep
deleted file mode 100644
index 0e7687448c..0000000000
--- a/system/doc/reference_manual/make.dep
+++ /dev/null
@@ -1,16 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex code_loading.tex data_types.tex distributed.tex \
- errors.tex expressions.tex functions.tex introduction.tex \
- macros.tex modules.tex part.tex patterns.tex \
- ports.tex processes.tex records.tex
-
diff --git a/system/doc/reference_manual/typespec.xml b/system/doc/reference_manual/typespec.xml
index f08639f9a1..f08639f9a1 100755..100644
--- a/system/doc/reference_manual/typespec.xml
+++ b/system/doc/reference_manual/typespec.xml
diff --git a/system/doc/system_architecture_intro/Makefile b/system/doc/system_architecture_intro/Makefile
index 0fff9bc4d5..8d677886b8 100644
--- a/system/doc/system_architecture_intro/Makefile
+++ b/system/doc/system_architecture_intro/Makefile
@@ -67,6 +67,8 @@ DVIPS_FLAGS +=
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
+_create_dirs := $(shell mkdir -p $(HTMLDIR))
+
docs: html
local_docs: PDFDIR=../../pdf
diff --git a/system/doc/system_architecture_intro/make.dep b/system/doc/system_architecture_intro/make.dep
deleted file mode 100644
index 6b7bd860a0..0000000000
--- a/system/doc/system_architecture_intro/make.dep
+++ /dev/null
@@ -1,13 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex part.tex sys_arch_intro.tex
-
diff --git a/system/doc/system_principles/Makefile b/system/doc/system_principles/Makefile
index b0698fec9d..da109be211 100644
--- a/system/doc/system_principles/Makefile
+++ b/system/doc/system_principles/Makefile
@@ -66,6 +66,8 @@ DVIPS_FLAGS +=
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
+_create_dirs := $(shell mkdir -p $(HTMLDIR))
+
docs: html
local_docs: PDFDIR=../../pdf
diff --git a/system/doc/system_principles/make.dep b/system/doc/system_principles/make.dep
deleted file mode 100644
index 28753ca5a0..0000000000
--- a/system/doc/system_principles/make.dep
+++ /dev/null
@@ -1,14 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex create_target.tex error_logging.tex \
- part.tex system_principles.tex
-
diff --git a/system/doc/top/src/erl_html_tools.erl b/system/doc/top/src/erl_html_tools.erl
index bb6a9a9f0a..1e2b8c86af 100644
--- a/system/doc/top/src/erl_html_tools.erl
+++ b/system/doc/top/src/erl_html_tools.erl
@@ -624,17 +624,9 @@ lines_to_key_value([Line | Lines]) ->
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% Extensions to the 'regexp' module.
+% Regular expression helpers.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% is_match(Ex, Re) ->
-%% case regexp:first_match(Ex, Re) of
-%% {match, _, _} ->
-%% true;
-%% nomatch ->
-%% false
-%% end.
-
%% -type gsub(String, RegExp, Fun, Acc) -> subres().
%% Substitute every match of the regular expression RegExp with the
%% string returned from the function Fun(Match, Acc). Accept pre-parsed
diff --git a/system/doc/tutorial/Makefile b/system/doc/tutorial/Makefile
index efb380248e..d48082484c 100644
--- a/system/doc/tutorial/Makefile
+++ b/system/doc/tutorial/Makefile
@@ -88,6 +88,8 @@ DVIPS_FLAGS +=
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
+_create_dirs := $(shell mkdir -p $(HTMLDIR))
+
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
diff --git a/system/doc/tutorial/make.dep b/system/doc/tutorial/make.dep
deleted file mode 100644
index e9f77ab439..0000000000
--- a/system/doc/tutorial/make.dep
+++ /dev/null
@@ -1,35 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex c_port.tex c_portdriver.tex cnode.tex \
- erl_interface.tex example.tex introduction.tex \
- overview.tex part.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-c_port.tex: port.c
-
-c_portdriver.tex: port_driver.c
-
-cnode.tex: complex3.erl
-
-example.tex: complex.c
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: port.ps
-
-book.dvi: port_driver.ps
-